Hi Android Developers,
What is the best way to interrupt a current rendering phase of GLSurfaceView and start a new one when mode is equal to "Render_when_dirty"? I artificially stop rendering in "onDraw" method by checking a flag and returning from actual rendering method which is called in "onDraw" method; then, in main thread's context i call "requestRender()" to refresh the scene. However, due to a reason that i am not aware of, some of the intermediary old frames are displayed for a very very short period of time(on the other hand, they endure for so long period of time that users can realize the transition); before actual scene is rendered by opengl es 2.x engine. It doesn't affect anything at all; but troublesome to be fixed. What do you suggest?
P.S. Throwing InterruptedException within onDraw method is useless due to the destruction of actual rendering thread of GLSurfaveView.
Kind Regards.
When you say some of the old frames are drawn - do you mean part of the frame that is drawn is old or multiple calls of onDraw() still lead to some of the old information being shown on the display.
There are a few things I can see happening here. If you have a onDraw() like this:
onDrawFrame(){
... stuff ...
if (stateVariableSet)
return;
... stuff ...
my understanding is that when the function is done being run, that the back/front buffer get swapped and drawn. One thing that could be happening here is that you see a few calls of onDrawFrame() being rendered while you try to update the state/State variable.
On the other hand, if you have something like this:
onDrawFrame(){
... stuff..
semaphore.acquire(); // lock the thread waiting for the state to update
... stuff ...
then the things that have been drawn before the lock will be stale (for that frame only though - at least that's what I'd anticipate).
Also are you running on a multi-core system?
Related
Talking in context of a game based on openGL renderer :
Lets assume there are two threads :
that updates the gameLogic and physics etc. for the in game objects
that makes openGL draw calls for each game object based on data in the game objects (that thread 1 keeps updating)
Unless you have two copies of each game object in the current state of the game you'll have to pause Thread 1 while Thread 2 makes the draw calls otherwise the game objects will get updated in the middle of a draw call for that object ! which is undesirable!
but stopping thread 1 to safely make draw calls from thread 2 kills the whole purpose of multithreading/cocurrency
Is there a better approach for this other than using hundreds or thousands or sync objects/fences so that the multicore architecture can be exploited for performance?
I know I can still use multiThreading for loading texture and compiling shaders for the objects which are yet to be the part of the current game state but how do I do it for the active/visible objects without causing conflict with draw and update?
The usual approach is that the simulation thread after completing a game step commits the state into an intermediary buffer and then signals the renderer thread. Since OpenGL executes asynchronously the render thread should complete rather quickly, thereby releasing the intermediary buffer for the next state.
You shouldn't render directly from the game state anyway, since what the renderer needs to do its works and what the simulation produces not always are the same things. So some mapping may be necessary anyway.
This is quite a general question you're asking. If you ask 10 different people, you'll probably get 10 different answers. In the past I implemented something similar, and here's what I did (after a long series of optimisation cycles).
Your model-update loop which runs on a background thread should look something like this:
while(true)
{
updateAllModels()
}
As you said, this will cause an issue when the GL thread kicks in, since it may very well render a view based on a model which is half way through being rendered, which can cause UI glitches at the best case.
The straight-forward way for dealing with this would be synchronising the update:
while (true)
{
synchronized(...)
{
updateAllModels();
}
}
Where the object you synchronize with here is the same object you'll use to synchronize the drawing method.
Now we have an improved method which won't cause glitches in the UI, but the overall rendering will probably take a very severe performance hit, since all rendering needs to wait until all model updates are finished, or vise versa - the models update will need to wait until all drawing is finished.
Now, lets think for a moment - what do we really need to be synchronizing?
In my app (a space game), when updating the models, I needed to calculate vectors, check for collisions and update all the object's positions, rotations, scale, etc.
Out of all these things, the only things the view cares about is the position, rotation, scale and a few other small considerations which the UI needs to know in order to correctly render the game world. The rendering process doesn't care about a game object's vector, the AI code, collision tests, etc. Considering this, I altered my update code to look something like this:
while (true)
{
synchronized(...)
{
updateVisibleChanges(); // sets all visible changes - positions, rotations, etc
}
updateInvisibleChanges(); // alters vectors, AI calculations, collision tests, etc
}
Same as before, we're synchronising the update and the draw methods, but this time, the critical section is much smaller than before. Essentially, the only things which should be set in the updateVisibleChanges method are things which pertain to the position, rotation, scale, etc of the objects which should be rendered. All other calculations (which are usually the most exhaustive ones) are performed afterwards, and do not stop the rendering from occurring.
An added bonus from this method - when you're performing your invisible changes, you can be sure that all objects are in the position they need to be (which is very useful for accurate collision tests). For example, in the method before the last one, object A moves, then object A tests a collision against object B which hasn't moved yet. It is possible that had object B moved before object A tested a collision, there would be a different result.
Of course, the last example I showed isn't perfect - you will still need to hang the rendering method and/or the updateVisible method to avoid clashes, but I fear that this will always be a problem, and the key is minimizing the amount of work you're doing in either thread sensitive method.
Hope this helps :)
So, I'm developing a game and I'm using Canvas with SurfaceHolder to update the screen every time an object is supposed to move. That much is working fine so far. Now, the problem happens when I want to stop drawing to the Canvas and just leave it as it is based on the last drawing commands.
So one way that I tried was to simply return from the function that I call when drawing when the end condition is met. However, when I do this, the canvas starts rapidly alternating between the commands sent right when the condition was met and the commands sent one iteration before. I have no idea how or why this is happening since the drawing function is not executing any of its draw commands after the condition is met. Can anyone explain how the canvas can keep refreshing itself when it doesn't get any draw commands?
The code in the thread for locking and unlocking is pretty simple:
public void run() {
Canvas c = null;
try {
c = sh.lockCanvas(null);
synchronized(sh) {
drawCan(c);
}
}
finally {
if(c!=null) {
sh.unlockCanvasAndPost(c);
}
}
}
and the drawCan function is structured like this:
public void drawCan(Canvas c) {
/* Check if user's health is greater than 0. Don't draw anything if it is less */
if(userHealth<=0) {
return;
}
/* Drawing commands - drawRect(), drawBitmap(), etc are run here */
}
Now normally, this runs fine. But when the userHealth condition is met, the Canvas constantly alternates between the last commands sent and the commands right before that. I know that the draw functions are not being called because I used Log.d() in that area of the code and no messages appeared on LogCat after the condition was met. Can someone explain why this is happening and what the solution would be?
The Canvas is double- or triple- buffered and not erased between frames. When you call lock/unlock, you're switching between previously-rendered buffers.
If you move your if(userHealth<=0) test into run() and use it to avoid calling lock/unlock, you should get the desired effect.
For a much longer explanation about what's going on, see this post.
Update: I realized today that I'd omitted a detail (from the answer and ensuing comments). It doesn't change the answer but it may be useful to know.
The lockCanvas() method takes an optional "dirty" rect that allows you to do partial updates. If you use this, and Surface is able to keep track of the "front" buffer you just rendered, the system will copy the non-dirty contents of the front buffer to the back buffer as part of locking the Surface (see copyBlt() in Surface.cpp).
The system doesn't guarantee that this will work, which is why the "dirty" rect is an in-out parameter. If the front buffer isn't available to copy from, the lock method will just expand the dirty rect to cover the entire screen. In either case, your app is responsible for updating every pixel in the "dirty" rect; if you don't, you get the effects you observed.
This does mean that the Surface is explicitly trying to be double-buffered when used with a Canvas, which would explain why you're seeing two frames alternating rather than three even though SurfaceView is generally triple-buffered. (Which is the thing that has been nagging at me since I wrote this up.) It's also possible to be double-buffered if you're just not generating frames fast enough to require triple-buffering.
In OpenGL Renderer onDrawFrame is called several time, until the page is completely rendered. I cannot find an event that my page is completeley rendered in order to take a snapshot of the OpenGL page and animate it.
I have the solution to take snapshot on at the animation trigger (specific button), but this will imply a specific delay, until Bitmap is created, such as i would like to keep in memory a mutable copy of every page.
Do you know other way to animate GLSurfaceView with rendered content?
Snippet for triggering snapshot.
glSurfaceView.queueEvent(new Runnable() {
#Override
public void run() {
glSurfaceView.getRenderer().takeGlSnapshot();
}
});
EGLContext for passing the GL11 object.
public void takeGlSnapshot() {
EGL10 egl = (EGL10) EGLContext.getEGL();
GL11 gl = (GL11) egl.eglGetCurrentContext().getGL();
takeSnapshot(gl);
}
onDrawFrame(Gl10 gl) {
//is last call for this page event ????????????
No such event exists, as I will explain below.
OpenGL is designed as a client/server architecture, with the two running asynchronously. In a modern implementation, you can generally think of the client as the API front-end that you use to issue commands and the server as the GPU/driver back-end. API calls will do a little bit of work to validate input parameters etc, but save for a few exceptions (like glReadPixels (...)) they buffer up a command for the server to execute at a later point. You never truly know when your commands are finished, unless you explicitly call glFinish (...).
Calling glFinish (...) at the end of each frame is an awful idea, as it will create a CPU/GPU synchronization point and undo the benefits of having the CPU and GPU run asynchronously. But, if you just want to take a screenshot of the current frame every once in a while, then glFinish (...) could be an acceptable practice.
Another thing to consider, if you are using double-buffered rendering is that you may be able to access the last fully rendered frame by reading the front-buffer. This is implementation specific behavior however, as some systems are designed to discard the contents of the front-buffer after the buffer swap operation, others make reading its contents an undefined operation. In any case, if you do attempt this solution, be aware that the image returned will have a 1 frame latency (however, the process of reading it will not require you to finish your current frame), which may be unacceptable.
I have got some strange and unexpected results from my program in OpenGL ES for android for example in the code below:
matrix = ThisRot.get();
gl.glMultMatrixf(matrix, 0);
currentRotation.toMatrix(matrix);
temp.set(matrix);
I set the matrix value before I use it as an argument for gl.glMultMatrixf and after that I change the value of matrix and use it for another purpose, but it has effect an the way the object rotate so it should have effect on gl.glMultMatrixf(). and that's not the only one, some other places in my code I had this unexpected results. so I have thought maybe these happen due to mutual exclusion and multitreading and those kind of things.
am I right? should we worry about multithreading when we code in Opengl ES for android? How can I avoid these kind of problems.
Of course you should worry about multithreading. In particular, Android creates its own GLThread for rendering, when you attach a GLRenderer-derived class to a GLSurfaceView using the setRenderer() function.
In fact, multithreading can cause crashes (not only unexpected behavior) in your programs especially when you loop through arrays adding/removing objects and such.
Check if you are modifying the same data inside the onDrawFrame function of your GLRenderer and your own thread. If you are, try adding the following around the modified code (in both threads):
synchronize(variable) {
modify(variable);
}
This will lock the variable throughout the modify() function until it ends the block. Try not to overuse it, though, only in places where you need it. One thread will block the other one until it's finished!
I am currently writing an app that should display a real time measurement curve in a scrolling fashion (think ECG recorder or oscilloscope). An unexpected system call in the UI-Thread makes the display stutter.
The data rolls in via bluetooth. All works fine and the display is reasonably smoothly scrolling with an average update rate of 26 frames/s. But, nevertheless the display is stuttering remarkably.
I used traceview to get more insight and according to traceview the stuttering is the result of a call to android/view/ViewRoot.handleMessage which lasts 131 ms per call on average.
If I dig down further in traceview the cycles are burnt inside android/view/ViewRoot.performTraversals. 92% of these CPU cycles are consumed in mostly recursive calls to android/view/View.measure.
From there it gets complicated due to the recursive call structure. But I can find calls to the onMeasure() method of LinearLayout, FrameLayout and RelativeLayout. The onMeasure() method of each Layout type consumes about the same amount of CPU cycles. Which is very strange since in my activity I use only a simple LinearLayout with just 2 Elements.
I just see no reason on why a supposed re-layout of a LinearLayout with 2 Elements performs calls to non-used Layouts and takes a whopping 131 ms to do that.
Further info:
Platform HTC desire HD with Android 2.3.1.
I use a handler to perform the drawing in the UI thread.
The Layout is a simple LinearLayout with 2 Elements: a custom view and a textField.
The status bar is hidden with getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);.
The drawing is performed on each new block of data, which arrives approx. every 50 ms.
The drawing itself uses a canvas and is performant enough to keep up with the incoming data.
After that long explanation, here are the questions:
What is calling the android/view/ViewRoot.handleMessage? (the calls are relatively equal spaced every 850 ms and have no obvious link (no direct calls, number of calls and relative positions are not linked to the message handler for drawing) to any activity of my Activity)
How can I suppress the calls to android/view/ViewRoot.handleMessage or how can I make them faster (there are just 2 elements in my LinearLayout)
the calls to unused layouts first got me think of the status bar or some hidden activity (e.g. home screen), which may use such layouts. But how come those calls are part of the trace of my activity? As far as I understand the trace should only trace the active process. e.g. the calls of my service which produces the real time data is not part of the trace.
Is there any possibility to trace individual calls to some system components? When I zoom in in traceview I see this call sequence: toplevel -> android/os/Message.clearForRecycle() -> android/os/MessageQueue.nativePollOnce() -> android/os/SystemClock.uptimeMillis() -> com/htc/profileflag/ProfileConfig.getProfilePerformance() -> android/os/Handler.dispatchMessage() -> android/view/ViewRoot.performTraversals()
Off topic: Is there a possibility to export the data which is shown inside traceview (parents-children-CPU time etc.) other than a screenshot?
Ok, I found the reason for the long call to android/view/ViewRoot.handleMessage.
This was indeed caused by my application.
My App has 2 screens (Activities) one with a complicated Layout for status information and the other one the real time display of incoming data.
The data, which comes in over bluetooth contains mixed real time data and status data. When I switch to the real time Activity, I was stopping the status Activity with finish(); after starting the new real time Activity. Unfortunately this is not enough to stop also the message handler, which receives the new status information in the UI thread, and continued to update status data in an invisible and finished Activity. The relayout of this activity caused the stutter of the real time data.
This is now solved. The display scrolling is now reasonable smooth.
Thanks for your patience. May it be useful to anyone who stumbles on this Thread on stackoverflow.
jepo