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:
parent
7bcbb93c5a
commit
602c82bce8
|
@ -7,6 +7,7 @@ C_SRCS = \
|
|||
ati_fragment_shader.c \
|
||||
buffer.c \
|
||||
context.c \
|
||||
cs.c \
|
||||
device.c \
|
||||
directx.c \
|
||||
drawprim.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);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue