diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2024-03-02 08:10:05 +0400 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2024-03-02 08:20:17 +0400 |
| commit | 93243d77728c3a0f7d314ed916b5f1a273861990 (patch) | |
| tree | 4426123e426f7c8424e1dade08bbe91f4693ad7b /src/backend | |
| parent | 24537ec2ba3c24e2dd969b8a78df95dbdae1ac6d (diff) | |
| download | niri-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.rs | 30 | ||||
| -rw-r--r-- | src/backend/winit.rs | 4 |
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(); } |
