[Mesa-dev] [PATCH 1/3] mesa: add _mesa_rebase_rgba_float/uint() functions
Jose Fonseca
jfonseca at vmware.com
Wed Feb 29 23:42:26 PST 2012
----- 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.
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.
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?
This is all quite confusing..
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.
This would be not only simpler but faster, as I get the impression that the most common case is L = R.
Jose
> + }
> + break;
> + case GL_LUMINANCE_ALPHA:
> + for (i = 0; i < n; i++) {
> + rgba[i][GCOMP] = 0.0F;
> + rgba[i][BCOMP] = 0.0F;
> + }
> + break;
> + default:
> + /* no-op */
> + ;
> + }
> +}
> +
> +
> +/**
> + * As above, but GLuint components.
> + */
> +void
> +_mesa_rebase_rgba_uint(GLuint n, GLuint rgba[][4], GLenum
> baseFormat)
> +{
> + GLuint i;
> +
> + switch (baseFormat) {
> + case GL_ALPHA:
> + for (i = 0; i < n; i++) {
> + rgba[i][RCOMP] = 0;
> + rgba[i][GCOMP] = 0;
> + rgba[i][BCOMP] = 0;
> + }
> + break;
> + case GL_INTENSITY:
> + /* fall-through */
> + case GL_LUMINANCE:
> + for (i = 0; i < n; i++) {
> + rgba[i][GCOMP] = 0;
> + rgba[i][BCOMP] = 0;
> + rgba[i][ACOMP] = 1;
> + }
> + break;
> + case GL_LUMINANCE_ALPHA:
> + for (i = 0; i < n; i++) {
> + rgba[i][GCOMP] = 0;
> + rgba[i][BCOMP] = 0;
> + }
> + break;
> + default:
> + /* no-op */
> + ;
> + }
> +}
> +
> +
> diff --git a/src/mesa/main/pack.h b/src/mesa/main/pack.h
> index b1853cd..cd49c74 100644
> --- a/src/mesa/main/pack.h
> +++ b/src/mesa/main/pack.h
> @@ -149,4 +149,11 @@ _mesa_pack_rgba_span_int(struct gl_context *ctx,
> GLuint n, GLuint rgba[][4],
> GLenum dstFormat, GLenum dstType,
> GLvoid *dstAddr);
>
> +
> +extern void
> +_mesa_rebase_rgba_float(GLuint n, GLfloat rgba[][4], GLenum
> baseFormat);
> +
> +extern void
> +_mesa_rebase_rgba_uint(GLuint n, GLuint rgba[][4], GLenum
> baseFormat);
> +
> #endif
> --
> 1.7.3.4
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
>
More information about the mesa-dev
mailing list