web-dev-qa-db-ja.com

onPauseがOpenGLコンテキストを破棄しないようにする

OpenGL ES(GLSurfaceViewおよびGLSurfaceView.Renderer)を使用するAndroidアプリケーションを作成しています。問題は、ユーザーがアプリケーションを切り替えてからアプリに戻ると、GLSurfaceViewが破棄されて再作成されることです。 GLコンテキスト。これはドキュメントによると想定されていることですが、これを防ぐ方法はありますか?

テクスチャをコンテキストにロードするのに長い時間がかかるので、テクスチャをリロードする必要がないようにしたいと思います。

21
cjserio

あなたが探しているものはGLSurfaceViewのドキュメントで議論されていると思います:

アクティビティが一時停止および再開された場合は、GLSurfaceViewに通知する必要があります。 GLSurfaceViewクライアントは、アクティビティが一時停止したときにonPause()を呼び出し、アクティビティが再開したときにonResume()を呼び出す必要があります。これらの呼び出しにより、GLSurfaceViewはレンダリングスレッドを一時停止および再開でき、GLSurfaceViewはOpenGL表示を解放して再作成することもできます。

標準のAndroid SDKを使用する場合、アクティビティが一時停止/再開されるたびに(画面の向きの変更を含む)、コンテキストを解放/再作成する必要があります。そうしないと、GLアクティビティがメモリにロードされたときに解放され、復元されないコンテキスト。非常に限られたリソース(特に低スペックのデバイス)を扱っていることを忘れないでください。つまり、簡単に言えば、それなしでは防ぐことはできません。あなたのアプリを壊します。

標準のAndroid/OpenGLフレームワークを使用していると仮定すると、次のことを行う必要があります...

アクティビティでは、次のオーバーライドされたメソッドがあることを確認してください。

public void onPause() {
    myGlSurfaceView.onPause();
}

public void onResume() {
    myGlSurfaceView.onResume();
}

GL環境の外にあるものはすべて、手動で保存および復元する必要があります(ビットマップ、ゲームの状態など)。これらの場合は、静的フィールドまたはSharedPreferencesなどのメカニズムを使用する必要があります。 。

更新

Android 3.xは、再作成する必要なしに GL一時停止時のコンテキストを保持 を保持する)機能を提供します。ただし、いくつかの注意点があります。

  1. Android 3.xの機能は、現時点では市場に出回っていません デバイスの約90%
  2. デバイスは複数のEGLコンテキストもサポートする必要があり、現在市場でこれをサポートしているデバイスの数は不明です。

一部のAPIリフレクションを使用して機能を確認すると、サポートするデバイスでこの機能を利用できる場合があります。ただし、残りのコンテキストの再作成にフォールバックする必要があります。私の意見では、より多くのデバイスが実行されるまでAndroid 3 setPreserveEGLContextOnPauseの使用を控え、コンテキストレクリエーションアプローチが十分にテストされていることを確認することに集中する方がよいでしょう。

16
seanhodges

上記のコメントで述べたように、GL以前のコンテキストAndroidリリース(1.x、2.x))を破棄することを回避することも可能です。 Android-15 SDKソースコードからGLSurfaceViewをコピーし、そのパッケージ名を変更してから、GlSurfaceViewの独自のコピーを使用します。

GLバージョンに関係なく、複数のAndroidコンテキスト(現時点ではAdrenoチップを除く)をサポートするデバイスで機能するはずです。注意点は、GLSurfaceView Android-15には、Android-15で動作するために必要なものだけが含まれています。このバージョンでは、すべてのOSバージョンを処理する必要があります。

私たちは、ReplicaIslandからのコピーに基づいたGlSurfaceViewの独自の実装を使用します。ここで、ChrissPruitも独自の実装を使用しました。

私たちのバージョンでは、SDK-15からsetPreserveEGLContextOnPauseを追加しました。これにより、たとえばGL 2.3を実行しているネクサスのコンテキストでAndroidコンテキストを保持できます。

また、ニーズに合わせて他のものを変更しましたが、これはこの質問には関係ありません(たとえば、それをサポートする電話での32ビットレンダリング、それ以外の場合は16ビット)。

私たちのGlSurfaceView: http://Pastebin.com/U4x5JjAr

これは、上記と同じ(Android)スタイルでフォーマットされたGlSurfaceViewの元のSDK-15バージョンです http://Pastebin.com/hziRmB3E (簡単に比較して変更を確認できるように)

次のコマンドを呼び出して、コンテキストの保存を有効にすることを忘れないでください。

    glSurfaceView.setPreserveEGLContextOnPause(true);
8
arberg

APIレベル11以降、コンテキストを保持する必要があるかどうかを指定できます。

ドキュメントから:

public void setPreserveEGLContextOnPause(boolean prepareOnPause)以降:APIレベル11

GLSurfaceViewが一時停止および再開されたときに、EGLコンテキストを保持するかどうかを制御します。

Trueに設定すると、GLSurfaceViewが一時停止したときにEGLコンテキストが保持される場合があります。 EGLコンテキストが実際に保持されるかどうかは、プログラムが実行されているAndroidデバイスが任意の数のEGLコンテキストをサポートできるかどうかによって異なります。限られた数のEGLコンテキストのみをサポートできるデバイス複数のアプリケーションがGPUを共有できるようにするには、EGLコンテキストがEGLコンテキストを解放する必要があります。

Falseに設定すると、GLSurfaceViewが一時停止したときにEGLコンテキストが解放され、GLSurfaceViewが再開したときに再作成されます。

デフォルトはfalseです。

パラメータpreserveOnPauseは、一時停止時にEGLコンテキストを保持します

3
rockeye

OpenGLを使用してからしばらく経ち、デスクトップPCの標準的な並べ替えでしたが、標準のOpenGLではコンテキストスイッチでテクスチャをリロードする必要がないことを覚えているようです。もちろん、この場合、それは実際には役に立ちません。

テクスチャをリロードする必要があると仮定すると、問題は次のようになります。これをどのように高速化しますか?そして、問題は、一度にいくつのテクスチャが必要で、オンデマンドでそれらをロードできるかということです。それらの寸法は何ですか? OpenGLの実装とドライバーにも依存する可能性がありますが、通常は2の累乗の方がロードが高速だったことを思い出します。

このスレッドのように、コンテキストが破壊されない場所に保持することについても聞いたことがあります: openglesビュー切り替えの問題

0
GenericMeatUnit