fix(gl): ask CGL for a stencil buffer — every stencil test passed on XQuartz - #353
Merged
Conversation
…XQuartz The appledri flavor created its CGL context with a depth size only, so its windows had no stencil buffer, and a stencil test against no buffer passes everywhere. STENCIL_SIZE now travels from the spec or config to kCGLPFAStencilSize, 8 bits by default as on the Cocoa backend. chooseGLConfig, chooseGLXConfig and the direct contexts report stencilSize. The dri3 flavor answers 0 and warns once, since x11-dri's Gpu takes no stencil size to pass on.
sidorares
pushed a commit
that referenced
this pull request
Sep 12, 2026
🤖 I have created a release *beep* *boop* --- ## [8.8.2](v8.8.1...v8.8.2) (2026-09-12) ### Bug Fixes * **gl:** ask CGL for a stencil buffer — every stencil test passed on XQuartz ([#353](#353)) ([4abff02](4abff02)) * **text:** resolve sans-serif to Helvetica on macOS, not a face with full-width Cyrillic ([#354](#354)) ([8af0711](8af0711)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A
<glarea>drawn through the direct backend on macOS/XQuartz had no stencil buffer.lib/renderingcontext_cgl.jscreated its CGL context with a depth size and nothing else, and x11-dri'sapple.ContextdefaultsstencilSizeto 0, sokCGLPFAStencilSizenever reached the pixel format. The Cocoa backend's GL surfaces carry DEPTH24_STENCIL8, so the same draw code had a stencil buffer on one macOS path and not on the other.Nothing errors when the buffer is missing: a stencil test against a framebuffer with no stencil buffer passes everywhere. The map renderer in sidorares/react-x11-components#101 fills polygons stencil-then-cover, so on XQuartz it has had to draw every frame into an offscreen framebuffer and copy it, 0.1–1.3 ms a frame.
What changes
STENCIL_SIZEfrom the spec, orstencilSizefrom a config, travels tokCGLPFAStencilSize, read under the same two spellings the depth size is. A config that names none gets 8 bits, the Cocoa backend's size;STENCIL_SIZE: 0still asks for none. CGL takes the size as a minimum.Gputakes a format, a depth size and a GL version, and itsCreateGpupasses noEGL_STENCIL_SIZE, so there is nothing to forward a stencil size to. This PR does not change x11-dri. The flavor now answers the request instead of dropping it, the way fix(gl): answer the multisample request instead of dropping it #343 answersSAMPLES:stencilSize: 0, and a warning once per connection naming the failure and the workaround.chooseGLConfigandchooseGLXConfiganswers carrystencilSizebesidesamples, and the direct contexts carrygl.stencilSize, so draw code can branch on what the window has. Indirect reports the chosen fbconfig's stencil bits, andnullwhen the spec pinsvisual, as it already does forsamples.directStencilSizeinlib/gl.jsis the one place that decides the per-flavor answer, asDIRECT_SAMPLESis for samples. When x11-dri'sGpugrows the option, the dri3 answer changes there and nowhere else.docs/context-gles.md, including the probe that can tell a real stencil buffer from a missing one, and the config shape indocs/context-opengl.md.Verified on real hardware
On this Apple M1 Pro under XQuartz, Apple-DRI flavor, with a probe that draws into a mapped window and reads back with
gl.readPixels:FRAMEBUFFER_ATTACHMENT_STENCIL_SIZEof the window's framebufferNOTEQUAL 0EQUAL 1The
NOTEQUALrow is the one that decides it: "write 1, draw where it is 1" draws the same with or without a stencil buffer, so only a test that has to fail can tell them apart. That probe is now a live test intest/gl-appledri-live.test.js, and the file passed 5 of 5 on XQuartz in two runs. One earlier run of that file failed atxp_attach_gl_context failed 2, and one run of master's copy skipped everything; both trees did this, so that flake belongs to this machine's XQuartz rather than to this change.Tests
test/gl-stencil.test.js, hermetic, on node-x11's JS X server with a recording stand-in forapple.Context: the options the CGL context is created with for the default, an explicit 0 and a hand-written config; the dri3 answer and its once-per-connection warning; indirect answers from the GLX emulator's fbconfig and from a pinned visual; the docs anchor the warning points at.test/gl-appledri-live.test.js: the stencil probe above. It skips wherever Apple-DRI is missing, CI included.Not verified: a real dri3 context. There is no Linux GPU here, so the dri3 side of this is the reported number and the warning, both covered by the hermetic test.