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/screens.c | 591 +++++++++++++++++++++++++++++++++++++ 1 file changed, 591 insertions(+) create mode 100755 Source/DirectFB/src/core/screens.c (limited to 'Source/DirectFB/src/core/screens.c') diff --git a/Source/DirectFB/src/core/screens.c b/Source/DirectFB/src/core/screens.c new file mode 100755 index 0000000..708f5e8 --- /dev/null +++ b/Source/DirectFB/src/core/screens.c @@ -0,0 +1,591 @@ +/* + (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 + + +D_DEBUG_DOMAIN( Core_Screen, "Core/Screen", "DirectFB Screen Core" ); + +/**********************************************************************************************************************/ + +typedef struct { + int magic; + + + int num; + CoreScreenShared *screens[MAX_SCREENS]; +} DFBScreenCoreShared; + +struct __DFB_DFBScreenCore { + int magic; + + CoreDFB *core; + + DFBScreenCoreShared *shared; +}; + + +DFB_CORE_PART( screen_core, ScreenCore ); + +/**********************************************************************************************************************/ + +static DFBScreenCoreShared *core_screens = NULL; /* FIXME */ + +static int num_screens = 0; /* FIXME */ +static CoreScreen *screens[MAX_SCREENS] = { NULL }; /* FIXME */ + + +static DFBResult +dfb_screen_core_initialize( CoreDFB *core, + DFBScreenCore *data, + DFBScreenCoreShared *shared ) +{ + int i; + DFBResult ret; + FusionSHMPoolShared *pool; + + D_DEBUG_AT( Core_Screen, "dfb_screen_core_initialize( %p, %p, %p )\n", core, data, shared ); + + D_ASSERT( data != NULL ); + D_ASSERT( shared != NULL ); + + data->core = core; + data->shared = shared; + + core_screens = shared; /* FIXME */ + + pool = dfb_core_shmpool( core ); + + /* Initialize all registered screens. */ + for (i=0; ifuncs; + DFBScreenDescription desc = { .caps = DSCCAPS_NONE }; + + /* Allocate shared data. */ + sshared = SHCALLOC( pool, 1, sizeof(CoreScreenShared) ); + + /* Assign ID (zero based index). */ + sshared->screen_id = i; + + snprintf( buf, sizeof(buf), "Screen %d", i ); + + /* Initialize the lock. */ + if (fusion_skirmish_init( &sshared->lock, buf, dfb_core_world(core) )) { + SHFREE( pool, sshared ); + return DFB_FUSION; + } + + /* Allocate driver's screen data. */ + if (funcs->ScreenDataSize) { + int size = funcs->ScreenDataSize(); + + if (size > 0) { + sshared->screen_data = SHCALLOC( pool, 1, size ); + if (!sshared->screen_data) { + fusion_skirmish_destroy( &sshared->lock ); + SHFREE( pool, sshared ); + return D_OOSHM(); + } + } + } + + /* Initialize the screen and get the screen description. */ + ret = funcs->InitScreen( screen, + screen->device, + screen->driver_data, + sshared->screen_data, + &desc ); + if (ret) { + D_ERROR("DirectFB/Core/screens: " + "Failed to initialize screen %d!\n", sshared->screen_id); + + fusion_skirmish_destroy( &sshared->lock ); + + if (sshared->screen_data) + SHFREE( pool, sshared->screen_data ); + + SHFREE( pool, sshared ); + + return ret; + } + + D_ASSUME( desc.mixers > 0 || !(desc.caps & DSCCAPS_MIXERS) ); + D_ASSUME( desc.mixers == 0 || (desc.caps & DSCCAPS_MIXERS) ); + + D_ASSUME( desc.encoders > 0 || !(desc.caps & DSCCAPS_ENCODERS) ); + D_ASSUME( desc.encoders == 0 || (desc.caps & DSCCAPS_ENCODERS) ); + + D_ASSUME( desc.outputs > 0 || !(desc.caps & DSCCAPS_OUTPUTS) ); + D_ASSUME( desc.outputs == 0 || (desc.caps & DSCCAPS_OUTPUTS) ); + + D_ASSERT( desc.mixers >= 0 ); + D_ASSERT( desc.mixers <= 32 ); + D_ASSERT( desc.encoders >= 0 ); + D_ASSERT( desc.encoders <= 32 ); + D_ASSERT( desc.outputs >= 0 ); + D_ASSERT( desc.outputs <= 32 ); + + /* Store description in sshared memory. */ + sshared->description = desc; + + /* Initialize mixers. */ + if (sshared->description.mixers) { + int i; + + D_ASSERT( funcs->InitMixer != NULL ); + D_ASSERT( funcs->SetMixerConfig != NULL ); + + sshared->mixers = SHCALLOC( pool, sshared->description.mixers, + sizeof(CoreScreenMixer) ); + for (i=0; idescription.mixers; i++) { + funcs->InitMixer( screen, + screen->driver_data, + sshared->screen_data, i, + &sshared->mixers[i].description, + &sshared->mixers[i].configuration ); + funcs->SetMixerConfig( screen, + screen->driver_data, + sshared->screen_data, i, + &sshared->mixers[i].configuration ); + } + } + + /* Initialize encoders. */ + if (sshared->description.encoders) { + int i; + + D_ASSERT( funcs->InitEncoder != NULL ); + D_ASSERT( funcs->SetEncoderConfig != NULL ); + + sshared->encoders = SHCALLOC( pool, sshared->description.encoders, + sizeof(CoreScreenEncoder) ); + for (i=0; idescription.encoders; i++) { + funcs->InitEncoder( screen, + screen->driver_data, + sshared->screen_data, i, + &sshared->encoders[i].description, + &sshared->encoders[i].configuration ); + funcs->SetEncoderConfig( screen, + screen->driver_data, + sshared->screen_data, i, + &sshared->encoders[i].configuration ); + } + } + + /* Initialize outputs. */ + if (sshared->description.outputs) { + int i; + + D_ASSERT( funcs->InitOutput != NULL ); + D_ASSERT( funcs->SetOutputConfig != NULL ); + + sshared->outputs = SHCALLOC( pool, sshared->description.outputs, + sizeof(CoreScreenOutput) ); + for (i=0; idescription.outputs; i++) { + funcs->InitOutput( screen, + screen->driver_data, + sshared->screen_data, i, + &sshared->outputs[i].description, + &sshared->outputs[i].configuration ); + funcs->SetOutputConfig( screen, + screen->driver_data, + sshared->screen_data, i, + &sshared->outputs[i].configuration ); + } + } + + /* Make a copy for faster access. */ + screen->screen_data = sshared->screen_data; + + /* Store pointer to sshared data and core. */ + screen->shared = sshared; + screen->core = core; + + /* Add the screen to the sshared list. */ + core_screens->screens[ core_screens->num++ ] = sshared; + } + + + D_MAGIC_SET( data, DFBScreenCore ); + D_MAGIC_SET( shared, DFBScreenCoreShared ); + + return DFB_OK; +} + +static DFBResult +dfb_screen_core_join( CoreDFB *core, + DFBScreenCore *data, + DFBScreenCoreShared *shared ) +{ + int i; + + D_DEBUG_AT( Core_Screen, "dfb_screen_core_join( %p, %p, %p )\n", core, data, shared ); + + D_ASSERT( data != NULL ); + D_MAGIC_ASSERT( shared, DFBScreenCoreShared ); + + data->core = core; + data->shared = shared; + + core_screens = shared; /* FIXME */ + + if (num_screens != core_screens->num) { + D_ERROR("DirectFB/core/screens: Number of screens does not match!\n"); + return DFB_BUG; + } + + for (i=0; iscreens[i]; + + /* Make a copy for faster access. */ + screen->screen_data = shared->screen_data; + + /* Store pointer to shared data and core. */ + screen->shared = shared; + screen->core = core; + } + + + D_MAGIC_SET( data, DFBScreenCore ); + + return DFB_OK; +} + +static DFBResult +dfb_screen_core_shutdown( DFBScreenCore *data, + bool emergency ) +{ + int i; + FusionSHMPoolShared *pool; + DFBScreenCoreShared *shared; + + D_DEBUG_AT( Core_Screen, "dfb_screen_core_shutdown( %p, %semergency )\n", data, emergency ? "" : "no " ); + + D_MAGIC_ASSERT( data, DFBScreenCore ); + D_MAGIC_ASSERT( data->shared, DFBScreenCoreShared ); + + shared = data->shared; + + pool = dfb_core_shmpool( data->core ); + + /* Begin with the most recently added screen. */ + for (i=num_screens-1; i>=0; i--) { + CoreScreen *screen = screens[i]; + CoreScreenShared *shared = screen->shared; + + /* Deinitialize the lock. */ + fusion_skirmish_destroy( &shared->lock ); + + /* Free the driver's screen data. */ + if (shared->screen_data) + SHFREE( pool, shared->screen_data ); + + /* Free mixer data. */ + if (shared->mixers) + SHFREE( pool, shared->mixers ); + + /* Free encoder data. */ + if (shared->encoders) + SHFREE( pool, shared->encoders ); + + /* Free output data. */ + if (shared->outputs) + SHFREE( pool, shared->outputs ); + + /* Free the shared screen data. */ + SHFREE( pool, shared ); + + /* Free the local screen data. */ + D_FREE( screen ); + } + + core_screens = NULL; + num_screens = 0; + + + D_MAGIC_CLEAR( data ); + D_MAGIC_CLEAR( shared ); + + return DFB_OK; +} + +static DFBResult +dfb_screen_core_leave( DFBScreenCore *data, + bool emergency ) +{ + int i; + DFBScreenCoreShared *shared; + + D_DEBUG_AT( Core_Screen, "dfb_screen_core_leave( %p, %semergency )\n", data, emergency ? "" : "no " ); + + D_MAGIC_ASSERT( data, DFBScreenCore ); + D_MAGIC_ASSERT( data->shared, DFBScreenCoreShared ); + + shared = data->shared; + + + /* Deinitialize all local stuff only. */ + for (i=0; ishared, DFBScreenCoreShared ); + + shared = data->shared; + + for (i=num_screens-1; i>=0; i--) + dfb_screen_suspend( screens[i] ); + + return DFB_OK; +} + +static DFBResult +dfb_screen_core_resume( DFBScreenCore *data ) +{ + int i; + DFBScreenCoreShared *shared; + + D_DEBUG_AT( Core_Screen, "dfb_screen_core_resume( %p )\n", data ); + + D_MAGIC_ASSERT( data, DFBScreenCore ); + D_MAGIC_ASSERT( data->shared, DFBScreenCoreShared ); + + shared = data->shared; + + for (i=0; idevice = device; + screen->driver_data = driver_data; + screen->funcs = funcs; + + /* add it to the local list */ + screens[num_screens++] = screen; + + return screen; +} + +typedef void (*AnyFunc)( void ); + +CoreScreen * +dfb_screens_hook_primary( CoreGraphicsDevice *device, + void *driver_data, + ScreenFuncs *funcs, + ScreenFuncs *primary_funcs, + void **primary_driver_data ) +{ + int i; + int entries; + CoreScreen *primary = screens[0]; + + D_ASSERT( primary != NULL ); + D_ASSERT( device != NULL ); + D_ASSERT( funcs != NULL ); + + /* copy content of original function table */ + if (primary_funcs) + direct_memcpy( primary_funcs, primary->funcs, sizeof(ScreenFuncs) ); + + /* copy pointer to original driver data */ + if (primary_driver_data) + *primary_driver_data = primary->driver_data; + + /* replace all entries in the old table that aren't NULL in the new one */ + entries = sizeof(ScreenFuncs) / sizeof(void(*)( void )); + for (i=0; ifuncs; + + if (newfuncs[i]) + oldfuncs[i] = newfuncs[i]; + } + + /* replace device and driver data pointer */ + primary->device = device; + primary->driver_data = driver_data; + + return primary; +} + +CoreScreen * +dfb_screens_register_primary( CoreGraphicsDevice *device, + void *driver_data, + ScreenFuncs *funcs ) +{ + CoreScreen *primary = screens[0]; + + D_ASSERT( primary != NULL ); + D_ASSERT( funcs != NULL ); + D_ASSERT( num_screens > 0 ); + + /* replace device, function table and driver data pointer */ + primary->device = device; + primary->funcs = funcs; + primary->driver_data = driver_data; + + return primary; +} + +void +dfb_screens_enumerate( CoreScreenCallback callback, + void *ctx ) +{ + int i; + + D_ASSERT( core_screens != NULL ); + D_ASSERT( callback != NULL ); + + for (i=0; i= 0); + D_ASSERT( screen_id < num_screens); + + return screens[screen_id]; +} + +CoreScreen * +dfb_screens_at_translated( DFBScreenID screen_id ) +{ + CoreScreen *primary; + + D_ASSERT( screen_id >= 0); + D_ASSERT( screen_id < num_screens); + + if (dfb_config->primary_layer > 0) { + primary = dfb_layer_screen( dfb_layer_at_translated( DLID_PRIMARY ) ); + + if (screen_id == DSCID_PRIMARY) + return primary; + + if (screen_id == primary->shared->screen_id) + return dfb_screens_at( DSCID_PRIMARY ); + } + + return dfb_screens_at( screen_id ); +} + +DFBScreenID +dfb_screen_id_translated( CoreScreen *screen ) +{ + CoreScreenShared *shared; + CoreScreen *primary; + + D_ASSERT( screen != NULL ); + D_ASSERT( screen->shared != NULL ); + + shared = screen->shared; + + if (dfb_config->primary_layer > 0) { + primary = dfb_layer_screen( dfb_layer_at_translated( DLID_PRIMARY ) ); + + if (shared->screen_id == DSCID_PRIMARY) + return primary->shared->screen_id; + + if (shared->screen_id == primary->shared->screen_id) + return DSCID_PRIMARY; + } + + return shared->screen_id; +} + -- cgit