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