[PATCH v2 2/4] wined3d: Support SRGB read for _B5G6R5 format.

Paul Gofman gofmanp at gmail.com
Wed Jan 22 10:01:44 CST 2020


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 at 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;
-- 
2.24.1




More information about the wine-devel mailing list