[Mesa-dev] [PATCH 1/4] mesa: Split _mesa_generate_mipmap along compressed/uncompressed lines.

Ian Romanick idr at cs.pdx.edu
Fri Jun 10 18:14:41 PDT 2011


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 06/10/2011 01:42 PM, Eric Anholt wrote:
> The path taken is wildly different based on this (do we generate from
> a temporary image, or from level-1's data), and we appear to have
> stride bugs in the compressed case that are tough to disentangle.
> 
> This just duplicates the code for the moment, the followon commit will
> do the actual changes.  Only real code change here is handling
> maxLevel in one common place.
> ---
>  src/mesa/main/mipmap.c |  251 +++++++++++++++++++++++++++++++++++++++++++-----
>  1 files changed, 225 insertions(+), 26 deletions(-)
> 
> diff --git a/src/mesa/main/mipmap.c b/src/mesa/main/mipmap.c
> index e9fcb54..2bdb111 100644
> --- a/src/mesa/main/mipmap.c
> +++ b/src/mesa/main/mipmap.c
> @@ -1885,38 +1885,208 @@ next_mipmap_level_size(GLenum target, GLint border,
>     }
>  }
>  
> +static void
> +generate_mipmap_uncompressed(struct gl_context *ctx, GLenum target,
> +			     struct gl_texture_object *texObj,
> +			     const struct gl_texture_image *srcImage,
> +			     GLuint maxLevel)
> +{
> +   GLint level;
> +   gl_format convertFormat;
> +   const GLubyte *srcData = NULL;
> +   GLubyte *dstData = NULL;
> +   GLenum datatype;
> +   GLuint comps;
>  
> +   /* Find convertFormat - the format that do_row() will process */
> +   if (_mesa_is_format_compressed(srcImage->TexFormat)) {
> +      /* setup for compressed textures - need to allocate temporary
> +       * image buffers to hold uncompressed images.
> +       */
> +      GLuint row;
> +      GLint  components, size;
> +      GLchan *dst;
>  
> +      assert(texObj->Target == GL_TEXTURE_2D ||
> +             texObj->Target == GL_TEXTURE_CUBE_MAP_ARB);

		|| texObj->Target == GL_TEXTURE_2D_ARRAY);

>  
> -/**
> - * Automatic mipmap generation.
> - * This is the fallback/default function for ctx->Driver.GenerateMipmap().
> - * Generate a complete set of mipmaps from texObj's BaseLevel image.
> - * Stop at texObj's MaxLevel or when we get to the 1x1 texture.
> - * For cube maps, target will be one of
> - * GL_TEXTURE_CUBE_MAP_POSITIVE/NEGATIVE_X/Y/Z; never GL_TEXTURE_CUBE_MAP.
> - */
> -void
> -_mesa_generate_mipmap(struct gl_context *ctx, GLenum target,
> -                      struct gl_texture_object *texObj)
> +      if (srcImage->_BaseFormat == GL_RGB) {
> +         convertFormat = MESA_FORMAT_RGB888;
> +         components = 3;
> +      } else if (srcImage->_BaseFormat == GL_RED) {
> +         convertFormat = MESA_FORMAT_R8;
> +         components = 1;
> +      } else if (srcImage->_BaseFormat == GL_RG) {
> +         convertFormat = MESA_FORMAT_RG88;
> +         components = 2;
> +      } else if (srcImage->_BaseFormat == GL_RGBA) {
> +         convertFormat = MESA_FORMAT_RGBA8888;
> +         components = 4;
> +      } else if (srcImage->_BaseFormat == GL_LUMINANCE) {
> +         convertFormat = MESA_FORMAT_L8;
> +         components = 1;
> +      } else if (srcImage->_BaseFormat == GL_LUMINANCE_ALPHA) {
> +         convertFormat = MESA_FORMAT_AL88;
> +         components = 2;
> +      } else {
> +         _mesa_problem(ctx, "bad srcImage->_BaseFormat in _mesa_generate_mipmaps");
> +         return;
> +      }
> +
> +      /* 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;
> +      /* 20 extra bytes, just be safe when calling last FetchTexel */
> +      srcData = (GLubyte *) malloc(size);
> +      if (!srcData) {
> +         _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;
> +      for (row = 0; row < srcImage->Height; row++) {
> +         GLuint col;
> +         for (col = 0; col < srcImage->Width; col++) {
> +            srcImage->FetchTexelc(srcImage, col, row, 0, dst);
> +            dst += components;
> +         }
> +      }
> +   }
> +   else {
> +      /* uncompressed */
> +      convertFormat = srcImage->TexFormat;
> +   }
> +
> +   _mesa_format_to_type_and_comps(convertFormat, &datatype, &comps);
> +
> +   for (level = texObj->BaseLevel; level < maxLevel; level++) {
> +      /* generate image[level+1] from image[level] */
> +      const struct gl_texture_image *srcImage;
> +      struct gl_texture_image *dstImage;
> +      GLint srcWidth, srcHeight, srcDepth;
> +      GLint dstWidth, dstHeight, dstDepth;
> +      GLint border;
> +      GLboolean nextLevel;
> +
> +      /* get src image parameters */
> +      srcImage = _mesa_select_tex_image(ctx, texObj, target, level);
> +      ASSERT(srcImage);
> +      srcWidth = srcImage->Width;
> +      srcHeight = srcImage->Height;
> +      srcDepth = srcImage->Depth;
> +      border = srcImage->Border;
> +
> +      nextLevel = next_mipmap_level_size(target, border,
> +                                         srcWidth, srcHeight, srcDepth,
> +                                         &dstWidth, &dstHeight, &dstDepth);
> +      if (!nextLevel) {
> +         /* all done */
> +         if (_mesa_is_format_compressed(srcImage->TexFormat)) {
> +            free((void *) srcData);
> +            free(dstData);
> +         }
> +         return;
> +      }
> +
> +      /* get dest gl_texture_image */
> +      dstImage = _mesa_get_tex_image(ctx, texObj, target, level + 1);
> +      if (!dstImage) {
> +         _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
> +         return;
> +      }
> +
> +      /* Free old image data */
> +      if (dstImage->Data)
> +         ctx->Driver.FreeTexImageData(ctx, dstImage);
> +
> +      /* 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;
> +         }
> +      }
> +
> +      /* Setup src and dest data pointers */
> +      if (_mesa_is_format_compressed(dstImage->TexFormat)) {
> +         /* srcData and dstData are already set */
> +         ASSERT(srcData);
> +         ASSERT(dstData);
> +      }
> +      else {
> +         srcData = (const GLubyte *) srcImage->Data;
> +         dstData = (GLubyte *) dstImage->Data;
> +      }
> +
> +      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);
> +
> +
> +      if (_mesa_is_format_compressed(dstImage->TexFormat)) {
> +         GLubyte *temp;
> +         /* compress image from dstData into dstImage->Data */
> +         const GLenum srcFormat = _mesa_get_format_base_format(convertFormat);
> +         GLint dstRowStride
> +            = _mesa_format_row_stride(dstImage->TexFormat, dstWidth);
> +
> +         _mesa_texstore(ctx, 2, dstImage->_BaseFormat,
> +                        dstImage->TexFormat,
> +                        dstImage->Data,
> +                        0, 0, 0, /* dstX/Y/Zoffset */
> +                        dstRowStride, 0, /* strides */
> +                        dstWidth, dstHeight, 1, /* size */
> +                        srcFormat, CHAN_TYPE,
> +                        dstData, /* src data, actually */
> +                        &ctx->DefaultPacking);
> +
> +         /* swap src and dest pointers */
> +         temp = (GLubyte *) srcData;
> +         srcData = dstData;
> +         dstData = temp;
> +      }
> +
> +   } /* loop over mipmap levels */
> +}
> +
> +static void
> +generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
> +			   struct gl_texture_object *texObj,
> +			   const struct gl_texture_image *srcImage,
> +			   GLuint maxLevel)
>  {
> -   const struct gl_texture_image *srcImage;
> +   GLint level;
>     gl_format convertFormat;
>     const GLubyte *srcData = NULL;
>     GLubyte *dstData = NULL;
> -   GLint level, maxLevels;
>     GLenum datatype;
>     GLuint comps;
>  
> -   ASSERT(texObj);
> -   srcImage = _mesa_select_tex_image(ctx, texObj, target, texObj->BaseLevel);
> -   ASSERT(srcImage);
> -
> -   maxLevels = _mesa_max_texture_levels(ctx, texObj->Target);
> -   ASSERT(maxLevels > 0);  /* bad target */
> -
>     /* Find convertFormat - the format that do_row() will process */
> -
>     if (_mesa_is_format_compressed(srcImage->TexFormat)) {
>        /* setup for compressed textures - need to allocate temporary
>         * image buffers to hold uncompressed images.
> @@ -1984,8 +2154,7 @@ _mesa_generate_mipmap(struct gl_context *ctx, GLenum target,
>  
>     _mesa_format_to_type_and_comps(convertFormat, &datatype, &comps);
>  
> -   for (level = texObj->BaseLevel; level < texObj->MaxLevel
> -           && level < maxLevels - 1; level++) {
> +   for (level = texObj->BaseLevel; level < maxLevel; level++) {
>        /* generate image[level+1] from image[level] */
>        const struct gl_texture_image *srcImage;
>        struct gl_texture_image *dstImage;
> @@ -2060,12 +2229,11 @@ _mesa_generate_mipmap(struct gl_context *ctx, GLenum target,
>        ASSERT(dstImage->FetchTexelf);
>  
>        _mesa_generate_mipmap_level(target, datatype, comps, border,
> -                                  srcWidth, srcHeight, srcDepth, 
> +                                  srcWidth, srcHeight, srcDepth,
>                                    srcData, srcImage->RowStride,
> -                                  dstWidth, dstHeight, dstDepth, 
> +                                  dstWidth, dstHeight, dstDepth,
>                                    dstData, dstImage->RowStride);
>  
> -
>        if (_mesa_is_format_compressed(dstImage->TexFormat)) {
>           GLubyte *temp;
>           /* compress image from dstData into dstImage->Data */
> @@ -2092,6 +2260,37 @@ _mesa_generate_mipmap(struct gl_context *ctx, GLenum target,
>     } /* loop over mipmap levels */
>  }
>  
> +/**
> + * Automatic mipmap generation.
> + * This is the fallback/default function for ctx->Driver.GenerateMipmap().
> + * Generate a complete set of mipmaps from texObj's BaseLevel image.
> + * Stop at texObj's MaxLevel or when we get to the 1x1 texture.
> + * For cube maps, target will be one of
> + * GL_TEXTURE_CUBE_MAP_POSITIVE/NEGATIVE_X/Y/Z; never GL_TEXTURE_CUBE_MAP.
> + */
> +void
> +_mesa_generate_mipmap(struct gl_context *ctx, GLenum target,
> +                      struct gl_texture_object *texObj)
> +{
> +   const struct gl_texture_image *srcImage;
> +   GLint maxLevel;
> +
> +   ASSERT(texObj);
> +   srcImage = _mesa_select_tex_image(ctx, texObj, target, texObj->BaseLevel);
> +   ASSERT(srcImage);
> +
> +   maxLevel = _mesa_max_texture_levels(ctx, texObj->Target) - 1;
> +   ASSERT(maxLevel >= 0);  /* bad target */
> +
> +   maxLevel = MIN2(maxLevel, texObj->MaxLevel);
> +
> +   if (_mesa_is_format_compressed(srcImage->TexFormat)) {
> +      generate_mipmap_compressed(ctx, target, texObj, srcImage, maxLevel);
> +   } else {
> +      generate_mipmap_uncompressed(ctx, target, texObj, srcImage, maxLevel);
> +   }
> +}
> +
>  
>  /**
>   * Helper function for drivers which need to rescale texture images to

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/

iEYEARECAAYFAk3ywYEACgkQX1gOwKyEAw86RgCgjpcTZLvpau3RjmCARvWMSCUU
3lwAn09My9eAheEBntzTEOFfRtMHut1O
=pUnR
-----END PGP SIGNATURE-----


More information about the mesa-dev mailing list