summaryrefslogtreecommitdiff
path: root/Source/DirectFB/gfxdrivers/neomagic/neo_overlay.c
diff options
context:
space:
mode:
Diffstat (limited to 'Source/DirectFB/gfxdrivers/neomagic/neo_overlay.c')
-rwxr-xr-xSource/DirectFB/gfxdrivers/neomagic/neo_overlay.c349
1 files changed, 349 insertions, 0 deletions
diff --git a/Source/DirectFB/gfxdrivers/neomagic/neo_overlay.c b/Source/DirectFB/gfxdrivers/neomagic/neo_overlay.c
new file mode 100755
index 0000000..b0d4c42
--- /dev/null
+++ b/Source/DirectFB/gfxdrivers/neomagic/neo_overlay.c
@@ -0,0 +1,349 @@
+/*
+ (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 <sys/io.h>
+
+#include <core/coredefs.h>
+#include <core/layers.h>
+#include <core/surface.h>
+
+#include "neomagic.h"
+
+typedef struct {
+ CoreLayerRegionConfig config;
+
+ /* overlay registers */
+ struct {
+ u32 OFFSET;
+ u16 PITCH;
+ u16 X1;
+ u16 X2;
+ u16 Y1;
+ u16 Y2;
+ u16 HSCALE;
+ u16 VSCALE;
+ u8 CONTROL;
+ } regs;
+} NeoOverlayLayerData;
+
+static void ovl_set_regs ( NeoDriverData *ndrv,
+ NeoOverlayLayerData *novl );
+static void ovl_calc_regs( NeoDriverData *ndrv,
+ NeoOverlayLayerData *novl,
+ CoreLayerRegionConfig *config,
+ CoreSurface *surface,
+ CoreSurfaceBufferLock *lock );
+
+#define NEO_OVERLAY_SUPPORTED_OPTIONS (DLOP_NONE)
+
+/**********************/
+
+static int
+ovlLayerDataSize( void )
+{
+ return sizeof(NeoOverlayLayerData);
+}
+
+static DFBResult
+ovlInitLayer( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ DFBDisplayLayerDescription *description,
+ DFBDisplayLayerConfig *default_config,
+ DFBColorAdjustment *default_adj )
+{
+ /* set capabilities and type */
+ description->caps = DLCAPS_SCREEN_LOCATION | DLCAPS_SURFACE |
+ DLCAPS_BRIGHTNESS;
+ description->type = DLTF_VIDEO | DLTF_STILL_PICTURE;
+
+ /* set name */
+ snprintf( description->name,
+ DFB_DISPLAY_LAYER_DESC_NAME_LENGTH, "NeoMagic Overlay" );
+
+ /* fill out the default configuration */
+ default_config->flags = DLCONF_WIDTH | DLCONF_HEIGHT |
+ DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE |
+ DLCONF_OPTIONS;
+ default_config->width = 640;
+ default_config->height = 480;
+ default_config->pixelformat = DSPF_YUY2;
+ default_config->buffermode = DLBM_FRONTONLY;
+ default_config->options = DLOP_NONE;
+
+ /* fill out default color adjustment,
+ only fields set in flags will be accepted from applications */
+ default_adj->flags = DCAF_BRIGHTNESS;
+ default_adj->brightness = 0x8000;
+
+ /* FIXME: use mmio */
+ if (iopl(3) < 0) {
+ D_PERROR( "NeoMagic/Overlay: Could not change I/O permission level!\n" );
+ return DFB_UNSUPPORTED;
+ }
+
+ neo_unlock();
+
+ /* reset overlay */
+ OUTGR(0xb0, 0x00);
+
+ /* reset brightness */
+ OUTGR(0xc4, 0x00);
+
+ /* disable capture */
+ OUTGR(0x0a, 0x21);
+ OUTSR(0x08, 0xa0);
+ OUTGR(0x0a, 0x01);
+
+ neo_lock();
+
+ return DFB_OK;
+}
+
+
+static void
+ovlOnOff( NeoDriverData *ndrv,
+ NeoOverlayLayerData *novl,
+ int on )
+{
+ /* set/clear enable bit */
+ if (on)
+ novl->regs.CONTROL = 0x01;
+ else
+ novl->regs.CONTROL = 0x00;
+
+ /* FIXME: use mmio */
+ if (iopl(3) < 0) {
+ D_PERROR( "NeoMagic/Overlay: Could not change I/O permission level!\n" );
+ return;
+ }
+
+ /* write back to card */
+ neo_unlock();
+ OUTGR(0xb0, novl->regs.CONTROL);
+ neo_lock();
+}
+
+static DFBResult
+ovlTestRegion( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ CoreLayerRegionConfig *config,
+ CoreLayerRegionConfigFlags *failed )
+{
+ CoreLayerRegionConfigFlags fail = 0;
+
+ /* check for unsupported options */
+ if (config->options & ~NEO_OVERLAY_SUPPORTED_OPTIONS)
+ fail |= CLRCF_OPTIONS;
+
+ /* check pixel format */
+ switch (config->format) {
+ case DSPF_YUY2:
+ break;
+
+ default:
+ fail |= CLRCF_FORMAT;
+ }
+
+ /* check width */
+ if (config->width > 1024 || config->width < 160)
+ fail |= CLRCF_WIDTH;
+
+ /* check height */
+ if (config->height > 1024 || 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
+ovlSetRegion( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data,
+ CoreLayerRegionConfig *config,
+ CoreLayerRegionConfigFlags updated,
+ CoreSurface *surface,
+ CorePalette *palette,
+ CoreSurfaceBufferLock *lock )
+{
+ NeoDriverData *ndrv = (NeoDriverData*) driver_data;
+ NeoOverlayLayerData *novl = (NeoOverlayLayerData*) layer_data;
+
+ /* remember configuration */
+ novl->config = *config;
+
+ ovl_calc_regs( ndrv, novl, config, surface, lock );
+ ovl_set_regs( ndrv, novl );
+
+ /* enable overlay */
+ ovlOnOff( ndrv, novl, config->opacity );
+
+ return DFB_OK;
+}
+
+static DFBResult
+ovlRemoveRegion( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data )
+{
+ NeoDriverData *ndrv = (NeoDriverData*) driver_data;
+ NeoOverlayLayerData *novl = (NeoOverlayLayerData*) layer_data;
+
+ /* disable overlay */
+ ovlOnOff( ndrv, novl, 0 );
+
+ return DFB_OK;
+}
+
+static DFBResult
+ovlFlipRegion( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data,
+ CoreSurface *surface,
+ DFBSurfaceFlipFlags flags,
+ CoreSurfaceBufferLock *lock )
+{
+ NeoDriverData *ndrv = (NeoDriverData*) driver_data;
+ NeoOverlayLayerData *novl = (NeoOverlayLayerData*) layer_data;
+#if 0
+ bool onsync = (flags & DSFLIP_WAITFORSYNC);
+
+ if (onsync)
+ dfb_fbdev_wait_vsync();
+#endif
+
+ dfb_surface_flip( surface, false );
+
+ ovl_calc_regs( ndrv, novl, &novl->config, surface, lock );
+ ovl_set_regs( ndrv, novl );
+
+ return DFB_OK;
+}
+
+static DFBResult
+ovlSetColorAdjustment( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ DFBColorAdjustment *adj )
+{
+ /* FIXME: use mmio */
+ if (iopl(3) < 0) {
+ D_PERROR( "NeoMagic/Overlay: Could not change I/O permission level!\n" );
+ return DFB_UNSUPPORTED;
+ }
+
+ neo_unlock();
+ OUTGR(0xc4, (signed char)((adj->brightness >> 8) -128));
+ neo_lock();
+
+ return DFB_OK;
+}
+
+
+DisplayLayerFuncs neoOverlayFuncs = {
+ .LayerDataSize = ovlLayerDataSize,
+ .InitLayer = ovlInitLayer,
+ .SetRegion = ovlSetRegion,
+ .RemoveRegion = ovlRemoveRegion,
+ .TestRegion = ovlTestRegion,
+ .FlipRegion = ovlFlipRegion,
+ .SetColorAdjustment = ovlSetColorAdjustment,
+};
+
+
+/* internal */
+
+static void ovl_set_regs( NeoDriverData *ndrv, NeoOverlayLayerData *novl )
+{
+ /* FIXME: use mmio */
+ if (iopl(3) < 0) {
+ D_PERROR( "NeoMagic/Overlay: Could not change I/O permission level!\n" );
+ return;
+ }
+
+ neo_unlock();
+
+ OUTGR(0xb1, ((novl->regs.X2 >> 4) & 0xf0) | (novl->regs.X1 >> 8));
+ OUTGR(0xb2, novl->regs.X1);
+ OUTGR(0xb3, novl->regs.X2);
+ OUTGR(0xb4, ((novl->regs.Y2 >> 4) & 0xf0) | (novl->regs.Y1 >> 8));
+ OUTGR(0xb5, novl->regs.Y1);
+ OUTGR(0xb6, novl->regs.Y2);
+ OUTGR(0xb7, novl->regs.OFFSET >> 16);
+ OUTGR(0xb8, novl->regs.OFFSET >> 8);
+ OUTGR(0xb9, novl->regs.OFFSET);
+ OUTGR(0xba, novl->regs.PITCH >> 8);
+ OUTGR(0xbb, novl->regs.PITCH);
+ OUTGR(0xbc, 0x2e); /* Neo2160: 0x4f */
+ OUTGR(0xbd, 0x02);
+ OUTGR(0xbe, 0x00);
+ OUTGR(0xbf, 0x02);
+
+ OUTGR(0xc0, novl->regs.HSCALE >> 8);
+ OUTGR(0xc1, novl->regs.HSCALE);
+ OUTGR(0xc2, novl->regs.VSCALE >> 8);
+ OUTGR(0xc3, novl->regs.VSCALE);
+
+ neo_lock();
+}
+
+static void ovl_calc_regs( NeoDriverData *ndrv,
+ NeoOverlayLayerData *novl,
+ CoreLayerRegionConfig *config,
+ CoreSurface *surface,
+ CoreSurfaceBufferLock *lock )
+{
+ /* fill register struct */
+ novl->regs.X1 = config->dest.x;
+ novl->regs.X2 = config->dest.x + config->dest.w - 1;
+
+ novl->regs.Y1 = config->dest.y;
+ novl->regs.Y2 = config->dest.y + config->dest.h - 1;
+
+ novl->regs.OFFSET = lock->offset;
+ novl->regs.PITCH = lock->pitch;
+
+ novl->regs.HSCALE = (surface->config.size.w << 12) / (config->dest.w + 1);
+ novl->regs.VSCALE = (surface->config.size.h << 12) / (config->dest.h + 1);
+}
+