[Mesa-dev] [PATCH v6 5/8] mesa/st: rework support for sRGB framebuffer attachements

Gert Wollny gw.fossdev at gmail.com
Thu Nov 15 12:45:56 UTC 2018


From: Gert Wollny <gert.wollny at collabora.com>

For GLES sRGB framebuffer attachemnt support is provided in two steps:
(1) sRGB attachments like described in EXT_sRGB (and GLES 3.0) that enable
linear to sRGB color space transformation automatically, and (2) the ability
to switch formats of the render target surface between sRGB and linear
that introduces full support for EXT_framebuffer_sRGB.

Set and use the according flags to reflect these two levels of sRGB support.

Also handle the difference between desktop GL and GLES regarding how the 
linear-sRGB conversion is enabled: on desktop GL for a sRGB framebuffer 
attachment the linear-sRGB conversion is turned off by default, and for GLES 
it is turned on. This needs to be taken into account when initially creating 
a surface, i.e. on desktop GL creation of a sRGB surface is preferred, but on
GLES sRGB surfaces are only created when explicitly requested.

v2: - always enable the extension when sRGB is supported (Ilia Mirkin).
    - Correct handling by moving extension initialization to the
      place where gallium/st actually takes care of this. This also
      fixes properly disabling the extension via MESA_EXTENSION_OVERRIDE
    - reinstate check for desktop GL and add check for the extension
      when creating the framebuffer

v3: - Only create sRGB renderbuffers based on Visual.srgbCapable when
      on desktop GL.

v4: - Use PIPE_FORMAT_B8G8R8A8_SRGB to check for the capability, since this
      is also the format that is used top check for EGL_KHR_gl_colorspace
      support.  virgl on a GLES host usually doesn't provide this format but
      one can make it available to signal that the host supports this
      extension.

v5: - drop check for PIPE_FORMAT_B8G8R8A8_SRGB in favour of using the new 
      PIPE_CAP_SRGB_WRITE_CONTROL cap flag.
    - enable EXT_sRGB based on the sRGB formats supported and 
      EXT_framebuffer_sRGB by checking for the caps .

v6: - Use the CAPS name PIPE_CAP_DEST_SURFACE_SRGB_CONTROL

Signed-off-by: Gert Wollny <gert.wollny at collabora.com>
---
 src/mesa/state_tracker/st_cb_fbo.c     |  4 +--
 src/mesa/state_tracker/st_extensions.c |  6 ++++-
 src/mesa/state_tracker/st_format.c     |  2 +-
 src/mesa/state_tracker/st_manager.c    | 37 ++++++++++++++++----------
 4 files changed, 31 insertions(+), 18 deletions(-)

diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c
index 0e535257cb..49a989f126 100644
--- a/src/mesa/state_tracker/st_cb_fbo.c
+++ b/src/mesa/state_tracker/st_cb_fbo.c
@@ -139,7 +139,7 @@ st_renderbuffer_alloc_storage(struct gl_context * ctx,
    /* If an sRGB framebuffer is unsupported, sRGB formats behave like linear
     * formats.
     */
-   if (!ctx->Extensions.EXT_framebuffer_sRGB) {
+   if (!ctx->Extensions.EXT_sRGB) {
       internalFormat = _mesa_get_linear_internalformat(internalFormat);
    }
 
@@ -656,7 +656,7 @@ st_validate_attachment(struct gl_context *ctx,
    /* If the encoding is sRGB and sRGB rendering cannot be enabled,
     * check for linear format support instead.
     * Later when we create a surface, we change the format to a linear one. */
-   if (!ctx->Extensions.EXT_framebuffer_sRGB &&
+   if (!ctx->Extensions.EXT_sRGB &&
        _mesa_get_format_color_encoding(texFormat) == GL_SRGB) {
       const mesa_format linearFormat = _mesa_get_srgb_format_linear(texFormat);
       format = st_mesa_format_to_pipe_format(st_context(ctx), linearFormat);
diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c
index 16889074f6..15f22ecf15 100644
--- a/src/mesa/state_tracker/st_extensions.c
+++ b/src/mesa/state_tracker/st_extensions.c
@@ -786,7 +786,7 @@ void st_init_extensions(struct pipe_screen *screen,
           PIPE_FORMAT_B10G10R10A2_UINT },
          GL_TRUE }, /* at least one format must be supported */
 
-      { { o(EXT_framebuffer_sRGB) },
+      { { o(EXT_sRGB) },
         { PIPE_FORMAT_A8B8G8R8_SRGB,
           PIPE_FORMAT_B8G8R8A8_SRGB,
           PIPE_FORMAT_R8G8B8A8_SRGB },
@@ -1316,6 +1316,10 @@ void st_init_extensions(struct pipe_screen *screen,
       extensions->ARB_texture_buffer_object_rgb32 &&
       extensions->ARB_shader_image_load_store;
 
+   extensions->EXT_framebuffer_sRGB =
+         screen->get_param(screen, PIPE_CAP_DEST_SURFACE_SRGB_CONTROL) &&
+         extensions->EXT_sRGB;
+
    /* Unpacking a varying in the fragment shader costs 1 texture indirection.
     * If the number of available texture indirections is very limited, then we
     * prefer to disable varying packing rather than run the risk of varying
diff --git a/src/mesa/state_tracker/st_format.c b/src/mesa/state_tracker/st_format.c
index caddd76c5d..aacb878828 100644
--- a/src/mesa/state_tracker/st_format.c
+++ b/src/mesa/state_tracker/st_format.c
@@ -2457,7 +2457,7 @@ st_QuerySamplesForFormat(struct gl_context *ctx, GLenum target,
    /* If an sRGB framebuffer is unsupported, sRGB formats behave like linear
     * formats.
     */
-   if (!ctx->Extensions.EXT_framebuffer_sRGB) {
+   if (!ctx->Extensions.EXT_sRGB) {
       internalFormat = _mesa_get_linear_internalformat(internalFormat);
    }
 
diff --git a/src/mesa/state_tracker/st_manager.c b/src/mesa/state_tracker/st_manager.c
index 076ad42646..25e2dcad4c 100644
--- a/src/mesa/state_tracker/st_manager.c
+++ b/src/mesa/state_tracker/st_manager.c
@@ -295,7 +295,7 @@ st_framebuffer_update_attachments(struct st_framebuffer *stfb)
  */
 static boolean
 st_framebuffer_add_renderbuffer(struct st_framebuffer *stfb,
-                                gl_buffer_index idx)
+                                gl_buffer_index idx, bool prefer_srgb)
 {
    struct gl_renderbuffer *rb;
    enum pipe_format format;
@@ -318,7 +318,7 @@ st_framebuffer_add_renderbuffer(struct st_framebuffer *stfb,
       break;
    default:
       format = stfb->iface->visual->color_format;
-      if (stfb->Base.Visual.sRGBCapable)
+      if (prefer_srgb)
          format = util_format_srgb(format);
       sw = FALSE;
       break;
@@ -436,6 +436,7 @@ st_framebuffer_create(struct st_context *st,
    struct st_framebuffer *stfb;
    struct gl_config mode;
    gl_buffer_index idx;
+   bool prefer_srgb = false;
 
    if (!stfbi)
       return NULL;
@@ -457,14 +458,15 @@ st_framebuffer_create(struct st_context *st,
     * format such that util_format_srgb(visual->color_format) can be supported
     * by the pipe driver.  We still need to advertise the capability here.
     *
-    * For GLES, however, sRGB framebuffer write is controlled only by the
-    * capability of the framebuffer.  There is GL_EXT_sRGB_write_control to
-    * give applications the control back, but sRGB write is still enabled by
-    * default.  To avoid unexpected results, we should not advertise the
-    * capability.  This could change when we add support for
-    * EGL_KHR_gl_colorspace.
+    * For GLES, however, sRGB framebuffer write is initially only controlled
+    * by the capability of the framebuffer, with GL_EXT_sRGB_write_control
+    * control is given back to the applications, but GL_FRAMEBUFFER_SRGB is
+    * still enabled by default since this is the behaviour when
+    * EXT_sRGB_write_control is not available. Since GL_EXT_sRGB_write_control
+    * brings GLES on par with desktop GLs EXT_framebuffer_sRGB, in mesa this
+    * is also expressed by using the same extension flag
     */
-   if (_mesa_is_desktop_gl(st->ctx)) {
+   if (st->ctx->Extensions.EXT_framebuffer_sRGB) {
       struct pipe_screen *screen = st->pipe->screen;
       const enum pipe_format srgb_format =
          util_format_srgb(stfbi->visual->color_format);
@@ -475,8 +477,14 @@ st_framebuffer_create(struct st_context *st,
                                       PIPE_TEXTURE_2D, stfbi->visual->samples,
                                       stfbi->visual->samples,
                                       (PIPE_BIND_DISPLAY_TARGET |
-                                       PIPE_BIND_RENDER_TARGET)))
+                                       PIPE_BIND_RENDER_TARGET))) {
          mode.sRGBCapable = GL_TRUE;
+         /* Since GL_FRAMEBUFFER_SRGB is enabled by default on GLES we must not
+          * create renderbuffers with an sRGB format derived from the
+          * visual->color_format, but we still want sRGB for desktop GL.
+          */
+         prefer_srgb = _mesa_is_desktop_gl(st->ctx);
+      }
    }
 
    _mesa_initialize_window_framebuffer(&stfb->Base, &mode);
@@ -487,13 +495,13 @@ st_framebuffer_create(struct st_context *st,
 
    /* add the color buffer */
    idx = stfb->Base._ColorDrawBufferIndexes[0];
-   if (!st_framebuffer_add_renderbuffer(stfb, idx)) {
+   if (!st_framebuffer_add_renderbuffer(stfb, idx, prefer_srgb)) {
       free(stfb);
       return NULL;
    }
 
-   st_framebuffer_add_renderbuffer(stfb, BUFFER_DEPTH);
-   st_framebuffer_add_renderbuffer(stfb, BUFFER_ACCUM);
+   st_framebuffer_add_renderbuffer(stfb, BUFFER_DEPTH, false);
+   st_framebuffer_add_renderbuffer(stfb, BUFFER_ACCUM, false);
 
    stfb->stamp = 0;
    st_framebuffer_update_attachments(stfb);
@@ -1183,7 +1191,8 @@ st_manager_add_color_renderbuffer(struct st_context *st,
       return FALSE;
    }
 
-   if (!st_framebuffer_add_renderbuffer(stfb, idx))
+   if (!st_framebuffer_add_renderbuffer(stfb, idx,
+                                        stfb->Base.Visual.sRGBCapable))
       return FALSE;
 
    st_framebuffer_update_attachments(stfb);
-- 
2.18.1



More information about the mesa-dev mailing list