fix(terminal): prevent transparent WebGL flicker (#6491)#6597
Conversation
xterm's WebGL renderer re-blends semi-transparent per-cell backgrounds over the retained framebuffer on partial redraws, so when terminal background opacity < 1 the background flickers/accumulates alpha on every output update. The DOM renderer composites the full background each frame and does not exhibit this. Force the DOM renderer whenever background transparency is active and restore WebGL automatically when opacity returns to 1. The gate lives in shouldUseTerminalWebgl so it covers every existing WebGL attach path, and applyTerminalAppearance flips the renderer live as the opacity slider crosses 1 (no remount). An explicit GPU "on" setting yields to transparency since the flicker is a correctness bug, not a perf choice. Fixes #6491 Co-authored-by: Orca <help@stably.ai>
|
Warning Review limit reached
Next review available in: 24 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (23)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Verification evidence (#6491)Unit tests (vitest)Full Live app validation (Electron over CDP, dev build of this branch)Attached to a dev build of
Raw eval output at opacity 0.85: {"opacity":0.85,"canvasCount":1,"canvasInfo":["xterm-decoration-overview-ruler"],"hasRowsDiv":true,"rowDivs":61}(the remaining Before/after reasoning: Before this fix, Screenshot of the terminal rendering cleanly at opacity 0.85 (DOM renderer) saved locally under the gitignored |
|
Follow-up pushed in What changed:
Tradeoff status: the reported user-facing tradeoff is eliminated for the current supported xterm WebGL addon. The remaining honest caveat is implementation-level: xterm has no public transparent-frame clear API, so the WebGL-preserving path is guarded and falls back to DOM if a future xterm version changes the private renderer shape. Validation:
|
Summary
Fixes #6491 — terminal backgrounds with opacity < 1 no longer flicker/step brightness on redraw.
Root cause:
@xterm/addon-webgldraws Orca's rgba terminal background into an alpha WebGL canvas. Without clearing that canvas before redraw, the semi-transparent background is blended over the previous frame again, so repeated output updates visibly accumulate alpha.Current fix:
renderRowspath so the alpha canvas is cleared to transparent before xterm draws the latest model.Tradeoffs
The reported user-facing tradeoff is eliminated for Orca's current supported
@xterm/addon-webglversion: transparent terminals no longer have to give up WebGL acceleration.Honest implementation caveat: xterm exposes no public API for this transparent-frame clear, so the WebGL-preserving path uses a guarded private renderer shape. If a future xterm update changes that shape, the guard intentionally falls back to DOM for transparent panes to preserve correctness.
Testing
./node_modules/.bin/vitest run --config config/vitest.config.ts src/renderer/src/lib/pane-manager/pane-webgl-transparent-clear.test.ts src/renderer/src/lib/pane-manager/pane-webgl-renderer.test.ts src/renderer/src/lib/pane-manager/pane-rendering-control.test.ts src/renderer/src/lib/pane-manager/pane-lifecycle.test.ts src/renderer/src/components/terminal-pane/terminal-cursor-inactive-style.test.ts— 38 passing./node_modules/.bin/vitest run --config config/vitest.config.ts src/renderer/src/lib/pane-manager— 268 passingpnpm typecheck:web— clean./node_modules/.bin/oxlint <changed terminal/pane-manager files> --quiet— cleangit merge-tree origin/main HEAD— clean merge tree, no conflictsNotes
The earlier PR evidence comment described the first implementation, where transparent panes switched to the DOM renderer. The latest commit changes that behavior: transparent panes now keep WebGL when the guarded clear hook installs, with DOM only as the compatibility fallback.
Made with Orca