This article is for the collation of the past notes, in this only for the record, do not do rigorous technical sharing.

Hardware acceleration refers to handing over some of the computing work to specialized hardware rather than handing it over to the CPU as usual. This not only takes the pressure off the CPU, but also speeds up the computation process by having “people” handling it. This is called “hardware acceleration”.

For Android, hardware acceleration has its own meaning: In Android, hardware acceleration specifically refers to handing over the computation work drawn in the View to the GPU. To be more specific, the “computation of drawing” refers to turning canvas.drawxxx () in the drawing method into actual pixels.

  • Starting with Android 3.0 (API 11), the 2D rendering pipeline supports hardware acceleration, with all drawing operations performed on the View canvas using the GPU.
  • If the target API is level 14 or higher, hardware acceleration is enabled by default.
  • If the application uses only standard views and Drawable, enabling hardware acceleration globally does not cause any bad drawing effects.
  • However, not all 2D draw operations support hardware acceleration, so enabling hardware acceleration may affect some custom view or draw calls.
  • Android allows you to select whether to enable or disable hardware acceleration at multiple levels.
  • Enabling hardware acceleration requires more resources, so the application takes up more memory.

Control hardware acceleration

App

 <application android:hardwareAccelerated="true" .>
Copy the code

Activity

    <application android:hardwareAccelerated="true">
        <activity . />
        <activity android:hardwareAccelerated="false" />
    </application>
Copy the code

Window

Hardware acceleration cannot currently be disabled at the window level

    / / open
	getWindow().setFlags(
        WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
        WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
Copy the code

View

Hardware acceleration cannot currently be enabled at the view level

    myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);/ / close
Copy the code

Determine whether hardware acceleration has occurred

  • If the View is attached to the window hardware acceleration, the * * the isHardwareAccelerated () will return true * *.
  • If the Canvas through hardware acceleration, the * * Canvas isHardwareAccelerated () will return true * *

Unsupported draw operation

Drawing model (Principle)

  • Software rendering: Draw to a Bitmap using the CPU, and then render the Bitmap to the screen
  • Hardware drawing: THE CPU converts the drawing content into GPU operation, and THE GPU is responsible for the real drawing

When hardware acceleration is off:

Canvas drawing works by writing the content to be drawn into a Bitmap, and the pixel content of the Bitmap is rendered directly to the screen during the later rendering process. The main computation of this rendering method is the process of converting the rendering operation into pixels, which is performed by the CPU. Something like this:

When hardware acceleration is enabled:

The way Canvas works has changed: THE CPU just saves the operation of converting the drawn content to the GPU, and then hands it over to the GPU, which ultimately does the actual display work. It goes something like this:

Reasons for faster hardware acceleration:

  • The GPU splits the work, and GPU computing is faster
  • The change of drawing mechanism greatly improves the refresh efficiency when the interface content changes. (Invalidate () will no longer refresh the parent View to the top View)

Hardware acceleration disadvantages:

Compatibility issues Because some drawing cannot be done (temporarily) using the GPU, for certain apis you need to turn off hardware acceleration and switch back to using the CPU for drawing

  • For custom drawing, see API compatibility
  • All native controls, there is no use of API version incompatible drawing operations, you can rest assured to use

Off-screen buffer

Starting with Android 3.0 (API level 11), you have better control over how and when layers are used with the view.setLayerType () method. Views can use one of three layer types:

  • LAYER_TYPE_NONE: View renders normally and is not supported by off-screen buffers. This is the default behavior.
  • LAYER_TYPE_HARDWARE: If the application is hardware-accelerated, the view is rendered in hardware as a hardware texture. If the application is not hardware accelerated, this layer type behaves in the same wayLAYER_TYPE_SOFTWAREThe same.
  • LAYER_TYPE_SOFTWARE: Software is used to render the view and draw to a Bitmap. And incidentally turn off hardware acceleration

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.

Based on this principle, enabling the Hardware Layer will greatly improve the efficiency of animation when moving, rotating and other ** without calling the invalidate()** attribute, because the View itself does not change during the animation process, only its position or Angle is changed. This change can be done by the GPU through simple calculation without redrawing the entire View. Therefore, turning on the Hardware Layer in the process of this animation can make the animation that has become smooth by relying on Hardware acceleration become smoother.

Note: This works only when animating properties such as translationX, translationY, rotation, and alpha that do not require invalidate() calls. Because this approach itself exploits the time savings of not updating the cache when the interface does not occur. So this simply doesn’t work for animations drawn based on custom properties.

Conclusion:

  • SetLayerType (LAYER_TYPE_SOFTWARE), “incidentally” to turn off hardware acceleration
  • The key point: translationX, translationY, rotation, alpha, etc., which do not need to call invalidate() to animate
  • Does not apply to animations drawn based on custom properties

use

view.setLayerType
    // Enable off-screen cache (software renders bitmap, and hardware acceleration is disabled)
	myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
	// Enable off-screen cache (hardware rendering bitmap, not necessarily hardware acceleration at this time)
	myView.setLayerType(View.LAYER_TYPE_HARDWARE, null);

	// The hardware layer takes up memory, so it is only enabled during the animation and then disabled after the animation ends
    ObjectAnimator animator = ObjectAnimator.ofFloat(view, "rotationY".180);
    animator.addListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            view.setLayerType(View.LAYER_TYPE_NONE, null);// Turn off the cache}}); animator.start();// withLayer() automates the complexity of the above code
	view.animate()
        .rotationY(90)
        .withLayer(); 
Copy the code
class RoundRectCoverView(context: Context, attrs: AttributeSet) : View(context, attrs) {
    private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
    private val porterDuffXfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_OUT)
  
    init {
        // Enable view-level off-screen buffering, turn off hardware acceleration, and use software to draw
        setLayerType(LAYER_TYPE_SOFTWARE, null)}override fun onDraw(canvas: Canvas) {
        canvas.drawRoundRect(mPadding, mPadding, width - mPadding, 
                             height - mPadding, mRoundCorner, mRoundCorner, paint)
        paint.color = mCoverColor
        paint.xfermode = porterDuffXfermode
        canvas.drawRect(0f.0f, width.toFloat(), height.toFloat(), paint)
        paint.xfermode = null
    }
Copy the code
canvas.saveLayer
    override fun onDraw(canvas: Canvas) {
         //Canvas off-screen buffer
          val count = canvas.saveLayer(bounds, paint)
          canvas.withSave {
              canvas.drawColor(mCoverColor)
              canvas.clipPath(clipPath)
              canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.SRC)
          }
          // Draw the off-screen buffer onto the View
          canvas.restoreToCount(count)
    }
Copy the code

Contrast:

  • SetLayerType:The whole ViewAll drawn in the off-screen buffer
  • SaveLayer:Part of View contentDraw in off-screen buffer (preferred)

Hardware acceleration versus off-screen rendering

Hardware acceleration and off-screen rendering are two different concepts, just related

  • Hardware acceleration: Hand over the computation work drawn in the View to the GPU and display it
  • Off-screen rendering: Whether hardware acceleration is enabled or not, a separate area is enabled to draw the View
    • LAYER_TYPE_SOFTWARE: Software is used to render the view and draw to a Bitmap. And incidentally turn off hardware acceleration
    • LAYER_TYPE_HARDWARE:
      • If the application is hardware accelerated, the view is rendered in hardware as a hardware texture.
      • If the application is not hardware accelerated, this layer type behaves in the same wayLAYER_TYPE_SOFTWAREThe same.

use

Hardware acceleration, which makes full use of GPU features, makes interface rendering smoother. But hardware acceleration itself isn’t perfect, consuming more memory, and the code isn’t right, causing flash, splashes, misplacement and other rendering problems.

There is no perfect solution for hardware acceleration or off-screen buffering. You can only choose which way to improve performance according to different situations:

  • Hardware acceleration: used when supporting the type of Api
  • Off-screen buffer: Used when the View’s contents remain unchanged and the invalidate() method is not called

The custom View

Hardware acceleration is enabled by default. Note that apis are not supported

Incompatibility problems:

Hardware acceleration enabled when using Paint setPathEffect(PathEffect Effect) to set the PathEffect effect (API 28 starting support). Workaround: Turn off hardware acceleration, or use off-screen buffering (SOFTWARE type)

Attribute animation

Control the opening and closing of the off-screen buffer at the beginning and end of the animation

Use hardware acceleration to improve Android animation performance

Webview

When the WebView is blocked and suddenly restored (such as when SlideMenu is used to slide the WebView out of the side), there is a white block and the screen flashes

** Solution: ** Is to temporarily close WebView hardware acceleration before the transition period, and then open after the transition period

There are two ways to play the video:

  1. Separate hardware acceleration for the webView that plays the video

  2. Call the external native player to play the video separately