Androidが一時停止したときにOpenGLコンテキストが失われる回避策はありますか?


40

Androidのドキュメントには次のように書かれています:

EGLレンダリングコンテキストが失われる状況があります。これは通常、デバイスがスリープ状態になってから起動したときに起こります。EGLコンテキストが失われると、そのコンテキストに関連付けられているすべてのOpenGLリソース(テクスチャなど)が自動的に削除されます。レンダリングを正しく維持するために、レンダラーは、必要な失われたリソースを再作成する必要があります。onSurfaceCreated(GL10、EGLConfig)メソッドは、これを行うのに便利な場所です。

ただし、OpenGLコンテキストですべてのテクスチャを再ロードする必要があるのは苦痛であり、一時停止後にアプリを再入力するときにユーザーのゲームエクスペリエンスが損なわれます。私は「Angry Birds」がどういうわけかこれを避けることを知っています、私は同じことを達成する方法についての提案を探していますか?

私はAndroid NDK r5(CrystaXバージョン)で作業しています。この問題に対するハッキングの可能性を見つけましたが、カスタムSDKバージョン全体のビルドを避けようとしています。


スリープとウェイクアップはデバイスを指すので、ユーザーがゲームを一時停止するかプロセスを切り替えるだけで、EGLコンテキストが失われます。
Ali1S232

回答:


22

レプリカアイランドには、この問題を処理するGLSurfaceViewの修正バージョンがあります(以前のAndroidバージョンでも動作します)。クリス・プルエットによると:

基本的に、元のGLSurfaceViewをハッキングして、非常に具体的な問題を解決しました。OpenGLの状態をすべて破棄せずに、アプリ内のさまざまなアクティビティに移動したかったのです。主な変更点は、EGLSurfaceをEGLContextから分離し、前者をonPause()で破棄し、コンテキストが明示的に失われるまで後者を保持することでした。GLSurfaceViewのデフォルトの実装(ちなみに私は書きませんでした)は、アクティビティが一時停止されるとすべてのGL状態を破棄し、再開されるとonSurfaceCreated()を呼び出します。つまり、ゲームでダイアログボックスが表示されたときに、すべてのテクスチャを再読み込みする必要があるため、ダイアログボックスを閉じるときに遅延が発生しました。

デフォルトのGLSurfaceViewを使用する必要があります。私が持っているのと同じ機能が必要な場合は、私のものを見ることができます。しかし、私がやったことを行うことで、いくつかのハンドセットであらゆる種類のひどいドライバーのバグを公開しました(そのファイルの終わり近くにある非常に長いコメントをご覧ください)。

編集:あなたはすでに同様のハックへのリンクを投稿していることに気付きました。ハニカムの前に組み込みのソリューションがあるとは思わない。レプリカ島は多くのデバイスで動作する人気のあるゲームであり、クリスの実装とコメントが役立つかもしれません。


1
これを回避するためにさまざまなアプローチを試した後、コンテキストを再作成するためにアプリをコーディングし直すことが最善の解決策であると判断しました。これは無駄なアプローチですが、良い解決策があるようには見えません。code.google.com/p/android/issues/detail?id
Nick Gotch

9

クリスプリュット(レプリカアイランド、ワインドアップナイトなど)から1年または2年前に渡された別の回答を追加したいと思います。4.3ではsetPreserveEglContextOnPause(true)が機能しないように見えるため、2013年は特に便利です。(私はそれについて間違っているかもしれませんが、2011年に最後に触れたゲームコードを更新するとき、それは今私に見える方法です)。

基本的に、トリックはアクティビティのonPause()からビュー階層からGLSurfaceViewをデタッチすることです。onPause()が実行される時点ではビュー階層にないため、コンテキストは破棄されません。

したがって、アクティビティのonPause()は次のようになります。

@Override
public void onPause() {
    view.setVisibility(View.GONE);
    super.onPause();
    ...
}

そして、GLSurfaceViewをonResume()からではなく onWindowFocusChanged()から階層に復元します:

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    if (hasFocus && view.getVisibility() == View.GONE) {
         view.setVisibility(View.VISIBLE);
    }
    ...
}

GLSurfaceViewのonPause()およびonResume()を呼び出すことはなく、これは公式のSDK GLSurfaceViewであり、ハックアップされた代替バージョンは必要ないことに注意してください。


実際、このアプローチはうまくいかないようです。Chris PruettはUnityと組み合わせて使用​​しましたが、この回避策がネイティブプロジェクトで機能しない可能性はありますか?しかし、GLView.onPause()を呼び出さないだけで機能するようです!?これを確認できる人はいますか?
sjkm 14

Android 2.2 OpenGl ES 2をターゲットにした私にとってはうまくいきました。他のデバイスでどのように動作するかはわかりません。LG G2 D802電話を持っています。これが一般的な解決策であるかどうかは誰にもわかりますか?
ピクセル

7

<暴言> 私はこの問題に膨大な時間を費やし、多くの異なるソリューションを試しましたが、今日まで何も動作しませんでした。本当に驚いた。 </ rant>

そのため、eglContextメンバーを上に移動して静的(グローバル)にし、破棄されないようにすることです。その後、再度作成する前に、nullかどうかを確認するだけです。

これまでのところ、このソリューションは機能しているようで、2005年のデバイスで問題が発生しても問題ありません。


4

ハニカムAPIを使用します。OGLコンテキストを保持するオプションがあります。それ以外の場合は、コンテキストをリロードする必要があります。難しくも苦痛もありません。

次の2つのケースがあることを理解する必要があります(Android 2.1):

  • 画面の一時停止:アプリケーションは常に最前面にあります=>ハッキング可能
  • アプリケーションの一時停止:別のフロントアプリケーションがあります=>解決策なし

注:古いandroid gpusはマルチコンテキストをサポートしていません。そのため、別のアプリケーションに切り替えるとopenglコンテキストが失われます=>利用可能なソリューションはありません(画面の一時停止時にハッキングしてコンテキストを保持できます)。

注2:HoneyComb関数はsetPreserveEGLContextOnPauseです


1
コンテキストを簡単にリロードするように設計されていないC ++ゲームをAndroid NDKに移植しているので、少なくとも私にとってはやや難しいです。難しさはさておき、このハニカム修正を聞くが、残念ながら、我々は2.1 +をサポートする必要があるために喜んで私たちの他のデバイス(iPhone、PSP、DS、等。)上に存在しない遅延紹介しますテクスチャをリロード
ニック・ゴッチを

1
これは彼の質問にはまったく答えません。
notlesh

1
あなたが理解していないなら、あなたはそれをすることができません。
エリス

2

ここでの回答のいくつかは、AndroidでOpenGL ESを早期に使用するのに適しています。最初のGLESデバイスは単一のコンテキストのみをサポートしていたため、GLSurfaceViewは状態を積極的に破棄するように設計されていました。そうでなければ、GLSurfaceViewを説得するのは簡単ではありません。

Androidの最新バージョン(おそらくGLES 2.xを使用しているもの)の場合、最良の答えは、プレーンなSurfaceViewを使用して、独自のEGLおよびスレッド管理を行うことです。EGLコンテキストを作成および破棄するための単純なクラスのライブラリなど、GrafikaのプレーンなSurfaceViewで使用されるGLESの複数の例を見つけることができます。

アプリがバックグラウンドになったときに状態をアンロードすることはまだ良い習慣ですが、クリス・プルエットの例では、アプリはまだフォアグラウンドにありますが、GLSurfaceViewをホストしているアクティビティは切り替えられており、ティアリングする価値はありませんコンテキストダウン。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.