From 10e418f3815d690b2526e835bc7eb421b6be7050 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 10 Jun 2011 12:58:56 -0700 Subject: [PATCH] mesa: Switch generate_mipmaps_compressed() to using TexImage2D to upload. The code was playing fast and loose with rowstrides, which meant that if a driver chose anything different for its alignment requirements, the generated mipmaps came out garbage. Unlike the uncompressed case, we can't generate mipmaps directly into image->Data, so by using TexImage2D we cut out most of the weird logic that existed to generate in-place into ->Data. The up/downside is that the driver recovery code for the fact that _mesa_generate_mipmaps whacked ->Data has to be turned off for compressed now. Fixes 6 piglit tests about compressed mipmap gen. --- src/mesa/drivers/dri/intel/intel_tex.c | 3 +- src/mesa/drivers/dri/nouveau/nouveau_texture.c | 6 +- src/mesa/drivers/dri/radeon/radeon_texture.c | 8 ++ src/mesa/main/mipmap.c | 104 +++++++++---------------- 4 files changed, 52 insertions(+), 69 deletions(-) diff --git a/src/mesa/drivers/dri/intel/intel_tex.c b/src/mesa/drivers/dri/intel/intel_tex.c index 2c3eab2..32e1fb7 100644 --- a/src/mesa/drivers/dri/intel/intel_tex.c +++ b/src/mesa/drivers/dri/intel/intel_tex.c @@ -75,6 +75,7 @@ intelGenerateMipmap(struct gl_context *ctx, GLenum target, /* sw path: need to map texture images */ struct intel_context *intel = intel_context(ctx); struct intel_texture_object *intelObj = intel_texture_object(texObj); + struct gl_texture_image *first_image = texObj->Image[0][texObj->BaseLevel]; fallback_debug("%s - fallback to swrast\n", __FUNCTION__); @@ -82,7 +83,7 @@ intelGenerateMipmap(struct gl_context *ctx, GLenum target, _mesa_generate_mipmap(ctx, target, texObj); intel_tex_unmap_level_images(intel, intelObj, texObj->BaseLevel); - { + if (!_mesa_is_format_compressed(first_image->TexFormat)) { GLuint nr_faces = (texObj->Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; GLuint face, i; /* Update the level information in our private data in the new images, diff --git a/src/mesa/drivers/dri/nouveau/nouveau_texture.c b/src/mesa/drivers/dri/nouveau/nouveau_texture.c index 36e68c9..dcfd316 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_texture.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_texture.c @@ -688,8 +688,10 @@ nouveau_generate_mipmap(struct gl_context *ctx, GLenum target, _mesa_generate_mipmap(ctx, target, t); nouveau_teximage_unmap(ctx, base); - store_mipmap(ctx, target, t->BaseLevel + 1, - get_last_level(t), t); + if (!_mesa_is_format_compressed(base->TexFormat)) { + store_mipmap(ctx, target, t->BaseLevel + 1, + get_last_level(t), t); + } } else { _mesa_meta_GenerateMipmap(ctx, target, t); diff --git a/src/mesa/drivers/dri/radeon/radeon_texture.c b/src/mesa/drivers/dri/radeon/radeon_texture.c index 9ec5388..ce0df32 100644 --- a/src/mesa/drivers/dri/radeon/radeon_texture.c +++ b/src/mesa/drivers/dri/radeon/radeon_texture.c @@ -249,6 +249,7 @@ static void radeon_generate_mipmap(struct gl_context *ctx, GLenum target, radeonTexObj* t = radeon_tex_obj(texObj); GLuint nr_faces = (t->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; int i, face; + struct gl_texture_image *first_image; radeon_print(RADEON_TEXTURE, RADEON_VERBOSE, "%s(%p, tex %p) Target type %s.\n", @@ -257,6 +258,13 @@ static void radeon_generate_mipmap(struct gl_context *ctx, GLenum target, _mesa_generate_mipmap(ctx, target, texObj); + /* For the compressed case, we don't need to do the + * non-TexImage recovery path below. + */ + first_image = texObj->Image[0][texObj->BaseLevel]; + if (_mesa_is_format_compressed(first_image->TexFormat)) + return; + for (face = 0; face < nr_faces; face++) { for (i = texObj->BaseLevel + 1; i < texObj->MaxLevel; i++) { radeon_texture_image *image; diff --git a/src/mesa/main/mipmap.c b/src/mesa/main/mipmap.c index 43eea50..f2724db 100644 --- a/src/mesa/main/mipmap.c +++ b/src/mesa/main/mipmap.c @@ -1971,13 +1971,12 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target, { GLint level; gl_format temp_format; - const GLubyte *srcData = NULL; - GLubyte *dstData = NULL; - GLenum datatype, temp_base_format; + GLenum datatype; GLuint comps; GLuint row; - GLint components, size; - GLchan *dst; + GLint components; + GLuint temp_src_stride, temp_dst_stride; /* in bytes */ + GLchan *temp_src = NULL, *temp_dst = NULL; /* Choose the format we will do _mesa_generate_mipmap_level() in, * and uncompress the firstImage into a temporary of that format. @@ -2009,25 +2008,18 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target, } /* 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; + temp_src_stride = _mesa_format_row_stride(temp_format, srcImage->Width); /* 20 extra bytes, just be safe when calling last FetchTexel */ - srcData = (GLubyte *) malloc(size); - if (!srcData) { + temp_src = (GLubyte *) malloc(temp_src_stride * srcImage->Height + 20); + if (!temp_src) { _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; + /* decompress base image to the temporary */ for (row = 0; row < srcImage->Height; row++) { GLuint col; + GLchan *dst = (GLchan *) temp_src + temp_src_stride * row; for (col = 0; col < srcImage->Width; col++) { srcImage->FetchTexelc(srcImage, col, row, 0, dst); dst += components; @@ -2035,7 +2027,6 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target, } _mesa_format_to_type_and_comps(temp_format, &datatype, &comps); - temp_base_format = _mesa_get_format_base_format(temp_format); for (level = texObj->BaseLevel; level < maxLevel; level++) { /* generate image[level+1] from image[level] */ @@ -2057,11 +2048,16 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target, nextLevel = next_mipmap_level_size(target, border, srcWidth, srcHeight, srcDepth, &dstWidth, &dstHeight, &dstDepth); - if (!nextLevel) { - /* all done */ - free((void *) srcData); - free(dstData); - return; + if (!nextLevel) + break; + + temp_dst_stride = _mesa_format_row_stride(temp_format, dstWidth); + if (!temp_dst) { + temp_dst = (GLubyte *) malloc(temp_dst_stride * dstHeight); + if (!temp_dst) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps"); + break; + } } /* get dest gl_texture_image */ @@ -2071,60 +2067,36 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target, return; } - /* Free old image data */ - if (dstImage->Data) - ctx->Driver.FreeTexImageData(ctx, dstImage); + _mesa_generate_mipmap_level(target, datatype, comps, border, + srcWidth, srcHeight, srcDepth, + temp_src, temp_src_stride / components, + dstWidth, dstHeight, dstDepth, + temp_dst, temp_dst_stride / components); /* 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; - } - } - - 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); - - /* compress image from dstData into dstImage->Data */ - _mesa_texstore(ctx, 2, dstImage->_BaseFormat, - dstImage->TexFormat, - dstImage->Data, - 0, 0, 0, /* dstX/Y/Zoffset */ - _mesa_format_row_stride(dstImage->TexFormat, dstWidth), - NULL, - dstWidth, dstHeight, 1, /* size */ - temp_base_format, CHAN_TYPE, - dstData, /* src data, actually */ - &ctx->DefaultPacking); + ctx->Driver.TexImage2D(ctx, target, level + 1, + srcImage->InternalFormat, + dstWidth, dstHeight, border, + _mesa_get_format_base_format(temp_format), + GL_UNSIGNED_BYTE, + temp_dst, &ctx->DefaultPacking, texObj, dstImage); /* swap src and dest pointers */ { - GLubyte *temp; - temp = (GLubyte *) srcData; - srcData = dstData; - dstData = temp; - } + GLchan *temp = temp_src; + temp_src = temp_dst; + temp_dst = temp; + temp_src_stride = temp_dst_stride; + } } /* loop over mipmap levels */ + + free((void *) temp_src); + free(temp_dst); } /** -- 2.7.4