static DFBResult uc_ovl_set_level(CoreLayer *layer, void *driver_data, void *layer_data, int level) { UcOverlayData* ucovl = (UcOverlayData*) layer_data; UcDriverData* ucdrv = (UcDriverData*) driver_data; if (level == 0) return DFB_INVARG; if (level < 0) { // Enable underlay mode. VIDEO_OUT(ucdrv->hwregs, V_ALPHA_CONTROL, uc_ovl_map_alpha(ucovl->opacity_primary)); } else { // Enable overlay mode (default) VIDEO_OUT(ucdrv->hwregs, V_ALPHA_CONTROL, uc_ovl_map_alpha(ucovl->v1.opacity)); } VIDEO_OUT(ucdrv->hwregs, V_COMPOSE_MODE, V1_COMMAND_FIRE | (ucovl->v1.dstkey_enabled ? ENABLE_COLOR_KEYING : 0)); ucovl->v1.level = level; return DFB_OK; }
static DFBResult uc_ovl_set_level(CoreLayer *layer, void *driver_data, void *layer_data, int level) { UcOverlayData* ucovl = (UcOverlayData*) layer_data; UcDriverData* ucdrv = (UcDriverData*) driver_data; if (level == 0) return DFB_INVARG; if (level > 0) { // Enable underlay mode. VIDEO_OUT(ucdrv->hwregs, V_ALPHA_CONTROL, uc_ovl_map_alpha(-1)); } else { // Enable overlay mode (default) VIDEO_OUT(ucdrv->hwregs, V_ALPHA_CONTROL, uc_ovl_map_alpha(ucovl->v1.opacity)); } ucovl->v1.level = level; return DFB_OK; }
static DFBResult osdSetRegion( CoreLayer *layer, void *driver_data, void *layer_data, void *region_data, CoreLayerRegionConfig *config, CoreLayerRegionConfigFlags updated, CoreSurface *surface, CorePalette *palette, CoreSurfaceBufferLock *lock ) { DFBResult ret; UcDriverData *ucdrv = (UcDriverData*) driver_data; /* call the original function */ ret = ucOldPrimaryFuncs.SetRegion( layer, ucOldPrimaryDriverData, layer_data, region_data, config, updated, surface, palette, lock ); if (ret) return ret; uc_ovl_vcmd_wait(ucdrv->hwregs); /* select pixel based or global alpha */ if (config->options & DLOP_ALPHACHANNEL) VIDEO_OUT(ucdrv->hwregs, V_ALPHA_CONTROL, uc_ovl_map_alpha(-1)); else if (config->options & DLOP_OPACITY) VIDEO_OUT(ucdrv->hwregs, V_ALPHA_CONTROL, uc_ovl_map_alpha(config->opacity)); else VIDEO_OUT(ucdrv->hwregs, V_ALPHA_CONTROL, uc_ovl_map_alpha(0xff)); VIDEO_OUT(ucdrv->hwregs, V_COMPOSE_MODE, V1_COMMAND_FIRE); return DFB_OK; }
static DFBResult osdSetRegion( CoreLayer *layer, void *driver_data, void *layer_data, void *region_data, CoreLayerRegionConfig *config, CoreLayerRegionConfigFlags updated, CoreSurface *surface, CorePalette *palette, CoreSurfaceBufferLock *lock ) { DFBResult ret; UcDriverData *ucdrv = (UcDriverData*) driver_data; /* call the original function */ ret = ucOldPrimaryFuncs.SetRegion( layer, ucOldPrimaryDriverData, layer_data, region_data, config, updated, surface, palette, lock ); if (ret) return ret; uc_ovl_vcmd_wait(ucdrv->hwregs); /* select pixel based or global alpha */ if (!ucdrv->ovl) // overlay not present return DFB_OK; if (config->options & DLOP_ALPHACHANNEL) ucdrv->ovl->opacity_primary = -1; // use primary alpha for overlay else if (config->options & DLOP_OPACITY) ucdrv->ovl->opacity_primary = config->opacity ^ 0xff; // use inverse for overlay else ucdrv->ovl->opacity_primary = 0x00; // primary opaque == overlay transparent if (ucdrv->ovl->v1.level < 0) // primary on top? { VIDEO_OUT(ucdrv->hwregs, V_ALPHA_CONTROL, uc_ovl_map_alpha(ucdrv->ovl->opacity_primary)); VIDEO_OUT(ucdrv->hwregs, V_COMPOSE_MODE, VIDEO_IN(ucdrv->hwregs, V_COMPOSE_MODE) | V1_COMMAND_FIRE); } return DFB_OK; }
DFBResult uc_ovl_update(UcDriverData* ucdrv, UcOverlayData* ucovl, int action, CoreSurface* surface) { int sw, sh, sp, sfmt; // Source width, height, pitch and format int dx, dy; // Destination position int dw, dh; // Destination width and height int pfetch; // Source pixels required for one line VideoMode *videomode; DFBRectangle scr; // Screen size u32 dst_key = 0; // Destination color key (hw format) bool write_buffers = false; bool write_settings = false; volatile u8* vio = ucdrv->hwregs; u32 win_start, win_end; // Overlay register settings u32 zoom, mini; u32 dcount, falign, qwfetch; u32 y_start, u_start, v_start; u32 v_ctrl, fifo_ctrl; u32 alpha = 0; int offset = surface->front_buffer->video.offset; if (!ucovl->v1.isenabled) return DFB_OK; qwfetch = 0; // Get screen size videomode = dfb_system_current_mode(); scr.w = videomode ? videomode->xres : 720; scr.h = videomode ? videomode->yres : 576; scr.x = 0; scr.y = 0; if (ucovl->scrwidth != scr.w) { // FIXME: fix uc_ovl_setup_fifo() // uc_ovl_setup_fifo(ucovl, scr.w); action |= UC_OVL_CHANGE; } D_ASSERT(surface); sw = surface->config.size.w; sh = surface->config.size.h; sp = surface->front_buffer->video.pitch; sfmt = surface->config.format; if (ucovl->deinterlace) { /*if (ucovl->field) offset += sp;*/ sh /= 2; //sp *= 2; } if (action & UC_OVL_CHANGE) { if ((sw > 4096) || (sh > 4096) || (sw < 32) || (sh < 1) || (sp > 0x1fff)) { D_DEBUG("Layer surface size is out of bounds."); return DFB_INVAREA; } dx = ucovl->v1.win.x; dy = ucovl->v1.win.y; dw = ucovl->v1.win.w; dh = ucovl->v1.win.h; // Get image format, FIFO size, etc. uc_ovl_map_v1_control(sfmt, sw, ucovl->hwrev, ucovl->extfifo_on, &v_ctrl, &fifo_ctrl); if (ucovl->deinterlace) { v_ctrl |= /*V1_BOB_ENABLE |*/ V1_FRAME_BASE; } // Get layer window. // The parts that fall outside the screen are clipped. uc_ovl_map_window(scr.w, scr.h, &(ucovl->v1.win), sw, sh, &win_start, &win_end, &ucovl->v1.ox, &ucovl->v1.oy, &pfetch); // Get scaling and data-fetch parameters // Note: the *_map_?zoom() functions return false if the scaling // is out of bounds. We don't act on it for now, because it only // makes the display look strange. zoom = 0; mini = 0; uc_ovl_map_vzoom(sh, dh, &zoom, &mini); uc_ovl_map_hzoom(sw, dw, &zoom, &mini, &falign, &dcount); qwfetch = uc_ovl_map_qwfetch(falign, sfmt, pfetch); // Prepare destination color key dst_key = uc_ovl_map_colorkey(&(ucovl->v1.dst_key)); // prepare opacity if (ucovl->v1.level > 0) // overlay alpha = uc_ovl_map_alpha(ucovl->v1.opacity); else alpha = uc_ovl_map_alpha(ucovl->opacity_primary); write_settings = true; } if (action & (UC_OVL_FIELD | UC_OVL_FLIP | UC_OVL_CHANGE)) { int field = 0; // Update the buffer pointers if (ucovl->deinterlace) { field = ucovl->field; } uc_ovl_map_buffer(sfmt, offset, ucovl->v1.ox, ucovl->v1.oy, sw, surface->config.size.h, sp, 0/*field*/, &y_start, &u_start, &v_start); if (field) { y_start |= 0x08000000; } write_buffers = true; } // Write to the hardware /* if (write_settings || write_buffers) uc_ovl_vcmd_wait(vio);*/ if (write_settings) { VIDEO_OUT(vio, V1_CONTROL, v_ctrl); VIDEO_OUT(vio, V_FIFO_CONTROL, fifo_ctrl); VIDEO_OUT(vio, V1_WIN_START_Y, win_start); VIDEO_OUT(vio, V1_WIN_END_Y, win_end); VIDEO_OUT(vio, V1_SOURCE_HEIGHT, (sh << 16) | dcount); VIDEO_OUT(vio, V12_QWORD_PER_LINE, qwfetch); VIDEO_OUT(vio, V1_STRIDE, sp | ((sp >> 1) << 16)); VIDEO_OUT(vio, V1_MINI_CONTROL, mini); VIDEO_OUT(vio, V1_ZOOM_CONTROL, zoom); VIDEO_OUT(vio, V_COLOR_KEY, dst_key); VIDEO_OUT(vio, V_ALPHA_CONTROL, alpha); } if (write_buffers) { VIDEO_OUT(vio, V1_STARTADDR_0, y_start); VIDEO_OUT(vio, V1_STARTADDR_CB0, u_start); VIDEO_OUT(vio, V1_STARTADDR_CR0, v_start); } if (write_settings || write_buffers) { VIDEO_OUT(vio, V_COMPOSE_MODE, V1_COMMAND_FIRE | (ucovl->v1.dstkey_enabled ? ENABLE_COLOR_KEYING : 0)); } return DFB_OK; }