cell: untwiddle surface contents in flush_frontbuffer()
authorKeith Whitwell <keithw@vmware.com>
Tue, 9 Mar 2010 14:03:41 +0000 (14:03 +0000)
committerKeith Whitwell <keithw@vmware.com>
Tue, 9 Mar 2010 14:03:41 +0000 (14:03 +0000)
Don't make the shared software winsys rely on internal knowledge about
the cell driver's texture twiddling.

This is just a sketch and hasn't even been compile tested.

src/gallium/drivers/cell/ppu/cell_screen.c
src/gallium/drivers/cell/ppu/cell_texture.c
src/gallium/drivers/cell/ppu/cell_texture.h
src/gallium/winsys/xlib/xlib_cell.c

index 36479e8e0c2889e8c49a22bcaeb27a15c1fa94ff..00035be53a1215954679e8a560ed3667e5cfcda7 100644 (file)
@@ -164,22 +164,6 @@ cell_destroy_screen( struct pipe_screen *screen )
    FREE(screen);
 }
 
-/* This used to be overriden by the co-state tracker, but really needs
- * to be active with sw_winsys.
- */
-static void
-cell_flush_frontbuffer(struct pipe_screen *_screen,
-                           struct pipe_surface *surface,
-                           void *context_private)
-{
-   struct cell_screen *screen = cell_screen(_screen);
-   struct sw_winsys *winsys = screen->winsys;
-   struct cell_texture *texture = cell_texture(surface->texture);
-
-   assert(texture->dt);
-   if (texture->dt)
-      winsys->displaytarget_display(winsys, texture->dt, context_private);
-}
 
 
 /**
index f3fc080aa39e0fd13dd06540e9639e6002afd21c..002dd3a9b55f57d56cc84b254784cd51b5a33a66 100644 (file)
@@ -108,7 +108,7 @@ cell_displaytarget_layout(struct pipe_screen *screen,
                                           ct->base.width0, 
                                           ct->base.height0,
                                           16,
-                                          &ct->stride[0] );
+                                          &ct->dt_stride );
 
    return ct->dt != NULL;
 }
@@ -125,21 +125,29 @@ cell_texture_create(struct pipe_screen *screen,
    pipe_reference_init(&ct->base.reference, 1);
    ct->base.screen = screen;
 
+   /* Create both a displaytarget (linear) and regular texture
+    * (twiddled).  Convert twiddled->linear at flush_frontbuffer time.
+    */
    if (ct->base.tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
                              PIPE_TEXTURE_USAGE_SCANOUT |
                              PIPE_TEXTURE_USAGE_SHARED)) {
       if (!cell_displaytarget_layout(screen, ct))
          goto fail;
    }
-   else {
-      if (!cell_texture_layout(screen, ct))
-         goto fail;
-   }
+
+   if (!cell_texture_layout(screen, ct))
+      goto fail;
 
    return &ct->base;
 
 fail:
+   if (ct->dt) {
+      struct sw_winsys winsys = cell_screen(screen)->winsys;
+      winsys->displaytarget_destroy(winsys, ct->dt);
+   }
+
    FREE(ct);
+
    return NULL;
 }
 
@@ -151,20 +159,12 @@ cell_texture_destroy(struct pipe_texture *pt)
    struct sw_winsys *winsys = screen->winsys;
    struct cell_texture *ct = cell_texture(pt);
 
-   if (ct->mapped) {
-      if (ct->dt)
-         winsys->displaytarget_unmap(winsys, ct->dt);
-      ct->mapped = NULL;
-   }
-
    if (ct->dt) {
       /* display target */
       winsys->displaytarget_destroy(winsys, ct->dt);
    }
-   else {
-      /* regular texture */
-      align_free(ct->data);
-   }
+
+   align_free(ct->data);
 
    FREE(ct);
 }
@@ -432,19 +432,9 @@ cell_transfer_map(struct pipe_screen *screen, struct pipe_transfer *transfer)
    assert(transfer->texture);
 
    if (ct->mapped == NULL) {
-      if (ct->dt) {
-         struct sw_winsys *winsys = cell_screen(screen)->winsys;
-         ct->mapped = winsys->displaytarget_map(screen, ct->dt,
-                                                pipe_transfer_buffer_flags(transfer));
-      }
-      else {
-         ct->mapped = ct->data;
-      }
+      ct->mapped = ct->data;
    }
 
-   if (ct->mapped == NULL)
-      return NULL;
-
    /*
     * Create a buffer of ordinary memory for the linear texture.
     * This is the memory that the user will read/write.
@@ -511,18 +501,51 @@ cell_transfer_unmap(struct pipe_screen *screen,
       }
    }
 
-   if (ct->dt) {
-      /* display target */
-      struct sw_winsys *winsys = cell_screen(screen)->winsys;
-      winsys->displaytarget_unmap(winsys, ct->dt);
-   }
-
    align_free(ctrans->map);
    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_flush_frontbuffer(struct pipe_screen *_screen,
+                       struct pipe_surface *surface,
+                       void *context_private)
+{
+   struct cell_screen *screen = cell_screen(_screen);
+   struct sw_winsys *winsys = screen->winsys;
+   struct cell_texture *ct = cell_texture(surface->texture);
+
+   if (!ct->dt)
+      return;
+
+   /* Need to untwiddle from our internal representation here:
+    */
+   {
+      unsigned *map = winsys->displaytarget_map(winsys, ct->dt);
+      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, c->dt);
+   }
+
+   winsys->displaytarget_display(winsys, ct->dt, context_private);
+}
 
 
 void
@@ -539,4 +562,6 @@ cell_init_screen_texture_funcs(struct pipe_screen *screen)
 
    screen->transfer_map = cell_transfer_map;
    screen->transfer_unmap = cell_transfer_unmap;
+
+   screen->flush_frontbuffer = cell_flush_frontbuffer;
 }
index 55b983218f97605c6af14a9ea9249e89fb75d4ec..b89db1a5a8c6c74e760581a1a81c074312b420cf 100644 (file)
@@ -48,6 +48,7 @@ struct cell_texture
     * usage.
     */
    struct sw_displaytarget *dt;
+   unsigned dt_stride;
 
    /**
     * Malloc'ed data for regular textures, or a mapping to dt above.
index ce4efe8851063d3b413fd6e55059547bd0f8f926..2ad1aab43977903ac70a80076141d192026b2fb7 100644 (file)
 
 
 
-/**
- * For Cell.  Basically, rearrange the pixels/quads from this layout:
- *  +--+--+--+--+
- *  |p0|p1|p2|p3|....
- *  +--+--+--+--+
- *
- * to this layout:
- *  +--+--+
- *  |p0|p1|....
- *  +--+--+
- *  |p2|p3|
- *  +--+--+
- */
-static void
-twiddle_tile(const uint *tileIn, uint *tileOut)
-{
-   int y, x;
-
-   for (y = 0; y < TILE_SIZE; y+=2) {
-      for (x = 0; x < TILE_SIZE; x+=2) {
-         int k = 4 * (y/2 * TILE_SIZE/2 + x/2);
-         tileOut[y * TILE_SIZE + (x + 0)] = tileIn[k];
-         tileOut[y * TILE_SIZE + (x + 1)] = tileIn[k+1];
-         tileOut[(y + 1) * TILE_SIZE + (x + 0)] = tileIn[k+2];
-         tileOut[(y + 1) * TILE_SIZE + (x + 1)] = tileIn[k+3];
-      }
-   }
-}
 
-/**
- * Display a surface that's in a tiled configuration.  That is, all the
- * pixels for a TILE_SIZExTILE_SIZE block are contiguous in memory.
- */
-static void
-xm_displaytarget_display(struct sw_winsys *ws,
-                         struct sw_displaytarget *dt,
-                         void *winsys_drawable)
-{
-   struct xmesa_buffer *xm_buffer = (struct xm_drawable *)winsys_drawable;
-   XImage *ximage;
-   struct xm_buffer *xm_buf = xm_buffer(
-      cell_texture(surf->texture)->buffer);
-   const uint tilesPerRow = (surf->width + TILE_SIZE - 1) / TILE_SIZE;
-   uint x, y;
-
-   ximage = b->tempImage;
-
-   /* check that the XImage has been previously initialized */
-   assert(ximage->format);
-   assert(ximage->bitmap_unit);
-
-   /* update XImage's fields */
-   ximage->width = TILE_SIZE;
-   ximage->height = TILE_SIZE;
-   ximage->bytes_per_line = TILE_SIZE * 4;
-
-   for (y = 0; y < surf->height; y += TILE_SIZE) {
-      for (x = 0; x < surf->width; x += TILE_SIZE) {
-         uint tmpTile[TILE_SIZE * TILE_SIZE];
-         int tx = x / TILE_SIZE;
-         int ty = y / TILE_SIZE;
-         int offset = ty * tilesPerRow + tx;
-         int w = TILE_SIZE;
-         int h = TILE_SIZE;
-
-         if (y + h > surf->height)
-            h = surf->height - y;
-         if (x + w > surf->width)
-            w = surf->width - x;
-
-         /* offset in pixels */
-         offset *= TILE_SIZE * TILE_SIZE;
-
-         /* twiddle from ximage buffer to temp tile */
-         twiddle_tile((uint *) xm_buf->data + offset, tmpTile);
-         /* display temp tile data */
-         ximage->data = (char *) tmpTile;
-         XPutImage(b->xm_visual->display, b->drawable, b->gc,
-                   ximage, 0, 0, x, y, w, h);
-      }
-   }
-}