[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