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/neomagic/neo2200.c | 570 ++++++++++++++++++++++++++ 1 file changed, 570 insertions(+) create mode 100755 Source/DirectFB/gfxdrivers/neomagic/neo2200.c (limited to 'Source/DirectFB/gfxdrivers/neomagic/neo2200.c') diff --git a/Source/DirectFB/gfxdrivers/neomagic/neo2200.c b/Source/DirectFB/gfxdrivers/neomagic/neo2200.c new file mode 100755 index 0000000..4ac54ac --- /dev/null +++ b/Source/DirectFB/gfxdrivers/neomagic/neo2200.c @@ -0,0 +1,570 @@ +/* + (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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä 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 + +#include + +#include "neomagic.h" + +typedef volatile struct { + u32 bltStat; + u32 bltCntl; + u32 xpColor; + u32 fgColor; + u32 bgColor; + u32 pitch; + u32 clipLT; + u32 clipRB; + u32 srcBitOffset; + u32 srcStart; + u32 reserved0; + u32 dstStart; + u32 xyExt; + + u32 reserved1[19]; + + u32 pageCntl; + u32 pageBase; + u32 postBase; + u32 postPtr; + u32 dataPtr; +} Neo2200; + +typedef struct { + NeoDeviceData neo; + + int dstOrg; + int dstPitch; + int dstPixelWidth; + + int srcOrg; + int srcPitch; + int srcPixelWidth; + + u32 bltCntl; + + bool src_dst_equal; + + /* state validation */ + int n_bltMode_dst; + int n_src; + int n_fgColor; + int n_xpColor; +} Neo2200DeviceData; + +typedef struct { + NeoDriverData neo; + + Neo2200 *neo2200; +} Neo2200DriverData; + + +static inline void neo2200_waitidle( Neo2200DriverData *ndrv, + Neo2200DeviceData *ndev ) +{ + while (ndrv->neo2200->bltStat & 1) + ndev->neo.idle_waitcycles++; +} + +static inline void neo2200_waitfifo( Neo2200DriverData *ndrv, + Neo2200DeviceData *ndev, + int requested_fifo_space ) +{ + ndev->neo.waitfifo_calls++; + ndev->neo.waitfifo_sum += requested_fifo_space; + + /* FIXME: does not work + if (neo_fifo_space < requested_fifo_space) + { + neo_fifo_waitcycles++; + + while (1) + { + neo_fifo_space = (neo2200->bltStat >> 8); + if (neo_fifo_space >= requested_fifo_space) + break; + } + } + else + { + neo_fifo_cache_hits++; + } + + neo_fifo_space -= requested_fifo_space; + */ + + neo2200_waitidle( ndrv, ndev ); +} + + + +static inline void neo2200_validate_bltMode_dst( Neo2200DriverData *ndrv, + Neo2200DeviceData *ndev, + CoreSurface *dst, + CoreSurfaceBufferLock *lock ) +{ + int bltMode = 0; + + if (ndev->n_bltMode_dst) + return; + + switch (dst->config.format) + { + case DSPF_A8: + case DSPF_LUT8: + case DSPF_RGB332: + bltMode |= NEO_MODE1_DEPTH8; + break; + case DSPF_ARGB1555: + case DSPF_RGB16: + case DSPF_YUY2: + bltMode |= NEO_MODE1_DEPTH16; + break; + default: + D_BUG( "unexpected pixelformat!" ); + break; + } + + ndev->dstOrg = lock->offset; + ndev->dstPitch = lock->pitch; + ndev->dstPixelWidth = DFB_BYTES_PER_PIXEL(dst->config.format); + + + neo2200_waitfifo( ndrv, ndev, 2 ); + + ndrv->neo2200->bltStat = bltMode << 16; + ndrv->neo2200->pitch = (ndev->dstPitch << 16) | (ndev->srcPitch & 0xffff); + + + ndev->n_bltMode_dst = 1; +} + +static inline void neo2200_validate_src( Neo2200DriverData *ndrv, + Neo2200DeviceData *ndev, + CoreSurface *src, + CoreSurfaceBufferLock *lock ) +{ + if (ndev->n_src) + return; + + ndev->srcOrg = lock->offset; + ndev->srcPitch = lock->pitch; + ndev->srcPixelWidth = DFB_BYTES_PER_PIXEL(src->config.format); + + neo2200_waitfifo( ndrv, ndev, 1 ); + ndrv->neo2200->pitch = (ndev->dstPitch << 16) | (ndev->srcPitch & 0xffff); + + ndev->n_src = 1; +} + +static inline void neo2200_validate_fgColor( Neo2200DriverData *ndrv, + Neo2200DeviceData *ndev, + CardState *state ) +{ + if (ndev->n_fgColor) + return; + + neo2200_waitfifo( ndrv, ndev, 1 ); + + switch (state->destination->config.format) + { + case DSPF_A8: + ndrv->neo2200->fgColor = state->color.a; + break; + case DSPF_LUT8: + ndrv->neo2200->fgColor = state->color_index; + break; + case DSPF_RGB332: + ndrv->neo2200->fgColor = PIXEL_RGB332( state->color.r, + state->color.g, + state->color.b ); + break; + case DSPF_ARGB1555: + ndrv->neo2200->fgColor = PIXEL_ARGB1555( state->color.a, + state->color.r, + state->color.g, + state->color.b ); + break; + case DSPF_RGB16: + ndrv->neo2200->fgColor = PIXEL_RGB16( state->color.r, + state->color.g, + state->color.b ); + break; + default: + D_BUG( "unexpected pixelformat!" ); + break; + } + + ndev->n_fgColor = 1; +} + +static inline void neo2200_validate_xpColor( Neo2200DriverData *ndrv, + Neo2200DeviceData *ndev, + CardState *state ) +{ + if (ndev->n_xpColor) + return; + + neo2200_waitfifo( ndrv, ndev, 1 ); + + ndrv->neo2200->xpColor = state->src_colorkey; + + ndev->n_xpColor = 1; +} + + +/* required implementations */ + +static DFBResult neo2200EngineSync( void *drv, void *dev ) +{ + Neo2200DriverData *ndrv = (Neo2200DriverData*) drv; + Neo2200DeviceData *ndev = (Neo2200DeviceData*) dev; + + neo2200_waitidle( ndrv, ndev ); + + return DFB_OK; +} + +#define NEO_SUPPORTED_DRAWINGFLAGS \ + (DSDRAW_NOFX) + +#define NEO_SUPPORTED_DRAWINGFUNCTIONS \ + (DFXL_FILLRECTANGLE | DFXL_DRAWRECTANGLE) + +#define NEO_SUPPORTED_BLITTINGFLAGS \ + (DSBLIT_SRC_COLORKEY) + +#define NEO_SUPPORTED_BLITTINGFUNCTIONS \ + (DFXL_BLIT) + +static void neo2200CheckState( void *drv, void *dev, + CardState *state, DFBAccelerationMask accel ) +{ + switch (state->destination->config.format) + { + case DSPF_A8: + case DSPF_LUT8: + case DSPF_RGB332: + case DSPF_ARGB1555: + case DSPF_RGB16: + break; + case DSPF_YUY2: + if (accel == DFXL_BLIT) + break; + default: + return; + } + + if (DFB_DRAWING_FUNCTION(accel)) + { + /* if the function is supported and there are no other + drawing flags than the supported */ + if (!(accel & ~NEO_SUPPORTED_DRAWINGFUNCTIONS) && + !(state->drawingflags & ~NEO_SUPPORTED_DRAWINGFLAGS)) + state->accel |= accel; + } + else + { + /* if the function is supported, there are no other + blitting flags than the supported, the source and + destination formats are the same and the source and dest. + are different due to a blitting bug */ + if (!(accel & ~NEO_SUPPORTED_BLITTINGFUNCTIONS) && + !(state->blittingflags & ~NEO_SUPPORTED_BLITTINGFLAGS) && + state->source->config.format == state->destination->config.format) + state->accel |= accel; + } +} + +static void neo2200SetState( void *drv, void *dev, + GraphicsDeviceFuncs *funcs, + CardState *state, DFBAccelerationMask accel ) +{ + Neo2200DriverData *ndrv = (Neo2200DriverData*) drv; + Neo2200DeviceData *ndev = (Neo2200DeviceData*) dev; + + if (state->mod_hw & SMF_DESTINATION) + ndev->n_fgColor = ndev->n_bltMode_dst = 0; + else if (state->mod_hw & SMF_COLOR) + ndev->n_fgColor = 0; + + if (state->mod_hw & SMF_SOURCE) + ndev->n_src = 0; + + if (state->mod_hw & SMF_SRC_COLORKEY) + ndev->n_xpColor = 0; + + neo2200_validate_bltMode_dst( ndrv, ndev, state->destination, &state->dst ); + + switch (accel) { + case DFXL_BLIT: + neo2200_validate_src( ndrv, ndev, state->source, &state->src ); + + ndev->src_dst_equal = (state->src.buffer == + state->dst.buffer); + + if (state->blittingflags & DSBLIT_SRC_COLORKEY) { + ndev->bltCntl = NEO_BC0_SRC_TRANS; + neo2200_validate_xpColor( ndrv, ndev, state ); + } + else + ndev->bltCntl = 0; + + state->set |= DFXL_BLIT; + break; + + case DFXL_FILLRECTANGLE: + case DFXL_DRAWRECTANGLE: + neo2200_validate_fgColor( ndrv, ndev, state ); + + state->set |= DFXL_FILLRECTANGLE | DFXL_DRAWRECTANGLE; + break; + + default: + D_BUG( "unexpected drawing/blitting function!" ); + break; + } + + state->mod_hw = 0; +} + +static bool neo2200FillRectangle( void *drv, void *dev, DFBRectangle *rect ) +{ + Neo2200DriverData *ndrv = (Neo2200DriverData*) drv; + Neo2200DeviceData *ndev = (Neo2200DeviceData*) dev; + Neo2200 *neo2200 = ndrv->neo2200; + + neo2200_waitfifo( ndrv, ndev, 3 ); + + /* set blt control */ + neo2200->bltCntl = NEO_BC3_FIFO_EN | + NEO_BC0_SRC_IS_FG | + NEO_BC3_SKIP_MAPPING | 0x0c0000; + + neo2200->dstStart = ndev->dstOrg + + (rect->y * ndev->dstPitch) + + (rect->x * ndev->dstPixelWidth); + + neo2200->xyExt = (rect->h << 16) | (rect->w & 0xffff); + + return true; +} + +static bool neo2200DrawRectangle( void *drv, void *dev, DFBRectangle *rect ) +{ + Neo2200DriverData *ndrv = (Neo2200DriverData*) drv; + Neo2200DeviceData *ndev = (Neo2200DeviceData*) dev; + Neo2200 *neo2200 = ndrv->neo2200; + + u32 dst = ndev->dstOrg + + (rect->y * ndev->dstPitch) + + (rect->x * ndev->dstPixelWidth); + + neo2200_waitfifo( ndrv, ndev, 3 ); + + /* set blt control */ + neo2200->bltCntl = NEO_BC3_FIFO_EN | + NEO_BC0_SRC_IS_FG | + NEO_BC3_SKIP_MAPPING | 0x0c0000; + + neo2200->dstStart = dst; + neo2200->xyExt = (1 << 16) | (rect->w & 0xffff); + + + dst += (rect->h - 1) * ndev->dstPitch; + neo2200_waitfifo( ndrv, ndev, 2 ); + neo2200->dstStart = dst; + neo2200->xyExt = (1 << 16) | (rect->w & 0xffff); + + + dst -= (rect->h - 2) * ndev->dstPitch; + neo2200_waitfifo( ndrv, ndev, 2 ); + neo2200->dstStart = dst; + neo2200->xyExt = ((rect->h - 2) << 16) | 1; + + + dst += (rect->w - 1) * ndev->dstPixelWidth; + neo2200_waitfifo( ndrv, ndev, 2 ); + neo2200->dstStart = dst; + neo2200->xyExt = ((rect->h - 2) << 16) | 1; + + return true; +} + +static bool neo2200Blit( void *drv, void *dev, + DFBRectangle *rect, int dx, int dy ) +{ + Neo2200DriverData *ndrv = (Neo2200DriverData*) drv; + Neo2200DeviceData *ndev = (Neo2200DeviceData*) dev; + Neo2200 *neo2200 = ndrv->neo2200; + + u32 src_start, dst_start; + u32 bltCntl = ndev->bltCntl; + +// fprintf(stderr, "blit: %d, %d (%dx%d) -> %d, %d\n", +// rect->x, rect->y, rect->w, rect->h, dx, dy); + +/* if (rect->x < dx) { + //rect->x += rect->w - 1; + //dx += rect->w - 1; + + bltCntl |= NEO_BC0_X_DEC; + } + + if (rect->y < dy) { + //rect->y += rect->h - 1; + //dy += rect->h - 1; + + bltCntl |= NEO_BC0_DST_Y_DEC | NEO_BC0_SRC_Y_DEC; + } +*/ + /* ARGH, the above code for the blitting direction doesn't work. */ + if (ndev->src_dst_equal && (rect->x < dx || rect->y < dy)) + return false; + + src_start = rect->y * ndev->srcPitch + rect->x * ndev->srcPixelWidth; + dst_start = dy * ndev->dstPitch + dx * ndev->dstPixelWidth; + + neo2200_waitfifo( ndrv, ndev, 4 ); + + /* set blt control */ + neo2200->bltCntl = bltCntl | + NEO_BC3_FIFO_EN | + NEO_BC3_SKIP_MAPPING | 0x0c0000; + + /* set start addresses */ + neo2200->srcStart = ndev->srcOrg + src_start; + neo2200->dstStart = ndev->dstOrg + dst_start; + + /* set size */ + neo2200->xyExt = (rect->h << 16) | (rect->w & 0xffff); + + return true; +} + + + +void +neo2200_get_info( CoreGraphicsDevice *device, + GraphicsDriverInfo *info ) +{ + info->version.major = 0; + info->version.minor = 3; + + info->driver_data_size = sizeof (Neo2200DriverData); + info->device_data_size = sizeof (Neo2200DeviceData); +} + +DFBResult +neo2200_init_driver( CoreGraphicsDevice *device, + GraphicsDeviceFuncs *funcs, + void *driver_data ) +{ + Neo2200DriverData *ndrv = (Neo2200DriverData*) driver_data; + + ndrv->neo2200 = (Neo2200*) ndrv->neo.mmio_base; + + funcs->CheckState = neo2200CheckState; + funcs->SetState = neo2200SetState; + funcs->EngineSync = neo2200EngineSync; + + funcs->FillRectangle = neo2200FillRectangle; + funcs->DrawRectangle = neo2200DrawRectangle; + // funcs->DrawLine = neoDrawLine2D; + funcs->Blit = neo2200Blit; + // funcs->StretchBlit = neoStretchBlit; + + /* overlay support */ + dfb_layers_register( dfb_screens_at(DSCID_PRIMARY), + driver_data, &neoOverlayFuncs ); + return DFB_OK; +} + +DFBResult +neo2200_init_device( CoreGraphicsDevice *device, + GraphicsDeviceInfo *device_info, + void *driver_data, + void *device_data ) +{ + /* fill device info */ + snprintf( device_info->name, + DFB_GRAPHICS_DEVICE_INFO_NAME_LENGTH, "2200/2230/2360/2380" ); + + snprintf( device_info->vendor, + DFB_GRAPHICS_DEVICE_INFO_VENDOR_LENGTH, "NeoMagic" ); + + + device_info->caps.flags = 0; + device_info->caps.accel = NEO_SUPPORTED_DRAWINGFUNCTIONS | + NEO_SUPPORTED_BLITTINGFUNCTIONS; + device_info->caps.drawing = NEO_SUPPORTED_DRAWINGFLAGS; + device_info->caps.blitting = NEO_SUPPORTED_BLITTINGFLAGS; + + device_info->limits.surface_byteoffset_alignment = 32 * 4; + device_info->limits.surface_pixelpitch_alignment = 32; + + return DFB_OK; +} + +void +neo2200_close_device( CoreGraphicsDevice *device, + void *driver_data, + void *device_data ) +{ +} + +void +neo2200_close_driver( CoreGraphicsDevice *device, + void *driver_data ) +{ +} + -- cgit