diff --git a/vulkano-win/src/raw_window_handle.rs b/vulkano-win/src/raw_window_handle.rs index 1b2fad81..1d208a78 100644 --- a/vulkano-win/src/raw_window_handle.rs +++ b/vulkano-win/src/raw_window_handle.rs @@ -11,8 +11,8 @@ use vulkano::{ swapchain::{Surface, SurfaceCreationError}, }; -/// Creates a vulkan surface from a generic window -/// which implements HasRawWindowHandle and thus can reveal the os-dependent handle. +/// Creates a Vulkan surface from a generic window which implements `HasRawWindowHandle` and thus +/// can reveal the OS-dependent handle. pub fn create_surface_from_handle( window: Arc, instance: Arc, @@ -75,3 +75,70 @@ pub fn create_surface_from_handle( } } } + +/// Creates a Vulkan surface from a generic window which implements `HasRawWindowHandle` and thus +/// can reveal the OS-dependent handle, without ensuring that the window outlives the surface. +/// +/// # Safety +/// +/// - The passed-in `window` must outlive the created [`Surface`]. +pub unsafe fn create_surface_from_handle_ref( + window: &(impl HasRawWindowHandle + HasRawDisplayHandle), + instance: Arc, +) -> Result, SurfaceCreationError> { + unsafe { + match window.raw_window_handle() { + RawWindowHandle::AndroidNdk(h) => { + Surface::from_android(instance, h.a_native_window, None) + } + RawWindowHandle::UiKit(_h) => { + #[cfg(target_os = "ios")] + { + // Ensure the layer is CAMetalLayer + let layer = get_metal_layer_ios(_h.ui_view); + Surface::from_ios(instance, layer, None) + } + #[cfg(not(target_os = "ios"))] + { + panic!("UiKit handle should only be used when target_os == 'ios'"); + } + } + RawWindowHandle::AppKit(_h) => { + #[cfg(target_os = "macos")] + { + // Ensure the layer is CAMetalLayer + let layer = get_metal_layer_macos(_h.ns_view); + Surface::from_mac_os(instance, layer as *const (), None) + } + #[cfg(not(target_os = "macos"))] + { + panic!("AppKit handle should only be used when target_os == 'macos'"); + } + } + RawWindowHandle::Wayland(h) => { + let d = match window.raw_display_handle() { + RawDisplayHandle::Wayland(d) => d, + _ => panic!("Invalid RawDisplayHandle"), + }; + Surface::from_wayland(instance, d.display, h.surface, None) + } + RawWindowHandle::Win32(h) => Surface::from_win32(instance, h.hinstance, h.hwnd, None), + RawWindowHandle::Xcb(h) => { + let d = match window.raw_display_handle() { + RawDisplayHandle::Xcb(d) => d, + _ => panic!("Invalid RawDisplayHandle"), + }; + Surface::from_xcb(instance, d.connection, h.window, None) + } + RawWindowHandle::Xlib(h) => { + let d = match window.raw_display_handle() { + RawDisplayHandle::Xlib(d) => d, + _ => panic!("Invalid RawDisplayHandle"), + }; + Surface::from_xlib(instance, d.display, h.window, None) + } + RawWindowHandle::Web(_) => unimplemented!(), + _ => unimplemented!(), + } + } +}