StretRegion * stret_iteration_next( StretIteration *iteration, const DFBRegion *clip ) { int index; int level; StretRegion *region; D_MAGIC_ASSERT( iteration, StretIteration ); DFB_REGION_ASSERT_IF( clip ); if (clip) D_DEBUG_AT( UniQuE_StReT, "stret_iteration_next( %d, %d - %dx%d )\n", DFB_RECTANGLE_VALS_FROM_REGION( clip ) ); else D_DEBUG_AT( UniQuE_StReT, "stret_iteration_next()\n" ); while (iteration->frame >= 0) { StretIterationStackFrame *frame = &iteration->stack[iteration->frame]; region = frame->region; level = frame->level; index = frame->index--; D_MAGIC_ASSERT( region, StretRegion ); D_DEBUG_AT( UniQuE_StReT, " -> (%d) %p, level [%d/%d], index %d\n", iteration->frame, region, level, region->levels - 1, index ); if (iteration->abort && region == iteration->abort) { D_MAGIC_CLEAR( iteration ); return NULL; } if (index < 0) { level = --frame->level; if (level < 0) { iteration->frame--; iteration->x0 -= region->bounds.x1; iteration->y0 -= region->bounds.y1; if (accept_region( region, iteration->x0, iteration->y0, clip )) return region; } else { frame->index = fusion_vector_size( ®ion->children[level] ) - 1; } } else { region = fusion_vector_at( ®ion->children[level], index ); D_MAGIC_ASSERT( region, StretRegion ); if (iteration->abort && region == iteration->abort) { D_MAGIC_CLEAR( iteration ); return NULL; } if (accept_region( region, iteration->x0, iteration->y0, clip )) { level = region->levels - 1; while (fusion_vector_is_empty( ®ion->children[level] )) { if (level) level--; else return region; } if (check_depth( iteration->frame + 1 )) { frame = &iteration->stack[++iteration->frame]; iteration->x0 += region->bounds.x1; iteration->y0 += region->bounds.y1; frame->region = region; frame->level = level; frame->index = fusion_vector_size( ®ion->children[level] ) - 1; continue; } return region; } } } D_ASSUME( iteration->x0 == 0 ); D_ASSUME( iteration->y0 == 0 ); D_MAGIC_CLEAR( iteration ); return NULL; }
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; }