From: Paul Gofman gofmanp@gmail.com
Signed-off-by: Paul Gofman gofmanp@gmail.com Signed-off-by: Henri Verbeet hverbeet@codeweavers.com --- dlls/d3d9/tests/visual.c | 4 +- dlls/wined3d/device.c | 49 ++++++++++++++++++---- dlls/wined3d/stateblock.c | 77 +++++++++++++++++++++++++++++++--- dlls/wined3d/wined3d_private.h | 7 +++- include/wine/wined3d.h | 1 + 5 files changed, 120 insertions(+), 18 deletions(-)
diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c index 366862a05aa..3151efaf330 100644 --- a/dlls/d3d9/tests/visual.c +++ b/dlls/d3d9/tests/visual.c @@ -26679,8 +26679,8 @@ static void test_alpha_to_coverage(void) get_rt_readback(rt, &rb); 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 */, + /* NVIDIA is probably using some proprietary algorithm for averaging sample colour values. */ + 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 d709ca189c2..1e6ec5d0981 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; const struct wined3d_saved_states *changed = &stateblock->changed; + struct wined3d_blend_state *blend_state; + struct wined3d_color colour; unsigned int i, j, count;
TRACE("device %p, stateblock %p.\n", device, stateblock); @@ -3941,18 +3945,32 @@ void CDECL wined3d_device_apply_stateblock(struct wined3d_device *device, } }
+ if (changed->blend_state) + { + if (wined3d_bitmap_is_set(changed->renderState, WINED3D_RS_BLENDFACTOR)) + wined3d_color_from_d3dcolor(&colour, stateblock->stateblock_state.rs[WINED3D_RS_BLENDFACTOR]); + else + wined3d_device_get_blend_state(device, &colour); + + wined3d_device_set_blend_state(device, state->blend_state, &colour); + } + for (i = 0; i < ARRAY_SIZE(state->rs); ++i) { - if (wined3d_bitmap_is_set(changed->renderState, i)) + if (!wined3d_bitmap_is_set(changed->renderState, i)) + continue; + + if (i != WINED3D_RS_BLENDFACTOR) { - if (i == WINED3D_RS_BLENDFACTOR) - { - struct wined3d_color color; - wined3d_color_from_d3dcolor(&color, state->rs[i]); - wined3d_device_set_blend_state(device, NULL, &color); - } - else - wined3d_device_set_render_state(device, i, state->rs[i]); + wined3d_device_set_render_state(device, i, state->rs[i]); + continue; + } + + if (!changed->blend_state) + { + blend_state = wined3d_device_get_blend_state(device, &colour); + wined3d_color_from_d3dcolor(&colour, state->rs[i]); + wined3d_device_set_blend_state(device, blend_state, &colour); } }
@@ -5760,6 +5778,7 @@ 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;
@@ -5814,6 +5833,18 @@ HRESULT wined3d_device_init(struct wined3d_device *device, struct wined3d *wined goto err; }
+ 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("Failed to create blend state object, hr %#x.\n", hr); + wined3d_cs_destroy(device->cs); + state_cleanup(&device->state); + goto err; + } + return WINED3D_OK;
err: diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c index 499d23fbbd3..71d88bf1949 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) { @@ -426,6 +428,7 @@ void state_unbind_resources(struct wined3d_state *state) struct wined3d_unordered_access_view *uav; struct wined3d_shader_resource_view *srv; struct wined3d_vertex_declaration *decl; + struct wined3d_blend_state *blend_state; struct wined3d_sampler *sampler; struct wined3d_texture *texture; struct wined3d_buffer *buffer; @@ -519,12 +522,19 @@ void state_unbind_resources(struct wined3d_state *state) } } } + + if ((blend_state = state->blend_state)) + { + state->blend_state = NULL; + wined3d_blend_state_decref(blend_state); + } }
void wined3d_stateblock_state_cleanup(struct wined3d_stateblock_state *state) { struct wined3d_light_info *light, *cursor; struct wined3d_vertex_declaration *decl; + struct wined3d_blend_state *blend_state; struct wined3d_texture *texture; struct wined3d_buffer *buffer; struct wined3d_shader *shader; @@ -580,6 +590,12 @@ void wined3d_stateblock_state_cleanup(struct wined3d_stateblock_state *state) heap_free(light); } } + + if ((blend_state = state->blend_state)) + { + state->blend_state = NULL; + wined3d_blend_state_decref(blend_state); + } }
void state_cleanup(struct wined3d_state *state) @@ -1017,6 +1033,15 @@ 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) + { + if (state->blend_state) + wined3d_blend_state_incref(state->blend_state); + if (stateblock->stateblock_state.blend_state) + wined3d_blend_state_decref(stateblock->stateblock_state.blend_state); + stateblock->stateblock_state.blend_state = state->blend_state; + } + TRACE("Capture done.\n"); }
@@ -1025,6 +1050,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; + struct wined3d_blend_state *blend_state; + struct wined3d_color colour; unsigned int i; DWORD map;
@@ -1113,20 +1140,41 @@ void CDECL wined3d_stateblock_apply(const struct wined3d_stateblock *stateblock, wined3d_device_set_ps_consts_b(device, idx, 1, &stateblock->stateblock_state.ps_consts_b[idx]); }
+ if (stateblock->changed.blend_state) + { + if (stateblock->stateblock_state.blend_state) + wined3d_blend_state_incref(stateblock->stateblock_state.blend_state); + if (state->blend_state) + wined3d_blend_state_decref(state->blend_state); + + state->blend_state = stateblock->stateblock_state.blend_state; + + if (wined3d_bitmap_is_set(stateblock->changed.renderState, WINED3D_RS_BLENDFACTOR)) + wined3d_color_from_d3dcolor(&colour, stateblock->stateblock_state.rs[WINED3D_RS_BLENDFACTOR]); + else + wined3d_device_get_blend_state(device, &colour); + + wined3d_device_set_blend_state(device, stateblock->stateblock_state.blend_state, &colour); + } + /* Render states. */ for (i = 0; i < stateblock->num_contained_render_states; ++i) { enum wined3d_render_state rs = stateblock->contained_render_states[i];
state->rs[rs] = stateblock->stateblock_state.rs[rs]; - if (rs == WINED3D_RS_BLENDFACTOR) + if (rs != WINED3D_RS_BLENDFACTOR) { - struct wined3d_color color; - wined3d_color_from_d3dcolor(&color, stateblock->stateblock_state.rs[rs]); - wined3d_device_set_blend_state(device, NULL, &color); - } - else wined3d_device_set_render_state(device, rs, stateblock->stateblock_state.rs[rs]); + continue; + } + + if (!stateblock->changed.blend_state) + { + blend_state = wined3d_device_get_blend_state(device, &colour); + wined3d_color_from_d3dcolor(&colour, stateblock->stateblock_state.rs[rs]); + wined3d_device_set_blend_state(device, blend_state, &colour); + } }
/* Texture states. */ @@ -1426,6 +1474,23 @@ 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) + { + wined3d_blend_state_incref(stateblock->device->blend_state_atoc_enabled); + stateblock->stateblock_state.blend_state = stateblock->device->blend_state_atoc_enabled; + } + else if (value == WINED3D_ALPHA_TO_COVERAGE_DISABLE && stateblock->stateblock_state.blend_state) + { + wined3d_blend_state_decref(stateblock->stateblock_state.blend_state); + 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 92634b71551..d29dfc312b2 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 d313c7aec86..d783e64a26d 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