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