From c0687b2ce9d0056bce2fc514f25baa20ab834f1e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20D=C3=B6singer?= <stefan@codeweavers.com>
Date: Sat, 6 Jul 2013 18:26:11 +0200
Subject: wined3d: Add query support to the command stream

---
 dlls/wined3d/cs.c              | 73 ++++++++++++++++++++++++++++++++++++++++++
 dlls/wined3d/query.c           |  8 +++--
 dlls/wined3d/wined3d_private.h |  4 +++
 3 files changed, 83 insertions(+), 2 deletions(-)

diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index d35f114..e4d60d8 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -67,6 +67,8 @@ enum wined3d_cs_op
     WINED3D_CS_OP_CLEAR_RTV,
     WINED3D_CS_OP_RESOURCE_MAP,
     WINED3D_CS_OP_RESOURCE_UNMAP,
+    WINED3D_CS_OP_QUERY_ISSUE,
+    WINED3D_CS_OP_QUERY_GET_DATA,
     WINED3D_CS_OP_STOP,
 };
 
@@ -364,6 +366,23 @@ struct wined3d_cs_skip
     DWORD size;
 };
 
+struct wined3d_cs_query_issue
+{
+    enum wined3d_cs_op opcode;
+    struct wined3d_query *query;
+    DWORD flags;
+};
+
+struct wined3d_cs_query_get_data
+{
+    enum wined3d_cs_op opcode;
+    struct wined3d_query *query;
+    void *data;
+    UINT data_size;
+    DWORD flags;
+    HRESULT *ret;
+};
+
 static void wined3d_cs_submit(struct wined3d_cs *cs, size_t size)
 {
     LONG new_val = (cs->queue.head + size) & (WINED3D_CS_QUEUE_SIZE - 1);
@@ -1683,6 +1702,58 @@ void wined3d_cs_emit_resource_unmap(struct wined3d_cs *cs, struct wined3d_resour
     cs->ops->submit(cs, sizeof(*op));
 }
 
+static UINT wined3d_cs_exec_query_issue(struct wined3d_cs *cs, const void *data)
+{
+    const struct wined3d_cs_query_issue *op = data;
+
+    op->query->query_ops->query_issue(op->query, op->flags);
+
+    return sizeof(*op);
+}
+
+void wined3d_cs_emit_query_issue(struct wined3d_cs *cs, struct wined3d_query *query, DWORD flags)
+{
+    struct wined3d_cs_query_issue *op;
+
+    op = cs->ops->require_space(cs, sizeof(*op));
+    op->opcode = WINED3D_CS_OP_QUERY_ISSUE;
+    op->query = query;
+    op->flags = flags;
+
+    cs->ops->submit(cs, sizeof(*op));
+}
+
+static UINT wined3d_cs_exec_query_get_data(struct wined3d_cs *cs, const void *data)
+{
+    const struct wined3d_cs_query_get_data *op = data;
+    struct wined3d_query *query = op->query;
+
+    *op->ret = query->query_ops->query_get_data(query, op->data, op->data_size, op->flags);
+
+    return sizeof(*op);
+}
+
+void wined3d_cs_emit_query_get_data(struct wined3d_cs *cs, struct wined3d_query *query, void *data,
+        UINT data_size, DWORD flags, HRESULT *ret)
+{
+    struct wined3d_cs_query_get_data *op;
+
+    op = cs->ops->require_space(cs, sizeof(*op));
+    op->opcode = WINED3D_CS_OP_QUERY_GET_DATA;
+    op->query = query;
+    op->data = data;
+    op->data_size = data_size;
+    op->flags = flags;
+    op->ret = ret;
+
+    cs->ops->submit(cs, sizeof(*op));
+
+    if (wined3d_settings.cs_multithreaded)
+        FIXME("Query handling is not particularly fast yet\n");
+
+    cs->ops->finish(cs);
+}
+
 static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) =
 {
     /* WINED3D_CS_OP_NOP                        */ wined3d_cs_exec_nop,
@@ -1728,6 +1799,8 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void
     /* WINED3D_CS_OP_CLEAR_RTV                  */ wined3d_cs_exec_clear_rtv,
     /* 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_GET_DATA             */ wined3d_cs_exec_query_get_data,
 };
 
 static void *wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size)
diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c
index 3de4282..6436bd7 100644
--- a/dlls/wined3d/query.c
+++ b/dlls/wined3d/query.c
@@ -275,10 +275,14 @@ ULONG CDECL wined3d_query_decref(struct wined3d_query *query)
 HRESULT CDECL wined3d_query_get_data(struct wined3d_query *query,
         void *data, UINT data_size, DWORD flags)
 {
+    HRESULT hr;
     TRACE("query %p, data %p, data_size %u, flags %#x.\n",
             query, data, data_size, flags);
 
-    return query->query_ops->query_get_data(query, data, data_size, flags);
+    wined3d_cs_emit_query_get_data(query->device->cs, query, data, data_size,
+            flags, &hr);
+
+    return hr;
 }
 
 UINT CDECL wined3d_query_get_data_size(const struct wined3d_query *query)
@@ -292,7 +296,7 @@ HRESULT CDECL wined3d_query_issue(struct wined3d_query *query, DWORD flags)
 {
     TRACE("query %p, flags %#x.\n", query, flags);
 
-    query->query_ops->query_issue(query, flags);
+    wined3d_cs_emit_query_issue(query->device->cs, query, flags);
     return WINED3D_OK;
 }
 
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index ff05a97..6175f13 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2639,6 +2639,10 @@ void wined3d_cs_emit_clear_rtv(struct wined3d_cs *cs, struct wined3d_rendertarge
 void *wined3d_cs_emit_resource_map(struct wined3d_cs *cs, struct wined3d_resource *resource,
         DWORD flags) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_resource_unmap(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN;
+void wined3d_cs_emit_query_issue(struct wined3d_cs *cs, struct wined3d_query *query,
+        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;
 
 /* 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

