[PATCH 5/5] wined3d: Alpha test emulation for core profile contexts.
Matteo Bruni
mbruni at codeweavers.com
Thu Mar 31 12:51:00 CDT 2016
Signed-off-by: Matteo Bruni <mbruni at codeweavers.com>
---
dlls/wined3d/glsl_shader.c | 117 ++++++++++++++++++++++++++++++++++-------
dlls/wined3d/shader.c | 5 ++
dlls/wined3d/utils.c | 5 ++
dlls/wined3d/wined3d_private.h | 30 +++++++----
4 files changed, 129 insertions(+), 28 deletions(-)
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index dbb0956..4801e1f 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -178,6 +178,8 @@ struct glsl_ps_program
GLint fog_density_location;
GLint fog_end_location;
GLint fog_scale_location;
+ GLint alpha_test_location;
+ GLint alpha_ref_location;
GLint ycorrection_location;
GLint np2_fixup_location;
GLint color_key_location;
@@ -1480,6 +1482,22 @@ static void shader_glsl_load_constants(void *shader_priv, struct wined3d_context
if (update_mask & WINED3D_SHADER_CONST_PS_FOG)
shader_glsl_load_fog_uniform(context, state, prog);
+ if (update_mask & WINED3D_SHADER_CONST_PS_ALPHA_TEST)
+ {
+ if (state->render_states[WINED3D_RS_ALPHATESTENABLE])
+ {
+ float ref = state->render_states[WINED3D_RS_ALPHAREF] / 255.0f;
+
+ GL_EXTCALL(glUniform1i(prog->ps.alpha_test_location, TRUE));
+ GL_EXTCALL(glUniform1f(prog->ps.alpha_ref_location, ref));
+ }
+ else
+ {
+ GL_EXTCALL(glUniform1i(prog->ps.alpha_test_location, FALSE));
+ }
+ checkGLcall("alpha test emulation uniforms");
+ }
+
if (priv->next_constant_version == UINT_MAX)
{
TRACE("Max constant version reached, resetting to 0.\n");
@@ -2014,6 +2032,12 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
shader_addline(buffer, "vec4 vpos;\n");
}
+ if (ps_args->alpha_func != WINED3D_CMP_ALWAYS)
+ {
+ shader_addline(buffer, "uniform bool alpha_test;\n");
+ shader_addline(buffer, "uniform float alpha_ref;\n");
+ }
+
if (!needs_legacy_glsl_syntax(gl_info))
shader_addline(buffer, "out vec4 ps_out[%u];\n", gl_info->limits.buffers);
@@ -5446,6 +5470,33 @@ static void shader_glsl_generate_fog_code(struct wined3d_string_buffer *buffer,
output, output);
}
+static void shader_glsl_generate_alpha_test(struct wined3d_string_buffer *buffer,
+ const struct wined3d_gl_info *gl_info, enum wined3d_cmp_func alpha_func)
+{
+ /* alpha_func is the PASS condition, not the DISCARD condition. Instead of
+ * flipping all the operators here, just negate the comparison below. */
+ static const char *comparison_operator[] =
+ {
+ "", /* WINED3D_CMP_NEVER */
+ "<", /* WINED3D_CMP_LESS */
+ "==", /* WINED3D_CMP_EQUAL */
+ "<=", /* WINED3D_CMP_LESSEQUAL */
+ ">", /* WINED3D_CMP_GREATER */
+ "!=", /* WINED3D_CMP_NOTEQUAL */
+ ">=", /* WINED3D_CMP_GREATEREQUAL */
+ "" /* WINED3D_CMP_ALWAYS */
+ };
+
+ if (alpha_func == WINED3D_CMP_ALWAYS)
+ return;
+
+ shader_addline(buffer, "if (alpha_test)\n");
+ if (alpha_func != WINED3D_CMP_NEVER)
+ shader_addline(buffer, " if (!(%s[0].a %s alpha_ref))\n",
+ get_fragment_output(gl_info), comparison_operator[alpha_func - WINED3D_CMP_NEVER]);
+ shader_addline(buffer, " discard;\n");
+}
+
/* Context activation is done by the caller. */
static GLuint shader_glsl_generate_pshader(const struct wined3d_context *context,
struct wined3d_string_buffer *buffer, struct wined3d_string_buffer_list *string_buffers,
@@ -5536,6 +5587,8 @@ static GLuint shader_glsl_generate_pshader(const struct wined3d_context *context
if (reg_maps->shader_version.major < 3)
shader_glsl_generate_fog_code(buffer, gl_info, args->fog);
+ shader_glsl_generate_alpha_test(buffer, gl_info, args->alpha_func);
+
shader_addline(buffer, "}\n");
TRACE("Compiling shader object %u.\n", shader_id);
@@ -6695,6 +6748,12 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv *
shader_addline(buffer, " float scale;\n");
shader_addline(buffer, "} ffp_fog;\n");
+ if (settings->alpha_func != WINED3D_CMP_ALWAYS)
+ {
+ shader_addline(buffer, "uniform bool alpha_test;\n");
+ shader_addline(buffer, "uniform float alpha_ref;\n");
+ }
+
if (legacy_context)
{
shader_addline(buffer, "vec4 ffp_varying_diffuse;\n");
@@ -6949,6 +7008,8 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv *
shader_glsl_generate_fog_code(buffer, gl_info, settings->fog);
+ shader_glsl_generate_alpha_test(buffer, gl_info, settings->alpha_func);
+
shader_addline(buffer, "}\n");
shader_id = GL_EXTCALL(glCreateShader(GL_FRAGMENT_SHADER));
@@ -7133,6 +7194,9 @@ static void shader_glsl_init_ps_uniform_locations(const struct wined3d_gl_info *
ps->fog_end_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_fog.end"));
ps->fog_scale_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_fog.scale"));
+ ps->alpha_test_location = GL_EXTCALL(glGetUniformLocation(program_id, "alpha_test"));
+ ps->alpha_ref_location = GL_EXTCALL(glGetUniformLocation(program_id, "alpha_ref"));
+
ps->np2_fixup_location = GL_EXTCALL(glGetUniformLocation(program_id, "ps_samplerNP2Fixup"));
ps->ycorrection_location = GL_EXTCALL(glGetUniformLocation(program_id, "ycorrection"));
ps->color_key_location = GL_EXTCALL(glGetUniformLocation(program_id, "color_key"));
@@ -7480,6 +7544,8 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const
if (entry->ps.fog_color_location != -1)
entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_FOG;
+ if (entry->ps.alpha_test_location != -1)
+ entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_ALPHA_TEST;
if (entry->ps.np2_fixup_location != -1)
entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_NP2_FIXUP;
if (entry->ps.color_key_location != -1)
@@ -8934,34 +9000,46 @@ static void glsl_fragment_pipe_invalidate_constants(struct wined3d_context *cont
context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_PS;
}
-static void glsl_fragment_pipe_alpha_test(struct wined3d_context *context,
+static void glsl_fragment_pipe_core_alpha_func(struct wined3d_context *context,
+ const struct wined3d_state *state, DWORD state_id)
+{
+ context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL;
+}
+
+static void glsl_fragment_pipe_alpha_func(struct wined3d_context *context,
const struct wined3d_state *state, DWORD state_id)
{
const struct wined3d_gl_info *gl_info = context->gl_info;
- int glParm;
- float ref;
+ GLint func = wined3d_gl_compare_func(state->render_states[WINED3D_RS_ALPHAFUNC]);
+ float ref = state->render_states[WINED3D_RS_ALPHAREF] / 255.0f;
- TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);
+ if (func)
+ {
+ gl_info->gl_ops.gl.p_glAlphaFunc(func, ref);
+ checkGLcall("glAlphaFunc");
+ }
+}
+
+static void glsl_fragment_pipe_core_alpha_test(struct wined3d_context *context,
+ const struct wined3d_state *state, DWORD state_id)
+{
+ context->constant_update_mask |= WINED3D_SHADER_CONST_PS_ALPHA_TEST;
+}
+
+static void glsl_fragment_pipe_alpha_test(struct wined3d_context *context,
+ const struct wined3d_state *state, DWORD state_id)
+{
+ const struct wined3d_gl_info *gl_info = context->gl_info;
if (state->render_states[WINED3D_RS_ALPHATESTENABLE])
{
gl_info->gl_ops.gl.p_glEnable(GL_ALPHA_TEST);
- checkGLcall("glEnable GL_ALPHA_TEST");
+ checkGLcall("glEnable(GL_ALPHA_TEST)");
}
else
{
gl_info->gl_ops.gl.p_glDisable(GL_ALPHA_TEST);
- checkGLcall("glDisable GL_ALPHA_TEST");
- return;
- }
-
- ref = ((float)state->render_states[WINED3D_RS_ALPHAREF]) / 255.0f;
- glParm = wined3d_gl_compare_func(state->render_states[WINED3D_RS_ALPHAFUNC]);
-
- if (glParm)
- {
- gl_info->gl_ops.gl.p_glAlphaFunc(glParm, ref);
- checkGLcall("glAlphaFunc");
+ checkGLcall("glDisable(GL_ALPHA_TEST)");
}
}
@@ -9055,9 +9133,12 @@ static const struct StateEntryTemplate glsl_fragment_pipe_state_template[] =
{STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
{STATE_TEXTURESTAGE(7, WINED3D_TSS_RESULT_ARG), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
{STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), glsl_fragment_pipe_shader }, WINED3D_GL_EXT_NONE },
- {STATE_RENDER(WINED3D_RS_ALPHAFUNC), {STATE_RENDER(WINED3D_RS_ALPHATESTENABLE), NULL }, WINED3D_GL_EXT_NONE },
+ {STATE_RENDER(WINED3D_RS_ALPHAFUNC), {STATE_RENDER(WINED3D_RS_ALPHAFUNC), glsl_fragment_pipe_alpha_func }, WINED3D_GL_LEGACY_CONTEXT},
+ {STATE_RENDER(WINED3D_RS_ALPHAFUNC), {STATE_RENDER(WINED3D_RS_ALPHAFUNC), glsl_fragment_pipe_core_alpha_func }, WINED3D_GL_EXT_NONE },
+ {STATE_RENDER(WINED3D_RS_ALPHAREF), {STATE_RENDER(WINED3D_RS_ALPHAFUNC), NULL }, WINED3D_GL_LEGACY_CONTEXT},
{STATE_RENDER(WINED3D_RS_ALPHAREF), {STATE_RENDER(WINED3D_RS_ALPHATESTENABLE), NULL }, WINED3D_GL_EXT_NONE },
- {STATE_RENDER(WINED3D_RS_ALPHATESTENABLE), {STATE_RENDER(WINED3D_RS_ALPHATESTENABLE), glsl_fragment_pipe_alpha_test }, WINED3D_GL_EXT_NONE },
+ {STATE_RENDER(WINED3D_RS_ALPHATESTENABLE), {STATE_RENDER(WINED3D_RS_ALPHATESTENABLE), glsl_fragment_pipe_alpha_test }, WINED3D_GL_LEGACY_CONTEXT},
+ {STATE_RENDER(WINED3D_RS_ALPHATESTENABLE), {STATE_RENDER(WINED3D_RS_ALPHATESTENABLE), glsl_fragment_pipe_core_alpha_test }, WINED3D_GL_EXT_NONE },
{STATE_RENDER(WINED3D_RS_COLORKEYENABLE), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE },
{STATE_COLOR_KEY, { STATE_COLOR_KEY, glsl_fragment_pipe_color_key }, WINED3D_GL_EXT_NONE },
{STATE_RENDER(WINED3D_RS_FOGENABLE), {STATE_RENDER(WINED3D_RS_FOGENABLE), glsl_fragment_pipe_fog }, WINED3D_GL_EXT_NONE },
diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c
index 0aa77b0..4445292 100644
--- a/dlls/wined3d/shader.c
+++ b/dlls/wined3d/shader.c
@@ -2957,6 +2957,11 @@ void find_ps_compile_args(const struct wined3d_state *state, const struct wined3
args->pointsprite = state->render_states[WINED3D_RS_POINTSPRITEENABLE]
&& state->gl_primitive_type == GL_POINTS;
+ if (gl_info->supported[WINED3D_GL_LEGACY_CONTEXT])
+ args->alpha_func = WINED3D_CMP_ALWAYS;
+ else
+ args->alpha_func = wined3d_sanitize_cmp_func(state->render_states[WINED3D_RS_ALPHAFUNC]);
+
if (d3d_info->emulated_flatshading)
args->flatshading = state->render_states[WINED3D_RS_SHADEMODE] == WINED3D_SHADE_FLAT;
}
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index efda6f2..5159c66 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -5093,6 +5093,11 @@ void gen_ffp_frag_op(const struct wined3d_context *context, const struct wined3d
settings->pointsprite = state->render_states[WINED3D_RS_POINTSPRITEENABLE]
&& state->gl_primitive_type == GL_POINTS;
+ if (gl_info->supported[WINED3D_GL_LEGACY_CONTEXT])
+ settings->alpha_func = WINED3D_CMP_ALWAYS;
+ else
+ settings->alpha_func = wined3d_sanitize_cmp_func(state->render_states[WINED3D_RS_ALPHAFUNC]);
+
if (d3d_info->emulated_flatshading)
settings->flatshading = state->render_states[WINED3D_RS_SHADEMODE] == WINED3D_SHADE_FLAT;
else
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index b86c460..259c632 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -197,6 +197,13 @@ extern const GLenum magLookup[WINED3D_TEXF_LINEAR + 1] DECLSPEC_HIDDEN;
GLenum wined3d_gl_compare_func(enum wined3d_cmp_func f) DECLSPEC_HIDDEN;
+static inline enum wined3d_cmp_func wined3d_sanitize_cmp_func(enum wined3d_cmp_func func)
+{
+ if (func < WINED3D_CMP_NEVER || func > WINED3D_CMP_ALWAYS)
+ return WINED3D_CMP_ALWAYS;
+ return func;
+}
+
static inline GLenum wined3d_gl_mag_filter(enum wined3d_texture_filter_type mag_filter)
{
return magLookup[mag_filter];
@@ -325,16 +332,17 @@ enum wined3d_shader_resource_type
#define WINED3D_SHADER_CONST_PS_B 0x00000080
#define WINED3D_SHADER_CONST_PS_BUMP_ENV 0x00000100
#define WINED3D_SHADER_CONST_PS_FOG 0x00000200
-#define WINED3D_SHADER_CONST_PS_Y_CORR 0x00000400
-#define WINED3D_SHADER_CONST_PS_NP2_FIXUP 0x00000800
-#define WINED3D_SHADER_CONST_FFP_MODELVIEW 0x00001000
-#define WINED3D_SHADER_CONST_FFP_VERTEXBLEND 0x00002000
-#define WINED3D_SHADER_CONST_FFP_PROJ 0x00004000
-#define WINED3D_SHADER_CONST_FFP_TEXMATRIX 0x00008000
-#define WINED3D_SHADER_CONST_FFP_MATERIAL 0x00010000
-#define WINED3D_SHADER_CONST_FFP_LIGHTS 0x00020000
-#define WINED3D_SHADER_CONST_FFP_PS 0x00040000
-#define WINED3D_SHADER_CONST_FFP_COLOR_KEY 0x00080000
+#define WINED3D_SHADER_CONST_PS_ALPHA_TEST 0x00000400
+#define WINED3D_SHADER_CONST_PS_Y_CORR 0x00000800
+#define WINED3D_SHADER_CONST_PS_NP2_FIXUP 0x00001000
+#define WINED3D_SHADER_CONST_FFP_MODELVIEW 0x00002000
+#define WINED3D_SHADER_CONST_FFP_VERTEXBLEND 0x00004000
+#define WINED3D_SHADER_CONST_FFP_PROJ 0x00008000
+#define WINED3D_SHADER_CONST_FFP_TEXMATRIX 0x00010000
+#define WINED3D_SHADER_CONST_FFP_MATERIAL 0x00020000
+#define WINED3D_SHADER_CONST_FFP_LIGHTS 0x00040000
+#define WINED3D_SHADER_CONST_FFP_PS 0x00080000
+#define WINED3D_SHADER_CONST_FFP_COLOR_KEY 0x00100000
enum wined3d_shader_register_type
{
@@ -973,6 +981,7 @@ struct ps_compile_args {
WORD texcoords_initialized; /* MAX_TEXTURES, 8 */
BOOL pointsprite;
BOOL flatshading;
+ enum wined3d_cmp_func alpha_func;
};
enum fog_src_type {
@@ -2022,6 +2031,7 @@ struct ffp_frag_settings
unsigned char pointsprite : 1;
unsigned char flatshading : 1;
unsigned char padding : 5;
+ enum wined3d_cmp_func alpha_func;
};
struct ffp_frag_desc
--
2.7.3
More information about the wine-patches
mailing list