Three things, one delivery path — a Fedora/Nobara box getting the patched gamescope. **The pin moves 8c676c39 -> 5fb8dce4** (3.16.25-1 -> 3.16.25-11). The commit that matters is ff6b924, `rendervulkan: fall back to XBGR2101010 when XRGB2101010 is unsupported`: it probes `linearTilingFeatures` for STORAGE+SAMPLED and captures as XBGR2101010 where A2R10G10B10 linear storage is unavailable — which is every NVIDIA. That covers the paths that are upstream's rather than ours: the RGB intermediate `paint_pipewire()` acquires when the stream is YCbCr, and AVIF screenshots. #143 fixed our own node host-side; this is the other half, and its commit message asked for exactly this bump. All six patches rebased. Only 0006 conflicted: upstream's f8be7ee added `vulkan_has_drm_modifiers_for_features()` immediately above the `g_device` declaration our patch turns into a reference — both kept. 0003 and 0005 come out byte-identical; 0006 also picks up the `--zero-commit --no-signature` form 0001-0005 already used. **Patch 0001 now offers `xBGR_210LE` BEFORE `xRGB_210LE`**, mirroring the host-side `HDR_FORMAT_ORDER` rationale on the producer end. A consumer takes the first pod it can use, and we were handing third-party consumers (OBS and friends) the one format NVIDIA fills byte-reversed under a correct-looking label. Deliberately NOT done by calling upstream's `vulkan_get_rgb10_capture_format()`, which is what pw_pods.rs proposes: that symbol landed after 3.16.25, so it would break `packaging/nix/gamescope.nix` — which applies these patches to whatever gamescope nixpkgs pins — with an opaque C++ error instead of a patch conflict. The reorder gets the same outcome on any base. Note added there so the next reader does not "fix" it. **And the RPM was never signed.** `Sign RPMs` runs right after `Build RPM`; the gamescope RPM is built ~90 steps later, behind its own ~10-minute cache, so it missed the signing pass entirely — every punktfunk-gamescope RPM ever published went out unsigned. The repo file we tell users to install carries `gpgcheck=1`, so `dnf install punktfunk-gamescope` failed with "The package is not signed" on every Fedora and Nobara box. The package was in the channel the whole time and could not be installed from it, which is worse than absent: the notes and the docs-site both say it is there. `sign-rpms.sh` now takes explicit paths (defaulting to `dist/*.rpm` as before) and a second pass signs this one before publish, fail-closed on a tag like the first. Verified on Nobara 44 (VM 123, RTX 5070 Ti passthrough), canary 0.27.0-0.ci12611.g516a2954: * Builds clean in the fc44 CI image; banner `3.16.25-17-ga87390d+pfhdr4` (11 upstream + our 6), so the marker the host probes still reads 4 — no capability moved, hence pkgrel 3 and `.pfhdrN` staying put. * `pw-cli enum-params` on the live node: BGRx, NV12, **xBGR_210LE (81), xRGB_210LE (80)** — 8-bit consumers still negotiate bit-for-bit, 10-bit now leads with the safe one. * All four patched flags present, `--pipewire-composite-external-overlay` included. * Patch 0006 confirmed working by comparison, which is the only way to see it: the new build exits 0 where both the pre-0006 `+pfhdr2` build and the stock 3.16.23.2 abort with 134. * Signing fix proven with a throwaway key: `Signature: (none)` -> `digests signatures OK`. * Host health on the canary: synthetic spike 300/300 encoded, loopback 300 recovered, 0 mismatches. One unexplained one-off: the very first headless run after install segfaulted at exit (SIGSEGV, after "Primary child shut down!"). Not reproduced in 11 subsequent runs across every flag combination, so it is recorded rather than diagnosed — the binary is stripped and there is no symbolised core.
108 lines
5.8 KiB
Nix
108 lines
5.8 KiB
Nix
# `punktfunk-gamescope` — nixpkgs' gamescope carrying punktfunk's `pipewire-hdr` patches, exposed
|
|
# under its own name so it sits BESIDE the system gamescope instead of replacing it.
|
|
#
|
|
# An override rather than a from-scratch derivation on purpose: gamescope vendors wlroots,
|
|
# vkroots, libliftoff, libdisplay-info, SPIRV-Headers and reshade as git submodules plus two meson
|
|
# wraps, and nixpkgs already solves all of that. What we add is the patch set and a rename.
|
|
#
|
|
# This is also why the override needs none of the `force_fallback_for` armour
|
|
# `build-punktfunk-gamescope.sh` carries: that exists because meson silently prefers a SYSTEM
|
|
# wlroots when the build host has one and links it shared, producing a binary that starts only on
|
|
# machines with that dev library. A nix closure names every library it links, so the outcome is
|
|
# whatever nixpkgs' own gamescope already does — reproducibly.
|
|
#
|
|
# `gamescope` in nixpkgs is a wrapper (it wires the WSI layer + capabilities); the buildable
|
|
# derivation is `gamescope.unwrapped` — patching the wrapper would be a no-op, so this asserts on
|
|
# it rather than silently shipping an unpatched binary.
|
|
#
|
|
# Version drift: the patches are applied to whatever gamescope your nixpkgs pins, NOT to the
|
|
# commit `packaging/gamescope/build-punktfunk-gamescope.sh` names. Both hunks sit in code that has
|
|
# been stable across the 3.16 series (`src/pipewire.cpp`'s format builders, `paint_pipewire()` in
|
|
# `src/steamcompmgr.cpp`), so this normally just works — and when it does not, the build fails
|
|
# loudly at `patchPhase` rather than producing a gamescope that quietly cannot do HDR.
|
|
#
|
|
# ⚠️ Kept deliberately free of any dependency on the pinned rev. The pin moved past upstream's
|
|
# `vulkan_get_rgb10_capture_format()` (`ff6b924`, after 3.16.25) to fix red/blue on NVIDIA, and it
|
|
# would have been natural to have patch `0001` call it — that is what the host-side note in
|
|
# `crates/pf-capture/src/linux/pw_pods.rs` proposes. It does NOT, precisely so this derivation
|
|
# keeps building against a nixpkgs that still pins 3.16.25, where that symbol does not exist and
|
|
# the failure would be an opaque C++ error rather than a patch conflict. Patch `0001` gets the
|
|
# same outcome version-independently by offering `xBGR_210LE` ahead of `xRGB_210LE`.
|
|
{
|
|
lib,
|
|
gamescope,
|
|
patchDir,
|
|
}:
|
|
let
|
|
# As of nixos-unstable (checked 2026-07-28) `gamescope` IS the buildable derivation — pname
|
|
# "gamescope", version 3.16.25, carrying `src`/`patches`/`mesonFlags`. Revisions that wrap it
|
|
# (to wire the WSI layer + capabilities) expose the build as `.unwrapped`, so prefer that where
|
|
# it exists and take `gamescope` itself otherwise.
|
|
#
|
|
# The check is on the RESULT, not on which attribute we found: `overrideAttrs` on a symlinkJoin
|
|
# wrapper succeeds and does nothing, which would hand us an UNPATCHED gamescope installed under
|
|
# our own name — the single worst outcome here, because the host reads the name as a promise of
|
|
# HDR. (`installCheckPhase` below greps for the marker as the second line of defence; this one
|
|
# fails at eval, before anything is built.)
|
|
base = gamescope.unwrapped or gamescope;
|
|
unwrapped =
|
|
if base ? src then
|
|
base
|
|
else
|
|
throw ''
|
|
punktfunk-gamescope needs a buildable gamescope derivation (one with a `src` that
|
|
`overrideAttrs` can patch); this nixpkgs' `gamescope` is neither that nor a wrapper
|
|
exposing `.unwrapped`. Update nixpkgs, or build the compositor with
|
|
packaging/gamescope/build-punktfunk-gamescope.sh instead.
|
|
'';
|
|
in
|
|
unwrapped.overrideAttrs (old: {
|
|
pname = "punktfunk-gamescope";
|
|
|
|
# Read the patch DIRECTORY rather than naming files: `builtins.attrNames` sorts
|
|
# lexicographically, which for `000N-` prefixes is exactly the apply order, and a patch added or
|
|
# renamed upstream of this file can no longer leave nix silently building a subset. (That already
|
|
# happened once — this list still named the level-1 banner patch after level 2 landed, so a nix
|
|
# build would have shipped a binary with no cursor patch and a marker claiming otherwise.)
|
|
patches =
|
|
(old.patches or [ ])
|
|
++ map (f: "${patchDir}/${f}") (
|
|
builtins.filter (lib.hasSuffix ".patch") (builtins.attrNames (builtins.readDir patchDir))
|
|
);
|
|
|
|
# nixpkgs builds from a `fetchFromGitHub` src, so there is no `.git` for `git describe` and the
|
|
# banner would read `+pfhdrN (gcc …)` with no version at all — which the host's diagnostic
|
|
# version gate then misreads (it takes the first X.Y.Z triple it finds, i.e. the compiler's).
|
|
# Substituting the real version in keeps `--version` honest AND keeps our marker.
|
|
postPatch = (old.postPatch or "") + ''
|
|
substituteInPlace src/meson.build \
|
|
--replace-fail \
|
|
"vcs_tag = run_command(vcs_tag_cmd, check: false).stdout().strip()" \
|
|
"vcs_tag = '${old.version}'"
|
|
'';
|
|
|
|
# Ship ONLY the compositor, renamed. Everything else nixpkgs installs (gamescopectl,
|
|
# gamescopereaper, gamescopestream, the WSI layer, .desktop files) belongs to the real gamescope
|
|
# package — duplicating it here would put two of each on PATH. The host only execs the
|
|
# compositor.
|
|
postInstall = (old.postInstall or "") + ''
|
|
find $out -mindepth 1 -maxdepth 1 ! -name bin -exec rm -rf {} +
|
|
find $out/bin -mindepth 1 ! -name gamescope -delete
|
|
mv $out/bin/gamescope $out/bin/punktfunk-gamescope
|
|
'';
|
|
|
|
# `gamescope --version` exits non-zero on some builds; the grep is the real assertion.
|
|
doInstallCheck = true;
|
|
installCheckPhase = ''
|
|
runHook preInstallCheck
|
|
$out/bin/punktfunk-gamescope --version 2>&1 | grep -q '+pfhdr' \
|
|
|| { echo "punktfunk-gamescope: the +pfhdr marker is missing — the patches did not take"; exit 1; }
|
|
runHook postInstallCheck
|
|
'';
|
|
|
|
meta = (old.meta or { }) // {
|
|
description = "gamescope with 10-bit BT.2020/PQ PipeWire capture, for punktfunk HDR streaming";
|
|
mainProgram = "punktfunk-gamescope";
|
|
};
|
|
})
|