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/nvidia/nvidia_overlay.c | 566 +++++++++++++++++++++ 1 file changed, 566 insertions(+) create mode 100755 Source/DirectFB/gfxdrivers/nvidia/nvidia_overlay.c (limited to 'Source/DirectFB/gfxdrivers/nvidia/nvidia_overlay.c') diff --git a/Source/DirectFB/gfxdrivers/nvidia/nvidia_overlay.c b/Source/DirectFB/gfxdrivers/nvidia/nvidia_overlay.c new file mode 100755 index 0000000..747f14c --- /dev/null +++ b/Source/DirectFB/gfxdrivers/nvidia/nvidia_overlay.c @@ -0,0 +1,566 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Oliver Schwartz and + Claudio Ciccani . + + 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. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "nvidia.h" +#include "nvidia_regs.h" +#include "nvidia_accel.h" + + +typedef struct { + CoreLayerRegionConfig config; + CoreSurface *videoSurface; + CoreSurfaceBufferLock *lock; + + short brightness; + short contrast; + short hue; + short saturation; + int field; + + struct { + u32 BUFFER; + u32 STOP; + u32 UVBASE_0; + u32 UVBASE_1; + u32 UVOFFSET_0; + u32 UVOFFSET_1; + u32 BASE_0; + u32 BASE_1; + u32 OFFSET_0; + u32 OFFSET_1; + u32 SIZE_IN_0; + u32 SIZE_IN_1; + u32 POINT_IN_0; + u32 POINT_IN_1; + u32 DS_DX_0; + u32 DS_DX_1; + u32 DT_DY_0; + u32 DT_DY_1; + u32 POINT_OUT_0; + u32 POINT_OUT_1; + u32 SIZE_OUT_0; + u32 SIZE_OUT_1; + u32 FORMAT_0; + u32 FORMAT_1; + } regs; +} NVidiaOverlayLayerData; + +static void ov0_set_regs ( NVidiaDriverData *nvdrv, + NVidiaOverlayLayerData *nvov0, + CoreLayerRegionConfigFlags flags ); +static void ov0_calc_regs ( NVidiaDriverData *nvdrv, + NVidiaOverlayLayerData *nvov0, + CoreLayerRegionConfig *config, + CoreLayerRegionConfigFlags flags ); +static void ov0_set_colorkey( NVidiaDriverData *nvdrv, + NVidiaOverlayLayerData *nvov0, + CoreLayerRegionConfig *config ); +static void ov0_set_csc ( NVidiaDriverData *nvdrv, + NVidiaOverlayLayerData *nvov0 ); + +#define OV0_SUPPORTED_OPTIONS \ + ( DLOP_DST_COLORKEY | DLOP_DEINTERLACING ) + +/**********************/ + + + +static int +ov0LayerDataSize( void ) +{ + return sizeof(NVidiaOverlayLayerData); +} + +static DFBResult +ov0InitLayer( CoreLayer *layer, + void *driver_data, + void *layer_data, + DFBDisplayLayerDescription *description, + DFBDisplayLayerConfig *config, + DFBColorAdjustment *adjustment ) +{ + NVidiaDriverData *nvdrv = (NVidiaDriverData*) driver_data; + NVidiaOverlayLayerData *nvov0 = (NVidiaOverlayLayerData*) layer_data; + + /* set capabilities and type */ + description->caps = DLCAPS_SURFACE | DLCAPS_SCREEN_LOCATION | + DLCAPS_BRIGHTNESS | DLCAPS_CONTRAST | + DLCAPS_SATURATION | DLCAPS_HUE | + DLCAPS_DST_COLORKEY | DLCAPS_DEINTERLACING; + description->type = DLTF_VIDEO | DLTF_STILL_PICTURE; + + /* set name */ + snprintf( description->name, + DFB_DISPLAY_LAYER_DESC_NAME_LENGTH, "NVidia Overlay" ); + + /* fill out the default configuration */ + config->flags = DLCONF_WIDTH | DLCONF_HEIGHT | + DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE | + DLCONF_OPTIONS; + config->width = 640; + config->height = 480; + config->pixelformat = DSPF_YUY2; + config->buffermode = DLBM_FRONTONLY; + config->options = DLOP_NONE; + + /* fill out default color adjustment, + only fields set in flags will be accepted from applications */ + adjustment->flags = DCAF_BRIGHTNESS | DCAF_CONTRAST | + DCAF_SATURATION | DCAF_HUE; + adjustment->brightness = 0x8000; + adjustment->contrast = 0x8000; + adjustment->saturation = 0x8000; + adjustment->hue = 0x8000; + + /* reset overlay */ + nvov0->brightness = 0; + nvov0->contrast = 4096; + nvov0->hue = 0; + nvov0->saturation = 4096; + ov0_set_csc( nvdrv, nvov0 ); + + return DFB_OK; +} + +static DFBResult +ov0Remove( CoreLayer *layer, + void *driver_data, + void *layer_data, + void *region_data ) +{ + NVidiaDriverData *nvdrv = (NVidiaDriverData*) driver_data; + volatile u8 *mmio = nvdrv->mmio_base; + + /* disable overlay */ + nv_out32( mmio, PVIDEO_STOP, PVIDEO_STOP_OVERLAY_ACTIVE | + PVIDEO_STOP_METHOD_IMMEDIATELY ); + nv_out32( mmio, PVIDEO_BUFFER, 0 ); + + return DFB_OK; +} + +static DFBResult +ov0TestRegion(CoreLayer *layer, + void *driver_data, + void *layer_data, + CoreLayerRegionConfig *config, + CoreLayerRegionConfigFlags *failed ) +{ + NVidiaDriverData *nvdrv = driver_data; + NVidiaDeviceData *nvdev = nvdrv->device_data; + CoreLayerRegionConfigFlags fail = CLRCF_NONE; + + + /* check for unsupported options */ + if (config->options & ~OV0_SUPPORTED_OPTIONS) + fail |= CLRCF_OPTIONS; + + /* check buffermode */ + switch (config->buffermode) { + case DLBM_FRONTONLY: + case DLBM_BACKSYSTEM: + case DLBM_BACKVIDEO: + case DLBM_TRIPLE: + break; + + default: + fail |= CLRCF_BUFFERMODE; + break; + } + + /* check pixel format */ + switch (config->format) { + case DSPF_YUY2: + case DSPF_UYVY: + break; + + case DSPF_NV12: + /*case DSPF_NV21:*/ + if (nvdev->arch < NV_ARCH_30) + fail |= CLRCF_FORMAT; + break; + + default: + fail |= CLRCF_FORMAT; + break; + } + + /* check width */ + if (config->width > 2046 || config->width < 1) + fail |= CLRCF_WIDTH; + + /* check height */ + if (config->height > 2046 || config->height < 1) + fail |= CLRCF_HEIGHT; + + /* write back failing fields */ + if (failed) + *failed = fail; + + /* return failure if any field failed */ + if (fail) + return DFB_UNSUPPORTED; + + return DFB_OK; +} + +static DFBResult +ov0SetRegion( CoreLayer *layer, + void *driver_data, + void *layer_data, + void *region_data, + CoreLayerRegionConfig *config, + CoreLayerRegionConfigFlags updated, + CoreSurface *surface, + CorePalette *palette, + CoreSurfaceBufferLock *lock ) +{ + NVidiaDriverData *nvdrv = (NVidiaDriverData*) driver_data; + NVidiaOverlayLayerData *nvov0 = (NVidiaOverlayLayerData*) layer_data; + + /* remember configuration */ + nvov0->config = *config; + + nvov0->videoSurface = surface; + nvov0->lock = lock; + + /* set configuration */ + if (updated & (CLRCF_WIDTH | CLRCF_HEIGHT | CLRCF_FORMAT | + CLRCF_SOURCE | CLRCF_DEST | CLRCF_OPTIONS | CLRCF_OPACITY)) + { + ov0_calc_regs( nvdrv, nvov0, config, updated ); + ov0_set_regs( nvdrv, nvov0, updated ); + } + + /* set destination colorkey */ + if (updated & CLRCF_DSTKEY) + ov0_set_colorkey( nvdrv, nvov0, config ); + + return DFB_OK; +} + +static DFBResult +ov0FlipRegion ( CoreLayer *layer, + void *driver_data, + void *layer_data, + void *region_data, + CoreSurface *surface, + DFBSurfaceFlipFlags flags, + CoreSurfaceBufferLock *lock ) +{ + NVidiaDriverData *nvdrv = (NVidiaDriverData*) driver_data; + NVidiaOverlayLayerData *nvov0 = (NVidiaOverlayLayerData*) layer_data; + + nvov0->videoSurface = surface; + nvov0->lock = lock; + + dfb_surface_flip( nvov0->videoSurface, false ); + + ov0_calc_regs( nvdrv, nvov0, &nvov0->config, CLRCF_SURFACE ); + ov0_set_regs( nvdrv, nvov0, CLRCF_SURFACE ); + + if (flags & DSFLIP_WAIT) + dfb_layer_wait_vsync( layer ); + + return DFB_OK; +} + +static DFBResult +ov0SetColorAdjustment( CoreLayer *layer, + void *driver_data, + void *layer_data, + DFBColorAdjustment *adj ) +{ + NVidiaDriverData *nvdrv = (NVidiaDriverData*) driver_data; + NVidiaOverlayLayerData *nvov0 = (NVidiaOverlayLayerData*) layer_data; + + if (adj->flags & DCAF_BRIGHTNESS) { + nvov0->brightness = (adj->brightness >> 8) - 128; + D_DEBUG( "DirectFB/NVidia/Overlay: brightness=%i\n", nvov0->brightness ); + } + + if (adj->flags & DCAF_CONTRAST) { + nvov0->contrast = 8191 - (adj->contrast >> 3); /* contrast inverted ?! */ + D_DEBUG( "DirectFB/NVidia/Overlay: contrast=%i\n", nvov0->contrast ); + } + + if (adj->flags & DCAF_SATURATION) { + nvov0->saturation = adj->saturation >> 3; + D_DEBUG( "DirectFB/NVidia/Overlay: saturation=%i\n", nvov0->saturation ); + } + + if (adj->flags & DCAF_HUE) { + nvov0->hue = (adj->hue / 182 - 180) % 360; + D_DEBUG( "DirectFB/NVidia/Overlay: hue=%i\n", nvov0->hue ); + } + + ov0_set_csc( nvdrv, nvov0 ); + + return DFB_OK; +} + +static DFBResult +ov0SetInputField( CoreLayer *layer, + void *driver_data, + void *layer_data, + void *region_data, + int field ) +{ + NVidiaDriverData *nvdrv = (NVidiaDriverData*) driver_data; + NVidiaOverlayLayerData *nvov0 = (NVidiaOverlayLayerData*) layer_data; + + nvov0->field = field; + nvov0->regs.BUFFER = 1 << (field << 2); + + nv_out32( nvdrv->mmio_base, PVIDEO_BUFFER, nvov0->regs.BUFFER ); + + return DFB_OK; +} + +DisplayLayerFuncs nvidiaOverlayFuncs = { + .LayerDataSize = ov0LayerDataSize, + .InitLayer = ov0InitLayer, + .SetRegion = ov0SetRegion, + .RemoveRegion = ov0Remove, + .TestRegion = ov0TestRegion, + .FlipRegion = ov0FlipRegion, + .SetColorAdjustment = ov0SetColorAdjustment, + .SetInputField = ov0SetInputField, +}; + + +/* internal */ + +static void ov0_set_regs( NVidiaDriverData *nvdrv, + NVidiaOverlayLayerData *nvov0, + CoreLayerRegionConfigFlags flags ) +{ + volatile u8 *mmio = nvdrv->mmio_base; + + if (flags & CLRCF_SURFACE) { + if (DFB_PLANAR_PIXELFORMAT(nvov0->config.format)) { + nv_out32( mmio, PVIDEO_UVBASE_0, nvov0->regs.UVBASE_0 ); + nv_out32( mmio, PVIDEO_UVBASE_1, nvov0->regs.UVBASE_1 ); + nv_out32( mmio, PVIDEO_UVOFFSET_0, nvov0->regs.UVOFFSET_0 ); + nv_out32( mmio, PVIDEO_UVOFFSET_1, nvov0->regs.UVOFFSET_1 ); + } + nv_out32( mmio, PVIDEO_BASE_0, nvov0->regs.BASE_0 ); + nv_out32( mmio, PVIDEO_BASE_1, nvov0->regs.BASE_1 ); + nv_out32( mmio, PVIDEO_OFFSET_0, nvov0->regs.OFFSET_0 ); + nv_out32( mmio, PVIDEO_OFFSET_1, nvov0->regs.OFFSET_1 ); + } + if (flags & (CLRCF_WIDTH | CLRCF_HEIGHT | CLRCF_OPTIONS)) { + nv_out32( mmio, PVIDEO_SIZE_IN_0, nvov0->regs.SIZE_IN_0 ); + nv_out32( mmio, PVIDEO_SIZE_IN_1, nvov0->regs.SIZE_IN_1 ); + } + if (flags & (CLRCF_SOURCE | CLRCF_DEST | CLRCF_OPTIONS)) { + nv_out32( mmio, PVIDEO_POINT_IN_0, nvov0->regs.POINT_IN_0 ); + nv_out32( mmio, PVIDEO_POINT_IN_1, nvov0->regs.POINT_IN_1 ); + nv_out32( mmio, PVIDEO_DS_DX_0, nvov0->regs.DS_DX_0 ); + nv_out32( mmio, PVIDEO_DS_DX_1, nvov0->regs.DS_DX_1 ); + nv_out32( mmio, PVIDEO_DT_DY_0, nvov0->regs.DT_DY_0 ); + nv_out32( mmio, PVIDEO_DT_DY_1, nvov0->regs.DT_DY_1 ); + } + if (flags & CLRCF_DEST) { + nv_out32( mmio, PVIDEO_POINT_OUT_0, nvov0->regs.POINT_OUT_0 ); + nv_out32( mmio, PVIDEO_POINT_OUT_1, nvov0->regs.POINT_OUT_1 ); + nv_out32( mmio, PVIDEO_SIZE_OUT_0, nvov0->regs.SIZE_OUT_0 ); + nv_out32( mmio, PVIDEO_SIZE_OUT_1, nvov0->regs.SIZE_OUT_1 ); + } + if (flags & (CLRCF_FORMAT | CLRCF_SURFACE | CLRCF_OPTIONS)) { + nv_out32( mmio, PVIDEO_FORMAT_0, nvov0->regs.FORMAT_0 ); + nv_out32( mmio, PVIDEO_FORMAT_1, nvov0->regs.FORMAT_1 ); + } + nv_out32( mmio, PVIDEO_BUFFER, nvov0->regs.BUFFER ); + nv_out32( mmio, PVIDEO_STOP, nvov0->regs.STOP ); +} + +static void +ov0_calc_regs( NVidiaDriverData *nvdrv, + NVidiaOverlayLayerData *nvov0, + CoreLayerRegionConfig *config, + CoreLayerRegionConfigFlags flags ) +{ + NVidiaDeviceData *nvdev = nvdrv->device_data; + + if (flags & (CLRCF_WIDTH | CLRCF_HEIGHT | + CLRCF_SOURCE | CLRCF_DEST | CLRCF_OPTIONS)) { + int width = config->width; + int height = config->height; + DFBRectangle source = config->source; + DFBRectangle dest = config->dest; + + source.x <<= 4; + source.y <<= 4; + + if (dest.x < 0) { + source.x -= (dest.x * source.w << 4) / dest.w; + source.w += dest.x * source.w / dest.w; + dest.w += dest.x; + dest.x = 0; + } + + if (dest.y < 0) { + source.y -= (dest.y * source.h << 4) / dest.h; + source.h += dest.y * source.h / dest.h; + dest.h += dest.y; + dest.y = 0; + } + + if (config->options & DLOP_DEINTERLACING) { + height /= 2; + source.y /= 2; + source.h /= 2; + } + + if (source.w < 1 || source.h < 1 || dest.w < 1 || dest.h < 1) { + nvov0->regs.STOP = PVIDEO_STOP_OVERLAY_ACTIVE | + PVIDEO_STOP_METHOD_NORMALLY; + return; + } + + nvov0->regs.SIZE_IN_0 = + nvov0->regs.SIZE_IN_1 = ((height << 16) & PVIDEO_SIZE_IN_HEIGHT_MSK) | + ( width & PVIDEO_SIZE_IN_WIDTH_MSK); + nvov0->regs.POINT_IN_0 = + nvov0->regs.POINT_IN_1 = ((source.y << 16) & PVIDEO_POINT_IN_T_MSK) | + ( source.x & PVIDEO_POINT_IN_S_MSK); + nvov0->regs.DS_DX_0 = + nvov0->regs.DS_DX_1 = (source.w << 20) / dest.w; + nvov0->regs.DT_DY_0 = + nvov0->regs.DT_DY_1 = (source.h << 20) / dest.h; + nvov0->regs.POINT_OUT_0 = + nvov0->regs.POINT_OUT_1 = ((dest.y << 16) & PVIDEO_POINT_OUT_Y_MSK) | + ( dest.x & PVIDEO_POINT_OUT_X_MSK); + nvov0->regs.SIZE_OUT_0 = + nvov0->regs.SIZE_OUT_1 = ((dest.h << 16) & PVIDEO_SIZE_OUT_HEIGHT_MSK) | + ( dest.w & PVIDEO_SIZE_OUT_WIDTH_MSK); + } + + if (flags & (CLRCF_SURFACE | CLRCF_FORMAT | CLRCF_OPTIONS)) { + CoreSurfaceBufferLock *lock = nvov0->lock; + u32 format; + + if (config->options & DLOP_DEINTERLACING) + format = (lock->pitch*2) & PVIDEO_FORMAT_PITCH_MSK; + else + format = lock->pitch & PVIDEO_FORMAT_PITCH_MSK; + + if (DFB_PLANAR_PIXELFORMAT(config->format)) + format |= PVIDEO_FORMAT_PLANAR_NV; + + if (config->format == DSPF_UYVY) + format |= PVIDEO_FORMAT_COLOR_YB8CR8YA8CB8; + else + format |= PVIDEO_FORMAT_COLOR_CR8YB8CB8YA8; + + if (config->options & DLOP_DST_COLORKEY) + format |= PVIDEO_FORMAT_DISPLAY_COLOR_KEY_EQUAL; + + /* Use Buffer 0 for Odd field */ + nvov0->regs.OFFSET_0 = (nvdev->fb_offset + lock->offset) & PVIDEO_OFFSET_MSK; + /* Use Buffer 1 for Even field */ + nvov0->regs.OFFSET_1 = nvov0->regs.OFFSET_0 + lock->pitch; + if (DFB_PLANAR_PIXELFORMAT(config->format)) { + CoreSurface *surface = nvov0->videoSurface; + nvov0->regs.UVOFFSET_0 = (nvov0->regs.OFFSET_0 + + lock->pitch * surface->config.size.h) & PVIDEO_UVOFFSET_MSK; + nvov0->regs.UVOFFSET_1 = nvov0->regs.UVOFFSET_0 + lock->pitch; + } + nvov0->regs.FORMAT_0 = + nvov0->regs.FORMAT_1 = format; + } + + nvov0->regs.BUFFER = 1 << (nvov0->field << 2); + nvov0->regs.STOP = (config->opacity) + ? PVIDEO_STOP_OVERLAY_INACTIVE + : PVIDEO_STOP_OVERLAY_ACTIVE; + nvov0->regs.STOP |= PVIDEO_STOP_METHOD_NORMALLY; +} + +static void +ov0_set_colorkey( NVidiaDriverData *nvdrv, + NVidiaOverlayLayerData *nvov0, + CoreLayerRegionConfig *config ) +{ + u32 key; + + key = dfb_color_to_pixel( dfb_primary_layer_pixelformat(), + config->dst_key.r, + config->dst_key.g, + config->dst_key.b ); + + nv_out32( nvdrv->mmio_base, PVIDEO_COLOR_KEY, key ); +} + +static void +ov0_set_csc( NVidiaDriverData *nvdrv, + NVidiaOverlayLayerData *nvov0 ) +{ + volatile u8 *mmio = nvdrv->mmio_base; + s32 satSine; + s32 satCosine; + double angle; + + angle = (double) nvov0->hue * M_PI / 180.0; + satSine = nvov0->saturation * sin(angle); + if (satSine < -1024) + satSine = -1024; + satCosine = nvov0->saturation * cos(angle); + if (satCosine < -1024) + satCosine = -1024; + + nv_out32( mmio, PVIDEO_LUMINANCE_0, (nvov0->brightness << 16) | + (nvov0->contrast & 0xffff) ); + nv_out32( mmio, PVIDEO_LUMINANCE_1, (nvov0->brightness << 16) | + (nvov0->contrast & 0xffff) ); + nv_out32( mmio, PVIDEO_CHROMINANCE_0, (satSine << 16) | + (satCosine & 0xffff) ); + nv_out32( mmio, PVIDEO_CHROMINANCE_1, (satSine << 16) | + (satCosine & 0xffff) ); +} + -- cgit