Quellcode durchsuchen

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 vor 14 Jahren
Ursprung
Commit
64f19b90d7
1 geänderte Dateien mit 63 neuen und 32 gelöschten Zeilen
  1. 63
    32
      src/mesa/state_tracker/st_gen_mipmap.c

+ 63
- 32
src/mesa/state_tracker/st_gen_mipmap.c Datei anzeigen

@@ -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);

Laden…
Abbrechen
Speichern