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
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.
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.
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.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
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/gamescopeat patch level 0 — noPUNKTFUNK_GAMESCOPE_BINoverride, nopunktfunk-gamescopeon PATH. Everything else was ready:host_wants_10bit=true,client_supports_10bit=true, HEVC, and the GPU's own probe reportsten_bit=true.Nothing in 0.31.x touched HDR gating —
discovery.rs, the handshake gate andcapturer_supports_hdr_forare 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.shhas been unbuildable since 2026-08-13.3ac4548cturned on-Denable_gamescope_wsi_layer=true, andbuild-punktfunk-gamescope.shtreats a missing layer as a hard error. The layer needsx11-xcb, which Debian alone splits intolibx11-xcb-dev; the distrobox apt list — last touched 2026-07-31 — never got it.ci/gamescope-trixie.Dockerfilewalked into the identical trap one release later (1b28a7f7, v0.28.1) and now assertsx11-xcbat image build; this list never got the same fix.Reproduced on
debian:trixiewith that list verbatim, gamescope at the pinned5fb8dce4:meson setupexits 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, deletingPUNKTFUNK_GAMESCOPE_BINfromhost.env— but a failed build replaced nothing: the installed binary is still on disk and still passesverifies. 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.
unwirehappens 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:Self-inflicted: commit 1 also took
libdisplay-info-devfrom the CI image's list. That list is for a.debthat 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 inforce_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-infojoinsforce_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
meson setup, Deck list vs fixed,debian:trixielibdisplay-info.so.2)libdisplay-info-devstill installedhost.envwired, stamp writtenlddon the resultlibdisplay-info.so.2, nothing missingpunktfunk-host hdr-probeon the VMlevel=8,gamescope offers 10-bit PQ capture: truecargo clippy -p pf-vdisplay --all-targets -- -D warnings(CI image)rustfmt --check,bash -nboth scriptsThe VM had none of it beforehand — no binary, no override, no stamp, and the same
x11-xcb/xkbcommon-x11gap in itspf2distrobox — 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 markergoes DEBUG → INFO. The handshake already reportscapture_supports_hdr=falseat INFO while the one line saying why sat a level below it; that asymmetry is what made this report expensive to answer.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.