Android Hardware Acceleration

Recently, the project encountered some problems caused by hardware acceleration, so here is an in-depth study of some things about hardware acceleration

background

What is hardware acceleration?

Hardware acceleration is the way the Android system draws graphics.

Graphic rendering is essentially interface rendering. When rendering an interface, it goes through a series of calculations, which are usually simple logic but large floating point calculations.

At the operating system level, there is something called the central processing unit (CPU), which is one of the core components of computer equipment. Its main function is to interpret computer instructions and process data in computer software. In addition, computers also have a device called a graphics processor — GPU, which is similar to a CPU but is a microprocessor designed to run graphics operations.

So what’s the difference between a CPU and a GPU?

  • CPU internal arithmetic logic unit (ALU) is small, the controller is more complex, suitable for complex logical operations
  • The GPU controller is simple, but it contains more arithmetic logic units and can run a large number of calculations in parallel

The result is obvious, because the calculation of interface rendering is a floating point operation with simple logic but large amount of data, so if using CPU to do the calculation of interface rendering, the effect is naturally inferior to that of GPU.

Therefore, hardware-accelerated graphics are generally used software graphics is drawn by the CPU. Hardware acceleration is to convert some of the graphics calculation that CPU is not good at into GPU-specific instructions through the underlying code, and then hand over to the GPU to complete. For Android, hardware acceleration means transferring the View drawing from the CPU to the GPU.

The principle of

Hardware rendering is “faster” than software rendering, in addition to the above mentioned prize part of the calculation to a more suitable hardware to do, there is a very important reason is that the selection of drawing areas, namely drawing content is not the same.

With hardware acceleration turned off, that is, with software drawing, the drawing area is obtained by walking through the View structure starting with the View on which the invalidate() method is to be executed, and marking the dirty areas that need to be redrawn. In this process, in addition to the View we directly modify need to draw, all other views, because of cover, intersection and other reasons, are marked as need to draw, so that the drawing area will become very large. As a result, many “innocent” views will be redrawn, even if they don’t really need to be redrawn.

With hardware acceleration, it’s a different story. Hardware rendering firstly abstracts the View as RenderNode node, and the drawing of the View as DrawOp. Each View not only holds the List of its DrawOp operation, but also holds the drawing entry of its sub-view. DrawOp preserves the corresponding OpenGL drawing command, thus forming a complete tree structure. Second, hardware rendering is handed over directly to a Render thread, rather than the main thread, which takes some of the pressure off the main thread. Finally, during the actual drawing, the actual drawing operation of each View corresponds to the DrawOp. During the drawing, you only need to update the saved drawing command to complete the single drawing of this View without affecting other views.

The problem

While hardware acceleration has many advantages, it also has many pitfalls.

First, some Api methods do not support hardware acceleration:

Secondly, when using Webview, if hardware acceleration is enabled, sometimes there will be a splintered screen, flashing and other abnormal conditions.

Finally, as mentioned earlier, there are some apis that are not supported, so when you do a custom View, it is possible to turn on hardware acceleration and render the View poorly.

How to use

At first Android turned hardware acceleration off by default. Starting with Android version 4.0, hardware acceleration is turned on by default. Hardware acceleration has many advantages, but for a variety of reasons (system design, legacy, and own limitations), there are situations where there are problems and you need to turn it off manually.

The switch of hardware acceleration is divided into four levels, namely App level, Activity level, Window level and View level.

  • App level: directly inAndroidManifest.xmlFile,<application>Add an attribute under the tagtrueTo open,falseTo shut down:
<application android:hardwareAccelerated="true">
Copy the code
  • Activity level: similar to App level, in<activity>Add the same attributes under the tag:
<activity android:hardwareAccelerated="true">
Copy the code
  • Window level: At the Window level, hardware acceleration can only be turned on dynamically, not off, through Java code:
getWindow().setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
Copy the code
  • View level: The View layer is special, where only hardware acceleration can be turned off, but not on. The interface is not specifically used for hardware acceleration, but “incidentally” to disable hardware acceleration when setting Layer to View:
view.setLayerType(LAYER_TYPE_SOFTWARE, null); 
Copy the code

This method simply sets the View to a LayerType with three arguments: LAYER_TYPE_SOFTWARE LAYER_TYPE_HARDWARE LAYER_TYPE_NONE. What does that mean? There is a detailed explanation about this part on the official website:

You currently cannot enable hardware acceleration at the view level. View layers have other functions besides disabling hardware acceleration. See View layers for more information about their uses.

The View layer can only be turned off, not on.

The setLayerType() method does exactly what it says: sets the View Layer type. The View Layer, also known as the off-screen Buffer, is used to enable a separate place to draw the View, rather than using a software-drawn Bitmap or a hardware-accelerated GPU. Depending on whether hardware acceleration is enabled, this “place” can be a separate Bitmap or an OpenGL texture. What is used to draw the View is not the key, the key is that when the View Layer is set, its drawing will be cached, and the cache is the final drawing result, instead of just saving the OPERATION of GPU and handing it to GPU for calculation like hardware acceleration. With this further caching, View redrawing is even more efficient: as long as the drawing remains the same, neither the CPU nor the GPU will have to recalculate, but only use the previously cached drawing results.

So, if you set the View Layer to SOFTWARE, then SOFTWARE is used to do the View Layer, and hardware acceleration is naturally turned off. If HARDWARE acceleration has been turned off, the parameter HARDWARE does the same as SOFTWARE and cannot be turned on. NONE turns the ViewLayer off, so it can only be turned off at the View layer.

  • LAYER_TYPE_NONE: The view is rendered normally and is not backed by an off-screen buffer. This is the default behavior.
  • LAYER_TYPE_HARDWARE: The view is rendered in hardware into a hardware texture if the application is hardware accelerated. If the application is not hardware accelerated, this layer type behaves the same as LAYER_TYPE_SOFTWARE.
  • LAYER_TYPE_SOFTWARE: The view is rendered in software into a bitmap.