Merge remote branch 'origin/7.8'
[mesa.git] / src / gallium / drivers / cell / ppu / cell_texture.c
index 4f16e2c6afcadb14de69ab7f2e9e19b56c1339ce..d08334d892b7592d95a4d1a8c17c27ec9db81e11 100644 (file)
 
 #include "pipe/p_context.h"
 #include "pipe/p_defines.h"
-#include "pipe/p_inlines.h"
-#include "pipe/internal/p_winsys_screen.h"
+#include "util/u_inlines.h"
+
+#include "util/u_format.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
 
 #include "cell_context.h"
+#include "cell_screen.h"
 #include "cell_state.h"
-#include "cell_texture.h"
+#include "cell_resource.h"
 
+#include "state_tracker/sw_winsys.h"
 
 
-static unsigned
-minify(unsigned d)
-{
-   return MAX2(1, d>>1);
-}
 
-
-static void
-cell_texture_layout(struct cell_texture *ct)
+static boolean
+cell_resource_layout(struct pipe_screen *screen, 
+                    struct cell_resource *ct)
 {
-   struct pipe_texture *pt = &ct->base;
+   struct pipe_resource *pt = &ct->base;
    unsigned level;
-   unsigned width = pt->width[0];
-   unsigned height = pt->height[0];
-   unsigned depth = pt->depth[0];
+   unsigned width = pt->width0;
+   unsigned height = pt->height0;
+   unsigned depth = pt->depth0;
 
    ct->buffer_size = 0;
 
-   for ( level = 0 ; level <= pt->last_level ; level++ ) {
+   for (level = 0; level <= pt->last_level; level++) {
       unsigned size;
       unsigned w_tile, h_tile;
 
@@ -72,17 +70,11 @@ cell_texture_layout(struct cell_texture *ct)
       w_tile = align(width, TILE_SIZE);
       h_tile = align(height, TILE_SIZE);
 
-      pt->width[level] = width;
-      pt->height[level] = height;
-      pt->depth[level] = depth;
-      pt->nblocksx[level] = pf_get_nblocksx(&pt->block, w_tile);  
-      pt->nblocksy[level] = pf_get_nblocksy(&pt->block, h_tile);  
-
-      ct->stride[level] = pt->nblocksx[level] * pt->block.size;
+      ct->stride[level] = util_format_get_stride(pt->format, w_tile);
 
       ct->level_offset[level] = ct->buffer_size;
 
-      size = pt->nblocksx[level] * pt->nblocksy[level] * pt->block.size;
+      size = ct->stride[level] * util_format_get_nblocksy(pt->format, h_tile);
       if (pt->target == PIPE_TEXTURE_CUBE)
          size *= 6;
       else
@@ -90,77 +82,94 @@ cell_texture_layout(struct cell_texture *ct)
 
       ct->buffer_size += size;
 
-      width  = minify(width);
-      height = minify(height);
-      depth = minify(depth);
+      width = u_minify(width, 1);
+      height = u_minify(height, 1);
+      depth = u_minify(depth, 1);
    }
+
+   ct->data = align_malloc(ct->buffer_size, 16);
+   return ct->data != NULL;
 }
 
 
-static struct pipe_texture *
-cell_texture_create(struct pipe_screen *screen,
-                    const struct pipe_texture *templat)
+/**
+ * Texture layout for simple color buffers.
+ */
+static boolean
+cell_displaytarget_layout(struct pipe_screen *screen,
+                          struct cell_resource * ct)
 {
-   struct pipe_winsys *ws = screen->winsys;
-   struct cell_texture *ct = CALLOC_STRUCT(cell_texture);
+   struct sw_winsys *winsys = cell_screen(screen)->winsys;
+
+   /* Round up the surface size to a multiple of the tile size?
+    */
+   ct->dt = winsys->displaytarget_create(winsys,
+                                          ct->base.bind,
+                                          ct->base.format,
+                                          ct->base.width0, 
+                                          ct->base.height0,
+                                          16,
+                                          &ct->dt_stride );
+
+   return ct->dt != NULL;
+}
+
+static struct pipe_resource *
+cell_resource_create(struct pipe_screen *screen,
+                    const struct pipe_resource *templat)
+{
+   struct cell_resource *ct = CALLOC_STRUCT(cell_resource);
    if (!ct)
       return NULL;
 
    ct->base = *templat;
-   ct->base.refcount = 1;
+   pipe_reference_init(&ct->base.reference, 1);
    ct->base.screen = screen;
 
-   cell_texture_layout(ct);
+   /* Create both a displaytarget (linear) and regular texture
+    * (twiddled).  Convert twiddled->linear at flush_frontbuffer time.
+    */
+   if (ct->base.bind & (PIPE_BIND_DISPLAY_TARGET |
+                        PIPE_BIND_SCANOUT |
+                        PIPE_BIND_SHARED)) {
+      if (!cell_displaytarget_layout(screen, ct))
+         goto fail;
+   }
+
+   if (!cell_resource_layout(screen, ct))
+      goto fail;
 
-   ct->buffer = ws->buffer_create(ws, 32, PIPE_BUFFER_USAGE_PIXEL,
-                                   ct->buffer_size);
+   return &ct->base;
 
-   if (!ct->buffer) {
-      FREE(ct);
-      return NULL;
+fail:
+   if (ct->dt) {
+      struct sw_winsys *winsys = cell_screen(screen)->winsys;
+      winsys->displaytarget_destroy(winsys, ct->dt);
    }
 
-   return &ct->base;
+   FREE(ct);
+
+   return NULL;
 }
 
 
 static void
-cell_texture_release(struct pipe_screen *screen,
-                     struct pipe_texture **pt)
+cell_resource_destroy(struct pipe_resource *pt)
 {
-   if (!*pt)
-      return;
-
-   /*
-   DBG("%s %p refcount will be %d\n",
-       __FUNCTION__, (void *) *pt, (*pt)->refcount - 1);
-   */
-   if (--(*pt)->refcount <= 0) {
-      /* Delete this texture now.
-       * But note that the underlying pipe_buffer may linger...
-       */
-      struct cell_texture *ct = cell_texture(*pt);
-      uint i;
-
-      /*
-      DBG("%s deleting %p\n", __FUNCTION__, (void *) ct);
-      */
-
-      pipe_buffer_reference(screen, &ct->buffer, NULL);
-
-      for (i = 0; i < CELL_MAX_TEXTURE_LEVELS; i++) {
-         /* Unreference the tiled image buffer.
-          * It may not actually be deleted until a fence is hit.
-          */
-         if (ct->tiled_buffer[i]) {
-            ct->tiled_mapped[i] = NULL;
-            pipe_buffer_reference(screen, &ct->tiled_buffer[i], NULL);
-         }
-      }
+   struct cell_screen *screen = cell_screen(pt->screen);
+   struct sw_winsys *winsys = screen->winsys;
+   struct cell_resource *ct = cell_resource(pt);
 
-      FREE(ct);
+   if (ct->dt) {
+      /* display target */
+      winsys->displaytarget_destroy(winsys, ct->dt);
+   }
+   else if (!ct->userBuffer) {
+      align_free(ct->data);
    }
-   *pt = NULL;
+
+   FREE(ct);
 }
 
 
@@ -294,235 +303,340 @@ untwiddle_image_uint(uint w, uint h, uint tile_size, uint *dst,
 }
 
 
-/**
- * Convert linear texture image data to tiled format for SPU usage.
- */
-static void
-cell_twiddle_texture(struct pipe_screen *screen,
-                     struct pipe_surface *surface)
-{
-   struct cell_texture *ct = cell_texture(surface->texture);
-   const uint level = surface->level;
-   const uint texWidth = ct->base.width[level];
-   const uint texHeight = ct->base.height[level];
-   const uint bufWidth = align(texWidth, TILE_SIZE);
-   const uint bufHeight = align(texHeight, TILE_SIZE);
-   const void *map = pipe_buffer_map(screen, surface->buffer,
-                                     PIPE_BUFFER_USAGE_CPU_READ);
-   const uint *src = (const uint *) ((const ubyte *) map + surface->offset);
-
-   switch (ct->base.format) {
-   case PIPE_FORMAT_A8R8G8B8_UNORM:
-   case PIPE_FORMAT_B8G8R8A8_UNORM:
-   case PIPE_FORMAT_S8Z24_UNORM:
-      {
-         int numFaces = ct->base.target == PIPE_TEXTURE_CUBE ? 6 : 1;
-         int offset = bufWidth * bufHeight * 4 * surface->face;
-         uint *dst;
-
-         if (!ct->tiled_buffer[level]) {
-            /* allocate buffer for tiled data now */
-            struct pipe_winsys *ws = screen->winsys;
-            uint bytes = bufWidth * bufHeight * 4 * numFaces;
-            ct->tiled_buffer[level] = ws->buffer_create(ws, 16,
-                                                         PIPE_BUFFER_USAGE_PIXEL,
-                                                         bytes);
-            /* and map it */
-            ct->tiled_mapped[level] = ws->buffer_map(ws, ct->tiled_buffer[level],
-                                                      PIPE_BUFFER_USAGE_GPU_READ);
-         }
-         dst = (uint *) ((ubyte *) ct->tiled_mapped[level] + offset);
-
-         twiddle_image_uint(texWidth, texHeight, TILE_SIZE, dst,
-                            surface->stride, src);
-      }
-      break;
-   default:
-      printf("Cell: twiddle unsupported texture format %s\n", pf_name(ct->base.format));
-      ;
-   }
-
-   pipe_buffer_unmap(screen, surface->buffer);
-}
-
-
-/**
- * Convert SPU tiled texture image data to linear format for app usage.
- */
-static void
-cell_untwiddle_texture(struct pipe_screen *screen,
-                     struct pipe_surface *surface)
-{
-   struct cell_texture *ct = cell_texture(surface->texture);
-   const uint level = surface->level;
-   const uint texWidth = ct->base.width[level];
-   const uint texHeight = ct->base.height[level];
-   const void *map = pipe_buffer_map(screen, surface->buffer,
-                                     PIPE_BUFFER_USAGE_CPU_READ);
-   const uint *src = (const uint *) ((const ubyte *) map + surface->offset);
-
-   switch (ct->base.format) {
-   case PIPE_FORMAT_A8R8G8B8_UNORM:
-   case PIPE_FORMAT_B8G8R8A8_UNORM:
-   case PIPE_FORMAT_S8Z24_UNORM:
-      {
-         int numFaces = ct->base.target == PIPE_TEXTURE_CUBE ? 6 : 1;
-         int offset = surface->stride * texHeight * 4 * surface->face;
-         uint *dst;
-
-         if (!ct->untiled_data[level]) {
-            ct->untiled_data[level] =
-               align_malloc(surface->stride * texHeight * 4 * numFaces, 16);
-         }
-
-         dst = (uint *) ((ubyte *) ct->untiled_data[level] + offset);
-
-         untwiddle_image_uint(texWidth, texHeight, TILE_SIZE, dst,
-                              surface->stride, src);
-      }
-      break;
-   default:
-      {
-         ct->untiled_data[level] = NULL;
-         printf("Cell: untwiddle unsupported texture format %s\n", pf_name(ct->base.format));
-      }
-   }
-
-   pipe_buffer_unmap(screen, surface->buffer);
-}
-
-
 static struct pipe_surface *
 cell_get_tex_surface(struct pipe_screen *screen,
-                     struct pipe_texture *pt,
+                     struct pipe_resource *pt,
                      unsigned face, unsigned level, unsigned zslice,
                      unsigned usage)
 {
-   struct pipe_winsys *ws = screen->winsys;
-   struct cell_texture *ct = cell_texture(pt);
+   struct cell_resource *ct = cell_resource(pt);
    struct pipe_surface *ps;
 
-   ps = ws->surface_alloc(ws);
+   ps = CALLOC_STRUCT(pipe_surface);
    if (ps) {
-      assert(ps->refcount);
-      assert(ps->winsys);
-      pipe_buffer_reference(screen, &ps->buffer, ct->buffer);
+      pipe_reference_init(&ps->reference, 1);
+      pipe_resource_reference(&ps->texture, pt);
       ps->format = pt->format;
-      ps->block = pt->block;
-      ps->width = pt->width[level];
-      ps->height = pt->height[level];
-      ps->nblocksx = pt->nblocksx[level];
-      ps->nblocksy = pt->nblocksy[level];
-      ps->stride = ct->stride[level];
+      ps->width = u_minify(pt->width0, level);
+      ps->height = u_minify(pt->height0, level);
       ps->offset = ct->level_offset[level];
-      ps->usage = usage;
-
       /* XXX may need to override usage flags (see sp_texture.c) */
-
-      pipe_texture_reference(&ps->texture, pt); 
+      ps->usage = usage;
       ps->face = face;
       ps->level = level;
       ps->zslice = zslice;
 
-      if (pt->target == PIPE_TEXTURE_CUBE || pt->target == PIPE_TEXTURE_3D) {
-                ps->offset += ((pt->target == PIPE_TEXTURE_CUBE) ? face : zslice) *
-                     ps->nblocksy *
-                     ps->stride;
+      if (pt->target == PIPE_TEXTURE_CUBE) {
+         unsigned h_tile = align(ps->height, TILE_SIZE);
+         ps->offset += face * util_format_get_nblocksy(ps->format, h_tile) * ct->stride[level];
+      }
+      else if (pt->target == PIPE_TEXTURE_3D) {
+         unsigned h_tile = align(ps->height, TILE_SIZE);
+         ps->offset += zslice * util_format_get_nblocksy(ps->format, h_tile) * ct->stride[level];
       }
       else {
          assert(face == 0);
          assert(zslice == 0);
       }
-
-      if (ps->usage & PIPE_BUFFER_USAGE_CPU_READ) {
-         /* convert from tiled to linear layout */
-         cell_untwiddle_texture(screen, ps);
-      }
    }
    return ps;
 }
 
 
 static void 
-cell_tex_surface_release(struct pipe_screen *screen, 
-                         struct pipe_surface **s)
+cell_tex_surface_destroy(struct pipe_surface *surf)
 {
-   struct cell_texture *ct = cell_texture((*s)->texture);
-   const uint level = (*s)->level;
+   pipe_resource_reference(&surf->texture, NULL);
+   FREE(surf);
+}
 
-   if (((*s)->usage & PIPE_BUFFER_USAGE_CPU_READ) && (ct->untiled_data[level]))
-   {
-      align_free(ct->untiled_data[level]);
-      ct->untiled_data[level] = NULL;
-   }
 
-   /* XXX if done rendering to teximage, re-tile */
+/**
+ * Create new pipe_transfer object.
+ * This is used by the user to put tex data into a texture (and get it
+ * back out for glGetTexImage).
+ */
+static struct pipe_transfer *
+cell_get_transfer(struct pipe_context *ctx,
+                 struct pipe_resource *resource,
+                 struct pipe_subresource sr,
+                 unsigned usage,
+                 const struct pipe_box *box)
+{
+   struct cell_resource *ct = cell_resource(resource);
+   struct cell_transfer *ctrans;
+   enum pipe_format *format = resource->format;
+
+   assert(resource);
+   assert(level <= resource->last_level);
+
+   /* make sure the requested region is in the image bounds */
+   assert(box->x + box->width <= u_minify(resource->width0, sr.level));
+   assert(box->y + box->height <= u_minify(resource->height0, sr.level));
+   assert(box->z + box->depth <= u_minify(resource->depth0, sr.level));
+
+   ctrans = CALLOC_STRUCT(cell_transfer);
+   if (ctrans) {
+      struct pipe_transfer *pt = &ctrans->base;
+      pipe_resource_reference(&pt->resource, resource);
+      pt->sr = sr;
+      pt->usage = usage;
+      pt->box = *box;
+      pt->stride = ct->stride[sr.level];
+
+      ctrans->offset = ct->level_offset[sr.level];
+
+      if (resource->target == PIPE_TEXTURE_CUBE) {
+         unsigned h_tile = align(u_minify(resource->height0, sr.level), TILE_SIZE);
+         ctrans->offset += sr.face * util_format_get_nblocksy(format, h_tile) * pt->stride;
+      }
+      else if (resource->target == PIPE_TEXTURE_3D) {
+         unsigned h_tile = align(u_minify(resource->height0, sr.level), TILE_SIZE);
+         ctrans->offset += box->z * util_format_get_nblocksy(format, h_tile) * pt->stride;
+      }
+      else {
+         assert(sr.face == 0);
+         assert(box->z == 0);
+      }
+
+      return pt;
+   }
+   return NULL;
+}
 
-   pipe_texture_reference(&(*s)->texture, NULL); 
 
-   screen->winsys->surface_release(screen->winsys, s);
+static void 
+cell_transfer_destroy(struct pipe_context *ctx, struct pipe_transfer *t)
+{
+   struct cell_transfer *transfer = cell_transfer(t);
+   /* Effectively do the texture_update work here - if texture images
+    * needed post-processing to put them into hardware layout, this is
+    * where it would happen.  For cell, nothing to do.
+    */
+   assert (transfer->base.resource);
+   pipe_resource_reference(&transfer->base.resource, NULL);
+   FREE(transfer);
 }
 
 
+/**
+ * Return pointer to texture image data in linear layout.
+ */
 static void *
-cell_surface_map(struct pipe_screen *screen,
-                 struct pipe_surface *surface,
-                 unsigned flags)
+cell_transfer_map(struct pipe_context *ctx, struct pipe_transfer *transfer)
 {
-   ubyte *map;
-   struct cell_texture *ct = cell_texture(surface->texture);
-   const uint level = surface->level;
+   struct cell_transfer *ctrans = cell_transfer(transfer);
+   struct pipe_resource *pt = transfer->resource;
+   struct cell_resource *ct = cell_resource(pt);
 
-   assert(ct);
+   assert(transfer->resource);
 
-   if (flags & ~surface->usage) {
-      assert(0);
-      return NULL;
+   if (ct->mapped == NULL) {
+      ct->mapped = ct->data;
    }
 
-   map = pipe_buffer_map( screen, surface->buffer, flags );
-   if (map == NULL)
-      return NULL;
-   else
-   {
-      if ((surface->usage & PIPE_BUFFER_USAGE_CPU_READ) && (ct->untiled_data[level])) {
-         return (void *) ((ubyte *) ct->untiled_data[level] + surface->offset);
+
+   /* Better test would be resource->is_linear
+    */
+   if (transfer->resource->target != PIPE_BUFFER) {
+      const uint level = ctrans->base.sr.level;
+      const uint texWidth = u_minify(pt->width0, level);
+      const uint texHeight = u_minify(pt->height0, level);
+      unsigned size;
+
+
+      /*
+       * Create a buffer of ordinary memory for the linear texture.
+       * This is the memory that the user will read/write.
+       */
+      size = (util_format_get_stride(pt->format, align(texWidth, TILE_SIZE)) *
+             util_format_get_nblocksy(pt->format, align(texHeight, TILE_SIZE)));
+
+      ctrans->map = align_malloc(size, 16);
+      if (!ctrans->map)
+        return NULL; /* out of memory */
+
+      if (transfer->usage & PIPE_TRANSFER_READ) {
+        /* Textures always stored twiddled, need to untwiddle the
+         * texture to make a linear version.
+         */
+        const uint bpp = util_format_get_blocksize(ct->base.format);
+        if (bpp == 4) {
+           const uint *src = (uint *) (ct->mapped + ctrans->offset);
+           uint *dst = ctrans->map;
+           untwiddle_image_uint(texWidth, texHeight, TILE_SIZE,
+                                dst, transfer->stride, src);
+        }
+        else {
+           // xxx fix
+        }
       }
-      else {
-         return (void *) (map + surface->offset);
+   }
+   else {
+      unsigned stride = transfer->stride;
+      enum pipe_format format = pt->format;
+      unsigned blocksize = util_format_get_blocksize(format);
+
+      ctrans->map = (ct->mapped + 
+                    ctrans->offset +
+                    ctrans->base.box.y / util_format_get_blockheight(format) * stride +
+                    ctrans->base.box.x / util_format_get_blockwidth(format) * blocksize);
+   }
+
+
+   return ctrans->map;
+}
+
+
+/**
+ * Called when user is done reading/writing texture data.
+ * If new data was written, this is where we convert the linear data
+ * to tiled data.
+ */
+static void
+cell_transfer_unmap(struct pipe_context *ctx,
+                    struct pipe_transfer *transfer)
+{
+   struct cell_transfer *ctrans = cell_transfer(transfer);
+   struct pipe_resource *pt = transfer->resource;
+   struct cell_resource *ct = cell_resource(pt);
+   const uint level = ctrans->base.sr.level;
+   const uint texWidth = u_minify(pt->width0, level);
+   const uint texHeight = u_minify(pt->height0, level);
+   const uint stride = ct->stride[level];
+
+   if (!ct->mapped) {
+      assert(0);
+      return;
+   }
+
+   if (pt->target != PIPE_BUFFER) {
+      if (transfer->usage & PIPE_TRANSFER_WRITE) {
+        /* The user wrote new texture data into the mapped buffer.
+         * We need to convert the new linear data into the twiddled/tiled format.
+         */
+        const uint bpp = util_format_get_blocksize(ct->base.format);
+        if (bpp == 4) {
+           const uint *src = ctrans->map;
+           uint *dst = (uint *) (ct->mapped + ctrans->offset);
+           twiddle_image_uint(texWidth, texHeight, TILE_SIZE, dst, stride, src);
+        }
+        else {
+           // xxx fix
+        }
       }
+      
+      align_free(ctrans->map);
    }
+   else {
+      /* nothing to do */
+   }
+
+   ctrans->map = NULL;
 }
 
 
+
+/* This used to be overriden by the co-state tracker, but really needs
+ * to be active with sw_winsys.
+ *
+ * Contrasting with llvmpipe and softpipe, this is the only place
+ * where we use the ct->dt display target in any real sense.
+ *
+ * Basically just untwiddle our local data into the linear
+ * displaytarget.
+ */
 static void
-cell_surface_unmap(struct pipe_screen *screen,
-                   struct pipe_surface *surface)
+cell_flush_frontbuffer(struct pipe_screen *_screen,
+                       struct pipe_surface *surface,
+                       void *context_private)
 {
-   struct cell_texture *ct = cell_texture(surface->texture);
+   struct cell_screen *screen = cell_screen(_screen);
+   struct sw_winsys *winsys = screen->winsys;
+   struct cell_resource *ct = cell_resource(surface->texture);
 
-   assert(ct);
+   if (!ct->dt)
+      return;
 
-   if ((ct->base.tex_usage & PIPE_TEXTURE_USAGE_SAMPLER) &&
-       (surface->usage & PIPE_BUFFER_USAGE_CPU_WRITE)) {
-      /* convert from linear to tiled layout */
-      cell_twiddle_texture(screen, surface);
+   /* Need to untwiddle from our internal representation here:
+    */
+   {
+      unsigned *map = winsys->displaytarget_map(winsys, ct->dt,
+                                                (PIPE_TRANSFER_READ |
+                                                 PIPE_TRANSFER_WRITE));
+      unsigned *src = (unsigned *)(ct->data + ct->level_offset[surface->level]);
+
+      untwiddle_image_uint(surface->width,
+                           surface->height,
+                           TILE_SIZE,
+                           map,
+                           ct->dt_stride,
+                           src);
+
+      winsys->displaytarget_unmap(winsys, ct->dt);
    }
 
-   pipe_buffer_unmap( screen, surface->buffer );
+   winsys->displaytarget_display(winsys, ct->dt, context_private);
 }
 
 
 
+/**
+ * Create buffer which wraps user-space data.
+ */
+static struct pipe_resource *
+cell_user_buffer_create(struct pipe_screen *screen,
+                            void *ptr,
+                            unsigned bytes,
+                           unsigned bind_flags)
+{
+   struct cell_resource *buffer;
+
+   buffer = CALLOC_STRUCT(cell_resource);
+   if(!buffer)
+      return NULL;
+
+   pipe_reference_init(&buffer->base.reference, 1);
+   buffer->base.screen = screen;
+   buffer->base.format = PIPE_FORMAT_R8_UNORM; /* ?? */
+   buffer->base.bind = PIPE_BIND_TRANSFER_READ | bind_flags;
+   buffer->base.usage = PIPE_USAGE_IMMUTABLE;
+   buffer->base.flags = 0;
+   buffer->base.width0 = bytes;
+   buffer->base.height0 = 1;
+   buffer->base.depth0 = 1;
+   buffer->userBuffer = TRUE;
+   buffer->data = ptr;
+
+   return &buffer->base;
+}
+
+
+
+
 void
 cell_init_screen_texture_funcs(struct pipe_screen *screen)
 {
-   screen->texture_create = cell_texture_create;
-   screen->texture_release = cell_texture_release;
+   screen->resource_create = cell_resource_create;
+   screen->resource_destroy = cell_resource_destroy;
+   screen->resource_from_handle = cell_resource_from_handle;
+   screen->resource_get_handle = cell_resource_get_handle;
+   screen->user_buffer_create = cell_user_buffer_create;
 
    screen->get_tex_surface = cell_get_tex_surface;
-   screen->tex_surface_release = cell_tex_surface_release;
+   screen->tex_surface_destroy = cell_tex_surface_destroy;
+
+   screen->flush_frontbuffer = cell_flush_frontbuffer;
+}
+
+void
+cell_init_transfer_funcs(struct cell_context *cell)
+{
+   cell->pipe.get_transfer = cell_get_transfer;
+   cell->pipe.transfer_destroy = cell_transfer_destroy;
+   cell->pipe.transfer_map = cell_transfer_map;
+   cell->pipe.transfer_unmap = cell_transfer_unmap;
 
-   screen->surface_map = cell_surface_map;
-   screen->surface_unmap = cell_surface_unmap;
+   cell->pipe.transfer_flush_region = u_default_transfer_flush_region;
+   cell->pipe.transfer_inline_write = u_default_transfer_inline_write;
 }