mesa: Switch generate_mipmaps_compressed() to using TexImage2D to upload.
authorEric Anholt <eric@anholt.net>
Fri, 10 Jun 2011 19:58:56 +0000 (12:58 -0700)
committerEric Anholt <eric@anholt.net>
Tue, 14 Jun 2011 18:17:39 +0000 (11:17 -0700)
The code was playing fast and loose with rowstrides, which meant that
if a driver chose anything different for its alignment requirements,
the generated mipmaps came out garbage.  Unlike the uncompressed case,
we can't generate mipmaps directly into image->Data, so by using
TexImage2D we cut out most of the weird logic that existed to generate
in-place into ->Data.  The up/downside is that the driver recovery
code for the fact that _mesa_generate_mipmaps whacked ->Data has to be
turned off for compressed now.

Fixes 6 piglit tests about compressed mipmap gen.

src/mesa/drivers/dri/intel/intel_tex.c
src/mesa/drivers/dri/nouveau/nouveau_texture.c
src/mesa/drivers/dri/radeon/radeon_texture.c
src/mesa/main/mipmap.c

index 2c3eab20fdadf9212dac42c8b8ce3882c2df6e3a..32e1fb7397a643fcf1a4f6165a32c1cff1b8f233 100644 (file)
@@ -75,6 +75,7 @@ intelGenerateMipmap(struct gl_context *ctx, GLenum target,
       /* sw path: need to map texture images */
       struct intel_context *intel = intel_context(ctx);
       struct intel_texture_object *intelObj = intel_texture_object(texObj);
+      struct gl_texture_image *first_image = texObj->Image[0][texObj->BaseLevel];
 
       fallback_debug("%s - fallback to swrast\n", __FUNCTION__);
 
@@ -82,7 +83,7 @@ intelGenerateMipmap(struct gl_context *ctx, GLenum target,
       _mesa_generate_mipmap(ctx, target, texObj);
       intel_tex_unmap_level_images(intel, intelObj, texObj->BaseLevel);
 
-      {
+      if (!_mesa_is_format_compressed(first_image->TexFormat)) {
          GLuint nr_faces = (texObj->Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
          GLuint face, i;
          /* Update the level information in our private data in the new images,
index 36e68c991812635d6a02ba162d78bcec27c8cc5b..dcfd316c49f4f2c24fc0c5f90215c51697365b32 100644 (file)
@@ -688,8 +688,10 @@ nouveau_generate_mipmap(struct gl_context *ctx, GLenum target,
                _mesa_generate_mipmap(ctx, target, t);
                nouveau_teximage_unmap(ctx, base);
 
-               store_mipmap(ctx, target, t->BaseLevel + 1,
-                            get_last_level(t), t);
+               if (!_mesa_is_format_compressed(base->TexFormat)) {
+                       store_mipmap(ctx, target, t->BaseLevel + 1,
+                                    get_last_level(t), t);
+               }
 
        } else {
                _mesa_meta_GenerateMipmap(ctx, target, t);
index 9ec53881bb29b428d77cfd86ecf96b26bd4c58a2..ce0df32bfe43b69757f01ddc877f66f3ca051d56 100644 (file)
@@ -249,6 +249,7 @@ static void radeon_generate_mipmap(struct gl_context *ctx, GLenum target,
        radeonTexObj* t = radeon_tex_obj(texObj);
        GLuint nr_faces = (t->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
        int i, face;
+       struct gl_texture_image *first_image;
 
        radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
                        "%s(%p, tex %p) Target type %s.\n",
@@ -257,6 +258,13 @@ static void radeon_generate_mipmap(struct gl_context *ctx, GLenum target,
 
        _mesa_generate_mipmap(ctx, target, texObj);
 
+       /* For the compressed case, we don't need to do the
+        * non-TexImage recovery path below.
+        */
+       first_image = texObj->Image[0][texObj->BaseLevel];
+       if (_mesa_is_format_compressed(first_image->TexFormat))
+               return;
+
        for (face = 0; face < nr_faces; face++) {
                for (i = texObj->BaseLevel + 1; i < texObj->MaxLevel; i++) {
                        radeon_texture_image *image;
index 43eea5050deb13e6f4a90c54c00e6d68e167fa20..f2724dbca7ee41039b127623a4b8d33971805898 100644 (file)
@@ -1971,13 +1971,12 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
 {
    GLint level;
    gl_format temp_format;
-   const GLubyte *srcData = NULL;
-   GLubyte *dstData = NULL;
-   GLenum datatype, temp_base_format;
+   GLenum datatype;
    GLuint comps;
    GLuint row;
-   GLint components, size;
-   GLchan *dst;
+   GLint components;
+   GLuint temp_src_stride, temp_dst_stride; /* in bytes */
+   GLchan *temp_src = NULL, *temp_dst = NULL;
 
    /* Choose the format we will do _mesa_generate_mipmap_level() in,
     * and uncompress the firstImage into a temporary of that format.
@@ -2009,25 +2008,18 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
    }
 
    /* allocate storage for uncompressed GL_RGB or GL_RGBA images */
-   size = _mesa_bytes_per_pixel(srcImage->_BaseFormat, CHAN_TYPE)
-      * srcImage->Width * srcImage->Height * srcImage->Depth + 20;
+   temp_src_stride = _mesa_format_row_stride(temp_format, srcImage->Width);
    /* 20 extra bytes, just be safe when calling last FetchTexel */
-   srcData = (GLubyte *) malloc(size);
-   if (!srcData) {
+   temp_src = (GLubyte *) malloc(temp_src_stride * srcImage->Height + 20);
+   if (!temp_src) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
       return;
    }
-   dstData = (GLubyte *) malloc(size / 2);  /* 1/4 would probably be OK */
-   if (!dstData) {
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
-      free((void *) srcData);
-      return;
-   }
 
-   /* decompress base image here */
-   dst = (GLchan *) srcData;
+   /* decompress base image to the temporary */
    for (row = 0; row < srcImage->Height; row++) {
       GLuint col;
+      GLchan *dst = (GLchan *) temp_src + temp_src_stride * row;
       for (col = 0; col < srcImage->Width; col++) {
         srcImage->FetchTexelc(srcImage, col, row, 0, dst);
         dst += components;
@@ -2035,7 +2027,6 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
    }
 
    _mesa_format_to_type_and_comps(temp_format, &datatype, &comps);
-   temp_base_format = _mesa_get_format_base_format(temp_format);
 
    for (level = texObj->BaseLevel; level < maxLevel; level++) {
       /* generate image[level+1] from image[level] */
@@ -2057,11 +2048,16 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
       nextLevel = next_mipmap_level_size(target, border,
                                          srcWidth, srcHeight, srcDepth,
                                          &dstWidth, &dstHeight, &dstDepth);
-      if (!nextLevel) {
-         /* all done */
-        free((void *) srcData);
-        free(dstData);
-         return;
+      if (!nextLevel)
+        break;
+
+      temp_dst_stride = _mesa_format_row_stride(temp_format, dstWidth);
+      if (!temp_dst) {
+        temp_dst = (GLubyte *) malloc(temp_dst_stride * dstHeight);
+        if (!temp_dst) {
+           _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
+           break;
+        }
       }
 
       /* get dest gl_texture_image */
@@ -2071,60 +2067,36 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
          return;
       }
 
-      /* Free old image data */
-      if (dstImage->Data)
-         ctx->Driver.FreeTexImageData(ctx, dstImage);
+      _mesa_generate_mipmap_level(target, datatype, comps, border,
+                                  srcWidth, srcHeight, srcDepth,
+                                  temp_src, temp_src_stride / components,
+                                  dstWidth, dstHeight, dstDepth,
+                                  temp_dst, temp_dst_stride / components);
 
       /* initialize new image */
       _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight,
                                  dstDepth, border, srcImage->InternalFormat,
                                  srcImage->TexFormat);
-      dstImage->DriverData = NULL;
-      dstImage->FetchTexelc = srcImage->FetchTexelc;
-      dstImage->FetchTexelf = srcImage->FetchTexelf;
 
-      /* Alloc new teximage data buffer */
-      {
-         GLuint size = _mesa_format_image_size(dstImage->TexFormat,
-                                               dstWidth, dstHeight, dstDepth);
-         dstImage->Data = _mesa_alloc_texmemory(size);
-         if (!dstImage->Data) {
-            _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
-            return;
-         }
-      }
-
-      ASSERT(dstImage->TexFormat);
-      ASSERT(dstImage->FetchTexelc);
-      ASSERT(dstImage->FetchTexelf);
-
-      _mesa_generate_mipmap_level(target, datatype, comps, border,
-                                  srcWidth, srcHeight, srcDepth,
-                                  srcData, srcImage->RowStride,
-                                  dstWidth, dstHeight, dstDepth,
-                                  dstData, dstImage->RowStride);
-
-      /* compress image from dstData into dstImage->Data */
-      _mesa_texstore(ctx, 2, dstImage->_BaseFormat,
-                    dstImage->TexFormat,
-                    dstImage->Data,
-                    0, 0, 0, /* dstX/Y/Zoffset */
-                    _mesa_format_row_stride(dstImage->TexFormat, dstWidth),
-                    NULL,
-                    dstWidth, dstHeight, 1, /* size */
-                    temp_base_format, CHAN_TYPE,
-                    dstData, /* src data, actually */
-                    &ctx->DefaultPacking);
+      ctx->Driver.TexImage2D(ctx, target, level + 1,
+                            srcImage->InternalFormat,
+                            dstWidth, dstHeight, border,
+                            _mesa_get_format_base_format(temp_format),
+                            GL_UNSIGNED_BYTE,
+                            temp_dst, &ctx->DefaultPacking, texObj, dstImage);
 
       /* swap src and dest pointers */
       {
-        GLubyte *temp;
-        temp = (GLubyte *) srcData;
-        srcData = dstData;
-        dstData = temp;
-      }
+        GLchan *temp = temp_src;
+        temp_src = temp_dst;
+        temp_dst = temp;
 
+        temp_src_stride = temp_dst_stride;
+      }
    } /* loop over mipmap levels */
+
+   free((void *) temp_src);
+   free(temp_dst);
 }
 
 /**