From 1ddba156e6aa9f96e9e05b18b1324183884a2596 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20D=C3=B6singer?= <stefan@codeweavers.com>
Date: Wed, 2 Oct 2013 22:50:08 +0200
Subject: wined3d: Clean up buffer resource data through the CS.

---
 dlls/wined3d/buffer.c          | 39 ++++++++++++++++++++-------------------
 dlls/wined3d/cs.c              | 28 ++++++++++++++++++++++++++++
 dlls/wined3d/wined3d_private.h |  2 ++
 3 files changed, 50 insertions(+), 19 deletions(-)

diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c
index e248ca9..12a1ca0 100644
--- a/dlls/wined3d/buffer.c
+++ b/dlls/wined3d/buffer.c
@@ -545,37 +545,38 @@ static void buffer_unload(struct wined3d_resource *resource)
     resource_unload(resource);
 }
 
+void wined3d_buffer_cleanup_cs(struct wined3d_buffer *buffer)
+{
+    struct wined3d_context *context;
+    struct wined3d_device *device = buffer->resource.device;
+
+    if (buffer->buffer_object)
+    {
+        context = context_acquire(device, NULL);
+        delete_gl_buffer(buffer, context->gl_info);
+        context_release(context);
+
+        HeapFree(GetProcessHeap(), 0, buffer->conversion_map);
+    }
+
+    HeapFree(GetProcessHeap(), 0, buffer->maps);
+    HeapFree(GetProcessHeap(), 0, buffer);
+}
+
 ULONG CDECL wined3d_buffer_decref(struct wined3d_buffer *buffer)
 {
     ULONG refcount = InterlockedDecrement(&buffer->resource.ref);
-    struct wined3d_context *context;
 
     TRACE("%p decreasing refcount to %u.\n", buffer, refcount);
 
     if (!refcount)
     {
-        if (wined3d_settings.cs_multithreaded)
-        {
-            FIXME("Waiting for cs.\n");
-            buffer->resource.device->cs->ops->finish(buffer->resource.device->cs);
-        }
-
-        if (buffer->buffer_object)
-        {
-            context = context_acquire(buffer->resource.device, NULL);
-            delete_gl_buffer(buffer, context->gl_info);
-            context_release(context);
-
-            HeapFree(GetProcessHeap(), 0, buffer->conversion_map);
-        }
+        struct wined3d_device *device = buffer->resource.device;
 
         resource_cleanup(&buffer->resource);
-        if (wined3d_settings.cs_multithreaded)
-            buffer->resource.device->cs->ops->finish(buffer->resource.device->cs);
 
         buffer->resource.parent_ops->wined3d_object_destroyed(buffer->resource.parent);
-        HeapFree(GetProcessHeap(), 0, buffer->maps);
-        HeapFree(GetProcessHeap(), 0, buffer);
+        wined3d_cs_emit_buffer_cleanup(device->cs, buffer);
     }
 
     return refcount;
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index 4a42ca3..f64c43d 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -84,6 +84,7 @@ enum wined3d_cs_op
     WINED3D_CS_OP_SHADER_CLEANUP,
     WINED3D_CS_OP_CREATE_VBO,
     WINED3D_CS_OP_RESOURCE_CLEANUP,
+    WINED3D_CS_OP_BUFFER_CLEANUP,
     WINED3D_CS_OP_STOP,
 };
 
@@ -494,6 +495,12 @@ struct wined3d_cs_resource_cleanup
     struct wined3d_resource *resource;
 };
 
+struct wined3d_cs_buffer_cleanup
+{
+    enum wined3d_cs_op opcode;
+    struct wined3d_buffer *buffer;
+};
+
 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);
@@ -2479,6 +2486,26 @@ void wined3d_cs_emit_resource_cleanup(struct wined3d_cs *cs, struct wined3d_reso
     cs->ops->submit(cs, sizeof(*op));
 }
 
+static UINT wined3d_cs_exec_buffer_cleanup(struct wined3d_cs *cs, const void *data)
+{
+    const struct wined3d_cs_buffer_cleanup *op = data;
+
+    wined3d_buffer_cleanup_cs(op->buffer);
+
+    return sizeof(*op);
+}
+
+void wined3d_cs_emit_buffer_cleanup(struct wined3d_cs *cs, struct wined3d_buffer *buffer)
+{
+    struct wined3d_cs_buffer_cleanup *op;
+
+    op = cs->ops->require_space(cs, sizeof(*op));
+    op->opcode = WINED3D_CS_OP_BUFFER_CLEANUP;
+    op->buffer = buffer;
+
+    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,
@@ -2541,6 +2568,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void
     /* WINED3D_CS_OP_SHADER_CLEANUP             */ wined3d_cs_exec_shader_cleanup,
     /* WINED3D_CS_OP_CREATE_VBO                 */ wined3d_cs_exec_create_vbo,
     /* WINED3D_CS_OP_RESOURCE_CLEANUP           */ wined3d_cs_exec_resource_cleanup,
+    /* WINED3D_CS_OP_BUFFER_CLEANUP             */ wined3d_cs_exec_buffer_cleanup,
 };
 
 static inline void *_wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size, BOOL prio)
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index e80859a..83c94c5 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2826,6 +2826,7 @@ void wined3d_cs_emit_shader_cleanup(struct wined3d_cs *cs, struct wined3d_shader
 void wined3d_cs_emit_create_vbo(struct wined3d_cs *cs, struct wined3d_buffer *buffer) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_resource_cleanup(struct wined3d_cs *cs,
         struct wined3d_resource *resource) DECLSPEC_HIDDEN;
+void wined3d_cs_emit_buffer_cleanup(struct wined3d_cs *cs, struct wined3d_buffer *buffer) 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
@@ -2916,6 +2917,7 @@ void buffer_invalidate_bo_range(struct wined3d_buffer *This, UINT offset, UINT s
 void buffer_swap_mem(struct wined3d_buffer *buffer, BYTE *mem) DECLSPEC_HIDDEN;
 void buffer_create_buffer_object(struct wined3d_buffer *This,
         struct wined3d_context *context) DECLSPEC_HIDDEN;
+void wined3d_buffer_cleanup_cs(struct wined3d_buffer *buffer) DECLSPEC_HIDDEN;
 HRESULT wined3d_buffer_upload_data(struct wined3d_buffer *buffer,
         const struct wined3d_box *box, const void *data) DECLSPEC_HIDDEN;
 
-- 
2.6.4

