LCD Framebuffer Memory Calculation: Include Stride, Alignment and Buffer Count

LCD framebuffer memory calculation worksheet: stored format, padded stride, buffer count, temporary surfaces, alignment and boot reservation.

LCD Framebuffer Memory Calculation: Include Stride, Alignment and Buffer Count
Posted on by CDTech James

A display that runs out of memory at the first full-screen animation usually passed a calculation that used only width, height and colour depth. The missing terms are the stored format, the padded stride, the second buffer and the temporary surface used for rotation or blending. This guide builds an LCD framebuffer memory calculation that can be checked against the linker map and reproduced by another engineer.

Which inputs belong in an LCD framebuffer memory calculation?

Width, height, storage depth, stride and buffer count.

Start from stored bytes per pixel, padded stride, buffer count and temporary surfaces, then add alignment and a safety margin.

The calculation begins with the visible geometry, but it must use the storage format rather than the panel’s colour depth. A layer can be stored as ARGB8888 for alpha or for graphics-pipeline convenience while the panel receives RGB565. The allocation is based on what is stored, not on what is displayed.

The second input is the stride: the number of bytes between the start of one row and the start of the next. It is often larger than the visible width because the row is padded to a bus, cache-line or DMA boundary. The third input is the number of complete surfaces: one for a single buffer, two for double buffering, three for triple buffering. The fourth is any temporary surface used for rotation, scaling or blending.

The panel’s resolution is only the starting point; the memory controller may require a minimum burst length or a row multiple that changes the stride. Add alignment for each allocation and a margin for growth. A worksheet that lists only the first three terms will under-estimate the memory and leave no room for the surfaces that appear later in the design.

How does storage format differ from visible color depth?

Storage format can be wider than the visible colour depth.

A layer may be stored as ARGB8888 while the panel displays RGB565, so the allocation must use the storage format, not the panel depth.

The panel’s input format describes what the display receives. The framebuffer format describes what the graphics pipeline stores. They are often different. A UI may use alpha blending and therefore store ARGB8888, while the display controller converts to RGB565 on the way to the panel. The memory cost is four bytes per pixel, not two.

The same distinction applies to indexed or compressed assets. A palette-based image stores one index per pixel plus a palette, but it must be expanded to a surface before the display can read it. The expanded surface is the allocation that matters for scan-out; the compressed asset belongs to a different pool.

Record the storage format and the visible format separately. A worksheet that uses the panel format for the framebuffer will under-count by a factor of two in the common ARGB8888-to-RGB565 case.

LCD module with dark front glass resting on a light surface
Module photograph from the industrial LCD display topic page. Interface and performance are not established by the image.

Why do stride and alignment increase allocation?

Stride padding and alignment add bytes beyond the image.

Rows may be padded to a bus or cache boundary and buffers aligned, so the allocation exceeds width times height times bytes per pixel.

A row of pixels is often padded so that the next row starts on a convenient boundary. A 64-byte cache line, a 32-byte bus burst or a DMA constraint can each force padding. The padding is repeated for every row, so its cost grows with the height. A row that is a few bytes wider than the visible width can add a meaningful percentage to a tall framebuffer.

The buffer itself may also need alignment. A surface that starts in the middle of a cache line can share that line with unrelated data, which complicates cache maintenance and can cause corruption during partial updates. Aligning the start to the cache-line size avoids that problem but adds padding before the buffer.

A stride that is not a multiple of the burst length can force the controller to split a row into two transactions, which costs bandwidth as well as memory. The ST AN4839 cache note explains line alignment. The worksheet should show the visible row bytes, the padded stride and the padding per row. A calculation that uses the visible width will not match the linker map and will be hard to debug when the allocation fails.

When does double buffering require another complete surface?

Double buffering needs a second complete surface.

If the display reads one buffer while the renderer writes the other, both must be full-size; a partial buffer works only for limited updates.

In a double-buffered design, one surface is being scanned or transmitted while the other is being rendered. The two must be independent, which means each must be large enough to hold the full frame. A partial second buffer can work for a small region, but only if the update policy never needs a full-frame render or a full-frame transition.

Triple buffering adds a third surface so the renderer can start the next frame while the previous one is still queued. It reduces stalls but increases memory. The decision should be based on the latency requirement and the available memory, not on a default.

If the application can tolerate a short blank during a transition, a single buffer with an explicit pause may be cheaper than a second full surface. Record the buffer count and the policy that uses it. A design that allocates two buffers but swaps them mid-scan may still tear; the memory alone does not guarantee correct behaviour.

What additional surfaces come from rotation and blending?

Rotation and blending can add temporary surfaces.

A 90-degree software rotation may need a destination surface, and blending may need scratch memory, so include those temporary allocations.

A hardware rotation may read the framebuffer with a different stride and avoid an extra surface. A software rotation usually needs a destination buffer because the rotated pixels are written in a different order. The destination is often the same size as the source, which doubles the memory for that operation.

Blending can also need a scratch surface, especially when several layers are composited before display. A temporary surface may be smaller than the full frame, but it still has to be allocated and aligned. If the operation is performed every frame, the buffer may be held permanently.

A rotation that is only used for a setup screen can allocate its destination at boot and release it when the screen closes; a rotation used on every frame cannot. The LVGL rotation documentation covers the buffer consequences. List the temporary surfaces with their lifetime: per frame, per transition or only during initialization. A temporary that is allocated once and never freed is a permanent cost, even if the code calls it temporary.

LCD module with exposed flexible printed-circuit tails below the screen
Module photograph from the custom LCD display topic page. The picture shows the module only; its interface and performance are not established here.

How should memory reservation be checked at boot?

Check the reservation against the linker map at boot.

Boot code should verify that the framebuffer region exists, is aligned and does not overlap the heap or stack, and should report the result.

A linker script can reserve a region for the framebuffer, but the reservation is only a promise. At boot, the code should confirm that the region is large enough, correctly aligned and does not overlap the heap, stack or other reserved areas. It should also confirm that the display controller’s address registers point to the intended base.

The check should also confirm that the display controller’s pitch register matches the calculated stride, because a mismatch produces a sheared image rather than a clean failure. A boot check can compare the configured region size with the calculated requirement and report a mismatch before the display is enabled. That converts a later corruption into an early, understandable error. The check should be part of the production build, not a debug-only assertion.

The ST AN4861 LTDC application note documents framebuffer addressing and pixel formats for specific STM32 families; the linker and memory-map details remain product-specific.

Which allocation failures deserve a graceful fallback?

Fail gracefully by reducing buffers or colour depth.

If allocation fails, drop to single buffering, a smaller format or a reduced animation set; a silent null pointer is not a fallback.

Memory can be exhausted by a configuration change, a larger font, a new animation or a firmware update that adds a surface. The product should detect the failure and choose a defined fallback: reduce the buffer count, use a smaller storage format, disable an optional animation or show a simplified screen.

The fallback should be visible in the diagnostics and recorded in the release notes. A product that silently drops to a lower quality without telling anyone is hard to support, and a product that dereferences a null pointer is worse.

Test the fallback by deliberately reducing the available memory and confirming that the product still boots and displays a usable screen. A fallback that has never been exercised is not a fallback.

What memory worksheet should accompany the design review?

The worksheet shows every term and its alignment.

A reviewable worksheet lists width, height, storage format, stride, buffers, temporary surfaces, alignment and total, with the linker region and free memory.

The worksheet should be a table, not a single number. Each surface gets a row with its width, height, storage format, stride, alignment and size. The total is the sum plus the temporary surfaces and a margin. The linker region and the measured free memory are recorded next to the total.

Keep the worksheet under version control with the linker script, so a change in either is reviewed together. If the total is close to the region, the design has no headroom for a new surface. That is a design risk, even if the current build fits. Record the margin and the assumptions that could change it.

The table below is a template for the worksheet. It is not a set of limits; the values come from the display, the graphics pipeline and the linker map.

Framebuffer memory worksheet
Workload or state Pixel or buffer format Measured traffic or energy Constraint Evidence source
Primary framebuffer ARGB8888 Stride times height times buffers Cache-line alignment Linker map
Secondary buffer ARGB8888 Full surface Independent scan and render Allocation record
Rotation destination RGB565 Full or partial surface Software rotation only Rotation test
Blend scratch RGB565 Region-sized surface Per-frame operation Graphics trace
Decoded asset RGB565 or ARGB8888 Decode destination Asset lifetime Memory profile

The LVGL 9.2 display porting guide documents draw buffers and flush behaviour for that release, the LVGL display module documentation covers the display object, and the allocation still depends on the product’s storage formats and buffer policy. The display and touch solutions centre shows how the display, touch and bonding decisions connect to the module design.

FAQ

Can the visible resolution predict allocation without knowing stride?

No. The visible resolution gives the pixel count, but the allocation depends on the stored bytes per pixel, the padded stride and the number of buffers. A row padded to a cache or bus boundary, or a surface stored with alpha, can make the real allocation much larger than width times height suggests.

Does triple buffering always require three equal-size surfaces?

Not always. Triple buffering normally uses three full-size surfaces so the renderer, the display and the next frame can each have one. Some drivers use a queue of smaller or differently formatted surfaces, but that limits which frames can be displayed. The allocation must follow the actual buffer policy, not the label.

Should compressed assets be counted as framebuffer memory?

They belong in the graphics budget, but not in the scan-out allocation. A compressed logo or image must be decoded into a surface before the display can read it, so count the compressed file, the decode buffer and the destination surface separately. Mixing them into one number hides which pool is under pressure.

If a display runs out of memory after adding a buffer or a rotation, send the surface list, formats and linker map to the CDTech engineering team for a memory-budget review.

Request a framebuffer memory review

Copyright Shenzhen CDTech Electronics Co., Ltd. All Rights Reserved