[resend PATCH v3 1/4] wined3d: Support AMD alpha to coverage state.

Paul Gofman gofmanp at gmail.com
Wed Feb 12 08:53:37 CST 2020


Signed-off-by: Paul Gofman <gofmanp at gmail.com>
---
    v3:
        - manage the state in state block.

 dlls/d3d9/tests/visual.c       |  2 +-
 dlls/wined3d/device.c          | 28 ++++++++++++++++++++++++++--
 dlls/wined3d/stateblock.c      | 32 ++++++++++++++++++++++++++++++--
 dlls/wined3d/wined3d_private.h |  7 ++++++-
 include/wine/wined3d.h         |  1 +
 5 files changed, 64 insertions(+), 6 deletions(-)

diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c
index 366862a05a..336d08513d 100644
--- a/dlls/d3d9/tests/visual.c
+++ b/dlls/d3d9/tests/visual.c
@@ -26680,7 +26680,7 @@ static void test_alpha_to_coverage(void)
     colour = get_readback_color(&rb, 64, 64);
 
     /* Nvidia is probably using some proprietary algorithm for averaging sample colour values. */
-    todo_wine ok(color_match(colour, 0x9f404080, 1) || color_match(colour, 0x9f485cbc, 1) /* Nvidia */,
+    ok(color_match(colour, 0x9f404080, 1) || color_match(colour, 0x9f485cbc, 1) /* Nvidia */,
             "Got unexpected colour %08x.\n", colour);
     release_surface_readback(&rb);
 
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 8405643741..5636ba7ddf 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -529,6 +529,8 @@ void wined3d_device_cleanup(struct wined3d_device *device)
     if (device->swapchain_count)
         wined3d_device_uninit_3d(device);
 
+    wined3d_blend_state_decref(device->blend_state_atoc_enabled);
+
     wined3d_cs_destroy(device->cs);
 
     for (i = 0; i < ARRAY_SIZE(device->multistate_funcs); ++i)
@@ -3837,6 +3839,8 @@ void CDECL wined3d_device_apply_stateblock(struct wined3d_device *device,
     const struct wined3d_d3d_info *d3d_info = &stateblock->device->adapter->d3d_info;
     const struct wined3d_stateblock_state *state = &stateblock->stateblock_state;
     unsigned int i, j, count;
+    BOOL blend_state_set = FALSE;
+    struct wined3d_color color;
 
     TRACE("device %p, stateblock %p.\n", device, stateblock);
 
@@ -3946,15 +3950,24 @@ void CDECL wined3d_device_apply_stateblock(struct wined3d_device *device,
         {
             if (i == WINED3D_RS_BLENDFACTOR)
             {
-                struct wined3d_color color;
+                struct wined3d_blend_state *blend_state = stateblock->changed.blend_state
+                        ? state->blend_state : wined3d_device_get_blend_state(device, &color);
+
                 wined3d_color_from_d3dcolor(&color, state->rs[i]);
-                wined3d_device_set_blend_state(device, NULL, &color);
+                wined3d_device_set_blend_state(device, blend_state, &color);
+                blend_state_set = TRUE;
             }
             else
                 wined3d_device_set_render_state(device, i, state->rs[i]);
         }
     }
 
+    if (stateblock->changed.blend_state && !blend_state_set)
+    {
+        wined3d_device_get_blend_state(device, &color);
+        wined3d_device_set_blend_state(device, state->blend_state, &color);
+    }
+
     for (i = 0; i < ARRAY_SIZE(state->texture_states); ++i)
     {
         for (j = 0; j < ARRAY_SIZE(state->texture_states[i]); ++j)
@@ -5759,12 +5772,23 @@ HRESULT wined3d_device_init(struct wined3d_device *device, struct wined3d *wined
     struct wined3d_adapter *adapter = wined3d->adapters[adapter_idx];
     const struct wined3d_fragment_pipe_ops *fragment_pipeline;
     const struct wined3d_vertex_pipe_ops *vertex_pipeline;
+    struct wined3d_blend_state_desc blend_state_desc;
     unsigned int i;
     HRESULT hr;
 
     if (!wined3d_select_feature_level(adapter, levels, level_count, &device->feature_level))
         return E_FAIL;
 
+    memset(&blend_state_desc, 0, sizeof(blend_state_desc));
+    blend_state_desc.alpha_to_coverage = TRUE;
+
+    if (FAILED(hr = wined3d_blend_state_create(device, &blend_state_desc,
+            NULL, &wined3d_null_parent_ops, &device->blend_state_atoc_enabled)))
+    {
+        ERR("Could not create blend state object.\n");
+        return hr;
+    }
+
     TRACE("Device feature level %s.\n", wined3d_debug_feature_level(device->feature_level));
 
     device->ref = 1;
diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c
index 499d23fbbd..0d3fad0a6d 100644
--- a/dlls/wined3d/stateblock.c
+++ b/dlls/wined3d/stateblock.c
@@ -209,6 +209,7 @@ static void stateblock_savedstates_set_all(struct wined3d_saved_states *states,
     states->pixelShader = 1;
     states->vertexShader = 1;
     states->scissorRect = 1;
+    states->blend_state = 1;
 
     /* Fixed size arrays */
     states->streamSource = 0xffff;
@@ -263,6 +264,7 @@ static void stateblock_savedstates_set_vertex(struct wined3d_saved_states *state
 
     states->vertexDecl = 1;
     states->vertexShader = 1;
+    states->blend_state = 1;
 
     for (i = 0; i < ARRAY_SIZE(vertex_states_render); ++i)
     {
@@ -1017,6 +1019,9 @@ void CDECL wined3d_stateblock_capture(struct wined3d_stateblock *stateblock,
 
     wined3d_state_record_lights(stateblock->stateblock_state.light_state, state->light_state);
 
+    if (stateblock->changed.blend_state)
+        stateblock->stateblock_state.blend_state = state->blend_state;
+
     TRACE("Capture done.\n");
 }
 
@@ -1025,6 +1030,8 @@ void CDECL wined3d_stateblock_apply(const struct wined3d_stateblock *stateblock,
 {
     struct wined3d_stateblock_state *state = &device_state->stateblock_state;
     struct wined3d_device *device = stateblock->device;
+    BOOL blend_state_set = FALSE;
+    struct wined3d_color color;
     unsigned int i;
     DWORD map;
 
@@ -1121,14 +1128,24 @@ void CDECL wined3d_stateblock_apply(const struct wined3d_stateblock *stateblock,
         state->rs[rs] = stateblock->stateblock_state.rs[rs];
         if (rs == WINED3D_RS_BLENDFACTOR)
         {
-            struct wined3d_color color;
+            struct wined3d_blend_state *blend_state = stateblock->changed.blend_state
+                    ? stateblock->stateblock_state.blend_state
+                    : wined3d_device_get_blend_state(device, &color);
+
             wined3d_color_from_d3dcolor(&color, stateblock->stateblock_state.rs[rs]);
-            wined3d_device_set_blend_state(device, NULL, &color);
+            wined3d_device_set_blend_state(device, blend_state, &color);
+            blend_state_set = TRUE;
         }
         else
             wined3d_device_set_render_state(device, rs, stateblock->stateblock_state.rs[rs]);
     }
 
+    if (stateblock->changed.blend_state && !blend_state_set)
+    {
+        wined3d_device_get_blend_state(device, &color);
+        wined3d_device_set_blend_state(device, stateblock->stateblock_state.blend_state, &color);
+    }
+
     /* Texture states. */
     for (i = 0; i < stateblock->num_contained_tss_states; ++i)
     {
@@ -1426,6 +1443,17 @@ void CDECL wined3d_stateblock_set_render_state(struct wined3d_stateblock *stateb
 
     stateblock->stateblock_state.rs[state] = value;
     stateblock->changed.renderState[state >> 5] |= 1u << (state & 0x1f);
+
+    if (state == WINED3D_RS_POINTSIZE
+            && (value == WINED3D_ALPHA_TO_COVERAGE_ENABLE || value == WINED3D_ALPHA_TO_COVERAGE_DISABLE))
+    {
+        stateblock->changed.blend_state = 1;
+
+        if (value == WINED3D_ALPHA_TO_COVERAGE_ENABLE)
+            stateblock->stateblock_state.blend_state = stateblock->device->blend_state_atoc_enabled;
+        else
+            stateblock->stateblock_state.blend_state = NULL;
+    }
 }
 
 void CDECL wined3d_stateblock_set_sampler_state(struct wined3d_stateblock *stateblock,
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 0e1e55d52b..f6e5dadf2a 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -76,6 +76,9 @@
 
 #define WINED3D_MAX_DIRTY_REGION_COUNT 7
 
+#define WINED3D_ALPHA_TO_COVERAGE_ENABLE MAKEFOURCC('A','2','M','1')
+#define WINED3D_ALPHA_TO_COVERAGE_DISABLE MAKEFOURCC('A','2','M','0')
+
 struct wined3d_fragment_pipe_ops;
 struct wined3d_adapter;
 struct wined3d_context;
@@ -3314,6 +3317,7 @@ struct wined3d_device
     /* Context management */
     struct wined3d_context **contexts;
     UINT context_count;
+    struct wined3d_blend_state *blend_state_atoc_enabled;
 };
 
 void wined3d_device_cleanup(struct wined3d_device *device) DECLSPEC_HIDDEN;
@@ -3932,7 +3936,8 @@ struct wined3d_saved_states
     DWORD vertexShader : 1;
     DWORD scissorRect : 1;
     DWORD store_stream_offset : 1;
-    DWORD padding : 4;
+    DWORD blend_state : 1;
+    DWORD padding : 3;
 };
 
 struct StageState {
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h
index d313c7aec8..d783e64a26 100644
--- a/include/wine/wined3d.h
+++ b/include/wine/wined3d.h
@@ -2168,6 +2168,7 @@ struct wined3d_stateblock_state
     RECT scissor_rect;
 
     struct wined3d_light_state *light_state;
+    struct wined3d_blend_state *blend_state;
 };
 
 struct wined3d_parent_ops
-- 
2.24.1




More information about the wine-devel mailing list