Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Improve performance of SurfaceView-dervied custom view?

I have written a simple Android application that draws a maze using a custom view derived from SurfaceView. It follows the model of the LunarLander sample application and performs all calculation and drawing using a background thread directly into the SurfaceHolder object.

All well and good and it's running well for small/medium mazes, however if I set the maze cell size to be 8 pixels there are lots of cells in the maze the application crawls along.

The code is doing something I don't like in that is draws every cell even if it hasn't changed and this is required to avoid screen flickering from the SurfaceView double buffer (in previous iterations of the application I was drawing just what changed and that resulted in a jumpy mess).

What I want then is the ability to use SurfaceView but be more selective about what gets drawn. Is this possible? If not, what are the alternatives? How about keeping an offscreen bitmap, and selectively drawing into that first?

EDIT: I implemented an offscreen Bitmap and Canvas combination, written to by my timer-driven state machine, drawing only those areas affected during carving/solution. I then simply draw the whole offscreen bitmap onto the SurfaceView within the run() method and this has solved my problem; I am able to drop the cell size to 5 pixels and performance is fine.

like image 945
trojanfoe Avatar asked Feb 14 '11 16:02

trojanfoe


1 Answers

About double-buffering issues:

Take a look at this tutorial series. Do you see any difference in the way you handle drawing? https://web.archive.org/web/20121109162356/http://www.droidnova.com/playing-with-graphics-in-android-part-iii,176.html

About optimizing your drawing:

The following link, explains some approaches:

http://developer.android.com/guide/topics/graphics/opengl.html

http://developer.android.com/reference/android/opengl/GLSurfaceView.html

Continuous rendering versus render-when-dirty

Most 3D applications, such as games or simulations, are continuously animated. But some 3D applications are more reactive: they wait passively until the user does something, and then react to it. For those types of applications, the default GLSurfaceView behavior of continuously redrawing the screen is a waste of time. If you are developing a reactive application, you can call GLSurfaceView.setRenderMode(RENDERMODE_WHEN_DIRTY), which turns off the continuous animation. Then you call GLSurfaceView.requestRender() whenever you want to re-render.

Also, in 2D games it's particulary easy to calculate what is being seen by the user so refrain from drawing objects out of the visible scene.

One final note:

You said

All well and good and it's running well for small/medium mazes, however if I set the maze cell size to be 8 pixels there are lots of cells in the maze the application crawls along.

Does this means that you are computing the maze's solution? If so, you shouldn't do it in the same thread where you draw it. You should solve it in another thread. (I might have understood you wrong)

like image 145
Pedro Loureiro Avatar answered Oct 17 '22 22:10

Pedro Loureiro