From: Elizabeth Figura zfigura@codeweavers.com
If the texture changes in a meaningful way, that is. --- dlls/wined3d/cs.c | 29 ------------------------- dlls/wined3d/stateblock.c | 45 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 31 deletions(-)
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index 063c5035290..9b1dd56e6fa 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -1522,54 +1522,25 @@ static void wined3d_cs_exec_set_texture(struct wined3d_cs *cs, const void *data) const struct wined3d_d3d_info *d3d_info = &cs->c.device->adapter->d3d_info; const struct wined3d_cs_set_texture *op = data; struct wined3d_shader_resource_view *prev; - BOOL old_use_color_key = FALSE, new_use_color_key = FALSE;
prev = cs->state.shader_resource_view[op->shader_type][op->bind_index]; cs->state.shader_resource_view[op->shader_type][op->bind_index] = op->view;
if (op->view) { - struct wined3d_texture *texture = texture_from_resource(op->view->resource); - ++op->view->resource->bind_count;
if (op->shader_type == WINED3D_SHADER_TYPE_PIXEL) { if (texture_binding_might_invalidate_ps(op->view, prev, d3d_info)) device_invalidate_state(cs->c.device, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL)); - - if (!prev && op->bind_index < d3d_info->ffp_fragment_caps.max_blend_stages) - { - /* The source arguments for color and alpha ops have different - * meanings when a NULL texture is bound. */ - device_invalidate_state(cs->c.device, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL)); - } - - if (!op->bind_index && texture->async.color_key_flags & WINED3D_CKEY_SRC_BLT) - new_use_color_key = TRUE; } }
if (prev) - { - struct wined3d_texture *prev_texture = texture_from_resource(prev->resource); - --prev->resource->bind_count;
- if (op->shader_type == WINED3D_SHADER_TYPE_PIXEL) - { - if (!op->view && op->bind_index < d3d_info->ffp_fragment_caps.max_blend_stages) - device_invalidate_state(cs->c.device, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL)); - - if (!op->bind_index && prev_texture->async.color_key_flags & WINED3D_CKEY_SRC_BLT) - old_use_color_key = TRUE; - } - } - device_invalidate_state(cs->c.device, STATE_GRAPHICS_SHADER_RESOURCE_BINDING); - - if (new_use_color_key != old_use_color_key) - device_invalidate_state(cs->c.device, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL)); }
void wined3d_device_context_emit_set_texture(struct wined3d_device_context *context, diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c index b0c2775080a..f6b01afd016 100644 --- a/dlls/wined3d/stateblock.c +++ b/dlls/wined3d/stateblock.c @@ -1670,9 +1670,47 @@ void CDECL wined3d_stateblock_set_texture_stage_state(struct wined3d_stateblock } }
+static bool texture_binding_might_invalidate_fs_settings(const struct wined3d_stateblock *stateblock, + const struct wined3d_texture *texture, const struct wined3d_texture *prev, unsigned int stage) +{ + const struct wined3d_d3d_info *d3d_info = &stateblock->device->adapter->d3d_info; + const struct wined3d_format *old_format, *new_format; + unsigned int old_usage, new_usage; + + /* The source arguments for color and alpha ops have different meanings when + * a NULL texture is bound. */ + if (!texture) + return !!prev; + if (!prev) + return true; + + old_usage = prev->resource.usage; + new_usage = texture->resource.usage; + if (texture->resource.type != prev->resource.type + || ((old_usage & WINED3DUSAGE_LEGACY_CUBEMAP) != (new_usage & WINED3DUSAGE_LEGACY_CUBEMAP))) + return true; + + if (!stage && stateblock->stateblock_state.rs[WINED3D_RS_COLORKEYENABLE] + && (texture->color_key_flags & WINED3D_CKEY_SRC_BLT)) + return true; + + old_format = prev->resource.format; + new_format = texture->resource.format; + + if (is_same_fixup(old_format->color_fixup, new_format->color_fixup)) + return false; + + if (can_use_texture_swizzle(d3d_info, new_format) && can_use_texture_swizzle(d3d_info, old_format)) + return false; + + return true; +} + void CDECL wined3d_stateblock_set_texture(struct wined3d_stateblock *stateblock, UINT stage, struct wined3d_texture *texture) { + struct wined3d_texture *prev = stateblock->stateblock_state.textures[stage]; + TRACE("stateblock %p, stage %u, texture %p.\n", stateblock, stage, texture);
if (stage >= ARRAY_SIZE(stateblock->stateblock_state.textures)) @@ -1683,10 +1721,13 @@ void CDECL wined3d_stateblock_set_texture(struct wined3d_stateblock *stateblock,
if (texture) wined3d_texture_incref(texture); - if (stateblock->stateblock_state.textures[stage]) - wined3d_texture_decref(stateblock->stateblock_state.textures[stage]); + if (prev) + wined3d_texture_decref(prev); stateblock->stateblock_state.textures[stage] = texture; stateblock->changed.textures |= 1u << stage; + + if (texture_binding_might_invalidate_fs_settings(stateblock, texture, prev, stage)) + stateblock->changed.ffp_ps_settings = 1; }
void CDECL wined3d_stateblock_set_transform(struct wined3d_stateblock *stateblock,