In the world of Linux graphics development, especially on embedded platforms where display timing accuracy and memory efficiency matter just as much as raw GPU throughput, the need for a reliable, low-level testing framework becomes indispensable. As more embedded systems transition toward complex display stacks involving multiple planes, overlays, hardware cursors, color management blocks, and synchronization primitives, having a testing tool that speaks to the graphics hardware at the same level as the kernel itself helps engineers uncover subtle timing problems, bandwidth bottlenecks, and pipeline misconfigurations before they reach production. It is within this environment that libDRM, along with its set of test utilities such as modetest, becomes an essential component for understanding and validating the behavior of any DRM/KMS-based display subsystem. Unlike higher-level graphical debugging tools, modetest interacts with the kernel’s Direct Rendering Manager interfaces directly, bypassing compositors, window managers, and user interface libraries. This gives developers a rare opportunity to observe the display hardware in its raw form, working directly with CRTCs, connectors, encoders, planes, and framebuffers without the abstractions introduced by Wayland or Xorg.
Before exploring the functionality of modetest, it is important to understand the purpose of libDRM itself. libDRM is a userspace interface library that sits directly above the kernel’s DRM subsystem. Its main role is to expose a stable and consistent API for tasks such as buffer allocation, mode setting, command submission, cursor operations, and synchronization across different GPU and display architectures. It becomes especially critical in embedded Linux systems where GPU vendors provide out-of-tree kernel drivers, experimental KMS support, or custom display engines that require rigorous functional validation. libDRM also functions as the foundation for the graphics stack used by major compositors, including GNOME Shell and KDE Plasma, and as such, testing with libDRM allows developers to verify behavior before the graphical stack touches the hardware. For developers attempting to validate a new display pipeline, debug flickering issues, or assess how their hardware behaves with various timing configurations, modetest is often the very first tool they reach for.
The modetest utility, included in the libdrm-tests package, exposes the full display pipeline and allows the developer to enumerate, configure, and test each element manually. Running modetest without parameters prints out the complete topology of the system’s DRM devices, showing every connector, encoder, CRTC, plane, and available mode. For a typical embedded platform using DRM/KMS, this initial command provides insight into how the system recognizes its display hardware. The output is particularly helpful when dealing with panels that require custom timing or where EDID probing does not behave as expected. A developer can begin exploring their environment by issuing:
modetest -cThis command displays the connectors, available resolutions, supported refresh rates, and their related properties. By combining additional flags, the developer can see CRTCs and planes:
modetest -c -e -pThe readability of this output is essential for embedded developers who may not have full documentation for their system-on-chip’s display engine or are attempting to diagnose mismatched timing configurations between the kernel’s DRM driver and the physical panel specifications. Viewing the raw hardware capabilities without the influence of compositors allows engineers to compare what the hardware claims it supports versus what the driver exposes.
One of the most critical aspects of display subsystem validation is ensuring that Vsync signals behave predictably. Vsync timing directly affects smoothness of animation, tear-free rendering, and synchronization of hardware overlays. Embedded developers often encounter situations where a mismatch between panel timing and the HDMI or MIPI-DSI controller causes subtle inconsistencies that are not visible until animations are run at full speed or GPU workloads spike. modetest enables developers to force specific modes onto CRTCs to assess whether the timing parameters behave as expected. A forced mode can be applied by using commands such as:
modetest -M <driver> -s <connector_id>@<crtc_id>:<width>x<height>@<refresh>This single command lets engineers validate whether the timing registers configure correctly and whether the panel responds with stable sync pulses. Developers can then watch the kernel logs in parallel using:
dmesg --followto catch warnings about underruns, FIFO starvation, or clock misconfigurations. These warnings frequently appear during early bring-up phases of embedded DRM drivers and become critical hints for identifying bandwidth miscalculations or improper pixel clock formulas.
Hardware cursor validation is another essential part of the testing workflow, especially because cursor planes often behave differently from primary or overlay planes. The hardware cursor usually has its own dedicated pipeline with its own bandwidth requirements and blending rules. When the hardware cursor is misconfigured, it can lead to cursor lag, disappearing pointer shapes, or occasional corruption when the cursor crosses the boundary between two display planes. modetest provides a direct way to enable and move a hardware cursor independent of any graphical environment. Once a CRTC and framebuffer are configured, a hardware cursor can be enabled using a sequence that involves specifying the cursor plane ID and providing a buffer for the cursor icon. modetest ships with a sample hardware cursor test operation that can be invoked using:
modetest -M <driver> -rThis automated cursor test is helpful not only for verifying position accuracy but also for checking whether the cursor plane supports alpha blending, scaling, or color keying properly. Developers working with embedded systems that have custom cursor size restrictions or that use proprietary display engines often rely on this simple test to validate cursor boundaries after warm-boot or resume cycles. Cursor artifacts can also reveal underlying cache or memory coherence problems, making this test one of the easiest but most informative diagnostics available.
Resolution switching is another major area where modetest proves indispensable. Certain display engines or panels support only a narrow set of preferred modes. Others may support a wider variety but behave unpredictably when switching between resolutions on the fly. By using modetest, developers can rapidly apply different modes to observe how the hardware behaves. A common testing workflow includes applying one mode, waiting for the panel to stabilize, and then switching to another. For example:
modetest -M <driver> -s <connector_id>@<crtc_id>:1920x1080@60
sleep 2
modetest -M <driver> -s <connector_id>@<crtc_id>:1280x720@60This real-time process makes it easy to observe flicker behavior, validate PLL reconfiguration accuracy, and ensure that the display pipeline can properly handle a full reallocation of bandwidth without generating frame underruns. When dealing with hardware that exposes multiple pixel formats or supports additional color encodings such as YUV420, developers can extend modetest to allocate buffers for alternative formats. For such cases, modetest allows specifying pixel formats through flags such as:
modetest -M <driver> -P <plane_id>:<crtc_id>@<width>x<height>@<format>This gives engineers deeper insight into whether the hardware’s color path matches what the driver reports, especially when dealing with YUV output on embedded HDMI controllers or custom RGB-to-LVDS bridges.
Many embedded platforms include multiple planes, often used for overlays, blending, or hardware composition acceleration. modetest is one of the few tools that lets developers test each plane individually by binding it to the CRTC and filling it with a buffer of a chosen format. The command below shows how a secondary plane can be bound and tested independently:
modetest -M <driver> -P 33@40:800x600@XR24This type of testing is invaluable when validating complex windowing systems where overlays display video content, user interface elements, or in-application layers. When something goes wrong in an embedded UI, particularly where flicker or tearing only occurs on specific planes, developers frequently return to modetest to isolate the issue by narrowing the problem to a particular pipeline.
One of the most compelling features of modetest is its ability to pinpoint Vblank and Vsync behavior through verbose options. When dealing with animations, overlays, real-time rendering, or sync-dependent media playback, it is essential to confirm that the system’s vblank interrupts are firing correctly. Running modetest in verbose mode reveals hardware event timing and frequently uncovers latency spikes or dropped Vblank events that do not appear in normal composited environments. A developer can invoke such diagnostics with:
modetest -M <driver> -vMonitoring these events helps determine whether issues originate in the panel, clock tree, or kernel driver’s interrupt handling path. This kind of debugging is common when developing for platforms where the display controller shares memory bandwidth with the GPU or DSP, and where contention might disrupt Vsync stability.
Beyond the raw modetest binary, libdrm includes several additional tools often used in conjunction to validate the GPU driver and buffer allocation subsystem. For instance, drm-info provides an alternative, JSON-style representation of the full DRM pipeline, and it helps developers compare kernel exposed capabilities in a structured form:
drm_infoThis is typically useful when verifying that the pipeline exposes modifiers correctly, such as AFBC, UBWC, or other vendor-specific buffer compression schemes that dramatically affect performance. It also helps confirm whether the driver correctly registers color management blocks, gamma LUTs, degamma LUTs, and CTM matrices.
When working in the depths of embedded Linux display development, it is important to recognize that modetest is not only a functional validation tool but also a performance validation tool. Understanding how your platform behaves at a signal level can make a massive difference when debugging issues such as tearing, underruns, and display jitter. Developers frequently enable kernel debug logs for the DRM subsystem to reveal deeper pipeline behavior. This is accomplished by adjusting the DRM debug mask using:
echo 0x1ff > /sys/module/drm/parameters/debugWith these flags enabled, modetest output becomes intertwined with kernel logging, revealing detailed state transitions that help identify subtle issues hidden beneath normal operation. Such a combination is extremely powerful during early bring-up phases when validating custom display boards, prototype SoCs, or systems that use external bridges like HDMI transmitters or LVDS logic.
Framebuffers play a central role in modetest-based validation, and understanding how they are allocated and tied to the display pipeline is essential. modetest allows developers to create dumb buffers, which are simple pixel buffers without GPU acceleration or tiling. These dumb buffers are ideal for deterministic driver testing, since their linear nature avoids complexities introduced by vendor-specific GPU allocation strategies. Once allocated, dumb buffers can be attached to CRTCs, planes, or hardware cursors, making them powerful tools for verifying correctness. A typical dumb buffer test might look like:
modetest -M <driver> -Dwhich lists the dumb buffer allocation capabilities available on the system. Creating a new dumb buffer involves specifying width, height, and bits-per-pixel, and the resulting buffer can then be mapped into userspace for direct pixel manipulation. These operations allow an engineer to write pixel patterns, colors, gradients, or timing bars directly into memory and evaluate how faithfully the hardware presents them.
Deepening the validation process, developers may create custom patterns to uncover bandwidth limitations or pixel pipeline anomalies. For example, filling the framebuffer with alternating colors helps detect timing jitter or potential clock skew between lanes in a MIPI-DSI transmission. Patterns can be drawn manually by writing to mapped dumb buffer memory after invoking:
modetest -M <driver> -s <connector>@<crtc>:<resolution> -w <property>=<value>This mechanism opens the door to validating not only fundamental functionality but also performance and stability under varying loads.
In more sophisticated evaluation scenarios, modetest works hand in hand with tools like kmscube, which exercises GPU composition using OpenGL ES. However, modetest remains the foundational tool for verifying raw plane behavior before GPU acceleration enters the picture. This layered approach of raw KMS validation followed by GPU pipeline validation allows embedded developers to isolate whether jitter, tearing, or corruption originates in the display engine or GPU render path.
On many embedded platforms, the interaction between display subsystems and power management must also be validated. modetest helps in evaluating how the system behaves when switching modes during runtime power transitions. For example, developers often suspend the device while modetest is active, then resume the system to verify whether the DRM driver can reinitialize hardware state correctly. This workflow might look like:
systemctl suspendfollowed by re-running modetest to check whether plane states remain intact. Some drivers struggle with suspended PLLs or clocks that must be reconfigured upon resume, leading to blank displays or corrupted frames. By keeping modetest in the loop, engineers obtain valuable insights into the reliability of the driver under real use cases.
Testing hardware cursor settings, scaling properties, rotation properties, and plane positioning is also essential. modetest offers a wide array of flags that let developers experiment with rotation:
modetest -M <driver> -P <plane_id>:<crtc_id>@<resolution> -w rotation:90This can expose whether the display hardware supports rotation in hardware or relies on GPU composition instead. Embedded developers targeting consumer devices like tablets often depend heavily on such features.
Resolution changes become particularly important in DRM/KMS drivers built for ARM or RISC-V where custom display engines might support non-standard timings. Using modetest’s ability to specify custom modes allows developers to inject hand-crafted modelines, such as:
modetest -M <driver> -s <connector>@<crtc>:"2560x1440@60" -m <mode_id>When dealing with EDID-less embedded panels, developers can pre-load modes from modeline files or manually set pixel clocks and sync widths. This is especially useful when debugging custom RGB panels driven by DPI or DSI hardware blocks.
For deeper debugging, developers may decide to compile modetest from source, enabling custom printouts or debugging symbols. The libDRM source tree makes it straightforward to modify modetest for platform-specific diagnostics. A developer can build from source using:
git clone https://gitlab.freedesktop.org/mesa/drm.git
cd drm
meson build/
ninja -C build/This yields a modetest binary that can be instrumented to print out register dumps or extra driver-specific information when needed, making it an invaluable tool for working with new or experimental KMS drivers.
As embedded Linux platforms continue evolving and GPU drivers for ARM and RISC-V SoCs mature, the role of libDRM and modetest becomes even more significant. Whether engineers are validating display bring-up on a brand-new SoC, troubleshooting sync issues introduced by power management transitions, assessing overlay behavior under GPU load, or verifying the consistency of hardware cursors, modetest provides a simple yet powerful entry point that uncovers issues hidden beneath compositors and application stacks. Its ability to apply resolutions, control CRTCs, manipulate planes, allocate dumb buffers, test hardware cursors, and capture Vblank timing makes it one of the most critical tools in the Linux graphics ecosystem.
What truly sets modetest apart is its inherently transparent interaction with the hardware. It gives the developer full visibility into the display controller’s raw behavior and provides the foundation upon which reliable, performant display stacks are built. While higher-level frameworks such as Wayland compositors or Xorg servers introduce layers of abstraction for usability, modetest preserves the purity of direct hardware communication. This purity is what makes it irreplaceable in the debugging pipeline, and why display engineers across consumer electronics, industrial systems, automotive clusters, and embedded development boards rely on it daily.
For any developer working with DRM/KMS drivers, understanding and mastering modetest is not merely a technical requirement but a critical part of building intuition about how the display subsystem operates. The commands detailed throughout this article offer a rich starting point for experimenting with different facets of display behavior. Whether validating Vsync behavior through verbose event output, testing hardware cursor movement with dedicated cursor tests, switching resolutions to verify timing stability, or mapping and filling dumb buffers to detect pixel anomalies, modetest remains the most precise and transparent tool in the developer’s arsenal. As embedded display pipelines grow more complex and diversified, the importance of such a versatile and hardware-focused testing utility continues to grow, making modetest and libDRM foundational pillars of Linux graphics development.
