Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/d3d11/device.c | 52 ++++++++++++------------ dlls/d3d11/tests/d3d11.c | 3 -- dlls/d3d8/device.c | 2 +- dlls/d3d9/device.c | 2 +- dlls/ddraw/device.c | 2 +- dlls/wined3d/cs.c | 34 ++++++++++------ dlls/wined3d/device.c | 50 ++++++++++++++--------- dlls/wined3d/glsl_shader.c | 13 ++++++ dlls/wined3d/state.c | 92 +++++++++++++++++++++++++++++++----------- dlls/wined3d/stateblock.c | 12 ++++-- dlls/wined3d/utils.c | 16 ++++---- dlls/wined3d/wined3d.spec | 2 +- dlls/wined3d/wined3d_private.h | 11 +++-- include/wine/wined3d.h | 5 ++- 14 files changed, 190 insertions(+), 106 deletions(-)
diff --git a/dlls/d3d11/device.c b/dlls/d3d11/device.c index 1fe62975d5..b941115ebc 100644 --- a/dlls/d3d11/device.c +++ b/dlls/d3d11/device.c @@ -961,25 +961,25 @@ static void STDMETHODCALLTYPE d3d11_immediate_context_RSSetViewports(ID3D11Devic UINT viewport_count, const D3D11_VIEWPORT *viewports) { struct d3d_device *device = device_from_immediate_ID3D11DeviceContext(iface); - struct wined3d_viewport wined3d_vp; + struct wined3d_viewport wined3d_vp[WINED3D_MAX_VIEWPORTS]; + unsigned int i;
TRACE("iface %p, viewport_count %u, viewports %p.\n", iface, viewport_count, viewports);
- if (viewport_count > 1) - FIXME("Multiple viewports not implemented.\n"); - - if (!viewport_count) - return; + viewport_count = min(WINED3D_MAX_VIEWPORTS, viewport_count);
- wined3d_vp.x = viewports[0].TopLeftX; - wined3d_vp.y = viewports[0].TopLeftY; - wined3d_vp.width = viewports[0].Width; - wined3d_vp.height = viewports[0].Height; - wined3d_vp.min_z = viewports[0].MinDepth; - wined3d_vp.max_z = viewports[0].MaxDepth; + for (i = 0; i < viewport_count; ++i) + { + wined3d_vp[i].x = viewports[i].TopLeftX; + wined3d_vp[i].y = viewports[i].TopLeftY; + wined3d_vp[i].width = viewports[i].Width; + wined3d_vp[i].height = viewports[i].Height; + wined3d_vp[i].min_z = viewports[i].MinDepth; + wined3d_vp[i].max_z = viewports[i].MaxDepth; + }
wined3d_mutex_lock(); - wined3d_device_set_viewport(device->wined3d_device, &wined3d_vp); + wined3d_device_set_viewports(device->wined3d_device, viewport_count, wined3d_vp); wined3d_mutex_unlock(); }
@@ -4149,25 +4149,25 @@ static void STDMETHODCALLTYPE d3d10_device_RSSetViewports(ID3D10Device1 *iface, UINT viewport_count, const D3D10_VIEWPORT *viewports) { struct d3d_device *device = impl_from_ID3D10Device(iface); - struct wined3d_viewport wined3d_vp; + struct wined3d_viewport wined3d_vp[WINED3D_MAX_VIEWPORTS]; + unsigned int i;
TRACE("iface %p, viewport_count %u, viewports %p.\n", iface, viewport_count, viewports);
- if (viewport_count > 1) - FIXME("Multiple viewports not implemented.\n"); - - if (!viewport_count) - return; + viewport_count = min(WINED3D_MAX_VIEWPORTS, viewport_count);
- wined3d_vp.x = viewports[0].TopLeftX; - wined3d_vp.y = viewports[0].TopLeftY; - wined3d_vp.width = viewports[0].Width; - wined3d_vp.height = viewports[0].Height; - wined3d_vp.min_z = viewports[0].MinDepth; - wined3d_vp.max_z = viewports[0].MaxDepth; + for (i = 0; i < viewport_count; ++i) + { + wined3d_vp[i].x = viewports[i].TopLeftX; + wined3d_vp[i].y = viewports[i].TopLeftY; + wined3d_vp[i].width = viewports[i].Width; + wined3d_vp[i].height = viewports[i].Height; + wined3d_vp[i].min_z = viewports[i].MinDepth; + wined3d_vp[i].max_z = viewports[i].MaxDepth; + }
wined3d_mutex_lock(); - wined3d_device_set_viewport(device->wined3d_device, &wined3d_vp); + wined3d_device_set_viewports(device->wined3d_device, viewport_count, wined3d_vp); wined3d_mutex_unlock(); }
diff --git a/dlls/d3d11/tests/d3d11.c b/dlls/d3d11/tests/d3d11.c index b3597ad1b3..6feac2bc9a 100644 --- a/dlls/d3d11/tests/d3d11.c +++ b/dlls/d3d11/tests/d3d11.c @@ -10578,7 +10578,6 @@ static void test_clear_state(void) ID3D11DeviceContext_RSGetViewports(context, &count, tmp_viewport); for (i = 0; i < D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; ++i) { - todo_wine_if(!i) ok(!tmp_viewport[i].TopLeftX && !tmp_viewport[i].TopLeftY && !tmp_viewport[i].Width && !tmp_viewport[i].Height && !tmp_viewport[i].MinDepth && !tmp_viewport[i].MaxDepth, "Got unexpected viewport {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e} in slot %u.\n", @@ -26078,7 +26077,6 @@ static void test_multiple_viewports(void) SetRect(&rect, 0, 0, width - 1, texture_desc.Height - 1); check_texture_sub_resource_vec4(texture, 0, &rect, &expected_values[0], 1); SetRect(&rect, width, 0, 2 * width - 1, texture_desc.Height - 1); -todo_wine check_texture_sub_resource_vec4(texture, 0, &rect, &expected_values[1], 1);
/* One viewport. */ @@ -26098,7 +26096,6 @@ todo_wine constant.draw_id = 3; ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &constant, 0, 0); draw_quad(&test_context); -todo_wine check_texture_sub_resource_vec4(texture, 0, NULL, &expected_values[4], 1);
ID3D11RenderTargetView_Release(rtv); diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c index 65480876d3..3bdb278ec5 100644 --- a/dlls/d3d8/device.c +++ b/dlls/d3d8/device.c @@ -1650,7 +1650,7 @@ static HRESULT WINAPI d3d8_device_SetViewport(IDirect3DDevice8 *iface, const D3D vp.min_z = viewport->MinZ; vp.max_z = viewport->MaxZ;
- wined3d_device_set_viewport(device->wined3d_device, &vp); + wined3d_device_set_viewports(device->wined3d_device, 1, &vp); wined3d_mutex_unlock();
return D3D_OK; diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c index 2265c1dca2..a1b25f9b04 100644 --- a/dlls/d3d9/device.c +++ b/dlls/d3d9/device.c @@ -2072,7 +2072,7 @@ static HRESULT WINAPI d3d9_device_SetViewport(IDirect3DDevice9Ex *iface, const D vp.max_z = viewport->MaxZ;
wined3d_mutex_lock(); - wined3d_device_set_viewport(device->wined3d_device, &vp); + wined3d_device_set_viewports(device->wined3d_device, 1, &vp); wined3d_mutex_unlock();
return D3D_OK; diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c index 35995625e4..23c61c5d80 100644 --- a/dlls/ddraw/device.c +++ b/dlls/ddraw/device.c @@ -5333,7 +5333,7 @@ static HRESULT d3d_device7_SetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *vi vp.min_z = viewport->dvMinZ; vp.max_z = viewport->dvMaxZ;
- wined3d_device_set_viewport(device->wined3d_device, &vp); + wined3d_device_set_viewports(device->wined3d_device, 1, &vp); wined3d_mutex_unlock();
return D3D_OK; diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index 2f0c4ed52e..8148cf73ad 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -33,7 +33,7 @@ enum wined3d_cs_op WINED3D_CS_OP_DRAW, WINED3D_CS_OP_FLUSH, WINED3D_CS_OP_SET_PREDICATION, - WINED3D_CS_OP_SET_VIEWPORT, + WINED3D_CS_OP_SET_VIEWPORTS, WINED3D_CS_OP_SET_SCISSOR_RECT, WINED3D_CS_OP_SET_RENDERTARGET_VIEW, WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW, @@ -138,10 +138,11 @@ struct wined3d_cs_set_predication BOOL value; };
-struct wined3d_cs_set_viewport +struct wined3d_cs_set_viewports { enum wined3d_cs_op opcode; - struct wined3d_viewport viewport; + struct wined3d_viewport viewports[WINED3D_MAX_VIEWPORTS]; + unsigned int viewport_count; };
struct wined3d_cs_set_scissor_rect @@ -530,7 +531,7 @@ void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT * { unsigned int rt_count = cs->device->adapter->gl_info.limits.buffers; const struct wined3d_state *state = &cs->device->state; - const struct wined3d_viewport *vp = &state->viewport; + const struct wined3d_viewport *vp = &state->viewports[0]; struct wined3d_rendertarget_view *view; struct wined3d_cs_clear *op; RECT view_rect; @@ -961,21 +962,30 @@ void wined3d_cs_emit_set_predication(struct wined3d_cs *cs, struct wined3d_query cs->ops->submit(cs, WINED3D_CS_QUEUE_DEFAULT); }
-static void wined3d_cs_exec_set_viewport(struct wined3d_cs *cs, const void *data) +static void wined3d_cs_exec_set_viewports(struct wined3d_cs *cs, const void *data) { - const struct wined3d_cs_set_viewport *op = data; + const struct wined3d_cs_set_viewports *op = data;
- cs->state.viewport = op->viewport; + if (op->viewport_count) + memcpy(cs->state.viewports, op->viewports, op->viewport_count * sizeof(*op->viewports)); + else + memset(cs->state.viewports, 0, sizeof(*cs->state.viewports)); + cs->state.viewport_count = op->viewport_count; device_invalidate_state(cs->device, STATE_VIEWPORT); }
-void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport *viewport) +void wined3d_cs_emit_set_viewports(struct wined3d_cs *cs, unsigned int viewport_count, + const struct wined3d_viewport *viewports) { - struct wined3d_cs_set_viewport *op; + struct wined3d_cs_set_viewports *op;
op = cs->ops->require_space(cs, sizeof(*op), WINED3D_CS_QUEUE_DEFAULT); - op->opcode = WINED3D_CS_OP_SET_VIEWPORT; - op->viewport = *viewport; + op->opcode = WINED3D_CS_OP_SET_VIEWPORTS; + if (viewport_count) + memcpy(op->viewports, viewports, viewport_count * sizeof(*viewports)); + else + memset(op->viewports, 0, sizeof(*op->viewports)); + op->viewport_count = viewport_count;
cs->ops->submit(cs, WINED3D_CS_QUEUE_DEFAULT); } @@ -2401,7 +2411,7 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void /* WINED3D_CS_OP_DRAW */ wined3d_cs_exec_draw, /* WINED3D_CS_OP_FLUSH */ wined3d_cs_exec_flush, /* WINED3D_CS_OP_SET_PREDICATION */ wined3d_cs_exec_set_predication, - /* WINED3D_CS_OP_SET_VIEWPORT */ wined3d_cs_exec_set_viewport, + /* 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_RENDERTARGET_VIEW */ wined3d_cs_exec_set_rendertarget_view, /* WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW */ wined3d_cs_exec_set_depth_stencil_view, diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index cc42dba45d..ae53628e48 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -1909,13 +1909,24 @@ INT CDECL wined3d_device_get_base_vertex_index(const struct wined3d_device *devi return device->state.base_vertex_index; }
-void CDECL wined3d_device_set_viewport(struct wined3d_device *device, const struct wined3d_viewport *viewport) +void CDECL wined3d_device_set_viewports(struct wined3d_device *device, unsigned int viewport_count, + const struct wined3d_viewport *viewports) { - TRACE("device %p, viewport %p.\n", device, viewport); - TRACE("x %.8e, y %.8e, w %.8e, h %.8e, min_z %.8e, max_z %.8e.\n", - viewport->x, viewport->y, viewport->width, viewport->height, viewport->min_z, viewport->max_z); + unsigned int i; + + TRACE("device %p, viewport_count %u, viewports %p.\n", device, viewport_count, viewports); + + for (i = 0; i < viewport_count; ++i) + { + TRACE("%u: x %.8e, y %.8e, w %.8e, h %.8e, min_z %.8e, max_z %.8e.\n", i, viewports[i].x, viewports[i].y, + viewports[i].width, viewports[i].height, viewports[i].min_z, viewports[i].max_z); + }
- device->update_state->viewport = *viewport; + if (viewport_count) + memcpy(device->update_state->viewports, viewports, viewport_count * sizeof(*viewports)); + else + memset(device->update_state->viewports, 0, sizeof(device->update_state->viewports)); + device->update_state->viewport_count = viewport_count;
/* Handle recording of state blocks */ if (device->recording) @@ -1925,14 +1936,14 @@ void CDECL wined3d_device_set_viewport(struct wined3d_device *device, const stru return; }
- wined3d_cs_emit_set_viewport(device->cs, viewport); + wined3d_cs_emit_set_viewports(device->cs, viewport_count, viewports); }
void CDECL wined3d_device_get_viewport(const struct wined3d_device *device, struct wined3d_viewport *viewport) { TRACE("device %p, viewport %p.\n", device, viewport);
- *viewport = device->state.viewport; + *viewport = device->state.viewports[0]; }
static void resolve_depth_buffer(struct wined3d_device *device) @@ -4448,19 +4459,18 @@ HRESULT CDECL wined3d_device_set_rendertarget_view(struct wined3d_device *device { struct wined3d_state *state = &device->state;
- state->viewport.x = 0; - state->viewport.y = 0; - state->viewport.width = view->width; - state->viewport.height = view->height; - state->viewport.min_z = 0.0f; - state->viewport.max_z = 1.0f; - wined3d_cs_emit_set_viewport(device->cs, &state->viewport); + state->viewports[0].x = 0; + state->viewports[0].y = 0; + state->viewports[0].width = view->width; + state->viewports[0].height = view->height; + state->viewports[0].min_z = 0.0f; + state->viewports[0].max_z = 1.0f; + 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); }
- prev = device->fb.render_targets[view_idx]; if (view == prev) return WINED3D_OK; @@ -4960,11 +4970,11 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device, wined3d_device_set_rendertarget_view(device, 0, view, FALSE);
/* Note the min_z / max_z is not reset. */ - state->viewport.x = 0; - state->viewport.y = 0; - state->viewport.width = view->width; - state->viewport.height = view->height; - wined3d_cs_emit_set_viewport(device->cs, &state->viewport); + state->viewports[0].x = 0; + state->viewports[0].y = 0; + state->viewports[0].width = view->width; + state->viewports[0].height = view->height; + 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); diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 121892dd47..acd2c48a63 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -6766,6 +6766,14 @@ static void shader_glsl_input_pack(const struct wined3d_shader *shader, struct w else FIXME("ARB_fragment_layer_viewport is not supported.\n"); } + else if (input->sysval_semantic == WINED3D_SV_VIEWPORT_ARRAY_INDEX && !semantic_idx) + { + if (gl_info->supported[ARB_VIEWPORT_ARRAY]) + shader_addline(buffer, "ps_in[%u]%s = intBitsToFloat(gl_ViewportIndex);\n", + input->register_idx, reg_mask); + else + FIXME("ARB_viewport_array is not supported.\n"); + } else { if (input->sysval_semantic) @@ -7057,6 +7065,11 @@ static void shader_glsl_setup_sm3_rasterizer_input(struct shader_glsl_priv *priv shader_addline(buffer, "gl_Layer = floatBitsToInt(outputs[%u])%s;\n", output->register_idx, reg_mask); } + else if (output->sysval_semantic == WINED3D_SV_VIEWPORT_ARRAY_INDEX && !semantic_idx) + { + shader_addline(buffer, "gl_ViewportIndex = floatBitsToInt(outputs[%u])%s;\n", + output->register_idx, reg_mask); + } else if (output->sysval_semantic == WINED3D_SV_CLIP_DISTANCE) { shader_glsl_generate_clip_or_cull_distances(buffer, output, reg_maps_out->clip_distance_mask); diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c index 83cc484be8..5a37fadabd 100644 --- a/dlls/wined3d/state.c +++ b/dlls/wined3d/state.c @@ -4514,21 +4514,24 @@ static void vertexdeclaration(struct wined3d_context *context, const struct wine } }
-static void get_viewport(struct wined3d_context *context, const struct wined3d_state *state, - struct wined3d_viewport *viewport) +static void get_viewports(struct wined3d_context *context, const struct wined3d_state *state, + unsigned int viewport_count, struct wined3d_viewport *viewports) { const struct wined3d_rendertarget_view *depth_stencil = state->fb->depth_stencil; const struct wined3d_rendertarget_view *target = state->fb->render_targets[0]; - unsigned int width, height; + unsigned int width, height, i;
- *viewport = state->viewport; - - if (target) + for (i = 0; i < viewport_count; ++i) { - if (viewport->width > target->width) - viewport->width = target->width; - if (viewport->height > target->height) - viewport->height = target->height; + viewports[i] = state->viewports[i]; + + if (target) + { + if (viewports[i].width > target->width) + viewports[i].width = target->width; + if (viewports[i].height > target->height) + viewports[i].height = target->height; + } }
/* @@ -4552,22 +4555,45 @@ static void get_viewport(struct wined3d_context *context, const struct wined3d_s return; }
- viewport->y = height - (viewport->y + viewport->height); + for (i = 0; i < viewport_count; ++i) + viewports[i].y = height - (viewports[i].y + viewports[i].height); }
static void viewport_miscpart(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { const struct wined3d_gl_info *gl_info = context->gl_info; - struct wined3d_viewport vp; + struct wined3d_viewport vp[WINED3D_MAX_VIEWPORTS]; + + if (gl_info->supported[ARB_VIEWPORT_ARRAY]) + { + unsigned int i, reset_count = 0;
- get_viewport(context, state, &vp); + get_viewports(context, state, state->viewport_count, vp); + for (i = 0; i < state->viewport_count; ++i) + { + GL_EXTCALL(glDepthRangeIndexed(i, vp[i].min_z, vp[i].max_z)); + GL_EXTCALL(glViewportIndexedf(i, vp[i].x, vp[i].y, vp[i].width, vp[i].height)); + }
- gl_info->gl_ops.gl.p_glDepthRange(vp.min_z, vp.max_z); + if (context->viewport_count > state->viewport_count) + reset_count = context->viewport_count - state->viewport_count;
- if (gl_info->supported[ARB_VIEWPORT_ARRAY]) - GL_EXTCALL(glViewportIndexedf(0, vp.x, vp.y, vp.width, vp.height)); + if (reset_count) + { + static const GLfloat reset[4 * WINED3D_MAX_VIEWPORTS]; + static const GLdouble resetd[2 * WINED3D_MAX_VIEWPORTS]; + + GL_EXTCALL(glDepthRangeArrayv(state->viewport_count, reset_count, resetd)); + GL_EXTCALL(glViewportArrayv(state->viewport_count, reset_count, reset)); + } + context->viewport_count = state->viewport_count; + } else - gl_info->gl_ops.gl.p_glViewport(vp.x, vp.y, vp.width, vp.height); + { + get_viewports(context, state, 1, vp); + gl_info->gl_ops.gl.p_glDepthRange(vp[0].min_z, vp[0].max_z); + gl_info->gl_ops.gl.p_glViewport(vp[0].x, vp[0].y, vp[0].width, vp[0].height); + } checkGLcall("setting clip space and viewport"); }
@@ -4578,16 +4604,34 @@ static void viewport_miscpart_cc(struct wined3d_context *context, float pixel_center_offset = context->d3d_info->wined3d_creation_flags & WINED3D_PIXEL_CENTER_INTEGER ? 63.0f / 128.0f : -1.0f / 128.0f; const struct wined3d_gl_info *gl_info = context->gl_info; - struct wined3d_viewport vp; - - get_viewport(context, state, &vp); - vp.x += pixel_center_offset; - vp.y += pixel_center_offset; + struct wined3d_viewport vp[WINED3D_MAX_VIEWPORTS]; + unsigned int i, reset_count = 0;
- gl_info->gl_ops.gl.p_glDepthRange(vp.min_z, vp.max_z); + get_viewports(context, state, state->viewport_count, vp);
GL_EXTCALL(glClipControl(context->render_offscreen ? GL_UPPER_LEFT : GL_LOWER_LEFT, GL_ZERO_TO_ONE)); - GL_EXTCALL(glViewportIndexedf(0, vp.x, vp.y, vp.width, vp.height)); + + for (i = 0; i < state->viewport_count; ++i) + { + vp[i].x += pixel_center_offset; + vp[i].y += pixel_center_offset; + GL_EXTCALL(glDepthRangeIndexed(i, vp[i].min_z, vp[i].max_z)); + GL_EXTCALL(glViewportIndexedf(i, vp[i].x, vp[i].y, vp[i].width, vp[i].height)); + } + + if (context->viewport_count > state->viewport_count) + reset_count = context->viewport_count - state->viewport_count; + + if (reset_count) + { + static const GLfloat reset[4 * WINED3D_MAX_VIEWPORTS]; + static const GLdouble resetd[2 * WINED3D_MAX_VIEWPORTS]; + + GL_EXTCALL(glDepthRangeArrayv(state->viewport_count, reset_count, resetd)); + GL_EXTCALL(glViewportArrayv(state->viewport_count, reset_count, reset)); + } + context->viewport_count = state->viewport_count; + checkGLcall("setting clip space and viewport"); }
diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c index 4c28eb55e8..d6a7189d83 100644 --- a/dlls/wined3d/stateblock.c +++ b/dlls/wined3d/stateblock.c @@ -811,11 +811,15 @@ void CDECL wined3d_stateblock_capture(struct wined3d_stateblock *stateblock) }
if (stateblock->changed.viewport - && memcmp(&src_state->viewport, &stateblock->state.viewport, sizeof(stateblock->state.viewport))) + && src_state->viewport_count != stateblock->state.viewport_count + && memcmp(src_state->viewports, stateblock->state.viewports, sizeof(stateblock->state.viewports))) { - TRACE("Updating viewport.\n"); + TRACE("Updating viewports.\n");
- stateblock->state.viewport = src_state->viewport; + if ((stateblock->state.viewport_count = src_state->viewport_count)) + memcpy(stateblock->state.viewports, src_state->viewports, sizeof(src_state->viewports)); + else + memset(stateblock->state.viewports, 0, sizeof(*stateblock->state.viewports)); }
if (stateblock->changed.scissorRect && memcmp(&src_state->scissor_rect, @@ -1055,7 +1059,7 @@ void CDECL wined3d_stateblock_apply(const struct wined3d_stateblock *stateblock) wined3d_device_set_material(device, &stateblock->state.material);
if (stateblock->changed.viewport) - wined3d_device_set_viewport(device, &stateblock->state.viewport); + 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); diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index 0775f53b7a..cf199b955a 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -4865,10 +4865,10 @@ void get_projection_matrix(const struct wined3d_context *context, const struct w if (context->last_was_rhw) { /* Transform D3D RHW coordinates to OpenGL clip coordinates. */ - float x = state->viewport.x; - float y = state->viewport.y; - float w = state->viewport.width; - float h = state->viewport.height; + float x = state->viewports[0].x; + float y = state->viewports[0].y; + float w = state->viewports[0].width; + float h = state->viewports[0].height; float x_scale = 2.0f / w; float x_offset = (center_offset - (2.0f * x) - w) / w; float y_scale = flip ? 2.0f / h : 2.0f / -h; @@ -4892,10 +4892,10 @@ void get_projection_matrix(const struct wined3d_context *context, const struct w else { float y_scale = flip ? -1.0f : 1.0f; - float x_offset = center_offset / state->viewport.width; + float x_offset = center_offset / state->viewports[0].width; float y_offset = flip - ? center_offset / state->viewport.height - : -center_offset / state->viewport.height; + ? center_offset / state->viewports[0].height + : -center_offset / state->viewports[0].height; float z_scale = clip_control ? 1.0f : 2.0f; float z_offset = clip_control ? 0.0f : -1.0f; const struct wined3d_matrix projection = @@ -5097,7 +5097,7 @@ void get_pointsize(const struct wined3d_context *context, const struct wined3d_s
if (state->render_states[WINED3D_RS_POINTSCALEENABLE]) { - float scale_factor = state->viewport.height * state->viewport.height; + float scale_factor = state->viewports[0].height * state->viewports[0].height;
out_att[0] = a.f / scale_factor; out_att[1] = b.f / scale_factor; diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index 16d22f5263..b4c41cc59a 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -187,7 +187,7 @@ @ cdecl wined3d_device_set_unordered_access_view(ptr long ptr long) @ cdecl wined3d_device_set_vertex_declaration(ptr ptr) @ cdecl wined3d_device_set_vertex_shader(ptr ptr) -@ cdecl wined3d_device_set_viewport(ptr ptr) +@ cdecl wined3d_device_set_viewports(ptr long ptr) @ cdecl wined3d_device_set_vs_cb(ptr long ptr) @ cdecl wined3d_device_set_vs_consts_b(ptr long long ptr) @ cdecl wined3d_device_set_vs_consts_f(ptr long long ptr) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index cdea1125f3..69b8b0d935 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1990,6 +1990,8 @@ struct wined3d_context GLfloat fog_coord_value; GLfloat color[4], fogstart, fogend, fogcolor[4]; GLuint dummy_arbfp_prog; + + unsigned int viewport_count; };
struct wined3d_fb_state @@ -2843,7 +2845,8 @@ struct wined3d_state struct wined3d_matrix transforms[HIGHEST_TRANSFORMSTATE + 1]; struct wined3d_vec4 clip_planes[MAX_CLIP_DISTANCES]; struct wined3d_material material; - struct wined3d_viewport viewport; + struct wined3d_viewport viewports[WINED3D_MAX_VIEWPORTS]; + unsigned int viewport_count; RECT scissor_rect;
/* Light hashmap. Collisions are handled using linked lists. */ @@ -3592,7 +3595,7 @@ void wined3d_cs_emit_set_unordered_access_view(struct wined3d_cs *cs, enum wined unsigned int initial_count) DECLSPEC_HIDDEN; void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs, struct wined3d_vertex_declaration *declaration) DECLSPEC_HIDDEN; -void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport *viewport) DECLSPEC_HIDDEN; +void wined3d_cs_emit_set_viewports(struct wined3d_cs *cs, unsigned int viewport_count, const struct wined3d_viewport *viewports) DECLSPEC_HIDDEN; void wined3d_cs_emit_unload_resource(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN; void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_resource *resource, unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch, @@ -4106,8 +4109,8 @@ static inline void shader_get_position_fixup(const struct wined3d_context *conte
position_fixup[0] = 1.0f; position_fixup[1] = 1.0f; - position_fixup[2] = center_offset / state->viewport.width; - position_fixup[3] = -center_offset / state->viewport.height; + position_fixup[2] = center_offset / state->viewports[0].width; + position_fixup[3] = -center_offset / state->viewports[0].height;
if (context->render_offscreen) { diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 446e98b96f..3539b4eb06 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -1561,6 +1561,8 @@ enum wined3d_shader_byte_code_format #define WINED3D_VIEW_TEXTURE_CUBE 0x00000008 #define WINED3D_VIEW_TEXTURE_ARRAY 0x00000010
+#define WINED3D_MAX_VIEWPORTS 16 + struct wined3d_display_mode { UINT width; @@ -2440,7 +2442,8 @@ void __cdecl wined3d_device_set_unordered_access_view(struct wined3d_device *dev void __cdecl wined3d_device_set_vertex_declaration(struct wined3d_device *device, struct wined3d_vertex_declaration *declaration); void __cdecl wined3d_device_set_vertex_shader(struct wined3d_device *device, struct wined3d_shader *shader); -void __cdecl wined3d_device_set_viewport(struct wined3d_device *device, const struct wined3d_viewport *viewport); +void __cdecl wined3d_device_set_viewports(struct wined3d_device *device, unsigned int viewport_count, + const struct wined3d_viewport *viewports); void __cdecl wined3d_device_set_vs_cb(struct wined3d_device *device, UINT idx, struct wined3d_buffer *buffer); HRESULT __cdecl wined3d_device_set_vs_consts_b(struct wined3d_device *device, unsigned int start_idx, unsigned int count, const BOOL *constants);