I'm porting a 2D action game from Windows Phone 7 (developed in XNA 4.0) over to Android. I'm using a lot of Canvas.drawBitmap() calls - around 200-300 per frame update - with different Paints for each call to handle varying transparency and colourisation at draw-time. This is managing particle systems and various other overlays and in-game effects as well as a tiled background and in-game sprites. I'm not doing any on-demand resizing or rotating, it's simple src->dest rectangles of the same size.
On WP7 this runs at 30+fps but I'm struggling to get 12fps on my test 'droid hardware (Samsung Galaxy S). This is making the game unplayable. Having profiled the code, I've confirmed that all my time is being lost in Canvas.drawBitmap()
I seem to be following all the usual performance advice - using a SurfaceView, mindful of GC so not creating loads of throwaway objects, and avoiding Drawables.
Am I right in understanding that Canvas.drawBitmap() is CPU-bound, and if I want to improve performance I have to switch to OpenGL which will use the GPU? I can't find it stated that baldly anywhere, but reading between the lines of some comments I think that might have to be my next step...?
This is normal. Canvas is amazingly slow when using transparency (like ARGB_8888).
2 options:
Switch to OpenGL ES
Use the least possible transparency on your bitmaps (i.e use RGB_565 the most you can).
Perhaps this will run better on Android 3+ since it uses hardware acceleration for canvas operations.
Related
I was using OpengGL (Gles2WatchFaceService.engine) for my Wear-OS watch-face projects and it was working great for years. Recently however, this engine got deprecated and therefore, before I recode all my graphics, I am reevaluating if OpenGL is needed at all.
My question to any experienced (watch face) developers here is: When should I use OpenGL for the graphics of a watch face? Only for 3D animation? What about an analog watch face with hands that should move smoothly (with the animation frame rate switching between 5 and 40 fps)? (I am also using some color blending with alpha channel, not sure if I can do that without OpenGL.)
It comes basically down to these considerations:
OpenGL for pure 2D animation could result in smoother animation at a lower CPU load. But, is this always true? Or can I get easily 40 fps for animating up to 9 graphical elements without OpenGL?
Am I getting the advantages of OpenGL (if there are any) at a cost of a more complicated code and more compatibility problems in the future (due to SW and HW updates)?
If OpenGL is the way to go, perhaps someone can point me to a good and recent code example (preferably java), because I can't find any.
Any help/comments appreciated!
Little prologue: I'm creating a some kind of drawing application for Android (API 14 and higher). Few months ago I've started working on it and decided to use SurfaceView as a canvas to draw on. I thought that this a good decision cause SurfaceView works directly with Graphics. And everything seemed to work fine until one day I've noticed that the drawing process is a little bit laggy. There're probably a lot of weird code down there.
Anyway, now I'm optimizing that code and stuff, and I thought, do I really need to use SurfaceView for such scenario? The main things I need from my "canvas" is to draw smooth and be able to save all the drawings to Bitmap->File on External storage (this works fine).
So, should I use the simple View or the SurfaceView? Also, it would be great to hear props and cons of your decision/proposition.
Thanks
If you want to use Canvas, you are increasingly better off with a custom View, rather than a SurfaceView. The simple reason is that Canvas rendering on a View can be hardware accelerated, while Canvas rendering on a SurfaceView's surface is always done in software (still true as of Android 5.0).
By drawing "smooth" I assume you want some anti-aliasing effects. Check the chart on the hardware acceleration page to confirm that the effects you want are supported for the Android releases you want to ship on.
As device display pixel counts get steadily higher, software rendering gets increasingly expensive, and on some devices the CPU or bus isn't fast enough to keep frame rates high. Fortunately on these the pixel density is so high that you don't really need anti-aliasing, so even if it's not supported you could ignore it until you generate your software-rendered bitmap.
Before you do anything, though, it would be wise to figure out what your source of sluggishness is. It's possible you're being slowed down by inefficiencies in your drawing code rather than pixel fill rate. Check it with some of the profiling tools.
(See also the graphics architecture doc.)
I'm playing around with the Android API with a long term prospect of developing a 2D game. Normally, I could live with just using the Canvas for drawing sprites as the graphics for my game. I'd like to be able to perform lots of drawing for visual effects, but it seems that the Android versions prior to Honeycomb (3.0, API level 11) don't support hardware acceleration.
I'm not sure what that exactly means though. I can't get myself round to believe that the drawing is done by the CPU, pixel by pixel !?! If I end up having effects like glow, lens effects etc... I'll be drawing over each pixel quite a few times. Am I right to believe that a typical smartphone CPU will not be able to cope with that at ~30 FPS?
I don't have the luxury to target Android versions >=3.0 as they constitute 8% of the already not SO big Android market. Should I take my time to go the OpenGL way (I'm a beginner at OpenGL)? If I do so, do you think I'll gain anything by overlaying a GLSurfaceView taking care of the effects on top of a custom android view using a Canvas to do the drawing otherwise. Or is it for any reason a bad idea to mix the two?
Oh God yes. Esepecially if you're targetting pre Android 3 devices, going from SurfaceView (with Canvas.drawXxx() calls) to OpenGlSurface works great. Not only do you have faster frames (updates) per second but memory consumption is A LOT better.
Here's some of the points I've noticed:
If you want to do (multi) sprite animations, doing them with the images loaded as OpenGL textures and displayed on an OpenGL quad gives you a lot more memory space. This is because while regular Bitmap objects are capped by the Android-per-process memory limit (which is something like 16-48 Mb, depending on device and Android version), creating OpenGL textures out of those images (and clearing the iamges right after) doesn't have this limitation. You're only limited by the total memory on the device which is A LOT more then 16-48 megs.
Secondly, but still related to this, with Android 2 and below tracking how much memory a Bitmap instance takes is a lot trickier since those intances are not reported against the Java heap memory. They are allocated in some other memory space. In short, another hassle less if you use OpenGL.
Simple animations such as rotating an image become a breeze with OpenGL. You just texture a quad, then roate it any way you want. Equivalent with Sprite animation is to sequentially display different (rotated versions ) of the image. This is better for memory consumption and speed.
If you're doing a 2D-like game, using OpenGL's orthogonal projection not only simplifies a lot of the (useless, in this case) hassle you'd have with a regular OpenGL perspective projection, but it actually alleviates A LOT of the issues you'd get with regular SurfaceView when needing to scale all your graphical elements so they'd look the same size on different screen resolutions/proportions. With OpenGL's ortho projection you effectifelly create a fixed area of desired widht and height and then have OpenGL project it on the device screen area automatically.
It comes without saying that making simple effects such as a pulsating light affecting some graphic element is a lot easier to do with OpenGL (where you just make the light and have it pulsate, and everything is lit accordingly) rather than simulate this with SurfaceView and baked in sprites.
I've actually started a small asteriod defence-like game with SurfaceView and Canvas and then quickly switched to OpenGL for the above mentioned reasons. Long story short, the game now looks better, and while it initially ran at 16 UPS on a Samsung TEOS and 30 UPS on an Optimus LG 2x it now runs at 33 UPS on the Teos and about 80 UPS on the LG 2x.
I'm currently playing around with 2D graphics in android and have been using a plain old SurfaceView to draw Drawables and Bitmaps to the screen. This has been working alright, but there's a little stutter in the sprite movement, and I'm wondering the feasibility to do a real time (but not terrible fast) game with this.
I know GLSurfaceView exists which uses OpenGL, but I'm curious as to the extent to which this makes a difference. Is a plain SurfaceView hardware accelerated, or do I need to use OpenGL? What type of speed difference could I expect from switching to OpenGL, and how much altering of code would it require to switch (the game logic is all in a separate object that provides an ordered array of drawables to the SurfaceView)?
As far as I can tell, you have to use openGL to get HW acceleration. But don't take is for granted and wait for other answers ^^
If it really is the case, the speedup should be quite important. Any 2D application should work at at very least 20 fps (generally less polygons than 3D applications)
it would take a substantial amount of code, but 1) as a first attempt, you could try with only 1 square VBO and change the matrix each time and 2) your rendering seems already quite encapsulated so it should simplify things a lot.
SurfaceView is not hardware accelerated in default.
if you want to get HW acceleration
use GLSurfaceView, which use opengl and is hardware accelerated.
Hardware acceleration is possible for a regular SurfaceView since 3.0.
http://developer.android.com/guide/topics/graphics/hardware-accel.html
I'm working with my friend on our first Android game. Basic idea is that every frame of the game the whole surface is redrawn (1 large bitmap) in 2 steps:
Background with some static image (PNG) wipes out previous frame
Then it is sprinkled all over with large number of particles which produces effect of soapy bubbles where there's a pool of about 20 bitmaps which randomly gets picked to produce illusion that all bubbles (between 200 - 300) are all different. Bubbles positions updated on each frame (~50ms) producing effect of moving bubbles.
The math engine is in C (JNI) and currently all drawing is done using android.graphics package very similar (since that was the example I was using) to Lunar Lander.
It works but animation is somewhat jerky and I can feel by temperature of my phone that it is very busy. Will we benefit from switching to OpenGL? And as a bonus question: what would be a good way to optimize the drawing mechanism (Lunar Lander like) we have now?
Now I've started to work with OpenGL ES, I would also use it for 2D graphics. This way is the most flexible and it's extremely fast (look at this example code. It's about 2D rendering, and there you can see the power of OpenGL.
It's not the easiest thing to start with, but there are some good tutorials out there - for example, this is a very good one.
Don't redraw the entire screen each time. That's what causes your low framerate. Use the invalidate method to mark the areas that have changed each frame.