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