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/surface.c | 768 +++++++++++++++++++++++++++++++++++++ 1 file changed, 768 insertions(+) create mode 100755 Source/DirectFB/src/core/surface.c (limited to 'Source/DirectFB/src/core/surface.c') 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 , + 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 + + +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; ibuffers[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; ibuffers[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; ibuffers[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, ¬ification, 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; inum_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; inum_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; ibuffers[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; inum_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; +} + -- cgit