Henri Verbeet : wined3d: Send present operations through a command stream.

Alexandre Julliard julliard at winehq.org
Fri Sep 27 11:33:12 CDT 2013


Module: wine
Branch: master
Commit: 602c82bce86db8fff427b146176490db8bf7529d
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=602c82bce86db8fff427b146176490db8bf7529d

Author: Henri Verbeet <hverbeet at codeweavers.com>
Date:   Fri Sep 27 00:15:13 2013 +0200

wined3d: Send present operations through a command stream.

The eventual goal is to have a multithreaded implementation of wined3d_cs_ops
and offload some processing to a different thread.

---

 dlls/wined3d/Makefile.in       |    1 +
 dlls/wined3d/cs.c              |  128 ++++++++++++++++++++++++++++++++++++++++
 dlls/wined3d/device.c          |   25 ++++++--
 dlls/wined3d/swapchain.c       |    5 +-
 dlls/wined3d/wined3d_private.h |   24 ++++++++
 5 files changed, 174 insertions(+), 9 deletions(-)

diff --git a/dlls/wined3d/Makefile.in b/dlls/wined3d/Makefile.in
index b1051c2..f77f35d 100644
--- a/dlls/wined3d/Makefile.in
+++ b/dlls/wined3d/Makefile.in
@@ -7,6 +7,7 @@ C_SRCS = \
 	ati_fragment_shader.c \
 	buffer.c \
 	context.c \
+	cs.c \
 	device.c \
 	directx.c \
 	drawprim.c \
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
new file mode 100644
index 0000000..5f9bb56
--- /dev/null
+++ b/dlls/wined3d/cs.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2013 Henri Verbeet for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include "wined3d_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d);
+
+#define WINED3D_INITIAL_CS_SIZE 4096
+
+enum wined3d_cs_op
+{
+    WINED3D_CS_OP_PRESENT,
+};
+
+struct wined3d_cs_present
+{
+    enum wined3d_cs_op opcode;
+    HWND dst_window_override;
+    struct wined3d_swapchain *swapchain;
+    const RECT *src_rect;
+    const RECT *dst_rect;
+    const RGNDATA *dirty_region;
+    DWORD flags;
+};
+
+static void wined3d_cs_exec_present(const void *data)
+{
+    const struct wined3d_cs_present *op = data;
+    struct wined3d_swapchain *swapchain;
+
+    swapchain = op->swapchain;
+    wined3d_swapchain_set_window(swapchain, op->dst_window_override);
+
+    swapchain->swapchain_ops->swapchain_present(swapchain,
+            op->src_rect, op->dst_rect, op->dirty_region, op->flags);
+}
+
+void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *swapchain,
+        const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override,
+        const RGNDATA *dirty_region, DWORD flags)
+{
+    struct wined3d_cs_present *op;
+
+    op = cs->ops->require_space(cs, sizeof(*op));
+    op->opcode = WINED3D_CS_OP_PRESENT;
+    op->dst_window_override = dst_window_override;
+    op->swapchain = swapchain;
+    op->src_rect = src_rect;
+    op->dst_rect = dst_rect;
+    op->dirty_region = dirty_region;
+    op->flags = flags;
+
+    cs->ops->submit(cs);
+}
+
+static void (* const wined3d_cs_op_handlers[])(const void *data) =
+{
+    /* WINED3D_CS_OP_PRESENT                */ wined3d_cs_exec_present,
+};
+
+static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size)
+{
+    if (size > cs->data_size)
+    {
+        void *new_data;
+
+        if (!(new_data = HeapReAlloc(GetProcessHeap(), 0, cs->data, cs->data_size * 2)))
+            return NULL;
+
+        cs->data_size *= 2;
+        cs->data = new_data;
+    }
+
+    return cs->data;
+}
+
+static void wined3d_cs_st_submit(struct wined3d_cs *cs)
+{
+    enum wined3d_cs_op opcode = *(const enum wined3d_cs_op *)cs->data;
+
+    wined3d_cs_op_handlers[opcode](cs->data);
+}
+
+static const struct wined3d_cs_ops wined3d_cs_st_ops =
+{
+    wined3d_cs_st_require_space,
+    wined3d_cs_st_submit,
+};
+
+struct wined3d_cs *wined3d_cs_create(void)
+{
+    struct wined3d_cs *cs;
+
+    if (!(cs = HeapAlloc(GetProcessHeap(), 0, sizeof(*cs))))
+        return NULL;
+
+    cs->ops = &wined3d_cs_st_ops;
+
+    cs->data_size = WINED3D_INITIAL_CS_SIZE;
+    if (!(cs->data = HeapAlloc(GetProcessHeap(), 0, cs->data_size)))
+    {
+        HeapFree(GetProcessHeap(), 0, cs);
+        return NULL;
+    }
+
+    return cs;
+}
+
+void wined3d_cs_destroy(struct wined3d_cs *cs)
+{
+    HeapFree(GetProcessHeap(), 0, cs);
+}
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 34ceaa7..ff23770 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -485,6 +485,8 @@ ULONG CDECL wined3d_device_decref(struct wined3d_device *device)
     {
         UINT i;
 
+        wined3d_cs_destroy(device->cs);
+
         if (device->recording && wined3d_stateblock_decref(device->recording))
             FIXME("Something's still holding the recording stateblock.\n");
         device->recording = NULL;
@@ -4975,17 +4977,28 @@ HRESULT device_init(struct wined3d_device *device, struct wined3d *wined3d,
     if (FAILED(hr = state_init(&device->state, &device->fb, &adapter->d3d_info)))
     {
         ERR("Failed to initialize device state, hr %#x.\n", hr);
-        for (i = 0; i < sizeof(device->multistate_funcs) / sizeof(device->multistate_funcs[0]); ++i)
-        {
-            HeapFree(GetProcessHeap(), 0, device->multistate_funcs[i]);
-        }
-        wined3d_decref(device->wined3d);
-        return hr;
+        goto err;
     }
     state_init_default(&device->state, &adapter->gl_info);
     device->update_state = &device->state;
 
+    if (!(device->cs = wined3d_cs_create()))
+    {
+        WARN("Failed to create command stream.\n");
+        state_cleanup(&device->state);
+        hr = E_FAIL;
+        goto err;
+    }
+
     return WINED3D_OK;
+
+err:
+    for (i = 0; i < sizeof(device->multistate_funcs) / sizeof(device->multistate_funcs[0]); ++i)
+    {
+        HeapFree(GetProcessHeap(), 0, device->multistate_funcs[i]);
+    }
+    wined3d_decref(device->wined3d);
+    return hr;
 }
 
 
diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c
index 62827c9..2bab9ed 100644
--- a/dlls/wined3d/swapchain.c
+++ b/dlls/wined3d/swapchain.c
@@ -149,9 +149,8 @@ HRESULT CDECL wined3d_swapchain_present(struct wined3d_swapchain *swapchain,
         return WINED3DERR_INVALIDCALL;
     }
 
-    wined3d_swapchain_set_window(swapchain, dst_window_override);
-
-    swapchain->swapchain_ops->swapchain_present(swapchain, src_rect, dst_rect, dirty_region, flags);
+    wined3d_cs_emit_present(swapchain->device->cs, swapchain, src_rect,
+            dst_rect, dst_window_override, dirty_region, flags);
 
     return WINED3D_OK;
 }
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 9b979dc..251de34 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1939,6 +1939,9 @@ struct wined3d_device
     UINT dummy_texture_3d[MAX_COMBINED_SAMPLERS];
     UINT dummy_texture_cube[MAX_COMBINED_SAMPLERS];
 
+    /* Command stream */
+    struct wined3d_cs *cs;
+
     /* Context management */
     struct wined3d_context **contexts;
     UINT context_count;
@@ -2452,6 +2455,27 @@ HRESULT state_init(struct wined3d_state *state, struct wined3d_fb_state *fb,
 void state_init_default(struct wined3d_state *state, const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN;
 void state_unbind_resources(struct wined3d_state *state) DECLSPEC_HIDDEN;
 
+struct wined3d_cs_ops
+{
+    void *(*require_space)(struct wined3d_cs *cs, size_t size);
+    void (*submit)(struct wined3d_cs *cs);
+};
+
+struct wined3d_cs
+{
+    const struct wined3d_cs_ops *ops;
+
+    size_t data_size;
+    void *data;
+};
+
+struct wined3d_cs *wined3d_cs_create(void) DECLSPEC_HIDDEN;
+void wined3d_cs_destroy(struct wined3d_cs *cs) DECLSPEC_HIDDEN;
+
+void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *swapchain,
+        const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override,
+        const RGNDATA *dirty_region, DWORD flags) 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
  * allows GetData on a created issue, but opengl doesn't




More information about the wine-cvs mailing list