From 3d676675eb8c7b1e26e22b49fcc0377a32863bc3 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Mon, 3 Mar 2014 12:44:43 +0800 Subject: [PATCH] st/mesa: make winsys fbo sRGB-capable when supported 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 --- 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