Framebuffer
A framebuffer is a piece of memory that is updated by the graphics engine to contain the next image to be shown on the display.
The framebuffer is a contiguous part of RAM of a given size.
A framebuffer has an associated width and height. Therefore we typically think of a framebuffer as being a two dimensional part of memory, indexable by x, y coordinates.
A framebuffer has an associated color format. Each entry in the framebuffer will be a color in this color format. We will refer to each such entry in the framebuffer as a pixel.
We can update the color of a pixel at position x,y in the framebuffer by calculating the memory address of the pixel within the framebuffer and updating the stored color.
uint32_t pixelAddress = x + y * WIDTH;
framebuffer[ pixelAddress ] = newColor;
Similarly we can obtain the color of a pixel in the framebuffer and use this in calculations. For instance darkening the color
of a pixel in the framebuffer (assuming we have a darken
function available).
uint32_t pixelAddress = x + y * WIDTH;
framebuffer[ pixelAddress ] = darken( framebuffer[ pixelAddress ] );
Often the framebuffer memory is not written and read pixel by pixel as above, but by utilizing the underlying hardware capabilities of the system, e.g. the Chrom-ART DMA.
Colors
In TouchGFX the pixel color format of a framebuffer can be either:
- Grayscale 1, 2 or 4 bits per pixel (bpp) grayscale, or
- High or true color 16, 24 or 32 bpp color
The more bits per pixels used the more distinct colors can be represented by the framebuffer, moreover the more bits per pixels used the more memory will be consumed by the framebuffer.
Display
The contents of the framebuffer is what is ultimately transferred to and seen on the physical display. Therefore it is very common to have the same pixel width and height of the framebuffer and the display.
Further reading
Location of framebuffer
One oversimplified view of a microcontroller based graphics system is here.
A framebuffer can be placed either internally in the MCU or in external RAM.
Each possible location has potential benefits and drawbacks.
Internal RAM
Placing the framebuffer in RAM internal to the MCU makes the read and write access to the framebuffer as fast as possible. This means that your TouchGFX application will run as smooth as possible. Conversely, internal RAM is a very scarce resource and one that is used by many parts of a system, therefore occupying a large part of this with a framebuffer might be infeasible.
If feasible, having a framebuffer in internal RAM, could reduce the overall cost of the system as no additional RAM is needed.
External RAM
If the system has external RAM, placing the framebuffer here is an alternative to placing it in internal RAM. The read and write access to external RAM will typically be slower than to the internal RAM, but the amount of external RAM will typically be much larger. Therefore this is sometimes the only viable solution.
The MCU might have capabilities, like caching, that makes access to external RAM faster. See the section on MCU for details.
Display with embedded RAM
Depending on the type of display in the system there might be memory embedded on the display. This memory holds the contents of the "physical" pixels of the display. Having this pixel memory in the display implies that the MCU can be idle while the display is still alive.
Placing a TouchGFX framebuffer in the RAM of the display is not possible, as the memory of the display is not memory mapped and is not intended nor suitable for random pixel reads or writes. Instead TouchGFX places the framebuffer in internal or external RAM and transfers this to the display RAM when appropriate.
Amount of framebuffers
TouchGFX can use one, multiple, or less than one framebuffer in the application. The amount of framebuffers might impact the visual appearance, performance and memory consumption of the application.
One framebuffer
One framebuffer is enough to hold precisely all pixels that are to be transferred to the display. One framebuffer (at least) is needed when the display has no display RAM on board. In this case one framebuffer is ideal when the complexity of the displayed graphics does not induce any visual artifacts.
More than one framebuffer
In TouchGFX, having multiple framebuffers means having two framebuffers. One framebuffer is used for writing the next resulting image, the other framebuffer is used for transferring to the display. This implies that no visual artifacts, e.g. tearing, will appear.
Less than one framebuffer
Having less than one framebuffer in general implies that
- less memory is consumed
- more drawing operations will be performed
- more transfers to display needed
In TouchGFX less than one framebuffer is denoted a partial framebuffer. The partial framebuffer scheme is available only for displays with display RAM.
Memory consumption
The amount of colors and the number of pixels in the framebuffer determines the memory consumed by the framebuffer.
In general the amount of memory used by a framebuffer is width * height * color depth in bits / 8 bytes.
Resolution (pixels) | Colors (bpp) | Calculation | Memory consumed (byte) |
---|---|---|---|
800x480 | 16 bpp | 800 * 480 * 16 / 8 | 768,000 B |
480x272 | 24 bpp | 480 * 272 * 24 / 8 | 391,680 B |
100x100 | 8 bpp | 100 * 100 * 8 / 8 | 10,000 B |
When having more than one framebuffer the amount of memory consumed will be correspondingly larger. For example when having a double buffering scheme, using two framebuffers, will consume twice the amount of memory.
When having less than one framebuffer the amount of memory is explicitly allocated and controlled by the application. The memory consumption is therefore completely customizable, but be warned that using too little will harm the overall graphics performance.