From 64f19b90d777ab21f8053eddcce83369754592a6 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 2 Mar 2011 15:28:32 +1000 Subject: [PATCH] mesa/st: fix generate mipmap for signed compressed formats. This was always converting to 8-bit per channel unsigned formats, which isn't suitable for RGTC signed formats, this special cases those two formats and converts to floats for those. Signed-off-by: Dave Airlie --- src/mesa/state_tracker/st_gen_mipmap.c | 95 +++++++++++++++++--------- 1 file changed, 63 insertions(+), 32 deletions(-) diff --git a/src/mesa/state_tracker/st_gen_mipmap.c b/src/mesa/state_tracker/st_gen_mipmap.c index 4bf68280839..2ec8431bc18 100644 --- a/src/mesa/state_tracker/st_gen_mipmap.c +++ b/src/mesa/state_tracker/st_gen_mipmap.c @@ -103,52 +103,78 @@ st_render_mipmap(struct st_context *st, * image with stride==width. */ static void -decompress_image(enum pipe_format format, - const uint8_t *src, uint8_t *dst, +decompress_image(enum pipe_format format, int datatype, + const uint8_t *src, void *dst, unsigned width, unsigned height, unsigned src_stride) { const struct util_format_description *desc = util_format_description(format); const uint bw = util_format_get_blockwidth(format); const uint bh = util_format_get_blockheight(format); - const uint dst_stride = 4 * MAX2(width, bw); - - desc->unpack_rgba_8unorm(dst, dst_stride, src, src_stride, width, height); - - if (width < bw || height < bh) { - /* We're decompressing an image smaller than the compression - * block size. We don't want garbage pixel values in the region - * outside (width x height) so replicate pixels from the (width - * x height) region to fill out the (bw x bh) block size. - */ - uint x, y; - for (y = 0; y < bh; y++) { - for (x = 0; x < bw; x++) { - if (x >= width || y >= height) { - uint p = (y * bw + x) * 4; - dst[p + 0] = dst[0]; - dst[p + 1] = dst[1]; - dst[p + 2] = dst[2]; - dst[p + 3] = dst[3]; - } - } + uint dst_stride = 4 * MAX2(width, bw); + + if (datatype == GL_FLOAT) { + desc->unpack_rgba_float((float *)dst, dst_stride * sizeof(GLfloat), src, src_stride, width, height); + if (width < bw || height < bh) { + float *dst_p = (float *)dst; + /* We're decompressing an image smaller than the compression + * block size. We don't want garbage pixel values in the region + * outside (width x height) so replicate pixels from the (width + * x height) region to fill out the (bw x bh) block size. + */ + uint x, y; + for (y = 0; y < bh; y++) { + for (x = 0; x < bw; x++) { + if (x >= width || y >= height) { + uint p = (y * bw + x) * 4; + dst_p[p + 0] = dst_p[0]; + dst_p[p + 1] = dst_p[1]; + dst_p[p + 2] = dst_p[2]; + dst_p[p + 3] = dst_p[3]; + } + } + } + } + } else { + desc->unpack_rgba_8unorm((uint8_t *)dst, dst_stride, src, src_stride, width, height); + if (width < bw || height < bh) { + uint8_t *dst_p = (uint8_t *)dst; + /* We're decompressing an image smaller than the compression + * block size. We don't want garbage pixel values in the region + * outside (width x height) so replicate pixels from the (width + * x height) region to fill out the (bw x bh) block size. + */ + uint x, y; + for (y = 0; y < bh; y++) { + for (x = 0; x < bw; x++) { + if (x >= width || y >= height) { + uint p = (y * bw + x) * 4; + dst_p[p + 0] = dst_p[0]; + dst_p[p + 1] = dst_p[1]; + dst_p[p + 2] = dst_p[2]; + dst_p[p + 3] = dst_p[3]; + } + } + } } } } - /** * Helper function to compress an image. The source is a 32-bpp RGBA image * with stride==width. */ static void -compress_image(enum pipe_format format, - const uint8_t *src, uint8_t *dst, +compress_image(enum pipe_format format, int datatype, + const void *src, uint8_t *dst, unsigned width, unsigned height, unsigned dst_stride) { const struct util_format_description *desc = util_format_description(format); const uint src_stride = 4 * width; - desc->pack_rgba_8unorm(dst, dst_stride, src, src_stride, width, height); + if (datatype == GL_FLOAT) + desc->pack_rgba_float(dst, dst_stride, (GLfloat *)src, src_stride * sizeof(GLfloat), width, height); + else + desc->pack_rgba_8unorm(dst, dst_stride, (uint8_t *)src, src_stride, width, height); } @@ -178,7 +204,12 @@ fallback_generate_mipmap(struct gl_context *ctx, GLenum target, _mesa_is_format_compressed(texObj->Image[face][baseLevel]->TexFormat); if (compressed) { - datatype = GL_UNSIGNED_BYTE; + if (texObj->Image[face][baseLevel]->TexFormat == MESA_FORMAT_SIGNED_RED_RGTC1 || + texObj->Image[face][baseLevel]->TexFormat == MESA_FORMAT_SIGNED_RG_RGTC2) + datatype = GL_FLOAT; + else + datatype = GL_UNSIGNED_BYTE; + comps = 4; } else { @@ -230,11 +261,11 @@ fallback_generate_mipmap(struct gl_context *ctx, GLenum target, assert(comps == 4); - srcTemp = malloc(srcWidth2 * srcHeight2 * comps + 000); - dstTemp = malloc(dstWidth2 * dstHeight2 * comps + 000); + srcTemp = malloc(srcWidth2 * srcHeight2 * comps * (datatype == GL_FLOAT ? 4 : 1)); + dstTemp = malloc(dstWidth2 * dstHeight2 * comps * (datatype == GL_FLOAT ? 4 : 1)); /* decompress the src image: srcData -> srcTemp */ - decompress_image(format, srcData, srcTemp, srcWidth, srcHeight, srcTrans->stride); + decompress_image(format, datatype, srcData, srcTemp, srcWidth, srcHeight, srcTrans->stride); _mesa_generate_mipmap_level(target, datatype, comps, 0 /*border*/, @@ -246,7 +277,7 @@ fallback_generate_mipmap(struct gl_context *ctx, GLenum target, dstWidth2); /* stride in texels */ /* compress the new image: dstTemp -> dstData */ - compress_image(format, dstTemp, dstData, dstWidth, dstHeight, dstTrans->stride); + compress_image(format, datatype, dstTemp, dstData, dstWidth, dstHeight, dstTrans->stride); free(srcTemp); free(dstTemp); -- 2.30.2