1
0
Fork 0
forked from wry/wry

output-schedule: refactor change tracking

This commit is contained in:
Julian Orth 2024-10-29 08:47:49 +01:00
parent 7e40e90c4d
commit 435b0a49da

View file

@ -15,6 +15,17 @@ use {
std::{cell::Cell, rc::Rc}, std::{cell::Cell, rc::Rc},
}; };
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
enum Change {
/// The backend has applied the latest changes.
None,
/// There are changes that the backend is not yet aware of.
Scheduled,
/// The backend is aware that there are changes and will apply them as part of the
/// next latch event.
AwaitingLatch,
}
pub struct OutputSchedule { pub struct OutputSchedule {
changed: AsyncEvent, changed: AsyncEvent,
run: Cell<bool>, run: Cell<bool>,
@ -32,9 +43,8 @@ pub struct OutputSchedule {
vrr_enabled: Cell<bool>, vrr_enabled: Cell<bool>,
present_scheduled: Cell<bool>, hardware_cursor_change: Cell<Change>,
needs_hardware_cursor_commit: Cell<bool>, software_cursor_change: Cell<Change>,
needs_software_cursor_damage: Cell<bool>,
iteration: NumCell<u64>, iteration: NumCell<u64>,
} }
@ -53,9 +63,8 @@ impl OutputSchedule {
ring: ring.clone(), ring: ring.clone(),
eng: eng.clone(), eng: eng.clone(),
vrr_enabled: Default::default(), vrr_enabled: Default::default(),
present_scheduled: Cell::new(true), hardware_cursor_change: Cell::new(Change::None),
needs_hardware_cursor_commit: Default::default(), software_cursor_change: Cell::new(Change::None),
needs_software_cursor_damage: Default::default(),
hardware_cursor: Default::default(), hardware_cursor: Default::default(),
persistent: persistent.clone(), persistent: persistent.clone(),
last_present_nsec: Default::default(), last_present_nsec: Default::default(),
@ -79,9 +88,9 @@ impl OutputSchedule {
fn trigger(&self) { fn trigger(&self) {
let trigger = self.vrr_enabled.get() let trigger = self.vrr_enabled.get()
&& !self.present_scheduled.get()
&& self.cursor_delta_nsec.is_some() && self.cursor_delta_nsec.is_some()
&& (self.needs_software_cursor_damage.get() || self.needs_hardware_cursor_commit.get()); && (self.software_cursor_change.get() == Change::Scheduled
|| self.hardware_cursor_change.get() == Change::Scheduled);
if trigger { if trigger {
self.run.set(true); self.run.set(true);
self.changed.trigger(); self.changed.trigger();
@ -90,7 +99,12 @@ impl OutputSchedule {
pub fn latched(&self) { pub fn latched(&self) {
self.last_present_nsec.set(self.eng.now().nsec()); self.last_present_nsec.set(self.eng.now().nsec());
self.present_scheduled.set(false); if self.software_cursor_change.get() == Change::AwaitingLatch {
self.software_cursor_change.set(Change::None);
}
if self.hardware_cursor_change.get() == Change::AwaitingLatch {
self.hardware_cursor_change.set(Change::None);
}
self.iteration.fetch_add(1); self.iteration.fetch_add(1);
self.trigger(); self.trigger();
} }
@ -126,25 +140,26 @@ impl OutputSchedule {
} }
pub fn hardware_cursor_changed(&self) { pub fn hardware_cursor_changed(&self) {
if !self.needs_hardware_cursor_commit.replace(true) { if self.hardware_cursor_change.get() == Change::None {
self.hardware_cursor_change.set(Change::Scheduled);
self.trigger(); self.trigger();
} }
} }
pub fn software_cursor_changed(&self) { pub fn software_cursor_changed(&self) {
if !self.needs_software_cursor_damage.replace(true) { if self.software_cursor_change.get() == Change::None {
self.software_cursor_change.set(Change::Scheduled);
self.trigger(); self.trigger();
} }
} }
async fn run_once(&self) { async fn run_once(&self) {
if self.present_scheduled.get() {
return;
}
if !self.needs_hardware_cursor_commit.get() && !self.needs_software_cursor_damage.get() {
return;
}
loop { loop {
if self.hardware_cursor_change.get() != Change::Scheduled
&& self.software_cursor_change.get() != Change::Scheduled
{
return;
}
if !self.vrr_enabled.get() { if !self.vrr_enabled.get() {
return; return;
} }
@ -169,15 +184,15 @@ impl OutputSchedule {
} }
pub fn commit_cursor(&self) { pub fn commit_cursor(&self) {
if self.needs_hardware_cursor_commit.take() { if self.hardware_cursor_change.get() == Change::Scheduled {
if let Some(hc) = self.hardware_cursor.get() { if let Some(hc) = self.hardware_cursor.get() {
hc.damage(); hc.damage();
self.present_scheduled.set(true);
} }
self.hardware_cursor_change.set(Change::AwaitingLatch);
} }
if self.needs_software_cursor_damage.take() { if self.software_cursor_change.get() == Change::Scheduled {
self.connector.damage(); self.connector.damage();
self.present_scheduled.set(true); self.software_cursor_change.set(Change::AwaitingLatch);
} }
} }
} }