Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Hardware Layer in Custom View onDraw

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?

like image 211
Kevin Coppock Avatar asked Jun 23 '13 05:06

Kevin Coppock


2 Answers

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 :)

like image 56
Romain Guy Avatar answered Sep 20 '22 18:09

Romain Guy


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.

like image 20
auselen Avatar answered Sep 22 '22 18:09

auselen