Exemple #1
0
static DFBResult
update_screen( CoreSurface *surface, int x, int y, int w, int h )
{
     DFBResult              ret;
     void                  *src;
     CoreSurfaceBufferLock  lock;

     D_ASSERT( surface != NULL );

     ret = dfb_surface_lock_buffer( surface, CSBR_FRONT, CSAF_CPU_READ, &lock );
     if (ret) {
          D_DERROR( ret, "DirectFB/RTD: Couldn't lock layer surface!\n" );
          return ret;
     }

     src = lock.addr; /* + DFB_BYTES_PER_LINE( surface->config.format, x ) + y * lock.pitch;*/


     switch(surface->config.format) {
     case DSPF_RGB16:
       libk_copyrect_16(src, lock.pitch, x, y, w, h);
       break;
     case DSPF_RGB32:
     case DSPF_ARGB:
       libk_copyrect_32(src, lock.pitch, x, y, w, h);
       break;
     default:
       printf("bad pixel format %d\n", surface->config.format);
       break;
     }

     dfb_surface_unlock_buffer( surface, &lock );

     return DFB_OK;
}
Exemple #2
0
static DFBResult
unrealize_region( CoreLayerRegion *region )
{
     DFBResult                ret;
     int                      index;
     CoreLayer               *layer;
     CoreLayerShared         *shared;
     const DisplayLayerFuncs *funcs;

     D_ASSERT( region != NULL );
     D_ASSERT( region->context != NULL );
     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 );

     shared = layer->shared;
     funcs  = layer->funcs;

     D_ASSERT( fusion_vector_contains( &shared->added_regions, region ) );

     index = fusion_vector_index_of( &shared->added_regions, region );

     D_DEBUG_AT( Core_Layers, "Removing region (%d, %d - %dx%d) from '%s'.\n",
                 DFB_RECTANGLE_VALS( &region->config.dest ), shared->description.name );

     /* Remove the region from hardware and driver. */
     if (funcs->RemoveRegion) {
          ret = funcs->RemoveRegion( layer, layer->driver_data,
                                     layer->layer_data, region->region_data );
          if (ret) {
               D_DERROR( ret, "Core/Layers: Could not remove region!\n" );
               return ret;
          }
     }

     /* Remove the region from the 'added' list. */
     fusion_vector_remove( &shared->added_regions, index );

     /* Deallocate the driver's region data. */
     if (region->region_data) {
          SHFREE( shared->shmpool, region->region_data );
          region->region_data = NULL;
     }

     /* Update the region's state. */
     D_FLAGS_CLEAR( region->state, CLRSF_REALIZED );
     D_FLAGS_SET( region->state, CLRSF_FROZEN );

     if (region->surface && region->surface_lock.buffer) {
          dfb_surface_unlock_buffer( region->surface, &region->surface_lock );
          dfb_surface_destroy_buffers( region->surface );
     }

     return DFB_OK;
}
Exemple #3
0
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, &region->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, &region->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;
}
Exemple #4
0
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, &region->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, &region->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;
}
static DFBResult
IDirectFBImageProvider_GIF_RenderTo( IDirectFBImageProvider *thiz,
                                     IDirectFBSurface       *destination,
                                     const DFBRectangle     *dest_rect )
{
     DFBResult              ret;
     DFBRegion              clip;
     DFBRectangle           rect;
     DFBSurfacePixelFormat  format;
     IDirectFBSurface_data *dst_data;
     CoreSurface           *dst_surface;

     DIRECT_INTERFACE_GET_DATA (IDirectFBImageProvider_GIF)

     dst_data = (IDirectFBSurface_data*) destination->priv;
     if (!dst_data)
          return DFB_DEAD;

     dst_surface = dst_data->surface;
     if (!dst_surface)
          return DFB_DESTROYED;

     dfb_region_from_rectangle( &clip, &dst_data->area.current );

     if (dest_rect) {
          if (dest_rect->w < 1 || dest_rect->h < 1)
               return DFB_INVARG;
          rect = *dest_rect;
          rect.x += dst_data->area.wanted.x;
          rect.y += dst_data->area.wanted.y;
     }
     else {
          rect = dst_data->area.wanted;
     }

     ret = destination->GetPixelFormat( destination, &format );
     if (ret)
          return ret;

     /* actual loading and rendering */
     if (dfb_rectangle_region_intersects( &rect, &clip )) {
          CoreSurfaceBufferLock lock;

          ret = dfb_surface_lock_buffer( dst_surface, CSBR_BACK, CSAID_CPU, CSAF_WRITE, &lock );
          if (ret)
               return ret;

          dfb_scale_linear_32( data->image, data->image_width, data->image_height,
                               lock.addr, lock.pitch, &rect, dst_surface, &clip );

          dfb_surface_unlock_buffer( dst_surface, &lock );

          if (data->base.render_callback) {
               DIRenderCallbackResult r;

               rect.x = 0;
               rect.y = 0;
               rect.w = data->image_width;
               rect.h = data->image_height;

               r = data->base.render_callback( &rect,
                                               data->base.render_callback_context );

               if (r != DIRCR_OK)
                       return DFB_INTERRUPTED;
          }
     }

     return DFB_OK;
}
static DFBResult
IDirectFBImageProvider_JPEG2000_RenderTo( IDirectFBImageProvider *thiz,
                                          IDirectFBSurface       *destination,
                                          const DFBRectangle     *dest_rect )
{
     IDirectFBSurface_data  *dst_data;
     CoreSurface            *dst_surface;
     CoreSurfaceBufferLock   lock;
     DFBRectangle            rect;
     DFBRegion               clip;
     DIRenderCallbackResult  cb_result = DIRCR_OK;
     DFBResult               ret       = DFB_OK;
     
     DIRECT_INTERFACE_GET_DATA( IDirectFBImageProvider_JPEG2000 )
     
     if (!destination)
          return DFB_INVARG;
          
     dst_data = destination->priv;
     if (!dst_data || !dst_data->surface)
          return DFB_DESTROYED;
          
     dst_surface = dst_data->surface;
     
     if (dest_rect) {
          if (dest_rect->w < 1 || dest_rect->h < 1)
               return DFB_INVARG;
          rect = *dest_rect;
          rect.x += dst_data->area.wanted.x;
          rect.y += dst_data->area.wanted.y;
     }
     else {
          rect = dst_data->area.wanted;
     }
     
     dfb_region_from_rectangle( &clip, &dst_data->area.current );
     if (!dfb_rectangle_region_intersects( &rect, &clip ))
          return DFB_OK;

     ret = dfb_surface_lock_buffer( dst_surface, CSBR_BACK, CSAID_CPU, CSAF_WRITE, &lock );
     if (ret)
          return ret;
     
     if (!data->buf) {
          int  cmptlut[3];
          int  width, height;
          int  tlx, tly;
          int  hs, vs;
          int  i, j;
          bool direct, mono;
     
          if (jas_image_numcmpts(data->image) > 1) {
               cmptlut[0] = jas_image_getcmptbytype(data->image,
                              JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R));
               cmptlut[1] = jas_image_getcmptbytype(data->image,
                              JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G));
               cmptlut[2] = jas_image_getcmptbytype(data->image,
                              JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B));
               if (cmptlut[0] < 0 || cmptlut[1] < 0 || cmptlut[2] < 0) {
                    dfb_surface_unlock_buffer( dst_surface, &lock );
                    return DFB_UNSUPPORTED;
               }
               mono = false;
          }
          else {
               cmptlut[0] = cmptlut[1] = cmptlut[2] = 0;
               mono = true;
          }
     
          width = jas_image_width(data->image);
          height = jas_image_height(data->image);
          tlx = jas_image_cmpttlx(data->image, 0);
          tly = jas_image_cmpttly(data->image, 0);
          hs = jas_image_cmpthstep(data->image, 0);
          vs = jas_image_cmptvstep(data->image, 0);
          
          data->buf = D_MALLOC( width*height*4 );
          if (!data->buf) {
               dfb_surface_unlock_buffer( dst_surface, &lock );
               return D_OOM();
          }
          
          direct = (rect.w == width && rect.h == height && data->render_callback);
          
#define GET_SAMPLE( n, x, y ) ({ \
     int _s; \
     _s = jas_image_readcmptsample(data->image, cmptlut[n], x, y); \
     _s >>= jas_image_cmptprec(data->image, cmptlut[n]) - 8; \
     if (_s > 255) \
          _s = 255; \
     else if (_s < 0) \
          _s = 0; \
     _s; \
})
            
          for (i = 0; i < height; i++) {
               u32 *dst = data->buf + i * width;
               int  x, y;
               
               y = (i - tly) / vs;
               if (y >= 0 && y < height) {     
                    for (j = 0; j < width; j++) {
                         x = (j - tlx) / hs;
                         if (x >= 0 && x < width) {
                              unsigned int r, g, b;
                              if (mono) {
                                   r = g = b = GET_SAMPLE(0, x, y);
                              }
                              else {
                                   r = GET_SAMPLE(0, x, y);
                                   g = GET_SAMPLE(1, x, y);
                                   b = GET_SAMPLE(2, x, y);
                              }
                              *dst++ = 0xff000000 | (r << 16) | (g << 8) | b;
                         }
                         else {
                              *dst++ = 0;
                         }
                    }
               }
               else {
                    memset( dst, 0, width*4 );
               }
               
               if (direct) {
                    DFBRectangle r = { rect.x, rect.y+i, width, 1 };
                    
                    dfb_copy_buffer_32( data->buf + i*width,
                                        lock.addr, lock.pitch, &r, dst_surface, &clip );
                    
                    if (data->render_callback) {                    
                         r = (DFBRectangle) { 0, i, width, 1 };
                         cb_result = data->render_callback( &r, data->render_callback_ctx );
                         if (cb_result != DIRCR_OK)
                              break;
                    }
               }
          }
          
          if (!direct) {
               dfb_scale_linear_32( data->buf, width, height,
                                    lock.addr, lock.pitch, &rect, dst_surface, &clip );

               if (data->render_callback) {
                    DFBRectangle r = { 0, 0, width, height };
                    data->render_callback( &r, data->render_callback_ctx );
               }
          }
          
          if (cb_result != DIRCR_OK) {
               D_FREE( data->buf );
               data->buf = NULL;
               ret = DFB_INTERRUPTED;
          }
     }
     else {
          int width  = jas_image_width(data->image);
          int height = jas_image_height(data->image);
          
          dfb_scale_linear_32( data->buf, width, height,
                               lock.addr, lock.pitch, &rect, dst_surface, &clip );
          
          if (data->render_callback) {
               DFBRectangle r = {0, 0, width, height};
               data->render_callback( &r, data->render_callback_ctx );
          }
     }
     
     dfb_surface_unlock_buffer( dst_surface, &lock );
     
     return ret;
}
static DFBResult
IDirectFBImageProvider_MPEG2_RenderTo( IDirectFBImageProvider *thiz,
                                       IDirectFBSurface       *destination,
                                       const DFBRectangle     *dest_rect )
{
     DFBResult              ret;
     IDirectFBSurface_data *dst_data;
     CoreSurface           *dst_surface;
     DFBRegion              clip;
     DFBRectangle           rect;

     DIRECT_INTERFACE_GET_DATA (IDirectFBImageProvider_MPEG2)

     dst_data = (IDirectFBSurface_data*) destination->priv;
     if (!dst_data)
          return DFB_DEAD;

     dst_surface = dst_data->surface;
     if (!dst_surface)
          return DFB_DESTROYED;

     dfb_region_from_rectangle( &clip, &dst_data->area.current );

     if (dest_rect) {
          if (dest_rect->w < 1 || dest_rect->h < 1)
               return DFB_INVARG;
          rect = *dest_rect;
          rect.w += dst_data->area.wanted.w;
          rect.h += dst_data->area.wanted.h;
     }
     else {
          rect = dst_data->area.wanted;
     }

     switch (data->stage) {
          case STAGE_END:
               break;
          case STAGE_IMAGE:
               if (MPEG2_Decode( data->dec, mpeg2_write_func, data )) {
                    data->stage = STAGE_ERROR;
                    return DFB_FAILURE;
               }
               data->stage = STAGE_END;
               break;
          default:
               return DFB_FAILURE;
     }

     /* actual rendering */
     if (dfb_rectangle_region_intersects( &rect, &clip )) {
          CoreSurfaceBufferLock lock;

          ret = dfb_surface_lock_buffer( dst_surface, CSBR_BACK, CSAID_CPU, CSAF_WRITE, &lock );
          if (ret)
               return ret;

          dfb_scale_linear_32( data->image, data->width, data->height,
                               lock.addr, lock.pitch, &rect, dst_surface, &clip );

          dfb_surface_unlock_buffer( dst_surface, &lock );
     }

     return DFB_OK;
}
static DFBResult
IDirectFBImageProvider_ANDROID_RenderTo( IDirectFBImageProvider *thiz,
                                         IDirectFBSurface       *destination,
                                         const DFBRectangle     *dest_rect )
{
     DFBResult              ret;
     bool                   direct = false;
     DFBRegion              clip;
     DFBRectangle           rect;
     DFBSurfacePixelFormat  format;
     IDirectFBSurface_data *dst_data;
     CoreSurface           *dst_surface;
     CoreSurfaceBufferLock  lock;
     DIRenderCallbackResult cb_result = DIRCR_OK;

     DIRECT_INTERFACE_GET_DATA(IDirectFBImageProvider_ANDROID)

     dst_data = (IDirectFBSurface_data*) destination->priv;
     if (!dst_data)
          return DFB_DEAD;

     dst_surface = dst_data->surface;
     if (!dst_surface)
          return DFB_DESTROYED;

     ret = decodeImage( data );
     if (ret)
          return ret;

     ret = destination->GetPixelFormat( destination, &format );
     if (ret)
          return ret;

     dfb_region_from_rectangle( &clip, &dst_data->area.current );

     if (dest_rect) {
          if (dest_rect->w < 1 || dest_rect->h < 1)
               return DFB_INVARG;

          rect = *dest_rect;
          rect.x += dst_data->area.wanted.x;
          rect.y += dst_data->area.wanted.y;

          if (!dfb_rectangle_region_intersects( &rect, &clip ))
               return DFB_OK;
     }
     else {
          rect = dst_data->area.wanted;
     }

     ret = dfb_surface_lock_buffer( dst_surface, CSBR_BACK, CSAID_CPU, CSAF_WRITE, &lock );
     if (ret)
          return ret;

     dfb_scale_linear_32( (u32 *)data->image, data->width, data->height, lock.addr, lock.pitch, &rect, dst_surface, &clip );
     if (data->base.render_callback) {
          DFBRectangle r = { 0, 0, data->width, data->height };
          data->base.render_callback( &r, data->base.render_callback_context );
     }

     dfb_surface_unlock_buffer( dst_surface, &lock );

     return DFB_OK;
}
static DFBResult
IDirectFBImageProvider_WebP_RenderTo( IDirectFBImageProvider *thiz,
                                      IDirectFBSurface       *destination,
                                      const DFBRectangle     *dest_rect )
{
     DFBResult               ret;

     DFBRegion               clip;
     CoreSurface            *dst_surface;
     CardState               state;

     CoreSurfaceBufferLock   lock;

     IDirectFBSurface_data  *dst_data;
     DIRenderCallbackResult  cb_result = DIRCR_OK;

     DFBRectangle           src_rect;
     DFBRectangle           rect;

     DIRECT_INTERFACE_GET_DATA( IDirectFBImageProvider_WebP )

     if (!destination)
          return DFB_INVARG;

     dst_data = destination->priv;
     if (!dst_data || !dst_data->surface)
          return DFB_DESTROYED;

     dst_surface = dst_data->surface;

     if (dest_rect) {
          if (dest_rect->w < 1 || dest_rect->h < 1)
               return DFB_INVARG;

          rect = *dest_rect;
          rect.x += dst_data->area.wanted.x;
          rect.y += dst_data->area.wanted.y;
     }
     else {
          rect = dst_data->area.wanted;
     }

     dfb_region_from_rectangle( &clip, &dst_data->area.current );
     if (!dfb_rectangle_region_intersects( &rect, &clip ))
          return DFB_OK;


     ret = dfb_surface_create_simple( data->base.core, data->width, data->height, data->pixelformat,
                                      DSCS_RGB, DSCAPS_NONE, CSTF_NONE,
                                      0, NULL, &data->decode_surface );
     if (ret) {
          D_ERROR( "Failed to create surface : '%s'\n", DirectResultString(ret) );
          goto error;
     }

     ret = dfb_surface_lock_buffer( data->decode_surface, CSBR_BACK, CSAID_CPU, CSAF_WRITE, &lock );
     if (ret) {
          D_ERROR( "Failed to lock the surface : '%s'\n", DirectResultString(ret) );
          goto error;
     }

     ret = WebP_decode_image( data, &lock );
     if (ret) {
          D_ERROR( "Failed to decode the image : '%s'\n", DirectResultString(ret) );
          goto error;
     }

     dfb_surface_unlock_buffer( data->decode_surface, &lock );

     dfb_state_init( &state, data->base.core );

     state.modified |= SMF_CLIP;

     state.clip =  DFB_REGION_INIT_FROM_RECTANGLE_VALS( rect.x, rect.y, rect.w, rect.h );
     src_rect = (DFBRectangle){0, 0, data->width, data->height};

     dfb_state_set_source( &state, data->decode_surface );
     dfb_state_set_destination( &state, dst_surface );

     dfb_gfxcard_batchstretchblit( &src_rect, &rect, 1, &state );

     data->serial = &state.serial;

     dfb_state_set_source(&state, NULL);
     dfb_state_set_destination(&state, NULL);

     dfb_state_destroy(&state);

     if (data->base.render_callback) {
          DFBRectangle r = { 0, 0, data->width, data->height };
          cb_result=data->base.render_callback( &r, data->base.render_callback_context );
     }

     if (cb_result == DIRCR_OK) {
          data->base.buffer->Release( data->base.buffer );
          data->base.buffer = NULL;
     }

     return DFB_OK;

error:
     if (data->decode_surface && lock.pitch)
          dfb_surface_unlock_buffer( data->decode_surface, &lock );

     dfb_surface_unref( data->decode_surface );

     data->base.buffer->Release( data->base.buffer );
     data->base.buffer = NULL;

     return ret;
}
Exemple #10
0
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, &region->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, &region->surface_lock );
}
Exemple #11
0
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( &region->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,
                                                        &region->surface_lock );

                         dfb_surface_unlock( surface );
                    }
                    else {
                         dfb_surface_unlock_buffer( buffer->surface, &region->surface_lock );

                         ret = dfb_surface_lock_buffer( surface, CSBR_FRONT, CSAF_CPU_READ | CSAF_GPU_READ,
                                                        &region->surface_lock );
                    }

               }
               else
                    ret = dfb_surface_lock_buffer( surface, CSBR_FRONT, CSAF_CPU_READ | CSAF_GPU_READ,
                                                   &region->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, &region->surface_lock );
     }
		
     /* Setup hardware. */
     return funcs->SetRegion( layer, layer->driver_data, layer->layer_data,
                              region->region_data, config, flags,
                              surface, surface ? surface->palette : NULL, &region->surface_lock );
}