feat(vdisplay): Linux keep-alive pool — registry-owned display lifecycle (Stage 1b)

The ownership split (design/display-management.md §3): the registry owns the
per-session virtual-display lifecycle on Linux, so a display can outlive its
session (keep-alive) and be reused on reconnect.

- registry.rs: a Linux pool driven by the pure lifecycle machine. acquire()
  reuses a kept (lingering/pinned) display of the same backend+mode, else
  creates one and keeps the backend's keepalive so the compositor output (and
  its PipeWire node_id) survives the session. The session's capturer holds a
  gen-stamped DisplayLease instead of the real keepalive; its drop drives
  linger/teardown. Enabling fact: KWin/Mutter/gamescope put their node on the
  DEFAULT PipeWire daemon (remote_fd=None) — reconnect re-attaches by node_id,
  no fd re-open. wlroots (remote_fd=Some, xdpw portal) passes through unchanged
  (teardown-on-drop) pending the fresh-portal-capture re-attach.
- Default (unconfigured) linger = Immediate → today's teardown-on-disconnect,
  so no behavior change without a keep-alive policy; concurrent sessions still
  each create their own output (reuse only matches LINGERING entries).
- Wired build_pipeline (punktfunk1) + gamestream through registry::acquire;
  capture_virtual_output signature unchanged. Windows delegates to vd.create
  (the manager already leases) — unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-04 23:37:21 +00:00
parent 2dd17dda80
commit 783c52dfad
3 changed files with 364 additions and 21 deletions
@@ -286,13 +286,15 @@ fn open_gs_virtual_source(
std::sync::atomic::AtomicBool::new(false),
))
});
let vout = vd
.create(punktfunk_core::Mode {
let vout = crate::vdisplay::registry::acquire(
&mut vd,
punktfunk_core::Mode {
width: cfg.width,
height: cfg.height,
refresh_hz: cfg.fps,
})
.context("create virtual output at client resolution")?;
},
)
.context("create virtual output at client resolution")?;
// HDR: pass the negotiated `cfg.hdr` (client asked for HDR AND the host can deliver it). On the
// Windows IDD-push path this proactively enables advanced color on the virtual display so a Main10
// PQ stream flows even from an SDR desktop; an already-HDR desktop streams PQ regardless (the