From ca375c7ce80f41d53c44c3db33a9ed0caa677b65 Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Tue, 16 Jun 2026 17:27:50 +0000 Subject: [PATCH] =?UTF-8?q?fix(host/windows):=20WGC=20mux=20=E2=80=94=20re?= =?UTF-8?q?use=20the=20SudoVDA=20monitor=20+=20helper=20across=20secure=20?= =?UTF-8?q?switches=20(no=20teardown/recreate)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit User: re-adding WGC brought back the teardown/recreate bug (audible disconnect/ connect on the secure<->normal switch). Cause: the secure->normal switch called build() = vd.create() = IOCTL_REMOVE old SudoVDA monitor + IOCTL_ADD new one + respawn the helper — the same teardown/recreate kernel stress we just eliminated from DDA, now on the mux path. Apply the same learning (reuse, don't tear down): the SudoVDA monitor and WGC helper persist for the whole session; only the host-DDA leg opens (on secure) and closes (on normal). On returning to normal, RESUME the still-alive helper (drain its secure-dwell backlog + request a keyframe) instead of rebuilding. The HDR-session colorspace restore (set_advanced_color(true) + helper rebuild) is kept ONLY for bit_depth>=10 — an SDR session never changed the colorspace, so it needs no rebuild at all. The secure switch already reuses the monitor (open_dda on the existing target). Co-Authored-By: Claude Opus 4.8 --- crates/punktfunk-host/src/m3.rs | 46 +++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/crates/punktfunk-host/src/m3.rs b/crates/punktfunk-host/src/m3.rs index c824481..36d4aa1 100644 --- a/crates/punktfunk-host/src/m3.rs +++ b/crates/punktfunk-host/src/m3.rs @@ -2581,31 +2581,39 @@ fn virtual_stream_relay( } next = std::time::Instant::now(); } else { - // Returning to the normal desktop: restore HDR on the SudoVDA (HDR sessions ONLY — WGC - // then captures it HDR). An SDR (8-bit) session must stay SDR; forcing HDR here is what - // made the rebuilt WGC helper capture HDR FP16 BT.2020 while the encoder is 8-bit SDR → - // format mismatch / broken image (the "HDR gets restored when flipping back" bug). + // Returning to the normal desktop: RESUME from the still-alive WGC helper. Do NOT + // recreate the SudoVDA monitor or respawn the helper — build()'s vd.create() is an + // IOCTL_REMOVE+ADD of the monitor (the audible disconnect/connect chime + the + // teardown/recreate kernel stress that broke DDA, now applied to the mux). The monitor + + // helper persist for the WHOLE session; only the host-DDA leg opens (secure) and closes + // (normal). Apply the DDA learning here: reuse, don't tear down. + dda = None; // free the secure DDA encoder; the relay (helper) is the source again + while relay.try_recv().is_ok() {} // drop secure-dwell backlog + relay.request_keyframe(); // client decoder resumes on the helper's next IDR if bit_depth >= 10 { + // HDR session ONLY: the secure switch dropped the SudoVDA to SDR for the DDA leg, so + // here we must restore HDR AND rebuild the helper so WGC re-detects the HDR + // colorspace. An SDR session never changed the colorspace → no rebuild, no recreate. unsafe { crate::vdisplay::sudovda::set_advanced_color(target.target_id, true); } - } - dda = None; // free the secure DDA encoder - match build(&mut vd, cur_mode) { - Ok((ka, rl, tg, hz)) => { - relay = rl; - _keepalive = ka; - target = tg; - effective_hz = hz; - interval = std::time::Duration::from_secs_f64(1.0 / hz.max(1) as f64); - } - Err(e) => { - tracing::error!(error = %format!("{e:#}"), - "two-process: helper rebuild on secure-exit failed"); - while relay.try_recv().is_ok() {} - relay.request_keyframe(); + match build(&mut vd, cur_mode) { + Ok((ka, rl, tg, hz)) => { + relay = rl; + _keepalive = ka; + target = tg; + effective_hz = hz; + interval = std::time::Duration::from_secs_f64(1.0 / hz.max(1) as f64); + } + Err(e) => { + tracing::error!(error = %format!("{e:#}"), + "two-process: helper rebuild on secure-exit failed"); + while relay.try_recv().is_ok() {} + relay.request_keyframe(); + } } } + next = std::time::Instant::now(); } } if want_kf {