=?UTF-8?Q?J=C3=B3zef=20Kucia=20?=: d3d11: Use wined3d blend state objects.

Alexandre Julliard julliard at winehq.org
Thu Feb 8 15:33:08 CST 2018


Module: wine
Branch: master
Commit: dec8b87c9450d2d458ed2b005d3b04c6a59f6414
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=dec8b87c9450d2d458ed2b005d3b04c6a59f6414

Author: Józef Kucia <jkucia at codeweavers.com>
Date:   Thu Feb  8 15:22:45 2018 +0100

d3d11: Use wined3d blend state objects.

Signed-off-by: Józef Kucia <jkucia at codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 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 1030b96..52496d8 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 b14c386..f9db15f 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 47058a0..a14c9d3 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;
 




More information about the wine-cvs mailing list