qt/vulkan: async resize via renderer thread (drop GUI-thread sync draw)
syncSurfaceSize was calling ghostty_surface_draw + drainVulkan inline on every resizeEvent. Wayland delivers configures (and Qt fires resize events) at compositor rate during an interactive drag (60-120 Hz), and each call blocked the GUI thread on a full Vulkan render - visible as laggy window-edge tracking and laggy content reflow. The async path already exists: ghostty_surface_set_size mails the IO thread which mails the renderer thread (.resize) and notifies its wakeup (termio/Termio.zig). The renderer produces the new-size frame on its own clock and it lands via presentVulkanDmabuf -> drainVulkan -> forceParentCommit. Drop the inline sync draw and let that work. The wp_viewport stretch + forceParentCommit stays so the subsurface keeps fully covering the new parent area until the real frame lands - without it, the area beyond the old subsurface extent shows through to whatever is behind the window during a fast drag (parent QWidget bg-fill paint can't reliably catch up). Brief bilinear stretch is the lesser evil vs. a transparent gap or a solid bg-color flood.pull/12846/head
parent
3f7d8b6aff
commit
91b6bb1856
|
|
@ -388,17 +388,31 @@ void GhosttySurface::syncSurfaceSize() {
|
|||
// path. The next Show event resets sizing state and triggers
|
||||
// a fresh sync, so dropping this is safe.
|
||||
//
|
||||
// Stretch the old buffer to the new destination first — gives
|
||||
// the compositor something to fill the new parent area with if
|
||||
// the synchronous render below takes more than one frame.
|
||||
// wp_viewport-stretch the existing buffer to the new dest so
|
||||
// the subsurface keeps covering the whole new parent area.
|
||||
// Without this the subsurface stays at its old buffer size at
|
||||
// position (0,0) and the area beyond it is uncovered — the
|
||||
// parent QWidget's bg-color paint can't reliably catch up
|
||||
// during a fast drag, so the gap shows through to whatever is
|
||||
// behind the window. The stretch is bilinear-filtered (text
|
||||
// briefly distorts), but full coverage with mildly distorted
|
||||
// text is the lesser evil vs. a transparent gap or jumping
|
||||
// back to a solid bg-color flood. The sync-mode child commit
|
||||
// is cached until parent commits, so forceParentCommit applies
|
||||
// it now.
|
||||
m_subsurfacePresenter->resizeDestination(width(), height());
|
||||
// Render at the new size and commit the proper new-size buffer.
|
||||
// drainVulkan calls forceParentCommit at the end, so the
|
||||
// sync-mode child cache + parent commit land atomically — the
|
||||
// compositor sees parent at new size + subsurface at new size
|
||||
// in the same frame, eliminating the resize bleed entirely.
|
||||
ghostty_surface_draw(m_surface);
|
||||
drainVulkan();
|
||||
forceParentCommit();
|
||||
// Do NOT call ghostty_surface_draw / drainVulkan here. The
|
||||
// ghostty_surface_set_size above mails the IO thread, which
|
||||
// mails the renderer thread (`.resize` message) and notifies
|
||||
// its wakeup (see termio/Termio.zig:500–502). The renderer
|
||||
// thread produces the next frame at the new size on its own
|
||||
// clock and it lands via presentVulkanDmabuf → drainVulkan →
|
||||
// forceParentCommit, replacing the stretched buffer. Running
|
||||
// ghostty_surface_draw inline here blocks the GUI thread on a
|
||||
// full Vulkan render per resize event during a continuous
|
||||
// drag (compositor delivers events at 60–120 Hz), lagging
|
||||
// both window edge tracking and content reflow.
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue