🐛 Fix stale tile cache when flex reflow changes modifier set between frames

This commit is contained in:
Alejandro Alonso 2026-04-20 08:50:40 +02:00 committed by Elena Torro
parent bc9496deaa
commit 1d454f3790
3 changed files with 31 additions and 4 deletions

View File

@ -866,7 +866,12 @@ pub extern "C" fn set_structure_modifiers() -> Result<()> {
#[wasm_error]
pub extern "C" fn clean_modifiers() -> Result<()> {
with_state_mut!(state, {
state.shapes.clean_all();
let prev_modifier_ids = state.shapes.clean_all();
if !prev_modifier_ids.is_empty() {
state
.render_state
.update_tiles_shapes(&prev_modifier_ids, &mut state.shapes)?;
}
});
Ok(())
}

View File

@ -1775,8 +1775,6 @@ impl RenderState {
self.render_shape_tree_partial(base_object, tree, timestamp, false)?;
}
self.flush_and_submit();
wapi::notify_tiles_render_complete!();
Ok(())
}

View File

@ -278,11 +278,35 @@ impl ShapesPoolImpl {
}
}
pub fn clean_all(&mut self) {
/// Clears transient per-frame state (modifiers, structure, scale_content)
/// and returns the list of UUIDs that had a `modifier` applied at the
/// moment of cleaning. The caller can use that list to re-sync the tile
/// index / tile cache for those shapes: after cleaning their modifier is
/// gone, but if we don't touch their tiles they keep pointing at the
/// previous modified position and the tile texture cache may serve stale
/// pixels.
pub fn clean_all(&mut self) -> Vec<Uuid> {
self.clean_shape_cache();
let modified_uuids: Vec<Uuid> = if self.modifiers.is_empty() {
Vec::new()
} else {
let mut idx_to_uuid: HashMap<usize, Uuid> =
HashMap::with_capacity(self.uuid_to_idx.len());
for (uuid, idx) in self.uuid_to_idx.iter() {
idx_to_uuid.insert(*idx, *uuid);
}
self.modifiers
.keys()
.filter_map(|idx| idx_to_uuid.get(idx).copied())
.collect()
};
self.modifiers = HashMap::default();
self.structure = HashMap::default();
self.scale_content = HashMap::default();
modified_uuids
}
pub fn subtree(&self, id: &Uuid) -> ShapesPoolImpl {