Commit a5d2b362 authored by Matteo Bruni's avatar Matteo Bruni Committed by Alexandre Julliard

wined3d: Use ARB_clip_control to avoid vertex position fixups.

parent 94956da9
......@@ -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");
......
......@@ -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;
......
......@@ -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");
......
......@@ -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);
}
......
......@@ -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 },
......
......@@ -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]);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment