A capped context still runs the game — only textures wider than the cap
render wrong — so don't hard-block. initGL now returns the context for
"limited"; GPURenderer proceeds and exposes the capped renderer/size via
glLimited (surfaced through MapRenderer), and ClientGameRunner shows the
gate as a warning with a "Continue anyway" button instead of aborting
game creation. GLUnavailableError is back to software/unsupported only.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
privacy.resistFingerprinting (default-on in LibreWolf and Mullvad Browser,
opt-in in Firefox) caps MAX_TEXTURE_SIZE at 2048 on an otherwise
hardware-accelerated context. The renderer unconditionally allocates a
4096-wide palette texture, so the oversized texImage2D calls fail silently,
framebuffers never complete, and the whole map renders black (#4357).
Extend initGL with a third failure class: after the software check, read
MAX_TEXTURE_SIZE and classify the context as "limited" when it's below the
palette size. The gate shows fingerprinting-specific instructions for this
case (add the site to privacy.resistFingerprinting.exemptedDomains) instead
of the hardware-acceleration steps, and gl_init reports the capped size.
Fixes#4357
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A small number of users run WebGL without GPU acceleration (hardware
acceleration disabled, blocklisted driver, or a locked-down machine) and
get a software (SwiftShader) context, which renders the game at ~1fps.
Demand a GPU-accelerated WebGL2 context at game start; if we can't get
one, show a full-screen gate with per-browser instructions for enabling
hardware acceleration / WebGL instead of letting the game crawl.
- initGL() demands failIfMajorPerformanceCaveat AND inspects the renderer
string — Chrome still hands back SwiftShader when acceleration is turned
off in settings (vs. a blocklisted driver). Classifies ok / software /
unsupported.
- GPURenderer throws GLUnavailableError on a non-accelerated context; the
game-start catch shows the gate. The orphaned canvas is cleaned up.
- <webgl-gate> Lit component renders the actionable gate (intentionally
inlined/untranslated — rarely seen, browser-specific troubleshooting).
- Log a gl_init analytics event (status + renderer) every session so we
can size the affected %.
- Unit tests for initGL's ok/software/unsupported branching.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>