[Mesa-stable] [PATCH 3/3] mesa: implement mipmap generation for compressed 2D array textures

Brian Paul brianp at vmware.com
Wed Jul 24 08:29:47 PDT 2013


We weren't looping over all the slices in the array.  The updated
code should also correctly handle 3D compressed textures too, whenever
we have that feature.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=66850

NOTE: This is a candidate for the 9.x branches
Cc: mesa-stable at lists.freedesktop.org
---
 src/mesa/main/mipmap.c |   59 +++++++++++++++++++++++++++++++++++-------------
 1 file changed, 43 insertions(+), 16 deletions(-)

diff --git a/src/mesa/main/mipmap.c b/src/mesa/main/mipmap.c
index edf7257..5839632 100644
--- a/src/mesa/main/mipmap.c
+++ b/src/mesa/main/mipmap.c
@@ -2020,13 +2020,15 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
    GLuint level;
    gl_format temp_format;
    GLint components;
-   GLuint temp_src_stride; /* in bytes */
+   GLuint temp_src_row_stride, temp_src_img_stride; /* in bytes */
    GLubyte *temp_src = NULL, *temp_dst = NULL;
    GLenum temp_datatype;
    GLenum temp_base_format;
+   GLubyte **temp_src_slices, **temp_dst_slices;
 
    /* only two types of compressed textures at this time */
    assert(texObj->Target == GL_TEXTURE_2D ||
+	  texObj->Target == GL_TEXTURE_2D_ARRAY ||
 	  texObj->Target == GL_TEXTURE_CUBE_MAP_ARB);
 
    /*
@@ -2051,15 +2053,24 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
 
 
    /* allocate storage for the temporary, uncompressed image */
-   /* 20 extra bytes, just be safe when calling last FetchTexel */
-   temp_src_stride = _mesa_format_row_stride(temp_format, srcImage->Width);
-   temp_src = malloc(temp_src_stride * srcImage->Height + 20);
-   if (!temp_src) {
+   temp_src_row_stride = _mesa_format_row_stride(temp_format, srcImage->Width);
+   temp_src_img_stride = _mesa_format_image_size(temp_format, srcImage->Width,
+                                                 srcImage->Height, 1);
+   temp_src = malloc(temp_src_img_stride * srcImage->Depth);
+
+   /* Allocate storage for arrays of slice pointers */
+   temp_src_slices = malloc(srcImage->Depth * sizeof(GLubyte *));
+   temp_dst_slices = malloc(srcImage->Depth * sizeof(GLubyte *));
+
+   if (!temp_src || !temp_src_slices || !temp_dst_slices) {
+      free(temp_src);
+      free(temp_src_slices);
+      free(temp_dst_slices);
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
       return;
    }
 
-   /* decompress base image to the temporary */
+   /* decompress base image to the temporary src buffer */
    {
       /* save pixel packing mode */
       struct gl_pixelstore_attrib save = ctx->Pack;
@@ -2075,7 +2086,6 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
       ctx->Pack = save;
    }
 
-
    for (level = texObj->BaseLevel; level < maxLevel; level++) {
       /* generate image[level+1] from image[level] */
       const struct gl_texture_image *srcImage;
@@ -2084,7 +2094,8 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
       GLint dstWidth, dstHeight, dstDepth;
       GLint border;
       GLboolean nextLevel;
-      GLuint temp_dst_stride; /* in bytes */
+      GLuint temp_dst_row_stride, temp_dst_img_stride; /* in bytes */
+      GLuint i;
 
       /* get src image parameters */
       srcImage = _mesa_select_tex_image(ctx, texObj, target, level);
@@ -2100,9 +2111,12 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
       if (!nextLevel)
 	 break;
 
-      temp_dst_stride = _mesa_format_row_stride(temp_format, dstWidth);
+      /* Compute dst image strides and alloc memory on first iteration */
+      temp_dst_row_stride = _mesa_format_row_stride(temp_format, dstWidth);
+      temp_dst_img_stride = _mesa_format_image_size(temp_format, dstWidth,
+                                                    dstHeight, 1);
       if (!temp_dst) {
-	 temp_dst = malloc(temp_dst_stride * dstHeight);
+	 temp_dst = malloc(temp_dst_img_stride * dstDepth);
 	 if (!temp_dst) {
 	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
 	    break;
@@ -2117,13 +2131,23 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
          return;
       }
 
-      /* rescale src image to dest image */
+      /* for 2D arrays, setup array[depth] of slice pointers */
+      for (i = 0; i < srcDepth; i++) {
+         temp_src_slices[i] = temp_src + temp_src_img_stride * i;
+      }
+      for (i = 0; i < dstDepth; i++) {
+         temp_dst_slices[i] = temp_dst + temp_dst_img_stride * i;
+      }
+
+      /* Rescale src image to dest image.
+       * This will loop over the slices of a 2D array.
+       */
       _mesa_generate_mipmap_level(target, temp_datatype, components, border,
                                   srcWidth, srcHeight, srcDepth,
-                                  (const GLubyte **) &temp_src,
-                                  temp_src_stride,
+                                  (const GLubyte **) temp_src_slices,
+                                  temp_src_row_stride,
                                   dstWidth, dstHeight, dstDepth,
-                                  &temp_dst, temp_dst_stride);
+                                  temp_dst_slices, temp_dst_row_stride);
 
       if (!_mesa_prepare_mipmap_level(ctx, texObj, level + 1,
                                       dstWidth, dstHeight, dstDepth,
@@ -2135,7 +2159,7 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
 
       /* The image space was allocated above so use glTexSubImage now */
       ctx->Driver.TexSubImage(ctx, 2, dstImage,
-                              0, 0, 0, dstWidth, dstHeight, 1,
+                              0, 0, 0, dstWidth, dstHeight, dstDepth,
                               temp_base_format, temp_datatype,
                               temp_dst, &ctx->DefaultPacking);
 
@@ -2144,12 +2168,15 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
 	 GLubyte *temp = temp_src;
 	 temp_src = temp_dst;
 	 temp_dst = temp;
-	 temp_src_stride = temp_dst_stride;
+         temp_src_row_stride = temp_dst_row_stride;
+         temp_src_img_stride = temp_dst_img_stride;
       }
    } /* loop over mipmap levels */
 
    free(temp_src);
    free(temp_dst);
+   free(temp_src_slices);
+   free(temp_dst_slices);
 }
 
 /**
-- 
1.7.10.4



More information about the mesa-stable mailing list