feat(host): enable GPU zero-copy by default on all backends
apple / swift (push) Failing after 45s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 1m15s
android / android (push) Successful in 4m56s
windows-host / package (push) Failing after 3m31s
windows-msix / package (x64, C:\Users\Public\ffmpeg, x86_64-pc-windows-msvc, C:\t) (push) Has been cancelled
windows / build (aarch64-pc-windows-msvc) (push) Has been cancelled
windows / build (x86_64-pc-windows-msvc) (push) Has been cancelled
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
arch / build-publish (push) Successful in 5m39s
release / apple (push) Has been cancelled
flatpak / build-publish (push) Has been cancelled
apple / screenshots (push) Has been skipped
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Has been cancelled
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Has been cancelled
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Has been cancelled
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Has been cancelled
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Has been cancelled
docker / deploy-docs (push) Has been cancelled
decky / build-publish (push) Has been cancelled
ci / web (push) Successful in 1m3s
ci / docs-site (push) Successful in 1m23s
ci / rust (push) Successful in 4m46s
ci / bench (push) Successful in 4m57s
deb / build-publish (push) Successful in 4m22s
apple / swift (push) Failing after 45s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 1m15s
android / android (push) Successful in 4m56s
windows-host / package (push) Failing after 3m31s
windows-msix / package (x64, C:\Users\Public\ffmpeg, x86_64-pc-windows-msvc, C:\t) (push) Has been cancelled
windows / build (aarch64-pc-windows-msvc) (push) Has been cancelled
windows / build (x86_64-pc-windows-msvc) (push) Has been cancelled
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
arch / build-publish (push) Successful in 5m39s
release / apple (push) Has been cancelled
flatpak / build-publish (push) Has been cancelled
apple / screenshots (push) Has been skipped
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Has been cancelled
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Has been cancelled
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Has been cancelled
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Has been cancelled
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Has been cancelled
docker / deploy-docs (push) Has been cancelled
decky / build-publish (push) Has been cancelled
ci / web (push) Successful in 1m3s
ci / docs-site (push) Successful in 1m23s
ci / rust (push) Successful in 4m46s
ci / bench (push) Successful in 4m57s
deb / build-publish (push) Successful in 4m22s
Now that the per-capture worker subprocess makes an NVENC EGL/CUDA driver fault survivable (design/zerocopy-worker-isolation.md), the reason the NVENC zero-copy path stayed opt-in is gone. zerocopy::enabled() now defaults ON for both GPU backends (was ON VAAPI / OFF NVENC). Fallbacks are intact: VAAPI's one-shot CPU auto-downgrade (VAAPI-gated, never trips for NVENC) and NVENC's per-capture fallback + worker-death latch. Reframe the shipped host.env examples and setup guides to rely on the default rather than force PUNKTFUNK_ZEROCOPY=1 (an explicit =1 skips the VAAPI auto-downgrade). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -51,18 +51,21 @@ pub fn vaapi_dmabuf_forced() -> bool {
|
|||||||
flag_opt("PUNKTFUNK_ZEROCOPY") == Some(true)
|
flag_opt("PUNKTFUNK_ZEROCOPY") == Some(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether the zero-copy path is on. `PUNKTFUNK_ZEROCOPY` decides when set (truthy = on, else
|
/// Whether the zero-copy path is on. `PUNKTFUNK_ZEROCOPY` decides when set (truthy = on, else off).
|
||||||
/// off). Unset defaults **on for the VAAPI (AMD/Intel) backend** — the stock AMD/Intel install
|
/// **Unset defaults ON for both GPU backends** — the stock install gets the GPU dmabuf path, not
|
||||||
/// gets the GPU dmabuf path, not three full-frame CPU touches — unless a failed negotiation
|
/// three full-frame CPU touches. This includes NVENC (previously opt-in): the EGL→CUDA (tiled) and
|
||||||
/// downgraded it ([`note_vaapi_dmabuf_failed`]); and **off for NVENC**, whose EGL→CUDA import
|
/// Vulkan (LINEAR) imports now run in a per-capture worker subprocess
|
||||||
/// stays opt-in (Mutter+NVIDIA has known dmabuf-capture races; see `PUNKTFUNK_FORCE_SHM`).
|
/// (`design/zerocopy-worker-isolation.md`), so a driver fault on a producer-invalidated dmabuf kills
|
||||||
|
/// the worker and the host degrades to its capture-loss rebuild instead of dying — the reason the
|
||||||
|
/// NVENC path stayed opt-in is gone. Fallbacks stay in place: VAAPI has a one-shot CPU downgrade if
|
||||||
|
/// the LINEAR-dmabuf offer never negotiates ([`note_vaapi_dmabuf_failed`]); NVENC falls back per
|
||||||
|
/// capture when no importer/importable modifier is available and latches the import off after
|
||||||
|
/// repeated worker deaths. `PUNKTFUNK_ZEROCOPY=0` opts out; `PUNKTFUNK_FORCE_SHM` forces the
|
||||||
|
/// race-free SHM path.
|
||||||
pub fn enabled() -> bool {
|
pub fn enabled() -> bool {
|
||||||
match flag_opt("PUNKTFUNK_ZEROCOPY") {
|
match flag_opt("PUNKTFUNK_ZEROCOPY") {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
None => {
|
None => !VAAPI_DMABUF_FAILED.load(Ordering::Relaxed),
|
||||||
crate::encode::linux_zero_copy_is_vaapi()
|
|
||||||
&& !VAAPI_DMABUF_FAILED.load(Ordering::Relaxed)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -85,13 +85,13 @@ cp /usr/share/punktfunk/host.env.bazzite ~/.config/punktfunk/host.env
|
|||||||
|
|
||||||
The template is deliberately minimal — it does **not** force a compositor, because the host
|
The template is deliberately minimal — it does **not** force a compositor, because the host
|
||||||
auto-detects Gaming Mode (gamescope) vs Desktop (KWin) on every connect and follows the switch
|
auto-detects Gaming Mode (gamescope) vs Desktop (KWin) on every connect and follows the switch
|
||||||
mid-stream. The only settings that matter are the session anchors plus zero-copy:
|
mid-stream. The only settings that matter are the session anchors (GPU zero-copy is on by default):
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
XDG_RUNTIME_DIR=/run/user/1000
|
XDG_RUNTIME_DIR=/run/user/1000
|
||||||
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
|
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
|
||||||
PUNKTFUNK_VIDEO_SOURCE=virtual
|
PUNKTFUNK_VIDEO_SOURCE=virtual
|
||||||
PUNKTFUNK_ZEROCOPY=1 # GPU zero-copy (dmabuf → CUDA → NVENC); auto-falls back to CPU
|
# GPU zero-copy (dmabuf → CUDA → NVENC) is ON by default; auto-falls back to CPU. Set =0 to force CPU.
|
||||||
PUNKTFUNK_GAMESCOPE_ATTACH=1 # Gaming Mode = attach to the box's own session (see below)
|
PUNKTFUNK_GAMESCOPE_ATTACH=1 # Gaming Mode = attach to the box's own session (see below)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ On Linux the host **rewrites `WAYLAND_DISPLAY` / `XDG_CURRENT_DESKTOP` / `XDG_RU
|
|||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `PUNKTFUNK_COMPOSITOR` | `kwin` · `mutter` · `gamescope` · `wlroots` (aliases: `kde`/`plasma`, `gnome`, `sway`/`hyprland`) | Which backend creates the virtual display. **Leave unset to auto-detect;** set only to force one. |
|
| `PUNKTFUNK_COMPOSITOR` | `kwin` · `mutter` · `gamescope` · `wlroots` (aliases: `kde`/`plasma`, `gnome`, `sway`/`hyprland`) | Which backend creates the virtual display. **Leave unset to auto-detect;** set only to force one. |
|
||||||
| `PUNKTFUNK_VIDEO_SOURCE` | `virtual` · `portal` | `virtual` creates a per-client display at the client's exact mode (the normal choice). `portal` captures an existing monitor instead. |
|
| `PUNKTFUNK_VIDEO_SOURCE` | `virtual` · `portal` | `virtual` creates a per-client display at the client's exact mode (the normal choice). `portal` captures an existing monitor instead. |
|
||||||
| `PUNKTFUNK_ZEROCOPY` | `1` · `0` | GPU zero-copy capture→encode (dmabuf → CUDA → NVENC, or D3D11 on Windows). Leave on; it falls back to a CPU path automatically. |
|
| `PUNKTFUNK_ZEROCOPY` | `1` · `0` *(default on)* | GPU zero-copy capture→encode (dmabuf → CUDA → NVENC, or D3D11 on Windows). **On by default** — no need to set it; it falls back to a CPU path automatically. Set `0` to force the CPU path. |
|
||||||
| `PUNKTFUNK_INPUT_BACKEND` | `libei` · `gamescope` · `wlr` · `uinput` | How input is injected. `libei` for GNOME/KDE, `gamescope` for Bazzite/gamescope, `wlr` for Sway/wlroots. Auto-detected with the compositor. |
|
| `PUNKTFUNK_INPUT_BACKEND` | `libei` · `gamescope` · `wlr` · `uinput` | How input is injected. `libei` for GNOME/KDE, `gamescope` for Bazzite/gamescope, `wlr` for Sway/wlroots. Auto-detected with the compositor. |
|
||||||
| `PUNKTFUNK_ENCODER` | `auto` · `nvenc` · `vaapi` (Linux) · `amf` · `qsv` (Windows) · `software` | Encoder backend. `auto` (default) detects the GPU vendor: NVIDIA→NVENC, AMD→VAAPI/AMF, Intel→VAAPI/QSV. `software` (aliases `sw`/`openh264`) is the GPU-less H.264 path on both platforms — on Windows `auto` falls back to it when no GPU is found; on Linux it is **explicit-only** (`auto` never picks it). |
|
| `PUNKTFUNK_ENCODER` | `auto` · `nvenc` · `vaapi` (Linux) · `amf` · `qsv` (Windows) · `software` | Encoder backend. `auto` (default) detects the GPU vendor: NVIDIA→NVENC, AMD→VAAPI/AMF, Intel→VAAPI/QSV. `software` (aliases `sw`/`openh264`) is the GPU-less H.264 path on both platforms — on Windows `auto` falls back to it when no GPU is found; on Linux it is **explicit-only** (`auto` never picks it). |
|
||||||
| `PUNKTFUNK_RENDER_NODE` | path | Linux DRM render node for zero-copy (default `/dev/dri/renderD128`). Set on multi-GPU boxes to pick the right GPU. |
|
| `PUNKTFUNK_RENDER_NODE` | path | Linux DRM render node for zero-copy (default `/dev/dri/renderD128`). Set on multi-GPU boxes to pick the right GPU. |
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ WAYLAND_DISPLAY=wayland-0
|
|||||||
XDG_CURRENT_DESKTOP=GNOME
|
XDG_CURRENT_DESKTOP=GNOME
|
||||||
PUNKTFUNK_COMPOSITOR=mutter
|
PUNKTFUNK_COMPOSITOR=mutter
|
||||||
PUNKTFUNK_VIDEO_SOURCE=virtual
|
PUNKTFUNK_VIDEO_SOURCE=virtual
|
||||||
PUNKTFUNK_ZEROCOPY=1
|
# GPU zero-copy (dmabuf → CUDA → NVENC) is ON by default; auto-falls back to CPU. Set =0 to force CPU.
|
||||||
PUNKTFUNK_INPUT_BACKEND=libei
|
PUNKTFUNK_INPUT_BACKEND=libei
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ WAYLAND_DISPLAY=wayland-0
|
|||||||
XDG_CURRENT_DESKTOP=KDE
|
XDG_CURRENT_DESKTOP=KDE
|
||||||
PUNKTFUNK_COMPOSITOR=kwin
|
PUNKTFUNK_COMPOSITOR=kwin
|
||||||
PUNKTFUNK_VIDEO_SOURCE=virtual
|
PUNKTFUNK_VIDEO_SOURCE=virtual
|
||||||
PUNKTFUNK_ZEROCOPY=1
|
# GPU zero-copy (dmabuf → CUDA → NVENC) is ON by default; auto-falls back to CPU. Set =0 to force CPU.
|
||||||
PUNKTFUNK_INPUT_BACKEND=libei
|
PUNKTFUNK_INPUT_BACKEND=libei
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ these in `~/.config/punktfunk/host.env`:
|
|||||||
PUNKTFUNK_COMPOSITOR=wlroots # aliases: sway, hyprland
|
PUNKTFUNK_COMPOSITOR=wlroots # aliases: sway, hyprland
|
||||||
PUNKTFUNK_INPUT_BACKEND=wlr
|
PUNKTFUNK_INPUT_BACKEND=wlr
|
||||||
PUNKTFUNK_VIDEO_SOURCE=virtual
|
PUNKTFUNK_VIDEO_SOURCE=virtual
|
||||||
PUNKTFUNK_ZEROCOPY=1 # GPU zero-copy capture→encode; auto-falls back to CPU
|
# GPU zero-copy capture→encode is ON by default; auto-falls back to CPU. Set PUNKTFUNK_ZEROCOPY=0 to force CPU.
|
||||||
```
|
```
|
||||||
|
|
||||||
See [Configuration](/docs/configuration) for the full reference.
|
See [Configuration](/docs/configuration) for the full reference.
|
||||||
|
|||||||
@@ -242,8 +242,9 @@ PUNKTFUNK_GAMESCOPE_APP=steam -gamepadui
|
|||||||
# gamescope hosts its own EIS input socket — input lands in the nested session.
|
# gamescope hosts its own EIS input socket — input lands in the nested session.
|
||||||
PUNKTFUNK_INPUT_BACKEND=gamescope
|
PUNKTFUNK_INPUT_BACKEND=gamescope
|
||||||
|
|
||||||
# GPU zero-copy capture (dmabuf -> CUDA -> NVENC). Auto-falls back to CPU if unavailable.
|
# GPU zero-copy capture (dmabuf -> CUDA -> NVENC) is ON by default and auto-falls back to CPU if
|
||||||
PUNKTFUNK_ZEROCOPY=1
|
# unavailable. No need to set it. Set to 0 only to force the CPU path.
|
||||||
|
# PUNKTFUNK_ZEROCOPY=0
|
||||||
|
|
||||||
#RUST_LOG=info
|
#RUST_LOG=info
|
||||||
```
|
```
|
||||||
@@ -257,7 +258,7 @@ PUNKTFUNK_ZEROCOPY=1
|
|||||||
| `PUNKTFUNK_VIDEO_SOURCE` | `virtual` | Create a per-client virtual output at the client's exact WxH@Hz (the flagship "native resolution, no scaling" mode), vs. `portal` which captures an existing monitor. |
|
| `PUNKTFUNK_VIDEO_SOURCE` | `virtual` | Create a per-client virtual output at the client's exact WxH@Hz (the flagship "native resolution, no scaling" mode), vs. `portal` which captures an existing monitor. |
|
||||||
| `PUNKTFUNK_GAMESCOPE_APP` | `steam -gamepadui` | The command launched **inside** the nested gamescope — here, a SteamOS-style couch UI. Set it to whatever you want the session to run. |
|
| `PUNKTFUNK_GAMESCOPE_APP` | `steam -gamepadui` | The command launched **inside** the nested gamescope — here, a SteamOS-style couch UI. Set it to whatever you want the session to run. |
|
||||||
| `PUNKTFUNK_INPUT_BACKEND` | `gamescope` | Inject mouse/keyboard/gamepad into the nested gamescope via its own EIS socket. |
|
| `PUNKTFUNK_INPUT_BACKEND` | `gamescope` | Inject mouse/keyboard/gamepad into the nested gamescope via its own EIS socket. |
|
||||||
| `PUNKTFUNK_ZEROCOPY` | `1` | GPU zero-copy capture (dmabuf → CUDA → NVENC). Falls back to CPU automatically if unavailable. |
|
| `PUNKTFUNK_ZEROCOPY` | `on` *(default)* | GPU zero-copy capture (dmabuf → CUDA → NVENC), on by default. Falls back to CPU automatically if unavailable; set `0` to force the CPU path. |
|
||||||
| `RUST_LOG` | (commented) | Uncomment `RUST_LOG=info` for verbose logs while debugging. |
|
| `RUST_LOG` | (commented) | Uncomment `RUST_LOG=info` for verbose logs while debugging. |
|
||||||
|
|
||||||
**Optional — a real DualSense for clients holding one:** add `PUNKTFUNK_GAMEPAD=dualsense` to present
|
**Optional — a real DualSense for clients holding one:** add `PUNKTFUNK_GAMEPAD=dualsense` to present
|
||||||
@@ -463,8 +464,8 @@ desktop viewer.
|
|||||||
after an `rpm-ostree`/`bootc` update, confirm the NVIDIA driver still loads (`nvidia-smi`) before
|
after an `rpm-ostree`/`bootc` update, confirm the NVIDIA driver still loads (`nvidia-smi`) before
|
||||||
blaming punktfunk.
|
blaming punktfunk.
|
||||||
|
|
||||||
- **`PUNKTFUNK_ZEROCOPY=1` but it falls back to CPU.** The zero-copy path needs working EGL/CUDA from
|
- **Zero-copy falls back to CPU.** The zero-copy path (on by default) needs working EGL/CUDA from the
|
||||||
the NVIDIA driver. The code falls back to CPU automatically; check the log for the fallback line and
|
NVIDIA driver. The code falls back to CPU automatically; check the log for the fallback line and
|
||||||
verify the `-nvidia` image / driver is healthy.
|
verify the `-nvidia` image / driver is healthy.
|
||||||
|
|
||||||
- **Wrong UID in `host.env`.** `XDG_RUNTIME_DIR=/run/user/1000` and the bus path assume UID 1000. Run
|
- **Wrong UID in `host.env`.** `XDG_RUNTIME_DIR=/run/user/1000` and the bus path assume UID 1000. Run
|
||||||
|
|||||||
@@ -10,8 +10,9 @@ DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
|
|||||||
|
|
||||||
PUNKTFUNK_VIDEO_SOURCE=virtual
|
PUNKTFUNK_VIDEO_SOURCE=virtual
|
||||||
|
|
||||||
# GPU zero-copy capture (dmabuf -> CUDA -> NVENC). Auto-falls back to CPU if unavailable.
|
# GPU zero-copy capture (dmabuf -> CUDA -> NVENC) is ON by default and auto-falls back to CPU if
|
||||||
PUNKTFUNK_ZEROCOPY=1
|
# unavailable. No need to set it. Set to 0 only to force the CPU path.
|
||||||
|
# PUNKTFUNK_ZEROCOPY=0
|
||||||
|
|
||||||
#RUST_LOG=info
|
#RUST_LOG=info
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ WAYLAND_DISPLAY=wayland-kde
|
|||||||
XDG_CURRENT_DESKTOP=KDE
|
XDG_CURRENT_DESKTOP=KDE
|
||||||
PUNKTFUNK_COMPOSITOR=kwin
|
PUNKTFUNK_COMPOSITOR=kwin
|
||||||
PUNKTFUNK_VIDEO_SOURCE=virtual
|
PUNKTFUNK_VIDEO_SOURCE=virtual
|
||||||
PUNKTFUNK_ZEROCOPY=1
|
# GPU zero-copy (dmabuf → CUDA → NVENC) is ON by default; auto-falls back to CPU. Set =0 to force CPU.
|
||||||
PUNKTFUNK_INPUT_BACKEND=libei
|
PUNKTFUNK_INPUT_BACKEND=libei
|
||||||
# UDP Generic Segmentation Offload on the send path: coalesce a frame's equal-size packets into
|
# UDP Generic Segmentation Offload on the send path: coalesce a frame's equal-size packets into
|
||||||
# kernel super-buffers (one sendmsg per ~64 packets instead of one per packet) — the dominant
|
# kernel super-buffers (one sendmsg per ~64 packets instead of one per packet) — the dominant
|
||||||
|
|||||||
@@ -13,8 +13,8 @@
|
|||||||
# bash scripts/headless/run-headless-kde.sh [WxH] # default 1920x1080
|
# bash scripts/headless/run-headless-kde.sh [WxH] # default 1920x1080
|
||||||
#
|
#
|
||||||
# Then in another shell:
|
# Then in another shell:
|
||||||
# WAYLAND_DISPLAY=wayland-kde XDG_CURRENT_DESKTOP=KDE PUNKTFUNK_ZEROCOPY=1 \
|
# WAYLAND_DISPLAY=wayland-kde XDG_CURRENT_DESKTOP=KDE \
|
||||||
# punktfunk-host punktfunk1-host --source virtual --seconds 14400
|
# punktfunk-host punktfunk1-host --source virtual --seconds 14400 # zero-copy is on by default
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
RES="${1:-1920x1080}"
|
RES="${1:-1920x1080}"
|
||||||
|
|||||||
@@ -16,8 +16,9 @@ XDG_CURRENT_DESKTOP=KDE
|
|||||||
# resolution+refresh (the flagship mode); `portal` captures an existing monitor.
|
# resolution+refresh (the flagship mode); `portal` captures an existing monitor.
|
||||||
PUNKTFUNK_VIDEO_SOURCE=virtual
|
PUNKTFUNK_VIDEO_SOURCE=virtual
|
||||||
|
|
||||||
# GPU zero-copy capture (EGL/Vulkan → CUDA → NVENC). Falls back to CPU automatically.
|
# GPU zero-copy capture (dmabuf → CUDA → NVENC / VAAPI / Vulkan) is ON by default and falls back to
|
||||||
PUNKTFUNK_ZEROCOPY=1
|
# CPU automatically. No need to set it. Set to 0 only to force the CPU path.
|
||||||
|
# PUNKTFUNK_ZEROCOPY=0
|
||||||
|
|
||||||
# --- Bazzite / SteamOS-like host: host-managed Steam-Deck-UI session -----------------------
|
# --- Bazzite / SteamOS-like host: host-managed Steam-Deck-UI session -----------------------
|
||||||
# The host LAUNCHES gamescope-session-plus headless AT THE CLIENT'S mode (so games see the
|
# The host LAUNCHES gamescope-session-plus headless AT THE CLIENT'S mode (so games see the
|
||||||
|
|||||||
Reference in New Issue
Block a user