Understanding DRM: From Application‑Level Programs to Kernel Drivers
This article explains the Linux DRM graphics framework, its three main components (libdrm, KMS, GEM), the essential elements for display pipelines, and provides step‑by‑step example programs for single‑buffer, double‑buffer, page‑flip, and plane‑based rendering, including complete source code and execution notes.
DRM Overview
DRM (Direct Rendering Manager) is the mainstream Linux graphics display framework. Compared with the older FB architecture, DRM natively supports multi‑layer composition, VSYNC, DMA‑BUF, asynchronous updates, fence mechanisms, and provides unified management of GPU and display drivers.
Core Modules
DRM can be divided into three parts:
libdrm : wraps low‑level IOCTL interfaces and offers a common API to upper layers.
KMS (Kernel Mode Setting): updates the screen and sets display parameters such as resolution, refresh rate, and power state.
GEM (Graphics Execution Manager): allocates and releases display buffers; it is the only part directly used by the GPU.
Basic Elements
Key DRM objects include:
KMS: CRTC, ENCODER, CONNECTOR, PLANE, FB, VBLANK, property.
GEM: DUMB, PRIME, fence.
Mastering these elements enables smooth DRM driver development.
Single‑Buffer DRM Application
A minimal DRM program demonstrates opening /dev/dri/card0, obtaining resources, creating a dumb buffer, mapping it, and displaying a white screen.
int main(int argc, char **argv) {
/* open the drm device */
open("/dev/dri/card0");
/* get crtc/encoder/connector id */
drmModeGetResources(...);
drmModeGetConnector(...);
/* create a dumb‑buffer */
drmIoctl(DRM_IOCTL_MODE_CREATE_DUMB);
/* bind the dumb‑buffer to an FB object */
drmModeAddFB(...);
/* map the dumb buffer for userspace drawing */
drmIoctl(DRM_IOCTL_MODE_MAP_DUMB);
mmap(...);
/* start display */
drmModeSetCrtc(crtc_id, fb_id, connector_id, mode);
}The crucial call is drmModeSetCrtc() , which initializes the entire display pipeline and shows the framebuffer content.
Prerequisites for this code to run: DRM driver supports MODESET. DRM driver supports dumb‑buffer. At least one CRTC, one ENCODER, and one CONNECTOR are available. The CONNECTOR provides a valid display mode.
Double‑Buffer DRM Application
Extending the single‑buffer example, two buffers are created (red and blue). The program alternates between them by calling drmModeSetCrtc() after each user key press, demonstrating how double buffering avoids visible buffer updates.
int main(void) {
...
while (1) {
drmModeSetCrtc(fb0);
...
drmModeSetCrtc(fb1);
...
}
}Repeated calls to drmModeSetCrtc() do not re‑initialize hardware as long as the display mode and pipeline connections remain unchanged.
Page‑Flip DRM Application
The drmModePageFlip() interface updates the screen only after a VSYNC event, preventing tearing. It requires the driver to support VBLANK events and uses drmHandleEvent() to wait for the event.
void my_page_flip_handler(...){
drmModePageFlip(DRM_MODE_PAGE_FLIP_EVENT);
...
}
int main(void) {
drmEventContext ev = {};
ev.version = DRM_EVENT_CONTEXT_VERSION;
ev.page_flip_handler = my_page_flip_handler;
...
drmModePageFlip(DRM_MODE_PAGE_FLIP_EVENT);
while (!terminate) {
drmHandleEvent(fd, &ev);
}
}Note: drmModePageFlip() may be called only once per VSYNC cycle; additional calls within the same cycle return -EBUSY .
Plane‑Test DRM Application
The drmModeSetPlane() function allows displaying only a portion of a framebuffer. A plane is a hardware layer that moves data from a framebuffer to a CRTC. The example shows cropping, translation, and scaling by setting source and CRTC coordinates.
int main(void) {
...
drmSetClientCap(DRM_CLIENT_CAP_UNIVERSAL_PLANES);
drmModeGetPlaneResources();
drmModeSetPlane(plane_id, crtc_id, fb_id, 0,
crtc_x, crtc_y, crtc_w, crtc_h,
src_x<<16, src_y<<16, src_w<<16, src_h<<16);
...
}Before calling drmModeSetPlane(), the display pipeline must be initialized with drmModeSetCrtc(), otherwise the plane setting has no effect.
Planes can be Primary, Overlay, or Cursor. Modern hardware often blurs the line between Primary and Overlay planes, supporting various formats including RGB, YUV, and compressed FBC.
Important Notes
Ensure no other process occupies /dev/dri/card0 before running the examples; otherwise a Permission Denied error occurs.
The sample code omits extensive error handling for brevity.
Running the single‑buffer program shows a full‑screen white image that waits for a key press before exiting.
The double‑buffer program alternates between red and blue screens on each key press.
The page‑flip example switches between red and blue frames synchronized with VSYNC.
The plane‑test program crops a 320×320 rectangle from (100,150) in the framebuffer and displays it at (50,50) on the screen.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Linux Code Review Hub
A professional Linux technology community and learning platform covering the kernel, memory management, process management, file system and I/O, performance tuning, device drivers, virtualization, and cloud computing.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
