Reputation: 1200
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.
Upvotes: 14
Views: 4802
Reputation: 337
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:
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.
Upvotes: 0
Reputation: 57
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.
Upvotes: 0
Reputation: 499
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.
Upvotes: 0
Reputation: 5579
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.
Upvotes: 11