feat(windows/capture): host-side cursor compositing for the capture model — the deterministic fix
Root cause, proven on-glass across five driver builds: a declared IddCx hardware cursor is IRREVOCABLE. There is no un-declare DDI, the empty-caps re-setup is rejected INVALID_PARAMETER, and after a successful same-mode re-commit with the driver's re-declare provably suppressed (sticky per-target flag, zero re-setups logged) DWM still never composites the software cursor back into the monitor's frames. Every DWM-based composite flip is therefore unfixable. The composite (capture) model is now implemented in OUR pipeline: - the driver keeps its hardware cursor declared for the session's whole life (the state that works) — frames stay pointer-free always; - in composite mode try_consume routes the conversion through a blend scratch: slot copy + one alpha-blended quad of the GDI poller's shape at its polled position (CursorBlendPass — fullscreen-triangle VS with viewport placement, straight-alpha PS, sRGB→linear for FP16/HDR rings), covering all four convert paths (NV12, 4:4:4 copy, P010, PyroWave) GPU-side under the slot's keyed mutex; - pointer-only motion produces no driver publish (declared hw cursor), so try_consume REGENERATES from the last slot whenever the polled cursor state changes — the cursor moves on a static desktop at tick rate, without faking freshness for the stall/death watchdogs; - set_cursor_forward becomes purely host-internal state; the SET_CURSOR_FORWARD IOCTL machinery is no longer used by the host (driver keeps it, dormant) and its sender plumbing is removed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -174,26 +174,6 @@ pub fn capture_virtual_output(
|
||||
},
|
||||
) as pf_capture::CursorChannelSender
|
||||
});
|
||||
// The mid-stream cursor-render flip (proto v6) — retained by the capturer so the client's
|
||||
// mouse-model chords can (un)declare the driver's hardware cursor live. Same facade contract
|
||||
// as `cursor_sender`.
|
||||
let cursor_forward_sender: Option<pf_capture::CursorForwardSender> =
|
||||
want.hw_cursor.then(|| {
|
||||
std::sync::Arc::new(
|
||||
move |req: &pf_driver_proto::control::SetCursorForwardRequest| {
|
||||
// SAFETY: `control_raw` is the pf-vdisplay control handle resolved above; it is
|
||||
// never closed for the process lifetime (`send_cursor_forward`'s precondition).
|
||||
unsafe {
|
||||
crate::vdisplay::driver::send_cursor_forward(
|
||||
windows::Win32::Foundation::HANDLE(
|
||||
control_raw as *mut core::ffi::c_void,
|
||||
),
|
||||
req,
|
||||
)
|
||||
}
|
||||
},
|
||||
) as pf_capture::CursorForwardSender
|
||||
});
|
||||
pf_capture::open_idd_push(
|
||||
target,
|
||||
pref,
|
||||
@@ -203,7 +183,6 @@ pub fn capture_virtual_output(
|
||||
keep,
|
||||
sender,
|
||||
cursor_sender,
|
||||
cursor_forward_sender,
|
||||
)
|
||||
.map_err(|(e, _keep)| e.context("IDD-push capture open (no fallback)"))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user