aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2024-09-10 10:48:45 +0300
committerIvan Molodetskikh <yalterz@gmail.com>2024-09-10 10:48:45 +0300
commit6b6a84e55be388589e49fc9ddd8502dd2da7aca9 (patch)
treedf5b3ab59e57cc6bf819d816c5d4f76276910a41 /src
parent7d5785e96f3deaee1bb279ee16b3b12f05344951 (diff)
downloadniri-6b6a84e55be388589e49fc9ddd8502dd2da7aca9.tar.gz
niri-6b6a84e55be388589e49fc9ddd8502dd2da7aca9.tar.bz2
niri-6b6a84e55be388589e49fc9ddd8502dd2da7aca9.zip
Avoid panics on more wrong VBlank events
Diffstat (limited to 'src')
-rw-r--r--src/backend/tty.rs35
-rw-r--r--src/niri.rs2
2 files changed, 19 insertions, 18 deletions
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]