summaryrefslogtreecommitdiff
path: root/Source/DirectFB/src/core/surface.c
diff options
context:
space:
mode:
Diffstat (limited to 'Source/DirectFB/src/core/surface.c')
-rwxr-xr-xSource/DirectFB/src/core/surface.c768
1 files changed, 768 insertions, 0 deletions
diff --git a/Source/DirectFB/src/core/surface.c b/Source/DirectFB/src/core/surface.c
new file mode 100755
index 0000000..7b8e4fc
--- /dev/null
+++ b/Source/DirectFB/src/core/surface.c
@@ -0,0 +1,768 @@
+/*
+ (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 <direct/debug.h>
+
+#include <core/core.h>
+#include <core/palette.h>
+#include <core/surface.h>
+
+#include <core/layers_internal.h>
+#include <core/windows_internal.h>
+
+#include <gfx/convert.h>
+
+
+D_DEBUG_DOMAIN( Core_Surface, "Core/Surface", "DirectFB Core Surface" );
+
+/**********************************************************************************************************************/
+
+static const ReactionFunc dfb_surface_globals[] = {
+/* 0 */ _dfb_layer_region_surface_listener,
+/* 1 */ _dfb_windowstack_background_image_listener,
+ NULL
+};
+
+static void
+surface_destructor( FusionObject *object, bool zombie, void *ctx )
+{
+ int i;
+ CoreSurface *surface = (CoreSurface*) object;
+
+ D_MAGIC_ASSERT( surface, CoreSurface );
+
+ D_DEBUG_AT( Core_Surface, "destroying %p (%dx%d%s)\n", surface,
+ surface->config.size.w, surface->config.size.h, zombie ? " ZOMBIE" : "");
+
+ dfb_surface_lock( surface );
+
+ surface->state |= CSSF_DESTROYED;
+
+ /* announce surface destruction */
+ dfb_surface_notify( surface, CSNF_DESTROY );
+
+ /* unlink palette */
+ if (surface->palette) {
+ dfb_palette_detach_global( surface->palette, &surface->palette_reaction );
+ dfb_palette_unlink( &surface->palette );
+ }
+
+ /* destroy buffers */
+ for (i=0; i<MAX_SURFACE_BUFFERS; i++) {
+ if (surface->buffers[i])
+ dfb_surface_buffer_destroy( surface->buffers[i] );
+ }
+
+ direct_serial_deinit( &surface->serial );
+
+ dfb_surface_unlock( surface );
+
+ fusion_skirmish_destroy( &surface->lock );
+
+ D_MAGIC_CLEAR( surface );
+
+ fusion_object_destroy( object );
+}
+
+FusionObjectPool *
+dfb_surface_pool_create( const FusionWorld *world )
+{
+ FusionObjectPool *pool;
+
+ pool = fusion_object_pool_create( "Surface Pool",
+ sizeof(CoreSurface),
+ sizeof(CoreSurfaceNotification),
+ surface_destructor, NULL, world );
+
+ return pool;
+}
+
+/**********************************************************************************************************************/
+
+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;
+ 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;
+
+ 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) );
+
+ 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_init( &surface->lock, buf, dfb_core_world(core) );
+
+ fusion_object_set_lock( &surface->object, &surface->lock );
+
+ 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 Surface Buffers. */
+ for (i=0; i<buffers; i++) {
+ CoreSurfaceBuffer *buffer;
+
+ ret = dfb_surface_buffer_new( surface, CSBF_NONE, &buffer );
+ if (ret) {
+ D_DERROR( ret, "Core/Surface: Error creating surface buffer!\n" );
+ goto error;
+ }
+
+ surface->buffers[surface->num_buffers++] = buffer;
+
+ 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;
+ }
+ }
+
+ fusion_object_activate( &surface->object );
+
+ *ret_surface = surface;
+
+ return DFB_OK;
+
+error:
+ D_MAGIC_CLEAR( surface );
+
+ for (i=0; i<MAX_SURFACE_BUFFERS; i++) {
+ if (surface->buffers[i])
+ dfb_surface_buffer_destroy( surface->buffers[i] );
+ }
+
+ fusion_skirmish_destroy( &surface->lock );
+
+ direct_serial_deinit( &surface->serial );
+
+ fusion_object_destroy( &surface->object );
+
+ return ret;
+}
+
+DFBResult
+dfb_surface_create_simple ( CoreDFB *core,
+ int width,
+ int height,
+ DFBSurfacePixelFormat format,
+ DFBSurfaceCapabilities caps,
+ CoreSurfaceTypeFlags type,
+ unsigned long resource_id,
+ CorePalette *palette,
+ CoreSurface **ret_surface )
+{
+ CoreSurfaceConfig config;
+
+ D_DEBUG_AT( Core_Surface, "%s( %p, %dx%d %s, %p )\n", __FUNCTION__, core, width, height,
+ dfb_pixelformat_name( format ), ret_surface );
+
+ D_ASSERT( core != NULL );
+ D_ASSERT( ret_surface != NULL );
+
+ config.flags = CSCONF_SIZE | CSCONF_FORMAT | CSCONF_CAPS;
+ config.size.w = width;
+ config.size.h = height;
+ config.format = format;
+ config.caps = caps;
+
+ return dfb_surface_create( core, &config, type, resource_id, palette, ret_surface );
+}
+
+DFBResult
+dfb_surface_init_palette( CoreDFB *core,
+ CoreSurface *surface )
+{
+ DFBResult ret;
+ CorePalette *palette;
+
+ ret = dfb_palette_create( core,
+ 1 << DFB_COLOR_BITS_PER_PIXEL( surface->config.format ),
+ &palette );
+ if (ret) {
+ D_DERROR( ret, "Core/Surface: Error creating palette!\n" );
+ return ret;
+ }
+
+ switch (surface->config.format) {
+ case DSPF_LUT8:
+ dfb_palette_generate_rgb332_map( palette );
+ break;
+
+ case DSPF_ALUT44:
+ dfb_palette_generate_rgb121_map( palette );
+ break;
+
+ default:
+ break;
+ }
+
+ dfb_surface_set_palette( surface, palette );
+
+ dfb_palette_unref( palette );
+
+ return DFB_OK;
+}
+
+
+DFBResult
+dfb_surface_notify( CoreSurface *surface,
+ CoreSurfaceNotificationFlags flags)
+{
+ CoreSurfaceNotification notification;
+
+ D_MAGIC_ASSERT( surface, CoreSurface );
+ FUSION_SKIRMISH_ASSERT( &surface->lock );
+ D_FLAGS_ASSERT( flags, CSNF_ALL );
+
+ direct_serial_increase( &surface->serial );
+
+ if (!(surface->state & CSSF_DESTROYED)) {
+ if (!(surface->notifications & flags))
+ return DFB_OK;
+ }
+
+ notification.flags = flags;
+ notification.surface = surface;
+
+ return dfb_surface_dispatch( surface, &notification, dfb_surface_globals );
+}
+
+DFBResult
+dfb_surface_flip( CoreSurface *surface, bool swap )
+{
+ unsigned int back, front;
+
+ D_MAGIC_ASSERT( surface, CoreSurface );
+
+ FUSION_SKIRMISH_ASSERT( &surface->lock );
+
+ back = (surface->flips + CSBR_BACK) % surface->num_buffers;
+ front = (surface->flips + CSBR_FRONT) % surface->num_buffers;
+
+ D_ASSERT( surface->buffer_indices[back] < surface->num_buffers );
+ D_ASSERT( surface->buffer_indices[front] < surface->num_buffers );
+
+ if (surface->buffers[surface->buffer_indices[back]]->policy !=
+ surface->buffers[surface->buffer_indices[front]]->policy || (surface->config.caps & DSCAPS_ROTATED))
+ return DFB_UNSUPPORTED;
+
+ if (swap) {
+ int tmp = surface->buffer_indices[back];
+ surface->buffer_indices[back] = surface->buffer_indices[front];
+ surface->buffer_indices[front] = tmp;
+ }
+ else
+ surface->flips++;
+
+ dfb_surface_notify( surface, CSNF_FLIP );
+
+ return DFB_OK;
+}
+
+DFBResult
+dfb_surface_reconfig( CoreSurface *surface,
+ const CoreSurfaceConfig *config )
+{
+ int i, buffers;
+ DFBResult ret;
+
+ D_DEBUG_AT( Core_Surface, "%s( %p, %dx%d %s -> %dx%d %s )\n", __FUNCTION__, surface,
+ surface->config.size.w, surface->config.size.h, dfb_pixelformat_name( surface->config.format ),
+ (config->flags & CSCONF_SIZE) ? config->size.w : surface->config.size.w,
+ (config->flags & CSCONF_SIZE) ? config->size.h : surface->config.size.h,
+ (config->flags & CSCONF_FORMAT) ? dfb_pixelformat_name( config->format ) :
+ dfb_pixelformat_name( surface->config.format ) );
+
+ D_MAGIC_ASSERT( surface, CoreSurface );
+ D_ASSERT( config != NULL );
+
+ if (surface->type & CSTF_PREALLOCATED)
+ return DFB_UNSUPPORTED;
+
+ if (config->flags & CSCONF_PREALLOCATED)
+ return DFB_UNSUPPORTED;
+
+ if (fusion_skirmish_prevail( &surface->lock ))
+ return DFB_FUSION;
+
+ if ( (config->flags == CSCONF_SIZE ||
+ ((config->flags == (CSCONF_SIZE | CSCONF_FORMAT)) && (config->format == surface->config.format))) &&
+ config->size.w <= surface->config.min_size.w &&
+ config->size.h <= surface->config.min_size.h)
+ {
+ surface->config.size = config->size;
+
+ fusion_skirmish_dismiss( &surface->lock );
+ return DFB_OK;
+ }
+
+#if 1
+ /* Precheck the Surface Buffers. */
+ for (i=0; i<surface->num_buffers; i++) {
+ if (surface->buffers[i]->locked) {
+ D_DEBUG_AT( Core_Surface, " -> surface is locked, cannot reconfigure!\n" );
+
+ fusion_skirmish_dismiss( &surface->lock );
+ return DFB_LOCKED;
+ }
+ }
+#endif
+
+ /* Destroy the Surface Buffers. */
+ for (i=0; i<surface->num_buffers; i++) {
+ dfb_surface_buffer_destroy( surface->buffers[i] );
+ surface->buffers[i] = NULL;
+ }
+
+ surface->num_buffers = 0;
+
+ if (config->flags & CSCONF_SIZE)
+ surface->config.size = config->size;
+
+ if (config->flags & CSCONF_FORMAT)
+ surface->config.format = config->format;
+
+ if (config->flags & CSCONF_CAPS) {
+ if (config->caps & DSCAPS_ROTATED)
+ D_UNIMPLEMENTED();
+
+ surface->config.caps = config->caps & ~DSCAPS_ROTATED;
+ }
+
+ if (surface->config.caps & DSCAPS_SYSTEMONLY)
+ surface->type = (surface->type & ~CSTF_EXTERNAL) | CSTF_INTERNAL;
+ else if (surface->config.caps & DSCAPS_VIDEOONLY)
+ surface->type = (surface->type & ~CSTF_INTERNAL) | CSTF_EXTERNAL;
+ else
+ surface->type = surface->type & ~(CSTF_INTERNAL | CSTF_EXTERNAL);
+
+ 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;
+ }
+
+ /* Recreate the Surface Buffers. */
+ for (i=0; i<buffers; i++) {
+ CoreSurfaceBuffer *buffer;
+
+ ret = dfb_surface_buffer_new( surface, CSBF_NONE, &buffer );
+ if (ret) {
+ D_DERROR( ret, "Core/Surface: Error creating surface buffer!\n" );
+ goto error;
+ }
+
+ surface->buffers[surface->num_buffers++] = buffer;
+
+ 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_notify( surface, CSNF_SIZEFORMAT );
+
+ fusion_skirmish_dismiss( &surface->lock );
+
+ return DFB_OK;
+
+error:
+ D_UNIMPLEMENTED();
+
+ fusion_skirmish_dismiss( &surface->lock );
+
+ return ret;
+}
+
+DFBResult
+dfb_surface_destroy_buffers( CoreSurface *surface )
+{
+ int i;
+
+ D_MAGIC_ASSERT( surface, CoreSurface );
+
+ if (surface->type & CSTF_PREALLOCATED)
+ return DFB_UNSUPPORTED;
+
+ if (fusion_skirmish_prevail( &surface->lock ))
+ return DFB_FUSION;
+
+ /* Destroy the Surface Buffers. */
+ for (i=0; i<surface->num_buffers; i++) {
+ dfb_surface_buffer_destroy( surface->buffers[i] );
+ surface->buffers[i] = NULL;
+ }
+
+ surface->num_buffers = 0;
+
+ fusion_skirmish_dismiss( &surface->lock );
+
+ return DFB_OK;
+}
+
+DFBResult
+dfb_surface_lock_buffer( CoreSurface *surface,
+ CoreSurfaceBufferRole role,
+ CoreSurfaceAccessorID accessor,
+ CoreSurfaceAccessFlags access,
+ CoreSurfaceBufferLock *ret_lock )
+{
+ DFBResult ret;
+ CoreSurfaceBuffer *buffer;
+
+ D_MAGIC_ASSERT( surface, CoreSurface );
+
+ if (fusion_skirmish_prevail( &surface->lock ))
+ return DFB_FUSION;
+
+ buffer = dfb_surface_get_buffer( surface, role );
+ D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );
+
+ ret = dfb_surface_buffer_lock( buffer, accessor, access, ret_lock );
+
+ fusion_skirmish_dismiss( &surface->lock );
+
+ return ret;
+}
+
+DFBResult
+dfb_surface_unlock_buffer( CoreSurface *surface,
+ CoreSurfaceBufferLock *lock )
+{
+ DFBResult ret;
+
+ D_MAGIC_ASSERT( surface, CoreSurface );
+
+ if (fusion_skirmish_prevail( &surface->lock ))
+ return DFB_FUSION;
+
+ ret = dfb_surface_buffer_unlock( lock );
+
+ fusion_skirmish_dismiss( &surface->lock );
+
+ return ret;
+}
+
+DFBResult
+dfb_surface_read_buffer( CoreSurface *surface,
+ CoreSurfaceBufferRole role,
+ void *destination,
+ int pitch,
+ const DFBRectangle *rect )
+{
+ DFBResult ret;
+ CoreSurfaceBuffer *buffer;
+
+ D_MAGIC_ASSERT( surface, CoreSurface );
+ D_ASSERT( destination != NULL );
+ D_ASSERT( pitch > 0 );
+ DFB_RECTANGLE_ASSERT_IF( rect );
+
+ if (fusion_skirmish_prevail( &surface->lock ))
+ return DFB_FUSION;
+
+ buffer = dfb_surface_get_buffer( surface, role );
+ D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );
+
+ ret = dfb_surface_buffer_read( buffer, destination, pitch, rect );
+
+ fusion_skirmish_dismiss( &surface->lock );
+
+ return ret;
+}
+
+DFBResult
+dfb_surface_write_buffer( CoreSurface *surface,
+ CoreSurfaceBufferRole role,
+ const void *source,
+ int pitch,
+ const DFBRectangle *rect )
+{
+ DFBResult ret;
+ CoreSurfaceBuffer *buffer;
+
+ D_MAGIC_ASSERT( surface, CoreSurface );
+ D_ASSERT( source != NULL );
+ D_ASSERT( pitch > 0 );
+ DFB_RECTANGLE_ASSERT_IF( rect );
+
+ if (fusion_skirmish_prevail( &surface->lock ))
+ return DFB_FUSION;
+
+ buffer = dfb_surface_get_buffer( surface, role );
+ D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );
+
+ ret = dfb_surface_buffer_write( buffer, source, pitch, rect );
+
+ fusion_skirmish_dismiss( &surface->lock );
+
+ return ret;
+}
+
+DFBResult
+dfb_surface_dump_buffer( CoreSurface *surface,
+ CoreSurfaceBufferRole role,
+ const char *path,
+ const char *prefix )
+{
+ DFBResult ret;
+ CoreSurfaceBuffer *buffer;
+
+ D_MAGIC_ASSERT( surface, CoreSurface );
+ D_ASSERT( path != NULL );
+ D_ASSERT( prefix != NULL );
+
+ if (fusion_skirmish_prevail( &surface->lock ))
+ return DFB_FUSION;
+
+ buffer = dfb_surface_get_buffer( surface, role );
+ D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );
+
+ ret = dfb_surface_buffer_dump( buffer, path, prefix );
+
+ fusion_skirmish_dismiss( &surface->lock );
+
+ return ret;
+}
+
+DFBResult
+dfb_surface_set_palette( CoreSurface *surface,
+ CorePalette *palette )
+{
+ D_MAGIC_ASSERT( surface, CoreSurface );
+ D_MAGIC_ASSERT_IF( palette, CorePalette );
+
+ if (fusion_skirmish_prevail( &surface->lock ))
+ return DFB_FUSION;
+
+ if (surface->palette != palette) {
+ if (surface->palette) {
+ dfb_palette_detach_global( surface->palette, &surface->palette_reaction );
+ dfb_palette_unlink( &surface->palette );
+ }
+
+ if (palette) {
+ dfb_palette_link( &surface->palette, palette );
+ dfb_palette_attach_global( palette, DFB_SURFACE_PALETTE_LISTENER,
+ surface, &surface->palette_reaction );
+ }
+
+ dfb_surface_notify( surface, CSNF_PALETTE_CHANGE );
+ }
+
+ fusion_skirmish_dismiss( &surface->lock );
+
+ return DFB_OK;
+}
+
+DFBResult
+dfb_surface_set_field( CoreSurface *surface,
+ int field )
+{
+ D_MAGIC_ASSERT( surface, CoreSurface );
+
+ if (fusion_skirmish_prevail( &surface->lock ))
+ return DFB_FUSION;
+
+ surface->field = field;
+
+ dfb_surface_notify( surface, CSNF_FIELD );
+
+ fusion_skirmish_dismiss( &surface->lock );
+
+ return DFB_OK;
+}
+
+DFBResult
+dfb_surface_set_alpha_ramp( CoreSurface *surface,
+ u8 a0,
+ u8 a1,
+ u8 a2,
+ u8 a3 )
+{
+ D_MAGIC_ASSERT( surface, CoreSurface );
+
+ if (fusion_skirmish_prevail( &surface->lock ))
+ return DFB_FUSION;
+
+ surface->alpha_ramp[0] = a0;
+ surface->alpha_ramp[1] = a1;
+ surface->alpha_ramp[2] = a2;
+ surface->alpha_ramp[3] = a3;
+
+ dfb_surface_notify( surface, CSNF_ALPHA_RAMP );
+
+ fusion_skirmish_dismiss( &surface->lock );
+
+ return DFB_OK;
+}
+
+ReactionResult
+_dfb_surface_palette_listener( const void *msg_data,
+ void *ctx )
+{
+ const CorePaletteNotification *notification = msg_data;
+ CoreSurface *surface = ctx;
+
+ if (notification->flags & CPNF_DESTROY)
+ return RS_REMOVE;
+
+ if (notification->flags & CPNF_ENTRIES) {
+ if (fusion_skirmish_prevail( &surface->lock ))
+ return RS_OK;
+
+ dfb_surface_notify( surface, CSNF_PALETTE_UPDATE );
+
+ fusion_skirmish_dismiss( &surface->lock );
+ }
+
+ return RS_OK;
+}
+