summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <[email protected]>2011-03-02 15:28:32 +1000
committerDave Airlie <[email protected]>2011-03-02 15:30:17 +1000
commit64f19b90d777ab21f8053eddcce83369754592a6 (patch)
tree8dace1fd3725012964c3f3220602618284d8ccf5
parent8d62b2aca99ba67f794dd682ed1ec49dc8826390 (diff)
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 <[email protected]>
-rw-r--r--src/mesa/state_tracker/st_gen_mipmap.c95
1 files 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);