llvmpipe: fix broken compressed cube maps
authorBrian Paul <brianp@vmware.com>
Tue, 4 May 2010 23:15:26 +0000 (17:15 -0600)
committerBrian Paul <brianp@vmware.com>
Tue, 4 May 2010 23:17:04 +0000 (17:17 -0600)
When the cube faces were stored in a compressed format, the img_stride
values were wrong and didn't match the per-face size computed in the
tex_image_face_size() function.  This caused bad rendering or segfaults.

src/gallium/drivers/llvmpipe/lp_texture.c

index 2f41d620c8a675f97a010efa5e4e38a2776e66da..e017fbe8c989b5322380288441674168218de910 100644 (file)
@@ -107,32 +107,55 @@ llvmpipe_texture_layout(struct llvmpipe_screen *screen,
    assert(LP_MAX_TEXTURE_3D_LEVELS <= LP_MAX_TEXTURE_LEVELS);
 
    for (level = 0; level <= pt->last_level; level++) {
-      const unsigned width_t = align(width, TILE_SIZE) / TILE_SIZE;
-      const unsigned height_t = align(height, TILE_SIZE) / TILE_SIZE;
-      unsigned nblocksx, num_slices;
-
-      if (lpr->base.target == PIPE_TEXTURE_CUBE)
-         num_slices = 6;
-      else if (lpr->base.target == PIPE_TEXTURE_3D)
-         num_slices = depth;
-      else
-         num_slices = 1;
-
-      /* Allocate storage for whole quads. This is particularly important
-       * for depth surfaces, which are currently stored in a swizzled format.
-       */
-      nblocksx = util_format_get_nblocksx(pt->format, align(width, TILE_SIZE));
 
-      lpr->row_stride[level] =
-         align(nblocksx * util_format_get_blocksize(pt->format), 16);
+      /* Row stride and image stride (for linear layout) */
+      {
+         unsigned alignment, nblocksx, nblocksy, block_size;
+
+         /* For non-compressed formats we need to align the texture size
+          * to the tile size to facilitate render-to-texture.
+          */
+         if (util_format_is_compressed(pt->format))
+            alignment = 1;
+         else
+            alignment = TILE_SIZE;
+
+         nblocksx = util_format_get_nblocksx(pt->format,
+                                             align(width, alignment));
+         nblocksy = util_format_get_nblocksy(pt->format,
+                                             align(height, alignment));
+         block_size = util_format_get_blocksize(pt->format);
 
-      lpr->img_stride[level] = lpr->row_stride[level] * align(height, TILE_SIZE);
+         lpr->row_stride[level] = align(nblocksx * block_size, 16);
+
+         lpr->img_stride[level] = lpr->row_stride[level] * nblocksy * block_size;
+      }
+
+      /* Size of the image in tiles (for tiled layout) */
+      {
+         const unsigned width_t = align(width, TILE_SIZE) / TILE_SIZE;
+         const unsigned height_t = align(height, TILE_SIZE) / TILE_SIZE;
+         lpr->tiles_per_row[level] = width_t;
+         lpr->tiles_per_image[level] = width_t * height_t;
+      }
 
-      lpr->tiles_per_row[level] = width_t;
-      lpr->tiles_per_image[level] = width_t * height_t;
-      lpr->num_slices_faces[level] = num_slices;
-      lpr->layout[level] = alloc_layout_array(num_slices, width, height);
+      /* Number of 3D image slices or cube faces */
+      {
+         unsigned num_slices;
 
+         if (lpr->base.target == PIPE_TEXTURE_CUBE)
+            num_slices = 6;
+         else if (lpr->base.target == PIPE_TEXTURE_3D)
+            num_slices = depth;
+         else
+            num_slices = 1;
+
+         lpr->num_slices_faces[level] = num_slices;
+
+         lpr->layout[level] = alloc_layout_array(num_slices, width, height);
+      }
+
+      /* Compute size of next mipmap level */
       width = u_minify(width, 1);
       height = u_minify(height, 1);
       depth = u_minify(depth, 1);
@@ -698,11 +721,8 @@ tex_image_face_size(const struct llvmpipe_resource *lpr, unsigned level,
       return buffer_size;
    }
    else {
-      const enum pipe_format format = lpr->base.format;
-      const unsigned nblocksy =
-         util_format_get_nblocksy(format, align(height, TILE_SIZE));
-      const unsigned buffer_size = nblocksy * lpr->row_stride[level];
-      return buffer_size;
+      /* we already computed this */
+      return lpr->img_stride[level];
    }
 }