Skip to content

Commit 340b45b

Browse files
committed
feat(graphics): compat.libdrm, compat.egl and compat.wayland — the KMS/DRM
stack closes compat.libgbm on its own can allocate a buffer and do nothing with it. These three are the rest of the stack, all on the binding shape libgbm validated: compat.libdrm the layer underneath -- drmModeAddFB2 / drmModeSetCrtc turn an allocated buffer into a scanout compat.egl the layer that makes it renderable -- eglGetPlatformDisplay(EGL_PLATFORM_GBM_KHR, gbm_dev, NULL) compat.wayland the other display path -- be a client of, or be, a compositor WHY BINDINGS AND NOT SOURCE BUILDS. libdrm and wayland both PASS the separable-unit test that libgbm fails -- independent freedesktop projects with their own releases, and Conan carries libdrm as a real recipe. They are bindings for the second criterion instead: the ecosystem already owns them, Mesa's own payload has DT_NEEDED on both, and a second libdrm.so.2 or libwayland-client.so.0 in a process that also loads Mesa means two handle tables for one connection. EGL is the sharpest case: it is a spec, the thing you link is glvnd's vendor-neutral dispatch library, and building a second one would be the "one loader per process" mistake compat.vulkan-runtime already documents. Three things worth knowing, each found by making it work: * libdrm needs TWO include roots. Public headers at the include root, the uapi headers they include under libdrm/, and xf86drm.h line 40 is a bare `#include <drm.h>`. Expose one root and nothing compiles -- measured while writing compat.libgbm's own test, which hit exactly that. * compat.egl ships ONLY EGL/, out of a payload that also carries GL/, GLES2/, GLES3/ and KHR/. A third provider of GL/ would turn the two-provider race compat.glx-headers documents into a three-way one; KHR/ comes from the index's existing compat.khrplatform, and that edge is load-bearing rather than tidy -- without it EGL/egl.h does not parse. X11 is deliberately not a dependency: that include is USE_X11-gated, and forcing Xorg onto headless GBM users would be exactly wrong. * compat.wayland harvests four libraries and puts only -lwayland-client on ldflags. A dependency's ldflags reach the consumer's link line with no way to opt out, so forcing libwayland-server on every client would be unfixable downstream. A compositor author adds it themselves and it resolves out of the farm -- and the test member does exactly that, so the documented escape hatch has a regression guarding it rather than a promise. Verified: all three `mcpp test` green cold via the CN mirror. EGL's client extension list includes EGL_KHR_platform_gbm / EGL_MESA_platform_gbm, which is the seam with compat.libgbm; libdrm's DRM_FORMAT_XRGB8888 is asserted equal to the 'XR24' fourcc compat.libgbm asserts, because those two values cross the gbm_bo -> drmModeAddFB2 boundary and a mismatch shows wrong colours rather than an error. Lint + xpkg parse clean across 139 descriptors. CN mirrors published for all three and re-fetched byte-identical against GLOBAL.
1 parent 1c08e2f commit 340b45b

12 files changed

Lines changed: 1032 additions & 2 deletions

File tree

docs/descriptor-examples.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ in the [root README](../README.md#reference-examples).
3131
| C++ application framework compat (dependencies reuse packages already in the index) | [`compat.eui-neo`](../pkgs/e/compat.eui-neo.lua) (upstream's `3rd/` ships 8 vendored dependencies; none of them is compiled here — all are redirected to the same-version `compat.*` packages in this index) |
3232
| Mutually exclusive backends (one of several inside one package) | [`compat.eui-neo`](../pkgs/e/compat.eui-neo.lua): `vulkan` / `sdl2` each **replace** the default OpenGL / GLFW, and the default backend is expressed by *naming no feature at all* — there is no `opengl`/`glfw` feature. A `default` feature cannot express exclusivity: its own `defines`/`sources`/`deps` have no effect whatsoever, while its `implies` always applies and cannot be overridden by a named feature (which is, conversely, exactly the solution for the "always-on interface define" row below). The workable answer is to read the `-DMCPP_FEATURE_<NAME>` mcpp passes anyway and decide up front in a force-included header. Note also that `cflags` only reaches C TUs — C++ needs `cxxflags`, so a backend define written only into `cflags` never reaches any `.cpp` |
3333
| Host runtime adaptation (drivers are not vendored) | [`compat.glx-runtime`](../pkgs/c/compat.glx-runtime.lua) · [`compat.vulkan-runtime`](../pkgs/c/compat.vulkan-runtime.lua) (mcpp binaries run against a bundled glibc, so a bare-soname `dlopen` never reaches the host drivers; a symlink farm plus `runtime.library_dirs` bridges that. The farm holds only versioned sonames, so nothing there can shadow an index package. Note that `runtime.library_dirs` renders as `-Wl,-rpath` and **not** as `-L` — the `-L` key is `runtime.link_library_dirs`, which these two do not need because nothing links against their farms; see the row below for one that does) |
34-
| Ecosystem-stack binding (zero host) | [`compat.libgbm`](../pkgs/c/compat.libgbm.lua) (Mesa's GBM — buffer allocation out of a DRM device. The row above reaches the HOST; this one reaches the ECOSYSTEM and nothing else, and the distinction is the whole design. **Why not a source build**: libgbm is a build target *inside* Mesa, not a project — `src/gbm/meson.build` is `link_with: [libloader]`, and `libloader` wants `idep_mesautil`, the whole of Mesa's internal util library (~120 TUs plus Python-generated tables) for exactly one function, `loader_open_driver_lib`. Building it would make this index re-import libdrm + expat + xcb + a Mesa-util carve-out to duplicate what `xim:mesa` has already resolved hermetically. Contrast `compat.vulkan`, which *does* build the Khronos loader from source — Khronos releases that as a standalone project, Mesa releases no such thing for GBM. **Zero host, with no escape hatch**: unlike its two neighbours it has no `/usr/lib*` path and no `MCPP_HOST_*` override, because host libgbm is a leak the ecosystem already closed — `xim:nvidia-gl-host-link` names it directly ("the table … was missing libm, libdrm, **libgbm**, libgcc_s … all of which were therefore coming from the HOST, silently, which is the leak this package exists to close"). NVIDIA's own GBM backend, if ever needed, belongs in that host-link layer rather than here. The measured surface is 1 ecosystem package (`xim:mesa`, not `xim:graphics`'s twenty-two), zero index deps, and zero transitive burden — libgbm.so.1's own RUNPATH resolves entirely inside `xim-x-*`. **What it deliberately does NOT do**: set the backend search path. libgbm is a loader — `gbm_create_device()` dlopens `<path>/<driver>_gbm.so`, and Mesa's compiled-in `/usr/lib/gbm` is right on a distro and wrong the moment the payload is relocated. The mechanism to fix that is Mesa's own (`GBM_BACKENDS_PATH`) and the job belongs to the ENVIRONMENT, which is where every other relocated stack puts it — Valve's pressure-vessel answers the identical breakage with `GBM_BACKENDS_PATH=/run/host/usr/lib64/gbm` (steam-runtime#797), Nix and Conda set it at activation. In this ecosystem `xim:mesa` now declares it through the graphics discovery layer (openxlings/xim-pkgindex#713), so this package sets nothing, generates no TU and ships no header of its own. It briefly did carry a constructor that set the variable itself; that was a workaround for the missing declaration, and deleting it took the descriptor from 598 lines to 303. **Two directory keys, not one**: `library_dirs` renders as `-Wl,-rpath` and `link_library_dirs` as `-L`, so a package that is *linked against* (unlike glx-runtime/vulkan-runtime, whose farms are only dlopen'd) needs both — with `library_dirs` alone the farm is complete, the rpath correct, and the build still dies at `ld: cannot find -lgbm`. It ships **two** test binaries: `stock_usage.cpp` includes stock `<gbm.h>` and nothing else, which is the minimal consumer and the tripwire on the two things outside this repo the package now depends on — xim-pkgindex's DISCOVERY row and mcpp's subos-env injection)
34+
| Ecosystem-stack binding (zero host) | [`compat.libgbm`](../pkgs/c/compat.libgbm.lua) (Mesa's GBM — buffer allocation out of a DRM device. The row above reaches the HOST; this one reaches the ECOSYSTEM and nothing else, and the distinction is the whole design. **Why not a source build**: libgbm is a build target *inside* Mesa, not a project — `src/gbm/meson.build` is `link_with: [libloader]`, and `libloader` wants `idep_mesautil`, the whole of Mesa's internal util library (~120 TUs plus Python-generated tables) for exactly one function, `loader_open_driver_lib`. Building it would make this index re-import libdrm + expat + xcb + a Mesa-util carve-out to duplicate what `xim:mesa` has already resolved hermetically. Contrast `compat.vulkan`, which *does* build the Khronos loader from source — Khronos releases that as a standalone project, Mesa releases no such thing for GBM. **Zero host, with no escape hatch**: unlike its two neighbours it has no `/usr/lib*` path and no `MCPP_HOST_*` override, because host libgbm is a leak the ecosystem already closed — `xim:nvidia-gl-host-link` names it directly ("the table … was missing libm, libdrm, **libgbm**, libgcc_s … all of which were therefore coming from the HOST, silently, which is the leak this package exists to close"). NVIDIA's own GBM backend, if ever needed, belongs in that host-link layer rather than here. The measured surface is 1 ecosystem package (`xim:mesa`, not `xim:graphics`'s twenty-two), zero index deps, and zero transitive burden — libgbm.so.1's own RUNPATH resolves entirely inside `xim-x-*`. **What it deliberately does NOT do**: set the backend search path. libgbm is a loader — `gbm_create_device()` dlopens `<path>/<driver>_gbm.so`, and Mesa's compiled-in `/usr/lib/gbm` is right on a distro and wrong the moment the payload is relocated. The mechanism to fix that is Mesa's own (`GBM_BACKENDS_PATH`) and the job belongs to the ENVIRONMENT, which is where every other relocated stack puts it — Valve's pressure-vessel answers the identical breakage with `GBM_BACKENDS_PATH=/run/host/usr/lib64/gbm` (steam-runtime#797), Nix and Conda set it at activation. In this ecosystem `xim:mesa` now declares it through the graphics discovery layer (openxlings/xim-pkgindex#713), so this package sets nothing, generates no TU and ships no header of its own. It briefly did carry a constructor that set the variable itself; that was a workaround for the missing declaration, and deleting it took the descriptor from 598 lines to 303. **Two directory keys, not one**: `library_dirs` renders as `-Wl,-rpath` and `link_library_dirs` as `-L`, so a package that is *linked against* (unlike glx-runtime/vulkan-runtime, whose farms are only dlopen'd) needs both — with `library_dirs` alone the farm is complete, the rpath correct, and the build still dies at `ld: cannot find -lgbm`. It ships **two** test binaries: `stock_usage.cpp` includes stock `<gbm.h>` and nothing else, which is the minimal consumer and the tripwire on the two things outside this repo the package now depends on — xim-pkgindex's DISCOVERY row and mcpp's subos-env injection · [`compat.libdrm`](../pkgs/c/compat.libdrm.lua) (the layer under GBM — `drmModeAddFB2`/`drmModeSetCrtc` turn an allocated buffer into a scanout. Passes the separable-unit test that libgbm fails — libdrm is an independent freedesktop project and Conan carries a real recipe — but is still a binding for the second reason: `xim:libdrm` exists, Mesa's own payload has DT_NEEDED on it, and two `libdrm.so.2` in one process means two DRM handle tables. **Two include roots**, which is the thing that bites: the public headers sit at the include root and the uapi headers they include sit under `libdrm/`, and `xf86drm.h` line 40 is a bare `#include <drm.h>` — expose one root and nothing compiles at all) · [`compat.egl`](../pkgs/c/compat.egl.lua) (what makes libgbm useful for RENDERING rather than only allocation: `eglGetPlatformDisplay(EGL_PLATFORM_GBM_KHR, gbm_device, NULL)`. Provider is libglvnd, not Mesa — EGL is a spec and the thing you link is a vendor-neutral dispatch library that must be the only one in the process. Ships **only** `EGL/` out of a payload that also carries `GL/`, `GLES2/`, `KHR/`: a third provider of `GL/` would make compat.glx-headers' documented two-provider race a three-way one, and `KHR/` comes from the index's existing `compat.khrplatform` instead — load-bearing, since `eglplatform.h` opens with `#include <KHR/khrplatform.h>`. X11 is deliberately NOT a dependency: that include is `USE_X11`-gated, and forcing Xorg on headless GBM users would be exactly wrong) · [`compat.wayland`](../pkgs/c/compat.wayland.lua) (client, server, cursor and EGL shim all harvested, but only `-lwayland-client` on `ldflags`. A dependency's ldflags reach the consumer's link line with no way to opt out, so forcing the server library on every client would be unfixable downstream; a compositor author adds `-lwayland-server` themselves and it resolves out of the farm. The test member does exactly that, so the documented escape hatch has a regression guarding it. `wayland-scanner` and the protocol XML are NOT here — that is a code generator plus a data package, the `compat.protobuf` `protoc` shape, and a separate package))
3535
| Always-on interface define | `CURL_STATICLIB` in [`compat.curl`](../pkgs/c/compat.curl.lua): `cflags` is always on but package-private, while a feature's `defines` reaches consumers yet has to be named — `default = { implies = … }` applies unconditionally and happens to give both |
3636
| Multiple majors in one package (shape switches with the version) | [`compat.catch2`](../pkgs/c/compat.catch2.lua) (3.x compiles `src/catch2/` into a static library; 2.x goes header-only through `single_include/`) |
3737
| External build system (`install()` builds from source) | [`compat.openblas`](../pkgs/c/compat.openblas.lua) (Make) · [`compat.openssl`](../pkgs/c/compat.openssl.lua) (Perl Configure + Make, static libssl/libcrypto) |

0 commit comments

Comments
 (0)