wined3d: Implement color keying in the glsl fragment pipeline.

This commit is contained in:
Stefan Dösinger 2015-04-10 12:05:54 +02:00 committed by Alexandre Julliard
parent 2d56694445
commit 5d51c97d07
12 changed files with 95 additions and 91 deletions

View File

@ -1329,14 +1329,9 @@ static void test_ck_rgba(void)
ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
color = get_surface_color(rt, 320, 240);
if (i == 2)
todo_wine ok(compare_color(color, tests[i].result1, 1) || compare_color(color, tests[i].result1_broken, 1),
"Expected color 0x%08x for test %u, got 0x%08x.\n",
tests[i].result1, i, color);
else
ok(compare_color(color, tests[i].result1, 1) || compare_color(color, tests[i].result1_broken, 1),
"Expected color 0x%08x for test %u, got 0x%08x.\n",
tests[i].result1, i, color);
ok(compare_color(color, tests[i].result1, 1) || compare_color(color, tests[i].result1_broken, 1),
"Expected color 0x%08x for test %u, got 0x%08x.\n",
tests[i].result1, i, color);
U5(fx).dwFillColor = 0xff0000ff;
hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
@ -1353,14 +1348,9 @@ static void test_ck_rgba(void)
/* This tests that fragments that are masked out by the color key are
* discarded, instead of just fully transparent. */
color = get_surface_color(rt, 320, 240);
if (i == 2)
todo_wine ok(compare_color(color, tests[i].result2, 1) || compare_color(color, tests[i].result2_broken, 1),
"Expected color 0x%08x for test %u, got 0x%08x.\n",
tests[i].result2, i, color);
else
ok(compare_color(color, tests[i].result2, 1) || compare_color(color, tests[i].result2_broken, 1),
"Expected color 0x%08x for test %u, got 0x%08x.\n",
tests[i].result2, i, color);
ok(compare_color(color, tests[i].result2, 1) || compare_color(color, tests[i].result2_broken, 1),
"Expected color 0x%08x for test %u, got 0x%08x.\n",
tests[i].result2, i, color);
}
IDirectDrawSurface_Release(rt);

View File

@ -1577,14 +1577,9 @@ static void test_ck_rgba(void)
ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
color = get_surface_color(rt, 320, 240);
if (i == 2)
todo_wine ok(compare_color(color, tests[i].result1, 1) || compare_color(color, tests[i].result1_broken, 1),
"Expected color 0x%08x for test %u, got 0x%08x.\n",
tests[i].result1, i, color);
else
ok(compare_color(color, tests[i].result1, 1) || compare_color(color, tests[i].result1_broken, 1),
"Expected color 0x%08x for test %u, got 0x%08x.\n",
tests[i].result1, i, color);
ok(compare_color(color, tests[i].result1, 1) || compare_color(color, tests[i].result1_broken, 1),
"Expected color 0x%08x for test %u, got 0x%08x.\n",
tests[i].result1, i, color);
U5(fx).dwFillColor = 0xff0000ff;
hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
@ -1600,14 +1595,9 @@ static void test_ck_rgba(void)
/* This tests that fragments that are masked out by the color key are
* discarded, instead of just fully transparent. */
color = get_surface_color(rt, 320, 240);
if (i == 2)
todo_wine ok(compare_color(color, tests[i].result2, 1) || compare_color(color, tests[i].result2_broken, 1),
"Expected color 0x%08x for test %u, got 0x%08x.\n",
tests[i].result2, i, color);
else
ok(compare_color(color, tests[i].result2, 1) || compare_color(color, tests[i].result2_broken, 1),
"Expected color 0x%08x for test %u, got 0x%08x.\n",
tests[i].result2, i, color);
ok(compare_color(color, tests[i].result2, 1) || compare_color(color, tests[i].result2_broken, 1),
"Expected color 0x%08x for test %u, got 0x%08x.\n",
tests[i].result2, i, color);
}
IDirectDrawSurface_Release(rt);

View File

@ -1766,14 +1766,9 @@ static void test_ck_rgba(void)
ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
color = get_surface_color(rt, 320, 240);
if (i == 2)
todo_wine ok(compare_color(color, tests[i].result1, 1) || compare_color(color, tests[i].result1_broken, 1),
"Expected color 0x%08x for test %u, got 0x%08x.\n",
tests[i].result1, i, color);
else
ok(compare_color(color, tests[i].result1, 1) || compare_color(color, tests[i].result1_broken, 1),
"Expected color 0x%08x for test %u, got 0x%08x.\n",
tests[i].result1, i, color);
ok(compare_color(color, tests[i].result1, 1) || compare_color(color, tests[i].result1_broken, 1),
"Expected color 0x%08x for test %u, got 0x%08x.\n",
tests[i].result1, i, color);
U5(fx).dwFillColor = 0xff0000ff;
hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
@ -1789,14 +1784,9 @@ static void test_ck_rgba(void)
/* This tests that fragments that are masked out by the color key are
* discarded, instead of just fully transparent. */
color = get_surface_color(rt, 320, 240);
if (i == 2)
todo_wine ok(compare_color(color, tests[i].result2, 1) || compare_color(color, tests[i].result2_broken, 1),
"Expected color 0x%08x for test %u, got 0x%08x.\n",
tests[i].result2, i, color);
else
ok(compare_color(color, tests[i].result2, 1) || compare_color(color, tests[i].result2_broken, 1),
"Expected color 0x%08x for test %u, got 0x%08x.\n",
tests[i].result2, i, color);
ok(compare_color(color, tests[i].result2, 1) || compare_color(color, tests[i].result2_broken, 1),
"Expected color 0x%08x for test %u, got 0x%08x.\n",
tests[i].result2, i, color);
}
IDirectDrawSurface4_Release(rt);

View File

@ -1471,14 +1471,9 @@ static void test_ck_rgba(void)
ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
color = get_surface_color(rt, 320, 240);
if (i == 2)
todo_wine ok(compare_color(color, tests[i].result1, 1) || compare_color(color, tests[i].result1_broken, 1),
"Expected color 0x%08x for test %u, got 0x%08x.\n",
tests[i].result1, i, color);
else
ok(compare_color(color, tests[i].result1, 1) || compare_color(color, tests[i].result1_broken, 1),
"Expected color 0x%08x for test %u, got 0x%08x.\n",
tests[i].result1, i, color);
ok(compare_color(color, tests[i].result1, 1) || compare_color(color, tests[i].result1_broken, 1),
"Expected color 0x%08x for test %u, got 0x%08x.\n",
tests[i].result1, i, color);
U5(fx).dwFillColor = 0xff0000ff;
hr = IDirectDrawSurface7_Blt(texture, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
@ -1494,14 +1489,9 @@ static void test_ck_rgba(void)
/* This tests that fragments that are masked out by the color key are
* discarded, instead of just fully transparent. */
color = get_surface_color(rt, 320, 240);
if (i == 2)
todo_wine ok(compare_color(color, tests[i].result2, 1) || compare_color(color, tests[i].result2_broken, 1),
"Expected color 0x%08x for test %u, got 0x%08x.\n",
tests[i].result2, i, color);
else
ok(compare_color(color, tests[i].result2, 1) || compare_color(color, tests[i].result2_broken, 1),
"Expected color 0x%08x for test %u, got 0x%08x.\n",
tests[i].result2, i, color);
ok(compare_color(color, tests[i].result2, 1) || compare_color(color, tests[i].result2_broken, 1),
"Expected color 0x%08x for test %u, got 0x%08x.\n",
tests[i].result2, i, color);
}
IDirectDrawSurface7_Release(rt);

View File

@ -7556,10 +7556,10 @@ static GLuint arbfp_gen_plain_shader(struct arbfp_blit_priv *priv,
shader_addline(&buffer, "TEMP compare;\n");
shader_addline(&buffer, "PARAM color_key = program.local[%u];\n", ARBFP_BLIT_PARAM_COLOR_KEY);
shader_addline(&buffer, "TEX color, fragment.texcoord[0], texture[0], %s;\n", tex_target);
shader_addline(&buffer, "SGE compare.r, color.a, color_key.a;\n");
shader_addline(&buffer, "SGE compare.g, -color.a, -color_key.a;\n");
shader_addline(&buffer, "MUL compare, compare.r, -compare.g;\n");
shader_addline(&buffer, "KIL compare;\n");
shader_addline(&buffer, "SUB compare, color, color_key;\n");
shader_addline(&buffer, "DP4 compare.r, compare, compare;\n");
shader_addline(&buffer, "SGE compare, -compare.r, 0.0;\n");
shader_addline(&buffer, "KIL -compare;\n");
shader_addline(&buffer, "MOV result.color, color;\n");
}
else
@ -7599,7 +7599,7 @@ static HRESULT arbfp_blit_set(void *blit_priv, struct wined3d_context *context,
struct wine_rb_entry *entry;
struct arbfp_blit_type type;
struct arbfp_blit_desc *desc;
float float_color_key[4] = {0.0f, 0.0f, 0.0f, 0.0f};
struct wined3d_color float_color_key;
if (is_complex_fixup(surface->resource.format->color_fixup))
fixup = get_complex_fixup(surface->resource.format->color_fixup);
@ -7699,10 +7699,10 @@ err_out:
checkGLcall("glProgramLocalParameter4fvARB");
if (type.use_color_key)
{
if (surface->resource.format->id == WINED3DFMT_P8_UINT)
float_color_key[3] = color_key->color_space_low_value / 255.0f;
GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARBFP_BLIT_PARAM_COLOR_KEY, float_color_key));
wined3d_format_convert_color_to_float(surface->resource.format, NULL,
surface->container->async.src_blt_color_key.color_space_high_value, &float_color_key);
GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB,
ARBFP_BLIT_PARAM_COLOR_KEY, &float_color_key.r));
checkGLcall("glProgramLocalParameter4fvARB");
}
@ -7790,10 +7790,6 @@ HRESULT arbfp_blit_surface(struct wined3d_device *device, DWORD filter,
struct wined3d_context *context;
RECT src_rect = *src_rect_in;
RECT dst_rect = *dst_rect_in;
struct wined3d_color_key old_color_key = src_surface->container->async.src_blt_color_key;
DWORD old_color_key_flags = src_surface->container->async.color_key_flags;
wined3d_texture_set_color_key(src_surface->container, WINED3D_CKEY_SRC_BLT, color_key);
/* Activate the destination context, set it up for blitting */
context = context_acquire(device, dst_surface);
@ -7840,9 +7836,6 @@ HRESULT arbfp_blit_surface(struct wined3d_device *device, DWORD filter,
surface_validate_location(dst_surface, dst_surface->container->resource.draw_binding);
surface_invalidate_location(dst_surface, ~dst_surface->container->resource.draw_binding);
wined3d_texture_set_color_key(src_surface->container, WINED3D_CKEY_SRC_BLT,
(old_color_key_flags & WINED3D_CKEY_SRC_BLT) ? &old_color_key : NULL);
return WINED3D_OK;
}

View File

@ -931,6 +931,9 @@ static void wined3d_cs_exec_set_color_key(struct wined3d_cs *cs, const void *dat
break;
}
}
if (texture->resource.bind_count && op->flags & WINED3D_CKEY_SRC_BLT)
device_invalidate_state(cs->device, STATE_RENDER(WINED3D_RS_COLORKEYENABLE));
}
void wined3d_cs_emit_set_color_key(struct wined3d_cs *cs, struct wined3d_texture *texture,

View File

@ -3565,6 +3565,7 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter)
adapter->fragment_pipe->get_caps(gl_info, &fragment_caps);
adapter->d3d_info.limits.ffp_blend_stages = fragment_caps.MaxTextureBlendStages;
adapter->d3d_info.limits.ffp_textures = fragment_caps.MaxSimultaneousTextures;
adapter->d3d_info.shader_color_key = fragment_caps.wined3d_caps & WINED3D_FRAGMENT_CAP_COLOR_KEY;
TRACE("Max texture stages: %u.\n", adapter->d3d_info.limits.ffp_blend_stages);
if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT])

View File

@ -143,6 +143,7 @@ struct glsl_ps_program
GLint specular_enable_location;
GLint ycorrection_location;
GLint np2_fixup_location;
GLint color_key_location;
const struct ps_np2fixup_info *np2_fixup_info;
};
@ -833,6 +834,18 @@ static void shader_glsl_ffp_vertex_normalmatrix_uniform(const struct wined3d_con
checkGLcall("glUniformMatrix3fv");
}
/* Context activation is done by the caller (state handler). */
static void shader_glsl_load_color_key_constant(const struct glsl_ps_program *ps,
const struct wined3d_gl_info *gl_info, const struct wined3d_state *state)
{
struct wined3d_color float_key;
const struct wined3d_texture *texture = state->textures[0];
wined3d_format_convert_color_to_float(texture->resource.format, NULL,
texture->async.src_blt_color_key.color_space_high_value, &float_key);
GL_EXTCALL(glUniform4fv(ps->color_key_location, 1, &float_key.r));
}
/* Context activation is done by the caller (state handler). */
static void shader_glsl_load_constants(void *shader_priv, struct wined3d_context *context,
const struct wined3d_state *state)
@ -947,6 +960,8 @@ static void shader_glsl_load_constants(void *shader_priv, struct wined3d_context
if (update_mask & WINED3D_SHADER_CONST_PS_NP2_FIXUP)
shader_glsl_load_np2fixup_constants(&prog->ps, gl_info, state);
if (update_mask & WINED3D_SHADER_CONST_FFP_COLOR_KEY)
shader_glsl_load_color_key_constant(&prog->ps, gl_info, state);
if (update_mask & WINED3D_SHADER_CONST_FFP_PS)
{
@ -5499,7 +5514,8 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct wined3d_shader_buf
arg1 = settings->op[stage].carg1 & WINED3DTA_SELECTMASK;
arg2 = settings->op[stage].carg2 & WINED3DTA_SELECTMASK;
if (arg0 == WINED3DTA_TEXTURE || arg1 == WINED3DTA_TEXTURE || arg2 == WINED3DTA_TEXTURE)
if (arg0 == WINED3DTA_TEXTURE || arg1 == WINED3DTA_TEXTURE || arg2 == WINED3DTA_TEXTURE
|| (stage == 0 && settings->color_key_enabled))
tex_map |= 1 << stage;
if (arg0 == WINED3DTA_TFACTOR || arg1 == WINED3DTA_TFACTOR || arg2 == WINED3DTA_TFACTOR)
tfactor_used = TRUE;
@ -5603,6 +5619,8 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct wined3d_shader_buf
}
if (tfactor_used)
shader_addline(buffer, "uniform vec4 tex_factor;\n");
if (settings->color_key_enabled)
shader_addline(buffer, "uniform vec4 color_key;\n");
shader_addline(buffer, "uniform vec4 specular_enable;\n");
if (settings->sRGB_write)
@ -5759,6 +5777,9 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct wined3d_shader_buf
settings->op[stage].color_fixup);
}
if (settings->color_key_enabled)
shader_addline(buffer, "if (all(equal(tex0, color_key))) discard;\n");
/* Generate the main shader */
for (stage = 0; stage < MAX_TEXTURES; ++stage)
{
@ -5949,6 +5970,7 @@ static void shader_glsl_init_ps_uniform_locations(const struct wined3d_gl_info *
ps->specular_enable_location = GL_EXTCALL(glGetUniformLocation(program_id, "specular_enable"));
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"));
}
static void shader_glsl_init_uniform_block_bindings(const struct wined3d_gl_info *gl_info, GLuint program_id,
@ -6245,6 +6267,8 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const
if (entry->ps.np2_fixup_location != -1)
entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_NP2_FIXUP;
if (entry->ps.color_key_location != -1)
entry->constant_update_mask |= WINED3D_SHADER_CONST_FFP_COLOR_KEY;
}
}
@ -7405,7 +7429,8 @@ static void glsl_fragment_pipe_enable(const struct wined3d_gl_info *gl_info, BOO
static void glsl_fragment_pipe_get_caps(const struct wined3d_gl_info *gl_info, struct fragment_caps *caps)
{
caps->wined3d_caps = WINED3D_FRAGMENT_CAP_PROJ_CONTROL
| WINED3D_FRAGMENT_CAP_SRGB_WRITE;
| WINED3D_FRAGMENT_CAP_SRGB_WRITE
| WINED3D_FRAGMENT_CAP_COLOR_KEY;
caps->PrimitiveMiscCaps = WINED3DPMISCCAPS_TSSARGTEMP
| WINED3DPMISCCAPS_PERSTAGECONSTANT;
caps->TextureOpCaps = WINED3DTEXOPCAPS_DISABLE

View File

@ -528,6 +528,9 @@ static void state_alpha(struct wined3d_context *context, const struct wined3d_st
context_apply_state(context, state, STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_OP));
context->last_was_ckey = enable_ckey;
if (context->d3d_info->shader_color_key)
enable_ckey = FALSE;
if (state->render_states[WINED3D_RS_ALPHATESTENABLE]
|| (state->render_states[WINED3D_RS_COLORKEYENABLE] && enable_ckey))
{

View File

@ -449,6 +449,7 @@ void wined3d_texture_load(struct wined3d_texture *texture,
{
UINT sub_count = texture->level_count * texture->layer_count;
const struct wined3d_gl_info *gl_info = context->gl_info;
const struct wined3d_d3d_info *d3d_info = context->d3d_info;
DWORD flag;
UINT i;
@ -462,10 +463,11 @@ void wined3d_texture_load(struct wined3d_texture *texture,
else
flag = WINED3D_TEXTURE_RGB_VALID;
if (!(texture->async.flags & WINED3D_TEXTURE_ASYNC_COLOR_KEY)
if (!d3d_info->shader_color_key
&& (!(texture->async.flags & WINED3D_TEXTURE_ASYNC_COLOR_KEY)
!= !(texture->async.color_key_flags & WINED3D_CKEY_SRC_BLT)
|| (texture->async.flags & WINED3D_TEXTURE_ASYNC_COLOR_KEY
&& !color_key_equal(&texture->async.gl_color_key, &texture->async.src_blt_color_key)))
&& !color_key_equal(&texture->async.gl_color_key, &texture->async.src_blt_color_key))))
{
unsigned int sub_count = texture->level_count * texture->layer_count;
unsigned int i;
@ -664,17 +666,21 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
void wined3d_texture_prepare_texture(struct wined3d_texture *texture, struct wined3d_context *context, BOOL srgb)
{
DWORD alloc_flag = srgb ? WINED3D_TEXTURE_SRGB_ALLOCATED : WINED3D_TEXTURE_RGB_ALLOCATED;
const struct wined3d_d3d_info *d3d_info = context->d3d_info;
if (!(texture->async.flags & WINED3D_TEXTURE_ASYNC_COLOR_KEY)
if (!d3d_info->shader_color_key
&& !(texture->async.flags & WINED3D_TEXTURE_ASYNC_COLOR_KEY)
!= !(texture->async.color_key_flags & WINED3D_CKEY_SRC_BLT))
{
wined3d_texture_force_reload(texture);
if (texture->async.color_key_flags & WINED3D_CKEY_SRC_BLT)
texture->async.flags |= WINED3D_TEXTURE_ASYNC_COLOR_KEY;
}
if (texture->flags & alloc_flag)
return;
if (texture->async.color_key_flags & WINED3D_CKEY_SRC_BLT)
texture->async.flags |= WINED3D_TEXTURE_ASYNC_COLOR_KEY;
texture->texture_ops->texture_prepare_texture(texture, context, srgb);
texture->flags |= alloc_flag;
}

View File

@ -3688,6 +3688,8 @@ void gen_ffp_frag_op(const struct wined3d_context *context, const struct wined3d
const struct wined3d_gl_info *gl_info = context->gl_info;
const struct wined3d_d3d_info *d3d_info = context->d3d_info;
settings->padding = 0;
for (i = 0; i < d3d_info->limits.ffp_blend_stages; ++i)
{
const struct wined3d_texture *texture;
@ -3915,6 +3917,13 @@ void gen_ffp_frag_op(const struct wined3d_context *context, const struct wined3d
} else {
settings->emul_clipplanes = 1;
}
if (state->render_states[WINED3D_RS_COLORKEYENABLE] && state->textures[0]
&& state->textures[0]->async.color_key_flags & WINED3D_CKEY_SRC_BLT
&& settings->op[0].cop != WINED3D_TOP_DISABLE)
settings->color_key_enabled = 1;
else
settings->color_key_enabled = 0;
}
const struct ffp_frag_desc *find_ffp_frag_shader(const struct wine_rb_tree *fragment_shaders,

View File

@ -309,6 +309,7 @@ enum wined3d_shader_resource_type
#define WINED3D_SHADER_CONST_FFP_MODELVIEW 0x00000400
#define WINED3D_SHADER_CONST_FFP_PROJ 0x00000800
#define WINED3D_SHADER_CONST_FFP_PS 0x00001000
#define WINED3D_SHADER_CONST_FFP_COLOR_KEY 0x00002000
enum wined3d_shader_register_type
{
@ -1258,6 +1259,7 @@ struct StateEntryTemplate
#define WINED3D_FRAGMENT_CAP_PROJ_CONTROL 0x00000001
#define WINED3D_FRAGMENT_CAP_SRGB_WRITE 0x00000002
#define WINED3D_FRAGMENT_CAP_COLOR_KEY 0x00000004
struct fragment_caps
{
@ -1744,6 +1746,7 @@ struct wined3d_d3d_info
struct wined3d_ffp_attrib_ops ffp_attrib_ops;
BOOL xyzrhw;
BOOL vs_clipping;
BOOL shader_color_key;
DWORD valid_rt_mask;
};
@ -1816,9 +1819,10 @@ struct ffp_frag_settings
{
struct texture_stage_op op[MAX_TEXTURES];
enum wined3d_ffp_ps_fog_mode fog;
/* Use shorts instead of chars to get dword alignment */
unsigned short sRGB_write;
unsigned short emul_clipplanes;
unsigned char sRGB_write;
unsigned char emul_clipplanes;
unsigned char color_key_enabled;
unsigned char padding;
};
struct ffp_frag_desc