summaryrefslogtreecommitdiff
path: root/Source/DirectFB/gfxdrivers/davinci/davinci_2d.c
diff options
context:
space:
mode:
Diffstat (limited to 'Source/DirectFB/gfxdrivers/davinci/davinci_2d.c')
-rwxr-xr-xSource/DirectFB/gfxdrivers/davinci/davinci_2d.c1050
1 files changed, 1050 insertions, 0 deletions
diff --git a/Source/DirectFB/gfxdrivers/davinci/davinci_2d.c b/Source/DirectFB/gfxdrivers/davinci/davinci_2d.c
new file mode 100755
index 0000000..7b97fb7
--- /dev/null
+++ b/Source/DirectFB/gfxdrivers/davinci/davinci_2d.c
@@ -0,0 +1,1050 @@
+/*
+ TI Davinci driver - 2D Acceleration
+
+ (c) Copyright 2007 Telio AG
+
+ Written by Denis Oliver Kropp <dok@directfb.org>
+
+ Code is derived from VMWare driver.
+
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ 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.
+
+ 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.
+*/
+
+//#define DIRECT_ENABLE_DEBUG
+
+#include <config.h>
+
+#include <asm/types.h>
+
+#include <directfb.h>
+
+#include <direct/debug.h>
+#include <direct/memcpy.h>
+#include <direct/messages.h>
+
+#include <core/state.h>
+#include <core/surface.h>
+
+#include <gfx/convert.h>
+
+#include "davinci_2d.h"
+#include "davinci_gfxdriver.h"
+
+
+D_DEBUG_DOMAIN( Davinci_2D, "Davinci/2D", "Davinci 2D Acceleration" );
+
+/*
+ * State validation flags.
+ *
+ * There's no prefix because of the macros below.
+ */
+enum {
+ DESTINATION = 0x00000001,
+ FILLCOLOR = 0x00000002,
+
+ SOURCE = 0x00000010,
+ SOURCE_MULT = 0x00000020,
+
+ BLIT_BLEND_SUB = 0x00010000,
+ DRAW_BLEND_SUB = 0x00020000,
+
+ ALL = 0x00030033
+};
+
+/*
+ * State handling macros.
+ */
+
+#define DAVINCI_VALIDATE(flags) do { ddev->v_flags |= (flags); } while (0)
+#define DAVINCI_INVALIDATE(flags) do { ddev->v_flags &= ~(flags); } while (0)
+
+#define DAVINCI_CHECK_VALIDATE(flag) do { \
+ if (! (ddev->v_flags & flag)) \
+ davinci_validate_##flag( ddev, state ); \
+ } while (0)
+
+/**************************************************************************************************/
+
+static bool davinciFillRectangle16( void *drv,
+ void *dev,
+ DFBRectangle *rect );
+
+static bool davinciFillRectangle32( void *drv,
+ void *dev,
+ DFBRectangle *rect );
+
+static bool davinciFillRectangleBlend32( void *drv,
+ void *dev,
+ DFBRectangle *rect );
+
+static bool davinciBlit16 ( void *drv,
+ void *dev,
+ DFBRectangle *srect,
+ int dx,
+ int dy );
+
+static bool davinciBlit32to16 ( void *drv,
+ void *dev,
+ DFBRectangle *srect,
+ int dx,
+ int dy );
+
+static bool davinciBlit32 ( void *drv,
+ void *dev,
+ DFBRectangle *srect,
+ int dx,
+ int dy );
+
+static bool davinciBlitKeyed16 ( void *drv,
+ void *dev,
+ DFBRectangle *srect,
+ int dx,
+ int dy );
+
+static bool davinciBlitKeyed32 ( void *drv,
+ void *dev,
+ DFBRectangle *srect,
+ int dx,
+ int dy );
+
+static bool davinciBlitBlend32 ( void *drv,
+ void *dev,
+ DFBRectangle *srect,
+ int dx,
+ int dy );
+
+/**************************************************************************************************/
+
+static inline int
+get_blit_blend_sub_function( const CardState *state )
+{
+ DFBSurfaceBlittingFlags flags = state->blittingflags & ~DSBLIT_COLORIZE;
+
+ if (state->dst_blend == DSBF_INVSRCALPHA) {
+ switch (state->src_blend) {
+ case DSBF_SRCALPHA:
+ if (flags == DSBLIT_BLEND_ALPHACHANNEL)
+ return C64X_BLEND_SRC_INVSRC;
+ break;
+
+ case DSBF_ONE:
+ switch (flags) {
+ case DSBLIT_BLEND_ALPHACHANNEL:
+ return C64X_BLEND_ONE_INVSRC;
+
+ case DSBLIT_BLEND_ALPHACHANNEL |
+ DSBLIT_SRC_PREMULTIPLY:
+ return C64X_BLEND_ONE_INVSRC_PREMULT_SRC;
+
+ case DSBLIT_BLEND_ALPHACHANNEL |
+ DSBLIT_BLEND_COLORALPHA |
+ DSBLIT_SRC_PREMULTCOLOR:
+ return C64X_BLEND_ONE_INVSRC_PREMULT_ALPHA;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return -1;
+}
+
+static inline int
+get_draw_blend_sub_function( const CardState *state )
+{
+ DFBSurfaceDrawingFlags flags = state->drawingflags;
+
+ if (state->dst_blend == DSBF_INVSRCALPHA) {
+ switch (state->src_blend) {
+ case DSBF_SRCALPHA:
+ if (flags == DSDRAW_BLEND)
+ return C64X_BLEND_SRC_INVSRC;
+ break;
+
+ case DSBF_ONE:
+ switch (flags) {
+ case DSDRAW_BLEND:
+ return C64X_BLEND_ONE_INVSRC;
+
+ case DSDRAW_BLEND |
+ DSDRAW_SRC_PREMULTIPLY:
+ return C64X_BLEND_ONE_INVSRC_PREMULT_SRC;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return -1;
+}
+
+/**************************************************************************************************/
+
+/*
+ * Called by davinciSetState() to ensure that the destination registers are properly set
+ * for execution of rendering functions.
+ */
+static inline void
+davinci_validate_DESTINATION( DavinciDeviceData *ddev,
+ CardState *state )
+{
+ /* Remember destination parameters for usage in rendering functions. */
+ ddev->dst_addr = state->dst.addr;
+ ddev->dst_phys = state->dst.phys;
+ ddev->dst_size = state->dst.allocation->size;
+ ddev->dst_pitch = state->dst.pitch;
+ ddev->dst_format = state->dst.buffer->format;
+ ddev->dst_bpp = DFB_BYTES_PER_PIXEL( ddev->dst_format );
+
+ D_DEBUG_AT( Davinci_2D, " => DESTINATION: 0x%08lx\n", ddev->dst_phys );
+
+ /* Set the flag. */
+ DAVINCI_VALIDATE( DESTINATION );
+}
+
+/*
+ * Called by davinciSetState() to ensure that the color register is properly set
+ * for execution of rendering functions.
+ */
+static inline void
+davinci_validate_FILLCOLOR( DavinciDeviceData *ddev,
+ CardState *state )
+{
+ switch (ddev->dst_format) {
+ case DSPF_ARGB:
+ case DSPF_RGB32:
+ ddev->fillcolor = ddev->color_argb;
+ break;
+
+ case DSPF_RGB16:
+ ddev->fillcolor = PIXEL_RGB16( state->color.r,
+ state->color.g,
+ state->color.b );
+
+ ddev->fillcolor |= ddev->fillcolor << 16;
+ break;
+
+ case DSPF_UYVY: {
+ int y, u, v;
+
+ RGB_TO_YCBCR( state->color.r, state->color.g, state->color.b, y, u, v );
+
+ ddev->fillcolor = PIXEL_UYVY( y, u, v );
+ break;
+ }
+
+ default:
+ D_BUG( "unexpected format %s", dfb_pixelformat_name(ddev->dst_format) );
+ return;
+ }
+
+ D_DEBUG_AT( Davinci_2D, " => FILLCOLOR: 0x%08lx\n", ddev->fillcolor );
+
+ /* Set the flag. */
+ DAVINCI_VALIDATE( FILLCOLOR );
+}
+
+/*
+ * Called by davinciSetState() to ensure that the source registers are properly set
+ * for execution of blitting functions.
+ */
+static inline void
+davinci_validate_SOURCE( DavinciDeviceData *ddev,
+ CardState *state )
+{
+ /* Remember source parameters for usage in rendering functions. */
+ ddev->src_addr = state->src.addr;
+ ddev->src_phys = state->src.phys;
+ ddev->src_pitch = state->src.pitch;
+ ddev->src_format = state->src.buffer->format;
+ ddev->src_bpp = DFB_BYTES_PER_PIXEL( ddev->src_format );
+
+ D_DEBUG_AT( Davinci_2D, " => SOURCE: 0x%08lx\n", ddev->src_phys );
+
+ /* Set the flag. */
+ DAVINCI_VALIDATE( SOURCE );
+}
+
+/*
+ * Called by davinciSetState() to ensure that the source ARGB modulation is properly set
+ * for execution of blitting functions.
+ */
+static inline void
+davinci_validate_SOURCE_MULT( DavinciDeviceData *ddev,
+ CardState *state )
+{
+ switch (ddev->dst_format) {
+ case DSPF_ARGB:
+ if (state->blittingflags & DSBLIT_COLORIZE)
+ ddev->source_mult = 0xff000000 | ddev->color_argb;
+ else
+ ddev->source_mult = 0xffffffff;
+ break;
+
+ default:
+ D_BUG( "unexpected format %s", dfb_pixelformat_name(ddev->dst_format) );
+ return;
+ }
+
+ D_DEBUG_AT( Davinci_2D, " => SOURCE_MULT: 0x%08lx\n", ddev->source_mult );
+
+ /* Set the flag. */
+ DAVINCI_VALIDATE( SOURCE_MULT );
+}
+
+/*
+ * Called by davinciSetState() to ensure that the blend sub function index is valid
+ * for execution of blitting functions.
+ */
+static inline void
+davinci_validate_BLIT_BLEND_SUB( DavinciDeviceData *ddev,
+ CardState *state )
+{
+ int index = get_blit_blend_sub_function( state );
+
+ if (index < 0) {
+ D_BUG( "unexpected state" );
+ return;
+ }
+
+ /* Set blend sub function index. */
+ ddev->blit_blend_sub_function = index;
+
+ D_DEBUG_AT( Davinci_2D, " => BLIT_BLEND_SUB: %d\n", index );
+
+ /* Set the flag. */
+ DAVINCI_VALIDATE( BLIT_BLEND_SUB );
+}
+
+/*
+ * Called by davinciSetState() to ensure that the blend sub function index is valid
+ * for execution of drawing functions.
+ */
+static inline void
+davinci_validate_DRAW_BLEND_SUB( DavinciDeviceData *ddev,
+ CardState *state )
+{
+ int index = get_draw_blend_sub_function( state );
+
+ if (index < 0) {
+ D_BUG( "unexpected state" );
+ return;
+ }
+
+ /* Set blend sub function index. */
+ ddev->draw_blend_sub_function = index;
+
+ D_DEBUG_AT( Davinci_2D, " => DRAW_BLEND_SUB: %d\n", index );
+
+ /* Set the flag. */
+ DAVINCI_VALIDATE( DRAW_BLEND_SUB );
+}
+
+/**************************************************************************************************/
+
+/*
+ * Wait for the blitter to be idle.
+ *
+ * This function is called before memory that has been written to by the hardware is about to be
+ * accessed by the CPU (software driver) or another hardware entity like video encoder (by Flip()).
+ * It can also be called by applications explicitly, e.g. at the end of a benchmark loop to include
+ * execution time of queued commands in the measurement.
+ */
+DFBResult
+davinciEngineSync( void *drv, void *dev )
+{
+ DFBResult ret;
+ DavinciDriverData *ddrv = drv;
+ DavinciDeviceData *ddev = dev;
+
+ D_DEBUG_AT( Davinci_2D, "%s()\n", __FUNCTION__ );
+
+ if (!ddev->synced) {
+ D_DEBUG_AT( Davinci_2D, " -> syncing...\n" );
+
+ ret = davinci_c64x_wait_low( &ddrv->c64x );
+ if (ret) {
+ D_DEBUG_AT( Davinci_2D, " -> ERROR (%s)\n", DirectFBErrorString(ret) );
+ return ret;
+ }
+
+ D_DEBUG_AT( Davinci_2D, " => syncing done.\n" );
+
+ ddev->synced = true;
+ }
+ else
+ D_DEBUG_AT( Davinci_2D, " => already synced!\n" );
+
+ return DFB_OK;
+}
+
+/*
+ * Reset the graphics engine.
+ */
+void
+davinciEngineReset( void *drv, void *dev )
+{
+ D_DEBUG_AT( Davinci_2D, "%s()\n", __FUNCTION__ );
+}
+
+/*
+ * Start processing of queued commands if required.
+ *
+ * This function is called before returning from the graphics core to the application.
+ * Usually that's after each rendering function. The only functions causing multiple commands
+ * to be queued with a single emition at the end are DrawString(), TileBlit(), BatchBlit(),
+ * DrawLines() and possibly FillTriangle() which is emulated using multiple FillRectangle() calls.
+ */
+void
+davinciEmitCommands( void *drv, void *dev )
+{
+ DFBResult ret;
+ DavinciDeviceData *ddev = dev;
+ DavinciDriverData *ddrv = drv;
+
+ D_DEBUG_AT( Davinci_2D, "%s()\n", __FUNCTION__ );
+
+ ret = davinci_c64x_emit_tasks( &ddrv->c64x, &ddrv->tasks, C64X_TEF_RESET );
+ if (ret)
+ D_DERROR( ret, "Davinci/Driver: Error emitting local task buffer!\n" );
+
+ ddev->synced = false;
+}
+
+/*
+ * Invalidate the DSP's read cache.
+ */
+void
+davinciFlushTextureCache( void *drv, void *dev )
+{
+ DavinciDriverData *ddrv = drv;
+ DavinciDeviceData *ddev = dev;
+
+ D_DEBUG_AT( Davinci_2D, "%s()\n", __FUNCTION__ );
+
+ /* Bad workaround */
+ davinci_c64x_blit_32( &ddrv->c64x, dfb_config->video_phys, 1024, dfb_config->video_phys, 1024, 256, 64 );
+
+ /* These don't work */
+// davinci_c64x_wb_inv_range( &ddrv->c64x, dfb_config->video_phys,
+// dfb_config->video_length, 2 );
+
+// davinci_c64x_wb_inv_range( &ddrv->c64x, ddev->fix[OSD0].smem_start,
+// ddev->fix[OSD0].smem_len, 2 );
+}
+
+/*
+ * Check for acceleration of 'accel' using the given 'state'.
+ */
+void
+davinciCheckState( void *drv,
+ void *dev,
+ CardState *state,
+ DFBAccelerationMask accel )
+{
+ D_DEBUG_AT( Davinci_2D, "%s( state %p, accel 0x%08x ) <- dest %p\n",
+ __FUNCTION__, state, accel, state->destination );
+
+ /* Return if the desired function is not supported at all. */
+ if (accel & ~(DAVINCI_SUPPORTED_DRAWINGFUNCTIONS | DAVINCI_SUPPORTED_BLITTINGFUNCTIONS))
+ return;
+
+ /* Return if the destination format is not supported. */
+ switch (state->destination->config.format) {
+ case DSPF_UYVY:
+ case DSPF_RGB16:
+ case DSPF_RGB32:
+ case DSPF_ARGB:
+ break;
+
+ default:
+ return;
+ }
+
+ /* Check if drawing or blitting is requested. */
+ if (DFB_DRAWING_FUNCTION( accel )) {
+ /* Return if unsupported drawing flags are set. */
+ if (state->drawingflags & ~DAVINCI_SUPPORTED_DRAWINGFLAGS)
+ return;
+
+ /* Limited blending support. */
+ if (state->drawingflags & (DSDRAW_BLEND | DSDRAW_SRC_PREMULTIPLY)) {
+ if (state->destination->config.format != DSPF_ARGB)
+ return;
+
+ if (get_draw_blend_sub_function( state ) < 0)
+ return;
+ }
+ }
+ else {
+ /* Return if unsupported blitting flags are set. */
+ if (state->blittingflags & ~DAVINCI_SUPPORTED_BLITTINGFLAGS)
+ return;
+
+ /* No other flags supported when color keying is used. */
+ if ((state->blittingflags & DSBLIT_SRC_COLORKEY) && state->blittingflags != DSBLIT_SRC_COLORKEY)
+ return;
+
+ /* Return if the source format is not supported. */
+ switch (state->source->config.format) {
+ case DSPF_UYVY:
+ case DSPF_RGB16:
+ /* Only color keying for these formats. */
+ if (state->blittingflags & ~DSBLIT_SRC_COLORKEY)
+ return;
+ /* No format conversion supported. */
+ if (state->source->config.format != state->destination->config.format)
+ return;
+ break;
+
+ case DSPF_RGB32:
+ /* Only color keying for these formats. */
+ if (state->blittingflags & ~DSBLIT_SRC_COLORKEY)
+ return;
+ /* fall through */
+ case DSPF_ARGB:
+ /* Only few blending combinations are valid. */
+ if ((state->blittingflags & ~DSBLIT_SRC_COLORKEY) && get_blit_blend_sub_function( state ) < 0)
+ return;
+ /* Only ARGB/RGB32 -> RGB16 conversion (without any flag). */
+ if (state->source->config.format != state->destination->config.format &&
+ (state->destination->config.format != DSPF_RGB16 || state->blittingflags))
+ return;
+ break;
+
+ default:
+ return;
+ }
+
+ /* Checks per function. */
+ switch (accel) {
+ case DFXL_STRETCHBLIT:
+ /* No flags supported with StretchBlit(). */
+ if (state->blittingflags)
+ return;
+
+ /* Only (A)RGB at 32 bit supported. */
+ if (state->source->config.format != DSPF_ARGB && state->source->config.format != DSPF_RGB32)
+ return;
+
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /* Enable acceleration of the function. */
+ state->accel |= accel;
+
+ D_DEBUG_AT( Davinci_2D, " => accel 0x%08x\n", state->accel );
+}
+
+/*
+ * Make sure that the hardware is programmed for execution of 'accel' according to the 'state'.
+ */
+void
+davinciSetState( void *drv,
+ void *dev,
+ GraphicsDeviceFuncs *funcs,
+ CardState *state,
+ DFBAccelerationMask accel )
+{
+ DavinciDeviceData *ddev = dev;
+ StateModificationFlags modified = state->mod_hw;
+
+ D_DEBUG_AT( Davinci_2D, "%s( state %p, accel 0x%08x ) <- dest %p, modified 0x%08x\n",
+ __FUNCTION__, state, accel, state->destination, modified );
+
+ /*
+ * 1) Invalidate hardware states
+ *
+ * Each modification to the hw independent state invalidates one or more hardware states.
+ */
+
+ /* Simply invalidate all? */
+ if (modified == SMF_ALL) {
+ D_DEBUG_AT( Davinci_2D, " <- ALL\n" );
+
+ DAVINCI_INVALIDATE( ALL );
+ }
+ else if (modified) {
+ /* Invalidate destination settings. */
+ if (modified & SMF_DESTINATION) {
+ D_DEBUG_AT( Davinci_2D, " <- DESTINATION | FILLCOLOR\n" );
+
+ DAVINCI_INVALIDATE( DESTINATION | FILLCOLOR );
+ }
+ else if (modified & SMF_COLOR) {
+ D_DEBUG_AT( Davinci_2D, " <- FILLCOLOR\n" );
+
+ DAVINCI_INVALIDATE( FILLCOLOR );
+ }
+
+ /* Invalidate source settings. */
+ if (modified & SMF_SOURCE) {
+ D_DEBUG_AT( Davinci_2D, " <- SOURCE\n" );
+
+ DAVINCI_INVALIDATE( SOURCE );
+ }
+
+ /* Invalidate source color(ize) settings. */
+ if (modified & (SMF_BLITTING_FLAGS | SMF_COLOR)) {
+ D_DEBUG_AT( Davinci_2D, " <- SOURCE_MULT\n" );
+
+ DAVINCI_INVALIDATE( SOURCE_MULT );
+ }
+
+ /* Invalidate blend function for blitting. */
+ if (modified & (SMF_BLITTING_FLAGS | SMF_SRC_BLEND | SMF_DST_BLEND)) {
+ D_DEBUG_AT( Davinci_2D, " <- BLIT_BLEND_SUB\n" );
+
+ DAVINCI_INVALIDATE( BLIT_BLEND_SUB );
+ }
+
+ /* Invalidate blend function for drawing. */
+ if (modified & (SMF_DRAWING_FLAGS | SMF_SRC_BLEND | SMF_DST_BLEND)) {
+ D_DEBUG_AT( Davinci_2D, " <- DRAW_BLEND_SUB\n" );
+
+ DAVINCI_INVALIDATE( DRAW_BLEND_SUB );
+ }
+ }
+
+ /*
+ * Just keep these values, no computations needed here.
+ * Values used by state validation or rendering functions.
+ */
+ ddev->blitting_flags = state->blittingflags;
+ ddev->clip = state->clip;
+ ddev->color = state->color;
+ ddev->colorkey = state->src_colorkey;
+ ddev->color_argb = PIXEL_ARGB( state->color.a,
+ state->color.r,
+ state->color.g,
+ state->color.b );
+
+ /*
+ * 2) Validate hardware states
+ *
+ * Each function has its own set of states that need to be validated.
+ */
+
+ /* Always requiring valid destination... */
+ DAVINCI_CHECK_VALIDATE( DESTINATION );
+
+ /* Depending on the function... */
+ switch (accel) {
+ case DFXL_FILLRECTANGLE:
+ D_DEBUG_AT( Davinci_2D, " -> FILLRECTANGLE\n" );
+
+ /* Validate blend sub function index for drawing... */
+ if (state->drawingflags & (DSDRAW_BLEND | DSDRAW_SRC_PREMULTIPLY))
+ DAVINCI_CHECK_VALIDATE( DRAW_BLEND_SUB );
+ else
+ /* ...or just validate fill color. */
+ DAVINCI_CHECK_VALIDATE( FILLCOLOR );
+
+ /* Choose function. */
+ switch (DFB_BYTES_PER_PIXEL( state->destination->config.format )) {
+ case 2:
+ funcs->FillRectangle = davinciFillRectangle16;
+ break;
+
+ case 4:
+ if (state->drawingflags & (DSDRAW_BLEND | DSDRAW_SRC_PREMULTIPLY))
+ funcs->FillRectangle = davinciFillRectangleBlend32;
+ else
+ funcs->FillRectangle = davinciFillRectangle32;
+ break;
+
+ default:
+ D_BUG( "unexpected destination bpp %d",
+ DFB_BYTES_PER_PIXEL( state->destination->config.format ) );
+ break;
+ }
+
+ /*
+ * 3) Tell which functions can be called without further validation, i.e. SetState()
+ *
+ * When the hw independent state is changed, this collection is reset.
+ */
+ state->set |= DAVINCI_SUPPORTED_DRAWINGFUNCTIONS;
+ break;
+
+ case DFXL_BLIT:
+ D_DEBUG_AT( Davinci_2D, " -> BLIT\n" );
+
+ /* ...require valid source. */
+ DAVINCI_CHECK_VALIDATE( SOURCE );
+
+ /* Validate blend sub function index for blitting. */
+ if (state->blittingflags & DSBLIT_BLEND_ALPHACHANNEL) {
+ DAVINCI_CHECK_VALIDATE( BLIT_BLEND_SUB );
+
+ /* Validate ARGB source modulator. */
+ DAVINCI_CHECK_VALIDATE( SOURCE_MULT );
+ }
+
+ /* Choose function. */
+ switch (DFB_BYTES_PER_PIXEL( state->destination->config.format )) {
+ case 2:
+ if (state->blittingflags & DSBLIT_SRC_COLORKEY)
+ funcs->Blit = davinciBlitKeyed16;
+ else if (state->source->config.format == DSPF_ARGB ||
+ state->source->config.format == DSPF_RGB32)
+ funcs->Blit = davinciBlit32to16;
+ else
+ funcs->Blit = davinciBlit16;
+ break;
+
+ case 4:
+ if (state->blittingflags & DSBLIT_SRC_COLORKEY)
+ funcs->Blit = davinciBlitKeyed32;
+ else if (state->blittingflags & DSBLIT_BLEND_ALPHACHANNEL)
+ funcs->Blit = davinciBlitBlend32;
+ else
+ funcs->Blit = davinciBlit32;
+ break;
+
+ default:
+ D_BUG( "unexpected destination bpp %d",
+ DFB_BYTES_PER_PIXEL( state->destination->config.format ) );
+ break;
+ }
+
+ /*
+ * 3) Tell which functions can be called without further validation, i.e. SetState()
+ *
+ * When the hw independent state is changed, this collection is reset.
+ */
+ state->set |= DFXL_BLIT;
+ break;
+
+ case DFXL_STRETCHBLIT:
+ D_DEBUG_AT( Davinci_2D, " -> STRETCHBLIT\n" );
+
+ /* ...require valid source. */
+ DAVINCI_CHECK_VALIDATE( SOURCE );
+
+ /* Choose function. */
+#if 0 // only 32bit, statically set in driver_init_driver()
+ switch (state->destination->config.format) {
+ case DSPF_ARGB:
+ case DSPF_RGB32:
+ funcs->StretchBlit = davinciStretchBlit32;
+ break;
+
+ default:
+ D_BUG( "unexpected destination format %s",
+ dfb_pixelformat_name( state->destination->config.format ) );
+ break;
+ }
+#endif
+
+ /*
+ * 3) Tell which functions can be called without further validation, i.e. SetState()
+ *
+ * When the hw independent state is changed, this collection is reset.
+ */
+ state->set |= DFXL_STRETCHBLIT;
+ break;
+
+ default:
+ D_BUG( "unexpected drawing/blitting function" );
+ break;
+ }
+
+ /*
+ * 4) Clear modification flags
+ *
+ * All flags have been evaluated in 1) and remembered for further validation.
+ * If the hw independent state is not modified, this function won't get called
+ * for subsequent rendering functions, unless they aren't defined by 3).
+ */
+ state->mod_hw = 0;
+}
+
+/**********************************************************************************************************************/
+/**********************************************************************************************************************/
+
+/*
+ * Render a filled rectangle using the current hardware state.
+ */
+static bool
+davinciFillRectangle16( void *drv, void *dev, DFBRectangle *rect )
+{
+ DavinciDriverData *ddrv = drv;
+ DavinciDeviceData *ddev = dev;
+
+ D_DEBUG_AT( Davinci_2D, "%s( %4d,%4d-%4dx%4d )\n", __FUNCTION__, DFB_RECTANGLE_VALS(rect) );
+
+ /* FIXME: Optimize in DSP. */
+ if ((rect->x | rect->w) & 1)
+ davinci_c64x_fill_16__L( &ddrv->tasks,
+ ddev->dst_phys + ddev->dst_pitch * rect->y + ddev->dst_bpp * rect->x,
+ ddev->dst_pitch,
+ rect->w, rect->h,
+ ddev->fillcolor );
+ else
+ davinci_c64x_fill_32__L( &ddrv->tasks,
+ ddev->dst_phys + ddev->dst_pitch * rect->y + ddev->dst_bpp * rect->x,
+ ddev->dst_pitch,
+ rect->w/2, rect->h,
+ ddev->fillcolor );
+
+ return true;
+}
+
+static bool
+davinciFillRectangle32( void *drv, void *dev, DFBRectangle *rect )
+{
+ DavinciDriverData *ddrv = drv;
+ DavinciDeviceData *ddev = dev;
+
+ D_DEBUG_AT( Davinci_2D, "%s( %4d,%4d-%4dx%4d )\n", __FUNCTION__, DFB_RECTANGLE_VALS(rect) );
+
+ if (ddev->dst_format == DSPF_ARGB && ddev->color.a == 0xff)
+ davinci_c64x_blit_blend_32__L( &ddrv->tasks,
+ C64X_BLEND_ONE_INVSRC,
+ ddev->dst_phys + ddev->dst_pitch * rect->y + ddev->dst_bpp * rect->x,
+ ddev->dst_pitch,
+ 0,
+ 0,
+ rect->w, rect->h,
+ ddev->color_argb,
+ 0xff );
+ else
+ davinci_c64x_fill_32__L( &ddrv->tasks,
+ ddev->dst_phys + ddev->dst_pitch * rect->y + ddev->dst_bpp * rect->x,
+ ddev->dst_pitch,
+ rect->w, rect->h,
+ ddev->fillcolor );
+
+ return true;
+}
+
+/**********************************************************************************************************************/
+
+static bool
+davinciFillRectangleBlend32( void *drv, void *dev, DFBRectangle *rect )
+{
+ DavinciDriverData *ddrv = drv;
+ DavinciDeviceData *ddev = dev;
+
+ D_DEBUG_AT( Davinci_2D, "%s( %4d,%4d-%4dx%4d )\n", __FUNCTION__, DFB_RECTANGLE_VALS(rect) );
+
+ davinci_c64x_blit_blend_32__L( &ddrv->tasks,
+ ddev->draw_blend_sub_function,
+ ddev->dst_phys + ddev->dst_pitch * rect->y + ddev->dst_bpp * rect->x,
+ ddev->dst_pitch,
+ 0,
+ 0,
+ rect->w, rect->h,
+ ddev->color_argb,
+ 0xff );
+
+ return true;
+}
+
+/**********************************************************************************************************************/
+/**********************************************************************************************************************/
+
+/*
+ * Blit a rectangle using the current hardware state.
+ */
+static bool
+davinciBlit16( void *drv, void *dev, DFBRectangle *rect, int dx, int dy )
+{
+ DavinciDriverData *ddrv = drv;
+ DavinciDeviceData *ddev = dev;
+
+ D_DEBUG_AT( Davinci_2D, "%s( %4d,%4d-%4dx%4d <- %4d,%4d )\n",
+ __FUNCTION__, dx, dy, rect->w, rect->h, rect->x, rect->y );
+
+ /* FIXME: Optimize in DSP. */
+ if ((dx | rect->x | rect->w) & 1)
+ davinci_c64x_blit_16__L( &ddrv->tasks,
+ ddev->dst_phys + ddev->dst_pitch * dy + ddev->dst_bpp * dx,
+ ddev->dst_pitch,
+ ddev->src_phys + ddev->src_pitch * rect->y + ddev->src_bpp * rect->x,
+ ddev->src_pitch,
+ rect->w, rect->h );
+ else
+ davinci_c64x_blit_32__L( &ddrv->tasks,
+ ddev->dst_phys + ddev->dst_pitch * dy + ddev->dst_bpp * dx,
+ ddev->dst_pitch,
+ ddev->src_phys + ddev->src_pitch * rect->y + ddev->src_bpp * rect->x,
+ ddev->src_pitch,
+ rect->w/2, rect->h );
+
+ return true;
+}
+
+static bool
+davinciBlit32( void *drv, void *dev, DFBRectangle *rect, int dx, int dy )
+{
+ DavinciDriverData *ddrv = drv;
+ DavinciDeviceData *ddev = dev;
+
+ D_DEBUG_AT( Davinci_2D, "%s( %4d,%4d-%4dx%4d <- %4d,%4d )\n",
+ __FUNCTION__, dx, dy, rect->w, rect->h, rect->x, rect->y );
+
+ davinci_c64x_blit_32__L( &ddrv->tasks,
+ ddev->dst_phys + ddev->dst_pitch * dy + ddev->dst_bpp * dx,
+ ddev->dst_pitch,
+ ddev->src_phys + ddev->src_pitch * rect->y + ddev->src_bpp * rect->x,
+ ddev->src_pitch,
+ rect->w, rect->h );
+
+ return true;
+}
+
+/**********************************************************************************************************************/
+
+static bool
+davinciBlit32to16( void *drv, void *dev, DFBRectangle *rect, int dx, int dy )
+{
+ DavinciDriverData *ddrv = drv;
+ DavinciDeviceData *ddev = dev;
+
+ D_DEBUG_AT( Davinci_2D, "%s( %4d,%4d-%4dx%4d <- %4d,%4d )\n",
+ __FUNCTION__, dx, dy, rect->w, rect->h, rect->x, rect->y );
+
+ davinci_c64x_dither_argb__L( &ddrv->tasks,
+ ddev->dst_phys + ddev->dst_pitch * dy + ddev->dst_bpp * dx,
+ DAVINCI_C64X_MEM,
+ ddev->dst_pitch,
+ ddev->src_phys + ddev->src_pitch * rect->y + ddev->src_bpp * rect->x,
+ ddev->src_pitch,
+ rect->w, rect->h );
+
+ return true;
+}
+
+/**********************************************************************************************************************/
+
+static bool
+davinciBlitKeyed16( void *drv, void *dev, DFBRectangle *rect, int dx, int dy )
+{
+ DavinciDriverData *ddrv = drv;
+ DavinciDeviceData *ddev = dev;
+
+ D_DEBUG_AT( Davinci_2D, "%s( %4d,%4d-%4dx%4d <- %4d,%4d ) <- key 0x%04lx\n",
+ __FUNCTION__, dx, dy, rect->w, rect->h, rect->x, rect->y, ddev->colorkey );
+
+ davinci_c64x_blit_keyed_16__L( &ddrv->tasks,
+ ddev->dst_phys + ddev->dst_pitch * dy + ddev->dst_bpp * dx,
+ ddev->dst_pitch,
+ ddev->src_phys + ddev->src_pitch * rect->y + ddev->src_bpp * rect->x,
+ ddev->src_pitch,
+ rect->w, rect->h,
+ ddev->colorkey,
+ (1 << DFB_COLOR_BITS_PER_PIXEL( ddev->dst_format )) - 1 );
+
+ return true;
+}
+
+static bool
+davinciBlitKeyed32( void *drv, void *dev, DFBRectangle *rect, int dx, int dy )
+{
+ DavinciDriverData *ddrv = drv;
+ DavinciDeviceData *ddev = dev;
+
+ D_DEBUG_AT( Davinci_2D, "%s( %4d,%4d-%4dx%4d <- %4d,%4d ) <- key 0x%08lx\n",
+ __FUNCTION__, dx, dy, rect->w, rect->h, rect->x, rect->y, ddev->colorkey );
+
+ davinci_c64x_blit_keyed_32__L( &ddrv->tasks,
+ ddev->dst_phys + ddev->dst_pitch * dy + ddev->dst_bpp * dx,
+ ddev->dst_pitch,
+ ddev->src_phys + ddev->src_pitch * rect->y + ddev->src_bpp * rect->x,
+ ddev->src_pitch,
+ rect->w, rect->h,
+ ddev->colorkey,
+ (1 << DFB_COLOR_BITS_PER_PIXEL( ddev->dst_format )) - 1 );
+
+ return true;
+}
+
+/**********************************************************************************************************************/
+
+static bool
+davinciBlitBlend32( void *drv, void *dev, DFBRectangle *rect, int dx, int dy )
+{
+ DavinciDriverData *ddrv = drv;
+ DavinciDeviceData *ddev = dev;
+
+ D_DEBUG_AT( Davinci_2D, "%s( %4d,%4d-%4dx%4d <- %4d,%4d )\n",
+ __FUNCTION__, dx, dy, rect->w, rect->h, rect->x, rect->y );
+
+ davinci_c64x_blit_blend_32__L( &ddrv->tasks,
+ ddev->blit_blend_sub_function,
+ ddev->dst_phys + ddev->dst_pitch * dy + ddev->dst_bpp * dx,
+ ddev->dst_pitch,
+ ddev->src_phys + ddev->src_pitch * rect->y + ddev->src_bpp * rect->x,
+ ddev->src_pitch,
+ rect->w, rect->h,
+ ddev->source_mult,
+ ddev->color.a );
+
+ return true;
+}
+
+/**********************************************************************************************************************/
+/**********************************************************************************************************************/
+
+bool
+davinciStretchBlit32( void *drv, void *dev, DFBRectangle *srect, DFBRectangle *drect )
+{
+ DavinciDriverData *ddrv = drv;
+ DavinciDeviceData *ddev = dev;
+
+ DFBRegion clip = DFB_REGION_INIT_FROM_RECTANGLE( drect );
+
+ D_DEBUG_AT( Davinci_2D, "%s( %4d,%4d-%4dx%4d <- %4d,%4d-%4dx%4d )\n",
+ __FUNCTION__, DFB_RECTANGLE_VALS(drect), DFB_RECTANGLE_VALS(srect) );
+
+ if (!dfb_region_region_intersect( &clip, &ddev->clip ))
+ return true;
+
+ dfb_region_translate( &clip, -drect->x, -drect->y );
+
+ davinci_c64x_stretch_32__L( &ddrv->tasks,
+ ddev->dst_phys + ddev->dst_pitch * drect->y + ddev->dst_bpp * drect->x,
+ ddev->dst_pitch,
+ ddev->src_phys + ddev->src_pitch * srect->y + ddev->src_bpp * srect->x,
+ ddev->src_pitch,
+ drect->w, drect->h,
+ srect->w, srect->h,
+ &clip );
+
+ return true;
+}
+