Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Smithay/drm-rs/llms.txt

Use this file to discover all available pages before exploring further.

The drm::node module provides DrmNode — a typed wrapper around a DRM device identified by its dev_t (a major:minor device number pair) and a NodeType. It lets you determine whether a file descriptor or filesystem path refers to a DRM device, what kind of node it is (primary, control, or render), and how to navigate between different node types for the same physical GPU. Internally, DrmNode is built on rustix for portable stat/fstat calls and uses the Linux /sys/dev/char/ hierarchy on Linux to resolve device information. On BSD systems, devname() is used instead.

DrmNode struct

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct DrmNode {
    dev: dev_t,
    ty: NodeType,
}
A DrmNode uniquely identifies one node of a DRM device by its raw device ID (dev_t) and its NodeType. Two DrmNode values are equal only if both the device ID and the node type match. Display: formats as "{prefix}{minor}", for example "card0" for a primary node or "renderD128" for a render node. This matches the filename that appears in /dev/dri/.

Constructors

MethodDescription
DrmNode::from_file<A: AsFd>(file: A) -> Result<DrmNode, CreateDrmNodeError>Create from an open file descriptor via fstat(2)
DrmNode::from_path<A: AsRef<Path>>(path: A) -> Result<DrmNode, CreateDrmNodeError>Create from a filesystem path via stat(2)
DrmNode::from_stat(stat: Stat) -> Result<DrmNode, CreateDrmNodeError>Create from a pre-computed rustix::fs::Stat
DrmNode::from_dev_id(dev: dev_t) -> Result<Self, CreateDrmNodeError>Create directly from a raw device ID
All constructors call is_device_drm() internally and return CreateDrmNodeError::NotDrmNode if the device is not a DRM node.

Methods

MethodReturn typeDescription
ty()NodeTypeThe node type of this node (Primary, Control, or Render)
dev_id()dev_tThe raw dev_t device ID
major()u32Major device number
minor()u32Minor device number
dev_path()Option<PathBuf>Path of this node under /dev/dri/, if it exists
dev_path_with_type(ty: NodeType)Option<PathBuf>Path of a different node type for the same GPU
node_with_type(ty: NodeType)Option<Result<DrmNode, CreateDrmNodeError>>A DrmNode of a different type for the same GPU
has_render()boolWhether a render node exists for this device (Linux only)

Example

use drm::node::{DrmNode, NodeType};

let node = DrmNode::from_path("/dev/dri/card0").unwrap();

println!("Type:           {:?}", node.ty());    // NodeType::Primary
println!("Major:          {}", node.major());
println!("Minor:          {}", node.minor());
println!("Has render node: {}", node.has_render());

// Resolve the render node path for the same GPU.
if let Some(render_path) = node.dev_path_with_type(NodeType::Render) {
    println!("Render node: {}", render_path.display()); // e.g. /dev/dri/renderD128
}

// Or obtain a full DrmNode for the render node.
if let Some(Ok(render_node)) = node.node_with_type(NodeType::Render) {
    println!("Render node type: {:?}", render_node.ty()); // NodeType::Render
}

NodeType enum

NodeType describes which of the three DRM node families a device node belongs to. The kernel assigns minor numbers in fixed ranges to distinguish them.
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub enum NodeType {
    /// /dev/dri/cardN — primary node, minor numbers 0–63.
    /// Used for modesetting and buffer allocation. Requires DRM master.
    Primary,

    /// /dev/dri/controlDN — control node, minor numbers 64–127.
    /// Reserved for future use; no stable kernel API exists for it yet.
    Control,

    /// /dev/dri/renderDN — render node, minor numbers 128–255.
    /// Unprivileged buffer allocation and GPU compute. No modesetting.
    Render,
}
The node type is derived from the minor number by inspecting bits 7:6 (minor >> 6):
minor >> 6Node typeMinor range
0Primary0–63
1Control64–127
2Render128–255

minor_name_prefix() -> &'static str

Returns the filename prefix used in /dev/dri/ for this node type.
NodeType::Primary.minor_name_prefix() // "card"      (e.g. card0)
NodeType::Control.minor_name_prefix() // "controlD"  (e.g. controlD64)
NodeType::Render.minor_name_prefix()  // "renderD"   (e.g. renderD128)
On OpenBSD the prefixes differ: "drm", "drmC", and "drmR" respectively.

CreateDrmNodeError enum

Returned by all DrmNode constructors when creation fails.
#[derive(Debug)]
pub enum CreateDrmNodeError {
    /// An OS-level I/O error occurred during stat/fstat (e.g. path not found).
    Io(io::Error),

    /// The file descriptor or path does not refer to a DRM device node.
    NotDrmNode,
}
CreateDrmNodeError implements std::error::Error. The Io variant chains the underlying io::Error as its source.

Free functions

These standalone functions provide lower-level access to DRM device detection and path resolution without requiring a DrmNode to already exist.

is_device_drm(dev: dev_t) -> bool

Returns true if the given major:minor pair identifies a DRM device.
  • Linux: stats /sys/dev/char/{major}:{minor}/device/drm. This correctly handles dynamic major numbers.
  • FreeBSD / DragonFly: calls devname_r() and checks for drm/, dri/card, dri/control, or dri/renderD prefixes.
  • Other platforms: compares the major number against the platform’s known DRM_MAJOR constant.

dev_path(dev: dev_t, ty: NodeType) -> io::Result<PathBuf>

Returns the filesystem path of a specific node type for the DRM device identified by dev.
  • Linux: reads /sys/dev/char/{major}:{minor}/device/drm/ and locates the entry matching the requested NodeType prefix, then checks that the corresponding path exists under /dev/dri/.
  • FreeBSD / DragonFly: derives the minor number arithmetically from the existing node and constructs the path.

node_path(node: &DrmNode, ty: NodeType) -> io::Result<PathBuf>

Same as dev_path, but takes a &DrmNode instead of a raw dev_t. Convenience wrapper used by DrmNode::dev_path() and DrmNode::dev_path_with_type() internally.

path_to_type<P: AsRef<Path>>(path: P, ty: NodeType) -> io::Result<PathBuf>

Given a path to any DRM device node, return the path of a different node type for the same physical device.
use drm::node::{path_to_type, NodeType};

// Starting from the primary node, find the render node for the same GPU.
let render_path = path_to_type("/dev/dri/card0", NodeType::Render).unwrap();
println!("Render node: {}", render_path.display()); // e.g. /dev/dri/renderD128

// Works in the opposite direction too.
let primary_path = path_to_type("/dev/dri/renderD128", NodeType::Primary).unwrap();
println!("Primary node: {}", primary_path.display()); // e.g. /dev/dri/card0
Internally, path_to_type calls stat() on the provided path and delegates to dev_path().

Platform notes

has_render() is only implemented on Linux. On FreeBSD, DragonFly BSD, and all other platforms it unconditionally returns false. Similarly, is_device_drm() uses /sys/dev/char/ on Linux, devname_r() on FreeBSD and DragonFly BSD, and a simple major number comparison (against the platform DRM_MAJOR constant) elsewhere.
For GPU compute or server-side rendering that does not require modesetting, open the render node (/dev/dri/renderDN) instead of the primary node. Render nodes do not require the DRM master lock, making them safe to open from unprivileged processes and from multiple clients simultaneously. Use DrmNode::dev_path_with_type(NodeType::Render) or path_to_type(primary_path, NodeType::Render) to locate the correct render node for a given GPU.

Build docs developers (and LLMs) love