bedrock/surface/
surface.rs

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