mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-24 08:50:13 +01:00
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. v2: do not set rb->Visual.sRGBCapable for GLES contexts to avoid surprises Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=75226 Reviewed-by: Brian Paul <brianp@vmware.com> Tested-by: Michel Dänzer <michel.daenzer@amd.com>
This commit is contained in:
parent
6d23ca1621
commit
4c68c6dcff
3 changed files with 66 additions and 12 deletions
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -400,7 +402,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 st_context *st,
|
||||
struct st_framebuffer_iface *stfbi)
|
||||
{
|
||||
struct st_framebuffer *stfb;
|
||||
struct gl_config mode;
|
||||
|
|
@ -414,6 +417,37 @@ st_framebuffer_create(struct st_framebuffer_iface *stfbi)
|
|||
return NULL;
|
||||
|
||||
st_visual_to_context_mode(stfbi->visual, &mode);
|
||||
|
||||
/*
|
||||
* For desktop GL, sRGB framebuffer write is controlled by both the
|
||||
* capability of the framebuffer and GL_FRAMEBUFFER_SRGB. We should
|
||||
* advertise the capability when the pipe driver supports it so that
|
||||
* applications can enable sRGB write when they want to.
|
||||
*
|
||||
* This is not to be confused with GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB. When
|
||||
* the attribute is GLX_TRUE, it tells the st manager to pick a color
|
||||
* 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.
|
||||
*/
|
||||
if (_mesa_is_desktop_gl(st->ctx)) {
|
||||
struct pipe_screen *screen = st->pipe->screen;
|
||||
const enum pipe_format srgb_format =
|
||||
util_format_srgb(stfbi->visual->color_format);
|
||||
|
||||
if (srgb_format != PIPE_FORMAT_NONE &&
|
||||
screen->is_format_supported(screen, srgb_format,
|
||||
PIPE_TEXTURE_2D, stfbi->visual->samples,
|
||||
PIPE_BIND_RENDER_TARGET))
|
||||
mode.sRGBCapable = GL_TRUE;
|
||||
}
|
||||
|
||||
_mesa_initialize_window_framebuffer(&stfb->Base, &mode);
|
||||
|
||||
stfb->iface = stfbi;
|
||||
|
|
@ -677,7 +711,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 st_context *st,
|
||||
struct gl_framebuffer *fb,
|
||||
struct st_framebuffer_iface *stfbi)
|
||||
{
|
||||
struct st_framebuffer *cur = st_ws_framebuffer(fb), *stfb = NULL;
|
||||
|
|
@ -690,7 +725,7 @@ st_framebuffer_reuse_or_create(struct gl_framebuffer *fb,
|
|||
}
|
||||
else {
|
||||
/* create a new one */
|
||||
stfb = st_framebuffer_create(stfbi);
|
||||
stfb = st_framebuffer_create(st, stfbi);
|
||||
}
|
||||
|
||||
return stfb;
|
||||
|
|
@ -709,12 +744,12 @@ st_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi,
|
|||
|
||||
if (st) {
|
||||
/* reuse or create the draw fb */
|
||||
stdraw = st_framebuffer_reuse_or_create(st->ctx->WinSysDrawBuffer,
|
||||
stdrawi);
|
||||
stdraw = st_framebuffer_reuse_or_create(st,
|
||||
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(st,
|
||||
st->ctx->WinSysReadBuffer, streadi);
|
||||
}
|
||||
else {
|
||||
stread = NULL;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue