From ef12b024a49a4390df02fad20938e04d5cfae35e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20D=C3=B6singer?= <stefan@codeweavers.com>
Date: Sat, 6 Jul 2013 21:54:45 +0200
Subject: wined3d: Destroy queries through the CS

---
 dlls/wined3d/cs.c              | 31 ++++++++++++++++++++
 dlls/wined3d/query.c           | 66 +++++++++++++++++++-----------------------
 dlls/wined3d/wined3d_private.h |  3 ++
 3 files changed, 64 insertions(+), 36 deletions(-)

diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index a7f7694..b2af05b 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -68,6 +68,7 @@ enum wined3d_cs_op
     WINED3D_CS_OP_RESOURCE_MAP,
     WINED3D_CS_OP_RESOURCE_UNMAP,
     WINED3D_CS_OP_QUERY_ISSUE,
+    WINED3D_CS_OP_QUERY_DESTROY,
     WINED3D_CS_OP_STOP,
 };
 
@@ -372,6 +373,12 @@ struct wined3d_cs_query_issue
     DWORD flags;
 };
 
+struct wined3d_cs_query_destroy
+{
+    enum wined3d_cs_op opcode;
+    struct wined3d_query *query;
+};
+
 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);
@@ -1726,6 +1733,29 @@ void wined3d_cs_emit_query_issue(struct wined3d_cs *cs, struct wined3d_query *qu
     cs->ops->submit(cs, sizeof(*op));
 }
 
+static UINT wined3d_cs_exec_query_destroy(struct wined3d_cs *cs, const void *data)
+{
+    const struct wined3d_cs_query_destroy *op = data;
+
+    if (!list_empty(&op->query->poll_list_entry))
+        list_remove(&op->query->poll_list_entry);
+
+    wined3d_query_destroy(op->query);
+
+    return sizeof(*op);
+}
+
+void wined3d_cs_emit_query_destroy(struct wined3d_cs *cs, struct wined3d_query *query)
+{
+    struct wined3d_cs_query_destroy *op;
+
+    op = cs->ops->require_space(cs, sizeof(*op));
+    op->opcode = WINED3D_CS_OP_QUERY_DESTROY;
+    op->query = query;
+
+    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,
@@ -1772,6 +1802,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void
     /* WINED3D_CS_OP_RESOURCE_MAP               */ wined3d_cs_exec_resource_map,
     /* WINED3D_CS_OP_RESOURCE_UNMAP             */ wined3d_cs_exec_resource_unmap,
     /* WINED3D_CS_OP_QUERY_ISSUE                */ wined3d_cs_exec_query_issue,
+    /* WINED3D_CS_OP_QUERY_DESTROY              */ wined3d_cs_exec_query_destroy,
 };
 
 static inline void *_wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size, BOOL prio)
diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c
index 621a9d7..f377eea 100644
--- a/dlls/wined3d/query.c
+++ b/dlls/wined3d/query.c
@@ -233,50 +233,44 @@ ULONG CDECL wined3d_query_incref(struct wined3d_query *query)
     return refcount;
 }
 
-ULONG CDECL wined3d_query_decref(struct wined3d_query *query)
+void wined3d_query_destroy(struct wined3d_query *query)
 {
-    ULONG refcount = InterlockedDecrement(&query->ref);
-
-    TRACE("%p decreasing refcount to %u.\n", query, refcount);
+    /* Queries are specific to the GL context that created them. Not
+     * deleting the query will obviously leak it, but that's still better
+     * than potentially deleting a different query with the same id in this
+     * context, and (still) leaking the actual query. */
+    if (query->type == WINED3D_QUERY_TYPE_EVENT)
+    {
+        struct wined3d_event_query *event_query = query->extendedData;
+        if (event_query) wined3d_event_query_destroy(event_query);
+    }
+    else if (query->type == WINED3D_QUERY_TYPE_OCCLUSION)
+    {
+        struct wined3d_occlusion_query *oq = query->extendedData;
 
-    if (!refcount)
+        if (oq->context) context_free_occlusion_query(oq);
+        HeapFree(GetProcessHeap(), 0, query->extendedData);
+    }
+    else if (query->type == WINED3D_QUERY_TYPE_TIMESTAMP)
     {
-        if (wined3d_settings.cs_multithreaded)
-        {
-            struct wined3d_device *device = query->device;
+        struct wined3d_timestamp_query *tq = query->extendedData;
 
-            FIXME("waiting for cs\n");
-            wined3d_cs_emit_glfinish(device->cs);
-            device->cs->ops->finish(device->cs);
-        }
+        if (tq->context)
+            context_free_timestamp_query(tq);
+        HeapFree(GetProcessHeap(), 0, query->extendedData);
+    }
 
-        /* Queries are specific to the GL context that created them. Not
-         * deleting the query will obviously leak it, but that's still better
-         * than potentially deleting a different query with the same id in this
-         * context, and (still) leaking the actual query. */
-        if (query->type == WINED3D_QUERY_TYPE_EVENT)
-        {
-            struct wined3d_event_query *event_query = query->extendedData;
-            if (event_query) wined3d_event_query_destroy(event_query);
-        }
-        else if (query->type == WINED3D_QUERY_TYPE_OCCLUSION)
-        {
-            struct wined3d_occlusion_query *oq = query->extendedData;
+    HeapFree(GetProcessHeap(), 0, query);
+}
 
-            if (oq->context) context_free_occlusion_query(oq);
-            HeapFree(GetProcessHeap(), 0, query->extendedData);
-        }
-        else if (query->type == WINED3D_QUERY_TYPE_TIMESTAMP)
-        {
-            struct wined3d_timestamp_query *tq = query->extendedData;
+ULONG CDECL wined3d_query_decref(struct wined3d_query *query)
+{
+    ULONG refcount = InterlockedDecrement(&query->ref);
 
-            if (tq->context)
-                context_free_timestamp_query(tq);
-            HeapFree(GetProcessHeap(), 0, query->extendedData);
-        }
+    TRACE("%p decreasing refcount to %u.\n", query, refcount);
 
-        HeapFree(GetProcessHeap(), 0, query);
-    }
+    if (!refcount)
+        wined3d_cs_emit_query_destroy(query->device->cs, query);
 
     return refcount;
 }
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index cf01a6a..28badf6 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2649,6 +2649,7 @@ void wined3d_cs_emit_query_issue(struct wined3d_cs *cs, struct wined3d_query *qu
         DWORD flags) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_query_get_data(struct wined3d_cs *cs, struct wined3d_query *query, void *data,
         UINT data_size, DWORD flags, HRESULT *ret) DECLSPEC_HIDDEN;
+void wined3d_cs_emit_query_destroy(struct wined3d_cs *cs, struct wined3d_query *query) 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
@@ -2683,6 +2684,8 @@ struct wined3d_query
     struct list              poll_list_entry;
 };
 
+void wined3d_query_destroy(struct wined3d_query *query) DECLSPEC_HIDDEN;
+
 /* TODO: Add tests and support for FLOAT16_4 POSITIONT, D3DCOLOR position, other
  * fixed function semantics as D3DCOLOR or FLOAT16 */
 enum wined3d_buffer_conversion_type
-- 
2.1.3

