Files
punktfunk/packaging/bazzite/host.env
T
enricobuehler ba16237c35
apple / swift (pull_request) Successful in 1m46s
apple / screenshots (pull_request) Skipped
android / android (pull_request) Successful in 8m43s
ci / bun-nix (pull_request) Successful in 22s
ci / web (pull_request) Successful in 1m7s
ci / docs-site (pull_request) Successful in 3m13s
ci / rust-arm64 (pull_request) Successful in 3m18s
ci / rust (pull_request) Successful in 15m34s
fix(bazzite): the shipped template pinned ATTACH, so Game Mode mirrored the box's screen instead of giving the client its own display
Field report: "on Bazzite when using gaming mode it is mirroring the main display
instead of giving the client its own." It is our own template that does it.

`packaging/bazzite/host.env` set `PUNKTFUNK_GAMESCOPE_ATTACH=1`, and every install
path — rpm, deb, Arch, nix — ships that file as `/usr/share/punktfunk/host.env.bazzite`
with the docs telling people to copy it verbatim. So the recommended Bazzite setup
turned the attach override ON for everyone.

That override is rung 2 of `pick_gamescope_mode`, ABOVE `dedicated_launch` at rung 3.
The rung comment calls the operator overrides a debug/CI escape hatch, which is right —
but we were shipping one as a distro default, so on a Bazzite box the managed takeover
and the dedicated game session were both unreachable. A game launched from a client's
library could not get a session of its own either, which is the case the dedicated
route exists for. With a physical display connected, attach then takes the
`physical_display_connected()` arm and streams the box's own head at the box's own
mode: the mirror the reporter saw.

The template now forces nothing and lets the per-connect detection answer, which on a
box with `gamescope-session-plus` is MANAGED. Attach stays available, documented as the
opt-in it is, with the mirror and the dedicated-session cost stated. Because managed
depends on the `punktfunk` group to stop the display manager, the template now says so
where someone choosing a model will read it, rather than only in the distro guide.

Also fixes the off-switch. Both overrides were read with `var_os(..).is_some()`, so
`PUNKTFUNK_GAMESCOPE_ATTACH=0` meant ATTACH ON — the opposite of what the line says,
and of every other knob on this host. They now use the shared `env_on` grammar, so
`0|false|off|no` disable and a bare `=1` keeps working. Anyone who "turned attach off"
in an older host.env had it on the whole time.

Note an upgrade never rewrites an existing `~/.config/punktfunk/host.env`, so boxes set
up from an older template keep the pin until the line is deleted by hand; the Bazzite
and HDR pages now say that.

Verified: `scripts/xcheck.sh linux` check + clippy `-D warnings` clean, pf-vdisplay
206/0 under rust:1.96, `cargo fmt --all --check` clean. Gate proved non-vacuous against
a planted `compile_error!` in routing.rs.
2026-08-13 09:45:52 +02:00

67 lines
4.0 KiB
Bash

# punktfunk host config for Bazzite (~/.config/punktfunk/host.env).
#
# The compositor + input backend are AUTO-DETECTED per connect from the ACTIVE session: the host
# follows the box as you flip between Steam Gaming Mode (gamescope — a managed session at the
# CLIENT's resolution) and a KDE/GNOME Desktop (KWin/Mutter virtual output at the client's mode).
# So nothing here forces a backend, and no session anchors are needed: a `systemctl --user`
# service inherits the correct XDG_RUNTIME_DIR and the host derives the bus from it. (Keys are
# CASE-SENSITIVE — use the exact uppercase names.)
PUNKTFUNK_VIDEO_SOURCE=virtual
# GPU zero-copy capture (dmabuf -> CUDA -> NVENC) is ON by default and auto-falls back to CPU if
# unavailable. No need to set it. Set to 0 only to force the CPU path.
# PUNKTFUNK_ZEROCOPY=0
#RUST_LOG=info
# --- Optional overrides (default is active-session auto-detection) ---
# Force a specific backend for testing (skips auto-detect + env retargeting):
# PUNKTFUNK_COMPOSITOR=kwin|mutter|wlroots|gamescope
# PUNKTFUNK_INPUT_BACKEND=libei|wlr|gamescope|uinput
#
# GAME MODE: nothing here forces a model — the host picks one per connect. On this box (Bazzite
# ships gamescope-session-plus) that is the MANAGED model: on connect the host takes the box's
# gaming session over and relaunches it headless at the CLIENT's exact resolution, then restores
# the box's own session on a debounced idle. That is what gives the client a display of its OWN
# instead of a copy of the TV, and it is also what lets a game launched from a client's library get
# a dedicated session to itself.
#
# ⚠ The managed takeover has to stop the display manager for the length of the stream, and that is
# privileged: it works for members of the `punktfunk` group and nobody else. Join it once —
# `sudo usermod -aG punktfunk "$USER"`, then log out and back in. Skip it and the takeover cannot
# stop SDDM, which relogin-loops against it for the whole stream and can starve the game. The host
# checks at startup and says so in its log.
#
# Opt IN to the ATTACH model if you would rather the BOX keep ownership: the host captures whatever
# gamescope is live and never tears it down, so Desktop<->Game switching is rock-solid and the box
# stays in its current mode when you disconnect. The cost is that a box driving a physical display
# streams at the BOX's own mode, MIRRORED — the client does not get its own display — and this
# override outranks a dedicated game session too. Remove the line to go back to auto (`=0` also
# turns it off; any other value is on):
# PUNKTFUNK_GAMESCOPE_ATTACH=1
#
# Force the MANAGED model on a box where the auto-detection finds no session infrastructure:
# PUNKTFUNK_GAMESCOPE_MANAGED=1
#
# Follow a Gaming<->Desktop switch MID-STREAM (rebuild the backend in place, no reconnect). This is
# ON BY DEFAULT on Bazzite/SteamOS (the host detects the platform); set =0 to disable it:
# PUNKTFUNK_SESSION_WATCH=0
#
# HDR (10-bit BT.2020 PQ) on the gamescope path. Needs `punktfunk-gamescope` — gamescope plus the
# patch that teaches its capture node the 10-bit formats — which the sysext ships alongside the
# host; it does NOT replace the system gamescope. ON by default when that binary is present; a
# host without it stays SDR either way. `punktfunk-host hdr-probe` says what it found. To force
# SDR on the gamescope backend:
# PUNKTFUNK_GAMESCOPE_HDR=0
#
# On an HDR session, how bright SDR content (desktop, Steam overlay, SDR games) is inside the PQ
# container. gamescope's default is 400 nits; raise it if whites look dim on your TV.
# PUNKTFUNK_GAMESCOPE_SDR_NITS=400
#
# HEADLESS GAME MODE: on a box with no display attached, Bazzite's "Switch to Game Mode" normally
# crashes (gamescope's DRM backend has no panel to drive). The host package ships
# /etc/gamescope-session-plus/sessions.d/steam, which auto-falls-back to gamescope's HEADLESS backend
# when no display is connected — so game mode boots offscreen and streams, with no config here. It's a
# no-op on display-attached boxes. (The host then auto-detects Gaming and streams it.)