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/layer_control.c | 589 +++++++++++++++++++++++++++++++ 1 file changed, 589 insertions(+) create mode 100755 Source/DirectFB/src/core/layer_control.c (limited to 'Source/DirectFB/src/core/layer_control.c') diff --git a/Source/DirectFB/src/core/layer_control.c b/Source/DirectFB/src/core/layer_control.c new file mode 100755 index 0000000..b190cc5 --- /dev/null +++ b/Source/DirectFB/src/core/layer_control.c @@ -0,0 +1,589 @@ +/* + (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 + + +D_DEBUG_DOMAIN( Core_Layers, "Core/Layers", "DirectFB Display Layer Core" ); + +/** public **/ + +DFBResult +dfb_layer_suspend( CoreLayer *layer ) +{ + CoreLayerShared *shared; + CoreLayerContexts *contexts; + + D_ASSERT( layer != NULL ); + D_ASSERT( layer->shared != NULL ); + + shared = layer->shared; + contexts = &shared->contexts; + + /* Lock the layer. */ + if (fusion_skirmish_prevail( &shared->lock )) + return DFB_FUSION; + + D_ASSUME( !shared->suspended ); + + if (shared->suspended) { + fusion_skirmish_dismiss( &shared->lock ); + return DFB_OK; + } + + /* Deactivate current context. */ + if (contexts->active >= 0) { + DFBResult ret; + CoreLayerContext *current = fusion_vector_at( &contexts->stack, + contexts->active ); + + ret = dfb_layer_context_deactivate( current ); + if (ret) { + D_ERROR("DirectFB/Core/layer: " + "Could not deactivate current context of '%s'! (%s)\n", + shared->description.name, DirectFBErrorString( ret )); + } + } + + shared->suspended = true; + + /* Unlock the layer. */ + fusion_skirmish_dismiss( &shared->lock ); + + return DFB_OK; +} + +DFBResult +dfb_layer_resume( CoreLayer *layer ) +{ + CoreLayerShared *shared; + CoreLayerContexts *contexts; + + D_ASSERT( layer != NULL ); + D_ASSERT( layer->shared != NULL ); + + shared = layer->shared; + contexts = &shared->contexts; + + /* Lock the layer. */ + if (fusion_skirmish_prevail( &shared->lock )) + return DFB_FUSION; + + D_ASSUME( shared->suspended ); + + if (!shared->suspended) { + fusion_skirmish_dismiss( &shared->lock ); + return DFB_OK; + } + + /* (Re)Activate current context. */ + if (contexts->active >= 0) { + DFBResult ret; + CoreLayerContext *current = fusion_vector_at( &contexts->stack, + contexts->active ); + + ret = dfb_layer_context_activate( current ); + if (ret) { + D_ERROR("DirectFB/Core/layer: " + "Could not activate current context of '%s'! (%s)\n", + shared->description.name, DirectFBErrorString( ret )); + } + } + + shared->suspended = false; + + /* Unlock the layer. */ + fusion_skirmish_dismiss( &shared->lock ); + + return DFB_OK; +} + +DFBResult +dfb_layer_create_context( CoreLayer *layer, + CoreLayerContext **ret_context ) +{ + DFBResult ret; + CoreLayerShared *shared; + CoreLayerContexts *contexts; + CoreLayerContext *context = NULL; + + D_ASSERT( layer != NULL ); + D_ASSERT( layer->shared != NULL ); + D_ASSERT( ret_context != NULL ); + + shared = layer->shared; + contexts = &shared->contexts; + + D_DEBUG_AT( Core_Layers, "%s (%s)\n", __FUNCTION__, shared->description.name ); + + /* Create the object. */ + context = dfb_core_create_layer_context( layer->core ); + if (!context) + return DFB_FUSION; + + /* Lock the layer. */ + if (fusion_skirmish_prevail( &shared->lock )) { + fusion_object_destroy( &context->object ); + return DFB_FUSION; + } + + /* Initialize the new context. */ + ret = dfb_layer_context_init( context, layer ); + if (ret) { + fusion_skirmish_dismiss( &shared->lock ); + return ret; + } + + /* Add it to the context stack. */ + if (fusion_vector_add( &contexts->stack, context )) { + dfb_layer_context_unref( context ); + fusion_skirmish_dismiss( &shared->lock ); + return DFB_FUSION; + } + + /* Unlock the layer. */ + fusion_skirmish_dismiss( &shared->lock ); + + /* Return the context. */ + *ret_context = context; + + return DFB_OK; +} + +DFBResult +dfb_layer_get_active_context( CoreLayer *layer, + CoreLayerContext **ret_context ) +{ + CoreLayerShared *shared; + CoreLayerContexts *contexts; + CoreLayerContext *context; + + D_ASSERT( layer != NULL ); + D_ASSERT( layer->shared != NULL ); + D_ASSERT( ret_context != NULL ); + + shared = layer->shared; + contexts = &shared->contexts; + + D_DEBUG_AT( Core_Layers, "%s (%s)\n", __FUNCTION__, shared->description.name ); + + /* Lock the layer. */ + if (fusion_skirmish_prevail( &shared->lock )) + return DFB_FUSION; + + /* Check for active context. */ + if (contexts->active < 0) { + fusion_skirmish_dismiss( &shared->lock ); + return DFB_NOCONTEXT; + } + + /* Fetch active context. */ + context = fusion_vector_at( &contexts->stack, contexts->active ); + + /* Increase the context's reference counter. */ + if (dfb_layer_context_ref( context )) { + fusion_skirmish_dismiss( &shared->lock ); + return DFB_FUSION; + } + + D_DEBUG_AT( Core_Layers, " => %p [%4dx%4d %8s]\n", context, + context->config.width, context->config.height, + dfb_pixelformat_name( context->config.pixelformat ) ); + + /* Return the context. */ + *ret_context = context; + + /* Unlock the layer. */ + fusion_skirmish_dismiss( &shared->lock ); + + return DFB_OK; +} + +DFBResult +dfb_layer_get_primary_context( CoreLayer *layer, + bool activate, + CoreLayerContext **ret_context ) +{ + DFBResult ret; + CoreLayerShared *shared; + CoreLayerContexts *contexts; + + D_ASSERT( layer != NULL ); + D_ASSERT( layer->shared != NULL ); + D_ASSERT( ret_context != NULL ); + + shared = layer->shared; + contexts = &shared->contexts; + + /* Lock the layer. */ + if (fusion_skirmish_prevail( &shared->lock )) + return DFB_FUSION; + + D_DEBUG_AT( Core_Layers, "%s (%s, %sactivate) <- active: %d\n", + __FUNCTION__, shared->description.name, + activate ? "" : "don't ", contexts->active ); + + /* Check for primary context. */ + if (contexts->primary) { + /* Increase the context's reference counter. */ + if (dfb_layer_context_ref( contexts->primary )) { + fusion_skirmish_dismiss( &shared->lock ); + return DFB_FUSION; + } + } + else { + CoreLayerContext *primary; + + /* Unlock the layer. */ + fusion_skirmish_dismiss( &shared->lock ); + + /* Create the primary (shared) context. */ + ret = dfb_layer_create_context( layer, &primary ); + if (ret) + return ret; + + /* Lock the layer again. */ + if (fusion_skirmish_prevail( &shared->lock )) { + dfb_layer_context_unref( primary ); + return DFB_FUSION; + } + + /* Check if there was a race. */ + if (contexts->primary) { + /* Throw away ours, the other was faster. */ + dfb_layer_context_unref( primary ); + + /* Increase the context's reference counter. */ + if (dfb_layer_context_ref( contexts->primary )) { + fusion_skirmish_dismiss( &shared->lock ); + return DFB_FUSION; + } + } + else + contexts->primary = primary; + } + + /* Activate if no context is active? */ + if (contexts->active < 0 && activate) { + ret = dfb_layer_activate_context( layer, contexts->primary ); + if (ret) { + dfb_layer_context_unref( contexts->primary ); + fusion_skirmish_dismiss( &shared->lock ); + return ret; + } + } + + /* Return the context. */ + *ret_context = contexts->primary; + + /* Unlock the layer. */ + fusion_skirmish_dismiss( &shared->lock ); + + return DFB_OK; +} + +DFBResult +dfb_layer_activate_context( CoreLayer *layer, + CoreLayerContext *context ) +{ + DFBResult ret = DFB_OK; + int index; + CoreLayerShared *shared; + CoreLayerContexts *ctxs; + + D_ASSERT( layer != NULL ); + D_ASSERT( layer->shared != NULL ); + D_ASSERT( context != NULL ); + + shared = layer->shared; + ctxs = &shared->contexts; + + /* Lock the layer. */ + if (fusion_skirmish_prevail( &shared->lock )) + return DFB_FUSION; + + D_DEBUG_AT( Core_Layers, "%s (%s, %p)\n", __FUNCTION__, shared->description.name, context ); + + D_ASSERT( fusion_vector_contains( &ctxs->stack, context ) ); + + /* Lookup the context in the context stack. */ + index = fusion_vector_index_of( &ctxs->stack, context ); + + /* Lock the context. */ + if (dfb_layer_context_lock( context )) { + fusion_skirmish_dismiss( &shared->lock ); + return DFB_FUSION; + } + + /* Need to activate? */ + if (ctxs->active != index) { + DFBResult ret; + + /* Another context currently active? */ + if (ctxs->active >= 0) { + CoreLayerContext *current = fusion_vector_at( &ctxs->stack, + ctxs->active ); + + /* Deactivate current context. */ + if (!shared->suspended) { + ret = dfb_layer_context_deactivate( current ); + if (ret) + goto error; + } + + /* No active context. */ + ctxs->active = -1; + } + + /* Activate context now. */ + if (!shared->suspended) { + ret = dfb_layer_context_activate( context ); + if (ret) + goto error; + } + + ctxs->active = index; + } + + /* Unlock the context. */ + dfb_layer_context_unlock( context ); + + /* Unlock the layer. */ + fusion_skirmish_dismiss( &shared->lock ); + + return DFB_OK; + +error: + dfb_layer_context_unlock( context ); + + fusion_skirmish_dismiss( &shared->lock ); + + return ret; +} + +DFBResult +dfb_layer_remove_context( CoreLayer *layer, + CoreLayerContext *context ) +{ + int index; + CoreLayerShared *shared; + CoreLayerContexts *ctxs; + + D_ASSERT( layer != NULL ); + D_ASSERT( layer->shared != NULL ); + D_ASSERT( context != NULL ); + + shared = layer->shared; + ctxs = &shared->contexts; + + /* Lock the layer. */ + if (fusion_skirmish_prevail( &shared->lock )) + return DFB_FUSION; + + D_DEBUG_AT( Core_Layers, "%s (%s, %p)\n", __FUNCTION__, shared->description.name, context ); + + D_ASSUME( fusion_vector_contains( &ctxs->stack, context ) ); + + /* Lookup the context in the context stack. */ + index = fusion_vector_index_of( &ctxs->stack, context ); + if (index < 0) { + fusion_skirmish_dismiss( &shared->lock ); + return DFB_OK; + } + + /* Lock the context. */ + if (dfb_layer_context_lock( context )) { + fusion_skirmish_dismiss( &shared->lock ); + return DFB_FUSION; + } + + /* Remove context from context stack. */ + fusion_vector_remove( &ctxs->stack, index ); + + /* Check if the primary context is removed. */ + if (context == ctxs->primary) + ctxs->primary = NULL; + + /* Need to deactivate? */ + if (ctxs->active == index) { + /* Deactivate the context. */ + if (!shared->suspended) + dfb_layer_context_deactivate( context ); + + /* There's no active context anymore. */ + ctxs->active = -1; + + if (ctxs->primary) + D_ASSERT( fusion_vector_contains( &ctxs->stack, ctxs->primary ) ); + + if (fusion_vector_has_elements( &ctxs->stack )) { + CoreLayerContext *ctx; + + /* Activate most recent context. */ + index = fusion_vector_size( &ctxs->stack ) - 1; + ctx = fusion_vector_at( &ctxs->stack, index ); + + if (shared->suspended || dfb_layer_context_activate( ctx ) == DFB_OK) + ctxs->active = index; + } + } + else if (ctxs->active > index) { + /* Adjust index of active context due to the removed context. */ + ctxs->active--; + } + + /* Unlock the context. */ + dfb_layer_context_unlock( context ); + + /* Unlock the layer. */ + fusion_skirmish_dismiss( &shared->lock ); + + return DFB_OK; +} + +DFBResult +dfb_layer_get_current_output_field( CoreLayer *layer, int *field ) +{ + DFBResult ret; + + D_ASSERT( layer != NULL ); + D_ASSERT( layer->funcs != NULL ); + D_ASSERT( field != NULL ); + + if (!layer->funcs->GetCurrentOutputField) + return DFB_UNSUPPORTED; + + ret = layer->funcs->GetCurrentOutputField( layer, layer->driver_data, + layer->layer_data, field ); + if (ret) + return ret; + + return DFB_OK; +} + +DFBResult +dfb_layer_get_level( CoreLayer *layer, int *ret_level ) +{ + const DisplayLayerFuncs *funcs; + + D_ASSERT( layer != NULL ); + D_ASSERT( layer->funcs != NULL ); + D_ASSERT( ret_level != NULL ); + + funcs = layer->funcs; + + if (!funcs->GetLevel) + return DFB_UNSUPPORTED; + + return funcs->GetLevel( layer, layer->driver_data, + layer->layer_data, ret_level ); +} + +DFBResult +dfb_layer_set_level( CoreLayer *layer, int level ) +{ + const DisplayLayerFuncs *funcs; + + D_ASSERT( layer != NULL ); + D_ASSERT( layer->funcs != NULL ); + + funcs = layer->funcs; + + if (!funcs->SetLevel) + return DFB_UNSUPPORTED; + + return funcs->SetLevel( layer, layer->driver_data, + layer->layer_data, level ); +} + +DFBResult +dfb_layer_wait_vsync( CoreLayer *layer ) +{ + D_ASSERT( layer != NULL ); + D_ASSERT( layer->screen != NULL ); + + return dfb_screen_wait_vsync( layer->screen ); +} + +DFBResult +dfb_layer_get_source_info( CoreLayer *layer, + int source, + DFBDisplayLayerSourceDescription *ret_desc ) +{ + D_ASSERT( layer != NULL ); + D_ASSERT( layer->shared != NULL ); + D_ASSERT( source >= 0 ); + D_ASSERT( source < layer->shared->description.sources ); + D_ASSERT( ret_desc != NULL ); + + *ret_desc = layer->shared->sources[source].description; + + return DFB_OK; +} + -- cgit