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.
This commit is contained in:
Ivan Molodetskikh
2024-03-02 08:10:05 +04:00
parent 24537ec2ba
commit 93243d7772
3 changed files with 43 additions and 30 deletions
+14 -16
View File
@@ -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;
}