On 19 April 2018 at 08:50, Nikolay Sivov <nsivov(a)codeweavers.com> wrote:
@@ -4770,25 +4770,44 @@ 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) - { - gl_info->gl_ops.gl.p_glScissor(r->left, r->top, r->right - r->left, r->bottom - r->top); - } - else + if (!context->render_offscreen) { const struct wined3d_rendertarget_view *target = state->fb->render_targets[0]; - UINT height; - UINT width; + unsigned int 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); + } + + if (gl_info->supported[ARB_VIEWPORT_ARRAY]) + { + unsigned int i; + + for (i = 0; i < state->scissor_rect_count; ++i) + { + r = &state->scissor_rects[i]; + GL_EXTCALL(glScissorIndexed(i, r->left, height ? height - r->top : r->top, + r->right - r->left, r->bottom - r->top)); + } + + if (state->viewport_count > state->scissor_rect_count) + { + static const GLint reset[4 * WINED3D_MAX_VIEWPORTS]; + unsigned int reset_count = state->viewport_count - state->scissor_rect_count; + GL_EXTCALL(glScissorArrayv(state->scissor_rect_count, reset_count, reset)); + } Does this also do the right thing if the viewport count is changed after setting the scissor rectangles?
@@ -825,12 +825,17 @@ 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, sizeof(src_state->scissor_rects)); + else + SetRectEmpty(stateblock->state.scissor_rects); This works, but is it intentional to copy the entire array in the non-zero scissor rect count case?