static DFBResult x11DeallocateBuffer( CoreSurfacePool *pool, void *pool_data, void *pool_local, CoreSurfaceBuffer *buffer, CoreSurfaceAllocation *allocation, void *alloc_data ) { x11AllocationData *alloc = alloc_data; x11PoolLocalData *local = pool_local; DFBX11 *x11 = local->x11; DFBX11Shared *shared = x11->shared; D_DEBUG_AT( X11_Surfaces, "%s()\n", __FUNCTION__ ); D_MAGIC_ASSERT( pool, CoreSurfacePool ); D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); CORE_SURFACE_ALLOCATION_ASSERT( allocation ); if (alloc->ptr) SHFREE( shared->data_shmpool, alloc->ptr ); return DFB_OK; }
static DFBResult allocate_transfer( CoreSurfacePoolBridge *bridge, CoreSurfaceBuffer *buffer, CoreSurfaceAllocation *from, CoreSurfaceAllocation *to, const DFBRectangle *rects, unsigned int num_rects, CoreSurfacePoolTransfer **ret_transfer ) { CoreSurfacePoolTransfer *transfer; unsigned int alloc_size; D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge ); D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); CORE_SURFACE_ALLOCATION_ASSERT( from ); CORE_SURFACE_ALLOCATION_ASSERT( to ); D_ASSERT( rects != NULL ); D_ASSERT( num_rects > 0 ); D_ASSERT( ret_transfer != NULL ); alloc_size = sizeof(CoreSurfacePoolTransfer) + num_rects * sizeof(DFBRectangle) + bridge->transfer_data_size; transfer = SHCALLOC( bridge->shmpool, 1, alloc_size ); if (!transfer) return D_OOSHM(); transfer->bridge = bridge; transfer->buffer = buffer; transfer->from = from; transfer->to = to; transfer->rects = (DFBRectangle*)(transfer + 1); if (bridge->transfer_data_size) transfer->data = transfer->rects + num_rects; transfer->num_rects = num_rects; direct_memcpy( transfer->rects, rects, num_rects * sizeof(DFBRectangle) ); D_MAGIC_SET( transfer, CoreSurfacePoolTransfer ); *ret_transfer = transfer; return DFB_OK; }
static DFBResult x11DeallocateBuffer( CoreSurfacePool *pool, void *pool_data, void *pool_local, CoreSurfaceBuffer *buffer, CoreSurfaceAllocation *allocation, void *alloc_data ) { x11AllocationData *alloc = alloc_data; x11PoolLocalData *local = pool_local; DFBX11 *x11 = local->x11; DFBX11Shared *shared = x11->shared; void *addr; D_DEBUG_AT( X11_Surfaces, "%s()\n", __FUNCTION__ ); D_MAGIC_ASSERT( pool, CoreSurfacePool ); CORE_SURFACE_ALLOCATION_ASSERT( allocation ); switch (alloc->type) { case X11_ALLOC_PIXMAP: case X11_ALLOC_WINDOW: if (allocation->type & CSTF_PREALLOCATED) { // don't delete } else XFreePixmap( x11->display, alloc->xid ); break; case X11_ALLOC_IMAGE: x11ImageDestroy( x11, &alloc->image ); // FIXME: also detach in other processes! (e.g. via reactor) addr = direct_hash_lookup( local->hash, alloc->image.seginfo.shmid ); if (addr) { x11ImageDetach( &alloc->image, addr ); direct_hash_remove( local->hash, alloc->image.seginfo.shmid ); } break; case X11_ALLOC_SHM: if (alloc->ptr) SHFREE( shared->data_shmpool, alloc->ptr ); break; default: D_BUG( "unexpected allocation type %d\n", alloc->type ); return DFB_BUG; } return DFB_OK; }
static DFBResult x11DeallocateBuffer( CoreSurfacePool *pool, void *pool_data, void *pool_local, CoreSurfaceBuffer *buffer, CoreSurfaceAllocation *allocation, void *alloc_data ) { x11AllocationData *alloc = alloc_data; x11PoolLocalData *local = pool_local; DFBX11 *x11 = local->x11; DFBX11Shared *shared = x11->shared; void *addr; D_DEBUG_AT( X11_Surfaces, "%s()\n", __FUNCTION__ ); D_MAGIC_ASSERT( pool, CoreSurfacePool ); CORE_SURFACE_ALLOCATION_ASSERT( allocation ); // FIXME: also detach in other processes! (e.g. via reactor) addr = direct_hash_lookup( local->hash, alloc->image.seginfo.shmid ); if (addr) { x11ImageDetach( &alloc->image, addr ); direct_hash_remove( local->hash, alloc->image.seginfo.shmid ); } if (alloc->real) return x11ImageDestroy( x11, &alloc->image ); if (alloc->ptr) SHFREE( shared->data_shmpool, alloc->ptr ); return DFB_OK; }
static DFBResult prealloc_transfer_readwrite( CoreSurface *surface, CoreSurfacePoolTransfer *transfer, CoreSurfaceAllocation *alloc, CoreSurfaceAccessFlags flags, CoreSlave *slave ) { DFBResult ret = DFB_OK; int index; int i, y; D_MAGIC_ASSERT( surface, CoreSurface ); D_ASSERT( transfer != NULL ); CORE_SURFACE_ALLOCATION_ASSERT( alloc ); index = dfb_surface_buffer_index( alloc->buffer ); D_DEBUG_AT( PreAlloc_Bridge, "%s()\n", __FUNCTION__ ); D_DEBUG_AT( PreAlloc_Bridge, " ->Transfer read/write %s Fusion ID %lu (index %d)\n", (flags & CSAF_WRITE) ? "from" : "to", surface->object.identity, index ); for (i=0; i<transfer->num_rects; i++) { const DFBRectangle *rect = &transfer->rects[i]; int offset = DFB_BYTES_PER_LINE( surface->config.format, rect->x ); int length = DFB_BYTES_PER_LINE( surface->config.format, rect->w ); u8 *temp = alloca( length ); // FIXME for (y=0; y<rect->h; y++) { DFBRectangle lrect = { rect->x, rect->y + y, rect->w, 1 }; if (flags & CSAF_WRITE) { ret = CoreSlave_GetData( slave, surface->config.preallocated[index].addr + (rect->y + y) * surface->config.preallocated[index].pitch + offset, length, temp ); if (ret) break; ret = dfb_surface_pool_write( alloc->pool, alloc, temp, length, &lrect ); } else { ret = dfb_surface_pool_read( alloc->pool, alloc, temp, length, &lrect ); if (ret) break; ret = CoreSlave_PutData( slave, surface->config.preallocated[index].addr + (rect->y + y) * surface->config.preallocated[index].pitch + offset, length, temp ); } if (ret) break; } if (ret) break; } return ret; }
static DFBResult prealloc_transfer_locked( CoreSurface *surface, CoreSurfacePoolTransfer *transfer, CoreSurfaceAllocation *locked, CoreSurfaceAccessFlags flags, CoreSlave *slave ) { DFBResult ret; CoreSurfaceBufferLock lock; int index; int i, y; D_MAGIC_ASSERT( surface, CoreSurface ); D_ASSERT( transfer != NULL ); CORE_SURFACE_ALLOCATION_ASSERT( locked ); index = dfb_surface_buffer_index( locked->buffer ); D_DEBUG_AT( PreAlloc_Bridge, "%s()\n", __FUNCTION__ ); D_DEBUG_AT( PreAlloc_Bridge, " -> Transfer locked %s Fusion ID %lu (index %d)\n", (flags & CSAF_WRITE) ? "from" : "to", surface->object.identity, index ); dfb_surface_buffer_lock_init( &lock, CSAID_CPU, flags ); ret = dfb_surface_pool_lock( locked->pool, locked, &lock ); if (ret) { dfb_surface_buffer_lock_deinit( &lock ); return ret; } for (i=0; i<transfer->num_rects; i++) { const DFBRectangle *rect = &transfer->rects[i]; int offset = DFB_BYTES_PER_LINE( surface->config.format, rect->x ); int length = DFB_BYTES_PER_LINE( surface->config.format, rect->w ); for (y=0; y<rect->h; y++) { if (flags & CSAF_WRITE) ret = CoreSlave_GetData( slave, surface->config.preallocated[index].addr + (rect->y + y) * surface->config.preallocated[index].pitch + offset, length, lock.addr + (rect->y + y) * lock.pitch + offset ); else ret = CoreSlave_PutData( slave, surface->config.preallocated[index].addr + (rect->y + y) * surface->config.preallocated[index].pitch + offset, length, lock.addr + (rect->y + y) * lock.pitch + offset ); if (ret) break; } if (ret) break; } dfb_surface_pool_unlock( locked->pool, locked, &lock ); dfb_surface_buffer_lock_deinit( &lock ); return ret; }
DFBResult dfb_surface_pool_bridges_transfer( CoreSurfaceBuffer *buffer, CoreSurfaceAllocation *from, CoreSurfaceAllocation *to, const DFBRectangle *rects, unsigned int num_rects ) { DFBResult ret; int i; DFBRectangle rect; CoreSurfacePoolBridge *bridge = NULL; const SurfacePoolBridgeFuncs *funcs; CoreSurfacePoolTransfer *transfer; D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); CORE_SURFACE_ALLOCATION_ASSERT( from ); CORE_SURFACE_ALLOCATION_ASSERT( to ); D_ASSERT( rects != NULL || num_rects == 0 ); D_ASSERT( num_rects > 0 || rects == NULL ); D_DEBUG_AT( Core_SurfPoolBridge, "%s( %p [%dx%d %s], %p -> %p, %d rects )\n", __FUNCTION__, buffer, buffer->config.size.w, buffer->config.size.h, dfb_pixelformat_name( buffer->format ), from, to, num_rects ); if (!rects) { rect.x = rect.y = 0; rect.w = buffer->config.size.w; rect.h = buffer->config.size.h; rects = ▭ num_rects = 1; } for (i=0; i<bridge_count; i++) { D_ASSERT( bridge_order[i] >= 0 ); D_ASSERT( bridge_order[i] < bridge_count ); bridge = bridge_array[bridge_order[i]]; D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge ); funcs = get_funcs( bridge ); D_ASSERT( funcs->CheckTransfer != NULL ); ret = funcs->CheckTransfer( bridge, bridge->data, get_local(bridge), buffer, from, to ); if (ret) bridge = NULL; else break; } if (!bridge) return DFB_UNSUPPORTED; D_DEBUG_AT( Core_SurfPoolBridge, " -> using '%s'\n", bridge->desc.name ); ret = allocate_transfer( bridge, buffer, from, to, rects, num_rects, &transfer ); if (ret) return ret; D_ASSERT( funcs->StartTransfer != NULL ); D_DEBUG_AT( Core_SurfPoolBridge, " -> start...\n" ); ret = funcs->StartTransfer( bridge, bridge->data, get_local(bridge), transfer, transfer->data ); if (ret) D_DERROR( ret, "Core/SurfacePoolBridge: Starting transfer via '%s' failed!\n", bridge->desc.name ); else if (funcs->FinishTransfer) { D_DEBUG_AT( Core_SurfPoolBridge, " -> finish...\n" ); ret = funcs->FinishTransfer( bridge, bridge->data, get_local(bridge), transfer, transfer->data ); if (ret) D_DERROR( ret, "Core/SurfacePoolBridge: Finishing transfer via '%s' failed!\n", bridge->desc.name ); } D_DEBUG_AT( Core_SurfPoolBridge, " => %s\n", DirectResultString(ret) ); deallocate_transfer( transfer ); return ret; }
static DFBResult x11DeallocateBuffer( CoreSurfacePool *pool, void *pool_data, void *pool_local, CoreSurfaceBuffer *buffer, CoreSurfaceAllocation *allocation, void *alloc_data ) { DFBResult ret = DFB_OK; x11AllocationData *alloc = alloc_data; x11PoolLocalData *local = pool_local; DFBX11 *x11 = local->x11; D_DEBUG_AT( X11_Surfaces, "%s()\n", __FUNCTION__ ); D_MAGIC_ASSERT( pool, CoreSurfacePool ); CORE_SURFACE_ALLOCATION_ASSERT( allocation ); XLockDisplay( x11->display ); if (alloc->gc) XFreeGC( x11->display, alloc->gc ); switch (alloc->type) { case X11_ALLOC_WINDOW: D_ASSUME( x11->showing != alloc->window ); if (x11->showing == alloc->window) { D_LOG( X11_Surfaces, VERBOSE, " -> Hiding window 0x%08lx that is to be destroyed!!!\n", x11->showing ); XUnmapWindow( x11->display, x11->showing ); x11->showing = 0; } case X11_ALLOC_PIXMAP: if (allocation->type & CSTF_PREALLOCATED) { // don't delete } else if (alloc->created) { if (alloc->xid != alloc->window) { D_INFO( "X11/Windows: Free Pixmap 0x%08lx\n", alloc->xid ); XFreePixmap( x11->display, alloc->xid ); } if (alloc->window) { D_INFO( "X11/Windows: Destroy Window 0x%08lx\n", alloc->window ); XDestroyWindow( x11->display, alloc->window ); } } break; default: D_BUG( "unexpected allocation type %d\n", alloc->type ); ret = DFB_BUG; } XUnlockDisplay( x11->display ); return ret; }
static DFBResult update_screen( DFBX11 *x11, const DFBRectangle *clip, CoreSurfaceBufferLock *lock, XWindow *xw ) { void *dst; void *src; unsigned int offset = 0; XImage *ximage; CoreSurface *surface; CoreSurfaceAllocation *allocation; DFBX11Shared *shared; DFBRectangle rect; bool direct = false; D_ASSERT( x11 != NULL ); DFB_RECTANGLE_ASSERT( clip ); D_DEBUG_AT( X11_Update, "%s( %4d,%4d-%4dx%4d )\n", __FUNCTION__, DFB_RECTANGLE_VALS( clip ) ); CORE_SURFACE_BUFFER_LOCK_ASSERT( lock ); shared = x11->shared; D_ASSERT( shared != NULL ); XLockDisplay( x11->display ); if (!xw) { XUnlockDisplay( x11->display ); return DFB_OK; } allocation = lock->allocation; CORE_SURFACE_ALLOCATION_ASSERT( allocation ); surface = allocation->surface; D_ASSERT( surface != NULL ); rect.x = rect.y = 0; rect.w = xw->width; rect.h = xw->height; if (!dfb_rectangle_intersect( &rect, clip )) { XUnlockDisplay( x11->display ); return DFB_OK; } D_DEBUG_AT( X11_Update, " -> %4d,%4d-%4dx%4d\n", DFB_RECTANGLE_VALS( &rect ) ); #ifdef USE_GLX /* Check for GLX allocation... */ if (allocation->pool == shared->glx_pool && lock->handle) { LocalPixmap *pixmap = lock->handle; D_MAGIC_ASSERT( pixmap, LocalPixmap ); /* ...and just call SwapBuffers... */ //D_DEBUG_AT( X11_Update, " -> Calling glXSwapBuffers( 0x%lx )...\n", alloc->drawable ); //glXSwapBuffers( x11->display, alloc->drawable ); D_DEBUG_AT( X11_Update, " -> Copying from GLXPixmap...\n" ); glXWaitGL(); XCopyArea( x11->display, pixmap->pixmap, xw->window, xw->gc, rect.x, rect.y, rect.w, rect.h, rect.x, rect.y ); glXWaitX(); XUnlockDisplay( x11->display ); return DFB_OK; } #endif /* Check for our special native allocation... */ if (allocation->pool == shared->x11image_pool && lock->handle) { x11Image *image = lock->handle; D_MAGIC_ASSERT( image, x11Image ); /* ...and directly XShmPutImage from that. */ ximage = image->ximage; direct = true; } else { /* ...or copy or convert into XShmImage or XImage allocated with the XWindow. */ ximage = xw->ximage; offset = xw->ximage_offset; xw->ximage_offset = (offset ? 0 : ximage->height / 2); /* make sure the 16-bit input formats are properly 2-pixel-clipped */ switch (surface->config.format) { case DSPF_I420: case DSPF_YV12: case DSPF_NV12: case DSPF_NV21: if (rect.y & 1) { rect.y--; rect.h++; } /* fall through */ case DSPF_YUY2: case DSPF_UYVY: case DSPF_NV16: if (rect.x & 1) { rect.x--; rect.w++; } default: /* no action */ break; } dst = xw->virtualscreen + rect.x * xw->bpp + (rect.y + offset) * ximage->bytes_per_line; src = lock->addr + DFB_BYTES_PER_LINE( surface->config.format, rect.x ) + rect.y * lock->pitch; switch (xw->depth) { case 32: dfb_convert_to_argb( surface->config.format, src, lock->pitch, surface->config.size.h, dst, ximage->bytes_per_line, rect.w, rect.h ); break; case 24: dfb_convert_to_rgb32( surface->config.format, src, lock->pitch, surface->config.size.h, dst, ximage->bytes_per_line, rect.w, rect.h ); break; case 16: if (surface->config.format == DSPF_LUT8) { int width = rect.w; int height = rect.h; const u8 *src8 = src; u16 *dst16 = dst; CorePalette *palette = surface->palette; int x; while (height--) { for (x=0; x<width; x++) { DFBColor color = palette->entries[src8[x]]; dst16[x] = PIXEL_RGB16( color.r, color.g, color.b ); } src8 += lock->pitch; dst16 += ximage->bytes_per_line / 2; } } else { dfb_convert_to_rgb16( surface->config.format, src, lock->pitch, surface->config.size.h, dst, ximage->bytes_per_line, rect.w, rect.h ); } break; case 15: dfb_convert_to_rgb555( surface->config.format, src, lock->pitch, surface->config.size.h, dst, ximage->bytes_per_line, rect.w, rect.h ); break; default: D_ONCE( "unsupported depth %d", xw->depth ); } } D_ASSERT( ximage != NULL ); /* Wait for previous data to be processed... */ XSync( x11->display, False ); /* ...and immediately queue or send the next! */ if (x11->use_shm) { /* Just queue the command, it's XShm :) */ XShmPutImage( xw->display, xw->window, xw->gc, ximage, rect.x, rect.y + offset, rect.x, rect.y, rect.w, rect.h, False ); /* Make sure the queue has really happened! */ XFlush( x11->display ); } else /* Initiate transfer of buffer... */ XPutImage( xw->display, xw->window, xw->gc, ximage, rect.x, rect.y + offset, rect.x, rect.y, rect.w, rect.h ); /* Wait for display if single buffered and not converted... */ if (direct && !(surface->config.caps & DSCAPS_FLIPPING)) XSync( x11->display, False ); XUnlockDisplay( x11->display ); return DFB_OK; }
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; }