From a26808a39c226fc0f168336becc97ed512029d52 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20D=C3=B6singer?= <stefan@codeweavers.com>
Date: Wed, 31 Jul 2013 23:06:27 +0200
Subject: wined3d: Destroy vertex declarations through the CS

---
 dlls/wined3d/cs.c                | 29 +++++++++++++++++++++++++++++
 dlls/wined3d/vertexdeclaration.c | 15 ++++++++-------
 dlls/wined3d/wined3d_private.h   |  4 ++++
 3 files changed, 41 insertions(+), 7 deletions(-)

diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index 8e48c55..38063d7 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -79,6 +79,7 @@ enum wined3d_cs_op
     WINED3D_CS_OP_UPDATE_TEXTURE,
     WINED3D_CS_OP_EVICT_RESOURCE,
     WINED3D_CS_OP_VIEW_DESTROY,
+    WINED3D_CS_OP_VDECL_DESTROY,
     WINED3D_CS_OP_STOP,
 };
 
@@ -456,6 +457,12 @@ struct wined3d_cs_view_destroy
     struct wined3d_rendertarget_view *view;
 };
 
+struct wined3d_cs_vertex_declaration_destroy
+{
+    enum wined3d_cs_op opcode;
+    struct wined3d_vertex_declaration *declaration;
+};
+
 static void wined3d_cs_mt_submit(struct wined3d_cs *cs, size_t size)
 {
     LONG new_val = (cs->queue.head + size) & (WINED3D_CS_QUEUE_SIZE - 1);
@@ -2251,6 +2258,27 @@ void wined3d_cs_emit_view_destroy(struct wined3d_cs *cs, struct wined3d_renderta
     cs->ops->submit(cs, sizeof(*op));
 }
 
+static UINT wined3d_cs_exec_vertex_declaration_destroy(struct wined3d_cs *cs, const void *data)
+{
+    const struct wined3d_cs_vertex_declaration_destroy *op = data;
+
+    wined3d_vertex_declaration_destroy(op->declaration);
+
+    return sizeof(*op);
+}
+
+void wined3d_cs_emit_vertex_declaration_destroy(struct wined3d_cs *cs,
+        struct wined3d_vertex_declaration *declaration)
+{
+    struct wined3d_cs_vertex_declaration_destroy *op;
+
+    op = cs->ops->require_space(cs, sizeof(*op));
+    op->opcode = WINED3D_CS_OP_VDECL_DESTROY;
+    op->declaration = declaration;
+
+    cs->ops->submit(cs, sizeof(*op));
+}
+
 static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) =
 {
     /* WINED3D_CS_OP_NOP                        */ wined3d_cs_exec_nop,
@@ -2308,6 +2336,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void
     /* WINED3D_CS_OP_UPDATE_TEXTURE             */ wined3d_cs_exec_update_texture,
     /* WINED3D_CS_OP_EVICT_RESOURCE             */ wined3d_cs_exec_evict_resource,
     /* WINED3D_CS_OP_VIEW_DESTROY               */ wined3d_cs_exec_view_destroy,
+    /* WINED3D_CS_OP_VDECL_DESTROY              */ wined3d_cs_exec_vertex_declaration_destroy,
 };
 
 static inline void *_wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size, BOOL prio)
diff --git a/dlls/wined3d/vertexdeclaration.c b/dlls/wined3d/vertexdeclaration.c
index 3f4d5e4..fc7a110 100644
--- a/dlls/wined3d/vertexdeclaration.c
+++ b/dlls/wined3d/vertexdeclaration.c
@@ -48,6 +48,12 @@ ULONG CDECL wined3d_vertex_declaration_incref(struct wined3d_vertex_declaration
     return refcount;
 }
 
+void wined3d_vertex_declaration_destroy(struct wined3d_vertex_declaration *declaration)
+{
+    HeapFree(GetProcessHeap(), 0, declaration->elements);
+    HeapFree(GetProcessHeap(), 0, declaration);
+}
+
 ULONG CDECL wined3d_vertex_declaration_decref(struct wined3d_vertex_declaration *declaration)
 {
     ULONG refcount = InterlockedDecrement(&declaration->ref);
@@ -56,14 +62,9 @@ ULONG CDECL wined3d_vertex_declaration_decref(struct wined3d_vertex_declaration
 
     if (!refcount)
     {
-        if (wined3d_settings.cs_multithreaded)
-        {
-            FIXME("Waiting for cs.\n");
-            declaration->device->cs->ops->finish(declaration->device->cs);
-        }
-        HeapFree(GetProcessHeap(), 0, declaration->elements);
+        const struct wined3d_device *device = declaration->device;
         declaration->parent_ops->wined3d_object_destroyed(declaration->parent);
-        HeapFree(GetProcessHeap(), 0, declaration);
+        wined3d_cs_emit_vertex_declaration_destroy(device->cs, declaration);
     }
 
     return refcount;
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 7d68448..5d3393c 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2499,6 +2499,8 @@ struct wined3d_vertex_declaration
     BOOL half_float_conv_needed;
 };
 
+void wined3d_vertex_declaration_destroy(struct wined3d_vertex_declaration *declaration) DECLSPEC_HIDDEN;
+
 struct wined3d_saved_states
 {
     DWORD transform[(HIGHEST_TRANSFORMSTATE >> 5) + 1];
@@ -2700,6 +2702,8 @@ void wined3d_cs_emit_buffer_invalidate_bo_range(struct wined3d_cs *cs,
         struct wined3d_buffer *buffer, UINT offset, UINT size) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_buffer_preload(struct wined3d_cs *cs, struct wined3d_buffer *buffer) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_view_destroy(struct wined3d_cs *cs, struct wined3d_rendertarget_view *view) DECLSPEC_HIDDEN;
+void wined3d_cs_emit_vertex_declaration_destroy(struct wined3d_cs *cs,
+        struct wined3d_vertex_declaration *declaration) DECLSPEC_HIDDEN;
 
 /* Direct3D terminology with little modifications. We do not have an issued state
  * because only the driver knows about it, but we have a created state because d3d
-- 
2.1.3

