Gate display frame callbacks on shared presentation visibility
This commit is contained in:
1 parent
6b2974d0fa
commit
2f63cae54c
5 files changed
+45
-18
No files matched your search
@@ -1552,14 +1552,14 @@ fn send_frame_callbacks(state: &mut Ferese, output: &Output) {
|
|||||||
.is_some_and(|id| state.window_belongs_to_output(*id, output))
|
.is_some_and(|id| state.window_belongs_to_output(*id, output))
|
||||||
})
|
})
|
||||||
.for_each(|window| {
|
.for_each(|window| {
|
||||||
window.send_frame(output, state.start_time.elapsed(), Some(Duration::ZERO), |_, _| {
|
window.send_frame(output, state.start_time.elapsed(), None, |surface, _| {
|
||||||
Some(output.clone())
|
state.display_presentation.callback_output(&surface.into())
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
let layers = layer_map_for_output(output).layers().cloned().collect::<Vec<_>>();
|
let layers = layer_map_for_output(output).layers().cloned().collect::<Vec<_>>();
|
||||||
layers.iter().for_each(|layer| {
|
layers.iter().for_each(|layer| {
|
||||||
layer.send_frame(output, state.start_time.elapsed(), Some(Duration::ZERO), |_, _| {
|
layer.send_frame(output, state.start_time.elapsed(), None, |surface, _| {
|
||||||
Some(output.clone())
|
state.display_presentation.callback_output(&surface.into())
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
state.send_cursor_frame(output);
|
state.send_cursor_frame(output);
|
||||||
|
|||||||
@@ -44,6 +44,17 @@ impl DisplayPresentation {
|
|||||||
self.outputs.values().any(|record| record.displayed.contains(surface))
|
self.outputs.values().any(|record| record.displayed.contains(surface))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Membership describes every output; callback ownership is a separate choice.
|
||||||
|
// A stable tie-break avoids alternating owners when refresh rates match.
|
||||||
|
pub fn callback_output(&self, surface: &Id) -> Option<Output> {
|
||||||
|
self.outputs
|
||||||
|
.iter()
|
||||||
|
.filter(|(_, record)| record.displayed.contains(surface))
|
||||||
|
.map(|(output, _)| output)
|
||||||
|
.max_by_key(|output| (output.current_mode().map_or(0, |mode| mode.refresh), output.name()))
|
||||||
|
.cloned()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn remove_surface(&mut self, surface: &Id) {
|
pub fn remove_surface(&mut self, surface: &Id) {
|
||||||
for record in self.outputs.values_mut() {
|
for record in self.outputs.values_mut() {
|
||||||
record.displayed.remove(surface);
|
record.displayed.remove(surface);
|
||||||
@@ -139,4 +150,20 @@ mod tests {
|
|||||||
states.states.get_mut(&id).unwrap().presentation_state = RenderElementPresentationState::Skipped;
|
states.states.get_mut(&id).unwrap().presentation_state = RenderElementPresentationState::Skipped;
|
||||||
assert!(visible(&states).is_empty());
|
assert!(visible(&states).is_empty());
|
||||||
}
|
}
|
||||||
|
#[test]
|
||||||
|
fn callback_ownership_is_stable_and_moves_when_an_output_disappears() {
|
||||||
|
let mut record = DisplayPresentation::default();
|
||||||
|
let a = output("a");
|
||||||
|
let b = output("b");
|
||||||
|
let id = Id::new();
|
||||||
|
for output in [&a, &b] {
|
||||||
|
record.queued(output, &scene(&id));
|
||||||
|
record.presented(output);
|
||||||
|
}
|
||||||
|
assert_eq!(record.callback_output(&id), Some(b.clone()));
|
||||||
|
record.remove_output(&b);
|
||||||
|
assert_eq!(record.callback_output(&id), Some(a.clone()));
|
||||||
|
record.remove_surface(&id);
|
||||||
|
assert_eq!(record.callback_output(&id), None);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -218,8 +218,8 @@ impl Ferese {
|
|||||||
surface.wl_surface(),
|
surface.wl_surface(),
|
||||||
output,
|
output,
|
||||||
self.start_time.elapsed(),
|
self.start_time.elapsed(),
|
||||||
Some(std::time::Duration::ZERO),
|
None,
|
||||||
|_, _| Some(output.clone()),
|
|surface, _| self.display_presentation.callback_output(&surface.into()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,13 +119,9 @@ impl Ferese {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
send_frames_surface_tree(
|
send_frames_surface_tree(surface, output, self.start_time.elapsed(), None, |surface, _| {
|
||||||
surface,
|
self.display_presentation.callback_output(&surface.into())
|
||||||
output,
|
});
|
||||||
self.start_time.elapsed(),
|
|
||||||
Some(Duration::ZERO),
|
|
||||||
|_, _| Some(output.clone()),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn window_under_visual(&self, position: Point<f64, Logical>) -> Option<Window> {
|
pub fn window_under_visual(&self, position: Point<f64, Logical>) -> Option<Window> {
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ pub fn init(event_loop: &mut EventLoop<Ferese>, state: &mut Ferese) -> Result<()
|
|||||||
// A callback means permission to draw the next client
|
// A callback means permission to draw the next client
|
||||||
// frame, not proof of a new compositor presentation.
|
// frame, not proof of a new compositor presentation.
|
||||||
// No-damage frames must still unblock layer clients.
|
// No-damage frames must still unblock layer clients.
|
||||||
send_nested_frame_callbacks(state, &output, refresh.get());
|
send_nested_frame_callbacks(state, &output);
|
||||||
state.space.refresh();
|
state.space.refresh();
|
||||||
state.popups.cleanup();
|
state.popups.cleanup();
|
||||||
layer_map_for_output(&output).cleanup();
|
layer_map_for_output(&output).cleanup();
|
||||||
@@ -209,7 +209,7 @@ pub fn init(event_loop: &mut EventLoop<Ferese>, state: &mut Ferese) -> Result<()
|
|||||||
sequence,
|
sequence,
|
||||||
PresentationKind::Vsync,
|
PresentationKind::Vsync,
|
||||||
);
|
);
|
||||||
send_nested_frame_callbacks(state, &output, refresh.get());
|
send_nested_frame_callbacks(state, &output);
|
||||||
state.space.refresh();
|
state.space.refresh();
|
||||||
state.popups.cleanup();
|
state.popups.cleanup();
|
||||||
layer_map_for_output(&output).cleanup();
|
layer_map_for_output(&output).cleanup();
|
||||||
@@ -224,7 +224,7 @@ pub fn init(event_loop: &mut EventLoop<Ferese>, state: &mut Ferese) -> Result<()
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_nested_frame_callbacks(state: &mut Ferese, output: &Output, refresh: Duration) {
|
fn send_nested_frame_callbacks(state: &mut Ferese, output: &Output) {
|
||||||
if state.session_lock.active {
|
if state.session_lock.active {
|
||||||
state.lock_frame_callbacks(output);
|
state.lock_frame_callbacks(output);
|
||||||
return;
|
return;
|
||||||
@@ -237,10 +237,14 @@ fn send_nested_frame_callbacks(state: &mut Ferese, output: &Output, refresh: Dur
|
|||||||
.get(*window)
|
.get(*window)
|
||||||
.is_some_and(|id| state.window_belongs_to_output(*id, output))
|
.is_some_and(|id| state.window_belongs_to_output(*id, output))
|
||||||
}) {
|
}) {
|
||||||
window.send_frame(output, time, Some(refresh), |_, _| Some(output.clone()));
|
window.send_frame(output, time, None, |surface, _| {
|
||||||
|
state.display_presentation.callback_output(&surface.into())
|
||||||
|
});
|
||||||
}
|
}
|
||||||
for layer in layer_surfaces(output) {
|
for layer in layer_surfaces(output) {
|
||||||
layer.send_frame(output, time, Some(refresh), |_, _| Some(output.clone()));
|
layer.send_frame(output, time, None, |surface, _| {
|
||||||
|
state.display_presentation.callback_output(&surface.into())
|
||||||
|
});
|
||||||
}
|
}
|
||||||
state.send_cursor_frame(output);
|
state.send_cursor_frame(output);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user