[Mesa-dev] [PATCH] mesa/swrast: handle sRGB FBOs correctly.

Brian Paul brianp at vmware.com
Mon Jan 10 07:24:53 PST 2011


On 01/09/2011 08:43 PM, Dave Airlie wrote:
> From: Dave Airlie<airlied at redhat.com>
>
>> From reading EXT_texture_sRGB and EXT_framebuffer_sRGB and interactions
> with FBO I've found that swrast is converting the sRGB values to linear for
> blending when an sRGB texture is bound as an FBO. According to the spec
> and further explained in the framebuffer_sRGB spec this behaviour is not
> required unless the GL_FRAMEBUFFER_SRGB is enabled and the Visual/config
> exposes GL_FRAMEBUFFER_SRGB_CAPABLE_EXT.
>
> This patch fixes swrast to use a separate Fetch call for FBOs bound to
> SRGB and avoid the conversions.

One comment below.

BTW, as long as you're looking at sRGB, it might be interesting to 
implement the new GL_EXT_texture_sRGB_decode extension: 
http://www.opengl.org/registry/specs/EXT/texture_sRGB_decode.txt

-Brian


> Signed-off-by: Dave Airlie<airlied at redhat.com>
> ---
>   src/mesa/main/texfetch.c  |    2 +-
>   src/mesa/main/texfetch.h  |    3 ++
>   src/mesa/main/texrender.c |   60 ++++++++++++++++++++++++++++++++++++--------
>   3 files changed, 53 insertions(+), 12 deletions(-)
>
> diff --git a/src/mesa/main/texfetch.c b/src/mesa/main/texfetch.c
> index 77bbc91..1135120 100644
> --- a/src/mesa/main/texfetch.c
> +++ b/src/mesa/main/texfetch.c
> @@ -759,7 +759,7 @@ texfetch_funcs[MESA_FORMAT_COUNT] =
>   };
>
>
> -static FetchTexelFuncF
> +FetchTexelFuncF
>   _mesa_get_texel_fetch_func(gl_format format, GLuint dims)
>   {
>   #ifdef DEBUG
> diff --git a/src/mesa/main/texfetch.h b/src/mesa/main/texfetch.h
> index ef13bf2..e78079a 100644
> --- a/src/mesa/main/texfetch.h
> +++ b/src/mesa/main/texfetch.h
> @@ -34,6 +34,9 @@
>   extern StoreTexelFunc
>   _mesa_get_texel_store_func(gl_format format);
>
> +extern FetchTexelFuncF
> +_mesa_get_texel_fetch_func(gl_format format, GLuint dims);
> +
>   extern void
>   _mesa_set_fetch_functions(struct gl_texture_image *texImage, GLuint dims);
>
> diff --git a/src/mesa/main/texrender.c b/src/mesa/main/texrender.c
> index 8961b92..1001444 100644
> --- a/src/mesa/main/texrender.c
> +++ b/src/mesa/main/texrender.c
> @@ -20,6 +20,7 @@ struct texture_renderbuffer
>      struct gl_renderbuffer Base;   /**<  Base class object */
>      struct gl_texture_image *TexImage;
>      StoreTexelFunc Store;
> +   FetchTexelFuncF Fetchf;
>      GLint Yoffset;                 /**<  Layer for 1D array textures. */
>      GLint Zoffset;                 /**<  Layer for 2D array textures, or slice
>   				   * for 3D textures
> @@ -48,7 +49,7 @@ texture_get_row(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count
>         GLchan *rgbaOut = (GLchan *) values;
>         for (i = 0; i<  count; i++) {
>            GLfloat rgba[4];
> -         trb->TexImage->FetchTexelf(trb->TexImage, x + i, y, z, rgba);
> +         trb->Fetchf(trb->TexImage, x + i, y, z, rgba);
>            UNCLAMPED_FLOAT_TO_RGBA_CHAN(rgbaOut + 4 * i, rgba);
>         }
>      }
> @@ -56,7 +57,7 @@ texture_get_row(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count
>         GLushort *zValues = (GLushort *) values;
>         for (i = 0; i<  count; i++) {
>            GLfloat flt;
> -         trb->TexImage->FetchTexelf(trb->TexImage, x + i, y, z,&flt);
> +         trb->Fetchf(trb->TexImage, x + i, y, z,&flt);
>            zValues[i] = (GLushort) (flt * 0xffff);
>         }
>      }
> @@ -67,7 +68,7 @@ texture_get_row(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count
>         */
>         for (i = 0; i<  count; i++) {
>            GLfloat flt;
> -         trb->TexImage->FetchTexelf(trb->TexImage, x + i, y, z,&flt);
> +         trb->Fetchf(trb->TexImage, x + i, y, z,&flt);
>   #if 0
>            /* this should work, but doesn't (overflow due to low precision) */
>            zValues[i] = (GLuint) (flt * scale);
> @@ -81,7 +82,7 @@ texture_get_row(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count
>         GLuint *zValues = (GLuint *) values;
>         for (i = 0; i<  count; i++) {
>            GLfloat flt;
> -         trb->TexImage->FetchTexelf(trb->TexImage, x + i, y, z,&flt);
> +         trb->Fetchf(trb->TexImage, x + i, y, z,&flt);
>            zValues[i] = ((GLuint) (flt * 0xffffff))<<  8;
>         }
>      }
> @@ -89,7 +90,7 @@ texture_get_row(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count
>         GLuint *zValues = (GLuint *) values;
>         for (i = 0; i<  count; i++) {
>            GLfloat flt;
> -         trb->TexImage->FetchTexelf(trb->TexImage, x + i, y, z,&flt);
> +         trb->Fetchf(trb->TexImage, x + i, y, z,&flt);
>            zValues[i] = (GLuint) (flt * 0xffffff);
>         }
>      }
> @@ -112,7 +113,7 @@ texture_get_values(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint co
>         GLchan *rgbaOut = (GLchan *) values;
>         for (i = 0; i<  count; i++) {
>            GLfloat rgba[4];
> -         trb->TexImage->FetchTexelf(trb->TexImage, x[i], y[i] + trb->Yoffset,
> +         trb->Fetchf(trb->TexImage, x[i], y[i] + trb->Yoffset,
>   				    z, rgba);
>            UNCLAMPED_FLOAT_TO_RGBA_CHAN(rgbaOut + 4 * i, rgba);
>         }
> @@ -121,7 +122,7 @@ texture_get_values(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint co
>         GLushort *zValues = (GLushort *) values;
>         for (i = 0; i<  count; i++) {
>            GLfloat flt;
> -         trb->TexImage->FetchTexelf(trb->TexImage, x[i], y[i] + trb->Yoffset,
> +         trb->Fetchf(trb->TexImage, x[i], y[i] + trb->Yoffset,
>   				    z,&flt);
>            zValues[i] = (GLushort) (flt * 0xffff);
>         }
> @@ -130,7 +131,7 @@ texture_get_values(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint co
>         GLuint *zValues = (GLuint *) values;
>         for (i = 0; i<  count; i++) {
>            GLfloat flt;
> -         trb->TexImage->FetchTexelf(trb->TexImage, x[i], y[i] + trb->Yoffset,
> +         trb->Fetchf(trb->TexImage, x[i], y[i] + trb->Yoffset,
>   				    z,&flt);
>   #if 0
>            zValues[i] = (GLuint) (flt * 0xffffffff);
> @@ -143,7 +144,7 @@ texture_get_values(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint co
>         GLuint *zValues = (GLuint *) values;
>         for (i = 0; i<  count; i++) {
>            GLfloat flt;
> -         trb->TexImage->FetchTexelf(trb->TexImage, x[i], y[i] + trb->Yoffset,
> +         trb->Fetchf(trb->TexImage, x[i], y[i] + trb->Yoffset,
>   				    z,&flt);
>            zValues[i] = ((GLuint) (flt * 0xffffff))<<  8;
>         }
> @@ -152,7 +153,7 @@ texture_get_values(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint co
>         GLuint *zValues = (GLuint *) values;
>         for (i = 0; i<  count; i++) {
>            GLfloat flt;
> -         trb->TexImage->FetchTexelf(trb->TexImage, x[i], y[i] + trb->Yoffset,
> +         trb->Fetchf(trb->TexImage, x[i], y[i] + trb->Yoffset,
>   				    z,&flt);
>            zValues[i] = (GLuint) (flt * 0xffffff);
>         }
> @@ -517,7 +518,31 @@ wrap_texture(struct gl_context *ctx, struct gl_renderbuffer_attachment *att)
>      _mesa_reference_renderbuffer(&att->Renderbuffer,&(trb->Base));
>   }
>
> -
> +static GLuint
> +get_texture_dims(GLenum target)
> +{
> +   switch (target) {
> +   case GL_TEXTURE_1D:
> +   case GL_TEXTURE_1D_ARRAY_EXT:
> +      return 1;
> +   case GL_TEXTURE_2D:
> +   case GL_TEXTURE_CUBE_MAP_ARB:
> +   case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
> +   case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
> +   case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
> +   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
> +   case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
> +   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
> +   case GL_TEXTURE_RECTANGLE_NV:
> +   case GL_TEXTURE_2D_ARRAY_EXT:
> +      return 2;
> +   case GL_TEXTURE_3D:
> +      return 3;
> +   default:
> +      assert(0&&  "invalid texture target in get_texture_dims()");
> +      return 1;
> +   }
> +}

Instead of duplicating this function from teximage.c, let's make the 
function non-static and put a declaration in the teximage.h file.


>
>   /**
>    * Update the renderbuffer wrapper for rendering to a texture.
> @@ -542,6 +567,8 @@ update_wrapper(struct gl_context *ctx, const struct gl_renderbuffer_attachment *
>         trb->Store = store_nop;
>      }
>
> +   trb->Fetchf = trb->TexImage->FetchTexelf;
> +
>      if (att->Texture->Target == GL_TEXTURE_1D_ARRAY_EXT) {
>         trb->Yoffset = att->Zoffset;
>         trb->Zoffset = 0;
> @@ -582,6 +609,17 @@ update_wrapper(struct gl_context *ctx, const struct gl_renderbuffer_attachment *
>         trb->Base.DataType = GL_UNSIGNED_INT;
>         trb->Base._BaseFormat = GL_DEPTH_COMPONENT;
>         break;
> +   /* SRGB formats pre EXT_framebuffer_sRGB don't do sRGB translations on FBO readback */
> +   case MESA_FORMAT_SRGB8:
> +      trb->Fetchf = _mesa_get_texel_fetch_func(MESA_FORMAT_RGB888, get_texture_dims(att->Texture->Target));
> +      trb->Base.DataType = CHAN_TYPE;
> +      trb->Base._BaseFormat = GL_RGBA;
> +      break;
> +   case MESA_FORMAT_SRGBA8:
> +      trb->Fetchf = _mesa_get_texel_fetch_func(MESA_FORMAT_RGBA8888, get_texture_dims(att->Texture->Target));
> +      trb->Base.DataType = CHAN_TYPE;
> +      trb->Base._BaseFormat = GL_RGBA;
> +      break;
>      default:
>         trb->Base.DataType = CHAN_TYPE;
>         trb->Base._BaseFormat = GL_RGBA;



More information about the mesa-dev mailing list