Esempio n. 1
0
static DirectResult
fusion_hash_create_internal (bool local,FusionSHMPoolShared *pool,
                             FusionHashType key_type,
                             FusionHashType value_type,
                             int  size, FusionHash **ret_hash )
{
     FusionHash *hash;

     if (!ret_hash)
          return DFB_BUG;
     if (!local && !pool)
          return DFB_BUG;

     if (size < FUSION_HASH_MIN_SIZE)
          size = FUSION_HASH_MIN_SIZE;

     if (local)
          hash = D_CALLOC(1, sizeof (FusionHash) );
     else
          hash = SHCALLOC(pool, 1, sizeof (FusionHash) );

     if (!hash)
          return local ?DFB_NOSYSTEMMEMORY:DFB_NOSHAREDMEMORY;

     hash->local              = local;
     hash->pool               = pool;
     hash->key_type           = key_type;
     hash->value_type         = value_type;
     hash->size               = size;
     hash->nnodes             = 0;
     if (local)
          hash->nodes = D_CALLOC(size,sizeof (FusionHashNode*) );
     else
          hash->nodes = SHCALLOC(pool, size, sizeof(FusionHashNode*) );

     if (!hash->nodes) {
          if (local)
               D_FREE(hash );
          else
               SHFREE(pool, hash );
          return local?DFB_NOSYSTEMMEMORY:DFB_NOSHAREDMEMORY;
     }

     D_MAGIC_SET(hash, FusionHash );

     *ret_hash = hash;

     return DFB_OK;
}
Esempio n. 2
0
DFBResult
dfb_palette_create( CoreDFB       *core,
                    unsigned int   size,
                    CorePalette  **ret_palette )
{
     CorePalette *palette;

     D_DEBUG_AT( Core_Palette, "%s( %d )\n", __FUNCTION__, size );

     D_ASSERT( ret_palette );

     palette = dfb_core_create_palette( core );
     if (!palette)
          return DFB_FUSION;

     palette->shmpool = dfb_core_shmpool( core );

     if (size) {
          palette->entries = SHCALLOC( palette->shmpool, size, sizeof(DFBColor) );
          if (!palette->entries) {
               fusion_object_destroy( &palette->object );
               return D_OOSHM();
          }

          palette->entries_yuv = SHCALLOC( palette->shmpool, size, sizeof(DFBColorYUV) );
          if (!palette->entries_yuv) {
               SHFREE( palette->shmpool, palette->entries );
               fusion_object_destroy( &palette->object );
               return D_OOSHM();
          }
     }

     palette->num_entries = size;

     /* reset cache */
     palette->search_cache.index = -1;

     D_MAGIC_SET( palette, CorePalette );

     /* activate object */
     fusion_object_activate( &palette->object );

     /* return the new palette */
     *ret_palette = palette;

     D_DEBUG_AT( Core_Palette, "  -> %p\n", palette );

     return DFB_OK;
}
Esempio n. 3
0
static DFBResult
system_initialize( CoreDFB *core, void **data )
{
     CoreScreen *core_screen;

     D_ASSERT( dfb_vnc == NULL );

     dfb_vnc = (DFBVNC*) SHCALLOC( dfb_core_shmpool(core), 1, sizeof(DFBVNC) );
     if (!dfb_vnc) {
          D_ERROR( "DirectFB/VNC: Couldn't allocate shared memory!\n" );
          return D_OOSHM();
     }

     dfb_vnc_core = core;

     fusion_skirmish_init( &dfb_vnc->lock, "VNC System", dfb_core_world(core) );

     fusion_call_init( &dfb_vnc->call, dfb_vnc_call_handler, NULL, dfb_core_world(core) );

     core_screen = dfb_screens_register( NULL, NULL, &vncPrimaryScreenFuncs );

     dfb_layers_register( core_screen, NULL, &vncPrimaryLayerFuncs );

     fusion_arena_add_shared_field( dfb_core_arena( core ), "vnc", dfb_vnc );

     *data = dfb_vnc;

     return DFB_OK;
}
Esempio n. 4
0
File: osx.c Progetto: ysei/uclinux-2
static DFBResult
system_initialize( CoreDFB *core, void **data )
{
     char       *driver;
     CoreScreen *screen;

     D_ASSERT( dfb_osx == NULL );

     dfb_osx = (DFBOSX*) SHCALLOC( dfb_core_shmpool(dfb_osx_core), 1, sizeof(DFBOSX) );
     if (!dfb_osx) {
          D_ERROR( "DirectFB/OSX: Couldn't allocate shared memory!\n" );
          return D_OOSHM();
     }

     dfb_osx_core = core;

     /* Initialize OSX */
     fusion_skirmish_init( &dfb_osx->lock, "OSX System", dfb_core_world(core) );

     fusion_call_init( &dfb_osx->call, dfb_osx_call_handler, NULL, dfb_core_world(core) );

     screen = dfb_screens_register( NULL, NULL, &osxPrimaryScreenFuncs );

     dfb_layers_register( screen, NULL, &osxPrimaryLayerFuncs );

     fusion_arena_add_shared_field( dfb_core_arena( core ), "OSX", dfb_osx );

     *data = dfb_osx;

     return DFB_OK;
}
Esempio n. 5
0
void
dfb_colorhash_attach( DFBColorHashCore *core,
                      CorePalette      *palette )
{
     DFBColorHashCoreShared *shared;

     D_ASSUME( core != NULL );

     if (core) {
          D_MAGIC_ASSERT( core, DFBColorHashCore );
          D_MAGIC_ASSERT( core->shared, DFBColorHashCoreShared );
     }
     else
          core = core_colorhash;

     shared = core->shared;

     fusion_skirmish_prevail( &shared->hash_lock );

     if (!shared->hash) {
          D_ASSERT( shared->hash_users == 0 );

          shared->hash = SHCALLOC( shared->shmpool, HASH_SIZE, sizeof (Colorhash) );
     }

     shared->hash_users++;

     fusion_skirmish_dismiss( &shared->hash_lock );
}
Esempio n. 6
0
/**
 * fusion_hash_insert:
 * @hash: a #FusionHash.
 * @key: a key to insert.
 * @value: the value to associate with the key.
 * 
 * Inserts a new key and value into a #FusionHash.
 * If the key already exists in the #FusionHash DFB_BUG is returned 
 * If you think a key may exist you should call fusion_hash_replace
 * Generally this is only used on a new FusionHash
 **/
DirectResult
fusion_hash_insert( FusionHash *hash,
                    void       *key,
                    void       *value )
{
     FusionHashNode **node;
     D_MAGIC_ASSERT( hash, FusionHash );

     node = fusion_hash_lookup_node (hash, key);

     if (*node) {
          D_BUG( "key already exists" );
          return DFB_BUG;
     }
     else {
          if (hash->local)
               (*node) = D_CALLOC(1,sizeof(FusionHashNode));
          else
               (*node) = SHCALLOC(hash->pool, 1, sizeof(FusionHashNode));
          if ( !(*node) )
               return hash->local?DFB_NOSYSTEMMEMORY:DFB_NOSHAREDMEMORY;

          (*node)->key = key;
          (*node)->value = value;
          hash->nnodes++;
          if ( fusion_hash_should_resize(hash) )
               fusion_hash_resize(hash);
     }
     return DFB_OK;
}
Esempio n. 7
0
static Chunk* split_chunk( Chunk *c, int length )
{
     Chunk *newchunk;

     D_MAGIC_ASSERT( c, _Chunk_ );

     if (c->length == length)          /* does not need be splitted */
          return c;

     newchunk = (Chunk*) SHCALLOC( 1, sizeof(Chunk) );

     /* calculate offsets and lengths of resulting chunks */
     newchunk->offset = c->offset + c->length - length;
     newchunk->length = length;
     c->length -= newchunk->length;

     /* insert newchunk after chunk c */
     newchunk->prev = c;
     newchunk->next = c->next;
     if (c->next)
          c->next->prev = newchunk;
     c->next = newchunk;

     D_MAGIC_SET( newchunk, _Chunk_ );

     return newchunk;
}
Esempio n. 8
0
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;
          }
          return ret;
     }

     fusion_skirmish_init2( &bridge->lock, bridge->desc.name, dfb_core_world(core), fusion_config->secure_fusion );

     return DFB_OK;
}
Esempio n. 9
0
static DFBResult
system_initialize( CoreDFB *core, void **ret_data )
{
     DFBResult            ret;
     MesaData            *mesa;
     MesaDataShared      *shared;
     FusionSHMPoolShared *pool;

     D_ASSERT( m_data == NULL );

     mesa = D_CALLOC( 1, sizeof(MesaData) );
     if (!mesa)
          return D_OOM();

     mesa->core = core;

     pool = dfb_core_shmpool( core );

     shared = SHCALLOC( pool, 1, sizeof(MesaDataShared) );
     if (!shared) {
          D_FREE( mesa );
          return D_OOSHM();
     }

     shared->shmpool = pool;

     mesa->shared = shared;

     m_data = mesa;
     
     if (dfb_config->vt) {
          ret = dfb_vt_initialize();
          if (ret) 
               return DFB_INIT;
     }

     ret = InitLocal( mesa );
     if (ret) {
          if (dfb_config->vt)
               dfb_vt_shutdown( false );

          return ret;
     }
     *ret_data = m_data;

     dfb_surface_pool_initialize( core, &mesaSurfacePoolFuncs, &shared->pool );

     mesa->screen = dfb_screens_register( NULL, mesa, mesaScreenFuncs );
     mesa->layer  = dfb_layers_register( mesa->screen, mesa, mesaLayerFuncs );


     core_arena_add_shared_field( core, "mesa", shared );

     return DFB_OK;
}
Esempio n. 10
0
static DFBResult
system_initialize( CoreDFB *core, void **ret_data )
{
     DFBResult            ret;
     DevMemData          *data;
     DevMemDataShared    *shared;
     FusionSHMPoolShared *pool;

     D_ASSERT( m_data == NULL );

     if (!dfb_config->video_phys || !dfb_config->video_length) {
          D_ERROR( "System/DevMem: Please supply 'video-phys = 0xXXXXXXXX' and 'video-length = XXXX' options!\n" );
          return DFB_INVARG;
     }

     if (dfb_config->mmio_phys && !dfb_config->mmio_length) {
          D_ERROR( "System/DevMem: Please supply both 'mmio-phys = 0xXXXXXXXX' and 'mmio-length = XXXX' options or none!\n" );
          return DFB_INVARG;
     }

     data = D_CALLOC( 1, sizeof(DevMemData) );
     if (!data)
          return D_OOM();

     pool = dfb_core_shmpool( core );

     shared = SHCALLOC( pool, 1, sizeof(DevMemDataShared) );
     if (!shared) {
          D_FREE( data );
          return D_OOSHM();
     }

     shared->shmpool = pool;

     data->shared = shared;

     ret = MapMemAndReg( data,
                         dfb_config->video_phys, dfb_config->video_length,
                         dfb_config->mmio_phys,  dfb_config->mmio_length );
     if (ret) {
          SHFREE( pool, shared );
          D_FREE( data );
          return ret;
     }


     *ret_data = m_data = data;

     dfb_surface_pool_initialize( core, &devmemSurfacePoolFuncs, &shared->pool );

     fusion_arena_add_shared_field( dfb_core_arena( core ), "devmem", shared );

     return DFB_OK;
}
Esempio n. 11
0
static DFBResult
system_initialize( CoreDFB *core, void **ret_data )
{
     DFBResult            ret;
     PVR2DData            *data;
     PVR2DDataShared      *shared;
     FusionSHMPoolShared *pool;

     D_ASSERT( m_data == NULL );

     data = D_CALLOC( 1, sizeof(PVR2DData) );
     if (!data)
          return D_OOM();

     data->core = core;

     pool = dfb_core_shmpool( core );

     shared = SHCALLOC( pool, 1, sizeof(PVR2DDataShared) );
     if (!shared) {
          D_FREE( data );
          return D_OOSHM();
     }

     shared->shmpool = pool;

     data->shared = shared;

     ret = InitPVR2D( data );
     if (ret) {
          SHFREE( pool, shared );
          D_FREE( data );
          return ret;
     }

     ret = InitEGL( data );
     if (ret) {
          SHFREE( pool, shared );
          D_FREE( data );
          return ret;
     }

     *ret_data = m_data = data;

     data->screen = dfb_screens_register( NULL, data, pvr2dPrimaryScreenFuncs );
     data->layer  = dfb_layers_register( data->screen, data, pvr2dPrimaryLayerFuncs );

     dfb_surface_pool_initialize( core, pvr2dSurfacePoolFuncs, &shared->pool );

     fusion_arena_add_shared_field( dfb_core_arena( core ), "pvr2d", shared );

     return DFB_OK;
}
Esempio n. 12
0
static int
dfb_core_arena_initialize( FusionArena *arena,
                           void        *ctx )
{
     DFBResult            ret;
     CoreDFB             *core = ctx;
     CoreDFBShared       *shared;
     FusionSHMPoolShared *pool;

     D_MAGIC_ASSERT( core, CoreDFB );

     D_DEBUG_AT( DirectFB_Core, "Initializing...\n" );

     /* Create the shared memory pool first! */
     ret = fusion_shm_pool_create( core->world, "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 );

     CoreDFB_Init_Dispatch( core, core, &shared->call );

     fusion_call_add_permissions( &shared->call, 0, FUSION_CALL_PERMIT_EXECUTE );

     /* Register shared data. */
     fusion_arena_add_shared_field( arena, "Core/Shared", shared );

     return DFB_OK;
}
Esempio n. 13
0
DFBResult
dfb_core_part_initialize( CoreDFB  *core,
                          CorePart *core_part )
{
     DFBResult            ret;
     void                *local  = NULL;
     void                *shared = NULL;
     FusionSHMPoolShared *pool;

     pool = dfb_core_shmpool( core );

     if (core_part->initialized) {
          D_BUG( "%s already initialized", core_part->name );
          return DFB_BUG;
     }

     D_DEBUG_AT( Core_Parts, "Going to initialize '%s' core...\n", core_part->name );

     if (core_part->size_local)
          local = D_CALLOC( 1, core_part->size_local );

     if (core_part->size_shared)
          shared = SHCALLOC( pool, 1, core_part->size_shared );
      
     D_INFO("Going to initialize '%s' core...\n", core_part->name );
     ret = core_part->Initialize( core, local, shared );
     D_INFO("Core '%s' initialized ...\n", core_part->name );

     if (ret) {
          D_ERROR( "DirectFB/Core: Could not initialize '%s' core!\n"
                    "    --> %s\n", core_part->name,
                    DirectFBErrorString( ret ) );

          if (shared)
               SHFREE( pool, shared );

          if (local)
               D_FREE( local );

          return ret;
     }

     if (shared)
          fusion_arena_add_shared_field( dfb_core_arena( core ),
                                         core_part->name, shared );

     core_part->data_local  = local;
     core_part->data_shared = shared;
     core_part->initialized = true;
     
     return DFB_OK;
}
Esempio n. 14
0
/**
 * hash_replace:
 * @hash: a #FusionHash.
 * @key: a key to insert.
 * @value: the value to associate with the key.
 * 
 * Inserts a new key and value into a #FusionHash similar to 
 * hash_insert(). The difference is that if the key already exists 
 * in the #FusionHash, it gets replaced by the new key. 
 * If you supplied a  oldkey pointer or oldkey value they are returned
 * otherwise free is called the key if table type is not type HASH_INT
 * and free is called on the old value if not supplied
 **/
DirectResult
fusion_hash_replace (FusionHash *hash,
                     void *   key, 
                     void *   value,
                     void **old_key,
                     void **old_value)
{
     FusionHashNode **node;
     D_MAGIC_ASSERT( hash, FusionHash );

     node = fusion_hash_lookup_node (hash, key);

     if (*node) {
          if ( old_key)
               *old_key = (*node)->key;
          else if ( hash->key_type != HASH_INT ) {
               if (hash->free_keys) {
                    if (hash->local)
                         D_FREE((*node)->key);
                    else
                         SHFREE(hash->pool, (*node)->key );
               }
          }

          if ( old_value)
               *old_value = (*node)->value;
          else if ( hash->value_type != HASH_INT ) {
               if (hash->free_values) {
                    if (hash->local)
                         D_FREE((*node)->value);
                    else
                         SHFREE(hash->pool, (*node)->value );
               }
          }
     }
     else {
          if (hash->local)
               *node = D_CALLOC(1, sizeof(FusionHashNode));
          else
               *node = SHCALLOC(hash->pool, 1, sizeof(FusionHashNode));

          if ( !(*node) )
               return hash->local?DFB_NOSYSTEMMEMORY:DFB_NOSHAREDMEMORY;

          hash->nnodes++;
     }
     (*node)->key = (void*)key;
     (*node)->value = (void*)value;

     return DFB_OK;
}
Esempio n. 15
0
SurfaceManager *
dfb_surfacemanager_create( unsigned int     length,
                           CardLimitations *limits )
{
     Chunk          *chunk;
     SurfaceManager *manager;

     manager = SHCALLOC( 1, sizeof(SurfaceManager) );
     if (!manager)
          return NULL;

     chunk = SHCALLOC( 1, sizeof(Chunk) );
     if (!chunk) {
          SHFREE( manager );
          return NULL;
     }

     chunk->offset = 0;
     chunk->length = length;

     manager->chunks           = chunk;
     manager->length           = length;
     manager->available        = length;
     manager->byteoffset_align = limits->surface_byteoffset_alignment;
     manager->pixelpitch_align = limits->surface_pixelpitch_alignment;
     manager->bytepitch_align  = limits->surface_bytepitch_alignment;
     manager->max_power_of_two_pixelpitch = limits->surface_max_power_of_two_pixelpitch;
     manager->max_power_of_two_bytepitch  = limits->surface_max_power_of_two_bytepitch;
     manager->max_power_of_two_height     = limits->surface_max_power_of_two_height;

     fusion_skirmish_init( &manager->lock, "Surface Manager" );

     D_MAGIC_SET( chunk, _Chunk_ );

     D_MAGIC_SET( manager, SurfaceManager );

     return manager;
}
Esempio n. 16
0
static DFBResult
system_initialize( CoreDFB *core, void **data )
{
     char       *driver;
     CoreScreen *screen;

     D_ASSERT( dfb_sdl == NULL );

     dfb_sdl = (DFBSDL*) SHCALLOC( dfb_core_shmpool(core), 1, sizeof(DFBSDL) );
     if (!dfb_sdl) {
          D_ERROR( "DirectFB/SDL: Couldn't allocate shared memory!\n" );
          return D_OOSHM();
     }

     dfb_sdl_core = core;

     dfb_fbdev_read_modes();  /* use same mode list as a fake */

     driver = getenv( "SDL_VIDEODRIVER" );
     if (driver && !strcasecmp( driver, "directfb" )) {
          D_INFO( "DirectFB/SDL: SDL_VIDEODRIVER is 'directfb', unsetting it.\n" );
          unsetenv( "SDL_VIDEODRIVER" );
     }

     /* Initialize SDL */
     if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
          D_ERROR( "DirectFB/SDL: Couldn't initialize SDL: %s\n", SDL_GetError() );

          SHFREE( dfb_core_shmpool(core), dfb_sdl );
          dfb_sdl = NULL;

          return DFB_INIT;
     }

     fusion_skirmish_init( &dfb_sdl->lock, "SDL System", dfb_core_world(core) );

     fusion_call_init( &dfb_sdl->call, dfb_sdl_call_handler, NULL, dfb_core_world(core) );

     screen = dfb_screens_register( NULL, NULL, sdlPrimaryScreenFuncs );

     dfb_layers_register( screen, NULL, sdlPrimaryLayerFuncs );

     fusion_arena_add_shared_field( dfb_core_arena( core ), "sdl", dfb_sdl );

     dfb_surface_pool_initialize( core, &sdlSurfacePoolFuncs, &dfb_sdl->sdl_pool );

     *data = dfb_sdl;

     return DFB_OK;
}
Esempio n. 17
0
/* Hash Functions
 * Resize the hash to minumim for this number of entries
 */
DirectResult
fusion_hash_resize (FusionHash *hash)
{
     FusionHashNode **new_nodes;
     FusionHashNode *node;
     FusionHashNode *next;
     unsigned int hash_val;
     int new_size;
     int i;
     D_MAGIC_ASSERT( hash, FusionHash );

     new_size = spaced_primes_closest (hash->nnodes);
     if (new_size > FUSION_HASH_MAX_SIZE )
          new_size = FUSION_HASH_MAX_SIZE;
     if (new_size <  FUSION_HASH_MIN_SIZE)
          new_size = FUSION_HASH_MIN_SIZE;

     if (hash->local)
          new_nodes = D_CALLOC (new_size, sizeof(FusionHashNode*));
     else
          new_nodes = SHCALLOC (hash->pool, new_size, sizeof(FusionHashNode*));
     if (!new_nodes)
          return hash->local?DFB_NOSYSTEMMEMORY:DFB_NOSHAREDMEMORY;

     for (i = 0; i < hash->size; i++)
          for (node = hash->nodes[i]; node; node = next) {
               next = node->next;
               /*TODO We could also optimize pointer hashing*/
               if (hash->key_type == HASH_STRING ) {
                    unsigned int h;
                    const signed char *p = node->key;
                    HASH_STR(h, p)
                    hash_val = h % new_size;
               }
               else
                    hash_val = ((unsigned long)node->key) % new_size;

               node->next = new_nodes[hash_val];
               new_nodes[hash_val] = node;
          }
     if (hash->local)
          D_FREE(hash->nodes);
     else
          SHFREE(hash->pool, hash->nodes);
     hash->nodes = new_nodes;
     hash->size = new_size;
     return true;
}
Esempio n. 18
0
static DFBResult
system_initialize( CoreDFB *core, void **ret_data )
{
     DFBResult            ret;
     AndroidData         *android;
     AndroidDataShared   *shared;
     FusionSHMPoolShared *pool;

     D_ASSERT( m_data == NULL );

     android = D_CALLOC( 1, sizeof(AndroidData) );
     if (!android)
          return D_OOM();

     android->core = core;

     pool = dfb_core_shmpool( core );

     shared = SHCALLOC( pool, 1, sizeof(AndroidDataShared) );
     if (!shared) {
          D_FREE( android );
          return D_OOSHM();
     }

     shared->shmpool = pool;

     android->shared = shared;

     m_data = android;

     ret = InitLocal( android );
     if (ret)
          return ret;

     *ret_data = m_data;

     dfb_surface_pool_initialize( core, &androidSurfacePoolFuncs, &shared->pool );

     android->screen   = dfb_screens_register( NULL, android, androidScreenFuncs );
     android->layer    = dfb_layers_register( android->screen, android, androidLayerFuncs );
     android->java_vm  = native_data.app->activity->vm;
     android->app_path = D_STRDUP( native_data.app->activity->internalDataPath) ;

     core_arena_add_shared_field( core, "android", shared );

     return DFB_OK;
}
Esempio n. 19
0
static DFBResult
x11Lock( CoreSurfacePool       *pool,
         void                  *pool_data,
         void                  *pool_local,
         CoreSurfaceAllocation *allocation,
         void                  *alloc_data,
         CoreSurfaceBufferLock *lock )
{
     DFBResult          ret;
     x11PoolLocalData  *local  = pool_local;
     x11AllocationData *alloc  = alloc_data;
     DFBX11            *x11    = local->x11;
     DFBX11Shared      *shared = x11->shared;
     CoreSurfaceBuffer *buffer;
     CoreSurface       *surface;

     D_DEBUG_AT( X11_Surfaces, "%s( %p )\n", __FUNCTION__, allocation );

     D_MAGIC_ASSERT( pool, CoreSurfacePool );
     D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );
     D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock );

     buffer = allocation->buffer;
     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );

     surface = buffer->surface;
     D_MAGIC_ASSERT( surface, CoreSurface );

     D_ASSERT( local->hash != NULL );

     pthread_mutex_lock( &local->lock );

      if (!alloc->ptr) {
           alloc->ptr = SHCALLOC( shared->data_shmpool, 1, allocation->size );
           if (!alloc->ptr)
                return D_OOSHM();
      }

      lock->addr = alloc->ptr;

     lock->pitch = alloc->pitch;

     pthread_mutex_unlock( &local->lock );

     return DFB_OK;
}
Esempio n. 20
0
static DFBResult
allocate_transfer( CoreSurfacePoolBridge    *bridge,
                   CoreSurfaceBuffer        *buffer,
                   CoreSurfaceAllocation    *from,
                   CoreSurfaceAllocation    *to,
                   const DFBRectangle       *rects,
                   unsigned int              num_rects,
                   CoreSurfacePoolTransfer **ret_transfer )
{
     CoreSurfacePoolTransfer *transfer;
     unsigned int             alloc_size;

     D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge );
     D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );
     CORE_SURFACE_ALLOCATION_ASSERT( from );
     CORE_SURFACE_ALLOCATION_ASSERT( to );
     D_ASSERT( rects != NULL );
     D_ASSERT( num_rects > 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;
}
Esempio n. 21
0
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_funcs[bridge->bridge_id] = NULL;
          bridge_array[bridge->bridge_id] = NULL;
          bridge_count--;
          D_MAGIC_CLEAR( bridge );
          SHFREE( shmpool, bridge );
          return ret;
     }

     /* Insert new bridge into priority order */
     insert_bridge_local( bridge );

     /* Return the new bridge. */
     *ret_bridge = bridge;

     return DFB_OK;
}
Esempio n. 22
0
static DFBResult
system_initialize( CoreDFB *core, void **data )
{
     DFBResult     ret;
     DFBX11       *x11;
     DFBX11Shared *shared;

     D_DEBUG_AT( X11_Core, "%s()\n", __FUNCTION__ );

     x11 = D_CALLOC( 1, sizeof(DFBX11) );
     if (!x11)
          return D_OOM();

     shared = SHCALLOC( dfb_core_shmpool( core ), 1, sizeof(DFBX11Shared) );
     if (!shared) {
          D_FREE( x11 );
          return D_OOSHM();
     }

     /* we need the error handler to signal the error to us, so
        use a global static */
     shared_for_error_handler = shared;
     XSetErrorHandler( error_handler );

     /*
      * Local init (master and slave)
      */
     ret = InitLocal( x11, shared, core );
     if (ret) {
          SHFREE( dfb_core_shmpool( core ), shared );
          D_FREE( x11 );
          return ret;
     }


     /*
      * Shared init (master only)
      */
     shared->data_shmpool = dfb_core_shmpool_data( core );

     shared->screen_size.w = x11->screenptr->width;
     shared->screen_size.h = x11->screenptr->height;

     fusion_skirmish_init( &shared->lock, "X11 System", dfb_core_world(core) );

     fusion_call_init( &shared->call, call_handler, x11, dfb_core_world(core) );


     /*
      * Must be set before initializing the pools!
      */
     *data = x11;


     /*
      * Master init
      */
     dfb_surface_pool_initialize( core, &x11SurfacePoolFuncs, &shared->x11image_pool );

#ifdef USE_GLX
     dfb_surface_pool_initialize( core, &glxSurfacePoolFuncs, &shared->glx_pool );
#endif

     if (dfb_config->video_length) {
          shared->vpsmem_length = dfb_config->video_length;

          dfb_surface_pool_initialize( core, &vpsmemSurfacePoolFuncs, &shared->vpsmem_pool );
     }

#ifdef USE_GLX
     dfb_surface_pool_bridge_initialize( core, &x11SurfacePoolBridgeFuncs, x11, &shared->x11_pool_bridge );
#endif

     fusion_arena_add_shared_field( dfb_core_arena( core ), "x11", shared );

     return DFB_OK;
}
static DFBResult
x11Lock( CoreSurfacePool       *pool,
         void                  *pool_data,
         void                  *pool_local,
         CoreSurfaceAllocation *allocation,
         void                  *alloc_data,
         CoreSurfaceBufferLock *lock )
{
     DFBResult          ret;
     x11PoolLocalData  *local  = pool_local;
     x11AllocationData *alloc  = alloc_data;
     DFBX11            *x11    = local->x11;
     DFBX11Shared      *shared = x11->shared;

     D_DEBUG_AT( X11_Surfaces, "%s( %p )\n", __FUNCTION__, allocation );

     D_MAGIC_ASSERT( pool, CoreSurfacePool );
     D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );
     D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock );

     D_ASSERT( local->hash != NULL );

     pthread_mutex_lock( &local->lock );

     if (alloc->real) {
          void *addr = direct_hash_lookup( local->hash, alloc->image.seginfo.shmid );

          if (!addr) {
               ret = x11ImageAttach( &alloc->image, &addr );
               if (ret) {
                    D_DERROR( ret, "X11/Surfaces: x11ImageAttach() failed!\n" );
                    pthread_mutex_unlock( &local->lock );
                    return ret;
               }

               direct_hash_insert( local->hash, alloc->image.seginfo.shmid, addr );

               /* FIXME: When to remove/detach? */
          }

          lock->addr   = addr;
          lock->handle = &alloc->image;
     }
     else {
          if (!alloc->ptr) {
               D_DEBUG_AT( X11_Surfaces, "  -> allocating memory in data_shmpool (%d bytes)\n", allocation->size );

               alloc->ptr = SHCALLOC( shared->data_shmpool, 1, allocation->size );
               if (!alloc->ptr) {
                    pthread_mutex_unlock( &local->lock );
                    return D_OOSHM();
               }
          }

          lock->addr = alloc->ptr;
     }

     lock->pitch = alloc->pitch;

     pthread_mutex_unlock( &local->lock );

     return DFB_OK;
}
Esempio n. 24
0
/*
 * parses video modes in /etc/fb.modes and stores them in dfb_fbdev->shared->modes
 * (to be replaced by DirectFB's own config system
 */
static DFBResult dfb_fbdev_read_modes( void )
{
     FILE *fp;
     char line[80],label[32],value[16];
     int geometry=0, timings=0;
     int dummy;
     VideoMode temp_mode;
     VideoMode *m = dfb_sdl->modes;

     if (!(fp = fopen("/etc/fb.modes","r")))
          return errno2result( errno );

     while (fgets(line,79,fp)) {
          if (sscanf(line, "mode \"%31[^\"]\"",label) == 1) {
               memset( &temp_mode, 0, sizeof(VideoMode) );
               geometry = 0;
               timings = 0;
               while (fgets(line,79,fp) && !(strstr(line,"endmode"))) {
                    if (5 == sscanf(line," geometry %d %d %d %d %d", &temp_mode.xres, &temp_mode.yres, &dummy, &dummy, &temp_mode.bpp)) {
                         geometry = 1;
                    }
                    else if (7 == sscanf(line," timings %d %d %d %d %d %d %d", &temp_mode.pixclock, &temp_mode.left_margin,  &temp_mode.right_margin,
                                         &temp_mode.upper_margin, &temp_mode.lower_margin, &temp_mode.hsync_len,    &temp_mode.vsync_len)) {
                         timings = 1;
                    }
                    else if (1 == sscanf(line, " hsync %15s",value) && 0 == strcasecmp(value,"high")) {
                         temp_mode.hsync_high = 1;
                    }
                    else if (1 == sscanf(line, " vsync %15s",value) && 0 == strcasecmp(value,"high")) {
                         temp_mode.vsync_high = 1;
                    }
                    else if (1 == sscanf(line, " csync %15s",value) && 0 == strcasecmp(value,"high")) {
                         temp_mode.csync_high = 1;
                    }
                    else if (1 == sscanf(line, " laced %15s",value) && 0 == strcasecmp(value,"true")) {
                         temp_mode.laced = 1;
                    }
                    else if (1 == sscanf(line, " double %15s",value) && 0 == strcasecmp(value,"true")) {
                         temp_mode.doubled = 1;
                    }
                    else if (1 == sscanf(line, " gsync %15s",value) && 0 == strcasecmp(value,"true")) {
                         temp_mode.sync_on_green = 1;
                    }
                    else if (1 == sscanf(line, " extsync %15s",value) && 0 == strcasecmp(value,"true")) {
                         temp_mode.external_sync = 1;
                    }
                    else if (1 == sscanf(line, " bcast %15s",value) && 0 == strcasecmp(value,"true")) {
                         temp_mode.broadcast = 1;
                    }
               }
               if (geometry && timings) {
                    if (!m) {
                         dfb_sdl->modes = SHCALLOC( dfb_core_shmpool(dfb_sdl_core), 1, sizeof(VideoMode) );
                         m = dfb_sdl->modes;
                    }
                    else {
                         m->next = SHCALLOC( dfb_core_shmpool(dfb_sdl_core), 1, sizeof(VideoMode) );
                         m = m->next;
                    }
                    direct_memcpy (m, &temp_mode, sizeof(VideoMode));
                    D_DEBUG( "DirectFB/FBDev: %20s %4dx%4d  %s%s\n", label, temp_mode.xres, temp_mode.yres,
                              temp_mode.laced ? "interlaced " : "", temp_mode.doubled ? "doublescan" : "" );
               }
          }
     }

     fclose (fp);

     return DFB_OK;
}
Esempio n. 25
0
DFBResult
dfb_surface_create( CoreDFB                  *core,
                    const CoreSurfaceConfig  *config,
                    CoreSurfaceTypeFlags      type,
                    unsigned long             resource_id,
                    CorePalette              *palette,
                    CoreSurface             **ret_surface )
{
     DFBResult    ret = DFB_BUG;
     int          i, data_size;
     int          buffers;
     CoreSurface *surface;
     char         buf[64];

     D_ASSERT( core != NULL );
     D_FLAGS_ASSERT( type, CSTF_ALL );
     D_MAGIC_ASSERT_IF( palette, CorePalette );
     D_ASSERT( ret_surface != NULL );

     D_DEBUG_AT( Core_Surface, "dfb_surface_create( %p, %p, %p )\n", core, config, ret_surface );

     surface = dfb_core_create_surface( core );
     if (!surface)
          return DFB_FUSION;

     surface->data = NULL;

     if (config) {
          D_FLAGS_ASSERT( config->flags, CSCONF_ALL );

          surface->config.flags = config->flags;

          if (config->flags & CSCONF_SIZE) {
               D_DEBUG_AT( Core_Surface, "  -> %dx%d\n", config->size.w, config->size.h );

               surface->config.size = config->size;
          }

          if (config->flags & CSCONF_FORMAT) {
               D_DEBUG_AT( Core_Surface, "  -> %s\n", dfb_pixelformat_name( config->format ) );

               surface->config.format = config->format;
          }

          if (config->flags & CSCONF_CAPS) {
               D_DEBUG_AT( Core_Surface, "  -> caps 0x%08x\n", config->caps );

               if (config->caps & DSCAPS_ROTATED)
                    D_UNIMPLEMENTED();

               surface->config.caps = config->caps & ~DSCAPS_ROTATED;
          }

          if (config->flags & CSCONF_PREALLOCATED) {
               D_DEBUG_AT( Core_Surface, "  -> prealloc %p [%d]\n",
                           config->preallocated[0].addr,
                           config->preallocated[0].pitch );

               direct_memcpy( surface->config.preallocated, config->preallocated, sizeof(config->preallocated) );

               surface->config.preallocated_pool_id = config->preallocated_pool_id;

               type |= CSTF_PREALLOCATED;
          }
     }

     if (surface->config.caps & DSCAPS_SYSTEMONLY)
          surface->type = (type & ~CSTF_EXTERNAL) | CSTF_INTERNAL;
     else if (surface->config.caps & DSCAPS_VIDEOONLY)
          surface->type = (type & ~CSTF_INTERNAL) | CSTF_EXTERNAL;
     else
          surface->type = type & ~(CSTF_INTERNAL | CSTF_EXTERNAL);

     if (surface->config.caps & DSCAPS_SHARED)
          surface->type |= CSTF_SHARED;

     surface->resource_id = resource_id;

     if (surface->config.caps & DSCAPS_TRIPLE)
          buffers = 3;
     else if (surface->config.caps & DSCAPS_DOUBLE)
          buffers = 2;
     else {
          buffers = 1;

          surface->config.caps &= ~DSCAPS_ROTATED;
     }

     surface->notifications = CSNF_ALL & ~CSNF_FLIP;

     surface->alpha_ramp[0] = 0x00;
     surface->alpha_ramp[1] = 0x55;
     surface->alpha_ramp[2] = 0xaa;
     surface->alpha_ramp[3] = 0xff;


     if (surface->config.caps & DSCAPS_STATIC_ALLOC)
          surface->config.min_size = surface->config.size;

     surface->shmpool = dfb_core_shmpool( core );

     direct_serial_init( &surface->serial );

     snprintf( buf, sizeof(buf), "Surface %dx%d %s", surface->config.size.w,
               surface->config.size.h, dfb_pixelformat_name(surface->config.format) );

     fusion_ref_set_name( &surface->object.ref, buf );

     fusion_skirmish_init2( &surface->lock, buf, dfb_core_world(core), fusion_config->secure_fusion );

//     fusion_skirmish_add_permissions( &surface->lock, 0, FUSION_SKIRMISH_PERMIT_PREVAIL | FUSION_SKIRMISH_PERMIT_DISMISS );

     D_MAGIC_SET( surface, CoreSurface );


     if (dfb_config->warn.flags & DCWF_CREATE_SURFACE &&
         dfb_config->warn.create_surface.min_size.w <= surface->config.size.w &&
         dfb_config->warn.create_surface.min_size.h <= surface->config.size.h)
          D_WARN( "create-surface  %4dx%4d %6s, buffers %d, caps 0x%08x, type 0x%08x",
                  surface->config.size.w, surface->config.size.h, dfb_pixelformat_name(surface->config.format),
                  buffers, surface->config.caps, surface->type );


     if (palette) {
          dfb_surface_set_palette( surface, palette );
     }
     else if (DFB_PIXELFORMAT_IS_INDEXED( surface->config.format )) {
          ret = dfb_surface_init_palette( core, surface );
          if (ret)
               goto error;
     }

     /* Create the system driver specific surface data information */
     data_size = dfb_system_surface_data_size();

     if (data_size) {
          surface->data = SHCALLOC( surface->shmpool, 1, data_size );
          if (!surface->data) {
              ret = D_OOSHM();
              goto error;
          }
     }

     dfb_system_surface_data_init(surface,surface->data);

     dfb_surface_lock( surface );

     /* Create the Surface Buffers. */
     for (i=0; i<buffers; i++) {
          ret = dfb_surface_buffer_create( core, surface, CSBF_NONE, &surface->buffers[i] );
          if (ret) {
               D_DERROR( ret, "Core/Surface: Error creating surface buffer!\n" );
               goto error;
          }

          surface->num_buffers++;

          dfb_surface_buffer_globalize( surface->buffers[i] );

          switch (i) {
               case 0:
                    surface->buffer_indices[CSBR_FRONT] = i;
               case 1:
                    surface->buffer_indices[CSBR_BACK] = i;
               case 2:
                    surface->buffer_indices[CSBR_IDLE] = i;
          }
     }

     dfb_surface_unlock( surface );


     CoreSurface_Init_Dispatch( core, surface, &surface->call );

     fusion_object_activate( &surface->object );

     *ret_surface = surface;

     return DFB_OK;

error:
     for (i=0; i<MAX_SURFACE_BUFFERS; i++) {
          if (surface->buffers[i])
               dfb_surface_buffer_decouple( surface->buffers[i] );
     }

     /* release the system driver specific surface data */
     if (surface->data) {
         dfb_system_surface_data_destroy( surface, surface->data );
         SHFREE( surface->shmpool, surface->data );
         surface->data = NULL;
     }

     fusion_skirmish_destroy( &surface->lock );

     direct_serial_deinit( &surface->serial );

     D_MAGIC_CLEAR( surface );

     fusion_object_destroy( &surface->object );

     return ret;
}
Esempio n. 26
0
static DFBResult
system_initialize( CoreDFB *core, void **data )
{
     int         i, n;
     CoreScreen *screen;

     D_ASSERT( dfb_x11 == NULL );

     dfb_x11 = (DFBX11*) SHCALLOC( dfb_core_shmpool(core), 1, sizeof(DFBX11) );
     if (!dfb_x11) {
          D_ERROR( "DirectFB/X11: Couldn't allocate shared memory!\n" );
          return D_OOSHM();
     }

     dfb_x11_core = core;

     fusion_skirmish_init( &dfb_x11->lock, "X11 System", dfb_core_world(core) );

     fusion_call_init( &dfb_x11->call, call_handler, NULL, dfb_core_world(core) );

     dfb_surface_pool_initialize( core, &x11SurfacePoolFuncs, &dfb_x11->surface_pool );

     screen = dfb_screens_register( NULL, NULL, &x11PrimaryScreenFuncs );

     dfb_layers_register( screen, NULL, &x11PrimaryLayerFuncs );

     fusion_arena_add_shared_field( dfb_core_arena( core ), "x11", dfb_x11 );

     *data = dfb_x11;

     XInitThreads();

     dfb_x11->data_shmpool = dfb_core_shmpool_data( core );

     dfb_x11->display = XOpenDisplay(getenv("DISPLAY"));
     if (!dfb_x11->display) {
          D_ERROR("X11: Error in XOpenDisplay for '%s'\n", getenv("DISPLAY"));
          return DFB_INIT;
     }

     dfb_x11->screenptr = DefaultScreenOfDisplay(dfb_x11->display);
     dfb_x11->screennum = DefaultScreen(dfb_x11->display);

     for (i=0; i<dfb_x11->screenptr->ndepths; i++) {
          const Depth *depth = &dfb_x11->screenptr->depths[i];

          for (n=0; n<depth->nvisuals; n++) {
               Visual *visual = &depth->visuals[n];

               D_DEBUG( "X11/Visual: ID %02lu, depth %d, red 0x%06lx, green 0x%06lx, blue 0x%06lx, %d bits/rgb, %d entries\n",
                        visual->visualid, depth->depth,
                        visual->red_mask, visual->green_mask, visual->blue_mask,
                        visual->bits_per_rgb, visual->map_entries );

               switch (depth->depth) {
                    case 24:
                         if (visual->red_mask   == 0xff0000 &&
                             visual->green_mask == 0x00ff00 &&
                             visual->blue_mask  == 0x0000ff) {
                              dfb_x11->visuals[DFB_PIXELFORMAT_INDEX(DSPF_RGB32)] = visual;
                              dfb_x11->visuals[DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]  = visual;
                         }
                         break;

                    case 16:
                         if (visual->red_mask   == 0xf800 &&
                             visual->green_mask == 0x07e0 &&
                             visual->blue_mask  == 0x001f)
                              dfb_x11->visuals[DFB_PIXELFORMAT_INDEX(DSPF_RGB16)] = visual;
                         break;

                    case 15:
                         if (visual->red_mask   == 0x7c00 &&
                             visual->green_mask == 0x03e0 &&
                             visual->blue_mask  == 0x001f)
                              dfb_x11->visuals[DFB_PIXELFORMAT_INDEX(DSPF_RGB555)] = visual;
                         break;
               }
          }
     }

     return DFB_OK;
}
Esempio n. 27
0
static DFBResult
realize_region( CoreLayerRegion *region )
{
     DFBResult          ret;
     CoreLayer         *layer;
     CoreLayerShared   *shared;
     DisplayLayerFuncs *funcs;

     D_ASSERT( region != NULL );
     D_ASSERT( region->context != NULL );
     D_ASSERT( D_FLAGS_IS_SET( region->state, CLRSF_CONFIGURED ) );
     D_ASSERT( ! D_FLAGS_IS_SET( region->state, CLRSF_REALIZED ) );

     layer = dfb_layer_at( region->context->layer_id );

     D_ASSERT( layer != NULL );
     D_ASSERT( layer->shared != NULL );
     D_ASSERT( layer->funcs != NULL );

     shared = layer->shared;
     funcs  = layer->funcs;

     D_ASSERT( ! fusion_vector_contains( &shared->added_regions, region ) );

     /* Allocate the driver's region data. */
     if (funcs->RegionDataSize) {
          int size = funcs->RegionDataSize();

          if (size > 0) {
               region->region_data = SHCALLOC( 1, size );
               if (!region->region_data)
                    return D_OOSHM();
          }
     }

     D_DEBUG_AT( Core_Layers, "Adding region (%d, %d - %dx%d) to '%s'.\n",
                 DFB_RECTANGLE_VALS( &region->config.dest ), shared->description.name );

     /* Add the region to the driver. */
     if (funcs->AddRegion) {
          ret = funcs->AddRegion( layer,
                                  layer->driver_data, layer->layer_data,
                                  region->region_data, &region->config );
          if (ret) {
               D_DERROR( ret, "Core/Layers: Could not add region!\n" );

               if (region->region_data) {
                    SHFREE( region->region_data );
                    region->region_data = NULL;
               }

               return ret;
          }
     }

     /* Add the region to the 'added' list. */
     fusion_vector_add( &shared->added_regions, region );

     /* Update the region's state. */
     D_FLAGS_SET( region->state, CLRSF_REALIZED );

     /* Initially setup hardware. */
     ret = set_region( region, &region->config, CLRCF_ALL, region->surface );
     if (ret) {
          unrealize_region( region );
          return ret;
     }

     return DFB_OK;
}