2

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

aslater
  • 105
  • 2
  • 9
  • I'm not sure, but I think the GPU loses all its stuff too, when the state of the application changes. So would have to reload all resources anyway. What's your real problem about reloading them? – TheWhiteLlama May 23 '12 at 16:56
  • My concern about reloading them, (which does work for my in a native test application), is the game is much more complicated. As context loss can occur any time i may have to add extra locks to parts of the game to make sure GL context restoration fully works. As we use render targets i will also need to allocate memory to resolve the contents to so i can restore them. All fully possible however it does add extra complication with the potential for bugs to creep in. That is why i wanted to explore the route of preventing GL context loss. Thanks. – aslater May 23 '12 at 18:21

1 Answers1

6

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().

Thomas Calc
  • 2,994
  • 3
  • 30
  • 56
  • Thanks for the comment Thomas. I am currently restoring GL objects in the onSurfaceCreated event however my question concerns preventing the GL context loss through not destroying the context. This method has been used by a number of native games in the Android market place and i wanted to see if it was valid for the devices in intend to support. Thanks again for your answer though. – aslater May 23 '12 at 18:13
  • If they prevent context loss, then either they don't do it correctly, or they support devices that enable multiple contexts. But even in the latter case, I think extreme care is needed and thorough knowledge to take care of everything. You mention: "as context loss can occur any time i may have to add extra locks to parts of the game to make sure GL context restoration fully works" -- it does not occur "any time" in the sense that you can be sure that your last GL render cycle (onDrawFrame) atomically ends before the context is lost (regardless your rendering is continous or on-demand). – Thomas Calc May 23 '12 at 21:06