[PATCH v2 1/8] wined3d: Alpha test emulation for core profile contexts.
Matteo Bruni
mbruni at codeweavers.com
Tue Apr 19 11:56:46 CDT 2016
Signed-off-by: Matteo Bruni <mbruni at codeweavers.com>
---
v2: Don't generate alpha test emulation code when alpha test is
disabled, shrink alpha test function field in the shader keys.
dlls/wined3d/glsl_shader.c | 103 +++++++++++++++++++++++++++++++++--------
dlls/wined3d/shader.c | 9 +++-
dlls/wined3d/utils.c | 7 +++
dlls/wined3d/wined3d_private.h | 37 +++++++++------
4 files changed, 123 insertions(+), 33 deletions(-)
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index cea5e5a..294147f 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -178,6 +178,7 @@ struct glsl_ps_program
GLint fog_density_location;
GLint fog_end_location;
GLint fog_scale_location;
+ GLint alpha_test_ref_location;
GLint ycorrection_location;
GLint np2_fixup_location;
GLint color_key_location;
@@ -1484,6 +1485,14 @@ 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)
+ {
+ float ref = state->render_states[WINED3D_RS_ALPHAREF] / 255.0f;
+
+ GL_EXTCALL(glUniform1f(prog->ps.alpha_test_ref_location, ref));
+ checkGLcall("alpha test emulation uniform");
+ }
+
if (priv->next_constant_version == UINT_MAX)
{
TRACE("Max constant version reached, resetting to 0.\n");
@@ -2018,6 +2027,9 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
shader_addline(buffer, "vec4 vpos;\n");
}
+ if (ps_args->alpha_test_func + 1 != WINED3D_CMP_ALWAYS)
+ shader_addline(buffer, "uniform float alpha_test_ref;\n");
+
if (!needs_legacy_glsl_syntax(gl_info))
shader_addline(buffer, "out vec4 ps_out[%u];\n", gl_info->limits.buffers);
@@ -5452,6 +5464,32 @@ 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;
+
+ if (alpha_func != WINED3D_CMP_NEVER)
+ shader_addline(buffer, "if (!(%s[0].a %s alpha_test_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,
@@ -5542,6 +5580,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_test_func + 1);
+
shader_addline(buffer, "}\n");
TRACE("Compiling shader object %u.\n", shader_id);
@@ -6550,6 +6590,9 @@ static void shader_glsl_ffp_fragment_op(struct wined3d_string_buffer *buffer, un
static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv *priv,
const struct ffp_frag_settings *settings, const struct wined3d_gl_info *gl_info)
{
+ struct wined3d_string_buffer *tex_reg_name = string_buffer_get(&priv->string_buffers);
+ enum wined3d_cmp_func alpha_test_func = settings->alpha_test_func + 1;
+ BOOL legacy_context = gl_info->supported[WINED3D_GL_LEGACY_CONTEXT];
struct wined3d_string_buffer *buffer = &priv->shader_buffer;
BYTE lum_map = 0, bump_map = 0, tex_map = 0, tss_const_map = 0;
BOOL tempreg_used = FALSE, tfactor_used = FALSE;
@@ -6557,8 +6600,6 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv *
GLuint shader_id;
DWORD arg0, arg1, arg2;
unsigned int stage;
- struct wined3d_string_buffer *tex_reg_name = string_buffer_get(&priv->string_buffers);
- BOOL legacy_context = gl_info->supported[WINED3D_GL_LEGACY_CONTEXT];
string_buffer_clear(buffer);
@@ -6701,6 +6742,9 @@ 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 (alpha_test_func != WINED3D_CMP_ALWAYS)
+ shader_addline(buffer, "uniform float alpha_test_ref;\n");
+
if (legacy_context)
{
shader_addline(buffer, "vec4 ffp_varying_diffuse;\n");
@@ -6955,6 +6999,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, alpha_test_func);
+
shader_addline(buffer, "}\n");
shader_id = GL_EXTCALL(glCreateShader(GL_FRAGMENT_SHADER));
@@ -7139,6 +7185,8 @@ 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_ref_location = GL_EXTCALL(glGetUniformLocation(program_id, "alpha_test_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"));
@@ -7486,6 +7534,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_ref_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)
@@ -8948,35 +8998,47 @@ 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_alpha_test_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->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL;
+}
+
+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;
+ checkGLcall("glDisable(GL_ALPHA_TEST)");
}
+}
- 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");
- }
+static void glsl_fragment_pipe_core_alpha_test_ref(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_color_key(struct wined3d_context *context,
@@ -9069,9 +9131,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_ALPHAFUNC), glsl_fragment_pipe_alpha_test_func }, WINED3D_GL_LEGACY_CONTEXT},
{STATE_RENDER(WINED3D_RS_ALPHAFUNC), {STATE_RENDER(WINED3D_RS_ALPHATESTENABLE), NULL }, WINED3D_GL_EXT_NONE },
- {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_ALPHAREF), {STATE_RENDER(WINED3D_RS_ALPHAFUNC), NULL }, WINED3D_GL_LEGACY_CONTEXT},
+ {STATE_RENDER(WINED3D_RS_ALPHAREF), {STATE_RENDER(WINED3D_RS_ALPHAREF), glsl_fragment_pipe_core_alpha_test_ref }, 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 8f8b727..55c1d5b 100644
--- a/dlls/wined3d/shader.c
+++ b/dlls/wined3d/shader.c
@@ -2668,7 +2668,7 @@ void find_vs_compile_args(const struct wined3d_state *state, const struct wined3
if (d3d_info->emulated_flatshading)
args->flatshading = state->render_states[WINED3D_RS_SHADEMODE] == WINED3D_SHADE_FLAT;
else
- args->flatshading = FALSE;
+ args->flatshading = 0;
}
static BOOL match_usage(BYTE usage1, BYTE usage_idx1, BYTE usage2, BYTE usage_idx2)
@@ -3091,6 +3091,13 @@ 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_test_func = WINED3D_CMP_ALWAYS - 1;
+ else
+ args->alpha_test_func = (state->render_states[WINED3D_RS_ALPHATESTENABLE]
+ ? wined3d_sanitize_cmp_func(state->render_states[WINED3D_RS_ALPHAFUNC])
+ : WINED3D_CMP_ALWAYS) - 1;
+
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 c0688b5..4c721ea 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -5115,6 +5115,13 @@ 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_test_func = WINED3D_CMP_ALWAYS - 1;
+ else
+ settings->alpha_test_func = (state->render_states[WINED3D_RS_ALPHATESTENABLE]
+ ? wined3d_sanitize_cmp_func(state->render_states[WINED3D_RS_ALPHAFUNC])
+ : WINED3D_CMP_ALWAYS) - 1;
+
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 5623a62..ebda4d6 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -201,6 +201,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];
@@ -330,16 +337,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
{
@@ -1015,8 +1023,10 @@ struct ps_compile_args {
WORD np2_fixup;
WORD shadow; /* MAX_FRAGMENT_SAMPLERS, 16 */
WORD texcoords_initialized; /* MAX_TEXTURES, 8 */
- BOOL pointsprite;
- BOOL flatshading;
+ DWORD pointsprite : 1;
+ DWORD flatshading : 1;
+ DWORD alpha_test_func : 3;
+ DWORD padding : 27;
};
enum fog_src_type {
@@ -2075,7 +2085,8 @@ struct ffp_frag_settings
unsigned char color_key_enabled : 1;
unsigned char pointsprite : 1;
unsigned char flatshading : 1;
- unsigned char padding : 5;
+ unsigned char alpha_test_func : 3;
+ unsigned char padding : 2;
};
struct ffp_frag_desc
--
2.7.3
More information about the wine-patches
mailing list