2
\$\begingroup\$

I'm developing simple Android game in OpenGL ES 2.0 and the development stage is getting closer to publishing game on play store, but I'm still unsure about EGL context behaviour on different devices.

GLSurfaceView Android documentation says:

A GLSurfaceView must be notified when the activity is paused and resumed. GLSurfaceView > clients are required to call onPause() when the activity pauses and onResume() when the > activity resumes. These calls allow GLSurfaceView to pause and resume the rendering thread, and also allow GLSurfaceView to release and recreate the OpenGL display.

Problem is that I don't want my game to recreate and reload all textures after every activity change or home button press, it really breaks user experience, so I don't invoke onPause and onResume methods on my GLSurfaceView in order to not loose my OpenGL assets. This approach works perfectly on some devices I've tested - Nexus 7 and Lenovo Yoga Tab 2, but I'm afraid it may cause some unexpected results on some specific devices. What are the drawbacks of this approach? Can I workaround EGL context lost in some other way?

I've read many resources about this subject but most of them are related to Android in version 2.x and were written 3-4 years ago. I'm targeting minimum API 16 which is Android 4.1.x, so maybe there are some new ways to work this out?

I did use some custom GLSurfaceView implementations as the one from Chris Pruett's game Replica Island but as I've said those workarounds were targetting older Android versions and still they didn't let me solve my problem. I was also trying using setPreserveEglContextOnPause method on GLSurfaceView but it doesn't seem to work.

\$\endgroup\$
  • \$\begingroup\$ To add to Sandalfoot's (comprehensive) answer: did you checked the power/CPU consumption of your app when the user sends the app in background? The main use of onPause/onResume in GLSurfaceView is to prevent the app from rendering in background when the user switches to something else: failing to do so will cause the battery to drain at alarming rates, and that's a sure way leading to bad reviews and application uninstalls... \$\endgroup\$ – R1ck77 Feb 20 '16 at 15:18
1
\$\begingroup\$

It's not just the EGL Context that gets lost; Android can (and will) simply kill any application running in the background when it's running low on resources and needs to reclaim them. There's simply no guarantee that your app won't have been unloaded since you last left it.

When your activity receives a call to the onStop() method, it's no longer visible and should release almost all resources that aren't needed while the user is not using it. Once your activity is stopped, the system might destroy the instance if it needs to recover system memory. In extreme cases, the system might simply kill your app process without calling the activity's final onDestroy() callback, so it's important you use onStop() to release resources that might leak memory.

Although the onPause() method is called before onStop(), you should use onStop() to perform larger, more CPU intensive shut-down operations, such as writing information to a database.

Android documentation on stopping Activities

In situations where the system needs more memory it may kill paused processes to reclaim resources. Because of this, you should be sure that all of your state is saved by the time you return from this function.

Android API onPause() method

Also, see the accepted answer to this question. The documentation on setPreserveEglContextOnPause indicates that it only works on devices that support multiple OpenGL contexts.

In short, you can't guarantee anything. Best to find another workaround.

\$\endgroup\$
  • \$\begingroup\$ Thank you for your answer. I'm aware that Android will kill application when running low on resources and I've written my engine to recreate resources after such case. I'm curious if my not pausing/resuming GLSurfaceView in Actiivity onPause method will cause any other issues than memory leak. As I understand this memory leak will be handle some time in the future by Android killing my application. I'm not afraid of reloading textures after context lost, but I do not want to reload them after every onPause/onResume events and that's why I'm skipping invoke of pause/resume on my GLSurfaceView. \$\endgroup\$ – Tomasz Lechman Jul 22 '15 at 3:55
  • \$\begingroup\$ Yes, it will keep your render thread from pausing - at least that's what the documentation for GLSurfaceView implies. And again, if you pause on a device that doesn't support multiple contexts your original problem still stands. \$\endgroup\$ – Sandalfoot Jul 22 '15 at 18:39
  • \$\begingroup\$ I don't understand why you've mentioned multiple contexts and correct me if I'm wrong but I thought that every OpenGL application gets its own OpenGL context, so not pausing it in my application should only affect this particular application. But if I'm wrong then how would devices without support for multiple contexts behave with my not pausing/resuming GLSurfaceView? If they would simply kill my context then I will just reload textures in onCreateSurface() and show loading screen but still got it solved for atleast these devices that do support multiple contexts. \$\endgroup\$ – Tomasz Lechman Jul 23 '15 at 4:01
  • \$\begingroup\$ Your original question asked if your solution would have any unforeseen side effects, and I pointed out that yes, they probably would on certain devices. If you intend to only "solve" the problem on certain devices anyway then it doesn't really matter. I was just pointing out that you probably can't come up with a one-size-fits all solution, here. And I mentioned multiple contexts because that's exactly why OpenGL would kill your context; because the device can't support each app having its own. \$\endgroup\$ – Sandalfoot Jul 23 '15 at 18:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.