2013-09-27 00:15:13 +02:00
|
|
|
/*
|
|
|
|
* 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,
|
2013-09-27 00:15:14 +02:00
|
|
|
WINED3D_CS_OP_CLEAR,
|
2013-09-27 00:15:15 +02:00
|
|
|
WINED3D_CS_OP_DRAW,
|
2013-09-30 09:40:39 +02:00
|
|
|
WINED3D_CS_OP_SET_VIEWPORT,
|
2013-09-27 00:15:13 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
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;
|
|
|
|
};
|
|
|
|
|
2013-09-27 00:15:14 +02:00
|
|
|
struct wined3d_cs_clear
|
|
|
|
{
|
|
|
|
enum wined3d_cs_op opcode;
|
|
|
|
DWORD rect_count;
|
|
|
|
const RECT *rects;
|
|
|
|
DWORD flags;
|
|
|
|
const struct wined3d_color *color;
|
|
|
|
float depth;
|
|
|
|
DWORD stencil;
|
|
|
|
};
|
|
|
|
|
2013-09-27 00:15:15 +02:00
|
|
|
struct wined3d_cs_draw
|
|
|
|
{
|
|
|
|
enum wined3d_cs_op opcode;
|
|
|
|
UINT start_idx;
|
|
|
|
UINT index_count;
|
|
|
|
UINT start_instance;
|
|
|
|
UINT instance_count;
|
|
|
|
BOOL indexed;
|
|
|
|
};
|
|
|
|
|
2013-09-30 09:40:39 +02:00
|
|
|
struct wined3d_cs_set_viewport
|
|
|
|
{
|
|
|
|
enum wined3d_cs_op opcode;
|
|
|
|
const struct wined3d_viewport *viewport;
|
|
|
|
};
|
|
|
|
|
2013-09-27 00:15:14 +02:00
|
|
|
static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data)
|
2013-09-27 00:15:13 +02:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2013-09-27 00:15:14 +02:00
|
|
|
static void wined3d_cs_exec_clear(struct wined3d_cs *cs, const void *data)
|
|
|
|
{
|
|
|
|
const struct wined3d_cs_clear *op = data;
|
|
|
|
struct wined3d_device *device;
|
|
|
|
RECT draw_rect;
|
|
|
|
|
|
|
|
device = cs->device;
|
|
|
|
wined3d_get_draw_rect(&device->state, &draw_rect);
|
|
|
|
device_clear_render_targets(device, device->adapter->gl_info.limits.buffers,
|
|
|
|
&device->fb, op->rect_count, op->rects, &draw_rect, op->flags,
|
|
|
|
op->color, op->depth, op->stencil);
|
|
|
|
}
|
|
|
|
|
|
|
|
void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT *rects,
|
|
|
|
DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil)
|
|
|
|
{
|
|
|
|
struct wined3d_cs_clear *op;
|
|
|
|
|
|
|
|
op = cs->ops->require_space(cs, sizeof(*op));
|
|
|
|
op->opcode = WINED3D_CS_OP_CLEAR;
|
|
|
|
op->rect_count = rect_count;
|
|
|
|
op->rects = rects;
|
|
|
|
op->flags = flags;
|
|
|
|
op->color = color;
|
|
|
|
op->depth = depth;
|
|
|
|
op->stencil = stencil;
|
|
|
|
|
|
|
|
cs->ops->submit(cs);
|
|
|
|
}
|
|
|
|
|
2013-09-27 00:15:15 +02:00
|
|
|
static void wined3d_cs_exec_draw(struct wined3d_cs *cs, const void *data)
|
|
|
|
{
|
|
|
|
const struct wined3d_cs_draw *op = data;
|
|
|
|
|
|
|
|
draw_primitive(cs->device, op->start_idx, op->index_count,
|
|
|
|
op->start_instance, op->instance_count, op->indexed);
|
|
|
|
}
|
|
|
|
|
|
|
|
void wined3d_cs_emit_draw(struct wined3d_cs *cs, UINT start_idx, UINT index_count,
|
|
|
|
UINT start_instance, UINT instance_count, BOOL indexed)
|
|
|
|
{
|
|
|
|
struct wined3d_cs_draw *op;
|
|
|
|
|
|
|
|
op = cs->ops->require_space(cs, sizeof(*op));
|
|
|
|
op->opcode = WINED3D_CS_OP_DRAW;
|
|
|
|
op->start_idx = start_idx;
|
|
|
|
op->index_count = index_count;
|
|
|
|
op->start_instance = start_instance;
|
|
|
|
op->instance_count = instance_count;
|
|
|
|
op->indexed = indexed;
|
|
|
|
|
|
|
|
cs->ops->submit(cs);
|
|
|
|
}
|
|
|
|
|
2013-09-30 09:40:39 +02:00
|
|
|
static void wined3d_cs_exec_set_viewport(struct wined3d_cs *cs, const void *data)
|
|
|
|
{
|
|
|
|
const struct wined3d_cs_set_viewport *op = data;
|
|
|
|
|
|
|
|
cs->state.viewport = *op->viewport;
|
|
|
|
device_invalidate_state(cs->device, STATE_VIEWPORT);
|
|
|
|
}
|
|
|
|
|
|
|
|
void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport *viewport)
|
|
|
|
{
|
|
|
|
struct wined3d_cs_set_viewport *op;
|
|
|
|
|
|
|
|
op = cs->ops->require_space(cs, sizeof(*op));
|
|
|
|
op->opcode = WINED3D_CS_OP_SET_VIEWPORT;
|
|
|
|
op->viewport = viewport;
|
|
|
|
|
|
|
|
cs->ops->submit(cs);
|
|
|
|
}
|
|
|
|
|
2013-09-27 00:15:14 +02:00
|
|
|
static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) =
|
2013-09-27 00:15:13 +02:00
|
|
|
{
|
|
|
|
/* WINED3D_CS_OP_PRESENT */ wined3d_cs_exec_present,
|
2013-09-27 00:15:14 +02:00
|
|
|
/* WINED3D_CS_OP_CLEAR */ wined3d_cs_exec_clear,
|
2013-09-27 00:15:15 +02:00
|
|
|
/* WINED3D_CS_OP_DRAW */ wined3d_cs_exec_draw,
|
2013-09-30 09:40:39 +02:00
|
|
|
/* WINED3D_CS_OP_SET_VIEWPORT */ wined3d_cs_exec_set_viewport,
|
2013-09-27 00:15:13 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2013-09-27 00:15:14 +02:00
|
|
|
wined3d_cs_op_handlers[opcode](cs, cs->data);
|
2013-09-27 00:15:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static const struct wined3d_cs_ops wined3d_cs_st_ops =
|
|
|
|
{
|
|
|
|
wined3d_cs_st_require_space,
|
|
|
|
wined3d_cs_st_submit,
|
|
|
|
};
|
|
|
|
|
2013-09-27 00:15:14 +02:00
|
|
|
struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device)
|
2013-09-27 00:15:13 +02:00
|
|
|
{
|
2013-09-30 09:40:39 +02:00
|
|
|
const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
|
2013-09-27 00:15:13 +02:00
|
|
|
struct wined3d_cs *cs;
|
|
|
|
|
2013-09-30 09:40:39 +02:00
|
|
|
if (!(cs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*cs))))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!(cs->fb.render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
|
|
|
|
sizeof(*cs->fb.render_targets) * gl_info->limits.buffers)))
|
|
|
|
{
|
|
|
|
HeapFree(GetProcessHeap(), 0, cs);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (FAILED(state_init(&cs->state, &cs->fb, &device->adapter->d3d_info, WINED3D_STATE_NO_REF)))
|
|
|
|
{
|
|
|
|
HeapFree(GetProcessHeap(), 0, cs->fb.render_targets);
|
|
|
|
HeapFree(GetProcessHeap(), 0, cs);
|
2013-09-27 00:15:13 +02:00
|
|
|
return NULL;
|
2013-09-30 09:40:39 +02:00
|
|
|
}
|
|
|
|
state_init_default(&cs->state, gl_info);
|
2013-09-27 00:15:13 +02:00
|
|
|
|
|
|
|
cs->ops = &wined3d_cs_st_ops;
|
2013-09-27 00:15:14 +02:00
|
|
|
cs->device = device;
|
2013-09-27 00:15:13 +02:00
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2013-09-30 09:40:39 +02:00
|
|
|
state_cleanup(&cs->state);
|
|
|
|
HeapFree(GetProcessHeap(), 0, cs->fb.render_targets);
|
2013-09-27 00:15:13 +02:00
|
|
|
HeapFree(GetProcessHeap(), 0, cs);
|
|
|
|
}
|