From fd63cab00863ec0fa2ea116be02569f47f724420 Mon Sep 17 00:00:00 2001 From: Noahnoah55 Date: Wed, 10 Apr 2024 22:27:30 -0400 Subject: [PATCH] Upgrade to raw-window-handle 0.6, imperfectly --- Cargo.toml | 4 +- examples/raw-window-handle-with-wgpu/main.rs | 17 +- src/sdl2/raw_window_handle.rs | 190 +++++++++++++------ tests/raw_window_handle.rs | 163 +++++++++------- 4 files changed, 238 insertions(+), 136 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ded08ca31e..afe5b2183a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,12 +31,12 @@ optional = true [dev-dependencies] rand = "0.7" -wgpu = { version = "0.15", features = ["spirv"] } +wgpu = { version = "0.19", features = ["spirv"] } pollster = "0.2.4" env_logger = "0.9.0" [dependencies.raw-window-handle] -version = "0.5.0" +version = "0.6.0" optional = true [features] diff --git a/examples/raw-window-handle-with-wgpu/main.rs b/examples/raw-window-handle-with-wgpu/main.rs index b096b5dede..a14598da40 100644 --- a/examples/raw-window-handle-with-wgpu/main.rs +++ b/examples/raw-window-handle-with-wgpu/main.rs @@ -27,9 +27,10 @@ fn main() -> Result<(), String> { let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { backends: wgpu::Backends::PRIMARY, dx12_shader_compiler: Default::default(), + ..Default::default() }); let surface = unsafe { - match instance.create_surface(&window) { + match instance.create_surface_unsafe(wgpu::SurfaceTargetUnsafe::from_window(&window).unwrap()) { Ok(s) => s, Err(e) => return Err(e.to_string()), } @@ -46,9 +47,9 @@ fn main() -> Result<(), String> { let (device, queue) = match pollster::block_on(adapter.request_device( &wgpu::DeviceDescriptor { - limits: wgpu::Limits::default(), + required_limits: wgpu::Limits::default(), label: Some("device"), - features: wgpu::Features::empty(), + required_features: wgpu::Features::empty(), }, None, )) { @@ -117,7 +118,7 @@ fn main() -> Result<(), String> { .formats .iter() .copied() - .find(|f| f.describe().srgb) + .find(|f| f.is_srgb()) .unwrap_or(surface_caps.formats[0]); let mut config = wgpu::SurfaceConfiguration { @@ -128,6 +129,7 @@ fn main() -> Result<(), String> { present_mode: wgpu::PresentMode::Fifo, alpha_mode: wgpu::CompositeAlphaMode::Auto, view_formats: Vec::default(), + desired_maximum_frame_latency: 2, }; surface.configure(&device, &config); @@ -166,7 +168,8 @@ fn main() -> Result<(), String> { SurfaceError::Lost => "Lost", SurfaceError::OutOfMemory => "OutOfMemory", }; - panic!("Failed to get current surface texture! Reason: {}", reason) + println!("Failed to get current surface texture! Reason: {}", reason); + continue 'running; } }; @@ -184,11 +187,13 @@ fn main() -> Result<(), String> { resolve_target: None, ops: wgpu::Operations { load: wgpu::LoadOp::Clear(wgpu::Color::GREEN), - store: true, + store: wgpu::StoreOp::Store, }, })], depth_stencil_attachment: None, label: None, + timestamp_writes: None, + occlusion_query_set: None, }); rpass.set_pipeline(&render_pipeline); rpass.set_bind_group(0, &bind_group, &[]); diff --git a/src/sdl2/raw_window_handle.rs b/src/sdl2/raw_window_handle.rs index fb88fc5d48..91c0b3c6a9 100644 --- a/src/sdl2/raw_window_handle.rs +++ b/src/sdl2/raw_window_handle.rs @@ -1,22 +1,23 @@ extern crate raw_window_handle; use self::raw_window_handle::{ - HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle, + RawDisplayHandle, RawWindowHandle, + HasWindowHandle, HasDisplayHandle, DisplayHandle, WindowHandle, HandleError }; use crate::{sys::SDL_Window, video::Window}; -unsafe impl HasRawWindowHandle for Window { - #[doc(alias = "SDL_GetVersion")] - fn raw_window_handle(&self) -> RawWindowHandle { +impl HasWindowHandle for Window { + fn window_handle(&self) -> Result, HandleError> { use self::SDL_SYSWM_TYPE::*; // Check if running on web before continuing, // since SDL_GetWindowWMInfo will fail on emscripten if cfg!(target_os = "emscripten") { use self::raw_window_handle::WebWindowHandle; - let mut handle = WebWindowHandle::empty(); - handle.id = 1; - return RawWindowHandle::Web(handle); + let handle = WebWindowHandle::new(1); + let handle = RawWindowHandle::Web(handle); + let handle = unsafe{WindowHandle::borrow_raw(handle)}; + return Ok(handle); } let mut wm_info: SDL_SysWMinfo = unsafe { std::mem::zeroed() }; @@ -35,20 +36,40 @@ unsafe impl HasRawWindowHandle for Window { SDL_SYSWM_WINDOWS => { use self::raw_window_handle::Win32WindowHandle; - let mut handle = Win32WindowHandle::empty(); - handle.hwnd = unsafe { wm_info.info.win }.window as *mut libc::c_void; - handle.hinstance = unsafe { wm_info.info.win }.hinstance as *mut libc::c_void; - - RawWindowHandle::Win32(handle) + let hwnd = unsafe { wm_info.info.win }.window as *mut isize; + let hwnd = core::num::NonZeroIsize::new(hwnd as isize); + let hwnd = match hwnd { + Some(hwnd) => hwnd, + None => { + return Err(HandleError::Unavailable); + } + }; + let mut handle = Win32WindowHandle::new(hwnd); + let hinstance = unsafe { wm_info.info.win }.hinstance as *mut libc::c_void; + let hinstance = core::num::NonZeroIsize::new(hinstance as isize); + handle.hinstance = hinstance; + + let handle = RawWindowHandle::Win32(handle); + let handle = unsafe {WindowHandle::borrow_raw(handle)}; + Ok(handle) } #[cfg(target_os = "windows")] SDL_SYSWM_WINRT => { use self::raw_window_handle::WinRtWindowHandle; - let mut handle = WinRtWindowHandle::empty(); - handle.core_window = unsafe { wm_info.info.winrt }.core_window; + let core_window = unsafe { wm_info.info.winrt }.core_window; + let core_window = core::ptr::NonNull::::new(core_window); + let core_window = match core_window { + Some(cw) => cw, + None => { + return Err(HandleError::Unavailable); + } + }; + let handle = WinRtWindowHandle::new(core_window); + let handle = RawWindowHandle::WinRt(handle); + let handle = unsafe {WindowHandle::borrow_raw(handle)}; - RawWindowHandle::WinRt(handle) + Ok(handle) } #[cfg(any( target_os = "linux", @@ -60,10 +81,21 @@ unsafe impl HasRawWindowHandle for Window { SDL_SYSWM_WAYLAND => { use self::raw_window_handle::WaylandWindowHandle; - let mut handle = WaylandWindowHandle::empty(); - handle.surface = unsafe { wm_info.info.wl }.surface as *mut libc::c_void; + let surf = unsafe {wm_info.info.wl}.surface as *mut libc::c_void; + let surf = core::ptr::NonNull::::new(surf); + + match surf { + Some(surf) => { + let handle = WaylandWindowHandle::new(surf); + let handle = RawWindowHandle::Wayland(handle); + let handle = unsafe {WindowHandle::borrow_raw(handle)}; + Ok(handle) + } + None => { + Err(HandleError::Unavailable) + } + } - RawWindowHandle::Wayland(handle) } #[cfg(any( target_os = "linux", @@ -75,44 +107,69 @@ unsafe impl HasRawWindowHandle for Window { SDL_SYSWM_X11 => { use self::raw_window_handle::XlibWindowHandle; - let mut handle = XlibWindowHandle::empty(); - handle.window = unsafe { wm_info.info.x11 }.window; + let window = unsafe { wm_info.info.x11 }.window; + let xlib_handle = XlibWindowHandle::new(window); + let raw_handle = RawWindowHandle::Xlib(xlib_handle); + let handle = unsafe{WindowHandle::borrow_raw(raw_handle)}; - RawWindowHandle::Xlib(handle) + Ok(handle) } #[cfg(target_os = "macos")] SDL_SYSWM_COCOA => { use self::raw_window_handle::AppKitWindowHandle; - let mut handle = AppKitWindowHandle::empty(); - handle.ns_window = unsafe { wm_info.info.cocoa }.window as *mut libc::c_void; - handle.ns_view = if self.context().metal_view.is_null() { - panic!("metal_view not initialized, please call WindowBuilder::metal_view() when building the window"); - } else { - self.context().metal_view + let ns_view = core::ptr::NonNull::::new(self.context().metal_view); + let ns_view = match ns_view { + Some(nv) => nv, + None => { + panic!("metal_view not initialized, please call WindowBuilder::metal_view() when building the window"); + } }; + + let handle = AppKitWindowHandle::new(ns_view); + let handle = RawWindowHandle::AppKit(handle); + let handle = unsafe {WindowHandle::borrow_raw(handle)}; - RawWindowHandle::AppKit(handle) + Ok(handle) } #[cfg(any(target_os = "ios"))] SDL_SYSWM_UIKIT => { use self::raw_window_handle::UiKitWindowHandle; - let mut handle = UiKitHandle::empty(); - handle.ui_window = unsafe { wm_info.info.uikit }.window as *mut libc::c_void; - handle.ui_view = 0 as *mut libc::c_void; // consumer of RawWindowHandle should determine this + let ui_window = unsafe { wm_info.info.uikit }.window as *mut libc::c_void; + let ui_window = core::ptr::NonNull::::new(ui_window); + let ui_window = match ui_window { + Some(uiw) => uiw, + None => { + return Err(HandleError::Unavailable); + } + }; - RawWindowHandle::UiKit(handle) + // https://developer.apple.com/documentation/uikit/uiwindow + // If this doesn't work then the actual fix is a lot more involved + // Someone with an IOS device please test + let handle = UiKitWindowHandle::new(ui_window); + let handle = RawWindowHandle::UiKit(handle); + let handle = unsafe {WindowHandle::borrow_raw(handle)}; + Ok(handle) } #[cfg(any(target_os = "android"))] SDL_SYSWM_ANDROID => { use self::raw_window_handle::AndroidNdkWindowHandle; - let mut handle = AndroidNdkWindowHandle::empty(); - handle.a_native_window = + let a_native_window = unsafe { wm_info.info.android }.window as *mut libc::c_void; - - RawWindowHandle::AndroidNdk(handle) + let a_native_window = core::ptr::NonNull::::new(a_native_window); + let a_native_window = match a_native_window { + Some(anw) => anw, + None => { + return Err(HandleError::Unavailable); + } + }; + let handle = AndroidNdkWindowHandle::new(a_native_window); + let handle = RawWindowHandle::AndroidNdk(handle); + let handle = unsafe{WindowHandle::borrow_raw(handle)}; + Ok(handle) } x => { let window_system = match x { @@ -127,17 +184,19 @@ unsafe impl HasRawWindowHandle for Window { } } -unsafe impl HasRawDisplayHandle for Window { +impl HasDisplayHandle for Window { #[doc(alias = "SDL_GetVersion")] - fn raw_display_handle(&self) -> RawDisplayHandle { + fn display_handle(&self) -> Result { use self::SDL_SYSWM_TYPE::*; // Check if running on web before continuing, // since SDL_GetWindowWMInfo will fail on emscripten if cfg!(target_os = "emscripten") { use self::raw_window_handle::WebDisplayHandle; - let handle = WebDisplayHandle::empty(); - return RawDisplayHandle::Web(handle); + let handle = WebDisplayHandle::new(); + let handle = RawDisplayHandle::Web(handle); + let handle = unsafe{DisplayHandle::borrow_raw(handle)}; + return Ok(handle); } let mut wm_info: SDL_SysWMinfo = unsafe { std::mem::zeroed() }; @@ -156,9 +215,11 @@ unsafe impl HasRawDisplayHandle for Window { SDL_SYSWM_WINDOWS | SDL_SYSWM_WINRT => { use self::raw_window_handle::WindowsDisplayHandle; - let handle = WindowsDisplayHandle::empty(); + let handle = WindowsDisplayHandle::new(); + let handle = RawDisplayHandle::Windows(handle); + let handle = unsafe {DisplayHandle::borrow_raw(handle)}; - RawDisplayHandle::Windows(handle) + Ok(handle) } #[cfg(any( target_os = "linux", @@ -170,10 +231,19 @@ unsafe impl HasRawDisplayHandle for Window { SDL_SYSWM_WAYLAND => { use self::raw_window_handle::WaylandDisplayHandle; - let mut handle = WaylandDisplayHandle::empty(); - handle.display = unsafe { wm_info.info.wl }.display as *mut libc::c_void; - - RawDisplayHandle::Wayland(handle) + let display = unsafe { wm_info.info.wl }.display as *mut libc::c_void; + let display = core::ptr::NonNull::::new(display); + match display { + Some(display) => { + let mut handle = WaylandDisplayHandle::new(display); + let handle = RawDisplayHandle::Wayland(handle); + let handle = unsafe{DisplayHandle::borrow_raw(handle)}; + Ok(handle) + } + None => { + Err(HandleError::Unavailable) + } + } } #[cfg(any( target_os = "linux", @@ -185,32 +255,42 @@ unsafe impl HasRawDisplayHandle for Window { SDL_SYSWM_X11 => { use self::raw_window_handle::XlibDisplayHandle; - let mut handle = XlibDisplayHandle::empty(); - handle.display = unsafe { wm_info.info.x11 }.display as *mut libc::c_void; + let display = unsafe { wm_info.info.x11 }.display as *mut libc::c_void; + let display = core::ptr::NonNull::::new(display); + let window = unsafe { wm_info.info.x11 }.window as i32; + let handle = XlibDisplayHandle::new(display, window); + let handle = RawDisplayHandle::Xlib(handle); + let handle = unsafe {DisplayHandle::borrow_raw(handle)}; - RawDisplayHandle::Xlib(handle) + Ok(handle) } #[cfg(target_os = "macos")] SDL_SYSWM_COCOA => { use self::raw_window_handle::AppKitDisplayHandle; - let handle = AppKitDisplayHandle::empty(); - RawDisplayHandle::AppKit(handle) + let handle = AppKitDisplayHandle::new(); + let handle = RawDisplayHandle::AppKit(handle); + let handle = unsafe {DisplayHandle::borrow_raw(handle)}; + Ok(handle) } #[cfg(any(target_os = "ios"))] SDL_SYSWM_UIKIT => { use self::raw_window_handle::UiKitDisplayHandle; - let handle = UiKitDisplayHandle::empty(); + let handle = UiKitDisplayHandle::new(); + let handle = RawDisplayHandle::UiKit(handle); + let handle = unsafe {DisplayHandle::borrow_raw(handle)}; - RawDisplayHandle::UiKit(handle) + Ok(handle) } #[cfg(any(target_os = "android"))] SDL_SYSWM_ANDROID => { use self::raw_window_handle::AndroidDisplayHandle; - let handle = AndroidDisplayHandle::empty(); + let handle = AndroidDisplayHandle::new(); + let handle = RawDisplayHandle::Android(handle); + let handle = unsafe {DisplayHandle::borrow_raw(handle)}; - RawDisplayHandle::Android(handle) + Ok(handle) } x => { let window_system = match x { diff --git a/tests/raw_window_handle.rs b/tests/raw_window_handle.rs index 2124e9f816..373fd1db81 100644 --- a/tests/raw_window_handle.rs +++ b/tests/raw_window_handle.rs @@ -4,7 +4,7 @@ mod raw_window_handle_test { extern crate sdl2; use self::raw_window_handle::{ - HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle, + HasDisplayHandle, HasWindowHandle, RawDisplayHandle, RawWindowHandle, }; use self::sdl2::video::Window; @@ -12,24 +12,38 @@ mod raw_window_handle_test { #[test] fn get_windows_handle() { let window = new_hidden_window(); - match window.raw_window_handle() { - RawWindowHandle::Win32(windows_handle) => { - assert_ne!(windows_handle.hwnd, 0 as *mut libc::c_void); - println!("Successfully received Windows RawWindowHandle!"); + match window.window_handle() { + Ok(window_handle) => { + match window_handle.as_raw() { + RawWindowHandle::Win32(_) => { + println!("Successfully received Win32 window handle") + }, + RawWindowHandle::WinRt(_) => { + println!("Successfully received WinRt window handle") + } + raw_handle => { + assert!(false, "Wrong window handle type for Windows: {:?}", raw_handle) + } + } + }, + Err(e) => { + assert!(false, "Failed to recieve window handle on Windows: {:?}", e) } - x => assert!( - false, - "Received wrong RawWindowHandle type for Windows: {:?}", - x - ), } - match window.raw_display_handle() { - RawDisplayHandle::Windows(_) => {} - x => assert!( - false, - "Received wrong RawDisplayHandle type for Windows: {:?}", - x - ), + match window.display_handle() { + Ok(display_handle) => { + match display_handle.as_raw() { + RawDisplayHandle::Windows(_) => { + println!("Successfully received Windows display handle") + }, + raw_handle => { + assert!(false, "Wrong display handle type for Windows: {:?}", raw_handle) + } + } + }, + Err(e) => { + assert!(false, "Failed to recieve display handle on Windows: {:?}", e) + } } } @@ -43,42 +57,41 @@ mod raw_window_handle_test { #[test] fn get_linux_handle() { let window = new_hidden_window(); - match window.raw_window_handle() { - RawWindowHandle::Xlib(x11_handle) => { - assert_ne!(x11_handle.window, 0, "Window for X11 should not be 0"); - println!("Successfully received linux X11 RawWindowHandle!"); - } - RawWindowHandle::Wayland(wayland_handle) => { - assert_ne!( - wayland_handle.surface, 0 as *mut libc::c_void, - "Surface for Wayland should not be null" - ); - println!("Successfully received linux Wayland RawWindowHandle!"); + match window.window_handle() { + Ok(handle) => { + match handle.as_raw() { + RawWindowHandle::Xlib(_) => { + println!("Successfully received X11 window handle") + } + RawWindowHandle::Wayland(_) => { + println!("Successfully received Wayland window handle") + } + raw_handle => { + assert!(false, "Wrong window handle type for Linux: {:?}", raw_handle) + } + } + }, + Err(e) => { + assert!(false, "Failed to recieve window handle on Linux: {:?}", e) } - x => assert!( - false, - "Received wrong RawWindowHandle type for linux: {:?}", - x - ), } - match window.raw_display_handle() { - RawDisplayHandle::Xlib(x11_display) => { - assert_ne!( - x11_display.display, 0 as *mut libc::c_void, - "Display for X11 should not be null" - ); - } - RawDisplayHandle::Wayland(wayland_display) => { - assert_ne!( - wayland_display.display, 0 as *mut libc::c_void, - "Display for Wayland should not be null" - ); + match window.display_handle() { + Ok(handle) => { + match handle.as_raw() { + RawDisplayHandle::Xlib(_) => { + println!("Successfully recieved X11 display handle") + } + RawDisplayHandle::Wayland(_) => { + println!("Successfully recieved Wayland display handle") + } + raw_handle => { + assert!(false, "Wrong display handle type for Linux: {:?}", raw_handle) + } + } } - x => assert!( - false, - "Received wrong RawDisplayHandle type for linux: {:?}", - x - ), + Err(e) => { + assert!(false, "Failed to recieve display handle on Linux: {:?}", e) + }, } } @@ -86,31 +99,35 @@ mod raw_window_handle_test { #[test] fn get_macos_handle() { let window = new_hidden_window(); - match window.raw_window_handle() { - RawWindowHandle::AppKit(macos_handle) => { - assert_ne!( - macos_handle.ns_window, 0 as *mut libc::c_void, - "ns_window should not be null" - ); - assert_ne!( - macos_handle.ns_view, 0 as *mut libc::c_void, - "nw_view should not be null" - ); - println!("Successfully received macOS RawWindowHandle!"); + match window.window_handle() { + Ok(handle) => { + match handle.as_raw() { + RawWindowHandle::AppKit(_) => { + println!("Successfully recieved AppKit window handle") + } + raw_handle => { + assert!(false, "Wrong window handle type for macOS: {:?}", raw_handle) + } + } + } + Err(e) => { + assert!(false, "Failed to recieve window handle on macOS: {:?}", e) } - x => assert!( - false, - "Received wrong RawWindowHandle type for macOS: {:?}", - x - ), }; - match window.raw_display_handle() { - RawDisplayHandle::AppKit(_) => {} - x => assert!( - false, - "Received wrong RawDisplayHandle type for macOS: {:?}", - x - ), + match window.display_handle() { + Ok(handle) => { + match handle.as_raw(){ + RawDisplayHandle::AppKit(_) => { + println!("Successfully recieved AppKit display handle") + } + raw_handle => { + assert!(false, "Wrong display handle type for macOS: {:?}", raw_handle) + } + } + }, + Err(e) => { + assert!(false, "Failed to recieve display handle on macOS: {:?}", e) + } } }