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.

drm-rs exposes two separate capability enums that serve different purposes. DriverCapability is used to query what the hardware and kernel driver support — you read these values and react to them. ClientCapability is used to enable optional features for the calling process — these are opt-in flags that change what the DRM subsystem exposes or allows on your file descriptor.
use drm::{Device, DriverCapability, ClientCapability};

// 1. Query what the driver supports
let has_dumb = card.get_driver_capability(DriverCapability::DumbBuffer).unwrap();

// 2. Opt in to features you want to use
card.set_client_capability(ClientCapability::UniversalPlanes, true).unwrap();
card.set_client_capability(ClientCapability::Atomic, true).unwrap();
ClientCapability settings are per-process and per-fd. Each open DRM file descriptor maintains its own capability state. Enabling a capability on one Card instance does not affect another instance that opened the same device node separately.

DriverCapability

Query driver capabilities using Device::get_driver_capability(). The return value is a u64; 0 means the capability is absent or disabled, and any non-zero value means it is present (with some capabilities returning a meaningful numeric value rather than just 1).
pub enum DriverCapability {
    DumbBuffer,
    VBlankHighCRTC,
    DumbPreferredDepth,
    DumbPreferShadow,
    Prime,
    MonotonicTimestamp,
    ASyncPageFlip,
    AtomicASyncPageFlip,
    CursorWidth,
    CursorHeight,
    AddFB2Modifiers,
    PageFlipTarget,
    CRTCInVBlankEvent,
    SyncObj,
    TimelineSyncObj,
}

Variants

VariantReturn valueDescription
DumbBuffer0 or 1Whether the driver supports dumb buffers — simple, CPU-accessible, linearly-tiled buffers suitable for scanout without GPU involvement. Required for software rendering to a framebuffer.
VBlankHighCRTC0 or 1Whether the driver supports high CRTC indices (beyond 1) in the legacy vblank interface. Check this before passing a non-zero high_crtc to wait_vblank.
DumbPreferredDepthbit depthThe driver’s preferred colour depth (in bits per pixel) for dumb buffers. Use this as a hint when allocating dumb buffers for scanout.
DumbPreferShadow0 or 1Whether the driver prefers a shadow (intermediate) buffer when rendering to a dumb buffer. If 1, consider blitting through a shadow rather than writing to the scanout buffer directly.
PrimebitmaskPRIME handle sharing support. Non-zero indicates that at least import (DRM_PRIME_CAP_IMPORT) or export (DRM_PRIME_CAP_EXPORT) is supported. Use PRIME to share GPU buffers between devices or processes via dmabuf file descriptors.
MonotonicTimestamp0 or 1Whether DRM timestamps use CLOCK_MONOTONIC. If 0, timestamps use CLOCK_REALTIME. Nearly all modern drivers return 1.
ASyncPageFlip0 or 1Whether the driver supports asynchronous page flipping via the legacy (non-atomic) DRM_IOCTL_MODE_PAGE_FLIP interface. Async flips skip waiting for vblank and may cause tearing.
AtomicASyncPageFlip0 or 1Whether the driver supports asynchronous page flipping via the atomic modesetting API. Requires ClientCapability::Atomic to be enabled.
CursorWidthpixelsMaximum supported cursor buffer width in pixels. Allocate cursor buffers no wider than this value.
CursorHeightpixelsMaximum supported cursor buffer height in pixels. Allocate cursor buffers no taller than this value.
AddFB2Modifiers0 or 1Whether the driver supports format modifiers in DRM_IOCTL_MODE_ADDFB2. Modifiers describe non-linear tiling layouts (e.g. Intel X-tiling, AMD DCC). Required to use tiled or compressed framebuffers.
PageFlipTarget0 or 1Whether the driver supports targeted page flips — scheduling a flip to occur at a specific vblank sequence number.
CRTCInVBlankEvent0 or 1Whether vblank and page flip events include the CRTC’s object ID. Required to correlate events back to a CRTC when handling multiple outputs.
SyncObj0 or 1Whether the driver supports binary DRM sync objects (drm_syncobj). Sync objects are GPU synchronisation primitives that can be waited on in userspace or exported as sync fences.
TimelineSyncObj0 or 1Whether the driver supports timeline DRM sync objects, which carry a monotonically increasing point value and allow more expressive GPU dependency tracking (similar to Vulkan timeline semaphores).

Usage examples

use drm::{Device, DriverCapability};

// Check dumb buffer support before allocating one
let dumb_ok = card.get_driver_capability(DriverCapability::DumbBuffer).unwrap();
if dumb_ok == 0 {
    eprintln!("Dumb buffers not supported by this driver");
}

// Query maximum cursor size
let max_w = card.get_driver_capability(DriverCapability::CursorWidth).unwrap();
let max_h = card.get_driver_capability(DriverCapability::CursorHeight).unwrap();
println!("Cursor limit: {}×{} pixels", max_w, max_h);

// Check for format modifier support before using tiled framebuffers
let modifiers_ok = card.get_driver_capability(DriverCapability::AddFB2Modifiers).unwrap();
if modifiers_ok != 0 {
    println!("Format modifiers supported — tiled buffers are available");
}

// Check timeline sync object support (needed for Vulkan-style GPU sync)
let timeline_ok = card.get_driver_capability(DriverCapability::TimelineSyncObj).unwrap();
println!("Timeline syncobj: {}", if timeline_ok != 0 { "yes" } else { "no" });

ClientCapability

Enable or disable per-fd features using Device::set_client_capability(). These capabilities default to disabled; your process must explicitly opt in before using the associated functionality.
pub enum ClientCapability {
    Stereo3D,
    UniversalPlanes,
    Atomic,
    AspectRatio,
    WritebackConnectors,
    CursorPlaneHotspot,
}

Variants

VariantDescription
Stereo3DThe driver provides 3D stereo screen control. Enables stereo mode flags in the display mode list. Rarely needed outside of specialised display hardware.
UniversalPlanesExposes all plane types — not just primary planes, but also overlay and cursor planes. This is required before working with the full plane list via get_plane_handles() and is a prerequisite for Atomic. Enable this first.
AtomicEnables the atomic modesetting API, which allows multiple KMS state changes to be prepared and committed as a single, all-or-nothing transaction. Requires UniversalPlanes to be set first. This is the recommended modesetting path for modern compositors.
AspectRatioInstructs the DRM core to include aspect ratio information in mode data (drm_mode_info). Needed when you need to correctly handle widescreen, 4:3, and other aspect ratios that may not be obvious from the resolution alone.
WritebackConnectorsExposes writeback connectors, which are virtual connectors that capture the composed display output to a memory buffer. Useful for screen recording and testing. Requires Atomic to be enabled first.
CursorPlaneHotspotRequired for para-virtualised hardware (e.g. QEMU virtio_gpu) where cursor planes must behave like a mouse cursor with correctly-set hotspot properties. Without this flag, the DRM core may hide cursor planes on virtualised drivers. Requires Atomic to be enabled first.

Usage examples

use drm::{Device, ClientCapability};

// Standard sequence to enable atomic modesetting
card.set_client_capability(ClientCapability::UniversalPlanes, true)
    .expect("UniversalPlanes not supported");
card.set_client_capability(ClientCapability::Atomic, true)
    .expect("Atomic modesetting not supported");

// Optionally enable writeback connectors (for screen capture)
card.set_client_capability(ClientCapability::WritebackConnectors, true)
    .ok(); // not all drivers support this

// On virtualised hardware, enable cursor hotspot handling
card.set_client_capability(ClientCapability::CursorPlaneHotspot, true)
    .ok();
Always enable UniversalPlanes before Atomic. The kernel rejects Atomic if UniversalPlanes has not been set first, because hiding overlay and cursor planes from the plane list while atomic is active would produce inconsistent state.

Build docs developers (and LLMs) love