From 6b6a84e55be388589e49fc9ddd8502dd2da7aca9 Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Tue, 10 Sep 2024 10:48:45 +0300 Subject: Avoid panics on more wrong VBlank events --- src/backend/tty.rs | 35 ++++++++++++++++++----------------- src/niri.rs | 2 +- 2 files changed, 19 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/backend/tty.rs b/src/backend/tty.rs index 41e067a9..4b012177 100644 --- a/src/backend/tty.rs +++ b/src/backend/tty.rs @@ -1153,15 +1153,24 @@ impl Tty { return; }; - // This happened for someone reconnecting 2 monitors with a KVM switch: - // https://github.com/YaLTeR/niri/issues/556 - // - // Maybe the vblank didn't get cancelled or got reordered weirdly? Either way, we can avoid - // crashing here. - if matches!(output_state.redraw_state, RedrawState::Idle) { - error!("got vblank for an idle output {name}"); - return; - } + let redraw_needed = match mem::replace(&mut output_state.redraw_state, RedrawState::Idle) { + RedrawState::WaitingForVBlank { redraw_needed } => redraw_needed, + state @ (RedrawState::Idle + | RedrawState::Queued + | RedrawState::WaitingForEstimatedVBlank(_) + | RedrawState::WaitingForEstimatedVBlankAndQueued(_)) => { + // This is an error!() because it shouldn't happen, but on some systems it somehow + // does. Kernel sending rogue vblank events? + // + // https://github.com/YaLTeR/niri/issues/556 + // https://github.com/YaLTeR/niri/issues/615 + error!( + "unexpected redraw state for output {name} (should be WaitingForVBlank); \ + can happen when resuming from sleep or powering on monitors: {state:?}" + ); + true + } + }; // Mark the last frame as submitted. match surface.compositor.frame_submitted() { @@ -1209,14 +1218,6 @@ impl Tty { output_state.frame_clock.presented(presentation_time); - let redraw_needed = match mem::replace(&mut output_state.redraw_state, RedrawState::Idle) { - RedrawState::Idle => unreachable!(), - RedrawState::Queued => unreachable!(), - RedrawState::WaitingForVBlank { redraw_needed } => redraw_needed, - RedrawState::WaitingForEstimatedVBlank(_) => unreachable!(), - RedrawState::WaitingForEstimatedVBlankAndQueued(_) => unreachable!(), - }; - if redraw_needed || output_state.unfinished_animations_remain { let vblank_frame = tracy_client::Client::running() .unwrap() diff --git a/src/niri.rs b/src/niri.rs index 0f43333b..7c87ecc5 100644 --- a/src/niri.rs +++ b/src/niri.rs @@ -344,7 +344,7 @@ pub struct OutputState { pub debug_damage_tracker: OutputDamageTracker, } -#[derive(Default)] +#[derive(Debug, Default)] pub enum RedrawState { /// The compositor is idle. #[default] -- cgit