📄 rmsoftmixer.c
字号:
/* RMDBGLOG((ENABLE, "Cannot erase surface\n")); *//* return err; *//* } */ /* * check if the gfx queue is empty * otherwise it's unsafe to release any picture */ RUAGetProperty(smx->pRUA, smx->gfx_id, RMGFXEnginePropertyID_CommandQueueEmpty, &empty_queue, sizeof(empty_queue)); if(!empty_queue){ RMDBGLOG((DISABLE, "GFX command queue not empty\n")); return RM_PENDING; } for(slot = 0; slot < MAX_SLOTS; slot++){ if(! smx->slots[slot].active) continue; smx->slots[slot].starved = FALSE; if(smx->slots[slot].new_pic.PictureAddress == 0){ read_next_pic: err = RUAGetProperty(smx->pRUA, smx->slots[slot].decoder, RMVideoDecoderPropertyID_NextPicture, &smx->slots[slot].new_pic, sizeof(smx->slots[slot].new_pic)); if(RMFAILED(err)){ /*this includes empty fifo */ RMDBGLOG((RMSMXDBG, "slot %ld EMPTY FIFO!\n", slot)); smx->slots[slot].new_pic.PictureAddress = 0; smx->slots[slot].starved = TRUE; continue; } } /* get stc */ err = RUAExchangeProperty(smx->pRUA, smx->slots[slot].stc, RMSTCPropertyID_TimeInfo, &smx->slots[slot].tir, sizeof(smx->slots[slot].stc), &stc, sizeof(stc)); if (err != RM_OK) { RMDBGLOG((ENABLE, "Cannot get STC time %s\n", RMstatusToString(err))); return err; } /*get pts */ pts = smx->slots[slot].new_pic.Picture.first_pts_hi; pts <<= 32; pts = smx->slots[slot].new_pic.Picture.first_pts_lo; pts <<= 1; if(pts > stc){ /* too early */ RMDBGLOG((RMSMXDBG, "slot %ld stc %lld, pts %lld: --EARLY\n", slot, stc, pts)); continue; } else{ /* too late or in time */ if(smx->slots[slot].current_pic.PictureAddress){ err = RUASetProperty(smx->pRUA, smx->slots[slot].decoder, RMVideoDecoderPropertyID_ReleasePicture, &(smx->slots[slot].current_pic.PictureAddress), sizeof(smx->slots[slot].current_pic.PictureAddress), 0); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot release picture\n")); } smx->slots[slot].current_pic.PictureAddress = 0; } /* if new_pic.pts > current_pic.pts */ RMMemcpy(&(smx->slots[slot].current_pic), &(smx->slots[slot].new_pic), sizeof(smx->slots[slot].current_pic)); smx->slots[slot].new_pic.PictureAddress = 0; if(pts + 3000 < stc){ /* too late */ RMDBGLOG((RMSMXDBG, "slot %ld stc %lld, pts %lld: --LATE\n", slot, stc, pts)); goto read_next_pic; } } } if (SMX_BUFFER_COUNT > 1) { /* block the engine until the current canvas is no longer on display */ SEND_GFX_COMMAND(smx, RMGFXEnginePropertyID_WaitForPicture, (smx->canvas_picture[smx->canvas_index])); } /* setup the gfx to draw on the current canvas buffer */ surface_param.SurfaceID = GFX_SURFACE_ID_NX; surface_param.StartAddress = smx->canvas_buffer[smx->canvas_index]; surface_param.TotalWidth = smx->canvas_width; surface_param.Tiled = FALSE; SEND_GFX_COMMAND(smx, RMGFXEnginePropertyID_Surface, surface_param); if(smx->canvas_dirty){ /* when a window is resized, moved, added, removed we need to clean the canvas */ struct GFXEngine_FillRectangle_type fill_param; smx->canvas_dirty--; fill_param.X = 0; fill_param.Y = 0; fill_param.Width = smx->canvas_width; fill_param.Height = smx->canvas_height; fill_param.Color = smx->canvas_color; SEND_GFX_COMMAND(smx, RMGFXEnginePropertyID_FillRectangle, fill_param); } for(slot = 0; slot < MAX_SLOTS; slot++){ if(smx->slots[slot].current_pic.PictureAddress) smx_set_picture(smx, &(smx->slots[slot].current_pic.Picture), slot); } /* ask gfx to display the current canvas buffer */ display_pic.Surface = smx->canvas_surface; display_pic.Picture = smx->canvas_picture[smx->canvas_index]; SEND_GFX_COMMAND(smx, RMGFXEnginePropertyID_DisplayPicture, display_pic); RMDBGLOG((RMSMXDBG, "Send picture 0x%08lx on surface 0x%08lx\n", smx->canvas_picture[smx->canvas_index], smx->canvas_surface)); /* flip the canvas buffer index */ smx->canvas_index++; smx->canvas_index %= SMX_BUFFER_COUNT; return RM_OK;}RMstatus RMSMXFlushSlot(RMsmx smx, RMuint32 slot){ RMstatus err; RMASSERT(slot<MAX_SLOTS); if (!smx->slots[slot].active) return RM_OK; if(smx->slots[slot].current_pic.PictureAddress){ err = RUASetProperty(smx->pRUA, smx->slots[slot].decoder, RMVideoDecoderPropertyID_KeepPictureBeforeFlushing, &(smx->slots[slot].current_pic.PictureAddress), sizeof(smx->slots[slot].current_pic.PictureAddress), 0); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot release picture\n")); } /* do not clear it to keep it on screen *//* smx->slots[slot].current_pic.PictureAddress = 0; */ } if(smx->slots[slot].new_pic.PictureAddress){ err = RUASetProperty(smx->pRUA, smx->slots[slot].decoder, RMVideoDecoderPropertyID_ReleasePicture, &(smx->slots[slot].new_pic.PictureAddress), sizeof(smx->slots[slot].new_pic.PictureAddress), 0); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot release picture\n")); } smx->slots[slot].new_pic.PictureAddress = 0; } err = RUASetProperty(smx->pRUA, smx->slots[slot].decoder, RMVideoDecoderPropertyID_FlushReaderDisplayFIFO, NULL, 0, 0); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot release picture\n")); } smx->slots[slot].starved = TRUE; return RM_OK;}RMstatus RMSMXSetCanvasColor(RMsmx smx, RMuint32 canvas_color){ smx->canvas_color = canvas_color; smx->canvas_dirty = SMX_BUFFER_COUNT; return RM_OK;}RMstatus RMSMXSetOutputWindow(RMsmx smx, struct rmsmx_window *window, RMuint32 slot){ if((window->x < window->border_width) || (window->y < window->border_width) || (window->x + window->width + window->border_width > smx->canvas_width) || (window->y + window->height + window->border_width > smx->canvas_height)){ RMDBGLOG((ENABLE, "INVALID WINDOW: X %ld Y %ld W %ld H %ld B %ld\n", window->x, window->y, window->width, window->height, window->border_width)); return RM_ERROR; } smx->canvas_dirty = SMX_BUFFER_COUNT; if(window->border_width) smx->slots[slot].draw_border = SMX_BUFFER_COUNT; RMMemcpy(&(smx->slots[slot].current_window), window, sizeof(struct rmsmx_window)); RMDBGLOG((RMSMXDBG, "WINDOW OK: X %ld Y %ld W %ld H %ld B %ld\n", smx->slots[slot].current_window.x, smx->slots[slot].current_window.y, smx->slots[slot].current_window.width, smx->slots[slot].current_window.height, smx->slots[slot].current_window.border_width)); return RM_OK;}static inline RMuint32 get_vbus_pixel_address(RMuint32 base, RMuint32 x, RMuint32 y, RMuint32 width, RMuint32 bits_per_pixel, RMbool tiled){ x = (x * bits_per_pixel) / 8; if (tiled) { RMuint32 buffer_start, x_offset, y_offset; buffer_start = base & ~(4095); /* (base / 4096) * 4096; */ x_offset = x + (base & 127); /* x + (base - buffer_start) % 128 */ y_offset = y + ((base & 4095) >> 7); /* y + (base - buffer_start) / 128 */ /* buffer_start + (x_offset/128)*4096 + (y_offset/32)*width*4096 + (x_offset%128) + (y_offset%32)*128 */ return buffer_start + ((x_offset >> 7)<<12) + ((y_offset >> 5)<<12)*width + (x_offset & 127) + ((y_offset & 31)<<7); } else { return base + y * width + x; }}static inline RMstatus smx_set_picture(RMsmx smx, struct EMhwlibNewPicture *pic, RMuint32 slot){ struct GFXEngine_MoveReplaceScaleRectangle_type move_param; struct GFXEngine_Surface_type surface_param; struct GFXEngine_FieldType_type field_param; RMuint32 width, height; RMuint32 val, x, y, w; surface_param.SurfaceID = GFX_SURFACE_ID_Z; val = pic->luma_address; x = pic->luma_position_in_buffer.x; y = pic->luma_position_in_buffer.y; w = pic->luma_total_width; val = get_vbus_pixel_address(val, x, y, w, 8, TRUE); surface_param.StartAddress = val; surface_param.TotalWidth = w; val = pic->chroma_address; x = pic->chroma_position_in_buffer.x; y = pic->chroma_position_in_buffer.y; w = pic->chroma_total_width; val = get_vbus_pixel_address(val, x, y, w, 8, TRUE); surface_param.ChromaStartAddress = val; surface_param.ChromaTotalWidth = w; surface_param.Tiled = TRUE; SEND_GFX_COMMAND(smx, RMGFXEnginePropertyID_Surface, surface_param); field_param.SurfaceID = GFX_SURFACE_ID_Z; field_param.LineSkipFactor = 2; field_param.FieldType = EMhwlibFieldType_Top; SEND_GFX_COMMAND(smx, RMGFXEnginePropertyID_FieldType, field_param); width = pic->luma_position_in_buffer.width; height = pic->luma_position_in_buffer.height; if(smx->slots[slot].draw_border){ struct GFXEngine_FillRectangle_type fill_param; fill_param.X = smx->slots[slot].current_window.x - smx->slots[slot].current_window.border_width; fill_param.Y = smx->slots[slot].current_window.y - smx->slots[slot].current_window.border_width; fill_param.Width = smx->slots[slot].current_window.width + 2*smx->slots[slot].current_window.border_width; fill_param.Height = smx->slots[slot].current_window.height + 2*smx->slots[slot].current_window.border_width; fill_param.Color = smx->slots[slot].current_window.border_color; SEND_GFX_COMMAND(smx, RMGFXEnginePropertyID_FillRectangle, fill_param); smx->slots[slot].draw_border--; } move_param.SrcX = 0; move_param.SrcY = 0; move_param.SrcWidth = width; move_param.SrcHeight = height; move_param.DstX = smx->slots[slot].current_window.x; move_param.DstY = smx->slots[slot].current_window.y; move_param.DstWidth = smx->slots[slot].current_window.width; move_param.DstHeight = smx->slots[slot].current_window.height; move_param.AlphaX = 0; move_param.AlphaY = 0; move_param.Merge = FALSE; SEND_GFX_COMMAND(smx, RMGFXEnginePropertyID_MoveAndScaleRectangle, move_param); return RM_OK;}static inline RMstatus smx_open_gfx(RMsmx smx, struct DCCOSDProfile *canvas_profile ){ struct GFXEngine_ColorFormat_type format_param; struct GFXEngine_DRAMSize_in_type dramSizeIn; struct GFXEngine_DRAMSize_out_type dramSizeOut; struct GFXEngine_Open_type profile; struct GFXEngine_AlphaPalette_type alpha_palette; RMuint32 gfx_count, i; RMstatus err; /* to queue at least the max number of commands that can be sent during a call to RMSMXRefresh() */ dramSizeIn.CommandFIFOCount = MAX_SLOTS*4+16; smx->gfx_id = EMHWLIB_MODULE(GFXEngine,0); err = RUAExchangeProperty(smx->pRUA, smx->gfx_id, RMGFXEnginePropertyID_DRAMSize, &dramSizeIn, sizeof(dramSizeIn), &dramSizeOut, sizeof(dramSizeOut)); if (RMFAILED(err)) { RMDBGLOG((RMSMXDBG, "Error getting dram size for gfx engine\n")); return RM_ERROR; } profile.CommandFIFOCount = dramSizeIn.CommandFIFOCount; profile.Priority = 1; profile.CachedSize = dramSizeOut.CachedSize; if (profile.CachedSize > 0){ profile.CachedAddress = RUAMalloc(smx->pRUA, 0, RUA_DRAM_CACHED, profile.CachedSize); smx->gfx_cached_buf = profile.CachedAddress; } profile.UncachedSize = dramSizeOut.UncachedSize; if (profile.UncachedSize > 0) { profile.UncachedAddress = RUAMalloc(smx->pRUA, 0, RUA_DRAM_UNCACHED, profile.UncachedSize); smx->gfx_uncached_buf = profile.UncachedAddress; } err = RUAExchangeProperty(smx->pRUA, EMHWLIB_MODULE(Enumerator,0), RMEnumeratorPropertyID_CategoryIDToNumberOfInstances, &(smx->gfx_id), sizeof(smx->gfx_id), &gfx_count, sizeof(gfx_count)); if (RMFAILED(err)) { RMDBGLOG((RMSMXDBG, "Error getting gfx engine count\n")); return RM_ERROR; } for (i=0 ; i< gfx_count ; i++) { smx->gfx_id = EMHWLIB_MODULE(GFXEngine, i); err = RUASetProperty(smx->pRUA, smx->gfx_id, RMGFXEnginePropertyID_Open, &profile, sizeof(profile), 0); if (err == RM_OK) break; } if (i==gfx_count) { RMDBGLOG((RMSMXDBG, "Cannot open a gfx engine [0..%lu[\n", gfx_count)); return RM_ERROR; } format_param.SurfaceID = GFX_SURFACE_ID_NX; format_param.MainMode = canvas_profile->ColorMode; format_param.SubMode = canvas_profile->ColorFormat; format_param.SamplingMode = canvas_profile->SamplingMode; format_param.ColorSpace = canvas_profile->ColorSpace; SEND_GFX_COMMAND(smx, RMGFXEnginePropertyID_ColorFormat, format_param); /* possibly let the application chose this */ alpha_palette.SurfaceID = GFX_SURFACE_ID_Z; alpha_palette.Alpha0 = 0xff; SEND_GFX_COMMAND(smx, RMGFXEnginePropertyID_AlphaPalette, alpha_palette); return RM_OK;}static RMstatus smx_clear_buffers(RMsmx smx){ struct GFXEngine_FillRectangle_type fill_param; struct GFXEngine_Surface_type surface_param; struct GFXEngine_DisplayPicture_type display_pic; RMuint32 i; surface_param.SurfaceID = GFX_SURFACE_ID_NX; surface_param.TotalWidth = smx->canvas_width; surface_param.Tiled = FALSE; fill_param.X = 0; fill_param.Y = 0; fill_param.Width = smx->canvas_width; fill_param.Height = smx->canvas_height; fill_param.Color = smx->canvas_color; /* clear buffers with background color */ for(i = 0; i < SMX_BUFFER_COUNT; i++){ surface_param.StartAddress = smx->canvas_buffer[i]; SEND_GFX_COMMAND(smx, RMGFXEnginePropertyID_Surface, surface_param); SEND_GFX_COMMAND(smx, RMGFXEnginePropertyID_FillRectangle, fill_param); } /* display the first buffer */ display_pic.Surface = smx->canvas_surface; display_pic.Picture = smx->canvas_picture[smx->canvas_index]; SEND_GFX_COMMAND(smx, RMGFXEnginePropertyID_DisplayPicture, display_pic); /* flip the canvas buffer index */ smx->canvas_index++; smx->canvas_index %= SMX_BUFFER_COUNT; return RM_OK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -