Signed-off-by: Józef Kucia jkucia@codeweavers.com --- dlls/d3d11/d3d11_private.h | 2 +- dlls/d3d11/device.c | 20 +++++++++--- dlls/d3d11/state.c | 78 ++++++++++++++++++++++++++++------------------ 3 files changed, 64 insertions(+), 36 deletions(-)
diff --git a/dlls/d3d11/d3d11_private.h b/dlls/d3d11/d3d11_private.h index 1030b96e7c67..52496d8b123e 100644 --- a/dlls/d3d11/d3d11_private.h +++ b/dlls/d3d11/d3d11_private.h @@ -392,6 +392,7 @@ struct d3d_blend_state LONG refcount;
struct wined3d_private_store private_store; + struct wined3d_blend_state *wined3d_state; D3D11_BLEND_DESC desc; struct wine_rb_entry entry; ID3D11Device *device; @@ -522,7 +523,6 @@ struct d3d_device struct wine_rb_tree rasterizer_states; struct wine_rb_tree sampler_states;
- struct d3d_blend_state *blend_state; float blend_factor[4]; struct d3d_depthstencil_state *depth_stencil_state; UINT stencil_ref; diff --git a/dlls/d3d11/device.c b/dlls/d3d11/device.c index b14c3862a1dc..f9db15f12fdc 100644 --- a/dlls/d3d11/device.c +++ b/dlls/d3d11/device.c @@ -686,6 +686,7 @@ static void STDMETHODCALLTYPE d3d11_immediate_context_OMSetBlendState(ID3D11Devi { struct d3d_device *device = device_from_immediate_ID3D11DeviceContext(iface); static const float default_blend_factor[] = {1.0f, 1.0f, 1.0f, 1.0f}; + struct d3d_blend_state *blend_state_impl; const D3D11_BLEND_DESC *desc;
TRACE("iface %p, blend_state %p, blend_factor %s, sample_mask 0x%08x.\n", @@ -697,8 +698,9 @@ static void STDMETHODCALLTYPE d3d11_immediate_context_OMSetBlendState(ID3D11Devi wined3d_mutex_lock(); memcpy(device->blend_factor, blend_factor, 4 * sizeof(*blend_factor)); wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_MULTISAMPLEMASK, sample_mask); - if (!(device->blend_state = unsafe_impl_from_ID3D11BlendState(blend_state))) + if (!(blend_state_impl = unsafe_impl_from_ID3D11BlendState(blend_state))) { + wined3d_device_set_blend_state(device->wined3d_device, NULL); wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_ALPHABLENDENABLE, FALSE); wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_COLORWRITEENABLE, D3D11_COLOR_WRITE_ENABLE_ALL); @@ -712,7 +714,8 @@ static void STDMETHODCALLTYPE d3d11_immediate_context_OMSetBlendState(ID3D11Devi return; }
- desc = &device->blend_state->desc; + wined3d_device_set_blend_state(device->wined3d_device, blend_state_impl->wined3d_state); + desc = &blend_state_impl->desc; wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_ALPHABLENDENABLE, desc->RenderTarget[0].BlendEnable); if (desc->RenderTarget[0].BlendEnable) @@ -1988,13 +1991,22 @@ static void STDMETHODCALLTYPE d3d11_immediate_context_OMGetBlendState(ID3D11Devi ID3D11BlendState **blend_state, FLOAT blend_factor[4], UINT *sample_mask) { struct d3d_device *device = device_from_immediate_ID3D11DeviceContext(iface); + struct wined3d_blend_state *wined3d_state; + struct d3d_blend_state *blend_state_impl;
TRACE("iface %p, blend_state %p, blend_factor %p, sample_mask %p.\n", iface, blend_state, blend_factor, sample_mask);
- if ((*blend_state = device->blend_state ? &device->blend_state->ID3D11BlendState_iface : NULL)) - ID3D11BlendState_AddRef(*blend_state); wined3d_mutex_lock(); + if ((wined3d_state = wined3d_device_get_blend_state(device->wined3d_device))) + { + blend_state_impl = wined3d_blend_state_get_parent(wined3d_state); + ID3D11BlendState_AddRef(*blend_state = &blend_state_impl->ID3D11BlendState_iface); + } + else + { + *blend_state = NULL; + } memcpy(blend_factor, device->blend_factor, 4 * sizeof(*blend_factor)); *sample_mask = wined3d_device_get_render_state(device->wined3d_device, WINED3D_RS_MULTISAMPLEMASK); wined3d_mutex_unlock(); diff --git a/dlls/d3d11/state.c b/dlls/d3d11/state.c index 47058a0a082e..a14c9d3cb40d 100644 --- a/dlls/d3d11/state.c +++ b/dlls/d3d11/state.c @@ -64,13 +64,15 @@ static ULONG STDMETHODCALLTYPE d3d11_blend_state_AddRef(ID3D11BlendState *iface)
TRACE("%p increasing refcount to %u.\n", state, refcount);
- return refcount; -} + if (refcount == 1) + { + ID3D11Device_AddRef(state->device); + wined3d_mutex_lock(); + wined3d_blend_state_incref(state->wined3d_state); + wined3d_mutex_unlock(); + }
-static void d3d_blend_state_cleanup(struct d3d_blend_state *state) -{ - wined3d_private_store_cleanup(&state->private_store); - ID3D11Device_Release(state->device); + return refcount; }
static ULONG STDMETHODCALLTYPE d3d11_blend_state_Release(ID3D11BlendState *iface) @@ -82,12 +84,13 @@ static ULONG STDMETHODCALLTYPE d3d11_blend_state_Release(ID3D11BlendState *iface
if (!refcount) { - struct d3d_device *device = impl_from_ID3D11Device(state->device); + ID3D11Device *device = state->device; + wined3d_mutex_lock(); - wine_rb_remove(&device->blend_states, &state->entry); - d3d_blend_state_cleanup(state); + wined3d_blend_state_decref(state->wined3d_state); wined3d_mutex_unlock(); - heap_free(state); + + ID3D11Device_Release(device); }
return refcount; @@ -288,24 +291,25 @@ static const struct ID3D10BlendState1Vtbl d3d10_blend_state_vtbl = d3d10_blend_state_GetDesc1, };
-static HRESULT d3d_blend_state_init(struct d3d_blend_state *state, struct d3d_device *device, - const D3D11_BLEND_DESC *desc) +static void STDMETHODCALLTYPE d3d_blend_state_wined3d_object_destroyed(void *parent) { - state->ID3D11BlendState_iface.lpVtbl = &d3d11_blend_state_vtbl; - state->ID3D10BlendState1_iface.lpVtbl = &d3d10_blend_state_vtbl; - state->refcount = 1; - wined3d_private_store_init(&state->private_store); - state->desc = *desc; - - state->device = &device->ID3D11Device_iface; - ID3D11Device_AddRef(state->device); + struct d3d_blend_state *state = parent; + struct d3d_device *device = impl_from_ID3D11Device(state->device);
- return S_OK; + wine_rb_remove(&device->blend_states, &state->entry); + wined3d_private_store_cleanup(&state->private_store); + heap_free(parent); }
+static const struct wined3d_parent_ops d3d_blend_state_wined3d_parent_ops = +{ + d3d_blend_state_wined3d_object_destroyed, +}; + HRESULT d3d_blend_state_create(struct d3d_device *device, const D3D11_BLEND_DESC *desc, struct d3d_blend_state **state) { + struct wined3d_blend_state_desc wined3d_desc; struct d3d_blend_state *object; struct wine_rb_entry *entry; D3D11_BLEND_DESC tmp_desc; @@ -337,9 +341,6 @@ HRESULT d3d_blend_state_create(struct d3d_device *device, const D3D11_BLEND_DESC tmp_desc.RenderTarget[i].RenderTargetWriteMask, i); }
- /* glSampleCoverage() */ - if (tmp_desc.AlphaToCoverageEnable) - FIXME("Ignoring AlphaToCoverageEnable %#x.\n", tmp_desc.AlphaToCoverageEnable); /* glEnableIndexedEXT(GL_BLEND, ...) */ if (tmp_desc.IndependentBlendEnable) FIXME("Per-rendertarget blend not implemented.\n"); @@ -363,24 +364,39 @@ HRESULT d3d_blend_state_create(struct d3d_device *device, const D3D11_BLEND_DESC return E_OUTOFMEMORY; }
- if (FAILED(hr = d3d_blend_state_init(object, device, &tmp_desc))) + object->ID3D11BlendState_iface.lpVtbl = &d3d11_blend_state_vtbl; + object->ID3D10BlendState1_iface.lpVtbl = &d3d10_blend_state_vtbl; + object->refcount = 1; + wined3d_private_store_init(&object->private_store); + object->desc = tmp_desc; + + if (wine_rb_put(&device->blend_states, &tmp_desc, &object->entry) == -1) { - WARN("Failed to initialize blend state, hr %#x.\n", hr); + ERR("Failed to insert blend state entry.\n"); + wined3d_private_store_cleanup(&object->private_store); heap_free(object); wined3d_mutex_unlock(); - return hr; + return E_FAIL; }
- if (wine_rb_put(&device->blend_states, desc, &object->entry) == -1) + wined3d_desc.alpha_to_coverage = desc->AlphaToCoverageEnable; + + /* We cannot fail after creating a wined3d_blend_state object. It + * would lead to double free. */ + if (FAILED(hr = wined3d_blend_state_create(device->wined3d_device, &wined3d_desc, + object, &d3d_blend_state_wined3d_parent_ops, &object->wined3d_state))) { - ERR("Failed to insert blend state entry.\n"); - d3d_blend_state_cleanup(object); + WARN("Failed to create wined3d blend state, hr %#x.\n", hr); + wined3d_private_store_cleanup(&object->private_store); + wine_rb_remove(&device->blend_states, &object->entry); heap_free(object); wined3d_mutex_unlock(); - return E_FAIL; + return hr; } wined3d_mutex_unlock();
+ ID3D11Device_AddRef(object->device = &device->ID3D11Device_iface); + TRACE("Created blend state %p.\n", object); *state = object;