-----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----- _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev