improved precision of glReadPixels for colorbuffers < 24bpp
authorBrian Paul <brian.paul@tungstengraphics.com>
Wed, 13 Dec 2000 00:46:21 +0000 (00:46 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Wed, 13 Dec 2000 00:46:21 +0000 (00:46 +0000)
src/mesa/main/pixel.c
src/mesa/main/pixel.h
src/mesa/swrast/s_readpix.c

index efd89cadd42dc90cced58788a81e673d7adf6233..cb0818c084daccf08d70cb18060e8018546d081f 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: pixel.c,v 1.20 2000/11/28 00:07:51 brianp Exp $ */
+/* $Id: pixel.c,v 1.21 2000/12/13 00:46:21 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -1109,3 +1109,48 @@ _mesa_map_stencil( const GLcontext *ctx, GLuint n, GLstencil stencil[] )
       stencil[i] = ctx->Pixel.MapStoS[ stencil[i] & mask ];
    }
 }
+
+
+
+/*
+ * This function converts an array of GLchan colors to GLfloat colors.
+ * Most importantly, it undoes the non-uniform quantization of pixel
+ * values introduced when we convert shallow (< 8 bit) pixel values
+ * to GLubytes in the ctx->Driver.ReadRGBASpan() functions.
+ * This fixes a number of OpenGL conformance failures when running on
+ * 16bpp displays, for example.
+ */
+void
+_mesa_chan_to_float_span(const GLcontext *ctx, GLuint n,
+                         CONST GLchan rgba[][4], GLfloat rgbaf[][4])
+{
+   const GLuint rShift = CHAN_BITS - ctx->Visual.RedBits;
+   const GLuint gShift = CHAN_BITS - ctx->Visual.GreenBits;
+   const GLuint bShift = CHAN_BITS - ctx->Visual.BlueBits;
+   GLuint aShift;
+   const GLfloat rScale = 1.0 / (GLfloat) ((1 << ctx->Visual.RedBits  ) - 1);
+   const GLfloat gScale = 1.0 / (GLfloat) ((1 << ctx->Visual.GreenBits) - 1);
+   const GLfloat bScale = 1.0 / (GLfloat) ((1 << ctx->Visual.BlueBits ) - 1);
+   GLfloat aScale;
+   GLuint i;
+
+   if (ctx->Visual.AlphaBits > 0) {
+      aShift = CHAN_BITS - ctx->Visual.AlphaBits;
+      aScale = 1.0 / (GLfloat) ((1 << ctx->Visual.AlphaBits) - 1);
+   }
+   else {
+      aShift = 0;
+      aScale = 1.0F / CHAN_MAXF;
+   }
+
+   for (i = 0; i < n; i++) {
+      const GLint r = rgba[i][RCOMP] >> rShift;
+      const GLint g = rgba[i][GCOMP] >> gShift;
+      const GLint b = rgba[i][BCOMP] >> bShift;
+      const GLint a = rgba[i][ACOMP] >> aShift;
+      rgbaf[i][RCOMP] = (GLfloat) r * rScale;
+      rgbaf[i][GCOMP] = (GLfloat) g * gScale;
+      rgbaf[i][BCOMP] = (GLfloat) b * bScale;
+      rgbaf[i][ACOMP] = (GLfloat) a * aScale;
+   }
+}
index db6dd78ffdb8436f5683117f5acdb960c3b740f6..6698d8c13f04c406e3062959756d3418dfc5eeb5 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: pixel.h,v 1.8 2000/11/28 00:07:51 brianp Exp $ */
+/* $Id: pixel.h,v 1.9 2000/12/13 00:46:21 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -131,4 +131,9 @@ extern void
 _mesa_map_stencil(const GLcontext *ctx, GLuint n, GLstencil index[]);
 
 
+extern void
+_mesa_chan_to_float_span(const GLcontext *ctx, GLuint n,
+                         CONST GLchan rgba[][4], GLfloat rgbaf[][4]);
+
+
 #endif
index 4c5e154b8fdaea9e7ba68f5d246fa73dbc639939..4cc3dbd6181c2c018536ceb3ef13a72efc1066f7 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: s_readpix.c,v 1.4 2000/11/28 00:04:39 brianp Exp $ */
+/* $Id: s_readpix.c,v 1.5 2000/12/13 00:46:22 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -716,9 +716,27 @@ static void read_rgba_pixels( GLcontext *ctx,
          }
          dst = _mesa_image_address(packing, pixels, width, height,
                                    format, type, 0, row, 0);
-         _mesa_pack_rgba_span(ctx, readWidth, (const GLchan (*)[4]) rgba,
-                              format, type, dst, packing,
-                              ctx->_ImageTransferState);
+         if (ctx->Visual.RedBits < CHAN_BITS ||
+             ctx->Visual.GreenBits < CHAN_BITS ||
+             ctx->Visual.BlueBits < CHAN_BITS) {
+            /* Requantize the color values into floating point and go from
+             * there.  This fixes conformance failures with 16-bit color
+             * buffers, for example.
+             */
+            GLfloat rgbaf[MAX_WIDTH][4];
+            _mesa_chan_to_float_span(ctx, readWidth,
+                                     (CONST GLchan (*)[4]) rgba, rgbaf);
+            _mesa_pack_float_rgba_span(ctx, readWidth,
+                                       (CONST GLfloat (*)[4]) rgbaf,
+                                       format, type, dst, packing,
+                                       ctx->_ImageTransferState);
+         }
+         else {
+            /* GLubytes are fine */
+            _mesa_pack_rgba_span(ctx, readWidth, (CONST GLchan (*)[4]) rgba,
+                                 format, type, dst, packing,
+                                 ctx->_ImageTransferState);
+         }
       }
    }