summaryrefslogtreecommitdiff
path: root/Source/DirectFB/gfxdrivers/mach64/mach64_overlay.c
diff options
context:
space:
mode:
Diffstat (limited to 'Source/DirectFB/gfxdrivers/mach64/mach64_overlay.c')
-rwxr-xr-xSource/DirectFB/gfxdrivers/mach64/mach64_overlay.c724
1 files changed, 724 insertions, 0 deletions
diff --git a/Source/DirectFB/gfxdrivers/mach64/mach64_overlay.c b/Source/DirectFB/gfxdrivers/mach64/mach64_overlay.c
new file mode 100755
index 0000000..11cff28
--- /dev/null
+++ b/Source/DirectFB/gfxdrivers/mach64/mach64_overlay.c
@@ -0,0 +1,724 @@
+/*
+ (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 Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <config.h>
+
+#include <stdio.h>
+
+#include <direct/messages.h>
+
+#include <core/coredefs.h>
+#include <core/layers.h>
+#include <core/surface.h>
+#include <core/system.h>
+
+#include <gfx/convert.h>
+
+#include <misc/util.h>
+
+#include "regs.h"
+#include "mmio.h"
+#include "mach64.h"
+
+typedef struct {
+ CoreLayerRegionConfig config;
+ bool visible;
+
+ /* overlay registers */
+ struct {
+ u32 overlay_Y_X_START;
+ u32 overlay_Y_X_END;
+ u32 overlay_GRAPHICS_KEY_CLR;
+ u32 overlay_GRAPHICS_KEY_MSK;
+ u32 overlay_VIDEO_KEY_CLR;
+ u32 overlay_VIDEO_KEY_MSK;
+ u32 overlay_KEY_CNTL;
+ u32 overlay_SCALE_INC;
+ u32 overlay_SCALE_CNTL;
+ u32 scaler_HEIGHT_WIDTH;
+ u32 scaler_BUF_PITCH;
+ u32 scaler_BUF0_OFFSET;
+ u32 scaler_BUF1_OFFSET;
+ u32 scaler_BUF0_OFFSET_U;
+ u32 scaler_BUF0_OFFSET_V;
+ u32 scaler_BUF1_OFFSET_U;
+ u32 scaler_BUF1_OFFSET_V;
+ u32 video_FORMAT;
+ u32 capture_CONFIG;
+ } regs;
+} Mach64OverlayLayerData;
+
+static void ov_reset( Mach64DriverData *mdrv );
+static void ov_set_regs( Mach64DriverData *mdrv, Mach64OverlayLayerData *mov );
+static void ov_calc_regs( Mach64DriverData *mdrv, Mach64OverlayLayerData *mov,
+ CoreLayerRegionConfig *config, CoreSurface *surface,
+ CoreSurfaceBufferLock *lock );
+static void ov_set_buffer( Mach64DriverData *mdrv, Mach64OverlayLayerData *mov );
+static void ov_calc_buffer( Mach64DriverData *mdrv, Mach64OverlayLayerData *mov,
+ CoreLayerRegionConfig *config, CoreSurface *surface,
+ CoreSurfaceBufferLock *lock );
+static void ov_set_colorkey( Mach64DriverData *mdrv, Mach64OverlayLayerData *mov );
+static void ov_calc_colorkey( Mach64DriverData *mdrv, Mach64OverlayLayerData *mov,
+ CoreLayerRegionConfig *config );
+static void ov_set_opacity( Mach64DriverData *mdrv, Mach64OverlayLayerData *mov );
+static void ov_calc_opacity( Mach64DriverData *mdrv, Mach64OverlayLayerData *mov,
+ CoreLayerRegionConfig *config );
+static void ov_set_field( Mach64DriverData *mdrv, Mach64OverlayLayerData *mov );
+
+#define OV_SUPPORTED_OPTIONS (DLOP_SRC_COLORKEY | DLOP_DST_COLORKEY | DLOP_DEINTERLACING)
+
+/**********************/
+
+static int
+ovLayerDataSize( void )
+{
+ return sizeof(Mach64OverlayLayerData);
+}
+
+static DFBResult
+ovInitLayer( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ DFBDisplayLayerDescription *description,
+ DFBDisplayLayerConfig *config,
+ DFBColorAdjustment *adjustment )
+{
+ Mach64DriverData *mdrv = (Mach64DriverData*) driver_data;
+ Mach64DeviceData *mdev = mdrv->device_data;
+
+ /* set capabilities and type */
+ description->caps = DLCAPS_SCREEN_LOCATION | DLCAPS_SURFACE |
+ DLCAPS_DST_COLORKEY | DLCAPS_DEINTERLACING;
+
+ if (mdev->chip >= CHIP_264VT3)
+ description->caps |= DLCAPS_SRC_COLORKEY;
+
+ description->type = DLTF_VIDEO | DLTF_STILL_PICTURE;
+
+ /* set name */
+ snprintf( description->name,
+ DFB_DISPLAY_LAYER_DESC_NAME_LENGTH, "Mach64 Overlay" );
+
+ /* fill out the default configuration */
+ config->flags = DLCONF_WIDTH | DLCONF_HEIGHT |
+ DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE |
+ DLCONF_OPTIONS;
+ config->width = (mdev->chip >= CHIP_264VT3) ? 640 : 320;
+ config->height = (mdev->chip >= CHIP_264VT3) ? 480 : 240;
+ config->pixelformat = DSPF_YUY2;
+ config->buffermode = DLBM_FRONTONLY;
+ config->options = DLOP_NONE;
+
+ adjustment->flags = DCAF_NONE;
+
+ if (mdev->chip >= CHIP_3D_RAGE_PRO) {
+ description->caps |= DLCAPS_BRIGHTNESS | DLCAPS_SATURATION;
+
+ /* fill out default color adjustment,
+ only fields set in flags will be accepted from applications */
+ adjustment->flags |= DCAF_BRIGHTNESS | DCAF_SATURATION;
+ adjustment->brightness = 0x8000;
+ adjustment->saturation = 0x8000;
+ }
+
+ return DFB_OK;
+}
+
+static DFBResult
+ovTestRegion( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ CoreLayerRegionConfig *config,
+ CoreLayerRegionConfigFlags *failed )
+{
+ Mach64DriverData *mdrv = (Mach64DriverData*) driver_data;
+ Mach64DeviceData *mdev = mdrv->device_data;
+ CoreLayerRegionConfigFlags fail = 0;
+ int max_width, max_height = 1024;
+
+ switch (mdev->chip) {
+ case CHIP_264VT: /* 264VT2 verified */
+ case CHIP_3D_RAGE: /* not verified */
+ max_width = 384;
+ break;
+ case CHIP_264VT3: /* not verified */
+ case CHIP_3D_RAGE_II: /* not verified */
+ case CHIP_3D_RAGE_IIPLUS:
+ case CHIP_264VT4: /* not verified */
+ case CHIP_3D_RAGE_IIC:
+ case CHIP_3D_RAGE_XLXC:
+ case CHIP_3D_RAGE_MOBILITY:
+ max_width = 720;
+ break;
+ case CHIP_3D_RAGE_PRO: /* not verified */
+ case CHIP_3D_RAGE_LT_PRO:
+ max_width = 768;
+ break;
+ default:
+ D_BUG( "unknown chip" );
+ return DFB_UNSUPPORTED;
+ }
+
+ if (config->options & DLOP_DEINTERLACING)
+ max_height = 2048;
+
+ /* check for unsupported options */
+ if (config->options & ~OV_SUPPORTED_OPTIONS)
+ fail |= CLRCF_OPTIONS;
+
+ /*
+ * Video keying doesn't work the same way on 264VT2 as it does
+ * on later chips. If enabled the overlay goes completely black
+ * so clearly it does something but not what we want.
+ */
+ if (mdev->chip < CHIP_264VT3 && config->options & DLOP_SRC_COLORKEY)
+ fail |= CLRCF_OPTIONS;
+
+ /* check pixel format */
+ switch (config->format) {
+ case DSPF_RGB555:
+ case DSPF_ARGB1555:
+ case DSPF_RGB16:
+ case DSPF_RGB32:
+ case DSPF_YUY2:
+ case DSPF_UYVY:
+ break;
+ case DSPF_I420:
+ case DSPF_YV12:
+ if (mdev->chip >= CHIP_3D_RAGE_PRO)
+ break;
+ default:
+ fail |= CLRCF_FORMAT;
+ }
+
+ switch (config->format) {
+ case DSPF_I420:
+ case DSPF_YV12:
+ if (config->height & 1)
+ fail |= CLRCF_HEIGHT;
+ case DSPF_YUY2:
+ case DSPF_UYVY:
+ if (config->width & 1)
+ fail |= CLRCF_WIDTH;
+ default:
+ break;
+ }
+
+ /* check width */
+ if (config->width > max_width || config->width < 1)
+ fail |= CLRCF_WIDTH;
+
+ /* check height */
+ if (config->height > max_height || 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
+ovSetRegion( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data,
+ CoreLayerRegionConfig *config,
+ CoreLayerRegionConfigFlags updated,
+ CoreSurface *surface,
+ CorePalette *palette,
+ CoreSurfaceBufferLock *lock )
+{
+ Mach64DriverData *mdrv = (Mach64DriverData*) driver_data;
+ Mach64OverlayLayerData *mov = (Mach64OverlayLayerData*) layer_data;
+
+ /* remember configuration */
+ mov->config = *config;
+
+ if (updated == CLRCF_ALL)
+ ov_reset( mdrv );
+
+ if (updated & (CLRCF_WIDTH | CLRCF_HEIGHT | CLRCF_FORMAT | CLRCF_SOURCE | CLRCF_DEST | CLRCF_OPTIONS)) {
+ ov_calc_buffer( mdrv, mov, config, surface, lock );
+ ov_calc_regs( mdrv, mov, config, surface, lock );
+ ov_set_buffer( mdrv, mov );
+ ov_set_regs( mdrv, mov );
+ }
+
+ if (updated & (CLRCF_OPTIONS | CLRCF_SRCKEY | CLRCF_DSTKEY)) {
+ ov_calc_colorkey( mdrv, mov, config );
+ ov_set_colorkey( mdrv, mov );
+ }
+
+ if (updated & CLRCF_OPTIONS)
+ ov_set_field( mdrv, mov );
+
+ if (updated & (CLRCF_DEST | CLRCF_OPACITY)) {
+ ov_calc_opacity( mdrv, mov, config );
+ ov_set_opacity( mdrv, mov );
+ }
+
+ return DFB_OK;
+}
+
+static DFBResult
+ovRemoveRegion( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data )
+{
+ Mach64DriverData *mdrv = (Mach64DriverData*) driver_data;
+ Mach64DeviceData *mdev = mdrv->device_data;
+ volatile u8 *mmio = mdrv->mmio_base;
+
+ mach64_waitfifo( mdrv, mdev, 2 );
+
+ /*
+ * On 264VT2 the keyer sometimes remains active
+ * even after the overlay has been disabled.
+ */
+ mach64_out32( mmio, OVERLAY_KEY_CNTL,
+ VIDEO_KEY_FN_FALSE | GRAPHICS_KEY_FN_FALSE | OVERLAY_CMP_MIX_OR );
+
+ mach64_out32( mmio, OVERLAY_SCALE_CNTL, 0 );
+
+ return DFB_OK;
+}
+
+static DFBResult
+ovFlipRegion( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data,
+ CoreSurface *surface,
+ DFBSurfaceFlipFlags flags,
+ CoreSurfaceBufferLock *lock )
+{
+ Mach64DriverData *mdrv = (Mach64DriverData*) driver_data;
+ Mach64OverlayLayerData *mov = (Mach64OverlayLayerData*) layer_data;
+
+ ov_calc_buffer( mdrv, mov, &mov->config, surface, lock );
+ ov_set_buffer( mdrv, mov );
+
+ dfb_surface_flip( surface, false );
+
+ return DFB_OK;
+}
+
+static DFBResult
+ovSetColorAdjustment( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ DFBColorAdjustment *adj )
+{
+ Mach64DriverData *mdrv = (Mach64DriverData*) driver_data;
+ Mach64DeviceData *mdev = mdrv->device_data;
+ volatile u8 *mmio = mdrv->mmio_base;
+
+ if (mdev->chip < CHIP_3D_RAGE_PRO)
+ return DFB_UNSUPPORTED;
+
+ mach64_waitfifo( mdrv, mdev, 1 );
+
+ mach64_out32( mmio, SCALER_COLOUR_CNTL,
+ (((adj->brightness >> 9) - 64) & 0x0000007F) |
+ ((adj->saturation >> 3) & 0x00001F00) |
+ ((adj->saturation << 5) & 0x001F0000) );
+
+ return DFB_OK;
+}
+
+static DFBResult
+ovSetInputField( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data,
+ int field )
+{
+ Mach64DriverData *mdrv = (Mach64DriverData*) driver_data;
+ Mach64OverlayLayerData *mov = (Mach64OverlayLayerData*) layer_data;
+
+ mov->regs.capture_CONFIG = OVL_BUF_MODE_SINGLE | (field ? OVL_BUF_NEXT_BUF1 : OVL_BUF_NEXT_BUF0);
+
+ ov_set_field( mdrv, mov );
+
+ return DFB_OK;
+}
+
+DisplayLayerFuncs mach64OverlayFuncs = {
+ .LayerDataSize = ovLayerDataSize,
+ .InitLayer = ovInitLayer,
+
+ .TestRegion = ovTestRegion,
+ .SetRegion = ovSetRegion,
+ .RemoveRegion = ovRemoveRegion,
+ .FlipRegion = ovFlipRegion,
+ .SetColorAdjustment = ovSetColorAdjustment,
+ .SetInputField = ovSetInputField,
+};
+
+/* internal */
+
+static void ov_reset( Mach64DriverData *mdrv )
+{
+ Mach64DeviceData *mdev = mdrv->device_data;
+ volatile u8 *mmio = mdrv->mmio_base;
+
+ if (mdev->chip >= CHIP_3D_RAGE_PRO) {
+ mach64_waitfifo( mdrv, mdev, 6 );
+
+ mach64_out32( mmio, SCALER_H_COEFF0, 0x00002000 );
+ mach64_out32( mmio, SCALER_H_COEFF1, 0x0D06200D );
+ mach64_out32( mmio, SCALER_H_COEFF2, 0x0D0A1C0D );
+ mach64_out32( mmio, SCALER_H_COEFF3, 0x0C0E1A0C );
+ mach64_out32( mmio, SCALER_H_COEFF4, 0x0C14140C );
+ mach64_out32( mmio, SCALER_COLOUR_CNTL, 0x00101000 );
+ }
+
+ if (mdev->chip >= CHIP_264VT3) {
+ mach64_waitfifo( mdrv, mdev, 2 );
+
+ mach64_out32( mmio, OVERLAY_EXCLUSIVE_HORZ, 0 );
+ mach64_out32( mmio, OVERLAY_EXCLUSIVE_VERT, 0 );
+ }
+
+ mach64_waitfifo( mdrv, mdev, 2 );
+
+ mach64_out32( mmio, OVERLAY_SCALE_CNTL, 0 );
+ mach64_out32( mmio, SCALER_TEST, 0 );
+}
+
+static void ov_set_regs( Mach64DriverData *mdrv,
+ Mach64OverlayLayerData *mov )
+{
+ Mach64DeviceData *mdev = mdrv->device_data;
+ volatile u8 *mmio = mdrv->mmio_base;
+
+ mach64_waitfifo( mdrv, mdev, (mdev->chip >= CHIP_264VT3) ? 6 : 7 );
+
+ mach64_out32( mmio, VIDEO_FORMAT, mov->regs.video_FORMAT );
+ mach64_out32( mmio, OVERLAY_Y_X_START, mov->regs.overlay_Y_X_START );
+ mach64_out32( mmio, OVERLAY_Y_X_END, mov->regs.overlay_Y_X_END );
+ mach64_out32( mmio, OVERLAY_SCALE_INC, mov->regs.overlay_SCALE_INC );
+ mach64_out32( mmio, SCALER_HEIGHT_WIDTH, mov->regs.scaler_HEIGHT_WIDTH );
+
+ if (mdev->chip >= CHIP_264VT3) {
+ mach64_out32( mmio, SCALER_BUF_PITCH, mov->regs.scaler_BUF_PITCH );
+ } else {
+ mach64_out32( mmio, BUF0_PITCH, mov->regs.scaler_BUF_PITCH );
+ mach64_out32( mmio, BUF1_PITCH, mov->regs.scaler_BUF_PITCH );
+ }
+}
+
+static void ov_set_buffer( Mach64DriverData *mdrv,
+ Mach64OverlayLayerData *mov )
+{
+ Mach64DeviceData *mdev = mdrv->device_data;
+ volatile u8 *mmio = mdrv->mmio_base;
+
+ mach64_waitfifo( mdrv, mdev, (mdev->chip >= CHIP_3D_RAGE_PRO) ? 6 : 2 );
+
+ if (mdev->chip >= CHIP_264VT3) {
+ mach64_out32( mmio, SCALER_BUF0_OFFSET, mov->regs.scaler_BUF0_OFFSET );
+ mach64_out32( mmio, SCALER_BUF1_OFFSET, mov->regs.scaler_BUF1_OFFSET );
+ } else {
+ mach64_out32( mmio, BUF0_OFFSET, mov->regs.scaler_BUF0_OFFSET );
+ mach64_out32( mmio, BUF1_OFFSET, mov->regs.scaler_BUF1_OFFSET );
+ }
+
+ if (mdev->chip >= CHIP_3D_RAGE_PRO) {
+ mach64_out32( mmio, SCALER_BUF0_OFFSET_U, mov->regs.scaler_BUF0_OFFSET_U );
+ mach64_out32( mmio, SCALER_BUF0_OFFSET_V, mov->regs.scaler_BUF0_OFFSET_V );
+ mach64_out32( mmio, SCALER_BUF1_OFFSET_U, mov->regs.scaler_BUF1_OFFSET_U );
+ mach64_out32( mmio, SCALER_BUF1_OFFSET_V, mov->regs.scaler_BUF1_OFFSET_V );
+ }
+}
+
+static void ov_set_colorkey( Mach64DriverData *mdrv,
+ Mach64OverlayLayerData *mov )
+{
+ Mach64DeviceData *mdev = mdrv->device_data;
+ volatile u8 *mmio = mdrv->mmio_base;
+
+ mach64_waitfifo( mdrv, mdev, 5 );
+
+ mach64_out32( mmio, OVERLAY_GRAPHICS_KEY_CLR, mov->regs.overlay_GRAPHICS_KEY_CLR );
+ mach64_out32( mmio, OVERLAY_GRAPHICS_KEY_MSK, mov->regs.overlay_GRAPHICS_KEY_MSK );
+ mach64_out32( mmio, OVERLAY_VIDEO_KEY_CLR, mov->regs.overlay_VIDEO_KEY_CLR );
+ mach64_out32( mmio, OVERLAY_VIDEO_KEY_MSK, mov->regs.overlay_VIDEO_KEY_MSK );
+ mach64_out32( mmio, OVERLAY_KEY_CNTL, mov->regs.overlay_KEY_CNTL );
+}
+
+static void ov_set_opacity( Mach64DriverData *mdrv,
+ Mach64OverlayLayerData *mov )
+{
+ Mach64DeviceData *mdev = mdrv->device_data;
+ volatile u8 *mmio = mdrv->mmio_base;
+
+ mach64_waitfifo( mdrv, mdev, 1 );
+
+ mach64_out32( mmio, OVERLAY_SCALE_CNTL, mov->regs.overlay_SCALE_CNTL );
+}
+
+static void ov_set_field( Mach64DriverData *mdrv,
+ Mach64OverlayLayerData *mov )
+{
+ Mach64DeviceData *mdev = mdrv->device_data;
+ volatile u8 *mmio = mdrv->mmio_base;
+
+ mach64_waitfifo( mdrv, mdev, 1 );
+
+ mach64_out32( mmio, CAPTURE_CONFIG, mov->regs.capture_CONFIG );
+}
+
+static void ov_calc_regs( Mach64DriverData *mdrv,
+ Mach64OverlayLayerData *mov,
+ CoreLayerRegionConfig *config,
+ CoreSurface *surface,
+ CoreSurfaceBufferLock *lock )
+{
+ Mach64DeviceData *mdev = mdrv->device_data;
+ volatile u8 *mmio = mdrv->mmio_base;
+ VideoMode *mode = dfb_system_current_mode();
+ int yres = mode->yres;
+ unsigned int pitch = lock->pitch / DFB_BYTES_PER_PIXEL( surface->config.format );
+ DFBRectangle source = config->source;
+ DFBRectangle dest = config->dest;
+
+ DFBRegion dst;
+ int h_inc, v_inc;
+ u32 lcd_gen_ctrl, vert_stretching;
+ u8 ecp_div;
+
+ if (mode->doubled) {
+ dest.y *= 2;
+ dest.h *= 2;
+ yres *= 2;
+ }
+
+ if (config->options & DLOP_DEINTERLACING) {
+ source.y /= 2;
+ source.h /= 2;
+ pitch *= 2;
+ } else
+ mov->regs.capture_CONFIG = OVL_BUF_MODE_SINGLE | OVL_BUF_NEXT_BUF0;
+
+ dst.x1 = dest.x;
+ dst.y1 = dest.y;
+ dst.x2 = dest.x + dest.w - 1;
+ dst.y2 = dest.y + dest.h - 1;
+
+ mov->visible = dfb_region_intersect( &dst, 0, 0, mode->xres - 1, yres - 1 );
+
+ if (mode->laced) {
+ dest.y /= 2;
+ dest.h /= 2;
+ }
+
+ ecp_div = (mach64_in_pll( mmio, PLL_VCLK_CNTL ) & ECP_DIV) >> 4;
+ h_inc = (source.w << (12 + ecp_div)) / dest.w;
+
+ lcd_gen_ctrl = mach64_in_lcd( mdev, mmio, LCD_GEN_CTRL );
+ vert_stretching = mach64_in_lcd( mdev, mmio, VERT_STRETCHING );
+ if ((lcd_gen_ctrl & LCD_ON) && (vert_stretching & VERT_STRETCH_EN))
+ v_inc = (source.h << 2) * (vert_stretching & VERT_STRETCH_RATIO0) / dest.h;
+ else
+ v_inc = (source.h << 12) / dest.h;
+
+ switch (surface->config.format) {
+ case DSPF_RGB555:
+ case DSPF_ARGB1555:
+ mov->regs.video_FORMAT = SCALER_IN_RGB15;
+ break;
+ case DSPF_RGB16:
+ mov->regs.video_FORMAT = SCALER_IN_RGB16;
+ break;
+ case DSPF_RGB32:
+ mov->regs.video_FORMAT = SCALER_IN_RGB32;
+ break;
+ case DSPF_UYVY:
+ mov->regs.video_FORMAT = SCALER_IN_YVYU422;
+ break;
+ case DSPF_YUY2:
+ mov->regs.video_FORMAT = SCALER_IN_VYUY422;
+ break;
+ case DSPF_I420:
+ case DSPF_YV12:
+ mov->regs.video_FORMAT = SCALER_IN_YUV12;
+ break;
+ default:
+ D_BUG( "unexpected pixelformat" );
+ }
+
+ mov->regs.scaler_HEIGHT_WIDTH = (source.w << 16) | source.h;
+ mov->regs.scaler_BUF_PITCH = pitch;
+
+ mov->regs.overlay_Y_X_START = (dst.x1 << 16) | dst.y1 | OVERLAY_LOCK_START;
+ mov->regs.overlay_Y_X_END = (dst.x2 << 16) | dst.y2;
+ mov->regs.overlay_SCALE_INC = (h_inc << 16) | v_inc;
+}
+
+static void ov_calc_buffer( Mach64DriverData *mdrv,
+ Mach64OverlayLayerData *mov,
+ CoreLayerRegionConfig *config,
+ CoreSurface *surface,
+ CoreSurfaceBufferLock *lock )
+{
+ unsigned int pitch = lock->pitch;
+ DFBRectangle source = config->source;
+
+ u32 offset, offset_u, offset_v;
+ int cropleft, croptop;
+
+ if (config->options & DLOP_DEINTERLACING) {
+ source.y /= 2;
+ source.h /= 2;
+ pitch *= 2;
+ }
+
+ /* Source cropping */
+ cropleft = source.x;
+ croptop = source.y;
+
+ /* Add destination cropping */
+ if (config->dest.x < 0)
+ cropleft += -config->dest.x * source.w / config->dest.w;
+ if (config->dest.y < 0)
+ croptop += -config->dest.y * source.h / config->dest.h;
+
+ switch (surface->config.format) {
+ case DSPF_I420:
+ cropleft &= ~15;
+ croptop &= ~1;
+
+ offset_u = lock->offset + surface->config.size.h * lock->pitch;
+ offset_v = offset_u + surface->config.size.h/2 * lock->pitch/2;
+ offset_u += croptop/2 * pitch/2 + cropleft/2;
+ offset_v += croptop/2 * pitch/2 + cropleft/2;
+ break;
+
+ case DSPF_YV12:
+ cropleft &= ~15;
+ croptop &= ~1;
+
+ offset_v = lock->offset + surface->config.size.h * lock->pitch;
+ offset_u = offset_v + surface->config.size.h/2 * lock->pitch/2;
+ offset_v += croptop/2 * pitch/2 + cropleft/2;
+ offset_u += croptop/2 * pitch/2 + cropleft/2;
+ break;
+
+ default:
+ offset_u = 0;
+ offset_v = 0;
+ break;
+ }
+
+ offset = lock->offset;
+ offset += croptop * pitch + cropleft * DFB_BYTES_PER_PIXEL( surface->config.format );
+
+ mov->regs.scaler_BUF0_OFFSET = offset;
+ mov->regs.scaler_BUF0_OFFSET_U = offset_u;
+ mov->regs.scaler_BUF0_OFFSET_V = offset_v;
+
+ mov->regs.scaler_BUF1_OFFSET = offset + lock->pitch;
+ mov->regs.scaler_BUF1_OFFSET_U = offset_u + lock->pitch/2;
+ mov->regs.scaler_BUF1_OFFSET_V = offset_v + lock->pitch/2;
+}
+
+static u32 ovColorKey[] = {
+ VIDEO_KEY_FN_TRUE | GRAPHICS_KEY_FN_TRUE | OVERLAY_CMP_MIX_OR, /* 0 */
+ VIDEO_KEY_FN_NOT_EQUAL | GRAPHICS_KEY_FN_FALSE | OVERLAY_CMP_MIX_OR, /* DLOP_SRC_COLORKEY */
+ VIDEO_KEY_FN_FALSE | GRAPHICS_KEY_FN_EQUAL | OVERLAY_CMP_MIX_OR, /* DLOP_DST_COLORKEY */
+ VIDEO_KEY_FN_NOT_EQUAL | GRAPHICS_KEY_FN_EQUAL | OVERLAY_CMP_MIX_AND /* DLOP_SRC_COLORKEY |
+ DLOP_DST_COLORKEY */
+};
+
+static void ov_calc_colorkey( Mach64DriverData *mdrv,
+ Mach64OverlayLayerData *mov,
+ CoreLayerRegionConfig *config )
+{
+ DFBSurfacePixelFormat primary_format = dfb_primary_layer_pixelformat();
+
+ /* Video key is always RGB24 */
+ mov->regs.overlay_VIDEO_KEY_CLR = PIXEL_RGB32( config->src_key.r,
+ config->src_key.g,
+ config->src_key.b );
+
+ /* The same mask is used for all three components */
+ mov->regs.overlay_VIDEO_KEY_MSK = 0xFF;
+
+ switch (primary_format) {
+ case DSPF_RGB332:
+ mov->regs.overlay_GRAPHICS_KEY_CLR = PIXEL_RGB332( config->dst_key.r,
+ config->dst_key.g,
+ config->dst_key.b );
+ break;
+ case DSPF_RGB555:
+ mov->regs.overlay_GRAPHICS_KEY_CLR = PIXEL_RGB555( config->dst_key.r,
+ config->dst_key.g,
+ config->dst_key.b );
+ break;
+ case DSPF_ARGB1555:
+ mov->regs.overlay_GRAPHICS_KEY_CLR = PIXEL_RGB555( config->dst_key.r,
+ config->dst_key.g,
+ config->dst_key.b );
+ break;
+ case DSPF_RGB16:
+ mov->regs.overlay_GRAPHICS_KEY_CLR = PIXEL_RGB16( config->dst_key.r,
+ config->dst_key.g,
+ config->dst_key.b );
+ break;
+ case DSPF_ARGB:
+ case DSPF_RGB32:
+ mov->regs.overlay_GRAPHICS_KEY_CLR = PIXEL_RGB32( config->dst_key.r,
+ config->dst_key.g,
+ config->dst_key.b );
+ break;
+ default:
+ D_BUG( "unexpected pixelformat" );
+ }
+
+ mov->regs.overlay_GRAPHICS_KEY_MSK = (1 << DFB_COLOR_BITS_PER_PIXEL( primary_format )) - 1;
+
+ mov->regs.overlay_KEY_CNTL = ovColorKey[(config->options >> 3) & 3];
+}
+
+static void ov_calc_opacity( Mach64DriverData *mdrv,
+ Mach64OverlayLayerData *mov,
+ CoreLayerRegionConfig *config )
+{
+ mov->regs.overlay_SCALE_CNTL = SCALE_PIX_EXPAND | SCALE_Y2R_TEMP;
+
+ if (config->opacity && mov->visible)
+ mov->regs.overlay_SCALE_CNTL |= OVERLAY_EN | SCALE_EN;
+}