1#![warn(trivial_casts, trivial_numeric_casts, unused_qualifications)]
2
3use std::os::raw::c_char;
4
5use ash::{
6 ext::metal_surface,
7 khr::{android_surface, surface, wayland_surface, win32_surface, xcb_surface, xlib_surface},
8 prelude::*,
9 vk, Entry, Instance,
10};
11use raw_window_handle::{RawDisplayHandle, RawWindowHandle};
12
13pub unsafe fn create_surface(
37 entry: &Entry,
38 instance: &Instance,
39 display_handle: RawDisplayHandle,
40 window_handle: RawWindowHandle,
41 allocation_callbacks: Option<&vk::AllocationCallbacks<'_>>,
42) -> VkResult<vk::SurfaceKHR> {
43 match (display_handle, window_handle) {
44 (RawDisplayHandle::Windows(_), RawWindowHandle::Win32(window)) => {
45 let surface_desc = vk::Win32SurfaceCreateInfoKHR::default()
46 .hwnd(window.hwnd.get())
47 .hinstance(
48 window
49 .hinstance
50 .ok_or(vk::Result::ERROR_INITIALIZATION_FAILED)?
51 .get(),
52 );
53 let surface_fn = win32_surface::Instance::new(entry, instance);
54 surface_fn.create_win32_surface(&surface_desc, allocation_callbacks)
55 }
56
57 (RawDisplayHandle::Wayland(display), RawWindowHandle::Wayland(window)) => {
58 let surface_desc = vk::WaylandSurfaceCreateInfoKHR::default()
59 .display(display.display.as_ptr())
60 .surface(window.surface.as_ptr());
61 let surface_fn = wayland_surface::Instance::new(entry, instance);
62 surface_fn.create_wayland_surface(&surface_desc, allocation_callbacks)
63 }
64
65 (RawDisplayHandle::Xlib(display), RawWindowHandle::Xlib(window)) => {
66 let surface_desc = vk::XlibSurfaceCreateInfoKHR::default()
67 .dpy(
68 display
69 .display
70 .ok_or(vk::Result::ERROR_INITIALIZATION_FAILED)?
71 .as_ptr(),
72 )
73 .window(window.window);
74 let surface_fn = xlib_surface::Instance::new(entry, instance);
75 surface_fn.create_xlib_surface(&surface_desc, allocation_callbacks)
76 }
77
78 (RawDisplayHandle::Xcb(display), RawWindowHandle::Xcb(window)) => {
79 let surface_desc = vk::XcbSurfaceCreateInfoKHR::default()
80 .connection(
81 display
82 .connection
83 .ok_or(vk::Result::ERROR_INITIALIZATION_FAILED)?
84 .as_ptr(),
85 )
86 .window(window.window.get());
87 let surface_fn = xcb_surface::Instance::new(entry, instance);
88 surface_fn.create_xcb_surface(&surface_desc, allocation_callbacks)
89 }
90
91 (RawDisplayHandle::Android(_), RawWindowHandle::AndroidNdk(window)) => {
92 let surface_desc =
93 vk::AndroidSurfaceCreateInfoKHR::default().window(window.a_native_window.as_ptr());
94 let surface_fn = android_surface::Instance::new(entry, instance);
95 surface_fn.create_android_surface(&surface_desc, allocation_callbacks)
96 }
97
98 #[cfg(target_os = "macos")]
99 (RawDisplayHandle::AppKit(_), RawWindowHandle::AppKit(window)) => {
100 use raw_window_metal::{appkit, Layer};
101
102 let layer = match appkit::metal_layer_from_handle(window) {
103 Layer::Existing(layer) | Layer::Allocated(layer) => layer.cast(),
104 };
105
106 let surface_desc = vk::MetalSurfaceCreateInfoEXT::default().layer(&*layer);
107 let surface_fn = metal_surface::Instance::new(entry, instance);
108 surface_fn.create_metal_surface(&surface_desc, allocation_callbacks)
109 }
110
111 #[cfg(target_os = "ios")]
112 (RawDisplayHandle::UiKit(_), RawWindowHandle::UiKit(window)) => {
113 use raw_window_metal::{uikit, Layer};
114
115 let layer = match uikit::metal_layer_from_handle(window) {
116 Layer::Existing(layer) | Layer::Allocated(layer) => layer.cast(),
117 };
118
119 let surface_desc = vk::MetalSurfaceCreateInfoEXT::default().layer(&*layer);
120 let surface_fn = metal_surface::Instance::new(entry, instance);
121 surface_fn.create_metal_surface(&surface_desc, allocation_callbacks)
122 }
123
124 _ => Err(vk::Result::ERROR_EXTENSION_NOT_PRESENT),
125 }
126}
127
128pub fn enumerate_required_extensions(
136 display_handle: RawDisplayHandle,
137) -> VkResult<&'static [*const c_char]> {
138 let extensions = match display_handle {
139 RawDisplayHandle::Windows(_) => {
140 const WINDOWS_EXTS: [*const c_char; 2] =
141 [surface::NAME.as_ptr(), win32_surface::NAME.as_ptr()];
142 &WINDOWS_EXTS
143 }
144
145 RawDisplayHandle::Wayland(_) => {
146 const WAYLAND_EXTS: [*const c_char; 2] =
147 [surface::NAME.as_ptr(), wayland_surface::NAME.as_ptr()];
148 &WAYLAND_EXTS
149 }
150
151 RawDisplayHandle::Xlib(_) => {
152 const XLIB_EXTS: [*const c_char; 2] =
153 [surface::NAME.as_ptr(), xlib_surface::NAME.as_ptr()];
154 &XLIB_EXTS
155 }
156
157 RawDisplayHandle::Xcb(_) => {
158 const XCB_EXTS: [*const c_char; 2] =
159 [surface::NAME.as_ptr(), xcb_surface::NAME.as_ptr()];
160 &XCB_EXTS
161 }
162
163 RawDisplayHandle::Android(_) => {
164 const ANDROID_EXTS: [*const c_char; 2] =
165 [surface::NAME.as_ptr(), android_surface::NAME.as_ptr()];
166 &ANDROID_EXTS
167 }
168
169 RawDisplayHandle::AppKit(_) | RawDisplayHandle::UiKit(_) => {
170 const METAL_EXTS: [*const c_char; 2] =
171 [surface::NAME.as_ptr(), metal_surface::NAME.as_ptr()];
172 &METAL_EXTS
173 }
174
175 _ => return Err(vk::Result::ERROR_EXTENSION_NOT_PRESENT),
176 };
177
178 Ok(extensions)
179}