Surface と SurfaceHolder

Surface オブジェクトにより、アプリは画像をレンダリングして画面上に表示できるようになります。 SurfaceHolder インターフェイスを使用すると、アプリでサーフェスを編集および制御できます。

表面

サーフェスは、プロデューサーがコンシューマーとバッファーを交換するためのインターフェイスです。

ディスプレイ サーフェスの BufferQueue は通常、トリプル バッファリング用に構成されます。バッファーはオンデマンドで割り当てられるため、プロデューサーがバッファーを十分にゆっくり生成する場合 (60 fps ディスプレイで 30 fps など)、キュー内に割り当てられたバッファーは 2 つだけになる可能性があります。オンデマンドでバッファを割り当てると、メモリ消費を最小限に抑えることができます。 dumpsys SurfaceFlingerの出力で、すべてのレイヤーに関連付けられたバッファーの概要を確認できます。

ほとんどのクライアントは、 OpenGL ESまたはVulkanを使用してサーフェスにレンダリングします。ただし、一部のクライアントはキャンバスを使用してサーフェスにレンダリングします。

キャンバスのレンダリング

キャンバスの実装は、 Skia Graphics Libraryによって提供されます。四角形を描画する場合は、Canvas API を呼び出して、バッファー内のバイトを適切に設定します。バッファーが 2 つのクライアントによって同時に更新されたり、表示中に書き込まれたりしないようにするには、バッファーにアクセスするためにバッファーをロックします。キャンバス ロックを操作するには、次のコマンドを使用します。

  • lockCanvas() 、CPU でのレンダリング用のバッファをロックし、描画に使用する Canvas を返します。
  • unlockCanvasAndPost()バッファのロックを解除し、それをコンポジタに送信します。
  • lockHardwareCanvas() GPU でのレンダリング用のバッファをロックし、描画に使用するキャンバスを返します。

初めてプロデューサーが BufferQueue にバッファを要求すると、バッファが割り当てられ、ゼロに初期化されます。初期化は、プロセス間で誤ってデータを共有しないようにするために必要です。ただし、バッファを再利用した場合、以前の内容はまだ存在します。何も描画せずにlockCanvas()unlockCanvasAndPost()を繰り返し呼び出すと、プロデューサーは以前にレンダリングされたフレーム間を循環します。

サーフェスのロック/ロック解除コードは、以前にレンダリングされたバッファーへの参照を保持します。サーフェスをロックするときにダーティ領域を指定すると、前のバッファから非ダーティ ピクセルがコピーされます。通常、SurfaceFlinger または HWC がバッファを処理します。ただし、バッファから読み取るだけでよいため、排他的アクセスを待つ必要はありません。

表面ホルダー

SurfaceHolder は、システムがサーフェスの所有権をアプリと共有するために使用するインターフェイスです。サーフェスを操作する一部のクライアントは、SurfaceHolder を必要とします。これは、サーフェス パラメータを取得および設定するための API が SurfaceHolder を通じて実装されているためです。 SurfaceView には SurfaceHolder が含まれています。

ビューと対話するほとんどのコンポーネントには、SurfaceHolder が含まれます。 MediaCodec などの他の API は、サーフェス自体で動作します。