cell: now do texture twiddling in the right way, at the right time.
authorBrian Paul <brian.paul@tungstengraphics.com>
Tue, 14 Oct 2008 16:55:38 +0000 (10:55 -0600)
committerBrian Paul <brian.paul@tungstengraphics.com>
Tue, 14 Oct 2008 18:54:30 +0000 (12:54 -0600)
Also handles images smaller than 32x32 now.

src/gallium/drivers/cell/ppu/cell_pipe_state.c
src/gallium/drivers/cell/ppu/cell_state_emit.c
src/gallium/drivers/cell/ppu/cell_texture.c
src/gallium/drivers/cell/ppu/cell_texture.h

index 02721e8..2e3086c 100644 (file)
@@ -258,8 +258,6 @@ cell_set_sampler_textures(struct pipe_context *pipe,
    }
    cell->num_textures = num;
 
-   cell_update_texture_mapping(cell); /* XXX temporary! */
-
    cell->dirty |= CELL_NEW_TEXTURE;
 }
 
index 7090b4c..cae546b 100644 (file)
@@ -222,8 +222,8 @@ cell_emit_state(struct cell_context *cell)
             uint level;
             for (level = 0; level < CELL_MAX_TEXTURE_LEVELS; level++) {
                texture->start[level] = NULL;
-               texture->width[level] = 1;
-               texture->height[level] = 1;
+               texture->width[level] = 0;
+               texture->height[level] = 0;
             }
          }
       }
index ad3344a..4bd8759 100644 (file)
@@ -150,15 +150,77 @@ cell_texture_release(struct pipe_screen *screen,
 }
 
 
-#if 0
+
+/**
+ * Convert image from linear layout to tiled layout.  4-byte pixels.
+ */
+static void
+swizzle_image_uint(uint w, uint h, uint tile_size, uint *dst, const uint *src)
+{
+   const uint tile_size2 = tile_size * tile_size;
+   const uint h_t = (h + tile_size - 1) / tile_size;
+   const uint w_t = (w + tile_size - 1) / tile_size;
+
+   uint it, jt;  /* tile counters */
+   uint i, j;    /* intra-tile counters */
+
+   /* loop over dest tiles */
+   for (it = 0; it < h_t; it++) {
+      for (jt = 0; jt < w_t; jt++) {
+         /* start of dest tile: */
+         uint *tdst = dst + (it * w_t + jt) * tile_size2;
+         /* loop over texels in the tile */
+         uint tile_width = MIN2(tile_size, w);
+         uint tile_height = MIN2(tile_size, h);
+         for (i = 0; i < tile_height; i++) {
+            for (j = 0; j < tile_width; j++) {
+               const uint srci = it * tile_size + i;
+               const uint srcj = jt * tile_size + j;
+               ASSERT(srci < w);
+               ASSERT(srcj < h);
+               tdst[i * TILE_SIZE + j] = src[srci * w + srcj];
+            }
+         }
+      }
+   }
+}
+
+
+/**
+ * Convert linear texture image data to tiled format for SPU usage.
+ */
 static void
-cell_texture_update(struct pipe_context *pipe, struct pipe_texture *texture,
-                    uint face, uint levelsMask)
+cell_twiddle_texture(struct pipe_screen *screen,
+                     struct pipe_surface *surface)
 {
-   /* XXX TO DO:  re-tile the texture data ... */
+   struct cell_texture *texture = cell_texture(surface->texture);
+   const uint level = surface->level;
+   const uint texWidth = texture->base.width[level];
+   const uint texHeight = texture->base.height[level];
+   const uint bufWidth = MAX2(texWidth, TILE_SIZE);
+   const uint bufHeight = MAX2(texHeight, TILE_SIZE);
+   const uint *src =
+      (const uint *) pipe_buffer_map(screen, surface->buffer,
+                                     PIPE_BUFFER_USAGE_CPU_READ);
+
+   switch (texture->base.format) {
+   case PIPE_FORMAT_A8R8G8B8_UNORM:
+      /* free old tiled data */
+      if (texture->tiled_data[level]) {
+         align_free(texture->tiled_data[level]);
+      }
+      /* alloc new tiled data */
+      texture->tiled_data[level] = align_malloc(bufWidth * bufHeight * 4, 16);
+      swizzle_image_uint(texWidth, texHeight, TILE_SIZE,
+                         texture->tiled_data[level], src);
+      break;
+   default:
+      printf("Unsupported texture format\n");
+      ;
+   }
 
+   pipe_buffer_unmap(screen, surface->buffer);
 }
-#endif
 
 
 static struct pipe_surface *
@@ -207,129 +269,12 @@ cell_get_tex_surface(struct pipe_screen *screen,
 }
 
 
-
-/**
- * Copy tile data from linear layout to tiled layout.
- * XXX this should be rolled into the future surface-creation code.
- * XXX also need "untile" code...
- */
-static void
-tile_copy_data(uint w, uint h, uint tile_size, uint *dst, const uint *src)
-{
-   const uint tile_size2 = tile_size * tile_size;
-   const uint h_t = h / tile_size, w_t = w / tile_size;
-
-   uint it, jt;  /* tile counters */
-   uint i, j;    /* intra-tile counters */
-
-   /* loop over dest tiles */
-   for (it = 0; it < h_t; it++) {
-      for (jt = 0; jt < w_t; jt++) {
-         /* start of dest tile: */
-         uint *tdst = dst + (it * w_t + jt) * tile_size2;
-         /* loop over texels in the tile */
-         for (i = 0; i < tile_size; i++) {
-            for (j = 0; j < tile_size; j++) {
-               const uint srci = it * tile_size + i;
-               const uint srcj = jt * tile_size + j;
-               *tdst++ = src[srci * w + srcj];
-            }
-         }
-      }
-   }
-}
-
-
-
-/**
- * Convert linear texture image data to tiled format for SPU usage.
- * XXX recast this in terms of pipe_surfaces (aka texture views).
- */
-static void
-cell_tile_texture(struct cell_context *cell,
-                  struct cell_texture *texture)
-{
-   struct pipe_screen *screen = cell->pipe.screen;
-   uint face = 0, level, zslice = 0;
-   const uint *src;
-
-   for (level = 0; level <= texture->base.last_level; level++) {
-      if (!texture->tiled_data[level]) {
-         struct pipe_surface *surf;
-
-         const uint w = texture->base.width[level], h = texture->base.height[level];
-
-         if (w < 32 || h < 32)
-            continue;
-         /* temporary restrictions: */
-         assert(w >= TILE_SIZE);
-         assert(h >= TILE_SIZE);
-         assert(w % TILE_SIZE == 0);
-         assert(h % TILE_SIZE == 0);
-
-         surf = screen->get_tex_surface(screen, &texture->base, face,
-                                        level, zslice,
-                                        PIPE_BUFFER_USAGE_CPU_WRITE);
-         ASSERT(surf);
-         
-         src = (const uint *) pipe_surface_map(surf,
-                                               PIPE_BUFFER_USAGE_CPU_WRITE);
-
-         if (texture->tiled_data[level]) {
-            align_free(texture->tiled_data[level]);
-         }
-         texture->tiled_data[level] = align_malloc(w * h * 4, 16);
-
-         tile_copy_data(w, h, TILE_SIZE, texture->tiled_data[level], src);
-
-         pipe_surface_unmap(surf);
-
-         pipe_surface_reference(&surf, NULL);
-      }
-   }
-}
-
-
-/** XXX temporary hack */
-void
-cell_update_texture_mapping(struct cell_context *cell)
-{
-#if 0
-   uint face = 0, level = 0, zslice = 0;
-#endif
-   uint i;
-
-   for (i = 0; i < CELL_MAX_SAMPLERS; i++) {
-      if (cell->texture[i])
-         cell_tile_texture(cell, cell->texture[i]);
-   }
-
-#if 0
-   if (cell->tex_surf && cell->tex_map) {
-      pipe_surface_unmap(cell->tex_surf);
-      cell->tex_map = NULL;
-   }
-
-   /* XXX free old surface */
-
-   cell->tex_surf = cell_get_tex_surface(&cell->pipe,
-                                         &cell->texture[0]->base,
-                                         face, level, zslice);
-
-   cell->tex_map = pipe_surface_map(cell->tex_surf);
-#endif
-}
-
-
 static void 
 cell_tex_surface_release(struct pipe_screen *screen, 
                          struct pipe_surface **s)
 {
-   /* 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 softpipe, nothing to do.
-    */
-   assert ((*s)->texture);
+   /* XXX if done rendering to teximage, re-tile */
+
    pipe_texture_reference(&(*s)->texture, NULL); 
 
    screen->winsys->surface_release(screen->winsys, s);
@@ -351,22 +296,8 @@ cell_surface_map(struct pipe_screen *screen,
    map = pipe_buffer_map( screen, surface->buffer, flags );
    if (map == NULL)
       return NULL;
-
-   /* May want to different things here depending on read/write nature
-    * of the map:
-    */
-   if (surface->texture &&
-       (flags & PIPE_BUFFER_USAGE_CPU_WRITE)) 
-   {
-      /* Do something to notify sharing contexts of a texture change.
-       * In softpipe, that would mean flushing the texture cache.
-       */
-#if 0
-      cell_screen(screen)->timestamp++;
-#endif
-   }
-   
-   return (void *) (map + surface->offset);
+   else
+      return (void *) (map + surface->offset);
 }
 
 
@@ -374,6 +305,16 @@ static void
 cell_surface_unmap(struct pipe_screen *screen,
                    struct pipe_surface *surface)
 {
+   struct cell_texture *ct = cell_texture(surface->texture);
+
+   assert(ct);
+
+   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);
+   }
+
    pipe_buffer_unmap( screen, surface->buffer );
 }
 
index 4647509..a075709 100644 (file)
@@ -62,10 +62,6 @@ cell_texture(struct pipe_texture *pt)
 
 
 extern void
-cell_update_texture_mapping(struct cell_context *cell);
-
-
-extern void
 cell_init_screen_texture_funcs(struct pipe_screen *screen);