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::control::Device extends drm::Device with full Kernel Modesetting (KMS) capabilities. Any type that already implements drm::Device can also implement this trait with an empty impl body — all methods have default implementations backed by DRM ioctls.
use drm::control::Device as ControlDevice;
/// Assuming Card already implements drm::Device
impl ControlDevice for Card {}
The trait provides access to the complete KMS pipeline: resource enumeration, connector/CRTC/plane/encoder inspection, legacy and atomic modesetting, framebuffer management, property queries, dumb buffers, PRIME, gamma tables, sync objects, and DRM leasing.
Resource Enumeration
resource_handles
fn resource_handles(&self) -> io::Result<ResourceHandles>
Returns handles for all framebuffers, CRTCs, connectors, and encoders that this device controls. The returned ResourceHandles also reports the minimum and maximum supported framebuffer dimensions.
ResourceHandles exposes the following accessors:
| Method | Return type | Description |
|---|
connectors() | &[connector::Handle] | All connector handles |
encoders() | &[encoder::Handle] | All encoder handles |
crtcs() | &[crtc::Handle] | All CRTC handles |
framebuffers() | &[framebuffer::Handle] | All framebuffer handles |
supported_fb_width() | impl RangeBounds<u32> | Minimum and maximum framebuffer width |
supported_fb_height() | impl RangeBounds<u32> | Minimum and maximum framebuffer height |
filter_crtcs(filter: CrtcListFilter) | Vec<crtc::Handle> | Filter CRTCs by encoder compatibility bitmask |
plane_handles
fn plane_handles(&self) -> io::Result<Vec<plane::Handle>>
Returns handles for all hardware planes. Overlay and cursor planes are only visible after enabling ClientCapability::UniversalPlanes on the device.
get_connector
fn get_connector(
&self,
handle: connector::Handle,
force_probe: bool,
) -> io::Result<connector::Info>
Returns the current state of a connector. The force_probe flag instructs the kernel to perform a hardware-level probe, refreshing connection state, detected modes, and the EDID. Force-probing should be performed at startup and after receiving a hotplug udev event. It may be slow and cause momentary flickering; avoid it in steady-state render loops.
get_encoder
fn get_encoder(&self, handle: encoder::Handle) -> io::Result<encoder::Info>
Returns metadata about an encoder, including its kind, the CRTC it is currently attached to, and bitmasks indicating which CRTCs and clones it is compatible with.
get_crtc
fn get_crtc(&self, handle: crtc::Handle) -> io::Result<crtc::Info>
Returns the current state of a CRTC: position offset, the active Mode (or None if disabled), the currently displayed framebuffer, and the size of its gamma lookup table.
get_plane
fn get_plane(&self, handle: plane::Handle) -> io::Result<plane::Info>
Returns metadata about a plane: the CRTC and framebuffer it is currently attached to, the bitmask of compatible CRTCs, and the list of supported pixel format FourCC codes.
Modesetting
set_crtc
fn set_crtc(
&self,
handle: crtc::Handle,
framebuffer: Option<framebuffer::Handle>,
pos: (u32, u32),
conns: &[connector::Handle],
mode: Option<Mode>,
) -> io::Result<()>
Legacy (non-atomic) modeset. Attaches a framebuffer to a CRTC and drives the listed connectors at the specified mode. Passing None for framebuffer or mode disables the CRTC. Use atomic_commit for modern hardware and Wayland compositors.
set_plane
fn set_plane(
&self,
handle: plane::Handle,
crtc: crtc::Handle,
framebuffer: Option<framebuffer::Handle>,
flags: u32,
crtc_rect: (i32, i32, u32, u32),
src_rect: (u32, u32, u32, u32),
) -> io::Result<()>
Configures a plane’s position and source crop. crtc_rect is (x, y, width, height) in screen coordinates. src_rect is (x, y, width, height) in the source framebuffer, specified in Q16.16 fixed-point units (multiply pixel values by 65536). Providing None for framebuffer clears the plane.
page_flip
fn page_flip(
&self,
handle: crtc::Handle,
framebuffer: framebuffer::Handle,
flags: PageFlipFlags,
target_sequence: Option<PageFlipTarget>,
) -> io::Result<()>
Queues a framebuffer swap on the given CRTC. The swap is applied at the next vblank unless PageFlipFlags::ASYNC is set. When PageFlipFlags::EVENT is set, a PageFlipEvent is delivered via receive_events() once the flip completes.
PageFlipTarget controls the specific vblank sequence:
| Variant | Description |
|---|
Absolute(n) | Apply at absolute vblank sequence number n |
Relative(n) | Apply n vblanks from now |
set_cursor (deprecated)
#[deprecated(note = "Usage of deprecated ioctl set_cursor: use a cursor plane instead")]
fn set_cursor<B>(&self, crtc: crtc::Handle, buffer: Option<&B>) -> io::Result<()>
where
B: buffer::Buffer + ?Sized
Sets a hardware cursor image on the given CRTC. Passing None clears the cursor. Deprecated — use a cursor plane with atomic modesetting instead.
set_cursor2 (deprecated)
#[deprecated(note = "Usage of deprecated ioctl set_cursor2: use a cursor plane instead")]
fn set_cursor2<B>(
&self,
crtc: crtc::Handle,
buffer: Option<&B>,
hotspot: (i32, i32),
) -> io::Result<()>
where
B: buffer::Buffer + ?Sized
Sets a hardware cursor image with a hotspot (x, y) that marks the click point. Passing None clears the cursor. Deprecated — use a cursor plane with atomic modesetting instead.
move_cursor (deprecated)
#[deprecated(note = "Usage of deprecated ioctl move_cursor: use a cursor plane instead")]
fn move_cursor(&self, crtc: crtc::Handle, pos: (i32, i32)) -> io::Result<()>
Moves the hardware cursor on a CRTC to the given (x, y) position without changing the cursor image. Deprecated — use a cursor plane with atomic modesetting instead.
atomic_commit
fn atomic_commit(
&self,
flags: AtomicCommitFlags,
req: atomic::AtomicModeReq,
) -> io::Result<()>
Submits an atomic commit request. See AtomicModeReq for how to build the request and a full description of AtomicCommitFlags.
Framebuffer Management
add_framebuffer
fn add_framebuffer<B>(
&self,
buffer: &B,
depth: u32,
bpp: u32,
) -> io::Result<framebuffer::Handle>
where
B: buffer::Buffer + ?Sized
Registers a GEM buffer as a scanout framebuffer. depth is the colour depth in bits (e.g. 24); bpp is the bits per pixel including padding (e.g. 32). Use this for single-plane packed formats such as XRGB8888.
add_planar_framebuffer
fn add_planar_framebuffer<B>(
&self,
planar_buffer: &B,
flags: FbCmd2Flags,
) -> io::Result<framebuffer::Handle>
where
B: buffer::PlanarBuffer + ?Sized
Registers a multi-plane or modifier-enabled framebuffer. Pass FbCmd2Flags::MODIFIERS to enable format modifier support for tiled/compressed formats. The buffer’s modifier() method must return a valid (non-Invalid) modifier when MODIFIERS is set.
get_framebuffer
fn get_framebuffer(&self, handle: framebuffer::Handle) -> io::Result<framebuffer::Info>
Returns legacy framebuffer metadata: size, pitch, bits-per-pixel, colour depth, and the underlying GEM buffer handle.
get_planar_framebuffer
fn get_planar_framebuffer(
&self,
handle: framebuffer::Handle,
) -> Result<framebuffer::PlanarInfo, GetPlanarFramebufferError>
Returns extended framebuffer metadata including pixel format (as DrmFourcc), per-plane pitches, offsets, buffer handles, and the optional format modifier. Returns GetPlanarFramebufferError::UnrecognizedFourcc if the kernel reports an unregistered FourCC code.
dirty_framebuffer
fn dirty_framebuffer(
&self,
handle: framebuffer::Handle,
clips: &[ClipRect],
) -> io::Result<()>
Marks rectangular regions of a framebuffer as dirty. Used with shadow framebuffers or display controllers that require explicit cache-flush hints. ClipRect::new(x1, y1, x2, y2) constructs a dirty region.
destroy_framebuffer
fn destroy_framebuffer(&self, handle: framebuffer::Handle) -> io::Result<()>
Releases a framebuffer handle and frees the associated kernel resources. The underlying GEM buffer is not automatically freed.
Property Management
get_property
fn get_property(&self, handle: property::Handle) -> io::Result<property::Info>
Returns property metadata: name, value type, mutability, and whether it is atomic-only. See property for the full type reference.
set_property
fn set_property<T: ResourceHandle>(
&self,
handle: T,
prop: property::Handle,
value: property::RawValue,
) -> io::Result<()>
Sets a property on a KMS object using the legacy (non-atomic) property API. Prefer atomic_commit for modesetting-related properties.
create_property_blob
fn create_property_blob<T: ?Sized>(&self, data: &T) -> io::Result<property::Value<'static>>
Serialises an arbitrary data structure as a kernel-managed blob and returns a property::Value::Blob containing its blob ID. Blobs are the mechanism for passing structured data such as Mode timing structs to atomic commits.
get_property_blob
fn get_property_blob(&self, blob: u64) -> io::Result<Vec<u8>>
Retrieves the raw byte content of an existing property blob by its ID.
destroy_property_blob
fn destroy_property_blob(&self, blob: u64) -> io::Result<()>
Destroys a property blob and frees its kernel storage.
get_properties
fn get_properties<T: ResourceHandle>(&self, handle: T) -> io::Result<PropertyValueSet>
Returns the complete set of property handles and their current raw values for any KMS object (connector, CRTC, plane, or framebuffer). See PropertyValueSet for iteration methods.
get_modes
fn get_modes(&self, handle: connector::Handle) -> io::Result<Vec<Mode>>
Returns the list of Mode timing structures that the connector reports as supported. This does not force a kernel-side probe; call get_connector with force_probe: true first to refresh the list after hotplug.
Buffer Management
open_buffer
fn open_buffer(&self, name: buffer::Name) -> io::Result<buffer::Handle>
Opens a GEM buffer by its global Flink name, returning a process-local handle. Flink is a legacy inter-process sharing mechanism; prefer PRIME (prime_fd_to_buffer) for new code.
close_buffer
fn close_buffer(&self, handle: buffer::Handle) -> io::Result<()>
Closes a process-local GEM handle, decrementing the kernel reference count. Does not free the underlying buffer memory if other handles exist.
create_dumb_buffer
fn create_dumb_buffer(
&self,
size: (u32, u32),
format: buffer::DrmFourcc,
bpp: u32,
) -> io::Result<DumbBuffer>
Allocates a CPU-accessible dumb buffer through the generic DRM interface. Dumb buffers are backed by system memory, are not GPU-accelerated, and are suitable for simple rendering or cursor images. Returns a DumbBuffer describing the allocation.
map_dumb_buffer
fn map_dumb_buffer<'a>(&self, buffer: &'a mut DumbBuffer) -> io::Result<DumbMapping<'a>>
Memory-maps a dumb buffer into the current process’s address space. The returned DumbMapping<'a> dereferences to &mut [u8] and unmaps automatically on drop.
destroy_dumb_buffer
fn destroy_dumb_buffer(&self, buffer: DumbBuffer) -> io::Result<()>
Frees a dumb buffer and its system-memory backing store. Any active DumbMapping must be dropped first.
prime_fd_to_buffer
fn prime_fd_to_buffer(&self, fd: BorrowedFd<'_>) -> io::Result<buffer::Handle>
Imports a PRIME DMA-buf file descriptor into a process-local GEM buffer handle. PRIME is the standard cross-driver, cross-process buffer sharing mechanism.
buffer_to_prime_fd
fn buffer_to_prime_fd(&self, handle: buffer::Handle, flags: u32) -> io::Result<OwnedFd>
Exports a GEM buffer as a PRIME DMA-buf file descriptor that can be passed to other processes or DRM drivers.
Gamma Ramp
get_gamma
fn get_gamma(
&self,
crtc: crtc::Handle,
red: &mut [u16],
green: &mut [u16],
blue: &mut [u16],
) -> io::Result<()>
Reads the currently programmed gamma lookup table for the given CRTC into the supplied slices. Each slice must be at least crtc_info.gamma_length() elements long.
set_gamma
fn set_gamma(
&self,
crtc: crtc::Handle,
red: &[u16],
green: &[u16],
blue: &[u16],
) -> io::Result<()>
Programs a new gamma LUT for the given CRTC. Each slice must be at least crtc_info.gamma_length() elements long.
Sync Objects
DRM sync objects are fence binding points used to synchronise GPU work with page flips. See syncobj for full documentation of all sync object methods:
create_syncobj(signalled: bool) -> io::Result<syncobj::Handle>
destroy_syncobj(handle) -> io::Result<()>
syncobj_to_fd(handle, export_sync_file) -> io::Result<OwnedFd>
fd_to_syncobj(fd, import_sync_file) -> io::Result<syncobj::Handle>
syncobj_wait(handles, timeout_nsec, wait_all, wait_for_submit) -> io::Result<u32>
syncobj_reset(handles) -> io::Result<()>
syncobj_signal(handles) -> io::Result<()>
syncobj_timeline_wait(...), syncobj_timeline_query(...), syncobj_timeline_transfer(...), syncobj_timeline_signal(...), syncobj_eventfd(...)
DRM Leasing
DRM leasing allows a DRM master to delegate a subset of its KMS resources — CRTCs, connectors, and planes — to another process via a file descriptor. The lessee has full modesetting authority over the leased objects and cannot access resources outside the lease. Leasing is used by VR compositor frameworks (like VK_EXT_direct_mode_display), multi-seat configurations, and virtualisation.
create_lease
fn create_lease(
&self,
objects: &[RawResourceHandle],
flags: u32,
) -> io::Result<(LeaseId, OwnedFd)>
Creates a new lease over the specified KMS object handles. Returns the LeaseId (a NonZeroU32) that identifies the lease and an OwnedFd that the lessee uses as its DRM device.
list_lessees
fn list_lessees(&self) -> io::Result<Vec<LeaseId>>
Returns the IDs of all active leases issued by this DRM master.
revoke_lease
fn revoke_lease(&self, lessee_id: LeaseId) -> io::Result<()>
Revokes a previously created lease. The lessee’s fd will start returning errors on modesetting calls.
get_lease is a free function (not a method), defined as drm::control::get_lease(lease: D) -> io::Result<LeaseResources>. It can be called on the lessee’s fd to enumerate which CRTCs, connectors, and planes were granted.
Events
receive_events
fn receive_events(&self) -> io::Result<Events>
where
Self: Sized,
Reads pending DRM events from the device file descriptor. Returns an Events iterator over Event values. Call this after poll() or epoll() indicates the fd is readable.
Event
pub enum Event {
Vblank(VblankEvent),
PageFlip(PageFlipEvent),
Unknown(Vec<u8>),
}
VblankEvent
Delivered when a vblank interrupt fires after wait_vblank is called.
| Field | Type | Description |
|---|
frame | u32 | Vblank sequence number |
time | Duration | Timestamp of the vblank |
crtc | crtc::Handle | CRTC that generated the event |
user_data | usize | Opaque value passed to wait_vblank |
PageFlipEvent
Delivered when a page flip completes (requires PageFlipFlags::EVENT).
| Field | Type | Description |
|---|
frame | u32 | Frame sequence number at flip completion |
duration | Duration | Timestamp of the completed flip |
crtc | crtc::Handle | CRTC that executed the page flip |
// Typical event loop usage
let events = card.receive_events().unwrap();
for event in events {
match event {
drm::control::Event::PageFlip(ev) => {
println!("Page flip complete on {:?}, frame {}", ev.crtc, ev.frame);
}
drm::control::Event::Vblank(ev) => {
println!("Vblank on {:?} at {:?}", ev.crtc, ev.time);
}
drm::control::Event::Unknown(_) => {}
}
}