In der Android-Dokumentation heißt es:
Es gibt Situationen, in denen der EGL-Renderingkontext verloren geht. Dies passiert normalerweise, wenn das Gerät nach dem Einschlafen aufwacht. Wenn der EGL-Kontext verloren geht, werden alle OpenGL-Ressourcen (z. B. Texturen), die diesem Kontext zugeordnet sind, automatisch gelöscht. Damit das Rendern korrekt bleibt, muss ein Renderer alle verlorenen Ressourcen neu erstellen, die er noch benötigt. Die Methode onSurfaceCreated (GL10, EGLConfig) bietet sich hierfür an.
Das erneute Laden aller Texturen im OpenGL-Kontext ist jedoch sowohl eine Belastung als auch eine Belastung für den Benutzer, wenn er die App nach einer Pause erneut betritt. Ich weiß, dass "Angry Birds" dies irgendwie vermeidet. Ich suche nach Vorschlägen, wie ich dasselbe erreichen kann.
Ich arbeite mit dem Android NDK r5 (CrystaX-Version). Ich habe diesen möglichen Hack für das Problem gefunden, aber ich versuche zu vermeiden, eine vollständige benutzerdefinierte SDK-Version zu erstellen .
Antworten:
Replica Island hat eine modifizierte Version von GLSurfaceView, die dieses Problem behebt (und mit früheren Android-Versionen funktioniert). Laut Chris Pruett :
Bearbeiten: Ich habe gerade festgestellt, dass Sie bereits den Link zu einem ähnlichen Hack gepostet haben. Ich glaube nicht, dass es vor Honeycomb eine integrierte Lösung gibt. Replica Island ist ein beliebtes Spiel, das auf vielen Geräten funktioniert. Vielleicht finden Sie Chris 'Implementierung und Kommentare hilfreich.
quelle
Ich möchte eine weitere Antwort hinzufügen, die mir vor ein oder zwei Jahren von Chris Pruett (Replica Island, Wind-Up Knight, etc.) übermittelt wurde. Dies ist 2013 besonders nützlich, da setPreserveEglContextOnPause (true) bei 4.3 nicht zu funktionieren scheint. (Daran könnte ich mich irren, aber für mich sieht es im Moment so aus, als ich den zuletzt in 2011 veröffentlichten Spielcode aktualisiere.)
Grundsätzlich besteht der Trick darin, Ihre GLSurfaceView von der Ansichtshierarchie von der onPause () Ihrer Aktivität zu trennen. Da es sich zum Zeitpunkt der Ausführung von onPause () nicht in der Ansichtshierarchie befindet, wird der Kontext nie zerstört.
Die onPause () Ihrer Aktivität sollte also so aussehen:
Und Sie stellen Ihre GLSurfaceView in der Hierarchie nicht von onResume (), sondern von onWindowFocusChanged () wieder her:
Beachten Sie, dass Sie niemals onPause () und onResume () des GLSurfaceView aufrufen und dass dies das offizielle SDK GLSurfaceView ist. Es ist keine gehackte alternative Version erforderlich.
quelle
<rant> Ich habe sehr viel Zeit mit diesem Problem verbracht, ich habe viele verschiedene Lösungen ausprobiert und bis heute hat keine funktioniert. Ich denke, dies ist eine der schrecklichsten Designentscheidungen, die ich je gesehen habe, aber ich komme nicht vom Android-Team wirklich überrascht. </ rant>
Die Lösung besteht also darin, das eglContext-Member nach oben zu verschieben und statisch (global) zu machen, damit es nicht zerstört wird. Sie müssen dann lediglich prüfen, ob es null ist oder nicht, bevor Sie es erneut erstellen.
Bisher scheint diese Lösung für uns zu funktionieren, und es ist uns egal, ob sie auf 2005-Geräten funktioniert.
quelle
Verwenden Sie die Waben-API. Es gibt eine Option, um den OGL-Kontext beizubehalten. Andernfalls müssen Sie Ihren Kontext neu laden. Es ist weder schwierig noch schmerzhaft.
Sie müssen verstehen, dass es zwei Fälle gibt (Android 2.1):
Hinweis: Alte Android-GPUS unterstützen keine Multi-Kontext. Der OpenGL-Kontext geht also verloren, wenn Sie zu einer anderen Anwendung wechseln => Keine Lösung verfügbar (Sie können hacken, um Ihren Kontext in der Bildschirmpause beizubehalten).
Hinweis 2: Die HoneyComb-Funktion ist setPreserveEGLContextOnPause
quelle
Einige der hier aufgeführten Antworten sind für die frühzeitige Verwendung von OpenGL ES unter Android angemessen. Die ersten GLES-Geräte unterstützten nur einen einzigen Kontext, daher wurde GLSurfaceView so konzipiert, dass der Status aggressiv verworfen wird. GLSurfaceView davon zu überzeugen, etwas anderes zu tun, ist nicht einfach.
Für neuere Versionen von Android (wahrscheinlich alles, was GLES 2.x verwendet) ist die beste Antwort, ein einfaches SurfaceView zu verwenden und Ihre eigene EGL- und Thread-Verwaltung durchzuführen. In Grafika finden Sie mehrere Beispiele für GLES, die mit einer einfachen SurfaceView verwendet werden , einschließlich einer Bibliothek einfacher Klassen zum Erstellen und Löschen von EGL-Kontexten.
Es ist immer noch eine gute Praxis, den Status zu entladen, wenn eine App in den Hintergrund tritt, aber für das Beispiel von Chris Pruett - wo die App noch im Vordergrund stand, aber die Aktivität, die das GLSurfaceView hostet, deaktiviert wurde - gibt es keinen Grund zum Zerreißen den Kontext durchgehen.
quelle