From 1943236bcae7b0d184455cfefc872091af7108c8 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Wed, 18 Dec 2024 23:34:49 +0100 Subject: [PATCH] allow redefining `NATIVE_DISPLAY` --- src/graphics/gl.rs | 3 +- src/lib.rs | 80 +++++++++++++++++++++---------------- src/native/android.rs | 2 +- src/native/ios.rs | 12 +++--- src/native/linux_wayland.rs | 2 +- src/native/linux_x11.rs | 12 +++--- src/native/macos.rs | 24 +++++------ src/native/wasm.rs | 6 +-- src/native/windows.rs | 18 ++++----- 9 files changed, 85 insertions(+), 74 deletions(-) diff --git a/src/graphics/gl.rs b/src/graphics/gl.rs index 74be9fd9..1ea0cf10 100644 --- a/src/graphics/gl.rs +++ b/src/graphics/gl.rs @@ -1455,8 +1455,7 @@ impl RenderingBackend for GlContext { TextureOrRenderbuffer::Renderbuffer(id) => id, }; unsafe { - self.cache - .bind_texture(n, texture.params.kind.into(), raw); + self.cache.bind_texture(n, texture.params.kind.into(), raw); glUniform1i(gl_loc, n as i32); } } diff --git a/src/lib.rs b/src/lib.rs index 7385cd86..18282875 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -80,19 +80,31 @@ pub mod date { pub type Context = dyn RenderingBackend; -use std::sync::{Mutex, OnceLock}; +use crate::native::NativeDisplayData; +use std::sync::{Mutex, MutexGuard}; -static NATIVE_DISPLAY: OnceLock> = OnceLock::new(); +static mut NATIVE_DISPLAY: Option> = None; -fn set_display(display: native::NativeDisplayData) { - NATIVE_DISPLAY - .set(Mutex::new(display)) - .unwrap_or_else(|_| panic!("NATIVE_DISPLAY already set")); +fn set_display(display: NativeDisplayData) { + unsafe { + NATIVE_DISPLAY = Some(Mutex::new(display)); + } } -fn native_display() -> &'static Mutex { - NATIVE_DISPLAY - .get() - .expect("Backend has not initialized NATIVE_DISPLAY yet.") //|| Mutex::new(Default::default())) + +fn native_display_blocking() -> MutexGuard<'static, NativeDisplayData> { + native_display().lock().unwrap() +} + +fn native_display_nonblocking() -> MutexGuard<'static, NativeDisplayData> { + native_display().try_lock().unwrap() +} + +fn native_display() -> &'static Mutex { + unsafe { + NATIVE_DISPLAY + .as_ref() + .expect("Backend has not initialized NATIVE_DISPLAY yet.") + } } /// Window and associated to window rendering context related functions. @@ -125,26 +137,26 @@ pub mod window { /// The current framebuffer size in pixels /// NOTE: [High DPI Rendering](../conf/index.html#high-dpi-rendering) pub fn screen_size() -> (f32, f32) { - let d = native_display().lock().unwrap(); + let d = native_display_blocking(); (d.screen_width as f32, d.screen_height as f32) } /// The dpi scaling factor (window pixels to framebuffer pixels) /// NOTE: [High DPI Rendering](../conf/index.html#high-dpi-rendering) pub fn dpi_scale() -> f32 { - let d = native_display().lock().unwrap(); + let d = native_display_blocking(); d.dpi_scale } /// True when high_dpi was requested and actually running in a high-dpi scenario /// NOTE: [High DPI Rendering](../conf/index.html#high-dpi-rendering) pub fn high_dpi() -> bool { - let d = native_display().lock().unwrap(); + let d = native_display_blocking(); d.high_dpi } pub fn blocking_event_loop() -> bool { - let d = native_display().lock().unwrap(); + let d = native_display_blocking(); d.blocking_event_loop } @@ -156,7 +168,7 @@ pub mod window { /// happen in the order_quit implmentation) and execution might continue for some time after /// But the window is going to be inevitably closed at some point. pub fn order_quit() { - let mut d = native_display().lock().unwrap(); + let mut d = native_display_blocking(); d.quit_ordered = true; } @@ -171,7 +183,7 @@ pub mod window { /// If the event handler callback does nothing, the application will be quit as usual. /// To prevent this, call the function "cancel_quit()"" from inside the event handler. pub fn request_quit() { - let mut d = native_display().lock().unwrap(); + let mut d = native_display_blocking(); d.quit_requested = true; } @@ -181,7 +193,7 @@ pub mod window { /// function makes sense is from inside the event handler callback when /// the "quit_requested_event" event has been received pub fn cancel_quit() { - let mut d = native_display().lock().unwrap(); + let mut d = native_display_blocking(); d.quit_requested = false; } /// Capture mouse cursor to the current window @@ -191,7 +203,7 @@ pub mod window { /// so set_cursor_grab(false) on window's focus lost is recommended. /// TODO: implement window focus events pub fn set_cursor_grab(grab: bool) { - let d = native_display().lock().unwrap(); + let d = native_display_blocking(); d.native_requests .send(native::Request::SetCursorGrab(grab)) .unwrap(); @@ -205,7 +217,7 @@ pub mod window { pub fn schedule_update() { #[cfg(not(target_arch = "wasm32"))] { - let d = native_display().lock().unwrap(); + let d = native_display_blocking(); d.native_requests .send(native::Request::ScheduleUpdate) .unwrap(); @@ -219,7 +231,7 @@ pub mod window { /// Show or hide the mouse cursor pub fn show_mouse(shown: bool) { - let d = native_display().lock().unwrap(); + let d = native_display_blocking(); d.native_requests .send(native::Request::ShowMouse(shown)) .unwrap(); @@ -227,7 +239,7 @@ pub mod window { /// Set the mouse cursor icon. pub fn set_mouse_cursor(cursor_icon: CursorIcon) { - let d = native_display().lock().unwrap(); + let d = native_display_blocking(); d.native_requests .send(native::Request::SetMouseCursor(cursor_icon)) .unwrap(); @@ -235,7 +247,7 @@ pub mod window { /// Set the application's window size. pub fn set_window_size(new_width: u32, new_height: u32) { - let d = native_display().lock().unwrap(); + let d = native_display_blocking(); d.native_requests .send(native::Request::SetWindowSize { new_width, @@ -245,7 +257,7 @@ pub mod window { } pub fn set_window_position(new_x: u32, new_y: u32) { - let d = native_display().lock().unwrap(); + let d = native_display_blocking(); d.native_requests .send(native::Request::SetWindowPosition { new_x, new_y }) .unwrap(); @@ -255,12 +267,12 @@ pub mod window { /// TODO: implement for other platforms #[cfg(any(target_os = "windows", target_os = "linux"))] pub fn get_window_position() -> (u32, u32) { - let d = native_display().lock().unwrap(); + let d = native_display_blocking(); d.screen_position } pub fn set_fullscreen(fullscreen: bool) { - let d = native_display().lock().unwrap(); + let d = native_display_blocking(); d.native_requests .send(native::Request::SetFullscreen(fullscreen)) .unwrap(); @@ -268,32 +280,32 @@ pub mod window { /// Get current OS clipboard value pub fn clipboard_get() -> Option { - let mut d = native_display().lock().unwrap(); + let mut d = native_display_blocking(); d.clipboard.get() } /// Save value to OS clipboard pub fn clipboard_set(data: &str) { - let mut d = native_display().lock().unwrap(); + let mut d = native_display_blocking(); d.clipboard.set(data) } pub fn dropped_file_count() -> usize { - let d = native_display().lock().unwrap(); + let d = native_display_blocking(); d.dropped_files.bytes.len() } pub fn dropped_file_bytes(index: usize) -> Option> { - let d = native_display().lock().unwrap(); + let d = native_display_blocking(); d.dropped_files.bytes.get(index).cloned() } pub fn dropped_file_path(index: usize) -> Option { - let d = native_display().lock().unwrap(); + let d = native_display_blocking(); d.dropped_files.paths.get(index).cloned() } /// Show/hide onscreen keyboard. /// Only works on Android right now. pub fn show_keyboard(show: bool) { - let d = native_display().lock().unwrap(); + let d = native_display_blocking(); d.native_requests .send(native::Request::ShowKeyboard(show)) .unwrap(); @@ -301,17 +313,17 @@ pub mod window { #[cfg(target_vendor = "apple")] pub fn apple_gfx_api() -> crate::conf::AppleGfxApi { - let d = native_display().lock().unwrap(); + let d = native_display_blocking(); d.gfx_api } #[cfg(target_vendor = "apple")] pub fn apple_view() -> crate::native::apple::frameworks::ObjcId { - let d = native_display().lock().unwrap(); + let d = native_display_blocking(); d.view } #[cfg(target_os = "ios")] pub fn apple_view_ctrl() -> crate::native::apple::frameworks::ObjcId { - let d = native_display().lock().unwrap(); + let d = native_display_blocking(); d.view_ctrl } } diff --git a/src/native/android.rs b/src/native/android.rs index 6cab4fa8..27916aa6 100644 --- a/src/native/android.rs +++ b/src/native/android.rs @@ -198,7 +198,7 @@ impl MainThreadState { } { - let mut d = crate::native_display().lock().unwrap(); + let mut d = crate::native_display_blocking(); d.screen_width = width as _; d.screen_height = height as _; } diff --git a/src/native/ios.rs b/src/native/ios.rs index f600430c..478a9f5b 100644 --- a/src/native/ios.rs +++ b/src/native/ios.rs @@ -14,7 +14,7 @@ use { }, NativeDisplayData, }, - native_display, + native_display_blocking, }, std::{ cell::RefCell, @@ -143,7 +143,7 @@ pub fn define_glk_or_mtk_view(superclass: &Class) -> *const Class { let ios_touch: ObjcId = msg_send![enumerator, nextObject]; let mut ios_pos: NSPoint = msg_send![ios_touch, locationInView: this]; - if native_display().lock().unwrap().high_dpi { + if native_display_blocking().high_dpi { ios_pos.x *= 2.; ios_pos.y *= 2.; } else { @@ -317,7 +317,7 @@ pub fn define_glk_or_mtk_view_dlg(superclass: &Class) -> *const Class { let main_screen: ObjcId = unsafe { msg_send![class!(UIScreen), mainScreen] }; let screen_rect: NSRect = unsafe { msg_send![main_screen, bounds] }; - let high_dpi = native_display().lock().unwrap().high_dpi; + let high_dpi = native_display_blocking().high_dpi; let (screen_width, screen_height) = if high_dpi { ( @@ -332,11 +332,11 @@ pub fn define_glk_or_mtk_view_dlg(superclass: &Class) -> *const Class { ) }; - if native_display().lock().unwrap().screen_width != screen_width - || native_display().lock().unwrap().screen_height != screen_height + if native_display_blocking().screen_width != screen_width + || native_display_blocking().screen_height != screen_height { { - let mut d = native_display().lock().unwrap(); + let mut d = native_display_blocking(); d.screen_width = screen_width; d.screen_height = screen_height; } diff --git a/src/native/linux_wayland.rs b/src/native/linux_wayland.rs index b5b6b2d8..33bedaab 100644 --- a/src/native/linux_wayland.rs +++ b/src/native/linux_wayland.rs @@ -480,7 +480,7 @@ unsafe extern "C" fn xdg_toplevel_handle_configure( ) -> () { assert!(!data.is_null()); let payload: &mut WaylandPayload = &mut *(data as *mut _); - let mut d = crate::native_display().lock().unwrap(); + let mut d = crate::native_display_blocking(); if width != 0 && height != 0 { let (egl_w, egl_h) = if payload.decorations.is_some() { diff --git a/src/native/linux_x11.rs b/src/native/linux_x11.rs index 12aeea03..f7b6e9f5 100644 --- a/src/native/linux_x11.rs +++ b/src/native/linux_x11.rs @@ -132,7 +132,7 @@ impl X11Display { event_handler.window_minimized_event(); } 22 => { - let mut d = crate::native_display().try_lock().unwrap(); + let mut d = crate::native_display_nonblocking(); let left = (*event).xconfigure.x; let top = (*event).xconfigure.y; d.screen_position = (left as _, top as _); @@ -148,7 +148,7 @@ impl X11Display { } } 33 => { - let mut d = crate::native_display().try_lock().unwrap(); + let mut d = crate::native_display_nonblocking(); if (*event).xclient.message_type == self.libx11.extensions.wm_protocols { let protocol = (*event).xclient.data.l[0 as libc::c_int as usize] as Atom; if protocol == self.libx11.extensions.wm_delete_window { @@ -177,11 +177,11 @@ impl X11Display { _ => {} }; - let d = crate::native_display().try_lock().unwrap(); + let d = crate::native_display_nonblocking(); if d.quit_requested && !d.quit_ordered { drop(d); event_handler.quit_requested_event(); - let mut d = crate::native_display().try_lock().unwrap(); + let mut d = crate::native_display_nonblocking(); if d.quit_requested { d.quit_ordered = true } @@ -422,7 +422,7 @@ where let mut event_handler = (f.take().unwrap())(); - while !crate::native_display().try_lock().unwrap().quit_ordered { + while !crate::native_display_nonblocking().quit_ordered { while let Ok(request) = rx.try_recv() { display.process_request(request); } @@ -534,7 +534,7 @@ where let mut event_handler = (f.take().unwrap())(); - while !crate::native_display().try_lock().unwrap().quit_ordered { + while !crate::native_display_nonblocking().quit_ordered { while let Ok(request) = rx.try_recv() { display.process_request(request); } diff --git a/src/native/macos.rs b/src/native/macos.rs index 7865c885..68b29f62 100644 --- a/src/native/macos.rs +++ b/src/native/macos.rs @@ -10,7 +10,7 @@ use { apple::{apple_util::*, frameworks::*}, gl, NativeDisplayData, Request, }, - native_display, CursorIcon, + native_display_blocking, CursorIcon, }, std::{ collections::HashMap, @@ -135,7 +135,7 @@ impl MacosDisplay { impl MacosDisplay { fn transform_mouse_point(&self, point: &NSPoint) -> (f32, f32) { - let d = native_display().lock().unwrap(); + let d = native_display_blocking(); let new_x = point.x as f32 * d.dpi_scale; let new_y = d.screen_height as f32 - (point.y as f32 * d.dpi_scale) - 1.; @@ -155,7 +155,7 @@ impl MacosDisplay { } unsafe fn update_dimensions(&mut self) -> Option<(i32, i32)> { - let mut d = native_display().lock().unwrap(); + let mut d = native_display_blocking(); unsafe { if self.gl_context != nil { msg_send_![self.gl_context, update]; @@ -270,20 +270,20 @@ pub fn define_cocoa_window_delegate() -> *const Class { } // only give user-code a chance to intervene when sapp_quit() wasn't already called - if !native_display().lock().unwrap().quit_ordered { + if !native_display_blocking().quit_ordered { // if window should be closed and event handling is enabled, give user code // a chance to intervene via sapp_cancel_quit() - native_display().lock().unwrap().quit_requested = true; + native_display_blocking().quit_requested = true; if let Some(event_handler) = payload.context() { event_handler.quit_requested_event(); } // user code hasn't intervened, quit the app - if native_display().lock().unwrap().quit_requested { - native_display().lock().unwrap().quit_ordered = true; + if native_display_blocking().quit_requested { + native_display_blocking().quit_ordered = true; } } - if native_display().lock().unwrap().quit_ordered { + if native_display_blocking().quit_ordered { return YES; } else { return NO; @@ -965,7 +965,7 @@ unsafe fn perform_redraw( } { - let d = native_display().lock().unwrap(); + let d = native_display_blocking(); if d.quit_requested || d.quit_ordered { drop(d); let () = msg_send![display.window, performClose: nil]; @@ -1089,7 +1089,7 @@ where AppleGfxApi::Metal => create_metal_view(&mut display, conf.sample_count, conf.high_dpi), }; { - let mut d = native_display().lock().unwrap(); + let mut d = native_display_blocking(); d.view = view; } (*view).set_ivar("display_ptr", &mut display as *mut _ as *mut c_void); @@ -1147,13 +1147,13 @@ where let distant_future: ObjcId = msg_send![class!(NSDate), distantFuture]; let distant_past: ObjcId = msg_send![class!(NSDate), distantPast]; let mut done = false; - while !(done || crate::native_display().lock().unwrap().quit_ordered) { + while !(done || crate::native_display_blocking().quit_ordered) { while let Ok(request) = display.native_requests.try_recv() { display.process_request(request); } { - let d = native_display().lock().unwrap(); + let d = native_display_blocking(); if d.quit_requested || d.quit_ordered { done = true; } diff --git a/src/native/wasm.rs b/src/native/wasm.rs index 3ca4be42..94de803e 100644 --- a/src/native/wasm.rs +++ b/src/native/wasm.rs @@ -310,7 +310,7 @@ pub extern "C" fn key_up(key: u32, modifiers: u32) { #[no_mangle] pub extern "C" fn resize(width: i32, height: i32) { { - let mut d = crate::native_display().lock().unwrap(); + let mut d = crate::native_display_blocking(); d.screen_width = width as _; d.screen_height = height as _; } @@ -340,7 +340,7 @@ pub extern "C" fn focus(has_focus: bool) { #[no_mangle] pub extern "C" fn on_files_dropped_start() { - let mut d = crate::native_display().lock().unwrap(); + let mut d = crate::native_display_blocking(); d.dropped_files = Default::default(); } @@ -356,7 +356,7 @@ pub extern "C" fn on_file_dropped( bytes: *mut u8, bytes_len: usize, ) { - let mut d = crate::native_display().lock().unwrap(); + let mut d = crate::native_display_blocking(); let path = PathBuf::from(unsafe { String::from_raw_parts(path, path_len, path_len) }); let bytes = unsafe { Vec::from_raw_parts(bytes, bytes_len, bytes_len) }; diff --git a/src/native/windows.rs b/src/native/windows.rs index a420e820..a7278fa5 100644 --- a/src/native/windows.rs +++ b/src/native/windows.rs @@ -175,7 +175,7 @@ impl WindowsDisplay { ); } else { let (w, h) = { - let d = crate::native_display().lock().unwrap(); + let d = crate::native_display_blocking(); (d.screen_width, d.screen_height) }; @@ -284,7 +284,7 @@ unsafe extern "system" fn win32_wndproc( match umsg { WM_CLOSE => { - let mut d = crate::native_display().lock().unwrap(); + let mut d = crate::native_display_blocking(); // only give user a chance to intervene when sapp_quit() wasn't already called if !d.quit_ordered { // if window should be closed and event handling is enabled, give user code @@ -294,7 +294,7 @@ unsafe extern "system" fn win32_wndproc( // the prevent event may require access to native_display event_handler.quit_requested_event(); // Re-acquire native_display - d = crate::native_display().lock().unwrap(); + d = crate::native_display_blocking(); // if user code hasn't intervened, quit the app if d.quit_requested { d.quit_ordered = true; @@ -431,7 +431,7 @@ unsafe extern "system" fn win32_wndproc( // convert from normalised absolute coordinates if (data.data.mouse().usFlags & MOUSE_MOVE_ABSOLUTE) == MOUSE_MOVE_ABSOLUTE { let (width, height) = { - let d = crate::native_display().lock().unwrap(); + let d = crate::native_display_blocking(); (d.screen_width as f32, d.screen_height as f32) }; @@ -496,7 +496,7 @@ unsafe extern "system" fn win32_wndproc( SwapBuffers(payload.dc); if payload.update_dimensions(hwnd) { - let d = crate::native_display().lock().unwrap(); + let d = crate::native_display_blocking(); let width = d.screen_width as f32; let height = d.screen_height as f32; drop(d); @@ -752,7 +752,7 @@ impl WindowsDisplay { /// and window position from the window's rect. /// returns true if size or position has changed unsafe fn update_dimensions(&mut self, hwnd: HWND) -> bool { - let mut d = crate::native_display().lock().unwrap(); + let mut d = crate::native_display_blocking(); let mut rect: RECT = std::mem::zeroed(); // Get the outer rectangle of the window in screen coordinates @@ -921,7 +921,7 @@ where SetWindowLong(wnd, GWLP_USERDATA, &mut display as *mut _ as isize); let mut done = false; - while !(done || crate::native_display().lock().unwrap().quit_ordered) { + while !(done || crate::native_display_blocking().quit_ordered) { while let Ok(request) = rx.try_recv() { display.process_request(request); } @@ -954,7 +954,7 @@ where } if display.update_dimensions(wnd) { - let d = crate::native_display().lock().unwrap(); + let d = crate::native_display_blocking(); let width = d.screen_width as f32; let height = d.screen_height as f32; drop(d); @@ -964,7 +964,7 @@ where .unwrap() .resize_event(width, height); } - if crate::native_display().lock().unwrap().quit_requested { + if crate::native_display_blocking().quit_requested { PostMessageW(display.wnd, WM_CLOSE, 0, 0); } }