[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