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

---
 dlls/wined3d/buffer.c          |  3 +++
 dlls/wined3d/cs.c              | 28 ++++++++++++++++++++++++++++
 dlls/wined3d/resource.c        | 15 ++++++++++-----
 dlls/wined3d/surface.c         |  5 +++++
 dlls/wined3d/texture.c         |  4 ++++
 dlls/wined3d/volume.c          |  3 +++
 dlls/wined3d/wined3d_private.h |  3 +++
 7 files changed, 56 insertions(+), 5 deletions(-)

diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c
index fc65d3a..d968dcb 100644
--- a/dlls/wined3d/buffer.c
+++ b/dlls/wined3d/buffer.c
@@ -570,6 +570,9 @@ ULONG CDECL wined3d_buffer_decref(struct wined3d_buffer *buffer)
         }
 
         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);
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index c00d1d3..6edd5e3 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -82,6 +82,7 @@ enum wined3d_cs_op
     WINED3D_CS_OP_VDECL_DESTROY,
     WINED3D_CS_OP_SHADER_CLEANUP,
     WINED3D_CS_OP_CREATE_VBO,
+    WINED3D_CS_OP_RESOURCE_CLEANUP,
     WINED3D_CS_OP_STOP,
 };
 
@@ -477,6 +478,12 @@ struct wined3d_cs_create_vbo
     struct wined3d_buffer *buffer;
 };
 
+struct wined3d_cs_resource_cleanup
+{
+    enum wined3d_cs_op opcode;
+    struct wined3d_resource *resource;
+};
+
 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);
@@ -2338,6 +2345,26 @@ void wined3d_cs_emit_create_vbo(struct wined3d_cs *cs, struct wined3d_buffer *bu
     cs->ops->finish_prio(cs);
 }
 
+static UINT wined3d_cs_exec_resource_cleanup(struct wined3d_cs *cs, const void *data)
+{
+    const struct wined3d_cs_resource_cleanup *op = data;
+
+    wined3d_resource_cleanup_cs(op->resource);
+
+    return sizeof(*op);
+}
+
+void wined3d_cs_emit_resource_cleanup(struct wined3d_cs *cs, struct wined3d_resource *resource)
+{
+    struct wined3d_cs_resource_cleanup *op;
+
+    op = cs->ops->require_space(cs, sizeof(*op));
+    op->opcode = WINED3D_CS_OP_RESOURCE_CLEANUP;
+    op->resource = resource;
+
+    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,
@@ -2398,6 +2425,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void
     /* WINED3D_CS_OP_VDECL_DESTROY              */ wined3d_cs_exec_vertex_declaration_destroy,
     /* 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,
 };
 
 static inline void *_wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size, BOOL prio)
diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c
index ef0b213..dd21986 100644
--- a/dlls/wined3d/resource.c
+++ b/dlls/wined3d/resource.c
@@ -157,6 +157,15 @@ void wined3d_resource_free_bo(struct wined3d_resource *resource)
     context_release(context);
 }
 
+void wined3d_resource_cleanup_cs(struct wined3d_resource *resource)
+{
+    if (resource->buffer)
+        wined3d_resource_free_bo(resource);
+
+    wined3d_resource_free_sysmem(resource);
+    resource->map_heap_memory = NULL;
+}
+
 void resource_cleanup(struct wined3d_resource *resource)
 {
     const struct wined3d *d3d = resource->device->wined3d;
@@ -169,11 +178,7 @@ void resource_cleanup(struct wined3d_resource *resource)
         adapter_adjust_memory(resource->device->adapter, (INT64)0 - resource->size);
     }
 
-    if (resource->buffer)
-        wined3d_resource_free_bo(resource);
-
-    wined3d_resource_free_sysmem(resource);
-    resource->map_heap_memory = NULL;
+    wined3d_cs_emit_resource_cleanup(resource->device->cs, resource);
 
     device_resource_released(resource->device, resource);
 }
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index 1d777e2..4a1cf30 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -101,9 +101,12 @@ static void surface_cleanup(struct wined3d_surface *surface)
 
 void wined3d_surface_destroy(struct wined3d_surface *surface)
 {
+    struct wined3d_device *device = surface->resource.device;
     TRACE("surface %p.\n", surface);
 
     surface_cleanup(surface);
+    if (wined3d_settings.cs_multithreaded)
+        device->cs->ops->finish(device->cs);
     surface->resource.parent_ops->wined3d_object_destroyed(surface->resource.parent);
     HeapFree(GetProcessHeap(), 0, surface);
 }
@@ -5321,6 +5324,8 @@ static HRESULT surface_init(struct wined3d_surface *surface, struct wined3d_text
     {
         ERR("Private setup failed, hr %#x.\n", hr);
         surface_cleanup(surface);
+        if (wined3d_settings.cs_multithreaded)
+            surface->resource.device->cs->ops->finish(surface->resource.device->cs);
         return hr;
     }
 
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index ea8589a..f7988e5 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -74,6 +74,8 @@ static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struc
     {
         ERR("Failed to allocate sub-resource array.\n");
         resource_cleanup(&texture->resource);
+        if (wined3d_settings.cs_multithreaded)
+            texture->resource.device->cs->ops->finish(texture->resource.device->cs);
         return E_OUTOFMEMORY;
     }
 
@@ -153,6 +155,8 @@ static void wined3d_texture_cleanup(struct wined3d_texture *texture)
     wined3d_texture_unload_gl_texture(texture);
     HeapFree(GetProcessHeap(), 0, texture->sub_resources);
     resource_cleanup(&texture->resource);
+    if (wined3d_settings.cs_multithreaded)
+        texture->resource.device->cs->ops->finish(texture->resource.device->cs);
 }
 
 void wined3d_texture_set_swapchain(struct wined3d_texture *texture, struct wined3d_swapchain *swapchain)
diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c
index 34b72d1..218118d 100644
--- a/dlls/wined3d/volume.c
+++ b/dlls/wined3d/volume.c
@@ -291,9 +291,12 @@ void wined3d_volume_load(struct wined3d_volume *volume, struct wined3d_context *
 
 void wined3d_volume_destroy(struct wined3d_volume *volume)
 {
+    struct wined3d_device *device = volume->resource.device;
     TRACE("volume %p.\n", volume);
 
     resource_cleanup(&volume->resource);
+    if (wined3d_settings.cs_multithreaded)
+        device->cs->ops->finish(device->cs);
     volume->resource.parent_ops->wined3d_object_destroyed(volume->resource.parent);
     HeapFree(GetProcessHeap(), 0, volume);
 }
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 74e059c..f4c269c 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2163,6 +2163,7 @@ void wined3d_resource_changed(struct wined3d_resource *resource,
         struct wined3d_gl_bo *swap_buffer, void *swap_heap_memory) DECLSPEC_HIDDEN;
 BOOL wined3d_resource_check_block_align(const struct wined3d_resource *resource,
         const struct wined3d_box *box) DECLSPEC_HIDDEN;
+void wined3d_resource_cleanup_cs(struct wined3d_resource *resource) DECLSPEC_HIDDEN;
 void wined3d_resource_free_bo(struct wined3d_resource *resource) DECLSPEC_HIDDEN;
 void wined3d_resource_free_sysmem(struct wined3d_resource *resource) DECLSPEC_HIDDEN;
 BYTE *wined3d_resource_get_map_ptr(const struct wined3d_resource *resource,
@@ -2706,6 +2707,8 @@ void wined3d_cs_emit_vertex_declaration_destroy(struct wined3d_cs *cs,
         struct wined3d_vertex_declaration *declaration) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_shader_cleanup(struct wined3d_cs *cs, struct wined3d_shader *shader) DECLSPEC_HIDDEN;
 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;
 
 /* 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

