Skip to content

fix(webgl): release throwaway context in premultiply-alpha probe#114

Merged
chiefcll merged 1 commit into
mainfrom
fix/release-premultiply-probe-context
Jun 25, 2026
Merged

fix(webgl): release throwaway context in premultiply-alpha probe#114
chiefcll merged 1 commit into
mainfrom
fix/release-premultiply-probe-context

Conversation

@chiefcll

Copy link
Copy Markdown
Contributor

What

detectPremultiplyAlphaHonored (src/core/lib/validateImageBitmap.ts) creates a temporary WebGL context to test whether createImageBitmap(..., { premultiplyAlpha: 'premultiply' }) is honored by the browser. It deleted the texture and framebuffer it used, but left the WebGL context itself dangling until GC.

This change releases that context immediately via WEBGL_lose_context.loseContext() on the exit path.

Why

Reported on Apollo/Sunrise TV boxes (Chrome 38+):

There are too many active WebGL contexts on this page, the oldest context will be lost
Could not create WebGL Texture   (WebGlCtxTexture.js)
Failed to upload texture: Error: Could not create WebGL Texture   (CoreTextureManager.js)

Embedded TV SoCs cap the number of live WebGL contexts very low. This probe runs in a microtask after the main render context is created, so a leaked probe context is the newest on the page. Holding that extra slot can push the page over the device's context budget, and the browser evicts the oldest context — the live render context. Once that happens, gl.createTexture() returns null and the engine spams Could not create WebGL Texture every requestAnimationFrame.

Don't wait for GC to reclaim the canvas — drop the context the moment the probe is done.

Notes for reviewers

  • The loseContext event fires only on the throwaway canvas, so it does not trip the main renderer's webglcontextlost handler in WebGlRenderer.ts.
  • This path only runs when the app opts in with premultiplyAlphaHonored: 'auto'. The default is true (no probe), so default configs are unaffected.
  • This is the secondary half of the fix. The primary context-leak source for the reported issue is in the consuming @solidtv/solid layer (getWebglSupportedVersions, which re-created a context on every non-default call); that fix ships as a separate PR in that repo.

Tests

  • Added getExtension to the mock GL in validateImageBitmap.test.ts and a test asserting loseContext() is called exactly once.
  • pnpm vitest run src/core/lib/validateImageBitmap.test.ts → 7/7 pass.
  • tsc --build clean; prettier + eslint clean (0 errors).

🤖 Generated with Claude Code

`detectPremultiplyAlphaHonored` creates a temporary WebGL context to test
whether `createImageBitmap(..., { premultiplyAlpha: 'premultiply' })` is
honored, but it only deleted the texture/framebuffer — the context itself was
left dangling until GC.

This probe runs in a microtask *after* the main render context is created, so a
leaked context here is the newest one on the page. On embedded TV browsers
(Apollo/Sunrise, Chrome 38+) the live-context budget is tiny; the lingering
probe pushes the page over the limit and the browser evicts the *oldest*
context — the live render context — after which every `createTexture()` returns
null and the engine spams "Could not create WebGL Texture" each frame.

Release the probe context immediately via `WEBGL_lose_context` on every exit
path instead of waiting for GC. The lose event fires only on the throwaway
canvas, so it does not trip the main renderer's `webglcontextlost` handler.

Only active when `premultiplyAlphaHonored: 'auto'` is set (default is `true`,
no probe).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@chiefcll chiefcll merged commit 1b23155 into main Jun 25, 2026
1 check passed
@chiefcll chiefcll deleted the fix/release-premultiply-probe-context branch June 25, 2026 18:23
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