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.

A DRM framebuffer wraps a GEM buffer object and annotates it with the metadata a CRTC needs to scan it out: width, height, pixel format, row stride (pitch), and an optional format modifier. Framebuffers are process-local resources; they cannot be passed to another process directly, though the underlying GEM buffer can be shared via PRIME. Two APIs exist for creating framebuffers. The legacy add_framebuffer API accepts a single packed-pixel buffer::Buffer and describes it with depth and bits-per-pixel. The modern add_planar_framebuffer API accepts a buffer::PlanarBuffer and supports multi-plane formats (e.g. NV12, YUV420) and format modifiers (e.g. tiling, compression).

framebuffer::Handle

An opaque, copy-cheap handle to a framebuffer resource. Internally a NonZeroU32 wrapped with repr(transparent). Implements ResourceHandle with FFI_TYPE = DRM_MODE_OBJECT_FB.
let fb_handle: framebuffer::Handle = card.add_framebuffer(&dumb_buf, 24, 32).unwrap();

framebuffer::Info

Returned by Device::get_framebuffer(). Describes a legacy (non-planar) framebuffer.
MethodReturn typeDescription
handle()HandleThe framebuffer’s own handle
size()(u32, u32)Width and height in pixels
pitch()u32Row stride in bytes (may be larger than width × (bpp/8) for alignment)
bpp()u32Bits per pixel including any padding
depth()u32Colour depth in bits (e.g. 24 for XRGB8888)
buffer()Option<buffer::Handle>The underlying GEM buffer handle, if accessible
Info also implements Display, formatting as "Framebuffer <id>".

framebuffer::PlanarInfo

Returned by Device::get_planar_framebuffer(). Provides extended metadata for multi-plane and modifier-enabled framebuffers.
MethodReturn typeDescription
handle()HandleThe framebuffer’s own handle
size()(u32, u32)Width and height in pixels
pixel_format()DrmFourccPixel format as a typed FourCC code
flags()FbCmd2FlagsCreation flags (see below)
buffers()[Option<buffer::Handle>; 4]Per-plane GEM buffer handles (up to 4 planes)
pitches()[u32; 4]Per-plane row strides in bytes
offsets()[u32; 4]Per-plane byte offsets within each buffer
modifier()Option<DrmModifier>Format modifier (tiling, compression), or None if MODIFIERS flag was not set

FbCmd2Flags

Bitflags controlling advanced framebuffer features.
FlagDescription
INTERLACEDThe framebuffer is interlaced — alternating fields are displayed on successive vblanks
MODIFIERSFormat modifiers are active; modifier() returns a meaningful value. Required for tiled or compressed GPU buffer layouts.

GetPlanarFramebufferError

Returned by Device::get_planar_framebuffer() instead of io::Error when an extended framebuffer query fails.
VariantDescription
Io(io::Error)Underlying ioctl failed
UnrecognizedFourcc(drm_fourcc::UnrecognizedFourcc)The kernel reported a FourCC code not in the drm_fourcc crate’s database

Creating a Framebuffer from a Dumb Buffer

The simplest path: allocate a CPU-accessible dumb buffer and register it as a framebuffer.
use drm::control::Device as ControlDevice;
use drm_fourcc::DrmFourcc;

// Allocate a 1920×1080 dumb buffer (XRGB8888 = 32 bpp)
let mut dumb = card.create_dumb_buffer((1920, 1080), DrmFourcc::Xrgb8888, 32).unwrap();

// Register as a legacy framebuffer (depth=24, bpp=32)
let fb = card.add_framebuffer(&dumb, 24, 32).unwrap();

// Write pixels by mapping
{
    let mut mapping = card.map_dumb_buffer(&mut dumb).unwrap();
    mapping.fill(0); // clear to black
}

// Use the framebuffer for display...

// Cleanup (framebuffer must be destroyed before the GEM buffer)
card.destroy_framebuffer(fb).unwrap();
card.destroy_dumb_buffer(dumb).unwrap();

Creating a Planar Framebuffer

For YUV formats, tiled GPU surfaces, or compressed buffer layouts, use the planar API with format modifiers.
use drm::control::{Device as ControlDevice, FbCmd2Flags};

// `planar_buf` implements buffer::PlanarBuffer with a valid DrmModifier
let fb = card
    .add_planar_framebuffer(&planar_buf, FbCmd2Flags::MODIFIERS)
    .unwrap();
When FbCmd2Flags::MODIFIERS is set, the buffer’s modifier() must return a valid (non-DrmModifier::Invalid) value. Mismatches between the declared modifier and the actual GPU buffer layout result in display corruption or an ioctl error.
Framebuffers must be destroyed with Device::destroy_framebuffer() when no longer needed. The kernel retains a reference to the underlying GEM buffer for as long as the framebuffer exists — failing to destroy a framebuffer before dropping the GEM handle will keep the GPU memory alive and may exhaust VRAM.

Build docs developers (and LLMs) love