Zebediah Figura : d3d11: Use wined3d depth/stencil state objects.

Alexandre Julliard julliard at winehq.org
Fri Sep 25 14:52:54 CDT 2020


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

Author: Zebediah Figura <z.figura12 at gmail.com>
Date:   Thu Sep 24 22:43:12 2020 -0500

d3d11: Use wined3d depth/stencil state objects.

Signed-off-by: Zebediah Figura <z.figura12 at gmail.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        | 23 ++++++++++----
 dlls/d3d11/state.c         | 75 +++++++++++++++++++++++++++++-----------------
 3 files changed, 66 insertions(+), 34 deletions(-)

diff --git a/dlls/d3d11/d3d11_private.h b/dlls/d3d11/d3d11_private.h
index cb2b9c3aed..3248285fcd 100644
--- a/dlls/d3d11/d3d11_private.h
+++ b/dlls/d3d11/d3d11_private.h
@@ -440,6 +440,7 @@ struct d3d_depthstencil_state
     LONG refcount;
 
     struct wined3d_private_store private_store;
+    struct wined3d_depth_stencil_state *wined3d_state;
     D3D11_DEPTH_STENCIL_DESC desc;
     struct wine_rb_entry entry;
     ID3D11Device2 *device;
@@ -549,7 +550,6 @@ struct d3d_device
     struct wine_rb_tree rasterizer_states;
     struct wine_rb_tree sampler_states;
 
-    struct d3d_depthstencil_state *depth_stencil_state;
     UINT stencil_ref;
 };
 
diff --git a/dlls/d3d11/device.c b/dlls/d3d11/device.c
index 2a68e02585..055e243a43 100644
--- a/dlls/d3d11/device.c
+++ b/dlls/d3d11/device.c
@@ -737,6 +737,7 @@ static void STDMETHODCALLTYPE d3d11_immediate_context_OMSetDepthStencilState(ID3
 {
     struct d3d_device *device = device_from_immediate_ID3D11DeviceContext1(iface);
     const D3D11_DEPTH_STENCILOP_DESC *front, *back;
+    struct d3d_depthstencil_state *state_impl;
     const D3D11_DEPTH_STENCIL_DESC *desc;
 
     TRACE("iface %p, depth_stencil_state %p, stencil_ref %u.\n",
@@ -744,14 +745,16 @@ static void STDMETHODCALLTYPE d3d11_immediate_context_OMSetDepthStencilState(ID3
 
     wined3d_mutex_lock();
     device->stencil_ref = stencil_ref;
-    if (!(device->depth_stencil_state = unsafe_impl_from_ID3D11DepthStencilState(depth_stencil_state)))
+    if (!(state_impl = unsafe_impl_from_ID3D11DepthStencilState(depth_stencil_state)))
     {
+        wined3d_device_set_depth_stencil_state(device->wined3d_device, NULL);
         set_default_depth_stencil_state(device->wined3d_device);
         wined3d_mutex_unlock();
         return;
     }
 
-    desc = &device->depth_stencil_state->desc;
+    wined3d_device_set_depth_stencil_state(device->wined3d_device, state_impl->wined3d_state);
+    desc = &state_impl->desc;
 
     front = &desc->FrontFace;
     back = &desc->BackFace;
@@ -1904,14 +1907,24 @@ static void STDMETHODCALLTYPE d3d11_immediate_context_OMGetDepthStencilState(ID3
         ID3D11DepthStencilState **depth_stencil_state, UINT *stencil_ref)
 {
     struct d3d_device *device = device_from_immediate_ID3D11DeviceContext1(iface);
+    struct wined3d_depth_stencil_state *wined3d_state;
+    struct d3d_depthstencil_state *state_impl;
 
     TRACE("iface %p, depth_stencil_state %p, stencil_ref %p.\n",
             iface, depth_stencil_state, stencil_ref);
 
-    if ((*depth_stencil_state = device->depth_stencil_state
-            ? &device->depth_stencil_state->ID3D11DepthStencilState_iface : NULL))
-        ID3D11DepthStencilState_AddRef(*depth_stencil_state);
+    wined3d_mutex_lock();
+    if ((wined3d_state = wined3d_device_get_depth_stencil_state(device->wined3d_device)))
+    {
+        state_impl = wined3d_depth_stencil_state_get_parent(wined3d_state);
+        ID3D11DepthStencilState_AddRef(*depth_stencil_state = &state_impl->ID3D11DepthStencilState_iface);
+    }
+    else
+    {
+        *depth_stencil_state = NULL;
+    }
     *stencil_ref = device->stencil_ref;
+    wined3d_mutex_unlock();
 }
 
 static void STDMETHODCALLTYPE d3d11_immediate_context_SOGetTargets(ID3D11DeviceContext1 *iface,
diff --git a/dlls/d3d11/state.c b/dlls/d3d11/state.c
index 32ef44091c..5d4c352659 100644
--- a/dlls/d3d11/state.c
+++ b/dlls/d3d11/state.c
@@ -493,13 +493,15 @@ static ULONG STDMETHODCALLTYPE d3d11_depthstencil_state_AddRef(ID3D11DepthStenci
 
     TRACE("%p increasing refcount to %u.\n", state, refcount);
 
-    return refcount;
-}
+    if (refcount == 1)
+    {
+        ID3D11Device2_AddRef(state->device);
+        wined3d_mutex_lock();
+        wined3d_depth_stencil_state_incref(state->wined3d_state);
+        wined3d_mutex_unlock();
+    }
 
-static void d3d_depthstencil_state_cleanup(struct d3d_depthstencil_state *state)
-{
-    wined3d_private_store_cleanup(&state->private_store);
-    ID3D11Device2_Release(state->device);
+    return refcount;
 }
 
 static ULONG STDMETHODCALLTYPE d3d11_depthstencil_state_Release(ID3D11DepthStencilState *iface)
@@ -511,12 +513,12 @@ static ULONG STDMETHODCALLTYPE d3d11_depthstencil_state_Release(ID3D11DepthStenc
 
     if (!refcount)
     {
-        struct d3d_device *device = impl_from_ID3D11Device2(state->device);
+        ID3D11Device2 *device = state->device;
+
         wined3d_mutex_lock();
-        wine_rb_remove(&device->depthstencil_states, &state->entry);
-        d3d_depthstencil_state_cleanup(state);
+        wined3d_depth_stencil_state_decref(state->wined3d_state);
         wined3d_mutex_unlock();
-        heap_free(state);
+        ID3D11Device2_Release(device);
     }
 
     return refcount;
@@ -695,23 +697,25 @@ static const struct ID3D10DepthStencilStateVtbl d3d10_depthstencil_state_vtbl =
     d3d10_depthstencil_state_GetDesc,
 };
 
-static HRESULT d3d_depthstencil_state_init(struct d3d_depthstencil_state *state, struct d3d_device *device,
-        const D3D11_DEPTH_STENCIL_DESC *desc)
+static void STDMETHODCALLTYPE d3d_depthstencil_state_wined3d_object_destroyed(void *parent)
 {
-    state->ID3D11DepthStencilState_iface.lpVtbl = &d3d11_depthstencil_state_vtbl;
-    state->ID3D10DepthStencilState_iface.lpVtbl = &d3d10_depthstencil_state_vtbl;
-    state->refcount = 1;
-    wined3d_private_store_init(&state->private_store);
-    state->desc = *desc;
-
-    ID3D11Device2_AddRef(state->device = &device->ID3D11Device2_iface);
+    struct d3d_depthstencil_state *state = parent;
+    struct d3d_device *device = impl_from_ID3D11Device2(state->device);
 
-    return S_OK;
+    wine_rb_remove(&device->depthstencil_states, &state->entry);
+    wined3d_private_store_cleanup(&state->private_store);
+    heap_free(parent);
 }
 
+static const struct wined3d_parent_ops d3d_depthstencil_state_wined3d_parent_ops =
+{
+    d3d_depthstencil_state_wined3d_object_destroyed,
+};
+
 HRESULT d3d_depthstencil_state_create(struct d3d_device *device, const D3D11_DEPTH_STENCIL_DESC *desc,
         struct d3d_depthstencil_state **state)
 {
+    struct wined3d_depth_stencil_state_desc wined3d_desc;
     struct d3d_depthstencil_state *object;
     D3D11_DEPTH_STENCIL_DESC tmp_desc;
     struct wine_rb_entry *entry;
@@ -775,25 +779,40 @@ HRESULT d3d_depthstencil_state_create(struct d3d_device *device, const D3D11_DEP
         return E_OUTOFMEMORY;
     }
 
-    if (FAILED(hr = d3d_depthstencil_state_init(object, device, &tmp_desc)))
+    object->ID3D11DepthStencilState_iface.lpVtbl = &d3d11_depthstencil_state_vtbl;
+    object->ID3D10DepthStencilState_iface.lpVtbl = &d3d10_depthstencil_state_vtbl;
+    object->refcount = 1;
+    wined3d_private_store_init(&object->private_store);
+    object->desc = tmp_desc;
+
+    if (wine_rb_put(&device->depthstencil_states, &tmp_desc, &object->entry) == -1)
     {
-        WARN("Failed to initialize depthstencil state, hr %#x.\n", hr);
+        ERR("Failed to insert depth/stencil 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->depthstencil_states, &tmp_desc, &object->entry) == -1)
+    wined3d_desc.depth = desc->DepthEnable;
+
+    /* We cannot fail after creating a wined3d_depth_stencil_state object. It
+     * would lead to double free. */
+    if (FAILED(hr = wined3d_depth_stencil_state_create(device->wined3d_device, &wined3d_desc,
+            object, &d3d_depthstencil_state_wined3d_parent_ops, &object->wined3d_state)))
     {
-        ERR("Failed to insert depthstencil state entry.\n");
-        d3d_depthstencil_state_cleanup(object);
+        WARN("Failed to create wined3d depth/stencil state, hr %#x.\n", hr);
+        wined3d_private_store_cleanup(&object->private_store);
+        wine_rb_remove(&device->depthstencil_states, &object->entry);
         heap_free(object);
         wined3d_mutex_unlock();
-        return E_FAIL;
+        return hr;
     }
     wined3d_mutex_unlock();
 
-    TRACE("Created depthstencil state %p.\n", object);
+    ID3D11Device2_AddRef(object->device = &device->ID3D11Device2_iface);
+
+    TRACE("Created depth/stencil state %p.\n", object);
     *state = object;
 
     return S_OK;




More information about the wine-cvs mailing list