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.
This commit is contained in:
Henri Verbeet 2013-09-27 00:15:13 +02:00 committed by Alexandre Julliard
parent 7bcbb93c5a
commit 602c82bce8
5 changed files with 174 additions and 9 deletions

View file

@ -7,6 +7,7 @@ C_SRCS = \
ati_fragment_shader.c \
buffer.c \
context.c \
cs.c \
device.c \
directx.c \
drawprim.c \

128
dlls/wined3d/cs.c Normal file
View file

@ -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);
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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