summaryrefslogtreecommitdiff
path: root/Source/DirectFB/proxy/requestor/idirectfbsurface_requestor.c
diff options
context:
space:
mode:
Diffstat (limited to 'Source/DirectFB/proxy/requestor/idirectfbsurface_requestor.c')
-rwxr-xr-xSource/DirectFB/proxy/requestor/idirectfbsurface_requestor.c1852
1 files changed, 1852 insertions, 0 deletions
diff --git a/Source/DirectFB/proxy/requestor/idirectfbsurface_requestor.c b/Source/DirectFB/proxy/requestor/idirectfbsurface_requestor.c
new file mode 100755
index 0000000..49984c0
--- /dev/null
+++ b/Source/DirectFB/proxy/requestor/idirectfbsurface_requestor.c
@@ -0,0 +1,1852 @@
+/*
+ (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 <stdlib.h>
+#include <string.h>
+
+#include <math.h>
+
+
+#include <directfb.h>
+#include <directfb_util.h>
+
+#include <direct/interface.h>
+#include <direct/mem.h>
+#include <direct/memcpy.h>
+#include <direct/messages.h>
+
+#include <voodoo/conf.h>
+#include <voodoo/interface.h>
+#include <voodoo/manager.h>
+#include <voodoo/message.h>
+
+#include <misc/conf.h>
+
+#include <idirectfbsurface_dispatcher.h>
+
+#include "idirectfbfont_requestor.h"
+#include "idirectfbpalette_requestor.h"
+#include "idirectfbsurface_requestor.h"
+
+
+D_DEBUG_DOMAIN( IDirectFBSurface_Requestor_, "IDirectFBSurface/Requestor", "IDirectFBSurface Requestor" );
+D_DEBUG_DOMAIN( IDirectFBSurface_RequestorFlip, "IDirectFBSurface/Requestor/Flip", "IDirectFBSurface Requestor Flip" );
+
+static DFBResult Probe( void );
+static DFBResult Construct( IDirectFBSurface *thiz,
+ VoodooManager *manager,
+ VoodooInstanceID instance,
+ void *arg );
+
+#include <direct/interface_implementation.h>
+
+DIRECT_INTERFACE_IMPLEMENTATION( IDirectFBSurface, Requestor )
+
+/**************************************************************************************************/
+
+static void
+IDirectFBSurface_Requestor_Destruct( IDirectFBSurface *thiz )
+{
+ IDirectFBSurface_Requestor_data *data = thiz->priv;
+
+ D_DEBUG( "%s (%p)\n", __FUNCTION__, thiz );
+
+ direct_mutex_deinit( &data->flip.lock );
+ direct_waitqueue_deinit( &data->flip.queue );
+
+ if (data->flip.window)
+ data->flip.window->Release( data->flip.window );
+
+ if (data->flip.buffer)
+ data->flip.buffer->Release( data->flip.buffer );
+
+ if (data->local != VOODOO_INSTANCE_NONE)
+ voodoo_manager_unregister_local( data->manager, data->local );
+
+ voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_Release, VREQ_NONE, NULL,
+ VMBT_NONE );
+
+ DIRECT_DEALLOCATE_INTERFACE( thiz );
+}
+
+/**************************************************************************************************/
+
+static DirectResult
+IDirectFBSurface_Requestor_AddRef( IDirectFBSurface *thiz )
+{
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ data->ref++;
+
+ return DFB_OK;
+}
+
+static DirectResult
+IDirectFBSurface_Requestor_Release( IDirectFBSurface *thiz )
+{
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ if (--data->ref == 0)
+ IDirectFBSurface_Requestor_Destruct( thiz );
+
+ return DFB_OK;
+}
+
+
+static DFBResult
+IDirectFBSurface_Requestor_GetPixelFormat( IDirectFBSurface *thiz,
+ DFBSurfacePixelFormat *ret_format )
+{
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ if (!ret_format)
+ return DFB_INVARG;
+
+ if (!data->format) {
+ DFBResult ret;
+ VoodooResponseMessage *response;
+ VoodooMessageParser parser;
+
+ ret = voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_GetPixelFormat, VREQ_RESPOND, &response,
+ VMBT_NONE );
+ if (ret)
+ return ret;
+
+ ret = response->result;
+ if (ret) {
+ voodoo_manager_finish_request( data->manager, response );
+ return ret;
+ }
+
+ VOODOO_PARSER_BEGIN( parser, response );
+ VOODOO_PARSER_GET_INT( parser, data->format );
+ VOODOO_PARSER_END( parser );
+
+ voodoo_manager_finish_request( data->manager, response );
+ }
+
+ *ret_format = data->format;
+
+ return DFB_OK;
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_GetAccelerationMask( IDirectFBSurface *thiz,
+ IDirectFBSurface *source,
+ DFBAccelerationMask *ret_mask )
+{
+ DirectResult ret;
+ VoodooResponseMessage *response;
+ VoodooMessageParser parser;
+ DFBAccelerationMask mask;
+
+ IDirectFBSurface_Requestor_data *source_data = NULL;
+
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ if (source)
+ DIRECT_INTERFACE_GET_DATA_FROM( source, source_data, IDirectFBSurface_Requestor );
+
+ ret = voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_GetAccelerationMask, VREQ_RESPOND, &response,
+ VMBT_ID, source_data ? source_data->instance : VOODOO_INSTANCE_NONE,
+ VMBT_NONE );
+ if (ret)
+ return ret;
+
+ ret = response->result;
+ if (ret) {
+ voodoo_manager_finish_request( data->manager, response );
+ return ret;
+ }
+
+ VOODOO_PARSER_BEGIN( parser, response );
+ VOODOO_PARSER_GET_INT( parser, mask );
+ VOODOO_PARSER_END( parser );
+
+ voodoo_manager_finish_request( data->manager, response );
+
+ *ret_mask = mask;
+
+ return ret;
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_GetPosition( IDirectFBSurface *thiz,
+ int *x,
+ int *y )
+{
+ DFBResult ret;
+ VoodooResponseMessage *response;
+ VoodooMessageParser parser;
+ const DFBPoint *position;
+
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ if (!x && !y)
+ return DFB_INVARG;
+
+ ret = voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_GetPosition,
+ VREQ_RESPOND, &response,
+ VMBT_NONE );
+ if (ret)
+ return ret;
+
+ ret = response->result;
+ if (ret) {
+ voodoo_manager_finish_request( data->manager, response );
+ return ret;
+ }
+
+ VOODOO_PARSER_BEGIN( parser, response );
+ VOODOO_PARSER_GET_DATA( parser, position );
+ VOODOO_PARSER_END( parser );
+
+ if (x)
+ *x = position->x;
+
+ if (y)
+ *y = position->y;
+
+ voodoo_manager_finish_request( data->manager, response );
+
+ return DFB_OK;
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_GetSize( IDirectFBSurface *thiz,
+ int *width,
+ int *height )
+{
+ DFBResult ret;
+ VoodooResponseMessage *response;
+ VoodooMessageParser parser;
+ const DFBDimension *dimension;
+
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ if (!width && !height)
+ return DFB_INVARG;
+
+ ret = voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_GetSize, VREQ_RESPOND, &response,
+ VMBT_NONE );
+ if (ret)
+ return ret;
+
+ ret = response->result;
+ if (ret) {
+ voodoo_manager_finish_request( data->manager, response );
+ return ret;
+ }
+
+ VOODOO_PARSER_BEGIN( parser, response );
+ VOODOO_PARSER_GET_DATA( parser, dimension );
+ VOODOO_PARSER_END( parser );
+
+ if (width)
+ *width = dimension->w;
+
+ if (height)
+ *height = dimension->h;
+
+ voodoo_manager_finish_request( data->manager, response );
+
+ return DFB_OK;
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_GetVisibleRectangle( IDirectFBSurface *thiz,
+ DFBRectangle *rect )
+{
+ DFBResult ret;
+ VoodooResponseMessage *response;
+ VoodooMessageParser parser;
+
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ if (!rect)
+ return DFB_INVARG;
+
+ ret = voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_GetVisibleRectangle,
+ VREQ_RESPOND, &response,
+ VMBT_NONE );
+ if (ret)
+ return ret;
+
+ ret = response->result;
+ if (ret) {
+ voodoo_manager_finish_request( data->manager, response );
+ return ret;
+ }
+
+ VOODOO_PARSER_BEGIN( parser, response );
+ VOODOO_PARSER_READ_DATA( parser, rect, sizeof(DFBRectangle) );
+ VOODOO_PARSER_END( parser );
+
+ voodoo_manager_finish_request( data->manager, response );
+
+ return DFB_OK;
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_GetCapabilities( IDirectFBSurface *thiz,
+ DFBSurfaceCapabilities *caps )
+{
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ if (!caps)
+ return DFB_INVARG;
+
+ D_UNIMPLEMENTED();
+
+ return DFB_UNIMPLEMENTED;
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_GetPalette( IDirectFBSurface *thiz,
+ IDirectFBPalette **ret_interface )
+{
+ DirectResult ret;
+ VoodooResponseMessage *response;
+ void *interface_ptr = NULL;
+
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ if (!ret_interface)
+ return DFB_INVARG;
+
+ ret = voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_GetPalette, VREQ_RESPOND, &response,
+ VMBT_NONE );
+ if (ret)
+ return ret;
+
+ ret = response->result;
+ if (ret == DR_OK)
+ ret = voodoo_construct_requestor( data->manager, "IDirectFBPalette",
+ response->instance, data->idirectfb, &interface_ptr );
+
+ voodoo_manager_finish_request( data->manager, response );
+
+ *ret_interface = interface_ptr;
+
+ return ret;
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_SetPalette( IDirectFBSurface *thiz,
+ IDirectFBPalette *palette )
+{
+ IDirectFBPalette_Requestor_data *palette_data = NULL;
+
+ DIRECT_INTERFACE_GET_DATA( IDirectFBSurface_Requestor )
+
+ if (!palette)
+ return DFB_INVARG;
+
+ DIRECT_INTERFACE_GET_DATA_FROM( palette, palette_data, IDirectFBPalette_Requestor );
+
+ return voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_SetPalette, VREQ_QUEUE, NULL,
+ VMBT_ID, palette_data->instance,
+ VMBT_NONE );
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_SetAlphaRamp( IDirectFBSurface *thiz,
+ u8 a0, u8 a1, u8 a2, u8 a3 )
+{
+ DIRECT_INTERFACE_GET_DATA( IDirectFBSurface_Requestor )
+
+ D_UNIMPLEMENTED();
+
+ return DFB_UNIMPLEMENTED;
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_Lock( IDirectFBSurface *thiz,
+ DFBSurfaceLockFlags flags,
+ void **ret_ptr, int *ret_pitch )
+{
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ if (!flags || !ret_ptr || !ret_pitch)
+ return DFB_INVARG;
+
+ D_UNIMPLEMENTED();
+
+ return DFB_UNIMPLEMENTED;
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_GetFramebufferOffset( IDirectFBSurface *thiz,
+ int *offset )
+{
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ if (!offset)
+ return DFB_INVARG;
+
+ D_UNIMPLEMENTED();
+
+ return DFB_UNIMPLEMENTED;
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_Unlock( IDirectFBSurface *thiz )
+{
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ D_UNIMPLEMENTED();
+
+ return DFB_UNIMPLEMENTED;
+}
+
+static DirectResult
+Handle_FlipReturned( IDirectFBSurface *thiz,
+ unsigned int millis )
+{
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ D_DEBUG_AT( IDirectFBSurface_RequestorFlip, "%s( %p, millis %u )\n", __FUNCTION__, thiz, millis );
+
+ long long now = direct_clock_get_micros();
+
+ data->flip.returned = millis;
+
+ data->flip.fps_count++;
+
+
+ long long diff = now - data->flip.fps_stamp;
+ unsigned int frames = data->flip.fps_count - data->flip.fps_old;
+
+ if (diff > 10000000) {
+ long long kfps = frames * 1000000000ULL / diff;
+
+ D_INFO( "IDirectFBSurface_Requestor_FlipNotify: FPS %lld.%03lld\n", kfps / 1000, kfps % 1000 );
+
+ data->flip.fps_stamp = now;
+ data->flip.fps_old = data->flip.fps_count;
+ }
+
+ return DR_OK;
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_Flip( IDirectFBSurface *thiz,
+ const DFBRegion *region,
+ DFBSurfaceFlipFlags flags )
+{
+ DirectResult ret;
+ unsigned int millis;
+ bool use_notify_or_buffer = false;
+
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ D_DEBUG_AT( IDirectFBSurface_RequestorFlip, "%s( %p, region %p, flags 0x%08x )\n", __FUNCTION__, thiz, region, flags );
+
+ // FIXME: find better heuristic for flip control, or use flag
+ if (!region || (region->x1 == 0 && region->y1 == 0))
+ use_notify_or_buffer = true;
+
+ millis = direct_clock_get_abs_millis();
+
+ if (flags & DSFLIP_WAIT) {
+ VoodooResponseMessage *response;
+
+ if (data->flip.use_notify)
+ ret = voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_Flip, VREQ_RESPOND, &response,
+ VMBT_ODATA, sizeof(DFBRegion), region,
+ VMBT_INT, flags,
+ VMBT_UINT, millis,
+ VMBT_NONE );
+ else
+ ret = voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_Flip, VREQ_RESPOND, &response,
+ VMBT_ODATA, sizeof(DFBRegion), region,
+ VMBT_INT, flags,
+ VMBT_NONE );
+ if (ret)
+ return ret;
+
+ ret = response->result;
+
+ voodoo_manager_finish_request( data->manager, response );
+
+ return ret;
+ }
+
+ if (data->flip.use_notify) {
+ D_DEBUG_AT( IDirectFBSurface_RequestorFlip, " -> millis %u, using FlipNotify\n", millis );
+
+ ret = voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_Flip, VREQ_NONE, NULL,
+ VMBT_ODATA, sizeof(DFBRegion), region,
+ VMBT_INT, flags,
+ VMBT_UINT, millis,
+ VMBT_NONE );
+ }
+ else {
+ D_DEBUG_AT( IDirectFBSurface_RequestorFlip, " -> millis %u, not using FlipNotify\n", millis );
+
+ ret = voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_Flip, VREQ_NONE, NULL,
+ VMBT_ODATA, sizeof(DFBRegion), region,
+ VMBT_INT, flags,
+ VMBT_NONE );
+ }
+
+ if (use_notify_or_buffer && data->flip.use_notify) {
+ if (data->flip.end && millis - data->flip.end < 16) {
+ D_DEBUG_AT( IDirectFBSurface_RequestorFlip, " -> delaying next frame by %d ms\n", 16 - (millis - data->flip.end) );
+
+ direct_thread_sleep( (16 - (millis - data->flip.end)) * 1000 );
+ }
+
+ data->flip.requested = millis;
+ data->flip.end = direct_clock_get_abs_millis();;
+
+ direct_mutex_lock( &data->flip.lock );
+
+ while (data->flip.requested - data->flip.returned > dfb_config->flip_notify_max_latency)
+ direct_waitqueue_wait( &data->flip.queue, &data->flip.lock );
+
+ direct_mutex_unlock( &data->flip.lock );
+ }
+ else if (use_notify_or_buffer && data->flip.use_buffer) {
+ ret = data->flip.window->MoveTo( data->flip.window, 1 + (millis & 0xffff), 1 + (millis >> 16) );
+ if (ret) {
+ D_DERROR( ret, "IDirectFBSurface_Requestor_Flip: MoveTo() for FlipNotify fallback failed!\n" );
+ data->flip.use_buffer = false;
+ return DFB_OK;
+ }
+
+ if (data->flip.end && millis - data->flip.end < 16) {
+ D_DEBUG_AT( IDirectFBSurface_RequestorFlip, " -> delaying next frame by %d ms\n", 16 - (millis - data->flip.end) );
+
+ direct_thread_sleep( (16 - (millis - data->flip.end)) * 1000 );
+ }
+
+ data->flip.requested = millis;
+ data->flip.end = direct_clock_get_abs_millis();;
+
+
+ DFBEvent event;
+
+ while (data->flip.buffer->GetEvent( data->flip.buffer, &event ) == DFB_OK) {
+ if (event.clazz == DFEC_WINDOW && event.window.type == DWET_POSITION)
+ Handle_FlipReturned( thiz, ((u32)event.window.x - 1) | (((u32)event.window.y - 1) << 16) );
+ }
+
+ while (data->flip.requested - data->flip.returned > dfb_config->flip_notify_max_latency) {
+ data->flip.buffer->WaitForEvent( data->flip.buffer );
+
+ while (data->flip.buffer->GetEvent( data->flip.buffer, &event ) == DFB_OK) {
+ if (event.clazz == DFEC_WINDOW && event.window.type == DWET_POSITION)
+ Handle_FlipReturned( thiz, ((u32)event.window.x - 1) | (((u32)event.window.y - 1) << 16) );
+ }
+ }
+ }
+
+ return ret;
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_SetField( IDirectFBSurface *thiz,
+ int field )
+{
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ if (field < 0 || field > 1)
+ return DFB_INVARG;
+
+ D_UNIMPLEMENTED();
+
+ return DFB_UNIMPLEMENTED;
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_Clear( IDirectFBSurface *thiz,
+ u8 r, u8 g, u8 b, u8 a )
+{
+ DFBColor color = { a, r, g, b };
+
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ return voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_Clear, VREQ_QUEUE, NULL,
+ VMBT_DATA, sizeof(DFBColor), &color,
+ VMBT_NONE );
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_SetClip( IDirectFBSurface *thiz, const DFBRegion *clip )
+{
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ return voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_SetClip, VREQ_QUEUE, NULL,
+ VMBT_ODATA, sizeof(DFBRegion), clip,
+ VMBT_NONE );
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_SetColor( IDirectFBSurface *thiz,
+ u8 r, u8 g, u8 b, u8 a )
+{
+ DFBColor color = { a, r, g, b };
+
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ return voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_SetColor, VREQ_QUEUE, NULL,
+ VMBT_DATA, sizeof(DFBColor), &color,
+ VMBT_NONE );
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_SetColorIndex( IDirectFBSurface *thiz,
+ unsigned int index )
+{
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ D_UNIMPLEMENTED();
+
+ return DFB_UNIMPLEMENTED;
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_SetSrcBlendFunction( IDirectFBSurface *thiz,
+ DFBSurfaceBlendFunction src )
+{
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ D_UNIMPLEMENTED();
+
+ return DFB_UNIMPLEMENTED;
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_SetDstBlendFunction( IDirectFBSurface *thiz,
+ DFBSurfaceBlendFunction dst )
+{
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ D_UNIMPLEMENTED();
+
+ return DFB_UNIMPLEMENTED;
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_SetPorterDuff( IDirectFBSurface *thiz,
+ DFBSurfacePorterDuffRule rule )
+{
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ D_UNIMPLEMENTED();
+
+ return DFB_UNIMPLEMENTED;
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_SetSrcColorKey( IDirectFBSurface *thiz,
+ u8 r,
+ u8 g,
+ u8 b )
+{
+ DFBColor color = { 0, r, g, b };
+
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ return voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_SetSrcColorKey, VREQ_QUEUE, NULL,
+ VMBT_DATA, sizeof(DFBColor), &color,
+ VMBT_NONE );
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_SetSrcColorKeyIndex( IDirectFBSurface *thiz,
+ unsigned int index )
+{
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ return voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_SetSrcColorKeyIndex, VREQ_QUEUE, NULL,
+ VMBT_UINT, index,
+ VMBT_NONE );
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_SetDstColorKey( IDirectFBSurface *thiz,
+ u8 r,
+ u8 g,
+ u8 b )
+{
+ DFBColor color = { 0, r, g, b };
+
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ return voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_SetDstColorKey, VREQ_QUEUE, NULL,
+ VMBT_DATA, sizeof(DFBColor), &color,
+ VMBT_NONE );
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_SetDstColorKeyIndex( IDirectFBSurface *thiz,
+ unsigned int index )
+{
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ return voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_SetDstColorKeyIndex, VREQ_QUEUE, NULL,
+ VMBT_UINT, index,
+ VMBT_NONE );
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_SetFont( IDirectFBSurface *thiz,
+ IDirectFBFont *font )
+{
+ IDirectFBFont_Requestor_data *font_data = NULL;
+
+ DIRECT_INTERFACE_GET_DATA( IDirectFBSurface_Requestor )
+
+ if (data->font == font)
+ return DFB_OK;
+
+ if (font) {
+ font->AddRef (font);
+
+ DIRECT_INTERFACE_GET_DATA_FROM( font, font_data, IDirectFBFont_Requestor );
+ }
+
+ if (data->font)
+ data->font->Release (data->font);
+
+ data->font = font;
+
+ return voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_SetFont, VREQ_QUEUE, NULL,
+ VMBT_ID, font_data ? font_data->instance : VOODOO_INSTANCE_NONE,
+ VMBT_NONE );
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_GetFont( IDirectFBSurface *thiz,
+ IDirectFBFont **font )
+{
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ D_UNIMPLEMENTED();
+
+ return DFB_UNIMPLEMENTED;
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_SetDrawingFlags( IDirectFBSurface *thiz,
+ DFBSurfaceDrawingFlags flags )
+{
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ return voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_SetDrawingFlags, VREQ_QUEUE, NULL,
+ VMBT_INT, flags,
+ VMBT_NONE );
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_FillRectangle( IDirectFBSurface *thiz,
+ int x, int y, int w, int h )
+{
+ DFBRectangle rect = { x, y, w, h };
+
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ if (w <= 0 || h <= 0)
+ return DFB_INVARG;
+
+ return voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_FillRectangle, VREQ_QUEUE, NULL,
+ VMBT_DATA, sizeof(DFBRectangle), &rect,
+ VMBT_NONE );
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_FillRectangles( IDirectFBSurface *thiz,
+ const DFBRectangle *rects,
+ unsigned int num_rects )
+{
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ if (!rects || !num_rects)
+ return DFB_INVARG;
+
+ return voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_FillRectangles, VREQ_QUEUE, NULL,
+ VMBT_UINT, num_rects,
+ VMBT_DATA, num_rects * sizeof(DFBRectangle), rects,
+ VMBT_NONE );
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_FillSpans( IDirectFBSurface *thiz,
+ int y,
+ const DFBSpan *spans,
+ unsigned int num_spans )
+{
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ if (!spans || !num_spans)
+ return DFB_INVARG;
+
+ return voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_FillSpans, VREQ_QUEUE, NULL,
+ VMBT_INT, y,
+ VMBT_UINT, num_spans,
+ VMBT_DATA, num_spans * sizeof(DFBSpan), spans,
+ VMBT_NONE );
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_DrawLine( IDirectFBSurface *thiz,
+ int x1, int y1, int x2, int y2 )
+{
+ DFBRegion line = { x1, y1, x2, y2 };
+
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ return voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_DrawLine, VREQ_QUEUE, NULL,
+ VMBT_DATA, sizeof(DFBRegion), &line,
+ VMBT_NONE );
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_DrawLines( IDirectFBSurface *thiz,
+ const DFBRegion *lines,
+ unsigned int num_lines )
+{
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ if (!lines || !num_lines)
+ return DFB_INVARG;
+
+ return voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_DrawLines, VREQ_QUEUE, NULL,
+ VMBT_UINT, num_lines,
+ VMBT_DATA, num_lines * sizeof(DFBRegion), lines,
+ VMBT_NONE );
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_DrawRectangle( IDirectFBSurface *thiz,
+ int x, int y, int w, int h )
+{
+ DFBRectangle rect = { x, y, w, h };
+
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ if (w <= 0 || h <= 0)
+ return DFB_INVARG;
+
+ return voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_DrawRectangle, VREQ_QUEUE, NULL,
+ VMBT_DATA, sizeof(DFBRectangle), &rect,
+ VMBT_NONE );
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_FillTriangle( IDirectFBSurface *thiz,
+ int x1, int y1,
+ int x2, int y2,
+ int x3, int y3 )
+{
+ DFBTriangle triangle = { x1, y1, x2, y2, x3, y3 };
+
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ return voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_FillTriangle, VREQ_QUEUE, NULL,
+ VMBT_DATA, sizeof(DFBTriangle), &triangle,
+ VMBT_NONE );
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_SetBlittingFlags( IDirectFBSurface *thiz,
+ DFBSurfaceBlittingFlags flags )
+{
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ return voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_SetBlittingFlags, VREQ_QUEUE, NULL,
+ VMBT_INT, flags,
+ VMBT_NONE );
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_Blit( IDirectFBSurface *thiz,
+ IDirectFBSurface *source,
+ const DFBRectangle *rect,
+ int x,
+ int y )
+{
+ DFBPoint point = { x, y };
+
+ IDirectFBSurface_Requestor_data *source_data;
+
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ if (!source)
+ return DFB_INVARG;
+
+ DIRECT_INTERFACE_GET_DATA_FROM( source, source_data, IDirectFBSurface_Requestor );
+
+ return voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_Blit, VREQ_QUEUE, NULL,
+ VMBT_ID, source_data->instance,
+ VMBT_ODATA, sizeof(DFBRectangle), rect,
+ VMBT_DATA, sizeof(point), &point,
+ VMBT_NONE );
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_TileBlit( IDirectFBSurface *thiz,
+ IDirectFBSurface *source,
+ const DFBRectangle *rect,
+ int x,
+ int y )
+{
+ DFBPoint point = { x, y };
+
+ IDirectFBSurface_Requestor_data *source_data;
+
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ if (!source)
+ return DFB_INVARG;
+
+ DIRECT_INTERFACE_GET_DATA_FROM( source, source_data, IDirectFBSurface_Requestor );
+
+ return voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_TileBlit, VREQ_QUEUE, NULL,
+ VMBT_ID, source_data->instance,
+ VMBT_ODATA, sizeof(DFBRectangle), rect,
+ VMBT_DATA, sizeof(point), &point,
+ VMBT_NONE );
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_BatchBlit( IDirectFBSurface *thiz,
+ IDirectFBSurface *source,
+ const DFBRectangle *source_rects,
+ const DFBPoint *dest_points,
+ int num )
+{
+ IDirectFBSurface_Requestor_data *source_data;
+
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ if (!source || !source_rects || !dest_points || num < 1)
+ return DFB_INVARG;
+
+ DIRECT_INTERFACE_GET_DATA_FROM( source, source_data, IDirectFBSurface_Requestor );
+
+ return voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_BatchBlit, VREQ_QUEUE, NULL,
+ VMBT_ID, source_data->instance,
+ VMBT_UINT, num,
+ VMBT_DATA, num * sizeof(DFBRectangle), source_rects,
+ VMBT_DATA, num * sizeof(DFBPoint), dest_points,
+ VMBT_NONE );
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_StretchBlit( IDirectFBSurface *thiz,
+ IDirectFBSurface *source,
+ const DFBRectangle *source_rect,
+ const DFBRectangle *destination_rect )
+{
+ IDirectFBSurface_Requestor_data *source_data;
+
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ if (!source)
+ return DFB_INVARG;
+
+ DIRECT_INTERFACE_GET_DATA_FROM( source, source_data, IDirectFBSurface_Requestor );
+
+ return voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_StretchBlit, VREQ_QUEUE, NULL,
+ VMBT_ID, source_data->instance,
+ VMBT_ODATA, sizeof(DFBRectangle), source_rect,
+ VMBT_ODATA, sizeof(DFBRectangle), destination_rect,
+ VMBT_NONE );
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_TextureTriangles( IDirectFBSurface *thiz,
+ IDirectFBSurface *source,
+ const DFBVertex *vertices,
+ const int *indices,
+ int num,
+ DFBTriangleFormation formation )
+{
+ int i;
+ int num_vertices = 0;
+ IDirectFBSurface_Requestor_data *source_data;
+
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ if (!source || !vertices || num < 3)
+ return DFB_INVARG;
+
+ if (indices) {
+ for (i=0; i<num; i++) {
+ if (num_vertices <= indices[i])
+ num_vertices = indices[i] + 1;
+ }
+ }
+
+ DIRECT_INTERFACE_GET_DATA_FROM( source, source_data, IDirectFBSurface_Requestor );
+
+ return voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_TextureTriangles, VREQ_QUEUE, NULL,
+ VMBT_ID, source_data->instance,
+ VMBT_DATA, num_vertices * sizeof(DFBVertex), vertices,
+ VMBT_ODATA, num * sizeof(int), indices,
+ VMBT_INT, num,
+ VMBT_INT, formation,
+ VMBT_NONE );
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_DrawString( IDirectFBSurface *thiz,
+ const char *text,
+ int bytes,
+ int x,
+ int y,
+ DFBSurfaceTextFlags flags )
+{
+ DFBPoint point = { x, y };
+
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ if (!text)
+ return DFB_INVARG;
+
+ if (!data->font)
+ return DFB_MISSINGFONT;
+
+
+ if (bytes < 0)
+ bytes = strlen (text);
+
+ if (bytes == 0)
+ return DFB_OK;
+
+ return voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_DrawString, VREQ_QUEUE, NULL,
+ VMBT_DATA, bytes, text,
+ VMBT_INT, bytes,
+ VMBT_DATA, sizeof(point), &point,
+ VMBT_INT, flags,
+ VMBT_NONE );
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_DrawGlyph( IDirectFBSurface *thiz,
+ unsigned int index,
+ int x,
+ int y,
+ DFBSurfaceTextFlags flags )
+{
+ DFBPoint point = { x, y };
+
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ if (!index)
+ return DFB_INVARG;
+
+ return voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_DrawGlyph, VREQ_QUEUE, NULL,
+ VMBT_UINT, index,
+ VMBT_DATA, sizeof(point), &point,
+ VMBT_INT, flags,
+ VMBT_NONE );
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_SetEncoding( IDirectFBSurface *thiz,
+ DFBTextEncodingID encoding )
+{
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ return voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_SetEncoding, VREQ_QUEUE, NULL,
+ VMBT_UINT, encoding,
+ VMBT_NONE );
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_GetSubSurface( IDirectFBSurface *thiz,
+ const DFBRectangle *rect,
+ IDirectFBSurface **ret_interface )
+{
+ DirectResult ret;
+ VoodooResponseMessage *response;
+ VoodooInstanceID instance_id;
+ void *interface_ptr = NULL;
+
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ if (!ret_interface)
+ return DFB_INVARG;
+
+ ret = voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_GetSubSurface, VREQ_RESPOND, &response,
+ VMBT_ODATA, sizeof(DFBRectangle), rect,
+ VMBT_NONE );
+ if (ret)
+ return ret;
+
+ instance_id = response->instance;
+
+ voodoo_manager_finish_request( data->manager, response );
+
+ ret = response->result;
+ if (ret == DR_OK)
+ ret = voodoo_construct_requestor( data->manager, "IDirectFBSurface",
+ instance_id, data->idirectfb, &interface_ptr );
+
+ *ret_interface = interface_ptr;
+
+ return ret;
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_GetGL( IDirectFBSurface *thiz,
+ IDirectFBGL **interface_ptr )
+{
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ if (!interface_ptr)
+ return DFB_INVARG;
+
+ D_UNIMPLEMENTED();
+
+ return DFB_UNIMPLEMENTED;
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_Dump( IDirectFBSurface *thiz,
+ const char *directory,
+ const char *prefix )
+{
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ if (!directory || !prefix)
+ return DFB_INVARG;
+
+ D_UNIMPLEMENTED();
+
+ return DFB_UNIMPLEMENTED;
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_DisableAcceleration( IDirectFBSurface *thiz,
+ DFBAccelerationMask mask )
+{
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ return voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_DisableAcceleration,
+ VREQ_QUEUE, NULL,
+ VMBT_UINT, mask,
+ VMBT_NONE );
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_ReleaseSource( IDirectFBSurface *thiz )
+{
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ return voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_ReleaseSource, VREQ_QUEUE, NULL,
+ VMBT_NONE );
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_SetIndexTranslation( IDirectFBSurface *thiz,
+ const int *indices,
+ int num_indices )
+{
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ D_UNIMPLEMENTED();
+
+ return DFB_UNIMPLEMENTED;
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_SetRenderOptions( IDirectFBSurface *thiz,
+ DFBSurfaceRenderOptions options )
+{
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ return voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_SetRenderOptions, VREQ_QUEUE, NULL,
+ VMBT_INT, options,
+ VMBT_NONE );
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_SetMatrix( IDirectFBSurface *thiz,
+ const s32 *matrix )
+{
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ return voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_SetMatrix, VREQ_QUEUE, NULL,
+ VMBT_DATA, sizeof(s32) * 9, matrix,
+ VMBT_NONE );
+}
+
+#define RLE16_KEY 0xf001
+
+static bool
+rle16_encode( const u16 *src,
+ u16 *dst,
+ unsigned int num,
+ unsigned int *ret_num )
+{
+ unsigned int n, last, count = 0, out = 0;
+
+ for (n=0; n<num; n++) {
+ if (out + 3 > num) {
+ *ret_num = num;
+ return false;
+ }
+
+ if (count > 0) {
+ D_ASSERT( src[n] == last );
+
+ count++;
+ }
+ else {
+ count = 1;
+ last = src[n];
+ }
+
+ if (n == num-1 || src[n+1] != last) {
+ if (count > 2 || (count > 1 && last == RLE16_KEY)) {
+ dst[out++] = RLE16_KEY;
+ dst[out++] = count;
+ dst[out++] = last;
+ }
+ else {
+ if (count > 1 || last == RLE16_KEY)
+ dst[out++] = last;
+
+ dst[out++] = last;
+ }
+
+ count = 0;
+ }
+ }
+
+ *ret_num = out;
+
+ return true;
+}
+
+#define RLE32_KEY 0xf0012345
+
+static bool
+rle32_encode( const u32 *src,
+ u32 *dst,
+ unsigned int num,
+ unsigned int *ret_num )
+{
+ unsigned int n, last, count = 0, out = 0;
+
+ for (n=0; n<num; n++) {
+ if (out + 3 > num) {
+ *ret_num = num;
+ return false;
+ }
+
+ if (count > 0) {
+ D_ASSERT( src[n] == last );
+
+ count++;
+ }
+ else {
+ count = 1;
+ last = src[n];
+ }
+
+ if (n == num-1 || src[n+1] != last) {
+ if (count > 2 || (count > 1 && last == RLE32_KEY)) {
+ dst[out++] = RLE32_KEY;
+ dst[out++] = count;
+ dst[out++] = last;
+ }
+ else {
+ if (count > 1 || last == RLE32_KEY)
+ dst[out++] = last;
+
+ dst[out++] = last;
+ }
+
+ count = 0;
+ }
+ }
+
+ *ret_num = out;
+
+ return true;
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_Write( IDirectFBSurface *thiz,
+ const DFBRectangle *rect,
+ const void *ptr,
+ int pitch )
+{
+ DFBResult ret = DFB_OK;
+ int y;
+ DFBRectangle r;
+ DFBSurfacePixelFormat format;
+
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ if (!rect || !ptr)
+ return DFB_INVARG;
+
+ thiz->GetPixelFormat( thiz, &format );
+
+ r.x = rect->x;
+ r.y = rect->y;
+ r.w = rect->w;
+ r.h = 1;
+
+ /* Use RLE only if Voodoo is not compressed already */
+ switch (voodoo_config->compression_min ? DSPF_UNKNOWN : format) {
+ case DSPF_RGB16:
+ case DSPF_ARGB1555: {
+ unsigned int num;
+ u16 *buf = (u16*) D_MALLOC( rect->w * 2 );
+
+ if (buf) {
+ for (y=0; y<rect->h; y++) {
+ bool encoded = rle16_encode( (u16*)((char*) ptr + y * pitch), buf, rect->w, &num );
+
+ //D_INFO( "%3d: %u -> %u\n", r.y, rect->w, num );
+
+ ret = voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_Write, VREQ_QUEUE, NULL,
+ VMBT_UINT, encoded ? 2 : 0,
+ VMBT_DATA, sizeof(DFBRectangle), &r,
+ VMBT_DATA, DFB_BYTES_PER_LINE( format, num ),
+ encoded ? buf : (u16*)((char*) ptr + y * pitch),
+ VMBT_INT, ABS(pitch),
+ VMBT_NONE );
+ if (ret)
+ break;
+
+ r.y++;
+ }
+
+ D_FREE( buf );
+ }
+ else
+ D_OOM();
+
+ break;
+ }
+
+ case DSPF_RGB32:
+ case DSPF_ARGB: {
+ unsigned int num;
+ u32 *buf = (u32*) D_MALLOC( rect->w * 4 );
+
+ if (buf) {
+ for (y=0; y<rect->h; y++) {
+ bool encoded = rle32_encode( (u32*)((char*) ptr + y * pitch), buf, rect->w, &num );
+
+ //D_INFO( "%3d: %u -> %u\n", r.y, rect->w, num );
+
+ ret = voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_Write, VREQ_QUEUE, NULL,
+ VMBT_UINT, encoded ? 4 : 0,
+ VMBT_DATA, sizeof(DFBRectangle), &r,
+ VMBT_DATA, DFB_BYTES_PER_LINE( format, num ),
+ encoded ? buf : (u32*)((char*) ptr + y * pitch),
+ VMBT_INT, ABS(pitch),
+ VMBT_NONE );
+ if (ret)
+ break;
+
+ r.y++;
+ }
+
+ D_FREE( buf );
+ }
+ else
+ D_OOM();
+
+ break;
+ }
+
+ default:
+ for (y=0; y<rect->h; y++) {
+ ret = voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_Write, VREQ_QUEUE, NULL,
+ VMBT_UINT, false,
+ VMBT_DATA, sizeof(DFBRectangle), &r,
+ VMBT_DATA, DFB_BYTES_PER_LINE( format, rect->w ), (char*) ptr + y * pitch,
+ VMBT_INT, ABS(pitch),
+ VMBT_NONE );
+ if (ret)
+ break;
+
+ r.y++;
+ }
+ break;
+ }
+
+ return ret;
+}
+
+
+#define RLE16_KEY 0xf001
+
+static void
+rle16_decode( const u16 *src,
+ u16 *dst,
+ unsigned int num )
+{
+ unsigned int n = 0, last, count, out = 0;
+
+ while (out < num) {
+ last = src[n++];
+
+ if (last == RLE16_KEY) {
+ count = src[n++];
+
+ if (count == RLE16_KEY) {
+ dst[out++] = RLE16_KEY;
+ }
+ else {
+ last = src[n++];
+
+ while (count >= 4) {
+ dst[out+0] =
+ dst[out+1] =
+ dst[out+2] =
+ dst[out+3] = last;
+
+ out += 4;
+ count -= 4;
+ }
+
+ while (count >= 2) {
+ dst[out+0] =
+ dst[out+1] = last;
+
+ out += 2;
+ count -= 2;
+ }
+
+ while (count--)
+ dst[out++] = last;
+ }
+ }
+ else
+ dst[out++] = last;
+ }
+
+ D_ASSERT( out == num );
+}
+
+#define RLE32_KEY 0xf0012345
+
+static void
+rle32_decode( const u32 *src,
+ u32 *dst,
+ unsigned int num )
+{
+ unsigned int n = 0, last, count, out = 0;
+
+ while (out < num) {
+ last = src[n++];
+
+ if (last == RLE32_KEY) {
+ count = src[n++];
+
+ if (count == RLE32_KEY) {
+ dst[out++] = RLE32_KEY;
+ }
+ else {
+ last = src[n++];
+
+ while (count >= 4) {
+ dst[out+0] =
+ dst[out+1] =
+ dst[out+2] =
+ dst[out+3] = last;
+
+ out += 4;
+ count -= 4;
+ }
+
+ while (count >= 2) {
+ dst[out+0] =
+ dst[out+1] = last;
+
+ out += 2;
+ count -= 2;
+ }
+
+ while (count--)
+ dst[out++] = last;
+ }
+ }
+ else
+ dst[out++] = last;
+ }
+
+ D_ASSERT( out == num );
+}
+
+static DFBResult
+IDirectFBSurface_Requestor_Read( IDirectFBSurface *thiz,
+ const DFBRectangle *rect,
+ void *ptr,
+ int pitch )
+{
+ DFBResult ret = DFB_OK;
+ int y;
+ DFBSurfacePixelFormat format;
+ VoodooMessageParser parser;
+ VoodooResponseMessage *response;
+
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ D_DEBUG_AT( IDirectFBSurface_Requestor_, "%s( %p, %p, %d )\n", __FUNCTION__, rect, ptr, pitch );
+
+ if (!rect || !ptr)
+ return DFB_INVARG;
+
+ D_DEBUG_AT( IDirectFBSurface_Requestor_, " -> %4d,%4d-%4dx%4d\n", DFB_RECTANGLE_VALS(rect) );
+
+ thiz->GetPixelFormat( thiz, &format );
+
+ ret = voodoo_manager_request( data->manager, data->instance,
+ IDIRECTFBSURFACE_METHOD_ID_Read, VREQ_RESPOND, &response,
+ VMBT_DATA, sizeof(DFBRectangle), rect,
+ VMBT_NONE );
+ if (ret)
+ return ret;
+
+ for (y=0; y<rect->h; y++) {
+ unsigned int encoded;
+ const void *buf;
+
+ D_DEBUG_AT( IDirectFBSurface_Requestor_, " -> [%d]\n", y );
+
+ VOODOO_PARSER_BEGIN( parser, response );
+ VOODOO_PARSER_GET_UINT( parser, encoded );
+ VOODOO_PARSER_GET_DATA( parser, buf );
+ VOODOO_PARSER_END( parser );
+
+ ret = response->result;
+ if (ret)
+ break;
+
+
+ if (encoded) {
+ switch (encoded) {
+ case 2:
+ rle16_decode( buf, (u16*)((char*) ptr + pitch * y), rect->w );
+ break;
+
+ case 4:
+ rle32_decode( buf, (u32*)((char*) ptr + pitch * y), rect->w );
+ break;
+
+ default:
+ D_UNIMPLEMENTED();
+ break;
+ }
+ }
+ else
+ direct_memcpy( (char*) ptr + pitch * y, buf, DFB_BYTES_PER_LINE(format, rect->w) );
+
+
+ if (y < rect->h - 1)
+ voodoo_manager_next_response( data->manager, response, &response );
+ }
+
+ voodoo_manager_finish_request( data->manager, response );
+
+ return ret;
+}
+
+
+/**************************************************************************************************/
+
+static DirectResult
+Dispatch_FlipNotify( IDirectFBSurface *thiz, IDirectFBSurface *real,
+ VoodooManager *manager, VoodooRequestMessage *msg )
+{
+ VoodooMessageParser parser;
+ unsigned int millis;
+
+ DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor)
+
+ direct_mutex_lock( &data->flip.lock );
+
+
+ VOODOO_PARSER_BEGIN( parser, msg );
+ VOODOO_PARSER_GET_UINT( parser, millis );
+ VOODOO_PARSER_END( parser );
+
+
+ Handle_FlipReturned( thiz, millis );
+
+
+ direct_mutex_unlock( &data->flip.lock );
+
+ direct_waitqueue_signal( &data->flip.queue );
+
+ return DR_OK;
+}
+
+static DirectResult
+LocalDispatch( void *dispatcher,
+ void *real,
+ VoodooManager *manager,
+ VoodooRequestMessage *msg )
+{
+ D_DEBUG( "IDirectFBSurface_Requestor/LocalDispatch: "
+ "Handling request for instance %u with method %u...\n", msg->instance, msg->method );
+
+ switch (msg->method) {
+ case IDIRECTFBSURFACE_REQUESTOR_METHOD_ID_FlipNotify:
+ return Dispatch_FlipNotify( real, real, manager, msg );
+ }
+
+ return DFB_NOSUCHMETHOD;
+}
+
+/**************************************************************************************************/
+
+static DFBResult
+Probe()
+{
+ /* This implementation has to be loaded explicitly. */
+ return DFB_UNSUPPORTED;
+}
+
+static DFBResult
+Construct( IDirectFBSurface *thiz,
+ VoodooManager *manager,
+ VoodooInstanceID instance,
+ void *arg )
+{
+ DFBResult ret;
+ VoodooResponseMessage *response;
+
+ DIRECT_ALLOCATE_INTERFACE_DATA(thiz, IDirectFBSurface_Requestor)
+
+ data->ref = 1;
+ data->manager = manager;
+ data->instance = instance;
+ data->idirectfb = arg;
+
+
+ direct_mutex_init( &data->flip.lock );
+ direct_waitqueue_init( &data->flip.queue );
+
+ if (dfb_config->flip_notify_max_latency) {
+ ret = voodoo_manager_register_local( manager, VOODOO_INSTANCE_NONE, NULL, thiz, LocalDispatch, &data->local );
+ if (ret) {
+ D_DERROR( ret, "IDirectFBSurface_Requestor: Could not register local dispatch!\n" );
+ DIRECT_DEALLOCATE_INTERFACE( thiz );
+ return ret;
+ }
+
+ ret = voodoo_manager_request( manager, instance,
+ IDIRECTFBSURFACE_METHOD_ID_SetRemoteInstance, VREQ_RESPOND, &response,
+ VMBT_ID, data->local,
+ VMBT_NONE );
+ if (ret)
+ D_DERROR( ret, "IDirectFBSurface_Requestor: Could not set remote instance, FlipNotify not used!\n" );
+ else if (response->result)
+ D_DERROR( response->result, "IDirectFBSurface_Requestor: Could not set remote instance, FlipNotify not used!\n" );
+ else {
+ D_INFO( "IDirectFBSurface_Requestor: Using FlipNotify\n" );
+
+ data->flip.use_notify = true;
+ }
+
+ voodoo_manager_finish_request( manager, response );
+
+ /*
+ * Implement fallback for missing FlipNotify support via event buffer and hidden window
+ */
+ if (!data->flip.use_notify) {
+ DFBWindowDescription desc;
+ IDirectFBDisplayLayer *layer;
+
+ ret = data->idirectfb->CreateEventBuffer( data->idirectfb, &data->flip.buffer );
+ if (ret) {
+ D_DERROR( ret, "IDirectFBSurface_Requestor: Could not create event buffer for FlipNotify fallback!\n" );
+ DIRECT_DEALLOCATE_INTERFACE( thiz );
+ return ret;
+ }
+
+ ret = data->idirectfb->GetDisplayLayer( data->idirectfb, DLID_PRIMARY, &layer );
+ if (ret) {
+ D_DERROR( ret, "IDirectFBSurface_Requestor: Could not get display layer for FlipNotify fallback!\n" );
+ DIRECT_DEALLOCATE_INTERFACE( thiz );
+ return ret;
+ }
+
+ desc.flags = DWDESC_CAPS;
+ desc.caps = DWCAPS_INPUTONLY | DWCAPS_NODECORATION;
+
+ ret = layer->CreateWindow( layer, &desc, &data->flip.window );
+ if (ret) {
+ D_DERROR( ret, "IDirectFBSurface_Requestor: Could not create window for FlipNotify fallback!\n" );
+ DIRECT_DEALLOCATE_INTERFACE( thiz );
+ return ret;
+ }
+
+ ret = data->flip.window->AttachEventBuffer( data->flip.window, data->flip.buffer );
+ if (ret) {
+ D_DERROR( ret, "IDirectFBSurface_Requestor: Could not attach event buffer for FlipNotify fallback!\n" );
+ DIRECT_DEALLOCATE_INTERFACE( thiz );
+ return ret;
+ }
+
+ layer->Release( layer );
+
+
+ D_INFO( "IDirectFBSurface_Requestor: Using FlipNotify fallback via event buffer/window!\n" );
+
+ data->flip.use_buffer = true;
+ }
+ }
+
+ thiz->AddRef = IDirectFBSurface_Requestor_AddRef;
+ thiz->Release = IDirectFBSurface_Requestor_Release;
+
+ thiz->GetCapabilities = IDirectFBSurface_Requestor_GetCapabilities;
+ thiz->GetPosition = IDirectFBSurface_Requestor_GetPosition;
+ thiz->GetSize = IDirectFBSurface_Requestor_GetSize;
+ thiz->GetVisibleRectangle = IDirectFBSurface_Requestor_GetVisibleRectangle;
+ thiz->GetPixelFormat = IDirectFBSurface_Requestor_GetPixelFormat;
+ thiz->GetAccelerationMask = IDirectFBSurface_Requestor_GetAccelerationMask;
+
+ thiz->GetPalette = IDirectFBSurface_Requestor_GetPalette;
+ thiz->SetPalette = IDirectFBSurface_Requestor_SetPalette;
+ thiz->SetAlphaRamp = IDirectFBSurface_Requestor_SetAlphaRamp;
+
+ thiz->Lock = IDirectFBSurface_Requestor_Lock;
+ thiz->GetFramebufferOffset = IDirectFBSurface_Requestor_GetFramebufferOffset;
+ thiz->Unlock = IDirectFBSurface_Requestor_Unlock;
+ thiz->Flip = IDirectFBSurface_Requestor_Flip;
+ thiz->SetField = IDirectFBSurface_Requestor_SetField;
+ thiz->Clear = IDirectFBSurface_Requestor_Clear;
+
+ thiz->SetClip = IDirectFBSurface_Requestor_SetClip;
+ thiz->SetColor = IDirectFBSurface_Requestor_SetColor;
+ thiz->SetColorIndex = IDirectFBSurface_Requestor_SetColorIndex;
+ thiz->SetSrcBlendFunction = IDirectFBSurface_Requestor_SetSrcBlendFunction;
+ thiz->SetDstBlendFunction = IDirectFBSurface_Requestor_SetDstBlendFunction;
+ thiz->SetPorterDuff = IDirectFBSurface_Requestor_SetPorterDuff;
+ thiz->SetSrcColorKey = IDirectFBSurface_Requestor_SetSrcColorKey;
+ thiz->SetSrcColorKeyIndex = IDirectFBSurface_Requestor_SetSrcColorKeyIndex;
+ thiz->SetDstColorKey = IDirectFBSurface_Requestor_SetDstColorKey;
+ thiz->SetDstColorKeyIndex = IDirectFBSurface_Requestor_SetDstColorKeyIndex;
+
+ thiz->SetBlittingFlags = IDirectFBSurface_Requestor_SetBlittingFlags;
+ thiz->Blit = IDirectFBSurface_Requestor_Blit;
+ thiz->TileBlit = IDirectFBSurface_Requestor_TileBlit;
+ thiz->BatchBlit = IDirectFBSurface_Requestor_BatchBlit;
+ thiz->StretchBlit = IDirectFBSurface_Requestor_StretchBlit;
+ thiz->TextureTriangles = IDirectFBSurface_Requestor_TextureTriangles;
+
+ thiz->SetDrawingFlags = IDirectFBSurface_Requestor_SetDrawingFlags;
+ thiz->FillRectangle = IDirectFBSurface_Requestor_FillRectangle;
+ thiz->FillRectangles = IDirectFBSurface_Requestor_FillRectangles;
+ thiz->FillSpans = IDirectFBSurface_Requestor_FillSpans;
+ thiz->DrawLine = IDirectFBSurface_Requestor_DrawLine;
+ thiz->DrawLines = IDirectFBSurface_Requestor_DrawLines;
+ thiz->DrawRectangle = IDirectFBSurface_Requestor_DrawRectangle;
+ thiz->FillTriangle = IDirectFBSurface_Requestor_FillTriangle;
+
+ thiz->SetFont = IDirectFBSurface_Requestor_SetFont;
+ thiz->GetFont = IDirectFBSurface_Requestor_GetFont;
+ thiz->DrawString = IDirectFBSurface_Requestor_DrawString;
+ thiz->DrawGlyph = IDirectFBSurface_Requestor_DrawGlyph;
+ thiz->SetEncoding = IDirectFBSurface_Requestor_SetEncoding;
+
+ thiz->GetSubSurface = IDirectFBSurface_Requestor_GetSubSurface;
+
+ thiz->GetGL = IDirectFBSurface_Requestor_GetGL;
+
+ thiz->Dump = IDirectFBSurface_Requestor_Dump;
+
+ thiz->DisableAcceleration = IDirectFBSurface_Requestor_DisableAcceleration;
+
+ thiz->ReleaseSource = IDirectFBSurface_Requestor_ReleaseSource;
+
+ thiz->SetIndexTranslation = IDirectFBSurface_Requestor_SetIndexTranslation;
+
+ thiz->SetRenderOptions = IDirectFBSurface_Requestor_SetRenderOptions;
+ thiz->SetMatrix = IDirectFBSurface_Requestor_SetMatrix;
+
+ thiz->Read = IDirectFBSurface_Requestor_Read;
+ thiz->Write = IDirectFBSurface_Requestor_Write;
+
+ return DFB_OK;
+}
+