パーシャル・フレームバッファによるメモリ使用量の軽減
This section explains, by exemplifying with a clock application, how to configure and use Partial Frame Buffers with a display with GRAM, to lower memory requirements at the expense of some performance.
STM32L4R9Discovery評価キット上で実行されるアプリケーションに関するビデオを以下からご覧になれます。
フルサイズのフレームバッファ・メモリ
通常、フレームバッファは、ディスプレイで使用可能なすべてのピクセルを保持するのに十分なメモリを備えた大規模なメモリ・アレイになります。 解像度480 x 272の24bitディスプレイを使用している場合、フルサイズのフレームバッファは480 x 272 x 3バイト = 391,680バイトのデータを保持しています。
アプリケーションによっては、2つ(ダブル・バッファリング)または3つのフレームバッファを使用することもあります。 この場合の必要なメモリ容量の合計は、783,360バイトまたは1,175,040バイトになります。
TouchGFXは、UIのどの部分を描画するときにもピクセルのデータをフレームバッファに書き込みます。すべての描画処理が完了した後、フレームバッファがディスプレイに転送されます。 通常、UIの一部のみが更新された場合でも、フレームバッファ全体がディスプレイに転送されます。 一般的に、多くの小さいブロックに分けて更新された後、フレームバッファは転送されます。
更新1, 更新2, 更新3, ..., 更新Nのように更新した後、ディスプレイへ転送
一部のケースでは、特に外部RAMを使用しない低コストのソリューションでは、フレームバッファとアプリケーションが必要とするメモリ容量が、内部RAMに収まるようにフレームバッファのサイズを十分小さくする必要があります。 このような場合に、パーシャル・フレームバッファが役立ちます。
パーシャル・フレームバッファ・メモリ
パーシャル・フレームバッファを使用すると、フルサイズよりも小さいフレームバッファ上で、TouchGFXアプリケーションを実行可能です。 フレームバッファの数とサイズは設定可能です。 この手法により、アプリケーションのメモリ要件をかなりの量削減できますが、いくつか制限事項も発生します。
- パーシャル・フレームバッファはメモリが内蔵されたディスプレイでのみ動作します。 これは通常はDSIディスプレイか、パラレル・バス接続(DBIタイプA/B、8080/6800)またはSPIバス接続を備えたディスプレイになります。
- 複雑なアプリケーションではティアリングの可能性があります。
フレームバッファを使用してディスプレイ上のすべてのピクセルを表すのとは異なり、パーシャル・フレームバッファは通常は小さな部分を対象とします。 この記事で使用する時計のアプリケーションの例では、それぞれ11,700バイトの3つのフレームバッファが使用されています。 この結果、フレームバッファに必要なメモリ量は35,100バイトになります。
アプリケーションでUIの一部を更新する必要がある場合、必ずTouchGFXは設定済みのパーシャル・フレームバッファのいずれかを選択し、そのパーシャル・フレームバッファ内で描画処理を完了させ、その部分をディスプレイに転送します。 レンダリングの必要があるUIのすべてのエリアに対してこの操作が繰り返されます。これにより、描画データの更新と転送の式は以下のように変更されます。
更新1, 転送1, 更新2, 転送2, 更新3, 転送3, ..., 更新N, 転送N
場合によっては、1つのパーシャル・フレームバッファの転送を、次のバッファの更新中に実行することもできます。
ディスプレイのティアリング
フルサイズのフレームバッファの使用とは対照的に、TouchGFXでパーシャル・フレームバッファを使用するときには、UIの各部分が更新後すぐに転送されます。 ディスプレイの画面上には、受信した更新が最大でも16ms後(60fpsのディスプレイの場合)に表示されます。ディスプレイは定期的にリフレッシュする必要があるからです。 このため、すべての更新が転送される前に、ディスプレイへの最初の更新が表示され、ユーザが気づく可能性があります。
描画処理と転送のシーケンス全体が完了するまでに時間がかかる(> 16ms)場合、ユーザには前のフレームと新しい更新の一部が混在して表示される可能性が高くなります。 これはディスプレイのティアリングと呼ばれる現象で、望ましいものではありません。 このため、パーシャル・フレームバッファは、レンダリングに時間のかかる複雑なアニメーションを使用するアプリケーションには適さないといえます。
ディスプレイの更新例
アプリケーション内でパーシャル・フレームバッファを設定する方法について説明する前に、秒を表す円弧が移動するデジタル時計の具体例を見てみたいと思います。 この緑色の円弧は毎秒6度ずつ移動しており、1分で1周します。 下の画像に示すように、UIは次の4つのウィジェットから構築されています。
デジタル時計と円弧を更新するコードを次に示します。
MainView.cpp
void MainView::handleTickEvent()
{
ticks++;
if (ticks == 10)
{
ticks = 0;
secs += 1;
if (secs == 60) //increment minutes
{
secs = 0;
min += 1;
if (min == 60) //increment hours
{
min = 0;
hour += 1;
if (hour == 24)
{
hour = 0;
}
}
//Only update digital clock when minutes or hours change
digitalClock.setTime24Hour(hour, min, secs);
}
//Always update seconds
circleSeconds.updateArc(secs*6 - 20, secs*6);
}
}
以下の画像は、円弧が一番上に到達し、デジタル時計が更新された時点で、最初の数秒間に更新される領域を示しています(灰色の長方形)。 最初の2つのフレームでは、秒のみが変化しています(58秒と59秒)。 3つ目のフレームでは60秒に到達し、時間と分のテキストが更新されています。
上の3つ目の画像で更新された長方形は、154x60ピクセル、20x12ピクセル、33x8ピクセルです。 標準のフレームバッファを使用する場合、この3つの長方形はフレームバッファ全体に描画(以前のピクセルに上書き)され、後からディスプレイに転送されることになります。 パーシャル・フレームバッファを使用すると、この3つの長方形はそれぞれ独自の小さいフレームバッファに描画され、更新されると即座にディスプレイに転送され表示されることになります。
パーシャル・フレームバッファの設定
The following steps are required for TouchGFX to use partial frame buffers:
- メモリ・バッファを含むフレームバッファ・アロケータ・オブジェクトを作成する
- そのアロケータを使用するためのTouchGFX HALクラスを設定する
- バッファをディスプレイに転送するためのコードを作成する
ステップ1と2は、TouchGFX GeneratorによってSTM32CubeMXを介して自動生成されますが、ステップ3はピクセルをディスプレイに転送するための独自のドライバが必要です。
Further reading
An example configuration with 3 partial framebuffer block of size 1920bytes used to draw the updates areas from the above section is shown below.
まずは、小さい円の更新を描画する(上の2つ目の画像)(24Bppを想定)ために割り当てられた2つのフレームバッファの位置とサイズを確認してみましょう。
長方形 | x | y | 幅 | 高さ | ピクセル |
---|---|---|---|---|---|
長方形1 | 112 | 56 | 22 | 14 | 308ピクセル = 924バイト |
長方形2 | 153 | 42 | 29 | 11 | 319ピクセル = 957バイト |
どちらの長方形も非常に小さいので、フレームバッファ・アロケータによって割り当てられたブロックに収まります。
上の3つ目の画像では、3つの長方形が更新されています。円への更新は少なく、大きな長方形がテキストを覆っています。
長方形 | x | y | 幅 | 高さ | ピクセル |
---|---|---|---|---|---|
長方形1 | 126 | 51 | 20 | 12 | 240ピクセル = 720バイト |
長方形2 | 165 | 42 | 33 | 8 | 264ピクセル = 792バイト |
長方形3 | 118 | 165 | 154 | 60 | 9,240ピクセル = 27,720バイト |
繰り返しますが、長方形1と2は非常に小さいので、フレームバッファ・アロケータによって割り当てられたブロックに収まります。ただし、フレームバッファ3は大きすぎます。 この長方形3は大きすぎるので、それぞれがフレームバッファ(11,700バイト)に収まる複数の長方形に分割されます。
次に、3つの長方形を更新しますが、アロケータには2つのブロックしかありません。 こうした状況では、TouchGFXは最初のブロックが転送されるのを待ってから、ブロックを再利用します。
画面へのフレームバッファの転送
The implementation of the code to transfer partial framebuffer blocks to the display depends on the display interface use. For examples on how this can be done, see the following articles:
まとめ
この記事では、パーシャル・フレームバッファ戦略によって、フレームバッファ・メモリが内蔵されたディスプレイを実装したプラットフォームのメモリ要件を、軽減する方法について説明しました。