diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index 4a04b00c54d..4ed68f3ae3e 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -49,6 +49,7 @@ enum wined3d_cs_op WINED3D_CS_OP_SET_SAMPLER_STATE, WINED3D_CS_OP_SET_TRANSFORM, WINED3D_CS_OP_SET_CLIP_PLANE, + WINED3D_CS_OP_SET_COLOR_KEY, WINED3D_CS_OP_SET_MATERIAL, WINED3D_CS_OP_RESET_STATE, }; @@ -170,6 +171,15 @@ struct wined3d_cs_set_texture struct wined3d_texture *texture; }; +struct wined3d_cs_set_color_key +{ + enum wined3d_cs_op opcode; + struct wined3d_texture *texture; + WORD flags; + WORD set; + struct wined3d_color_key color_key; +}; + struct wined3d_cs_set_shader_resource_view { enum wined3d_cs_op opcode; @@ -870,6 +880,79 @@ void wined3d_cs_emit_set_clip_plane(struct wined3d_cs *cs, UINT plane_idx, const cs->ops->submit(cs); } +static void wined3d_cs_exec_set_color_key(struct wined3d_cs *cs, const void *data) +{ + const struct wined3d_cs_set_color_key *op = data; + struct wined3d_texture *texture = op->texture; + + if (op->set) + { + switch (op->flags & ~WINED3D_CKEY_COLORSPACE) + { + case WINED3D_CKEY_DST_BLT: + texture->async.dst_blt_color_key = op->color_key; + texture->async.color_key_flags |= WINED3D_CKEY_DST_BLT; + break; + + case WINED3D_CKEY_DST_OVERLAY: + texture->async.dst_overlay_color_key = op->color_key; + texture->async.color_key_flags |= WINED3D_CKEY_DST_OVERLAY; + break; + + case WINED3D_CKEY_SRC_BLT: + texture->async.src_blt_color_key = op->color_key; + texture->async.color_key_flags |= WINED3D_CKEY_SRC_BLT; + break; + + case WINED3D_CKEY_SRC_OVERLAY: + texture->async.src_overlay_color_key = op->color_key; + texture->async.color_key_flags |= WINED3D_CKEY_SRC_OVERLAY; + break; + } + } + else + { + switch (op->flags & ~WINED3D_CKEY_COLORSPACE) + { + case WINED3D_CKEY_DST_BLT: + texture->async.color_key_flags &= ~WINED3D_CKEY_DST_BLT; + break; + + case WINED3D_CKEY_DST_OVERLAY: + texture->async.color_key_flags &= ~WINED3D_CKEY_DST_OVERLAY; + break; + + case WINED3D_CKEY_SRC_BLT: + texture->async.color_key_flags &= ~WINED3D_CKEY_SRC_BLT; + break; + + case WINED3D_CKEY_SRC_OVERLAY: + texture->async.color_key_flags &= ~WINED3D_CKEY_SRC_OVERLAY; + break; + } + } +} + +void wined3d_cs_emit_set_color_key(struct wined3d_cs *cs, struct wined3d_texture *texture, + WORD flags, const struct wined3d_color_key *color_key) +{ + struct wined3d_cs_set_color_key *op; + + op = cs->ops->require_space(cs, sizeof(*op)); + op->opcode = WINED3D_CS_OP_SET_COLOR_KEY; + op->texture = texture; + op->flags = flags; + if (color_key) + { + op->color_key = *color_key; + op->set = 1; + } + else + op->set = 0; + + cs->ops->submit(cs); +} + static void wined3d_cs_exec_set_material(struct wined3d_cs *cs, const void *data) { const struct wined3d_cs_set_material *op = data; @@ -936,6 +1019,7 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void /* WINED3D_CS_OP_SET_SAMPLER_STATE */ wined3d_cs_exec_set_sampler_state, /* WINED3D_CS_OP_SET_TRANSFORM */ wined3d_cs_exec_set_transform, /* WINED3D_CS_OP_SET_CLIP_PLANE */ wined3d_cs_exec_set_clip_plane, + /* WINED3D_CS_OP_SET_COLOR_KEY */ wined3d_cs_exec_set_color_key, /* WINED3D_CS_OP_SET_MATERIAL */ wined3d_cs_exec_set_material, /* WINED3D_CS_OP_RESET_STATE */ wined3d_cs_exec_reset_state, }; diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c index 69623af0f0e..f5c1b4fa118 100644 --- a/dlls/wined3d/state.c +++ b/dlls/wined3d/state.c @@ -521,7 +521,7 @@ static void state_alpha(struct wined3d_context *context, const struct wined3d_st * WINED3D_RS_COLORKEYENABLE state(which is d3d <= 3 only). The texture * function will call alpha in case it finds some texture + colorkeyenable * combination which needs extra care. */ - if (state->textures[0] && (state->textures[0]->color_key_flags & WINED3D_CKEY_SRC_BLT)) + if (state->textures[0] && (state->textures[0]->async.color_key_flags & WINED3D_CKEY_SRC_BLT)) enable_ckey = TRUE; if (enable_ckey || context->last_was_ckey) @@ -3210,7 +3210,7 @@ void tex_alphaop(struct wined3d_context *context, const struct wined3d_state *st if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB) { - if (texture->color_key_flags & WINED3D_CKEY_SRC_BLT && !texture->resource.format->alpha_size) + if (texture->async.color_key_flags & WINED3D_CKEY_SRC_BLT && !texture->resource.format->alpha_size) { /* Color keying needs to pass alpha values from the texture through to have the alpha test work * properly. On the other hand applications can still use texture combiners apparently. This code diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index e3601a2d128..7a707f68333 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -3410,7 +3410,7 @@ static void surface_blt_to_drawable(const struct wined3d_device *device, * other cases pixels that should be masked away have alpha set to 0. */ if (src_surface->resource.format->id == WINED3DFMT_P8_UINT) gl_info->gl_ops.gl.p_glAlphaFunc(GL_NOTEQUAL, - (float)src_surface->container->src_blt_color_key.color_space_low_value / 255.0f); + (float)src_surface->container->async.src_blt_color_key.color_space_low_value / 255.0f); else gl_info->gl_ops.gl.p_glAlphaFunc(GL_NOTEQUAL, 0.0f); checkGLcall("glAlphaFunc"); @@ -3586,8 +3586,8 @@ static HRESULT surface_blt_special(struct wined3d_surface *dst_surface, const RE else if (src_surface) { /* Blit from offscreen surface to render target */ - struct wined3d_color_key old_blt_key = src_surface->container->src_blt_color_key; - DWORD old_color_key_flags = src_surface->container->color_key_flags; + struct wined3d_color_key old_blt_key = src_surface->container->async.src_blt_color_key; + DWORD old_color_key_flags = src_surface->container->async.color_key_flags; TRACE("Blt from surface %p to rendertarget %p\n", src_surface, dst_surface); @@ -4168,7 +4168,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, if (texture->swapchain && texture->swapchain->palette) palette = texture->swapchain->palette; conversion->convert(data.addr, src_pitch, mem, dst_pitch, - width, height, palette, &texture->gl_color_key); + width, height, palette, &texture->async.gl_color_key); src_pitch = dst_pitch; data.addr = mem; } @@ -4830,8 +4830,8 @@ do { \ /* The color keying flags are checked for correctness in ddraw */ if (flags & WINEDDBLT_KEYSRC) { - keylow = src_surface->container->src_blt_color_key.color_space_low_value; - keyhigh = src_surface->container->src_blt_color_key.color_space_high_value; + keylow = src_surface->container->async.src_blt_color_key.color_space_low_value; + keyhigh = src_surface->container->async.src_blt_color_key.color_space_high_value; } else if (flags & WINEDDBLT_KEYSRCOVERRIDE) { @@ -4842,8 +4842,8 @@ do { \ if (flags & WINEDDBLT_KEYDEST) { /* Destination color keys are taken from the source surface! */ - destkeylow = src_surface->container->dst_blt_color_key.color_space_low_value; - destkeyhigh = src_surface->container->dst_blt_color_key.color_space_high_value; + destkeylow = src_surface->container->async.dst_blt_color_key.color_space_low_value; + destkeyhigh = src_surface->container->async.dst_blt_color_key.color_space_high_value; } else if (flags & WINEDDBLT_KEYDESTOVERRIDE) { diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 6b2e266ac76..7c47189e68a 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -437,6 +437,12 @@ struct wined3d_resource * CDECL wined3d_texture_get_resource(struct wined3d_text return &texture->resource; } +static BOOL color_key_equal(const struct wined3d_color_key *c1, struct wined3d_color_key *c2) +{ + return c1->color_space_low_value == c2->color_space_low_value + && c1->color_space_high_value == c2->color_space_high_value; +} + /* Context activation is done by the caller */ void wined3d_texture_load(struct wined3d_texture *texture, struct wined3d_context *context, BOOL srgb) @@ -456,10 +462,10 @@ void wined3d_texture_load(struct wined3d_texture *texture, else flag = WINED3D_TEXTURE_RGB_VALID; - if (!(texture->flags & WINED3D_TEXTURE_COLOR_KEY) != !(texture->color_key_flags & WINED3D_CKEY_SRC_BLT) - || (texture->flags & WINED3D_TEXTURE_COLOR_KEY - && (texture->gl_color_key.color_space_low_value != texture->src_blt_color_key.color_space_low_value - || texture->gl_color_key.color_space_high_value != texture->src_blt_color_key.color_space_high_value))) + if (!(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))) { unsigned int sub_count = texture->level_count * texture->layer_count; unsigned int i; @@ -469,7 +475,7 @@ void wined3d_texture_load(struct wined3d_texture *texture, texture->texture_ops->texture_sub_resource_add_dirty_region(texture->sub_resources[i], NULL); wined3d_texture_set_dirty(texture); - texture->gl_color_key = texture->src_blt_color_key; + texture->async.gl_color_key = texture->async.src_blt_color_key; } if (texture->flags & flag) @@ -571,60 +577,25 @@ enum wined3d_texture_filter_type CDECL wined3d_texture_get_autogen_filter_type(c HRESULT CDECL wined3d_texture_set_color_key(struct wined3d_texture *texture, DWORD flags, const struct wined3d_color_key *color_key) { + struct wined3d_device *device = texture->resource.device; + static const DWORD all_flags = WINED3D_CKEY_COLORSPACE | WINED3D_CKEY_DST_BLT + | WINED3D_CKEY_DST_OVERLAY | WINED3D_CKEY_SRC_BLT | WINED3D_CKEY_SRC_OVERLAY; + TRACE("texture %p, flags %#x, color_key %p.\n", texture, flags, color_key); + if (flags & ~all_flags) + { + WARN("Invalid flags passed, returning WINED3DERR_INVALIDCALL.\n"); + return WINED3DERR_INVALIDCALL; + } + if (flags & WINED3D_CKEY_COLORSPACE) { FIXME("Unhandled flags %#x.\n", flags); return WINED3DERR_INVALIDCALL; } - if (color_key) - { - switch (flags & ~WINED3D_CKEY_COLORSPACE) - { - case WINED3D_CKEY_DST_BLT: - texture->dst_blt_color_key = *color_key; - texture->color_key_flags |= WINED3D_CKEY_DST_BLT; - break; - - case WINED3D_CKEY_DST_OVERLAY: - texture->dst_overlay_color_key = *color_key; - texture->color_key_flags |= WINED3D_CKEY_DST_OVERLAY; - break; - - case WINED3D_CKEY_SRC_BLT: - texture->src_blt_color_key = *color_key; - texture->color_key_flags |= WINED3D_CKEY_SRC_BLT; - break; - - case WINED3D_CKEY_SRC_OVERLAY: - texture->src_overlay_color_key = *color_key; - texture->color_key_flags |= WINED3D_CKEY_SRC_OVERLAY; - break; - } - } - else - { - switch (flags & ~WINED3D_CKEY_COLORSPACE) - { - case WINED3D_CKEY_DST_BLT: - texture->color_key_flags &= ~WINED3D_CKEY_DST_BLT; - break; - - case WINED3D_CKEY_DST_OVERLAY: - texture->color_key_flags &= ~WINED3D_CKEY_DST_OVERLAY; - break; - - case WINED3D_CKEY_SRC_BLT: - texture->color_key_flags &= ~WINED3D_CKEY_SRC_BLT; - break; - - case WINED3D_CKEY_SRC_OVERLAY: - texture->color_key_flags &= ~WINED3D_CKEY_SRC_OVERLAY; - break; - } - } + wined3d_cs_emit_set_color_key(device->cs, texture, flags, color_key); return WINED3D_OK; } @@ -694,14 +665,15 @@ void wined3d_texture_prepare_texture(struct wined3d_texture *texture, struct win { DWORD alloc_flag = srgb ? WINED3D_TEXTURE_SRGB_ALLOCATED : WINED3D_TEXTURE_RGB_ALLOCATED; - if (!(texture->flags & WINED3D_TEXTURE_COLOR_KEY) != !(texture->color_key_flags & WINED3D_CKEY_SRC_BLT)) + if (!(texture->async.flags & WINED3D_TEXTURE_ASYNC_COLOR_KEY) + != !(texture->async.color_key_flags & WINED3D_CKEY_SRC_BLT)) wined3d_texture_force_reload(texture); if (texture->flags & alloc_flag) return; - if (texture->color_key_flags & WINED3D_CKEY_SRC_BLT) - texture->flags |= WINED3D_TEXTURE_COLOR_KEY; + 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; @@ -713,7 +685,8 @@ void wined3d_texture_force_reload(struct wined3d_texture *texture) unsigned int i; texture->flags &= ~(WINED3D_TEXTURE_RGB_ALLOCATED | WINED3D_TEXTURE_SRGB_ALLOCATED - | WINED3D_TEXTURE_CONVERTED | WINED3D_TEXTURE_COLOR_KEY); + | WINED3D_TEXTURE_CONVERTED); + texture->async.flags &= ~WINED3D_TEXTURE_ASYNC_COLOR_KEY; for (i = 0; i < sub_count; ++i) { texture->texture_ops->texture_sub_resource_invalidate_location(texture->sub_resources[i], diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index 215ddd85b40..41326de9786 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -843,7 +843,7 @@ const struct wined3d_color_key_conversion * wined3d_format_get_color_key_convers WINED3DFMT_B8G8R8A8_UNORM, convert_p8_uint_b8g8r8a8_unorm }; - if (need_alpha_ck && (texture->flags & WINED3D_TEXTURE_COLOR_KEY)) + if (need_alpha_ck && (texture->async.flags & WINED3D_TEXTURE_ASYNC_COLOR_KEY)) { for (i = 0; i < sizeof(color_key_info) / sizeof(*color_key_info); ++i) { @@ -3781,7 +3781,7 @@ void gen_ffp_frag_op(const struct wined3d_context *context, const struct wined3d if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB) { - if (texture->color_key_flags & WINED3D_CKEY_SRC_BLT && !texture->resource.format->alpha_size) + if (texture->async.color_key_flags & WINED3D_CKEY_SRC_BLT && !texture->resource.format->alpha_size) { if (aop == WINED3D_TOP_DISABLE) { diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index f9e01009fd1..6f02f1c84f5 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2187,7 +2187,8 @@ struct wined3d_texture_ops #define WINED3D_TEXTURE_PIN_SYSMEM 0x00000100 #define WINED3D_TEXTURE_DYNAMIC_MAP 0x00000200 #define WINED3D_TEXTURE_NORMALIZED_COORDS 0x00000400 -#define WINED3D_TEXTURE_COLOR_KEY 0x00000800 + +#define WINED3D_TEXTURE_ASYNC_COLOR_KEY 0x00000001 struct wined3d_texture { @@ -2205,13 +2206,19 @@ struct wined3d_texture DWORD flags; GLenum target; - /* Color keys for DDraw */ - struct wined3d_color_key dst_blt_color_key; - struct wined3d_color_key src_blt_color_key; - struct wined3d_color_key dst_overlay_color_key; - struct wined3d_color_key src_overlay_color_key; - struct wined3d_color_key gl_color_key; - DWORD color_key_flags; + /* May only be accessed from the command stream worker thread. */ + struct wined3d_texture_async + { + DWORD flags; + + /* Color keys for DDraw */ + struct wined3d_color_key dst_blt_color_key; + struct wined3d_color_key src_blt_color_key; + struct wined3d_color_key dst_overlay_color_key; + struct wined3d_color_key src_overlay_color_key; + struct wined3d_color_key gl_color_key; + DWORD color_key_flags; + } async; }; static inline struct wined3d_texture *wined3d_texture_from_resource(struct wined3d_resource *resource) @@ -2553,6 +2560,8 @@ void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *sw void wined3d_cs_emit_reset_state(struct wined3d_cs *cs) DECLSPEC_HIDDEN; void wined3d_cs_emit_set_clip_plane(struct wined3d_cs *cs, UINT plane_idx, const struct wined3d_vec4 *plane) DECLSPEC_HIDDEN; +void wined3d_cs_emit_set_color_key(struct wined3d_cs *cs, struct wined3d_texture *texture, + WORD flags, const struct wined3d_color_key *color_key) DECLSPEC_HIDDEN; void wined3d_cs_emit_set_constant_buffer(struct wined3d_cs *cs, enum wined3d_shader_type type, UINT cb_idx, struct wined3d_buffer *buffer) DECLSPEC_HIDDEN; void wined3d_cs_emit_set_depth_stencil_view(struct wined3d_cs *cs,