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/core.c | 1160 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 1160 insertions(+) create mode 100755 Source/DirectFB/src/core/core.c (limited to 'Source/DirectFB/src/core/core.c') diff --git a/Source/DirectFB/src/core/core.c b/Source/DirectFB/src/core/core.c new file mode 100755 index 0000000..ca20152 --- /dev/null +++ b/Source/DirectFB/src/core/core.c @@ -0,0 +1,1160 @@ +/* + (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. +*/ + +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +D_DEBUG_DOMAIN( DirectFB_Core, "DirectFB/Core", "DirectFB Core" ); + +/******************************************************************************/ + +extern CorePart dfb_clipboard_core; +extern CorePart dfb_colorhash_core; +extern CorePart dfb_graphics_core; +extern CorePart dfb_input_core; +extern CorePart dfb_layer_core; +extern CorePart dfb_screen_core; +extern CorePart dfb_surface_core; +extern CorePart dfb_system_core; +extern CorePart dfb_wm_core; + +static CorePart *core_parts[] = { + &dfb_clipboard_core, + &dfb_colorhash_core, + &dfb_surface_core, + &dfb_system_core, + &dfb_input_core, + &dfb_graphics_core, + &dfb_screen_core, + &dfb_layer_core, + &dfb_wm_core +}; + +void * +dfb_core_get_part( CoreDFB *core, + DFBCorePartID part_id ) +{ + switch (part_id) { + case DFCP_CLIPBOARD: + return dfb_clipboard_core.data_local; + + case DFCP_COLORHASH: + return dfb_colorhash_core.data_local; + + case DFCP_GRAPHICS: + return dfb_graphics_core.data_local; + + case DFCP_INPUT: + return dfb_input_core.data_local; + + case DFCP_LAYER: + return dfb_layer_core.data_local; + + case DFCP_SCREEN: + return dfb_screen_core.data_local; + + case DFCP_SURFACE: + return dfb_surface_core.data_local; + + case DFCP_SYSTEM: + return dfb_system_core.data_local; + + case DFCP_WM: + return dfb_wm_core.data_local; + + default: + D_BUG( "unknown core part" ); + } + + return NULL; +} + +/******************************************************************************/ + +/* + * one entry in the cleanup stack + */ +struct _CoreCleanup { + DirectLink link; + + CoreCleanupFunc func; /* the cleanup function to be called */ + void *data; /* context of the cleanup function */ + bool emergency; /* if true, cleanup is also done during + emergency shutdown (from signal hadler) */ +}; + +/******************************************************************************/ + +struct __DFB_CoreDFBShared { + int magic; + + FusionSkirmish lock; + bool active; + + FusionObjectPool *layer_context_pool; + FusionObjectPool *layer_region_pool; + FusionObjectPool *palette_pool; + FusionObjectPool *surface_pool; + FusionObjectPool *window_pool; + + FusionSHMPoolShared *shmpool; + FusionSHMPoolShared *shmpool_data; /* for raw data, e.g. surface buffers */ +}; + +struct __DFB_CoreDFB { + int magic; + + int refs; + + int fusion_id; + + FusionWorld *world; + FusionArena *arena; + + CoreDFBShared *shared; + + bool master; + bool suspended; + + DirectLink *cleanups; + + DirectThreadInitHandler *init_handler; + + DirectSignalHandler *signal_handler; + + DirectCleanupHandler *cleanup_handler; +}; + +/******************************************************************************/ + +/* + * ckecks if stack is clean, otherwise prints warning, then calls core_deinit() + */ +static void dfb_core_deinit_check( void *ctx ); + +static void dfb_core_thread_init_handler( DirectThread *thread, void *arg ); + +static void dfb_core_process_cleanups( CoreDFB *core, bool emergency ); + +static DirectSignalHandlerResult dfb_core_signal_handler( int num, + void *addr, + void *ctx ); + +/******************************************************************************/ + +static int dfb_core_arena_initialize( FusionArena *arena, + void *ctx ); +static int dfb_core_arena_shutdown ( FusionArena *arena, + void *ctx, + bool emergency ); +static int dfb_core_arena_join ( FusionArena *arena, + void *ctx ); +static int dfb_core_arena_leave ( FusionArena *arena, + void *ctx, + bool emergency ); + +/******************************************************************************/ + +#if defined(DFB_DYNAMIC_LINKING) && defined(SOPATH) +/* + * the library handle for dlopen'ing ourselves + */ +static void* dfb_lib_handle = NULL; +#endif + +/******************************************************************************/ + +static CoreDFB *core_dfb = NULL; +static pthread_mutex_t core_dfb_lock = PTHREAD_MUTEX_INITIALIZER; + +/******************************************************************************/ + +DFBResult +dfb_core_create( CoreDFB **ret_core ) +{ + int ret; +#if FUSION_BUILD_MULTI + char buf[16]; +#endif + CoreDFB *core = NULL; + CoreDFBShared *shared = NULL; + + D_ASSERT( ret_core != NULL ); + D_ASSERT( dfb_config != NULL ); + + D_DEBUG_AT( DirectFB_Core, "%s...\n", __FUNCTION__ ); + + pthread_mutex_lock( &core_dfb_lock ); + + D_ASSERT( core_dfb == NULL || core_dfb->refs > 0 ); + + if (core_dfb) { + D_MAGIC_ASSERT( core_dfb, CoreDFB ); + + core_dfb->refs++; + + *ret_core = core_dfb; + + pthread_mutex_unlock( &core_dfb_lock ); + + return DFB_OK; + } + + direct_initialize(); + + + D_INFO( "DirectFB/Core: %s Application Core. ("BUILDTIME") %s%s\n", + FUSION_BUILD_MULTI ? "Multi" : "Single", + DIRECT_BUILD_DEBUG ? "[ DEBUG ]" : "", + DIRECT_BUILD_TRACE ? "[ TRACE ]" : "" ); + + +#if defined(DFB_DYNAMIC_LINKING) && defined(SOPATH) + if (!dfb_lib_handle) +#ifdef RTLD_GLOBAL + dfb_lib_handle = dlopen(SOPATH, RTLD_GLOBAL|RTLD_LAZY); +#else + /* RTLD_GLOBAL is not defined on OpenBSD */ + dfb_lib_handle = dlopen(SOPATH, RTLD_LAZY); +#endif +#endif + + ret = dfb_system_lookup(); + if (ret) + goto error; + + + /* Allocate local core structure. */ + core = D_CALLOC( 1, sizeof(CoreDFB) ); + if (!core) { + ret = D_OOM(); + goto error; + } + + core->refs = 1; + + core->init_handler = direct_thread_add_init_handler( dfb_core_thread_init_handler, core ); + +#if FUSION_BUILD_MULTI + dfb_system_thread_init(); +#endif + + direct_find_best_memcpy(); + + D_MAGIC_SET( core, CoreDFB ); + + core_dfb = core; + + ret = fusion_enter( dfb_config->session, DIRECTFB_CORE_ABI, FER_ANY, &core->world ); + if (ret) + goto error; + + core->fusion_id = fusion_id( core->world ); + +#if FUSION_BUILD_MULTI + D_DEBUG_AT( DirectFB_Core, "world %d, fusion id %d\n", fusion_world_index(core->world), core->fusion_id ); + + snprintf( buf, sizeof(buf), "%d", fusion_world_index(core->world) ); + + setenv( "DIRECTFB_SESSION", buf, true ); +#endif + + if (dfb_config->sync) { + D_INFO( "DirectFB/Core: calling sync()...\n" ); + sync(); + } + + direct_signal_handler_add( DIRECT_SIGNAL_ANY, dfb_core_signal_handler, core, &core->signal_handler ); + + if (fusion_arena_enter( core->world, "DirectFB/Core", + dfb_core_arena_initialize, dfb_core_arena_join, + core, &core->arena, &ret ) || ret) + { + ret = ret ? ret : DFB_FUSION; + goto error; + } + + shared = core->shared; + D_MAGIC_ASSERT( shared, CoreDFBShared ); + + if (dfb_config->block_all_signals) + direct_signals_block_all(); + + if (dfb_config->deinit_check) + direct_cleanup_handler_add( dfb_core_deinit_check, NULL, &core->cleanup_handler ); + + + fusion_skirmish_prevail( &shared->lock ); + + if (!core->master) { + while (!shared->active) + fusion_skirmish_wait( &shared->lock, 0 ); + } + + fusion_skirmish_dismiss( &shared->lock ); + + + *ret_core = core; + + pthread_mutex_unlock( &core_dfb_lock ); + + D_DEBUG_AT( DirectFB_Core, "Core successfully created.\n" ); + + return DFB_OK; + + +error: + if (core) { + if (core->world) + fusion_exit( core->world, false ); + + if (core->init_handler) + direct_thread_remove_init_handler( core->init_handler ); + + if (core->signal_handler) + direct_signal_handler_remove( core->signal_handler ); + + D_MAGIC_CLEAR( core ); + + D_FREE( core ); + core_dfb = NULL; + } + + pthread_mutex_unlock( &core_dfb_lock ); + + direct_shutdown(); + + return ret; +} + +DFBResult +dfb_core_destroy( CoreDFB *core, bool emergency ) +{ + D_MAGIC_ASSERT( core, CoreDFB ); + D_ASSERT( core->refs > 0 ); + D_ASSERT( core == core_dfb ); + + D_DEBUG_AT( DirectFB_Core, "%s...\n", __FUNCTION__ ); + + if (!emergency) { + pthread_mutex_lock( &core_dfb_lock ); + + if (--core->refs) { + pthread_mutex_unlock( &core_dfb_lock ); + return DFB_OK; + } + } + + direct_signal_handler_remove( core->signal_handler ); + + if (core->cleanup_handler) + direct_cleanup_handler_remove( core->cleanup_handler ); + + if (core->master) { + if (emergency) { + fusion_kill( core->world, 0, SIGKILL, 1000 ); + } + else { + fusion_kill( core->world, 0, SIGTERM, 5000 ); + fusion_kill( core->world, 0, SIGKILL, 2000 ); + } + } + + dfb_core_process_cleanups( core, emergency ); + + while (fusion_arena_exit( core->arena, dfb_core_arena_shutdown, + core->master ? NULL : dfb_core_arena_leave, + core, emergency, NULL ) == DFB_BUSY) + { + D_ONCE( "waiting for DirectFB slaves to terminate" ); + usleep( 100000 ); + } + + fusion_exit( core->world, emergency ); + + if (!emergency) + direct_thread_remove_init_handler( core->init_handler ); + + D_MAGIC_CLEAR( core ); + + D_FREE( core ); + core_dfb = NULL; + + if (!emergency) { + pthread_mutex_unlock( &core_dfb_lock ); + + direct_shutdown(); + } + + return DFB_OK; +} + +CoreLayerContext * +dfb_core_create_layer_context( CoreDFB *core ) +{ + CoreDFBShared *shared; + + D_ASSUME( core != NULL ); + + if (!core) + core = core_dfb; + + D_MAGIC_ASSERT( core, CoreDFB ); + + shared = core->shared; + + D_MAGIC_ASSERT( shared, CoreDFBShared ); + D_ASSERT( shared->layer_context_pool != NULL ); + + return (CoreLayerContext*) fusion_object_create( shared->layer_context_pool, core->world ); +} + +CoreLayerRegion * +dfb_core_create_layer_region( CoreDFB *core ) +{ + CoreDFBShared *shared; + + D_ASSUME( core != NULL ); + + if (!core) + core = core_dfb; + + D_MAGIC_ASSERT( core, CoreDFB ); + + shared = core->shared; + + D_MAGIC_ASSERT( shared, CoreDFBShared ); + D_ASSERT( core->shared->layer_region_pool != NULL ); + + return (CoreLayerRegion*) fusion_object_create( core->shared->layer_region_pool, core->world ); +} + +CorePalette * +dfb_core_create_palette( CoreDFB *core ) +{ + CoreDFBShared *shared; + + D_ASSUME( core != NULL ); + + if (!core) + core = core_dfb; + + D_MAGIC_ASSERT( core, CoreDFB ); + + shared = core->shared; + + D_MAGIC_ASSERT( shared, CoreDFBShared ); + D_ASSERT( core->shared->palette_pool != NULL ); + + return (CorePalette*) fusion_object_create( core->shared->palette_pool, core->world ); +} + +CoreSurface * +dfb_core_create_surface( CoreDFB *core ) +{ + CoreDFBShared *shared; + + D_ASSUME( core != NULL ); + + if (!core) + core = core_dfb; + + D_MAGIC_ASSERT( core, CoreDFB ); + + shared = core->shared; + + D_MAGIC_ASSERT( shared, CoreDFBShared ); + D_ASSERT( core->shared->surface_pool != NULL ); + + return (CoreSurface*) fusion_object_create( core->shared->surface_pool, core->world ); +} + +CoreWindow * +dfb_core_create_window( CoreDFB *core ) +{ + CoreDFBShared *shared; + + D_ASSUME( core != NULL ); + + if (!core) + core = core_dfb; + + D_MAGIC_ASSERT( core, CoreDFB ); + + shared = core->shared; + + D_MAGIC_ASSERT( shared, CoreDFBShared ); + D_ASSERT( core->shared->window_pool != NULL ); + + return (CoreWindow*) fusion_object_create( core->shared->window_pool, core->world ); +} + +DirectResult +dfb_core_enum_surfaces( CoreDFB *core, + FusionObjectCallback callback, + void *ctx ) +{ + CoreDFBShared *shared; + + D_ASSERT( core != NULL || core_dfb != NULL ); + + if (!core) + core = core_dfb; + + D_MAGIC_ASSERT( core, CoreDFB ); + + shared = core->shared; + + D_MAGIC_ASSERT( shared, CoreDFBShared ); + + return fusion_object_pool_enum( shared->surface_pool, callback, ctx ); +} + +DirectResult +dfb_core_enum_layer_contexts( CoreDFB *core, + FusionObjectCallback callback, + void *ctx ) +{ + CoreDFBShared *shared; + + D_ASSERT( core != NULL || core_dfb != NULL ); + + if (!core) + core = core_dfb; + + D_MAGIC_ASSERT( core, CoreDFB ); + + shared = core->shared; + + D_MAGIC_ASSERT( shared, CoreDFBShared ); + + return fusion_object_pool_enum( shared->layer_context_pool, callback, ctx ); +} + +DirectResult +dfb_core_enum_layer_regions( CoreDFB *core, + FusionObjectCallback callback, + void *ctx ) +{ + CoreDFBShared *shared; + + D_ASSERT( core != NULL || core_dfb != NULL ); + + if (!core) + core = core_dfb; + + D_MAGIC_ASSERT( core, CoreDFB ); + + shared = core->shared; + + D_MAGIC_ASSERT( shared, CoreDFBShared ); + + return fusion_object_pool_enum( shared->layer_region_pool, callback, ctx ); +} + +bool +dfb_core_is_master( CoreDFB *core ) +{ + D_MAGIC_ASSERT( core, CoreDFB ); + + return core->master; +} + +void +dfb_core_activate( CoreDFB *core ) +{ + CoreDFBShared *shared; + + D_MAGIC_ASSERT( core, CoreDFB ); + + shared = core->shared; + D_MAGIC_ASSERT( shared, CoreDFBShared ); + + fusion_skirmish_prevail( &shared->lock ); + + shared->active = true; + + fusion_skirmish_notify( &shared->lock ); + + fusion_skirmish_dismiss( &shared->lock ); +} + +FusionWorld * +dfb_core_world( CoreDFB *core ) +{ +// D_ASSUME( core != NULL ); + + if (!core) + core = core_dfb; + + D_MAGIC_ASSERT( core, CoreDFB ); + + return core->world; +} + +FusionArena * +dfb_core_arena( CoreDFB *core ) +{ + D_ASSUME( core != NULL ); + + if (!core) + core = core_dfb; + + D_MAGIC_ASSERT( core, CoreDFB ); + + return core->arena; +} + +FusionSHMPoolShared * +dfb_core_shmpool( CoreDFB *core ) +{ + CoreDFBShared *shared; + + D_ASSUME( core != NULL ); + + if (!core) + core = core_dfb; + + D_MAGIC_ASSERT( core, CoreDFB ); + + shared = core->shared; + + D_MAGIC_ASSERT( shared, CoreDFBShared ); + + return shared->shmpool; +} + +FusionSHMPoolShared * +dfb_core_shmpool_data( CoreDFB *core ) +{ + CoreDFBShared *shared; + + D_ASSUME( core != NULL ); + + if (!core) + core = core_dfb; + + D_MAGIC_ASSERT( core, CoreDFB ); + + shared = core->shared; + + D_MAGIC_ASSERT( shared, CoreDFBShared ); + + return shared->shmpool_data; +} + +DFBResult +dfb_core_suspend( CoreDFB *core ) +{ + DFBResult ret; + + D_ASSUME( core != NULL ); + + if (!core) + core = core_dfb; + + D_MAGIC_ASSERT( core, CoreDFB ); + + if (!core->master) + return DFB_ACCESSDENIED; + + if (core->suspended) + return DFB_BUSY; + + ret = dfb_input_core.Suspend( dfb_input_core.data_local ); + if (ret) + goto error_input; + + ret = dfb_layer_core.Suspend( dfb_layer_core.data_local ); + if (ret) + goto error_layers; + + ret = dfb_screen_core.Suspend( dfb_screen_core.data_local ); + if (ret) + goto error_screens; + + ret = dfb_graphics_core.Suspend( dfb_graphics_core.data_local ); + if (ret) + goto error_graphics; + + core->suspended = true; + + return DFB_OK; + +error_graphics: + dfb_screen_core.Resume( dfb_screen_core.data_local ); +error_screens: + dfb_layer_core.Resume( dfb_layer_core.data_local ); +error_layers: + dfb_input_core.Resume( dfb_input_core.data_local ); +error_input: + return ret; +} + +DFBResult +dfb_core_resume( CoreDFB *core ) +{ + DFBResult ret; + + D_ASSUME( core != NULL ); + + if (!core) + core = core_dfb; + + D_MAGIC_ASSERT( core, CoreDFB ); + + if (!core->master) + return DFB_ACCESSDENIED; + + if (!core->suspended) + return DFB_BUSY; + + ret = dfb_graphics_core.Resume( dfb_graphics_core.data_local ); + if (ret) + goto error_graphics; + + ret = dfb_screen_core.Resume( dfb_screen_core.data_local ); + if (ret) + goto error_screens; + + ret = dfb_layer_core.Resume( dfb_layer_core.data_local ); + if (ret) + goto error_layers; + + ret = dfb_input_core.Resume( dfb_input_core.data_local ); + if (ret) + goto error_input; + + core->suspended = false; + + return DFB_OK; + +error_input: + dfb_layer_core.Suspend( dfb_layer_core.data_local ); +error_layers: + dfb_screen_core.Suspend( dfb_screen_core.data_local ); +error_screens: + dfb_graphics_core.Suspend( dfb_graphics_core.data_local ); +error_graphics: + return ret; +} + +CoreCleanup * +dfb_core_cleanup_add( CoreDFB *core, + CoreCleanupFunc func, + void *data, + bool emergency ) +{ + CoreCleanup *cleanup; + + D_ASSUME( core != NULL ); + + if (!core) + core = core_dfb; + + D_MAGIC_ASSERT( core, CoreDFB ); + + cleanup = D_CALLOC( 1, sizeof(CoreCleanup) ); + + cleanup->func = func; + cleanup->data = data; + cleanup->emergency = emergency; + + direct_list_prepend( &core->cleanups, &cleanup->link ); + + return cleanup; +} + +void +dfb_core_cleanup_remove( CoreDFB *core, + CoreCleanup *cleanup ) +{ + D_ASSUME( core != NULL ); + + if (!core) + core = core_dfb; + + D_MAGIC_ASSERT( core, CoreDFB ); + + direct_list_remove( &core->cleanups, &cleanup->link ); + + D_FREE( cleanup ); +} + +/******************************************************************************/ + +static void +dfb_core_deinit_check( void *ctx ) +{ + if (core_dfb && core_dfb->refs) { + D_WARN( "Application exited without deinitialization of DirectFB!" ); + dfb_core_destroy( core_dfb, true ); + } +} + +static void +dfb_core_thread_init_handler( DirectThread *thread, void *arg ) +{ + dfb_system_thread_init(); +} + +static void +dfb_core_process_cleanups( CoreDFB *core, bool emergency ) +{ + D_MAGIC_ASSERT( core, CoreDFB ); + + while (core->cleanups) { + CoreCleanup *cleanup = (CoreCleanup*) core->cleanups; + + core->cleanups = core->cleanups->next; + + if (cleanup->emergency || !emergency) + cleanup->func( cleanup->data, emergency ); + + D_FREE( cleanup ); + } +} + +static DirectSignalHandlerResult +dfb_core_signal_handler( int num, + void *addr, + void *ctx ) +{ + CoreDFB *core = ctx; + + D_ASSERT( core == core_dfb ); + + dfb_core_destroy( core, true ); + + return DSHR_OK; +} + +/******************************************************************************/ + +static int +dfb_core_shutdown( CoreDFB *core, bool emergency ) +{ + CoreDFBShared *shared; + + D_MAGIC_ASSERT( core, CoreDFB ); + + shared = core->shared; + + D_MAGIC_ASSERT( shared, CoreDFBShared ); + + /* Suspend input core to stop all input threads before shutting down. */ + if (dfb_input_core.initialized) + dfb_input_core.Suspend( dfb_input_core.data_local ); + + fusion_stop_dispatcher( core->world, emergency ); + + /* Destroy window objects. */ + fusion_object_pool_destroy( shared->window_pool, core->world ); + + /* Close window stacks. */ + if (dfb_wm_core.initialized) + dfb_wm_close_all_stacks( dfb_wm_core.data_local ); + + /* Destroy layer context and region objects. */ + fusion_object_pool_destroy( shared->layer_region_pool, core->world ); + fusion_object_pool_destroy( shared->layer_context_pool, core->world ); + + /* Shutdown WM core. */ + dfb_core_part_shutdown( core, &dfb_wm_core, emergency ); + + /* Shutdown layer core. */ + dfb_core_part_shutdown( core, &dfb_layer_core, emergency ); + dfb_core_part_shutdown( core, &dfb_screen_core, emergency ); + + /* Destroy surface and palette objects. */ + fusion_object_pool_destroy( shared->surface_pool, core->world ); + fusion_object_pool_destroy( shared->palette_pool, core->world ); + + /* Destroy remaining core parts. */ + dfb_core_part_shutdown( core, &dfb_graphics_core, emergency ); + dfb_core_part_shutdown( core, &dfb_surface_core, emergency ); + dfb_core_part_shutdown( core, &dfb_input_core, emergency ); + dfb_core_part_shutdown( core, &dfb_system_core, emergency ); + dfb_core_part_shutdown( core, &dfb_colorhash_core, emergency ); + dfb_core_part_shutdown( core, &dfb_clipboard_core, emergency ); + + /* Destroy shared memory pool for surface data. */ + fusion_shm_pool_destroy( core->world, shared->shmpool_data ); + + return 0; +} + +static DFBResult +dfb_core_initialize( CoreDFB *core ) +{ + int i; + DFBResult ret; + CoreDFBShared *shared; + + D_MAGIC_ASSERT( core, CoreDFB ); + + shared = core->shared; + + D_MAGIC_ASSERT( shared, CoreDFBShared ); + + ret = fusion_shm_pool_create( core->world, "DirectFB Data Pool", 0x1000000, + fusion_config->debugshm, &shared->shmpool_data ); + if (ret) + return ret; + + shared->layer_context_pool = dfb_layer_context_pool_create( core->world ); + shared->layer_region_pool = dfb_layer_region_pool_create( core->world ); + shared->palette_pool = dfb_palette_pool_create( core->world ); + shared->surface_pool = dfb_surface_pool_create( core->world ); + shared->window_pool = dfb_window_pool_create( core->world ); + + for (i=0; i=0; i--) + dfb_core_part_leave( core, core_parts[i], emergency ); + + return DFB_OK; +} + +static int +dfb_core_join( CoreDFB *core ) +{ + int i; + + D_MAGIC_ASSERT( core, CoreDFB ); + + for (i=0; iworld, "DirectFB Main Pool", 0x400000, + fusion_config->debugshm, &pool ); + if (ret) + return ret; + + /* Allocate shared structure in the new pool. */ + shared = SHCALLOC( pool, 1, sizeof(CoreDFBShared) ); + if (!shared) { + fusion_shm_pool_destroy( core->world, pool ); + return D_OOSHM(); + } + + core->shared = shared; + core->master = true; + + shared->shmpool = pool; + + D_MAGIC_SET( shared, CoreDFBShared ); + + /* Initialize. */ + ret = dfb_core_initialize( core ); + if (ret) { + D_MAGIC_CLEAR( shared ); + SHFREE( pool, shared ); + fusion_shm_pool_destroy( core->world, pool ); + return ret; + } + + fusion_skirmish_init( &shared->lock, "DirectFB Core", core->world ); + + /* Register shared data. */ + fusion_arena_add_shared_field( arena, "Core/Shared", shared ); + + return DFB_OK; +} + +static int +dfb_core_arena_shutdown( FusionArena *arena, + void *ctx, + bool emergency) +{ + DFBResult ret; + CoreDFB *core = ctx; + CoreDFBShared *shared; + FusionSHMPoolShared *pool; + + D_MAGIC_ASSERT( core, CoreDFB ); + + shared = core->shared; + + D_MAGIC_ASSERT( shared, CoreDFBShared ); + + pool = shared->shmpool; + + D_DEBUG_AT( DirectFB_Core, "Shutting down...\n" ); + + if (!core->master) { + D_WARN( "refusing shutdown in slave" ); + return dfb_core_leave( core, emergency ); + } + + /* Shutdown. */ + ret = dfb_core_shutdown( core, emergency ); + + fusion_skirmish_destroy( &shared->lock ); + + D_MAGIC_CLEAR( shared ); + + SHFREE( pool, shared ); + + fusion_shm_pool_destroy( core->world, pool ); + + return ret; +} + +static int +dfb_core_arena_join( FusionArena *arena, + void *ctx ) +{ + DFBResult ret; + CoreDFB *core = ctx; + void *field; + + D_MAGIC_ASSERT( core, CoreDFB ); + + D_DEBUG_AT( DirectFB_Core, "Joining...\n" ); + + /* Get shared data. */ + if (fusion_arena_get_shared_field( arena, "Core/Shared", &field )) + return DFB_FUSION; + + core->shared = field; + + /* Join. */ + ret = dfb_core_join( core ); + if (ret) + return ret; + + return DFB_OK; +} + +static int +dfb_core_arena_leave( FusionArena *arena, + void *ctx, + bool emergency) +{ + DFBResult ret; + CoreDFB *core = ctx; + + D_MAGIC_ASSERT( core, CoreDFB ); + + D_DEBUG_AT( DirectFB_Core, "Leaving...\n" ); + + /* Leave. */ + ret = dfb_core_leave( core, emergency ); + if (ret) + return ret; + + return DFB_OK; +} + -- cgit