From d2e536d299970aa89e736bf4366e5cf23b60ea6c Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Tue, 16 Jun 2026 17:13:02 +0000 Subject: [PATCH] =?UTF-8?q?fix(host/windows):=20WGC=20relay=20=E2=80=94=20?= =?UTF-8?q?don't=20force=20HDR=20on=20SDR=20sessions=20across=20the=20secu?= =?UTF-8?q?re=20mux?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Re-enabling the WGC relay brought back a broken image on the secure->normal switch. Log root cause: on returning to the normal desktop the relay called set_advanced_color(target, true) to 'restore HDR', so the rebuilt WGC helper captured HDR FP16 BT.2020 PQ while the session encoder is 8-bit SDR -> format mismatch (the 'HDR gets restored when flipping back to WGC' bug). Gate BOTH set_advanced_color toggles on bit_depth>=10. An SDR (8-bit) session now stays SDR across WGC<->DDA switches (no HDR force, no needless topology change); HDR sessions keep the drop-on-secure / restore-on-normal behavior. Co-Authored-By: Claude Opus 4.8 --- crates/punktfunk-host/src/m3.rs | 35 ++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/crates/punktfunk-host/src/m3.rs b/crates/punktfunk-host/src/m3.rs index 3dd59db..c5b65c8 100644 --- a/crates/punktfunk-host/src/m3.rs +++ b/crates/punktfunk-host/src/m3.rs @@ -2541,17 +2541,20 @@ fn virtual_stream_relay( "two-process: source switch" ); if secure { - // SDR-while-secure: drop the SudoVDA out of HDR so the secure (Winlogon) desktop - // renders SDR/composed — the HDR fullscreen independent-flip is what made DDA storm - // ACCESS_LOST (black). Give the reconfig a moment to settle, then (re)open DDA fresh on - // the now-SDR output. - let toggled = unsafe { - crate::vdisplay::sudovda::set_advanced_color(target.target_id, false) - }; - if toggled { - std::thread::sleep(std::time::Duration::from_millis(250)); + // SDR-while-secure (HDR sessions ONLY): drop the SudoVDA out of HDR so the secure + // (Winlogon) desktop renders SDR/composed — HDR fullscreen independent-flip is what made + // DDA storm ACCESS_LOST (black). For an SDR (8-bit) session the output is already SDR, so + // toggling is a needless topology change AND its matching restore on the way back would + // force the desktop into HDR the 8-bit encoder can't take (broken image). + if bit_depth >= 10 { + let toggled = unsafe { + crate::vdisplay::sudovda::set_advanced_color(target.target_id, false) + }; + if toggled { + std::thread::sleep(std::time::Duration::from_millis(250)); + } } - dda = None; // reopen so we capture the post-toggle (SDR) output + dda = None; // reopen so we capture the (SDR) output match open_dda(&target, cur_mode.width, cur_mode.height, effective_hz) { Ok(mut p) => { p.enc.request_keyframe(); @@ -2564,10 +2567,14 @@ fn virtual_stream_relay( } next = std::time::Instant::now(); } else { - // Returning to the normal desktop: restore HDR on the SudoVDA (WGC captures it HDR), then - // rebuild the helper fresh so its WGC re-detects the restored colorspace, and resume. - unsafe { - crate::vdisplay::sudovda::set_advanced_color(target.target_id, true); + // 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). + if bit_depth >= 10 { + unsafe { + crate::vdisplay::sudovda::set_advanced_color(target.target_id, true); + } } dda = None; // free the secure DDA encoder match build(&mut vd, cur_mode) {