フレームバッファ
フレームバッファは1まとまりのメモリで、ディスプレイに次に表示する画像を格納するためにグラフィック・エンジンによって更新されます。
フレームバッファは、所定のサイズの連続したRAMの領域です。
フレームバッファには関連付けられた幅と高さがあります。 このため、通常フレームバッファは、XY座標によってインデックス付け可能な2次元でアクセスするメモリであると考えられます。
フレームバッファには関連付けられたカラーフォーマットがあります。 フレームバッファの各エントリは、このカラーフォーマットの色になります。 フレームバッファ内のこうしたエントリのことを、ピクセルと呼びます。
フレームバッファ内の(X、Y)位置のピクセルの色を更新するには、フレームバッファ内のピクセルのメモリ・アドレスを計算し、そこに保存されている色を更新します。
uint32_t pixelAddress = x + y * WIDTH;
framebuffer[ pixelAddress ] = newColor;
同様に、フレームバッファ内のピクセルの色を取得し、これを計算で使用できます。 たとえば、フレームバッファ内のピクセルの色を暗くする場合は、次のようになります(darken
関数が使用可能だとします)。
uint32_t pixelAddress = x + y * WIDTH;
framebuffer[ pixelAddress ] = darken( framebuffer[ pixelAddress ] );
多くの場合、フレームバッファ・メモリは、上記のようにピクセルごとに読み書きされるのではなく、基盤となるシステムのハードウェア機能(Chrom-ART DMAなど)を利用することで書き込まれます。
色
TouchGFXでは、フレームバッファのピクセルのカラーフォーマットは次のいずれかになります。
- グレースケール: 1、2、または4 bppのグレースケール
- ハイカラーまたはトゥルーカラー: 16、24、または32 bppカラー
使用するbppの値が大きいほど、フレームバッファで表すことのできる色が明瞭になります。さらに、使用するbppの値が大きいほど、フレームバッファに必要なメモリサイズも大きくなります。
ディスプレイ
フレームバッファのコンテンツは最終的には物理ディスプレイに転送され、そこで表示されます。 このため、通常はフレームバッファとディスプレイのピクセルの幅と高さは同じにします。
Further reading
フレームバッファの場所
マイクロコントローラ・ベースのグラフィック・システムを非常に簡略化した図を、次に示します。
フレームバッファはマイクロコントローラ内部、または外部RAMに配置できます。
配置可能な場所それぞれに、利点と欠点があります。
内部RAM
フレームバッファをマイクロコントローラ内部のRAMに配置すると、フレームバッファの読み書きアクセスが最大限に高速化されます。 つまり、TouchGFXアプリケーションが可能な限りスムーズに実行されます。 その反面、内部RAMは非常に少量のリソースで、システムの多くの部分によって使用されるため、フレームバッファがこの大部分を占有することは現実的ではないと考えられます。
フレームバッファを内部RAMに配置するとことが可能であれば、追加のRAMが必要なくなるので、システム全体のコストを削減することができます。
外部RAM
システムに外部RAMがある場合、フレームバッファを内部RAMの代わりにこの外部RAMに配置できます。 一般的に、外部RAMに対する読み書きアクセスは内部RAMより低速ですが、外部RAMの容量の方が通常は非常に大きくなります。 このため、場合によってはこれが唯一の解決策になります。
マイクロコントローラには、外部RAMへのアクセスを高速化させる機能(キャッシュなど)が備わっていることがあります。 詳細については、「マイクロコントローラ」のセクションを参照してください。
Display with GRAM
Depending on the type of display in the system there might be memory embedded on the display (often called GRAM). このメモリには、ディスプレイの「物理的な」ピクセルの内容が保持されます。 ディスプレイにこのピクセル・メモリがあると、マイクロコントローラがアイドル状態でもディスプレイが動作を続けることができます。
TouchGFXのフレームバッファをディスプレイ内のRAMに配置することは不可能です。ディスプレイのメモリはメモリ・マップドではなく、ランダムなピクセルの読み書きに適するようにできていないからです。 代わりに、TouchGFXはフレームバッファを内部または外部RAMに配置し、これを適切なタイミングでディスプレイのRAMに転送します。
メモリ使用量
フレームバッファの色の量やピクセル数によって、フレームバッファが必要とするメモリサイズが決まります。
一般的に、フレームバッファで使用されるメモリの量は、幅x高さx色深度(ビット)/ 8 バイトになります。
解像度(ピクセル) | 色(bpp) | 計算 | メモリ使用量(バイト) |
---|---|---|---|
800x480 | 16 bpp | 800 x 480 x 16 / 8 | 768,000 B |
480x272 | 24 bpp | 480 x 272 x 24 / 8 | 391,680 B |
100x100 | 8 bpp | 100 x 100 x 8 / 8 | 10,000 B |
複数のフレームバッファを持つと、それに応じてメモリ使用量も大きくなります。 たとえば、2つのフレームバッファを使用するダブル・バッファリング方式では、メモリ使用量は2倍になります。
1つ未満のフレームバッファを持つ場合、アプリケーションによってメモリの量が明示的に割り当てられ、制御されます。 このためメモリ使用量は完全にカスタマイズ可能になりますが、使用量が少なすぎるとグラフィックス全体のパフォーマンスに悪影響を及ぼすので注意してください。
Framebuffer Strategies
Framebuffer strategy is a core feature, that enables you to make the most optimal match between TouchGFX rendering and your existing hardware (MCU, RAM and Display). In case you are selecting new hardware, it is recommended to get familiar with the available framebuffer strategies in relation to your use case. The right choice can help optimize your hardware cost, i.e. assist you in selecting the minimum required hardware in terms of the amount of RAM for framebuffer(s) and the suitable display interface.
A framebuffer strategy defines how much RAM is used for framebuffers and controls how TouchGFX renders to the RAM. The strategy must match the available RAM and the type of display in the system. TouchGFX offers three different strategies, applicable on display systems with and without GRAM. Below is an overview of the strategies, highlighting their advantages and drawbacks in relation to display systems.
Displays without GRAM
Strategy | Advantages | Drawbacks | Use Cases |
---|---|---|---|
Double | No risk of tearing, optimal time for rendering | RAM for 2 framebuffers | High performance UIs |
Single | Only RAM for 1 framebuffer | Risk of tearing, suboptimal time for rendering | High - Moderate performance UIs |
Partial | Only RAM for less than a framebuffer | Higher risk of tearing, higher CPU load | Moderate - Low performance UIs |
Displays with GRAM
Strategy | Advantages | Drawbacks | Use Cases |
---|---|---|---|
Double | No risk of tearing, optimal time for rendering | RAM for 2 framebuffers | High performance UIs |
Single | Only RAM for 1 framebuffer, no risk of tearing | Suboptimal time for rendering | High - Moderate performance UIs |
Partial | Only RAM for less than a framebuffer | Risk of tearing | Moderate - Low performance UIs |
Tearing
Tearing is a visual artifact on the display where pixel data from two frames are shown in one screen draw, e.g. the screen has half of an old frame and half of a current one, with a clean horizontal split across (the tear). The location of the tear varies according to timing, it usually jumps all over the place, which can be distracting.
UI Performance
In the general Performance article, you will be introduced to aspects of UI performance, which covers how the individual UI components and there structure impacts performance. In the context of framebuffer strategy we think of:
- High performance, as UIs that uses multiple complex UI components/animations, e.g. Texture Mappers, SVGs, screen transitions
- Moderate performance, as UIs that uses few complex UI components/animations
- Low performance, as UIs that uses no complex UI components/animations
Note
Glossary
The following terms are used to describe the different framebuffer strategies.
- Display Controller (DC) - The hardware that reads pixels from memory. Is continuously reading the memory containing pixels. Sometimes referred to as the scanline.
- Display Transfer (DT) - The hardware responsible of transferring pixels from framebuffer memory to GRAM. Is only initiated by the MCU when required. Sometimes referred to as the transferline.
- Framebuffer Write (W) - The rendering of pixels to the framebuffer.
Displays without GRAM
The following demonstrates the working concept of framebuffer strategies on displays without GRAM. Common for all strategies are the use of a Display Controller which continuously reads pixel data directly from a framebuffer.
Double Buffering Strategy
Having two framebuffers allows rendering of the next frame into one framebuffer while the Display Controller scans the other framebuffer. Render time of the next frame is unrestricted by the Display Controller. Swapping framebuffers is blocked until the next frame is ready, meaning no risk of tearing because the Display Controller just scans the current framebuffer once again. The framebuffers are swapped after the Display Controller has scanned the entire framebuffer and the rendering is complete.
Single Buffering Strategy
Having one framebuffer allows rendering of the next frame into the same framebuffer as the Display Controller scans from. Render time of the next frame is restricted by the Display Controller. The Display Controller scans continuously, so if writing to the framebuffer takes too long, the Display Controller will collide (catch up) with the writing area and tearing will occur. This is caused by rendering complex UI components.
Partial Buffering Strategy
A single partial framebuffer block is used to emulate a full size framebuffer through a Memory Management Unit (MMU). Therefore this strategy is also known as Emulated Framebuffer Strategy.
The partial block acts as a sliding window moving down through the emulated framebuffer, with the phase and speed of the Display Controller.
Having a partial framebuffer block only allows rendering of a small portion of the next frame, because the block is reused multiple times to render the current frame. The reuse of the partial block results in a large number of small rendering operations, which result in higher CPU load. Render time of the next frame is restricted by the Display Controller and the partial block size. The Display Controller scans continuously, so if writing to the partial framebuffer block takes too long for any given region of the emulated framebuffer, the Display Controller will collide (catch up) with the writing area and tearing will occur. This is caused by rendering complex UI components. Compared to the Single Buffering Strategy the risk of tearing is higher because the working area of the Display Controller and framebuffer rendering is much smaller.
Note
Displays with GRAM
The following demonstrates the working concept of framebuffer strategies on GRAM displays. Common for all strategies are the use of a Display Interface used for transferring pixel data from a framebuffer to the GRAM on the display.
Double Buffering Strategy
Having two framebuffers allows rendering of the next frame into one framebuffer while the pixels are transferred to GRAM from the other. Render time of the next frame is unrestricted by the Display Transfer. Display transfers are only initiated when the next frame is ready, meaning no risk of tearing because the Display Controller just scans what is already in GRAM. The framebuffers are swapped after the display transfer and the rendering is complete.
Single Buffering Strategy
Having one framebuffer allows rendering of the next frame into the same framebuffer where pixels are transferred to GRAM. Render time of the next frame is restricted by the Display Transfer bandwidth. Display transfers are only initiated when the next frame is ready, meaning no risk of tearing because the Display Controller just scans what is already in GRAM. Rendering of the next frame cannot complete before the corresponding area to update has been transferred to GRAM.
Partial Buffering Strategy
One or more partial framebuffer blocks are used to emulate a full size framebuffer.
The partial blocks are reused to render all parts of the current frame that needs to be updated. When a block is rendered it can be transferred to GRAM and used for subsequent rendering.
To minimize the risk of tearing we strive to have the largest margin between GRAM being updated by the Display Transfer and the Display Controller scanline. This is done be having the transferline behind the scanline, which means that we can only render the current frame and not begin rendering the next frame. Render time of the current frame depends on the number of partial blocks defined and the time it takes to transfer each block. This means that we are allowed to render a block that is ahead of the Display Controller scanline if a block is available. If rendering and transferring of all the dirty areas of the current frame takes longer than the Display Controller its scanline can wrap around and catch the transferline, resulting in tearing. This is caused by rendering complex UI components and/or transferring too many pixels.
Getting Started with Framebuffer Strategies
In the following section we will show common hardware setups and point to scenarios on how to use framebuffer strategies on various hardware setups.
Further reading
Displays with GRAM
This display type has a dedicated RAM buffer with the same size as the display, i.e. a full size framebuffer.
The interfaces for this type of display are:
- FMC
- SPI
- DSI (Command Mode)
Scenarios demonstrating the use of these interfaces can be found here:
Displays without GRAM
This display type doesn't have a dedicated RAM buffer.
The interfaces for this type of display are:
- LTDC
- DSI (Video Mode)
Scenarios demonstrating the use of these interfaces can be found here: