fix: eliminate WebGL re-render flicker during tab switch

Stop toggling WebGL renderer off/on around large buffer writes in
chunkedTerminalWrite(). The dispose+loadAddon cycle caused visible
re-render flashes and (before the deferred fix) synchronous GPU stalls
from ReadPixels blocking the main thread. Instead, keep WebGL active
and rely on 32KB chunked writes to keep per-frame render work under
~5ms.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
arkon
2026-03-04 16:01:16 +01:00
co-authored by Claude Opus 4.6
parent d79e25d5d8
commit f8b81b8478
6 changed files with 76 additions and 49 deletions
+5 -19
View File
@@ -1346,35 +1346,21 @@ class CodemanApp {
// (from historical SSE data that was stored with markers)
const cleanBuffer = buffer.replace(DEC_SYNC_STRIP_RE, '');
// Disable WebGL during large buffer loads to prevent GPU stalls.
// The canvas renderer handles bulk writes without blocking the main thread.
// WebGL's synchronous ReadPixels calls cause "page unresponsive" on dense ANSI buffers.
const isLargeBuffer = cleanBuffer.length > chunkSize;
if (isLargeBuffer && this._webglAddon) {
try { this._webglAddon.dispose(); } catch (_e) { /* already disposed */ }
this._webglAddon = null;
}
const finish = () => {
// Re-enable WebGL after buffer load completes
if (isLargeBuffer && !this._webglAddon && typeof WebglAddon !== 'undefined') {
try {
this._webglAddon = new WebglAddon.WebglAddon();
this._webglAddon.onContextLoss(() => { this._webglAddon.dispose(); this._webglAddon = null; });
this.terminal.loadAddon(this._webglAddon);
} catch (_e) { /* WebGL re-init failed — stay on canvas */ }
}
this._finishBufferLoad();
resolve();
};
// For small buffers, write directly (WebGL stays active — small writes are fine)
if (!isLargeBuffer) {
// For small buffers, write directly — single-frame render is fast enough
if (cleanBuffer.length <= chunkSize) {
this.terminal.write(cleanBuffer);
finish();
return;
}
// Large buffers: write in chunks across animation frames.
// Each 32KB chunk keeps per-frame WebGL render work under ~5ms,
// avoiding GPU stalls without needing to toggle the renderer.
let offset = 0;
const writeChunk = () => {
if (offset >= cleanBuffer.length) {