aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2024-03-02 08:10:05 +0400
committerIvan Molodetskikh <yalterz@gmail.com>2024-03-02 08:20:17 +0400
commit93243d77728c3a0f7d314ed916b5f1a273861990 (patch)
tree4426123e426f7c8424e1dade08bbe91f4693ad7b /src/backend
parent24537ec2ba3c24e2dd969b8a78df95dbdae1ac6d (diff)
downloadniri-93243d77728c3a0f7d314ed916b5f1a273861990.tar.gz
niri-93243d77728c3a0f7d314ed916b5f1a273861990.tar.bz2
niri-93243d77728c3a0f7d314ed916b5f1a273861990.zip
Disentangle frame callback sequence from real DRM sequence
It can currently happen that the estimated VBlank timer fires right before a real VBlank, which can cause some sequence collisions, which might cause frame callbacks to never be sent. To prevent this, just track the frame callback sequence fully separately. There isn't really any harm in this, and if we accidentally increment it more frequently than necessary then nothing terrible will happen.
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/tty.rs30
-rw-r--r--src/backend/winit.rs4
2 files changed, 18 insertions, 16 deletions
diff --git a/src/backend/tty.rs b/src/backend/tty.rs
index 63e81322..77b88cc8 100644
--- a/src/backend/tty.rs
+++ b/src/backend/tty.rs
@@ -983,15 +983,15 @@ impl Tty {
}
}
- if let Some(last_sequence) = output_state.current_estimated_sequence {
+ if let Some(last_sequence) = output_state.last_drm_sequence {
let delta = meta.sequence as f64 - last_sequence as f64;
tracy_client::Client::running()
.unwrap()
.plot(surface.sequence_delta_plot_name, delta);
}
+ output_state.last_drm_sequence = Some(meta.sequence);
output_state.frame_clock.presented(presentation_time);
- output_state.current_estimated_sequence = Some(meta.sequence);
let redraw_needed = match mem::replace(&mut output_state.redraw_state, RedrawState::Idle) {
RedrawState::Idle => unreachable!(),
@@ -1024,6 +1024,9 @@ impl Tty {
return;
};
+ // We waited for the timer, now we can send frame callbacks again.
+ output_state.frame_callback_sequence = output_state.frame_callback_sequence.wrapping_add(1);
+
match mem::replace(&mut output_state.redraw_state, RedrawState::Idle) {
RedrawState::Idle => unreachable!(),
RedrawState::Queued(_) => unreachable!(),
@@ -1036,14 +1039,10 @@ impl Tty {
}
}
- if let Some(sequence) = output_state.current_estimated_sequence.as_mut() {
- *sequence = sequence.wrapping_add(1);
-
- if output_state.unfinished_animations_remain {
- niri.queue_redraw(output);
- } else {
- niri.send_frame_callbacks(&output);
- }
+ if output_state.unfinished_animations_remain {
+ niri.queue_redraw(output);
+ } else {
+ niri.send_frame_callbacks(&output);
}
}
@@ -1147,12 +1146,11 @@ impl Tty {
}
};
- // We queued this frame successfully, so now we'll be sending frame
- // callbacks for the next sequence.
- if let Some(sequence) = output_state.current_estimated_sequence.as_mut()
- {
- *sequence = sequence.wrapping_add(1);
- }
+ // We queued this frame successfully, so the current client buffers were
+ // latched. We can send frame callbacks now, since a new client commit
+ // will no longer overwrite this frame and will wait for a VBlank.
+ output_state.frame_callback_sequence =
+ output_state.frame_callback_sequence.wrapping_add(1);
return RenderResult::Submitted;
}
diff --git a/src/backend/winit.rs b/src/backend/winit.rs
index e9413698..580802bc 100644
--- a/src/backend/winit.rs
+++ b/src/backend/winit.rs
@@ -199,6 +199,10 @@ impl Winit {
RedrawState::WaitingForEstimatedVBlankAndQueued(_) => unreachable!(),
}
+ output_state.frame_callback_sequence = output_state.frame_callback_sequence.wrapping_add(1);
+
+ // FIXME: this should wait until a frame callback from the host compositor, but it redraws
+ // right away instead.
if output_state.unfinished_animations_remain {
self.backend.window().request_redraw();
}