[PATCH 7/7] wined3d: Handle D3DRS_SRGBWRITEENABLE in clears when ARB_framebuffer_sRGB is not supported.

Matteo Bruni mbruni at codeweavers.com
Fri Nov 27 13:39:36 CST 2015


Signed-off-by: Matteo Bruni <mbruni at codeweavers.com>
---
We could in theory also do something better when there are multiple
render targets with only some of them sRGB-capable but that would
require a lot of work for an arguably very marginal case.

 dlls/d3d9/tests/visual.c | 14 ++------------
 dlls/wined3d/device.c    | 29 +++++++++++++++++++++++++++++
 2 files changed, 31 insertions(+), 12 deletions(-)

diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c
index e126258..24915ff 100644
--- a/dlls/d3d9/tests/visual.c
+++ b/dlls/d3d9/tests/visual.c
@@ -905,7 +905,6 @@ static void clear_test(void)
     IDirect3DDevice9 *device;
     IDirect3D9 *d3d;
     ULONG refcount;
-    D3DCAPS9 caps;
     HWND window;
 
     window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
@@ -1155,9 +1154,6 @@ static void clear_test(void)
     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
 
     /* Test D3DRS_SRGBWRITEENABLE interactions with clears. */
-    hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
-    ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
-
     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x7f7f7f7f, 0.0, 0);
     ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
 
@@ -1195,10 +1191,7 @@ static void clear_test(void)
     ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
 
     color = getPixelColor(device, 320, 240);
-    if (caps.PrimitiveMiscCaps & D3DPMISCCAPS_POSTBLENDSRGBCONVERT)
-        ok(color_match(color, 0x00bbbbbb, 1), "Clear has color %08x.\n", color);
-    else
-        todo_wine ok(color_match(color, 0x00bbbbbb, 1), "Clear has color %08x.\n", color);
+    ok(color_match(color, 0x00bbbbbb, 1), "Clear has color %08x.\n", color);
 
     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRGBWRITEENABLE, FALSE);
     ok(SUCCEEDED(hr), "Failed to disable sRGB write, hr %#x.\n", hr);
@@ -1250,10 +1243,7 @@ static void clear_test(void)
     ok(SUCCEEDED(hr), "Failed to blit surface, hr %#x.\n", hr);
 
     color = getPixelColor(device, 320, 240);
-    if (caps.PrimitiveMiscCaps & D3DPMISCCAPS_POSTBLENDSRGBCONVERT)
-        ok(color_match(color, 0x00bbbbbb, 1), "Clear has color %08x.\n", color);
-    else
-        todo_wine ok(color_match(color, 0x00bbbbbb, 1), "Clear has color %08x.\n", color);
+    ok(color_match(color, 0x00bbbbbb, 1), "Clear has color %08x.\n", color);
 
     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRGBWRITEENABLE, FALSE);
     ok(SUCCEEDED(hr), "Failed to disable sRGB write, hr %#x.\n", hr);
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 170536d..057ae18 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -294,6 +294,7 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c
     const RECT *clear_rect = (rect_count > 0 && rects) ? (const RECT *)rects : NULL;
     const struct wined3d_gl_info *gl_info;
     UINT drawable_width, drawable_height;
+    struct wined3d_color corrected_color;
     struct wined3d_context *context;
     GLbitfield clear_mask = 0;
     BOOL render_offscreen;
@@ -402,6 +403,34 @@ 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 (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;
+            }
+        }
+
         gl_info->gl_ops.gl.p_glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
         context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE));
         context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE1));
-- 
2.4.10




More information about the wine-patches mailing list