fix: invalidate semantic materials on scene changes

This commit is contained in:
Samuel Onoja committed 2026-09-25 05:16:38 +01:00
1 parent ae6ec1c5f5
commit b3c5821e3b
4 files changed
+55 -19

No files matched your search

+38 -19
View File
@@ -96,11 +96,14 @@ impl SurfaceEffectsState {
} }
} }
fn set_role(&self, role: Option<SemanticRole>) { fn set_role(&self, role: Option<SemanticRole>) -> bool {
let mut current = self.role.lock().unwrap(); let mut current = self.role.lock().unwrap();
if *current != role { if *current != role {
*current = role; *current = role;
self.generation.fetch_add(1, Ordering::Release); self.generation.fetch_add(1, Ordering::Release);
true
} else {
false
} }
} }
} }
@@ -192,7 +195,7 @@ impl Dispatch<FereseEffectsManagerV1, ()> for Ferese {
impl Dispatch<FereseSurfaceEffectsV1, SurfaceEffectsUserData> for Ferese { impl Dispatch<FereseSurfaceEffectsV1, SurfaceEffectsUserData> for Ferese {
fn request( fn request(
_state: &mut Self, state: &mut Self,
_client: &Client, _client: &Client,
_resource: &FereseSurfaceEffectsV1, _resource: &FereseSurfaceEffectsV1,
request: ferese_surface_effects_v1::Request, request: ferese_surface_effects_v1::Request,
@@ -220,10 +223,23 @@ impl Dispatch<FereseSurfaceEffectsV1, SurfaceEffectsUserData> for Ferese {
WEnum::Value(ferese_surface_effects_v1::Role::Modal) => SemanticRole::Modal, WEnum::Value(ferese_surface_effects_v1::Role::Modal) => SemanticRole::Modal,
WEnum::Unknown(_) | WEnum::Value(_) => return, WEnum::Unknown(_) | WEnum::Value(_) => return,
}; };
set_surface_role(&surface, Some(role)); if set_surface_role(&surface, Some(role)) {
state.invalidate_material_scene();
crate::backends::direct::render_all(state);
}
}
ferese_surface_effects_v1::Request::ClearRole => {
if set_surface_role(&surface, None) {
state.invalidate_material_scene();
crate::backends::direct::render_all(state);
}
}
ferese_surface_effects_v1::Request::Destroy => {
if detach(&surface) {
state.invalidate_material_scene();
crate::backends::direct::render_all(state);
}
} }
ferese_surface_effects_v1::Request::ClearRole => set_surface_role(&surface, None),
ferese_surface_effects_v1::Request::Destroy => detach(&surface),
_ => unreachable!(), _ => unreachable!(),
} }
} }
@@ -240,21 +256,24 @@ impl Dispatch<FereseSurfaceEffectsV1, SurfaceEffectsUserData> for Ferese {
} }
} }
fn set_surface_role(surface: &WlSurface, role: Option<SemanticRole>) { fn set_surface_role(surface: &WlSurface, role: Option<SemanticRole>) -> bool {
with_states(surface, |states| { with_states(surface, |states| {
if let Some(effects) = states.data_map.get::<SurfaceEffectsState>() { states
effects.set_role(role); .data_map
} .get::<SurfaceEffectsState>()
}); .is_some_and(|effects| effects.set_role(role))
})
} }
fn detach(surface: &WlSurface) { fn detach(surface: &WlSurface) -> bool {
with_states(surface, |states| { with_states(surface, |states| {
if let Some(effects) = states.data_map.get::<SurfaceEffectsState>() { let Some(effects) = states.data_map.get::<SurfaceEffectsState>() else {
effects.set_role(None); return false;
effects.attached.store(false, Ordering::Release); };
} let role_changed = effects.set_role(None);
}); let was_attached = effects.attached.swap(false, Ordering::AcqRel);
role_changed || was_attached
})
} }
#[cfg(test)] #[cfg(test)]
@@ -264,13 +283,13 @@ mod tests {
#[test] #[test]
fn role_changes_advance_generation_only_when_material_changes() { fn role_changes_advance_generation_only_when_material_changes() {
let effects = SurfaceEffectsState::new(); let effects = SurfaceEffectsState::new();
effects.set_role(Some(SemanticRole::Panel)); assert!(effects.set_role(Some(SemanticRole::Panel)));
assert_eq!(effects.generation.load(Ordering::Acquire), 1); assert_eq!(effects.generation.load(Ordering::Acquire), 1);
effects.set_role(Some(SemanticRole::Panel)); assert!(!effects.set_role(Some(SemanticRole::Panel)));
assert_eq!(effects.generation.load(Ordering::Acquire), 1); assert_eq!(effects.generation.load(Ordering::Acquire), 1);
effects.set_role(Some(SemanticRole::Popover)); assert!(effects.set_role(Some(SemanticRole::Popover)));
assert_eq!(effects.generation.load(Ordering::Acquire), 2); assert_eq!(effects.generation.load(Ordering::Acquire), 2);
} }
+1
View File
@@ -32,6 +32,7 @@ impl CompositorHandler for Ferese {
fn commit(&mut self, surface: &WlSurface) { fn commit(&mut self, surface: &WlSurface) {
on_commit_buffer_handler::<Self>(surface); on_commit_buffer_handler::<Self>(surface);
self.invalidate_material_scene();
if !is_sync_subsurface(surface) { if !is_sync_subsurface(surface) {
let mut root = surface.clone(); let mut root = surface.clone();
while let Some(parent) = get_parent(&root) { while let Some(parent) = get_parent(&root) {
+14
View File
@@ -124,6 +124,7 @@ pub struct Ferese {
pub(crate) rounded_clip_programs: HashMap<ErasedContextId, crate::winit::RoundedClipPrograms>, pub(crate) rounded_clip_programs: HashMap<ErasedContextId, crate::winit::RoundedClipPrograms>,
pub(crate) material_programs: HashMap<ErasedContextId, crate::winit::MaterialProgram>, pub(crate) material_programs: HashMap<ErasedContextId, crate::winit::MaterialProgram>,
pub(crate) material_buffers: HashMap<WlSurface, crate::winit::MaterialBuffers>, pub(crate) material_buffers: HashMap<WlSurface, crate::winit::MaterialBuffers>,
material_scene_generation: u64,
closing_windows: HashMap<WindowId, ClosingAnimation>, closing_windows: HashMap<WindowId, ClosingAnimation>,
viewport_animations: HashMap<WorkspaceId, AnimatedValue>, viewport_animations: HashMap<WorkspaceId, AnimatedValue>,
scrolling_world_x: HashMap<WindowId, (WorkspaceId, AnimatedValue)>, scrolling_world_x: HashMap<WindowId, (WorkspaceId, AnimatedValue)>,
@@ -438,6 +439,7 @@ impl Ferese {
rounded_clip_programs: HashMap::new(), rounded_clip_programs: HashMap::new(),
material_programs: HashMap::new(), material_programs: HashMap::new(),
material_buffers: HashMap::new(), material_buffers: HashMap::new(),
material_scene_generation: 0,
closing_windows: HashMap::new(), closing_windows: HashMap::new(),
viewport_animations: HashMap::new(), viewport_animations: HashMap::new(),
scrolling_world_x: HashMap::new(), scrolling_world_x: HashMap::new(),
@@ -1276,9 +1278,21 @@ impl Ferese {
} }
self.sync_window_stacking(); self.sync_window_stacking();
if active_animation {
self.invalidate_material_scene();
}
active_animation active_animation
} }
pub(crate) fn invalidate_material_scene(&mut self) {
self.material_scene_generation = self.material_scene_generation.wrapping_add(1);
}
pub(crate) fn material_scene_generation(&self) -> u64 {
self.material_scene_generation
}
pub fn record_client_commit(&mut self, window: &Window) { pub fn record_client_commit(&mut self, window: &Window) {
let Some(id) = self.window_ids.get(window) else { let Some(id) = self.window_ids.get(window) else {
return; return;
+2
View File
@@ -247,6 +247,7 @@ struct MaterialParameters {
tint: [f32; 4], tint: [f32; 4],
noise: f32, noise: f32,
generation: u64, generation: u64,
scene_generation: u64,
opaque: bool, opaque: bool,
} }
@@ -1207,6 +1208,7 @@ fn material_element(
tint, tint,
noise: material.noise, noise: material.noise,
generation, generation,
scene_generation: state.material_scene_generation(),
opaque: material.opacity == 1.0, opaque: material.opacity == 1.0,
}; };
let context = renderer.context_id().erased(); let context = renderer.context_id().erased();