aslater
aslater

Reputation: 105

Preventing Android GL Context loss

Apologies for raising this issue again as i'm sure its been done to death already. :)

However i'm converting a fully native game over to Android and i'm now looking into handling GL context loss.

As we maintain a list of 'resources' within our game that contain the GL assets i'm able to spin through them and restore the GL context. However, though this works in a simplified test application i'm a little concerned that as context loss can occur at any time, i suspect i'll have to modify other game areas, (threaded resource handling for a start), to make sure i'm covering everything.

At the back of my mind i can't help feeling that preventing the context loss from occurring might be a safer option for the range of devices i need to support, (all less than 2yrs old), and using API8.

As a first pass at this to determine if this would was actually viable on the i simply created a static EGLContext in my extended GLSurfaceView class implementation and created the context into this, (our native Android applications are based around the hello-gl2jni example in the android ndk):

public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig) {
  if (mEGLContext == null)
  {
    ...
    mEGLContext = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list);
  }
  return mEGLContext;
}

I then simply removed the destroy context call:

public void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context) {
  //egl.eglDestroyContext(display, context);
}

Then on application re-entry, through pressing Home then selecting the application from the Recent Apps List button, the application crashed. Here is the trace log:

// home button pressed
05-23 17:04:26.784: W/GlContextTrace(11504): Activity State Change: 'onPause' (pausing)
05-23 17:04:26.808: W/GlContextTrace(11504): 'GLSurfaceView.EGLContextFactory::destroyContext' (doesn't actually call eglDestroyContext)
05-23 17:04:27.519: W/GlContextTrace(11504): Activity State Change: 'onStop'

// application re-entry
05-23 17:04:30.089: W/GlContextTrace(11504): Activity State Change: 'onRestart'
05-23 17:04:30.089: W/GlContextTrace(11504): Activity State Change: 'onStart'
05-23 17:04:30.089: W/GlContextTrace(11504): Activity State Change: 'onResume'
05-23 17:04:30.229: W/GlContextTrace(11504): 'GLSurfaceView.EGLContextFactory::createContext' (uses the  previously created GL context)

// which immediately invokes destroyContext and ends my application:
05-23 17:04:30.315: W/GlContextTrace(11504): 'GLSurfaceView.EGLContextFactory::destroyContext'
05-23 17:04:30.479: W/GlContextTrace(11504): Activity State Change: 'onPause'
05-23 17:04:30.636: W/GlContextTrace(11504): Activity State Change: 'onStop'
05-23 17:04:30.636: W/GlContextTrace(11504): Activity State Change: 'onDestroy'

The crash log was:

05-23 17:04:30.401: W/dalvikvm(11504): threadid=11: thread exiting with uncaught exception (group=0x40a361f8)
05-23 17:04:30.409: E/AndroidRuntime(11504): FATAL EXCEPTION: GLThread 753
05-23 17:04:30.409: E/AndroidRuntime(11504): java.lang.RuntimeException: eglMakeCurrent failed: EGL_SUCCESS
05-23 17:04:30.409: E/AndroidRuntime(11504):    at android.opengl.GLSurfaceView$EglHelper.throwEglException(GLSurfaceView.java:1178)
05-23 17:04:30.409: E/AndroidRuntime(11504):    at android.opengl.GLSurfaceView$EglHelper.throwEglException(GLSurfaceView.java:1170)
05-23 17:04:30.409: E/AndroidRuntime(11504):    at android.opengl.GLSurfaceView$EglHelper.createSurface(GLSurfaceView.java:1081)
05-23 17:04:30.409: E/AndroidRuntime(11504):    at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1433)
05-23 17:04:30.409: E/AndroidRuntime(11504):    at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1216)

I was a little surprised at the crash though i think it highlights that i don't fully understand the process here.

Does anyone now how i can modify my GLSurfaceView class implementation to prevent GL context loss and be able to successfully re-enter the application without crashing so i can test is this option is worth following?

I should say that i'm attempting to do this myself so i'll post the answer if i work out how to do it. :)

Many thanks,

Andy Slater

Upvotes: 2

Views: 8055

Answers (1)

Thomas Calc
Thomas Calc

Reputation: 3014

On Android, you shouldn't forcefully retain the GL context. On mobile devices, depending on the device capabitilies, it is normal that your application is asked or expected to release the context (and later it will get it back).

Instead of retaining it, you should reload your game resources when the GL context is available again. A good place to do this is the Renderer.onSurfaceCreated event. This method is called by the GL renderer thread whenever your context is created or recreated (i.e. when your previously lost context is given back to you).

So you don't need to worry that the GL context is lost and you won't know about it: when the context is regained, onSurfaceCreated will ALWAYS be called, you can be sure about this.

On a side note, in an Android application, you should pause your GLSurfaceView in your Activity.onPause(), and resume it in your Activity.onResume(). These can be accomplished via GLSurfaceView.onPause() and onResume().

Upvotes: 6

Related Questions