예제 #1
0
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( &region->children[level] ) - 1;
               }
          }
          else {
               region = fusion_vector_at( &region->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( &region->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( &region->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;
}