[Mesa-dev] [PATCH] mesa: fix glGetTexImage for srgb textures when srgb decode is skipped

Mike Kaplinskiy mike.kaplinskiy at gmail.com
Sat May 21 16:15:15 PDT 2011


This fixes the loading screen for Assassins Creed Brotherhood running
under wine for me [exposed by a fast-path that actually fixed it at
be0a2f62f3a5bc6f05c3c7c6b674f2688aee031d]. May also fix bug 37150.
-------------- next part --------------
From e27f7265ab4add4ce53a6f493fca22b8a704c02b Mon Sep 17 00:00:00 2001
From: Mike Kaplinskiy <mike.kaplinskiy at gmail.com>
Date: Sat, 21 May 2011 19:05:29 -0400
Subject: mesa: fix glGetTexImage for cases when srgb decode is skipped

---
 src/mesa/main/texgetimage.c |   89 +++++++++++--------------------------------
 1 files changed, 23 insertions(+), 66 deletions(-)

diff --git a/src/mesa/main/texgetimage.c b/src/mesa/main/texgetimage.c
index b23317c..ffb344b 100644
--- a/src/mesa/main/texgetimage.c
+++ b/src/mesa/main/texgetimage.c
@@ -243,73 +243,14 @@ linear_to_nonlinear(GLfloat cl)
 }
 
 
-/**
- * glGetTexImagefor sRGB pixels;
- */
-static void
-get_tex_srgb(struct gl_context *ctx, GLuint dimensions,
-             GLenum format, GLenum type, GLvoid *pixels,
-             const struct gl_texture_image *texImage)
-{
-   const GLint width = texImage->Width;
-   const GLint height = texImage->Height;
-   const GLint depth = texImage->Depth;
-   const GLbitfield transferOps = 0x0;
-   GLint img, row;
-   GLfloat (*rgba)[4] = (GLfloat (*)[4]) malloc(4 * width * sizeof(GLfloat));
-
-   if (!rgba) {
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
-      return;
-   }
-
-   for (img = 0; img < depth; img++) {
-      for (row = 0; row < height; row++) {
-         void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
-                                          width, height, format, type,
-                                          img, row, 0);
-
-         GLint col;
-
-         /* convert row to RGBA format */
-         for (col = 0; col < width; col++) {
-            texImage->FetchTexelf(texImage, col, row, img, rgba[col]);
-            if (texImage->_BaseFormat == GL_LUMINANCE) {
-               rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
-               rgba[col][GCOMP] = 0.0;
-               rgba[col][BCOMP] = 0.0;
-            }
-            else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) {
-               rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
-               rgba[col][GCOMP] = 0.0;
-               rgba[col][BCOMP] = 0.0;
-            }
-            else if (texImage->_BaseFormat == GL_RGB ||
-                     texImage->_BaseFormat == GL_RGBA) {
-               rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
-               rgba[col][GCOMP] = linear_to_nonlinear(rgba[col][GCOMP]);
-               rgba[col][BCOMP] = linear_to_nonlinear(rgba[col][BCOMP]);
-            }
-         }
-         _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
-                                    format, type, dest,
-                                    &ctx->Pack, transferOps);
-      }
-   }
-
-   free(rgba);
-}
-
-
 #else /* FEATURE_EXT_texture_sRGB */
 
 
-static INLINE void
-get_tex_srgb(struct gl_context *ctx, GLuint dimensions,
-             GLenum format, GLenum type, GLvoid *pixels,
-             const struct gl_texture_image *texImage)
+static INLINE GLfloat
+linear_to_nonlinear(GLfloat cl)
 {
    ASSERT_NO_FEATURE();
+   return cl;
 }
 
 
@@ -317,7 +258,7 @@ get_tex_srgb(struct gl_context *ctx, GLuint dimensions,
 
 
 /**
- * glGetTexImagefor RGBA, Luminance, etc. pixels.
+ * glGetTexImage for (s)RGBA, Luminance, etc. pixels.
  * This is the slow way since we use texture sampling.
  */
 static void
@@ -335,6 +276,18 @@ get_tex_rgba(struct gl_context *ctx, GLuint dimensions,
    GLint img, row;
    GLfloat (*rgba)[4] = (GLfloat (*)[4]) malloc(4 * width * sizeof(GLfloat));
 
+   /* glGetTexImage for sRGB textures always returns sRGB data. We need to
+    * do nonlinear-to-linear conversion if TexFetchf converts to linear. */
+   const GLboolean srgb_unlinearize =
+       _mesa_get_format_color_encoding(texImage->TexFormat) == GL_SRGB &&
+       texImage->TexObject->Sampler.sRGBDecode == GL_DECODE_EXT &&
+          (texImage->_BaseFormat == GL_ALPHA ||
+           texImage->_BaseFormat == GL_LUMINANCE ||
+           texImage->_BaseFormat == GL_LUMINANCE_ALPHA ||
+           texImage->_BaseFormat == GL_INTENSITY ||
+           texImage->_BaseFormat == GL_RGB ||
+           texImage->_BaseFormat == GL_RGBA);
+
    if (!rgba) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
       return;
@@ -363,6 +316,13 @@ get_tex_rgba(struct gl_context *ctx, GLuint dimensions,
 
          for (col = 0; col < width; col++) {
             texImage->FetchTexelf(texImage, col, row, img, rgba[col]);
+            if (srgb_unlinearize) {
+               rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
+               rgba[col][GCOMP] = linear_to_nonlinear(rgba[col][GCOMP]);
+               rgba[col][BCOMP] = linear_to_nonlinear(rgba[col][BCOMP]);
+               /* alpha is linear */
+            }
+
             if (texImage->_BaseFormat == GL_ALPHA) {
                rgba[col][RCOMP] = 0.0F;
                rgba[col][GCOMP] = 0.0F;
@@ -548,9 +508,6 @@ _mesa_get_teximage(struct gl_context *ctx, GLenum target, GLint level,
    else if (format == GL_YCBCR_MESA) {
       get_tex_ycbcr(ctx, dimensions, format, type, pixels, texImage);
    }
-   else if (_mesa_get_format_color_encoding(texImage->TexFormat) == GL_SRGB) {
-      get_tex_srgb(ctx, dimensions, format, type, pixels, texImage);
-   }
    else {
       get_tex_rgba(ctx, dimensions, format, type, pixels, texImage);
    }
-- 
1.7.4.4


More information about the mesa-dev mailing list