diff options
Diffstat (limited to 'src/mesa')
-rw-r--r-- | src/mesa/swrast/s_readpix.c | 71 |
1 files changed, 45 insertions, 26 deletions
diff --git a/src/mesa/swrast/s_readpix.c b/src/mesa/swrast/s_readpix.c index 334dc02918..78441bff38 100644 --- a/src/mesa/swrast/s_readpix.c +++ b/src/mesa/swrast/s_readpix.c @@ -262,6 +262,41 @@ fast_read_rgba_pixels( GLcontext *ctx, } +/** + * When we're using a low-precision color buffer (like 16-bit 5/6/5) + * we have to adjust our color values a bit to pass conformance. + * The problem is when a 5 or 6-bit color value is convert to an 8-bit + * value and then a floating point value, the floating point values don't + * increment uniformly as the 5 or 6-bit value is incremented. + * + * This function adjusts floating point values to compensate. + */ +static void +adjust_colors(GLcontext *ctx, GLuint n, GLfloat rgba[][4]) +{ + const GLuint rShift = 8 - ctx->Visual.redBits; + const GLuint gShift = 8 - ctx->Visual.greenBits; + const GLuint bShift = 8 - ctx->Visual.blueBits; + const GLfloat rScale = 1.0F / (GLfloat) ((1 << ctx->Visual.redBits ) - 1); + const GLfloat gScale = 1.0F / (GLfloat) ((1 << ctx->Visual.greenBits) - 1); + const GLfloat bScale = 1.0F / (GLfloat) ((1 << ctx->Visual.blueBits ) - 1); + GLuint i; + for (i = 0; i < n; i++) { + GLint r, g, b; + /* convert float back to ubyte */ + CLAMPED_FLOAT_TO_UBYTE(r, rgba[i][RCOMP]); + CLAMPED_FLOAT_TO_UBYTE(g, rgba[i][GCOMP]); + CLAMPED_FLOAT_TO_UBYTE(b, rgba[i][BCOMP]); + /* using only the N most significant bits of the ubyte value, convert to + * float in [0,1]. + */ + rgba[i][RCOMP] = (GLfloat) (r >> rShift) * rScale; + rgba[i][GCOMP] = (GLfloat) (g >> gShift) * gScale; + rgba[i][BCOMP] = (GLfloat) (b >> bShift) * bScale; + } +} + + /* * Read R, G, B, A, RGB, L, or LA pixels. @@ -376,34 +411,18 @@ read_rgba_pixels( GLcontext *ctx, _mesa_map_ci_to_rgba(ctx, width, index, rgba); } - /* pack the row of RGBA pixels into user's buffer */ -#if 0 - /* XXX may need to rejuvinate this code if we get conformance - * falures on 16bpp displays (i.e. 5/6/5). - */ - if (fb->Visual.redBits < CHAN_BITS || - fb->Visual.greenBits < CHAN_BITS || - fb->Visual.blueBits < CHAN_BITS) { - /* Requantize the color values into floating point and go from - * there. This fixes conformance failures with 5/6/5 color - * buffers, for example. - */ - GLfloat rgbaf[MAX_WIDTH][4]; - _mesa_chan_to_float_span(ctx, width, - (CONST GLchan (*)[4]) rgba, rgbaf); - _mesa_pack_rgba_span_float(ctx, width, - (CONST GLfloat (*)[4]) rgbaf, - format, type, dst, packing, - ctx->_ImageTransferState); - } - else -#endif - { - _mesa_pack_rgba_span_float(ctx, width, (CONST GLfloat (*)[4]) rgba, - format, type, dst, - packing, ctx->_ImageTransferState); + /* apply fudge factor for shallow color buffers */ + if (fb->Visual.redBits < 8 || + fb->Visual.greenBits < 8 || + fb->Visual.blueBits < 8) { + adjust_colors(ctx, width, rgba); } + /* pack the row of RGBA pixels into user's buffer */ + _mesa_pack_rgba_span_float(ctx, width, (CONST GLfloat (*)[4]) rgba, + format, type, dst, + packing, ctx->_ImageTransferState); + dst += dstStride; } } |