aboutsummaryrefslogtreecommitdiff
path: root/adapters/fparkan-platform-winit
diff options
context:
space:
mode:
Diffstat (limited to 'adapters/fparkan-platform-winit')
-rw-r--r--adapters/fparkan-platform-winit/src/lib.rs159
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]