Re-enable WebGL for remote-runtime terminals (#5048)

PR #4946 forced terminalGpuAcceleration to 'off' whenever a remote
runtime environment is active, as a conservative workaround alongside
the real fixes (CSS anchor-name encoding and rebuilding the WebGL
renderer after replay bytes parse). That left every remote-runtime
terminal on the slower DOM renderer even though the post-replay
rebuildPaneWebgl already covers the snapshot-after-attach race.

Remove the forced-off resolver so remote-runtime panes honor the user
GPU setting again. The snapshot path (onSnapshot -> processData with
replayingBufferedData -> onReplayData -> rebuildPaneWebgl after parse)
keeps the glyph atlas in sync, and attachWebgl re-checks all guards
(gpuRenderingEnabled, deferred attachment, context loss) on rebuild.

Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
Neil
2026-06-11 12:28:53 -07:00
committed by Jinwoo-H
co-authored by Orca
parent f71df6a434
commit d7f431d9cf
2 changed files with 6 additions and 44 deletions
@@ -1,6 +1,5 @@
import { describe, expect, it, vi } from 'vitest'
import {
resolveTerminalGpuAccelerationForRuntime,
shouldDetachPaneTransportOnUnmount,
splitPaneWithOneShotStartup,
suppressIntentionalPaneCloseExit
@@ -126,24 +125,6 @@ describe('shouldDetachPaneTransportOnUnmount', () => {
})
})
describe('resolveTerminalGpuAccelerationForRuntime', () => {
it('forces DOM rendering while a remote runtime is active', () => {
expect(resolveTerminalGpuAccelerationForRuntime('env-1', 'on')).toBe('off')
})
it('honors the user GPU setting for local terminals', () => {
expect(resolveTerminalGpuAccelerationForRuntime(null, 'on')).toBe('on')
})
it('defaults local terminals to auto when the setting is missing', () => {
expect(resolveTerminalGpuAccelerationForRuntime(null, undefined)).toBe('auto')
})
it('treats blank runtime ids as local', () => {
expect(resolveTerminalGpuAccelerationForRuntime(' ', 'auto')).toBe('auto')
})
})
describe('suppressIntentionalPaneCloseExit', () => {
it('suppresses the pane PTY exit before intentional close teardown destroys the transport', () => {
const suppressPtyExit = vi.fn()
@@ -310,16 +310,6 @@ export function shouldDetachPaneTransportOnUnmount(args: {
)
}
export function resolveTerminalGpuAccelerationForRuntime(
activeRuntimeEnvironmentId: GlobalSettings['activeRuntimeEnvironmentId'] | null | undefined,
terminalGpuAcceleration: GlobalSettings['terminalGpuAcceleration'] | null | undefined
): GlobalSettings['terminalGpuAcceleration'] {
if (activeRuntimeEnvironmentId?.trim()) {
return 'off'
}
return terminalGpuAcceleration ?? 'auto'
}
export function useTerminalPaneLifecycle({
tabId,
worktreeId,
@@ -1058,12 +1048,10 @@ export function useTerminalPaneLifecycle({
// so PTYs survive navigation. Creating WebGL for those offscreen panes
// still consumes Chromium's context budget and can blank visible panes.
initialRenderingSuspended: !isVisibleRef.current,
// Why: remote-runtime snapshots arrive after pane open; WebGL can hold an
// empty atlas/canvas while the server-side buffer is already populated.
terminalGpuAcceleration: resolveTerminalGpuAccelerationForRuntime(
settingsRef.current?.activeRuntimeEnvironmentId,
settingsRef.current?.terminalGpuAcceleration
),
// Why: remote-runtime panes honor the user GPU setting too — snapshots
// that arrive after WebGL attaches are handled by the post-replay
// rebuildPaneWebgl in pty-connection's replay callback.
terminalGpuAcceleration: settingsRef.current?.terminalGpuAcceleration ?? 'auto',
debugLabel: `tab:${tabId}/wt:${worktreeId}`
})
@@ -1382,15 +1370,8 @@ export function useTerminalPaneLifecycle({
}, [settings, systemPrefersDark, effectiveMacOptionAsAlt])
useEffect(() => {
// Why: remote-runtime panes stay on DOM rendering; local panes still honor
// the user's GPU setting and can switch live when settings change.
managerRef.current?.setTerminalGpuAcceleration(
resolveTerminalGpuAccelerationForRuntime(
settings?.activeRuntimeEnvironmentId,
settings?.terminalGpuAcceleration
)
)
}, [settings?.activeRuntimeEnvironmentId, settings?.terminalGpuAcceleration, managerRef])
managerRef.current?.setTerminalGpuAcceleration(settings?.terminalGpuAcceleration ?? 'auto')
}, [settings?.terminalGpuAcceleration, managerRef])
useEffect(() => {
const manager = managerRef.current