EmscriptenにおけるEGLサポート

注記

この記事は現在作成中です。

Khronos GroupはEGLと呼ばれる仕様を公開しています。これは、(その他のタスクの中でも)グラフィックスコンテキストの作成、レンダリングサーフェスの管理、および異なるKhronos GroupグラフィックスAPI(OpenGL、OpenGL ES、OpenVG)間の相互運用性を処理するAPIです。詳細については、Khronos EGLウェブページを参照してください。

現在、EGLはオペレーティングシステム/グラフィックスドライバベンダー間で広く使用されているわけではありません。最も注目すべき採用例はAndroidアーキテクチャであり、そこでEGLはAndroid NDKを使用する場合のOpenGL ES 1&2のレンダリングコンテキストを作成する主要な方法です。また、MesaはグラフィックスドライバにEGL仕様の実装を持っています。

EmscriptenもEGL v1.4仕様の実装を提供します。これにより、C/C++クライアントコードは、Web、Linux(Mesaを使用)、Android NDKでGLES2(WebGL)レンダリングコンテキストを作成するための(ほぼ)統一されたコードベースを使用できます。EmscriptenでのEGL仕様の実装は完璧ではありません。このページの最後にステータスチャートを参照してください。

EGLではないもの

やや残念なことに、EGLはGLES2グラフィックスレンダリング(Emscriptenだけでなく、あらゆるプラットフォームで)の初期化と、関連するさまざまなタスクの監督を行うための、自己完結型の完全なソリューションではありません。仕様の範囲は限定されており、いくつかの機能が不足しています。特に、EGLは次のタスクには役立ちません。

  • レンダリングウィンドウの作成。EGL仕様では、レンダリング先のターゲットウィンドウの作り方を指定していません。まず、プラットフォーム固有のネイティブウィンドウシステム関数(X11、Win32 API、ANativeWindow)を使用して、レンダリングウィンドウを作成する必要があります。

  • 任意のピクセル増分でレンダリングウィンドウサイズを指定する。EGLには、メインレンダリングウィンドウのサイズを要求したり、サイズを変更したりする機能がありません。

  • フルスクリーンビデオモード/画面解像度の指定。EGLを使用して、ウィンドウモードまたはフルスクリーンモードでレンダリングするかどうか、または実行時にそれらの間を切り替えるかどうかを制御することはできません。

したがって、Emscriptenを含む各プラットフォームには、これらのタスクを実行するためのプラットフォーム固有の方法が存在します。

EGLを使用してWebGLコンテキストを作成する方法

Web環境では、WebGLは3Dアクセラレーションレンダリングに使用されるテクノロジーです。WebGLはGLES2とほぼ同一であり、EGLはWebGLにはまったく適用されないため、このページではすべての目的でWebGLとGLES2という用語を交換して使用します。したがって、WebGLコンテキストを作成するには、EGLを使用し、その言葉遣いに従ってGLES2コンテキストを作成します。

初期化

EGLを使用してGLES2コンテキストを作成するには、次の手順を実行します。

  1. eglGetDisplayを呼び出すことで、EGLDisplayオブジェクトへのハンドルを取得します。

  2. eglInitializeを呼び出すことで、そのディスプレイでEGLを初期化します。

  3. eglGetConfigsおよび/またはeglChooseConfigを1回以上呼び出して、目的のメインレンダリングターゲットパラメータを表すEGLConfigを見つけます。EGLConfigの属性を調べるには、eglGetConfigAttribを呼び出します。

  4. この時点で、使用可能なプラットフォーム固有の関数(*X11*、*Win32 API*、*ANativeWindow*)を使用して、レンダリング先のネイティブウィンドウを設定します。Emscriptenの場合、このステップは適用されず、スキップできます。

  5. 有効なディスプレイとコンフィグパラメータを使用してeglCreateWindowSurfaceを呼び出すことで、メインレンダリングターゲットサーフェース(EGLSurface)を作成します。ウィンドウと属性リストパラメータをnullに設定します。

  6. eglCreateContextを呼び出してGLES2レンダリングコンテキスト(EGLContext)を作成し、続いてeglMakeCurrentを呼び出してレンダリングコンテキストをアクティブにします。コンテキストの作成時に、コンテキスト属性EGL_CONTEXT_CLIENT_VERSION == 2を指定します。

これらの手順の後、メインGLES2レンダリングコンテキストを表すEGLオブジェクトEGLDisplayEGLConfigEGLSurface、およびEGLContextのセットが作成されます。

クリーンアップ

初期化解除時のクリーンアップシーケンスは次のとおりです。

  1. eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)を呼び出すことで、現在アクティブなレンダリングコンテキストを解放します。

  2. それを対象にeglDestroyContextを呼び出すことで、EGLContextオブジェクトを初期化解除します。

  3. それらを対象にeglDestroySurfaceを呼び出すことで、初期化されたすべてのEGLSurfaceオブジェクトを破棄します。

  4. eglTerminate(display)を呼び出すことで、EGLを完全に初期化解除します。

  5. ネイティブレンダリングウィンドウを削除します。このステップはEmscriptenには適用されません。

サンプルコード

EGLを使用してWebGLコンテキストを初期化するためのサンプルコードは、emscripten/test/third_party/glbookディレクトリ、より具体的にはesUtil.cファイルにあるサンプルアプリケーションで見つけることができます。

実装状況と注記

このセクションでは、すべてのEGL v1.4関数をリストし、Emscriptenでの現在の実装状況について説明します。

完全に実装済み

  • eglInitializeeglGetConfigseglQueryContexteglQueryStringeglQuerySurfaceeglGetCurrentContextglGetCurrentSurfaceeglGetCurrentDisplayeglReleaseThreadeglDestroySurfaceeglDestroyContext:実装されており、EGL v1.4仕様に従って動作するはずです。

  • eglSwapBuffers:実装されていますが、この関数はWebGLではスワップ動作を実際には制御できません。Emscriptenでは、この関数を呼び出すことはオプションです。WebGLでは、ディスプレイの内容は、コードが実行をブラウザに戻すまで、つまりemscripten_set_main_loop()に渡したチックコールバックハンドラから戻った後にのみ、常に画面に表示されます。eglSwapBuffers関数は、GLコンテキストの損失イベントが発生したときに検出するために使用できます。

  • eglGetDisplay: 仕様に従って実装されています。Emscriptenは複数のEGLNativeDisplayTypeオブジェクトを使用しないため、ここではEGL_DEFAULT_DISPLAYを渡してください。Emscriptenは現在、Linuxエミュレーションのためにここで渡された値を無視していますが、将来はこの動作に依存しないでください。

  • eglGetError: 仕様に従って実装されています。

    重要

    仕様によると、eglGetErrorは以前のすべてのエラーのリストではなく、最新の単一のエラーを報告します。glGetErrorを呼び出すのと同じ方法で、この関数をループ内で呼び出さないでください。

部分的に実装済み

  • eglChooseConfig: スタブとして実装されていますが、この関数は検索/フィルタリングを行わず、現時点ではeglGetConfigsと同一です(issue #643)。

  • eglGetConfigAttrib: 実装済みです。属性EGL_BUFFER_SIZEEGL_ALPHA_SIZEEGL_BLUE_SIZEEGL_GREEN_SIZEEGL_RED_SIZEEGL_DEPTH_SIZEEGL_STENCIL_SIZEのクエリは、現在ハードコードされたデフォルト値を返します(issue #644)。属性EGL_MIN_SWAP_INTERVALEGL_MAX_SWAP_INTERVALは現在機能していません。代わりに、メインループの更新レートを指定するにはemscripten_set_main_loop()を呼び出してください。

  • eglCreateWindowSurface: 実装されていますが、複数のレンダリングウィンドウを作成するためにこの関数を複数回呼び出すことはできません。

  • eglCreateContext: スタブとして実装されています。複数のコンテキストを作成するためにこの関数を複数回呼び出すことはできません。

  • eglBindAPIeglQueryAPI: 実装されていますが、GLES2クライアントAPIのみがサポートされているため、Emscriptenではこれらの関数の有用性はほとんどありません。

  • eglWaitClienteglWaitNative: ノーオペレーション関数として実装されています。Emscriptenではこれらは意味を持ちません。

  • eglSwapInterval: ノーオペレーションスタブとして実装されています。現在、この関数はvsync間隔を設定したり、有効/無効にしたりすることはできません。

  • eglMakeCurrent: ノーオペレーションスタブとして実装されています。

  • eglTerminate: ノーオペレーション関数スタブとして実装されています。JavaScriptアプリケーションは手動でシャットダウンされることはあまりありませんが、ブラウザを閉じたり、ウェブページを切り替える際に、ブラウザがすべての終了処理を自動的に管理します。したがって、この関数はEmscriptenでは重要な意味を持ちません。

  • eglGetProcAddress: 実装済み、実験段階。

未実装機能

現在、次の関数は実装されていません。

  • eglCreatePbufferSurfaceeglCreatePixmapSurfaceeglCreatePbufferFromClientBuffereglSurfaceAttribeglBindTexImageeglReleaseTexImageeglWaitGLeglCopyBuffers

重要

これらの関数をEmscriptenコードで呼び出さないでください。そうしないと、未定義関数の実行を試行した際にアプリケーションが停止します。

EGL拡張機能

現在、EmscriptenはEGL Extension Registryの拡張機能を一切実装していません。