OpenGL ES と EGL を実装する

OpenGL は、3D グラフィック処理ハードウェアの標準ソフトウェア インターフェースを定める、クロス プラットフォームのグラフィック API です。OpenGL ES は OpenGL 仕様の組み込みデバイス向けのサブセットです。

Android 互換であるためには、EGL、OpenGL ES 1.x、OpenGL ES 2.0 用のドライバを提供する必要があります。OpenGL ES 3.x のサポートは任意です。主に以下の点を考慮してください。

  • GL ドライバを安定させ、OpenGL ES 標準に準拠するようにします。
  • GL コンテキスト数を無制限にします。Android は、バックグラウンドのアプリを許可し、GL コンテキストを有効のままにしようとするため、ドライバでコンテキスト数を制限しないでください。
  • 20~30 個の有効な GL コンテキストが同時に存在することがよくあるため、各コンテキストに割り当てられるメモリの量に注意してください。
  • メディア コーデックやカメラなど、システム内の他のコンポーネントに由来する YV12 画像形式やその他の YUV 画像形式をサポートしてください。
  • 必須の拡張機能である EGL_KHR_wait_syncGL_OES_texture_externalEGL_ANDROID_image_native_bufferEGL_ANDROID_recordable をサポートしてください。また、Hardware Composer v1.1 以降では、EGL_ANDROID_framebuffer_target 拡張機能が必要です。

加えて、EGL_ANDROID_blob_cacheEGL_KHR_fence_syncEGL_ANDROID_native_fence_sync をサポートすることも強くおすすめします。

Android 10 は、EGL 1.5 インターフェースを実装しています。EGL 1.5 の新機能については、Khronos リリース 1.5 の仕様をご覧ください。

ドライバの読み込み

Android では、システム イメージのビルド時にシステムで使用可能な GPU が認識されると想定しています。32 ビット、64 ビットの OpenGL ES ドライバの推奨パスは、それぞれ /vendor/lib/egl/vendor/lib64/egl です。ローダーは、2 つのシステム プロパティ ro.hardware.eglro.board.platform を使用して、または正確な名前を使用して、システム ドライバを検出して読み込みます。OpenGL ES ドライバは、1 つのバイナリでリリースするか、3 つのバイナリに分割してリリースする必要があります。OpenGL ES ドライバを 1 つのバイナリでリリースする場合、次のいずれかの名前を使用します。

libGLES_${ro.hardware.egl}.so
libGLES_${ro.board.platform}.so
libGLES.so

OpenGL ES ドライバを 3 つのバイナリでリリースする場合、次の名前の組のいずれかを使用します。

libEGL_${ro.hardware.egl}.so
libGLESv1_CM_${ro.hardware.egl}.so
libGLESv2_${ro.hardware.egl}.so

libEGL_${ro.board.platform}.so
libGLESv1_CM_${ro.board.platform}.so
libGLESv2_${ro.board.platform}.so

libEGL.so
libGLESv1_CM.so
libGLESv2.so

OpenGL ES レイヤ

Android 10 では、GLES 2.0 以降のレイヤシステムが導入されています。GLES レイヤは、アプリ内またはツールから提供される共有オブジェクトです。GLES レイヤは、Vulkan と同じ設定メカニズムを使用して、デバッグ可能アプリがレイヤを検出して読み込めるようにします。

GLES LayerLoader は、EGL ローダー内のコンポーネントであり、GLES レイヤを検出します。 GLES LayerLoader が検出したレイヤごとに、GLES LayerLoader が AndroidGLESLayer_Initialize を呼び出し、libEGL の関数リストを調べて、すべての既知の関数に対して AndroidGLESLayer_GetProcAddress を呼び出します。関数をインターセプトするレイヤの場合、関数のアドレスがトラッキングされます。 関数をインターセプトしないレイヤの場合、AndroidGLESLayer_GetProcAddress は、渡されたものと同じ関数アドレスを返します。次に、LayerLoader はレイヤのエントリ ポイントを指すように関数フックリストを更新します。

レイヤを有効にする

GLES レイヤは、アプリレベルかグローバル レベルで有効にできます。アプリレベルの設定は再起動後も保持されますが、グローバル プロパティは再起動時にクリアされます。

アプリレベルでレイヤを有効にするには、次のコマンドを実行します。

# Enable layers
adb shell settings put global enable_gpu_debug_layers 1

# Specify target app
adb shell settings put global gpu_debug_app package_name

# Specify layer list (from top to bottom)
adb shell settings put global gpu_debug_layers_gles layer1:layer2:...:layerN

# Specify packages to search for layers
adb shell settings put global gpu_debug_layer_app package1:package2:...:packageN

アプリレベルでレイヤを無効にするには、次のコマンドを実行します。

adb shell settings delete global enable_gpu_debug_layers
adb shell settings delete global gpu_debug_app
adb shell settings delete global gpu_debug_layer_app

グローバル レベルでレイヤを有効にするには、次のコマンドを実行します。

# Attempts to load layers for all applications, including native executables
adb shell setprop debug.gles.layers layer1:layer2:...:layerN

レイヤをテストする

GLES レイヤは Android CTS に基づいているため、互換性のあるデバイスの CTS テストに合格する必要があります。デバイスでレイヤが動作しているかどうかを確認するには、$ atest CtsGpuToolsHostTestCases を実行します。