So I'm trying to understand how I can properly use hardware acceleration (when available) in a custom View
that is persistently animating. This is the basic premise of my onDraw()
:
canvas.drawColor(mBackgroundColor);
for (Layer layer : mLayers) {
canvas.save();
canvas.translate(layer.x, layer.y);
//Draw that number of images in a grid, offset by -1
for (int i = -1; i < layer.xCount - 1; i++) {
for (int j = -1; j < layer.yCount - 1; j++) {
canvas.drawBitmap(layer.bitmap, layer.w * i, layer.h * j, null);
}
}
//If the layer's x has moved past its width, reset back to a seamless position
layer.x += ((difference * layer.xSpeed) / 1000f);
float xOverlap = layer.x % layer.w;
if (xOverlap > 0) {
layer.x = xOverlap;
}
//If the layer's y has moved past its height, reset back to a seamless position
layer.y += ((difference * layer.ySpeed) / 1000f);
float yOverlap = layer.y % layer.h;
if (yOverlap > 0) {
layer.y = yOverlap;
}
canvas.restore();
}
//Redraw the view
ViewCompat.postInvalidateOnAnimation(this);
I'm enabling hardware layers in onAttachedToWindow()
and disabling them in onDetachedFromWindow()
, but I'm trying to understand whether or not I'm actually using it. Essentially, the i/j
loop that calls drawBitmap()
never changes; the only thing that changes is the Canvas
translation. Is the Bitmap
automatically saved to the GPU as a texture behind the scenes, or is there something I need to do manually to do so?
On what view(s) are you setting View.LAYER_TYPE_HARDWARE
exactly? If you are setting a hardware layer on the view that contains the drawing code shown above, you are causing the system to do a lot more work than necessary. Since you are only drawing bitmaps you don't need to do anything here. If you call Canvas.drawBitmap()
the framework will cache the resulting OpenGL texture on your behalf.
You could however optimize your code a little more. Instead of calling drawBitmap()
, you could use child views. If you move these children using the offset*()
methods (or setX()
/setY()
) the framework will apply further optimizations to avoid calling the draw()
methods again.
In general, hardware layers should be set on views that are expensive to draw and whose content won't change often (so pretty much the opposite of what you're doing :)
You can use Android's Tracer for OpenGL ES to see if your view issue OpenGL commands.
From developer.android.com
Tracer is a tool for analyzing OpenGL for Embedded Systems (ES) code in your Android application. The tool allows you to capture OpenGL ES commands and frame by frame images to help you understand how your graphics commands are being executed.
There is also a tutorial about Android Performance Study by Romain Guy which describes its use almost step by step.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With