1
1
mirror of https://github.com/wez/wezterm.git synced 2024-11-23 15:04:36 +03:00

wayland: make use of the frame callback

This commit ties our invalidation requests together with the surface
frame callback request so that we can throttle our frame rate if
we're busy, but still remain largely idle if we're not changing
any content.

refs: https://github.com/wez/wezterm/issues/884
This commit is contained in:
Wez Furlong 2021-08-07 09:30:36 -07:00
parent 609f9358eb
commit 45576eeeab

View File

@ -123,6 +123,7 @@ pub struct WaylandWindowInner {
pending_mouse: Arc<Mutex<PendingMouse>>,
pending_first_configure: Option<async_channel::Sender<()>>,
frame_callback: Option<Main<WlCallback>>,
invalidated: bool,
// wegl_surface is listed before gl_state because it
// must be dropped before gl_state otherwise the underlying
// libraries will segfault on shutdown
@ -308,6 +309,7 @@ impl WaylandWindow {
copy_and_paste,
events: WindowEventSender::new(event_handler),
surface,
invalidated: false,
window: Some(window),
dimensions,
window_state: WindowState::default(),
@ -648,26 +650,36 @@ impl WaylandWindowInner {
Ok(gl_state)
}
fn next_frame_is_ready(&mut self) {
self.frame_callback.take();
if self.invalidated {
self.do_paint().ok();
}
}
fn do_paint(&mut self) -> anyhow::Result<()> {
if self.frame_callback.is_some() {
// Painting now won't be productive, so skip it but
// remember that we need to be painted so that when
// the compositor is ready for us, we can paint then.
self.invalidated = true;
return Ok(());
}
self.invalidated = false;
self.events.dispatch(WindowEvent::NeedRepaint);
// We could request a callback when we should render the next frame
// by doing this here, but unconditionally doing this will make us
// redraw at the display refresh rate which is potentially more
// often than we want.
if false {
let callback = self.surface.frame();
let window_id = self.window_id;
callback.quick_assign(move |_source, _event, _data| {
WaylandConnection::with_window_inner(window_id, |inner| {
inner.invalidate();
Ok(())
});
// Ask the compositor to wake us up when its time to paint
// the next frame
let window_id = self.window_id;
let callback = self.surface.frame();
callback.quick_assign(move |_source, _event, _data| {
WaylandConnection::with_window_inner(window_id, |inner| {
inner.next_frame_is_ready();
Ok(())
});
self.frame_callback.replace(callback);
} else {
self.frame_callback.take();
}
});
self.frame_callback.replace(callback);
Ok(())
}
@ -943,6 +955,10 @@ impl WaylandWindowInner {
}
fn invalidate(&mut self) {
if self.frame_callback.is_some() {
self.invalidated = true;
return;
}
self.do_paint().unwrap();
}