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 pub fn capabilities(this: &Self) -> Result<vk::SurfaceCapabilitiesKHR, DriverError> {
26 let surface_ext = Device::expect_surface_ext(&this.device);
27
28 unsafe {
29 surface_ext.get_physical_device_surface_capabilities(
30 *this.device.physical_device,
31 this.surface,
32 )
33 }
34 .inspect_err(|err| warn!("unable to get surface capabilities: {err}"))
35 .or(Err(DriverError::Unsupported))
36 }
37
38 #[profiling::function]
43 pub fn create(
44 device: &Arc<Device>,
45 window: &(impl HasDisplayHandle + HasWindowHandle),
46 ) -> Result<Self, DriverError> {
47 let device = Arc::clone(device);
48 let instance = Device::instance(&device);
49 let display_handle = window.display_handle().map_err(|err| {
50 warn!("{err}");
51
52 DriverError::Unsupported
53 })?;
54 let window_handle = window.window_handle().map_err(|err| {
55 warn!("{err}");
56
57 DriverError::Unsupported
58 })?;
59 let surface = unsafe {
60 create_surface(
61 Instance::entry(instance),
62 instance,
63 display_handle.as_raw(),
64 window_handle.as_raw(),
65 None,
66 )
67 }
68 .map_err(|err| {
69 warn!("Unable to create surface: {err}");
70
71 DriverError::Unsupported
72 })?;
73
74 Ok(Self { device, surface })
75 }
76
77 #[profiling::function]
79 pub fn formats(this: &Self) -> Result<Vec<vk::SurfaceFormatKHR>, DriverError> {
80 unsafe {
81 this.device
82 .surface_ext
83 .as_ref()
84 .unwrap()
85 .get_physical_device_surface_formats(*this.device.physical_device, this.surface)
86 .map_err(|err| {
87 warn!("Unable to get surface formats: {err}");
88
89 DriverError::Unsupported
90 })
91 }
92 }
93
94 #[profiling::function]
96 pub fn linear(formats: &[vk::SurfaceFormatKHR]) -> Option<vk::SurfaceFormatKHR> {
97 formats
98 .iter()
99 .find(|&&vk::SurfaceFormatKHR { format, .. }| {
100 matches!(
101 format,
102 vk::Format::R8G8B8A8_UNORM | vk::Format::B8G8R8A8_UNORM
103 )
104 })
105 .copied()
106 }
107
108 pub fn linear_or_default(formats: &[vk::SurfaceFormatKHR]) -> vk::SurfaceFormatKHR {
114 Self::linear(formats).unwrap_or_else(|| formats.first().copied().unwrap_or_default())
115 }
116
117 pub fn present_modes(this: &Self) -> Result<Vec<vk::PresentModeKHR>, DriverError> {
119 let surface_ext = Device::expect_surface_ext(&this.device);
120
121 unsafe {
122 surface_ext.get_physical_device_surface_present_modes(
123 *this.device.physical_device,
124 this.surface,
125 )
126 }
127 .inspect_err(|err| warn!("unable to get surface present modes: {err}"))
128 .or(Err(DriverError::Unsupported))
129 }
130
131 #[profiling::function]
133 pub fn srgb(formats: &[vk::SurfaceFormatKHR]) -> Option<vk::SurfaceFormatKHR> {
134 formats
135 .iter()
136 .find(
137 |&&vk::SurfaceFormatKHR {
138 color_space,
139 format,
140 }| {
141 matches!(color_space, vk::ColorSpaceKHR::SRGB_NONLINEAR)
142 && matches!(
143 format,
144 vk::Format::R8G8B8A8_SRGB | vk::Format::B8G8R8A8_SRGB
145 )
146 },
147 )
148 .copied()
149 }
150
151 pub fn srgb_or_default(formats: &[vk::SurfaceFormatKHR]) -> vk::SurfaceFormatKHR {
157 Self::srgb(formats).unwrap_or_else(|| formats.first().copied().unwrap_or_default())
158 }
159}
160
161impl Debug for Surface {
162 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
163 f.write_str("Surface")
164 }
165}
166
167impl Deref for Surface {
168 type Target = vk::SurfaceKHR;
169
170 fn deref(&self) -> &Self::Target {
171 &self.surface
172 }
173}
174
175impl Drop for Surface {
176 #[profiling::function]
177 fn drop(&mut self) {
178 if panicking() {
179 return;
180 }
181
182 let surface_ext = Device::expect_surface_ext(&self.device);
183
184 unsafe {
185 surface_ext.destroy_surface(self.surface, None);
186 }
187 }
188}