cmd/ebitenmobile: use setPreserveEGLContextOnPause(true)

setPreserveEGLContextOnPause(true) suppresses context losts, and
basically we will no longer need our restoring logic.

Updates #805
This commit is contained in:
Hajime Hoshi 2024-01-08 03:50:14 +09:00
parent 9539a87b17
commit a30f075896
4 changed files with 44 additions and 41 deletions

View File

@ -33,12 +33,17 @@ class EbitenSurfaceView extends GLSurfaceView implements RenderRequester {
private class EbitenRenderer implements GLSurfaceView.Renderer { private class EbitenRenderer implements GLSurfaceView.Renderer {
private boolean errored_ = false; private boolean errored_ = false;
private boolean onceSurfaceCreated_ = false;
private boolean contextLost_ = false;
@Override @Override
public void onDrawFrame(GL10 gl) { public void onDrawFrame(GL10 gl) {
if (errored_) { if (errored_) {
return; return;
} }
if (contextLost_) {
return;
}
try { try {
Ebitenmobileview.update(); Ebitenmobileview.update();
} catch (final Exception e) { } catch (final Exception e) {
@ -54,7 +59,17 @@ class EbitenSurfaceView extends GLSurfaceView implements RenderRequester {
@Override @Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) { public void onSurfaceCreated(GL10 gl, EGLConfig config) {
Ebitenmobileview.onContextLost(); if (!onceSurfaceCreated_) {
onceSurfaceCreated_ = true;
return;
}
contextLost_ = true;
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
onContextLost();
}
});
} }
@Override @Override
@ -76,6 +91,7 @@ class EbitenSurfaceView extends GLSurfaceView implements RenderRequester {
setEGLContextClientVersion(3); setEGLContextClientVersion(3);
setEGLConfigChooser(8, 8, 8, 8, 0, 0); setEGLConfigChooser(8, 8, 8, 8, 0, 0);
setRenderer(new EbitenRenderer()); setRenderer(new EbitenRenderer());
setPreserveEGLContextOnPause(true);
Ebitenmobileview.setRenderRequester(this); Ebitenmobileview.setRenderRequester(this);
} }
@ -83,6 +99,12 @@ class EbitenSurfaceView extends GLSurfaceView implements RenderRequester {
((EbitenView)getParent()).onErrorOnGameUpdate(e); ((EbitenView)getParent()).onErrorOnGameUpdate(e);
} }
private void onContextLost() {
Log.v("Go", "Kill the application due to a context lost");
// TODO: Relaunch this application for better UX (#805).
Runtime.getRuntime().exit(0);
}
@Override @Override
public synchronized void setExplicitRenderingMode(boolean explicitRendering) { public synchronized void setExplicitRenderingMode(boolean explicitRendering) {
if (explicitRendering) { if (explicitRendering) {

View File

@ -315,6 +315,12 @@ func (g *Graphics) NeedsRestoring() bool {
if runtime.GOOS == "js" { if runtime.GOOS == "js" {
return false return false
} }
// On Android, `setPreserveEGLContextOnPause(true)` is called and then context loss unlikely happens.
// If this happens, Ebitengine tries to relaunch the app (#805).
if runtime.GOOS == "android" {
return false
}
// TODO: Remove the entire logic of the restoring (#805).
return g.context.ctx.IsES() return g.context.ctx.IsES()
} }

View File

@ -15,8 +15,6 @@
package restorable package restorable
import ( import (
"runtime"
"github.com/hajimehoshi/ebiten/v2/internal/debug" "github.com/hajimehoshi/ebiten/v2/internal/debug"
"github.com/hajimehoshi/ebiten/v2/internal/graphicscommand" "github.com/hajimehoshi/ebiten/v2/internal/graphicscommand"
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver" "github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
@ -47,7 +45,6 @@ type images struct {
images map[*Image]struct{} images map[*Image]struct{}
shaders map[*Shader]struct{} shaders map[*Shader]struct{}
lastTarget *Image lastTarget *Image
contextLost bool
} }
// theImages represents the images for the current process. // theImages represents the images for the current process.
@ -91,9 +88,6 @@ func RestoreIfNeeded(graphicsDriver graphicsdriver.Graphics) error {
if !forceRestoring { if !forceRestoring {
var r bool var r bool
if canDetectContextLostExplicitly {
r = theImages.contextLost
} else {
// As isInvalidated() is expensive, call this only for one image. // As isInvalidated() is expensive, call this only for one image.
// This assumes that if there is one image that is invalidated, all images are invalidated. // This assumes that if there is one image that is invalidated, all images are invalidated.
for img := range theImages.images { for img := range theImages.images {
@ -108,7 +102,6 @@ func RestoreIfNeeded(graphicsDriver graphicsdriver.Graphics) error {
} }
break break
} }
}
if !r { if !r {
return nil return nil
@ -265,8 +258,6 @@ func (i *images) restore(graphicsDriver graphicsdriver.Graphics) error {
} }
} }
i.contextLost = false
return nil return nil
} }
@ -283,14 +274,3 @@ func InitializeGraphicsDriverState(graphicsDriver graphicsdriver.Graphics) error
func MaxImageSize(graphicsDriver graphicsdriver.Graphics) int { func MaxImageSize(graphicsDriver graphicsdriver.Graphics) int {
return graphicscommand.MaxImageSize(graphicsDriver) return graphicscommand.MaxImageSize(graphicsDriver)
} }
// OnContextLost is called when the context lost is detected in an explicit way.
func OnContextLost() {
canDetectContextLostExplicitly = true
theImages.contextLost = true
}
// canDetectContextLostExplicitly reports whether Ebitengine can detect a context lost in an explicit way.
// On Android, a context lost can be detected via GLSurfaceView.Renderer.onSurfaceCreated.
// On iOS w/ OpenGL ES, this can be detected only when gomobile-build is used.
var canDetectContextLostExplicitly = runtime.GOOS == "android"

View File

@ -30,7 +30,6 @@ import (
"sync" "sync"
"github.com/hajimehoshi/ebiten/v2" "github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/internal/restorable"
"github.com/hajimehoshi/ebiten/v2/internal/ui" "github.com/hajimehoshi/ebiten/v2/internal/ui"
) )
@ -113,10 +112,6 @@ func Resume() error {
return ui.Get().SetForeground(true) return ui.Get().SetForeground(true)
} }
func OnContextLost() {
restorable.OnContextLost()
}
func DeviceScale() float64 { func DeviceScale() float64 {
return ui.Get().DeviceScaleFactor() return ui.Get().DeviceScaleFactor()
} }