EDID and DisplayID parsing — how a compositor learns a monitor's make, model,
serial and mode list. This is the gate on wlroots: backend/drm/meson.build
declares it required: 'drm' in backends, and everything else wlroots needs is
already in mcpp-index.
upstream/ is libdisplay-info 0.2.0, unmodified. mcpp/ is the adaptation.
No sh, no python3, no checked-in generated code. mcpp/displayinfo/build.mcpp
is a C++ program that mcpp compiles and runs before the library:
| output | what it is |
|---|---|
pnp-id-table.c |
2,583-line PNP vendor id → manufacturer table, into the out dir |
src/libdisplay-info.cppm |
the module wrapper — 206 names read out of the public headers |
The module is written into src/ rather than the out dir because [lib] path
names it statically.
Upstream falls back to the build machine's /usr/share/hwdata/pnp.ids when
no hwdata is found. Measured 2026-08-30: the host's file and hwdata v0.410's
differ by 35 lines, and the tables generated from them by 15. A package built
that way answers di_info_get_make differently depending on where it was
compiled.
mcpp/data/pnp.ids is hwdata v0.410's copy, checked in as an input.
It is also more correct than upstream's generator. pnp.ids stores
DemoPad<U+00A0>Software<U+00A0>Ltd; upstream reads the file as text and
escapes U+00A0 by ordinal to \240, a single byte that is not its UTF-8
encoding. build.mcpp escapes bytes, so the pair survives as \302\240.
import displayinfo; // no extern "C" needed — the module does itThe raw headers have no extern "C" of their own, so a C++ TU that #includes
them mangles every declaration. The module wrapper does that once.
import displayinfo; — not freedesktop.displayinfo. freedesktop.org
hosts this library; the interfaces it parses are VESA's (EDID, DisplayID),
and freedesktop.* in a module name is reserved for freedesktop's own
specifications the way freedesktop.wayland.client is. The index namespace is
a shelf label and never enters the module name.
This changed in this release. A consumer on the old name gets a compile error naming the module, which is the right place to find out.
Not one DI_* came through — the module carried enum di_edid_… but nothing
inside it. It went unnoticed because no test named an enumerator, and
adding one on GCC alone would not have noticed either: exporting the enum makes
its enumerators visible there, and clang rejects the same file with use of undeclared identifier.
The scan now walks typedef enum bodies, the export count is 501, and the test
compares two enumerators so the list cannot silently collapse again.