Mesa (master): mesa: implement mipmap generation for compressed 2D array textures

Brian Paul brianp at kemper.freedesktop.org
Wed Jul 24 21:38:02 UTC 2013


Module: Mesa
Branch: master
Commit: 8a9df7a370b66ec50b6255e4d66ac1ed331319fb
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=8a9df7a370b66ec50b6255e4d66ac1ed331319fb

Author: Brian Paul <brianp at vmware.com>
Date:   Tue Jul 16 06:04:32 2013 -0600

mesa: implement mipmap generation for compressed 2D array textures

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
Reviewed-by: José Fonseca <jfonseca at vmware.com>

---

 src/mesa/main/mipmap.c |   59 +++++++++++++++++++++++++++++++++++-------------
 1 files 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);
 }
 
 /**




More information about the mesa-commit mailing list