diff --git a/release-notes.md b/release-notes.md index 442abccf..d2ee7ad4 100644 --- a/release-notes.md +++ b/release-notes.md @@ -1,5 +1,6 @@ # Unreleased +- Various bugfixes. - Add support fo ext-data-control-v1. # 1.7.0 (2024-10-25) diff --git a/src/backends/metal/present.rs b/src/backends/metal/present.rs index f99ac26f..082aa1be 100644 --- a/src/backends/metal/present.rs +++ b/src/backends/metal/present.rs @@ -173,6 +173,9 @@ impl MetalConnector { _ => return Ok(()), }; + if self.has_damage.get() > 0 || self.cursor_damage.get() { + node.schedule.commit_cursor(); + } self.latch_cursor(&node)?; let cursor_programming = self.compute_cursor_programming(); let latched = self.latch(&node); diff --git a/src/output_schedule.rs b/src/output_schedule.rs index df83d6af..548701f9 100644 --- a/src/output_schedule.rs +++ b/src/output_schedule.rs @@ -15,6 +15,17 @@ use { 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 { changed: AsyncEvent, run: Cell, @@ -32,9 +43,8 @@ pub struct OutputSchedule { vrr_enabled: Cell, - present_scheduled: Cell, - needs_hardware_cursor_commit: Cell, - needs_software_cursor_damage: Cell, + hardware_cursor_change: Cell, + software_cursor_change: Cell, iteration: NumCell, } @@ -53,9 +63,8 @@ impl OutputSchedule { ring: ring.clone(), eng: eng.clone(), vrr_enabled: Default::default(), - present_scheduled: Cell::new(true), - needs_hardware_cursor_commit: Default::default(), - needs_software_cursor_damage: Default::default(), + hardware_cursor_change: Cell::new(Change::None), + software_cursor_change: Cell::new(Change::None), hardware_cursor: Default::default(), persistent: persistent.clone(), last_present_nsec: Default::default(), @@ -79,9 +88,9 @@ impl OutputSchedule { fn trigger(&self) { let trigger = self.vrr_enabled.get() - && !self.present_scheduled.get() && 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 { self.run.set(true); self.changed.trigger(); @@ -90,7 +99,12 @@ impl OutputSchedule { pub fn latched(&self) { 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.trigger(); } @@ -126,25 +140,26 @@ impl OutputSchedule { } 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(); } } 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(); } } 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 { + if self.hardware_cursor_change.get() != Change::Scheduled + && self.software_cursor_change.get() != Change::Scheduled + { + return; + } if !self.vrr_enabled.get() { return; } @@ -165,15 +180,19 @@ impl OutputSchedule { break; } } - if self.needs_hardware_cursor_commit.take() { + self.commit_cursor(); + } + + pub fn commit_cursor(&self) { + if self.hardware_cursor_change.get() == Change::Scheduled { if let Some(hc) = self.hardware_cursor.get() { 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.present_scheduled.set(true); + self.software_cursor_change.set(Change::AwaitingLatch); } } }