Surface のオブジェクトを使用すると、アプリは画面上に表示される画像をレンダリングできます。SurfaceHolder インターフェースによりサーフェスの編集や設定が可能になります。
Surface
Surface は、プロデューサーがバッファを消費者と交換するためのインターフェースです。
通常、表示サーフェスの BufferQueue は、トリプル バッファリングに設定されます。バッファはオンデマンドで割り当てられるため、60 fps ディスプレイで 30 fps など、プロデューサーがバッファを緩やかに生成する場合、キューにはバッファが 2 つだけ割り当てられる可能性があります。オンデマンドでバッファを割り当てると、メモリ消費量を最小限に抑えることができます。dumpsys SurfaceFlinger
出力で各レイヤに関連付けられたバッファの概要を確認できます。
ほとんどのクライアントは、OpenGL ES または Vulkan を使用してサーフェスにレンダリングします。ただし、キャンバスを使用してサーフェスにレンダリングするクライアントも存在します。
キャンバスのレンダリング
キャンバスの実装は、Skia Graphics Library が提供しています。長方形を描画する場合は、バッファに適切にバイトを設定する Canvas API を呼び出します。バッファが 2 つのクライアントによって同時に更新されないようにする、または表示中に書き込みが行われないようにするには、バッファをロックしてアクセスします。キャンバス ロックで操作するには、次のコマンドを使用します。
lockCanvas()
は、CPU でレンダリングするバッファをロックし、描画に使用する Canvas を返します。unlockCanvasAndPost()
は、バッファをロック解除してコンポジタに送信します。lockHardwareCanvas()
は、GPU でレンダリングするバッファをロックし、描画に使用するキャンバスを返します。
プロデューサーが BufferQueue からバッファを初めて要求すると、バッファが割り当てられ、0 に初期化されます。初期化は、プロセス間で誤ってデータを共有しないようにするために必要です。ただし、バッファを再利用すると、以前の内容はそのまま残ります。何も描画することなく lockCanvas()
と unlockCanvasAndPost()
を繰り返し呼び出すと、プロデューサーは以前にレンダリングされたフレーム間を循環します。
サーフェスのロックコードまたはロック解除コードは、以前にレンダリングされたバッファへの参照を保持します。サーフェスをロックするときにダーティな領域を指定すると、直前のバッファからダーティでないピクセルをコピーします。通常、SurfaceFlinger または HWC がバッファを処理します。ただし、バッファからの読み取りのみが必要なため、排他的なアクセスを待つ必要はありません。
SurfaceHolder
SurfaceHolder は、システムがサーフェスの所有権をアプリと共有するために使用するインターフェースです。サーフェスのパラメータを取得および設定する API は SurfaceHolder を介して実装されるため、サーフェスを操作するクライアントには SurfaceHolder が必要な場合があります。SurfaceView には SurfaceHolder が含まれています。
ビューを操作するコンポーネントのほとんどは、SurfaceHolder を使用します。MediaCodec などの他の API は、サーフェス自体で動作します。