Nvidia and Intel support that and Warhammer Online relies on that if detects GPU as Nvidia.
The patch introduces a forced fallback to code path without EXT_TEXTURE_SRGB_DECODE for specified formats. Otherwise 16 bit d3d formats with SRGB reads supported would always use 24 or 32 bit internal GL format.
Spotted in https://bugs.winehq.org/show_bug.cgi?id=48302.
Signed-off-by: Paul Gofman gofmanp@gmail.com --- v2: - introduce WINED3DFMT_FLAG_SEPARATE_SRGB to avoid always using 24 bit internal format for WINED3DFMT_B5G6R5_UNORM when EXT_TEXTURE_SRGB_DECODE is present.
dlls/wined3d/texture.c | 7 +++++-- dlls/wined3d/utils.c | 24 ++++++++++++++---------- dlls/wined3d/wined3d_private.h | 9 +++++++-- 3 files changed, 26 insertions(+), 14 deletions(-)
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index c191e2423a..e970c13d7a 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -876,7 +876,8 @@ void wined3d_texture_gl_bind(struct wined3d_texture_gl *texture_gl, gl_tex->sampler_desc.max_anisotropy = 1; gl_tex->sampler_desc.compare = FALSE; gl_tex->sampler_desc.comparison_func = WINED3D_CMP_LESSEQUAL; - if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE]) + if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE] + && !(texture_gl->t.resource.format_flags & WINED3DFMT_FLAG_SEPARATE_SRGB)) gl_tex->sampler_desc.srgb_decode = TRUE; else gl_tex->sampler_desc.srgb_decode = srgb; @@ -1045,7 +1046,8 @@ void wined3d_texture_gl_apply_sampler_desc(struct wined3d_texture_gl *texture_gl
if (!sampler_desc->srgb_decode != !gl_tex->sampler_desc.srgb_decode && (context_gl->c.d3d_info->wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL) - && gl_info->supported[EXT_TEXTURE_SRGB_DECODE]) + && gl_info->supported[EXT_TEXTURE_SRGB_DECODE] + && !(texture_gl->t.resource.format_flags & WINED3DFMT_FLAG_SEPARATE_SRGB)) { gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_SRGB_DECODE_EXT, sampler_desc->srgb_decode ? GL_DECODE_EXT : GL_SKIP_DECODE_EXT); @@ -2750,6 +2752,7 @@ static BOOL wined3d_texture_gl_load_texture(struct wined3d_texture_gl *texture_g
if (!depth && sub_resource->locations & (WINED3D_LOCATION_TEXTURE_SRGB | WINED3D_LOCATION_TEXTURE_RGB) && (texture_gl->t.resource.format_flags & WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB) + && !(texture_gl->t.resource.format_flags & WINED3DFMT_FLAG_SEPARATE_SRGB) && fbo_blitter_supported(WINED3D_BLIT_OP_COLOR_BLIT, gl_info, &texture_gl->t.resource, WINED3D_LOCATION_TEXTURE_RGB, &texture_gl->t.resource, WINED3D_LOCATION_TEXTURE_SRGB)) diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index 820a4c7d80..59a571c997 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -1535,15 +1535,15 @@ static const struct wined3d_format_texture_info format_texture_info[] = WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_SRGB_WRITE, WINED3D_GL_EXT_NONE, NULL}, - {WINED3DFMT_B5G6R5_UNORM, GL_RGB5, GL_RGB5, GL_RGB8, + {WINED3DFMT_B5G6R5_UNORM, GL_RGB5, GL_SRGB8_EXT, GL_RGB8, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0, WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING - | WINED3DFMT_FLAG_RENDERTARGET, + | WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_SEPARATE_SRGB, WINED3D_GL_EXT_NONE, NULL}, - {WINED3DFMT_B5G6R5_UNORM, GL_RGB565, GL_RGB565, GL_RGB8, + {WINED3DFMT_B5G6R5_UNORM, GL_RGB565, GL_SRGB8_EXT, GL_RGB8, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0, WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING - | WINED3DFMT_FLAG_RENDERTARGET, + | WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_SEPARATE_SRGB, ARB_ES2_COMPATIBILITY, NULL}, {WINED3DFMT_B5G5R5X1_UNORM, GL_RGB5, GL_RGB5, 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, 0, @@ -2756,7 +2756,8 @@ static void check_fbo_compat(struct wined3d_caps_gl_ctx *ctx, struct wined3d_for TRACE("Format %s's sRGB format is FBO attachable, type %u.\n", debug_d3dformat(format->f.id), type); format->f.flags[type] |= WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB; - if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE]) + if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE] + && !(format->f.flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_SEPARATE_SRGB)) format->internal = format->srgb_internal; } else @@ -2891,7 +2892,6 @@ static void init_format_fbo_compat_info(const struct wined3d_adapter *adapter, } } } - if (format->internal != format->srgb_internal) { gl_info->gl_ops.ext.p_glGetInternalformativ(wined3d_gl_type_to_enum(type), @@ -2901,7 +2901,8 @@ static void init_format_fbo_compat_info(const struct wined3d_adapter *adapter, TRACE("Format %s's sRGB format is FBO attachable, resource type %u.\n", debug_d3dformat(format->f.id), type); format->f.flags[type] |= WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB; - if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE]) + if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE] + && !(format->f.flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_SEPARATE_SRGB)) format->internal = format->srgb_internal; } else @@ -3114,7 +3115,8 @@ static void query_internal_format(struct wined3d_adapter *adapter, query_format_flag(gl_info, format, format->srgb_internal, GL_SRGB_READ, WINED3DFMT_FLAG_SRGB_READ, "sRGB read");
- if (srgb_write_supported) + if (srgb_write_supported + && !(format->f.flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_SEPARATE_SRGB)) query_format_flag(gl_info, format, format->srgb_internal, GL_SRGB_WRITE, WINED3DFMT_FLAG_SRGB_WRITE, "sRGB write"); else @@ -3123,7 +3125,8 @@ static void query_internal_format(struct wined3d_adapter *adapter, if (!(format->f.flags[WINED3D_GL_RES_TYPE_TEX_2D] & (WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_SRGB_WRITE))) format->srgb_internal = format->internal; - else if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE]) + else if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE] + && !(format->f.flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_SEPARATE_SRGB)) format->internal = format->srgb_internal; } } @@ -3145,7 +3148,8 @@ static void query_internal_format(struct wined3d_adapter *adapter, format->srgb_internal = format->internal; format_clear_flag(&format->f, WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_SRGB_WRITE); } - else if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE]) + else if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE] + && !(format->f.flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_SEPARATE_SRGB)) { format->internal = format->srgb_internal; } diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 1f3808a7f1..62791c8d96 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4919,6 +4919,7 @@ extern enum wined3d_format_id pixelformat_for_depth(DWORD depth) DECLSPEC_HIDDEN #define WINED3DFMT_FLAG_VERTEX_ATTRIBUTE 0x01000000 #define WINED3DFMT_FLAG_BLIT 0x02000000 #define WINED3DFMT_FLAG_MAPPABLE 0x04000000 +#define WINED3DFMT_FLAG_SEPARATE_SRGB 0x08000000
struct wined3d_rational { @@ -5069,15 +5070,19 @@ static inline BOOL is_srgb_enabled(const DWORD *sampler_states) static inline BOOL needs_separate_srgb_gl_texture(const struct wined3d_context *context, const struct wined3d_texture *texture) { + BOOL format_separate_srgb; + if (!(context->d3d_info->wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL)) return FALSE;
- if (!context->d3d_info->srgb_read_control + format_separate_srgb = texture->resource.format_flags & WINED3DFMT_FLAG_SEPARATE_SRGB; + + if ((!context->d3d_info->srgb_read_control || format_separate_srgb) && (texture->resource.bind_flags & WINED3D_BIND_SHADER_RESOURCE) && (texture->resource.format_flags & WINED3DFMT_FLAG_SRGB_READ)) return TRUE;
- if (!context->d3d_info->srgb_write_control + if ((!context->d3d_info->srgb_write_control || format_separate_srgb) && (texture->resource.bind_flags & WINED3D_BIND_RENDER_TARGET) && (texture->resource.format_flags & WINED3DFMT_FLAG_SRGB_WRITE)) return TRUE;