Maintain smooth frame rates when ProMotion and direct mode are enabled (#7305)

This is achieved by starting a `CADisplayLink` that will invoke the
`on_request_frame` callback at the refresh interval of the display.

We only actually draw frames when the window was dirty, or for 2 extra
seconds after the last input event to ensure ProMotion doesn't downclock
the refresh rate when the user is actively interacting with the window.

Release Notes:

- Improved performance when using a ProMotion display with fast key
repeat rates.

---------

Co-authored-by: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
Antonio Scandurra 2024-02-02 16:42:46 -07:00 committed by GitHub
parent f2ba969d5b
commit 15edc46827
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 50 additions and 37 deletions

View file

@ -652,27 +652,20 @@ impl AppContext {
}
}
} else {
for window in self.windows.values() {
if let Some(window) = window.as_ref() {
if window.dirty {
window.platform_window.invalidate();
}
}
}
#[cfg(any(test, feature = "test-support"))]
for window in self
.windows
.values()
.filter_map(|window| {
let window = window.as_ref()?;
(window.dirty || window.focus_invalidated).then_some(window.handle)
(window.dirty.get() || window.focus_invalidated).then_some(window.handle)
})
.collect::<Vec<_>>()
{
self.update_window(window, |_, cx| cx.draw()).unwrap();
}
#[allow(clippy::collapsible_else_if)]
if self.pending_effects.is_empty() {
break;
}
@ -749,7 +742,7 @@ impl AppContext {
fn apply_refresh_effect(&mut self) {
for window in self.windows.values_mut() {
if let Some(window) = window.as_mut() {
window.dirty = true;
window.dirty.set(true);
}
}
}