Skip to content

fix(desktop): fall back from terminal WebGL on context loss#4612

Closed
Kitenite wants to merge 4 commits into
mainfrom
vscode-xterm-glyph-issues
Closed

fix(desktop): fall back from terminal WebGL on context loss#4612
Kitenite wants to merge 4 commits into
mainfrom
vscode-xterm-glyph-issues

Conversation

@Kitenite
Copy link
Copy Markdown
Collaborator

@Kitenite Kitenite commented May 16, 2026

Summary

  • marks terminal WebGL as unavailable after a WebGL context loss in both V1 and V2 terminal setup paths
  • keeps the existing dispose + refresh behavior so the current terminal falls back to DOM rendering
  • avoids clearTextureAtlas-based recovery

Why

Clearing xterm's texture atlas can trigger the garbled glyph rendering issue in our app. A safer prevention path is to stop using WebGL after a context loss rather than rebuilding the atlas in place.

Validation

  • bun run lint -- apps/desktop/src/renderer/lib/terminal/terminal-addons.ts apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.ts
  • bun run --cwd apps/desktop typecheck

Summary by CodeRabbit

  • Bug Fixes
    • Improved terminal stability by implementing automatic fallback to DOM rendering when WebGL context is lost. This ensures the terminal remains functional when hardware acceleration becomes unavailable, with subsequent instances using DOM rendering by default.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 16, 2026

📝 Walkthrough

Walkthrough

When the WebGL addon detects a context loss event, it now persistently marks the preferred renderer type as "dom". This flag is set in both the addon's context loss handler and the terminal wrapper's initialization, ensuring subsequent terminal instances skip WebGL and use DOM rendering instead.

Changes

WebGL context loss DOM fallback

Layer / File(s) Summary
WebGL context loss handler and integration
apps/desktop/src/renderer/lib/terminal/terminal-addons.ts, apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.ts
When WebGL context loss occurs, both the addon handler and terminal wrapper initialization set suggestedRendererType to "dom", disabling WebGL for future terminal instances.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

Possibly related PRs

  • superset-sh/superset#4541: Implements the WebGL context-loss fallback path by marking the preferred renderer as DOM via suggestedRendererType for subsequent terminal instances.

Poem

A context lost, the WebGL fades away,
Yet DOM rendering saves the day,
With flags set firm and handlers true,
The terminal finds a path anew. 🐰✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: falling back from WebGL to DOM rendering when a context loss occurs in the terminal.
Description check ✅ Passed The description provides a clear summary of changes, explains the reasoning, and includes validation steps. All critical sections are present and complete.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch vscode-xterm-glyph-issues

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@capy-ai
Copy link
Copy Markdown

capy-ai Bot commented May 16, 2026

Capy auto-review is paused for this organization because the monthly auto-review limit has been reached. Increase the limit or turn it off in billing settings to resume automatic reviews.

@Kitenite
Copy link
Copy Markdown
Collaborator Author

Closing this after validation showed the automatic texture-atlas clear on terminal attach can itself trigger the garbled rendering issue. The branch now contains a revert and has no net diff; we should not merge this approach.

@Kitenite Kitenite closed this May 16, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 16, 2026

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ✅ Neon database branch

Thank you for your contribution! 🎉

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 16, 2026

Greptile Summary

This PR adds suggestedRendererType = "dom" to the WebGL onContextLoss callback in both terminal-addons.ts and helpers.ts. The fix ensures that when a running WebGL context is lost at runtime (GPU memory pressure, driver reload, etc.), the process-level flag that prevents new terminals from attempting WebGL is updated — closing a gap that the existing catch block (which only covers initialization failures) did not handle.

  • terminal-addons.ts / helpers.ts: Both files' onContextLoss handlers now set suggestedRendererType = \"dom\" before disposing the addon, mirroring the VS Code pattern already used in the WebGL initialization catch blocks. The change is a single-line addition in each file.

Confidence Score: 5/5

Safe to merge — the change is a one-line addition in two symmetric locations that closes an existing gap without touching the PTY, WebSocket, or any React state.

The two files receive identical, minimal additions to a well-understood callback. The rest of the onContextLoss cleanup logic (dispose, null-out, refresh) is unchanged. terminal-runtime.ts is untouched and does not contain the texture-atlas or recovery code flagged in earlier review rounds. No regressions are expected.

No files require special attention.

Important Files Changed

Filename Overview
apps/desktop/src/renderer/lib/terminal/terminal-addons.ts Adds suggestedRendererType = "dom" to the onContextLoss handler; closes gap where runtime context loss did not update the module-level renderer flag.
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.ts Identical single-line fix in the v1-terminal-cache code path's onContextLoss handler; keeps both terminal creation paths in sync.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[requestAnimationFrame fires] --> B{disposed or\nsuggestedRendererType === 'dom'?}
    B -- Yes --> C[Skip WebGL, use DOM renderer]
    B -- No --> D[new WebglAddon]
    D --> E{loadAddon succeeds?}
    E -- No / catch --> F[suggestedRendererType = 'dom']
    E -- Yes --> G[WebGL active]
    G --> H{onContextLoss fires\nat runtime}
    H --> I[suggestedRendererType = 'dom'\n NEW in this PR]
    I --> J[dispose webglAddon]
    J --> K[terminal.refresh — falls back to DOM]
    F --> L[Future terminals skip WebGL]
    K --> L
Loading

Reviews (2): Last reviewed commit: "fix(desktop): fall back from terminal We..." | Re-trigger Greptile

@Kitenite Kitenite reopened this May 16, 2026
@Kitenite Kitenite changed the title fix(desktop): recover terminal renderer on attach fix(desktop): fall back from terminal WebGL on context loss May 16, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
apps/desktop/src/renderer/lib/terminal/terminal-addons.ts (1)

46-62: ⚡ Quick win

Consider consolidating duplicate WebGL loading logic.

The WebGL loading pattern (rAF deferral, context loss handling, fallback flag) is duplicated in helpers.ts lines 128-144. Both files maintain separate module-scoped suggestedRendererType variables, which means a WebGL failure in one code path won't prevent WebGL attempts in the other.

If the intent is truly "for all subsequent runtimes" (line 16), consider extracting this logic to a shared module with a single global state variable. Otherwise, clarify in the comment that the fallback is scoped per terminal creation method.

♻️ Potential consolidation approach

Create a shared module (e.g., terminal-webgl.ts):

// Shared WebGL state and loading logic
let suggestedRendererType: "webgl" | "dom" | undefined;

export function loadWebGLAddon(
  terminal: XTerm,
  onDisposed: () => boolean
): { dispose: () => void } | null {
  if (suggestedRendererType === "dom") return null;
  
  let webglAddon: WebglAddon | null = null;
  const rafId = requestAnimationFrame(() => {
    if (onDisposed() || suggestedRendererType === "dom") return;
    
    try {
      webglAddon = new WebglAddon();
      webglAddon.onContextLoss(() => {
        suggestedRendererType = "dom";
        webglAddon?.dispose();
        webglAddon = null;
        terminal.refresh(0, terminal.rows - 1);
      });
      terminal.loadAddon(webglAddon);
    } catch {
      suggestedRendererType = "dom";
      webglAddon = null;
    }
  });
  
  return {
    dispose: () => {
      cancelAnimationFrame(rafId);
      try {
        webglAddon?.dispose();
      } catch {}
      webglAddon = null;
    }
  };
}

Then both files can call this shared function.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/desktop/src/renderer/lib/terminal/terminal-addons.ts` around lines 46 -
62, The WebGL load/fallback logic is duplicated and uses separate module-scoped
suggestedRendererType variables; extract the shared behavior into a single
module (e.g., terminal-webgl) that exposes a loadWebGLAddon function which
accepts the terminal and a disposal predicate; inside it reuse
requestAnimationFrame, create WebglAddon, attach onContextLoss to set a single
shared suggestedRendererType = "dom", call terminal.loadAddon(webglAddon), and
return a dispose() that cancels the rafId and disposes the addon; update
terminal-addons.ts and helpers.ts to call this shared loadWebGLAddon instead of
duplicating the requestAnimationFrame/WebglAddon/rafId/suggestedRendererType
logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@apps/desktop/src/renderer/lib/terminal/terminal-addons.ts`:
- Around line 46-62: The WebGL load/fallback logic is duplicated and uses
separate module-scoped suggestedRendererType variables; extract the shared
behavior into a single module (e.g., terminal-webgl) that exposes a
loadWebGLAddon function which accepts the terminal and a disposal predicate;
inside it reuse requestAnimationFrame, create WebglAddon, attach onContextLoss
to set a single shared suggestedRendererType = "dom", call
terminal.loadAddon(webglAddon), and return a dispose() that cancels the rafId
and disposes the addon; update terminal-addons.ts and helpers.ts to call this
shared loadWebGLAddon instead of duplicating the
requestAnimationFrame/WebglAddon/rafId/suggestedRendererType logic.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bca9982e-978d-4168-ac3c-7da3eb2bfa1d

📥 Commits

Reviewing files that changed from the base of the PR and between da0282c and 8136f8d.

📒 Files selected for processing (2)
  • apps/desktop/src/renderer/lib/terminal/terminal-addons.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.ts

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 2 files

Re-trigger cubic

@Kitenite
Copy link
Copy Markdown
Collaborator Author

Closing this after testing the actual WebGL context-loss path. Forcing WEBGL_lose_context shows the terminal already recovers on main via the existing xterm handler: the WebGL addon is disposed and the terminal refreshes.

The added fallback only changed future terminal creation after context loss, but it does not address the garbled glyph case we were trying to prevent. I removed that code so we do not ship an unproven behavior change.

@Kitenite Kitenite closed this May 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant