e2c9bfd3d9
apple / swift (push) Successful in 1m4s
windows-host / package (push) Successful in 6m28s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 1m14s
windows-msix / package (x64, C:\Users\Public\ffmpeg, x86_64-pc-windows-msvc, C:\t) (push) Successful in 1m10s
release / apple (push) Successful in 7m53s
android / android (push) Successful in 10m33s
ci / web (push) Successful in 44s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 3m4s
ci / docs-site (push) Successful in 53s
ci / rust (push) Successful in 12m22s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 1m11s
apple / screenshots (push) Successful in 5m24s
deb / build-publish (push) Successful in 3m16s
decky / build-publish (push) Successful in 21s
ci / bench (push) Successful in 4m42s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 27s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 2m34s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 2m42s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 2m13s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 47s
flatpak / build-publish (push) Successful in 4m24s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 8m5s
docker / deploy-docs (push) Successful in 25s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 7m44s
HDR (display-driven, matching the WGC path): - CTA-861.3 HDR EDID (BT.2020 primaries + HDR Static Metadata block) so Windows offers "Use HDR" on the virtual display. The host FOLLOWS the display's live advanced-color state, recreating the shared ring at the matching format (FP16 in HDR / BGRA in SDR) on a toggle — no freeze. - Always emit Main10/BT.2020-PQ Rgb10a2 while the display is HDR; the client auto-detects PQ from the HEVC VUI (clients under-report VIDEO_CAP_10BIT). Generic HDR10 mastering SEI on every IDR. - Generation-tagged `latest` (gen<<40|seq<<8|slot) + driver `is_stale` re-attach kill the toggle-time garbage frame and any stale-ring read. Perf: - Pipeline the encode loop (Capturer::pipeline_depth; IDD-push = 2): submit N+1 before polling N so the convert/copy on the 3D engine overlaps the NVENC encode of N on the ASIC. PUNKTFUNK_IDD_DEPTH overrides (1 = synchronous). - Rotating host output ring (OUT_RING) so the in-flight encode and the next convert never touch the same texture. - HDR converts directly from the keyed-mutex slot's SRV into the output ring (drops the redundant slot->fp16 scratch copy); SDR copies the BGRA slot in. The slot mutex is held only across the convert/copy, not the encode. RING_LEN 3->6 for publish headroom. - Capture-health diagnostic: new_fps vs repeat_fps under PUNKTFUNK_PERF (a low new_fps at a high send rate means the source isn't compositing, not an encode stall). Validated live on the RTX box: 5120x1440@240 HDR streams; driver composes ~180 new fps, encode 240 fps @ ~4.3 ms p50. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
131 lines
5.2 KiB
Rust
131 lines
5.2 KiB
Rust
//! Driver entry + WDF device-add. Adapted from virtual-display-rs (its event-log/boot-retry logger
|
|
//! dance is replaced by the `OutputDebugString` logger in `logger.rs`).
|
|
|
|
use log::{error, info};
|
|
use wdf_umdf::{
|
|
IddCxDeviceInitConfig, IddCxDeviceInitialize, WdfDeviceCreate, WdfDeviceCreateDeviceInterface,
|
|
WdfDeviceInitSetPnpPowerEventCallbacks, WdfDriverCreate,
|
|
};
|
|
use wdf_umdf_sys::{
|
|
GUID, IDD_CX_CLIENT_CONFIG, NTSTATUS, WDFDEVICE_INIT, WDFDRIVER__, WDFOBJECT, WDF_DRIVER_CONFIG,
|
|
WDF_OBJECT_ATTRIBUTES, WDF_PNPPOWER_EVENT_CALLBACKS, _DRIVER_OBJECT, _UNICODE_STRING,
|
|
};
|
|
|
|
use crate::callbacks::{
|
|
adapter_commit_modes, adapter_commit_modes2, adapter_init_finished, assign_swap_chain,
|
|
device_d0_entry, monitor_get_default_modes, monitor_query_modes, monitor_query_modes2,
|
|
parse_monitor_description, parse_monitor_description2, query_target_info,
|
|
set_default_hdr_metadata, set_gamma_ramp, unassign_swap_chain,
|
|
};
|
|
use crate::context::DeviceContext;
|
|
use crate::control::device_io_control;
|
|
|
|
// SudoVDA control-interface GUID — the host opens this to drive the ADD/REMOVE/PING IOCTLs.
|
|
// {e5bcc234-1e0c-418a-a0d4-ef8b7501414d}
|
|
const SUVDA_INTERFACE_GUID: GUID = GUID {
|
|
Data1: 0xe5bc_c234,
|
|
Data2: 0x1e0c,
|
|
Data3: 0x418a,
|
|
Data4: [0xa0, 0xd4, 0xef, 0x8b, 0x75, 0x01, 0x41, 0x4d],
|
|
};
|
|
|
|
/// Driver entry point (called by the framework via `FxDriverEntryUm`).
|
|
#[no_mangle]
|
|
extern "C-unwind" fn DriverEntry(
|
|
driver_object: *mut _DRIVER_OBJECT,
|
|
registry_path: *mut _UNICODE_STRING,
|
|
) -> NTSTATUS {
|
|
crate::logger::init();
|
|
crate::panic::set_hook();
|
|
info!("pf-vdisplay v{} starting", env!("CARGO_PKG_VERSION"));
|
|
|
|
let mut attributes = WDF_OBJECT_ATTRIBUTES::init();
|
|
let mut config = WDF_DRIVER_CONFIG::init(Some(driver_add));
|
|
|
|
unsafe {
|
|
WdfDriverCreate(
|
|
driver_object,
|
|
registry_path,
|
|
Some(&mut attributes),
|
|
&mut config,
|
|
None,
|
|
)
|
|
}
|
|
.into()
|
|
}
|
|
|
|
extern "C-unwind" fn driver_add(
|
|
_driver: *mut WDFDRIVER__,
|
|
mut init: *mut WDFDEVICE_INIT,
|
|
) -> NTSTATUS {
|
|
let mut callbacks = WDF_PNPPOWER_EVENT_CALLBACKS::init();
|
|
callbacks.EvtDeviceD0Entry = Some(device_d0_entry);
|
|
|
|
unsafe {
|
|
_ = WdfDeviceInitSetPnpPowerEventCallbacks(init, &mut callbacks);
|
|
}
|
|
|
|
let Some(mut config) = IDD_CX_CLIENT_CONFIG::init() else {
|
|
error!("Failed to create IDD_CX_CLIENT_CONFIG");
|
|
return NTSTATUS::STATUS_NOT_FOUND;
|
|
};
|
|
|
|
config.EvtIddCxAdapterInitFinished = Some(adapter_init_finished);
|
|
config.EvtIddCxParseMonitorDescription = Some(parse_monitor_description);
|
|
config.EvtIddCxMonitorGetDefaultDescriptionModes = Some(monitor_get_default_modes);
|
|
config.EvtIddCxMonitorQueryTargetModes = Some(monitor_query_modes);
|
|
config.EvtIddCxAdapterCommitModes = Some(adapter_commit_modes);
|
|
// IddCx 1.10 *2 mode DDIs (HDR-capable path). The OS prefers these on 1.10; the 1.x callbacks
|
|
// above stay as the down-level fallback. B1 advertises SDR through them (so behaviour is unchanged);
|
|
// B2 enables HDR by adding 10 bpc in `wire_bits()`, HIGH_COLOR_SPACE caps, and CAN_PROCESS_FP16.
|
|
config.EvtIddCxParseMonitorDescription2 = Some(parse_monitor_description2);
|
|
config.EvtIddCxMonitorQueryTargetModes2 = Some(monitor_query_modes2);
|
|
config.EvtIddCxAdapterCommitModes2 = Some(adapter_commit_modes2);
|
|
config.EvtIddCxAdapterQueryTargetInfo = Some(query_target_info);
|
|
config.EvtIddCxMonitorSetDefaultHdrMetaData = Some(set_default_hdr_metadata);
|
|
config.EvtIddCxMonitorSetGammaRamp = Some(set_gamma_ramp);
|
|
config.EvtIddCxMonitorAssignSwapChain = Some(assign_swap_chain);
|
|
config.EvtIddCxMonitorUnassignSwapChain = Some(unassign_swap_chain);
|
|
// IddCx redirects device IOCTLs to this callback — our SudoVDA-compatible control plane.
|
|
config.EvtIddCxDeviceIoControl = Some(device_io_control);
|
|
|
|
let init_data = unsafe { &mut *init };
|
|
let status = unsafe { IddCxDeviceInitConfig(init_data, &config) };
|
|
if let Err(e) = status {
|
|
error!("Failed to init iddcx config: {e:?}");
|
|
return e.into();
|
|
}
|
|
|
|
let mut attributes =
|
|
WDF_OBJECT_ATTRIBUTES::init_context_type(unsafe { DeviceContext::get_type_info() });
|
|
attributes.EvtCleanupCallback = Some(event_cleanup);
|
|
|
|
let mut device = std::ptr::null_mut();
|
|
let status = unsafe { WdfDeviceCreate(&mut init, Some(&mut attributes), &mut device) };
|
|
if let Err(e) = status {
|
|
error!("Failed to create device: {e:?}");
|
|
return e.into();
|
|
}
|
|
|
|
// Register the SudoVDA control interface so the host can open it + send the control IOCTLs.
|
|
let status =
|
|
unsafe { WdfDeviceCreateDeviceInterface(device, &SUVDA_INTERFACE_GUID, std::ptr::null()) };
|
|
if let Err(e) = status {
|
|
error!("Failed to create control device interface: {e:?}");
|
|
return e.into();
|
|
}
|
|
|
|
let status = unsafe { IddCxDeviceInitialize(device) };
|
|
if let Err(e) = status {
|
|
error!("Failed to init iddcx device: {e:?}");
|
|
return e.into();
|
|
}
|
|
|
|
let context = DeviceContext::new(device);
|
|
unsafe { context.init(device as WDFOBJECT).into() }
|
|
}
|
|
|
|
unsafe extern "C-unwind" fn event_cleanup(wdf_object: WDFOBJECT) {
|
|
_ = unsafe { DeviceContext::drop(wdf_object) };
|
|
}
|