diff options
Diffstat (limited to 'Source/DirectFB/proxy/dispatcher/idirectfb_dispatcher.c')
-rwxr-xr-x | Source/DirectFB/proxy/dispatcher/idirectfb_dispatcher.c | 1305 |
1 files changed, 1305 insertions, 0 deletions
diff --git a/Source/DirectFB/proxy/dispatcher/idirectfb_dispatcher.c b/Source/DirectFB/proxy/dispatcher/idirectfb_dispatcher.c new file mode 100755 index 0000000..e42fb72 --- /dev/null +++ b/Source/DirectFB/proxy/dispatcher/idirectfb_dispatcher.c @@ -0,0 +1,1305 @@ +/* + (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 <directfb.h> + +#include <direct/debug.h> +#include <direct/interface.h> +#include <direct/list.h> +#include <direct/mem.h> +#include <direct/memcpy.h> +#include <direct/messages.h> +#include <direct/thread.h> +#include <direct/util.h> + +#include <idirectfb.h> + +#include <voodoo/conf.h> +#include <voodoo/interface.h> +#include <voodoo/manager.h> +#include <voodoo/message.h> + +#include "idirectfb_dispatcher.h" + +static DFBResult Probe( void ); +static DFBResult Construct( IDirectFB *thiz, + VoodooManager *manager, + VoodooInstanceID *ret_instance ); + +#include <direct/interface_implementation.h> + +DIRECT_INTERFACE_IMPLEMENTATION( IDirectFB, Dispatcher ) + + +/**************************************************************************************************/ + +typedef struct { + DirectLink link; + + VoodooInstanceID instance; + IDirectFBDataBuffer *requestor; +} DataBufferEntry; + +/* + * private data struct of IDirectFB_Dispatcher + */ +typedef struct { + int ref; /* reference counter */ + + IDirectFB *real; + + CoreDFB *core; + + VoodooInstanceID self; /* The instance of this dispatcher itself. */ + + DirectLink *data_buffers; /* list of known data buffers */ +} IDirectFB_Dispatcher_data; + +/**************************************************************************************************/ + +static void +IDirectFB_Dispatcher_Destruct( IDirectFB *thiz ) +{ + DirectLink *l, *n; + IDirectFB_Dispatcher_data *data = thiz->priv; + + D_DEBUG( "%s (%p)\n", __FUNCTION__, thiz ); + + direct_list_foreach_safe (l, n, data->data_buffers) { + DataBufferEntry *entry = (DataBufferEntry*) l; + + entry->requestor->Release( entry->requestor ); + + D_FREE( entry ); + } + + data->real->Release( data->real ); + + DIRECT_DEALLOCATE_INTERFACE( thiz ); +} + +/**************************************************************************************************/ + +static DirectResult +IDirectFB_Dispatcher_AddRef( IDirectFB *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + data->ref++; + + return DFB_OK; +} + +static DirectResult +IDirectFB_Dispatcher_Release( IDirectFB *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + if (--data->ref == 0) + IDirectFB_Dispatcher_Destruct( thiz ); + + return DFB_OK; +} + +static DFBResult +IDirectFB_Dispatcher_SetCooperativeLevel( IDirectFB *thiz, + DFBCooperativeLevel level ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + + + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFB_Dispatcher_GetDeviceDescription( IDirectFB *thiz, + DFBGraphicsDeviceDescription *ret_desc ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + if (!ret_desc) + return DFB_INVARG; + + + + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFB_Dispatcher_EnumVideoModes( IDirectFB *thiz, + DFBVideoModeCallback callbackfunc, + void *callbackdata ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + if (!callbackfunc) + return DFB_INVARG; + + + + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFB_Dispatcher_SetVideoMode( IDirectFB *thiz, + int width, + int height, + int bpp ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + + + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFB_Dispatcher_CreateSurface( IDirectFB *thiz, + const DFBSurfaceDescription *desc, + IDirectFBSurface **interface_ptr ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + if (!desc || !interface_ptr) + return DFB_INVARG; + + + + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFB_Dispatcher_CreatePalette( IDirectFB *thiz, + const DFBPaletteDescription *desc, + IDirectFBPalette **interface_ptr ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + if (!interface_ptr) + return DFB_INVARG; + + + + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFB_Dispatcher_EnumScreens( IDirectFB *thiz, + DFBScreenCallback callbackfunc, + void *callbackdata ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + if (!callbackfunc) + return DFB_INVARG; + + + + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFB_Dispatcher_GetScreen( IDirectFB *thiz, + DFBScreenID id, + IDirectFBScreen **interface_ptr ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + if (!interface_ptr) + return DFB_INVARG; + + + + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFB_Dispatcher_EnumDisplayLayers( IDirectFB *thiz, + DFBDisplayLayerCallback callbackfunc, + void *callbackdata ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + if (!callbackfunc) + return DFB_INVARG; + + + + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFB_Dispatcher_GetDisplayLayer( IDirectFB *thiz, + DFBDisplayLayerID id, + IDirectFBDisplayLayer **interface_ptr ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + if (!interface_ptr) + return DFB_INVARG; + + + + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFB_Dispatcher_EnumInputDevices( IDirectFB *thiz, + DFBInputDeviceCallback callbackfunc, + void *callbackdata ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + if (!callbackfunc) + return DFB_INVARG; + + + + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFB_Dispatcher_GetInputDevice( IDirectFB *thiz, + DFBInputDeviceID id, + IDirectFBInputDevice **interface_ptr ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + if (!interface_ptr) + return DFB_INVARG; + + + + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFB_Dispatcher_CreateEventBuffer( IDirectFB *thiz, + IDirectFBEventBuffer **interface_ptr) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + if (!interface_ptr) + return DFB_INVARG; + + + + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFB_Dispatcher_CreateInputEventBuffer( IDirectFB *thiz, + DFBInputDeviceCapabilities caps, + DFBBoolean global, + IDirectFBEventBuffer **interface_ptr) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + if (!interface_ptr) + return DFB_INVARG; + + + + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFB_Dispatcher_CreateImageProvider( IDirectFB *thiz, + const char *filename, + IDirectFBImageProvider **interface_ptr ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + /* Check arguments */ + if (!filename || !interface_ptr) + return DFB_INVARG; + + + + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFB_Dispatcher_CreateVideoProvider( IDirectFB *thiz, + const char *filename, + IDirectFBVideoProvider **interface_ptr ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + /* Check arguments */ + if (!interface_ptr || !filename) + return DFB_INVARG; + + + + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFB_Dispatcher_CreateFont( IDirectFB *thiz, + const char *filename, + const DFBFontDescription *desc, + IDirectFBFont **interface_ptr ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + /* Check arguments */ + if (!interface_ptr) + return DFB_INVARG; + + + + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFB_Dispatcher_CreateDataBuffer( IDirectFB *thiz, + const DFBDataBufferDescription *desc, + IDirectFBDataBuffer **interface_ptr ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + if (!interface_ptr) + return DFB_INVARG; + + + + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFB_Dispatcher_SetClipboardData( IDirectFB *thiz, + const char *mime_type, + const void *data, + unsigned int size, + struct timeval *timestamp ) +{ + if (!mime_type || !data || !size) + return DFB_INVARG; + + + + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFB_Dispatcher_GetClipboardData( IDirectFB *thiz, + char **mime_type, + void **clip_data, + unsigned int *size ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + if (!mime_type && !clip_data && !size) + return DFB_INVARG; + + + + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFB_Dispatcher_GetClipboardTimeStamp( IDirectFB *thiz, + struct timeval *timestamp ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + if (!timestamp) + return DFB_INVARG; + + + + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFB_Dispatcher_Suspend( IDirectFB *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + + + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFB_Dispatcher_Resume( IDirectFB *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + + + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFB_Dispatcher_WaitIdle( IDirectFB *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + + + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFB_Dispatcher_WaitForSync( IDirectFB *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + + + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFB_Dispatcher_GetInterface( IDirectFB *thiz, + const char *type, + const char *implementation, + void *arg, + void **interface_ptr ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + + + return DFB_UNIMPLEMENTED; +} + +/**************************************************************************************************/ + +static DirectResult +Dispatch_Release( IDirectFB *thiz, IDirectFB *real, + VoodooManager *manager, VoodooRequestMessage *msg ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + return voodoo_manager_unregister_local( manager, data->self ); +} + +static DirectResult +Dispatch_SetCooperativeLevel( IDirectFB *thiz, IDirectFB *real, + VoodooManager *manager, VoodooRequestMessage *msg ) +{ + DirectResult ret; + DFBCooperativeLevel level; + VoodooMessageParser parser; + + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + VOODOO_PARSER_BEGIN( parser, msg ); + VOODOO_PARSER_GET_INT( parser, level ); + VOODOO_PARSER_END( parser ); + + ret = real->SetCooperativeLevel( real, level ); + + return voodoo_manager_respond( manager, true, msg->header.serial, + ret, VOODOO_INSTANCE_NONE, + VMBT_NONE ); +} + +static DirectResult +Dispatch_GetDeviceDescription( IDirectFB *thiz, IDirectFB *real, + VoodooManager *manager, VoodooRequestMessage *msg ) +{ + DirectResult ret; + DFBGraphicsDeviceDescription desc; + + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + ret = real->GetDeviceDescription( real, &desc ); + if (ret) + return ret; + + return voodoo_manager_respond( manager, true, msg->header.serial, + DFB_OK, VOODOO_INSTANCE_NONE, + VMBT_DATA, sizeof(DFBGraphicsDeviceDescription), &desc, + VMBT_NONE ); +} + +static DirectResult +Dispatch_SetVideoMode( IDirectFB *thiz, IDirectFB *real, + VoodooManager *manager, VoodooRequestMessage *msg ) +{ + DirectResult ret; + VoodooMessageParser parser; + int width; + int height; + int bpp; + + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + VOODOO_PARSER_BEGIN( parser, msg ); + VOODOO_PARSER_GET_INT( parser, width ); + VOODOO_PARSER_GET_INT( parser, height ); + VOODOO_PARSER_GET_INT( parser, bpp ); + VOODOO_PARSER_END( parser ); + + ret = real->SetVideoMode( real, width, height, bpp ); + + return voodoo_manager_respond( manager, true, msg->header.serial, + ret, VOODOO_INSTANCE_NONE, + VMBT_NONE ); +} + +#define MAX_MODES 128 + +typedef struct { + int num; + IDirectFB_Dispatcher_EnumVideoModes_Item items[MAX_MODES]; +} EnumVideoModes_Context; + +static DFBEnumerationResult +EnumVideoModes_Callback( int width, + int height, + int bpp, + void *callbackdata ) +{ + int index; + EnumVideoModes_Context *context = callbackdata; + + if (context->num == MAX_MODES) { + D_WARN( "maximum number of %d modes reached", MAX_MODES ); + return DFENUM_CANCEL; + } + + index = context->num++; + + context->items[index].width = width; + context->items[index].height = height; + context->items[index].bpp = bpp; + + return DFENUM_OK; +} + +static DirectResult +Dispatch_EnumVideoModes( IDirectFB *thiz, IDirectFB *real, + VoodooManager *manager, VoodooRequestMessage *msg ) +{ + DirectResult ret; + EnumVideoModes_Context context = { 0 }; + + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + ret = real->EnumVideoModes( real, EnumVideoModes_Callback, &context ); + if (ret) + return ret; + + return voodoo_manager_respond( manager, true, msg->header.serial, + DFB_OK, VOODOO_INSTANCE_NONE, + VMBT_INT, context.num, + VMBT_DATA, context.num * sizeof(IDirectFB_Dispatcher_EnumVideoModes_Item), context.items, + VMBT_NONE ); +} + +static DirectResult +Dispatch_CreateEventBuffer( IDirectFB *thiz, IDirectFB *real, + VoodooManager *manager, VoodooRequestMessage *msg ) +{ + DirectResult ret; + IDirectFBEventBuffer *buffer; + VoodooInstanceID instance; + VoodooMessageParser parser; + void *requestor; + + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + VOODOO_PARSER_BEGIN( parser, msg ); + VOODOO_PARSER_GET_ID( parser, instance ); + VOODOO_PARSER_END( parser ); + + ret = real->CreateEventBuffer( real, &buffer ); + if (ret) + return ret; + + ret = voodoo_construct_requestor( manager, "IDirectFBEventBuffer", + instance, buffer, &requestor ); + + buffer->Release( buffer ); + + return ret; +} + +static DirectResult +Dispatch_CreateInputEventBuffer( IDirectFB *thiz, IDirectFB *real, + VoodooManager *manager, VoodooRequestMessage *msg ) +{ + DirectResult ret; + IDirectFBEventBuffer *buffer; + VoodooInstanceID instance; + DFBInputDeviceCapabilities caps; + DFBBoolean global; + VoodooMessageParser parser; + void *requestor; + + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + VOODOO_PARSER_BEGIN( parser, msg ); + VOODOO_PARSER_GET_ID( parser, instance ); + VOODOO_PARSER_GET_INT( parser, caps ); + VOODOO_PARSER_GET_INT( parser, global ); + VOODOO_PARSER_END( parser ); + + ret = real->CreateInputEventBuffer( real, caps, global, &buffer ); + if (ret) + return ret; + + ret = voodoo_construct_requestor( manager, "IDirectFBEventBuffer", + instance, buffer, &requestor ); + + buffer->Release( buffer ); + + return ret; +} + +static DirectResult +Dispatch_CreateImageProvider( IDirectFB *thiz, IDirectFB *real, + VoodooManager *manager, VoodooRequestMessage *msg ) +{ + DirectResult ret; + DirectLink *l; + VoodooMessageParser parser; + VoodooInstanceID instance; + IDirectFBImageProvider *provider; + IDirectFBDataBuffer *buffer = NULL; + + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + VOODOO_PARSER_BEGIN( parser, msg ); + VOODOO_PARSER_GET_ID( parser, instance ); + VOODOO_PARSER_END( parser ); + + if (1) { + ret = voodoo_manager_check_allocation( manager, 0x100000 /*FIXME*/ ); + if (ret) { + D_ERROR( "Allocation not permitted!\n" ); + return ret; + } + } + + direct_list_foreach (l, data->data_buffers) { + DataBufferEntry *entry = (DataBufferEntry*) l; + + if (entry->instance == instance) { + buffer = entry->requestor; + break; + } + } + + ret = buffer->CreateImageProvider( buffer, &provider ); + if (ret) + return ret; + + ret = voodoo_construct_dispatcher( manager, "IDirectFBImageProvider", + provider, data->self, NULL, &instance, NULL ); + if (ret) { + provider->Release( provider ); + return ret; + } + + return voodoo_manager_respond( manager, true, msg->header.serial, + DFB_OK, instance, + VMBT_NONE ); +} + +static DirectResult +Dispatch_CreateSurface( IDirectFB *thiz, IDirectFB *real, + VoodooManager *manager, VoodooRequestMessage *msg ) +{ + DirectResult ret; + DFBSurfaceDescription desc; + IDirectFBSurface *surface; + VoodooInstanceID instance; + VoodooMessageParser parser; + bool force_system = (voodoo_config->resource_id != 0); + + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + VOODOO_PARSER_BEGIN( parser, msg ); + VOODOO_PARSER_READ_DFBSurfaceDescription( parser, desc ); + VOODOO_PARSER_END( parser ); + + if (1) { + unsigned int w = 256, h = 256, b = 2, size; + + if (desc.flags & DSDESC_WIDTH) + w = desc.width; + + if (desc.flags & DSDESC_HEIGHT) + h = desc.height; + + if (desc.flags & DSDESC_PIXELFORMAT) + b = DFB_BYTES_PER_PIXEL( desc.pixelformat ) ? DFB_BYTES_PER_PIXEL( desc.pixelformat ) : 2; + + size = w * h * b; + + D_INFO( "Checking creation of %u kB surface\n", size / 1024 ); + + if (voodoo_config->surface_max && voodoo_config->surface_max < size) { + D_ERROR( "Allocation of %u kB surface not permitted (limit %u kB)\n", + size / 1024, voodoo_config->surface_max / 1024 ); + return DR_LIMITEXCEEDED; + } + + ret = voodoo_manager_check_allocation( manager, size ); + if (ret) { + D_ERROR( "Allocation not permitted!\n" ); + return ret; + } + } + + if (voodoo_config->resource_id) { + if (desc.flags & DSDESC_RESOURCE_ID) { + if (desc.resource_id == voodoo_config->resource_id) { + force_system = false; + } + } + } + + if (force_system) { + DFBSurfaceDescription sd = desc; + + if (sd.flags & DSDESC_CAPS) { + sd.caps &= ~DSCAPS_VIDEOONLY; + sd.caps |= DSCAPS_SYSTEMONLY; + } + else { + sd.flags |= DSDESC_CAPS; + sd.caps = DSCAPS_SYSTEMONLY; + } + + ret = real->CreateSurface( real, &sd, &surface ); + } + else if (desc.flags & (DSDESC_PALETTE | DSDESC_PREALLOCATED)) { + DFBSurfaceDescription sd = desc; + sd.flags &= ~(DSDESC_PALETTE | DSDESC_PREALLOCATED); + + ret = real->CreateSurface( real, &sd, &surface ); + } + else { + ret = real->CreateSurface( real, &desc, &surface ); + } + if (ret) + return ret; + + ret = voodoo_construct_dispatcher( manager, "IDirectFBSurface", + surface, data->self, NULL, &instance, NULL ); + if (ret) { + surface->Release( surface ); + return ret; + } + + return voodoo_manager_respond( manager, true, msg->header.serial, + DFB_OK, instance, + VMBT_NONE ); +} + +typedef struct { + int num; + IDirectFB_Dispatcher_EnumScreens_Item items[MAX_SCREENS]; +} EnumScreens_Context; + +static DFBEnumerationResult +EnumScreens_Callback( DFBScreenID screen_id, + DFBScreenDescription desc, + void *callbackdata ) +{ + int index; + EnumScreens_Context *context = callbackdata; + + if (context->num == MAX_SCREENS) { + D_WARN( "maximum number of %d screens reached", MAX_SCREENS ); + return DFENUM_CANCEL; + } + + index = context->num++; + + context->items[index].screen_id = screen_id; + context->items[index].desc = desc; + + return DFENUM_OK; +} + +static DirectResult +Dispatch_EnumScreens( IDirectFB *thiz, IDirectFB *real, + VoodooManager *manager, VoodooRequestMessage *msg ) +{ + DirectResult ret; + EnumScreens_Context context = { 0 }; + + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + ret = real->EnumScreens( real, EnumScreens_Callback, &context ); + if (ret) + return ret; + + return voodoo_manager_respond( manager, true, msg->header.serial, + DFB_OK, VOODOO_INSTANCE_NONE, + VMBT_INT, context.num, + VMBT_DATA, context.num * sizeof(IDirectFB_Dispatcher_EnumScreens_Item), context.items, + VMBT_NONE ); +} + +static DirectResult +Dispatch_GetDisplayLayer( IDirectFB *thiz, IDirectFB *real, + VoodooManager *manager, VoodooRequestMessage *msg ) +{ + DirectResult ret; + DFBDisplayLayerID id; + IDirectFBDisplayLayer *layer; + VoodooInstanceID instance; + VoodooMessageParser parser; + + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + VOODOO_PARSER_BEGIN( parser, msg ); + VOODOO_PARSER_GET_ID( parser, id ); + VOODOO_PARSER_END( parser ); + + if (voodoo_config->layer_mask && !(voodoo_config->layer_mask & (1 << id))) { + D_ERROR( "Layer with id %u not allowed!\n", id ); + return DR_ACCESSDENIED; + } + + ret = real->GetDisplayLayer( real, id, &layer ); + if (ret) + return ret; + + ret = voodoo_construct_dispatcher( manager, "IDirectFBDisplayLayer", + layer, data->self, NULL, &instance, NULL ); + if (ret) { + layer->Release( layer ); + return ret; + } + + return voodoo_manager_respond( manager, true, msg->header.serial, + DFB_OK, instance, + VMBT_NONE ); +} + +#define MAX_INPUT_DEVICES 64 + +typedef struct { + int num; + IDirectFB_Dispatcher_EnumInputDevices_Item items[MAX_INPUT_DEVICES]; +} EnumInputDevices_Context; + +static DFBEnumerationResult +EnumInputDevices_Callback( DFBInputDeviceID device_id, + DFBInputDeviceDescription desc, + void *callbackdata ) +{ + int index; + EnumInputDevices_Context *context = callbackdata; + + if (context->num == MAX_INPUT_DEVICES) { + D_WARN( "maximum number of %d input devices reached", MAX_INPUT_DEVICES ); + return DFENUM_CANCEL; + } + + index = context->num++; + + context->items[index].device_id = device_id; + context->items[index].desc = desc; + + return DFENUM_OK; +} + +static DirectResult +Dispatch_EnumInputDevices( IDirectFB *thiz, IDirectFB *real, + VoodooManager *manager, VoodooRequestMessage *msg ) +{ + DirectResult ret; + EnumInputDevices_Context context = { 0 }; + + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + ret = real->EnumInputDevices( real, EnumInputDevices_Callback, &context ); + if (ret) + return ret; + + return voodoo_manager_respond( manager, true, msg->header.serial, + DFB_OK, VOODOO_INSTANCE_NONE, + VMBT_INT, context.num, + VMBT_DATA, context.num * sizeof(IDirectFB_Dispatcher_EnumInputDevices_Item), context.items, + VMBT_NONE ); +} + +static DirectResult +Dispatch_GetInputDevice( IDirectFB *thiz, IDirectFB *real, + VoodooManager *manager, VoodooRequestMessage *msg ) +{ + DirectResult ret; + DFBScreenID device_id; + IDirectFBInputDevice *device; + VoodooInstanceID instance; + VoodooMessageParser parser; + + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + VOODOO_PARSER_BEGIN( parser, msg ); + VOODOO_PARSER_GET_ID( parser, device_id ); + VOODOO_PARSER_END( parser ); + + ret = real->GetInputDevice( real, device_id, &device ); + if (ret) + return ret; + + ret = voodoo_construct_dispatcher( manager, "IDirectFBInputDevice", + device, data->self, NULL, &instance, NULL ); + if (ret) { + device->Release( device ); + return ret; + } + + return voodoo_manager_respond( manager, true, msg->header.serial, + DFB_OK, instance, + VMBT_NONE ); +} + +static DirectResult +Dispatch_GetScreen( IDirectFB *thiz, IDirectFB *real, + VoodooManager *manager, VoodooRequestMessage *msg ) +{ + DirectResult ret; + DFBScreenID screen_id; + IDirectFBScreen *screen; + VoodooInstanceID instance; + VoodooMessageParser parser; + + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + VOODOO_PARSER_BEGIN( parser, msg ); + VOODOO_PARSER_GET_ID( parser, screen_id ); + VOODOO_PARSER_END( parser ); + + ret = real->GetScreen( real, screen_id, &screen ); + if (ret) + return ret; + + ret = voodoo_construct_dispatcher( manager, "IDirectFBScreen", + screen, data->self, NULL, &instance, NULL ); + if (ret) { + screen->Release( screen ); + return ret; + } + + return voodoo_manager_respond( manager, true, msg->header.serial, + DFB_OK, instance, + VMBT_NONE ); +} + +static DirectResult +Dispatch_CreateFont( IDirectFB *thiz, IDirectFB *real, + VoodooManager *manager, VoodooRequestMessage *msg ) +{ + DirectResult ret; + DirectLink *l; + VoodooMessageParser parser; + VoodooInstanceID instance; + IDirectFBFont *font; + IDirectFBDataBuffer *buffer = NULL; + const DFBFontDescription *desc; + + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + VOODOO_PARSER_BEGIN( parser, msg ); + VOODOO_PARSER_GET_ID( parser, instance ); + VOODOO_PARSER_GET_DATA( parser, desc ); + VOODOO_PARSER_END( parser ); + + direct_list_foreach (l, data->data_buffers) { + DataBufferEntry *entry = (DataBufferEntry*) l; + + if (entry->instance == instance) { + buffer = entry->requestor; + break; + } + } + + if (1) { + unsigned int size; + + buffer->GetLength( buffer, &size ); + + ret = voodoo_manager_check_allocation( manager, size ); + if (ret) { + D_ERROR( "Allocation not permitted!\n" ); + return ret; + } + } + + ret = buffer->CreateFont( buffer, desc, &font ); + if (ret) + return ret; + + ret = voodoo_construct_dispatcher( manager, "IDirectFBFont", + font, data->self, NULL, &instance, NULL ); + if (ret) { + font->Release( font ); + return ret; + } + + return voodoo_manager_respond( manager, true, msg->header.serial, + DFB_OK, instance, + VMBT_NONE ); +} + +static DirectResult +Dispatch_CreateDataBuffer( IDirectFB *thiz, IDirectFB *real, + VoodooManager *manager, VoodooRequestMessage *msg ) +{ + DirectResult ret; + IDirectFBDataBuffer *requestor; + VoodooMessageParser parser; + VoodooInstanceID instance; + DataBufferEntry *entry; + void *ptr; + + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + VOODOO_PARSER_BEGIN( parser, msg ); + VOODOO_PARSER_GET_ID( parser, instance ); + VOODOO_PARSER_END( parser ); + + ret = voodoo_construct_requestor( manager, "IDirectFBDataBuffer", + instance, data->real, &ptr ); + if (ret) + return ret; + + requestor = ptr; + + entry = D_CALLOC( 1, sizeof(DataBufferEntry) ); + if (!entry) { + D_WARN( "out of memory" ); + requestor->Release( requestor ); + return DFB_NOSYSTEMMEMORY; + } + + entry->instance = instance; + entry->requestor = requestor; + + entry->requestor->AddRef( entry->requestor ); + + direct_list_prepend( &data->data_buffers, &entry->link ); + + return DFB_OK; +} + +static DirectResult +Dispatch_WaitIdle( IDirectFB *thiz, IDirectFB *real, + VoodooManager *manager, VoodooRequestMessage *msg ) +{ + DirectResult ret; + + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + ret = real->WaitIdle( real ); + + return voodoo_manager_respond( manager, true, msg->header.serial, + ret, VOODOO_INSTANCE_NONE, + VMBT_NONE ); +} + +static DirectResult +Dispatch_GetInterface( IDirectFB *thiz, IDirectFB *real, + VoodooManager *manager, VoodooRequestMessage *msg ) +{ + DirectResult ret; + VoodooMessageParser parser; + const char *type; + IAny *interface_ptr; + VoodooInstanceID instance; + + DIRECT_INTERFACE_GET_DATA(IDirectFB_Dispatcher) + + VOODOO_PARSER_BEGIN( parser, msg ); + VOODOO_PARSER_GET_STRING( parser, type ); + VOODOO_PARSER_END( parser ); + + ret = real->GetInterface( real, type, NULL, NULL, (void**) &interface_ptr ); + if (ret) + return ret; + + ret = voodoo_construct_dispatcher( manager, type, interface_ptr, data->self, NULL, &instance, NULL ); + if (ret) { + interface_ptr->Release( interface_ptr ); + return ret; + } + + return voodoo_manager_respond( manager, true, msg->header.serial, + ret, instance, + VMBT_NONE ); +} + +static DirectResult +Dispatch( void *dispatcher, void *real, VoodooManager *manager, VoodooRequestMessage *msg ) +{ + D_DEBUG( "IDirectFB/Dispatcher: " + "Handling request for instance %u with method %u...\n", msg->instance, msg->method ); + + switch (msg->method) { + case IDIRECTFB_METHOD_ID_Release: + return Dispatch_Release( dispatcher, real, manager, msg ); + + case IDIRECTFB_METHOD_ID_SetCooperativeLevel: + return Dispatch_SetCooperativeLevel( dispatcher, real, manager, msg ); + + case IDIRECTFB_METHOD_ID_GetDeviceDescription: + return Dispatch_GetDeviceDescription( dispatcher, real, manager, msg ); + + case IDIRECTFB_METHOD_ID_SetVideoMode: + return Dispatch_SetVideoMode( dispatcher, real, manager, msg ); + + case IDIRECTFB_METHOD_ID_EnumVideoModes: + return Dispatch_EnumVideoModes( dispatcher, real, manager, msg ); + + case IDIRECTFB_METHOD_ID_CreateSurface: + return Dispatch_CreateSurface( dispatcher, real, manager, msg ); + + case IDIRECTFB_METHOD_ID_EnumScreens: + return Dispatch_EnumScreens( dispatcher, real, manager, msg ); + + case IDIRECTFB_METHOD_ID_GetScreen: + return Dispatch_GetScreen( dispatcher, real, manager, msg ); + + case IDIRECTFB_METHOD_ID_GetDisplayLayer: + return Dispatch_GetDisplayLayer( dispatcher, real, manager, msg ); + + case IDIRECTFB_METHOD_ID_EnumInputDevices: + return Dispatch_EnumInputDevices( dispatcher, real, manager, msg ); + + case IDIRECTFB_METHOD_ID_GetInputDevice: + return Dispatch_GetInputDevice( dispatcher, real, manager, msg ); + + case IDIRECTFB_METHOD_ID_CreateEventBuffer: + return Dispatch_CreateEventBuffer( dispatcher, real, manager, msg ); + + case IDIRECTFB_METHOD_ID_CreateInputEventBuffer: + return Dispatch_CreateInputEventBuffer( dispatcher, real, manager, msg ); + + case IDIRECTFB_METHOD_ID_CreateImageProvider: + return Dispatch_CreateImageProvider( dispatcher, real, manager, msg ); + + case IDIRECTFB_METHOD_ID_CreateFont: + return Dispatch_CreateFont( dispatcher, real, manager, msg ); + + case IDIRECTFB_METHOD_ID_CreateDataBuffer: + return Dispatch_CreateDataBuffer( dispatcher, real, manager, msg ); + + case IDIRECTFB_METHOD_ID_WaitIdle: + return Dispatch_WaitIdle( dispatcher, real, manager, msg ); + + case IDIRECTFB_METHOD_ID_GetInterface: + return Dispatch_GetInterface( dispatcher, real, manager, msg ); + } + + return DFB_NOSUCHMETHOD; +} + +/**************************************************************************************************/ + +static DFBResult +Probe() +{ + /* This implementation has to be loaded explicitly. */ + return DFB_UNSUPPORTED; +} + +/* + * Constructor + * + * Fills in function pointers and intializes data structure. + */ +static DFBResult +Construct( IDirectFB *thiz, VoodooManager *manager, VoodooInstanceID *ret_instance ) +{ + DFBResult ret; + IDirectFB *real; + VoodooInstanceID instance; + + DIRECT_ALLOCATE_INTERFACE_DATA(thiz, IDirectFB_Dispatcher) + + ret = DirectFBCreate( &real ); + if (ret) { + DIRECT_DEALLOCATE_INTERFACE( thiz ); + return ret; + } + + ret = voodoo_manager_register_local( manager, VOODOO_INSTANCE_NONE, thiz, real, Dispatch, &instance ); + if (ret) { + real->Release( real ); + DIRECT_DEALLOCATE_INTERFACE( thiz ); + return ret; + } + + *ret_instance = instance; + + data->ref = 1; + data->real = real; + data->core = ((IDirectFB_data*)(real->priv))->core; + data->self = instance; + + thiz->AddRef = IDirectFB_Dispatcher_AddRef; + thiz->Release = IDirectFB_Dispatcher_Release; + thiz->SetCooperativeLevel = IDirectFB_Dispatcher_SetCooperativeLevel; + thiz->GetDeviceDescription = IDirectFB_Dispatcher_GetDeviceDescription; + thiz->EnumVideoModes = IDirectFB_Dispatcher_EnumVideoModes; + thiz->SetVideoMode = IDirectFB_Dispatcher_SetVideoMode; + thiz->CreateSurface = IDirectFB_Dispatcher_CreateSurface; + thiz->CreatePalette = IDirectFB_Dispatcher_CreatePalette; + thiz->EnumScreens = IDirectFB_Dispatcher_EnumScreens; + thiz->GetScreen = IDirectFB_Dispatcher_GetScreen; + thiz->EnumDisplayLayers = IDirectFB_Dispatcher_EnumDisplayLayers; + thiz->GetDisplayLayer = IDirectFB_Dispatcher_GetDisplayLayer; + thiz->EnumInputDevices = IDirectFB_Dispatcher_EnumInputDevices; + thiz->GetInputDevice = IDirectFB_Dispatcher_GetInputDevice; + thiz->CreateEventBuffer = IDirectFB_Dispatcher_CreateEventBuffer; + thiz->CreateInputEventBuffer = IDirectFB_Dispatcher_CreateInputEventBuffer; + thiz->CreateImageProvider = IDirectFB_Dispatcher_CreateImageProvider; + thiz->CreateVideoProvider = IDirectFB_Dispatcher_CreateVideoProvider; + thiz->CreateFont = IDirectFB_Dispatcher_CreateFont; + thiz->CreateDataBuffer = IDirectFB_Dispatcher_CreateDataBuffer; + thiz->SetClipboardData = IDirectFB_Dispatcher_SetClipboardData; + thiz->GetClipboardData = IDirectFB_Dispatcher_GetClipboardData; + thiz->GetClipboardTimeStamp = IDirectFB_Dispatcher_GetClipboardTimeStamp; + thiz->Suspend = IDirectFB_Dispatcher_Suspend; + thiz->Resume = IDirectFB_Dispatcher_Resume; + thiz->WaitIdle = IDirectFB_Dispatcher_WaitIdle; + thiz->WaitForSync = IDirectFB_Dispatcher_WaitForSync; + thiz->GetInterface = IDirectFB_Dispatcher_GetInterface; + + return DFB_OK; +} + |