The vertical blanking interval (vblank) is the brief period between the last scanline of one frame and the first scanline of the next, during which the display is not actively being refreshed. Synchronising buffer swaps to this window eliminates visible tearing and keeps frame pacing smooth.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.
Device::wait_vblank() is the primitive that lets userspace block until a specific vblank occurs, or schedule an asynchronous notification for one.
The vblank API predates atomic modesetting. It is still useful for simple, single-CRTC scenarios or when working with the legacy KMS API. For atomic workflows, prefer page flip events (see the note at the bottom of this page).
wait_vblank
flags, this either blocks until the target vblank sequence occurs, or returns immediately and delivers a DRM event to the file descriptor when the vblank fires.
Parameters
| Parameter | Type | Description |
|---|---|---|
target_sequence | VblankWaitTarget | The vblank sequence to target — either an absolute frame number or a relative offset from the current frame. |
flags | VblankWaitFlags | Modifier flags controlling blocking vs. event mode and missed-target behaviour. |
high_crtc | u32 | CRTC index used for hardware with more than two CRTCs. Requires DriverCapability::VBlankHighCRTC. Pass 0 for the first CRTC. |
user_data | usize | An arbitrary value that is echoed back unchanged in the VblankWaitReply. Useful for correlating async events. |
Returns
io::Result<VblankWaitReply> — the frame number and timestamp of the vblank that was waited for. If VblankWaitFlags::EVENT is set, the reply is returned immediately (with a zeroed timestamp) and the real event is delivered later via the DRM fd.
VblankWaitTarget
VblankWaitTarget::Relative(1) is the most common value — it means “wait for exactly the next vblank.” Relative(0) returns immediately (current frame). Absolute(n) is useful when you have computed an exact presentation deadline in terms of frame sequence numbers.
The frame sequence counter is a 32-bit value and will wrap around after approximately 497 days at 100 Hz. If you are using
Absolute targets across long sessions, handle wrapping carefully.VblankWaitFlags
Flag descriptions
VblankWaitFlags::EVENT
When set, wait_vblank returns immediately rather than blocking. The kernel queues an event that will be readable from the DRM file descriptor when the vblank fires. The event payload includes the frame number, timestamp, and the user_data value you passed in.
Use this flag when you are running an event loop (e.g. poll/epoll on the DRM fd) and cannot afford to block a thread.
VblankWaitFlags::NEXT_ON_MISS
When set, if the target vblank sequence number is already in the past (i.e. was missed), the kernel waits for the next upcoming vblank rather than returning an error. This makes the call more robust when there is scheduling jitter between preparing work and submitting the wait.
VblankWaitReply
wait_vblank describes the vblank event that was waited for.
frame() -> u32
NEXT_ON_MISS is used and the original target was missed, this may be greater than the requested sequence number.
time() -> Option<Duration>
Duration since the Unix epoch (or since system boot, if DriverCapability::MonotonicTimestamp returns non-zero). Returns None when VblankWaitFlags::EVENT was set, because the actual event has not yet fired at the time wait_vblank returns.
Usage Examples
Blocking wait for the next vblank
The simplest case: block the calling thread until the very next vblank on CRTC 0.Async vblank event with NEXT_ON_MISS
Schedule a vblank notification without blocking. The event arrives later on the DRM fd.Checking the frame counter
UseRelative(0) to query the current frame number without waiting.
For modern compositor workflows, page flip events are preferred over direct vblank waits. Call
page_flip() on a CRTC with PageFlipFlags::EVENT set, and the DRM subsystem delivers a flip-complete event that is implicitly synchronised to the vblank. This approach is simpler, integrates naturally with the atomic API, and avoids the race between submitting a flip and arming a separate vblank wait.