feat(windows-host): STEP 4 (3/n) — host pf_vdisplay backend (talks to the new driver)
apple / swift (push) Failing after 1s
apple / screenshots (push) Has been skipped
ci / rust (push) Failing after 28s
ci / web (push) Successful in 39s
android / android (push) Successful in 3m28s
ci / docs-site (push) Successful in 56s
deb / build-publish (push) Failing after 25s
decky / build-publish (push) Successful in 11s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 4s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 3s
windows-host / package (push) Successful in 6m32s
ci / bench (push) Successful in 4m34s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Failing after 3m21s
docker / deploy-docs (push) Successful in 17s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled

The host can now drive the new pf-vdisplay IddCx driver instead of SudoVDA. Compiles
clean on BOTH Windows (cargo check -p punktfunk-host green) and Linux (cfg(windows)-gated,
main CI unaffected); adversarially reviewed (no blockers, lockstep with the driver).

- new vdisplay/pf_vdisplay.rs: cloned from the proven sudovda.rs, repointed to
  pf_vdisplay_proto — interface GUID 70667664 (not e5bcc234), IOCTL 0x900-0x905 (not the
  gappy 0x800/0x888/0x8FF), AddRequest/AddReply/RemoveRequest/SetRenderAdapterRequest
  (bytemuck Pod, not the GUID-keyed AddParams), a u64 session_id monitor key (not a minted
  GUID), and a single IOCTL_GET_INFO handshake that HARD-asserts protocol_version (vs
  SudoVDA two-IOCTL best-effort). Full MGR/linger/refcount/teardown lifecycle preserved.
- reuses sudovda.rs backend-neutral CCD/DXGI helpers (set_active_mode, isolate/restore_
  displays_ccd, resolve_gdi_name, resolve_render_adapter_luid, MON_GEN/CURRENT_MON_GEN,
  SavedConfig) — widened to pub(crate), not duplicated.
- vdisplay::open()/probe() select the backend: PUNKTFUNK_VDISPLAY=pf|sudovda forces one;
  default auto-detects (prefer pf-vdisplay if its interface enumerates, else SudoVDA stays
  the shipping fallback).

Notes: SET_RENDER_ADAPTER is tolerated as the driver returns NOT_IMPLEMENTED today (STEP 4
tail); the cross-MGR wait_for_monitor_released only paces sudovda's MGR (benign until
IDD-push lands on pf-vdisplay, STEP 6 — documented in-code). On-glass "monitor appears at
WxH@Hz" gate is next.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-25 07:50:41 +00:00
parent bbc891e50a
commit 94e82df9f3
4 changed files with 769 additions and 8 deletions
+31 -3
View File
@@ -529,9 +529,15 @@ pub fn open(compositor: Compositor) -> Result<Box<dyn VirtualDisplay>> {
}
#[cfg(target_os = "windows")]
{
// Windows has a single virtual-display backend (SudoVDA); the compositor arg is moot.
// Two virtual-display backends: the new pf-vdisplay IddCx driver (pf_vdisplay_proto) and the
// shipping SudoVDA fallback. The compositor arg is moot on Windows. PUNKTFUNK_VDISPLAY overrides;
// default auto-detects (prefer pf-vdisplay if its driver interface is present).
let _ = compositor;
Ok(Box::new(sudovda::SudoVdaDisplay::new()?))
if windows_use_pf_vdisplay() {
Ok(Box::new(pf_vdisplay::PfVdisplayDisplay::new()?))
} else {
Ok(Box::new(sudovda::SudoVdaDisplay::new()?))
}
}
#[cfg(not(any(target_os = "linux", target_os = "windows")))]
{
@@ -540,6 +546,22 @@ pub fn open(compositor: Compositor) -> Result<Box<dyn VirtualDisplay>> {
}
}
/// Pick the Windows virtual-display backend. `PUNKTFUNK_VDISPLAY=pf|pf-vdisplay|pfvd` forces the new
/// pf-vdisplay IddCx driver; `=sudovda|sudo` forces the shipping SudoVDA driver; anything else (the
/// default) auto-detects, preferring pf-vdisplay if its device interface is enumerable.
#[cfg(target_os = "windows")]
fn windows_use_pf_vdisplay() -> bool {
match std::env::var("PUNKTFUNK_VDISPLAY")
.ok()
.as_deref()
.map(str::trim)
{
Some("pf") | Some("pf-vdisplay") | Some("pfvd") => true,
Some("sudovda") | Some("sudo") => false,
_ => pf_vdisplay::is_available(),
}
}
/// Readiness probe for `compositor`: is it up and able to create a virtual output *right
/// now*? A session-bringup script polls this (via `punktfunk-host probe-compositor`) to gate
/// on actual readiness instead of racing the compositor with a blind sleep.
@@ -560,7 +582,11 @@ pub fn probe(compositor: Compositor) -> Result<()> {
#[cfg(target_os = "windows")]
{
let _ = compositor;
sudovda::probe()
if windows_use_pf_vdisplay() {
pf_vdisplay::probe()
} else {
sudovda::probe()
}
}
#[cfg(not(any(target_os = "linux", target_os = "windows")))]
{
@@ -608,6 +634,8 @@ mod kwin;
#[cfg(target_os = "linux")]
mod mutter;
#[cfg(target_os = "windows")]
pub(crate) mod pf_vdisplay;
#[cfg(target_os = "windows")]
pub(crate) mod sudovda;
#[cfg(target_os = "linux")]
mod wlroots;