fix: keep WebGL contexts across panel hides to stop renderer-swap ghosting#313
Conversation
…sting Disposing WebGL on every panel hide and reattaching on show swaps renderers (WebGL->DOM->WebGL) on every tab switch. A stale frame or texture atlas from one renderer can survive into the next, producing ghosted/overdrawn rows that persist through live output until a manual full refresh — the same family as the blank-canvas-on-refocus bug (#306) and the missed repaint after blur. - Attach WebGL lazily on first show, keep the context while the panel is mounted (bounded by the active session's terminals, ~16-context ceiling is not approached; onContextLoss falls back to DOM renderer) - Detach only after the sustained app-blur timeout and on unmount - On reattach, clear the texture atlas before the deferred full repaint - Update the TerminalPanel lifecycle doc to match
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7654d9fff9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| } | ||
| // Lazy first attach: never-shown background panels stay on the DOM | ||
| // renderer; once attached, the context survives hides (see policy above). | ||
| if (!panelVisible && !webglAddonRef.current) return; |
There was a problem hiding this comment.
Cap retained WebGL contexts for hidden terminals
When a user opens and visits many terminal tabs in one session, this guard only skips never-shown hidden panels; every previously shown hidden terminal keeps its WebGL context because the hide path no longer detaches it. PanelGroupView keeps terminal tabs mounted behind display:none, and the UI/IPC paths allow creating arbitrary terminal panels, so sessions with enough visited terminals can exceed Chromium's WebGL context budget and force context loss or renderer fallback in active terminals. Please add an eviction/cap for hidden WebGL contexts rather than retaining all of them indefinitely.
Useful? React with 👍 / 👎.
Summary
On v2.4.11+ (post-#310), switching tabs/panes can leave ghosted/overdrawn terminal rows — two frames of text interleaved in the same rows — persisting through live output until the manual Refresh button's full reset+replay. Reported on v2.4.13 in production use.
Root cause
Every panel hide disposed the WebGL addon and every show recreated it, swapping renderers (WebGL→DOM→WebGL) on each tab switch. A stale frame or texture-atlas state from one renderer can survive the swap; the light activation repaint (which replaced the old full reset+replay in #310) redraws the live renderer but cannot touch the stale layer, so the ghost persists. Same failure family as blank-canvas-on-refocus (#306) and the missed-repaint-after-blur fix in #310.
Change
Context budget: contexts are bounded by the active session's mounted terminals (typically ≤5–8, under the browser's ~16 ceiling); idle contexts cost no GPU time;
onContextLossalready falls back to the DOM renderer gracefully.Pre-Merge Testing
Build Verification
pnpm typecheckpassespnpm lintpasses (0 errors)