[PATCH 1/9] wined3d: Set color keys through the command stream (v2).

Stefan Dösinger stefan at codeweavers.com
Thu Apr 9 15:48:11 CDT 2015


Changes in version 2:
*) Start a separate structure for data that may only be accessed by the
command stream's thread. I have given this structure a name for more
useful compiler errors.
*) Split the DWORD into two WORDs instead of using a private flag and
make sure no invalid flags are passed.

Some, or potentially all, of the other texture flags should go into the
async flags field too, but that's something for another patch.
---
 dlls/wined3d/cs.c              | 84 ++++++++++++++++++++++++++++++++++++++++++
 dlls/wined3d/state.c           |  4 +-
 dlls/wined3d/surface.c         | 16 ++++----
 dlls/wined3d/texture.c         | 81 ++++++++++++++--------------------------
 dlls/wined3d/utils.c           |  4 +-
 dlls/wined3d/wined3d_private.h | 25 +++++++++----
 6 files changed, 140 insertions(+), 74 deletions(-)

diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index 4a04b00..4ed68f3 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 69623af..f5c1b4f 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 e3601a2..7a707f6 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 6b2e266..7c47189 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 & WINED3D_CKEY_COLORSPACE)
+    if (flags & ~all_flags)
     {
-        FIXME("Unhandled flags %#x.\n", flags);
+        WARN("Invalid flags passed, returning WINED3DERR_INVALIDCALL.\n");
         return WINED3DERR_INVALIDCALL;
     }
 
-    if (color_key)
+    if (flags & WINED3D_CKEY_COLORSPACE)
     {
-        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;
-        }
+        FIXME("Unhandled flags %#x.\n", flags);
+        return WINED3DERR_INVALIDCALL;
     }
-    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 215ddd8..41326de 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 5d736dd..0191ba7 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2186,7 +2186,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
 {
@@ -2204,13 +2205,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)
@@ -2552,6 +2559,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,
-- 
2.3.4




More information about the wine-patches mailing list