summaryrefslogtreecommitdiff
path: root/Source/DirectFB/lib/voodoo/manager_c.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/DirectFB/lib/voodoo/manager_c.cpp')
-rwxr-xr-xSource/DirectFB/lib/voodoo/manager_c.cpp553
1 files changed, 553 insertions, 0 deletions
diff --git a/Source/DirectFB/lib/voodoo/manager_c.cpp b/Source/DirectFB/lib/voodoo/manager_c.cpp
new file mode 100755
index 0000000..7019da8
--- /dev/null
+++ b/Source/DirectFB/lib/voodoo/manager_c.cpp
@@ -0,0 +1,553 @@
+/*
+ (c) Copyright 2001-2011 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.
+*/
+
+//#define DIRECT_ENABLE_DEBUG
+
+#include <config.h>
+
+#include <list>
+
+#include <stdarg.h>
+
+extern "C" {
+#include <direct/debug.h>
+#include <direct/messages.h>
+#include <direct/util.h>
+
+#include <voodoo/conf.h>
+#include <voodoo/server.h>
+}
+
+#include <voodoo/manager.h>
+
+
+D_DEBUG_DOMAIN( Voodoo_Manager, "Voodoo/Manager", "Voodoo Manager" );
+
+/**********************************************************************************************************************/
+
+
+#define VOODOO_MANAGER_MESSAGE_BLOCKS_MAX 20
+
+static __inline__ int
+calc_blocks( va_list args,
+ VoodooMessageBlock *ret_blocks, size_t *ret_num )
+{
+ int size = 4; /* for the terminating VMBT_NONE */
+ size_t num = 0;
+ VoodooMessageBlockType type;
+
+ /* Fetch first block type. */
+ type = (VoodooMessageBlockType) va_arg( args, int );
+
+ while (type != VMBT_NONE) {
+ if (num == VOODOO_MANAGER_MESSAGE_BLOCKS_MAX) {
+ // FIXME: support more blocks?
+ D_UNIMPLEMENTED();
+ break;
+ }
+
+ /* Set message block type. */
+ ret_blocks[num].type = type;
+
+ switch (type) {
+ case VMBT_ID:
+ ret_blocks[num].len = 4;
+ ret_blocks[num].ptr = NULL;
+ ret_blocks[num].val = va_arg( args, u32 );
+
+ D_DEBUG( "Voodoo/Message: + ID %u\n", ret_blocks[num].val );
+ break;
+
+ case VMBT_INT:
+ ret_blocks[num].len = 4;
+ ret_blocks[num].ptr = NULL;
+ ret_blocks[num].val = va_arg( args, s32 );
+
+ D_DEBUG( "Voodoo/Message: + INT %d\n", ret_blocks[num].val );
+ break;
+
+ case VMBT_UINT:
+ ret_blocks[num].len = 4;
+ ret_blocks[num].ptr = NULL;
+ ret_blocks[num].val = va_arg( args, u32 );
+
+ D_DEBUG( "Voodoo/Message: + UINT %u\n", ret_blocks[num].val );
+ break;
+
+ case VMBT_DATA:
+ ret_blocks[num].len = va_arg( args, int );
+ ret_blocks[num].ptr = va_arg( args, void * );
+
+// D_ASSERT( ret_blocks[num].len > 0 );
+ D_ASSERT( ret_blocks[num].ptr != NULL );
+
+ D_DEBUG( "Voodoo/Message: + DATA at %p with length %d\n", ret_blocks[num].ptr, ret_blocks[num].len );
+ break;
+
+ case VMBT_ODATA:
+ ret_blocks[num].len = va_arg( args, int );
+ ret_blocks[num].ptr = va_arg( args, void * );
+
+ D_ASSERT( ret_blocks[num].len > 0 );
+
+ D_DEBUG( "Voodoo/Message: + ODATA at %p with length %d\n", ret_blocks[num].ptr, ret_blocks[num].len );
+
+ if (!ret_blocks[num].ptr)
+ ret_blocks[num].len = 0;
+ break;
+
+ case VMBT_STRING:
+ ret_blocks[num].ptr = va_arg( args, char * );
+ ret_blocks[num].len = strlen( (const char*) ret_blocks[num].ptr ) + 1;
+
+ D_ASSERT( ret_blocks[num].ptr != NULL );
+
+ D_DEBUG( "Voodoo/Message: + STRING '%s' at %p with length %d\n", (char*) ret_blocks[num].ptr, ret_blocks[num].ptr, ret_blocks[num].len );
+ break;
+
+ default:
+ D_BREAK( "unknown message block type" );
+ }
+
+ /* Fetch next block type. */
+ type = (VoodooMessageBlockType) va_arg( args, int );
+
+ size += 8 + VOODOO_MSG_ALIGN(ret_blocks[num].len);
+
+ num++;
+ }
+
+ *ret_num = num;
+
+ return size;
+}
+
+
+/**********************************************************************************************************************/
+/**********************************************************************************************************************/
+/**********************************************************************************************************************/
+/* Old C API
+ */
+
+/*
+
+
+register add refs proxy
+unregister releases proxy
+
+proxy destruct releases real
+
+*/
+
+class VoodooInstanceInterface : public VoodooInstance {
+public:
+ VoodooManager *manager;
+ VoodooInstance *super;
+ IAny *proxy;
+ IAny *real;
+ VoodooDispatch dispatch;
+
+
+ static std::list<VoodooInstanceInterface*> interfaces;
+
+
+public:
+ VoodooInstanceInterface( VoodooManager *manager,
+ VoodooInstance *super,
+ IAny *proxy,
+ IAny *real,
+ VoodooDispatch dispatch )
+ :
+ manager( manager ),
+ super( super ),
+ proxy( proxy ),
+ real( real ),
+ dispatch( dispatch )
+ {
+ D_DEBUG_AT( Voodoo_Manager, "VoodooInstanceInterface::%s( %p, manager %p, super %p, proxy %p, real %p, dispatch %p )\n",
+ __func__, this, manager, super, proxy, real, dispatch );
+
+ if (super)
+ super->AddRef();
+
+ interfaces.push_back( this );
+ }
+
+protected:
+ virtual ~VoodooInstanceInterface()
+ {
+ D_DEBUG_AT( Voodoo_Manager, "VoodooInstanceInterface::%s( %p )\n", __func__, this );
+
+ D_MAGIC_ASSERT( this, VoodooInstance );
+
+ if (proxy) {
+ D_DEBUG_AT( Voodoo_Manager, " -> releasing proxy interface\n" );
+
+ proxy->Release( proxy );
+ }
+
+
+ if (super) {
+ D_DEBUG_AT( Voodoo_Manager, " -> releasing super instance\n" );
+
+ super->Release();
+ }
+
+ interfaces.remove( this );
+ }
+
+public:
+ virtual DirectResult
+ Dispatch( VoodooManager *manager,
+ VoodooRequestMessage *msg )
+ {
+ D_DEBUG_AT( Voodoo_Manager, "VoodooInstanceInterface::%s( %p, manager %p, msg %p )\n", __func__, this, manager, msg );
+
+ D_MAGIC_ASSERT( this, VoodooInstance );
+
+ D_ASSERT( dispatch != NULL );
+
+ return dispatch( proxy, real, manager, msg );
+ }
+};
+
+std::list<VoodooInstanceInterface*> VoodooInstanceInterface::interfaces;
+
+/**********************************************************************************************************************/
+
+class VoodooContextClassic : public VoodooContext {
+private:
+ VoodooServer *server;
+
+public:
+ VoodooContextClassic( VoodooServer *server )
+ :
+ server( server )
+ {
+ }
+
+ virtual DirectResult
+ HandleSuper( VoodooManager *manager, const char *name, VoodooInstanceID *ret_instance )
+ {
+ return voodoo_server_construct( server, manager, name, ret_instance );
+ }
+};
+
+DirectResult
+voodoo_manager_create( VoodooLink *link,
+ VoodooClient *client,
+ VoodooServer *server,
+ VoodooManager **ret_manager )
+{
+ D_ASSERT( ret_manager != NULL );
+
+ *ret_manager = new VoodooManager( link, new VoodooContextClassic( server ) ); // FIXME: leak
+
+ return DR_OK;
+}
+
+DirectResult
+voodoo_manager_quit( VoodooManager *manager )
+{
+ D_MAGIC_ASSERT( manager, VoodooManager );
+
+ manager->quit();
+
+ return DR_OK;
+}
+
+DirectResult
+voodoo_manager_destroy( VoodooManager *manager )
+{
+ D_MAGIC_ASSERT( manager, VoodooManager );
+
+ delete manager;
+
+ for (std::list<VoodooInstanceInterface*>::const_iterator iter = VoodooInstanceInterface::interfaces.begin();
+ iter != VoodooInstanceInterface::interfaces.end(); iter++)
+ {
+ VoodooInstanceInterface *instance = *iter;
+
+ if (instance->manager == manager)
+ D_INFO( "Zombie: Instance %p, proxy %p, real %p, super %p\n", instance, instance->proxy, instance->real, instance->super );
+ }
+
+ return DR_OK;
+}
+
+bool
+voodoo_manager_is_closed( const VoodooManager *manager )
+{
+ D_MAGIC_ASSERT( manager, VoodooManager );
+
+ return manager->is_quit;
+}
+
+/**************************************************************************************************/
+
+DirectResult
+voodoo_manager_super( VoodooManager *manager,
+ const char *name,
+ VoodooInstanceID *ret_instance )
+{
+ D_MAGIC_ASSERT( manager, VoodooManager );
+
+ return manager->do_super( name, ret_instance );
+}
+
+DirectResult
+voodoo_manager_request( VoodooManager *manager,
+ VoodooInstanceID instance,
+ VoodooMethodID method,
+ VoodooRequestFlags flags,
+ VoodooResponseMessage **ret_response, ... )
+{
+ DirectResult ret;
+
+ D_MAGIC_ASSERT( manager, VoodooManager );
+
+ va_list ap;
+
+ va_start( ap, ret_response );
+
+
+ VoodooMessageBlock blocks[VOODOO_MANAGER_MESSAGE_BLOCKS_MAX];
+ size_t num_blocks;
+ size_t data_size;
+
+ data_size = calc_blocks( ap, blocks, &num_blocks );
+
+
+ ret = manager->do_request( instance, method, flags, ret_response, blocks, num_blocks, data_size );
+
+ va_end( ap );
+
+ return ret;
+}
+
+DirectResult
+voodoo_manager_next_response( VoodooManager *manager,
+ VoodooResponseMessage *response,
+ VoodooResponseMessage **ret_response )
+{
+ D_MAGIC_ASSERT( manager, VoodooManager );
+
+ return manager->next_response( response, ret_response );
+}
+
+DirectResult
+voodoo_manager_finish_request( VoodooManager *manager,
+ VoodooResponseMessage *response )
+{
+ D_MAGIC_ASSERT( manager, VoodooManager );
+
+ return manager->finish_request( response );
+}
+
+DirectResult
+voodoo_manager_respond( VoodooManager *manager,
+ bool flush,
+ VoodooMessageSerial request,
+ DirectResult result,
+ VoodooInstanceID instance, ... )
+{
+ DirectResult ret;
+
+ D_MAGIC_ASSERT( manager, VoodooManager );
+
+ va_list ap;
+
+ va_start( ap, instance );
+
+
+ VoodooMessageBlock blocks[VOODOO_MANAGER_MESSAGE_BLOCKS_MAX];
+ size_t num_blocks;
+ size_t data_size;
+
+ data_size = calc_blocks( ap, blocks, &num_blocks );
+
+
+ ret = manager->do_respond( flush, request, result, instance, blocks, num_blocks, data_size );
+
+ va_end( ap );
+
+ return ret;
+}
+
+DirectResult
+voodoo_manager_register_local( VoodooManager *manager,
+ VoodooInstanceID super,
+ void *dispatcher,
+ void *real,
+ VoodooDispatch dispatch,
+ VoodooInstanceID *ret_instance )
+{
+ DirectResult ret;
+ VoodooInstance *super_instance = NULL;
+
+ D_MAGIC_ASSERT( manager, VoodooManager );
+
+ if (super != VOODOO_INSTANCE_NONE) {
+ ret = manager->lookup_local( super, &super_instance );
+ if (ret) {
+ D_DERROR( ret, "Voodoo/Manager: Could not lookup super instance %u!\n", super );
+ return ret;
+ }
+ }
+
+
+ VoodooInstanceInterface *instance = new VoodooInstanceInterface( manager, super_instance, (IAny*) dispatcher, (IAny*) real, dispatch );
+
+ ret = manager->register_local( instance, ret_instance );
+
+ instance->Release();
+
+ return ret;
+}
+
+DirectResult
+voodoo_manager_unregister_local( VoodooManager *manager,
+ VoodooInstanceID instance_id )
+{
+ D_MAGIC_ASSERT( manager, VoodooManager );
+
+ return manager->unregister_local( instance_id );
+}
+
+DirectResult
+voodoo_manager_lookup_local( VoodooManager *manager,
+ VoodooInstanceID instance_id,
+ void **ret_dispatcher,
+ void **ret_real )
+{
+ DirectResult ret;
+ VoodooInstance *instance;
+
+ D_MAGIC_ASSERT( manager, VoodooManager );
+
+ ret = manager->lookup_local( instance_id, &instance );
+ if (ret)
+ return ret;
+
+ if (ret_dispatcher)
+ *ret_dispatcher = ((VoodooInstanceInterface*) instance)->proxy;
+
+ if (ret_real)
+ *ret_real = ((VoodooInstanceInterface*) instance)->real;
+
+ return DR_OK;
+}
+
+DirectResult
+voodoo_manager_register_remote( VoodooManager *manager,
+ bool super,
+ void *requestor,
+ VoodooInstanceID instance_id )
+{
+ DirectResult ret;
+
+ D_MAGIC_ASSERT( manager, VoodooManager );
+
+ VoodooInstanceInterface *instance = new VoodooInstanceInterface( manager, NULL, (IAny*) requestor, NULL, NULL);
+
+ ret = manager->register_remote( instance, instance_id );
+
+ instance->Release();
+
+ return ret;
+}
+
+
+DirectResult
+voodoo_manager_lookup_remote( VoodooManager *manager,
+ VoodooInstanceID instance_id,
+ void **ret_requestor )
+{
+ DirectResult ret;
+ VoodooInstance *instance;
+
+ D_MAGIC_ASSERT( manager, VoodooManager );
+
+ ret = manager->lookup_remote( instance_id, &instance );
+ if (ret)
+ return ret;
+
+ if (ret_requestor)
+ *ret_requestor = ((VoodooInstanceInterface*) instance)->proxy;
+
+ return DR_OK;
+}
+
+DirectResult
+voodoo_manager_check_allocation( VoodooManager *manager,
+ unsigned int amount )
+{
+#ifndef WIN32
+ FILE *f;
+ char buf[2000];
+ int size;
+ char *p;
+ size_t bytes;
+
+ D_MAGIC_ASSERT( manager, VoodooManager );
+
+ if (!voodoo_config->memory_max)
+ return DR_OK;
+
+ direct_snprintf( buf, sizeof(buf), "/proc/%d/status", direct_getpid() );
+
+ f = fopen( buf, "r" );
+ if (!f) {
+ D_ERROR( "Could not open '%s'!\n", buf );
+ return DR_FAILURE;
+ }
+
+ bytes = fread( buf, 1, sizeof(buf)-1, f );
+
+ fclose( f );
+
+ if (bytes) {
+ buf[bytes] = 0;
+
+ p = strstr( buf, "VmRSS:" );
+ if (!p) {
+ D_ERROR( "Could not find memory information!\n" );
+ return DR_FAILURE;
+ }
+
+ sscanf( p + 6, " %u", &size );
+
+ D_INFO( "SIZE: %u kB (+%u kB)\n", size, amount / 1024 );
+
+ if (size * 1024 + amount > voodoo_config->memory_max)
+ return DR_LIMITEXCEEDED;
+ }
+#endif
+ return DR_OK;
+}
+