Browse Source

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 <airlied@redhat.com>
tags/android-x86-2.2-r2
Dave Airlie 14 years ago
parent
commit
64f19b90d7
1 changed files with 63 additions and 32 deletions
  1. 63
    32
      src/mesa/state_tracker/st_gen_mipmap.c

+ 63
- 32
src/mesa/state_tracker/st_gen_mipmap.c View File

* image with stride==width. * image with stride==width.
*/ */
static void 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) unsigned width, unsigned height, unsigned src_stride)
{ {
const struct util_format_description *desc = util_format_description(format); const struct util_format_description *desc = util_format_description(format);
const uint bw = util_format_get_blockwidth(format); const uint bw = util_format_get_blockwidth(format);
const uint bh = util_format_get_blockheight(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 * Helper function to compress an image. The source is a 32-bpp RGBA image
* with stride==width. * with stride==width.
*/ */
static void 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) unsigned width, unsigned height, unsigned dst_stride)
{ {
const struct util_format_description *desc = util_format_description(format); const struct util_format_description *desc = util_format_description(format);
const uint src_stride = 4 * width; 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);
} }




_mesa_is_format_compressed(texObj->Image[face][baseLevel]->TexFormat); _mesa_is_format_compressed(texObj->Image[face][baseLevel]->TexFormat);


if (compressed) { 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; comps = 4;
} }
else { else {


assert(comps == 4); 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 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, _mesa_generate_mipmap_level(target, datatype, comps,
0 /*border*/, 0 /*border*/,
dstWidth2); /* stride in texels */ dstWidth2); /* stride in texels */


/* compress the new image: dstTemp -> dstData */ /* 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(srcTemp);
free(dstTemp); free(dstTemp);

Loading…
Cancel
Save