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