Android Activity lifecycle and OpenGL ES 2.0 (VBOs, Shaders,..) - android

Could you describe me when I should recreate vbos, shaders, textures? I know that OpenGL functions are called in separated thread. I call GLSurfaceView's method onResume in Activity's onResume (the same with onPause method).
When the GLContext is lost?
Let's assume that the user touch home button. Activity's onPause method is called. Should I delete vbo, shaders, textures? Or should I delete those resources when onDestroy is called (resume GL Thread to delete them?)? What if user touch back button?
The another question. Should I keep bitmaps, vertices attributes in Java to reinit VBOs, Textures?
Now I delete all shaders, vbos & textures each time the Activity's onPaused method is called. I send a special event to event queue. In onSurfaceCreated I reinit all resources. It's working but it's not fast & it consumes a lot of memory. Is there a better solution?

As long as you are using GLSurfaceView , dont worry about deletion of OpenGL resources. Everytime user clicks home button / back button the EGL context and all the resources associated with that context (textures,VBOs,shaders) will be deleted. So it is your responsibility to create them in onSurfaceCreated() method.
Moreover I dont think deleting resources in onDestroy() will work because there wont be a valid EGL context available there.

Related

OpenGL ES 2.0 works only once

I'm successfully drawing simple shapes on my GLSurfaceView using OpenGL ES 2.0. So far i'm not using any textures. The problem is that when i re-run for the second time the activity with GLSurfaceView the screen is empty (black), shapes are not being drawn again. I have to reinstall the whole app to make it work again.
I don't have any special methods onPause & onResume so i assume the new instance of GLSurfaceView should redraw the screen each time i re-run the application.
Does anyone have any clue what am i missing here?
I don't have any special methods onPause & onResume
That's likely your problem. You need to follow the documentation of GLSurfaceView, specifically what it says under "Activity Life-cycle":
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.

glCreateProgram returns 0 after context restore

I'm working on an Android OpenGL ES 2.0 program coded natively. In my Activity's onPause method I call the GLSurfaceView's onPause method, then call a native function which glDeletes all textures and shader programs. In the Activity's onResume method I call the GLSurfaceView's onResume method then call a native function which recreates all of the textures and shader programs. The GLSurfaceView methods I mentioned are not overridden. The textures seem to recreate without hassle (no glGetErrors after each call) but glCreateProgram is giving me zero and glGetProgramiv(program, GL_LINK_STATUS, &linkResults) crashes the app. This happens only with onPause/onResume, before then the shaders are created without a problem. Any insight you could offer would be greatly appreciated.

How to save OpenGL textures when lose context on Android

Our game requires that several large textures are built up dynamically from small images, and we don't keep a data copy of the textures, we just use OpenGL with glTexSubImage2d to update the actual textures.
When Back is pressed, or the game loses focus, we want to save these textures to ram, so if the user then goes back to the game, we can recreate/reload them in onSurfaceCreated. We already reload from 'disk' all static textures.
However, its proving hard to find out where we can get a message to know that we are about to lose the EGL context. If we set a flag in the main activity's onBackPressed then check that flag in the main render loop, we can save the textures there, but we can't access the textures from the main activity, so putting the call in the main activity's onStop callback is too late. There is no subsequent render loop to save the textures, as, well, its stopped by then. We need to do this as there will be other ways where onStop is called other than pressing the Back button.
Supposedly I can't delay onStop to get one more "render" in either. Any other ideas ?
Since you already generate this textures dynamically during the cold start of your application, it may be a good point just to part this textures dirty and regenerate them just as if your application was starting cold.
If you want to save those textures then don't wait for onStop() to be called. Just save them once you have generated their content.
It sounds as a problem of synchronising threads. The button pressed event or the onPause event (in case another app goes to the front) runs on the main (UI) thread, while the opengl render has his own thread. When the events on UI thread are triggered, you set a flag and wait on a condition_variable. the render thread checks always the flag, and when it is set then saves the textures, changes the condition of the condition_variable and notifies the UI thread.

GLSurfaceView renderer, how to force surface re-creation?

I have a GLSurfaceView renderer and method onSurfaceCreated is called only once (basically only when activity is created or re-created).
I need to test behavior when EGL context is lost and surface is recreated during normal activity life cycle, however I am unable to put app into such situation no matter what I do.
Is there anything that I can do to simulate situation in which is onSurfaceCreated called again? How to make my app lose EGL context?
Edit: After a few days I noticed that the problem was gone and the app started to behave properly as said in specs:
public abstract void onSurfaceCreated (GL10 gl, EGLConfig config)
Called when the surface is created or recreated.
Called when the rendering thread starts and whenever the EGL context is lost.
The EGL context will typically be lost when the Android device awakes
after going to sleep
Before that, every time the device went to sleep, the activity was destroyed and recreated on awake which was preventing me to test if the code in OnSurfaceCreated worked well.
Now it behaves much better when sleep/awake occurs - it usually does not destroy the activity and just calls OnSurfaceCreated method which is the situation I was aiming for.
I'm not sure but the only thing that i can think of is to switch the GLSUrfaceView with a new one using the same GLSurfaceView.Renderer.
That should create a new EGL context and call the onSurfaceCreated() a second time.
According to the documentation, GLSurfaceView.Renderer.onSurfaceCreated is called when the surface is created or recreated.
Called when the rendering thread starts and whenever the EGL context is lost. The EGL context will typically be lost when the Android device awakes after going to sleep.
Have you tried locking your device's screen and unlocking it?
Maybe you can look at onScreenStateChanged method but it's available for API 16 or higher. If you mean "pausing and resuming the activity" by "normal activity life ciycle" maybe you can use onPause or onResume to track this.
What exactly do you want to do with onSurfaceCreated() ? You can force the rendering by requestRender() method of SurfaceView and do the necessary calculations inside onDrawFrame() of GLSurfaceView.Renderer
If your view is in a fragment, you can detach and re-attach the fragment.

Andengine get pixels from RenderTexture when game pauses

Here is the situation, I need to save the pixels from a RenderTexture and store them into a Bitmap when the game activity pauses (home button was pressed), and restore the render texture with the Bitmap that was saved.
Currently I'm doing the following:
In onPause register a Draw Handler to the engine that calls getBtimap() on the render texture, then call RenderSurfaceView.reqestRender() method, to force redraw and then Thread sleep for 1 second, to ensure that drawing will happen, and then finally call super.onPause().
I think this is not a good method :).
The problem is that RenderTexture.getBitmap() have to be called in the render thread because is calling glReadPixels() which needs a GL context to be executed properly.
So is there anyway to get notified before the GL context is destroyed ?
Or any suggestions on how this could be done in a different way ?

Categories

Resources