[PATCH v2 2/7] wined3d: Add support for separate sRGB formats.

Józef Kucia jkucia at codeweavers.com
Fri Feb 5 08:08:08 CST 2016


Signed-off-by: Józef Kucia <jkucia at codeweavers.com>
---
Version 2:
* Remove the redundant "!!".
* Store wined3d creation flags in struct d3d_info.
* Pass wined3d creation flags instead of struct wined3d to wined3d_adpater_init().
* Rename should_use_separate_srgb_gl_texture() to needs_separate_srgb_gl_texture().
* Introduce a flag enabling sRGB read/write control instead of a flag enabling separate sRGB formats.
* Remove the 'glGammaInternal' field from struct wined3d_format_srgb_info.
* Reorganize sRGB formats initialization code.
---
 dlls/d3d8/directx.c            |  3 +-
 dlls/d3d9/directx.c            |  3 +-
 dlls/ddraw/ddraw_private.h     |  3 +-
 dlls/wined3d/context.c         |  5 ++-
 dlls/wined3d/device.c          | 46 ++++++++++------------
 dlls/wined3d/directx.c         |  9 +++--
 dlls/wined3d/shader.c          | 16 +++-----
 dlls/wined3d/state.c           | 12 +++---
 dlls/wined3d/texture.c         |  5 +--
 dlls/wined3d/utils.c           | 87 +++++++++++++++++++++++++++++++++---------
 dlls/wined3d/wined3d_private.h | 23 +++++++++--
 include/wine/wined3d.h         |  1 +
 12 files changed, 137 insertions(+), 76 deletions(-)

diff --git a/dlls/d3d8/directx.c b/dlls/d3d8/directx.c
index 0ca0dd3..5d0f6a8 100644
--- a/dlls/d3d8/directx.c
+++ b/dlls/d3d8/directx.c
@@ -432,7 +432,8 @@ static const struct IDirect3D8Vtbl d3d8_vtbl =
 BOOL d3d8_init(struct d3d8 *d3d8)
 {
     DWORD flags = WINED3D_LEGACY_DEPTH_BIAS | WINED3D_VIDMEM_ACCOUNTING
-            | WINED3D_HANDLE_RESTORE | WINED3D_PIXEL_CENTER_INTEGER;
+            | WINED3D_HANDLE_RESTORE | WINED3D_PIXEL_CENTER_INTEGER
+            | WINED3D_SRGB_READ_WRITE_CONTROL;
 
     d3d8->IDirect3D8_iface.lpVtbl = &d3d8_vtbl;
     d3d8->refcount = 1;
diff --git a/dlls/d3d9/directx.c b/dlls/d3d9/directx.c
index fb096c4..b09809c 100644
--- a/dlls/d3d9/directx.c
+++ b/dlls/d3d9/directx.c
@@ -667,7 +667,8 @@ static const struct IDirect3D9ExVtbl d3d9_vtbl =
 
 BOOL d3d9_init(struct d3d9 *d3d9, BOOL extended)
 {
-    DWORD flags = WINED3D_PRESENT_CONVERSION | WINED3D_HANDLE_RESTORE | WINED3D_PIXEL_CENTER_INTEGER;
+    DWORD flags = WINED3D_PRESENT_CONVERSION | WINED3D_HANDLE_RESTORE | WINED3D_PIXEL_CENTER_INTEGER
+            | WINED3D_SRGB_READ_WRITE_CONTROL;
 
     if (!extended)
         flags |= WINED3D_VIDMEM_ACCOUNTING;
diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h
index 704d6db..f2399e4 100644
--- a/dlls/ddraw/ddraw_private.h
+++ b/dlls/ddraw/ddraw_private.h
@@ -60,7 +60,8 @@ struct FvfToDecl
 #define DDRAW_STRIDE_ALIGNMENT  8
 
 #define DDRAW_WINED3D_FLAGS     (WINED3D_LEGACY_DEPTH_BIAS | WINED3D_VIDMEM_ACCOUNTING \
-        | WINED3D_RESTORE_MODE_ON_ACTIVATE | WINED3D_FOCUS_MESSAGES | WINED3D_PIXEL_CENTER_INTEGER)
+        | WINED3D_RESTORE_MODE_ON_ACTIVATE | WINED3D_FOCUS_MESSAGES | WINED3D_PIXEL_CENTER_INTEGER \
+        | WINED3D_SRGB_READ_WRITE_CONTROL)
 
 enum ddraw_device_state
 {
diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index 490c20f..664ef73 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -214,7 +214,7 @@ static void context_attach_surface_fbo(struct wined3d_context *context,
             case WINED3D_LOCATION_TEXTURE_SRGB:
                 srgb = location == WINED3D_LOCATION_TEXTURE_SRGB;
                 gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_COLOR_ATTACHMENT0 + idx,
-                        surface->texture_target, surface_get_texture_name(surface, gl_info, srgb),
+                        surface->texture_target, surface_get_texture_name(surface, context, srgb),
                         surface->texture_level);
                 checkGLcall("glFramebufferTexture2D()");
                 break;
@@ -2470,7 +2470,8 @@ BOOL context_apply_clear_state(struct wined3d_context *context, const struct win
     gl_info->gl_ops.gl.p_glEnable(GL_SCISSOR_TEST);
     if (gl_info->supported[ARB_FRAMEBUFFER_SRGB])
     {
-        if (device->state.render_states[WINED3D_RS_SRGBWRITEENABLE])
+        if (!(context->d3d_info->wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL)
+                || device->state.render_states[WINED3D_RS_SRGBWRITEENABLE])
             gl_info->gl_ops.gl.p_glEnable(GL_FRAMEBUFFER_SRGB);
         else
             gl_info->gl_ops.gl.p_glDisable(GL_FRAMEBUFFER_SRGB);
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 8f39c3b..93624f8 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -403,32 +403,28 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c
             }
         }
 
-        if (!gl_info->supported[ARB_FRAMEBUFFER_SRGB]
-                && device->state.render_states[WINED3D_RS_SRGBWRITEENABLE])
+        if (!gl_info->supported[ARB_FRAMEBUFFER_SRGB] && needs_srgb_write(context, &device->state, fb))
         {
-            if (fb->render_targets[0]->format_flags & WINED3DFMT_FLAG_SRGB_WRITE)
-            {
-                if (rt_count > 1)
-                    WARN("Clearing multiple sRGB render targets with no GL_ARB_framebuffer_sRGB "
-                            "support, this might cause graphical issues.\n");
-
-                corrected_color.r = color->r < wined3d_srgb_const1[0]
-                        ? color->r * wined3d_srgb_const0[3]
-                        : pow(color->r, wined3d_srgb_const0[0]) * wined3d_srgb_const0[1]
-                        - wined3d_srgb_const0[2];
-                corrected_color.r = min(max(corrected_color.r, 0.0f), 1.0f);
-                corrected_color.g = color->g < wined3d_srgb_const1[0]
-                        ? color->g * wined3d_srgb_const0[3]
-                        : pow(color->g, wined3d_srgb_const0[0]) * wined3d_srgb_const0[1]
-                        - wined3d_srgb_const0[2];
-                corrected_color.g = min(max(corrected_color.g, 0.0f), 1.0f);
-                corrected_color.b = color->b < wined3d_srgb_const1[0]
-                        ? color->b * wined3d_srgb_const0[3]
-                        : pow(color->b, wined3d_srgb_const0[0]) * wined3d_srgb_const0[1]
-                        - wined3d_srgb_const0[2];
-                corrected_color.b = min(max(corrected_color.b, 0.0f), 1.0f);
-                color = &corrected_color;
-            }
+            if (rt_count > 1)
+                WARN("Clearing multiple sRGB render targets with no GL_ARB_framebuffer_sRGB "
+                        "support, this might cause graphical issues.\n");
+
+            corrected_color.r = color->r < wined3d_srgb_const1[0]
+                    ? color->r * wined3d_srgb_const0[3]
+                    : pow(color->r, wined3d_srgb_const0[0]) * wined3d_srgb_const0[1]
+                    - wined3d_srgb_const0[2];
+            corrected_color.r = min(max(corrected_color.r, 0.0f), 1.0f);
+            corrected_color.g = color->g < wined3d_srgb_const1[0]
+                    ? color->g * wined3d_srgb_const0[3]
+                    : pow(color->g, wined3d_srgb_const0[0]) * wined3d_srgb_const0[1]
+                    - wined3d_srgb_const0[2];
+            corrected_color.g = min(max(corrected_color.g, 0.0f), 1.0f);
+            corrected_color.b = color->b < wined3d_srgb_const1[0]
+                    ? color->b * wined3d_srgb_const0[3]
+                    : pow(color->b, wined3d_srgb_const0[0]) * wined3d_srgb_const0[1]
+                    - wined3d_srgb_const0[2];
+            corrected_color.b = min(max(corrected_color.b, 0.0f), 1.0f);
+            color = &corrected_color;
         }
 
         gl_info->gl_ops.gl.p_glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index c7b63f1..afcac3b 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -3365,7 +3365,7 @@ static void wined3d_adapter_init_limits(struct wined3d_gl_info *gl_info)
 }
 
 /* Context activation is done by the caller. */
-static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter)
+static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter, DWORD wined3d_creation_flags)
 {
     static const struct
     {
@@ -3739,6 +3739,7 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter)
     adapter->d3d_info.limits.ffp_blend_stages = fragment_caps.MaxTextureBlendStages;
     adapter->d3d_info.limits.ffp_textures = fragment_caps.MaxSimultaneousTextures;
     adapter->d3d_info.shader_color_key = fragment_caps.wined3d_caps & WINED3D_FRAGMENT_CAP_COLOR_KEY;
+    adapter->d3d_info.wined3d_creation_flags = wined3d_creation_flags;
     TRACE("Max texture stages: %u.\n", adapter->d3d_info.limits.ffp_blend_stages);
 
     if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT])
@@ -5822,7 +5823,7 @@ static void wined3d_adapter_init_fb_cfgs(struct wined3d_adapter *adapter, HDC dc
     }
 }
 
-static BOOL wined3d_adapter_init(struct wined3d_adapter *adapter, UINT ordinal)
+static BOOL wined3d_adapter_init(struct wined3d_adapter *adapter, UINT ordinal, DWORD wined3d_creation_flags)
 {
     static const DWORD supported_gl_versions[] =
     {
@@ -5899,7 +5900,7 @@ static BOOL wined3d_adapter_init(struct wined3d_adapter *adapter, UINT ordinal)
                 supported_gl_versions[i] >> 16, supported_gl_versions[i] & 0xffff);
     }
 
-    if (!wined3d_adapter_init_gl_caps(adapter))
+    if (!wined3d_adapter_init_gl_caps(adapter, wined3d_creation_flags))
     {
         ERR("Failed to initialize GL caps for adapter %p.\n", adapter);
         wined3d_caps_gl_ctx_destroy(&caps_gl_ctx);
@@ -5993,7 +5994,7 @@ HRESULT wined3d_init(struct wined3d *wined3d, DWORD flags)
         return WINED3D_OK;
     }
 
-    if (!wined3d_adapter_init(&wined3d->adapters[0], 0))
+    if (!wined3d_adapter_init(&wined3d->adapters[0], 0, flags))
     {
         WARN("Failed to initialize adapter.\n");
         return E_FAIL;
diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c
index e81fc4e..8ec8a8e 100644
--- a/dlls/wined3d/shader.c
+++ b/dlls/wined3d/shader.c
@@ -2615,18 +2615,14 @@ void find_ps_compile_args(const struct wined3d_state *state, const struct wined3
     UINT i;
 
     memset(args, 0, sizeof(*args)); /* FIXME: Make sure all bits are set. */
-    if (!gl_info->supported[ARB_FRAMEBUFFER_SRGB] && state->render_states[WINED3D_RS_SRGBWRITEENABLE])
+    if (!gl_info->supported[ARB_FRAMEBUFFER_SRGB] && needs_srgb_write(context, state, state->fb))
     {
-        unsigned int rt_fmt_flags = state->fb->render_targets[0]->format_flags;
-        if (rt_fmt_flags & WINED3DFMT_FLAG_SRGB_WRITE)
-        {
-            static unsigned int warned = 0;
+        static unsigned int warned = 0;
 
-            args->srgb_correction = 1;
-            if (state->render_states[WINED3D_RS_ALPHABLENDENABLE] && !warned++)
-                WARN("Blending into a sRGB render target with no GL_ARB_framebuffer_sRGB "
-                        "support, expect rendering artifacts.\n");
-        }
+        args->srgb_correction = 1;
+        if (state->render_states[WINED3D_RS_ALPHABLENDENABLE] && !warned++)
+            WARN("Blending into a sRGB render target with no GL_ARB_framebuffer_sRGB "
+                    "support, expect rendering artifacts.\n");
     }
 
     if (shader->reg_maps.shader_version.major == 1
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index 1d80fa0..903f0d4 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -3477,7 +3477,7 @@ static enum wined3d_texture_address wined3d_texture_address_mode(const struct wi
 }
 
 static void wined3d_sampler_desc_from_sampler_states(struct wined3d_sampler_desc *desc,
-        const struct wined3d_gl_info *gl_info, const DWORD *sampler_states, const struct wined3d_texture *texture)
+        const struct wined3d_context *context, const DWORD *sampler_states, const struct wined3d_texture *texture)
 {
     union
     {
@@ -3513,7 +3513,8 @@ static void wined3d_sampler_desc_from_sampler_states(struct wined3d_sampler_desc
         desc->max_anisotropy = 1;
     desc->compare = texture->resource.format_flags & WINED3DFMT_FLAG_SHADOW;
     desc->comparison_func = WINED3D_CMP_LESSEQUAL;
-    desc->srgb_decode = sampler_states[WINED3D_SAMP_SRGB_TEXTURE];
+    desc->srgb_decode = !(context->d3d_info->wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL)
+            || sampler_states[WINED3D_SAMP_SRGB_TEXTURE];
 
     if (!(texture->resource.format_flags & WINED3DFMT_FLAG_FILTERING))
     {
@@ -3525,7 +3526,7 @@ static void wined3d_sampler_desc_from_sampler_states(struct wined3d_sampler_desc
     if (texture->flags & WINED3D_TEXTURE_COND_NP2)
     {
         desc->mip_filter = WINED3D_TEXF_NONE;
-        if (gl_info->supported[WINED3D_GL_NORMALIZED_TEXRECT])
+        if (context->gl_info->supported[WINED3D_GL_NORMALIZED_TEXRECT])
             desc->min_filter = WINED3D_TEXF_POINT;
     }
 }
@@ -3563,7 +3564,7 @@ static void sampler(struct wined3d_context *context, const struct wined3d_state
         struct gl_texture *gl_tex;
         unsigned int base_level;
 
-        wined3d_sampler_desc_from_sampler_states(&desc, gl_info, sampler_states, texture);
+        wined3d_sampler_desc_from_sampler_states(&desc, context, sampler_states, texture);
 
         wined3d_texture_bind(texture, context, srgb);
         if (!gl_info->supported[ARB_SAMPLER_OBJECTS])
@@ -4785,12 +4786,11 @@ static void psorigin(struct wined3d_context *context, const struct wined3d_state
 
 void state_srgbwrite(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
-    unsigned int rt_fmt_flags = state->fb->render_targets[0]->format_flags;
     const struct wined3d_gl_info *gl_info = context->gl_info;
 
     TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);
 
-    if (state->render_states[WINED3D_RS_SRGBWRITEENABLE] && rt_fmt_flags & WINED3DFMT_FLAG_SRGB_WRITE)
+    if (needs_srgb_write(context, state, state->fb))
         gl_info->gl_ops.gl.p_glEnable(GL_FRAMEBUFFER_SRGB);
     else
         gl_info->gl_ops.gl.p_glDisable(GL_FRAMEBUFFER_SRGB);
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index 88507fa..09c4ff8 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -153,7 +153,7 @@ void wined3d_texture_bind(struct wined3d_texture *texture,
 
     TRACE("texture %p, context %p, srgb %#x.\n", texture, context, srgb);
 
-    if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
+    if (!needs_separate_srgb_gl_texture(context))
         srgb = FALSE;
 
     /* sRGB mode cache for preload() calls outside drawprim. */
@@ -439,14 +439,13 @@ void wined3d_texture_load(struct wined3d_texture *texture,
         struct wined3d_context *context, BOOL srgb)
 {
     UINT sub_count = texture->level_count * texture->layer_count;
-    const struct wined3d_gl_info *gl_info = context->gl_info;
     const struct wined3d_d3d_info *d3d_info = context->d3d_info;
     DWORD flag;
     UINT i;
 
     TRACE("texture %p, context %p, srgb %#x.\n", texture, context, srgb);
 
-    if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
+    if (!needs_separate_srgb_gl_texture(context))
         srgb = FALSE;
 
     if (srgb)
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index 3100967..b8a065d 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -58,8 +58,11 @@ static const struct wined3d_format_channels formats[] =
     {WINED3DFMT_DXT4,                       0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
     {WINED3DFMT_DXT5,                       0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
     {WINED3DFMT_BC1_UNORM,                  0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
+    {WINED3DFMT_BC1_UNORM_SRGB,             0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
     {WINED3DFMT_BC2_UNORM,                  0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
+    {WINED3DFMT_BC2_UNORM_SRGB,             0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
     {WINED3DFMT_BC3_UNORM,                  0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
+    {WINED3DFMT_BC3_UNORM_SRGB,             0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
     {WINED3DFMT_MULTI2_ARGB8,               0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
     {WINED3DFMT_G8R8_G8B8,                  0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
     {WINED3DFMT_R8G8_B8G8,                  0,  0,  0,  0,   0,  0,  0,  0,    1,   0,     0},
@@ -961,17 +964,17 @@ static const struct wined3d_format_texture_info format_texture_info[] =
             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
             | WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_COMPRESSED,
             EXT_TEXTURE_COMPRESSION_S3TC, NULL},
-    {WINED3DFMT_BC1_UNORM,              GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,       0,
+    {WINED3DFMT_BC1_UNORM,              GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 0,
             GL_RGBA,                    GL_UNSIGNED_BYTE,                 0,
             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
             | WINED3DFMT_FLAG_COMPRESSED,
             EXT_TEXTURE_COMPRESSION_S3TC, NULL},
-    {WINED3DFMT_BC2_UNORM,              GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,       0,
+    {WINED3DFMT_BC2_UNORM,              GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 0,
             GL_RGBA,                    GL_UNSIGNED_BYTE,                 0,
             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
             | WINED3DFMT_FLAG_COMPRESSED,
             EXT_TEXTURE_COMPRESSION_S3TC, NULL},
-    {WINED3DFMT_BC3_UNORM,              GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,       0,
+    {WINED3DFMT_BC3_UNORM,              GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 0,
             GL_RGBA,                    GL_UNSIGNED_BYTE,                 0,
             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
             | WINED3DFMT_FLAG_COMPRESSED,
@@ -1344,6 +1347,20 @@ static const struct wined3d_format_texture_info format_texture_info[] =
             ARB_FRAMEBUFFER_OBJECT,     NULL},
 };
 
+struct wined3d_format_srgb_info
+{
+    enum wined3d_format_id srgb_format_id;
+    enum wined3d_format_id base_format_id;
+};
+
+static const struct wined3d_format_srgb_info format_srgb_info[] =
+{
+    {WINED3DFMT_BC1_UNORM_SRGB,      WINED3DFMT_BC1_UNORM},
+    {WINED3DFMT_BC2_UNORM_SRGB,      WINED3DFMT_BC2_UNORM},
+    {WINED3DFMT_BC3_UNORM_SRGB,      WINED3DFMT_BC3_UNORM},
+    {WINED3DFMT_R8G8B8A8_UNORM_SRGB, WINED3DFMT_R8G8B8A8_UNORM},
+};
+
 static inline int getFmtIdx(enum wined3d_format_id format_id)
 {
     /* First check if the format is at the position of its value.
@@ -2172,7 +2189,7 @@ static void init_format_fbo_compat_info(struct wined3d_caps_gl_ctx *ctx)
 
 static void query_internal_format(struct wined3d_adapter *adapter,
         struct wined3d_format *format, const struct wined3d_format_texture_info *texture_info,
-        struct wined3d_gl_info *gl_info)
+        struct wined3d_gl_info *gl_info, BOOL srgb_format)
 {
     GLint count, multisample_types[MAX_MULTISAMPLE_TYPES];
     struct fragment_caps fragment_caps;
@@ -2192,7 +2209,7 @@ static void query_internal_format(struct wined3d_adapter *adapter,
         query_format_flag(gl_info, format, format->glInternal, GL_FILTER,
                 WINED3DFMT_FLAG_FILTERING, "filtering");
 
-        if (format->glGammaInternal != format->glInternal)
+        if (srgb_format || format->glGammaInternal != format->glInternal)
         {
             query_format_flag(gl_info, format, format->glGammaInternal, GL_SRGB_READ,
                     WINED3DFMT_FLAG_SRGB_READ, "sRGB read");
@@ -2219,7 +2236,7 @@ static void query_internal_format(struct wined3d_adapter *adapter,
         else if (format->id != WINED3DFMT_R32G32B32A32_FLOAT && format->id != WINED3DFMT_R32_FLOAT)
             format_clear_flag(format, WINED3DFMT_FLAG_VTF);
 
-        if (format->glGammaInternal != format->glInternal)
+        if (srgb_format || format->glGammaInternal != format->glInternal)
         {
             /* Filter sRGB capabilities if EXT_texture_sRGB is not supported. */
             if (!gl_info->supported[EXT_TEXTURE_SRGB])
@@ -2278,12 +2295,12 @@ static void query_internal_format(struct wined3d_adapter *adapter,
 
 static BOOL init_format_texture_info(struct wined3d_adapter *adapter, struct wined3d_gl_info *gl_info)
 {
-    unsigned int i;
+    unsigned int i, j;
 
     for (i = 0; i < sizeof(format_texture_info) / sizeof(*format_texture_info); ++i)
     {
-        int fmt_idx = getFmtIdx(format_texture_info[i].id);
-        struct wined3d_format *format;
+        int srgb_fmt_idx = -1, fmt_idx = getFmtIdx(format_texture_info[i].id);
+        struct wined3d_format *format, *srgb_format;
 
         if (fmt_idx == -1)
         {
@@ -2330,11 +2347,51 @@ static BOOL init_format_texture_info(struct wined3d_adapter *adapter, struct win
         format->flags[WINED3D_GL_RES_TYPE_RB] |= format_texture_info[i].flags;
         format->flags[WINED3D_GL_RES_TYPE_RB] &= ~WINED3DFMT_FLAG_TEXTURE;
 
-        query_internal_format(adapter, format, &format_texture_info[i], gl_info);
+        if (format->glGammaInternal != format->glInternal
+                && !(adapter->d3d_info.wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL))
+        {
+            format->glGammaInternal = format->glInternal;
+            format_clear_flag(format, WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_SRGB_WRITE);
+        }
+
+        query_internal_format(adapter, format, &format_texture_info[i], gl_info, FALSE);
 
         /* Texture conversion stuff */
         format->convert = format_texture_info[i].convert;
         format->conv_byte_count = format_texture_info[i].conv_byte_count;
+
+        for (j = 0; j < sizeof(format_srgb_info) / sizeof(*format_srgb_info); ++j)
+        {
+            if (format_srgb_info[j].base_format_id == format->id)
+            {
+                srgb_fmt_idx = getFmtIdx(format_srgb_info[j].srgb_format_id);
+                if (srgb_fmt_idx == -1)
+                {
+                    ERR("Format %s (%#x) not found.\n",
+                            debug_d3dformat(format_srgb_info[j].srgb_format_id),
+                            format_srgb_info[j].srgb_format_id);
+                    return FALSE;
+                }
+                break;
+            }
+        }
+
+        if (srgb_fmt_idx == -1)
+            continue;
+
+        srgb_format = &gl_info->formats[srgb_fmt_idx];
+
+        *srgb_format = *format;
+        srgb_format->id = format_srgb_info[j].srgb_format_id;
+
+        if (gl_info->supported[EXT_TEXTURE_SRGB]
+                && !(adapter->d3d_info.wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL))
+        {
+            srgb_format->glInternal = format_texture_info[i].gl_srgb_internal;
+            srgb_format->glGammaInternal = format_texture_info[i].gl_srgb_internal;
+            format_set_flag(srgb_format, WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_SRGB_WRITE);
+            query_internal_format(adapter, srgb_format, &format_texture_info[i], gl_info, TRUE);
+        }
     }
 
     return TRUE;
@@ -4414,7 +4471,6 @@ void gen_ffp_frag_op(const struct wined3d_context *context, const struct wined3d
     unsigned int i;
     DWORD ttff;
     DWORD cop, aop, carg0, carg1, carg2, aarg0, aarg1, aarg2;
-    unsigned int rt_fmt_flags = state->fb->render_targets[0]->format_flags;
     const struct wined3d_gl_info *gl_info = context->gl_info;
     const struct wined3d_d3d_info *d3d_info = context->d3d_info;
 
@@ -4628,14 +4684,7 @@ void gen_ffp_frag_op(const struct wined3d_context *context, const struct wined3d
                 break;
         }
     }
-    if (!gl_info->supported[ARB_FRAMEBUFFER_SRGB]
-            && state->render_states[WINED3D_RS_SRGBWRITEENABLE]
-            && rt_fmt_flags & WINED3DFMT_FLAG_SRGB_WRITE)
-    {
-        settings->sRGB_write = 1;
-    } else {
-        settings->sRGB_write = 0;
-    }
+    settings->sRGB_write = !gl_info->supported[ARB_FRAMEBUFFER_SRGB] && needs_srgb_write(context, state, state->fb);
     if (d3d_info->vs_clipping || !use_vs(state) || !state->render_states[WINED3D_RS_CLIPPING]
             || !state->render_states[WINED3D_RS_CLIPPLANEENABLE])
     {
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 6f4dc36..5cab5bb 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1875,6 +1875,7 @@ struct wined3d_d3d_info
     BOOL vs_clipping;
     BOOL shader_color_key;
     DWORD valid_rt_mask;
+    DWORD wined3d_creation_flags;
 };
 
 /* The adapter structure */
@@ -1884,10 +1885,10 @@ struct wined3d_adapter
     POINT monitor_position;
     enum wined3d_format_id screen_format;
 
-    struct wined3d_gl_info  gl_info;
+    struct wined3d_gl_info gl_info;
     struct wined3d_d3d_info d3d_info;
     struct wined3d_driver_info driver_info;
-    WCHAR                   DeviceName[CCHDEVICENAME]; /* DeviceName for use with e.g. ChangeDisplaySettings */
+    WCHAR DeviceName[CCHDEVICENAME]; /* DeviceName for use with e.g. ChangeDisplaySettings */
     unsigned int cfg_count;
     struct wined3d_pixel_format *cfgs;
     UINT64 vram_bytes;
@@ -2526,10 +2527,16 @@ static inline struct wined3d_surface *surface_from_resource(struct wined3d_resou
     return CONTAINING_RECORD(resource, struct wined3d_surface, resource);
 }
 
+static inline BOOL needs_separate_srgb_gl_texture(const struct wined3d_context *context)
+{
+    return !context->gl_info->supported[EXT_TEXTURE_SRGB_DECODE]
+            && context->d3d_info->wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL;
+}
+
 static inline GLuint surface_get_texture_name(const struct wined3d_surface *surface,
-        const struct wined3d_gl_info *gl_info, BOOL srgb)
+        const struct wined3d_context *context, BOOL srgb)
 {
-    return srgb && !gl_info->supported[EXT_TEXTURE_SRGB_DECODE]
+    return srgb && needs_separate_srgb_gl_texture(context)
             ? surface->container->texture_srgb.name : surface->container->texture_rgb.name;
 }
 
@@ -3371,6 +3378,14 @@ static inline void context_apply_state(struct wined3d_context *context,
     state_table[rep].apply(context, state, rep);
 }
 
+static inline BOOL needs_srgb_write(const struct wined3d_context *context,
+        const struct wined3d_state *state, const struct wined3d_fb_state *fb)
+{
+    return (!(context->d3d_info->wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL)
+            || state->render_states[WINED3D_RS_SRGBWRITEENABLE])
+            && fb->render_targets[0]->format_flags & WINED3DFMT_FLAG_SRGB_WRITE;
+}
+
 /* The WNDCLASS-Name for the fake window which we use to retrieve the GL capabilities */
 #define WINED3D_OPENGL_WINDOW_CLASS_NAME "WineD3D_OpenGL"
 
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h
index 1e91397..73dd05c 100644
--- a/include/wine/wined3d.h
+++ b/include/wine/wined3d.h
@@ -1230,6 +1230,7 @@ enum wined3d_display_rotation
 #define WINED3D_HANDLE_RESTORE                                  0x00000040
 #define WINED3D_PIXEL_CENTER_INTEGER                            0x00000080
 #define WINED3D_LEGACY_FFP_LIGHTING                             0x00000100
+#define WINED3D_SRGB_READ_WRITE_CONTROL                         0x00000200
 
 #define WINED3D_RESZ_CODE                                       0x7fa05000
 
-- 
2.4.10




More information about the wine-patches mailing list