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

Mike Kaplinskiy mike.kaplinskiy at gmail.com
Mon May 23 21:33:03 PDT 2011


I see; that sounds fine. I was a bit wary of changing the code since I
don't know what else calls it. Would something like the attached work?

I also included an attempt at changing the tex-srgb piglit test to
check for glGetTexImage.

On Mon, May 23, 2011 at 11:57 AM, Roland Scheidegger <sroland at vmware.com> wrote:
> I'd support that as well, sounds more sane than doing
> nonlinear-to-linear plus linear-to-linear - when I did the fast-path
> srgb texgetimage patch I didn't notice there is already other code which
> is switching the fetch functions for GL_SKIP_DECODE_EXT.
> Sounds to me though wine is doing something inefficient in the first
> place, since I don't think d3d apps would generally do something which
> would really require reading back the texture image.
>
> Roland
>
>
> Am 23.05.2011 16:45, schrieb Brian Paul:
>> I think another approach would be to temporarily set the
>> Sampler.sRGBDecode field to GL_SKIP_DECODE_EXT, use the non-sRGB path
>> to get the texels, then restore Sampler.sRGBDecode to its original
>> value.  Call _mesa_set_fetch_functions() as needed to choose the
>> non-decoding texel fetch functions.  Then we could avoid the
>> linear_to_nonlinear() function altogether.
>>
>> We should probably have a piglit test to exercise glGetTexImage with
>> sRGB textures...
>>
>> -Brian
>>
>>
>> On Sat, May 21, 2011 at 5:37 PM, Mike Kaplinskiy
>> <mike.kaplinskiy at gmail.com> wrote:
>>> Sorry looks like I edited that comment a few too many times. Here's an
>>> updated patch with the comment fixed.
>>>
>>> On Sat, May 21, 2011 at 7:15 PM, Mike Kaplinskiy
>>> <mike.kaplinskiy at gmail.com> wrote:
>>>> 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.
>>>>
>>>
>>> _______________________________________________
>>> mesa-dev mailing list
>>> mesa-dev at lists.freedesktop.org
>>> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
>>>
>>>
>> _______________________________________________
>> mesa-dev mailing list
>> mesa-dev at lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
>
>
-------------- next part --------------
From 793c985d421a78fe2f08af70eff66b411e148957 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: [PATCH] mesa: fix glGetTexImage for cases when srgb decode is
 skipped

---
 src/mesa/main/texgetimage.c |  119 +++++++------------------------------------
 1 files changed, 18 insertions(+), 101 deletions(-)

diff --git a/src/mesa/main/texgetimage.c b/src/mesa/main/texgetimage.c
index b23317c..4234b40 100644
--- a/src/mesa/main/texgetimage.c
+++ b/src/mesa/main/texgetimage.c
@@ -40,6 +40,7 @@
 #include "pack.h"
 #include "pbo.h"
 #include "texgetimage.h"
+#include "texfetch.h"
 #include "teximage.h"
 
 
@@ -220,110 +221,14 @@ get_tex_ycbcr(struct gl_context *ctx, GLuint dimensions,
 }
 
 
-#if FEATURE_EXT_texture_sRGB
-
-
 /**
- * Convert a float value from linear space to a
- * non-linear sRGB value in [0, 255].
- * Not terribly efficient.
- */
-static INLINE GLfloat
-linear_to_nonlinear(GLfloat cl)
-{
-   /* can't have values outside [0, 1] */
-   GLfloat cs;
-   if (cl < 0.0031308f) {
-      cs = 12.92f * cl;
-   }
-   else {
-      cs = (GLfloat)(1.055 * pow(cl, 0.41666) - 0.055);
-   }
-   return cs;
-}
-
-
-/**
- * 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)
-{
-   ASSERT_NO_FEATURE();
-}
-
-
-#endif /* FEATURE_EXT_texture_sRGB */
-
-
-/**
- * glGetTexImagefor RGBA, Luminance, etc. pixels.
+ * glGetTexImage for (s)RGBA, Luminance, etc. pixels.
  * This is the slow way since we use texture sampling.
  */
 static void
 get_tex_rgba(struct gl_context *ctx, GLuint dimensions,
              GLenum format, GLenum type, GLvoid *pixels,
-             const struct gl_texture_image *texImage)
+             struct gl_texture_image *texImage)
 {
    const GLint width = texImage->Width;
    const GLint height = texImage->Height;
@@ -334,12 +239,22 @@ get_tex_rgba(struct gl_context *ctx, GLuint dimensions,
    GLbitfield transferOps = 0x0;
    GLint img, row;
    GLfloat (*rgba)[4] = (GLfloat (*)[4]) malloc(4 * width * sizeof(GLfloat));
+   const GLboolean is_sampler_srgb_decode =
+       _mesa_get_format_color_encoding(texImage->TexFormat) == GL_SRGB &&
+       texImage->TexObject->Sampler.sRGBDecode == GL_DECODE_EXT;
 
    if (!rgba) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
       return;
    }
 
+   /* glGetTexImage always returns sRGB data for sRGB textures. Make sure the
+    * fetch functions return sRGB data without linearizing it. */
+   if (is_sampler_srgb_decode) {
+      texImage->TexObject->Sampler.sRGBDecode = GL_SKIP_DECODE_EXT;
+      _mesa_set_fetch_functions(texImage, dimensions);
+   }
+
    for (img = 0; img < depth; img++) {
       for (row = 0; row < height; row++) {
          void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
@@ -389,6 +304,11 @@ get_tex_rgba(struct gl_context *ctx, GLuint dimensions,
       }
    }
 
+   if (is_sampler_srgb_decode) {
+      texImage->TexObject->Sampler.sRGBDecode = GL_DECODE_EXT;
+      _mesa_set_fetch_functions(texImage, dimensions);
+   }
+
    free(rgba);
 }
 
@@ -548,9 +468,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
-------------- next part --------------
From 4127816431e1b13c7f65ac59080485521191b84c Mon Sep 17 00:00:00 2001
From: Mike Kaplinskiy <mike.kaplinskiy at gmail.com>
Date: Tue, 24 May 2011 00:29:35 -0400
Subject: [PATCH] tex-srgb: check glGetTexImage as well

---
 tests/texturing/tex-srgb.c |   19 ++++++++++++++-----
 1 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/tests/texturing/tex-srgb.c b/tests/texturing/tex-srgb.c
index 1f53508..5b73d54 100644
--- a/tests/texturing/tex-srgb.c
+++ b/tests/texturing/tex-srgb.c
@@ -68,7 +68,6 @@ static void fill_level(int level, const GLfloat *color)
         int size = SIZE / (1 << level);
         int i;
 
-        /* Update a square inside the texture to red */
         data = malloc(size * size * 4 * sizeof(GLfloat));
         for (i = 0; i < 4 * size * size; i += 4) {
                 data[i + 0] = color[0];
@@ -93,6 +92,10 @@ srgb_tex_test(int srgb_format)
 
 	have_decode = glutExtensionSupported("GL_EXT_texture_sRGB_decode");
 
+	memcpy(expected_green, green, sizeof(float) * 4);
+	memcpy(expected_srgb_green, green, sizeof(float) * 4);
+	expected_srgb_green[1] = nonlinear_to_linear(255.0*green[1]);
+
 	glGenTextures(1, &tex);
 
 	glBindTexture(GL_TEXTURE_2D, tex);
@@ -108,10 +111,20 @@ srgb_tex_test(int srgb_format)
 	glEnable(GL_TEXTURE_2D);
 	piglit_draw_rect_tex(0, 0, 20, 20, 0, 0, 1, 1);
 
+	if (!piglit_probe_texel_rect_rgba(GL_TEXTURE_2D, 0, 0, 0, SIZE, SIZE,
+					  expected_green)) {
+		pass = GL_FALSE;
+	}
+
 	if (have_decode) {
 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SRGB_DECODE_EXT,
 				GL_SKIP_DECODE_EXT);
 
+		if (!piglit_probe_texel_rect_rgba(GL_TEXTURE_2D, 0, 0, 0, SIZE,
+						  SIZE, expected_green)) {
+			pass = GL_FALSE;
+		}
+
 		piglit_draw_rect_tex(20, 0, 20, 20, 0, 0, 1, 1);
 
 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SRGB_DECODE_EXT,
@@ -120,10 +133,6 @@ srgb_tex_test(int srgb_format)
 		piglit_draw_rect_tex(40, 0, 20, 20, 0, 0, 1, 1);
 	}
 
-	memcpy(expected_green, green, sizeof(float) * 4);
-	memcpy(expected_srgb_green, green, sizeof(float) * 4);
-	expected_srgb_green[1] = nonlinear_to_linear(255.0*green[1]);
-
 	if (!piglit_probe_rect_rgb(0, 0, 20, 20, expected_srgb_green))
 		pass = GL_FALSE;
 
-- 
1.7.4.4


More information about the mesa-dev mailing list