1 // Copyright (c) 2016 The vulkano developers
2 // Licensed under the Apache License, Version 2.0
3 // <LICENSE-APACHE or
4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT
5 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
6 // at your option. All files in the project carrying such
7 // notice may not be copied, modified, or distributed except
8 // according to those terms.
9 
10 use super::{FullScreenExclusive, Win32Monitor};
11 use crate::{
12     cache::OnceCache,
13     format::Format,
14     image::ImageUsage,
15     instance::Instance,
16     macros::{impl_id_counter, vulkan_bitflags_enum, vulkan_enum},
17     swapchain::{
18         display::{DisplayMode, DisplayPlane},
19         SurfaceSwapchainLock,
20     },
21     OomError, RequiresOneOf, VulkanError, VulkanObject,
22 };
23 
24 #[cfg(target_os = "ios")]
25 use objc::{class, msg_send, runtime::Object, sel, sel_impl};
26 
27 use std::{
28     any::Any,
29     error::Error,
30     fmt::{Debug, Display, Error as FmtError, Formatter},
31     mem::MaybeUninit,
32     num::NonZeroU64,
33     ptr,
34     sync::{atomic::AtomicBool, Arc},
35 };
36 
37 /// Represents a surface on the screen.
38 ///
39 /// Creating a `Surface` is platform-specific.
40 pub struct Surface {
41     handle: ash::vk::SurfaceKHR,
42     instance: Arc<Instance>,
43     id: NonZeroU64,
44     api: SurfaceApi,
45     object: Option<Arc<dyn Any + Send + Sync>>,
46     // If true, a swapchain has been associated to this surface, and that any new swapchain
47     // creation should be forbidden.
48     has_swapchain: AtomicBool,
49     #[cfg(target_os = "ios")]
50     metal_layer: IOSMetalLayer,
51 
52     // Data queried by the user at runtime, cached for faster lookups.
53     // This is stored here rather than on `PhysicalDevice` to ensure that it's freed when the
54     // `Surface` is destroyed.
55     pub(crate) surface_formats:
56         OnceCache<(ash::vk::PhysicalDevice, SurfaceInfo), Vec<(Format, ColorSpace)>>,
57     pub(crate) surface_present_modes: OnceCache<ash::vk::PhysicalDevice, Vec<PresentMode>>,
58     pub(crate) surface_support: OnceCache<(ash::vk::PhysicalDevice, u32), bool>,
59 }
60 
61 impl Surface {
62     /// Creates a `Surface` from a raw handle.
63     ///
64     /// # Safety
65     ///
66     /// - `handle` must be a valid Vulkan object handle created from `instance`.
67     /// - `handle` must have been created from `api`.
68     /// - The window object that `handle` was created from must outlive the created `Surface`.
69     ///   The `object` parameter can be used to ensure this.
from_handle( instance: Arc<Instance>, handle: ash::vk::SurfaceKHR, api: SurfaceApi, object: Option<Arc<dyn Any + Send + Sync>>, ) -> Self70     pub unsafe fn from_handle(
71         instance: Arc<Instance>,
72         handle: ash::vk::SurfaceKHR,
73         api: SurfaceApi,
74         object: Option<Arc<dyn Any + Send + Sync>>,
75     ) -> Self {
76         Surface {
77             handle,
78             instance,
79             id: Self::next_id(),
80             api,
81             object,
82             has_swapchain: AtomicBool::new(false),
83             #[cfg(target_os = "ios")]
84             metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()),
85             surface_formats: OnceCache::new(),
86             surface_present_modes: OnceCache::new(),
87             surface_support: OnceCache::new(),
88         }
89     }
90 
91     /// Creates a `Surface` with no backing window or display.
92     ///
93     /// Presenting to a headless surface does nothing, so this is mostly useless in itself. However,
94     /// it may be useful for testing, and it is available for future extensions to layer on top of.
headless( instance: Arc<Instance>, object: Option<Arc<dyn Any + Send + Sync>>, ) -> Result<Arc<Self>, SurfaceCreationError>95     pub fn headless(
96         instance: Arc<Instance>,
97         object: Option<Arc<dyn Any + Send + Sync>>,
98     ) -> Result<Arc<Self>, SurfaceCreationError> {
99         Self::validate_headless(&instance)?;
100 
101         unsafe { Ok(Self::headless_unchecked(instance, object)?) }
102     }
103 
validate_headless(instance: &Instance) -> Result<(), SurfaceCreationError>104     fn validate_headless(instance: &Instance) -> Result<(), SurfaceCreationError> {
105         if !instance.enabled_extensions().ext_headless_surface {
106             return Err(SurfaceCreationError::RequirementNotMet {
107                 required_for: "`Surface::headless`",
108                 requires_one_of: RequiresOneOf {
109                     instance_extensions: &["ext_headless_surface"],
110                     ..Default::default()
111                 },
112             });
113         }
114 
115         Ok(())
116     }
117 
118     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
headless_unchecked( instance: Arc<Instance>, object: Option<Arc<dyn Any + Send + Sync>>, ) -> Result<Arc<Self>, VulkanError>119     pub unsafe fn headless_unchecked(
120         instance: Arc<Instance>,
121         object: Option<Arc<dyn Any + Send + Sync>>,
122     ) -> Result<Arc<Self>, VulkanError> {
123         let create_info = ash::vk::HeadlessSurfaceCreateInfoEXT {
124             flags: ash::vk::HeadlessSurfaceCreateFlagsEXT::empty(),
125             ..Default::default()
126         };
127 
128         let handle = {
129             let fns = instance.fns();
130             let mut output = MaybeUninit::uninit();
131             (fns.ext_headless_surface.create_headless_surface_ext)(
132                 instance.handle(),
133                 &create_info,
134                 ptr::null(),
135                 output.as_mut_ptr(),
136             )
137             .result()
138             .map_err(VulkanError::from)?;
139             output.assume_init()
140         };
141 
142         Ok(Arc::new(Self::from_handle(
143             instance,
144             handle,
145             SurfaceApi::Headless,
146             object,
147         )))
148     }
149 
150     /// Creates a `Surface` from a `DisplayPlane`.
151     ///
152     /// # Panics
153     ///
154     /// - Panics if `display_mode` and `plane` don't belong to the same physical device.
155     /// - Panics if `plane` doesn't support the display of `display_mode`.
from_display_plane( display_mode: &DisplayMode, plane: &DisplayPlane, ) -> Result<Arc<Self>, SurfaceCreationError>156     pub fn from_display_plane(
157         display_mode: &DisplayMode,
158         plane: &DisplayPlane,
159     ) -> Result<Arc<Self>, SurfaceCreationError> {
160         Self::validate_from_display_plane(display_mode, plane)?;
161 
162         unsafe { Ok(Self::from_display_plane_unchecked(display_mode, plane)?) }
163     }
164 
validate_from_display_plane( display_mode: &DisplayMode, plane: &DisplayPlane, ) -> Result<(), SurfaceCreationError>165     fn validate_from_display_plane(
166         display_mode: &DisplayMode,
167         plane: &DisplayPlane,
168     ) -> Result<(), SurfaceCreationError> {
169         if !display_mode
170             .display()
171             .physical_device()
172             .instance()
173             .enabled_extensions()
174             .khr_display
175         {
176             return Err(SurfaceCreationError::RequirementNotMet {
177                 required_for: "`Surface::from_display_plane`",
178                 requires_one_of: RequiresOneOf {
179                     instance_extensions: &["khr_display"],
180                     ..Default::default()
181                 },
182             });
183         }
184 
185         assert_eq!(
186             display_mode.display().physical_device(),
187             plane.physical_device()
188         );
189         assert!(plane.supports(display_mode.display()));
190 
191         Ok(())
192     }
193 
194     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
from_display_plane_unchecked( display_mode: &DisplayMode, plane: &DisplayPlane, ) -> Result<Arc<Self>, VulkanError>195     pub unsafe fn from_display_plane_unchecked(
196         display_mode: &DisplayMode,
197         plane: &DisplayPlane,
198     ) -> Result<Arc<Self>, VulkanError> {
199         let instance = display_mode.display().physical_device().instance();
200 
201         let create_info = ash::vk::DisplaySurfaceCreateInfoKHR {
202             flags: ash::vk::DisplaySurfaceCreateFlagsKHR::empty(),
203             display_mode: display_mode.handle(),
204             plane_index: plane.index(),
205             plane_stack_index: 0, // FIXME: plane.properties.currentStackIndex,
206             transform: ash::vk::SurfaceTransformFlagsKHR::IDENTITY, // TODO: let user choose
207             global_alpha: 0.0,    // TODO: let user choose
208             alpha_mode: ash::vk::DisplayPlaneAlphaFlagsKHR::OPAQUE, // TODO: let user choose
209             image_extent: ash::vk::Extent2D {
210                 // TODO: let user choose
211                 width: display_mode.visible_region()[0],
212                 height: display_mode.visible_region()[1],
213             },
214             ..Default::default()
215         };
216 
217         let handle = {
218             let fns = instance.fns();
219             let mut output = MaybeUninit::uninit();
220             (fns.khr_display.create_display_plane_surface_khr)(
221                 instance.handle(),
222                 &create_info,
223                 ptr::null(),
224                 output.as_mut_ptr(),
225             )
226             .result()
227             .map_err(VulkanError::from)?;
228             output.assume_init()
229         };
230 
231         Ok(Arc::new(Self::from_handle(
232             instance.clone(),
233             handle,
234             SurfaceApi::DisplayPlane,
235             None,
236         )))
237     }
238 
239     /// Creates a `Surface` from an Android window.
240     ///
241     /// # Safety
242     ///
243     /// - `window` must be a valid Android `ANativeWindow` handle.
244     /// - The object referred to by `window` must outlive the created `Surface`.
245     ///   The `object` parameter can be used to ensure this.
from_android<W>( instance: Arc<Instance>, window: *const W, object: Option<Arc<dyn Any + Send + Sync>>, ) -> Result<Arc<Self>, SurfaceCreationError>246     pub unsafe fn from_android<W>(
247         instance: Arc<Instance>,
248         window: *const W,
249         object: Option<Arc<dyn Any + Send + Sync>>,
250     ) -> Result<Arc<Self>, SurfaceCreationError> {
251         Self::validate_from_android(&instance, window)?;
252 
253         Ok(Self::from_android_unchecked(instance, window, object)?)
254     }
255 
validate_from_android<W>( instance: &Instance, _window: *const W, ) -> Result<(), SurfaceCreationError>256     fn validate_from_android<W>(
257         instance: &Instance,
258         _window: *const W,
259     ) -> Result<(), SurfaceCreationError> {
260         if !instance.enabled_extensions().khr_android_surface {
261             return Err(SurfaceCreationError::RequirementNotMet {
262                 required_for: "`Surface::from_android`",
263                 requires_one_of: RequiresOneOf {
264                     instance_extensions: &["khr_android_surface"],
265                     ..Default::default()
266                 },
267             });
268         }
269 
270         // VUID-VkAndroidSurfaceCreateInfoKHR-window-01248
271         // Can't validate, therefore unsafe
272 
273         Ok(())
274     }
275 
276     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
from_android_unchecked<W>( instance: Arc<Instance>, window: *const W, object: Option<Arc<dyn Any + Send + Sync>>, ) -> Result<Arc<Self>, VulkanError>277     pub unsafe fn from_android_unchecked<W>(
278         instance: Arc<Instance>,
279         window: *const W,
280         object: Option<Arc<dyn Any + Send + Sync>>,
281     ) -> Result<Arc<Self>, VulkanError> {
282         let create_info = ash::vk::AndroidSurfaceCreateInfoKHR {
283             flags: ash::vk::AndroidSurfaceCreateFlagsKHR::empty(),
284             window: window as *mut _,
285             ..Default::default()
286         };
287 
288         let handle = {
289             let fns = instance.fns();
290             let mut output = MaybeUninit::uninit();
291             (fns.khr_android_surface.create_android_surface_khr)(
292                 instance.handle(),
293                 &create_info,
294                 ptr::null(),
295                 output.as_mut_ptr(),
296             )
297             .result()
298             .map_err(VulkanError::from)?;
299             output.assume_init()
300         };
301 
302         Ok(Arc::new(Self::from_handle(
303             instance,
304             handle,
305             SurfaceApi::Android,
306             object,
307         )))
308     }
309 
310     /// Creates a `Surface` from a DirectFB surface.
311     ///
312     /// # Safety
313     ///
314     /// - `dfb` must be a valid DirectFB `IDirectFB` handle.
315     /// - `surface` must be a valid DirectFB `IDirectFBSurface` handle.
316     /// - The object referred to by `dfb` and `surface` must outlive the created `Surface`.
317     ///   The `object` parameter can be used to ensure this.
from_directfb<D, S>( instance: Arc<Instance>, dfb: *const D, surface: *const S, object: Option<Arc<dyn Any + Send + Sync>>, ) -> Result<Arc<Self>, SurfaceCreationError>318     pub unsafe fn from_directfb<D, S>(
319         instance: Arc<Instance>,
320         dfb: *const D,
321         surface: *const S,
322         object: Option<Arc<dyn Any + Send + Sync>>,
323     ) -> Result<Arc<Self>, SurfaceCreationError> {
324         Self::validate_from_directfb(&instance, dfb, surface)?;
325 
326         Ok(Self::from_directfb_unchecked(
327             instance, dfb, surface, object,
328         )?)
329     }
330 
validate_from_directfb<D, S>( instance: &Instance, _dfb: *const D, _surface: *const S, ) -> Result<(), SurfaceCreationError>331     fn validate_from_directfb<D, S>(
332         instance: &Instance,
333         _dfb: *const D,
334         _surface: *const S,
335     ) -> Result<(), SurfaceCreationError> {
336         if !instance.enabled_extensions().ext_directfb_surface {
337             return Err(SurfaceCreationError::RequirementNotMet {
338                 required_for: "`Surface::from_directfb`",
339                 requires_one_of: RequiresOneOf {
340                     instance_extensions: &["ext_directfb_surface"],
341                     ..Default::default()
342                 },
343             });
344         }
345 
346         // VUID-VkDirectFBSurfaceCreateInfoEXT-dfb-04117
347         // Can't validate, therefore unsafe
348 
349         // VUID-VkDirectFBSurfaceCreateInfoEXT-surface-04118
350         // Can't validate, therefore unsafe
351 
352         Ok(())
353     }
354 
355     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
from_directfb_unchecked<D, S>( instance: Arc<Instance>, dfb: *const D, surface: *const S, object: Option<Arc<dyn Any + Send + Sync>>, ) -> Result<Arc<Self>, VulkanError>356     pub unsafe fn from_directfb_unchecked<D, S>(
357         instance: Arc<Instance>,
358         dfb: *const D,
359         surface: *const S,
360         object: Option<Arc<dyn Any + Send + Sync>>,
361     ) -> Result<Arc<Self>, VulkanError> {
362         let create_info = ash::vk::DirectFBSurfaceCreateInfoEXT {
363             flags: ash::vk::DirectFBSurfaceCreateFlagsEXT::empty(),
364             dfb: dfb as *mut _,
365             surface: surface as *mut _,
366             ..Default::default()
367         };
368 
369         let handle = {
370             let fns = instance.fns();
371             let mut output = MaybeUninit::uninit();
372             (fns.ext_directfb_surface.create_direct_fb_surface_ext)(
373                 instance.handle(),
374                 &create_info,
375                 ptr::null(),
376                 output.as_mut_ptr(),
377             )
378             .result()
379             .map_err(VulkanError::from)?;
380             output.assume_init()
381         };
382 
383         Ok(Arc::new(Self::from_handle(
384             instance,
385             handle,
386             SurfaceApi::DirectFB,
387             object,
388         )))
389     }
390 
391     /// Creates a `Surface` from an Fuchsia ImagePipe.
392     ///
393     /// # Safety
394     ///
395     /// - `image_pipe_handle` must be a valid Fuchsia `zx_handle_t` handle.
396     /// - The object referred to by `image_pipe_handle` must outlive the created `Surface`.
397     ///   The `object` parameter can be used to ensure this.
from_fuchsia_image_pipe( instance: Arc<Instance>, image_pipe_handle: ash::vk::zx_handle_t, object: Option<Arc<dyn Any + Send + Sync>>, ) -> Result<Arc<Self>, SurfaceCreationError>398     pub unsafe fn from_fuchsia_image_pipe(
399         instance: Arc<Instance>,
400         image_pipe_handle: ash::vk::zx_handle_t,
401         object: Option<Arc<dyn Any + Send + Sync>>,
402     ) -> Result<Arc<Self>, SurfaceCreationError> {
403         Self::validate_from_fuchsia_image_pipe(&instance, image_pipe_handle)?;
404 
405         Ok(Self::from_fuchsia_image_pipe_unchecked(
406             instance,
407             image_pipe_handle,
408             object,
409         )?)
410     }
411 
validate_from_fuchsia_image_pipe( instance: &Instance, _image_pipe_handle: ash::vk::zx_handle_t, ) -> Result<(), SurfaceCreationError>412     fn validate_from_fuchsia_image_pipe(
413         instance: &Instance,
414         _image_pipe_handle: ash::vk::zx_handle_t,
415     ) -> Result<(), SurfaceCreationError> {
416         if !instance.enabled_extensions().fuchsia_imagepipe_surface {
417             return Err(SurfaceCreationError::RequirementNotMet {
418                 required_for: "`Surface::from_fuchsia_image_pipe`",
419                 requires_one_of: RequiresOneOf {
420                     instance_extensions: &["fuchsia_imagepipe_surface"],
421                     ..Default::default()
422                 },
423             });
424         }
425 
426         // VUID-VkImagePipeSurfaceCreateInfoFUCHSIA-imagePipeHandle-04863
427         // Can't validate, therefore unsafe
428 
429         Ok(())
430     }
431 
432     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
from_fuchsia_image_pipe_unchecked( instance: Arc<Instance>, image_pipe_handle: ash::vk::zx_handle_t, object: Option<Arc<dyn Any + Send + Sync>>, ) -> Result<Arc<Self>, VulkanError>433     pub unsafe fn from_fuchsia_image_pipe_unchecked(
434         instance: Arc<Instance>,
435         image_pipe_handle: ash::vk::zx_handle_t,
436         object: Option<Arc<dyn Any + Send + Sync>>,
437     ) -> Result<Arc<Self>, VulkanError> {
438         let create_info = ash::vk::ImagePipeSurfaceCreateInfoFUCHSIA {
439             flags: ash::vk::ImagePipeSurfaceCreateFlagsFUCHSIA::empty(),
440             image_pipe_handle,
441             ..Default::default()
442         };
443 
444         let handle = {
445             let fns = instance.fns();
446             let mut output = MaybeUninit::uninit();
447             (fns.fuchsia_imagepipe_surface
448                 .create_image_pipe_surface_fuchsia)(
449                 instance.handle(),
450                 &create_info,
451                 ptr::null(),
452                 output.as_mut_ptr(),
453             )
454             .result()
455             .map_err(VulkanError::from)?;
456             output.assume_init()
457         };
458 
459         Ok(Arc::new(Self::from_handle(
460             instance,
461             handle,
462             SurfaceApi::FuchsiaImagePipe,
463             object,
464         )))
465     }
466 
467     /// Creates a `Surface` from a Google Games Platform stream descriptor.
468     ///
469     /// # Safety
470     ///
471     /// - `stream_descriptor` must be a valid Google Games Platform `GgpStreamDescriptor` handle.
472     /// - The object referred to by `stream_descriptor` must outlive the created `Surface`.
473     ///   The `object` parameter can be used to ensure this.
from_ggp_stream_descriptor( instance: Arc<Instance>, stream_descriptor: ash::vk::GgpStreamDescriptor, object: Option<Arc<dyn Any + Send + Sync>>, ) -> Result<Arc<Self>, SurfaceCreationError>474     pub unsafe fn from_ggp_stream_descriptor(
475         instance: Arc<Instance>,
476         stream_descriptor: ash::vk::GgpStreamDescriptor,
477         object: Option<Arc<dyn Any + Send + Sync>>,
478     ) -> Result<Arc<Self>, SurfaceCreationError> {
479         Self::validate_from_ggp_stream_descriptor(&instance, stream_descriptor)?;
480 
481         Ok(Self::from_ggp_stream_descriptor_unchecked(
482             instance,
483             stream_descriptor,
484             object,
485         )?)
486     }
487 
validate_from_ggp_stream_descriptor( instance: &Instance, _stream_descriptor: ash::vk::GgpStreamDescriptor, ) -> Result<(), SurfaceCreationError>488     fn validate_from_ggp_stream_descriptor(
489         instance: &Instance,
490         _stream_descriptor: ash::vk::GgpStreamDescriptor,
491     ) -> Result<(), SurfaceCreationError> {
492         if !instance.enabled_extensions().ggp_stream_descriptor_surface {
493             return Err(SurfaceCreationError::RequirementNotMet {
494                 required_for: "`Surface::from_ggp_stream_descriptor`",
495                 requires_one_of: RequiresOneOf {
496                     instance_extensions: &["ggp_stream_descriptor_surface"],
497                     ..Default::default()
498                 },
499             });
500         }
501 
502         // VUID-VkStreamDescriptorSurfaceCreateInfoGGP-streamDescriptor-02681
503         // Can't validate, therefore unsafe
504 
505         Ok(())
506     }
507 
508     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
from_ggp_stream_descriptor_unchecked( instance: Arc<Instance>, stream_descriptor: ash::vk::GgpStreamDescriptor, object: Option<Arc<dyn Any + Send + Sync>>, ) -> Result<Arc<Self>, VulkanError>509     pub unsafe fn from_ggp_stream_descriptor_unchecked(
510         instance: Arc<Instance>,
511         stream_descriptor: ash::vk::GgpStreamDescriptor,
512         object: Option<Arc<dyn Any + Send + Sync>>,
513     ) -> Result<Arc<Self>, VulkanError> {
514         let create_info = ash::vk::StreamDescriptorSurfaceCreateInfoGGP {
515             flags: ash::vk::StreamDescriptorSurfaceCreateFlagsGGP::empty(),
516             stream_descriptor,
517             ..Default::default()
518         };
519 
520         let handle = {
521             let fns = instance.fns();
522             let mut output = MaybeUninit::uninit();
523             (fns.ggp_stream_descriptor_surface
524                 .create_stream_descriptor_surface_ggp)(
525                 instance.handle(),
526                 &create_info,
527                 ptr::null(),
528                 output.as_mut_ptr(),
529             )
530             .result()
531             .map_err(VulkanError::from)?;
532             output.assume_init()
533         };
534 
535         Ok(Arc::new(Self::from_handle(
536             instance,
537             handle,
538             SurfaceApi::GgpStreamDescriptor,
539             object,
540         )))
541     }
542 
543     /// Creates a `Surface` from an iOS `UIView`.
544     ///
545     /// # Safety
546     ///
547     /// - `metal_layer` must be a valid `IOSMetalLayer` handle.
548     /// - The object referred to by `metal_layer` must outlive the created `Surface`.
549     ///   The `object` parameter can be used to ensure this.
550     /// - The `UIView` must be backed by a `CALayer` instance of type `CAMetalLayer`.
551     #[cfg(target_os = "ios")]
from_ios( instance: Arc<Instance>, metal_layer: IOSMetalLayer, object: Option<Arc<dyn Any + Send + Sync>>, ) -> Result<Arc<Self>, SurfaceCreationError>552     pub unsafe fn from_ios(
553         instance: Arc<Instance>,
554         metal_layer: IOSMetalLayer,
555         object: Option<Arc<dyn Any + Send + Sync>>,
556     ) -> Result<Arc<Self>, SurfaceCreationError> {
557         Self::validate_from_ios(&instance, &metal_layer)?;
558 
559         Ok(Self::from_ios_unchecked(instance, metal_layer, object)?)
560     }
561 
562     #[cfg(target_os = "ios")]
validate_from_ios( instance: &Instance, _metal_layer: &IOSMetalLayer, ) -> Result<(), SurfaceCreationError>563     fn validate_from_ios(
564         instance: &Instance,
565         _metal_layer: &IOSMetalLayer,
566     ) -> Result<(), SurfaceCreationError> {
567         if !instance.enabled_extensions().mvk_ios_surface {
568             return Err(SurfaceCreationError::RequirementNotMet {
569                 required_for: "`Surface::from_ios`",
570                 requires_one_of: RequiresOneOf {
571                     instance_extensions: &["mvk_ios_surface"],
572                     ..Default::default()
573                 },
574             });
575         }
576 
577         // VUID-VkIOSSurfaceCreateInfoMVK-pView-04143
578         // Can't validate, therefore unsafe
579 
580         // VUID-VkIOSSurfaceCreateInfoMVK-pView-01316
581         // Can't validate, therefore unsafe
582 
583         Ok(())
584     }
585 
586     #[cfg(target_os = "ios")]
587     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
from_ios_unchecked( instance: Arc<Instance>, metal_layer: IOSMetalLayer, object: Option<Arc<dyn Any + Send + Sync>>, ) -> Result<Arc<Self>, VulkanError>588     pub unsafe fn from_ios_unchecked(
589         instance: Arc<Instance>,
590         metal_layer: IOSMetalLayer,
591         object: Option<Arc<dyn Any + Send + Sync>>,
592     ) -> Result<Arc<Self>, VulkanError> {
593         let create_info = ash::vk::IOSSurfaceCreateInfoMVK {
594             flags: ash::vk::IOSSurfaceCreateFlagsMVK::empty(),
595             p_view: metal_layer.render_layer.0 as *const _,
596             ..Default::default()
597         };
598 
599         let handle = {
600             let fns = instance.fns();
601             let mut output = MaybeUninit::uninit();
602             (fns.mvk_ios_surface.create_ios_surface_mvk)(
603                 instance.handle(),
604                 &create_info,
605                 ptr::null(),
606                 output.as_mut_ptr(),
607             )
608             .result()
609             .map_err(VulkanError::from)?;
610             output.assume_init()
611         };
612 
613         Ok(Arc::new(Self::from_handle(
614             instance,
615             handle,
616             SurfaceApi::Ios,
617             object,
618         )))
619     }
620 
621     /// Creates a `Surface` from a MacOS `NSView`.
622     ///
623     /// # Safety
624     ///
625     /// - `view` must be a valid `CAMetalLayer` or `NSView` handle.
626     /// - The object referred to by `view` must outlive the created `Surface`.
627     ///   The `object` parameter can be used to ensure this.
628     /// - The `NSView` must be backed by a `CALayer` instance of type `CAMetalLayer`.
629     #[cfg(target_os = "macos")]
from_mac_os<V>( instance: Arc<Instance>, view: *const V, object: Option<Arc<dyn Any + Send + Sync>>, ) -> Result<Arc<Self>, SurfaceCreationError>630     pub unsafe fn from_mac_os<V>(
631         instance: Arc<Instance>,
632         view: *const V,
633         object: Option<Arc<dyn Any + Send + Sync>>,
634     ) -> Result<Arc<Self>, SurfaceCreationError> {
635         Self::validate_from_mac_os(&instance, view)?;
636 
637         Ok(Self::from_mac_os_unchecked(instance, view, object)?)
638     }
639 
640     #[cfg(target_os = "macos")]
validate_from_mac_os<V>( instance: &Instance, _view: *const V, ) -> Result<(), SurfaceCreationError>641     fn validate_from_mac_os<V>(
642         instance: &Instance,
643         _view: *const V,
644     ) -> Result<(), SurfaceCreationError> {
645         if !instance.enabled_extensions().mvk_macos_surface {
646             return Err(SurfaceCreationError::RequirementNotMet {
647                 required_for: "`Surface::from_mac_os`",
648                 requires_one_of: RequiresOneOf {
649                     instance_extensions: &["mvk_macos_surface"],
650                     ..Default::default()
651                 },
652             });
653         }
654 
655         // VUID-VkMacOSSurfaceCreateInfoMVK-pView-04144
656         // Can't validate, therefore unsafe
657 
658         // VUID-VkMacOSSurfaceCreateInfoMVK-pView-01317
659         // Can't validate, therefore unsafe
660 
661         Ok(())
662     }
663 
664     #[cfg(target_os = "macos")]
665     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
from_mac_os_unchecked<V>( instance: Arc<Instance>, view: *const V, object: Option<Arc<dyn Any + Send + Sync>>, ) -> Result<Arc<Self>, VulkanError>666     pub unsafe fn from_mac_os_unchecked<V>(
667         instance: Arc<Instance>,
668         view: *const V,
669         object: Option<Arc<dyn Any + Send + Sync>>,
670     ) -> Result<Arc<Self>, VulkanError> {
671         let create_info = ash::vk::MacOSSurfaceCreateInfoMVK {
672             flags: ash::vk::MacOSSurfaceCreateFlagsMVK::empty(),
673             p_view: view as *const _,
674             ..Default::default()
675         };
676 
677         let handle = {
678             let fns = instance.fns();
679             let mut output = MaybeUninit::uninit();
680             (fns.mvk_macos_surface.create_mac_os_surface_mvk)(
681                 instance.handle(),
682                 &create_info,
683                 ptr::null(),
684                 output.as_mut_ptr(),
685             )
686             .result()
687             .map_err(VulkanError::from)?;
688             output.assume_init()
689         };
690 
691         Ok(Arc::new(Self::from_handle(
692             instance,
693             handle,
694             SurfaceApi::MacOs,
695             object,
696         )))
697     }
698 
699     /// Creates a `Surface` from a Metal `CAMetalLayer`.
700     ///
701     /// # Safety
702     ///
703     /// - `layer` must be a valid Metal `CAMetalLayer` handle.
704     /// - The object referred to by `layer` must outlive the created `Surface`.
705     ///   The `object` parameter can be used to ensure this.
from_metal<L>( instance: Arc<Instance>, layer: *const L, object: Option<Arc<dyn Any + Send + Sync>>, ) -> Result<Arc<Self>, SurfaceCreationError>706     pub unsafe fn from_metal<L>(
707         instance: Arc<Instance>,
708         layer: *const L,
709         object: Option<Arc<dyn Any + Send + Sync>>,
710     ) -> Result<Arc<Self>, SurfaceCreationError> {
711         Self::validate_from_metal(&instance, layer)?;
712 
713         Ok(Self::from_metal_unchecked(instance, layer, object)?)
714     }
715 
validate_from_metal<L>( instance: &Instance, _layer: *const L, ) -> Result<(), SurfaceCreationError>716     fn validate_from_metal<L>(
717         instance: &Instance,
718         _layer: *const L,
719     ) -> Result<(), SurfaceCreationError> {
720         if !instance.enabled_extensions().ext_metal_surface {
721             return Err(SurfaceCreationError::RequirementNotMet {
722                 required_for: "`Surface::from_metal`",
723                 requires_one_of: RequiresOneOf {
724                     instance_extensions: &["ext_metal_surface"],
725                     ..Default::default()
726                 },
727             });
728         }
729 
730         Ok(())
731     }
732 
733     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
from_metal_unchecked<L>( instance: Arc<Instance>, layer: *const L, object: Option<Arc<dyn Any + Send + Sync>>, ) -> Result<Arc<Self>, VulkanError>734     pub unsafe fn from_metal_unchecked<L>(
735         instance: Arc<Instance>,
736         layer: *const L,
737         object: Option<Arc<dyn Any + Send + Sync>>,
738     ) -> Result<Arc<Self>, VulkanError> {
739         let create_info = ash::vk::MetalSurfaceCreateInfoEXT {
740             flags: ash::vk::MetalSurfaceCreateFlagsEXT::empty(),
741             p_layer: layer as *const _,
742             ..Default::default()
743         };
744 
745         let handle = {
746             let fns = instance.fns();
747             let mut output = MaybeUninit::uninit();
748             (fns.ext_metal_surface.create_metal_surface_ext)(
749                 instance.handle(),
750                 &create_info,
751                 ptr::null(),
752                 output.as_mut_ptr(),
753             )
754             .result()
755             .map_err(VulkanError::from)?;
756             output.assume_init()
757         };
758 
759         Ok(Arc::new(Self::from_handle(
760             instance,
761             handle,
762             SurfaceApi::Metal,
763             object,
764         )))
765     }
766 
767     /// Creates a `Surface` from a QNX Screen window.
768     ///
769     /// # Safety
770     ///
771     /// - `context` must be a valid QNX Screen `_screen_context` handle.
772     /// - `window` must be a valid QNX Screen `_screen_window` handle.
773     /// - The object referred to by `window` must outlive the created `Surface`.
774     ///   The `object` parameter can be used to ensure this.
from_qnx_screen<C, W>( instance: Arc<Instance>, context: *const C, window: *const W, object: Option<Arc<dyn Any + Send + Sync>>, ) -> Result<Arc<Self>, SurfaceCreationError>775     pub unsafe fn from_qnx_screen<C, W>(
776         instance: Arc<Instance>,
777         context: *const C,
778         window: *const W,
779         object: Option<Arc<dyn Any + Send + Sync>>,
780     ) -> Result<Arc<Self>, SurfaceCreationError> {
781         Self::validate_from_qnx_screen(&instance, context, window)?;
782 
783         Ok(Self::from_qnx_screen_unchecked(
784             instance, context, window, object,
785         )?)
786     }
787 
validate_from_qnx_screen<C, W>( instance: &Instance, _context: *const C, _window: *const W, ) -> Result<(), SurfaceCreationError>788     fn validate_from_qnx_screen<C, W>(
789         instance: &Instance,
790         _context: *const C,
791         _window: *const W,
792     ) -> Result<(), SurfaceCreationError> {
793         if !instance.enabled_extensions().qnx_screen_surface {
794             return Err(SurfaceCreationError::RequirementNotMet {
795                 required_for: "`Surface::from_qnx_screen`",
796                 requires_one_of: RequiresOneOf {
797                     instance_extensions: &["qnx_screen_surface"],
798                     ..Default::default()
799                 },
800             });
801         }
802 
803         // VUID-VkScreenSurfaceCreateInfoQNX-context-04741
804         // Can't validate, therefore unsafe
805 
806         // VUID-VkScreenSurfaceCreateInfoQNX-window-04742
807         // Can't validate, therefore unsafe
808 
809         Ok(())
810     }
811 
812     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
from_qnx_screen_unchecked<C, W>( instance: Arc<Instance>, context: *const C, window: *const W, object: Option<Arc<dyn Any + Send + Sync>>, ) -> Result<Arc<Self>, VulkanError>813     pub unsafe fn from_qnx_screen_unchecked<C, W>(
814         instance: Arc<Instance>,
815         context: *const C,
816         window: *const W,
817         object: Option<Arc<dyn Any + Send + Sync>>,
818     ) -> Result<Arc<Self>, VulkanError> {
819         let create_info = ash::vk::ScreenSurfaceCreateInfoQNX {
820             flags: ash::vk::ScreenSurfaceCreateFlagsQNX::empty(),
821             context: context as *mut _,
822             window: window as *mut _,
823             ..Default::default()
824         };
825 
826         let handle = {
827             let fns = instance.fns();
828             let mut output = MaybeUninit::uninit();
829             (fns.qnx_screen_surface.create_screen_surface_qnx)(
830                 instance.handle(),
831                 &create_info,
832                 ptr::null(),
833                 output.as_mut_ptr(),
834             )
835             .result()
836             .map_err(VulkanError::from)?;
837             output.assume_init()
838         };
839 
840         Ok(Arc::new(Self::from_handle(
841             instance,
842             handle,
843             SurfaceApi::Qnx,
844             object,
845         )))
846     }
847 
848     /// Creates a `Surface` from a `code:nn::code:vi::code:Layer`.
849     ///
850     /// # Safety
851     ///
852     /// - `window` must be a valid `nn::vi::NativeWindowHandle` handle.
853     /// - The object referred to by `window` must outlive the created `Surface`.
854     ///   The `object` parameter can be used to ensure this.
from_vi<W>( instance: Arc<Instance>, window: *const W, object: Option<Arc<dyn Any + Send + Sync>>, ) -> Result<Arc<Self>, SurfaceCreationError>855     pub unsafe fn from_vi<W>(
856         instance: Arc<Instance>,
857         window: *const W,
858         object: Option<Arc<dyn Any + Send + Sync>>,
859     ) -> Result<Arc<Self>, SurfaceCreationError> {
860         Self::validate_from_vi(&instance, window)?;
861 
862         Ok(Self::from_vi_unchecked(instance, window, object)?)
863     }
864 
validate_from_vi<W>( instance: &Instance, _window: *const W, ) -> Result<(), SurfaceCreationError>865     fn validate_from_vi<W>(
866         instance: &Instance,
867         _window: *const W,
868     ) -> Result<(), SurfaceCreationError> {
869         if !instance.enabled_extensions().nn_vi_surface {
870             return Err(SurfaceCreationError::RequirementNotMet {
871                 required_for: "`Surface::from_vi`",
872                 requires_one_of: RequiresOneOf {
873                     instance_extensions: &["nn_vi_surface"],
874                     ..Default::default()
875                 },
876             });
877         }
878 
879         // VUID-VkViSurfaceCreateInfoNN-window-01318
880         // Can't validate, therefore unsafe
881 
882         Ok(())
883     }
884 
885     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
from_vi_unchecked<W>( instance: Arc<Instance>, window: *const W, object: Option<Arc<dyn Any + Send + Sync>>, ) -> Result<Arc<Self>, VulkanError>886     pub unsafe fn from_vi_unchecked<W>(
887         instance: Arc<Instance>,
888         window: *const W,
889         object: Option<Arc<dyn Any + Send + Sync>>,
890     ) -> Result<Arc<Self>, VulkanError> {
891         let create_info = ash::vk::ViSurfaceCreateInfoNN {
892             flags: ash::vk::ViSurfaceCreateFlagsNN::empty(),
893             window: window as *mut _,
894             ..Default::default()
895         };
896 
897         let handle = {
898             let fns = instance.fns();
899             let mut output = MaybeUninit::uninit();
900             (fns.nn_vi_surface.create_vi_surface_nn)(
901                 instance.handle(),
902                 &create_info,
903                 ptr::null(),
904                 output.as_mut_ptr(),
905             )
906             .result()
907             .map_err(VulkanError::from)?;
908             output.assume_init()
909         };
910 
911         Ok(Arc::new(Self::from_handle(
912             instance,
913             handle,
914             SurfaceApi::Vi,
915             object,
916         )))
917     }
918 
919     /// Creates a `Surface` from a Wayland window.
920     ///
921     /// The window's dimensions will be set to the size of the swapchain.
922     ///
923     /// # Safety
924     ///
925     /// - `display` must be a valid Wayland `wl_display` handle.
926     /// - `surface` must be a valid Wayland `wl_surface` handle.
927     /// - The objects referred to by `display` and `surface` must outlive the created `Surface`.
928     ///   The `object` parameter can be used to ensure this.
from_wayland<D, S>( instance: Arc<Instance>, display: *const D, surface: *const S, object: Option<Arc<dyn Any + Send + Sync>>, ) -> Result<Arc<Self>, SurfaceCreationError>929     pub unsafe fn from_wayland<D, S>(
930         instance: Arc<Instance>,
931         display: *const D,
932         surface: *const S,
933         object: Option<Arc<dyn Any + Send + Sync>>,
934     ) -> Result<Arc<Self>, SurfaceCreationError> {
935         Self::validate_from_wayland(&instance, display, surface)?;
936 
937         Ok(Self::from_wayland_unchecked(
938             instance, display, surface, object,
939         )?)
940     }
941 
validate_from_wayland<D, S>( instance: &Instance, _display: *const D, _surface: *const S, ) -> Result<(), SurfaceCreationError>942     fn validate_from_wayland<D, S>(
943         instance: &Instance,
944         _display: *const D,
945         _surface: *const S,
946     ) -> Result<(), SurfaceCreationError> {
947         if !instance.enabled_extensions().khr_wayland_surface {
948             return Err(SurfaceCreationError::RequirementNotMet {
949                 required_for: "`Surface::from_wayland`",
950                 requires_one_of: RequiresOneOf {
951                     instance_extensions: &["khr_wayland_surface"],
952                     ..Default::default()
953                 },
954             });
955         }
956 
957         // VUID-VkWaylandSurfaceCreateInfoKHR-display-01304
958         // Can't validate, therefore unsafe
959 
960         // VUID-VkWaylandSurfaceCreateInfoKHR-surface-01305
961         // Can't validate, therefore unsafe
962 
963         Ok(())
964     }
965 
966     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
from_wayland_unchecked<D, S>( instance: Arc<Instance>, display: *const D, surface: *const S, object: Option<Arc<dyn Any + Send + Sync>>, ) -> Result<Arc<Self>, VulkanError>967     pub unsafe fn from_wayland_unchecked<D, S>(
968         instance: Arc<Instance>,
969         display: *const D,
970         surface: *const S,
971         object: Option<Arc<dyn Any + Send + Sync>>,
972     ) -> Result<Arc<Self>, VulkanError> {
973         let create_info = ash::vk::WaylandSurfaceCreateInfoKHR {
974             flags: ash::vk::WaylandSurfaceCreateFlagsKHR::empty(),
975             display: display as *mut _,
976             surface: surface as *mut _,
977             ..Default::default()
978         };
979 
980         let handle = {
981             let fns = instance.fns();
982             let mut output = MaybeUninit::uninit();
983             (fns.khr_wayland_surface.create_wayland_surface_khr)(
984                 instance.handle(),
985                 &create_info,
986                 ptr::null(),
987                 output.as_mut_ptr(),
988             )
989             .result()
990             .map_err(VulkanError::from)?;
991             output.assume_init()
992         };
993 
994         Ok(Arc::new(Self::from_handle(
995             instance,
996             handle,
997             SurfaceApi::Wayland,
998             object,
999         )))
1000     }
1001 
1002     /// Creates a `Surface` from a Win32 window.
1003     ///
1004     /// The surface's min, max and current extent will always match the window's dimensions.
1005     ///
1006     /// # Safety
1007     ///
1008     /// - `hinstance` must be a valid Win32 `HINSTANCE` handle.
1009     /// - `hwnd` must be a valid Win32 `HWND` handle.
1010     /// - The objects referred to by `hwnd` and `hinstance` must outlive the created `Surface`.
1011     ///   The `object` parameter can be used to ensure this.
from_win32<I, W>( instance: Arc<Instance>, hinstance: *const I, hwnd: *const W, object: Option<Arc<dyn Any + Send + Sync>>, ) -> Result<Arc<Self>, SurfaceCreationError>1012     pub unsafe fn from_win32<I, W>(
1013         instance: Arc<Instance>,
1014         hinstance: *const I,
1015         hwnd: *const W,
1016         object: Option<Arc<dyn Any + Send + Sync>>,
1017     ) -> Result<Arc<Self>, SurfaceCreationError> {
1018         Self::validate_from_win32(&instance, hinstance, hwnd)?;
1019 
1020         Ok(Self::from_win32_unchecked(
1021             instance, hinstance, hwnd, object,
1022         )?)
1023     }
1024 
validate_from_win32<I, W>( instance: &Instance, _hinstance: *const I, _hwnd: *const W, ) -> Result<(), SurfaceCreationError>1025     fn validate_from_win32<I, W>(
1026         instance: &Instance,
1027         _hinstance: *const I,
1028         _hwnd: *const W,
1029     ) -> Result<(), SurfaceCreationError> {
1030         if !instance.enabled_extensions().khr_win32_surface {
1031             return Err(SurfaceCreationError::RequirementNotMet {
1032                 required_for: "`Surface::from_win32`",
1033                 requires_one_of: RequiresOneOf {
1034                     instance_extensions: &["khr_win32_surface"],
1035                     ..Default::default()
1036                 },
1037             });
1038         }
1039 
1040         // VUID-VkWin32SurfaceCreateInfoKHR-hinstance-01307
1041         // Can't validate, therefore unsafe
1042 
1043         // VUID-VkWin32SurfaceCreateInfoKHR-hwnd-01308
1044         // Can't validate, therefore unsafe
1045 
1046         Ok(())
1047     }
1048 
1049     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
from_win32_unchecked<I, W>( instance: Arc<Instance>, hinstance: *const I, hwnd: *const W, object: Option<Arc<dyn Any + Send + Sync>>, ) -> Result<Arc<Self>, VulkanError>1050     pub unsafe fn from_win32_unchecked<I, W>(
1051         instance: Arc<Instance>,
1052         hinstance: *const I,
1053         hwnd: *const W,
1054         object: Option<Arc<dyn Any + Send + Sync>>,
1055     ) -> Result<Arc<Self>, VulkanError> {
1056         let create_info = ash::vk::Win32SurfaceCreateInfoKHR {
1057             flags: ash::vk::Win32SurfaceCreateFlagsKHR::empty(),
1058             hinstance: hinstance as *mut _,
1059             hwnd: hwnd as *mut _,
1060             ..Default::default()
1061         };
1062 
1063         let handle = {
1064             let fns = instance.fns();
1065             let mut output = MaybeUninit::uninit();
1066             (fns.khr_win32_surface.create_win32_surface_khr)(
1067                 instance.handle(),
1068                 &create_info,
1069                 ptr::null(),
1070                 output.as_mut_ptr(),
1071             )
1072             .result()
1073             .map_err(VulkanError::from)?;
1074             output.assume_init()
1075         };
1076 
1077         Ok(Arc::new(Self::from_handle(
1078             instance,
1079             handle,
1080             SurfaceApi::Win32,
1081             object,
1082         )))
1083     }
1084 
1085     /// Creates a `Surface` from an XCB window.
1086     ///
1087     /// The surface's min, max and current extent will always match the window's dimensions.
1088     ///
1089     /// # Safety
1090     ///
1091     /// - `connection` must be a valid X11 `xcb_connection_t` handle.
1092     /// - `window` must be a valid X11 `xcb_window_t` handle.
1093     /// - The objects referred to by `connection` and `window` must outlive the created `Surface`.
1094     ///   The `object` parameter can be used to ensure this.
from_xcb<C>( instance: Arc<Instance>, connection: *const C, window: ash::vk::xcb_window_t, object: Option<Arc<dyn Any + Send + Sync>>, ) -> Result<Arc<Self>, SurfaceCreationError>1095     pub unsafe fn from_xcb<C>(
1096         instance: Arc<Instance>,
1097         connection: *const C,
1098         window: ash::vk::xcb_window_t,
1099         object: Option<Arc<dyn Any + Send + Sync>>,
1100     ) -> Result<Arc<Self>, SurfaceCreationError> {
1101         Self::validate_from_xcb(&instance, connection, window)?;
1102 
1103         Ok(Self::from_xcb_unchecked(
1104             instance, connection, window, object,
1105         )?)
1106     }
1107 
validate_from_xcb<C>( instance: &Instance, _connection: *const C, _window: ash::vk::xcb_window_t, ) -> Result<(), SurfaceCreationError>1108     fn validate_from_xcb<C>(
1109         instance: &Instance,
1110         _connection: *const C,
1111         _window: ash::vk::xcb_window_t,
1112     ) -> Result<(), SurfaceCreationError> {
1113         if !instance.enabled_extensions().khr_xcb_surface {
1114             return Err(SurfaceCreationError::RequirementNotMet {
1115                 required_for: "`Surface::from_xcb`",
1116                 requires_one_of: RequiresOneOf {
1117                     instance_extensions: &["khr_xcb_surface"],
1118                     ..Default::default()
1119                 },
1120             });
1121         }
1122 
1123         // VUID-VkXcbSurfaceCreateInfoKHR-connection-01310
1124         // Can't validate, therefore unsafe
1125 
1126         // VUID-VkXcbSurfaceCreateInfoKHR-window-01311
1127         // Can't validate, therefore unsafe
1128 
1129         Ok(())
1130     }
1131 
1132     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
from_xcb_unchecked<C>( instance: Arc<Instance>, connection: *const C, window: ash::vk::xcb_window_t, object: Option<Arc<dyn Any + Send + Sync>>, ) -> Result<Arc<Self>, VulkanError>1133     pub unsafe fn from_xcb_unchecked<C>(
1134         instance: Arc<Instance>,
1135         connection: *const C,
1136         window: ash::vk::xcb_window_t,
1137         object: Option<Arc<dyn Any + Send + Sync>>,
1138     ) -> Result<Arc<Self>, VulkanError> {
1139         let create_info = ash::vk::XcbSurfaceCreateInfoKHR {
1140             flags: ash::vk::XcbSurfaceCreateFlagsKHR::empty(),
1141             connection: connection as *mut _,
1142             window,
1143             ..Default::default()
1144         };
1145 
1146         let handle = {
1147             let fns = instance.fns();
1148             let mut output = MaybeUninit::uninit();
1149             (fns.khr_xcb_surface.create_xcb_surface_khr)(
1150                 instance.handle(),
1151                 &create_info,
1152                 ptr::null(),
1153                 output.as_mut_ptr(),
1154             )
1155             .result()
1156             .map_err(VulkanError::from)?;
1157             output.assume_init()
1158         };
1159 
1160         Ok(Arc::new(Self::from_handle(
1161             instance,
1162             handle,
1163             SurfaceApi::Xcb,
1164             object,
1165         )))
1166     }
1167 
1168     /// Creates a `Surface` from an Xlib window.
1169     ///
1170     /// The surface's min, max and current extent will always match the window's dimensions.
1171     ///
1172     /// # Safety
1173     ///
1174     /// - `display` must be a valid Xlib `Display` handle.
1175     /// - `window` must be a valid Xlib `Window` handle.
1176     /// - The objects referred to by `display` and `window` must outlive the created `Surface`.
1177     ///   The `object` parameter can be used to ensure this.
from_xlib<D>( instance: Arc<Instance>, display: *const D, window: ash::vk::Window, object: Option<Arc<dyn Any + Send + Sync>>, ) -> Result<Arc<Self>, SurfaceCreationError>1178     pub unsafe fn from_xlib<D>(
1179         instance: Arc<Instance>,
1180         display: *const D,
1181         window: ash::vk::Window,
1182         object: Option<Arc<dyn Any + Send + Sync>>,
1183     ) -> Result<Arc<Self>, SurfaceCreationError> {
1184         Self::validate_from_xlib(&instance, display, window)?;
1185 
1186         Ok(Self::from_xlib_unchecked(
1187             instance, display, window, object,
1188         )?)
1189     }
1190 
validate_from_xlib<D>( instance: &Instance, _display: *const D, _window: ash::vk::Window, ) -> Result<(), SurfaceCreationError>1191     fn validate_from_xlib<D>(
1192         instance: &Instance,
1193         _display: *const D,
1194         _window: ash::vk::Window,
1195     ) -> Result<(), SurfaceCreationError> {
1196         if !instance.enabled_extensions().khr_xlib_surface {
1197             return Err(SurfaceCreationError::RequirementNotMet {
1198                 required_for: "`Surface::from_xlib`",
1199                 requires_one_of: RequiresOneOf {
1200                     instance_extensions: &["khr_xlib_surface"],
1201                     ..Default::default()
1202                 },
1203             });
1204         }
1205 
1206         // VUID-VkXlibSurfaceCreateInfoKHR-dpy-01313
1207         // Can't validate, therefore unsafe
1208 
1209         // VUID-VkXlibSurfaceCreateInfoKHR-window-01314
1210         // Can't validate, therefore unsafe
1211 
1212         Ok(())
1213     }
1214 
1215     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
from_xlib_unchecked<D>( instance: Arc<Instance>, display: *const D, window: ash::vk::Window, object: Option<Arc<dyn Any + Send + Sync>>, ) -> Result<Arc<Self>, VulkanError>1216     pub unsafe fn from_xlib_unchecked<D>(
1217         instance: Arc<Instance>,
1218         display: *const D,
1219         window: ash::vk::Window,
1220         object: Option<Arc<dyn Any + Send + Sync>>,
1221     ) -> Result<Arc<Self>, VulkanError> {
1222         let create_info = ash::vk::XlibSurfaceCreateInfoKHR {
1223             flags: ash::vk::XlibSurfaceCreateFlagsKHR::empty(),
1224             dpy: display as *mut _,
1225             window,
1226             ..Default::default()
1227         };
1228 
1229         let handle = {
1230             let fns = instance.fns();
1231             let mut output = MaybeUninit::uninit();
1232             (fns.khr_xlib_surface.create_xlib_surface_khr)(
1233                 instance.handle(),
1234                 &create_info,
1235                 ptr::null(),
1236                 output.as_mut_ptr(),
1237             )
1238             .result()
1239             .map_err(VulkanError::from)?;
1240             output.assume_init()
1241         };
1242 
1243         Ok(Arc::new(Self::from_handle(
1244             instance,
1245             handle,
1246             SurfaceApi::Xlib,
1247             object,
1248         )))
1249     }
1250 
1251     /// Returns the instance this surface was created with.
1252     #[inline]
instance(&self) -> &Arc<Instance>1253     pub fn instance(&self) -> &Arc<Instance> {
1254         &self.instance
1255     }
1256 
1257     /// Returns the windowing API that was used to construct the surface.
1258     #[inline]
api(&self) -> SurfaceApi1259     pub fn api(&self) -> SurfaceApi {
1260         self.api
1261     }
1262 
1263     /// Returns a reference to the `object` parameter that was passed when creating the
1264     /// surface.
1265     #[inline]
object(&self) -> Option<&Arc<dyn Any + Send + Sync>>1266     pub fn object(&self) -> Option<&Arc<dyn Any + Send + Sync>> {
1267         self.object.as_ref()
1268     }
1269 
1270     /// Resizes the sublayer bounds on iOS.
1271     /// It may not be necessary if original window size matches device's, but often it does not.
1272     /// Thus this should be called after a resize has occurred abd swapchain has been recreated.
1273     ///
1274     /// On iOS, we've created CAMetalLayer as a sublayer. However, when the view changes size,
1275     /// its sublayers are not automatically resized, and we must resize
1276     /// it here.
1277     #[cfg(target_os = "ios")]
1278     #[inline]
update_ios_sublayer_on_resize(&self)1279     pub unsafe fn update_ios_sublayer_on_resize(&self) {
1280         use core_graphics_types::geometry::CGRect;
1281         let class = class!(CAMetalLayer);
1282         let main_layer: *mut Object = self.metal_layer.main_layer.0;
1283         let bounds: CGRect = msg_send![main_layer, bounds];
1284         let render_layer: *mut Object = self.metal_layer.render_layer.0;
1285         let () = msg_send![render_layer, setFrame: bounds];
1286     }
1287 }
1288 
1289 impl Drop for Surface {
1290     #[inline]
drop(&mut self)1291     fn drop(&mut self) {
1292         unsafe {
1293             let fns = self.instance.fns();
1294             (fns.khr_surface.destroy_surface_khr)(self.instance.handle(), self.handle, ptr::null());
1295         }
1296     }
1297 }
1298 
1299 unsafe impl VulkanObject for Surface {
1300     type Handle = ash::vk::SurfaceKHR;
1301 
1302     #[inline]
handle(&self) -> Self::Handle1303     fn handle(&self) -> Self::Handle {
1304         self.handle
1305     }
1306 }
1307 
1308 impl_id_counter!(Surface);
1309 
1310 impl Debug for Surface {
fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError>1311     fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
1312         let Self {
1313             handle,
1314             instance,
1315             api,
1316             object: _,
1317             has_swapchain,
1318             ..
1319         } = self;
1320 
1321         f.debug_struct("Surface")
1322             .field("handle", handle)
1323             .field("instance", instance)
1324             .field("api", api)
1325             .field("window", &())
1326             .field("has_swapchain", &has_swapchain)
1327             .finish()
1328     }
1329 }
1330 
1331 unsafe impl SurfaceSwapchainLock for Surface {
1332     #[inline]
flag(&self) -> &AtomicBool1333     fn flag(&self) -> &AtomicBool {
1334         &self.has_swapchain
1335     }
1336 }
1337 
1338 /// Error that can happen when creating a debug callback.
1339 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1340 pub enum SurfaceCreationError {
1341     /// Not enough memory.
1342     OomError(OomError),
1343 
1344     RequirementNotMet {
1345         required_for: &'static str,
1346         requires_one_of: RequiresOneOf,
1347     },
1348 }
1349 
1350 impl Error for SurfaceCreationError {
source(&self) -> Option<&(dyn Error + 'static)>1351     fn source(&self) -> Option<&(dyn Error + 'static)> {
1352         match self {
1353             SurfaceCreationError::OomError(err) => Some(err),
1354             _ => None,
1355         }
1356     }
1357 }
1358 
1359 impl Display for SurfaceCreationError {
fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError>1360     fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
1361         match self {
1362             Self::OomError(_) => write!(f, "not enough memory available"),
1363             Self::RequirementNotMet {
1364                 required_for,
1365                 requires_one_of,
1366             } => write!(
1367                 f,
1368                 "a requirement was not met for: {}; requires one of: {}",
1369                 required_for, requires_one_of,
1370             ),
1371         }
1372     }
1373 }
1374 
1375 impl From<OomError> for SurfaceCreationError {
from(err: OomError) -> SurfaceCreationError1376     fn from(err: OomError) -> SurfaceCreationError {
1377         SurfaceCreationError::OomError(err)
1378     }
1379 }
1380 
1381 impl From<VulkanError> for SurfaceCreationError {
from(err: VulkanError) -> SurfaceCreationError1382     fn from(err: VulkanError) -> SurfaceCreationError {
1383         match err {
1384             err @ VulkanError::OutOfHostMemory => {
1385                 SurfaceCreationError::OomError(OomError::from(err))
1386             }
1387             err @ VulkanError::OutOfDeviceMemory => {
1388                 SurfaceCreationError::OomError(OomError::from(err))
1389             }
1390             _ => panic!("unexpected error: {:?}", err),
1391         }
1392     }
1393 }
1394 
1395 /// The windowing API that was used to construct a surface.
1396 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1397 #[non_exhaustive]
1398 pub enum SurfaceApi {
1399     Headless,
1400     DisplayPlane,
1401 
1402     // Alphabetical order
1403     Android,
1404     DirectFB,
1405     FuchsiaImagePipe,
1406     GgpStreamDescriptor,
1407     Ios,
1408     MacOs,
1409     Metal,
1410     Qnx,
1411     Vi,
1412     Wayland,
1413     Win32,
1414     Xcb,
1415     Xlib,
1416 }
1417 
1418 vulkan_enum! {
1419     #[non_exhaustive]
1420 
1421     /// The mode of action when a swapchain image is presented.
1422     ///
1423     /// Swapchain images can be in one of three possible states:
1424     /// - Exactly one image is currently displayed on the screen.
1425     /// - Zero or more are acquired by the application, or available to be acquired.
1426     /// - Some may be held inside the presentation engine waiting to be displayed. The present mode
1427     ///   concerns the behaviour of this category, and by extension, which images are left over for
1428     ///   acquiring.
1429     ///
1430     /// The present mode affects what is commonly known as "vertical sync" or "vsync" for short.
1431     /// The `Immediate` mode is equivalent to disabling vertical sync, while the others enable
1432     /// vertical sync in various forms. An important aspect of the present modes is their potential
1433     /// *latency*: the time between when an image is presented, and when it actually appears on
1434     /// the display.
1435     ///
1436     /// Only `Fifo` is guaranteed to be supported on every device. For the others, you must call
1437     /// [`surface_present_modes`] to see if they are supported.
1438     ///
1439     /// [`surface_present_modes`]: crate::device::physical::PhysicalDevice::surface_present_modes
1440     PresentMode = PresentModeKHR(i32);
1441 
1442     /// The presentation engine holds only the currently displayed image. When presenting an image,
1443     /// the currently displayed image is immediately replaced with the presented image. The old
1444     /// image will be available for future acquire operations.
1445     ///
1446     /// This mode has the lowest latency of all present modes, but if the display is not in a
1447     /// vertical blanking period when the image is replaced, a tear will be visible.
1448     Immediate = IMMEDIATE,
1449 
1450     /// The presentation engine holds the currently displayed image, and optionally another in a
1451     /// waiting slot. The presentation engine waits until the next vertical blanking period, then
1452     /// removes any image from the waiting slot and displays it. Tearing will never be visible.
1453     /// When presenting an image, it is stored in the waiting slot. Any previous entry
1454     /// in the slot is discarded, and will be available for future acquire operations.
1455     ///
1456     /// Latency is relatively low with this mode, and will never be longer than the time between
1457     /// vertical blanking periods. However, if a previous image in the waiting slot is discarded,
1458     /// the work that went into producing that image was wasted.
1459     ///
1460     /// With two swapchain images, this mode behaves essentially identical to `Fifo`: once both
1461     /// images are held in the presentation engine, no images can be acquired until one is finished
1462     /// displaying. But with three or more swapchain images, any images beyond those two are always
1463     /// available to acquire.
1464     Mailbox = MAILBOX,
1465 
1466     /// The presentation engine holds the currently displayed image, and a queue of waiting images.
1467     /// When presenting an image, it is added to the tail of the queue, after previously presented
1468     /// images. The presentation engine waits until the next vertical blanking period, then removes
1469     /// an image from the head of the queue and displays it. Tearing will never be visible. Images
1470     /// become available for future acquire operations only after they have been displayed.
1471     ///
1472     /// This mode is guaranteed to be always supported. It is possible for all swapchain images to
1473     /// end up being held by the presentation engine, either being displayed or in the queue. When
1474     /// that happens, no images can be acquired until one is finished displaying. This can be used
1475     /// to limit the presentation rate to the display frame rate. Latency is bounded only by the
1476     /// number of images in the swapchain.
1477     ///
1478     /// This is the equivalent of OpenGL's `SwapInterval` with a value of 1.
1479     Fifo = FIFO,
1480 
1481     /// Similar to `Fifo`, but with the ability for images to "skip the queue" if presentation is
1482     /// lagging behind the display frame rate. If the queue is empty and a vertical blanking period
1483     /// has already passed since the previous image was displayed, then the currently displayed
1484     /// image is immediately replaced with the presented image, as in `Immediate`.
1485     ///
1486     /// This mode has high latency if images are presented faster than the display frame rate,
1487     /// as they will accumulate in the queue. But the latency is low if images are presented slower
1488     /// than the display frame rate. However, slower presentation can result in visible tearing.
1489     ///
1490     /// This is the equivalent of OpenGL's `SwapInterval` with a value of -1.
1491     FifoRelaxed = FIFO_RELAXED,
1492 
1493     /* TODO: enable
1494     // TODO: document
1495     SharedDemandRefresh = SHARED_DEMAND_REFRESH_KHR {
1496         device_extensions: [khr_shared_presentable_image],
1497     },*/
1498 
1499     /* TODO: enable
1500     // TODO: document
1501     SharedContinuousRefresh = SHARED_CONTINUOUS_REFRESH_KHR {
1502         device_extensions: [khr_shared_presentable_image],
1503     },*/
1504 }
1505 
1506 vulkan_bitflags_enum! {
1507     #[non_exhaustive]
1508 
1509     /// A set of [`SurfaceTransform`] values.
1510     SurfaceTransforms,
1511 
1512     /// The presentation transform to apply when presenting a swapchain image to a surface.
1513     SurfaceTransform,
1514 
1515     = SurfaceTransformFlagsKHR(u32);
1516 
1517     /// Don't transform the image.
1518     IDENTITY, Identity = IDENTITY,
1519 
1520     /// Rotate 90 degrees.
1521     ROTATE_90, Rotate90 = ROTATE_90,
1522 
1523     /// Rotate 180 degrees.
1524     ROTATE_180, Rotate180 = ROTATE_180,
1525 
1526     /// Rotate 270 degrees.
1527     ROTATE_270, Rotate270 = ROTATE_270,
1528 
1529     /// Mirror the image horizontally.
1530     HORIZONTAL_MIRROR, HorizontalMirror = HORIZONTAL_MIRROR,
1531 
1532     /// Mirror the image horizontally and rotate 90 degrees.
1533     HORIZONTAL_MIRROR_ROTATE_90, HorizontalMirrorRotate90 = HORIZONTAL_MIRROR_ROTATE_90,
1534 
1535     /// Mirror the image horizontally and rotate 180 degrees.
1536     HORIZONTAL_MIRROR_ROTATE_180, HorizontalMirrorRotate180 = HORIZONTAL_MIRROR_ROTATE_180,
1537 
1538     /// Mirror the image horizontally and rotate 270 degrees.
1539     HORIZONTAL_MIRROR_ROTATE_270, HorizontalMirrorRotate270 = HORIZONTAL_MIRROR_ROTATE_270,
1540 
1541     /// Let the operating system or driver implementation choose.
1542     INHERIT, Inherit = INHERIT,
1543 }
1544 
1545 impl Default for SurfaceTransform {
1546     #[inline]
default() -> SurfaceTransform1547     fn default() -> SurfaceTransform {
1548         SurfaceTransform::Identity
1549     }
1550 }
1551 
1552 vulkan_bitflags_enum! {
1553     #[non_exhaustive]
1554 
1555     /// A set of [`CompositeAlpha`] values.
1556     CompositeAlphas,
1557 
1558     /// How the alpha values of the pixels of the window are treated.
1559     CompositeAlpha,
1560 
1561     = CompositeAlphaFlagsKHR(u32);
1562 
1563     /// The alpha channel of the image is ignored. All the pixels are considered as if they have a
1564     /// value of 1.0.
1565     OPAQUE, Opaque = OPAQUE,
1566 
1567     /// The alpha channel of the image is respected. The color channels are expected to have
1568     /// already been multiplied by the alpha value.
1569     PRE_MULTIPLIED, PreMultiplied = PRE_MULTIPLIED,
1570 
1571     /// The alpha channel of the image is respected. The color channels will be multiplied by the
1572     /// alpha value by the compositor before being added to what is behind.
1573     POST_MULTIPLIED, PostMultiplied = POST_MULTIPLIED,
1574 
1575     /// Let the operating system or driver implementation choose.
1576     INHERIT, Inherit = INHERIT,
1577 }
1578 
1579 vulkan_enum! {
1580     #[non_exhaustive]
1581 
1582     /// How the presentation engine should interpret the data.
1583     ///
1584     /// # A quick lesson about color spaces
1585     ///
1586     /// ## What is a color space?
1587     ///
1588     /// Each pixel of a monitor is made of three components: one red, one green, and one blue. In
1589     /// the past, computers would simply send to the monitor the intensity of each of the three
1590     /// components.
1591     ///
1592     /// This proved to be problematic, because depending on the brand of the monitor the colors
1593     /// would not exactly be the same. For example on some monitors, a value of `[1.0, 0.0, 0.0]`
1594     /// would be a
1595     /// bit more orange than on others.
1596     ///
1597     /// In order to standardize this, there exist what are called *color spaces*: sRGB, AdobeRGB,
1598     /// DCI-P3, scRGB, etc. When you manipulate RGB values in a specific color space, these values
1599     /// have a precise absolute meaning in terms of color, that is the same across all systems and
1600     /// monitors.
1601     ///
1602     /// > **Note**: Color spaces are orthogonal to concept of RGB. *RGB* only indicates what is the
1603     /// > representation of the data, but not how it is interpreted. You can think of this a bit
1604     /// > like text encoding. An *RGB* value is a like a byte, in other words it is the medium by
1605     /// > which values are communicated, and a *color space* is like a text encoding (eg. UTF-8),
1606     /// > in other words it is the way the value should be interpreted.
1607     ///
1608     /// The most commonly used color space today is sRGB. Most monitors today use this color space,
1609     /// and most images files are encoded in this color space.
1610     ///
1611     /// ## Pixel formats and linear vs non-linear
1612     ///
1613     /// In Vulkan all images have a specific format in which the data is stored. The data of an
1614     /// image consists of pixels in RGB but contains no information about the color space (or lack
1615     /// thereof) of these pixels. You are free to store them in whatever color space you want.
1616     ///
1617     /// But one big practical problem with color spaces is that they are sometimes not linear, and
1618     /// in particular the popular sRGB color space is not linear. In a non-linear color space, a
1619     /// value of `[0.6, 0.6, 0.6]` for example is **not** twice as bright as a value of `[0.3, 0.3,
1620     /// 0.3]`. This is problematic, because operations such as taking the average of two colors or
1621     /// calculating the lighting of a texture with a dot product are mathematically incorrect and
1622     /// will produce incorrect colors.
1623     ///
1624     /// > **Note**: If the texture format has an alpha component, it is not affected by the color
1625     /// > space and always behaves linearly.
1626     ///
1627     /// In order to solve this Vulkan also provides image formats with the `Srgb` suffix, which are
1628     /// expected to contain RGB data in the sRGB color space. When you sample an image with such a
1629     /// format from a shader, the implementation will automatically turn the pixel values into a
1630     /// linear color space that is suitable for linear operations (such as additions or
1631     /// multiplications). When you write to a framebuffer attachment with such a format, the
1632     /// implementation will automatically perform the opposite conversion. These conversions are
1633     /// most of the time performed by the hardware and incur no additional cost.
1634     ///
1635     /// ## Color space of the swapchain
1636     ///
1637     /// The color space that you specify when you create a swapchain is how the implementation will
1638     /// interpret the raw data inside of the image.
1639     ///
1640     /// > **Note**: The implementation can choose to send the data in the swapchain image directly
1641     /// > to the monitor, but it can also choose to write it in an intermediary buffer that is then
1642     /// > read by the operating system or windowing system. Therefore the color space that the
1643     /// > implementation supports is not necessarily the same as the one supported by the monitor.
1644     ///
1645     /// It is *your* job to ensure that the data in the swapchain image is in the color space
1646     /// that is specified here, otherwise colors will be incorrect. The implementation will never
1647     /// perform any additional automatic conversion after the colors have been written to the
1648     /// swapchain image.
1649     ///
1650     /// # How do I handle this correctly?
1651     ///
1652     /// The easiest way to handle color spaces in a cross-platform program is:
1653     ///
1654     /// - Always request the `SrgbNonLinear` color space when creating the swapchain.
1655     /// - Make sure that all your image files use the sRGB color space, and load them in images
1656     ///   whose format has the `Srgb` suffix. Only use non-sRGB image formats for intermediary
1657     ///   computations or to store non-color data.
1658     /// - Swapchain images should have a format with the `Srgb` suffix.
1659     ///
1660     /// > **Note**: Lots of developers are confused by color spaces. You can sometimes find articles
1661     /// > talking about gamma correction and suggestion to put your colors to the power 2.2 for
1662     /// > example. These are all hacks and you should use the sRGB pixel formats instead.
1663     ///
1664     /// If you follow these three rules, then everything should render the same way on all
1665     /// platforms.
1666     ///
1667     /// Additionally you can try detect whether the implementation supports any additional color
1668     /// space and perform a manual conversion to that color space from inside your shader.
1669     ColorSpace = ColorSpaceKHR(i32);
1670 
1671     // TODO: document
1672     SrgbNonLinear = SRGB_NONLINEAR,
1673 
1674     // TODO: document
1675     DisplayP3NonLinear = DISPLAY_P3_NONLINEAR_EXT {
1676         instance_extensions: [ext_swapchain_colorspace],
1677     },
1678 
1679     // TODO: document
1680     ExtendedSrgbLinear = EXTENDED_SRGB_LINEAR_EXT {
1681         instance_extensions: [ext_swapchain_colorspace],
1682     },
1683 
1684     // TODO: document
1685     ExtendedSrgbNonLinear = EXTENDED_SRGB_NONLINEAR_EXT {
1686         instance_extensions: [ext_swapchain_colorspace],
1687     },
1688 
1689     // TODO: document
1690     DisplayP3Linear = DISPLAY_P3_LINEAR_EXT {
1691         instance_extensions: [ext_swapchain_colorspace],
1692     },
1693 
1694     // TODO: document
1695     DciP3NonLinear = DCI_P3_NONLINEAR_EXT {
1696         instance_extensions: [ext_swapchain_colorspace],
1697     },
1698 
1699     // TODO: document
1700     Bt709Linear = BT709_LINEAR_EXT {
1701         instance_extensions: [ext_swapchain_colorspace],
1702     },
1703 
1704     // TODO: document
1705     Bt709NonLinear = BT709_NONLINEAR_EXT {
1706         instance_extensions: [ext_swapchain_colorspace],
1707     },
1708 
1709     // TODO: document
1710     Bt2020Linear = BT2020_LINEAR_EXT {
1711         instance_extensions: [ext_swapchain_colorspace],
1712     },
1713 
1714     // TODO: document
1715     Hdr10St2084 = HDR10_ST2084_EXT {
1716         instance_extensions: [ext_swapchain_colorspace],
1717     },
1718 
1719     // TODO: document
1720     DolbyVision = DOLBYVISION_EXT {
1721         instance_extensions: [ext_swapchain_colorspace],
1722     },
1723 
1724     // TODO: document
1725     Hdr10Hlg = HDR10_HLG_EXT {
1726         instance_extensions: [ext_swapchain_colorspace],
1727     },
1728 
1729     // TODO: document
1730     AdobeRgbLinear = ADOBERGB_LINEAR_EXT {
1731         instance_extensions: [ext_swapchain_colorspace],
1732     },
1733 
1734     // TODO: document
1735     AdobeRgbNonLinear = ADOBERGB_NONLINEAR_EXT {
1736         instance_extensions: [ext_swapchain_colorspace],
1737     },
1738 
1739     // TODO: document
1740     PassThrough = PASS_THROUGH_EXT {
1741         instance_extensions: [ext_swapchain_colorspace],
1742     },
1743 
1744     // TODO: document
1745     DisplayNative = DISPLAY_NATIVE_AMD {
1746         device_extensions: [amd_display_native_hdr],
1747     },
1748 }
1749 
1750 /// Parameters for [`PhysicalDevice::surface_capabilities`] and [`PhysicalDevice::surface_formats`].
1751 ///
1752 /// [`PhysicalDevice::surface_capabilities`]: crate::device::physical::PhysicalDevice::surface_capabilities
1753 /// [`PhysicalDevice::surface_formats`]: crate::device::physical::PhysicalDevice::surface_formats
1754 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
1755 pub struct SurfaceInfo {
1756     pub full_screen_exclusive: FullScreenExclusive,
1757     pub win32_monitor: Option<Win32Monitor>,
1758     pub _ne: crate::NonExhaustive,
1759 }
1760 
1761 impl Default for SurfaceInfo {
1762     #[inline]
default() -> Self1763     fn default() -> Self {
1764         Self {
1765             full_screen_exclusive: FullScreenExclusive::Default,
1766             win32_monitor: None,
1767             _ne: crate::NonExhaustive(()),
1768         }
1769     }
1770 }
1771 
1772 #[cfg(target_os = "ios")]
1773 struct LayerHandle(*mut Object);
1774 
1775 #[cfg(target_os = "ios")]
1776 unsafe impl Send for LayerHandle {}
1777 
1778 #[cfg(target_os = "ios")]
1779 unsafe impl Sync for LayerHandle {}
1780 
1781 /// Represents the metal layer for IOS
1782 #[cfg(target_os = "ios")]
1783 pub struct IOSMetalLayer {
1784     main_layer: LayerHandle,
1785     render_layer: LayerHandle,
1786 }
1787 
1788 #[cfg(target_os = "ios")]
1789 impl IOSMetalLayer {
1790     #[inline]
new(main_layer: *mut Object, render_layer: *mut Object) -> Self1791     pub fn new(main_layer: *mut Object, render_layer: *mut Object) -> Self {
1792         Self {
1793             main_layer: LayerHandle(main_layer),
1794             render_layer: LayerHandle(render_layer),
1795         }
1796     }
1797 }
1798 
1799 #[cfg(target_os = "ios")]
1800 unsafe impl Send for IOSMetalLayer {}
1801 
1802 #[cfg(target_os = "ios")]
1803 unsafe impl Sync for IOSMetalLayer {}
1804 
1805 /// The capabilities of a surface when used by a physical device.
1806 ///
1807 /// You have to match these capabilities when you create a swapchain.
1808 #[derive(Clone, Debug)]
1809 #[non_exhaustive]
1810 pub struct SurfaceCapabilities {
1811     /// Minimum number of images that must be present in the swapchain.
1812     pub min_image_count: u32,
1813 
1814     /// Maximum number of images that must be present in the swapchain, or `None` if there is no
1815     /// maximum value. Note that "no maximum" doesn't mean that you can set a very high value, as
1816     /// you may still get out of memory errors.
1817     pub max_image_count: Option<u32>,
1818 
1819     /// The current dimensions of the surface. `None` means that the surface's dimensions will
1820     /// depend on the dimensions of the swapchain that you are going to create.
1821     pub current_extent: Option<[u32; 2]>,
1822 
1823     /// Minimum width and height of a swapchain that uses this surface.
1824     pub min_image_extent: [u32; 2],
1825 
1826     /// Maximum width and height of a swapchain that uses this surface.
1827     pub max_image_extent: [u32; 2],
1828 
1829     /// Maximum number of image layers if you create an image array. The minimum is 1.
1830     pub max_image_array_layers: u32,
1831 
1832     /// List of transforms supported for the swapchain.
1833     pub supported_transforms: SurfaceTransforms,
1834 
1835     /// Current transform used by the surface.
1836     pub current_transform: SurfaceTransform,
1837 
1838     /// List of composite alpha modes supports for the swapchain.
1839     pub supported_composite_alpha: CompositeAlphas,
1840 
1841     /// List of image usages that are supported for images of the swapchain. Only
1842     /// the `color_attachment` usage is guaranteed to be supported.
1843     pub supported_usage_flags: ImageUsage,
1844 
1845     /// Whether creating a protected swapchain is supported.
1846     pub supports_protected: bool,
1847 
1848     /// Whether full-screen exclusivity is supported.
1849     pub full_screen_exclusive_supported: bool,
1850 }
1851 
1852 #[cfg(test)]
1853 mod tests {
1854     use crate::{
1855         swapchain::{Surface, SurfaceCreationError},
1856         RequiresOneOf,
1857     };
1858     use std::ptr;
1859 
1860     #[test]
khr_win32_surface_ext_missing()1861     fn khr_win32_surface_ext_missing() {
1862         let instance = instance!();
1863         match unsafe { Surface::from_win32(instance, ptr::null::<u8>(), ptr::null::<u8>(), None) } {
1864             Err(SurfaceCreationError::RequirementNotMet {
1865                 requires_one_of:
1866                     RequiresOneOf {
1867                         instance_extensions,
1868                         ..
1869                     },
1870                 ..
1871             }) if instance_extensions.contains(&"khr_win32_surface") => (),
1872             _ => panic!(),
1873         }
1874     }
1875 
1876     #[test]
khr_xcb_surface_ext_missing()1877     fn khr_xcb_surface_ext_missing() {
1878         let instance = instance!();
1879         match unsafe { Surface::from_xcb(instance, ptr::null::<u8>(), 0, None) } {
1880             Err(SurfaceCreationError::RequirementNotMet {
1881                 requires_one_of:
1882                     RequiresOneOf {
1883                         instance_extensions,
1884                         ..
1885                     },
1886                 ..
1887             }) if instance_extensions.contains(&"khr_xcb_surface") => (),
1888             _ => panic!(),
1889         }
1890     }
1891 
1892     #[test]
khr_xlib_surface_ext_missing()1893     fn khr_xlib_surface_ext_missing() {
1894         let instance = instance!();
1895         match unsafe { Surface::from_xlib(instance, ptr::null::<u8>(), 0, None) } {
1896             Err(SurfaceCreationError::RequirementNotMet {
1897                 requires_one_of:
1898                     RequiresOneOf {
1899                         instance_extensions,
1900                         ..
1901                     },
1902                 ..
1903             }) if instance_extensions.contains(&"khr_xlib_surface") => (),
1904             _ => panic!(),
1905         }
1906     }
1907 
1908     #[test]
khr_wayland_surface_ext_missing()1909     fn khr_wayland_surface_ext_missing() {
1910         let instance = instance!();
1911         match unsafe { Surface::from_wayland(instance, ptr::null::<u8>(), ptr::null::<u8>(), None) }
1912         {
1913             Err(SurfaceCreationError::RequirementNotMet {
1914                 requires_one_of:
1915                     RequiresOneOf {
1916                         instance_extensions,
1917                         ..
1918                     },
1919                 ..
1920             }) if instance_extensions.contains(&"khr_wayland_surface") => (),
1921             _ => panic!(),
1922         }
1923     }
1924 
1925     #[test]
khr_android_surface_ext_missing()1926     fn khr_android_surface_ext_missing() {
1927         let instance = instance!();
1928         match unsafe { Surface::from_android(instance, ptr::null::<u8>(), None) } {
1929             Err(SurfaceCreationError::RequirementNotMet {
1930                 requires_one_of:
1931                     RequiresOneOf {
1932                         instance_extensions,
1933                         ..
1934                     },
1935                 ..
1936             }) if instance_extensions.contains(&"khr_android_surface") => (),
1937             _ => panic!(),
1938         }
1939     }
1940 }
1941