On 03/01/2012 12:42 AM, Jose Fonseca wrote:
----- Original Message -----
These will be used by glReadPixels() and glGetTexImage() to fix
issues
with reading GL_LUMINANCE and other formats.
---
  src/mesa/main/pack.c |   91
  ++++++++++++++++++++++++++++++++++++++++++++++++++
  src/mesa/main/pack.h |    7 ++++
  2 files changed, 98 insertions(+), 0 deletions(-)

diff --git a/src/mesa/main/pack.c b/src/mesa/main/pack.c
index 41485a1..4d4b4a8 100644
--- a/src/mesa/main/pack.c
+++ b/src/mesa/main/pack.c
@@ -5250,3 +5250,94 @@ _mesa_unpack_image( GLuint dimensions,
     }
  }

+
+
+/**
+ * If we unpack colors from a luminance surface, we'll get pixel
colors
+ * such as (l, l, l, a).
+ * When we call _mesa_pack_rgba_span_float(format=GL_LUMINANCE),
that
+ * function will compute L=R+G+B before packing.  The net effect is
we'll
+ * accidentally store luminance values = 3*l.
+ * This function compensates for that by converting (aka rebasing)
(l,l,l,a)
+ * to be (l,0,0,a).
+ * It's a similar story for other formats such as LUMINANCE_ALPHA,
ALPHA
+ * and INTENSITY.
+ *
+ * Finally, we also need to do this when the actual surface format
does
+ * not match the logical surface format.  For example, suppose the
user
+ * requests a GL_LUMINANCE texture but the driver stores it as RGBA.
+ * Again, we'll get pixel values like (l,l,l,a).
+ */
+void
+_mesa_rebase_rgba_float(GLuint n, GLfloat rgba[][4], GLenum
baseFormat)
+{
+   GLuint i;
+
+   switch (baseFormat) {
+   case GL_ALPHA:
+      for (i = 0; i<  n; i++) {
+         rgba[i][RCOMP] = 0.0F;
+         rgba[i][GCOMP] = 0.0F;
+         rgba[i][BCOMP] = 0.0F;
+      }
+      break;
+   case GL_INTENSITY:
+      /* fall-through */
+   case GL_LUMINANCE:
+      for (i = 0; i<  n; i++) {
+         rgba[i][GCOMP] = 0.0F;
+         rgba[i][BCOMP] = 0.0F;
+         rgba[i][ACOMP] = 1.0F;

Is it really OK to set A == 1 for GL_INTENSITY? Imagine that baseFormat == 
INTENSITY, and the user is requesting LUMINANCE_ALPHA. It seems this would 
return L = I, A = 1, but I'd expect to get L = A = I.

I think that the

   rgba[i][ACOMP] = 1.0F

should be simply removed here, as alpha values either have the right value, or 
will be ignored.

Actually, table 6.1 of the 2.1 spec says that luminance and intensity values both map to rgba as (x, 0, 0, 1).

But also note that GL_INTENSITY is not a legal format for glReadPixels or glGetTexImage().

In any case I was just moving the code over from texgetimage.c and consolidated the two cases when I saw they were doing the same thing. So, we've been doing this for a while and nobody's complained. These are fairly obscure paths.

I'll have to write a test program to see what other drivers do.


Also, the 2.1 spec, section 4.3.2 "Reading Pixels", says

   Conversion to L

   This step applies only to RGBA component groups, and only if the format is 
either
   LUMINANCE or LUMINANCE_ALPHA. A value L is computed as

     L=R+G+B

   where R, G, and B are the values of the R, G, and B components. The single
   computed L component replaces the R, G, and B components in the group.

I couldn't find similar text about INTENSITY.  So I wonder if the INTENSITY is 
really the same -- perhaps intensity packing functions should not do the R + G 
+ B operation at all, and it looks they don't.

Since you can't 'get' GL_INTENSITY images, it's moot. I think a user would just use GL_LUMINANCE instead if they wanted to read back an intensity surface and they'd see the expected values.


Also, when baseFormat = GL_LUMINANCE and the user is calling 
glReadPixels(GL_RGBA), won't _mesa_rebase_rgba_float() wrongly zero G and B 
components?

I'll have to test that with another driver to be sure. But again, table 6.1 would seem to say "no".


This is all quite confusing..

Yup.


I wonder if instead of doing this way (ie, always do the L = R + G + B, but clear 
G&  B components when L = R is intended), it would be simpler (and more 
efficient) to do the opposite: have the L/LA pack functions do just L = R, and when 
L = R + G + B is really intended either:
- insert a R = R + G + B step between pack and unpack calls
- only do the L = R + G + B inside the transfer ops case, and fallback to that 
we.
- or pass a flag (or baseFormat) to the L/LA pack functions to choose.

I considered that too, but I wanted to do the least invasive change for the time being, basically reusing the code from glGetTexImage for glReadPixels.


This would be not only simpler but faster, as I get the impression that the 
most common case is L = R.

I'll do some test with another driver and see what happens. This might have to wait until next week though.

-Brian
_______________________________________________
mesa-dev mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to