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

Ian Romanick idr at freedesktop.org
Fri Jun 10 18:17:33 PDT 2011


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

On 06/10/2011 06:14 PM, Ian Romanick wrote:
> 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);

And after seeing all this blown away in the next patch, never mind. :)

>> -/**
>> - * 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/

iEYEARECAAYFAk3ywi0ACgkQX1gOwKyEAw8qrQCfSFM8yYhQLpcJ1QCtmaZ9M0Ow
zFoAmwd7u3hkUWiC4O2nI1ss195/rYMC
=hfnR
-----END PGP SIGNATURE-----


More information about the mesa-dev mailing list