feat(packaging): ship punktfunk-gamescope on RPM and apt too
ci / web (pull_request) Successful in 1m4s
ci / bun-nix (pull_request) Successful in 26s
apple / swift (pull_request) Successful in 1m40s
apple / screenshots (pull_request) Skipped
ci / rust (pull_request) Failing after 2m3s
ci / docs-site (pull_request) Successful in 1m41s
ci / rust-arm64 (pull_request) Successful in 2m44s
android / android (pull_request) Successful in 4m50s
nix / flake (pull_request) Failing after 16m12s
ci / web (pull_request) Successful in 1m4s
ci / bun-nix (pull_request) Successful in 26s
apple / swift (pull_request) Successful in 1m40s
apple / screenshots (pull_request) Skipped
ci / rust (pull_request) Failing after 2m3s
ci / docs-site (pull_request) Successful in 1m41s
ci / rust-arm64 (pull_request) Successful in 2m44s
android / android (pull_request) Successful in 4m50s
nix / flake (pull_request) Failing after 16m12s
Until now the patched gamescope reached exactly four kinds of box: the Bazzite/Fedora-Atomic sysext, the Arch package, the SteamOS installer and a NixOS option. Everyone else was told to build gamescope from source. A traditional Fedora-family box — Nobara, plain Fedora, the HTPCs people actually stream from — therefore ran stock gamescope by default, which streams SDR, cursorless, and tells every game its display is 60 Hz. That is not a user error; there was no package to install. Both new packages REPACK the binary CI already builds rather than building gamescope again: it is a ~10-minute meson compile of an unrelated tree, cached per distro base because the binary is soname-coupled to it. The Arch PKGBUILD stays the one recipe that builds from source, because that is what makepkg is for. - packaging/gamescope/punktfunk-gamescope.spec + build-gamescope-rpm.sh. Version is derived from the binary's own banner (3.16.25.pfhdr4) — the only source that cannot drift from what is in the package. rpmbuild's automatic ELF Requires are what stop an f43 build installing on f44. - packaging/debian/build-gamescope-deb.sh, same shape, with dpkg-shlibdeps for Depends. - rpm.yml packages and publishes it beside the host RPMs; deb.yml gains a cached gamescope build (keyed on packaging/gamescope/** alone) and packages it into the existing publish loop. Both legs are best-effort, matching the sysext's existing rule: no binary, no package, and the host stays on its current SDR path. Neither package Provides or Conflicts with gamescope — it installs as /usr/bin/punktfunk-gamescope and only the sessions the host starts itself resolve it, so a box's own Game Mode keeps using the distro binary. Both refuse to package a binary without the +pfhdr marker. That marker is the host's entire capability probe, so a build that lost the patches would install fine and then silently stream SDR with no cursor. Verified: build-gamescope-deb.sh produces an installable .deb from a stand-in binary (correct version derived from the banner, 0755 tree, control fields) and exits 1 on an unmarked one. The .spec is not yet exercised — no rpm tooling on the box I had; CI's Fedora leg is its first run.
This commit is contained in:
@@ -320,6 +320,46 @@ jobs:
|
||||
run: |
|
||||
VERSION="$VERSION" BUNDLE_FFMPEG=1 bash packaging/debian/build-deb.sh
|
||||
|
||||
# punktfunk-gamescope for apt. Same reasoning as the RPM leg in rpm.yml: without a packaged
|
||||
# build, a Debian/Ubuntu box has no route to the patched gamescope except compiling it, and a
|
||||
# stock gamescope streams SDR, cursorless, and tells every game its display is 60 Hz.
|
||||
#
|
||||
# CACHED on packaging/gamescope/** alone — it depends on nothing else in this repo, so a
|
||||
# normal push restores a binary instead of spending ~10 minutes on someone else's tree.
|
||||
- uses: actions/cache@v4
|
||||
id: gamescope
|
||||
with:
|
||||
path: gs-cache
|
||||
key: punktfunk-gamescope-noble-${{ hashFiles('packaging/gamescope/**') }}
|
||||
|
||||
- name: Build the patched gamescope
|
||||
if: steps.gamescope.outputs.cache-hit != 'true'
|
||||
# Best-effort, exactly like rpm.yml: the host packages above are the primary delivery and
|
||||
# work without this binary, so a hiccup building an unrelated tree must not fail the job.
|
||||
# `build-dep gamescope` resolves the distro's much older packaged version, so it can come up
|
||||
# short — that is what the `|| true`s absorb, and the marker check downstream is what makes
|
||||
# a half-built result impossible to ship.
|
||||
run: |
|
||||
set -x
|
||||
apt-get update
|
||||
apt-get install -y --no-install-recommends meson ninja-build glslc git || true
|
||||
apt-get build-dep -y gamescope || true
|
||||
if bash packaging/gamescope/build-punktfunk-gamescope.sh \
|
||||
--destdir "$PWD/gs-stage" --prefix /usr --jobs "$(nproc)"; then
|
||||
install -Dm0755 gs-stage/usr/bin/punktfunk-gamescope gs-cache/punktfunk-gamescope
|
||||
else
|
||||
echo "::warning::punktfunk-gamescope failed to build on noble — no .deb this run (gamescope sessions stay SDR)"
|
||||
fi
|
||||
|
||||
- name: Build punktfunk-gamescope .deb
|
||||
# Picked up by the publish loop below, which globs dist/*.deb.
|
||||
run: |
|
||||
if [ -x gs-cache/punktfunk-gamescope ] && gs-cache/punktfunk-gamescope --version >/dev/null 2>&1; then
|
||||
bash packaging/debian/build-gamescope-deb.sh --binary gs-cache/punktfunk-gamescope
|
||||
else
|
||||
echo "::warning::no usable punktfunk-gamescope — skipping its .deb"
|
||||
fi
|
||||
|
||||
- name: Publish to the Gitea apt registry
|
||||
env:
|
||||
TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
||||
|
||||
@@ -213,6 +213,40 @@ jobs:
|
||||
echo "::warning::punktfunk-gamescope failed to build for f${{ matrix.fedver }} — the sysext ships without it (gamescope sessions stay SDR)"
|
||||
fi
|
||||
|
||||
# The same binary, as an ordinary RPM. The sysext below is the Atomic/Bazzite delivery; this
|
||||
# is the one a traditional Fedora-family box (Nobara, plain Fedora) can actually install —
|
||||
# until it existed those users had no packaged route to the patched build at all, and a stock
|
||||
# gamescope tells every game its display is 60 Hz whatever the client negotiated.
|
||||
#
|
||||
# Same best-effort rule as the build above: no binary, no package, and the host stays on its
|
||||
# existing SDR/host-composited path. The spec re-checks the +pfhdr marker itself.
|
||||
- name: Package punktfunk-gamescope as an RPM
|
||||
run: |
|
||||
if [ -x gs-cache/punktfunk-gamescope ] && gs-cache/punktfunk-gamescope --version >/dev/null 2>&1; then
|
||||
bash packaging/gamescope/build-gamescope-rpm.sh \
|
||||
--binary gs-cache/punktfunk-gamescope \
|
||||
--release "$PF_RELEASE"
|
||||
else
|
||||
echo "::warning::no usable punktfunk-gamescope for f${{ matrix.fedver }} — skipping its RPM"
|
||||
fi
|
||||
|
||||
- name: Publish punktfunk-gamescope to the Gitea RPM registry
|
||||
env:
|
||||
TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
||||
run: |
|
||||
shopt -s nullglob
|
||||
for rpm in dist/punktfunk-gamescope-*.rpm; do
|
||||
case "$rpm" in *debuginfo*|*debugsource*) continue;; esac
|
||||
NAME=$(rpm -qp --qf '%{NAME}' "$rpm" 2>/dev/null)
|
||||
VR=$(rpm -qp --qf '%{VERSION}-%{RELEASE}' "$rpm" 2>/dev/null)
|
||||
ARCH=$(rpm -qp --qf '%{ARCH}' "$rpm" 2>/dev/null)
|
||||
echo "uploading $rpm"
|
||||
curl -fsS -o /dev/null --user "enricobuehler:$TOKEN" -X DELETE \
|
||||
"https://$REGISTRY/api/packages/$OWNER/rpm/$GROUP/package/$NAME/$VR/$ARCH" || true
|
||||
curl -fsS --user "enricobuehler:$TOKEN" --upload-file "$rpm" \
|
||||
"https://$REGISTRY/api/packages/$OWNER/rpm/$GROUP/upload"
|
||||
done
|
||||
|
||||
# The no-layering Bazzite path: wrap the just-built host + web RPMs into a systemd-sysext
|
||||
# image and publish it to the per-Fedora-major feed (punktfunk-sysext/f43[-canary], …) that
|
||||
# `punktfunk-sysext install|update` reads. Same RPMs, same channels — just no rpm-ostree.
|
||||
|
||||
@@ -161,6 +161,9 @@ To stream real HDR you need `punktfunk-gamescope`: gamescope plus a small patch
|
||||
own name and does **not** replace your system gamescope — your Gaming Mode keeps using that one.
|
||||
|
||||
- **Bazzite / Fedora Atomic** — included in the Punktfunk sysext; `punktfunk-sysext update` gets it.
|
||||
- **Fedora, Nobara and other RPM boxes** — `sudo dnf install punktfunk-gamescope` from the same
|
||||
Punktfunk repo the host comes from.
|
||||
- **Debian / Ubuntu** — `sudo apt install punktfunk-gamescope` from the Punktfunk apt repo.
|
||||
- **Arch** — the `punktfunk-gamescope` package.
|
||||
- **SteamOS (Steam Deck installer)** — built and wired automatically by
|
||||
`scripts/steamdeck/install.sh` / `update.sh`.
|
||||
@@ -200,6 +203,22 @@ These apply to the **Gaming Mode (gamescope)** path only; the desktop path is un
|
||||
capture node, so the overlay is missing from an otherwise perfect picture. Either case is logged
|
||||
at startup with the version found. Bazzite's and SteamOS's current gamescope is past both; this
|
||||
only bites if you've pinned an old one.
|
||||
- **On a stock gamescope, Gaming Mode reports the wrong refresh rate — and offers no resolutions.**
|
||||
A headless gamescope has no EDID, and upstream's headless connector advertises no display modes
|
||||
and no refresh rates at all. Steam's in-session display settings then show a single refresh entry
|
||||
and an empty resolution list, and that one entry is whatever the session was launched with — or
|
||||
**60 Hz** if the launch flag went missing. Games that pace themselves to the display will hold
|
||||
themselves there, even though the stream is running at your client's full rate (the client's own
|
||||
fps counter keeps reading correctly, because the encoder repeats held frames — so the counter is
|
||||
not the thing to trust here; an in-game fps readout is). `punktfunk-gamescope` publishes the real
|
||||
mode and rate, and `PUNKTFUNK_GAMESCOPE_REFRESH_RATES=60,90,120` puts more than one entry in that
|
||||
menu. If the host log says *"the session did not start at the mode we asked for"*, a file in
|
||||
`/etc/gamescope-session-plus/sessions.d/` is overriding `GAMESCOPE_BIN` or setting `GAMESCOPECMD`.
|
||||
- **The performance overlay (fps / frametime / stats) needs the patched build.** It is mangoapp,
|
||||
which gamescope draws as an *external overlay* — a layer upstream's capture composite has never
|
||||
included on any version, so on a stock gamescope you can turn the overlay on and it simply will
|
||||
not appear in the stream. There is no host-side substitute: the host cannot reconstruct another
|
||||
process's overlay window. `punktfunk-gamescope` paints it into the capture stream.
|
||||
- **The cursor comes from the compositor when it can, and from the host otherwise.** A stock
|
||||
gamescope leaves the pointer out of its captured image, so the host reads it separately and draws
|
||||
it into every frame — a full pass over the picture, and the fastest encode source cannot blend at
|
||||
|
||||
Executable
+113
@@ -0,0 +1,113 @@
|
||||
#!/usr/bin/env bash
|
||||
# Package an already-built punktfunk-gamescope binary as a .deb, for the Gitea apt registry.
|
||||
#
|
||||
# Counterpart to ../gamescope/build-gamescope-rpm.sh, and the same argument: the binary is a
|
||||
# ~10-minute meson build of an unrelated tree that CI does once and caches, so this repacks rather
|
||||
# than rebuilds. The Arch package (../gamescope/PKGBUILD) is the one recipe that builds from source,
|
||||
# because that is what makepkg is for.
|
||||
#
|
||||
# Installed as /usr/bin/punktfunk-gamescope — it does NOT replace the distro's gamescope, and does
|
||||
# not Provide/Conflict with it. Only the sessions punktfunk-host starts itself resolve this binary
|
||||
# (PUNKTFUNK_GAMESCOPE_BIN > punktfunk-gamescope > gamescope).
|
||||
#
|
||||
# Usage:
|
||||
# VERSION=3.16.25.pfhdr4~ci42.gdeadbee bash packaging/debian/build-gamescope-deb.sh \
|
||||
# --binary gs-cache/punktfunk-gamescope [--arch amd64]
|
||||
# Output: dist/punktfunk-gamescope_<version>_<arch>.deb
|
||||
set -euo pipefail
|
||||
|
||||
BINARY=""
|
||||
DEB_ARCH=""
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--binary) BINARY="${2:?--binary needs a path}"; shift 2 ;;
|
||||
--arch) DEB_ARCH="${2:?--arch needs a value}"; shift 2 ;;
|
||||
*) echo "unknown argument: $1" >&2; exit 2 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[ -n "$BINARY" ] || { echo "ERROR: --binary is required" >&2; exit 2; }
|
||||
[ -x "$BINARY" ] || { echo "ERROR: $BINARY is not an executable file" >&2; exit 1; }
|
||||
|
||||
PKG="punktfunk-gamescope"
|
||||
ROOTDIR="$(cd "$(dirname "$0")/../.." && pwd)"
|
||||
cd "$ROOTDIR"
|
||||
|
||||
DEB_ARCH="${DEB_ARCH:-$(dpkg --print-architecture)}"
|
||||
|
||||
# The marker is the host's whole capability probe: a binary that lost the patches installs fine and
|
||||
# then silently streams SDR, cursorless, at a 60 Hz-advertising session. Refuse to package it.
|
||||
BANNER="$("$BINARY" --version 2>&1 | head -1)"
|
||||
case "$BANNER" in
|
||||
*'+pfhdr'*) ;;
|
||||
*) echo "ERROR: $BINARY has no +pfhdr marker — it is not a punktfunk gamescope build" >&2
|
||||
echo " banner: $BANNER" >&2
|
||||
exit 1 ;;
|
||||
esac
|
||||
|
||||
# Derive the version from the binary when the caller did not pass one — it is the only source that
|
||||
# cannot drift from what is actually in the package.
|
||||
if [ -z "${VERSION:-}" ]; then
|
||||
UPSTREAM="$(printf '%s\n' "$BANNER" | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' | head -1)"
|
||||
PFHDR="$(printf '%s\n' "$BANNER" | grep -o '+pfhdr[0-9]\+' | head -1 | tr -d '+')"
|
||||
[ -n "$UPSTREAM" ] || { echo "ERROR: no X.Y.Z version in banner: $BANNER" >&2; exit 1; }
|
||||
VERSION="${UPSTREAM}.${PFHDR}"
|
||||
fi
|
||||
|
||||
STAGE="$(mktemp -d)"
|
||||
trap 'rm -rf "$STAGE"' EXIT
|
||||
# mktemp gives 0700; the package root has to be world-readable or `dpkg-deb -c` shows the tree as
|
||||
# root-only and some tooling refuses it.
|
||||
chmod 0755 "$STAGE"
|
||||
install -Dm0755 "$BINARY" "$STAGE/usr/bin/punktfunk-gamescope"
|
||||
mkdir -p "$STAGE/DEBIAN"
|
||||
|
||||
# Shared-library dependencies straight from the binary's own ELF NEEDED entries. That is what makes
|
||||
# the package honest about the Ubuntu release it was compiled on: gamescope links a broad set
|
||||
# (wlroots, SDL, libliftoff, vulkan, xwayland's libs), and hand-listing them would rot.
|
||||
DEPS=""
|
||||
if command -v dpkg-shlibdeps >/dev/null 2>&1; then
|
||||
# dpkg-shlibdeps insists on running from a package root with a debian/ dir.
|
||||
mkdir -p "$STAGE/debian"
|
||||
: > "$STAGE/debian/control"
|
||||
( cd "$STAGE" && dpkg-shlibdeps -O --ignore-missing-info usr/bin/punktfunk-gamescope 2>/dev/null ) \
|
||||
> "$STAGE/.shlibdeps" || true
|
||||
DEPS="$(sed -n 's/^shlibs:Depends=//p' "$STAGE/.shlibdeps" | head -1)"
|
||||
rm -rf "$STAGE/debian" "$STAGE/.shlibdeps"
|
||||
fi
|
||||
[ -n "$DEPS" ] || echo "WARNING: dpkg-shlibdeps produced no Depends — packaging without them" >&2
|
||||
|
||||
{
|
||||
echo "Package: $PKG"
|
||||
echo "Version: $VERSION"
|
||||
echo "Architecture: $DEB_ARCH"
|
||||
echo "Maintainer: unom <packages@unom.io>"
|
||||
echo "Section: utils"
|
||||
echo "Priority: optional"
|
||||
[ -n "$DEPS" ] && echo "Depends: $DEPS"
|
||||
# Not a hard dependency in either direction: the host works without this binary (SDR,
|
||||
# host-composited cursor), and someone may want the binary for their own capture consumer.
|
||||
echo "Recommends: punktfunk-host"
|
||||
echo "Homepage: https://git.unom.io/unom/punktfunk"
|
||||
echo "Description: gamescope with punktfunk's PipeWire capture patches"
|
||||
echo " gamescope built from the upstream revision punktfunk pins, plus the patches in"
|
||||
echo " packaging/gamescope/patches:"
|
||||
echo " ."
|
||||
echo " * 10-bit BT.2020/PQ capture formats, so an HDR game reaches a capture consumer as HDR"
|
||||
echo " instead of pre-tonemapped SDR."
|
||||
echo " * --pipewire-composite-cursor: the pointer is painted into the capture stream, so a"
|
||||
echo " consumer with no cursor of its own gets one and the host stops blending one in."
|
||||
echo " * A headless session advertises its real mode and refresh rates (and"
|
||||
echo " --custom-refresh-rates), so Steam and games see the resolution and refresh the stream"
|
||||
echo " actually runs at instead of an unnamed 60 Hz panel."
|
||||
echo " * --pipewire-composite-external-overlay: the mangoapp performance overlay is painted"
|
||||
echo " into the capture stream, so the fps/stats readout is visible remotely."
|
||||
echo " ."
|
||||
echo " Installed as /usr/bin/punktfunk-gamescope; your system gamescope is untouched."
|
||||
} > "$STAGE/DEBIAN/control"
|
||||
|
||||
mkdir -p dist
|
||||
OUT="dist/${PKG}_${VERSION}_${DEB_ARCH}.deb"
|
||||
dpkg-deb --build --root-owner-group "$STAGE" "$OUT"
|
||||
echo "==> wrote $OUT"
|
||||
echo " banner: $BANNER"
|
||||
Executable
+78
@@ -0,0 +1,78 @@
|
||||
#!/usr/bin/env bash
|
||||
# Package an already-built punktfunk-gamescope binary as an RPM, for the Gitea RPM registry.
|
||||
#
|
||||
# WHY this exists: before it, the only ways to get punktfunk-gamescope were the Bazzite/Atomic
|
||||
# sysext, the Arch package, the SteamOS installer, a NixOS option — or building gamescope from
|
||||
# source yourself. A traditional Fedora-family box (Nobara, plain Fedora, Nobara-derived HTPCs)
|
||||
# had no packaged route at all, which is how a field report ended up on a stock gamescope streaming
|
||||
# a session that told every game the display was 60 Hz.
|
||||
#
|
||||
# The binary is NOT built here; CI builds it once per Fedora major and caches it
|
||||
# (.gitea/workflows/rpm.yml). See punktfunk-gamescope.spec's header for why repacking beats
|
||||
# rebuilding.
|
||||
#
|
||||
# Usage:
|
||||
# bash packaging/gamescope/build-gamescope-rpm.sh \
|
||||
# --binary gs-cache/punktfunk-gamescope \
|
||||
# [--version 3.16.25] [--release 1] [--outdir dist]
|
||||
#
|
||||
# Output: <outdir>/punktfunk-gamescope-<version>-<release>.<arch>.rpm
|
||||
set -euo pipefail
|
||||
|
||||
BINARY=""
|
||||
# Default the version to the upstream gamescope the pinned revision describes as, suffixed with the
|
||||
# patch-set revision — same shape as the Arch package's `pkgver`, so the two channels read alike.
|
||||
VERSION=""
|
||||
RELEASE="1"
|
||||
OUTDIR="dist"
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--binary) BINARY="${2:?--binary needs a path}"; shift 2 ;;
|
||||
--version) VERSION="${2:?--version needs a value}"; shift 2 ;;
|
||||
--release) RELEASE="${2:?--release needs a value}"; shift 2 ;;
|
||||
--outdir) OUTDIR="${2:?--outdir needs a value}"; shift 2 ;;
|
||||
*) echo "unknown argument: $1" >&2; exit 2 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[ -n "$BINARY" ] || { echo "ERROR: --binary is required" >&2; exit 2; }
|
||||
[ -x "$BINARY" ] || { echo "ERROR: $BINARY is not an executable file" >&2; exit 1; }
|
||||
|
||||
ROOTDIR="$(cd "$(dirname "$0")/../.." && pwd)"
|
||||
cd "$ROOTDIR"
|
||||
|
||||
# Derive the version from the binary itself when not told: it is the only source that cannot drift
|
||||
# from what is actually being packaged. `gamescope version 3.16.25-1-g8c676c3+pfhdr4 (gcc …)` →
|
||||
# `3.16.25` + the marker. RPM versions may not contain `-`, hence the trailing `.pfhdrN` form.
|
||||
BANNER="$("$BINARY" --version 2>&1 | head -1)"
|
||||
case "$BANNER" in
|
||||
*'+pfhdr'*) ;;
|
||||
*) echo "ERROR: $BINARY has no +pfhdr marker — it is not a punktfunk gamescope build" >&2
|
||||
echo " banner: $BANNER" >&2
|
||||
exit 1 ;;
|
||||
esac
|
||||
PFHDR="$(printf '%s\n' "$BANNER" | grep -o '+pfhdr[0-9]\+' | head -1 | tr -d '+')"
|
||||
if [ -z "$VERSION" ]; then
|
||||
UPSTREAM="$(printf '%s\n' "$BANNER" | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' | head -1)"
|
||||
[ -n "$UPSTREAM" ] || { echo "ERROR: no X.Y.Z version in banner: $BANNER" >&2; exit 1; }
|
||||
VERSION="${UPSTREAM}.${PFHDR}"
|
||||
fi
|
||||
|
||||
echo "==> packaging $BINARY as punktfunk-gamescope-${VERSION}-${RELEASE}"
|
||||
echo " banner: $BANNER"
|
||||
|
||||
TOP="$(mktemp -d)"
|
||||
trap 'rm -rf "$TOP"' EXIT
|
||||
mkdir -p "$TOP"/{SOURCES,SPECS,BUILD,BUILDROOT,RPMS,SRPMS}
|
||||
install -m0755 "$BINARY" "$TOP/SOURCES/punktfunk-gamescope"
|
||||
|
||||
mkdir -p "$OUTDIR"
|
||||
rpmbuild \
|
||||
--define "_topdir $TOP" \
|
||||
--define "pf_version $VERSION" \
|
||||
--define "pf_release $RELEASE" \
|
||||
-bb packaging/gamescope/punktfunk-gamescope.spec
|
||||
|
||||
find "$TOP/RPMS" -name '*.rpm' -exec cp -v {} "$OUTDIR/" \;
|
||||
echo "==> wrote $(find "$OUTDIR" -name 'punktfunk-gamescope-*.rpm' -newer "$TOP" -print -quit 2>/dev/null || echo "$OUTDIR"/punktfunk-gamescope-*.rpm)"
|
||||
@@ -0,0 +1,78 @@
|
||||
# punktfunk-gamescope — gamescope carrying punktfunk's capture patches, installed under its own
|
||||
# name so it sits BESIDE the distro's gamescope (Game Mode keeps using that one).
|
||||
#
|
||||
# This spec REPACKS a binary that was already built, rather than building gamescope itself: the
|
||||
# build is a ~10-minute meson compile of an unrelated tree that CI already does once per Fedora
|
||||
# major and caches (.gitea/workflows/rpm.yml). Rebuilding it inside rpmbuild would double that for
|
||||
# no gain, and would need network access in the build root to fetch the upstream tree.
|
||||
#
|
||||
# The counterpart for Arch is packaging/gamescope/PKGBUILD, which DOES build from source, because
|
||||
# makepkg fetches sources by design and the AUR-style recipe is what an Arch user expects.
|
||||
#
|
||||
# Usage: bash packaging/gamescope/build-gamescope-rpm.sh --binary <path-to-punktfunk-gamescope>
|
||||
Name: punktfunk-gamescope
|
||||
Version: %{pf_version}
|
||||
Release: %{pf_release}%{?dist}
|
||||
Summary: gamescope with punktfunk's PipeWire capture patches (HDR, cursor, overlay, virtual-display modes)
|
||||
|
||||
# gamescope is BSD-2-Clause; our patches are contributed under the same terms.
|
||||
License: BSD-2-Clause
|
||||
URL: https://git.unom.io/unom/punktfunk
|
||||
Source0: punktfunk-gamescope
|
||||
|
||||
# Not `Provides: gamescope` and not `Conflicts:` either — this ships a differently-named binary and
|
||||
# is designed to coexist. A box's Game Mode session keeps running the distro's gamescope; only the
|
||||
# sessions punktfunk-host starts itself resolve this one (PUNKTFUNK_GAMESCOPE_BIN >
|
||||
# punktfunk-gamescope > gamescope).
|
||||
#
|
||||
# The runtime library Requires are auto-generated by rpmbuild from the binary's ELF NEEDED entries,
|
||||
# which is exactly right here: this binary is soname-coupled to the Fedora major it was compiled
|
||||
# on, and the generated Requires are what stop it installing on the wrong one.
|
||||
Recommends: punktfunk-host
|
||||
|
||||
# Nothing is compiled here, so there is no debuginfo to extract; without this rpmbuild fails
|
||||
# looking for sources it was never given.
|
||||
%global debug_package %{nil}
|
||||
|
||||
%description
|
||||
gamescope built from the upstream revision punktfunk pins, plus the patches in
|
||||
packaging/gamescope/patches:
|
||||
|
||||
* 10-bit BT.2020/PQ capture formats on the PipeWire node, so an HDR game reaches a capture
|
||||
consumer as HDR instead of pre-tonemapped SDR.
|
||||
* --pipewire-composite-cursor: paint the pointer into the capture stream, so a consumer with no
|
||||
cursor of its own gets one — and the host stops blending one in, which frees the encoder's
|
||||
fastest zero-copy source.
|
||||
* A headless session advertises its real mode and refresh rates (and --custom-refresh-rates), so
|
||||
Steam and games see the resolution and refresh the stream actually runs at instead of an
|
||||
unnamed 60 Hz panel.
|
||||
* --pipewire-composite-external-overlay: paint the mangoapp performance overlay into the capture
|
||||
stream, so the fps/stats readout is visible to someone watching remotely.
|
||||
|
||||
Installed as /usr/bin/punktfunk-gamescope. Your system gamescope is untouched.
|
||||
|
||||
%prep
|
||||
# Nothing to unpack: Source0 IS the binary.
|
||||
|
||||
%build
|
||||
# Nothing to build — see the header.
|
||||
|
||||
%install
|
||||
install -Dm0755 %{SOURCE0} %{buildroot}%{_bindir}/punktfunk-gamescope
|
||||
|
||||
%check
|
||||
# The marker is the host's entire capability probe (`gamescope_patch_level()`): a binary that lost
|
||||
# the patches would install fine and then silently stream SDR with no cursor. Refuse to package it.
|
||||
#
|
||||
# Executed in the build root, which is the same container the binary was compiled in — if that ever
|
||||
# stops being true this check is the thing that notices.
|
||||
%{buildroot}%{_bindir}/punktfunk-gamescope --version 2>&1 | grep -q '+pfhdr' || {
|
||||
echo "punktfunk-gamescope: the +pfhdr marker is missing — the patches did not take" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
%files
|
||||
%{_bindir}/punktfunk-gamescope
|
||||
|
||||
%changelog
|
||||
# Generated per build; see the git history for the patch set's own changes.
|
||||
Reference in New Issue
Block a user