[Mesa-dev] [PATCH] st/mesa: make winsys fbo sRGB-capable when supported

Chia-I Wu olvaffe at gmail.com
Mon Mar 3 00:22:36 PST 2014


The texture formats of winsys fbo are always linear becase the st manager
(st/dri for example) could not know the colorspace used.  But it does not mean
that we cannot make the fbo sRGB-capable.  By

 - setting rb->Visual.sRGBCapable to GL_TRUE when the pipe driver supports the
   format in sRGB colorspace,
 - giving rb an sRGB internal format, and
 - updating code to check rb->Format instead of strb->texture->format,

we should be good.

Fixed bug 75226 for at least llvmpipe and ilo, with no piglit regression.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=75226
Signed-off-by: Chia-I Wu <olvaffe at gmail.com>
---
 src/mesa/state_tracker/st_atom_framebuffer.c |  4 ++--
 src/mesa/state_tracker/st_cb_fbo.c           | 25 ++++++++++++++++---
 src/mesa/state_tracker/st_manager.c          | 36 ++++++++++++++++++++--------
 3 files changed, 50 insertions(+), 15 deletions(-)

diff --git a/src/mesa/state_tracker/st_atom_framebuffer.c b/src/mesa/state_tracker/st_atom_framebuffer.c
index c08d912..4c4f839 100644
--- a/src/mesa/state_tracker/st_atom_framebuffer.c
+++ b/src/mesa/state_tracker/st_atom_framebuffer.c
@@ -73,8 +73,8 @@ update_framebuffer_state( struct st_context *st )
       strb = st_renderbuffer(fb->_ColorDrawBuffers[i]);
 
       if (strb) {
-         if (strb->is_rtt ||
-             (strb->texture && util_format_is_srgb(strb->texture->format))) {
+         if (strb->is_rtt || (strb->texture &&
+             _mesa_get_format_color_encoding(strb->Base.Format) == GL_SRGB)) {
             /* rendering to a GL texture, may have to update surface */
             st_update_renderbuffer_surface(st, strb);
          }
diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c
index 6449c62..ce8d915 100644
--- a/src/mesa/state_tracker/st_cb_fbo.c
+++ b/src/mesa/state_tracker/st_cb_fbo.c
@@ -295,7 +295,7 @@ st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw)
    strb->Base.Format = st_pipe_format_to_mesa_format(format);
    strb->Base._BaseFormat = _mesa_get_format_base_format(strb->Base.Format);
    strb->software = sw;
-   
+
    switch (format) {
    case PIPE_FORMAT_R8G8B8A8_UNORM:
    case PIPE_FORMAT_B8G8R8A8_UNORM:
@@ -307,6 +307,16 @@ st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw)
    case PIPE_FORMAT_X8R8G8B8_UNORM:
       strb->Base.InternalFormat = GL_RGB8;
       break;
+   case PIPE_FORMAT_R8G8B8A8_SRGB:
+   case PIPE_FORMAT_B8G8R8A8_SRGB:
+   case PIPE_FORMAT_A8R8G8B8_SRGB:
+      strb->Base.InternalFormat = GL_SRGB8_ALPHA8;
+      break;
+   case PIPE_FORMAT_R8G8B8X8_SRGB:
+   case PIPE_FORMAT_B8G8R8X8_SRGB:
+   case PIPE_FORMAT_X8R8G8B8_SRGB:
+      strb->Base.InternalFormat = GL_SRGB8;
+      break;
    case PIPE_FORMAT_B5G5R5A1_UNORM:
       strb->Base.InternalFormat = GL_RGB5_A1;
       break;
@@ -401,8 +411,17 @@ st_update_renderbuffer_surface(struct st_context *st,
    int rtt_width = strb->Base.Width;
    int rtt_height = strb->Base.Height;
    int rtt_depth = strb->Base.Depth;
-   enum pipe_format format = st->ctx->Color.sRGBEnabled ? resource->format :
-         util_format_linear(resource->format);
+   /*
+    * For winsys fbo, it is possible that the renderbuffer is sRGB-capable but
+    * the format of strb->texture is linear (because we have no control over
+    * the format).  Check strb->Base.Format instead of strb->texture->format
+    * to determine if the rb is sRGB-capable.
+    */
+   boolean enable_srgb = (st->ctx->Color.sRGBEnabled &&
+         _mesa_get_format_color_encoding(strb->Base.Format) == GL_SRGB);
+   enum pipe_format format = (enable_srgb) ?
+      util_format_srgb(resource->format) :
+      util_format_linear(resource->format);
    unsigned first_layer, last_layer, level;
 
    if (resource->target == PIPE_TEXTURE_1D_ARRAY) {
diff --git a/src/mesa/state_tracker/st_manager.c b/src/mesa/state_tracker/st_manager.c
index 6a776a8..2c445fd 100644
--- a/src/mesa/state_tracker/st_manager.c
+++ b/src/mesa/state_tracker/st_manager.c
@@ -302,6 +302,8 @@ st_framebuffer_add_renderbuffer(struct st_framebuffer *stfb,
       break;
    default:
       format = stfb->iface->visual->color_format;
+      if (stfb->Base.Visual.sRGBCapable)
+         format = util_format_srgb(format);
       sw = FALSE;
       break;
    }
@@ -330,7 +332,8 @@ st_framebuffer_add_renderbuffer(struct st_framebuffer *stfb,
  * Intialize a struct gl_config from a visual.
  */
 static void
-st_visual_to_context_mode(const struct st_visual *visual,
+st_visual_to_context_mode(struct pipe_screen *screen,
+                          const struct st_visual *visual,
                           struct gl_config *mode)
 {
    memset(mode, 0, sizeof(*mode));
@@ -342,6 +345,9 @@ st_visual_to_context_mode(const struct st_visual *visual,
       mode->stereoMode = GL_TRUE;
 
    if (visual->color_format != PIPE_FORMAT_NONE) {
+      const enum pipe_format srgb_format =
+         util_format_srgb(visual->color_format);
+
       mode->rgbMode = GL_TRUE;
 
       mode->redBits =
@@ -359,6 +365,12 @@ st_visual_to_context_mode(const struct st_visual *visual,
 
       mode->rgbBits = mode->redBits +
          mode->greenBits + mode->blueBits + mode->alphaBits;
+
+      if (srgb_format != PIPE_FORMAT_NONE &&
+          screen->is_format_supported(screen, srgb_format,
+                                      PIPE_TEXTURE_2D, visual->samples,
+                                      PIPE_BIND_RENDER_TARGET))
+         mode->sRGBCapable = GL_TRUE;
    }
 
    if (visual->depth_stencil_format != PIPE_FORMAT_NONE) {
@@ -400,7 +412,8 @@ st_visual_to_context_mode(const struct st_visual *visual,
  * Create a framebuffer from a manager interface.
  */
 static struct st_framebuffer *
-st_framebuffer_create(struct st_framebuffer_iface *stfbi)
+st_framebuffer_create(struct pipe_screen *screen,
+                      struct st_framebuffer_iface *stfbi)
 {
    struct st_framebuffer *stfb;
    struct gl_config mode;
@@ -413,7 +426,7 @@ st_framebuffer_create(struct st_framebuffer_iface *stfbi)
    if (!stfb)
       return NULL;
 
-   st_visual_to_context_mode(stfbi->visual, &mode);
+   st_visual_to_context_mode(screen, stfbi->visual, &mode);
    _mesa_initialize_window_framebuffer(&stfb->Base, &mode);
 
    stfb->iface = stfbi;
@@ -619,7 +632,7 @@ st_api_create_context(struct st_api *stapi, struct st_manager *smapi,
       return NULL;
    }
 
-   st_visual_to_context_mode(&attribs->visual, &mode);
+   st_visual_to_context_mode(smapi->screen, &attribs->visual, &mode);
    st = st_create_context(api, pipe, &mode, shared_ctx, &attribs->options);
    if (!st) {
       *error = ST_CONTEXT_ERROR_NO_MEMORY;
@@ -677,7 +690,8 @@ st_api_get_current(struct st_api *stapi)
 }
 
 static struct st_framebuffer *
-st_framebuffer_reuse_or_create(struct gl_framebuffer *fb,
+st_framebuffer_reuse_or_create(struct pipe_screen *screen,
+                               struct gl_framebuffer *fb,
                                struct st_framebuffer_iface *stfbi)
 {
    struct st_framebuffer *cur = st_ws_framebuffer(fb), *stfb = NULL;
@@ -690,7 +704,7 @@ st_framebuffer_reuse_or_create(struct gl_framebuffer *fb,
    }
    else {
       /* create a new one */
-      stfb = st_framebuffer_create(stfbi);
+      stfb = st_framebuffer_create(screen, stfbi);
    }
 
    return stfb;
@@ -708,13 +722,15 @@ st_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi,
    _glapi_check_multithread();
 
    if (st) {
+      struct pipe_screen *screen = st->pipe->screen;
+
       /* reuse or create the draw fb */
-      stdraw = st_framebuffer_reuse_or_create(st->ctx->WinSysDrawBuffer,
-                                              stdrawi);
+      stdraw = st_framebuffer_reuse_or_create(screen,
+            st->ctx->WinSysDrawBuffer, stdrawi);
       if (streadi != stdrawi) {
          /* do the same for the read fb */
-         stread = st_framebuffer_reuse_or_create(st->ctx->WinSysReadBuffer,
-                                                 streadi);
+         stread = st_framebuffer_reuse_or_create(screen,
+               st->ctx->WinSysReadBuffer, streadi);
       }
       else {
          stread = NULL;
-- 
1.8.5.3



More information about the mesa-dev mailing list