wgpu_hal/vulkan/
drm.rs
1#![cfg(all(unix, not(target_vendor = "apple"), not(target_family = "wasm")))]
2
3use alloc::{string::ToString, vec::Vec};
4use core::mem::MaybeUninit;
5
6use ash::{ext, khr, vk};
7
8macro_rules! to_u64 {
9 ($expr:expr) => {{
10 #[allow(trivial_numeric_casts)]
11 let expr = $expr as u64;
12 assert!(size_of_val(&expr) <= size_of::<u64>());
13 expr
14 }};
15}
16
17impl super::Instance {
18 pub unsafe fn create_surface_from_drm(
24 &self,
25 fd: i32,
26 plane: u32,
27 connector_id: u32,
28 width: u32,
29 height: u32,
30 refresh_rate: u32,
31 ) -> Result<super::Surface, crate::InstanceError> {
32 if !self
33 .shared
34 .extensions
35 .contains(&ext::acquire_drm_display::NAME)
36 {
37 return Err(crate::InstanceError::new(
38 "Vulkan driver does not support VK_EXT_acquire_drm_display".to_string(),
39 ));
40 }
41
42 let drm_stat = {
43 let mut stat = MaybeUninit::<libc::stat>::uninit();
44
45 if unsafe { libc::fstat(fd, stat.as_mut_ptr()) } != 0 {
46 return Err(crate::InstanceError::new(
47 "Unable to fstat drm device".to_string(),
48 ));
49 }
50
51 unsafe { stat.assume_init() }
52 };
53
54 let raw_devices = match unsafe { self.shared.raw.enumerate_physical_devices() } {
55 Ok(devices) => devices,
56 Err(err) => {
57 log::error!("enumerate_adapters: {err}");
58 Vec::new()
59 }
60 };
61
62 let mut physical_device = None;
63
64 for device in raw_devices {
65 let properties2 = vk::PhysicalDeviceProperties2KHR::default();
66
67 let mut drm_props = vk::PhysicalDeviceDrmPropertiesEXT::default();
68 let mut properties2 = properties2.push_next(&mut drm_props);
69
70 unsafe {
71 self.shared
72 .raw
73 .get_physical_device_properties2(device, &mut properties2)
74 };
75
76 let primary_devid =
85 libc::makedev(drm_props.primary_major as _, drm_props.primary_minor as _);
86 let render_devid =
87 libc::makedev(drm_props.render_major as _, drm_props.render_minor as _);
88
89 #[allow(clippy::useless_conversion)]
98 if [primary_devid, render_devid]
99 .map(|devid| to_u64!(devid))
100 .contains(&to_u64!(drm_stat.st_rdev))
101 {
102 physical_device = Some(device)
103 }
104 }
105
106 let physical_device = physical_device.ok_or(crate::InstanceError::new(
107 "Failed to find suitable drm device".to_string(),
108 ))?;
109
110 let acquire_drm_display_instance =
111 ext::acquire_drm_display::Instance::new(&self.shared.entry, &self.shared.raw);
112
113 let display = unsafe {
114 acquire_drm_display_instance
115 .get_drm_display(physical_device, fd, connector_id)
116 .expect("Failed to get drm display")
117 };
118
119 unsafe {
120 acquire_drm_display_instance
121 .acquire_drm_display(physical_device, fd, display)
122 .expect("Failed to acquire drm display")
123 }
124
125 let display_instance = khr::display::Instance::new(&self.shared.entry, &self.shared.raw);
126
127 let modes = unsafe {
128 display_instance
129 .get_display_mode_properties(physical_device, display)
130 .expect("Failed to get display modes")
131 };
132
133 let mut mode = None;
134
135 for current_mode in modes {
136 log::trace!(
137 "Comparing mode {}x{}@{} with {width}x{height}@{refresh_rate}",
138 current_mode.parameters.visible_region.width,
139 current_mode.parameters.visible_region.height,
140 current_mode.parameters.refresh_rate
141 );
142 if current_mode.parameters.refresh_rate == refresh_rate
143 && current_mode.parameters.visible_region.width == width
144 && current_mode.parameters.visible_region.height == height
145 {
146 mode = Some(current_mode)
147 }
148 }
149
150 let mode = mode.ok_or(crate::InstanceError::new(
151 "Failed to find suitable display mode".to_string(),
152 ))?;
153
154 let create_info = vk::DisplaySurfaceCreateInfoKHR::default()
155 .display_mode(mode.display_mode)
156 .image_extent(mode.parameters.visible_region)
157 .transform(vk::SurfaceTransformFlagsKHR::IDENTITY)
158 .alpha_mode(vk::DisplayPlaneAlphaFlagsKHR::OPAQUE)
159 .plane_index(plane);
160
161 let surface = unsafe { display_instance.create_display_plane_surface(&create_info, None) }
162 .expect("Failed to create DRM surface");
163
164 Ok(self.create_surface_from_vk_surface_khr(surface))
165 }
166}