4543a3f529
The client now advertises VIDEO_CAP_10BIT|HDR and carries the result all the way to glass: - csc_rows is bit-depth exact (10-bit limited code points differ from 8-bit by ~half a code) and folds in the P010/X6 MSB-packing factor; new 10-bit white/black tests. - The CSC shader grows a params block: mode 0 passes the transfer through (SDR as-is, or PQ onto an HDR10 swapchain); mode 1 tonemaps PQ→SDR in-shader (ST.2084 EOTF, 203-nit reference white exposure, BT.2020→709, soft maxRGB rolloff, sRGB encode) for desktops without an HDR surface. PUNKTFUNK_TONEMAP_PEAK tunes the rolloff. - The presenter probes VK_EXT_swapchain_colorspace + an HDR10/ST.2084 10-bit surface format and flips modes in-band with the stream's PQ signaling: fence-quiesce, then CSC pass + video image (10-bit A2B10G10R10 intermediate — PQ in 8 bits bands) + overlay pipe + swapchain rebuild through the deferred-destroy rules. - P010 decodes through all three paths: Vulkan Video (X6 multiplanar pool, R10X6 plane views), VAAPI dmabuf (R16/RG1616 plane imports), software (swscale as before). - session pump advertises the caps; the host still gates Main10 behind its PUNKTFUNK_10BIT policy. Probed on glass hardware: the KDE/NVIDIA surface exposes A2B10G10R10+HDR10_ST2084, so true PQ passthrough is available there. Known v1 gaps: software-decode PQ shows untonemapped (8-bit RGBA carries the transfer baked); the SDR overlay composites unscaled onto an HDR10 surface (dim OSD); no vkSetHdrMetadataEXT yet. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
92 lines
4.1 KiB
Markdown
92 lines
4.1 KiB
Markdown
---
|
|
title: Hyprland
|
|
description: Configure a punktfunk host on a Hyprland session — headless output via hyprctl, capture via xdg-desktop-portal-hyprland.
|
|
---
|
|
|
|
Hyprland is a **first-class backend.** The host adds a per-client headless output at the client's
|
|
exact mode with `hyprctl`, captures it through the **xdg-desktop-portal-hyprland (xdph)** ScreenCast
|
|
portal (zero-copy dmabuf), and injects input via the wlroots virtual pointer/keyboard protocols —
|
|
which Hyprland still implements even after dropping wlroots in v0.42.
|
|
|
|
This is a distinct backend from [Sway / wlroots](/docs/sway): Hyprland has its own IPC (`hyprctl`)
|
|
and its own portal (xdph), so it is auto-detected and driven separately.
|
|
|
|
This page assumes the package is already installed — see [Arch](/docs/arch), [Ubuntu](/docs/ubuntu),
|
|
or [Fedora](/docs/fedora).
|
|
|
|
> New here? Read [Security & Safe Use](/docs/security) first — a streaming host is remote control of
|
|
> the machine, so keep it on a trusted LAN or VPN and require pairing.
|
|
|
|
## host.env
|
|
|
|
The host auto-detects a Hyprland session, so you usually need nothing here. To force the backend, set
|
|
these in `~/.config/punktfunk/host.env`:
|
|
|
|
```ini
|
|
PUNKTFUNK_COMPOSITOR=hyprland
|
|
PUNKTFUNK_INPUT_BACKEND=wlr
|
|
PUNKTFUNK_VIDEO_SOURCE=virtual
|
|
# 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.
|
|
|
|
## How it works
|
|
|
|
- **Video** — the host runs `hyprctl output create headless PF-1` and applies a monitor rule for the
|
|
client's exact mode. Outputs are **named**, so there's no before/after diffing. The rule uses
|
|
`hyprctl keyword monitor …` (the hyprlang config manager — the default on every release, 0.55
|
|
included) and falls back to the Lua `hyprctl eval 'hl.monitor{…}'` only if you've opted into the
|
|
Lua config manager. The host confirms the output actually adopted the mode before streaming.
|
|
- **Capture** — it captures that output through the **xdg-desktop-portal-hyprland (xdph)** ScreenCast
|
|
portal. To pick the output without a GUI on a headless host, the host writes a managed
|
|
`~/.config/hypr/xdph.conf` pointing xdph's `custom_picker_binary` at a small shim that selects the
|
|
new output automatically — no interactive picker dialog to answer.
|
|
- **Input** — mouse and keyboard are injected via the wlroots **virtual pointer** and **virtual
|
|
keyboard** protocols (Hyprland kept them). Gamepads and audio are compositor-independent.
|
|
|
|
For how long the virtual output lives, and extend-vs-exclusive topology, see
|
|
[Virtual displays](/docs/virtual-displays).
|
|
|
|
## Requirements
|
|
|
|
- A running Hyprland session (any recent release; validate on both a ≤ 0.54 and a ≥ 0.55 install).
|
|
- **xdg-desktop-portal-hyprland (xdph)** installed and running — the host captures through its
|
|
ScreenCast portal, and steers its custom picker. Without it there is no video.
|
|
- The ScreenCast interface routed to xdph — see `scripts/headless/portals.conf` (a `[Hyprland]`
|
|
section pins `org.freedesktop.impl.portal.ScreenCast=hyprland`).
|
|
|
|
## Permission system
|
|
|
|
Hyprland's permission system (`ecosystem.enforce_permissions`, 0.49+, **off by default**) can deny
|
|
direct screencopy and virtual-input clients — and denial is **silent**: capture goes to *black
|
|
frames* and input is *dropped*, with no error. If you've enabled it, grant the host explicitly in
|
|
your Hyprland config:
|
|
|
|
```ini
|
|
ecosystem {
|
|
enforce_permissions = true
|
|
}
|
|
|
|
permission = /usr/bin/punktfunk-host, screencopy, allow
|
|
permission = /usr/bin/punktfunk-host, virtual-pointer, allow
|
|
permission = /usr/bin/punktfunk-host, virtual-keyboard, allow
|
|
```
|
|
|
|
The host logs a warning at startup when it detects enforcement is on. (Adjust the binary path to
|
|
where your package installed `punktfunk-host`.)
|
|
|
|
## Start the host
|
|
|
|
With the backend selected, start the host from **inside your Hyprland session**:
|
|
|
|
```sh
|
|
systemctl --user enable --now punktfunk-host
|
|
journalctl --user -u punktfunk-host -f
|
|
```
|
|
|
|
## Bring up the console and pair
|
|
|
|
Enable the web console, read its login password, and arm PIN pairing — see
|
|
[The Web Console](/docs/web-console). Then [connect a client](/docs/clients).
|