From 0f90bc90dacb7dbd0169a19bf31cd39fd7e966fa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20D=C3=B6singer?= <stefan@codeweavers.com>
Date: Sun, 6 Oct 2013 16:12:24 +0200
Subject: wined3d: Clean up surfaces through the cs.

---
 dlls/wined3d/cs.c              | 28 ++++++++++++++++++++++++++++
 dlls/wined3d/surface.c         | 37 ++++++++++++++++---------------------
 dlls/wined3d/wined3d_private.h |  2 ++
 3 files changed, 46 insertions(+), 21 deletions(-)

diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index bcc88a2..819e7e2 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -84,6 +84,7 @@ enum wined3d_cs_op
     WINED3D_CS_OP_RESOURCE_CLEANUP,
     WINED3D_CS_OP_BUFFER_CLEANUP,
     WINED3D_CS_OP_VOLUME_CLEANUP,
+    WINED3D_CS_OP_SURFACE_CLEANUP,
     WINED3D_CS_OP_STOP,
 };
 
@@ -491,6 +492,12 @@ struct wined3d_cs_volume_cleanup
     struct wined3d_volume *volume;
 };
 
+struct wined3d_cs_surface_cleanup
+{
+    enum wined3d_cs_op opcode;
+    struct wined3d_surface *surface;
+};
+
 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);
@@ -2436,6 +2443,26 @@ void wined3d_cs_emit_volume_cleanup(struct wined3d_cs *cs, struct wined3d_volume
     cs->ops->submit(cs, sizeof(*op));
 }
 
+static UINT wined3d_cs_exec_surface_cleanup(struct wined3d_cs *cs, const void *data)
+{
+    const struct wined3d_cs_surface_cleanup *op = data;
+
+    wined3d_surface_cleanup_cs(op->surface);
+
+    return sizeof(*op);
+}
+
+void wined3d_cs_emit_surface_cleanup(struct wined3d_cs *cs, struct wined3d_surface *surface)
+{
+    struct wined3d_cs_surface_cleanup *op;
+
+    op = cs->ops->require_space(cs, sizeof(*op));
+    op->opcode = WINED3D_CS_OP_SURFACE_CLEANUP;
+    op->surface = surface;
+
+    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,
@@ -2498,6 +2525,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void
     /* WINED3D_CS_OP_RESOURCE_CLEANUP           */ wined3d_cs_exec_resource_cleanup,
     /* WINED3D_CS_OP_BUFFER_CLEANUP             */ wined3d_cs_exec_buffer_cleanup,
     /* WINED3D_CS_OP_VOLUME_CLEANUP             */ wined3d_cs_exec_volume_cleanup,
+    /* WINED3D_CS_OP_SURFACE_CLEANUP            */ wined3d_cs_exec_surface_cleanup,
 };
 
 static inline void *_wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size, BOOL prio)
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index 8ea999a..7ceb86a 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -36,20 +36,10 @@ WINE_DECLARE_DEBUG_CHANNEL(d3d);
 
 #define MAXLOCKCOUNT 50 /* After this amount of locks do not free the sysmem copy. */
 
-static void surface_cleanup(struct wined3d_surface *surface)
-{
-    struct wined3d_surface *overlay, *cur;
 
-    TRACE("surface %p.\n", surface);
-
-    if (wined3d_settings.cs_multithreaded)
-    {
-        FIXME("Waiting for cs.\n");
-        surface->resource.device->cs->ops->finish(surface->resource.device->cs);
-    }
-
-    if (surface->resource.buffer || surface->rb_multisample
-            || surface->rb_resolved || !list_empty(&surface->renderbuffers))
+void wined3d_surface_cleanup_cs(struct wined3d_surface *surface)
+{
+    if (surface->rb_multisample || surface->rb_resolved || !list_empty(&surface->renderbuffers))
     {
         struct wined3d_renderbuffer_entry *entry, *entry2;
         const struct wined3d_gl_info *gl_info;
@@ -87,6 +77,16 @@ static void surface_cleanup(struct wined3d_surface *surface)
         surface->resource.bitmap_data = NULL;
     }
 
+    TRACE("Destroyed surface %p.\n", surface);
+    HeapFree(GetProcessHeap(), 0, surface);
+}
+
+static void surface_cleanup(struct wined3d_surface *surface)
+{
+    struct wined3d_surface *overlay, *cur;
+
+    TRACE("surface %p.\n", surface);
+
     if (surface->overlay_dest)
         list_remove(&surface->overlay_entry);
 
@@ -97,18 +97,15 @@ static void surface_cleanup(struct wined3d_surface *surface)
     }
 
     resource_cleanup(&surface->resource);
+    wined3d_cs_emit_surface_cleanup(surface->resource.device->cs, 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);
+    surface_cleanup(surface);
 }
 
 void surface_get_drawable_size(const struct wined3d_surface *surface, const struct wined3d_context *context,
@@ -5077,8 +5074,6 @@ 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;
     }
 
@@ -5121,7 +5116,7 @@ HRESULT wined3d_surface_create(struct wined3d_texture *container, const struct w
     if (FAILED(hr = surface_init(object, container, desc, target, level, layer, flags)))
     {
         WARN("Failed to initialize surface, returning %#x.\n", hr);
-        HeapFree(GetProcessHeap(), 0, object);
+        /* The command stream takes care of freeing the memory. */
         return hr;
     }
 
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 9739437..263e089 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2662,6 +2662,7 @@ void wined3d_surface_upload_data(struct wined3d_surface *surface, const struct w
 void surface_blt_ugly(struct wined3d_surface *dst_surface, const RECT *dst_rect_in,
         struct wined3d_surface *src_surface, const RECT *src_rect_in, DWORD flags,
         const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN;
+void wined3d_surface_cleanup_cs(struct wined3d_surface *surface) DECLSPEC_HIDDEN;
 
 void draw_textured_quad(const struct wined3d_surface *src_surface, struct wined3d_context *context,
         const RECT *src_rect, const RECT *dst_rect, enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN;
@@ -2920,6 +2921,7 @@ 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;
 void wined3d_cs_emit_volume_cleanup(struct wined3d_cs *cs, struct wined3d_volume *volume) DECLSPEC_HIDDEN;
+void wined3d_cs_emit_surface_cleanup(struct wined3d_cs *cs, struct wined3d_surface *surface) 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.7.1

