From 6ccab61de4ccdc098a432e775a0e2f093f2480f2 Mon Sep 17 00:00:00 2001 From: Kiet Ho Date: Tue, 28 Apr 2026 10:55:15 -0700 Subject: [PATCH 1/2] fix(desktop): raise Chromium WebGL context cap to 256 Chromium defaults `max-active-webgl-contexts` to 16 per renderer process. Each xterm holds one WebGL context, and the v2 parking model keeps panes alive across workspace switches, so cumulative panes routinely reach the low hundreds. Once over the cap, Blink forcibly fires `webglcontextlost` on the oldest pane, producing the blank/garbled terminals in #3572, #3504, #3527. Raising to 256 covers low-hundreds of cumulative panes while staying bounded enough to surface a real leak. Does not address upstream xterm.js texture-atlas bugs (xtermjs/xterm.js#5849), which manifest as similar corruption but require a different fix. --- .../src/lib/electron-app/factories/app/setup.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/apps/desktop/src/lib/electron-app/factories/app/setup.ts b/apps/desktop/src/lib/electron-app/factories/app/setup.ts index 05a1138209e..06cd2dbecdd 100644 --- a/apps/desktop/src/lib/electron-app/factories/app/setup.ts +++ b/apps/desktop/src/lib/electron-app/factories/app/setup.ts @@ -74,6 +74,18 @@ PLATFORM.IS_WINDOWS && app.commandLine.appendSwitch("force-color-profile", "srgb"); +// Chromium's default active-WebGL-context cap is 16 per renderer process +// (content/renderer/webgraphicscontext3d_provider_impl.cc). When exceeded, +// Blink's ForciblyLoseOldestContext fires `webglcontextlost` on the oldest +// xterm, producing the blank/garbled terminals reported in #3572, #3504, +// #3527. Each pane's xterm holds one WebGL context, and the v2 parking model +// keeps them alive across workspace switches — cumulative panes routinely +// reach the low hundreds. VS Code's 32 covers their ~16-terminal budget but +// is too low here; Tabby's 9000 is high enough to mask leaks. 256 sits in +// the middle: 16× the default, covers low-hundreds of panes, and stays +// bounded enough that a real leak still surfaces. +app.commandLine.appendSwitch("max-active-webgl-contexts", "256"); + // Only expose CDP in development when a port is explicitly configured. const cdpPort = env.NODE_ENV === "development" From bc55d1788aab69c668a8f0d0249ac1a6a92beb4e Mon Sep 17 00:00:00 2001 From: Kiet Ho Date: Tue, 28 Apr 2026 11:03:06 -0700 Subject: [PATCH 2/2] deslop: trim WebGL cap-raise comment Drop issue references (belong in PR description) and Chromium source path (rots if files move). Keep the WHY: parking holds contexts, default 16 is too low at hundreds of cumulative panes, 256 is bounded enough to surface leaks. --- .../src/lib/electron-app/factories/app/setup.ts | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/apps/desktop/src/lib/electron-app/factories/app/setup.ts b/apps/desktop/src/lib/electron-app/factories/app/setup.ts index 06cd2dbecdd..e48db56505a 100644 --- a/apps/desktop/src/lib/electron-app/factories/app/setup.ts +++ b/apps/desktop/src/lib/electron-app/factories/app/setup.ts @@ -74,16 +74,12 @@ PLATFORM.IS_WINDOWS && app.commandLine.appendSwitch("force-color-profile", "srgb"); -// Chromium's default active-WebGL-context cap is 16 per renderer process -// (content/renderer/webgraphicscontext3d_provider_impl.cc). When exceeded, -// Blink's ForciblyLoseOldestContext fires `webglcontextlost` on the oldest -// xterm, producing the blank/garbled terminals reported in #3572, #3504, -// #3527. Each pane's xterm holds one WebGL context, and the v2 parking model -// keeps them alive across workspace switches — cumulative panes routinely -// reach the low hundreds. VS Code's 32 covers their ~16-terminal budget but -// is too low here; Tabby's 9000 is high enough to mask leaks. 256 sits in -// the middle: 16× the default, covers low-hundreds of panes, and stays -// bounded enough that a real leak still surfaces. +// Each xterm pane holds one WebGL context. v2 parking keeps panes alive +// across workspace switches, so cumulative contexts can reach the low +// hundreds — past Chromium's default cap of 16, Blink force-evicts the +// oldest context and the terminal blanks out. 256 covers the parking load +// while staying bounded enough that a runaway leak still surfaces (Tabby +// raises this to 9000, which masks leaks). app.commandLine.appendSwitch("max-active-webgl-contexts", "256"); // Only expose CDP in development when a port is explicitly configured.