refactor(host/W6.1): extract the config() global into the pf-host-config leaf crate

Third de-coupling for the host crate carve (plan §W6.1 leaf). HostConfig + the config()
OnceLock (config.rs, pure std, zero deps) move to a new pf-host-config leaf so every
subsystem crate (pf-encode/pf-capture/pf-vdisplay/pf-gpu) can read process config WITHOUT
depending on the orchestrator. 34 crate::config::config() call sites across 19 files
repoint to pf_host_config::config(). thread_qos stays in the host for now (it calls
session_tuning::on_hot_thread — its own leaf-ification rides the encode carve).

Granular-crate decision (supersedes the plan's single pf-media): split capture/encode/
vdisplay into separate crates rather than one broad crate — the capture↔encode cycle is
broken by a shared frame-types leaf, and vdisplay→encode (can_open_another_session) is a
legal one-way edge since encode never references vdisplay.

Verified: Linux (home-worker-5) clippy -p pf-host-config -p punktfunk-host --all-targets
-D warnings; Windows (192.168.1.158) clippy --features nvenc,amf-qsv --all-targets green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-17 08:54:47 +02:00
parent c42ce88921
commit 3495d189e1
25 changed files with 55 additions and 36 deletions
+3 -3
View File
@@ -873,7 +873,7 @@ pub(super) fn virtual_stream(ctx: SessionContext) -> Result<()> {
#[cfg(not(any(target_os = "windows", target_os = "linux")))]
let _ = &launch;
let perf = crate::config::config().perf;
let perf = pf_host_config::config().perf;
// Microburst cap (applied in send_loop/paced_submit): a frame ≤ the cap bursts out
// immediately; only a bigger frame's overflow is spread. `None` = auto — max(128 KB, the
// AU's wire bytes / 4), so the burst stays a bounded fraction of high-rate frames instead
@@ -956,7 +956,7 @@ pub(super) fn virtual_stream(ctx: SessionContext) -> Result<()> {
// place when the box flips Gaming↔Desktop. When not spawned, session_rx just stays empty.
let mut compositor = compositor;
let (session_tx, session_rx) = std::sync::mpsc::channel::<SessionSwitch>();
let watch = session_watch_enabled() && crate::config::config().compositor.is_none();
let watch = session_watch_enabled() && pf_host_config::config().compositor.is_none();
let _watcher = if watch {
tracing::info!("session watcher on — following a mid-stream Gaming↔Desktop switch");
let stop = stop.clone();
@@ -1461,7 +1461,7 @@ pub(super) fn virtual_stream(ctx: SessionContext) -> Result<()> {
let (new_cap, new_enc, new_frame, new_interval, new_node_id, new_display_gen) = loop {
// Follow the active session unless an explicit PUNKTFUNK_COMPOSITOR pin forbids
// retargeting (then we stick to the pinned backend and just rebuild it).
if crate::config::config().compositor.is_none() {
if pf_host_config::config().compositor.is_none() {
let active = crate::vdisplay::detect_active_session();
// A4: fold any compositor-instance change into the epoch/invalidation before we
// rebuild, so the rebuild's acquire won't reuse a dead-instance node.