The host cursor stops riding the video and becomes a real OS cursor on the client (the Parsec/RDP model): pointer feel no longer pays the capture→encode→network→decode→present round trip. Wire (M2a): - Hello grows a client_caps trailing byte (CLIENT_CAP_CURSOR) after the fixed display_hdr block — presence disambiguated by remaining length, which caps the post-HDR tail at 27 bytes (documented); Welcome answers HOST_CAP_CURSOR (capable-and-asked, the 444/clipboard precedent). - CursorShape (0x50, control stream): serial + dims + hotspot + straight RGBA, ≤120px/side so the u16 frame always fits (128² would overshoot); client caches by serial — re-showing a known shape costs 14 bytes, not a bitmap (RDP pointer-cache for free). - CursorState (0xD0 datagram): serial + visible/relative_hint flags + position, sent once per encode-loop tick — latest-wins, self-healing under loss, no refresh timer. relative_hint is reserved for M3. - Client core: two new planes (control-task + datagram-task arms) → next_cursor_shape/next_cursor_state; connect() grows client_caps (C ABI passes 0 until the v11 cursor poll fns exist). Host (M2b, Linux portal only): - handshake::cursor_forward is THE predicate (client asked ∧ Linux ∧ compositor ≠ gamescope) — Welcome bit and session wiring both read it. - SessionPlan.cursor_blend goes false for a forwarding session; the encode loop ticks a CursorForwarder every iteration: shape-serial diff → control-task bridge (mirrors probe_result), state datagram → conn. - CursorOverlay/capture CursorState carry the hotspot through (nearest-neighbor downscale backstop for XL cursors, unit-tested). Presenter: - CursorChannel drains both planes per loop iteration; shapes become SDL color cursors (from_surface + hotspot), applied while the desktop mouse model is engaged; visibility follows the host; capture/released hands back the system cursor. Sessions advertise the cap when they START in desktop mode. Verified on .21: fmt + clippy -D warnings (7 crates) + tests green (core 218 incl. new wire roundtrips, host 245 incl. e2e + forwarder downscale tests). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
42 lines
1.7 KiB
Rust
42 lines
1.7 KiB
Rust
//! The Vulkan session presenter (punktfunk-planning `linux-client-rearchitecture.md`,
|
|
//! Phase 1): an SDL3 window + ash swapchain that presents the shared session pump's
|
|
//! decoded frames, captures input on the `ui_stream` state-machine contract, and reports
|
|
//! the unified stats window on stdout. No UI toolkit anywhere in the dependency tree.
|
|
//!
|
|
//! Three frame paths: software (`CpuFrame` RGBA staging upload), Vulkan Video (the
|
|
//! decoder's VkImage on THIS device — plane views + the CICP-driven CSC pass), and on
|
|
//! Linux additionally VAAPI hardware (NV12 dmabuf imported per-plane — `dmabuf.rs`),
|
|
//! all composited by a letterboxed blit. Devices without the import extensions, and any
|
|
//! import/present failure streak, demote the decoder to software via the session pump's
|
|
//! `force_software` contract, same as the GTK presenter.
|
|
//!
|
|
//! Builds on Linux AND Windows; `dmabuf` is Linux-only (DRM-PRIME does not exist on
|
|
//! Windows) and `d3d11` is its Windows counterpart (D3D11VA shared-texture import) —
|
|
//! the decode chain there is Vulkan → D3D11VA → software.
|
|
|
|
#[cfg(any(target_os = "linux", windows))]
|
|
pub mod csc;
|
|
#[cfg(any(target_os = "linux", windows))]
|
|
pub mod cursor;
|
|
#[cfg(windows)]
|
|
pub mod d3d11;
|
|
#[cfg(target_os = "linux")]
|
|
pub mod dmabuf;
|
|
#[cfg(any(target_os = "linux", windows))]
|
|
pub mod input;
|
|
#[cfg(any(target_os = "linux", windows))]
|
|
pub mod keymap_sdl;
|
|
#[cfg(any(target_os = "linux", windows))]
|
|
pub mod overlay;
|
|
#[cfg(any(target_os = "linux", windows))]
|
|
mod run;
|
|
#[cfg(any(target_os = "linux", windows))]
|
|
pub mod touch;
|
|
#[cfg(any(target_os = "linux", windows))]
|
|
pub mod vk;
|
|
#[cfg(windows)]
|
|
mod win32;
|
|
|
|
#[cfg(any(target_os = "linux", windows))]
|
|
pub use run::{run_browse, run_session, ActionOutcome, Outcome, SessionOpts};
|