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.
| Method | Return type | Description |
|---|
handle() | Handle | The framebuffer’s own handle |
size() | (u32, u32) | Width and height in pixels |
pitch() | u32 | Row stride in bytes (may be larger than width × (bpp/8) for alignment) |
bpp() | u32 | Bits per pixel including any padding |
depth() | u32 | Colour 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.
| Method | Return type | Description |
|---|
handle() | Handle | The framebuffer’s own handle |
size() | (u32, u32) | Width and height in pixels |
pixel_format() | DrmFourcc | Pixel format as a typed FourCC code |
flags() | FbCmd2Flags | Creation 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.
| Flag | Description |
|---|
INTERLACED | The framebuffer is interlaced — alternating fields are displayed on successive vblanks |
MODIFIERS | Format 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.
| Variant | Description |
|---|
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.