Embedded Graphics Frameworks
An embedded graphics framework is the body of software that sits between an application and a display panel, turning a description of what the screen should contain into the stream of pixels the panel actually receives. On a desktop or a phone this layer is supplied by the operating system and is largely invisible to the application developer. On a microcontroller it is a deliberate engineering choice, and it is one of the few choices in a firmware project that simultaneously commits memory, processor time, build tooling, licensing terms, and, in regulated products, part of the safety argument.
The decision is difficult because the constraint is unusual. A single uncompressed frame at a modest resolution can exceed the entire internal memory of the processor, so the framework cannot simply assume the existence of a frame buffer the way a desktop toolkit does. Every framework in this space is, at bottom, a set of answers to one question: how does a device with a few hundred kilobytes of random-access memory produce a continuously updating image that a person will judge by the standards set by their telephone? This article examines those answers as engineering, comparing the architectures rather than cataloguing feature lists, and separating what the frameworks demonstrably do from what their vendors claim.
What a Graphics Framework Adds Above the Display Driver
A display driver is a narrow piece of code. It configures the panel, sets up whatever peripheral moves pixel data, and exposes a way to write a rectangle of pixels to a region of the screen. Many products need nothing more. A framework becomes worthwhile only when the interface acquires structure that would otherwise be reimplemented by hand: overlapping elements, scrolling regions, text that must reflow, animation, and state that changes independently of the code that draws it.
Nearly every framework in this field decomposes into the same layers, and understanding the decomposition makes the comparisons that follow far easier.
The Porting Layer
At the bottom sits a small, well-defined set of functions the integrator writes: a flush routine that accepts a rectangle of rendered pixels and delivers them to the panel, a tick source, an input read routine, and optionally hooks for hardware acceleration and memory allocation. This layer is the entire contact surface with the hardware, and its size is a reasonable proxy for how hard the framework will be to port. A porting layer of a few hundred lines is normal; one that requires an operating system underneath it is a substantially different proposition.
The Rendering Core and the Object Model
Above the porting layer is the software that turns geometric requests into pixels: filled rectangles, rounded corners, gradients, lines, arcs, blended images, and glyphs. This core owns the pixel formats, the blending rules, the clipping logic, and the decision about whether a given primitive is executed by the processor or handed to an accelerator. It determines both visual quality and the majority of the processor load.
Most frameworks wrap that core in a tree of user interface objects carrying position, size, style, and parent-child relationships. The tree provides clipping and coordinate transformation for free, defines hit testing for input, and gives the framework the information it needs to decide which parts of the screen actually changed. Frameworks that omit the tree, discussed below, make a different trade that is coherent but has different memory consequences.
The Loop, the Assets, and the Tooling
A handler runs periodically, drains the input queue, advances animations, dispatches events to objects, and then performs whatever rendering the accumulated changes require. How this loop cooperates with the rest of the firmware, and in particular with a real-time kernel, is one of the recurring integration problems and is treated in its own section below.
Surrounding all of this is a host-side pipeline, because fonts, images, and animations do not exist on the target in the formats designers produce them in. Every serious framework ships tools that convert scalable fonts into glyph tables, images into the target pixel format, and, in the designer-driven products, a visual layout into generated source code. This tooling is part of the framework in every practical sense: it enters the build system, it must be version-controlled, and its output is the majority of the flash the interface consumes.
Retained Widget Trees Against Immediate Mode
The most consequential architectural division in this field is between retained-mode and immediate-mode rendering, and on a microcontroller the division is decided by memory rather than by taste.
The Retained Model
In a retained framework the application constructs objects that persist. A button exists as a structure in random-access memory holding its coordinates, its style, its text pointer, its state flags, and its callbacks. The application mutates that structure; the framework decides when and what to draw. LVGL, TouchGFX, emWin, GUIX, Qt for MCUs, Embedded Wizard, and Slint are all retained frameworks, and the model dominates the field for a specific reason: because the framework owns the object tree, it knows exactly which pixels can possibly have changed, and can therefore redraw a fraction of the screen instead of all of it. Partial redraw is the single technique that makes a smooth interface possible without a full frame buffer, and it requires retained state to work.
The cost is that every visible element occupies memory permanently. Object structures in these frameworks typically run from tens to a few hundred bytes each, so a screen with a hundred elements commits several kilobytes before any pixel data exists. Deeply nested layouts, long lists, and screens that are kept resident rather than destroyed on navigation all multiply this cost. A common and effective pattern is to build each screen on entry and free it on exit, accepting a construction delay at transition time in exchange for a working set that reflects one screen rather than all of them.
The Immediate Model
An immediate-mode framework retains nothing. Each frame the application calls functions that both describe and draw the interface, and any state the interface appears to hold lives in the application's own variables. Dear ImGui and Nuklear are the well-known examples. The programming model is attractive: there is no synchronization problem between application state and interface state, because there is only one copy of the state.
The consequence is that the framework has no basis for computing what changed, so it redraws everything, every frame. That is entirely reasonable on a system with a full frame buffer and spare processor cycles, and immediate mode is used successfully on embedded Linux devices, on internal engineering and calibration tools, and on hardware with a graphics processing unit. It is a poor fit for a microcontroller driving a panel over a serial link, where redrawing the whole screen is precisely the operation the design cannot afford.
Declarative Descriptions Compiled Ahead of Time
A third position has become common. Qt Quick Ultralite, Slint, and Embedded Wizard accept a declarative description of the interface in a domain-specific language and compile it, on the host, into C or C++ that is baked into the firmware. The result behaves as a retained tree at run time, but the layout, the property bindings, and much of the styling are resolved by the compiler rather than by code executing on the target. This moves work from run time to build time and moves data from random-access memory to flash. It also means the interface description is not modifiable at run time, which is usually irrelevant and occasionally fatal, as when a product must render a layout downloaded after deployment.
Invalidation and Partial Redraw
Partial redraw is the mechanism that makes retained frameworks viable on small hardware, and its behavior is worth understanding in detail because it is where most performance surprises originate.
The Invalid Area List
When an object's appearance changes, the framework marks the rectangle it occupies as invalid. Marking is cheap; it records coordinates and returns. At the next rendering opportunity the framework collects the accumulated invalid rectangles, merges those that overlap or are close enough that merging is cheaper than handling them separately, and then, for each surviving rectangle, walks the object tree and draws every object that intersects it, in back-to-front order, clipped to the rectangle. Objects that do not intersect any invalid rectangle are not touched at all.
The merging heuristic matters. Two small updates at opposite corners of the screen, merged into one bounding rectangle, force a redraw of the entire display. Frameworks limit this with a bounded list of invalid areas and rules about when merging is permitted, but the pathological case remains reachable: an interface that animates several widely separated elements simultaneously can cost more than one that animates a single large element.
Transparency Propagates Invalidation Downward
Redrawing a rectangle correctly requires drawing everything beneath it whenever the changed object is not fully opaque. A semi-transparent overlay, a rounded corner with an anti-aliased edge, and a drop shadow all force the framework to render the background, then the intermediate layers, then the object itself. Translucency is therefore expensive in a way flat color is not, and a design that looks modest can cost more than one that looks elaborate. Where a framework offers an opaque style for a container, using it is among the highest-value optimizations available, because it terminates the downward walk.
The Cases Where Partial Redraw Fails
Three situations defeat the technique. Full-screen transitions between screens invalidate everything by definition. Scrolling moves every pixel in the scrolling region, so the region must be redrawn in full each frame unless the hardware can offset the read address of the display controller. Video or camera preview updates a large rectangle at the frame rate of the source. In each case the design must either accept a lower frame rate, restrict the changing region to a fraction of the panel, or move to a full frame buffer with hardware assistance. Recognizing these cases during design review, rather than during integration, avoids the most common late-stage rework in graphical firmware.
Frame Buffers, Tearing, and Where the Memory Comes From
Frame buffer arithmetic is unforgiving and should be done on the first day of a project. The size of one buffer is the product of width, height, and bytes per pixel. TouchGFX documentation states the relationship directly as width multiplied by height multiplied by color depth in bits, divided by eight, and gives the worked example of an 800 by 480 display at sixteen bits per pixel consuming 768,000 bytes.
A few reference points make the scale clear. A 320 by 240 panel at sixteen bits per pixel needs 153,600 bytes. A 480 by 272 panel, common on entry-level evaluation boards, needs 261,120 bytes. The 800 by 480 panel above needs 768,000 bytes at sixteen bits and 1,152,000 bytes at twenty-four. A 1024 by 600 panel at sixteen bits needs 1,228,800 bytes. Against these figures, a microcontroller with 512 kilobytes of internal random-access memory can hold one full buffer for a small panel and nothing larger, which is why external synchronous dynamic memory appears on the bill of materials the moment the panel exceeds a few hundred pixels on a side.
Partial Buffering
The alternative is to allocate a buffer far smaller than a frame and use it repeatedly. The framework renders one invalid rectangle, or one horizontal stripe, into the buffer, transfers it to the panel, and reuses the buffer for the next region. LVGL's documented requirement is a draw buffer larger than one horizontal line of the display, with roughly ten lines recommended, which for an 800-pixel-wide panel at sixteen bits per pixel is about sixteen kilobytes rather than 768,000 bytes. TouchGFX describes partial buffering as operating with less than one complete frame buffer, at the cost of higher processor load and, in its own words, a higher risk of tearing.
Partial buffering is what allows a serious interface to run on a microcontroller with no external memory at all, and its limitations are equally real. Any effect requiring readback of what was previously drawn becomes impossible, because the screen contents are not held anywhere the processor can read, so frame-wide effects such as a full-screen blur or a cross-fade between two complete screens are unavailable or must be composed from smaller pieces. And because the transfer happens in pieces, a fast-moving update can be caught by the panel refresh partway through.
Double and Triple Buffering
With two full buffers, the display controller scans out one while the framework renders into the other, and the buffers swap at the vertical blanking interval. TouchGFX documentation describes this arrangement as eliminating the risk of tearing and providing optimal time for rendering, at the cost of random-access memory for two full frames. This is the standard configuration for any device with external memory and a parallel display interface, and it is the point at which embedded graphics starts to behave like graphics on a larger machine.
Triple buffering adds a third buffer so that the renderer never has to wait for a swap to complete. It raises sustained throughput when render times vary from frame to frame, and it decouples the renderer from the panel refresh entirely. It also adds one frame of latency between an input and its visible consequence, and on a touch interface, where the user's finger is physically present on the glass, that latency is perceptible in dragging and scrolling. Triple buffering is therefore common in media playback and rare in direct-manipulation interfaces.
Tearing and Synchronization
Tearing occurs when the panel displays pixel data belonging to two different frames within a single refresh, which appears as a horizontal seam across a moving element. TouchGFX defines the artifact in exactly those terms. The remedy depends on the interface. On a continuously scanned interface the framework must swap buffers, or confine its writes to regions the scanout has already passed, during the vertical blanking interval, which the display controller signals by interrupt. On a command-mode panel that holds its own frame memory, the panel provides a tearing effect output that pulses when its internal scanout reaches a safe point, and the transfer is started from that signal.
Single buffering without synchronization is not always wrong. An interface whose changes are small, infrequent, and confined to a region such as a numeric readout may never produce a visible tear, and the memory saved is substantial. The judgement is about the content, not about correctness in the abstract.
Where the Memory Physically Lives
The placement of the buffer matters as much as its size. Internal static memory is fast and deterministic but scarce. External synchronous dynamic memory is plentiful but shares its bus with instruction fetches and direct memory access transfers, so frame buffer traffic and code execution contend. Some devices provide a tightly coupled memory region that the processor can reach with no wait states but that peripherals may not be able to address, which makes it excellent for the rendering scratch buffer and useless for the scanout buffer. Where a device offers a graphics memory management unit, ST's Chrom-GRC being the example TouchGFX names in connection with partial buffering, the buffer can be laid out non-contiguously or with the unused corners of a round display omitted, recovering memory that a rectangular allocation would waste.
Display Interfaces as a Constraint on the Framework
The electrical interface to the panel does more to determine the achievable interface than the processor does. It sets the maximum rate at which pixels can reach the glass, and it determines whether the panel holds its own image or must be refreshed continuously.
Parallel RGB
A parallel interface, standardized by the MIPI Alliance as the Display Pixel Interface and universally called parallel RGB, carries color data on sixteen to twenty-four data lines with pixel clock, horizontal sync, vertical sync, and data enable. The panel has no memory; the display controller in the processor must read the frame buffer and drive every pixel of every refresh. An 800 by 480 panel at sixty hertz, including blanking intervals, requires a pixel clock on the order of thirty megahertz and sustains a continuous read of roughly thirty megabytes per second from the frame buffer. That traffic is the dominant load on the memory system and must be budgeted alongside everything else the processor does. In exchange, the interface imposes no ceiling on update rate: the framework may change any pixel at any time, and the panel will show it at the next refresh.
MIPI DSI
The Display Serial Interface replaces the wide parallel bus with one or more high-speed differential lanes, which reduces pin count, electromagnetic emission, and cable complexity, and is why it dominates in handheld products. DSI panels operate in two modes with different implications. In video mode the panel behaves like a parallel panel, requiring a continuous stream. In command mode the panel contains its own frame memory, and the host sends only updated regions. Command mode is a natural fit for partial redraw: the framework already computes the rectangles that changed, and the interface accepts exactly that. It also provides the tearing effect signal that makes single-buffered operation safe.
Serial Interfaces and Panel-Resident Memory
Small panels are frequently driven over a serial peripheral interface or the parallel variant of the MIPI Display Bus Interface, historically called the 8080 interface. In both cases the panel controller holds the frame, and the host writes only what changes. This is the cheapest way to add a display to a microcontroller, and it is the configuration in which framework choice matters most, because the link is the bottleneck.
The arithmetic is stark. A 320 by 240 panel at sixteen bits per pixel is 1,228,800 bits per frame; over a serial link clocked at forty megahertz that is about thirty-one milliseconds, or roughly thirty-two full frames per second at best, with the link fully occupied. The same link driving an 800 by 480 panel needs about 154 milliseconds per full frame, under seven frames per second. A design in that position cannot afford full-screen redraw at any price, and the framework's invalidation behavior becomes the deciding factor in whether the product feels responsive. Direct memory access with the transfer running in the background, and double-buffered stripes so that rendering of the next stripe overlaps transmission of the current one, are the standard mitigations.
Memory-in-Pixel and Electrophoretic Displays
Two panel technologies invert the usual assumptions entirely. Memory-in-pixel liquid crystal displays, of which Sharp's monochrome modules are the familiar example, store one bit per pixel in the panel itself and consume power only when the image changes, though they require a periodic polarity inversion signal to prevent damage to the liquid crystal. They accept line-addressed updates over a serial link, so a framework that can render and transmit individual lines maps onto them well, while a framework that assumes a color frame buffer does not.
Electrophoretic displays, commonly called electronic paper, are more demanding still. The pixels are driven by a waveform lasting a substantial fraction of a second, and controllers typically expose both a full update, which flashes the panel and takes on the order of a second, and a partial update, which is faster and quieter but leaves residual ghosting that accumulates until a full update clears it. No conventional graphics framework anticipates a display that takes a large fraction of a second to change and degrades if changed too often. Products using these panels either drive them with purpose-built code or use a framework in a restricted mode, rendering into a one-bit or two-bit buffer and pushing frames on an application-controlled schedule rather than a periodic one. Animation, in any usual sense, is not available.
Two-Dimensional Acceleration and How Frameworks Use It
Many microcontrollers aimed at graphical products contain a fixed-function block that performs the operations a two-dimensional interface spends most of its time on. Whether a framework uses that block, and how well, is a large part of what separates products on identical silicon.
Blitters
ST's DMA2D peripheral, marketed as the Chrom-ART Accelerator, is the canonical example. Its reference documentation describes four operating modes: filling a region with a constant color, copying a region, copying with conversion between pixel formats, and blending two sources into a destination. Those four operations cover the great majority of the work in a flat interface, and they run without processor involvement, so a well-integrated framework issues a transfer and then either performs unrelated work or sleeps until the completion interrupt. NXP provides an analogous Pixel Pipeline on its i.MX RT family, and other vendors offer equivalents under their own names.
Two integration details determine whether the acceleration is actually realized. The block cannot be used for very small operations, because configuring it costs more than the copy, so frameworks apply a size threshold below which they fall back to software, and that threshold is worth tuning per platform. More consequentially, the accelerator reads and writes memory independently of the processor's caches: on a device with a data cache the framework must clean the cache before a transfer that reads processor-written data and invalidate it after a transfer that writes memory the processor will read. Omitting either produces intermittent visual corruption that is notoriously difficult to diagnose, and it is one of the most common defects in hand-written porting layers.
Vector Units and Small Graphics Processors
Above the blitter sit blocks that rasterize paths rather than move rectangles. Vivante's VGLite programming interface, exposed on several NXP i.MX RT parts, and ThinkSilicon's NemaGFX are examples that LVGL's own documentation lists among its supported accelerators, alongside NXP's Pixel Pipeline and Arm's Arm-2D. Arm-2D occupies an interesting middle position: rather than a hardware block, it is an open-source library that exploits the Helium vector extension present in some Cortex-M cores, giving a measurable speedup on parts that have no dedicated graphics hardware at all.
These units matter because vector rendering changes what the asset pipeline must produce. A framework that rasterizes paths on the target stores an icon as a few hundred bytes of path data and scales it to any size, where a bitmap approach stores every size that will be displayed; across a large icon set that difference amounts to hundreds of kilobytes of flash.
When Frameworks Ignore the Hardware
A framework may support an accelerator nominally while using it for a narrow set of cases. The honest test is measurement rather than a feature matrix: instrument the processor load with the acceleration enabled and disabled and compare. Common gaps include text rendering that remains entirely in software because glyph blending does not map onto the block's blend modes, rotation and scaling that the block does not implement, and blending of formats the block does not convert between. A framework that renders its widgets with the accelerator but its text without it may spend most of a text-heavy screen's time in software regardless.
Fonts, Text Rendering, and Anti-Aliasing
Text is the part of an embedded interface that most reliably reveals whether the framework was engineered or assembled, and it is usually the largest single consumer of flash.
Prerendered Glyphs Against On-Target Rasterization
The dominant approach converts a scalable outline font on the host into a table of prerendered glyph bitmaps at a fixed size, together with advance widths, bearings, and kerning pairs. Rendering on the target reduces to looking up a glyph and blending its coverage values into the destination, which is fast and entirely predictable. The cost is that every combination of typeface, size, and weight is a separate table in flash, and that no size can be produced that was not anticipated at build time.
The alternative rasterizes outlines on the target, generally with FreeType, which is available under either the FreeType License or the GNU General Public License version 2. This buys arbitrary sizes and a much smaller font footprint, at the cost of processing time, a glyph cache in random-access memory, and a rendering time that varies with the glyph. Products with a fixed set of sizes almost always prerender; products that must scale text for accessibility, or that render user-supplied content, increasingly rasterize.
The Cost of Coverage Depth
Anti-aliased text stores a coverage value per pixel rather than a single bit, and the depth of that value is a direct multiplier on font size in flash. One bit per pixel gives hard, aliased edges and the smallest table. Two bits give four coverage levels, which is visibly better and quadruples nothing. Four bits give sixteen levels, which is generally indistinguishable from eight bits at typical interface sizes while occupying half the space. Eight bits is the reference. Moving a font from eight bits to four is one of the least painful size reductions available in embedded graphics, and most frameworks expose the choice in their font conversion tool.
Blending coverage correctly requires knowing the color beneath each pixel, which is why text over a gradient or a photograph costs more than text over a flat fill.
Scripts Beyond Latin
Internationalization changes the calculation completely. A Latin font covering the printable ASCII range needs fewer than one hundred glyphs. Covering Chinese, Japanese, and Korean requires thousands, and a full set at a usable size runs to megabytes, which is why products for those markets place fonts in external serial flash and either execute in place from it or cache glyphs on demand. Arabic and Hebrew require bidirectional layout, and Arabic additionally requires contextual shaping, where the form of a letter depends on its neighbors. Devanagari and Thai require reordering and mark positioning. LVGL's documentation states support for the CJK scripts along with Thai, Hindi, Arabic, and Persian, and frameworks that handle these cases generally do so by integrating a shaping engine such as HarfBuzz. A project that will eventually need these scripts should verify the support early, because retrofitting bidirectional layout onto an interface built for left-to-right text is a rewrite of the layout code rather than a configuration change.
The Asset Pipeline
Interface assets originate as design files and must end as constants in the firmware image. The pipeline that performs this conversion is where most of the flash budget is decided, and it deserves to be treated as build infrastructure rather than as a manual step.
Conversion and Pixel Formats
An image imported into an embedded framework is converted to the pixel format the panel uses, most often five bits of red, six of green, and five of blue for a sixteen-bit panel, with an alpha channel added where transparency is required. Storing an image in the native format allows the blitter to copy it directly; storing it in any other format forces a conversion on every draw. The conversion tool typically also offers indexed color, where the image references a palette of sixteen or 256 entries, which is highly effective for interface artwork with limited color counts and useless for photographs.
Compression trades flash for time and for random-access memory. A run-length scheme decodes cheaply and helps on flat artwork, while full PNG or JPEG decoding requires a decoder in flash and a decompression buffer large enough to hold the decoded image, which reintroduces the memory problem the compression was meant to solve. The usual resolution is to compress large, rarely drawn assets such as a splash screen and to store frequently drawn assets uncompressed in the native format.
External Flash and Execute in Place
When assets exceed internal flash, they move to an external serial memory, most often a quad or octal serial peripheral interface device operated in memory-mapped mode so that the processor can read it with ordinary load instructions. This works well and is widely deployed, with two caveats worth planning for. Read throughput is a fraction of internal flash, so drawing directly from external memory is slower and less deterministic; and a cache miss on an asset read introduces a delay that lands unpredictably within a frame. Products with a strict frame budget copy the assets needed for the current screen into random-access memory at screen entry, paying a single predictable cost instead of many unpredictable ones.
Whichever route the assets take, the conversion belongs in the build rather than in a manual step. If it runs from checked-in source images and a checked-in tool version, the firmware image is reproducible and a designer's change to an icon cannot silently fail to reach the device. Generated files that are committed and regenerated by hand drift from their sources, and the drift is normally discovered by a customer.
Input, Touch, and Event Plumbing
Input is deceptively simple and is a frequent source of interfaces that feel wrong despite rendering correctly.
Reading the Touch Controller
A projected-capacitive touch panel is served by a controller that communicates over a two-wire serial bus and asserts an interrupt line when a touch is present. The framework typically asks for input through a periodic read callback rather than reading in the interrupt itself, because a bus transaction inside an interrupt handler blocks for hundreds of microseconds and interacts badly with real-time deadlines elsewhere in the system. The standard structure is an interrupt that records the event and signals a task, a task that performs the bus transaction, and a queue between that task and the framework.
The polling rate governs how the interface feels. A framework polling at the rate of a sixty-hertz display samples touch every seventeen milliseconds, which is adequate for taps and marginal for dragging, where the pointer visibly lags the finger. Sampling touch faster than the render rate, and interpolating between samples when rendering, is a well-established improvement that costs almost nothing.
Gestures, Hit Testing, and Acknowledgment
Above the raw coordinates the framework interprets press, release, movement, long press, and directional swipes, and decides which object receives them by walking the object tree from front to back. Two thresholds do most of the work in making this feel correct. The movement threshold determines how far a finger may travel before a press becomes a drag, and setting it too low makes buttons impossible to press reliably because a small movement during the press cancels the activation. The long-press interval determines when a held press becomes a distinct gesture. Both should be expressed in physical units rather than pixels, because the same pixel distance is a different physical distance on panels of different densities. Hit target size is a related constraint the framework can help with: most frameworks allow padding that extends an object's sensitive region beyond its drawn one, which is often the difference between an interface that works with a gloved hand and one that does not.
The most valuable property of the input path, however, is that the visual response to a press is not queued behind the work the press initiates. Frameworks make this straightforward by separating the event that changes the visual state from the callback that performs the action, but the discipline is the developer's: any callback that blocks for longer than a frame stops rendering and input processing for its duration.
Designer Tools and the Code-Generation Round Trip
Every commercial framework in this field ships a visual designer, and the quality of that tool is frequently the real reason a team chooses one product over another.
What the Tools Produce
The tools differ in what they generate and how they expect the generated output to be modified. Eclipse ThreadX GUIX is accompanied by GUIX Studio, which its documentation describes as generating C code compatible with the GUIX library and ready for compilation on the target. TouchGFX Designer generates C++ classes for each screen, following a pattern in which the generated base class is overwritten on every regeneration and a derived class, written by the developer, is not. Embedded Wizard, from TARA Systems of Munich, compiles a description written in its own language into target source. Qt Design Studio produces QML that the Qt Quick Ultralite compiler turns into C++ for microcontroller targets. Crank Storyboard takes a different route, keeping the design as data interpreted by a runtime engine so that the design and the application logic can be changed independently.
The distinction that matters in practice is whether developer code and generated code are separated by a mechanism the tool enforces. Where they are, as in the base-and-derived-class pattern, regeneration is safe and designers and developers can work in parallel on the same screens. Where they are not, and developers edit generated files directly, the first regeneration destroys their work, and the team's response is invariably to stop using the designer, at which point the tool's value is lost.
Simulation on the Host
Most of these frameworks build for a desktop host as well as for the target, rendering into a window instead of a panel, which lets interface iteration happen in seconds rather than in flash-and-reboot cycles and lets work begin before hardware exists. It is also a reliable source of false confidence: the host has effectively unlimited memory and speed, so an interface that is smooth in simulation may be unusable on the target, and memory exhaustion the host absorbs silently becomes a failed allocation on the device. Simulation validates layout, navigation, and logic, and says nothing about cost. The related organizational failure is a visual design produced without reference to the target at all, since blur, large translucent overlays, freely scaled photography, and full-screen animation are all cheap in a design tool and expensive or impossible on a microcontroller. Fixing the frame and memory budgets before the visual design begins is cheaper than negotiating the design down later.
Living with the RTOS or the Superloop
A graphics framework is a large, periodic consumer of processor time inserted into a system that already has timing obligations. How it is scheduled determines whether it degrades the rest of the firmware.
The Superloop
In a bare-metal design the framework's handler is called from the main loop, and the loop's period becomes the render period. This is simple and entirely adequate when every other activity in the loop is short. It fails when any activity is not: a blocking flash write, a sensor conversion, or a network transaction that takes fifty milliseconds stalls rendering and input for fifty milliseconds, and the user sees it. Bare-metal graphical firmware therefore tends to acquire a discipline of non-blocking state machines for every long operation, which is achievable but must be maintained by everyone who touches the code.
The Framework as a Task
Under a real-time kernel the framework normally runs in its own task, which resolves the blocking problem because a task that blocks yields the processor rather than stalling the system. Three rules make this arrangement work. The graphics task should run at a priority below every hard real-time activity, because a dropped frame is a cosmetic defect while a missed control deadline is a functional one. Almost all of these frameworks are not internally thread-safe, so every call into the framework must come from the graphics task, and other tasks must communicate through a queue rather than by touching objects directly. And the display transfer should be performed by direct memory access with the task blocking on a semaphore given from the completion interrupt, so that the task's priority does not matter during the transfer.
Violating the second rule is the single most common defect in graphics integration. A sensor task that updates a label directly appears to work, then corrupts the object tree the first time it preempts the framework mid-render. The failure is intermittent, depends on timing, and typically survives testing to appear in the field.
Memory Allocation
Retained frameworks allocate objects dynamically, and dynamic allocation over a long deployment invites fragmentation: a heap that satisfies every request in the first week may fail on an identical request in the second month because the free space has become discontiguous. Four mitigations are established. Give the framework its own heap rather than the system heap, so its pattern is isolated and its consumption measurable. Allocate a screen's objects together and free them together, returning the heap to a known state at every navigation. Track peak usage against a budget rather than discovering it on failure. And in high-integrity products avoid dynamic allocation after initialization altogether, which the ahead-of-time compiled frameworks make easier because much of the object graph is static.
The Frame Budget and How to Measure It
Performance work in embedded graphics is quantitative and does not reward intuition. The budget is fixed by the refresh rate: sixty frames per second allows 16.7 milliseconds per frame, thirty frames allows 33.3, and twenty frames, which is acceptable for interfaces without continuous animation, allows fifty. Every frame must fit rendering, transfer, input handling, and whatever else shares the processor.
Instrumentation
The most useful measurement in this field remains a general-purpose output pin toggled at the start and end of the render, observed on an oscilloscope or logic analyzer. It costs two instructions, perturbs nothing, and shows both duration and jitter directly. On an Arm Cortex-M core the cycle counter in the debug watchpoint unit gives cycle-accurate timing in software without external equipment. Instruction trace over a single-wire output, and tools such as SEGGER's SystemView, extend this to a full timeline showing which task ran when, which is what is needed to attribute a dropped frame to the activity that caused it.
Measurements must be taken from the worst case rather than the average. The frame that matters is the one containing a full-screen transition, a font cache miss, an external flash read, and a preempting interrupt, and it is the frame the user will notice. Averaging obscures exactly the events worth finding.
Where the Time Actually Goes
Four costs dominate in most measured interfaces. Overdraw, meaning pixels written more than once per frame because of stacked translucent layers, is usually the largest and is reduced by making backgrounds opaque and flattening the object hierarchy. Text blending is next, particularly at high coverage depth over non-uniform backgrounds. Transfer to the panel dominates whenever the link is serial. And memory bandwidth contention, where scanout traffic and processor accesses compete for the same external memory, appears as rendering that is slower than the arithmetic predicts and is diagnosed by observing the render time change when scanout is disabled.
What the resulting numbers should be optimized toward is worth stating, because it is not simply the largest one. A consistent thirty frames per second is preferable to an interface alternating between sixty and fifteen, since irregularity is more noticeable than a uniformly lower rate, and for direct manipulation the latency from input to visible response matters more than the frame rate at all.
Safety-Critical Rendering
In some products a displayed value is not merely informative. An automotive instrument cluster must show a brake warning, an infusion pump must show a delivered dose, and an industrial control must show a machine state. The requirement in these cases is not that the interface look good but that what appears on the glass be demonstrably correct, and a general-purpose graphics framework offers no such demonstration.
The Standards Involved
The applicable standard depends on the domain: ISO 26262 for road vehicles, with its automotive safety integrity levels; IEC 62304 for medical device software; IEC 61508 for industrial functional safety; and EN 50128 for railway control and protection software. Each requires that software contributing to a safety function be developed under a defined process with evidence, which places the graphics stack inside or outside the safety boundary according to what the display is relied upon to do. Bringing a large, feature-rich framework inside that boundary is generally impractical, so the standard architectural response is to arrange matters so that most of the stack falls outside it.
Separating the Safe Path
The prevailing pattern renders safety-relevant elements through a small, independent path and everything else through the ordinary framework. Qt Safe Renderer is a commercial implementation of exactly this idea; its documentation describes it as a rendering component for safety-critical items such as warning indicators, which separates safety-critical rendering from other system components so that critical elements continue to function when the main interface fails, and states that safety certification artifacts are delivered on request. Qt does not, in that overview, name the specific standards or integrity levels the component is certified against, so a project relying on it should obtain those artifacts and verify their scope directly rather than assuming a level.
The mechanism is composition in hardware. Where the display controller supports multiple layers, the safe elements are rendered into their own layer that the controller composites above the application layer. The application cannot overwrite that memory, and a fault in the application layer therefore cannot conceal or corrupt a warning. Where the processor supports memory protection or partitioning, the safe layer's buffer and code are placed in a region the application cannot write.
Proving What Reached the Glass
Separation establishes that the safe path was not corrupted by the unsafe one. It does not establish that the safe path produced the right image, and several complementary techniques address that. Reading back the rendered region and computing a checksum over it, then comparing that checksum against a value precomputed for the expected content, verifies that the intended glyph or symbol is actually present in memory. A freshness counter incremented every frame and monitored by an independent watchdog detects a rendering path that has stopped, which is a particularly dangerous failure because a frozen display showing a plausible value gives no indication of malfunction. Where a display controller reports underrun or transfer errors, those must be treated as faults rather than ignored. And the fallback behavior must be specified: on detected failure the system should present a defined safe state, which is frequently a blank screen with an unambiguous fault indication, since a blank display is honest while a stale one is misleading.
Comparing the Frameworks by Architecture
The comparison below groups the well-known options by the architectural choices described above rather than by feature count. Figures given are those stated in the projects' own documentation, and where a claim originates with a vendor it is identified as such.
LVGL
LVGL is a retained, partial-buffer framework distributed under the MIT license, which places no royalty or source-disclosure obligation on a commercial product using it. Its documented minimum requirements are a sixteen-, thirty-two-, or sixty-four-bit processor with a clock above sixteen megahertz recommended, more than sixty-four kilobytes of flash for the essential components with more than 180 kilobytes recommended, roughly two kilobytes of static random-access memory depending on the features used, and a draw buffer larger than one horizontal line, with ten lines recommended. The project's own repository gives more practical figures for a complete interface: a minimum of thirty-two kilobytes of random-access memory and 128 kilobytes of flash, with a typical interface needing about one hundred kilobytes of memory and two to three hundred kilobytes of flash. It supports a wide range of accelerators, its documentation naming VG-Lite, Dave2D, NeoChrom, OpenGL, NXP's Pixel Pipeline, Arm-2D, and ThinkSilicon's NemaGFX. Its principal architectural characteristic is that it is designed from the outset around rendering into a buffer that is a fraction of the screen, which is why it appears on hardware where other frameworks do not fit.
TouchGFX
TouchGFX is STMicroelectronics' retained framework for STM32 devices, supplied with the TouchGFX Designer tool and free of charge for use on STM32 parts. Its documentation is unusually explicit about buffer strategy, presenting double buffering, single buffering, and partial buffering as a deliberate choice with stated consequences, and describing partial buffering as emulating a full-size buffer with a graphics memory management unit at the cost of higher processor load and higher tearing risk. Its close coupling to one vendor's silicon is simultaneously its main strength, since the acceleration integration and the tooling are tuned for those parts, and its main limitation, since the interface does not travel to a different vendor's processor.
emWin
emWin is SEGGER's commercial graphics library, offering a window manager, widget library, anti-aliasing, alpha blending, and a font converter, with memory devices as its mechanism for flicker-free composition. SEGGER licenses it on a one-time, royalty-free basis, and states that a free commercial license may be used to develop applications for certain devices from particular silicon vendors, naming Nuvoton, NXP, and Renesas among its partners; a non-commercial license is available for evaluation and education. Because the free-license arrangement is negotiated per vendor and changes over time, the licensing position for a specific part should be confirmed against SEGGER's current terms rather than assumed from a previous project.
Eclipse ThreadX GUIX
GUIX is a retained framework paired with GUIX Studio, its design environment, which generates C code for the GUIX library. The codebase now lives at the Eclipse Foundation as Eclipse ThreadX under an MIT license, and its repository notes integration within semiconductor vendor development kits including those of NXP, Renesas, and Microchip. Its natural pairing with the ThreadX kernel makes it attractive to teams already using that kernel, and the licensing change removed the principal commercial objection to it.
Qt for MCUs
Qt for MCUs brings the QML declarative language and the Qt Design Studio tooling to microcontrollers through Qt Quick Ultralite, which compiles the declarative description ahead of time into C++ rather than interpreting it. It is a commercial product. Its distinguishing property is continuity of tooling and of the declarative language across the whole range from a microcontroller to a Linux device, which is valuable to an organization shipping a product family spanning several classes of hardware and largely irrelevant to a team shipping a single device. Qt Safe Renderer, discussed above, is available under certain Qt licenses for the safety-relevant case.
Slint and Embedded Wizard
Slint is a more recent declarative framework with bindings for Rust, C++, JavaScript, and Python, offered under a choice of a GNU General Public License, a royalty-free permissive license for desktop, mobile, and web use, and a support-inclusive perpetual-fallback commercial license. Its own documentation states that the Slint runtime fits in less than three hundred kibibytes of random-access memory, which is a vendor figure and should be confirmed against the specific interface a project intends to build. Embedded Wizard, from TARA Systems, similarly compiles a description in its own language into target code and states support for more than ninety platform packages; its published material emphasizes operation on limited hardware without giving specific footprints, so a footprint figure for a particular target should be obtained from the vendor and verified by building a representative screen.
Making the Choice
Four questions settle most selections faster than any feature comparison. Does a full frame buffer fit, and if not, does the framework genuinely support rendering in fractions of a screen? Is the processor's acceleration hardware used by the framework for the operations this specific interface performs, verified by measurement rather than by a support matrix? Do the licensing terms suit the product's distribution model over its full commercial life, including the possibility of moving to a different silicon vendor? And does the designer tool separate generated code from developer code well enough that the team will still be using it in a year? A framework that answers these four well will outperform one that answers them poorly regardless of how many widgets it offers.
Conclusion
An embedded graphics framework is a memory architecture before it is a widget library. The central question every framework answers is how to produce a continuously changing image without room to hold one, and the answers, retained object trees that permit partial redraw, invalid-area tracking, partial buffers flushed in stripes, and ahead-of-time compilation that moves layout from memory into flash, all follow from that constraint.
The subsidiary decisions follow the same logic. Buffering strategy trades random-access memory against tearing and against latency, and the trade is legitimate in every direction depending on what the interface displays. The panel interface sets a ceiling on update rate that no amount of processing power raises. Acceleration hardware helps only for the operations a given framework actually routes through it, which is a measurement rather than a specification. Fonts and images dominate the flash budget, and coverage depth, indexed color, and external memory placement are the levers that control it. And the framework must be scheduled deliberately, in a task below the hard real-time work, with all calls into it originating from a single thread.
Two obligations remain that no framework discharges. Performance must be measured on the target under worst-case conditions, because host simulation validates behavior and says nothing about cost. And where a displayed value carries safety consequences, correctness must be demonstrated rather than assumed, through a separate rendering path, hardware composition, readback verification, freshness monitoring, and a defined failure state. Frameworks make an interface possible on small hardware; they do not make it correct, and the distinction is the engineer's responsibility.