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::buffer module provides the core types for GPU buffer management. GEM (Graphics Execution Manager) buffers are the kernel’s abstraction for GPU memory, represented by 32-bit handles local to the current process. These handles are automatically reference-counted in the kernel, but drm-rs does not track their lifetimes — it is the caller’s responsibility to close buffers correctly and avoid use-after-free. The module also re-exports pixel format and modifier types from the drm-fourcc crate, which are used throughout the drm-rs API wherever a buffer format is required.

buffer::Handle

A handle to an open GEM buffer in the current process.
#[repr(transparent)]
#[derive(Copy, Clone, Hash, PartialEq, Eq)]
pub struct Handle(control::RawResourceHandle);

impl std::fmt::Debug for Handle { /* formats as buffer::Handle(N) */ }
Handle is a repr(transparent) newtype over control::RawResourceHandle, which is itself a NonZeroU32. This means a Handle is guaranteed to be non-zero, and Option<Handle> is pointer-sized with no overhead. Trait implementations: Copy, Clone, Hash, PartialEq, Eq, Debug (manual implementation, formats as buffer::Handle(N)). Conversions:
FromToNotes
control::RawResourceHandleHandleVia From<RawResourceHandle>
Handlecontrol::RawResourceHandleVia Into<RawResourceHandle>
Handleu32Via Into<u32>
There are no runtime guarantees that a Handle is valid. It is up to the caller to ensure a handle does not outlive its underlying buffer and that every buffer is properly closed when no longer needed. Leaking a handle leaks kernel memory.

buffer::Name

A global 32-bit “Flink” name used to share a GEM buffer across processes.
#[repr(transparent)]
#[derive(Copy, Clone, Hash, PartialEq, Eq)]
pub struct Name(u32);

impl std::fmt::Debug for Name { /* formats as buffer::Name(N) */ }
A Name is produced by the kernel’s Flink mechanism and can be passed to another process, which can then open it with control::Device::open_buffer(). Like Handle, there is no runtime validation — the caller must ensure the name is still valid. Conversion: Into<u32>.
Global GEM names are deprecated in favour of PRIME file descriptors. Any process that knows (or can guess) a Flink name can open the buffer, making it a security risk. Prefer buffer_to_prime_fd() for sharing across process boundaries.

Buffer trait

The Buffer trait describes any single-plane GPU buffer. It is implemented by DumbBuffer and can be implemented by any user-defined buffer type.
pub trait Buffer {
    /// Width and height of the buffer in pixels.
    fn size(&self) -> (u32, u32);

    /// Pixel format of the buffer.
    fn format(&self) -> DrmFourcc;

    /// Number of bytes per row (row stride).
    fn pitch(&self) -> u32;

    /// GEM handle for this buffer.
    fn handle(&self) -> Handle;
}
Methods on control::Device that accept a buffer (such as add_framebuffer) are generic over B: Buffer, so any type implementing this trait can be used directly without wrapping.

PlanarBuffer trait

The PlanarBuffer trait extends buffer abstraction to multi-plane formats (e.g. YUV 4:2:0, NV12) and formats with hardware-specific layout modifiers (tiling, compression).
pub trait PlanarBuffer {
    /// Width and height of the buffer in pixels.
    fn size(&self) -> (u32, u32);

    /// Pixel format of the buffer.
    fn format(&self) -> DrmFourcc;

    /// Optional format modifier (e.g. tiling layout, vendor compression).
    fn modifier(&self) -> Option<DrmModifier>;

    /// Per-plane byte strides. Unused planes should return 0.
    fn pitches(&self) -> [u32; 4];

    /// Per-plane GEM handles. `None` indicates an unused plane.
    fn handles(&self) -> [Option<Handle>; 4];

    /// Per-plane byte offsets into each plane's buffer.
    fn offsets(&self) -> [u32; 4];
}
Use control::Device::add_planar_framebuffer() to register a planar buffer as a KMS framebuffer.

Re-exports from drm-fourcc

The drm::buffer module re-exports the following types from the drm-fourcc crate:
TypeDescription
DrmFourccPixel format codes, e.g. DrmFourcc::Xrgb8888, DrmFourcc::Nv12
DrmModifierFormat modifiers that describe memory layout, e.g. tiling or vendor compression schemes
DrmVendorVendor namespace for modifier codes
UnrecognizedFourccError type returned when a raw FourCC code is not a known DrmFourcc variant
UnrecognizedVendorError type returned when a vendor code is not a known DrmVendor variant
See the drm-fourcc crate documentation for the full list of DrmFourcc and DrmModifier variants. The list covers all formats defined by the Linux kernel’s drm_fourcc.h header.

DumbBuffer and DumbMapping

DumbBuffer is a software-backed, driver-agnostic buffer type returned by control::Device::create_dumb_buffer(). It is the simplest way to allocate a CPU-accessible GPU buffer without any driver-specific library. Performance is limited — dumb buffers are not hardware-accelerated — but they work with any DRM driver that supports kernel modesetting.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct DumbBuffer {
    // Fields are private; access via trait methods below.
}
DumbBuffer implements the Buffer trait. The following accessors are available:
MethodReturn typeDescription
size()(u32, u32)Width and height in pixels
format()DrmFourccPixel format as specified at creation
pitch()u32Bytes per row, as determined by the kernel
handle()buffer::HandleGEM handle for this buffer

DumbMapping<'_>

DumbMapping is a CPU memory mapping of a DumbBuffer, returned by control::Device::map_dumb_buffer(). It borrows the buffer mutably for its lifetime and unmaps the memory automatically when dropped.
pub struct DumbMapping<'a> { /* ... */ }
Trait implementations: AsRef<[u8]>, AsMut<[u8]>, Borrow<[u8]>, BorrowMut<[u8]>, Deref<Target = [u8]>, DerefMut. The mapping unmaps itself via munmap in its Drop implementation, so there is no need to call an explicit unmap function.

Full usage example

use drm::buffer::DrmFourcc;

// Allocate a 1920×1080 dumb buffer with 32 bits per pixel in XRGB 8:8:8:8 format.
let mut db = card.create_dumb_buffer((1920, 1080), DrmFourcc::Xrgb8888, 32).unwrap();

// Map the buffer into the process address space and clear it to black.
{
    let mut map = card.map_dumb_buffer(&mut db).unwrap();
    map.as_mut().fill(0);
} // `map` is dropped here — the memory mapping is released automatically.

// Register the buffer as a KMS framebuffer (depth=24, bpp=32).
let fb = card.add_framebuffer(&db, 24, 32).unwrap();

// ... use `fb` for modesetting ...

// Cleanup: destroy the framebuffer first, then the buffer.
card.destroy_framebuffer(fb).unwrap();
card.destroy_dumb_buffer(db).unwrap();
To share a DumbBuffer (or any GEM buffer) with another process, convert it to a PRIME file descriptor using control::Device::buffer_to_prime_fd(handle, flags), then pass the OwnedFd over a Unix socket. The receiving process can import it back with control::Device::prime_fd_to_buffer(fd). This is more secure than Flink (buffer::Name) because the kernel enforces that only the holder of the file descriptor can access the buffer.

Build docs developers (and LLMs) love