diff options
| author | Valentin Popov <valentin@popov.link> | 2026-06-25 03:18:32 +0300 |
|---|---|---|
| committer | Valentin Popov <valentin@popov.link> | 2026-06-25 10:45:32 +0300 |
| commit | ba69bdb6eab57817b45055d60ea1d2f6687757a8 (patch) | |
| tree | 6c1ea4db8fd2a715c01a38d2fc3fb71140320eb3 /adapters/fparkan-platform-winit/src | |
| parent | 5cc2c5819f2dcfc9b9a8b86615d604d2b8f4c018 (diff) | |
| download | fparkan-ba69bdb6eab57817b45055d60ea1d2f6687757a8.tar.xz fparkan-ba69bdb6eab57817b45055d60ea1d2f6687757a8.zip | |
feat(stage0): close native smoke acceptance gate
Diffstat (limited to 'adapters/fparkan-platform-winit/src')
| -rw-r--r-- | adapters/fparkan-platform-winit/src/lib.rs | 159 |
1 files changed, 15 insertions, 144 deletions
diff --git a/adapters/fparkan-platform-winit/src/lib.rs b/adapters/fparkan-platform-winit/src/lib.rs index 30c5497..1640b23 100644 --- a/adapters/fparkan-platform-winit/src/lib.rs +++ b/adapters/fparkan-platform-winit/src/lib.rs @@ -27,15 +27,14 @@ use fparkan_platform::{ use raw_window_handle::{HasDisplayHandle, HasWindowHandle}; use std::collections::VecDeque; use std::sync::atomic::{AtomicU64, Ordering}; -use std::time::{SystemTime, UNIX_EPOCH}; -use winit::application::ApplicationHandler; -use winit::dpi::PhysicalSize as WinitPhysicalSize; +use std::sync::OnceLock; +use std::time::Instant; use winit::event::{Event, MouseButton, WindowEvent}; -use winit::event_loop::{ActiveEventLoop, EventLoop}; use winit::platform::scancode::PhysicalKeyExtScancode; -use winit::window::{Window, WindowId}; +use winit::window::Window; static NEXT_WINDOW_HANDLE_ID: AtomicU64 = AtomicU64::new(1); +static CLOCK_START: OnceLock<Instant> = OnceLock::new(); const DEFAULT_SMOKE_WIDTH: u32 = 1280; const DEFAULT_SMOKE_HEIGHT: u32 = 720; @@ -49,10 +48,8 @@ pub struct WinitClock; impl MonotonicClock for WinitClock { fn now(&self) -> MonotonicInstant { - let duration = SystemTime::now() - .duration_since(UNIX_EPOCH) - .unwrap_or_default(); - MonotonicInstant(duration.as_millis().try_into().unwrap_or(u64::MAX)) + let elapsed = CLOCK_START.get_or_init(Instant::now).elapsed(); + MonotonicInstant(elapsed.as_millis().try_into().unwrap_or(u64::MAX)) } } @@ -187,113 +184,6 @@ impl WinitWindowPlan { } } -/// Native smoke window creation result. -#[derive(Clone, Copy, Debug)] -pub struct WinitSmokeWindowProbe { - /// Validated creation plan. - pub plan: WinitWindowPlan, - /// Captured window descriptor. - pub window: WinitWindow, -} - -impl WinitSmokeWindowProbe { - /// Returns raw native handles captured from the native window. - #[must_use] - pub fn native_handles(&self) -> Option<NativeWindowHandles> { - self.window.native_handles() - } -} - -/// Creates a native smoke window, captures raw handles, then exits the event loop. -/// -/// # Errors -/// -/// Returns [`PlatformError`] when the plan is invalid, the event loop/window -/// cannot be created, or raw native handles are unavailable. -pub fn probe_smoke_window() -> Result<WinitSmokeWindowProbe, PlatformError> { - let plan = WinitWindowPlan::smoke().validate()?; - let event_loop = EventLoop::new().map_err(|err| PlatformError::Backend { - context: "winit event loop", - message: err.to_string(), - })?; - let mut app = SmokeWindowApp::new(plan); - event_loop - .run_app(&mut app) - .map_err(|err| PlatformError::Backend { - context: "winit event loop", - message: err.to_string(), - })?; - app.into_probe() -} - -struct SmokeWindowApp { - plan: WinitWindowPlan, - window: Option<WinitWindow>, - error: Option<String>, -} - -impl SmokeWindowApp { - const fn new(plan: WinitWindowPlan) -> Self { - Self { - plan, - window: None, - error: None, - } - } - - fn into_probe(self) -> Result<WinitSmokeWindowProbe, PlatformError> { - if let Some(message) = self.error { - return Err(PlatformError::Backend { - context: "winit smoke window", - message, - }); - } - let window = self.window.ok_or_else(|| PlatformError::Backend { - context: "winit smoke window", - message: "event loop exited before creating a window".to_string(), - })?; - if self.plan.requires_native_handles && window.native_handles().is_none() { - return Err(PlatformError::Backend { - context: "winit smoke window", - message: "native window/display handles are unavailable".to_string(), - }); - } - Ok(WinitSmokeWindowProbe { - plan: self.plan, - window, - }) - } -} - -impl ApplicationHandler for SmokeWindowApp { - fn resumed(&mut self, event_loop: &ActiveEventLoop) { - if self.window.is_some() || self.error.is_some() { - event_loop.exit(); - return; - } - let attributes = Window::default_attributes() - .with_title("FParkan Vulkan smoke") - .with_inner_size(WinitPhysicalSize::new(self.plan.width, self.plan.height)); - match event_loop.create_window(attributes) { - Ok(window) => { - self.window = Some(WinitWindow::from_window(&window)); - } - Err(err) => { - self.error = Some(err.to_string()); - } - } - event_loop.exit(); - } - - fn window_event( - &mut self, - _event_loop: &ActiveEventLoop, - _window_id: WindowId, - _event: WindowEvent, - ) { - } -} - /// Minimal window view over a `winit` window. #[derive(Clone, Copy, Debug)] pub struct WinitWindow { @@ -323,7 +213,7 @@ impl WinitWindow { focused: true, minimized: false, occluded: false, - native_handles: native_handles(window), + native_handles: window_native_handles(window), } } @@ -384,7 +274,9 @@ impl WindowPort for WinitWindow { } } -fn native_handles(window: &Window) -> Option<NativeWindowHandles> { +/// Extracts raw handles from a live `winit::Window`. +#[must_use] +pub fn window_native_handles(window: &Window) -> Option<NativeWindowHandles> { let display = window.display_handle().ok()?.as_raw(); let window = window.window_handle().ok()?.as_raw(); Some(NativeWindowHandles { display, window }) @@ -454,33 +346,12 @@ mod tests { } #[test] - fn smoke_window_app_requires_created_native_window() { - let app = SmokeWindowApp::new(WinitWindowPlan::smoke()); - - assert!(matches!( - app.into_probe(), - Err(PlatformError::Backend { - context: "winit smoke window", - .. - }) - )); - } - - #[test] - fn smoke_window_app_rejects_synthetic_window_without_native_handles() { - let mut app = SmokeWindowApp::new(WinitWindowPlan::smoke()); - app.window = Some(WinitWindow::synthetic( - DEFAULT_SMOKE_WIDTH, - DEFAULT_SMOKE_HEIGHT, - )); + fn monotonic_clock_uses_process_local_epoch() { + let clock = WinitClock; + let first = clock.now(); + let second = clock.now(); - assert!(matches!( - app.into_probe(), - Err(PlatformError::Backend { - context: "winit smoke window", - .. - }) - )); + assert!(second >= first); } #[test] |
