feat(host/windows): native res, cursor, secure-desktop capture, windowless SYSTEM launch
apple / swift (push) Successful in 52s
ci / rust (push) Failing after 36s
ci / web (push) Successful in 31s
android / android (push) Successful in 1m52s
ci / docs-site (push) Successful in 29s
ci / bench (push) Successful in 1m39s
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 3s
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 4s
deb / build-publish (push) Successful in 3m19s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 5m15s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 4m57s
docker / deploy-docs (push) Successful in 17s
apple / swift (push) Successful in 52s
ci / rust (push) Failing after 36s
ci / web (push) Successful in 31s
android / android (push) Successful in 1m52s
ci / docs-site (push) Successful in 29s
ci / bench (push) Successful in 1m39s
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 3s
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 4s
deb / build-publish (push) Successful in 3m19s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 5m15s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 4m57s
docker / deploy-docs (push) Successful in 17s
Live-validated Mac <-> RTX 4090 at the display's native 5120x1440@240: - Resolution: set_active_mode enumerates the IDD's advertised modes and sets the requested resolution at the best supported refresh (keeps 5120x1440@240; no more silent fallback to the 1080p OS default when an exact mode is briefly unavailable). - Bitrate auto-cap: NVENC init probes and steps the average bitrate down to the GPU's codec-level max so a high client bitrate connects (matches the Linux host; we do not split NVENC sessions). - Mouse cursor: DXGI duplication excludes the HW cursor; capture the pointer shape/position (GetFramePointerShape) and GPU-composite it before NVENC. Color cursors alpha-blend; masked-color (the text I-beam) uses an INV_DEST_COLOR inversion blend so the caret inverts the screen and shows on any background (no black box); monochrome handled too. - Secure desktop (lock / login / UAC): run as SYSTEM in the interactive session, follow the input desktop via SetThreadDesktop, and on the WinSta switch recreate the D3D11 device and re-resolve the virtual output's GDI name from the stable SudoVDA target id (the name changes across the topology rebuild; the old failure hunted the stale \\.\DISPLAYn and dropped). ACCESS_LOST / INVALID_CALL / device-removed are recoverable, and a mid-stream resolution change is followed (capturer + NVENC re-init at the new size). isolate_displays detaches other monitors so Winlogon renders to the virtual output. One real session recovered 1012 desktop switches and completed cleanly. Windows-only backends; Linux/macOS unaffected. Builds clean on x86_64-pc-windows-msvc. Deployment (windowless SYSTEM launch via PsExec + hidden VBScript) documented in docs/windows-host.md. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -47,6 +47,42 @@ coexisting with a running Apollo (two concurrent NVENC sessions).
|
||||
- **Frame pacing on static content** — DXGI duplication is change-driven, so a blank/idle virtual
|
||||
display delivers only ~12 fps (181/177 frames over ~15 s); a rendering app drives the full rate.
|
||||
|
||||
### Live UX hardening (2026-06-15, validated Mac ↔ RTX 4090)
|
||||
|
||||
Driven by live testing with the native macOS client at the display's native **5120×1440@240**:
|
||||
|
||||
- **Native resolution, not 1080p.** `sudovda::set_active_mode` enumerates the modes the IDD actually
|
||||
advertises (`EnumDisplaySettingsW`) and sets the requested **resolution** at the best supported
|
||||
refresh — keeping 5120×1440@240, never silently collapsing to the 1280×720/1920×1080 OS default
|
||||
when an exact mode is briefly unavailable.
|
||||
- **Bitrate auto-cap.** NVENC `init_session` probes and steps the average bitrate down (×3/4 to a
|
||||
floor) when the requested rate exceeds the GPU's codec-level max, so a high client bitrate connects
|
||||
instead of failing (matches the Linux host; we do NOT split NVENC sessions).
|
||||
- **Mouse cursor.** DXGI duplication excludes the hardware cursor; we read the pointer
|
||||
position/shape from the frame info (`GetFramePointerShape`) and GPU-composite it onto the captured
|
||||
texture before NVENC (a CPU read-back would stall the pipeline). Color cursors alpha-blend;
|
||||
**masked-color** cursors (the text I-beam) use an `INV_DEST_COLOR` blend for true screen inversion,
|
||||
so the caret is visible on any background (no black box). Monochrome handled too.
|
||||
- **Secure desktop (lock / login / UAC).** The host runs as **SYSTEM in the interactive session**;
|
||||
the capturer `SetThreadDesktop`s onto the current input desktop and, on the WinSta switch,
|
||||
**recreates the D3D11 device** and **re-resolves the virtual output's GDI name from the stable
|
||||
SudoVDA target id** (the name changes across the topology rebuild — the old failure was hunting the
|
||||
stale `\\.\DISPLAYn` and dropping). `ACCESS_LOST` / `INVALID_CALL` / device-removed are all treated
|
||||
as recoverable, and a mid-stream resolution change is followed (capturer + NVENC re-init at the new
|
||||
size). Validated: logging in / locking through the stream stays connected (one real session
|
||||
recovered 1012 desktop switches and completed cleanly). *Display isolation* (`isolate_displays`
|
||||
detaches other monitors so Winlogon renders to the virtual output) covers the case where a physical
|
||||
monitor is also attached.
|
||||
|
||||
### Running as SYSTEM, windowless (deployment)
|
||||
|
||||
To capture the secure desktop the host must run as **SYSTEM in the interactive Session 1** (a Session
|
||||
0 service can't duplicate Session 1). Launch chain: a scheduled task (Interactive, Highest) →
|
||||
`PsExec64 -s -i 1 -d wscript.exe launch.vbs` → `launch.vbs` runs `host-run.cmd` with a **hidden
|
||||
window** (`WScript.Shell.Run …, 0`). This keeps the host off the captured desktop — no `cmd` windows
|
||||
the user can see or accidentally close (which would kill the stream). `host-run.cmd` sets
|
||||
`APPDATA=C:\Users\Public` (shared identity/pairing) + `PUNKTFUNK_ENCODER=nvenc` and runs `m3-host`.
|
||||
|
||||
### Real-GPU test box (RTX 4090, `ssh "Enrico Bühler"@192.168.1.174`)
|
||||
|
||||
Windows 11, RTX 4090 (driver 596.36) + AMD iGPU, SudoVDA + Apollo (sunshine) installed. SSH lands in
|
||||
|
||||
Reference in New Issue
Block a user