From b6bb20ed114f5f1c18c73c6eaa981ea3951c78eb Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Wed, 25 Sep 2024 11:06:33 -0700 Subject: [PATCH] Remove `backend::drm::node`; replaced with `drm` crate `node` --- src/backend/drm/mod.rs | 3 +- src/backend/drm/node/constants.rs | 39 --- src/backend/drm/node/mod.rs | 390 ------------------------------ src/backend/x11/mod.rs | 3 +- 4 files changed, 3 insertions(+), 432 deletions(-) delete mode 100644 src/backend/drm/node/constants.rs delete mode 100644 src/backend/drm/node/mod.rs diff --git a/src/backend/drm/mod.rs b/src/backend/drm/mod.rs index ceff7665d068..84efda0d54e4 100644 --- a/src/backend/drm/mod.rs +++ b/src/backend/drm/mod.rs @@ -78,7 +78,6 @@ pub mod dumb; mod error; #[cfg(feature = "backend_gbm")] pub mod gbm; -pub mod node; mod surface; @@ -89,11 +88,11 @@ pub use device::{ DrmDevice, DrmDeviceFd, DrmDeviceNotifier, DrmEvent, EventMetadata as DrmEventMetadata, PlaneClaim, Time as DrmEventTime, }; +pub use drm::node::{CreateDrmNodeError, DrmNode, NodeType}; use drm_fourcc::{DrmFormat, DrmFourcc, DrmModifier}; pub use error::AccessError as DrmAccessError; pub use error::Error as DrmError; use indexmap::IndexSet; -pub use node::{CreateDrmNodeError, DrmNode, NodeType}; #[cfg(feature = "backend_gbm")] pub use surface::gbm::{Error as GbmBufferedSurfaceError, GbmBufferedSurface}; pub use surface::{DrmSurface, PlaneConfig, PlaneDamageClips, PlaneState}; diff --git a/src/backend/drm/node/constants.rs b/src/backend/drm/node/constants.rs deleted file mode 100644 index bbed6a956b03..000000000000 --- a/src/backend/drm/node/constants.rs +++ /dev/null @@ -1,39 +0,0 @@ -//! OS-Specific DRM constants - -// DRM major value. - -#[cfg(target_os = "dragonfly")] -pub const DRM_MAJOR: u32 = 145; - -#[cfg(target_os = "netbsd")] -pub const DRM_MAJOR: u32 = 180; - -#[cfg(all(target_os = "openbsd", target_arch = "x86"))] -pub const DRM_MAJOR: u32 = 88; - -#[cfg(all(target_os = "openbsd", not(target_arch = "x86")))] -pub const DRM_MAJOR: u32 = 87; - -#[cfg(not(any(target_os = "dragonfly", target_os = "netbsd", target_os = "openbsd")))] -#[allow(dead_code)] // Not used on Linux -pub const DRM_MAJOR: u32 = 226; - -// DRM node prefixes - -#[cfg(not(target_os = "openbsd"))] -pub const PRIMARY_NAME: &str = "card"; - -#[cfg(target_os = "openbsd")] -pub const PRIMARY_NAME: &str = "drm"; - -#[cfg(not(target_os = "openbsd"))] -pub const CONTROL_NAME: &str = "controlD"; - -#[cfg(target_os = "openbsd")] -pub const CONTROL_NAME: &str = "drmC"; - -#[cfg(not(target_os = "openbsd"))] -pub const RENDER_NAME: &str = "renderD"; - -#[cfg(target_os = "openbsd")] -pub const RENDER_NAME: &str = "drmR"; diff --git a/src/backend/drm/node/mod.rs b/src/backend/drm/node/mod.rs deleted file mode 100644 index 443b5b4f2ec6..000000000000 --- a/src/backend/drm/node/mod.rs +++ /dev/null @@ -1,390 +0,0 @@ -//! Module for abstractions on drm device nodes - -pub(crate) mod constants; - -use constants::*; - -use std::{ - fmt::{self, Display, Formatter}, - io, - os::unix::io::AsFd, - path::{Path, PathBuf}, -}; - -use rustix::fs::{fstat, major, minor, stat, Dev as dev_t, Stat}; - -/// A node which refers to a DRM device. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct DrmNode { - dev: dev_t, - ty: NodeType, -} - -impl DrmNode { - /// Creates a DRM node from an open drm device. - /// - /// This function does not take ownership of the passed in file descriptor. - pub fn from_file(file: A) -> Result { - let stat = fstat(file).map_err(Into::::into)?; - DrmNode::from_stat(stat) - } - - /// Creates a DRM node from path. - pub fn from_path>(path: A) -> Result { - let stat = stat(path.as_ref()).map_err(Into::::into)?; - DrmNode::from_stat(stat) - } - - /// Creates a DRM node from a file stat. - pub fn from_stat(stat: Stat) -> Result { - let dev = stat.st_rdev; - DrmNode::from_dev_id(dev) - } - - /// Creates a DRM node from a dev_t - pub fn from_dev_id(dev: dev_t) -> Result { - if !is_device_drm(dev) { - return Err(CreateDrmNodeError::NotDrmNode); - } - - /* - The type of the DRM node is determined by the minor number ranges. - - 0-63 -> Primary - 64-127 -> Control - 128-255 -> Render - */ - let ty = match minor(dev) >> 6 { - 0 => NodeType::Primary, - 1 => NodeType::Control, - 2 => NodeType::Render, - _ => return Err(CreateDrmNodeError::NotDrmNode), - }; - - Ok(DrmNode { dev, ty }) - } - - /// Returns the type of the DRM node. - pub fn ty(&self) -> NodeType { - self.ty - } - - /// Returns the device_id of the underlying DRM node. - pub fn dev_id(&self) -> dev_t { - self.dev - } - - /// Returns the path of the open device if possible. - pub fn dev_path(&self) -> Option { - node_path(self, self.ty).ok() - } - - /// Returns the path of the specified node type matching the device, if available. - pub fn dev_path_with_type(&self, ty: NodeType) -> Option { - node_path(self, ty).ok() - } - - /// Returns a new node of the specified node type matching the device, if available. - pub fn node_with_type(&self, ty: NodeType) -> Option> { - self.dev_path_with_type(ty).map(DrmNode::from_path) - } - - /// Returns the major device number of the DRM device. - pub fn major(&self) -> u32 { - major(self.dev_id()) - } - - /// Returns the minor device number of the DRM device. - pub fn minor(&self) -> u32 { - minor(self.dev_id()) - } - - /// Returns whether the DRM device has render nodes. - pub fn has_render(&self) -> bool { - #[cfg(target_os = "linux")] - { - node_path(self, NodeType::Render).is_ok() - } - - // TODO: More robust checks on non-linux. - #[cfg(target_os = "freebsd")] - { - false - } - - #[cfg(not(any(target_os = "linux", target_os = "freebsd")))] - { - false - } - } -} - -impl Display for DrmNode { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "{}{}", self.ty.minor_name_prefix(), minor(self.dev_id())) - } -} - -/// A type of node -#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] -pub enum NodeType { - /// A primary node may be used to allocate buffers. - /// - /// If no other node is present, this may be used to post a buffer to an output with mode-setting. - Primary, - - /// A control node may be used for mode-setting. - /// - /// This is almost never used since no DRM API for control nodes is available yet. - Control, - - /// A render node may be used by a client to allocate buffers. - /// - /// Mode-setting is not possible with a render node. - Render, -} - -impl NodeType { - /// Returns a string representing the prefix of a minor device's name. - /// - /// For example, on Linux with a primary node, the returned string would be `card`. - pub fn minor_name_prefix(&self) -> &str { - match self { - NodeType::Primary => PRIMARY_NAME, - NodeType::Control => CONTROL_NAME, - NodeType::Render => RENDER_NAME, - } - } -} - -impl Display for NodeType { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!( - f, - "{}", - match self { - NodeType::Primary => "Primary", - NodeType::Control => "Control", - NodeType::Render => "Render", - } - ) - } -} - -/// An error that may occur when creating a DrmNode from a file descriptor. -#[derive(Debug, thiserror::Error)] -pub enum CreateDrmNodeError { - /// Some underlying IO error occured while trying to create a DRM node. - #[error("{0}")] - Io(io::Error), - - /// The provided file descriptor does not refer to a DRM node. - #[error("the provided file descriptor does not refer to a DRM node.")] - NotDrmNode, -} - -impl From for CreateDrmNodeError { - #[inline] - fn from(err: io::Error) -> Self { - CreateDrmNodeError::Io(err) - } -} - -/// Returns if the given device by major:minor pair is a drm device -#[cfg(target_os = "linux")] -pub fn is_device_drm(dev: dev_t) -> bool { - let path = format!("/sys/dev/char/{}:{}/device/drm", major(dev), minor(dev)); - stat(path.as_str()).is_ok() -} - -#[cfg(target_os = "freebsd")] -fn devname(dev: dev_t) -> Option { - use std::os::raw::{c_char, c_int}; - - // Matching value of SPECNAMELEN in FreeBSD 13+ - let mut dev_name = vec![0u8; 255]; - - let buf: *mut c_char = unsafe { - libc::devname_r( - dev, - libc::S_IFCHR, // Must be S_IFCHR or S_IFBLK - dev_name.as_mut_ptr() as *mut c_char, - dev_name.len() as c_int, - ) - }; - - // Buffer was too small (weird issue with the size of buffer) or the device could not be named. - if buf.is_null() { - return None; - } - - // SAFETY: The buffer written to by devname_r is guaranteed to be NUL terminated. - unsafe { dev_name.set_len(libc::strlen(buf)) }; - - Some(String::from_utf8(dev_name).expect("Returned device name is not valid utf8")) -} - -/// Returns if the given device by major:minor pair is a drm device -#[cfg(target_os = "freebsd")] -pub fn is_device_drm(dev: dev_t) -> bool { - devname(dev).map_or(false, |dev_name| { - dev_name.starts_with("drm/") - || dev_name.starts_with("dri/card") - || dev_name.starts_with("dri/control") - || dev_name.starts_with("dri/renderD") - }) -} - -/// Returns if the given device by major:minor pair is a drm device -#[cfg(not(any(target_os = "linux", target_os = "freebsd")))] -pub fn is_device_drm(dev: dev_t) -> bool { - major(dev) == DRM_MAJOR -} - -/// Returns the path of a specific type of node from the same DRM device as another path of the same node. -pub fn path_to_type>(path: P, ty: NodeType) -> io::Result { - let stat = stat(path.as_ref()).map_err(Into::::into)?; - dev_path(stat.st_rdev, ty) -} - -/// Returns the path of a specific type of node from the same DRM device as an existing DrmNode. -pub fn node_path(node: &DrmNode, ty: NodeType) -> io::Result { - dev_path(node.dev, ty) -} - -/// Returns the path of a specific type of node from the DRM device described by major and minor device numbers. -#[cfg(target_os = "linux")] -pub fn dev_path(dev: dev_t, ty: NodeType) -> io::Result { - use std::fs; - use std::io::ErrorKind; - - if !is_device_drm(dev) { - return Err(io::Error::new( - ErrorKind::NotFound, - format!("{}:{} is no DRM device", major(dev), minor(dev)), - )); - } - - let read = fs::read_dir(format!("/sys/dev/char/{}:{}/device/drm", major(dev), minor(dev)))?; - - for entry in read.flatten() { - let name = entry.file_name(); - let name = name.to_string_lossy(); - - // Only 1 primary, control and render node may exist simultaneously, so the - // first occurrence is good enough. - if name.starts_with(ty.minor_name_prefix()) { - let path = [r"/", "dev", "dri", &name].iter().collect::(); - if path.exists() { - return Ok(path); - } - } - } - - Err(io::Error::new( - ErrorKind::NotFound, - format!( - "Could not find node of type {} from DRM device {}:{}", - ty, - major(dev), - minor(dev) - ), - )) -} - -/// Returns the path of a specific type of node from the DRM device described by major and minor device numbers. -#[cfg(target_os = "freebsd")] -fn dev_path(dev: dev_t, ty: NodeType) -> io::Result { - // Based on libdrm `drmGetMinorNameForFD`. Should be updated if the code - // there is replaced with anything more sensible... - - use std::io::ErrorKind; - - if !is_device_drm(dev) { - return Err(io::Error::new( - ErrorKind::NotFound, - format!("{}:{} is no DRM device", major(dev), minor(dev)), - )); - } - - if let Some(dev_name) = devname(dev) { - let suffix = dev_name.trim_start_matches(|c: char| !c.is_numeric()); - if let Ok(old_id) = suffix.parse::() { - let old_ty = match old_id >> 6 { - 0 => NodeType::Primary, - 1 => NodeType::Control, - 2 => NodeType::Render, - _ => { - return Err(io::Error::new( - ErrorKind::NotFound, - format!("{}:{} is no DRM device", major(dev), minor(dev)), - )); - } - }; - let id = old_id - get_minor_base(old_ty) + get_minor_base(ty); - let path = PathBuf::from(format!("/dev/dri/{}{}", ty.minor_name_prefix(), id)); - if path.exists() { - return Ok(path); - } - } - } - - Err(io::Error::new( - ErrorKind::NotFound, - format!( - "Could not find node of type {} from DRM device {}:{}", - ty, - major(dev), - minor(dev) - ), - )) -} - -#[cfg(any(target_os = "netbsd", target_os = "openbsd"))] -fn dev_path(dev: dev_t, ty: NodeType) -> io::Result { - use std::io::ErrorKind; - - if !is_device_drm(dev) { - return Err(io::Error::new( - ErrorKind::NotFound, - format!("{}:{} is no DRM device", major(dev), minor(dev)), - )); - } - - let old_id = minor(dev); - let old_ty = match old_id >> 6 { - 0 => NodeType::Primary, - 1 => NodeType::Control, - 2 => NodeType::Render, - _ => { - return Err(io::Error::new( - ErrorKind::NotFound, - format!("{}:{} is no DRM device", major(dev), minor(dev)), - )); - } - }; - let id = old_id - get_minor_base(old_ty) + get_minor_base(ty); - let path = PathBuf::from(format!("/dev/dri/{}{}", ty.minor_name_prefix(), id)); - if path.exists() { - return Ok(path); - } - - Err(io::Error::new( - ErrorKind::NotFound, - format!( - "Could not find node of type {} from DRM device {}:{}", - ty, - major(dev), - minor(dev) - ), - )) -} - -#[cfg(any(target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))] -fn get_minor_base(type_: NodeType) -> u32 { - match type_ { - NodeType::Primary => 0, - NodeType::Control => 64, - NodeType::Render => 128, - } -} diff --git a/src/backend/x11/mod.rs b/src/backend/x11/mod.rs index b17492ed3e95..dcf1bbaa9cef 100644 --- a/src/backend/x11/mod.rs +++ b/src/backend/x11/mod.rs @@ -80,13 +80,14 @@ mod window_inner; use crate::{ backend::{ allocator::{Allocator, Swapchain}, - drm::{node::path_to_type, CreateDrmNodeError, DrmNode, NodeType}, + drm::{CreateDrmNodeError, DrmNode, NodeType}, egl::{native::X11DefaultDisplay, EGLDevice, EGLDisplay, Error as EGLError}, input::{Axis, ButtonState, InputEvent, KeyState, Keycode}, }, utils::{x11rb::X11Source, Logical, Size}, }; use calloop::{EventSource, Poll, PostAction, Readiness, Token, TokenFactory}; +use drm::node::path_to_type; use drm_fourcc::{DrmFourcc, DrmModifier}; /* use nix::{