aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2024-03-23 12:46:26 +0400
committerIvan Molodetskikh <yalterz@gmail.com>2024-03-23 15:45:44 +0400
commit021a2a1af771421e39a990bb1eac624e0ef274de (patch)
treecfd607d93c740d960325f0a6df9a0afa33f04ca2 /src
parent354f0b039a768c77e9c703cbcbca693f0b8c6f96 (diff)
downloadniri-021a2a1af771421e39a990bb1eac624e0ef274de.tar.gz
niri-021a2a1af771421e39a990bb1eac624e0ef274de.tar.bz2
niri-021a2a1af771421e39a990bb1eac624e0ef274de.zip
Don't use an idle for queued redraw tracking
This way we can order the redraw after all the refreshing, where it should be.
Diffstat (limited to 'src')
-rw-r--r--src/backend/tty.rs16
-rw-r--r--src/backend/winit.rs2
-rw-r--r--src/niri.rs79
3 files changed, 48 insertions, 49 deletions
diff --git a/src/backend/tty.rs b/src/backend/tty.rs
index 82320ab4..fdf25df8 100644
--- a/src/backend/tty.rs
+++ b/src/backend/tty.rs
@@ -1055,7 +1055,7 @@ impl Tty {
let redraw_needed = match mem::replace(&mut output_state.redraw_state, RedrawState::Idle) {
RedrawState::Idle => unreachable!(),
- RedrawState::Queued(_) => unreachable!(),
+ RedrawState::Queued => unreachable!(),
RedrawState::WaitingForVBlank { redraw_needed } => redraw_needed,
RedrawState::WaitingForEstimatedVBlank(_) => unreachable!(),
RedrawState::WaitingForEstimatedVBlankAndQueued(_) => unreachable!(),
@@ -1089,12 +1089,12 @@ impl Tty {
match mem::replace(&mut output_state.redraw_state, RedrawState::Idle) {
RedrawState::Idle => unreachable!(),
- RedrawState::Queued(_) => unreachable!(),
+ RedrawState::Queued => unreachable!(),
RedrawState::WaitingForVBlank { .. } => unreachable!(),
RedrawState::WaitingForEstimatedVBlank(_) => (),
// The timer fired just in front of a redraw.
- RedrawState::WaitingForEstimatedVBlankAndQueued((_, idle)) => {
- output_state.redraw_state = RedrawState::Queued(idle);
+ RedrawState::WaitingForEstimatedVBlankAndQueued(_) => {
+ output_state.redraw_state = RedrawState::Queued;
return;
}
}
@@ -1198,10 +1198,10 @@ impl Tty {
};
match mem::replace(&mut output_state.redraw_state, new_state) {
RedrawState::Idle => unreachable!(),
- RedrawState::Queued(_) => (),
+ RedrawState::Queued => (),
RedrawState::WaitingForVBlank { .. } => unreachable!(),
RedrawState::WaitingForEstimatedVBlank(_) => unreachable!(),
- RedrawState::WaitingForEstimatedVBlankAndQueued((token, _)) => {
+ RedrawState::WaitingForEstimatedVBlankAndQueued(token) => {
niri.event_loop.remove(token);
}
};
@@ -1909,10 +1909,10 @@ fn queue_estimated_vblank_timer(
let output_state = niri.output_state.get_mut(&output).unwrap();
match mem::take(&mut output_state.redraw_state) {
RedrawState::Idle => unreachable!(),
- RedrawState::Queued(_) => (),
+ RedrawState::Queued => (),
RedrawState::WaitingForVBlank { .. } => unreachable!(),
RedrawState::WaitingForEstimatedVBlank(token)
- | RedrawState::WaitingForEstimatedVBlankAndQueued((token, _)) => {
+ | RedrawState::WaitingForEstimatedVBlankAndQueued(token) => {
output_state.redraw_state = RedrawState::WaitingForEstimatedVBlank(token);
return;
}
diff --git a/src/backend/winit.rs b/src/backend/winit.rs
index 580802bc..ca80f339 100644
--- a/src/backend/winit.rs
+++ b/src/backend/winit.rs
@@ -193,7 +193,7 @@ impl Winit {
let output_state = niri.output_state.get_mut(output).unwrap();
match mem::replace(&mut output_state.redraw_state, RedrawState::Idle) {
RedrawState::Idle => unreachable!(),
- RedrawState::Queued(_) => (),
+ RedrawState::Queued => (),
RedrawState::WaitingForVBlank { .. } => unreachable!(),
RedrawState::WaitingForEstimatedVBlank(_) => unreachable!(),
RedrawState::WaitingForEstimatedVBlankAndQueued(_) => unreachable!(),
diff --git a/src/niri.rs b/src/niri.rs
index 54c99453..baf62c5b 100644
--- a/src/niri.rs
+++ b/src/niri.rs
@@ -43,7 +43,7 @@ use smithay::output::{self, Output, PhysicalProperties, Subpixel};
use smithay::reexports::calloop::generic::Generic;
use smithay::reexports::calloop::timer::{TimeoutAction, Timer};
use smithay::reexports::calloop::{
- Idle, Interest, LoopHandle, LoopSignal, Mode, PostAction, RegistrationToken,
+ Interest, LoopHandle, LoopSignal, Mode, PostAction, RegistrationToken,
};
use smithay::reexports::wayland_protocols::ext::session_lock::v1::server::ext_session_lock_v1::ExtSessionLockV1;
use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel::WmCapabilities;
@@ -270,13 +270,13 @@ pub enum RedrawState {
#[default]
Idle,
/// A redraw is queued.
- Queued(Idle<'static>),
+ Queued,
/// We submitted a frame to the KMS and waiting for it to be presented.
WaitingForVBlank { redraw_needed: bool },
/// We did not submit anything to KMS and made a timer to fire at the estimated VBlank.
WaitingForEstimatedVBlank(RegistrationToken),
/// A redraw is queued on top of the above.
- WaitingForEstimatedVBlankAndQueued((RegistrationToken, Idle<'static>)),
+ WaitingForEstimatedVBlankAndQueued(RegistrationToken),
}
pub struct PopupGrabState {
@@ -417,6 +417,7 @@ impl State {
self.update_keyboard_focus();
self.refresh_pointer_focus();
foreign_toplevel::refresh(self);
+ self.niri.redraw_queued_outputs(&mut self.backend);
{
let _span = tracy_client::span!("flush_clients");
@@ -1497,13 +1498,10 @@ impl Niri {
match state.redraw_state {
RedrawState::Idle => (),
- RedrawState::Queued(idle) => idle.cancel(),
+ RedrawState::Queued => (),
RedrawState::WaitingForVBlank { .. } => (),
RedrawState::WaitingForEstimatedVBlank(token) => self.event_loop.remove(token),
- RedrawState::WaitingForEstimatedVBlankAndQueued((token, idle)) => {
- self.event_loop.remove(token);
- idle.cancel();
- }
+ RedrawState::WaitingForEstimatedVBlankAndQueued(token) => self.event_loop.remove(token),
}
// Disable the output global and remove some time later to give the clients some time to
@@ -1890,34 +1888,36 @@ impl Niri {
/// Schedules an immediate redraw if one is not already scheduled.
pub fn queue_redraw(&mut self, output: Output) {
let state = self.output_state.get_mut(&output).unwrap();
- let token = match mem::take(&mut state.redraw_state) {
- RedrawState::Idle => None,
- RedrawState::WaitingForEstimatedVBlank(token) => Some(token),
-
- // A redraw is already queued, put it back and do nothing.
- value @ (RedrawState::Queued(_)
- | RedrawState::WaitingForEstimatedVBlankAndQueued(_)) => {
- state.redraw_state = value;
- return;
+ state.redraw_state = match mem::take(&mut state.redraw_state) {
+ RedrawState::Idle => RedrawState::Queued,
+ RedrawState::WaitingForEstimatedVBlank(token) => {
+ RedrawState::WaitingForEstimatedVBlankAndQueued(token)
}
- // We're waiting for VBlank, request a redraw afterwards.
- RedrawState::WaitingForVBlank { .. } => {
- state.redraw_state = RedrawState::WaitingForVBlank {
- redraw_needed: true,
- };
- return;
+ // A redraw is already queued.
+ value @ (RedrawState::Queued | RedrawState::WaitingForEstimatedVBlankAndQueued(_)) => {
+ value
}
+
+ // We're waiting for VBlank, request a redraw afterwards.
+ RedrawState::WaitingForVBlank { .. } => RedrawState::WaitingForVBlank {
+ redraw_needed: true,
+ },
};
+ }
- let idle = self.event_loop.insert_idle(move |state| {
- state.niri.redraw(&mut state.backend, &output);
- });
+ pub fn redraw_queued_outputs(&mut self, backend: &mut Backend) {
+ let _span = tracy_client::span!("Niri::redraw_queued_outputs");
- state.redraw_state = match token {
- Some(token) => RedrawState::WaitingForEstimatedVBlankAndQueued((token, idle)),
- None => RedrawState::Queued(idle),
- };
+ while let Some((output, _)) = self.output_state.iter().find(|(_, state)| {
+ matches!(
+ state.redraw_state,
+ RedrawState::Queued | RedrawState::WaitingForEstimatedVBlankAndQueued(_)
+ )
+ }) {
+ let output = output.clone();
+ self.redraw(backend, &output);
+ }
}
pub fn pointer_element<R: NiriRenderer>(
@@ -2290,7 +2290,7 @@ impl Niri {
let state = self.output_state.get_mut(output).unwrap();
assert!(matches!(
state.redraw_state,
- RedrawState::Queued(_) | RedrawState::WaitingForEstimatedVBlankAndQueued(_)
+ RedrawState::Queued | RedrawState::WaitingForEstimatedVBlankAndQueued(_)
));
let target_presentation_time = state.frame_clock.next_presentation_time();
@@ -2324,15 +2324,14 @@ impl Niri {
if res == RenderResult::Skipped {
// Update the redraw state on failed render.
- state.redraw_state =
- if let RedrawState::WaitingForEstimatedVBlank(token)
- | RedrawState::WaitingForEstimatedVBlankAndQueued((token, _)) =
- state.redraw_state
- {
- RedrawState::WaitingForEstimatedVBlank(token)
- } else {
- RedrawState::Idle
- };
+ state.redraw_state = if let RedrawState::WaitingForEstimatedVBlank(token)
+ | RedrawState::WaitingForEstimatedVBlankAndQueued(token) =
+ state.redraw_state
+ {
+ RedrawState::WaitingForEstimatedVBlank(token)
+ } else {
+ RedrawState::Idle
+ };
}
// Update the lock render state on successful render, or if monitors are inactive. When