feat(glx): derive GLX vendor names from the render driver - #119
Merged
Conversation
…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.
Defect A of the NVIDIA GLX investigation: GLX_VENDOR_NAMES_EXT is hardcoded to "mesa" (glx.rs:179), so libglvnd loads libGLX_mesa.so on every screen and falls back to llvmpipe on NVIDIA hardware. The server already holds the discriminating fact in vk.driver_id. Design derives the vendor from vk.driver_id, crosses the Backend seam the same way glx_tfp_supported does, returns the list "nvidia mesa" for the libglvnd fallback path, and adds a YSERVER_GLX_VENDOR override. Rev 2: Opus adversarial review round 1 returned REJECT; all six blocking findings applied. Notably the risk section was inverted — Plasma already crashes on llvmpipe today (defect B), so this change moves an existing crash rather than creating one — and the Plasma measurement was promoted from a note to a merge precondition. Base: glx-reply-xorg-alignment @ bd168cf. Not implemented yet. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Rev 2 named a defect in its own design and then documented it instead of
fixing it: the vendor crossed the Backend seam as a field assigned at two
call sites, so an implementer who forgot lib.rs:337 passed every unit
test while the server still shipped "mesa" on NVIDIA. That hole is the
shape of the surrounding code, not an oversight — lib.rs:336-337 and
nested.rs:416-417 are duplicated backend->state snapshot blocks inside
two run() functions no test can call, and glx_tfp_supported already
carries the same defect today.
D2 now routes the snapshot through a BackendCapabilities struct that both
ServerState constructors take as a required parameter, so the omission
does not compile. This is cheap because those two constructors have
exactly one call site each — the two run() functions; the 617 call sites
of ServerState::new are untouched. The pre-existing glx_tfp_supported gap
closes with it.
D1 drops the cached field: under D2 the getter runs once per server
lifetime and the computation is a matches! on an enum, so caching would
buy nothing and would cost an initialiser in for_tests_seed, which this
design now leaves alone.
D4 gained the rewrite of the comment above the arm it changes, which rev
2 modified the code under and left standing ("returning mesa (matching
Xorg)"). The Asahi/cogl SIGSEGV rationale underneath is still live and is
preserved, now carried by the non-NVIDIA arm of D1.
Rev 2's "Unverified here" section was wrong about this box: ~/Projects/
xserver is checked out here at 5541a5c8 and libglvnd 1.7.0's source ships
in Gentoo's distfiles. All six Xorg citations verified exact, plus
glxscreens.h:150 (char *glvnd — a single string) as structural proof that
Xorg never emits more than one name. libglvnd's __glXLookupVendorByScreen
verified exact at libglxmapping.c:519-600, which closes rev 2's escape
hatch in favour of the "nvidia mesa" list rather than a bare "nvidia".
25 of 26 yserver citations exact; backend.rs:2107 corrected to 2104.
Base: glx-reply-xorg-alignment @ bd168cf. Still not implemented.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Rev 3 was reviewed against AGENTS.md and against the norms this project already set. Six findings applied, one dismissed with its reasoning recorded. Withdrew overstated evidence. Rev 3 added glxscreens.h:150 (char *glvnd) as "structural confirmation" that Xorg never emits more than one vendor name. It confirms nothing: a char * holds "nvidia mesa" as readily as "mesa", so the field type is compatible with one name and with many. The claim rests on the assignment sites alone, which rev 2 already cited. This mattered because it sat in the section whose entire purpose is closing rev 2's escape hatch on the divergence — the same failure mode (a citation that does not support what it is cited for) that Opus round 1 caught in rev 1. Scoped an unverified universal negative. Rev 3 asserted "no X client parses this string itself" in the exact sentence carrying AGENTS.md:19's "clients are tested for 40+ years on Xorg". Reading one library cannot establish that. Narrowed to the checked claim — libglvnd is the only known consumer and handles a list as described — with the residual exposure named: a client that queries GLX_VENDOR_NAMES_EXT on raw xcb-glx and assumes one name. Our own rawglx probe issues that query. Declared severability. D2's BackendCapabilities refactor touches dpms_capable and glx_tfp_supported and closes a pre-existing wiring gap; none of that is defect A. The two changes now have their own section and the plan must order the refactor first. This is not bookkeeping: the vendor work is gated on a Plasma measurement that can fail, since defect B is open and unmeasured, and a change that is independently correct must not be held behind a hardware result it does not depend on. It also keeps the AGENTS.md:18 squash honest. Moved from_backend out of trait_def.rs into backend/mod.rs — core does read YSERVER_* elsewhere, but every such read is in a behaviour module, and startup policy does not belong in the contract. Not params.rs either: that module is explicitly core -> backend, per-request. Named the module and test homes rev 3 left ambiguous, and gave docs/status.md a second entry for the seam change, belonging to task 1. Dismissed: the with_* constructor naming. It reads like a break until you notice width/height are already absent from two of the three names — the convention names the differentiator from the base constructor, and capabilities becomes common to both randr constructors. Recorded so it is not re-raised. Base: glx-reply-xorg-alignment @ bd168cf. Still not implemented. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Six tasks against spec rev 4. Task 1 is the severable BackendCapabilities refactor and carries no hardware precondition; tasks 2-6 are defect A proper, gated on the Plasma measurement in task 6. Task 1 deliberately does NOT add the glx_vendor_names field. That is the severability boundary, and it exercises the mechanism the refactor exists for: task 2's new field fails to compile at from_backend's struct literal until it is handled. Task 4's integration test is the designated verified-failing-first test — against today's code the arm returns the VENDOR_NAMES constant regardless of state, so it fails with "mesa" rather than failing to compile. Both docs/status.md entries are folded into the tasks that own them: the seam entry into task 1, the YSERVER_GLX_VENDOR knob into task 4. Task 6 leads with the branch check. run-probe-session-0805.sh builds whatever branch is checked out, and on 2026-08-05 that produced four output files byte-identical to the baseline — a re-measurement of the bug mistaken for a measurement of the fix. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
lib.rs:336-337 and nested.rs:416-417 were duplicated backend->state snapshot blocks inside two run() functions no test can call: yserver::run needs a DRM device and a VT, nested::run needs a host X server. Nothing caught an omission at either site, so a missed glx_tfp_supported assignment compiled, passed every unit test, and silently shipped the default. Both randr constructors now require a BackendCapabilities, built only by from_backend, so the omission does not compile. This is cheap because those constructors have exactly one call site each -- the two run() functions; the 617 call sites of ServerState::new are untouched. The move is semantically inert: with_randr_outputs_and_modes' body reads neither dpms nor glx_tfp_supported, so assigning them inside the constructor rather than after it is indistinguishable. Severable from the GLX vendor work it was written for.
…ed-assignment test Review findings on the BackendCapabilities commit: - backend/mod.rs re-exported BackendCapabilities as pub(crate), letting nested.rs reach it via crate::backend::BackendCapabilities. That path contradicts the type's own doc comment (server.rs): backend depends on server, not the reverse, and the type lives in crate::server. lib.rs already named it correctly. Drop the re-export back to a private use (still visible to the test submodule) and call it as crate::server::BackendCapabilities from nested.rs, matching lib.rs. - randr_constructors_deposit_capabilities_into_server_state built both BackendCapabilities fields as true/true, so a crossed assignment in with_randr_outputs_and_modes (dpms <-> glx_tfp_supported swapped) left the test green. Made each call's two fields disagree, and inverted between the two calls, so either call alone still proves both fields land un-mixed. Verified by swapping the two assignments in with_randr_outputs_and_modes locally: the amended test fails, as expected; reverted before committing.
Adds Backend::glx_vendor_names (default "mesa", the same value Xorg's glamor provider falls back to), the ServerState field it feeds, and resolve_glx_vendor_names for the YSERVER_GLX_VENDOR override. ash is a yserver-crate dependency only, so the value crosses the seam as a &'static str the way glx_tfp_supported crosses as a bool. The override takes the env value as a parameter rather than reading it inside the resolver: env mutation races under a parallel test runner. from_backend is the single place that reads std::env, and it runs once per server lifetime, so no OnceLock caching is warranted. Blank or whitespace-only input degrades to the derived value with a warning -- a typo must not keep the display server from starting. An unloadable name is deliberately not validated server-side: libglvnd falls through to the next entry in the list. No behaviour change yet; the reply arm still returns the constant.
KmsBackend now answers "nvidia mesa" on NVIDIA_PROPRIETARY and keeps "mesa" everywhere else. Same shape as the tree's other per-driver policies, scanout_prefers_linear and VkContext::supports_dri3_syncobj. The mapping is deliberately binary: an unmeasured mapping that redirects a configuration working today onto a nonexistent libGLX_*.so is worse than the status quo. The second entry is insurance for the package split where the NVIDIA Vulkan ICD is present but libGLX_nvidia.so is not -- a bare "nvidia" would leave libglvnd on FALLBACK_VENDOR_NAME "indirect", worse than today's llvmpipe. libglvnd 1.7.0 honours a list (src/GLX/libglxmapping.c:519-600). No cached field: the getter runs once per server lifetime and the computation is a matches! on an enum, so for_tests_seed is untouched.
The arm returned the hardcoded VENDOR_NAMES ("mesa") for every screen,
so libglvnd loaded libGLX_mesa.so on NVIDIA hardware, Mesa found no DRI
driver for the PCI id, and GL fell back to llvmpipe on a discrete GPU.
It now reads ServerState::glx_vendor_names, derived from vk.driver_id at
startup. The regression test was verified failing against the previous
commit first.
Also adds a debug! on the QueryServerString path. That path had no
logging at all, which made the server log structurally incapable of
showing the query this whole change rests on -- without it a hardware
run cannot tell "libglvnd honoured our list" from "libglvnd guessed
nvidia for unrelated reasons".
The comment above the arm was rewritten rather than dropped: the
Asahi/cogl SIGSEGV rationale is still live, now carried by the
non-NVIDIA arm of the driver mapping instead of by a constant.
…efault
The end-to-end reviewer traced vk.driver_id through Backend::glx_vendor_names,
BackendCapabilities::from_backend, ServerState, and the QueryServerString
reply arm and found the value's path correct. But
from_backend_takes_vendor_names_from_the_backend asserted "mesa" -- byte-
identical to the trait default, the with_geometry struct-literal default,
and what a hardcoded glx::VENDOR_NAMES.to_string() inside from_backend
would also produce. The test passed whether or not from_backend actually
called backend.glx_vendor_names(). RecordingBackend now carries its own
overridable glx_vendor_names field, following the exact pattern already
used for dpms_capable, and the test sets it to a non-default value before
asserting it survives the round trip. Temporarily hardcoding the constant
inside from_backend was confirmed to fail this test and reverted.
KmsBackend's override -- the one place the driver-derived value is actually
computed -- had no test reaching it through the Backend trait at all,
leaving room for the override to end up on an inherent impl instead of the
trait impl, which compiles and is silently dead against &dyn Backend call
sites. Added a UFCS-style call through the trait that also pins the
platform.vk == None fallback.
resolve_glx_vendor_names trimmed only the ends of YSERVER_GLX_VENDOR, so
an internal tab or newline would reach the wire intact. libglvnd splits
the reply on a literal single space, so that survivor becomes one
unloadable token with no fallback entry behind it -- worse than not
overriding at all. Switched to split_whitespace().join(" "), which
normalizes instead of rejecting and keeps the existing trim-equivalent
behaviour and the deliberate no-server-side-validation stance intact.
Reworded the doc comment and the blank-value log line, which called
whitespace-only input "empty."
randr_constructors_deposit_capabilities_into_server_state used "mesa" for
the with_randr_outputs case -- the constructor ynest actually calls, and
the one no other test reaches -- so that half of the test couldn't detect
the field being dropped either. Swapped the two vendor strings between
the cases so each half carries a non-default value in the constructor it
covers.
Updated the two comments left stale by this field's addition: nested.rs's
capability-snapshot comment still said "DPMS support, GLX
texture-from-pixmap support," and mod.rs's cross-reference had drifted to
a stale line number after with_randr_outputs moved.
docs/status.md's precedence paragraph didn't say what YSERVER_GLX_VENDOR=""
actually does (warn and fall back, same as unset) -- worth stating since
an operator clearing the variable to disable the override would otherwise
have to read the code to find out. The Task-1 bullet referenced a "Task 2"
that doesn't exist as changelog vocabulary and described this file's own
follow-on commits in future tense; rewritten in past tense.
YSERVER_GLX_VENDOR is an operator rollback lever, not developer tracing,
so it belongs in the man page's ENVIRONMENT section alongside
YSERVER_DRM_DEVICE and friends rather than under the "further YSERVER_*
variables are deliberately not documented" clause -- docs/status.md gets
archived periodically and isn't a durable home for it.
Finally, dropped the Default derive from BackendCapabilities. Nothing in
the workspace called ::default() or ..Default::default(), and Default
was a compiling bypass of the exact invariant the type exists to
enforce -- that a ServerState cannot be built without consulting a
backend.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
scdoc parses a leading double-underscore as an empty italic span and silently drops it -- exit status 0 either way. The YSERVER_GLX_VENDOR entry named libglvnd's own override as GLX_VENDOR_LIBRARY_NAME in the rendered roff, missing its leading __ entirely, which points an operator at a variable that doesn't exist. Escaped both underscores (*\_\_GLX_VENDOR_LIBRARY_NAME*) and restored the bold markup that had to be dropped earlier to work around the parse error; the surrounding entries already bold variable names mentioned in body text (see GLX_VENDOR_NAMES_EXT two lines up), so this brings it back in line. Verified against the actual roff output, not just scdoc's exit code: before, \fI\fRGLX_VENDOR_LIBRARY_NAME; after, \fB__GLX_VENDOR_LIBRARY_NAME\fR. backend/mod.rs's cross-reference to RecordingBackend::dpms_capable() had drifted to recording.rs:1526 -- a field added since now pushes the getter down to 1533, and 1526 lands inside an unrelated COW-release method's Ok(final_release). The doc comment on glx_vendor_names_falls_back_to_mesa_with_no_vk claimed the UFCS call "forces dispatch through impl Backend for KmsBackend rather than a same-named inherent method." True, but with platform.vk == None the override and the trait default return the identical &'static str, so the assertion passes regardless of which impl supplies the method, and the trait's default means UFCS still resolves even if the inherent method vanished -- no compile-time discrimination either. Added a sentence naming what the test actually pins: the map_or fallback body in glx_vendor_names, which breaks if that map_or becomes an unwrap/expect on vk or if the no-Vulkan default moves off "mesa" -- and saying plainly that it does not distinguish trait from inherent dispatch. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…nment # Conflicts: # docs/status.md
…iver # Conflicts: # crates/yserver/src/kms/render/backend.rs # docs/status.md
Owner
|
Thx, I'll review later, please fix the conflicts first. |
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>
Contributor
Author
|
I fixed the conflicts |
Owner
|
Thx! I tested cinnamon on my 1050 box, and it was UNUSABLE on master, and with your branch, everything was fixed! |
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.
feat(glx): derive GLX vendor names from the render driver
Branch:
glx-vendor-names-from-driver, opened againstmaster.Hardware numbers below were measured on this branch before it was merged with current
master. The post-merge tree is green (2252 tests, clippy and fmt clean), andmaster's new commits touch the Present/TFP wait paths rather than the vendor derivation, but the probe has not been re-run against the exact merged tree. Say the word and I'll re-measure before you look at it seriously.Problem
GLX_VENDOR_NAMES_EXTwas answered with a hardcoded constant:libglvnd therefore loaded
libGLX_mesa.soon every screen yserver serves. Mesa has no DRI driver for an NVIDIA PCI id, so DRI3 screen creation failed and GL fell back to llvmpipe — software rasterisation on a discrete GPU:The server already held the discriminating fact —
vk.driver_id, which it consults today to suppressGLX_EXT_texture_from_pixmapon NVIDIA. It was simply never consulted for the vendor query.This PR contains two separable changes
1.
BackendCapabilities(commitsdd63b51,b71a715) — a refactor that stands on its own.yserver::runandyserver_core::nested::runeach carried a duplicated backend→state snapshot block, inside functions no test can call (one needs a DRM device and a VT, the other a host X server). Nothing caught an omission at either site, andglx_tfp_supportedalready carried that defect.Both
ServerStaterandr constructors now require aBackendCapabilities, built only byfrom_backend, so the omission does not compile. This is cheap because those constructors have exactly one call site each — the tworun()functions; the 617 call sites ofServerState::neware untouched.This half touches
dpms_capableandglx_tfp_supported, neither of which is the GLX defect. It is severable and reviewable on its own.2. The vendor derivation (the rest).
KmsBackendanswers"nvidia mesa"onNVIDIA_PROPRIETARYand"mesa"everywhere else; the value crosses theBackendseam as a&'static str(ashis ayserver-crate dependency only), is snapshotted intoServerStateat startup, and the reply arm reads it.Deliberate divergence from Xorg
Xorg never emits more than one vendor name (
glx/glxscreens.h:150is a singlechar *, assigned once fromgbm_device_get_backend_nameorstrdup("mesa")). This sends two.GLX_EXT_libglvnddefines the reply as a space-separated list, so a one-element list is a subset, not a contradiction. The second entry is insurance for a routine package split: with a bare"nvidia"on a system where the NVIDIA Vulkan ICD is installed butlibGLX_nvidia.sois not, libglvnd resolves no vendor and falls toFALLBACK_VENDOR_NAME = "indirect"— worse than today's llvmpipe.Verified against libglvnd 1.7.0 source (
src/GLX/libglxmapping.c:519-600):__glXLookupVendorByScreensplits the reply withstrtok_r(..., " ", ...), tries each name in order, moves to the next when a vendor fails to load or itsisScreenSupportedreturns False, and uses the fallback only when all fail. Happy to drop to a bare"nvidia"if you'd rather stay strictly Xorg-shaped — that is a one-line change and nothing else in the design moves.The mapping is deliberately binary. Arms for AMD proprietary, Imagination and the rest are omitted because nobody here can measure them, and an unmeasured mapping that redirects a working configuration onto a nonexistent
libGLX_*.sois worse than the status quo.Escape hatch
YSERVER_GLX_VENDORoverrides the derived value verbatim (nvidia,mesa,nvidia mesa). Precedence is env > driver derivation >"mesa". A blank value warns and falls back rather than failing startup; an unloadable name is deliberately not validated server-side, since libglvnd falls through to the next entry. Documented indocs/status.mdand in the man page's ENVIRONMENT section, including that it is read by the server, so changing it needs a server restart — unlike__GLX_VENDOR_LIBRARY_NAME, which takes effect on the next client launch.Verification
Measured on an RTX 5060 Ti, NVIDIA 610.57.04, open kernel modules.
With no
__GLX_VENDOR_LIBRARY_NAMEset:That probe output was byte-identical to the llvmpipe baseline before this change (md5
b45bacfb…); it is now4760fdae…. Control: forcing__GLX_VENDOR_LIBRARY_NAME=mesastill lands on llvmpipe with the Mesa loader errors, so the NVIDIA result is caused by the vendor selection and not by something else on the branch.Known limitation — please read before merging
KWin still cannot start GL compositing on NVIDIA, and this change moves where it fails.
kwin_x11aborts with:The client-side GLX extension string that
libGLX_nvidiacomputes against yserver omitsGLX_ARB_get_proc_address, and libepoxy aborts resolving the entrypoint. Setting__GLX_VENDOR_LIBRARY_NAME=nvidiadoes not avoid it.Two things worth stating plainly:
glXBindTexImageEXT. Both vendors break KWin; this changes which call aborts, and therefore what the default shipped failure is. Applications are unaffected — Steam and Hollow Knight launch and render on the GPU.GLX_ARB_get_proc_addresseither; it is excluded fromknown_glx_extensionswith the comment "GLX_ARB_get_proc_address is implemented on the client" (glx/extension_string.c:74). Adding it server-side would diverge from Xorg without addressing the cause.Measured so far, against a live XWayland on the same GPU and driver as a control: XWayland's client string leads with
GLX_ARB_get_proc_addresswhile its server string lacks it, solibGLX_nvidiaadds it there and not here. An A/B eliminated the GLX vendor string,GLX_EXT_import_context, and the size/content of the server extension list. NVIDIA withholds exactly two entries against yserver —GLX_ARB_get_proc_addressandGLX_SGIX_fbconfig, the latter one we do advertise — which points at something structural rather than at the list. The remaining untested difference is fbconfig synthesis: 2 configs against XWayland's 168. That investigation is ongoing and is not part of this PR.Happy to hold this until that is resolved if you'd rather not change the default failure mode.
Notes
cargo clippy --all-targets -- -D warningsclean,cargo +nightly fmt --checkclean. All commits signed.docs/superpowers/."mesa"; PRIME/Optimus, wherevk.driver_idnames the render device's driver and need not match the KMS node's vendor.🤖 Generated with Claude Code