Skip to content

fix(glx): match GetDrawableAttributes and MakeCurrent to Xorg - #118

Merged
joske merged 7 commits into
joske:masterfrom
ariel3259:glx-reply-xorg-alignment
Aug 7, 2026
Merged

fix(glx): match GetDrawableAttributes and MakeCurrent to Xorg#118
joske merged 7 commits into
joske:masterfrom
ariel3259:glx-reply-xorg-alignment

Conversation

@ariel3259

Copy link
Copy Markdown
Contributor

fix(glx): match GetDrawableAttributes and MakeCurrent to Xorg

Branch: glx-reply-xorg-alignment, opened against master. Merged with current master (2252 tests, clippy --all-targets -- -D warnings and +nightly fmt --check clean).

The hardware numbers below were measured on this branch before the merge with current master. master's new commits touch the Present/TFP wait paths rather than the GLX reply arms, and the tree is green, but the probe has not been re-run against the exact merged tree.

Problem

NVIDIA's libGLX_nvidia could not bind a GL context against yserver. Clients died with:

X Error of failed request:  BadAlloc (insufficient resources for operation)
Major opcode of failed request:  148 (GLX)
Minor opcode of failed request:  5 (X_GLXMakeCurrent)
Serial number of failed request:  0

Serial 0 was the clue: yserver never emits that error. Its MAKE_CURRENT handler always replies with a contextTag and cannot fail, and libglvnd 1.7.0 does not synthesise BadAlloc either (it produces BadAccess/BadMatch/GLXBadContext/GLXBadDrawable). The error was fabricated client-side by libGLX_nvidia after reading a reply it considered impossible.

This hit KWin (QGLXContext: Failed to create dummy context), Steam, and games.

Root cause

GetDrawableAttributes reported GLX_FBCONFIG_ID = 0 — a nonexistent id — for a bare X window. drawable_attributes_for looked the XID up in glx_drawables and fell back to 0 when absent, but a GLX 1.2 "naked window" is not in that table by definition.

Xorg has an explicit path for this case (glx/glxcmds.c:1873-1914) and omits the attribute entirely rather than sending a bogus one. It also always sends GLX_DRAWABLE_TYPE, which yserver never sent, and never sends GLX_RENDER_TYPE, which yserver did.

Fix

Six commits, aligning the two replies with Xorg's observable behaviour:

  • D1 — geometry resolves from the backing X drawable. The GLXWindow/GLXPixmap XID is a fresh client-allocated id with no X resource behind it, so the old lookup always missed and reported 0×0. This was a live defect against Mesa's loader_dri3 too, which sizes its buffers from this reply.
  • D2-D6 — attribute set and error arms matched to Xorg, including the naked-window omission above.
  • MakeCurrent returns contextTag = 0 when releasing (context == 0), matching glx/vndcmds.c:232-234,272. yserver previously returned a fresh incrementing tag.

Verification

Measured on an RTX 5060 Ti, NVIDIA 610.57.04, open kernel modules, over a real KMS session.

The causal proof is a single difference in the client trace against the pre-fix baseline: GetDrawableAttributes went from 7 attribs to 5 attribs. Everything before that point is byte-identical. Immediately after, the baseline did MakeCurrent and died; with the fix, NVIDIA continues into DRI3::SetDRMDeviceInUseGetSupportedModifiersPixmapFromBuffersMakeCurrent.

Probe result after the fix:

GL_VERSION:   4.6.0 NVIDIA 610.57.04
GL_RENDERER:  NVIDIA GeForce RTX 5060 Ti/PCIe/SSE2
direct=1
RESULT: GL works

The BadAlloc is gone. Steam — a 32-bit client that previously crashed on launch with the exact signature above — now starts, as does Hollow Knight.

Notes

  • docs/status.md updated (entry dated 2026-08-04).
  • Design doc and implementation plan included under docs/superpowers/.
  • Two divergences from Xorg were found and deliberately not fixed here, recorded in the design's "Deferred" section so they are not rediscovered: QUERY_CONTEXT answers 0 attributes where Xorg answers FBCONFIG_ID/RENDER_TYPE/SCREEN, and fbconfig synthesis produces 2 configs against XWayland's 168.
  • Workspace green: 2241 tests, cargo clippy --all-targets -- -D warnings clean, cargo +nightly fmt --check clean. All commits signed.

🤖 Generated with Claude Code

…wable

A GLXWindow/GLXPixmap XID is a fresh client-allocated id with no X
resource behind it, so resolving GLX_WIDTH/GLX_HEIGHT from the GLX XID
itself always missed and reported 0x0. Mesa's loader_dri3 sizes its
buffer from these fields and fails with "failed to create drawable";
measured on the wire against libGLX_nvidia (2026-08-03): a 64x32
backing drawable was reported as 0x0. Resolve from the backing X
drawable recorded at create time, as Xorg does
(pGlxDraw->pDraw->width/height, glxcmds.c:1891).
Add GlxDrawableKind { Window, Pixmap, Pbuffer } (no Default impl, so a
missed construction site is a compile error) and set it at all three
glx_drawables.insert sites plus the resource-allocator test literal.

ChangeDrawableAttributes now records only GLX_EVENT_MASK and ignores
every other attribute, matching Xorg's single-case switch
(glxcmds.c:1494-1503). Re-key the is_pbuffer checks in
drawable_attributes_for and glx_pbuffer_geometry onto the kind,
preserving both 0x0-pbuffer behaviours (backing-pixmap 1x1 fallthrough
and the GetGeometry BadDrawable guard).
Restructure drawable_attributes_for around Xorg's exact branch
(glxcmds.c:1863-1914): Y_INVERTED/WIDTH/HEIGHT/SCREEN always; the
TEXTURE_TARGET/EVENT_MASK/FBCONFIG_ID block (plus PRESERVED_CONTENTS
for pbuffers, STEREO_TREE_EXT for windows) only with a GLX record;
DRAWABLE_TYPE last, WINDOW_BIT for the no-record fallthrough. A naked
X window no longer gets a bogus GLX_FBCONFIG_ID = 0 (measured defect
against libGLX_nvidia), and GLX_RENDER_TYPE is dropped — Xorg never
sends it for a drawable.

Delete the generic ChangeDrawableAttributes override pass; the
event_mask field recorded in the previous commit is the only state.

GET_DRAWABLE_ATTRIBUTES now emits Xorg's two distinct error codes
instead of a silent Success: a naked X pixmap gets GLXBadDrawable
(GLX_FIRST_ERROR + 2; glxproto.h:43 — GLXVND forwards pixmaps, then
dixLookupWindow fails), and an XID that is not a drawable at all gets
core BadDrawable (the GLXVND dispatch stub errors before
DoGetDrawableAttributes is reached). Add the missing GLX_STEREO_TREE_EXT
and ERROR_GLX_BAD_DRAWABLE constants with citations.
Parse the request body, which the arm ignored entirely: the new
context XID sits at body[4..8] for minor 5 (MakeCurrent) and
body[12..16] for minor 26 (MakeContextCurrent), per
glxproto.h:225-233 and :471-481. The release form (context == None)
now returns contextTag = 0 — tag 0 is reserved by the protocol to
mean "no context current" — instead of allocating a fresh monotonic
tag, matching Xorg (vndcmds.c:232-234, :271-273). Measured defect:
yserver.log showed tag=1 then tag=2, the second being the release.
@joske
joske merged commit 247b7a4 into joske:master Aug 7, 2026
1 check passed
@joske

joske commented Aug 7, 2026

Copy link
Copy Markdown
Owner

Thx.

ariel3259 added a commit to ariel3259/yserver that referenced this pull request Aug 7, 2026
PR joske#118 (glx-reply-xorg-alignment) was squash-merged upstream as 247b7a4,
so the reply-alignment commits this branch carries individually now exist
on master as one commit. The content is identical, so git collapsed the
duplication cleanly -- the branch's net diff against upstream/master is
now purely the vendor-name work.

Conflicts resolved:

- process_request.rs, GET_DRAWABLE_ATTRIBUTES error arm: took upstream's
  47b0633 (fix(glx): preserve minor opcode in drawable errors), switching
  the unknown-XID path from emit_x11_error to emit_x11_error_with_minor
  and passing u16::from(header.data). The pixmap arm directly above
  already reported the minor opcode; this brings the core BadDrawable arm
  in line, and the paired assertions on buf[8..10]/buf[10] in
  glx_get_drawable_attributes_unknown_xid_returns_core_bad_drawable came
  in with it.

- process_request.rs tests: kept
  glx_vendor_names_query_answers_from_server_state, which upstream does
  not have -- an adjacency conflict, not a semantic one.

- docs/status.md: kept both entries. Upstream's direct-scanout idle paint
  starvation note and this branch's GLX_VENDOR_NAMES_EXT /
  BackendCapabilities notes are independent.

Verified: cargo clippy --all-targets -D warnings and the full test suite
(1474 tests) on yserver-core and yserver-protocol, plus cargo +nightly
fmt --check. The yserver crate could not be built here -- its build
script needs glslc, which is not installed in this environment -- but no
conflict touched that crate.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.

2 participants