use alloc::{string::ToString, vec::Vec}; use core::{mem::MaybeUninit, num::NonZeroU32}; use std::os::fd::{AsFd, BorrowedFd};
use ash::{ext, khr, vk};
use drm::{ self,
control::{self, connector, Device as _},
};
struct Card(i32); impl AsFd for Card { fn as_fd(&self) -> BorrowedFd<'_> { unsafe { BorrowedFd::borrow_raw(self.0) }
}
} impl control::Device for Card {} impl drm::Device for Card {}
macro_rules! to_u64 {
($expr:expr) => {{ #[allow(trivial_numeric_casts)] let expr = $expr as u64;
assert!(size_of_val(&expr) <= size_of::<u64>());
expr
}};
}
implsuper::Instance { /// Creates a new surface from the given drm fd and plane, deriving the connector and mode. /// /// # Safety /// /// - All parameters must point to valid DRM values. pubfn create_surface_from_drm_plane(
&self,
fd: i32,
plane: u32,
) -> Result<super::Surface, crate::InstanceError> { let card = Card(fd); let plane_info = card
.get_plane(
NonZeroU32::new(plane)
.ok_or(crate::InstanceError::new("Invalid drm plane".to_string()))?
.into(),
)
.map_err(|e| crate::InstanceError::with_source("drm plane not found".to_string(), e))?; let crtc_handle = plane_info.crtc().ok_or(crate::InstanceError::new( "No CRTC for drm plane".to_string(),
))?; let crtc_info = card
.get_crtc(crtc_handle)
.map_err(|e| crate::InstanceError::with_source("drm CRTC not found".to_string(), e))?; let mode = crtc_info.mode().ok_or(crate::InstanceError::new( "No mode for drm CRTC".to_string(),
))?;
letmut connector_and_mode = None; let resources = card.resource_handles().map_err(|e| { crate::InstanceError::with_source("No drm resource handles found".to_string(), e)
})?; for connector_handle in resources.connectors() { let Ok(connector_info) = card.get_connector(*connector_handle, false) else { continue;
}; if connector_info.state() != connector::State::Connected { continue;
}
let (connector_handle, mode) = connector_and_mode.ok_or(crate::InstanceError::new( "Failed to derive drm connector and mode for plane".to_string(),
))?; let (width, height) = mode.size(); // Rate in millihertz let refresh_rate = (((mode.clock() as f64 * 1000.0)
/ (mode.hsync().2as f64 * mode.vsync().2as f64))
* 1000.0)
.round() as u32; unsafe { self.create_surface_from_drm(
fd,
plane,
connector_handle.into(),
width as u32,
height as u32,
refresh_rate,
)
}
}
/// Creates a new surface from the given drm configuration. /// /// # Safety /// /// - All parameters must point to valid DRM values. pubunsafefn create_surface_from_drm(
&self,
fd: i32,
plane: u32,
connector_id: u32,
width: u32,
height: u32,
refresh_rate: u32,
) -> Result<super::Surface, crate::InstanceError> { if !self
.shared
.extensions
.contains(&ext::acquire_drm_display::NAME)
{ return Err(crate::InstanceError::new( "Vulkan driver does not support VK_EXT_acquire_drm_display".to_string(),
));
}
let drm_stat = { letmut stat = MaybeUninit::<libc::stat>::uninit();
let primary_devid =
libc::makedev(drm_props.primary_major as _, drm_props.primary_minor as _); let render_devid =
libc::makedev(drm_props.render_major as _, drm_props.render_minor as _);
// On most platforms, both `*_devid`s and `st_rdev` are `dev_t`s (which is generally // observed to be an unsigned integral type no greater than 64 bits). However, on some // platforms, there divergences from this pattern: // // - `armv7-linux-androideabi`: `dev_t` is `c_ulong`, and `*_devid`s are `dev_t`, but // `st_rdev` is `c_ulonglong`. So, we can't just do a `==` comparison. // - OpenBSD has `dev_t` on both sides, but is `i32` (N.B., unsigned). Therefore, we // can't just use `u64::from`. #[allow(clippy::useless_conversion)] if [primary_devid, render_devid]
.map(|devid| to_u64!(devid))
.contains(&to_u64!(drm_stat.st_rdev))
{
physical_device = Some(device)
}
}
let physical_device = physical_device.ok_or(crate::InstanceError::new( "Failed to find suitable drm device".to_string(),
))?;
let acquire_drm_display_instance =
ext::acquire_drm_display::Instance::new(&self.shared.entry, &self.shared.raw);
let display = unsafe {
acquire_drm_display_instance
.get_drm_display(physical_device, fd, connector_id)
.expect("Failed to get drm display")
};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.