screen_13/driver/
surface.rs1use {
4 super::{DriverError, Instance, device::Device},
5 ash::vk,
6 ash_window::create_surface,
7 log::warn,
8 raw_window_handle::{HasDisplayHandle, HasWindowHandle},
9 std::{
10 fmt::{Debug, Formatter},
11 ops::Deref,
12 sync::Arc,
13 thread::panicking,
14 },
15};
16
17pub struct Surface {
19 device: Arc<Device>,
20 surface: vk::SurfaceKHR,
21}
22
23impl Surface {
24 #[profiling::function]
29 pub fn create(
30 device: &Arc<Device>,
31 window: &(impl HasDisplayHandle + HasWindowHandle),
32 ) -> Result<Self, DriverError> {
33 let device = Arc::clone(device);
34 let instance = Device::instance(&device);
35 let display_handle = window.display_handle().map_err(|err| {
36 warn!("{err}");
37
38 DriverError::Unsupported
39 })?;
40 let window_handle = window.window_handle().map_err(|err| {
41 warn!("{err}");
42
43 DriverError::Unsupported
44 })?;
45 let surface = unsafe {
46 create_surface(
47 Instance::entry(instance),
48 instance,
49 display_handle.as_raw(),
50 window_handle.as_raw(),
51 None,
52 )
53 }
54 .map_err(|err| {
55 warn!("Unable to create surface: {err}");
56
57 DriverError::Unsupported
58 })?;
59
60 Ok(Self { device, surface })
61 }
62
63 #[profiling::function]
65 pub fn formats(this: &Self) -> Result<Vec<vk::SurfaceFormatKHR>, DriverError> {
66 unsafe {
67 this.device
68 .surface_ext
69 .as_ref()
70 .unwrap()
71 .get_physical_device_surface_formats(*this.device.physical_device, this.surface)
72 .map_err(|err| {
73 warn!("Unable to get surface formats: {err}");
74
75 DriverError::Unsupported
76 })
77 }
78 }
79
80 #[profiling::function]
82 pub fn linear(formats: &[vk::SurfaceFormatKHR]) -> Option<vk::SurfaceFormatKHR> {
83 formats
84 .iter()
85 .find(|&&vk::SurfaceFormatKHR { format, .. }| {
86 matches!(
87 format,
88 vk::Format::R8G8B8A8_UNORM | vk::Format::B8G8R8A8_UNORM
89 )
90 })
91 .copied()
92 }
93
94 pub fn linear_or_default(formats: &[vk::SurfaceFormatKHR]) -> vk::SurfaceFormatKHR {
100 Self::linear(formats).unwrap_or_else(|| formats.first().copied().unwrap_or_default())
101 }
102
103 #[profiling::function]
105 pub fn srgb(formats: &[vk::SurfaceFormatKHR]) -> Option<vk::SurfaceFormatKHR> {
106 formats
107 .iter()
108 .find(
109 |&&vk::SurfaceFormatKHR {
110 color_space,
111 format,
112 }| {
113 matches!(color_space, vk::ColorSpaceKHR::SRGB_NONLINEAR)
114 && matches!(
115 format,
116 vk::Format::R8G8B8A8_SRGB | vk::Format::B8G8R8A8_SRGB
117 )
118 },
119 )
120 .copied()
121 }
122
123 pub fn srgb_or_default(formats: &[vk::SurfaceFormatKHR]) -> vk::SurfaceFormatKHR {
129 Self::srgb(formats).unwrap_or_else(|| formats.first().copied().unwrap_or_default())
130 }
131}
132
133impl Debug for Surface {
134 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
135 f.write_str("Surface")
136 }
137}
138
139impl Deref for Surface {
140 type Target = vk::SurfaceKHR;
141
142 fn deref(&self) -> &Self::Target {
143 &self.surface
144 }
145}
146
147impl Drop for Surface {
148 #[profiling::function]
149 fn drop(&mut self) {
150 if panicking() {
151 return;
152 }
153
154 let surface_ext = Device::expect_surface_ext(&self.device);
155
156 unsafe {
157 surface_ext.destroy_surface(self.surface, None);
158 }
159 }
160}