Repository navigation
renderer: vsync unfocused surfaces while dirty - #14068
Merged
Merged
Conversation
6ae1784 Unfocused surfaces stopped the CVDisplayLink and encoded a GPU frame on every PTY wakeup. A burst of close writes became that many Metal submits instead of one vsync. Keep the link running while the surface is visible and dirty or animating, whether or not it is focused. Idle surfaces still park. Focus continues to gate cursor blink, custom-shader animation, and QoS.
mitchellh
approved these changes
Aug 30, 2026
mitchellh
left a comment
Contributor
There was a problem hiding this comment.
This actually makes sense to me.
danielitus
added a commit
to danielitus/ghostty
that referenced
this pull request
Sep 5, 2026
The installed app hard-froze on 2026-09-04: a render thread was stuck forever inside CVDisplayLinkStop (exposed by upstream's per-frame display-link parking, ghostty-org#14035/ghostty-org#14068), its 64-slot mailbox filled, and the app thread then blocked forever in occlusionCallback. - Keep the display link running while visible and stop it only on occlusion, and never call CVDisplayLinkStop on a link that is not running (deinit, loopExit). - Bound every app-thread push to the render mailbox (including the macOS display-id change) and the IO thread's resize push. After the first timeout the surface is marked wedged and later pushes fail fast instead of stalling the UI again. - Never lose state-carrying messages: undelivered visibility, focus, display, config and font-grid messages are kept and retried in order before the next push and on every render request, so a recovered render thread converges. Ownership of the config allocation and the font grid ref stays with the surface until delivered; the cell size is applied only once the renderer holds the new grid. - Closing a surface whose render thread is wedged detaches the thread and leaks the surface instead of joining it (embedded apprt), so a dead tab can be closed without hanging the app.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A follow on for #14035, we can now fix a long standing effiency/performance bug now that we park the display link while idle. This actually could cause "animated" un-focused windows to use more GPU than their focused counterparts. (AI Agent interfaces seem to love animation).
6ae1784
Unfocused surfaces stopped the CVDisplayLink and encoded a GPU frame on every PTY wakeup. A burst of close writes became that many Metal submits instead of one vsync.
Keep the link running while the surface is visible and dirty or animating, whether or not it is focused. Idle surfaces still park.