diff --git a/src/backends/metal/monitor.rs b/src/backends/metal/monitor.rs index 1d9a85e5..44c425bd 100644 --- a/src/backends/metal/monitor.rs +++ b/src/backends/metal/monitor.rs @@ -236,7 +236,13 @@ impl MetalBackend { return; } }; - let master = Rc::new(DrmMaster::new(&slf.state.ring, res.fd.clone())); + let master = match DrmMaster::new(&slf.state.ring, res.fd.clone()) { + Ok(m) => Rc::new(m), + Err(e) => { + log::error!("Could not open the drm device: {}", ErrorFmt(e)); + return; + } + }; let dev = match slf.create_drm_device(dev, &master) { Ok(d) => d, Err(e) => { diff --git a/src/backends/x.rs b/src/backends/x.rs index 21438f97..c5fc89ef 100644 --- a/src/backends/x.rs +++ b/src/backends/x.rs @@ -59,7 +59,7 @@ use { rc::Rc, }, thiserror::Error, - uapi::{c::dev_t, Errno}, + uapi::c::dev_t, }; #[derive(Debug, Error)] @@ -114,8 +114,6 @@ pub enum XBackendError { MapWindow(#[source] XconError), #[error("Could not query device")] QueryDevice(#[source] XconError), - #[error("Could not fstat the drm device")] - DrmDeviceFstat(#[source] Errno), #[error("Render device does not support XRGB8888 format")] XRGB8888, } @@ -174,10 +172,7 @@ pub async fn create(state: &Rc) -> Result, XBackendError> { Err(e) => return Err(XBackendError::DriOpen(e)), } }; - let drm_dev = match uapi::fstat(drm.raw()) { - Ok(s) => s.st_rdev, - Err(e) => return Err(XBackendError::DrmDeviceFstat(e)), - }; + let drm_dev = drm.dev(); let gbm = GbmDevice::new(&drm)?; let ctx = match state.create_gfx_context(&drm, None) { Ok(r) => r, diff --git a/src/drm_feedback.rs b/src/drm_feedback.rs index f998ddc8..136aa2f9 100644 --- a/src/drm_feedback.rs +++ b/src/drm_feedback.rs @@ -36,11 +36,10 @@ impl DrmFeedback { ids: &DrmFeedbackIds, render_ctx: &dyn GfxContext, ) -> Result { - let drm = match render_ctx.allocator().drm() { - Some(drm) => drm.raw(), + let main_device = match render_ctx.allocator().drm() { + Some(drm) => drm.dev(), _ => return Err(DrmFeedbackError::NoDrmDevice), }; - let main_device = uapi::fstat(drm).map_err(OsError::from)?.st_rdev; let (data, index_map) = create_fd_data(render_ctx); let mut memfd = uapi::memfd_create("drm_feedback", c::MFD_CLOEXEC | c::MFD_ALLOW_SEALING).unwrap(); diff --git a/src/gfx_apis/vulkan.rs b/src/gfx_apis/vulkan.rs index 14e2ca82..63c5f778 100644 --- a/src/gfx_apis/vulkan.rs +++ b/src/gfx_apis/vulkan.rs @@ -91,8 +91,6 @@ pub enum VulkanError { CreateInstance(#[source] vk::Result), #[error("Could not create a debug-utils messenger")] Messenger(#[source] vk::Result), - #[error("Could not fstat the DRM FD")] - Fstat(#[source] OsError), #[error("Could not enumerate the physical devices")] EnumeratePhysicalDevices(#[source] vk::Result), #[error("Could not find a vulkan device that matches dev_t {0}")] diff --git a/src/gfx_apis/vulkan/device.rs b/src/gfx_apis/vulkan/device.rs index 5ff1d796..9a781de2 100644 --- a/src/gfx_apis/vulkan/device.rs +++ b/src/gfx_apis/vulkan/device.rs @@ -104,11 +104,7 @@ impl VulkanInstance { } fn find_dev(&self, drm: &Drm) -> Result { - let stat = match uapi::fstat(drm.raw()) { - Ok(s) => s, - Err(e) => return Err(VulkanError::Fstat(e.into())), - }; - let dev = stat.st_rdev; + let dev = drm.dev(); log::log!( self.log_level, "Searching for vulkan device with devnum {}:{}", diff --git a/src/ifs/wp_drm_lease_device_v1.rs b/src/ifs/wp_drm_lease_device_v1.rs index c6abc93d..88a5377f 100644 --- a/src/ifs/wp_drm_lease_device_v1.rs +++ b/src/ifs/wp_drm_lease_device_v1.rs @@ -210,6 +210,8 @@ efrom!(WpDrmLeaseDeviceV1Error, ClientError); enum ReopenError { #[error("Could not open the dev node")] OpenNode(#[source] OsError), + #[error("Could not create the DRM device")] + CreateDrm(#[source] DrmError), #[error("Could not drop DRM master")] DropMaster(#[source] DrmError), } @@ -218,7 +220,7 @@ fn reopen_card(devnode: &str) -> Result, ReopenError> { let fd = uapi::open(devnode, c::O_RDWR | c::O_CLOEXEC, 0) .map_err(|e| ReopenError::OpenNode(e.into()))?; let fd = Rc::new(fd); - let drm = Drm::open_existing(fd.clone()); + let drm = Drm::open_existing(fd.clone()).map_err(ReopenError::CreateDrm)?; if drm.is_master() { drm.drop_master().map_err(ReopenError::DropMaster)?; } diff --git a/src/it/test_backend.rs b/src/it/test_backend.rs index 383dab9e..62ac58d0 100644 --- a/src/it/test_backend.rs +++ b/src/it/test_backend.rs @@ -24,7 +24,7 @@ use { on_change::OnChange, oserror::OsError, syncqueue::SyncQueue, }, video::{ - drm::{ConnectorType, Drm}, + drm::{ConnectorType, Drm, DrmError}, gbm::{GbmDevice, GbmError}, }, }, @@ -42,6 +42,8 @@ pub enum TestBackendError { NoDrmNode, #[error("Could not open drm node {0}")] OpenDrmNode(String, #[source] OsError), + #[error("Could not open the drm device")] + OpenDrmDevice(#[source] DrmError), #[error("Could not create a render context")] RenderContext(#[source] GfxError), #[error("Could not create a gbm device")] @@ -264,7 +266,7 @@ where )) } }; - let drm = Drm::open_existing(file); + let drm = Drm::open_existing(file).map_err(TestBackendError::OpenDrmDevice)?; f(drm) } diff --git a/src/portal/ptl_display.rs b/src/portal/ptl_display.rs index 5f555a6e..16a42cc5 100644 --- a/src/portal/ptl_display.rs +++ b/src/portal/ptl_display.rs @@ -162,13 +162,14 @@ impl UsrJayRenderCtxOwner for PortalDisplay { fn device(&self, fd: Rc, server_formats: Option>) { self.render_ctx.take(); - let dev_id = match uapi::fstat(fd.raw()) { - Ok(s) => s.st_rdev, + let drm = match Drm::open_existing(fd) { + Ok(d) => d, Err(e) => { - log::error!("Could not fstat display device: {}", ErrorFmt(e)); + log::error!("Could not open the drm device: {}", ErrorFmt(e)); return; } }; + let dev_id = drm.dev(); let mut render_ctx = None; if let Some(ctx) = self.state.render_ctxs.get(&dev_id) { if let Some(ctx) = ctx.upgrade() { @@ -176,7 +177,6 @@ impl UsrJayRenderCtxOwner for PortalDisplay { } } if render_ctx.is_none() { - let drm = Drm::open_existing(fd); let ctx = match create_gfx_context(&self.state.eng, &self.state.ring, &drm, GfxApi::OpenGl) { Ok(c) => c, diff --git a/src/video/drm.rs b/src/video/drm.rs index be0a05e2..a3293a7b 100644 --- a/src/video/drm.rs +++ b/src/video/drm.rs @@ -144,6 +144,8 @@ pub enum DrmError { DropMaster(#[source] OsError), #[error("Could not queue a CRTC sequence")] QueueSequence(#[source] OsError), + #[error("Could not stat the DRM fd")] + Stat(#[source] OsError), } fn render_node_name(fd: c::c_int) -> Result { @@ -177,17 +179,24 @@ fn reopen(fd: c::c_int, need_primary: bool) -> Result, DrmError> { pub struct Drm { fd: Rc, + dev: c::dev_t, } impl Drm { - pub fn open_existing(fd: Rc) -> Self { - Self { fd } + pub fn open_existing(fd: Rc) -> Result { + let stat = uapi::fstat(fd.raw()).map_err(|e| DrmError::Stat(e.into()))?; + Ok(Self { + fd, + dev: stat.st_rdev, + }) } pub fn reopen(fd: c::c_int, need_primary: bool) -> Result { - Ok(Self { - fd: reopen(fd, need_primary)?, - }) + Self::open_existing(reopen(fd, need_primary)?) + } + + pub fn dev(&self) -> c::dev_t { + self.dev } pub fn fd(&self) -> &Rc { @@ -291,16 +300,16 @@ impl DrmLease { } impl DrmMaster { - pub fn new(ring: &Rc, fd: Rc) -> Self { - Self { - drm: Drm { fd }, + pub fn new(ring: &Rc, fd: Rc) -> Result { + Ok(Self { + drm: Drm::open_existing(fd)?, u32_bufs: Default::default(), u64_bufs: Default::default(), gem_handles: Default::default(), events: Default::default(), ring: ring.clone(), buf: RefCell::new(Buf::new(1024)), - } + }) } pub fn raw(&self) -> c::c_int {