A failed gamescope rebuild took HDR from boxes whose compositor still worked #382

Merged
enricobuehler merged 2 commits from worktree-gamescope-rebuild-keeps-hdr into main 2026-08-23 08:06:56 +00:00
Owner

Field report: "after updating to 0.31.2 HDR is no longer working" on a SteamOS box. The host log's only failed gate was capture_supports_hdr=false, with discovery resolving the distro's stock /usr/bin/gamescope at patch level 0 — no PUNKTFUNK_GAMESCOPE_BIN override, no punktfunk-gamescope on PATH. Everything else was ready: host_wants_10bit=true, client_supports_10bit=true, HEVC, and the GPU's own probe reports ten_bit=true.

Nothing in 0.31.x touched HDR gating — discovery.rs, the handshake gate and capturer_supports_hdr_for are unchanged since ≤0.30.0. The update didn't regress the code; it took the patched compositor away.

Two defects, one symptom

1. scripts/steamdeck/build-gamescope.sh has been unbuildable since 2026-08-13. 3ac4548c turned on -Denable_gamescope_wsi_layer=true, and build-punktfunk-gamescope.sh treats a missing layer as a hard error. The layer needs x11-xcb, which Debian alone splits into libx11-xcb-dev; the distrobox apt list — last touched 2026-07-31 — never got it. ci/gamescope-trixie.Dockerfile walked into the identical trap one release later (1b28a7f7, v0.28.1) and now asserts x11-xcb at image build; this list never got the same fix.

Reproduced on debian:trixie with that list verbatim, gamescope at the pinned 5fb8dce4:

Run-time dependency x11-xcb found: NO (tried pkgconfig and cmake)
src/layer/meson.build:3:14: ERROR: Dependency "x11-xcb" not found

meson setup exits 1 with the old list, 0 with the package added.

2. The failure then took HDR from a box that still had a working compositor. The build-failure branch called unwire, deleting PUNKTFUNK_GAMESCOPE_BIN from host.env — but a failed build replaced nothing: the installed binary is still on disk and still passes verifies. The script warns into a log nobody reads and exits 0, the update reports success, and the host falls back to stock gamescope and fixes the session at 8-bit SDR in the Welcome, which punktfunk/1 cannot take back.

A verifying binary now stays wired, and a box a previous run of this bug unwired gets re-wired. unwire happens only where the binary itself fails its on-glass check — the branch that also removes it.

The second commit, caught on real glass

Verifying commit 1 on the SteamOS lab VM, the build finally completed (652/652, banner +pfhdr8) and then failed its on-glass check:

punktfunk-gamescope: error while loading shared libraries:
libdisplay-info.so.2: cannot open shared object file

Self-inflicted: commit 1 also took libdisplay-info-dev from the CI image's list. That list is for a .deb that runs on Debian; this one cross-builds in trixie for a binary that must run on SteamOS. gamescope vendors libdisplay-info, but it wasn't in force_fallback_for, so meson preferred the system lib and linked it shared.

This is verbatim the wlroots trap the same comment block already documents ("starts fine on the build host and dies with libwlroots-0.19.so … anywhere else"), so it gets the same remedy: libdisplay-info joins force_fallback_for. "Just don't install the -dev package" doesn't hold — Debian, Fedora and Arch all ship it and anything can pull it in transitively.

Verification

check result
meson setup, Deck list vs fixed, debian:trixie exit 1 → exit 0
SteamOS VM, commit 1 built 652/652, on-glass check failed (libdisplay-info.so.2)
SteamOS VM, commit 2, libdisplay-info-dev still installed 929/929, on-glass passed, host.env wired, stamp written
ldd on the result no libdisplay-info.so.2, nothing missing
punktfunk-host hdr-probe on the VM level=8, gamescope offers 10-bit PQ capture: true
cargo clippy -p pf-vdisplay --all-targets -- -D warnings (CI image) exit 0
rustfmt --check, bash -n both scripts clean
changed branch driven through its four states 4/4

The VM had none of it beforehand — no binary, no override, no stamp, and the same x11-xcb/xkbcommon-x11 gap in its pf2 distrobox — i.e. sitting in the identical broken state the report came from.

The on-glass check did its job throughout: it caught the unrunnable binary, removed it, and left the box SDR rather than letting the host promise HDR it could not deliver.

Also

no +pfhdr marker goes DEBUG → INFO. The handshake already reports capture_supports_hdr=false at INFO while the one line saying why sat a level below it; that asymmetry is what made this report expensive to answer.

Field report: "after updating to 0.31.2 HDR is no longer working" on a SteamOS box. The host log's only failed gate was `capture_supports_hdr=false`, with discovery resolving the distro's stock `/usr/bin/gamescope` at patch level 0 — no `PUNKTFUNK_GAMESCOPE_BIN` override, no `punktfunk-gamescope` on PATH. Everything else was ready: `host_wants_10bit=true`, `client_supports_10bit=true`, HEVC, and the GPU's own probe reports `ten_bit=true`. Nothing in 0.31.x touched HDR gating — `discovery.rs`, the handshake gate and `capturer_supports_hdr_for` are unchanged since ≤0.30.0. The update didn't regress the code; it took the patched compositor away. ## Two defects, one symptom **1. `scripts/steamdeck/build-gamescope.sh` has been unbuildable since 2026-08-13.** `3ac4548c` turned on `-Denable_gamescope_wsi_layer=true`, and `build-punktfunk-gamescope.sh` treats a missing layer as a hard error. The layer needs `x11-xcb`, which Debian alone splits into `libx11-xcb-dev`; the distrobox apt list — last touched 2026-07-31 — never got it. `ci/gamescope-trixie.Dockerfile` walked into the identical trap one release later (`1b28a7f7`, v0.28.1) and now asserts `x11-xcb` at image build; this list never got the same fix. Reproduced on `debian:trixie` with that list verbatim, gamescope at the pinned `5fb8dce4`: ``` Run-time dependency x11-xcb found: NO (tried pkgconfig and cmake) src/layer/meson.build:3:14: ERROR: Dependency "x11-xcb" not found ``` `meson setup` exits 1 with the old list, 0 with the package added. **2. The failure then took HDR from a box that still had a working compositor.** The build-failure branch called `unwire`, deleting `PUNKTFUNK_GAMESCOPE_BIN` from `host.env` — but a failed build replaced nothing: the installed binary is still on disk and still passes `verifies`. The script warns into a log nobody reads and exits 0, the update reports success, and the host falls back to stock gamescope and fixes the session at 8-bit SDR in the Welcome, which punktfunk/1 cannot take back. A verifying binary now stays wired, and a box a previous run of this bug unwired gets **re-wired**. `unwire` happens only where the binary itself fails its on-glass check — the branch that also removes it. ## The second commit, caught on real glass Verifying commit 1 on the SteamOS lab VM, the build finally **completed** (652/652, banner `+pfhdr8`) and then failed its on-glass check: ``` punktfunk-gamescope: error while loading shared libraries: libdisplay-info.so.2: cannot open shared object file ``` Self-inflicted: commit 1 also took `libdisplay-info-dev` from the CI image's list. That list is for a `.deb` that runs **on Debian**; this one cross-builds in trixie for a binary that must run **on SteamOS**. gamescope vendors libdisplay-info, but it wasn't in `force_fallback_for`, so meson preferred the system lib and linked it shared. This is verbatim the wlroots trap the same comment block already documents ("starts fine on the build host and dies with `libwlroots-0.19.so` … anywhere else"), so it gets the same remedy: `libdisplay-info` joins `force_fallback_for`. "Just don't install the -dev package" doesn't hold — Debian, Fedora and Arch all ship it and anything can pull it in transitively. ## Verification | check | result | |---|---| | `meson setup`, Deck list vs fixed, `debian:trixie` | exit **1** → exit **0** | | SteamOS VM, commit 1 | built 652/652, **on-glass check failed** (`libdisplay-info.so.2`) | | SteamOS VM, commit 2, `libdisplay-info-dev` still installed | 929/929, on-glass **passed**, `host.env` wired, stamp written | | `ldd` on the result | no `libdisplay-info.so.2`, nothing missing | | `punktfunk-host hdr-probe` on the VM | `level=8`, `gamescope offers 10-bit PQ capture: true` | | `cargo clippy -p pf-vdisplay --all-targets -- -D warnings` (CI image) | exit 0 | | `rustfmt --check`, `bash -n` both scripts | clean | | changed branch driven through its four states | 4/4 | The VM had none of it beforehand — no binary, no override, no stamp, and the same `x11-xcb`/`xkbcommon-x11` gap in its `pf2` distrobox — i.e. sitting in the identical broken state the report came from. The on-glass check did its job throughout: it caught the unrunnable binary, removed it, and left the box SDR rather than letting the host promise HDR it could not deliver. ## Also `no +pfhdr marker` goes DEBUG → INFO. The handshake already reports `capture_supports_hdr=false` at INFO while the one line saying *why* sat a level below it; that asymmetry is what made this report expensive to answer.
enricobuehler added 2 commits 2026-08-23 07:59:33 +00:00
ROOT CAUSE of "HDR stopped working after updating to 0.31.2" on a Deck source install.
Two defects, one symptom.

1. scripts/steamdeck/build-gamescope.sh has been UNBUILDABLE since 2026-08-13, when
   3ac4548c turned `-Denable_gamescope_wsi_layer=true` on. The layer needs x11-xcb, which
   Debian splits into its own libx11-xcb-dev; the distrobox apt list — last touched
   2026-07-31 — never got it. MEASURED on debian:trixie against that list verbatim,
   gamescope at the pinned 5fb8dce4:

       Run-time dependency x11-xcb found: NO (tried pkgconfig and cmake)
       src/layer/meson.build:3:14: ERROR: Dependency "x11-xcb" not found

   `meson setup` exits 1 with the list as it was and 0 with libx11-xcb-dev added, and
   build-punktfunk-gamescope.sh treats a missing layer as a hard error, so the whole build
   fails. ci/gamescope-trixie.Dockerfile walked into the identical trap one release later
   (1b28a7f7, v0.28.1) and asserts x11-xcb at image build; this list never got the same
   fix. Debian-family only: Arch's libx11 and Fedora's libX11-devel carry x11-xcb.pc.
   xkbcommon-x11 and libdisplay-info measured absent too, and are added with it.

2. The build-failure branch then called `unwire`, deleting PUNKTFUNK_GAMESCOPE_BIN from
   host.env. A failed build REPLACED NOTHING — the previously installed binary is still on
   disk and still passes `verifies`. So a rebuild that never landed took HDR away from a
   box that had been streaming it minutes earlier. The script warns into a log nobody reads
   and exits 0, the update reports success, and the host then resolves the distro's stock
   /usr/bin/gamescope at patch level 0 and fixes the session at 8-bit SDR in the Welcome —
   which the punktfunk/1 handshake cannot take back.

   A verifying binary now stays wired (and a box a previous run of this bug unwired gets
   re-wired). `unwire` happens only where the binary itself fails its on-glass check, which
   is the branch that also removes it.

Also promote the "no +pfhdr marker" line from DEBUG to INFO. The handshake already reports
capture_supports_hdr=false at INFO while the one line saying WHY sat a level below it —
that asymmetry is what made this field report expensive to answer.

Verified: the meson reproduction above (exit 1 -> exit 0); all three added package names
resolve on trixie and satisfy their pkg-config modules; the four states of the changed
branch exercised in isolation (working binary stays wired, stock/missing binary unwired,
previously-unwired box re-wired). Not verified on real SteamOS glass — the lab VM was
unreachable from this machine.
fix(gamescope): pin libdisplay-info to the vendored subproject, like wlroots
ci / web (pull_request) Successful in 1m55s
ci / rust-arm64 (pull_request) Successful in 3m27s
ci / bun-nix (pull_request) Successful in 31s
ci / docs-drift (pull_request) Successful in 30s
ci / docs-site (pull_request) Successful in 2m2s
android / android (pull_request) Successful in 6m13s
ci / rust (pull_request) Successful in 6m44s
3b08da11ff
Caught on the SteamOS lab VM while verifying the previous commit end to end. With
libx11-xcb-dev added the build finally COMPLETED (652/652, banner "3.16.25-21-gb71a56c
+pfhdr8") — and then failed its on-glass check:

    punktfunk-gamescope: error while loading shared libraries:
    libdisplay-info.so.2: cannot open shared object file

Self-inflicted: the previous commit also took libdisplay-info-dev from the CI image's
list. gamescope vendors libdisplay-info as a submodule, but it is NOT in
force_fallback_for, so meson preferred the system lib the moment the build box had the
-dev package and linked it SHARED. SteamOS ships no libdisplay-info.so.2, so the binary
built, installed and printed its +pfhdr banner inside the distrobox and could not start
on the machine it exists for.

This is verbatim the wlroots trap the same comment block already documents ("starts fine
on the build host and dies with libwlroots-0.19.so ... anywhere else"), so it gets the
same remedy rather than a second one: libdisplay-info joins force_fallback_for. "Just
don't install the -dev package" does not hold — Debian, Fedora and Arch all have it and
anything can pull it in transitively, and the failure is silent right up to the on-glass
check that build-gamescope.sh happens to run.

Also drop libdisplay-info-dev from the Deck list (pointless once the fallback is pinned)
and record why that list must NOT be synced with ci/gamescope-trixie.Dockerfile: the CI
list targets a .deb that runs on Debian, this one cross-builds in trixie for SteamOS
glass. libx11-xcb-dev and libxkbcommon-x11-dev stay — SteamOS ships both sonames.

The on-glass check did its job here: it caught the bad binary, removed it and left the
box SDR rather than letting the host promise HDR it could not deliver.
enricobuehler merged commit 19df33e0f7 into main 2026-08-23 08:06:56 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: unom/punktfunk#382