From 7fe60435bce6595a9c58a9bfd8244d74b5320e96 Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Tue, 15 Jan 2013 08:46:13 +0100 Subject: Import DirectFB141_2k11R3_beta5 --- Source/DirectFB/gfxdrivers/unichrome/uc_overlay.c | 405 ++++++++++++++++++++++ 1 file changed, 405 insertions(+) create mode 100755 Source/DirectFB/gfxdrivers/unichrome/uc_overlay.c (limited to 'Source/DirectFB/gfxdrivers/unichrome/uc_overlay.c') diff --git a/Source/DirectFB/gfxdrivers/unichrome/uc_overlay.c b/Source/DirectFB/gfxdrivers/unichrome/uc_overlay.c new file mode 100755 index 0000000..4402cb3 --- /dev/null +++ b/Source/DirectFB/gfxdrivers/unichrome/uc_overlay.c @@ -0,0 +1,405 @@ +/* + Copyright (c) 2003 Andreas Robinson, All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. +*/ + +#include + +#include + +#include "unichrome.h" +#include "uc_overlay.h" +#include "uc_ioctl.h" +#include "vidregs.h" +#include "mmio.h" + +#include +#include + +#include + +#include + +#include + +// Forward declaration +static DFBResult +uc_ovl_remove(CoreLayer *layer, + void *driver_data, + void *layer_data, + void *region_data); + + +static int uc_ovl_datasize( void ) +{ + return sizeof(UcOverlayData); +} + + +static DFBResult +uc_ovl_init_layer( CoreLayer *layer, + void *driver_data, + void *layer_data, + DFBDisplayLayerDescription *description, + DFBDisplayLayerConfig *config, + DFBColorAdjustment *adjustment ) +{ + UcDriverData* ucdrv = (UcDriverData*) driver_data; + UcOverlayData* ucovl = (UcOverlayData*) layer_data; + + // Save a pointer to the layer data for access by the primary + // This is needed to properly support levels and the primary alpha channel + + ucdrv->ovl = ucovl; + + // Set layer type, capabilities and name + + description->caps = UC_OVL_CAPS; + description->type = DLTF_GRAPHICS | DLTF_VIDEO | DLTF_STILL_PICTURE; + snprintf(description->name, + DFB_DISPLAY_LAYER_DESC_NAME_LENGTH, "VIA Unichrome Video"); + + adjustment->flags = DCAF_NONE; + + // Fill out the default configuration + + config->flags = DLCONF_WIDTH | DLCONF_HEIGHT | + DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE | DLCONF_OPTIONS; + + ucovl->v1.win.w = 720; + ucovl->v1.win.h = 576; + ucovl->v1.win.x = 0; + ucovl->v1.win.y = 0; + + config->width = 720; + config->height = 576; + + config->pixelformat = DSPF_YV12; + config->buffermode = DLBM_FRONTONLY; + config->options = DLOP_NONE; + + // Reset overlay + + ucovl->extfifo_on = false; + ucovl->hwrev = ucdrv->hwrev; + ucovl->scrwidth = ucovl->v1.win.w; + + ucovl->v1.isenabled = false; + ucovl->v1.cfg = *config; + ucovl->v1.ox = 0; + ucovl->v1.oy = 0; + ucovl->v1.dst_key.index = 0; + ucovl->v1.dst_key.r = 0; + ucovl->v1.dst_key.g = 0; + ucovl->v1.dst_key.b = 0; + ucovl->v1.dstkey_enabled = false; + ucovl->v1.opacity = 0xff; + ucovl->v1.level = 1; + +// adjustment->flags = DCAF_BRIGHTNESS | DCAF_CONTRAST | +// DCAF_HUE | DCAF_SATURATION; + adjustment->brightness = 0x8000; + adjustment->contrast = 0x8000; + adjustment->saturation = 0x8000; + adjustment->hue = 0x8000; + ucovl->v1.adj = *adjustment; + + uc_ovl_remove(layer, driver_data, layer_data, NULL); + + return DFB_OK; +} + + +static DFBResult +uc_ovl_set_region( CoreLayer *layer, + void *driver_data, + void *layer_data, + void *region_data, + CoreLayerRegionConfig *config, + CoreLayerRegionConfigFlags updated, + CoreSurface *surface, + CorePalette *palette, + CoreSurfaceBufferLock *lock ) +{ + UcDriverData* ucdrv = (UcDriverData*) driver_data; + UcOverlayData* ucovl = (UcOverlayData*) layer_data; + DFBRectangle win; + + /* remember configuration */ + ucovl->config = *config; + + /* get new destination rectangle */ + win = config->dest; + + // Bounds checking + if ((win.x < -8192) || (win.x > 8192) || + (win.y < -8192) || (win.y > 8192) || + (win.w < 32) || (win.w > 4096) || + (win.h < 32) || (win.h > 4096)) + { + D_DEBUG("Layer size or position is out of bounds."); + return DFB_INVAREA; + } + + ucovl->v1.isenabled = true; + ucovl->v1.win = win; + ucovl->v1.dst_key = config->dst_key; + ucovl->v1.dstkey_enabled = config->options & DLOP_DST_COLORKEY; + + if (config->options & DLOP_OPACITY) + ucovl->v1.opacity = config->opacity; + else + ucovl->v1.opacity = 0xff; + + // printf("uc_overlay: color-keying is %s\n", + // ucovl->v1.dstkey_enabled ? "enabled" : "disabled"); + + ucovl->deinterlace = config->options & DLOP_DEINTERLACING; + ucovl->surface = surface; + ucovl->lock = lock; + + if (ucdrv->canfliponvsync) { + FBDev *dfb_fbdev = dfb_system_data(); + int field_option = VIAFB_WAIT_FLIP; // wait for any pending flip + ioctl(dfb_fbdev->fd, FBIO_WAITFORVSYNC, &field_option); + } + + return uc_ovl_update(ucdrv, ucovl, UC_OVL_CHANGE, surface, lock); +} + + +static DFBResult +uc_ovl_remove(CoreLayer *layer, + void *driver_data, + void *layer_data, + void *region_data) +{ + UcDriverData* ucdrv = (UcDriverData*) driver_data; + UcOverlayData* ucovl = (UcOverlayData*) layer_data; + volatile u8* vio = ucdrv->hwregs; + + ucovl->v1.isenabled = false; + + uc_ovl_vcmd_wait(vio); + + VIDEO_OUT(vio, V_FIFO_CONTROL, UC_MAP_V1_FIFO_CONTROL(16,12,8)); + // VIDEO_OUT(vio, ALPHA_V3_FIFO_CONTROL, 0x0407181f); + + if (ucovl->hwrev >= 0x10) { + VIDEO_OUT(vio, V1_ColorSpaceReg_1, ColorSpaceValue_1_3123C0); + VIDEO_OUT(vio, V1_ColorSpaceReg_2, ColorSpaceValue_2_3123C0); + } + else { + VIDEO_OUT(vio, V1_ColorSpaceReg_1, ColorSpaceValue_1); + VIDEO_OUT(vio, V1_ColorSpaceReg_2, ColorSpaceValue_2); + } + + VIDEO_OUT(vio, HQV_CONTROL, VIDEO_IN(vio, HQV_CONTROL) & ~HQV_ENABLE); + VIDEO_OUT(vio, V1_CONTROL, VIDEO_IN(vio, V1_CONTROL) & ~V1_ENABLE); + // VIDEO_OUT(vio, V3_CONTROL, VIDEO_IN(vio, V3_CONTROL) & ~V3_ENABLE); + + VIDEO_OUT(vio, V_COMPOSE_MODE, + (VIDEO_IN(vio, V_COMPOSE_MODE) & ~ENABLE_COLOR_KEYING) | V1_COMMAND_FIRE); + + ucovl->surface = NULL; + + return DFB_OK; +} + + +static DFBResult +uc_ovl_test_region(CoreLayer *layer, + void *driver_data, + void *layer_data, + CoreLayerRegionConfig *config, + CoreLayerRegionConfigFlags *failed) +{ + CoreLayerRegionConfigFlags fail = 0; + + // Check layer options + + if (config->options & ~UC_OVL_OPTIONS) + fail |= CLRCF_OPTIONS; + + // Check pixelformats + + switch (config->format) { + case DSPF_YUY2: + break; + case DSPF_UYVY: + fail |= CLRCF_FORMAT; // Nope... doesn't work. + break; + case DSPF_I420: + case DSPF_YV12: + case DSPF_ARGB1555: + case DSPF_RGB16: + case DSPF_RGB32: + case DSPF_ARGB: + break; + default: + fail |= CLRCF_FORMAT; + } + + // Check width and height + + if (config->width > 4096 || config->width < 32) + fail |= CLRCF_WIDTH; + + if (config->height > 4096 || config->height < 32) + fail |= CLRCF_HEIGHT; + + if (failed) *failed = fail; + if (fail) return DFB_UNSUPPORTED; + + return DFB_OK; +} + + +static DFBResult +uc_ovl_flip_region( CoreLayer *layer, + void *driver_data, + void *layer_data, + void *region_data, + CoreSurface *surface, + DFBSurfaceFlipFlags flags, + CoreSurfaceBufferLock *lock ) +{ + //printf("Entering %s ... \n", __PRETTY_FUNCTION__); + + UcDriverData* ucdrv = (UcDriverData*) driver_data; + UcOverlayData* ucovl = (UcOverlayData*) layer_data; + DFBResult ret; + FBDev *dfb_fbdev = dfb_system_data(); + + dfb_surface_flip(surface, false); + + ucovl->field = 0; + ucovl->lock = lock; + + if (ucdrv->canfliponvsync) + { + if (ucovl->config.options & DLOP_FIELD_PARITY) + { + struct fb_flip flip; + int field_option; + + field_option = VIAFB_WAIT_FLIP; // ensure last pending flip complete + ioctl(dfb_fbdev->fd, FBIO_WAITFORVSYNC, &field_option); + + flip.device = VIAFB_FLIP_V1; + flip.field = ucovl->config.parity; + flip.count = 0; // until we implement this + + uc_ovl_map_buffer(surface->config.format, + lock->offset, + ucovl->v1.ox, ucovl->v1.oy, surface->config.size.w, surface->config.size.h, + lock->pitch, 0, + &flip.offset[0], &flip.offset[1], &flip.offset[2]); + + ioctl(dfb_fbdev->fd, FBIO_FLIPONVSYNC, &flip); + } + else + { + ret = uc_ovl_update(ucdrv, ucovl, UC_OVL_FLIP, surface, lock); + if (ret) + return ret; + } + } + else + { + if (ucovl->config.options & DLOP_FIELD_PARITY) + { + int field_option; + + if (ucovl->config.parity == 0) // top field first? + field_option = VIAFB_WAIT_BOTTOMFIELD; + else + field_option = VIAFB_WAIT_TOPFIELD; + ioctl(dfb_fbdev->fd, FBIO_WAITFORVSYNC, &field_option); + // that actually waits for VBLANK so we need a further delay + // to be sure the field has started and that the flip will + // take effect on the next field + usleep(2500); + } + + ret = uc_ovl_update(ucdrv, ucovl, UC_OVL_FLIP, surface, lock); + if (ret) + return ret; + } + + if (flags & DSFLIP_WAIT) + dfb_layer_wait_vsync(layer); + + return DFB_OK; +} + +static DFBResult +uc_ovl_get_level(CoreLayer *layer, + void *driver_data, + void *layer_data, + int *level) +{ + UcOverlayData* ucovl = (UcOverlayData*) layer_data; + *level = ucovl->v1.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(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_input_field( CoreLayer *layer, + void *driver_data, + void *layer_data, + void *region_data, + int field ) +{ + UcOverlayData* ucovl = (UcOverlayData*) layer_data; + UcDriverData* ucdrv = (UcDriverData*) driver_data; + + ucovl->field = field; + + return uc_ovl_update(ucdrv, ucovl, UC_OVL_FIELD, ucovl->surface, ucovl->lock); +} + +DisplayLayerFuncs ucOverlayFuncs = { + .LayerDataSize = uc_ovl_datasize, + .InitLayer = uc_ovl_init_layer, + .SetRegion = uc_ovl_set_region, + .RemoveRegion = uc_ovl_remove, + .TestRegion = uc_ovl_test_region, + .FlipRegion = uc_ovl_flip_region, + .GetLevel = uc_ovl_get_level, + .SetLevel = uc_ovl_set_level, + .SetInputField = uc_ovl_set_input_field, +// .SetColorAdjustment = uc_ovl_set_adjustment, +}; -- cgit