From 7fe60435bce6595a9c58a9bfd8244d74b5320e96 Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Tue, 15 Jan 2013 08:46:13 +0100 Subject: Import DirectFB141_2k11R3_beta5 --- Source/DirectFB/src/core/surface_pool_bridge.c | 531 +++++++++++++++++++++++++ 1 file changed, 531 insertions(+) create mode 100755 Source/DirectFB/src/core/surface_pool_bridge.c (limited to 'Source/DirectFB/src/core/surface_pool_bridge.c') diff --git a/Source/DirectFB/src/core/surface_pool_bridge.c b/Source/DirectFB/src/core/surface_pool_bridge.c new file mode 100755 index 0000000..244ca2d --- /dev/null +++ b/Source/DirectFB/src/core/surface_pool_bridge.c @@ -0,0 +1,531 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +//#define DIRECT_ENABLE_DEBUG + +#include + +#include +#include + +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include + +#include + +#include + + +D_DEBUG_DOMAIN( Core_SurfPoolBridge, "Core/SurfPoolBridge", "DirectFB Core Surface Pool Bridge" ); + +/**********************************************************************************************************************/ + +static const SurfacePoolBridgeFuncs *bridge_funcs[MAX_SURFACE_POOL_BRIDGES]; +static void *bridge_locals[MAX_SURFACE_POOL_BRIDGES]; +static int bridge_count; +static CoreSurfacePoolBridge *bridge_array[MAX_SURFACE_POOL_BRIDGES]; + +/**********************************************************************************************************************/ + +static inline const SurfacePoolBridgeFuncs * +get_funcs( const CoreSurfacePoolBridge *bridge ) +{ + D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge ); + + D_ASSERT( bridge->bridge_id >= 0 ); + D_ASSERT( bridge->bridge_id < MAX_SURFACE_POOL_BRIDGES ); + D_ASSERT( bridge_funcs[bridge->bridge_id] != NULL ); + + /* Return function table of the bridge. */ + return bridge_funcs[bridge->bridge_id]; +} + +static inline void * +get_local( const CoreSurfacePoolBridge *bridge ) +{ + D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge ); + + D_ASSERT( bridge->bridge_id >= 0 ); + D_ASSERT( bridge->bridge_id < MAX_SURFACE_POOL_BRIDGES ); + + /* Return local data of the bridge. */ + return bridge_locals[bridge->bridge_id]; +} + +/**********************************************************************************************************************/ + +static DFBResult init_bridge( CoreDFB *core, + CoreSurfacePoolBridge *bridge, + const SurfacePoolBridgeFuncs *funcs, + void *context ); + +/**********************************************************************************************************************/ + +DFBResult +dfb_surface_pool_bridge_initialize( CoreDFB *core, + const SurfacePoolBridgeFuncs *funcs, + void *context, + CoreSurfacePoolBridge **ret_bridge ) +{ + DFBResult ret; + CoreSurfacePoolBridge *bridge; + FusionSHMPoolShared *shmpool; + + D_DEBUG_AT( Core_SurfPoolBridge, "%s( %p, %p )\n", __FUNCTION__, funcs, context ); + + D_ASSERT( core != NULL ); + D_ASSERT( funcs != NULL ); + D_ASSERT( ret_bridge != NULL ); + + /* Check against bridge limit. */ + if (bridge_count == MAX_SURFACE_POOL_BRIDGES) { + D_ERROR( "Core/SurfacePoolBridge: Maximum number of bridges (%d) reached!\n", MAX_SURFACE_POOL_BRIDGES ); + return DFB_LIMITEXCEEDED; + } + + D_ASSERT( bridge_funcs[bridge_count] == NULL ); + + shmpool = dfb_core_shmpool( core ); + + /* Allocate bridge structure. */ + bridge = SHCALLOC( shmpool, 1, sizeof(CoreSurfacePoolBridge) ); + if (!bridge) + return D_OOSHM(); + + /* Assign a bridge ID. */ + bridge->bridge_id = bridge_count++; + + /* Remember shared memory pool. */ + bridge->shmpool = shmpool; + + /* Set function table of the bridge. */ + bridge_funcs[bridge->bridge_id] = funcs; + + /* Add to global bridge list. */ + bridge_array[bridge->bridge_id] = bridge; + + D_MAGIC_SET( bridge, CoreSurfacePoolBridge ); + + ret = init_bridge( core, bridge, funcs, context ); + if (ret) { + bridge_count--; + D_MAGIC_CLEAR( bridge ); + SHFREE( shmpool, bridge ); + return ret; + } + + /* Return the new bridge. */ + *ret_bridge = bridge; + + return DFB_OK; +} + +DFBResult +dfb_surface_pool_bridge_join( CoreDFB *core, + CoreSurfacePoolBridge *bridge, + const SurfacePoolBridgeFuncs *funcs, + void *context ) +{ + DFBResult ret; + + D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge ); + + D_DEBUG_AT( Core_SurfPoolBridge, "%s( %p [%d], %p, %p )\n", __FUNCTION__, bridge, bridge->bridge_id, funcs, context ); + + D_ASSERT( core != NULL ); + D_ASSERT( funcs != NULL ); + + D_ASSERT( bridge->bridge_id < MAX_SURFACE_POOL_BRIDGES ); + D_ASSERT( bridge->bridge_id == bridge_count ); + D_ASSERT( bridge_funcs[bridge->bridge_id] == NULL ); + + /* Enforce same order as initialization to be used during join. */ + if (bridge->bridge_id != bridge_count) { + D_ERROR( "Core/SurfacePoolBridge: Wrong order of joining bridges, got %d, should be %d!\n", + bridge->bridge_id, bridge_count ); + return DFB_BUG; + } + + /* Allocate local bridge data. */ + if (bridge->bridge_local_data_size && + !(bridge_locals[bridge->bridge_id] = D_CALLOC( 1, bridge->bridge_local_data_size ))) + return D_OOM(); + + /* Set function table of the bridge. */ + bridge_funcs[bridge->bridge_id] = funcs; + + /* Add to global bridge list. */ + bridge_array[bridge->bridge_id] = bridge; + + /* Adjust bridge count. */ + if (bridge_count < bridge->bridge_id + 1) + bridge_count = bridge->bridge_id + 1; + + funcs = get_funcs( bridge ); + + if (funcs->JoinPoolBridge) { + ret = funcs->JoinPoolBridge( core, bridge, bridge->data, get_local(bridge), context ); + if (ret) { + D_DERROR( ret, "Core/SurfacePoolBridge: Joining '%s' failed!\n", bridge->desc.name ); + + if (bridge_locals[bridge->bridge_id]) { + D_FREE( bridge_locals[bridge->bridge_id] ); + bridge_locals[bridge->bridge_id] = NULL; + } + + bridge_array[bridge->bridge_id] = NULL; + bridge_funcs[bridge->bridge_id] = NULL; + + bridge_count--; + + return ret; + } + } + + return DFB_OK; +} + +DFBResult +dfb_surface_pool_bridge_destroy( CoreSurfacePoolBridge *bridge ) +{ + CoreSurfacePoolBridgeID bridge_id; + const SurfacePoolBridgeFuncs *funcs; + + D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge ); + + bridge_id = bridge->bridge_id; + + D_DEBUG_AT( Core_SurfPoolBridge, "%s( %p, '%s' [%d] )\n", __FUNCTION__, bridge, bridge->desc.name, bridge_id ); + + D_ASSERT( bridge->bridge_id >= 0 ); + D_ASSERT( bridge_id < MAX_SURFACE_POOL_BRIDGES ); + D_ASSERT( bridge_array[bridge_id] == bridge ); + + funcs = get_funcs( bridge ); + + if (funcs->DestroyPoolBridge) + funcs->DestroyPoolBridge( bridge, bridge->data, get_local(bridge) ); + + /* Free shared bridge data. */ + if (bridge->data) + SHFREE( bridge->shmpool, bridge->data ); + + /* Free local bridge data. */ + if (bridge_locals[bridge_id]) + D_FREE( bridge_locals[bridge_id] ); + + /* Remove from arrays. */ + bridge_array[bridge_id] = NULL; + bridge_funcs[bridge_id] = NULL; + bridge_locals[bridge_id] = NULL; + + fusion_skirmish_destroy( &bridge->lock ); + + D_MAGIC_CLEAR( bridge ); + + SHFREE( bridge->shmpool, bridge ); + + return DFB_OK; +} + +DFBResult +dfb_surface_pool_bridge_leave( CoreSurfacePoolBridge *bridge ) +{ + CoreSurfacePoolBridgeID bridge_id; + const SurfacePoolBridgeFuncs *funcs; + + D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge ); + + bridge_id = bridge->bridge_id; + + D_DEBUG_AT( Core_SurfPoolBridge, "%s( %p, '%s' [%d] )\n", __FUNCTION__, bridge, bridge->desc.name, bridge_id ); + + D_ASSERT( bridge->bridge_id >= 0 ); + D_ASSERT( bridge_id < MAX_SURFACE_POOL_BRIDGES ); + D_ASSERT( bridge_array[bridge_id] == bridge ); + + funcs = get_funcs( bridge ); + + if (funcs->LeavePoolBridge) + funcs->LeavePoolBridge( bridge, bridge->data, get_local(bridge) ); + + /* Free local bridge data. */ + if (bridge_locals[bridge_id]) + D_FREE( bridge_locals[bridge_id] ); + + /* Remove from arrays. */ + bridge_array[bridge_id] = NULL; + bridge_funcs[bridge_id] = NULL; + bridge_locals[bridge_id] = NULL; + + return DFB_OK; +} + +/**********************************************************************************************************************/ + +DFBResult +dfb_surface_pool_bridges_enumerate( CoreSurfacePoolBridgeCallback callback, + void *ctx ) +{ + int i; + + D_ASSERT( callback != NULL ); + + D_DEBUG_AT( Core_SurfPoolBridge, "%s( %p, %p )\n", __FUNCTION__, callback, ctx ); + + for (i=0; i 0 ); + D_ASSERT( ret_transfer != NULL ); + + alloc_size = sizeof(CoreSurfacePoolTransfer) + num_rects * sizeof(DFBRectangle) + bridge->transfer_data_size; + + transfer = SHCALLOC( bridge->shmpool, 1, alloc_size ); + if (!transfer) + return D_OOSHM(); + + transfer->bridge = bridge; + transfer->buffer = buffer; + transfer->from = from; + transfer->to = to; + + transfer->rects = (DFBRectangle*)(transfer + 1); + + if (bridge->transfer_data_size) + transfer->data = transfer->rects + num_rects; + + transfer->num_rects = num_rects; + + direct_memcpy( transfer->rects, rects, num_rects * sizeof(DFBRectangle) ); + + D_MAGIC_SET( transfer, CoreSurfacePoolTransfer ); + + *ret_transfer = transfer; + + return DFB_OK; +} + +static void +deallocate_transfer( CoreSurfacePoolTransfer *transfer ) +{ + CoreSurfacePoolBridge *bridge; + + D_MAGIC_ASSERT( transfer, CoreSurfacePoolTransfer ); + + bridge = transfer->bridge; + D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge ); + + D_MAGIC_CLEAR( transfer ); + + SHFREE( bridge->shmpool, transfer ); +} + +DFBResult +dfb_surface_pool_bridges_transfer( CoreSurfaceBuffer *buffer, + CoreSurfaceAllocation *from, + CoreSurfaceAllocation *to, + const DFBRectangle *rects, + unsigned int num_rects ) +{ + DFBResult ret; + int i; + DFBRectangle rect; + CoreSurface *surface; + CoreSurfacePoolBridge *bridge = NULL; + const SurfacePoolBridgeFuncs *funcs; + CoreSurfacePoolTransfer *transfer; + + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + CORE_SURFACE_ALLOCATION_ASSERT( from ); + CORE_SURFACE_ALLOCATION_ASSERT( to ); + D_ASSERT( rects != NULL || num_rects == 0 ); + D_ASSERT( num_rects > 0 || rects == NULL ); + + D_DEBUG_AT( Core_SurfPoolBridge, "%s( %p [%s], %p -> %p, %d rects )\n", __FUNCTION__, + buffer, dfb_pixelformat_name( buffer->format ), from, to, num_rects ); + + surface = buffer->surface; + D_MAGIC_ASSERT( surface, CoreSurface ); + FUSION_SKIRMISH_ASSERT( &surface->lock ); + + if (!rects) { + rect.x = rect.y = 0; + rect.w = surface->config.size.w; + rect.h = surface->config.size.h; + + rects = ▭ + num_rects = 1; + } + + for (i=0; iCheckTransfer != NULL ); + + ret = funcs->CheckTransfer( bridge, bridge->data, get_local(bridge), buffer, from, to ); + if (ret) + bridge = NULL; + else + break; + } + + if (!bridge) + return DFB_UNSUPPORTED; + + D_DEBUG_AT( Core_SurfPoolBridge, " -> using '%s'\n", bridge->desc.name ); + + ret = allocate_transfer( bridge, buffer, from, to, rects, num_rects, &transfer ); + if (ret) + return ret; + + D_ASSERT( funcs->StartTransfer != NULL ); + + D_DEBUG_AT( Core_SurfPoolBridge, " -> start...\n" ); + + ret = funcs->StartTransfer( bridge, bridge->data, get_local(bridge), transfer, transfer->data ); + if (ret) + D_DERROR( ret, "Core/SurfacePoolBridge: Starting transfer via '%s' failed!\n", bridge->desc.name ); + else if (funcs->FinishTransfer) { + D_DEBUG_AT( Core_SurfPoolBridge, " -> finish...\n" ); + + ret = funcs->FinishTransfer( bridge, bridge->data, get_local(bridge), transfer, transfer->data ); + if (ret) + D_DERROR( ret, "Core/SurfacePoolBridge: Finishing transfer via '%s' failed!\n", bridge->desc.name ); + } + + D_DEBUG_AT( Core_SurfPoolBridge, " => %s\n", DirectResultString(ret) ); + + deallocate_transfer( transfer ); + + return ret; +} + +/**********************************************************************************************************************/ + +static DFBResult +init_bridge( CoreDFB *core, + CoreSurfacePoolBridge *bridge, + const SurfacePoolBridgeFuncs *funcs, + void *context ) +{ + DFBResult ret; + + D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge ); + D_ASSERT( funcs != NULL ); + D_ASSERT( funcs->InitPoolBridge != NULL ); + + D_DEBUG_AT( Core_SurfPoolBridge, "%s( %p, %p )\n", __FUNCTION__, bridge, funcs ); + + if (funcs->PoolBridgeDataSize) + bridge->bridge_data_size = funcs->PoolBridgeDataSize(); + + if (funcs->PoolBridgeLocalDataSize) + bridge->bridge_local_data_size = funcs->PoolBridgeLocalDataSize(); + + if (funcs->PoolTransferDataSize) + bridge->transfer_data_size = funcs->PoolTransferDataSize(); + + /* Allocate shared bridge data. */ + if (bridge->bridge_data_size) { + bridge->data = SHCALLOC( bridge->shmpool, 1, bridge->bridge_data_size ); + if (!bridge->data) + return D_OOSHM(); + } + + /* Allocate local bridge data. */ + if (bridge->bridge_local_data_size && + !(bridge_locals[bridge->bridge_id] = D_CALLOC( 1, bridge->bridge_local_data_size ))) + { + SHFREE( bridge->shmpool, bridge->data ); + return D_OOM(); + } + + ret = funcs->InitPoolBridge( core, bridge, bridge->data, get_local(bridge), context, &bridge->desc ); + if (ret) { + D_DERROR( ret, "Core/SurfacePoolBridge: Initializing '%s' failed!\n", bridge->desc.name ); + + if (bridge_locals[bridge->bridge_id]) { + D_FREE( bridge_locals[bridge->bridge_id] ); + bridge_locals[bridge->bridge_id] = NULL; + } + + if (bridge->data) { + SHFREE( bridge->shmpool, bridge->data ); + bridge->data = NULL; + } + + bridge_array[bridge->bridge_id] = NULL; + bridge_funcs[bridge->bridge_id] = NULL; + + return ret; + } + + fusion_skirmish_init( &bridge->lock, bridge->desc.name, dfb_core_world(core) ); + + return DFB_OK; +} + -- cgit