summaryrefslogtreecommitdiff
path: root/Source/DirectFB/src/core/state.c
diff options
context:
space:
mode:
Diffstat (limited to 'Source/DirectFB/src/core/state.c')
-rwxr-xr-xSource/DirectFB/src/core/state.c416
1 files changed, 416 insertions, 0 deletions
diff --git a/Source/DirectFB/src/core/state.c b/Source/DirectFB/src/core/state.c
new file mode 100755
index 0000000..8ae97e0
--- /dev/null
+++ b/Source/DirectFB/src/core/state.c
@@ -0,0 +1,416 @@
+/*
+ (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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <config.h>
+
+#include <string.h>
+
+#include <pthread.h>
+
+#include <fusion/fusion.h>
+#include <fusion/reactor.h>
+
+#include <directfb.h>
+
+#include <core/core.h>
+#include <core/coretypes.h>
+
+#include <core/palette.h>
+#include <core/state.h>
+#include <core/surface.h>
+
+#include <direct/mem.h>
+#include <direct/memcpy.h>
+#include <direct/util.h>
+
+#include <misc/conf.h>
+
+
+static inline void
+validate_clip( CardState *state,
+ int xmax,
+ int ymax,
+ bool warn )
+{
+ D_MAGIC_ASSERT( state, CardState );
+ DFB_REGION_ASSERT( &state->clip );
+
+ D_ASSERT( xmax >= 0 );
+ D_ASSERT( ymax >= 0 );
+ D_ASSERT( state->clip.x1 <= state->clip.x2 );
+ D_ASSERT( state->clip.y1 <= state->clip.y2 );
+
+ if (state->clip.x1 <= xmax &&
+ state->clip.y1 <= ymax &&
+ state->clip.x2 <= xmax &&
+ state->clip.y2 <= ymax)
+ return;
+
+ if (warn)
+ D_WARN( "Clip %d,%d-%dx%d invalid, adjusting to fit %dx%d",
+ DFB_RECTANGLE_VALS_FROM_REGION( &state->clip ), xmax+1, ymax+1 );
+
+ if (state->clip.x1 > xmax)
+ state->clip.x1 = xmax;
+
+ if (state->clip.y1 > ymax)
+ state->clip.y1 = ymax;
+
+ if (state->clip.x2 > xmax)
+ state->clip.x2 = xmax;
+
+ if (state->clip.y2 > ymax)
+ state->clip.y2 = ymax;
+
+ state->modified |= SMF_CLIP;
+}
+
+int
+dfb_state_init( CardState *state, CoreDFB *core )
+{
+ D_ASSERT( state != NULL );
+
+ memset( state, 0, sizeof(CardState) );
+
+ state->core = core;
+ state->fusion_id = fusion_id( dfb_core_world(core) );
+ state->modified = SMF_ALL;
+ state->src_blend = DSBF_SRCALPHA;
+ state->dst_blend = DSBF_INVSRCALPHA;
+ state->render_options = dfb_config->render_options;
+
+ state->matrix[0] = 0x10000;
+ state->matrix[1] = 0x00000;
+ state->matrix[2] = 0x00000;
+ state->matrix[3] = 0x00000;
+ state->matrix[4] = 0x10000;
+ state->matrix[5] = 0x00000;
+ state->matrix[6] = 0x00000;
+ state->matrix[7] = 0x00000;
+ state->matrix[8] = 0x10000;
+ state->affine_matrix = DFB_TRUE;
+
+ state->from = CSBR_FRONT;
+ state->to = CSBR_BACK;
+
+ direct_util_recursive_pthread_mutex_init( &state->lock );
+
+ direct_serial_init( &state->dst_serial );
+ direct_serial_init( &state->src_serial );
+ direct_serial_init( &state->src_mask_serial );
+
+ D_MAGIC_SET( state, CardState );
+
+ return 0;
+}
+
+void
+dfb_state_destroy( CardState *state )
+{
+ D_MAGIC_ASSERT( state, CardState );
+
+ D_ASSUME( !(state->flags & CSF_DRAWING) );
+
+ D_ASSERT( state->destination == NULL );
+ D_ASSERT( state->source == NULL );
+ D_ASSERT( state->source_mask == NULL );
+
+ D_MAGIC_CLEAR( state );
+
+ direct_serial_deinit( &state->dst_serial );
+ direct_serial_deinit( &state->src_serial );
+ direct_serial_deinit( &state->src_mask_serial );
+
+ if (state->gfxs) {
+ GenefxState *gfxs = state->gfxs;
+
+ if (gfxs->ABstart)
+ D_FREE( gfxs->ABstart );
+
+ D_FREE( gfxs );
+ }
+
+ if (state->num_translation) {
+ D_ASSERT( state->index_translation != NULL );
+
+ D_FREE( state->index_translation );
+ }
+ else
+ D_ASSERT( state->index_translation == NULL );
+
+ pthread_mutex_destroy( &state->lock );
+}
+
+DFBResult
+dfb_state_set_destination( CardState *state, CoreSurface *destination )
+{
+ D_MAGIC_ASSERT( state, CardState );
+
+ dfb_state_lock( state );
+
+ D_ASSUME( !(state->flags & CSF_DRAWING) );
+
+ if (state->destination != destination) {
+ if (destination) {
+ if (dfb_surface_ref( destination )) {
+ D_WARN( "could not ref() destination" );
+ dfb_state_unlock( state );
+ return DFB_DEAD;
+ }
+
+ validate_clip( state, destination->config.size.w - 1, destination->config.size.h - 1, false );
+ }
+
+ if (state->destination) {
+ D_ASSERT( D_FLAGS_IS_SET( state->flags, CSF_DESTINATION ) );
+ dfb_surface_unref( state->destination );
+ }
+
+ state->destination = destination;
+ state->modified |= SMF_DESTINATION;
+
+ if (destination) {
+ direct_serial_copy( &state->dst_serial, &destination->serial );
+
+ D_FLAGS_SET( state->flags, CSF_DESTINATION );
+ }
+ else
+ D_FLAGS_CLEAR( state->flags, CSF_DESTINATION );
+ }
+
+ dfb_state_unlock( state );
+
+ return DFB_OK;
+}
+
+DFBResult
+dfb_state_set_source( CardState *state, CoreSurface *source )
+{
+ D_MAGIC_ASSERT( state, CardState );
+
+ dfb_state_lock( state );
+
+ if (state->source != source) {
+ if (source && dfb_surface_ref( source )) {
+ D_WARN( "could not ref() source" );
+ dfb_state_unlock( state );
+ return DFB_DEAD;
+ }
+
+ if (state->source) {
+ D_ASSERT( D_FLAGS_IS_SET( state->flags, CSF_SOURCE ) );
+ dfb_surface_unref( state->source );
+ }
+
+ state->source = source;
+ state->modified |= SMF_SOURCE;
+
+ if (source) {
+ direct_serial_copy( &state->src_serial, &source->serial );
+
+ D_FLAGS_SET( state->flags, CSF_SOURCE );
+ }
+ else
+ D_FLAGS_CLEAR( state->flags, CSF_SOURCE );
+ }
+
+ dfb_state_unlock( state );
+
+ return DFB_OK;
+}
+
+DFBResult
+dfb_state_set_source_mask( CardState *state, CoreSurface *source_mask )
+{
+ D_MAGIC_ASSERT( state, CardState );
+
+ dfb_state_lock( state );
+
+ if (state->source_mask != source_mask) {
+ if (source_mask && dfb_surface_ref( source_mask )) {
+ D_WARN( "could not ref() source mask" );
+ dfb_state_unlock( state );
+ return DFB_DEAD;
+ }
+
+ if (state->source_mask) {
+ D_ASSERT( D_FLAGS_IS_SET( state->flags, CSF_SOURCE_MASK ) );
+ dfb_surface_unref( state->source_mask );
+ }
+
+ state->source_mask = source_mask;
+ state->modified |= SMF_SOURCE_MASK;
+
+ if (source_mask) {
+ direct_serial_copy( &state->src_mask_serial, &source_mask->serial );
+
+ D_FLAGS_SET( state->flags, CSF_SOURCE_MASK );
+ }
+ else
+ D_FLAGS_CLEAR( state->flags, CSF_SOURCE_MASK );
+ }
+
+ dfb_state_unlock( state );
+
+ return DFB_OK;
+}
+
+void
+dfb_state_update( CardState *state, bool update_sources )
+{
+ CoreSurface *destination;
+
+ D_MAGIC_ASSERT( state, CardState );
+ DFB_REGION_ASSERT( &state->clip );
+
+ destination = state->destination;
+
+ if (D_FLAGS_IS_SET( state->flags, CSF_DESTINATION )) {
+
+ D_ASSERT( destination != NULL );
+
+ if (direct_serial_update( &state->dst_serial, &destination->serial )) {
+ validate_clip( state, destination->config.size.w - 1, destination->config.size.h - 1, true );
+
+ state->modified |= SMF_DESTINATION;
+ }
+ }
+ else if (destination)
+ validate_clip( state, destination->config.size.w - 1, destination->config.size.h - 1, true );
+
+ if (update_sources && D_FLAGS_IS_SET( state->flags, CSF_SOURCE )) {
+ CoreSurface *source = state->source;
+
+ D_ASSERT( source != NULL );
+
+ if (direct_serial_update( &state->src_serial, &source->serial ))
+ state->modified |= SMF_SOURCE;
+ }
+
+ if (update_sources && D_FLAGS_IS_SET( state->flags, CSF_SOURCE_MASK )) {
+ CoreSurface *source_mask = state->source_mask;
+
+ D_ASSERT( source_mask != NULL );
+
+ if (direct_serial_update( &state->src_mask_serial, &source_mask->serial ))
+ state->modified |= SMF_SOURCE_MASK;
+ }
+}
+
+DFBResult
+dfb_state_set_index_translation( CardState *state,
+ const int *indices,
+ int num_indices )
+{
+ D_MAGIC_ASSERT( state, CardState );
+
+ D_ASSERT( indices != NULL || num_indices == 0 );
+
+ dfb_state_lock( state );
+
+ if (state->num_translation != num_indices) {
+ int *new_trans = D_REALLOC( state->index_translation,
+ num_indices * sizeof(int) );
+
+ D_ASSERT( num_indices || new_trans == NULL );
+
+ if (num_indices && !new_trans) {
+ dfb_state_unlock( state );
+ return D_OOM();
+ }
+
+ state->index_translation = new_trans;
+ state->num_translation = num_indices;
+ }
+
+ if (num_indices)
+ direct_memcpy( state->index_translation, indices, num_indices * sizeof(int) );
+
+ state->modified |= SMF_INDEX_TRANSLATION;
+
+ dfb_state_unlock( state );
+
+ return DFB_OK;
+}
+
+void
+dfb_state_set_matrix( CardState *state,
+ const s32 *matrix )
+{
+ D_MAGIC_ASSERT( state, CardState );
+
+ D_ASSERT( matrix != NULL );
+
+ if (memcmp( state->matrix, matrix, sizeof(state->matrix) )) {
+ direct_memcpy( state->matrix, matrix, sizeof(state->matrix) );
+
+ state->affine_matrix = (matrix[6] == 0x00000 &&
+ matrix[7] == 0x00000 &&
+ matrix[8] == 0x10000);
+
+ state->modified |= SMF_MATRIX;
+ }
+}
+
+void
+dfb_state_set_color_or_index( CardState *state,
+ const DFBColor *color,
+ int index )
+{
+ CoreSurface *destination;
+ CorePalette *palette = NULL;
+
+ D_MAGIC_ASSERT( state, CardState );
+ D_ASSERT( color != NULL );
+
+ destination = state->destination;
+ if (destination)
+ palette = destination->palette;
+
+ if (index < 0) {
+ D_ASSERT( color != NULL );
+
+ if (palette)
+ dfb_state_set_color_index( state, dfb_palette_search( palette,
+ color->r, color->g,
+ color->b, color->a ) );
+
+ dfb_state_set_color( state, color );
+ }
+ else {
+ dfb_state_set_color_index( state, index );
+
+ if (palette) {
+ D_ASSERT( palette->num_entries > 0 );
+ D_ASSUME( palette->num_entries > index );
+
+ dfb_state_set_color( state, &palette->entries[index % palette->num_entries] );
+ }
+ }
+}
+