softpipe: Simplify texture memory layout.
authorMichel Dänzer <michel@tungstengraphics.com>
Thu, 10 Jan 2008 09:03:47 +0000 (10:03 +0100)
committerMichel Dänzer <michel@tungstengraphics.com>
Thu, 10 Jan 2008 09:06:00 +0000 (10:06 +0100)
src/mesa/pipe/softpipe/sp_surface.c
src/mesa/pipe/softpipe/sp_texture.c
src/mesa/pipe/softpipe/sp_texture.h

index 5259fbfd2079593643e014cffdd64d67e1fb4146..ece30e36ec490924ceb7af6a31bd3bc165731d20 100644 (file)
@@ -46,20 +46,6 @@ softpipe_get_tex_surface(struct pipe_context *pipe,
 {
    struct softpipe_texture *spt = softpipe_texture(pt);
    struct pipe_surface *ps;
-   unsigned offset;  /* in bytes */
-
-   offset = spt->level_offset[level];
-
-   if (pt->target == PIPE_TEXTURE_CUBE) {
-      offset += spt->image_offset[level][face] * pt->cpp;
-   }
-   else if (pt->target == PIPE_TEXTURE_3D) {
-      offset += spt->image_offset[level][zslice] * pt->cpp;
-   }
-   else {
-      assert(face == 0);
-      assert(zslice == 0);
-   }
 
    ps = pipe->winsys->surface_alloc(pipe->winsys);
    if (ps) {
@@ -69,8 +55,17 @@ softpipe_get_tex_surface(struct pipe_context *pipe,
       ps->cpp = pt->cpp;
       ps->width = pt->width[level];
       ps->height = pt->height[level];
-      ps->pitch = spt->pitch;
-      ps->offset = offset;
+      ps->pitch = ps->width;
+      ps->offset = spt->level_offset[level];
+
+      if (pt->target == PIPE_TEXTURE_CUBE || pt->target == PIPE_TEXTURE_3D) {
+        ps->offset += ((pt->target == PIPE_TEXTURE_CUBE) ? face : zslice) *
+                      (pt->compressed ? ps->height/4 : ps->height) *
+                      ps->width * ps->cpp;
+      } else {
+        assert(face == 0);
+        assert(zslice == 0);
+      }
    }
    return ps;
 }
index 44512e4281eff864fa49351ce45eccc50581ae0b..e5e6bfe01b8d2f7a9608d7cf620759142a720db9 100644 (file)
 #include "sp_texture.h"
 
 
-/* At the moment, just make softpipe use the same layout for its
- * textures as the i945.  Softpipe needs some sort of texture layout,
- * this one was handy.  May be worthwhile to simplify this code a
- * little.
+/* Simple, maximally packed layout.
  */
 
 static unsigned minify( unsigned d )
@@ -53,319 +50,35 @@ static unsigned minify( unsigned d )
 }
 
 
-
-static void
-sp_miptree_set_level_info(struct softpipe_texture *spt,
-                         unsigned level,
-                         unsigned nr_images,
-                         unsigned x, unsigned y, unsigned w, unsigned h,
-                         unsigned d)
-{
-   struct pipe_texture *pt = &spt->base;
-
-   assert(level < PIPE_MAX_TEXTURE_LEVELS);
-
-   pt->width[level] = w;
-   pt->height[level] = h;
-   pt->depth[level] = d;
-
-   spt->nr_images[level] = nr_images;
-   spt->level_offset[level] = (x + y * spt->pitch) * pt->cpp;
-
-   /*
-   DBG("%s level %d size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__,
-       level, w, h, d, x, y, spt->level_offset[level]);
-   */
-
-   /* Not sure when this would happen, but anyway: 
-    */
-   if (spt->image_offset[level]) {
-      FREE( spt->image_offset[level] );
-      spt->image_offset[level] = NULL;
-   }
-
-   assert(nr_images);
-   assert(!spt->image_offset[level]);
-
-   spt->image_offset[level] = (unsigned *) MALLOC( nr_images * sizeof(unsigned) );
-   spt->image_offset[level][0] = 0;
-}
-
-
-static void
-sp_miptree_set_image_offset(struct softpipe_texture *spt,
-                           unsigned level, unsigned img, unsigned x, unsigned y)
-{
-   if (img == 0 && level == 0)
-      assert(x == 0 && y == 0);
-
-   assert(img < spt->nr_images[level]);
-
-   spt->image_offset[level][img] = (x + y * spt->pitch);
-
-   /*
-   DBG("%s level %d img %d pos %d,%d image_offset %x\n",
-       __FUNCTION__, level, img, x, y, spt->image_offset[level][img]);
-   */
-}
-
-
 static void
-sp_miptree_layout_2d( struct softpipe_texture *spt )
+softpipe_texture_layout(struct softpipe_texture * spt)
 {
    struct pipe_texture *pt = &spt->base;
-   int align_h = 2, align_w = 4;
    unsigned level;
-   unsigned x = 0;
-   unsigned y = 0;
    unsigned width = pt->width[0];
    unsigned height = pt->height[0];
+   unsigned depth = pt->depth[0];
 
-   spt->pitch = pt->width[0];
-   /* XXX FIX THIS:
-    * we use alignment=64 bytes in sp_region_alloc(). If we change
-    * that, change this too.
-    */
-   if (spt->pitch < 16)
-      spt->pitch = 16;
-
-   /* May need to adjust pitch to accomodate the placement of
-    * the 2nd mipmap.  This occurs when the alignment
-    * constraints of mipmap placement push the right edge of the
-    * 2nd mipmap out past the width of its parent.
-    */
-   if (pt->first_level != pt->last_level) {
-      unsigned mip1_width = align(minify(pt->width[0]), align_w)
-                       + minify(minify(pt->width[0]));
-
-      if (mip1_width > pt->width[0])
-        spt->pitch = mip1_width;
-   }
-
-   /* Pitch must be a whole number of dwords, even though we
-    * express it in texels.
-    */
-   spt->pitch = align(spt->pitch * pt->cpp, 4) / pt->cpp;
-   spt->total_height = 0;
+   spt->buffer_size = 0;
 
    for ( level = pt->first_level ; level <= pt->last_level ; level++ ) {
-      unsigned img_height;
-
-      sp_miptree_set_level_info(spt, level, 1, x, y, width, height, 1);
-
-      if (pt->compressed)
-        img_height = MAX2(1, height/4);
-      else
-        img_height = align(height, align_h);
+      pt->width[level] = width;
+      pt->height[level] = height;
+      pt->depth[level] = depth;
 
+      spt->level_offset[level] = spt->buffer_size;
 
-      /* Because the images are packed better, the final offset
-       * might not be the maximal one:
-       */
-      spt->total_height = MAX2(spt->total_height, y + img_height);
-
-      /* Layout_below: step right after second mipmap.
-       */
-      if (level == pt->first_level + 1) {
-        x += align(width, align_w);
-      }
-      else {
-        y += img_height;
-      }
+      spt->buffer_size += ((pt->compressed) ? MAX2(1, height/4) : height) *
+                         ((pt->target == PIPE_TEXTURE_CUBE) ? 6 : depth) *
+                         width * pt->cpp;
 
       width  = minify(width);
       height = minify(height);
+      depth = minify(depth);
    }
 }
 
 
-static const int initial_offsets[6][2] = {
-   {0, 0},
-   {0, 2},
-   {1, 0},
-   {1, 2},
-   {1, 1},
-   {1, 3}
-};
-
-static const int step_offsets[6][2] = {
-   {0, 2},
-   {0, 2},
-   {-1, 2},
-   {-1, 2},
-   {-1, 1},
-   {-1, 1}
-};
-
-
-
-static boolean
-softpipe_mipmap_tree_layout(struct pipe_context *pipe, struct softpipe_texture * spt)
-{
-   struct pipe_texture *pt = &spt->base;
-   unsigned level;
-
-   switch (pt->target) {
-   case PIPE_TEXTURE_CUBE:{
-         const unsigned dim = pt->width[0];
-         unsigned face;
-         unsigned lvlWidth = pt->width[0], lvlHeight = pt->height[0];
-
-         assert(lvlWidth == lvlHeight); /* cubemap images are square */
-
-         /* Depending on the size of the largest images, pitch can be
-          * determined either by the old-style packing of cubemap faces,
-          * or the final row of 4x4, 2x2 and 1x1 faces below this. 
-          */
-         if (dim > 32)
-            spt->pitch = ((dim * pt->cpp * 2 + 3) & ~3) / pt->cpp;
-         else
-            spt->pitch = 14 * 8;
-
-         spt->total_height = dim * 4 + 4;
-
-         /* Set all the levels to effectively occupy the whole rectangular region. 
-          */
-         for (level = pt->first_level; level <= pt->last_level; level++) {
-            sp_miptree_set_level_info(spt, level, 6,
-                                         0, 0,
-                                         lvlWidth, lvlHeight, 1);
-           lvlWidth /= 2;
-           lvlHeight /= 2;
-        }
-
-
-         for (face = 0; face < 6; face++) {
-            unsigned x = initial_offsets[face][0] * dim;
-            unsigned y = initial_offsets[face][1] * dim;
-            unsigned d = dim;
-
-            if (dim == 4 && face >= 4) {
-               y = spt->total_height - 4;
-               x = (face - 4) * 8;
-            }
-            else if (dim < 4 && (face > 0 || pt->first_level > 0)) {
-               y = spt->total_height - 4;
-               x = face * 8;
-            }
-
-            for (level = pt->first_level; level <= pt->last_level; level++) {
-               sp_miptree_set_image_offset(spt, level, face, x, y);
-
-               d >>= 1;
-
-               switch (d) {
-               case 4:
-                  switch (face) {
-                  case PIPE_TEX_FACE_POS_X:
-                  case PIPE_TEX_FACE_NEG_X:
-                     x += step_offsets[face][0] * d;
-                     y += step_offsets[face][1] * d;
-                     break;
-                  case PIPE_TEX_FACE_POS_Y:
-                  case PIPE_TEX_FACE_NEG_Y:
-                     y += 12;
-                     x -= 8;
-                     break;
-                  case PIPE_TEX_FACE_POS_Z:
-                  case PIPE_TEX_FACE_NEG_Z:
-                     y = spt->total_height - 4;
-                     x = (face - 4) * 8;
-                     break;
-                  }
-
-               case 2:
-                  y = spt->total_height - 4;
-                  x = 16 + face * 8;
-                  break;
-
-               case 1:
-                  x += 48;
-                  break;
-
-               default:
-                  x += step_offsets[face][0] * d;
-                  y += step_offsets[face][1] * d;
-                  break;
-               }
-            }
-         }
-         break;
-      }
-   case PIPE_TEXTURE_3D:{
-         unsigned width = pt->width[0];
-         unsigned height = pt->height[0];
-         unsigned depth = pt->depth[0];
-         unsigned pack_x_pitch, pack_x_nr;
-         unsigned pack_y_pitch;
-         unsigned level;
-
-         spt->pitch = ((pt->width[0] * pt->cpp + 3) & ~3) / pt->cpp;
-         spt->total_height = 0;
-
-         pack_y_pitch = MAX2(pt->height[0], 2);
-         pack_x_pitch = spt->pitch;
-         pack_x_nr = 1;
-
-         for (level = pt->first_level; level <= pt->last_level; level++) {
-            unsigned nr_images = pt->target == PIPE_TEXTURE_3D ? depth : 6;
-            int x = 0;
-            int y = 0;
-            unsigned q, j;
-
-            sp_miptree_set_level_info(spt, level, nr_images,
-                                     0, spt->total_height,
-                                     width, height, depth);
-
-            for (q = 0; q < nr_images;) {
-               for (j = 0; j < pack_x_nr && q < nr_images; j++, q++) {
-                  sp_miptree_set_image_offset(spt, level, q, x, y);
-                  x += pack_x_pitch;
-               }
-
-               x = 0;
-               y += pack_y_pitch;
-            }
-
-
-            spt->total_height += y;
-
-            if (pack_x_pitch > 4) {
-               pack_x_pitch >>= 1;
-               pack_x_nr <<= 1;
-               assert(pack_x_pitch * pack_x_nr <= spt->pitch);
-            }
-
-            if (pack_y_pitch > 2) {
-               pack_y_pitch >>= 1;
-            }
-
-            width = minify(width);
-            height = minify(height);
-            depth = minify(depth);
-         }
-         break;
-      }
-
-   case PIPE_TEXTURE_1D:
-   case PIPE_TEXTURE_2D:
-//   case PIPE_TEXTURE_RECTANGLE:
-         sp_miptree_layout_2d(spt);
-         break;
-   default:
-      assert(0);
-      break;
-   }
-
-   /*
-   DBG("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__,
-       spt->pitch,
-       spt->total_height, pt->cpp, spt->pitch * spt->total_height * pt->cpp);
-   */
-
-   return TRUE;
-}
-
 void
 softpipe_texture_create(struct pipe_context *pipe, struct pipe_texture **pt)
 {
@@ -376,15 +89,13 @@ softpipe_texture_create(struct pipe_context *pipe, struct pipe_texture **pt)
       memset(&spt->base + 1, 0,
             sizeof(struct softpipe_texture) - sizeof(struct pipe_texture));
 
-      if (softpipe_mipmap_tree_layout(pipe, spt)) {
-        spt->buffer = pipe->winsys->buffer_create(pipe->winsys, 32, 0, 0);
+      softpipe_texture_layout(spt);
 
-        if (spt->buffer) {
-           pipe->winsys->buffer_data(pipe->winsys, spt->buffer,
-                                     spt->pitch * spt->base.cpp *
-                                     spt->total_height, NULL,
-                                     PIPE_BUFFER_USAGE_PIXEL);
-        }
+      spt->buffer = pipe->winsys->buffer_create(pipe->winsys, 32, 0, 0);
+
+      if (spt->buffer) {
+        pipe->winsys->buffer_data(pipe->winsys, spt->buffer, spt->buffer_size,
+                                  NULL, PIPE_BUFFER_USAGE_PIXEL);
       }
 
       if (!spt->buffer) {
@@ -408,7 +119,6 @@ softpipe_texture_release(struct pipe_context *pipe, struct pipe_texture **pt)
    */
    if (--(*pt)->refcount <= 0) {
       struct softpipe_texture *spt = softpipe_texture(*pt);
-      uint i;
 
       /*
       DBG("%s deleting %p\n", __FUNCTION__, (void *) spt);
@@ -416,10 +126,6 @@ softpipe_texture_release(struct pipe_context *pipe, struct pipe_texture **pt)
 
       pipe->winsys->buffer_reference(pipe->winsys, &spt->buffer, NULL);
 
-      for (i = 0; i < PIPE_MAX_TEXTURE_LEVELS; i++)
-         if (spt->image_offset[i])
-            free(spt->image_offset[i]);
-
       free(spt);
    }
    *pt = NULL;
index 732064d98671eaa736327c943024c0981a9c1f89..e1a5db279118ccbd6eda9f70c9a346363f9251ff 100644 (file)
@@ -10,29 +10,12 @@ struct softpipe_texture
 {
    struct pipe_texture base;
 
-   /* Derived from the above:
-    */
-   unsigned pitch;
-   unsigned depth_pitch;          /* per-image on i945? */
-   unsigned total_height;
-
-   unsigned nr_images[PIPE_MAX_TEXTURE_LEVELS];
-
-   /* Explicitly store the offset of each image for each cube face or
-    * depth value.  Pretty much have to accept that hardware formats
-    * are going to be so diverse that there is no unified way to
-    * compute the offsets of depth/cube images within a mipmap level,
-    * so have to store them as a lookup table:
-    */
-   unsigned *image_offset[PIPE_MAX_TEXTURE_LEVELS];   /**< array [depth] of offsets */
-
-   /* Includes image offset tables:
-    */
    unsigned long level_offset[PIPE_MAX_TEXTURE_LEVELS];
 
    /* The data is held here:
     */
    struct pipe_buffer_handle *buffer;
+   unsigned long buffer_size;
 };