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 boolean errored_ = false;
private boolean onceSurfaceCreated_ = false;
private boolean contextLost_ = false;
@Override
public void onDrawFrame(GL10 gl) {
if (errored_) {
return;
}
if (contextLost_) {
return;
}
try {
Ebitenmobileview.update();
} catch (final Exception e) {
@ -54,7 +59,17 @@ class EbitenSurfaceView extends GLSurfaceView implements RenderRequester {
@Override
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
@ -76,6 +91,7 @@ class EbitenSurfaceView extends GLSurfaceView implements RenderRequester {
setEGLContextClientVersion(3);
setEGLConfigChooser(8, 8, 8, 8, 0, 0);
setRenderer(new EbitenRenderer());
setPreserveEGLContextOnPause(true);
Ebitenmobileview.setRenderRequester(this);
}
@ -83,6 +99,12 @@ class EbitenSurfaceView extends GLSurfaceView implements RenderRequester {
((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
public synchronized void setExplicitRenderingMode(boolean explicitRendering) {
if (explicitRendering) {

View File

@ -315,6 +315,12 @@ func (g *Graphics) NeedsRestoring() bool {
if runtime.GOOS == "js" {
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()
}

View File

@ -15,8 +15,6 @@
package restorable
import (
"runtime"
"github.com/hajimehoshi/ebiten/v2/internal/debug"
"github.com/hajimehoshi/ebiten/v2/internal/graphicscommand"
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
@ -44,10 +42,9 @@ func EnableRestoringForTesting() {
// images is a set of Image objects.
type images struct {
images map[*Image]struct{}
shaders map[*Shader]struct{}
lastTarget *Image
contextLost bool
images map[*Image]struct{}
shaders map[*Shader]struct{}
lastTarget *Image
}
// theImages represents the images for the current process.
@ -91,23 +88,19 @@ func RestoreIfNeeded(graphicsDriver graphicsdriver.Graphics) error {
if !forceRestoring {
var r bool
if canDetectContextLostExplicitly {
r = theImages.contextLost
} else {
// 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.
for img := range theImages.images {
// The screen image might not have a texture. Skip this.
if img.imageType == ImageTypeScreen {
continue
}
var err error
r, err = img.isInvalidated(graphicsDriver)
if err != nil {
return err
}
break
// 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.
for img := range theImages.images {
// The screen image might not have a texture. Skip this.
if img.imageType == ImageTypeScreen {
continue
}
var err error
r, err = img.isInvalidated(graphicsDriver)
if err != nil {
return err
}
break
}
if !r {
@ -265,8 +258,6 @@ func (i *images) restore(graphicsDriver graphicsdriver.Graphics) error {
}
}
i.contextLost = false
return nil
}
@ -283,14 +274,3 @@ func InitializeGraphicsDriverState(graphicsDriver graphicsdriver.Graphics) error
func MaxImageSize(graphicsDriver graphicsdriver.Graphics) int {
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"
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/internal/restorable"
"github.com/hajimehoshi/ebiten/v2/internal/ui"
)
@ -113,10 +112,6 @@ func Resume() error {
return ui.Get().SetForeground(true)
}
func OnContextLost() {
restorable.OnContextLost()
}
func DeviceScale() float64 {
return ui.Get().DeviceScaleFactor()
}