概要#
公式の紹介:Android-Graphics
-
画像ストリームプロデューサー:グラフィックスプロデューサーは、グラフィックスバッファを生成し、グラフィックスコンシューマーが使用できるようにします。例えば、OpenGL ES、Canvas 2D、および mediaserver ビデオデコーダーなどです。
-
ネイティブフレームワーク:Libgui ライブラリには、グラフィックシステムの基本要素である Surface、BufferQueue、GraphicBufferConsumer、GraphicBufferProducer、SurfaceComposer などが含まれています。
-
ウィンドウの配置:WindowManager は、ウィンドウオブジェクトを制御するために使用されます。ウィンドウは、ビューオブジェクトのグループです。SurfaceFlinger は、Surface を画面に合成するために、SurfaceComposer からバッファとウィンドウメタデータを提供されます。
-
画像ストリームコンシューマー:グラフィックスコンシューマーには、SurfaceFlinger といくつかのグラフィックスアプリケーションが含まれます。
- 画像ストリームの最も一般的なコンシューマーは SurfaceFlinger です。このシステムサービスは、表示されている Surface を消費し、WindowManager から提供された情報を使用してそれらを画面に合成します。SurfaceFlinger は、OpenGL とハードウェアコンポーザーを使用して一連の Surface を合成します。
- 一部の OpenGL ES アプリケーションもコンシューマーとして機能することがあります。たとえば、カメラアプリはカメラプレビューの画像ストリームを消費します。非 GL アプリケーションもコンシューマーになることがあります。例えば、ImageReader クラスなどです。
-
HAL:ディスプレイサブシステムのハードウェア抽象化の実装であり、ハードウェアコンポーザーと Gralloc を含みます。
- SurfaceFlinger は、一部の合成作業をハードウェアコンポーザーに委任して、OpenGL と GPU の負荷を軽減することができます。この場合、SurfaceFlinger は単なる別の OpenGL ES クライアントとして機能し、ハードウェアコンポーザーがグラフィックスレンダリングを行います。ハードウェアコンポーザーは、イベントをサポートする必要があります。その 1 つは VSYNC です(もう 1 つはプラグアンドプレイ HDMI のサポートです)。
- Gralloc は、グラフィックスプロデューサーが要求するメモリを割り当てるために使用されます。
BufferQueue#
公式の紹介:Android-BufferQueue
左側のオブジェクトは、レンダラーによって生成されるグラフィックバッファです。例えば、ホーム画面、ステータスバー、システムインターフェースなどです。SurfaceFlinger はコンポジタであり、Hardware Composer は製作者です。BufferQueue は Android グラフィックスシステムの重要な部分であり、データの転送を担当します:
図のプロデューサーとコンシューマーは、異なるプロセスで実行されます。BufferQueue は、バッファプールとキューを組み合わせたデータ構造であり、バッファをプロセス間で Binder IPC を使用して転送します。いくつかの重要な関数は次のとおりです:
- プロデューサーは BufferQueue に空きバッファ(GraphicBuffer)を要求します:IGraphicBufferProducer.dequeueBuffer メソッド
- バッファ(GraphicBuffer)にデータ(描画など)を埋めた後、プロデューサーはバッファ(GraphicBuffer)を BufferQueue にキューイングします:IGraphicBufferProducer.queueBuffer メソッド
- コンシューマーは BufferQueue からバッファ(GraphicBuffer)をデキューします:IGraphicBufferConsumer.acquireBuffer メソッド
- コンシューマーが完了した後(通常は SurfaceFlinger がデータを合成する場合)、バッファ(GraphicBuffer)をキューに返します:IGraphicBufferConsumer.releaseBuffer メソッド
IGraphicBufferProducer は BufferQueue のプロデューサーインターフェースであり、実装クラスは BufferQueueProducer プロデューサークラスです。IGraphicBufferConsumer は BufferQueue のコンシューマーインターフェースであり、実装クラスは BufferQueueConsumer コンシューマークラスです。
SurfaceFlinger#
SurfaceFlinger は、現在表示されている Surface を管理するために使用されます。すべての表示されている Surface は、SurfaceFlinger によって WindowManager から提供された情報を使用して(OpenGL と HardWare Composer を使用して)画面のバックバッファに合成され、次の Vsync 信号が到着するのを待ってから画面に表示されます。SurfaceFlinger は、バックバッファと画面を関連付けるために使用され、Surface と上位レイヤーとの間の接続を確立する役割を果たします。
SurfaceFlinger の動作フロー
SurfaceFlinger の registerCallback 時のthisは、SurfaceFlinger が ComposerCallback インターフェースの実装です。
-
onHotplugReceived
ホットプラグイベント、ディスプレイの接続または切断時にコールバックされます。
-
onRefreshReceived
ローレベルの HWComposer からのリフレッシュリクエストを受け取ります。実装方法は次のとおりです:
void SurfaceFlinger::onRefreshReceived(int sequenceId, hwc2_display_t /*display*/) { Mutex::Autolock lock(mStateLock); if (sequenceId !=getBE().mComposerSequenceId) { return; } repaintEverythingLocked(); } void SurfaceFlinger::repaintEverythingLocked() { android_atomic_or(1, &mRepaintEverything); //リフレッシュをトリガーして、表示を再合成します signalTransaction(); }
-
onVsyncReceived
Vsync イベントの報告であり、ローレベルのハードウェアからの垂直同期信号を受け取ります。
なぜ垂直同期信号が必要なのかについては、https://juejin.cn/post/6863756420380196877#heading-1を参照してください。
合成方法#
- クライアント合成
各レイヤの内容を GPU でレンダリングしてバッファに合成し、最後にバッファをディスプレイハードウェアに送信します。クライアント合成には RenderEngine が使用されます。
- デバイス合成
ハードウェアコンポーザーによる合成 HWComposer は、各レイヤのデータをディスプレイハードウェアに直接送り、ディスプレイの異なる部分からデータを読み取るように指示します。
HWC 関連のチャート#
合成チャート#
ダンプ情報#
adb shell dumpsys SurfaceFlinger
レイヤー#
レイヤー(Layer)は合成の最も重要な単位です。各レイヤには、他のレイヤとの相互作用方法を定義する一連のプロパティがあります。レイヤの実装は各レイヤで異なりますが、基本的なアイデアは同じです。
frameworks/native/services/surfaceflinger
├── Layer.h
├── Layer.cpp
├── ColorLayer.h
├── ColorLayer.cpp
├── BufferLayer.h
└── BufferLayer.cpp
結論#
グラフィックス表示システム全体は、グラフィックスと表示の 2 つのシステムで理解することができます。
- グラフィックスシステムは、描画とグラフィックス処理のサポートを提供します。2D の Skia や 3D の OpenGLES、さまざまな画像デコーダーライブラリなどが含まれます。
- 表示システムは、グラフィックスが描画された後に表示するためにウィンドウを合成する必要があります。そのためには Surfaceflinger が必要であり、上位の表示システムには View、ActivityManagerService、WindowManagerService が含まれます。ウィンドウは Surface であり、SurfaceFlinger は Layer を使用してウィンドウを記述します。