wined3d: Add support for setting multiple scissor rectangles.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
9dd88e31ef
commit
409497ee84
|
@ -998,7 +998,7 @@ static void STDMETHODCALLTYPE d3d11_immediate_context_RSSetScissorRects(ID3D11De
|
|||
return;
|
||||
|
||||
wined3d_mutex_lock();
|
||||
wined3d_device_set_scissor_rect(device->wined3d_device, rects);
|
||||
wined3d_device_set_scissor_rects(device->wined3d_device, 1, rects);
|
||||
wined3d_mutex_unlock();
|
||||
}
|
||||
|
||||
|
@ -4192,7 +4192,7 @@ static void STDMETHODCALLTYPE d3d10_device_RSSetScissorRects(ID3D10Device1 *ifac
|
|||
return;
|
||||
|
||||
wined3d_mutex_lock();
|
||||
wined3d_device_set_scissor_rect(device->wined3d_device, rects);
|
||||
wined3d_device_set_scissor_rects(device->wined3d_device, 1, rects);
|
||||
wined3d_mutex_unlock();
|
||||
}
|
||||
|
||||
|
|
|
@ -2564,7 +2564,7 @@ static HRESULT WINAPI d3d9_device_SetScissorRect(IDirect3DDevice9Ex *iface, cons
|
|||
TRACE("iface %p, rect %p.\n", iface, rect);
|
||||
|
||||
wined3d_mutex_lock();
|
||||
wined3d_device_set_scissor_rect(device->wined3d_device, rect);
|
||||
wined3d_device_set_scissor_rects(device->wined3d_device, 1, rect);
|
||||
wined3d_mutex_unlock();
|
||||
|
||||
return D3D_OK;
|
||||
|
|
|
@ -2244,6 +2244,10 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
|
|||
if (device->dummy_textures.tex_2d)
|
||||
context_bind_dummy_textures(device, ret);
|
||||
|
||||
/* Initialise all rectangles to avoid resetting unused ones later. */
|
||||
gl_info->gl_ops.gl.p_glScissor(0, 0, 0, 0);
|
||||
checkGLcall("glScissor");
|
||||
|
||||
TRACE("Created context %p.\n", ret);
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -34,7 +34,7 @@ enum wined3d_cs_op
|
|||
WINED3D_CS_OP_FLUSH,
|
||||
WINED3D_CS_OP_SET_PREDICATION,
|
||||
WINED3D_CS_OP_SET_VIEWPORTS,
|
||||
WINED3D_CS_OP_SET_SCISSOR_RECT,
|
||||
WINED3D_CS_OP_SET_SCISSOR_RECTS,
|
||||
WINED3D_CS_OP_SET_RENDERTARGET_VIEW,
|
||||
WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW,
|
||||
WINED3D_CS_OP_SET_VERTEX_DECLARATION,
|
||||
|
@ -145,10 +145,11 @@ struct wined3d_cs_set_viewports
|
|||
struct wined3d_viewport viewports[1];
|
||||
};
|
||||
|
||||
struct wined3d_cs_set_scissor_rect
|
||||
struct wined3d_cs_set_scissor_rects
|
||||
{
|
||||
enum wined3d_cs_op opcode;
|
||||
RECT rect;
|
||||
unsigned int rect_count;
|
||||
RECT rects[1];
|
||||
};
|
||||
|
||||
struct wined3d_cs_set_rendertarget_view
|
||||
|
@ -545,7 +546,7 @@ void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT *
|
|||
op->fb = &cs->fb;
|
||||
SetRect(&op->draw_rect, vp->x, vp->y, vp->x + vp->width, vp->y + vp->height);
|
||||
if (state->render_states[WINED3D_RS_SCISSORTESTENABLE])
|
||||
IntersectRect(&op->draw_rect, &op->draw_rect, &state->scissor_rect);
|
||||
IntersectRect(&op->draw_rect, &op->draw_rect, &state->scissor_rects[0]);
|
||||
op->color = *color;
|
||||
op->depth = depth;
|
||||
op->stencil = stencil;
|
||||
|
@ -989,21 +990,28 @@ void wined3d_cs_emit_set_viewports(struct wined3d_cs *cs, unsigned int viewport_
|
|||
cs->ops->submit(cs, WINED3D_CS_QUEUE_DEFAULT);
|
||||
}
|
||||
|
||||
static void wined3d_cs_exec_set_scissor_rect(struct wined3d_cs *cs, const void *data)
|
||||
static void wined3d_cs_exec_set_scissor_rects(struct wined3d_cs *cs, const void *data)
|
||||
{
|
||||
const struct wined3d_cs_set_scissor_rect *op = data;
|
||||
const struct wined3d_cs_set_scissor_rects *op = data;
|
||||
|
||||
cs->state.scissor_rect = op->rect;
|
||||
if (op->rect_count)
|
||||
memcpy(cs->state.scissor_rects, op->rects, op->rect_count * sizeof(*op->rects));
|
||||
else
|
||||
SetRectEmpty(cs->state.scissor_rects);
|
||||
cs->state.scissor_rect_count = op->rect_count;
|
||||
device_invalidate_state(cs->device, STATE_SCISSORRECT);
|
||||
}
|
||||
|
||||
void wined3d_cs_emit_set_scissor_rect(struct wined3d_cs *cs, const RECT *rect)
|
||||
void wined3d_cs_emit_set_scissor_rects(struct wined3d_cs *cs, unsigned int rect_count, const RECT *rects)
|
||||
{
|
||||
struct wined3d_cs_set_scissor_rect *op;
|
||||
struct wined3d_cs_set_scissor_rects *op;
|
||||
|
||||
op = cs->ops->require_space(cs, sizeof(*op), WINED3D_CS_QUEUE_DEFAULT);
|
||||
op->opcode = WINED3D_CS_OP_SET_SCISSOR_RECT;
|
||||
op->rect = *rect;
|
||||
op = cs->ops->require_space(cs, FIELD_OFFSET(struct wined3d_cs_set_scissor_rects, rects[rect_count]),
|
||||
WINED3D_CS_QUEUE_DEFAULT);
|
||||
op->opcode = WINED3D_CS_OP_SET_SCISSOR_RECTS;
|
||||
if (rect_count)
|
||||
memcpy(op->rects, rects, rect_count * sizeof(*rects));
|
||||
op->rect_count = rect_count;
|
||||
|
||||
cs->ops->submit(cs, WINED3D_CS_QUEUE_DEFAULT);
|
||||
}
|
||||
|
@ -2411,7 +2419,7 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void
|
|||
/* WINED3D_CS_OP_FLUSH */ wined3d_cs_exec_flush,
|
||||
/* WINED3D_CS_OP_SET_PREDICATION */ wined3d_cs_exec_set_predication,
|
||||
/* WINED3D_CS_OP_SET_VIEWPORTS */ wined3d_cs_exec_set_viewports,
|
||||
/* WINED3D_CS_OP_SET_SCISSOR_RECT */ wined3d_cs_exec_set_scissor_rect,
|
||||
/* WINED3D_CS_OP_SET_SCISSOR_RECTS */ wined3d_cs_exec_set_scissor_rects,
|
||||
/* WINED3D_CS_OP_SET_RENDERTARGET_VIEW */ wined3d_cs_exec_set_rendertarget_view,
|
||||
/* WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW */ wined3d_cs_exec_set_depth_stencil_view,
|
||||
/* WINED3D_CS_OP_SET_VERTEX_DECLARATION */ wined3d_cs_exec_set_vertex_declaration,
|
||||
|
|
|
@ -413,9 +413,7 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c
|
|||
gl_info->gl_ops.gl.p_glScissor(draw_rect->left, drawable_height - draw_rect->bottom,
|
||||
draw_rect->right - draw_rect->left, draw_rect->bottom - draw_rect->top);
|
||||
}
|
||||
checkGLcall("glScissor");
|
||||
gl_info->gl_ops.gl.p_glClear(clear_mask);
|
||||
checkGLcall("glClear");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -450,12 +448,11 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c
|
|||
gl_info->gl_ops.gl.p_glScissor(current_rect.left, drawable_height - current_rect.bottom,
|
||||
current_rect.right - current_rect.left, current_rect.bottom - current_rect.top);
|
||||
}
|
||||
checkGLcall("glScissor");
|
||||
|
||||
gl_info->gl_ops.gl.p_glClear(clear_mask);
|
||||
checkGLcall("glClear");
|
||||
}
|
||||
}
|
||||
context->scissor_rect_count = WINED3D_MAX_VIEWPORTS;
|
||||
checkGLcall("clear");
|
||||
|
||||
if (flags & WINED3DCLEAR_TARGET && target->swapchain && target->swapchain->front_buffer == target)
|
||||
gl_info->gl_ops.gl.p_glFlush();
|
||||
|
@ -2123,19 +2120,33 @@ DWORD CDECL wined3d_device_get_sampler_state(const struct wined3d_device *device
|
|||
return device->state.sampler_states[sampler_idx][state];
|
||||
}
|
||||
|
||||
void CDECL wined3d_device_set_scissor_rect(struct wined3d_device *device, const RECT *rect)
|
||||
void CDECL wined3d_device_set_scissor_rects(struct wined3d_device *device, unsigned int rect_count,
|
||||
const RECT *rects)
|
||||
{
|
||||
TRACE("device %p, rect %s.\n", device, wine_dbgstr_rect(rect));
|
||||
unsigned int i;
|
||||
|
||||
TRACE("device %p, rect_count %u, rects %p.\n", device, rect_count, rects);
|
||||
|
||||
for (i = 0; i < rect_count; ++i)
|
||||
{
|
||||
TRACE("%u: %s\n", i, wine_dbgstr_rect(&rects[i]));
|
||||
}
|
||||
|
||||
if (device->recording)
|
||||
device->recording->changed.scissorRect = TRUE;
|
||||
|
||||
if (EqualRect(&device->update_state->scissor_rect, rect))
|
||||
if (device->update_state->scissor_rect_count == rect_count
|
||||
&& !memcmp(device->update_state->scissor_rects, rects, rect_count * sizeof(*rects)))
|
||||
{
|
||||
TRACE("App is setting the old scissor rectangle over, nothing to do.\n");
|
||||
TRACE("App is setting the old scissor rectangles over, nothing to do.\n");
|
||||
return;
|
||||
}
|
||||
CopyRect(&device->update_state->scissor_rect, rect);
|
||||
|
||||
if (rect_count)
|
||||
memcpy(device->update_state->scissor_rects, rects, rect_count * sizeof(*rects));
|
||||
else
|
||||
memset(device->update_state->scissor_rects, 0, sizeof(device->update_state->scissor_rects));
|
||||
device->update_state->scissor_rect_count = rect_count;
|
||||
|
||||
if (device->recording)
|
||||
{
|
||||
|
@ -2143,14 +2154,14 @@ void CDECL wined3d_device_set_scissor_rect(struct wined3d_device *device, const
|
|||
return;
|
||||
}
|
||||
|
||||
wined3d_cs_emit_set_scissor_rect(device->cs, rect);
|
||||
wined3d_cs_emit_set_scissor_rects(device->cs, rect_count, rects);
|
||||
}
|
||||
|
||||
void CDECL wined3d_device_get_scissor_rect(const struct wined3d_device *device, RECT *rect)
|
||||
{
|
||||
TRACE("device %p, rect %p.\n", device, rect);
|
||||
|
||||
*rect = device->state.scissor_rect;
|
||||
*rect = device->state.scissor_rects[0];
|
||||
TRACE("Returning rect %s.\n", wine_dbgstr_rect(rect));
|
||||
}
|
||||
|
||||
|
@ -4476,8 +4487,9 @@ HRESULT CDECL wined3d_device_set_rendertarget_view(struct wined3d_device *device
|
|||
state->viewport_count = 1;
|
||||
wined3d_cs_emit_set_viewports(device->cs, 1, state->viewports);
|
||||
|
||||
SetRect(&state->scissor_rect, 0, 0, view->width, view->height);
|
||||
wined3d_cs_emit_set_scissor_rect(device->cs, &state->scissor_rect);
|
||||
SetRect(&state->scissor_rects[0], 0, 0, view->width, view->height);
|
||||
state->scissor_rect_count = 1;
|
||||
wined3d_cs_emit_set_scissor_rects(device->cs, 1, state->scissor_rects);
|
||||
}
|
||||
|
||||
prev = device->fb.render_targets[view_idx];
|
||||
|
@ -4986,8 +4998,9 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
|
|||
state->viewport_count = 1;
|
||||
wined3d_cs_emit_set_viewports(device->cs, 1, state->viewports);
|
||||
|
||||
SetRect(&state->scissor_rect, 0, 0, view->width, view->height);
|
||||
wined3d_cs_emit_set_scissor_rect(device->cs, &state->scissor_rect);
|
||||
SetRect(&state->scissor_rects[0], 0, 0, view->width, view->height);
|
||||
state->scissor_rect_count = 1;
|
||||
wined3d_cs_emit_set_scissor_rects(device->cs, 1, state->scissor_rects);
|
||||
}
|
||||
|
||||
if (device->d3d_initialized)
|
||||
|
|
|
@ -4252,27 +4252,53 @@ static void light(struct wined3d_context *context, const struct wined3d_state *s
|
|||
static void scissorrect(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
|
||||
{
|
||||
const struct wined3d_gl_info *gl_info = context->gl_info;
|
||||
const RECT *r = &state->scissor_rect;
|
||||
unsigned int height = 0;
|
||||
const RECT *r;
|
||||
|
||||
/* Warning: glScissor uses window coordinates, not viewport coordinates,
|
||||
* so our viewport correction does not apply. Warning2: Even in windowed
|
||||
* mode the coords are relative to the window, not the screen. */
|
||||
TRACE("Setting new scissor rect to %s.\n", wine_dbgstr_rect(r));
|
||||
|
||||
if (context->render_offscreen)
|
||||
if (!context->render_offscreen)
|
||||
{
|
||||
gl_info->gl_ops.gl.p_glScissor(r->left, r->top, r->right - r->left, r->bottom - r->top);
|
||||
const struct wined3d_rendertarget_view *target = state->fb->render_targets[0];
|
||||
unsigned int width;
|
||||
|
||||
wined3d_rendertarget_view_get_drawable_size(target, context, &width, &height);
|
||||
}
|
||||
|
||||
if (gl_info->supported[ARB_VIEWPORT_ARRAY])
|
||||
{
|
||||
GLint sr[4 * WINED3D_MAX_VIEWPORTS];
|
||||
unsigned int i, reset_count = 0;
|
||||
|
||||
for (i = 0; i < state->scissor_rect_count; ++i)
|
||||
{
|
||||
r = &state->scissor_rects[i];
|
||||
|
||||
sr[i * 4] = r->left;
|
||||
sr[i * 4 + 1] = height ? height - r->top : r->top;
|
||||
sr[i * 4 + 2] = r->right - r->left;
|
||||
sr[i * 4 + 3] = r->bottom - r->top;
|
||||
}
|
||||
|
||||
if (context->scissor_rect_count > state->scissor_rect_count)
|
||||
reset_count = context->scissor_rect_count - state->scissor_rect_count;
|
||||
|
||||
if (reset_count)
|
||||
memset(&sr[state->scissor_rect_count * 4], 0, reset_count * 4 * sizeof(GLint));
|
||||
|
||||
GL_EXTCALL(glScissorArrayv(0, state->scissor_rect_count + reset_count, sr));
|
||||
checkGLcall("glScissorArrayv");
|
||||
context->scissor_rect_count = state->scissor_rect_count;
|
||||
}
|
||||
else
|
||||
{
|
||||
const struct wined3d_rendertarget_view *target = state->fb->render_targets[0];
|
||||
UINT height;
|
||||
UINT width;
|
||||
|
||||
wined3d_rendertarget_view_get_drawable_size(target, context, &width, &height);
|
||||
gl_info->gl_ops.gl.p_glScissor(r->left, height - r->bottom, r->right - r->left, r->bottom - r->top);
|
||||
r = &state->scissor_rects[0];
|
||||
gl_info->gl_ops.gl.p_glScissor(r->left, height ? height - r->top : r->top,
|
||||
r->right - r->left, r->bottom - r->top);
|
||||
checkGLcall("glScissor");
|
||||
}
|
||||
checkGLcall("glScissor");
|
||||
}
|
||||
|
||||
static void indexbuffer(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
|
||||
|
|
|
@ -825,12 +825,18 @@ void CDECL wined3d_stateblock_capture(struct wined3d_stateblock *stateblock)
|
|||
memset(stateblock->state.viewports, 0, sizeof(*stateblock->state.viewports));
|
||||
}
|
||||
|
||||
if (stateblock->changed.scissorRect && memcmp(&src_state->scissor_rect,
|
||||
&stateblock->state.scissor_rect, sizeof(stateblock->state.scissor_rect)))
|
||||
if (stateblock->changed.scissorRect
|
||||
&& (src_state->scissor_rect_count != stateblock->state.scissor_rect_count
|
||||
|| memcmp(src_state->scissor_rects, stateblock->state.scissor_rects,
|
||||
src_state->scissor_rect_count * sizeof(*stateblock->state.scissor_rects))))
|
||||
{
|
||||
TRACE("Updating scissor rect.\n");
|
||||
TRACE("Updating scissor rects.\n");
|
||||
|
||||
stateblock->state.scissor_rect = src_state->scissor_rect;
|
||||
if ((stateblock->state.scissor_rect_count = src_state->scissor_rect_count))
|
||||
memcpy(stateblock->state.scissor_rects, src_state->scissor_rects,
|
||||
src_state->scissor_rect_count * sizeof(*src_state->scissor_rects));
|
||||
else
|
||||
SetRectEmpty(stateblock->state.scissor_rects);
|
||||
}
|
||||
|
||||
map = stateblock->changed.streamSource;
|
||||
|
@ -1065,7 +1071,8 @@ void CDECL wined3d_stateblock_apply(const struct wined3d_stateblock *stateblock)
|
|||
wined3d_device_set_viewports(device, stateblock->state.viewport_count, stateblock->state.viewports);
|
||||
|
||||
if (stateblock->changed.scissorRect)
|
||||
wined3d_device_set_scissor_rect(device, &stateblock->state.scissor_rect);
|
||||
wined3d_device_set_scissor_rects(device, stateblock->state.scissor_rect_count,
|
||||
stateblock->state.scissor_rects);
|
||||
|
||||
map = stateblock->changed.streamSource;
|
||||
for (i = 0; map; map >>= 1, ++i)
|
||||
|
|
|
@ -176,7 +176,7 @@
|
|||
@ cdecl wined3d_device_set_render_state(ptr long long)
|
||||
@ cdecl wined3d_device_set_rendertarget_view(ptr long ptr long)
|
||||
@ cdecl wined3d_device_set_sampler_state(ptr long long long)
|
||||
@ cdecl wined3d_device_set_scissor_rect(ptr ptr)
|
||||
@ cdecl wined3d_device_set_scissor_rects(ptr long ptr)
|
||||
@ cdecl wined3d_device_set_software_vertex_processing(ptr long)
|
||||
@ cdecl wined3d_device_set_stream_output(ptr long ptr long)
|
||||
@ cdecl wined3d_device_set_stream_source(ptr long ptr long long)
|
||||
|
|
|
@ -1995,6 +1995,7 @@ struct wined3d_context
|
|||
GLuint dummy_arbfp_prog;
|
||||
|
||||
unsigned int viewport_count;
|
||||
unsigned int scissor_rect_count;
|
||||
};
|
||||
|
||||
struct wined3d_fb_state
|
||||
|
@ -2863,7 +2864,8 @@ struct wined3d_state
|
|||
struct wined3d_material material;
|
||||
struct wined3d_viewport viewports[WINED3D_MAX_VIEWPORTS];
|
||||
unsigned int viewport_count;
|
||||
RECT scissor_rect;
|
||||
RECT scissor_rects[WINED3D_MAX_VIEWPORTS];
|
||||
unsigned int scissor_rect_count;
|
||||
|
||||
/* Light hashmap. Collisions are handled using linked lists. */
|
||||
#define LIGHTMAP_SIZE 43
|
||||
|
@ -3599,7 +3601,7 @@ void wined3d_cs_emit_set_sampler(struct wined3d_cs *cs, enum wined3d_shader_type
|
|||
UINT sampler_idx, struct wined3d_sampler *sampler) DECLSPEC_HIDDEN;
|
||||
void wined3d_cs_emit_set_sampler_state(struct wined3d_cs *cs, UINT sampler_idx,
|
||||
enum wined3d_sampler_state state, DWORD value) DECLSPEC_HIDDEN;
|
||||
void wined3d_cs_emit_set_scissor_rect(struct wined3d_cs *cs, const RECT *rect) DECLSPEC_HIDDEN;
|
||||
void wined3d_cs_emit_set_scissor_rects(struct wined3d_cs *cs, unsigned int rect_count, const RECT *rects) DECLSPEC_HIDDEN;
|
||||
void wined3d_cs_emit_set_shader(struct wined3d_cs *cs, enum wined3d_shader_type type,
|
||||
struct wined3d_shader *shader) DECLSPEC_HIDDEN;
|
||||
void wined3d_cs_emit_set_stream_output(struct wined3d_cs *cs, UINT stream_idx,
|
||||
|
|
|
@ -2426,7 +2426,8 @@ HRESULT __cdecl wined3d_device_set_rendertarget_view(struct wined3d_device *devi
|
|||
unsigned int view_idx, struct wined3d_rendertarget_view *view, BOOL set_viewport);
|
||||
void __cdecl wined3d_device_set_sampler_state(struct wined3d_device *device,
|
||||
UINT sampler_idx, enum wined3d_sampler_state state, DWORD value);
|
||||
void __cdecl wined3d_device_set_scissor_rect(struct wined3d_device *device, const RECT *rect);
|
||||
void __cdecl wined3d_device_set_scissor_rects(struct wined3d_device *device,
|
||||
unsigned int rect_count, const RECT *rect);
|
||||
void __cdecl wined3d_device_set_software_vertex_processing(struct wined3d_device *device, BOOL software);
|
||||
void __cdecl wined3d_device_set_stream_output(struct wined3d_device *device, UINT idx,
|
||||
struct wined3d_buffer *buffer, UINT offset);
|
||||
|
|
Loading…
Reference in New Issue