Android Native Window Create, Destroy, and OpenGL Context

Started by
4 comments, last by noodleBowl 8 years, 5 months ago
This might be rough to explain, but I'm working in NDK using the Android Native activity. And Im wondering about the callbacks:
onNativeWindowCreated (ANativeActivity *activity, ANativeWindow *window)
onNativeWindowDestroyed (ANativeActivity *activity, ANativeWindow *window)
And their relation with an OpengGL context
More specifically those calls and when I should be using calls to OpenGL and creating rendering systems like a SpriteBatcher

Currently in my activity, I have it setup where the onNativeWindowCreated callback triggers the creation of a EGLDisplay, which in turn creates an OpenGL context. In addition, this trigger (the onNativeWindowCreated one) also creates my SpriteBatcher rendering class.
//In Trigger for onNativeWindowCreated 
//Code that creates and sets up opengl
CreateEGLDisplay();

//Code that creates everything needed by the sprite batcher 
//(OpenGL calls happen here, creation of buffers and etc)
spriteBatcher = new SpriteBatcher(); 

And the onNativeWindowDestroyed callback triggers a method to destroy said EGLDisplay and the sprite batcher.
//In Trigger for onNativeWindowDestroyed  
//Code that creates and sets up opengl
DestroyEGLDisplay();

//Free up the sprite batcher
delete spriteBatcher;
So I'm wondering is this how I should I be handling classes and things that make OpenGL calls? I know you need a OpenGL context in order to make those calls. But...

Since I'm destroying the context when the window is killed (which I assume is perfectly normal or what I should be doing) I'm wondering how should OpenGL textures, buffers, and etc are handled. Do I just need to recreate them each time? Is this normal? Should I be doing it differently?
Advertisement

i dont know exactly how its done i did little research and i use egl context created in java but rest is handled in c++, in order to delete oglbuffers you need to delete them inside opengl thread. So where ever you place 'glDraw' function you should make a switch like if(killme) { glDeleteBuffers, glDeleteTextures etc }

if drawing function will work then freeing should be called inside that function, anyway i am not sure how does that work in native activity (i told you the case for java es initialized thing)

anyway it should work the same for native activity, this is the one thing i hate about android : )

any way i am not sure if this is my apps fault but when its supposed to be paused (because android pauses the activity it should be reopened very fast (they say that) but the thing is it starts the app again, and uses the data from old ogl context which is now used by something else. (this is the case for wrong buffer, texture etc deletion) the best way would be to handle home and back button and kill the process (stop activity, kill it destory it) so app will crash and whole resources that are stored for the game are being set that can be rewritten tongue.png (giving Appname has stopped working on exit) well i wasnt aware of the thing that i need to destroy all objects, in opengl thread, need to write a specific function that does that (few hundred opengl glDeleteXX(); calls .... so i warn you you better list all the things you need to delete right away so you wont have to digh through whole code of the project just to see what have you created...

btw take a look at: https://groups.google.com/forum/#!topic/android-ndk/bWD2vMXOyDo

especially that sounds reasonable:

You do not need to destroy *anything* --- Android does it for you. In

fact, you can't stop it! The last point you can do anything OpenGL
related is in the SurfaceHolder.Callback.onSurfaceDestroyed() method,
which is called immediately before the context gets destroyed. As soon
as you return from this method, your OpenGL context is invalid and you
must not touch it (or bad stuff happens).

It would be nice if Android actually caught attempts to access the
context when it was invalid and failed gracefully, but... this does not
seem to happen.

What we do in our system (we make an interface layer allowing people to
write apps using OpenKODE and EGL and OpenGL, on top of various
platforms including Android: see http://antixlabs.com) is that when the
game calls eglSwapBuffers() from the rendering thread it takes and
releases a semaphore. When onSurfaceDestroyed() is called from the UI
thread we take this semaphore and wait. This causes the rendering thread
to halt at a known point. Once this has happened we change state so that
the rendering thread no longer accesses the OpenGL context, and then
allow Android to proceed to destroy it. It was a pig to get right, but
does actually appear to work.

any way i am not sure if this is my apps fault but when its supposed to be paused (because android pauses the activity it should be reopened very fast (they say that) but the thing is it starts the app again, and uses the data from old ogl context which is now used by something else. (this is the case for wrong buffer, texture etc deletion) the best way would be to handle home and back button and kill the process (stop activity, kill it destory it) so app will crash and whole resources that are stored for the game are being set that can be rewritten tongue.png (giving Appname has stopped working on exit) well i wasnt aware of the thing that i need to destroy all objects, in opengl thread, need to write a specific function that does that (few hundred opengl glDeleteXX(); calls ....


This part is what I'm curious about. So let me explain with the Android lifecycle steps (I think this would make more sense).

So lets say we are running, the user can see our app and they can interact with it. Then they hit the home button.
The app will go into the back ground. So Android does its callbacks:

onPause() <- onNativeWindowDestroyed gets called right about here in my case. Current OpenGL context is destroyed
onStop()

In the onPause() you lose the OpenGl context right? So all of your buffers, textures, and etc for OpenGL are invalidated.
Now to simplify my question, what should one do when the user reopens the app. So the Android system preforms the callbacks:

onRestart()
onStart()
onResume() <- onNativeWindowCreated gets called right about here in my case. New OpenGl context

That is what I'm not really sure how to handle

i really dont know for now, i just did a quick test because

in order to setup egl in java you have to set GLSurfaceView etc it has something like Pause and Resume Method


//this is code from java activity

	@Override
	protected void onPause() {
		super.onPause();

		if (rendererSet) {
//			glSurfaceView.onPause();
		}
	}

	@Override
	protected void onResume() {
		super.onResume();

		if (rendererSet) {
//			glSurfaceView.onResume();
		}
	}

like you see i commented these out and hit home button then reopened the applciation it opened in less than 2 seconds

i tried even to open other programs after launching my app, and then had to hold home button and select my app, it opened in less than 2 seconds again, so i think its up to you if you want to delete contex or pause the rendering just by using some switch liek if(notpaused) glDraw();

im not sure what happnes if other application will request the memory that is taken by your app (if it will take it) or wont launch at all

so hitting back button doesnt seem to pause the application (looks like home button does that only)

i think overriding these onpause onresume will allow you to do pretty much the same thing, still hittong back button needs to be properly handled (properly destroying all shaders, textures, buffers) <- that pisses me off coz i have lots of classes that have implemented destructors and they are 'static' meaning i dont do someclass * ashader = new someclass(); then delete ashader;

its just someclass ashader;

If you follow the life-cycle documentation, then you shouldn't have a problem. If you OpenGLES context was not created with the capability to preserve objects, then whenever the associated EGL window is changed ( modified/deleted ) you will have to delete all objects and recreate them when window is recreated. Also since the context requires an active EGL window, you will have to destroy all context objects prior to window getting destroyed.


onPause() <- onNativeWindowDestroyed gets called right about here in my case. Current OpenGL context is destroyed
onStop()

In the onPause() you lose the OpenGl context right? So all of your buffers, textures, and etc for OpenGL are invalidated.
Now to simplify my question, what should one do when the user reopens the app. So the Android system preforms the callbacks:

onRestart()
onStart()
onResume() <- onNativeWindowCreated gets called right about here in my case. New OpenGl context

That is what I'm not really sure how to handle


You objects are invalidated, thus you MUST recreate them. Its a royal pain, but you seems to be on the right track.

You objects are invalidated, thus you MUST recreate them. Its a royal pain, but you seems to be on the right track.


Do all of my objects (non OpenGL buffers, textures, shaders, and etc) still exist?
EG If I create a Texture Class does the object that is the Texture Class till exist when my application things go into the background? Basically I only need to reload the texture, but I can still use the same container

Tips on how I should be handling m app coming back into the background? EG a switch:


//In the On Start (or my case onNativeWindowCreate)
switch(APP_STATE)
{
   case MENU:
       LoadMenuTextures();
   break;

   case LEVEL1:
       LoadLevelOneTexture();
   break;

   //Other things like it
}

This topic is closed to new replies.

Advertisement