lockCanvas() really slow - android

Testing my game on a slower device (Orange San Francisco aka ZTE Blade) and I have been getting an appalling frame rate.
I put some debug code into the draw loop and discovered the following line is taking over 100ms:
c = mSurfaceHolder.lockCanvas();
Anyone else seen this behaviour? I temporarily replaced the surfaceview by extending View and implementing onDraw(), and I got a much better framerate.
Although in general surfaceView is much faster on my HTC Desire. I am suspicious this may be a Android 2.1 problem. I'm contemplating rooting the phone and upgrading it to 2.2 if possible, but I did want a device running on 2.1 so that might be counter-productive in the long run.
** update **
I've been working on this some more, and have discovered some more puzzling aspects to it.
I rooted the phone and installed 2.2 and the problem still happens. When the app is first started, the lockCanvas is working as expected (0-1 ms). Then at some point during my initialisation, lockCanvas suddenly starts taking approx 100ms.
It might be worth pointing out that I am loading my assets in an Async task, so that I can display a loading screen.
Despite my best efforts to pin down what the program is actually doing when the slowness occurrs I was not able to do so. In fact when I run it in debug mode and single step, it works fast!
Now I discovered that if I add a delay in the constructor of my SurfaceView (of about 10 seconds), the slowness doesn't occur and all works fine.
However if you press Home, and then switch back, the slowness comes back.
I'm pretty much at the end of my tether on this stupid illogical problem! I've got a mind to put it down to a device specific problem.
I feel it could have something to do with memory usage. Maybe something is being swapped out and it affects the video ram?
I'd be interested in theories at least.

About lockCanvas() from docs:
If you call this repeatedly when the
Surface is not ready (before
Callback.surfaceCreated or after
Callback.surfaceDestroyed), your calls
will be throttled to a slow rate in
order to avoid consuming CPU.
Is it possible that your draw loop is initiated too early for some devices? I think this is the problem, since you wrote:
Now I discovered that if I add a delay
in the constructor of my SurfaceView
(of about 10 seconds), the slowness
doesn't occur and all works fine.

So, maybe we could use holder.isCreating() to check state?
this method will return true if canvas still creating.
Something like
while(holder.isCreating()) {}
can=holder.lockCanvas();
But I'm a bit confuse now. As i know colbeck is called when a surfaceview is creates. We should implement SurfaceHolder.Callback interface. And when surface is created callback method
public void surfaceCreated(SurfaceHolder holder) { } will be called.
From surfaceCreated method I'm starting gameloop thread.

I have recently discovered that if large bitmaps are used to draw on the canvas and these bitmaps are stored in the activity class - the "_surfaceHolder.lockCanvas()" command itself takes very long (about 70ms depending on device). HOWEVER, moving these bitmaps storage to other class (in different file, say MY_DATA), and the activity has just a reference to that new class - solves the problem.
I'm have no explanation to this phenomenon.

I was encountered the same mysterious problem with Canvas drawing, but solved it by changing Canvas drawing to drawing on the SurfaceView. But now I have constantly slow lockCanvas() call.
Here is my observation results.
Problem is only present on some devices:
Galaxy Note 3 n900: has problems
Galaxy Note 3 n9005: has problems
Galaxy S4 i9505: has problems
Galaxy Gio: no problems
LG G2 D802: has problems
Galaxy S2 i9100: no problems
I temporarily replaced the surfaceview by extending View and implementing onDraw(), and I got a much better framerate
I also noticed, that Samsung phones using GLES20Canvas instead of regular Canvas with onDraw() drawing, as a result, better performance.

Related

OpenGL Runtime Exception Issue [duplicate]

I have android game, using libgdx framework
on Google Play store there are report:
java.lang.RuntimeException: eglSwapBuffers failed: EGL_SUCCESS
at android.opengl.GLSurfaceView$EglHelper.throwEglException(GLSurfaceView.java:1085)
at android.opengl.GLSurfaceView$EglHelper.swap(GLSurfaceView.java:1043)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1369)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1123)
what I can do?
devices reported : Samsung GT-S5830i, Samsung galaxy Y, LGE LG-P990 , Motorola Photon 4G, Motorola Droid X2,
This problem has been reported here before. There is already an issue filed.
You can help by providing more details to this issue.
I made some research and found out that this problem occurs in low end devices because they have low memory. Loading and unloading of textures between two scene crashes SwapBuffer and hence throws this Runtime exception.
Most annoying thing about this issue is that, when I tested in such devices, I didn't get any such error but in playstore I got too many report with this issue.
So, we can tackle this issue in two ways:
1)Filter out low end devices from compatible list.
2)Catch the exception using UncaughtExceptionHandler() and tell user about low memory problem.
Solution in last edit.
It actually did happen on my low end devices as well (GT-S5830 and GT-S5830i).
The thing is, it did not happen because of low memory; I logged the current memory usage of my game and it did not cross 3 megabytes, when I had like 80 or more megabytes of free ram. I even ran System.gc() consistently, which hints the garbage collector to free up some ram space.
I have no workaround but will update this answer as soon as I find one.
After some search, gpu related stuff (like textures) are not managed by the garbage collector (that's why they should be disposed manually). So calling System.gc() is somehow pointless. Still, I'm disposing all of my textures, and the memory usage of my game is pretty low.
I tried all sorts of solutions and nothing worked BUT here is something that should fix the problem (haven't tried this one, but should work nonetheless):
Simply don't load so much textures over and over. My game used to dispose and then initialize all textures whenever the user navigated away from a screen. That is possibly causing the problem. What you need to do is to keep the loaded textures/texture atlases in memory (don't lose their reference). That way, navigating back to a screen wouldn't reload all the textures.
Avoid using raw Textures and instead use a POT (Power Of Two) TextureAtlas.
I will apply these two steps to my project, and if the problem goes away, I'll come back to confirm my solution.
That wasn't the problem at all. I ran a really long loop of disposing and loading of textures, no exception/error was thrown. My above suggestion is not the solution. The problem is probably related to excessive Screen switching, but I guess not since this problem also happens when changing the screen orientation repeatedly from portrait mode to landscape mode and vice versa.
Solution:
I thought that Game's setScreen(screen) calls Screen's dispose() automatically (which is not the case). dispose() was used to dispose all of my underlying textures. I simply solved the problem by calling dispose() in Screen's hide() overridden method.
Using TextureAtlass is very important because you reduce the amount of handles that are attached to each Texture. (Which may be the reason of the EGL_SUCCESS error)
Tested on both GT-S5830 and GT-S5830i (Samsung Galaxy Ace and Samsung Galaxy Y). Problem no longer occurs.

java.lang.RuntimeException: eglSwapBuffers failed: EGL_SUCCESS report

I have android game, using libgdx framework
on Google Play store there are report:
java.lang.RuntimeException: eglSwapBuffers failed: EGL_SUCCESS
at android.opengl.GLSurfaceView$EglHelper.throwEglException(GLSurfaceView.java:1085)
at android.opengl.GLSurfaceView$EglHelper.swap(GLSurfaceView.java:1043)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1369)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1123)
what I can do?
devices reported : Samsung GT-S5830i, Samsung galaxy Y, LGE LG-P990 , Motorola Photon 4G, Motorola Droid X2,
This problem has been reported here before. There is already an issue filed.
You can help by providing more details to this issue.
I made some research and found out that this problem occurs in low end devices because they have low memory. Loading and unloading of textures between two scene crashes SwapBuffer and hence throws this Runtime exception.
Most annoying thing about this issue is that, when I tested in such devices, I didn't get any such error but in playstore I got too many report with this issue.
So, we can tackle this issue in two ways:
1)Filter out low end devices from compatible list.
2)Catch the exception using UncaughtExceptionHandler() and tell user about low memory problem.
Solution in last edit.
It actually did happen on my low end devices as well (GT-S5830 and GT-S5830i).
The thing is, it did not happen because of low memory; I logged the current memory usage of my game and it did not cross 3 megabytes, when I had like 80 or more megabytes of free ram. I even ran System.gc() consistently, which hints the garbage collector to free up some ram space.
I have no workaround but will update this answer as soon as I find one.
After some search, gpu related stuff (like textures) are not managed by the garbage collector (that's why they should be disposed manually). So calling System.gc() is somehow pointless. Still, I'm disposing all of my textures, and the memory usage of my game is pretty low.
I tried all sorts of solutions and nothing worked BUT here is something that should fix the problem (haven't tried this one, but should work nonetheless):
Simply don't load so much textures over and over. My game used to dispose and then initialize all textures whenever the user navigated away from a screen. That is possibly causing the problem. What you need to do is to keep the loaded textures/texture atlases in memory (don't lose their reference). That way, navigating back to a screen wouldn't reload all the textures.
Avoid using raw Textures and instead use a POT (Power Of Two) TextureAtlas.
I will apply these two steps to my project, and if the problem goes away, I'll come back to confirm my solution.
That wasn't the problem at all. I ran a really long loop of disposing and loading of textures, no exception/error was thrown. My above suggestion is not the solution. The problem is probably related to excessive Screen switching, but I guess not since this problem also happens when changing the screen orientation repeatedly from portrait mode to landscape mode and vice versa.
Solution:
I thought that Game's setScreen(screen) calls Screen's dispose() automatically (which is not the case). dispose() was used to dispose all of my underlying textures. I simply solved the problem by calling dispose() in Screen's hide() overridden method.
Using TextureAtlass is very important because you reduce the amount of handles that are attached to each Texture. (Which may be the reason of the EGL_SUCCESS error)
Tested on both GT-S5830 and GT-S5830i (Samsung Galaxy Ace and Samsung Galaxy Y). Problem no longer occurs.

Open GL stutter when rendering on Galaxy S2

Our Android game has an issue which appears unique to the Galaxy S2.
Occasionally the render will stutter. By this I mean it basically seems to render the last two frames (as though its swapping the last two render buffers without updating either).
What's really odd about this is that the game continues to update, so say the stutter lasts for 2 seconds, the game will have progressed 2 seconds behind the scenes.
This is odd because our code is basically like this:
function Update()
DoGameLogic()
DoRender()
So this means that if our the game has updated, the game has also rendered. The maximum delta time is capped to 1 frame so there must have been more than one Update and thus multiple renders during the stutter.
My current theory is that on most devices the game lags during render, but on the S2 the render calls are executed but they "fall through" without updating the render buffer.
Has anyone run into this problem? I would really appreciate any suggestions about what this could be.
We found out what the problem is.
The Galaxy S 2 was for some reason running out of GL memory. This wasn't apparent on the devices we were testing with, but on other devices it would crash on some Open GL call - not the offending call mind you.
Eventually we tracked it down to using Point sprite VBO's. As the S 2 is a powerful device, we replaced Point sprites with Quad's mimicking point sprites as a workaround.
Incidentally, SoundPool would also run out of memory on this device, requiring another workaround.

Android OpenGLES - Lag between calls to OnDrawFrame on Moto Droid at large resolution

We are currently developing an Android Game using opengles. We are now trying to support different resolutions, however, when allowing for large resolutions, the moto droid we are testing on seems to lag at it's native resolution (800x400). We have the frames locked at 30 fps, and when we check, our game only takes about 15-20 ms to do it's updating and drawing on the droid, however, there is sometimes 30-60 ms that elapses between calls to ondrawframe. My Galaxy S device doesn't have this problem, and when we put the resolution down on the motorola droid it seems perfectly fine.
We've investigated the issue and have found people with what seems to have been the exact same issue but no one could offer a solution. Other games on the market that seem to use opengles run fine on the moto droid.
Is there something we're missing? Something we need to call or do to? There seems like there should be no reason for there to be 30-60 ms between calls to ondrawframe, especially when the native resolution (800x400) isn't leaps and bounds larger than the default of 533x320, or whatever it is that it goes to when not allowing for large screens, so it seems ridiculous for it to be because of a buffer swap. The lag even happens when near nothing is being drawn to screen, so it's not because we're drawing too much.
Any enlightenment or help as to how to fix this would be great.
You have to give more information. If its not because of drawing, then it should be because of any calculation or object allocation code. Allocating Objects often during a game, invokes the GC, which is bad for games.
Things about performance and allocating memory for Android games is explained in the links below.
I suggest you watch these 2 videos done by Google Android Group.
http://www.youtube.com/watch?v=U4Bk5rmIpic&feature=player_embedded
http://www.youtube.com/watch?v=7-62tRHLcHk&feature=player_embedded
Hope that helps in optimizing.

SurfaceView Fast Enough For Emulation?

For years now I've maintained a Tandy Color Computer Emulator applet on my home page. With the purchase of an Incredible I decided to do a port. Getting it going in Android didn't take long but I'm really surprised how slow it runs. You can literally see the pixels painting. I know there are other successful Android emulators so I must be doing something wrong.
My approach was to use a SurfaceView for rendering. There's a separate thread that runs a virtual 6809 CPU. Whenever that thread updates the emulated video memory, it calls SurfaceHolder.lockCanvas() with a Rect describing the part of the screen requiring a repaint. Then it calls the gfx routines with the resulting Canvas...this is where I did a repaint() in AWT/Swing. The gfx routines are smart enough to just render what's in the clipRect. Perhaps I'm still stuck in AWT but I can't think of any way to make this thing run at an acceptable speed. I tried to coalesce the gfx calls but that didn't work either. Any thoughts?
SurfaceView should be fast enough. All the drawing routines are smart enough to not do anything if outside of the clip region but you can cull the calls ahead of time if you want. It looks like you need to profile your app and see where you spend too much time.

Categories

Resources