925130d1f9152f483100f053ca874578c35e3901
4
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
925130d1f9 |
feat(vdisplay): compositor-embedded pointer for sessions without the cursor channel (Phase B)
Since the cursor-channel work, every Linux virtual output was created in metadata pointer mode — making ALL sessions depend on host-side cursor compositing, including the ones that can never use the channel (Moonlight/ GameStream, legacy clients, capture-mode starts). Those sessions paid the blend bring-up per session and, whenever a visible cursor was composited, the loss of NVENC's stream-ordered submit — for a strictly worse cursor than the compositor's own. Mirror the Windows no-regression gate: the already-wired per-session set_hw_cursor(cursor_forward) now drives the Linux backends too. A cursor-channel session gets metadata (shapes forwarded, composite flip blends host-side — today's validated path, unchanged); every other session gets the pointer compositor-EMBEDDED at creation (KWin zkde pointer=2, Mutter cursor-mode=1, wlroots/hyprland portal CursorMode::Embedded — their pre-channel default; the portal pair also gains the Metadata arm for channel sessions, wired but untested on-glass). SessionPlan.cursor_blend narrows to cursor-forward sessions and rides into the direct-SDK NVENC open, which skips the Vulkan slot-blend bring-up entirely when off — embedded sessions ring on plain CUDA surfaces and pay zero cursor cost, per-session or per-frame. The keep-alive registry's reuse key grows the created pointer mode (new VirtualDisplay::hw_cursor getter): a kept embedded display has no cursor metadata for a channel session to forward, and a kept metadata display would leave a channel-less session with no pointer in its frames. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
af87549052 |
fix(linux/vdisplay): KWin virtual outputs stream above 60 Hz via sacrificial-birth renegotiation
KWin's ScreenCastStream builds its PipeWire format offer — including the maxFramerate cap it actively throttles delivery to — ONCE at stream creation, when the virtual output sits at its hardcoded birth 60 Hz. A kscreen custom-mode change afterwards updates the OUTPUT (readback says 240) but never the offer, so every consumer negotiates max=60 and the stream delivers 60 (pw-dump-verified on KWin 6.6.4). The only path that rebuilds the offer is the stream's own resize handling: a source SIZE change while recording re-runs buildFormats — picking up the output's current refresh — and renegotiates the live stream. So above 60 Hz, birth the output at a sacrificial height (+16), then install + select the real WxH@hz custom mode: the first frame recorded after the consumer connects triggers KWin's resize path, which renegotiates the live stream to WxH@hz. The capturer holds (requeues) buffers until the negotiated size matches — new expect_exact_dims plumbing VirtualOutput → registry (fresh creates only) → open_virtual_output → a self-disarming gate in the process callback — bounded by a 3 s deadline that accepts the producer's dims rather than wedging the session into the first-frame retry loop. set_custom_refresh reads back the full active mode; a size reject (pre-6.6 KWin) recreates plain at the real size @60. Every kscreen operation now addresses the output by its NUMERIC id, resolved by matching the managed name-prefix AND the just-created birth size (newest id wins): a mode-switch supersede reuses the per-slot output NAME (deliberately, for KWin's per-name config persistence) while the superseded sibling is still alive, and name addressing hit the FIRST match = the OLD output — on-glass that resized the live session's display out from under it (wrong-res/black), read the old output back as 'mode applied', and set the old output primary while the replacement starved at its birth mode. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
3a34440a6b |
feat(windows): IddCx hardware-cursor channel — remote-desktop sweep M2c
Brings the cursor channel to Windows hosts. The pf-vdisplay driver declares an IddCx hardware cursor for sessions that negotiated cursor-forward — DWM then EXCLUDES the pointer from the IDD frame and delivers shape/position out-of-band, into the same CursorOverlay → forwarder → wire → client pipeline the Linux portal path uses. - pf-driver-proto v5 (additive, host floor stays 3): AddRequest's spare tail becomes hw_cursor (same size/offsets); IOCTL_SET_CURSOR_CHANNEL delivers a host-created CursorShm section (64-byte seqlock header + 256² shape buffer, layout pinned + tested). No event crosses the boundary — the host polls at encode-tick pace. - driver: wdk-iddcx grows the two cursor DDI wrappers; a per-monitor cursor worker (event wait → QueryHardwareCursor → seqlock publish) starts only when BOTH the ADD asked and the channel arrived, so a failed delivery leaves DWM compositing as today. Shape bytes ship raw (BGRA/masked + pitch); the host converts. - host: the section rides the existing sealed-channel broker (least- privilege dup, remote reap on failure); IddPushCapturer::cursor() seqlock-reads → CursorOverlay (BGRA→RGBA, masked-color approximation, desktop→frame origin shift, per-shape conversion cache). New Capturer::cursor() trait hook — the encode loop prefers it over the frame-attached overlay because hardware-cursor moves produce NO new frame on a static desktop. hw_cursor survives the re-arrival resize (carried on the manager's Monitor). - negotiation: cursor_forward grows the Windows arm (client cap ∧ driver proto ≥ 5, probed once via the control device); SessionPlan carries cursor_forward → OutputFormat.hw_cursor. - drive-by: wdk-probe's two pre-existing same-type casts (clippy) and pf-vdisplay's stale spike-test refs (crate::win_display moved to pf-win-display; tracing-subscriber was never a dep) repaired. Verified: proto tests on Mac AND MSVC (15/15 incl. the CursorShm layout pin); clippy -D warnings for proto/frame/capture/vdisplay/host on Linux (.21) and native Windows (.173); the DRIVER workspace clippy -D warnings green against the real WDK 10.0.26100 bindgen (DDI names, enum variants and IDARG layouts all bind). On-box driver deploy + on-glass validation follow. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
27a5d8daac |
refactor(host/W6.2): extract virtual-display orchestration into the pf-vdisplay crate
vdisplay.rs + vdisplay/* (the per-compositor Linux backends — KWin zkde-screencast,
wlroots swaymsg, Mutter RemoteDesktop, Hyprland — and the Windows IddCx/pf-vdisplay
driver backend, behind one VirtualDisplay trait; the mode-conflict admission
registry, the display policy/identity/custom-preset state, and the session-env /
gamescope routing) move into crates/pf-vdisplay (plan §W6). The DDC/CI panel-power
control (used only here) and the KWin zkde protocol XML move with it. This
completes the host-crate decomposition: capture, encode, inject, and vdisplay are
now four subsystem crates over the shared leaves, and punktfunk-host is the
orchestrator (serve/supervisor + native + gamestream + mgmt).
Coupling breaks (all down-only, cargo-tree acyclic):
- capture::dxgi identity -> pf_frame::dxgi; win_display/monitor_devnode/
console_session_mismatch -> pf-win-display leaf; can_open_another_session ->
pf-encode (the NVENC session-budget admission gate — acyclic peer edge).
- The registry's DisplayCreated/DisplayReleased emits into the host SSE event bus
invert to a leaf hook: pf-vdisplay emits a neutral DisplayEvent to a
host-registered DISPLAY_EVENT_SINK, so it never reaches the orchestrator's
events module.
- The IddCx driver module is renamed pf_vdisplay -> driver (its old name collided
with the crate name through the host's `mod vdisplay` shim glob).
The host keeps `mod vdisplay { pub use pf_vdisplay::* }` so every crate::vdisplay::*
path (serve/mgmt/native/the capture FrameChannelSender seam) is unchanged; the
heavy deps (wayland/ashpd/tokio + the zkde protocol) moved with the crate.
Co-authored: a fail-closed IOCTL-reply-length security fix (reject short/zeroed
pf-vdisplay driver replies before trusting protocol_version/target_id/wudf_pid/luid,
security-review 2026-07-17) rides this commit in the moved driver module.
Verified: Linux clippy -D warnings (pf-vdisplay + host nvenc,vulkan-encode,pyrowave
--all-targets) + pf-vdisplay 63/63 + host 167/167 tests; Windows clippy -D warnings
(pf-vdisplay --all-targets + host nvenc,amf-qsv --all-targets) Finished exit 0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|