グラフィックス

Android グラフィック HAL アイコン

Android フレームワークは、メーカーによって実装されるグラフィック ドライバと連携する、2D および 3D 用のさまざまなグラフィック レンダリング API を提供します。したがって、上位レベルでの API の動作を十分に理解することが重要です。このページでは、ドライバがビルドされるグラフィック Hardware Abstraction Layer(HAL)について説明します。このセクションに進む前に、以下の用語についてよく理解しておいてください。

キャンバス(一般用語)、Canvas(API 要素)
ビットマップ オブジェクトや Surface オブジェクトに対して、実際のビットの合成を処理する描画サーフェス。Canvas には、ビットマップ、線、円、長方形、テキストなど、標準的なコンピュータ図形描画用のメソッドが用意されており、ビットマップやサーフェスにバインドされます。キャンバスは、2D オブジェクトを画面上に描画するためのシンプルで簡単な方法です。基本クラスは Canvas です。
ドローアブル
背景やタイトルなど、画面内のパーツとして使用できるコンパイル済みビジュアル リソース。ドローアブルは通常、背景画像などの別の UI 要素に読み込まれます。ドローアブルではイベントの受信はできませんが、状態やスケジュールなど、他のさまざまなプロパティを割り当てて、サブクラス(アニメーション オブジェクトやイメージ ライブラリなど)を有効にできます。ドローアブル オブジェクトの多くは、ドローアブル リソース ファイル(画像を記述した XML ファイルやビットマップ ファイル)から読み込まれます。ドローアブル リソースは、android.graphics.drawable のサブクラスにコンパイルされます。ドローアブルや各種リソースの詳細については、アプリリソースの概要をご覧ください。
レイアウト リソース
アクティビティの画面レイアウトを記述する XML ファイル。詳しくは、レイアウト リソースをご覧ください。
nine-patch(9-patch、NinePatch)
デバイス上で背景や各種画像用に使用できるサイズ変更可能なビットマップ リソース。詳しくは、nine-patch をご覧ください。
OpenGL ES
2D グラフィックと 3D グラフィックのレンダリング用のクロスプラットフォーム API。Android には、ハードウェア アクセラレーテッド 3D レンダリング用の OpenGL ES ライブラリが用意されています。2D レンダリングの場合は、シンプルなキャンバスをおすすめします。OpenGL ES は Android Native Development Kit(NDK)で入手できます。OpenGL ES 機能は、android.opengl パッケージと javax.microedition.khronos.opengles パッケージからエクスポーズされます。
サーフェス(一般用語)、Surface(API 要素)
画面に合成されるメモリのブロックを表します。サーフェスは、描画用のキャンバスを保持し、レイヤの描画や Surface オブジェクトのサイズ変更を行うさまざまなヘルパー メソッドを備えています。Surface クラスを直接使用するのではなく、SurfaceView クラスを使用します。
サーフェス ビュー(一般用語)、SurfaceView(API 要素)
描画用の Surface オブジェクトをラップする View オブジェクト。サイズや形式を動的に指定するメソッドをエクスポーズします。サーフェス ビューを使用すると、リソース消費の多い処理(ゲームやカメラ プレビューなど)において、UI スレッドから独立して描画を行うことができます。ただし、結果的にメモリ使用量は増えます。サーフェス ビューは、キャンバスと OpenGL ES の両方のグラフィックをサポートしています。SurfaceView オブジェクトの基本クラスは SurfaceView です。
テーマ
テキストサイズ、背景色などのプロパティのセット。これらのプロパティを組み合わせて、さまざまなデフォルトの表示設定を定義します。Android には標準テーマがいくつか用意されています。標準テーマは R.style にリストされ、Theme_ から始まります。
ビュー(一般用語)、View(API 要素)
画面上に長方形領域を描画し、クリック、キーボード入力などの操作イベントを処理します。View クラスが、アクティビティ画面やダイアログ画面のほとんどのレイアウト コンポーネント(テキスト ボックス、ウィンドウなど)の基本クラスです。View オブジェクトは、親オブジェクトからの呼び出しを受け取って(ViewGroup を参照)自身を描画し、使用するサイズと場所を親オブジェクトに伝えます(親によって適用されない可能性もあります)。詳しくは、View をご覧ください。
ビューグループ(一般用語)ViewGroup(API 要素)
一連の子ビューをグループ化します。子ビューの配置やサイズを決定したり、必要に応じて各子ビューを呼び出して描画させたりすることが、ビューグループの役割です。ビューグループの中には、レイアウト専用で非表示のものもあれば、固有の UI(スクロール リストボックスなど)を持っているものもあります。ビューグループは widget パッケージに含まれますが、ViewGroup クラスを拡張します。
ビュー階層
アプリの各コンポーネントのユーザー インターフェースを定義するビュー オブジェクトとビューグループ オブジェクトの配置。1 つ以上の子ビューまたは子ビューグループを含むビューグループで構成されます。Android SDK に含まれている Hierarchy Viewer を使用すると、ビュー階層を視覚化できるため、デバッグや最適化の際に便利です。
Vulkan
Vulkan は、高パフォーマンスの 3D グラフィックを実現する、低オーバーヘッドのクロス プラットフォーム API です。
ウィジェット
フォーム要素や各種 UI コンポーネント(テキスト ボックスやポップアップ メニューなど)をレンダリングする完全実装型ビュー サブクラスのセットの 1 つ。ウィジェットは完全実装型であるため、自身の測定や描画、画面イベントへの応答を処理します。ウィジェットは android.widget パッケージにあります。
ウィンドウ(一般用語)、Window(API 要素)
Android アプリでは、ウィンドウは Window 抽象クラスから派生したオブジェクトで、デザイン、タイトルバーのテキスト、メニューの位置やコンテンツなど、汎用ウィンドウの要素を指定します。ダイアログとアクティビティは Window クラスの実装を使用して Window オブジェクトをレンダリングします。アプリで Window クラスを実装したりウィンドウを使用したりする必要はありません。

アプリ デベロッパーが画面に画像を描画するには、CanvasOpenGL ES、または Vulkan を使用する 3 つの方法があります。

Android グラフィック コンポーネント

デベロッパーがどのレンダリング API を使用しても、すべてサーフェスにレンダリングされます。サーフェスは、SurfaceFlinger でよく使用されるバッファキューのプロデューサー側を表します。Android プラットフォームで作成されるすべてのウィンドウは、サーフェスによってサポートされています。レンダリングされた表示可能なすべてのサーフェスは、SurfaceFlinger によってディスプレイ上に合成されます。

主要コンポーネントの連携の仕組みを次の図に示します。

画像レンダリング コンポーネント

図 1. サーフェスのレンダリングの仕組み

主要コンポーネントについて以下で説明します。

画像ストリーム プロデューサー

画像ストリーム プロデューサーとは、使用するグラフィック バッファを生成するもののことです。たとえば、OpenGL ES、Canvas 2D、mediaserver 動画デコーダなどがあります。

画像ストリーム コンシューマ

画像ストリームの最も一般的なコンシューマは SurfaceFlinger です。このシステム サービスはウィンドウ マネージャーから提供された情報を使用して、現在表示されているサーフェスをディスプレイに合成します。SurfaceFlinger は、ディスプレイのコンテンツを変更できる唯一のサービスであり、OpenGL と Hardware Composer を使用してサーフェスのグループを作成します。

その他の OpenGL ES アプリでも画像ストリームを使用できます(カメラアプリがカメラ プレビュー画像ストリームを使用するなど)。GL 以外のアプリがコンシューマになる場合もあります(ImageReader クラスなど)。

Hardware Composer

ディスプレイ サブシステム用のハードウェア抽象化です。SurfaceFlinger は特定の合成処理を Hardware Composer に委任して、OpenGL と GPU から作業をオフロードできます。SurfaceFlinger は普通の OpenGL ES クライアントとして動作するため、たとえば SurfaceFlinger がアクティブに 1 つまたは 2 つのバッファを 3 つ目に合成する場合、OpenGL ES が使用されます。この結果、GPU ですべての計算を実行するよりも、合成の消費電力が抑えられます。

残りの処理を行う Hardware Composer HAL は、すべての Android グラフィック レンダリングの中心です。Hardware Composer は、VSYNC などのイベントに対応する必要があります(他のイベントとして、プラグアンドプレイ HDMI をサポートするためのホットプラグがあります)。

Gralloc

グラフィック メモリ アロケータ(Gralloc)は、画像プロデューサーが要求するメモリを割り当てるために必要です。詳細については、Gralloc HAL をご覧ください。

データフロー

Android グラフィック パイプラインを示した次の図をご覧ください。

グラフィック データフロー

図 2. Android でのグラフィック データフロー

左側のオブジェクトは、ホーム画面、ステータスバー、システム UI などのグラフィック バッファを作成するレンダラです。SurfaceFlinger はコンポジターで、Hardware Composer はコンポーザーです。

BufferQueue

BufferQueue は、Android グラフィック コンポーネント同士を接続します。これらは、プロデューサーからコンシューマへのバッファのサイクルを一定に保つキューのペアです。プロデューサーがバッファを渡すと、SurfaceFlinger はディスプレイ上にすべてを合成します。

BufferQueue の通信プロセスについては、次の図をご覧ください。

BufferQueue の通信プロセス

図 3. BufferQueue の通信プロセス

BufferQueue には、画像ストリーム プロデューサーと画像ストリーム コンシューマを関連付けるロジックが含まれます。画像プロデューサーには、カメラ HAL または OpenGL ES ゲームで作成されるカメラ プレビューなどがあります。画像コンシューマには、SurfaceFlinger や、OpenGL ES ストリームを表示するアプリ(カメラのビューファインダーを表示するカメラアプリなど)があります。

BufferQueue は、バッファプールとキューを結合し、Binder IPC を使用してプロセス間でバッファを渡すデータ構造です。プロデューサー インターフェース、つまりグラフィック バッファを生成する相手に渡すものは、IGraphicBufferProducer(SurfaceTexture の一部)です。BufferQueue は、さまざまなタスクの中でもサーフェスへのレンダリングと GL コンシューマでの処理によく使用されます。

BufferQueue は次の 3 つのモードで動作します。

同期優先モード - デフォルトで BufferQueue は同期優先モードで動作し、プロデューサーから受け取ったすべてのバッファをコンシューマに渡します。このモードでは、バッファが破棄されることはありません。プロデューサーの速度が速すぎて、使いきる前にバッファが作成される場合は、ブロックして空きバッファを待機します。

非ブロッキング モード - BufferQueue は非ブロッキング モードでも動作可能で、前述の状況ではバッファを待たずにエラーを生成します。このモードでもバッファは破棄されません。これは、グラフィック フレームワークの複雑な依存関係を認識できないアプリ ソフトウェアでデッドロックが発生することを回避するために役立ちます。

破棄モード - 最終的には、エラーを生成したり待機したりせずに古いバッファを破棄するように BufferQueue を設定できます。たとえば、GL レンダリングをテクスチャ表示にして、できるだけ早く描画する場合は、バッファを破棄する必要があります。

この作業のほとんどを実施するために、SurfaceFlinger は普通の OpenGL ES クライアントとして動作します。したがって、たとえば SurfaceFlinger がアクティブに 1 つまたは 2 つのバッファを 3 つ目に合成する場合、OpenGL ES が使用されます。

Hardware Composer HAL が残り半分の作業を行います。この HAL は、すべての Android グラフィック レンダリングの中心として機能します。