[PATCH 6/6] wined3d: Use ARB_clip_control to avoid vertex position fixups.
Matteo Bruni
mbruni at codeweavers.com
Mon Oct 3 16:46:56 CDT 2016
Signed-off-by: Matteo Bruni <mbruni at codeweavers.com>
---
FTR, next in the queue there are a couple tests for the derivative
shader instructions.
dlls/wined3d/arb_program_shader.c | 32 ++++++++++----------
dlls/wined3d/context.c | 15 ++++++++--
dlls/wined3d/directx.c | 17 +++++++++++
dlls/wined3d/glsl_shader.c | 26 +++++++++++-----
dlls/wined3d/state.c | 63 +++++++++++++++++++++++++++++++++++++++
dlls/wined3d/utils.c | 26 +++++++++-------
6 files changed, 143 insertions(+), 36 deletions(-)
diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index f8ecb80..87794ea 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -3264,22 +3264,24 @@ static void vshader_add_footer(struct shader_arb_ctx_priv *priv_ctx,
* 1.0 or -1.0 to turn the rendering upside down for offscreen rendering. PosFixup.x
* contains 1.0 to allow a mad, but arb vs swizzles are too restricted for that.
*/
- shader_addline(buffer, "MUL TA, posFixup, TMP_OUT.w;\n");
- shader_addline(buffer, "ADD TMP_OUT.x, TMP_OUT.x, TA.z;\n");
- shader_addline(buffer, "MAD TMP_OUT.y, TMP_OUT.y, posFixup.y, TA.w;\n");
-
- /* Z coord [0;1]->[-1;1] mapping, see comment in transform_projection in state.c
- * and the glsl equivalent
- */
- if (need_helper_const(shader_data, reg_maps, gl_info))
- {
- const char *two = arb_get_helper_value(WINED3D_SHADER_TYPE_VERTEX, ARB_TWO);
- shader_addline(buffer, "MAD TMP_OUT.z, TMP_OUT.z, %s, -TMP_OUT.w;\n", two);
- }
- else
+ if (!gl_info->supported[ARB_CLIP_CONTROL])
{
- shader_addline(buffer, "ADD TMP_OUT.z, TMP_OUT.z, TMP_OUT.z;\n");
- shader_addline(buffer, "ADD TMP_OUT.z, TMP_OUT.z, -TMP_OUT.w;\n");
+ shader_addline(buffer, "MUL TA, posFixup, TMP_OUT.w;\n");
+ shader_addline(buffer, "ADD TMP_OUT.x, TMP_OUT.x, TA.z;\n");
+ shader_addline(buffer, "MAD TMP_OUT.y, TMP_OUT.y, posFixup.y, TA.w;\n");
+
+ /* Z coord [0;1]->[-1;1] mapping, see comment in
+ * get_projection_matrix() in utils.c. */
+ if (need_helper_const(shader_data, reg_maps, gl_info))
+ {
+ const char *two = arb_get_helper_value(WINED3D_SHADER_TYPE_VERTEX, ARB_TWO);
+ shader_addline(buffer, "MAD TMP_OUT.z, TMP_OUT.z, %s, -TMP_OUT.w;\n", two);
+ }
+ else
+ {
+ shader_addline(buffer, "ADD TMP_OUT.z, TMP_OUT.z, TMP_OUT.z;\n");
+ shader_addline(buffer, "ADD TMP_OUT.z, TMP_OUT.z, -TMP_OUT.w;\n");
+ }
}
shader_addline(buffer, "MOV result.position, TMP_OUT;\n");
diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index 8c08310..fa47850 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -1971,6 +1971,8 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
{
GL_EXTCALL(glProvokingVertexEXT(GL_FIRST_VERTEX_CONVENTION_EXT));
}
+ if (gl_info->supported[ARB_CLIP_CONTROL])
+ GL_EXTCALL(glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT));
device->shader_backend->shader_init_context_state(ret);
ret->shader_update_mask = (1u << WINED3D_SHADER_TYPE_PIXEL)
| (1u << WINED3D_SHADER_TYPE_VERTEX)
@@ -2261,6 +2263,10 @@ static void SetupForBlit(const struct wined3d_device *device, struct wined3d_con
gl_info->gl_ops.gl.p_glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)");
context_invalidate_state(context, STATE_RENDER(WINED3D_RS_CLIPPING));
+ /* FIXME: Make draw_textured_quad() able to work with a upper left origin. */
+ if (gl_info->supported[ARB_CLIP_CONTROL])
+ GL_EXTCALL(glClipControl(GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE));
+
set_blit_dimension(gl_info, rt_size.cx, rt_size.cy);
/* Disable shaders */
@@ -2413,11 +2419,14 @@ static void context_set_render_offscreen(struct wined3d_context *context, BOOL o
{
if (context->render_offscreen == offscreen) return;
- context_invalidate_state(context, STATE_POINTSPRITECOORDORIGIN);
- context_invalidate_state(context, STATE_TRANSFORM(WINED3D_TS_PROJECTION));
context_invalidate_state(context, STATE_VIEWPORT);
context_invalidate_state(context, STATE_SCISSORRECT);
- context_invalidate_state(context, STATE_FRONTFACE);
+ if (!context->gl_info->supported[ARB_CLIP_CONTROL])
+ {
+ context_invalidate_state(context, STATE_FRONTFACE);
+ context_invalidate_state(context, STATE_POINTSPRITECOORDORIGIN);
+ context_invalidate_state(context, STATE_TRANSFORM(WINED3D_TS_PROJECTION));
+ }
if (context->gl_info->supported[ARB_FRAGMENT_COORD_CONVENTIONS])
context_invalidate_state(context, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL));
context->render_offscreen = offscreen;
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index b03ddf6..5d91981 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -3856,6 +3856,23 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter, DWORD
if (!counter_bits)
gl_info->supported[ARB_TIMER_QUERY] = FALSE;
}
+ if (gl_info->supported[ARB_VIEWPORT_ARRAY])
+ {
+ GLint subpixel_bits;
+
+ gl_info->gl_ops.gl.p_glGetIntegerv(GL_VIEWPORT_SUBPIXEL_BITS, &subpixel_bits);
+ TRACE("Viewport supports %d subpixel bits.\n", subpixel_bits);
+ if (!subpixel_bits)
+ gl_info->supported[ARB_VIEWPORT_ARRAY] = FALSE;
+ }
+ if (gl_info->supported[ARB_CLIP_CONTROL] && !gl_info->supported[ARB_VIEWPORT_ARRAY])
+ {
+ /* When using ARB_clip_control we need the float viewport parameters
+ * introduced by ARB_viewport_array to take care of the shifted pixel
+ * coordinates. */
+ TRACE("Disabling ARB_clip_control because ARB_viewport_array is not supported.\n");
+ gl_info->supported[ARB_CLIP_CONTROL] = FALSE;
+ }
if (!gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] && gl_info->supported[EXT_TEXTURE_MIRROR_CLAMP])
{
TRACE(" IMPLIED: ATI_texture_mirror_once support (by EXT_texture_mirror_clamp).\n");
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 72740af..0a7af72 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -4398,7 +4398,8 @@ static void shader_glsl_emit(const struct wined3d_shader_instruction *ins)
unsigned int stream = ins->handler_idx == WINED3DSIH_EMIT ? 0 : ins->src[0].reg.idx[0].offset;
shader_addline(ins->ctx->buffer, "setup_gs_output(gs_out);\n");
- shader_glsl_fixup_position(ins->ctx->buffer);
+ if (!ins->ctx->gl_info->supported[ARB_CLIP_CONTROL])
+ shader_glsl_fixup_position(ins->ctx->buffer);
if (!stream)
shader_addline(ins->ctx->buffer, "EmitVertex();\n");
@@ -6046,7 +6047,7 @@ static GLuint shader_glsl_generate_vshader(const struct wined3d_context *context
/* Base Declarations */
shader_generate_glsl_declarations(context, buffer, shader, reg_maps, &priv_ctx);
- if (args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL)
+ if (args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL && !gl_info->supported[ARB_CLIP_CONTROL])
shader_addline(buffer, "uniform vec4 pos_fixup;\n");
if (reg_maps->shader_version.major >= 4)
@@ -6093,7 +6094,7 @@ static GLuint shader_glsl_generate_vshader(const struct wined3d_context *context
if (args->point_size && !args->per_vertex_point_size)
shader_addline(buffer, "gl_PointSize = clamp(ffp_point.size, ffp_point.size_min, ffp_point.size_max);\n");
- if (args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL)
+ if (args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL && !gl_info->supported[ARB_CLIP_CONTROL])
shader_glsl_fixup_position(buffer);
shader_addline(buffer, "}\n");
@@ -6127,7 +6128,8 @@ static GLuint shader_glsl_generate_geometry_shader(const struct wined3d_context
memset(&priv_ctx, 0, sizeof(priv_ctx));
priv_ctx.string_buffers = string_buffers;
shader_generate_glsl_declarations(context, buffer, shader, reg_maps, &priv_ctx);
- shader_addline(buffer, "uniform vec4 pos_fixup;\n");
+ if (!gl_info->supported[ARB_CLIP_CONTROL])
+ shader_addline(buffer, "uniform vec4 pos_fixup;\n");
shader_glsl_generate_sm4_rasterizer_input_setup(priv, shader, args->ps_input_count, gl_info);
shader_addline(buffer, "void main()\n{\n");
shader_generate_main(shader, buffer, reg_maps, function, &priv_ctx);
@@ -6767,12 +6769,21 @@ static GLuint shader_glsl_generate_ffp_vertex_shader(struct shader_glsl_priv *pr
case WINED3D_FFP_VS_FOG_DEPTH:
if (settings->ortho_fog)
- /* Need to undo the [0.0 - 1.0] -> [-1.0 - 1.0] transformation from D3D to GL coordinates. */
- shader_addline(buffer, "ffp_varying_fogcoord = gl_Position.z * 0.5 + 0.5;\n");
+ {
+ if (gl_info->supported[ARB_CLIP_CONTROL])
+ shader_addline(buffer, "ffp_varying_fogcoord = gl_Position.z;\n");
+ else
+ /* Need to undo the [0.0 - 1.0] -> [-1.0 - 1.0] transformation from D3D to GL coordinates. */
+ shader_addline(buffer, "ffp_varying_fogcoord = gl_Position.z * 0.5 + 0.5;\n");
+ }
else if (settings->transformed)
+ {
shader_addline(buffer, "ffp_varying_fogcoord = ec_pos.z;\n");
+ }
else
+ {
shader_addline(buffer, "ffp_varying_fogcoord = abs(ec_pos.z);\n");
+ }
break;
default:
@@ -7994,7 +8005,8 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const
if (gshader)
{
- entry->constant_update_mask |= WINED3D_SHADER_CONST_POS_FIXUP;
+ if (entry->gs.pos_fixup_location != -1)
+ entry->constant_update_mask |= WINED3D_SHADER_CONST_POS_FIXUP;
shader_glsl_init_uniform_block_bindings(gl_info, priv, program_id, &gshader->reg_maps);
shader_glsl_load_icb(gl_info, priv, program_id, &gshader->reg_maps);
}
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index 1b0d018..3b96acc 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -4648,6 +4648,55 @@ static void viewport_miscpart(struct wined3d_context *context, const struct wine
checkGLcall("glViewport");
}
+static void viewport_miscpart_cc(struct wined3d_context *context,
+ const struct wined3d_state *state, DWORD state_id)
+{
+ const struct wined3d_rendertarget_view *depth_stencil = state->fb->depth_stencil;
+ const struct wined3d_rendertarget_view *target = state->fb->render_targets[0];
+ float pixel_center_offset = context->swapchain->device->wined3d->flags
+ & WINED3D_PIXEL_CENTER_INTEGER ? 0.5f : 0.0f;
+ const struct wined3d_gl_info *gl_info = context->gl_info;
+ struct wined3d_viewport vp = state->viewport;
+ unsigned int width, height;
+
+ if (target)
+ {
+ if (vp.width > target->width)
+ vp.width = target->width;
+ if (vp.height > target->height)
+ vp.height = target->height;
+
+ surface_get_drawable_size(wined3d_rendertarget_view_get_surface(target), context, &width, &height);
+ }
+ else if (depth_stencil)
+ {
+ width = depth_stencil->width;
+ height = depth_stencil->height;
+ }
+ else
+ {
+ FIXME("No attachments draw calls not supported.\n");
+ return;
+ }
+
+ gl_info->gl_ops.gl.p_glDepthRange(vp.min_z, vp.max_z);
+ checkGLcall("glDepthRange");
+
+ if (context->render_offscreen)
+ {
+ GL_EXTCALL(glClipControl(GL_UPPER_LEFT, GL_ZERO_TO_ONE));
+ GL_EXTCALL(glViewportIndexedf(0, vp.x + pixel_center_offset, vp.y + pixel_center_offset,
+ vp.width, vp.height));
+ }
+ else
+ {
+ GL_EXTCALL(glClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE));
+ GL_EXTCALL(glViewportIndexedf(0, vp.x + pixel_center_offset,
+ (height - (vp.y + vp.height)) + pixel_center_offset, vp.width, vp.height));
+ }
+ checkGLcall("setting clip space and viewport");
+}
+
static void viewport_vertexpart(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
{
if (!isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_PROJECTION)))
@@ -4837,6 +4886,17 @@ static void frontface(struct wined3d_context *context, const struct wined3d_stat
checkGLcall("glFrontFace");
}
+static void frontface_cc(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+ const struct wined3d_gl_info *gl_info = context->gl_info;
+ GLenum mode;
+
+ mode = state->rasterizer_state && state->rasterizer_state->desc.front_ccw ? GL_CCW : GL_CW;
+
+ gl_info->gl_ops.gl.p_glFrontFace(mode);
+ checkGLcall("glFrontFace");
+}
+
static void psorigin_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
{
static BOOL warned;
@@ -4923,8 +4983,10 @@ const struct StateEntryTemplate misc_state_template[] =
{ STATE_RENDER(WINED3D_RS_BLENDOPALPHA), { STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE },
{ STATE_STREAMSRC, { STATE_STREAMSRC, streamsrc }, WINED3D_GL_EXT_NONE },
{ STATE_VDECL, { STATE_VDECL, vdecl_miscpart }, WINED3D_GL_EXT_NONE },
+ { STATE_FRONTFACE, { STATE_FRONTFACE, frontface_cc }, ARB_CLIP_CONTROL },
{ STATE_FRONTFACE, { STATE_FRONTFACE, frontface }, WINED3D_GL_EXT_NONE },
{ STATE_SCISSORRECT, { STATE_SCISSORRECT, scissorrect }, WINED3D_GL_EXT_NONE },
+ { STATE_POINTSPRITECOORDORIGIN, { STATE_POINTSPRITECOORDORIGIN, state_nop }, ARB_CLIP_CONTROL },
{ STATE_POINTSPRITECOORDORIGIN, { STATE_POINTSPRITECOORDORIGIN, psorigin }, WINED3D_GL_VERSION_2_0 },
{ STATE_POINTSPRITECOORDORIGIN, { STATE_POINTSPRITECOORDORIGIN, psorigin_w }, WINED3D_GL_EXT_NONE },
@@ -4980,6 +5042,7 @@ const struct StateEntryTemplate misc_state_template[] =
{ STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE), { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE), shader_bumpenv }, WINED3D_GL_EXT_NONE },
{ STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LOFFSET), { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE), NULL }, WINED3D_GL_EXT_NONE },
+ { STATE_VIEWPORT, { STATE_VIEWPORT, viewport_miscpart_cc}, ARB_CLIP_CONTROL },
{ STATE_VIEWPORT, { STATE_VIEWPORT, viewport_miscpart }, WINED3D_GL_EXT_NONE },
{ STATE_INDEXBUFFER, { STATE_INDEXBUFFER, indexbuffer }, ARB_VERTEX_BUFFER_OBJECT },
{ STATE_INDEXBUFFER, { STATE_INDEXBUFFER, state_nop }, WINED3D_GL_EXT_NONE },
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index 0dae0d0..173b028 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -4494,6 +4494,8 @@ void get_modelview_matrix(const struct wined3d_context *context, const struct wi
void get_projection_matrix(const struct wined3d_context *context, const struct wined3d_state *state,
struct wined3d_matrix *mat)
{
+ BOOL clip_control = context->gl_info->supported[ARB_CLIP_CONTROL];
+ BOOL flip = !clip_control && context->render_offscreen;
float center_offset;
/* There are a couple of additional things we have to take into account
@@ -4511,7 +4513,7 @@ void get_projection_matrix(const struct wined3d_context *context, const struct w
* driver, but small enough to prevent it from interfering with any
* anti-aliasing. */
- if (context->swapchain->device->wined3d->flags & WINED3D_PIXEL_CENTER_INTEGER)
+ if (!clip_control && context->swapchain->device->wined3d->flags & WINED3D_PIXEL_CENTER_INTEGER)
center_offset = 63.0f / 64.0f;
else
center_offset = -1.0f / 64.0f;
@@ -4525,14 +4527,14 @@ void get_projection_matrix(const struct wined3d_context *context, const struct w
float h = state->viewport.height;
float x_scale = 2.0f / w;
float x_offset = (center_offset - (2.0f * x) - w) / w;
- float y_scale = context->render_offscreen ? 2.0f / h : 2.0f / -h;
- float y_offset = context->render_offscreen
+ float y_scale = flip ? 2.0f / h : 2.0f / -h;
+ float y_offset = flip
? (center_offset - (2.0f * y) - h) / h
: (center_offset - (2.0f * y) - h) / -h;
enum wined3d_depth_buffer_type zenable = state->fb->depth_stencil ?
state->render_states[WINED3D_RS_ZENABLE] : WINED3D_ZB_FALSE;
- float z_scale = zenable ? 2.0f : 0.0f;
- float z_offset = zenable ? -1.0f : 0.0f;
+ float z_scale = zenable ? clip_control ? 1.0f : 2.0f : 0.0f;
+ float z_offset = zenable ? clip_control ? 0.0f : -1.0f : 0.0f;
const struct wined3d_matrix projection =
{
x_scale, 0.0f, 0.0f, 0.0f,
@@ -4545,17 +4547,19 @@ void get_projection_matrix(const struct wined3d_context *context, const struct w
}
else
{
- float y_scale = context->render_offscreen ? -1.0f : 1.0f;
+ float y_scale = flip ? -1.0f : 1.0f;
float x_offset = center_offset / state->viewport.width;
- float y_offset = context->render_offscreen
+ float y_offset = flip
? center_offset / state->viewport.height
: -center_offset / state->viewport.height;
+ float z_scale = clip_control ? 1.0f : 2.0f;
+ float z_offset = clip_control ? 0.0f : -1.0f;
const struct wined3d_matrix projection =
{
- 1.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, y_scale, 0.0f, 0.0f,
- 0.0f, 0.0f, 2.0f, 0.0f,
- x_offset, y_offset, -1.0f, 1.0f,
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, y_scale, 0.0f, 0.0f,
+ 0.0f, 0.0f, z_scale, 0.0f,
+ x_offset, y_offset, z_offset, 1.0f,
};
multiply_matrix(mat, &projection, &state->transforms[WINED3D_TS_PROJECTION]);
--
2.7.3
More information about the wine-patches
mailing list