Tips regarding high performance drawing in Android - android

Background
I'm writing a graphing library for an android application (yes yes, I know there are plenty out there but none that offer the customizability we need).
I want the graphs to zoomable and pan-able.
Problem
I want the experience to be smooth, leave a small CPU footprint.
Solutions
Use View.onDraw(Canvas)
Use high resolution Bitmap
Use OpenGL
View.onDraw():
Benefits
Some what easy to implement
Drawbacks
Bad performance? (unless it uses OpenGL, does it?)
Bitmap:
Benefits
Really easy to implement
Great performance
Drawbacks
Have to use scaling which is ugly
OpenGL:
Benefits
Probably good performance depending on my implementation
Drawbacks
More work to implement
Final words
OpenGL would probably be the professional solution and would definitely offer more flexibility but it would require more work (how much is unclear).
One thing that is definitely easier in OpenGL is panning/zooming since I can just manipulate the matrix to get it right, the rest should be harder though I think.
I'm not afraid to get my hands dirty but I want to know I'm heading in the right direction before I start digging.
Have I missed any solutions? Are all my solutions sane?
Additional notes:
I can add that when a graph changes I want to animated the changes, this will perhaps be the most demanding task of all.

The problem with using Views is that you inherit from the overhead of the UI toolkit itself. While the toolkit is pretty well optimized, what it does it not necessarily what you want. The biggest drawback when you want to control your drawing is the invalidate/draw loop.
You can work around this "issue" by using a SurfaceView. A SurfaceView lets you render onto a window using your own rendering thread, thus bypassing the UI toolkit's overhead. And you can still use the Canvas 2D rendering API.
Canvas is however using a software rendering pipeline. Your performance will mostly depend on the speed of the CPU and the bandwidth available. In practice, it's rarely as fast as OpenGL. Android 3.0 offer a new hardware pipeline for Canvas but only when rendering through Views. You cannot at this time use the hardware pipeline to render directly onto a SurfaceView.
I would recommend you give SurfaceView a try first. If you write your code correctly (don't draw more than you need it, redraw only what has changed, etc.) you should be able to achieve the performance you seek. If that doesn't work, go with OpenGL.

Related

Does OpenGL ES drain more battery than standard 2D graphics?

I'm contemplating writing an app which does a lot of moving 2D graphics. I'm not very familiar with the standard android 2D graphics API, and I'm a lot more comfortable with OpenGL so I'm naturally considering using OpenGL instead.
My consideration right now is this, if I make sure to reduce my frame rate and not do any continuous updates unless I need to animate stuff, is there a significant difference in power consumption/battery life with using OpenGL ES compared to standard graphics?
Note that I'm not making a game, and I will not need continuous updates except when animating UI elements.
OpenGL-ES on most devices leverages the device's GPU, and therefore likely has a slightly higher battery usage than non-OpenGL-ES display systems, however I believe that this is a negligible difference. Usually battery strain considerations circle areas such as networking or GPS tracking. For graphics, the best approach to minimizing battery consumption would be minimizing the overall usage of the device's CPU.
OpenGL-ES is optimized to be as efficient as possible for heavy graphic rendering, and has a bonus advantage of running outside the sandbox Android allocates to each running app, granting it a much larger pool of memory, along with access to the GPU making it optimal when considering a graphic rich presentation layer in your app.
Barring OpenGL-ES, you would probably either want to work with Bitmaps & Canvases or work with Views nested inside ViewGroups and move them around by altering their LayoutParams, or manipulating their Matrices in order to animate objects around the screen. Performance-wise, animations which are done like this are rarely impressive when compared with animations performed by OpenGL based platforms.
On the other hand, managing a structured app entirely in OpenGL-ES could be a nightmare as well. Using Fragments and Views are always the method of choice when building a non-graphic rich app, simply because they make everything so much simpler, and they were built and optimized for exactly this purpose.
At the end, it really depends on the requirements of the app you're building. You could also consider developing certain segments which have higher graphical requirements in OpenGL-ES and others which do not in more conventional methods such as Fragments.
Battery-wise, utilizing the GPU via OpenGL-ES definitely has some overhead, but if you overclock the CPU using conventional animation methods, you may end up putting even more strain on the battery, and even damaging your app's user experience with low frame rates.

What to use Canvas/Surfaceview or OpenGL

I know this question has been asked too many times here, but all the time it is related to either 2D or 3D game.
I am trying to create an application like Skitch, and want to know either to use Opengl or stick with Canvas, Surface view.
Which is best to use Performance wise.
Maximum performance = OpenGL
Easy implementation & more than average performance = SurfaceView
I'm not providing any benchmark tests here, but that's based on own experience. Sometimes even OpenGL may have performance problems)
Remember - KISS

Will making too many transformations "onDrawFrame" create lag?

I am using the Rajawali framework to make OpenGL ES based live wallpapers. To achieve many of my animation effects I have created some functions that are called from the onDrawFrame method. These functions vary from simple x,y,z rotations to more complicated equations with conditional statements that simulate wind or other randomized motions. It works well currently, and it is highly responsive especially when sleeping and waking the device.
As my live wallpapers become more complex I am worried that my crude solution will eventually start causing performance issues. Is that the case?
Is there a better way to make these types of cyclical or repetitive changes, like maybe making background threads?
Try to move as much computing as posible into vertex and fragment shaders. It's easier to hit other limits than CPU limits. Nobody can answer your question easily without examples and without knowing in depth what are you trying to archive.
Best TIP: Measure often and early during development.
Hope that helps.
Rajawali onDrawFrame() method is called by a timer, which is set with the frameRate() method. This gives much smoother animation than estimating thread sleeps (an alternate solution which is not advised).
If you are at 100fps, this gives you 10ms in between frames to do your calculations - that's it, but that is a lot of time to a modern CPU.
Putting the GPU calculations in a separate thread is problematic since this is not thread safe. You could put any non-GPU calcs in a separate thread, but this could result in sync issues.
Shaders are compiled into native code, but really should be limited to bitwise (integer) operations required to render the actual pixels (always the bottleneck) after all the expensive 3D calcs are done.
For example, an anaglyph shader would take care of overlaying two stereoscopic frames.
Hope this helps!

Turn based game, which drawing method?

I am going to create a simple turn based 2D game for Android and as far as I know there are basically three methods to do the drawing.
Using a "normal" View, and only drawing when needed (for example on a touch event).
Using a SurfaceView combined with a "game loop" in a separate thread, drawing on each loop iteration.
OpenGL (I have no idea how this works yet).
When I made a small simulation game (a la Farmville) I used the SurfaceView, because it used some simple animation, and if I used a "normal" View, I had to use a Timer to update the graphics at certain intervals. I don't know which one of the two methods was better, but the SurfaceView method seemed to be easier. On the other hand, I figure that using an infinite "game loop" drains the battery very quickly. As for OpenGL, I have no idea how that works or if it is way too complicated for simple games.
So if I have a simple turn based game (think a bit like the fighting parts of Pokémon), which of the above methods would be best? What do other games use (like Angry Birds, DanteInferno, Inotia, Jewels, Robo Defense, Wisp, Zonina, etc)?
I find that the information on the web is very unclear on which to use when.
I had a simple board game which is kind of a turned based game and i used SurfaceView and it came out pretty darn good. You can optimize SurfaceView, but You'll eventually run into problems if you use standard views, specially if you have a scrolling game.
I've use this article and it was very helpful, it has a bunch of different methods of implementing the game loop with their pros and cons: http://www.koonsolo.com/news/dewitters-gameloop/
It's a good starting point.
About the draining of the battery - you can use Thread.sleep() so it will last longer. Didn't do any tests on the battery yet, but you have to face the fact that games drain battery, specially if you play it for hours :)
OpenGL also uses a drawing loop which is called repeatedly, so it will operate in a similar fashion to your SurfaceView approach. OpenGL is praised for its performance capabilities but does carry with it quite a lot of complexity - for a small project it might not be worth the investment, unless you fancy learning about how it works!
As for battery life, the most CPU intensive tasks will be the most draining, meaning the redrawing strategy (time based or event-driven) which is most effecient will be the best choice. Benchmarking a simple prototype should give you an idea of which works best with your game code.
I haven't done game development on Android but I have been creating an application that involves a lot of animated and scrolling UI elements. For this project I've used a mixture of normal extended Views and SurfaceViews, and I've had to borrow lots of techniques traditionally used in game programming. Along the way I've learned how normal Views and SurfaceViews differ, and the pros and cons of using each.
The big difference between the two, which I think is important to grasp, is that with a SurfaceView you're in effect almost directly writing to the screen buffer (not technically correct - but the easiest way to think about it) as soon as you want, and often as you'd like (within limits). It doesn't 'sit' within the normal View hierarchy. Being able to draw in this manner allows for fast animated graphics (particularly by offsetting bitmaps to create scrolling backgrounds and overlaying animated bitmap sprites over the top). Your code does the drawing directly when it wants to. Main disadvantage of a SurfaceView as far as I have been able to tell from my own experience is that you cannot have any other View appear behind it (i.e. no transparency effects).
A normal View on the other hand sits in the normal View hierarchy. Unlike with a SurfaceView you cannot perform a redraw of a normal View as soon as your code wants to. You have to call invalidate() (or postInvalidate() from a non-UI thread) on that View to tell the system that you want to redraw it, and then the system will eventually call that View's onDraw() after some time to do the drawing. There's no guarantee on how quickly that'll be called and this potentially limits the speed at which you can update graphics. The advantage of a normal View however is that it sits within the normal View heirarchy and you can have Views placed on top of each other with transparency and so on.

Is OpenGL on Android a battery killer?

I'm currently implementing a software keyboard ( using some sophisticated prediction ), and drawing it using canvas is insufficient in terms of perfomance. I'm getting frame drawing times well above 100ms, which is clearly unacceptable.
The keyboard itself consists of about 33 keys, each of them drawn using drawRoundRect and a simple Text above that. No widgets whatsoever are used, so it's the plain perfomance. Also, almost all of Googles perfomance tips are in use, so thats not the reason for the speed either.
I've now reached a point where switching to opengl actually would make sense, but I'm still sceptical considering the impact an opengl-based keyboard might have on battery life.
As I've found no sufficient documentation on that topic, I hope someone here can point me to the right direction.
Regardless of how much it drains the battery, you probably don't want to do this because most existing devices don't support multiple OpenGL contexts at the same time, so your soft keyboard would be incompatible with any application that is using OpenGL for its own drawing. On these devices the OpenGL context is owned only by the foreground application; it can not be used in secondary parts of the UI like the soft keyboard.
Also as the previous poster said, you would probably be best off looking how to optimize your regular drawing. Drawing vectors is quite slow, so pre-rendering them into a bitmap to just do bitmap blits would help a lot. Also be careful to only draw the parts of the window that have changed. 100ms is a pretty insane amount of time to take to draw the UI, so there are almost certainly significant optimizations you can make. You might want to look at the KeyboardView code in the platform (which is used by the standard soft keyboard and sample IME); this already contains many similar drawing optimizations.
An aside: Have you considered rendering the keys once and then grabbing them as sprites and blitting these? It should be vastly superior to rendering vector graphics.
I cannot give you hard numbers (and as apphacker pointed out, this is device-specific), but even if OpenGL is hardware-accelerated and hence might use more battery, the operation should complete much faster and so use less power in total.
If it is not hardware-accelerated, it seems logical that it should only use more power if it takes longer to complete the operation, as you are only exchanging one drawing API for another.
All in all, as you only have to draw when external events happen it shouldn't matter much in the long run, as people are probably tiping only a few keys per minute.
You'll probably just have to implement it (maybe in a simplified test case) and make measurements.

Categories

Resources