static void surface_client_destructor( FusionObject *object, bool zombie, void *ctx ) { CoreSurfaceClient *client = (CoreSurfaceClient*) object; CoreSurface *surface; int index; D_MAGIC_ASSERT( client, CoreSurfaceClient ); surface = client->surface; CORE_SURFACE_ASSERT( surface ); D_DEBUG_AT( Core_SurfClient, "destroying %p (%dx%d%s)\n", client, surface->config.size.w, surface->config.size.h, zombie ? " ZOMBIE" : ""); CoreSurfaceClient_Deinit_Dispatch( &client->call ); dfb_surface_lock( surface ); index = fusion_vector_index_of( &surface->clients, client ); D_ASSERT( index >= 0 ); fusion_vector_remove( &surface->clients, index ); dfb_surface_check_acks( surface ); dfb_surface_unlock( surface ); dfb_surface_unlink( &client->surface ); D_MAGIC_CLEAR( client ); fusion_object_destroy( object ); }
static DFBResult region_buffer_lock( CoreLayerRegion *region, CoreSurface *surface, CoreSurfaceBufferRole role ) { DFBResult ret; CoreSurfaceBuffer *buffer; CoreSurfaceAllocation *allocation; CoreLayerContext *context; D_ASSERT( region != NULL ); D_MAGIC_ASSERT( surface, CoreSurface ); context = region->context; D_MAGIC_ASSERT( context, CoreLayerContext ); /* First unlock any previously locked buffer. */ if (region->surface_lock.buffer) { D_MAGIC_ASSERT( region->surface_lock.buffer, CoreSurfaceBuffer ); dfb_surface_unlock_buffer( region->surface_lock.buffer->surface, ®ion->surface_lock ); } if (dfb_surface_lock( surface )) return DFB_FUSION; buffer = dfb_surface_get_buffer( surface, role ); D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); /* Lock the surface buffer. */ ret = dfb_surface_buffer_lock( buffer, CSAID_LAYER0 + context->layer_id, CSAF_READ, ®ion->surface_lock ); if (ret) { D_DERROR( ret, "Core/LayerRegion: Could not lock region surface for SetRegion()!\n" ); dfb_surface_unlock( surface ); return ret; } allocation = region->surface_lock.allocation; D_ASSERT( allocation != NULL ); /* If hardware has written or is writing... */ if (allocation->accessed[CSAID_GPU] & CSAF_WRITE) { D_DEBUG_AT( Core_Layers, " -> Waiting for pending writes...\n" ); /* ...wait for the operation to finish. */ dfb_gfxcard_sync(); /* TODO: wait for serial instead */ allocation->accessed[CSAID_GPU] &= ~CSAF_WRITE; } /* surface is unlocked by caller */ return DFB_OK; }
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" : ""); Core_Resource_RemoveSurface( surface ); CoreSurface_Deinit_Dispatch( &surface->call ); 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_decouple( surface->buffers[i] ); } dfb_system_surface_data_destroy( surface, surface->data ); /* release the system driver specific surface data */ if (surface->data) { SHFREE( surface->shmpool, surface->data ); surface->data = NULL; } direct_serial_deinit( &surface->serial ); dfb_surface_unlock( surface ); fusion_skirmish_destroy( &surface->lock ); D_MAGIC_CLEAR( surface ); fusion_object_destroy( object ); }
static DFBResult region_buffer_lock( CoreLayerRegion *region, CoreSurface *surface, CoreSurfaceBufferRole role ) { DFBResult ret; CoreSurfaceAccessFlags flags; CoreSurfaceBuffer *buffer; CoreSurfaceAllocation *allocation; /* First unlock any previously locked buffer. */ if (region->surface_lock.buffer) { D_MAGIC_ASSERT( region->surface_lock.buffer, CoreSurfaceBuffer ); dfb_surface_unlock_buffer( region->surface_lock.buffer->surface, ®ion->surface_lock ); } /* Determine flags to use. */ if (surface->config.caps & DSCAPS_SYSTEMONLY) flags = CSAF_CPU_READ; else flags = CSAF_GPU_READ; if (dfb_surface_lock( surface )) return DFB_FUSION; buffer = dfb_surface_get_buffer( surface, role ); D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); /* Lock the surface buffer. */ ret = dfb_surface_buffer_lock( buffer, flags, ®ion->surface_lock ); if (ret) { D_DERROR( ret, "Core/LayerRegion: Could not lock region surface for SetRegion()!\n" ); dfb_surface_unlock( surface ); return ret; } allocation = region->surface_lock.allocation; D_ASSERT( allocation != NULL ); /* If hardware has written or is writing... */ if (allocation->accessed & CSAF_GPU_WRITE) { D_DEBUG_AT( Core_Layers, " -> Waiting for pending writes...\n" ); /* ...wait for the operation to finish. */ dfb_gfxcard_sync(); /* TODO: wait for serial instead */ allocation->accessed &= ~CSAF_GPU_WRITE; } return DFB_OK; }
DFBResult ISurface_Real__Flip( CoreSurface *obj, bool swap ) { DFBResult ret; D_DEBUG_AT( DirectFB_CoreSurface, "%s()\n", __FUNCTION__ ); dfb_surface_lock( obj ); ret = dfb_surface_flip( obj, swap ); dfb_surface_unlock( obj ); return ret; }
DFBResult dfb_surface_client_create( CoreDFB *core, CoreSurface *surface, CoreSurfaceClient **ret_client ) { DFBResult ret; CoreSurfaceClient *client; CORE_SURFACE_ASSERT( surface ); D_ASSERT( ret_client != NULL ); D_DEBUG_AT( Core_SurfClient, "%s( %p %dx%d %s )\n", __FUNCTION__, surface, surface->config.size.w, surface->config.size.h, dfb_pixelformat_name( surface->config.format ) ); client = dfb_core_create_surface_client( core ); if (!client) return DFB_FUSION; ret = dfb_surface_link( &client->surface, surface ); if (ret) { fusion_object_destroy( &client->object ); return ret; } D_MAGIC_SET( client, CoreSurfaceClient ); *ret_client = client; CoreSurfaceClient_Init_Dispatch( core, client, &client->call ); dfb_surface_lock( surface ); client->flip_count = surface->flips; fusion_vector_add( &surface->clients, client ); dfb_surface_unlock( surface ); fusion_object_activate( &client->object ); return DFB_OK; }
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 ); }
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, data_size; 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; surface->data = NULL; 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) ); surface->config.preallocated_pool_id = config->preallocated_pool_id; 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_init2( &surface->lock, buf, dfb_core_world(core), fusion_config->secure_fusion ); // fusion_skirmish_add_permissions( &surface->lock, 0, FUSION_SKIRMISH_PERMIT_PREVAIL | FUSION_SKIRMISH_PERMIT_DISMISS ); 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 system driver specific surface data information */ data_size = dfb_system_surface_data_size(); if (data_size) { surface->data = SHCALLOC( surface->shmpool, 1, data_size ); if (!surface->data) { ret = D_OOSHM(); goto error; } } dfb_system_surface_data_init(surface,surface->data); dfb_surface_lock( surface ); /* Create the Surface Buffers. */ for (i=0; i<buffers; i++) { ret = dfb_surface_buffer_create( core, surface, CSBF_NONE, &surface->buffers[i] ); if (ret) { D_DERROR( ret, "Core/Surface: Error creating surface buffer!\n" ); goto error; } surface->num_buffers++; dfb_surface_buffer_globalize( surface->buffers[i] ); 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_unlock( surface ); CoreSurface_Init_Dispatch( core, surface, &surface->call ); fusion_object_activate( &surface->object ); *ret_surface = surface; return DFB_OK; error: for (i=0; i<MAX_SURFACE_BUFFERS; i++) { if (surface->buffers[i]) dfb_surface_buffer_decouple( surface->buffers[i] ); } /* release the system driver specific surface data */ if (surface->data) { dfb_system_surface_data_destroy( surface, surface->data ); SHFREE( surface->shmpool, surface->data ); surface->data = NULL; } fusion_skirmish_destroy( &surface->lock ); direct_serial_deinit( &surface->serial ); D_MAGIC_CLEAR( surface ); fusion_object_destroy( &surface->object ); return ret; }
static void handle_expose_Async( void *ctx, void *ctx2 ) { DFBX11 *x11 = ctx; DFBX11Shared *shared = x11->shared; const XExposeEvent *expose = ctx2; CoreLayer *layer; CoreLayerContext *context; int i; X11LayerData *lds; D_DEBUG_AT( X11_Input, "%s( %d,%d-%dx%d )\n", __FUNCTION__, expose->x, expose->y, expose->width, expose->height ); //D_INFO_LINE_MSG("handle_expose %d,%d-%dx%d", expose->x, expose->y, expose->width, expose->height); /* find the correct layer */ for (i=0; i<shared->outputs; i++) { if (shared->output[i].xw && (shared->output[i].xw->window == expose->window)) break; } /* layer not found? */ if (i == shared->outputs) return; lds = shared->output[i].layers[0]; layer = dfb_layer_at( lds->layer_id ); D_ASSERT( layer != NULL ); /* Get the currently active context. */ if (dfb_layer_get_active_context( layer, &context ) == DFB_OK) { CoreLayerRegion *region; /* Get the first region. */ if (dfb_layer_context_get_primary_region( context, false, ®ion ) == DFB_OK) { /* Lock the region. */ dfb_layer_region_lock( region ); /* Get the surface of the region. */ if (region->surface && D_FLAGS_ARE_SET( region->state, CLRSF_REALIZED )) { if (dfb_config->task_manager) { DFBRegion update = { expose->x, expose->y, expose->x + expose->width - 1, expose->y + expose->height - 1 }; /* Tell the driver about the update if the region is realized. */ D_DEBUG_AT( X11_Input, " -> Issuing display task...\n" ); dfb_surface_lock( region->surface ); DisplayTask_Generate( region, &update, &update, DSFLIP_NONE, -1, NULL ); dfb_surface_unlock( region->surface ); } else { //if (lds->lock_left.buffer) { DFBRegion update = { expose->x, expose->y, expose->x + expose->width - 1, expose->y + expose->height - 1 }; // dfb_x11_update_screen( x11, lds, &update, &update, &lds->lock_left, &lds->lock_right ); //} dfb_x11_update_screen( x11, lds, &update, &update, NULL, NULL ); } } /* Unlock the region. */ dfb_layer_region_unlock( region ); /* Release the region. */ dfb_layer_region_unref( region ); } /* Release the context. */ dfb_layer_context_unref( context ); } }
static DFBResult set_region( CoreLayerRegion *region, CoreLayerRegionConfig *config, CoreLayerRegionConfigFlags flags, CoreSurface *surface ) { DFBResult ret; CoreLayer *layer; CoreLayerShared *shared; const DisplayLayerFuncs *funcs; D_DEBUG_AT( Core_Layers, "%s( %p, %p, 0x%08x, %p )\n", __FUNCTION__, region, config, flags, surface ); DFB_CORE_LAYER_REGION_CONFIG_DEBUG_AT( Core_Layers, config ); D_DEBUG_AT( Core_Layers, " -> state 0x%08x\n", region->state ); D_ASSERT( region != NULL ); D_ASSERT( region->context != NULL ); D_ASSERT( config != NULL ); D_ASSERT( config->buffermode != DLBM_WINDOWS ); D_ASSERT( D_FLAGS_IS_SET( region->state, CLRSF_REALIZED ) ); layer = dfb_layer_at( region->context->layer_id ); D_ASSERT( layer != NULL ); D_ASSERT( layer->shared != NULL ); D_ASSERT( layer->funcs != NULL ); D_ASSERT( layer->funcs->SetRegion != NULL ); if (region->state & CLRSF_FROZEN) { D_DEBUG_AT( Core_Layers, " -> FROZEN!\n" ); return DFB_OK; } shared = layer->shared; funcs = layer->funcs; if (surface) { if (flags & (CLRCF_SURFACE | CLRCF_WIDTH | CLRCF_HEIGHT | CLRCF_FORMAT)) { ret = region_buffer_lock( region, surface, CSBR_FRONT ); if (ret) return ret; dfb_surface_unlock( surface ); } D_ASSERT( region->surface_lock.buffer != NULL ); } else if (region->surface_lock.buffer) { D_MAGIC_ASSERT( region->surface_lock.buffer, CoreSurfaceBuffer ); dfb_surface_unlock_buffer( region->surface_lock.buffer->surface, ®ion->surface_lock ); } D_DEBUG_AT( Core_Layers, " => setting region of '%s'\n", shared->description.name ); /* Setup hardware. */ return funcs->SetRegion( layer, layer->driver_data, layer->layer_data, region->region_data, config, flags, surface, surface ? surface->palette : NULL, ®ion->surface_lock ); }
DFBResult dfb_layer_region_flip_update( CoreLayerRegion *region, const DFBRegion *update, DFBSurfaceFlipFlags flags ) { DFBResult ret = DFB_OK; DFBRegion rotated; CoreLayer *layer; CoreLayerContext *context; CoreSurface *surface; const DisplayLayerFuncs *funcs; if (update) D_DEBUG_AT( Core_Layers, "dfb_layer_region_flip_update( %p, %p, 0x%08x ) <- [%d, %d - %dx%d]\n", region, update, flags, DFB_RECTANGLE_VALS_FROM_REGION( update ) ); else D_DEBUG_AT( Core_Layers, "dfb_layer_region_flip_update( %p, %p, 0x%08x )\n", region, update, flags ); D_ASSERT( region != NULL ); D_ASSERT( region->context != NULL ); /* Lock the region. */ if (dfb_layer_region_lock( region )) return DFB_FUSION; D_ASSUME( region->surface != NULL ); /* Check for NULL surface. */ if (!region->surface) { D_DEBUG_AT( Core_Layers, " -> No surface => no update!\n" ); dfb_layer_region_unlock( region ); return DFB_UNSUPPORTED; } context = region->context; surface = region->surface; layer = dfb_layer_at( context->layer_id ); D_ASSERT( layer->funcs != NULL ); funcs = layer->funcs; /* Unfreeze region? */ if (D_FLAGS_IS_SET( region->state, CLRSF_FROZEN )) { D_FLAGS_CLEAR( region->state, CLRSF_FROZEN ); if (D_FLAGS_IS_SET( region->state, CLRSF_REALIZED )) { ret = set_region( region, ®ion->config, CLRCF_ALL, surface ); if (ret) D_DERROR( ret, "Core/LayerRegion: set_region() in dfb_layer_region_flip_update() failed!\n" ); } else if (D_FLAGS_ARE_SET( region->state, CLRSF_ENABLED | CLRSF_ACTIVE )) { ret = realize_region( region ); if (ret) D_DERROR( ret, "Core/LayerRegion: realize_region() in dfb_layer_region_flip_update() failed!\n" ); } if (ret) { dfb_layer_region_unlock( region ); return ret; } } /* Depending on the buffer mode... */ switch (region->config.buffermode) { case DLBM_TRIPLE: case DLBM_BACKVIDEO: /* Check if simply swapping the buffers is possible... */ if (!(flags & DSFLIP_BLIT) && !surface->rotation && (!update || (update->x1 == 0 && update->y1 == 0 && update->x2 == surface->config.size.w - 1 && update->y2 == surface->config.size.h - 1))) { D_DEBUG_AT( Core_Layers, " -> Going to swap buffers...\n" ); /* Use the driver's routine if the region is realized. */ if (D_FLAGS_IS_SET( region->state, CLRSF_REALIZED )) { D_ASSUME( funcs->FlipRegion != NULL ); ret = region_buffer_lock( region, surface, CSBR_BACK ); if (ret) { dfb_layer_region_unlock( region ); return ret; } D_DEBUG_AT( Core_Layers, " -> Flipping region using driver...\n" ); if (funcs->FlipRegion) ret = funcs->FlipRegion( layer, layer->driver_data, layer->layer_data, region->region_data, surface, flags, ®ion->surface_lock ); dfb_surface_unlock( surface ); } else { D_DEBUG_AT( Core_Layers, " -> Flipping region not using driver...\n" ); /* Just do the hardware independent work. */ dfb_surface_lock( surface ); dfb_surface_flip( surface, false ); dfb_surface_unlock( surface ); } break; } /* fall through */ case DLBM_BACKSYSTEM: D_DEBUG_AT( Core_Layers, " -> Going to copy portion...\n" ); if ((flags & DSFLIP_WAITFORSYNC) == DSFLIP_WAITFORSYNC) { D_DEBUG_AT( Core_Layers, " -> Waiting for VSync...\n" ); dfb_layer_wait_vsync( layer ); } D_DEBUG_AT( Core_Layers, " -> Copying content from back to front buffer...\n" ); /* ...or copy updated contents from back to front buffer. */ dfb_back_to_front_copy_rotation( surface, update, surface->rotation ); if ((flags & DSFLIP_WAITFORSYNC) == DSFLIP_WAIT) { D_DEBUG_AT( Core_Layers, " -> Waiting for VSync...\n" ); dfb_layer_wait_vsync( layer ); } /* fall through */ case DLBM_FRONTONLY: /* Tell the driver about the update if the region is realized. */ if (funcs->UpdateRegion && D_FLAGS_IS_SET( region->state, CLRSF_REALIZED )) { if (surface) { CoreSurfaceAllocation *allocation; allocation = region->surface_lock.allocation; D_ASSERT( allocation != NULL ); /* If hardware has written or is writing... */ if (allocation->accessed[CSAID_GPU] & CSAF_WRITE) { D_DEBUG_AT( Core_Layers, " -> Waiting for pending writes...\n" ); /* ...wait for the operation to finish. */ if (!(flags & DSFLIP_PIPELINE)) dfb_gfxcard_sync(); /* TODO: wait for serial instead */ allocation->accessed[CSAID_GPU] &= ~CSAF_WRITE; } dfb_surface_lock( surface ); dfb_surface_allocation_update( allocation, CSAF_READ ); dfb_surface_unlock( surface ); } D_DEBUG_AT( Core_Layers, " -> Notifying driver about updated content...\n" ); dfb_region_from_rotated( &rotated, update, &surface->config.size, surface->rotation ); ret = funcs->UpdateRegion( layer, layer->driver_data, layer->layer_data, region->region_data, surface, &rotated, ®ion->surface_lock ); } break; default: D_BUG("unknown buffer mode"); ret = DFB_BUG; } D_DEBUG_AT( Core_Layers, " -> done.\n" ); /* Unlock the region. */ dfb_layer_region_unlock( region ); return ret; }
static DFBResult set_region( CoreLayerRegion *region, CoreLayerRegionConfig *config, CoreLayerRegionConfigFlags flags, CoreSurface *surface ) { DFBResult ret = DFB_OK; CoreLayer *layer; const DisplayLayerFuncs *funcs; D_ASSERT( region != NULL ); D_ASSERT( region->context != NULL ); D_ASSERT( config != NULL ); D_ASSERT( config->buffermode != DLBM_WINDOWS ); D_ASSERT( D_FLAGS_IS_SET( region->state, CLRSF_REALIZED ) ); layer = dfb_layer_at( region->context->layer_id ); D_ASSERT( layer != NULL ); D_ASSERT( layer->funcs != NULL ); D_ASSERT( layer->funcs->SetRegion != NULL ); if (region->state & CLRSF_FROZEN) return DFB_OK; funcs = layer->funcs; if (surface) { if (flags & (CLRCF_SURFACE | CLRCF_WIDTH | CLRCF_HEIGHT | CLRCF_FORMAT)) { if (region->surface_lock.buffer) { CoreSurfaceBuffer *buffer = region->surface_lock.buffer; D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); if (surface == buffer->surface) { if (dfb_surface_lock( surface )) return DFB_FUSION; dfb_surface_buffer_unlock( ®ion->surface_lock ); buffer = dfb_surface_get_buffer( surface, CSBR_FRONT ); D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); ret = dfb_surface_buffer_lock( buffer, CSAF_CPU_READ | CSAF_GPU_READ, ®ion->surface_lock ); dfb_surface_unlock( surface ); } else { dfb_surface_unlock_buffer( buffer->surface, ®ion->surface_lock ); ret = dfb_surface_lock_buffer( surface, CSBR_FRONT, CSAF_CPU_READ | CSAF_GPU_READ, ®ion->surface_lock ); } } else ret = dfb_surface_lock_buffer( surface, CSBR_FRONT, CSAF_CPU_READ | CSAF_GPU_READ, ®ion->surface_lock ); } if (ret) { D_DERROR( ret, "Core/LayerRegion: Could not lock region surface for SetRegion()!\n" ); return ret; } D_ASSERT( region->surface_lock.buffer != NULL ); } else if (region->surface_lock.buffer) { D_MAGIC_ASSERT( region->surface_lock.buffer, CoreSurfaceBuffer ); dfb_surface_unlock_buffer( region->surface_lock.buffer->surface, ®ion->surface_lock ); } /* Setup hardware. */ return funcs->SetRegion( layer, layer->driver_data, layer->layer_data, region->region_data, config, flags, surface, surface ? surface->palette : NULL, ®ion->surface_lock ); }
DFBResult ISurface_Real__PreWriteBuffer( CoreSurface *obj, CoreSurfaceBuffer *buffer, const DFBRectangle *rect, CoreSurfaceAllocation **ret_allocation ) { DFBResult ret; CoreSurfaceAllocation *allocation; CoreSurface *surface = obj; bool allocated = false; D_DEBUG_AT( DirectFB_CoreSurface, "%s()\n", __FUNCTION__ ); D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); dfb_surface_lock( surface ); if (!buffer->surface) { dfb_surface_unlock( surface ); return DFB_BUFFEREMPTY; } /* Use last read allocation if it's up to date... */ if (buffer->read && direct_serial_check( &buffer->read->serial, &buffer->serial )) allocation = buffer->read; else { /* ...otherwise look for allocation with CPU access. */ allocation = dfb_surface_buffer_find_allocation( buffer, CSAID_CPU, CSAF_WRITE, false ); if (!allocation) { /* If no allocation exists, create one. */ ret = dfb_surface_pools_allocate( buffer, CSAID_CPU, CSAF_WRITE, &allocation ); if (ret) { D_DERROR( ret, "Core/SurfBuffer: Buffer allocation failed!\n" ); goto out; } allocated = true; } } CORE_SURFACE_ALLOCATION_ASSERT( allocation ); /* Synchronize with other allocations. */ ret = dfb_surface_allocation_update( allocation, CSAF_WRITE ); if (ret) { /* Destroy if newly created. */ if (allocated) dfb_surface_allocation_decouple( allocation ); goto out; } if (!(allocation->pool->desc.caps & CSPCAPS_WRITE)) { ret = dfb_surface_pool_prelock( allocation->pool, allocation, CSAID_CPU, CSAF_WRITE ); if (ret) { /* Destroy if newly created. */ if (allocated) dfb_surface_allocation_decouple( allocation ); goto out; } manage_interlocks( allocation, CSAID_CPU, CSAF_WRITE ); } dfb_surface_allocation_ref( allocation ); *ret_allocation = allocation; out: dfb_surface_unlock( surface ); return ret; }
DFBResult ISurface_Real__PreLockBuffer2( CoreSurface *obj, CoreSurfaceBufferRole role, CoreSurfaceAccessorID accessor, CoreSurfaceAccessFlags access, bool lock, CoreSurfaceAllocation **ret_allocation ) { DFBResult ret; CoreSurfaceBuffer *buffer; CoreSurfaceAllocation *allocation; CoreSurface *surface = obj; bool allocated = false; D_DEBUG_AT( DirectFB_CoreSurface, "%s( surface %p, role %d, accessor 0x%02x, access 0x%02x, %slock )\n", __FUNCTION__, surface, role, accessor, access, lock ? "" : "no " ); ret = (DFBResult) dfb_surface_lock( surface ); if (ret) return ret; if (surface->num_buffers < 1) { dfb_surface_unlock( surface ); return DFB_BUFFEREMPTY; } buffer = dfb_surface_get_buffer( surface, role ); D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); D_DEBUG_AT( DirectFB_CoreSurface, " -> buffer %p\n", buffer ); if (!lock && access & CSAF_READ) { if (fusion_vector_is_empty( &buffer->allocs )) { dfb_surface_unlock( surface ); return DFB_NOALLOCATION; } } /* Look for allocation with proper access. */ allocation = dfb_surface_buffer_find_allocation( buffer, accessor, access, lock ); if (!allocation) { /* If no allocation exists, create one. */ ret = dfb_surface_pools_allocate( buffer, accessor, access, &allocation ); if (ret) { if (ret != DFB_NOVIDEOMEMORY && ret != DFB_UNSUPPORTED) D_DERROR( ret, "Core/SurfBuffer: Buffer allocation failed!\n" ); goto out; } allocated = true; } CORE_SURFACE_ALLOCATION_ASSERT( allocation ); /* Synchronize with other allocations. */ ret = dfb_surface_allocation_update( allocation, access ); if (ret) { /* Destroy if newly created. */ if (allocated) dfb_surface_allocation_decouple( allocation ); goto out; } if (!lock) { if (access & CSAF_WRITE) { if (!(allocation->pool->desc.caps & CSPCAPS_WRITE)) lock = true; } else if (access & CSAF_READ) { if (!(allocation->pool->desc.caps & CSPCAPS_READ)) lock = true; } } if (lock) { ret = dfb_surface_pool_prelock( allocation->pool, allocation, accessor, access ); if (ret) { /* Destroy if newly created. */ if (allocated) dfb_surface_allocation_decouple( allocation ); goto out; } manage_interlocks( allocation, accessor, access ); } dfb_surface_allocation_ref( allocation ); *ret_allocation = allocation; out: dfb_surface_unlock( surface ); return ret; }
DFBResult ISurface_Real__PreLockBuffer( CoreSurface *obj, CoreSurfaceBuffer *buffer, CoreSurfaceAccessorID accessor, CoreSurfaceAccessFlags access, CoreSurfaceAllocation **ret_allocation ) { DFBResult ret; CoreSurfaceAllocation *allocation; CoreSurface *surface = obj; bool allocated = false; D_DEBUG_AT( DirectFB_CoreSurface, "%s()\n", __FUNCTION__ ); D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); dfb_surface_lock( surface ); if (!buffer->surface) { dfb_surface_unlock( surface ); return DFB_BUFFEREMPTY; } /* Look for allocation with proper access. */ allocation = dfb_surface_buffer_find_allocation( buffer, accessor, access, true ); if (!allocation) { /* If no allocation exists, create one. */ ret = dfb_surface_pools_allocate( buffer, accessor, access, &allocation ); if (ret) { if (ret != DFB_NOVIDEOMEMORY && ret != DFB_UNSUPPORTED) D_DERROR( ret, "Core/SurfBuffer: Buffer allocation failed!\n" ); goto out; } allocated = true; } CORE_SURFACE_ALLOCATION_ASSERT( allocation ); /* Synchronize with other allocations. */ ret = dfb_surface_allocation_update( allocation, access ); if (ret) { /* Destroy if newly created. */ if (allocated) dfb_surface_allocation_decouple( allocation ); goto out; } ret = dfb_surface_pool_prelock( allocation->pool, allocation, accessor, access ); if (ret) { /* Destroy if newly created. */ if (allocated) dfb_surface_allocation_decouple( allocation ); goto out; } manage_interlocks( allocation, accessor, access ); dfb_surface_allocation_ref( allocation ); *ret_allocation = allocation; out: dfb_surface_unlock( surface ); return ret; }