Opengl-es calling onDrawFrame manually - android

I am creating a game loop and I need to be able to call onDrawFrame (from inside the renderer manually) in order to "skip frames" if I find that I am falling behind on processes.
Currently I have a GLSurfaceView class that calls
setRenderer(glSurfaceRenderer);
With this set up I understand that onDrawFrame is called every tick.
I tried putting the above call inside a method so that I could call it from inside my game loop but on the second run of the game loop I crash with the message saying
setRenderer has already been called for this instance
Is there a way to call the renderer manually every frame
Will just calling the
onDrawFrame
method work properly. Or is it not good practice to control the renderer in such a way when using openGL

I don't see how calling setRenderer() nor manually calling onDrawFrame() in the game loop will solve anything. You should refactor your rendering calls to take into account the time it takes draw so in other words time based animation. In any case manually calling onDrawFrame() without a call to eglMakeCurrent() before any drawing calls won't work as you have both the renderer and game loop thread drawing.
Edit: Since you are using GLSurfaceView, you can call requestRender() from your game loop to trigger a render if you feel RENDERMODE_CONTINUOUSLY is too slow for you.

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.

where to put infinite loop in android app to handle tweens

I would like to make use of the universal tween engine in my pure android app, and understand that I will need to put a loop somewhere which will update the tweenmanager every frame. I have used this before in game projects where i have access to the game loop provided but in the case of a pure android application, where would I create this loop and what is the best way to handle this as my app is opened/closed/paused/resumed etc?
Am I best creating a new thread in the onResume method for each activity and starting the loop there and ending the loop in the onPause method? or is it better to create a class that acts as a sort of "Activity manager" and is always available? if so how would I do this?
I found some useful documentation on this at https://code.google.com/archive/p/java-universal-tween-engine/wikis/AndroidUI.wiki and It seems the 'correct' way to achieve this is to create a new loop for each activity in onResume() and end the loop in onPause()
There is an API available starting in API level 16 called Choreographer. This is the thing that keeps the main thread pumping events at 60 frames per second. You can register a callback to be executed with the next frame, then within that callback, register to run it again at the next frame. This is the most reliable way to get called at every frame with near-perfect timing (as long as the main thread is not being blocked in a way that would case frame loss).
Your callbacks will all be called on the main thread, so be careful yourself about blocking the main thread. So keep your work super fast.

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.

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 ?

How to change content view from a GLSurfaceView?

I'm working on a small game and I'm having problems changing my Activity's content view when a GLSurfaceView is set, let me describe how the app works:
The app has only one Activity, it starts with a static view: setContentView(R.layout.main);, when the user sends a certain input using menus a GLSurfaceView is instantiated and set via setContentView(gameSession); (where gameSession is the class extending GLSurfaceView). The GLSurfaceView class then sets the Renderer on which the real application logic runs.
What happens now is that the game logic (ran inside the Renderer) is the one responsible for knowing when the game is over and the view should change back to R.layout.main, the Renderer then calls a synchronized method on the GLSurfaceView, which notifies the Activity to be changed (again with setContentView(R.layout.main);).
And here comes the problem, as soon as setContentView(R.layout.main); is called everything hangs, the GLSurfaceView is still there (just not getting updated anymore). I fear that I'm experiencing a deadlock, with the Activity waiting for the Renderer to be done before removing it.
I've been thinking on a few solutions but all of them bring other issues:
Having the GLSurfaceView or the Activity see if the game is over by polling a flag on the Renderer, but there is no loop on those classes, (and the onDraw on the GLSurfaceView is never called)
Using the queueEvent() method, but the Renderer class doesn't have it (and using GLSurfaceView.queueEvent() doesn't work because the Runnable remains of the Renderer thread)
Implementing some kind of message thread only to check for game end, but that sounds like a waste of resources.
Has any one of you experienced a similar issue? What's the best way to change your Activity's content view from a GLSurfaceView to something else if the logic for when to swap is on the Renderer?
You shouldn't be calling setContentView() multiple times.
You could instead use multiple activities, calling finish() on your game activity when you're done with it to return to the static view Activity.

Categories

Resources