Skip to main content

bedrock/
surface.rs

1//! Vulkan Surface/Swapchain Extensions
2
3use bedrock_vk as brvk;
4
5use crate::*;
6
7#[cfg(feature = "VK_KHR_swapchain")]
8mod swapchain;
9#[cfg(feature = "VK_KHR_swapchain")]
10pub use self::swapchain::*;
11
12#[cfg(feature = "VK_KHR_swapchain")]
13mod swapchain_surface_integrated;
14#[cfg(feature = "VK_KHR_swapchain")]
15pub use self::swapchain_surface_integrated::*;
16
17#[cfg(feature = "VK_EXT_full_screen_exclusive")]
18mod full_screen_exclusive;
19#[cfg(feature = "VK_EXT_full_screen_exclusive")]
20pub use self::full_screen_exclusive::*;
21
22/// Opaque handle to a surface object
23#[derive(VkHandle, VkObject, InstanceChild)]
24#[VkObject(type = brvk::VkSurfaceKHR::OBJECT_TYPE)]
25pub struct SurfaceObject<Instance: crate::Instance>(pub(crate) brvk::VkSurfaceKHR, #[parent] pub(crate) Instance);
26unsafe impl<Instance: crate::Instance + Sync> Sync for SurfaceObject<Instance> {}
27unsafe impl<Instance: crate::Instance + Send> Send for SurfaceObject<Instance> {}
28#[implements]
29impl<Instance: crate::Instance> Drop for SurfaceObject<Instance> {
30    #[inline(always)]
31    fn drop(&mut self) {
32        unsafe {
33            crate::vkfn_wrapper::destroy_surface(self.1.as_transparent_ref(), VkHandleRefMut::dangling(self.0), None);
34        }
35    }
36}
37impl<Instance: crate::Instance> Surface for SurfaceObject<Instance> {}
38impl<Instance: crate::Instance> SurfaceObject<Instance> {
39    #[implements]
40    #[inline(always)]
41    pub fn new(
42        pd: impl crate::PhysicalDevice + crate::InstanceChildTransferrable<ConcreteInstance = Instance>,
43        create_info: &(impl SurfaceCreateInfo + ?Sized),
44    ) -> crate::Result<Self> {
45        Ok(Self(create_info.execute(pd.instance(), None)?, pd.transfer_instance()))
46    }
47
48    #[inline(always)]
49    pub const unsafe fn manage(handle: brvk::VkSurfaceKHR, instance: Instance) -> Self {
50        Self(handle, instance)
51    }
52
53    #[inline(always)]
54    pub const fn unmanage(self) -> (brvk::VkSurfaceKHR, Instance) {
55        let handle = unsafe { core::ptr::read(&self.0) };
56        let instance = unsafe { core::ptr::read(&self.1) };
57        core::mem::forget(self);
58
59        (handle, instance)
60    }
61}
62impl<Instance: crate::Instance + Clone> SurfaceObject<&'_ Instance> {
63    /// Owning parent object by cloning it.
64    #[inline(always)]
65    pub fn clone_parent(self) -> SurfaceObject<Instance> {
66        let r = SurfaceObject(self.0, self.1.clone());
67        core::mem::forget(self);
68
69        r
70    }
71}
72
73pub trait Surface: VkHandle<Handle = brvk::VkSurfaceKHR> + InstanceChild {}
74DerefContainerBracketImpl!(for Surface {});
75
76pub trait TransferSurfaceObject {
77    type ConcreteSurface: crate::Surface;
78
79    fn transfer_surface(self) -> Self::ConcreteSurface;
80}
81impl<Parent: VulkanStructureProvider + TransferSurfaceObject, T> TransferSurfaceObject for Extends<Parent, T> {
82    type ConcreteSurface = Parent::ConcreteSurface;
83
84    #[inline(always)]
85    fn transfer_surface(self) -> Self::ConcreteSurface {
86        self.0.transfer_surface()
87    }
88}
89
90/// Presentation mode supported for a surface
91#[repr(i32)]
92#[derive(Debug, Clone, PartialEq, Eq, Copy)]
93pub enum PresentMode {
94    /// The presentation engine does not wait for a vertical blanking period to update the current image, meaning
95    /// this mode may result in visible tearing
96    Immediate = brvk::VK_PRESENT_MODE_IMMEDIATE_KHR,
97    /// The presentation engine waits for the next vertical blanking period to update the current image.
98    /// Tearing cannot be observed. An internal single-entry queue is used to hold pending presentation requests.
99    /// If the queue is full when a new presentation request is received, the new request replaces the existing entry, and any images
100    /// associated with the prior entry become available for re-use by the application
101    Mailbox = brvk::VK_PRESENT_MODE_MAILBOX_KHR,
102    /// The presentation engine waits for the next vertical blanking period to update the current image.
103    /// Tearing cannot be observed. An internal queue is used to hold pending presentation requests.
104    /// New requests are appended to the end of the queue, and one request is removed from the beginning of the queue
105    /// and processed during each vertical blanking period in which the queue is non-empty.
106    FIFO = brvk::VK_PRESENT_MODE_FIFO_KHR,
107    /// The presentation engine generally waits for the next vertical blanking period to update the currnt image.
108    /// If a vertical blanking period has already passed since the last update of the current image then the presentation engine
109    /// does not wait for another vertical blanking period for the update, meaning this mode may result in visible tearing in this case
110    FIFORelaxed = brvk::VK_PRESENT_MODE_FIFO_RELAXED_KHR,
111}
112
113/// Presentation transforms supported on a device
114#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
115#[bitflags_newtype]
116pub struct SurfaceTransformFlags(pub(crate) brvk::VkSurfaceTransformFlagsKHR);
117impl SurfaceTransformFlags {
118    /// The image content is presented without being transformed
119    pub const IDENTITY: Self = Self(brvk::VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR);
120    /// The image content is rotated 90 degrees clockwise
121    pub const ROTATE_90: Self = Self(brvk::VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR);
122    /// The image content is rotated 180 degrees clockwise
123    pub const ROTATE_180: Self = Self(brvk::VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR);
124    /// The image content is rotated 270 degrees clockwise
125    pub const ROTATE_270: Self = Self(brvk::VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR);
126    /// The image content is mirrored horizontally
127    pub const HORIZONTAL_MIRROR: Self = Self(brvk::VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR);
128    /// The image content is mirrored horizontally, then rotated 90 degrees clockwise
129    pub const HORIZONTAL_MIRROR_ROTATE_90: Self = Self(brvk::VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR);
130    /// The image content is mirrored horizontally, then rotated 180 degrees clockwise
131    pub const HORIZONTAL_MIRROR_ROTATE_180: Self =
132        Self(brvk::VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR);
133    /// The image content is mirrored horizontally, then rotated 270 degrees clockwise
134    pub const HORIZONTAL_MIRROR_ROTATE_270: Self =
135        Self(brvk::VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR);
136    /// The presentation transform is not specified, and is instead determined by platform-specific considerations and mechanisms outside Vulkan
137    pub const INHERIT: Self = Self(brvk::VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR);
138}
139
140/// Alpha compositing modes supported on a device
141#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
142#[bitflags_newtype]
143pub struct CompositeAlphaFlags(brvk::VkCompositeAlphaFlagsKHR);
144impl CompositeAlphaFlags {
145    /// The alpha channel, if it exists, of the image is ignored in the compositing process
146    pub const OPAQUE: Self = Self(brvk::VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR);
147    /// The alpha channel, if it exists, of the images is respected in the compositing process.
148    /// The non-alpha channels of the image are expected to already be multiplied by the alpha channel by the application
149    pub const PRE_MULTIPLIED: Self = Self(brvk::VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR);
150    /// The alpha channel, if it exists, of the images is respected in the compositing process.
151    /// The non-alpha channels of the image are not expected to already be multiplied by the alpha channel by the application;
152    /// instead, the compositor will multiply the non-alpha channels of the image by the alpha channel during compositing
153    pub const POST_MULTIPLIED: Self = Self(brvk::VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR);
154    /// The way in which the presentation engine treats the alpha channel in the images is unknown to the Vulkan API.
155    /// Instead, the application is responsible for setting the composite alpha blending mode using native window system commands
156    pub const INHERIT: Self = Self(brvk::VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR);
157}
158
159#[repr(transparent)]
160pub struct SurfaceCapabilities(pub brvk::VkSurfaceCapabilitiesKHR);
161impl SurfaceCapabilities {
162    /// The presentation transforms supported for the surface
163    pub const fn supported_transforms(&self) -> SurfaceTransformFlags {
164        SurfaceTransformFlags(self.0.supportedTransforms)
165    }
166
167    /// The surface's current transform relative to the presentation engine's natural orientation
168    pub const fn current_transform(&self) -> SurfaceTransformFlags {
169        SurfaceTransformFlags(self.0.currentTransform)
170    }
171
172    /// The alpha compositing modes supported by the presentation engine for the surface
173    pub const fn supported_composite_alpha(&self) -> CompositeAlphaFlags {
174        CompositeAlphaFlags(self.0.supportedCompositeAlpha)
175    }
176
177    /// The ways the application can use the presentable images of a swapchain
178    pub const fn supported_usage_flags(&self) -> ImageUsageFlags {
179        unsafe { core::mem::transmute(self.0.supportedUsageFlags) }
180    }
181}
182
183pub use brvk::VkSurfaceFormatKHR as SurfaceFormat;
184
185pub trait SurfaceCreateInfo {
186    // Note: executeは安全になるようにする(selfの構築でunsafeにするかsafetyを担保する)
187    #[implements]
188    fn execute(
189        &self,
190        instance: &(impl VkHandle<Handle = brvk::VkInstance> + ?Sized),
191        allocation_callbacks: Option<&brvk::VkAllocationCallbacks>,
192    ) -> crate::Result<brvk::VkSurfaceKHR>;
193}
194
195#[cfg(feature = "VK_KHR_xlib_surface")]
196#[repr(transparent)]
197pub struct XlibSurfaceCreateInfo(brvk::VkXlibSurfaceCreateInfoKHR);
198#[cfg(feature = "VK_KHR_xlib_surface")]
199impl XlibSurfaceCreateInfo {
200    /// # Safety
201    /// Provided `display` must be a valid reference
202    pub const unsafe fn new(display: *mut x11::xlib::Display, window: x11::xlib::Window) -> Self {
203        Self(brvk::VkXlibSurfaceCreateInfoKHR {
204            sType: brvk::VkXlibSurfaceCreateInfoKHR::TYPE,
205            pNext: core::ptr::null(),
206            flags: 0,
207            dpy: display,
208            window,
209        })
210    }
211}
212#[cfg(feature = "VK_KHR_xlib_surface")]
213impl SurfaceCreateInfo for XlibSurfaceCreateInfo {
214    #[implements]
215    #[inline(always)]
216    fn execute(
217        &self,
218        instance: &(impl VkHandle<Handle = brvk::VkInstance> + ?Sized),
219        allocation_callbacks: Option<&brvk::VkAllocationCallbacks>,
220    ) -> crate::Result<brvk::VkSurfaceKHR> {
221        let mut h = core::mem::MaybeUninit::uninit();
222        crate::error::translate_vk_result(unsafe {
223            brvk::fns::create_xlib_surface_khr(
224                instance.native_ptr(),
225                &self.0,
226                crate::ffi_helper::opt_pointer(allocation_callbacks),
227                h.as_mut_ptr(),
228            )
229        })?;
230
231        Ok(unsafe { h.assume_init() })
232    }
233}
234
235#[cfg(feature = "VK_KHR_xcb_surface")]
236#[repr(transparent)]
237pub struct XcbSurfaceCreateInfo(brvk::VkXcbSurfaceCreateInfoKHR);
238#[cfg(feature = "VK_KHR_xcb_surface")]
239impl XcbSurfaceCreateInfo {
240    /// # Safety
241    /// Provided `connection` must be a valid reference
242    pub const unsafe fn new(connection: *mut xcb::ffi::xcb_connection_t, window: xcb::x::Window) -> Self {
243        Self(brvk::VkXcbSurfaceCreateInfoKHR {
244            sType: brvk::VkXcbSurfaceCreateInfoKHR::TYPE,
245            pNext: core::ptr::null(),
246            flags: 0,
247            connection,
248            window,
249        })
250    }
251}
252#[cfg(feature = "VK_KHR_xcb_surface")]
253impl SurfaceCreateInfo for XcbSurfaceCreateInfo {
254    #[implements]
255    #[inline(always)]
256    fn execute(
257        &self,
258        instance: &(impl VkHandle<Handle = brvk::VkInstance> + ?Sized),
259        allocation_callbacks: Option<&brvk::VkAllocationCallbacks>,
260    ) -> crate::Result<brvk::VkSurfaceKHR> {
261        let mut h = core::mem::MaybeUninit::uninit();
262        crate::error::translate_vk_result(unsafe {
263            brvk::fns::create_xcb_surface_khr(
264                instance.native_ptr(),
265                &self.0,
266                crate::ffi_helper::opt_pointer(allocation_callbacks),
267                h.as_mut_ptr(),
268            )
269        })?;
270
271        Ok(unsafe { h.assume_init() })
272    }
273}
274
275#[cfg(feature = "VK_KHR_wayland_surface")]
276#[repr(transparent)]
277pub struct WaylandSurfaceCreateInfo(brvk::VkWaylandSurfaceCreateInfoKHR);
278#[cfg(feature = "VK_KHR_wayland_surface")]
279impl WaylandSurfaceCreateInfo {
280    /// # Safety
281    /// Provided `display` and `surface` must be a valid reference
282    pub const unsafe fn new(display: *mut core::ffi::c_void, surface: *mut core::ffi::c_void) -> Self {
283        Self(brvk::VkWaylandSurfaceCreateInfoKHR {
284            sType: brvk::VkWaylandSurfaceCreateInfoKHR::TYPE,
285            pNext: core::ptr::null(),
286            flags: 0,
287            display,
288            surface,
289        })
290    }
291}
292#[cfg(feature = "VK_KHR_wayland_surface")]
293impl SurfaceCreateInfo for WaylandSurfaceCreateInfo {
294    #[implements]
295    #[inline(always)]
296    fn execute(
297        &self,
298        instance: &(impl VkHandle<Handle = brvk::VkInstance> + ?Sized),
299        allocation_callbacks: Option<&brvk::VkAllocationCallbacks>,
300    ) -> crate::Result<brvk::VkSurfaceKHR> {
301        let mut h = core::mem::MaybeUninit::uninit();
302        crate::error::translate_vk_result(unsafe {
303            brvk::fns::create_wayland_surface_khr(
304                instance.native_ptr(),
305                &self.0,
306                crate::ffi_helper::opt_pointer(allocation_callbacks),
307                h.as_mut_ptr(),
308            )
309        })?;
310
311        Ok(unsafe { h.assume_init() })
312    }
313}
314
315#[cfg(feature = "VK_KHR_android_surface")]
316#[repr(transparent)]
317pub struct AndroidSurfaceCreateInfo(brvk::VkAndroidSurfaceCreateInfoKHR);
318#[cfg(feature = "VK_KHR_android_surface")]
319impl AndroidSurfaceCreateInfo {
320    /// # Safety
321    /// Provided `window` must be a valid reference
322    pub const unsafe fn new(window: *mut android::ANativeWindow) -> Self {
323        Self(brvk::VkAndroidSurfaceCreateInfoKHR {
324            sType: brvk::VkAndroidSurfaceCreateInfoKHR::TYPE,
325            pNext: core::ptr::null(),
326            flags: 0,
327            window,
328        })
329    }
330}
331#[cfg(feature = "VK_KHR_android_surface")]
332impl SurfaceCreateInfo for AndroidSurfaceCreateInfo {
333    #[implements]
334    #[inline(always)]
335    fn execute(
336        &self,
337        instance: &(impl VkHandle<Handle = brvk::VkInstance> + ?Sized),
338        allocation_callbacks: Option<&brvk::VkAllocationCallbacks>,
339    ) -> crate::Result<brvk::VkSurfaceKHR> {
340        let mut h = core::mem::MaybeUninit::uninit();
341        crate::error::translate_vk_result(unsafe {
342            brvk::fns::create_android_surface_khr(
343                instance.native_ptr(),
344                &self.0,
345                crate::ffi_helper::opt_pointer(allocation_callbacks),
346                h.as_mut_ptr(),
347            )
348        })?;
349
350        Ok(unsafe { h.assume_init() })
351    }
352}
353
354#[cfg(feature = "VK_KHR_win32_surface")]
355#[repr(transparent)]
356pub struct Win32SurfaceCreateInfo(brvk::VkWin32SurfaceCreateInfoKHR);
357#[cfg(feature = "VK_KHR_win32_surface")]
358impl Win32SurfaceCreateInfo {
359    pub const fn new(hinstance: windows::Win32::Foundation::HINSTANCE, hwnd: windows::Win32::Foundation::HWND) -> Self {
360        Self(brvk::VkWin32SurfaceCreateInfoKHR {
361            sType: brvk::VkWin32SurfaceCreateInfoKHR::TYPE,
362            pNext: core::ptr::null(),
363            flags: 0,
364            hinstance,
365            hwnd,
366        })
367    }
368}
369#[cfg(feature = "VK_KHR_win32_surface")]
370impl SurfaceCreateInfo for Win32SurfaceCreateInfo {
371    #[implements]
372    #[inline]
373    fn execute(
374        &self,
375        instance: &(impl VkHandle<Handle = brvk::VkInstance> + ?Sized),
376        allocation_callbacks: Option<&brvk::VkAllocationCallbacks>,
377    ) -> crate::Result<brvk::VkSurfaceKHR> {
378        let mut h = core::mem::MaybeUninit::uninit();
379        crate::error::translate_vk_result(unsafe {
380            brvk::fns::create_win32_surface_khr(
381                instance.native_ptr(),
382                &self.0,
383                crate::ffi_helper::opt_pointer(allocation_callbacks),
384                h.as_mut_ptr(),
385            )
386        })?;
387
388        Ok(unsafe { h.assume_init() })
389    }
390}
391
392#[cfg(feature = "VK_EXT_metal_surface")]
393#[repr(transparent)]
394pub struct MetalSurfaceCreateInfo(brvk::VkMetalSurfaceCreateInfoEXT);
395#[cfg(feature = "VK_EXT_metal_surface")]
396impl MetalSurfaceCreateInfo {
397    /// # Safety
398    /// Provided `layer` must be a valid reference
399    pub const unsafe fn new(layer: *const core::ffi::c_void) -> Self {
400        Self(brvk::VkMetalSurfaceCreateInfoEXT {
401            sType: brvk::VkMetalSurfaceCreateInfoEXT::TYPE,
402            pNext: core::ptr::null(),
403            flags: 0,
404            pLayer: layer,
405        })
406    }
407}
408#[cfg(feature = "VK_EXT_metal_surface")]
409impl SurfaceCreateInfo for MetalSurfaceCreateInfo {
410    #[implements]
411    #[inline(always)]
412    fn execute(
413        &self,
414        instance: &(impl VkHandle<Handle = brvk::VkInstance> + ?Sized),
415        allocation_callbacks: Option<&brvk::VkAllocationCallbacks>,
416    ) -> crate::Result<brvk::VkSurfaceKHR> {
417        let mut h = core::mem::MaybeUninit::uninit();
418        crate::error::translate_vk_result(unsafe {
419            brvk::fns::create_metal_surface_ext(
420                instance.native_ptr(),
421                &self.0,
422                crate::ffi_helper::opt_pointer(allocation_callbacks),
423                h.as_mut_ptr(),
424            )
425        })?;
426
427        Ok(unsafe { h.assume_init() })
428    }
429}
430
431#[cfg(feature = "VK_KHR_display")]
432#[repr(transparent)]
433pub struct DisplaySurfaceCreateInfo(pub brvk::VkDisplaySurfaceCreateInfoKHR);
434#[cfg(feature = "VK_KHR_display")]
435impl DisplaySurfaceCreateInfo {
436    pub const fn new(
437        mode: &super::DisplayMode,
438        plane_index: u32,
439        plane_stack_index: u32,
440        transform: SurfaceTransformFlags,
441        global_alpha: f32,
442        alpha_mode: super::DisplayPlaneAlpha,
443        extent: brvk::VkExtent2D,
444    ) -> Self {
445        Self(brvk::VkDisplaySurfaceCreateInfoKHR {
446            sType: brvk::VkDisplaySurfaceCreateInfoKHR::TYPE,
447            pNext: core::ptr::null(),
448            flags: 0,
449            displayMode: mode.0,
450            planeIndex: plane_index,
451            planeStackIndex: plane_stack_index,
452            transform: transform.bits(),
453            globalAlpha: global_alpha,
454            alphaMode: alpha_mode as _,
455            imageExtent: extent,
456        })
457    }
458}