このページでは

C

部分フレームバッファ

概要

通常、フレームバッファはディスプレイに表示されるすべてのピクセルを保持する。レイヤーをサポートするプラットフォームでは、アプリケーションはディスプレイのサイズより小さい複数のレイヤーを含むことができます。

ディスプレイ用に独立したメモリを提供するプラットフォームでは、部分フレームバッファを使用して、再描画が必要なピクセル(ダーティレクタングルと呼ばれる)だけを格納することができます。

パーシャルフレームバッファ戦略は、再描画領域ごとにダーティレクタングルを提供し、ディスプレイに転送する必要のあるデータ量を最小限に抑えます。

単一または複数のパーシャルバッファを使用できます。複数のパーシャルバッファは、前面のパーシャルフレームバッファがフラッシュされている間に、背面のパーシャルフレームバッファでレンダリングすることを可能にします。

あるいは、部分バッファリングは、独立したディスプレイメモリを持たず、単一のフルフレームバッファを使用するプラットフォームで、レンダリングアーティファクトを低減するために使用できます。部分的にレンダリングされたコンテンツは、まず部分バッファでレンダリングし、その後、完全にレンダリングされたコンテンツをフルディスプレイフレームバッファにコピーすることで削減できます。ただし、この場合、部分バッファリングを使用すると、部分フレームバッファに完全に収まらない要素を移動する際にティアリング効果が発生する可能性があります。

メモリ使用量

部分バッファリングは、シングルバッファリングやダブルバッファリンググラフィックスに比べて、メモリ使用量を大幅に削減できます。

部分フレームバッファの最小ピクセル数はレイヤーの幅です。高いピクセルカウントを使用すると、レンダリングのオーバーヘッドが減少しますが、メモリ要件が増加します。

部分フレームバッファの最適サイズはプラットフォームに依存します。まずはフル解像度の⅛サイズから始め、徐々にニーズに合わせてサイズを調整することができます。

部分フレームバッファに必要なメモリは以下のように表すことができます:

Memory usage in bytes = width x height x bytes per pixel x number of buffers

以下は、解像度と部分フレームバッファ戦略の組み合わせのいくつかの例に対するメモリ使用要件です:

レイヤーの解像度(幅×高さ)色の深さフレームバッファリング戦略メモリ使用量
320x24016 bppダブルバッファリング300 KB
320x24016bppシングルバッファリング150 KB
320x48 (320x240/5)116bpp部分バッファリング30 KB
320x24 (320x240/10)116 bpp2つのパーシャルバッファによるパーシャルバッファリング30 KB
320x1 (320x240/240)116 bpp部分バッファリング640 B

注: 1部分フレームバッファの解像度は固定ではなく、最大pixel count of a single partial framebuffer を示す。

部分フレームバッファによるレンダリング

シングル/ダブルバッファのグラフィックスのレンダリング

Qt Quick Ultraliteコアは、視覚的な更新が必要な各エリアに対して、beginFrameendFrame を1回呼び出します。更新された領域はPlatformContext::beginFramerect で与えられます。

フレーム更新中、Qt Quick ウルトラライトコアは各レイヤーに対して beginFrameendFrame を呼び出します。ダーティエリアのフレームバッファへのレンダリングは、これらの関数呼び出しの間に行われます。

beginFrame の引数rect は更新されるダーティエリアを指定します。rect は、与えられたレイヤーのすべてのダーティエリアを合わせた外接矩形を表します。

presentFrame メソッドは各レイヤーの最後に呼び出されます。通常、この関数は新しいコンテンツをディスプレイに表示するために、前後のフレームバッファを入れ替えます。シングルバッファのグラフィックスでは、部分的にレンダリングされたUIエレメントが表示されることがあり、特に動くUIエレメントはちらつきの原因になります。

次の擬似コードは、Qt Quick Ultralite Coreによってプラットフォーム適応関数がどのように呼び出されるかを示しています。ここで、render は、フレームバッファへの新しいコンテンツのブ リットまたはブレンドによるレンダリングアクションを表します。

beginFrame(layer X, boundingRect(dirtyRects A|B|... ))
render(dirtyRect A)
...
render(dirtyRect B)
...
endFrame(layer X)

beginFrame(layer Y, ...)
...
endFrame(layer Y)

...

presentFrame(boundingRect(dirtyRects A|B|...)) // swap buffers if double buffered

部分バッファされたグラフィックスのレンダリング

パーシャルフレームバッファ戦略を使用する場合、Qt Quick Ultralite Coreは、与えられたレイヤーのすべてのダーティエリアに対してbeginFrameendFrame を呼び出します。

ピクセル単位のパーシャルフレームバッファサイズに応じて、Qt Quick Ultralite Core はダーティエリアの更新をパーシャルフレームバッファに収まる矩形 (beginFramerect 入力引数 ) に分割し、その中に描画します。

次の擬似コードはこの概念を示しています。上記と同様に、render は、部分フレームバッファへの新しいコンテンツのブレンドまたはブレンディングによるレンダリング動作を表します。

beginFrame(layer X, dirtyRect A)
render(dirtyRect A)
...
endFrame(layer X) // flush partial framebuffer to display

beginFrame(layer X, dirtyRect B)
render(dirtyRect B)
...
endFrame(layer X) // flush partial framebuffer to display

...

beginFrame(layer Y, ...)
...
endFrame(layer Y) // flush partial framebuffer to display

...

presentFrame(boundingRect(dirtyRects A|B|...))

次の例では、Qt Quick Ultralite Thermostat DemoのRoomビューの1つで、ユーザーがボタンを押してアプリケーションと対話するときに、ディスプレイメモリと部分フレームバッファのコンテンツを表示します。

次の画像は、ボタンが押される前、アプリケーションがアイドル状態のときのディスプレイメモリの内容を示しています:

ボタンが押される前、アプリケーションがアイドル状態のときにメモリの内容を表示する。

プラットフォーム適応は部分フレームバッファ戦略を使用しており、部分フレームバッファのサイズは16320 ピクセルです。 Qt Quick Ultralite CoreはpartialBufferPixelCount 関数を呼び出して、ダーティ領域に必要な最大領域を計算します。

下矢印が押されて低い温度が設定されると、再塗装イベントがトリガーされ、下のボタン領域が更新されます。照らされたボタンの合計ダーティ領域は、サイズ285x132=37620 ピクセルの矩形です。それぞれを部分フレームバッファに収めるために、3つのダーティ矩形に分割する必要があります。

以下は、ユーザーの操作に続く更新段階の説明で、ディスプレイメモリの内容と部分フレームバッファの内容の両方を示しています:

  1. 最初の更新
    • 下矢印が押された後にendFrame が呼び出されたときの部分フレームバッファの内容:

      下矢印が押された後にendFrameが呼ばれたときのフレームバッファの内容の一部。

      x: 258, y: 291, width: 285 and height: 57 (total 16245 pixels).

    • endFrame 、部分的なフレームバッファコンテンツがディスプレイにフラッシュされた後のディスプレイメモリコンテンツ:

      部分的なフレームバッファの内容がendFrameでディスプレイにフラッシュされた後、メモリの内容を表示する。

  2. 2回目の更新
    • ダーティエリアの次の部分を含む、2回目の更新中の部分的なフレームバッファの内容。

      ダーティエリアの次の部分を含むフレームバッファの部分的な内容。

      x: 258, y: 291, width: 285 and height: 57 (total 16245 pixels).

    • フラッシュ後のメモリ内容を表示:

      フラッシュ後にメモリの内容を表示する。

  3. 3回目の更新
    • ダーティエリアの3番目と最後の部分のフレームバッファの部分的な内容。

      ダーティエリアの最後の部分のフレームバッファの部分的な内容。

      x: 258, y: 405, width: 285 and height: 18 (total 5130 pixels).

    • 最後の部分がディスプレイにフラッシュされた後のディスプレイメモリの内容:

      メモリの内容を、最後の部分をディスプレイにフラッシュして表示する。

部分フレームバッファリングのサポートの実装

部分フレームバッファの追加

この例では、ディスプレイ・サイズの⅛が部分フレームバッファ・サイズとして使用される。dirtyRect 、ディスプレイ・フラッシュ用に現在のダーティな矩形を保存するために追加される。

namespace Private {

static constexpr uint16_t displayWidth = 320;
static constexpr uint16_t displayHeight = 240;
static constexpr size_t bufferPixelCount = displayWidth * displayHeight / 8;
static constexpr uint8_t bytesPerPixel = 2;
static uchar framebuffer[bufferPixelCount * bytesPerPixel];
PlatformInterface::Rect dirtyRect;

} // namespace Private

フレームバッファリングタイプの設定

使用中のフレームバッファリング戦略をQt Quick Ultralite Core に通知するために、プラットフォーム適応はPartialBufferingframebuffering type として返す必要があります。

FrameBufferingType frameBufferingType(const PlatformInterface::LayerEngine::ItemLayer *) const override
{
    return PartialBuffering;
}

部分バッファサイズ

partialBufferPixelCount のプラットフォーム適応コードは、ダーティな矩形サイズを計算するために、部分フレームバッファサイズをピクセル単位で返すべきです。

size_t partialBufferPixelCount(const PlatformInterface::LayerEngine::ItemLayer *) const override
{
    return Private::bufferPixelCount;
}

DrawingDeviceのサイズと1行あたりのバイト数の設定

beginFramerect は、描画されるダーティ領域を指定します。PlatformInterface::DrawingDeviceサイズと1行あたりのバイト数は、rect の幅と高さに基づいて設定される。

プラットフォーム・アダプテーションは、endFrame で後で使用するために、この矩形を保存する必要があります。

PlatformInterface::DrawingDevice *beginFrame(const PlatformInterface::LayerEngine::ItemLayer *,
                                             const PlatformInterface::Rect &rect,
                                             int refreshInterval) override
{
    static PlatformInterface::DrawingEngine drawingEngine;

    static PlatformInterface::DrawingDevice buffer = {Qul::PixelFormat_RGB16,
                                                      PlatformInterface::Size(Private::displayWidth,
                                                                              Private::displayHeight),
                                                      Private::framebuffer,
                                                      Private::displayWidth * Private::bytesPerPixel,
                                                      &drawingEngine};

    Private::dirtyRect = rect;

    buffer.setSize(PlatformInterface::Size(rect.width(), rect.height()));
    buffer.setBytesPerLine(rect.width() * Private::bytesPerPixel);
    buffer.setBits(Private::framebuffer);

    return &buffer;
}

フレームバッファの内容をディスプレイにフラッシュする

beginFrame に渡されたダーティな矩形は、DrawingEngine によって描画された後、endFrame で使用され、更新された部分的なフレームバッファのコンテンツをディスプレイにフラッシュします。

void endFrame(const PlatformInterface::LayerEngine::ItemLayer *) override
{
    // Lcd_Flush(Private::dirtyRect.x(),
    //    Private::dirtyRect.y(),
    //    Private::dirtyRect.x() + Private::dirtyRect.width(),
    //    Private::dirtyRect.y() + Private::dirtyRect.height(),
    //    Private::framebuffer);
}

ダーティな矩形をプラットフォーム要件に合わせる

プラットフォーム・アダプテーションは、adjustedPartialUpdateRect を使用して、後にbeginFrame に渡されるダーティな矩形を調整することができます。これにより、プラットフォーム・アダプテーションは、データの整列、フラッシュ領域の最小サイズなど、プラットフォーム固有のニーズに基づいて矩形を調整することができます。

注: このメソッドの実装はオプションです。

PlatformInterface::Rect adjustedPartialUpdateRect(const PlatformInterface::LayerEngine::ItemLayer *layer,
                                                  const PlatformInterface::Rect &rect) const override
{
    auto r = PlatformInterface::Rect(rect);

    // r.setX(...);
    // r.setWidth(...);

    return r;
}

対応プラットフォーム

パーシャル・フレームバッファをサポートするリファレンス・ポートのリストについては、「サポートされる機能」を参照してください。

注: この機能を有効にするには、CMake オプションQUL_PLATFORM_PARTIAL_FRAMEBUFFERを使用して、これらのポートのプラットフォーム・ライブラリを再構築する必要があります。詳細については、評価パッケージに対するQt Quick Ultralite プラットフォーム・ライブラリのビルドを参照してください。

画面にグラフィックを表示する」も参照して ください。

特定の Qt ライセンスの下で利用可能です。
詳細をご覧ください。