mirror of
https://github.com/wez/wezterm.git
synced 2024-11-30 14:49:26 +03:00
don't vsync on x11, do our own throttling
Some users mentioned that there's a lag after selecting text on X11. Tracing through, I saw that the we invalidate the window quite a lot when dragging the selection, and the buffer swap could delay for several ms each time while waiting for the vsync. Rather than blocking the GUI thread and making it bog down, this commit adopts a technique similar to the recent Wayland frame sync changes, except that we enforce a minimum of 33ms between frames in our own scheduler to avoid blocking for several ms at a time. This seems to do a decent job of balancing responsiveness during selection with updating the display, and keeps the buffer swap delay down to microseconds. We may want to make this delay configurable.
This commit is contained in:
parent
2446ac5d7f
commit
fc5ca5a297
@ -488,17 +488,7 @@ impl GlState {
|
||||
display: Option<ffi::EGLNativeDisplayType>,
|
||||
wegl_surface: &wayland_egl::WlEglSurface,
|
||||
) -> anyhow::Result<Self> {
|
||||
let state = Self::create(display, wegl_surface.ptr())?;
|
||||
// Request non-blocking buffer swaps when using egl with wayland:
|
||||
// <https://emersion.fr/blog/2018/wayland-rendering-loop/>
|
||||
unsafe {
|
||||
state
|
||||
.connection
|
||||
.egl
|
||||
.egl
|
||||
.SwapInterval(state.connection.display, 0);
|
||||
}
|
||||
Ok(state)
|
||||
Self::create(display, wegl_surface.ptr())
|
||||
}
|
||||
|
||||
pub fn create(
|
||||
@ -651,6 +641,13 @@ impl GlState {
|
||||
|
||||
log::trace!("Successfully created a surface using this configuration");
|
||||
connection.egl.log_config_info(connection.display, config);
|
||||
|
||||
// Request non-blocking buffer swaps; we'll manage throttling
|
||||
// frames at the application level.
|
||||
unsafe {
|
||||
connection.egl.egl.SwapInterval(connection.display, 0);
|
||||
}
|
||||
|
||||
return Ok(Self {
|
||||
connection: Rc::clone(connection),
|
||||
context,
|
||||
|
@ -67,6 +67,8 @@ pub(crate) struct XWindowInner {
|
||||
title: String,
|
||||
has_focus: bool,
|
||||
last_cursor_position: Rect,
|
||||
invalidated: bool,
|
||||
paint_throttled: bool,
|
||||
}
|
||||
|
||||
impl Drop for XWindowInner {
|
||||
@ -782,6 +784,8 @@ impl XWindow {
|
||||
config: config.clone(),
|
||||
has_focus: false,
|
||||
last_cursor_position: Rect::default(),
|
||||
paint_throttled: false,
|
||||
invalidated: false,
|
||||
}))
|
||||
};
|
||||
|
||||
@ -829,8 +833,29 @@ impl XWindowInner {
|
||||
fn show(&mut self) {
|
||||
xcb::map_window(self.conn().conn(), self.window_id);
|
||||
}
|
||||
|
||||
fn invalidate(&mut self) {
|
||||
if self.paint_throttled {
|
||||
self.invalidated = true;
|
||||
return;
|
||||
}
|
||||
self.invalidated = false;
|
||||
self.events.dispatch(WindowEvent::NeedRepaint);
|
||||
|
||||
self.paint_throttled = true;
|
||||
let window_id = self.window_id;
|
||||
promise::spawn::spawn(async move {
|
||||
// Don't try to paint more frequently than 30 fps
|
||||
async_io::Timer::after(std::time::Duration::from_millis(1000 / 30)).await;
|
||||
XConnection::with_window_inner(window_id, |inner| {
|
||||
inner.paint_throttled = false;
|
||||
if inner.invalidated {
|
||||
inner.invalidate();
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
fn toggle_fullscreen(&mut self) {
|
||||
|
Loading…
Reference in New Issue
Block a user