Depending on MCU, display type (TFT Controller / 8080 based), display resolution and UI complexity the choice of using either one or two frame buffers can have a great impact on both memory usage and performance.
On most platforms double buffering requires external memory (e.g. SDRAM), because the MCU does not have enough SRAM to hold two frame buffers (depending on display resolution). This article outlines in which cases single buffering is sufficient.
TFT Controller based systems
This sections deals with TFT controller based system where the display is connected using parallel RGB lines and VSYNC/HSYNC/DE control signals.
Traditionally, double buffering is used on these systems to avoid the risk of screen tearing. With double buffering, TouchGFX will render the next frame into one frame buffer, whereas the TFT controller accesses the other frame buffer. When the next frame has been rendered, the buffers are swapped. With this approach there is never any risk of tearing regardless of how long it takes to render the next frame, since the TFT controller always has access to the latest complete frame data. The drawback is that two buffers are required, often demanding external RAM.
An optimized configuration exists for single buffering which tracks the current progress of the TFT controller and allows TouchGFX to gradually render the portions of the screen that are “safe” to modify in memory. This greatly improves frame render time without screen tearing compared to more naive implementations, thereby making single buffering possible on more platforms. Tearing can still occur if the UI takes a long time to render (e.g. makes extensive use of texture mapping or alpha blending). The following rules apply generally, assuming a 60Hz display refresh rate:
- Render time less than 16.67ms: guaranteed no tearing, TouchGFX runs at 60FPS
- Render time 17-32ms: tearing unlikely, TouchGFX runs at 30FPS
- Render time 33ms+: tearing will occur, TouchGFX runs at 20FPS
Note that render time of an application can be measured via the GPIO::RENDER_TIME signal.
(note: ref performance article)
It can be difficult to predict beforehand whether your UI will have rendering times that make single buffering impossible. As a guideline we have verified that the following applications run without tearing in single buffer mode, and thereby require no external memory whatsoever:
- The “touchgfx_demo2015_480x272_8MB” on the STM32F746-G Discovery board
- The “touchgfx_demo2014_240x320” on the STM32F429I Discovery board
For application templates in the TouchGFX designer the method touchgfx_init() in BoardConfiguration.cpp configures buffering strategies. For some application templates the following symbol can be used to control the configuration:
The following sections programatically control the buffering strategies:
//setup for single buffering hal.setFrameBufferStartAddress((uint16_t*)frameBuf0, 16, false, false); // The optimized strategy for single buffering requires the presence of a // task delay function. hal.registerTaskDelayFunction(&OSWrappers::taskDelay); // Enable single buffer strategy. hal.setFrameRefreshStrategy(HAL::REFRESH_STRATEGY_OPTIM_SINGLE_BUFFER_TFT_CTRL); // Allow immediate drawing hal.lockDMAToFrontPorch(false);
hal.setFrameBufferStartAddress((uint16_t*)frameBuf0); // Allow immediate drawing hal.lockDMAToFrontPorch(false);
8080/SPI based systems
On these systems, the display itself has an integrated frame buffer. Therefore a long frame rendering time does not cause tearing even in a single frame buffer system. There is no gain in using double buffering here. See this article on how to configure TouchGFX on 8080/SPI based systems.