【iOS】—— off-screen rendering

off-screen rendering

UIView and CALayer relationship

  • UIView inherits from UIResponder and can handle events passed by the system, such as: UIApplication, UIViewController, UIView, and all UIKit classes derived from UIView. There is a CALayer inside each UIView that provides content drawing and display, and acts as a proxy view of the internal RootLayer.
  • CALayer inherits from the NSObject class and is responsible for displaying the contents provided by UIView. CALayer has three visual elements: background color, content and border, among which, the essence of the content is a CGImage.

There are two ways of GPU screen rendering:

1. On-Screen Rendering (current screen rendering)
means that the rendering operation of the GPU is performed on the screen buffer currently used for display.

2. Off-Screen Rendering (off-screen rendering)
refers to the GPU opening a buffer outside the current screen buffer for rendering operations.

The current screen rendering does not need to create a new cache, nor does it need to open a new context, which has better performance than off-screen rendering. However, due to the limitations of the current screen rendering (only its own context, limited screen cache, etc.), in some cases the current screen rendering cannot be solved by rendering, off-screen rendering is used.

Reasons for off-screen rendering:

The Apple system cannot process the views one at a time, and needs to process the views one by one, then it will need to open up an off-screen cache to store the processed views one by one, and the opened off-screen cache will cause Offscreen rendering.

Since off-screen rendering consumes so much performance, why is there such a mechanism?

Some effects are considered not to be directly displayed on the screen, and require additional processing and pre-synthesis elsewhere. Mixtures of layer properties cannot be drawn directly on screen without pre-compositing, so off-screen rendering is required.

What happens when rendering off-screen?

  • Set a mask for a layer ( layer.mask)
  • Set the layer's layer.masksToBounds / view.clipsToBoundsproperties totrue
  • Set layer layer.allowsGroupOpacityproperties to YESandlayer.opacity小于1.0
  • Sets a shadow ( layer.shadow *) for the layer.
  • Rasterize the layerlayer.shouldRasterize=true
  • Layers with layer.cornerRadius, of course not all rounded corners will result in off-screen layer.edgeAntialiasingMaskrenderinglayer.allowsEdgeAntialiasing
  • Text (any kind, including UILabel, CATextLayer, Core Textetc.).
  • Using draw CGContextin drawRect :method will result in off-screen rendering in most cases, even just an empty implementation.

Since off-screen rendering is so bad, why do we have to force it on?

When an image is mixed with multiple layers, these layers must be recomposited every frame every time it is moved, which is very performance-consuming. When we turn on rasterization, a bitmap cache will be generated for the first time, and this cache will be reused when it is used again. But if the layer changes, the bitmap cache will be regenerated. Therefore, this function cannot be used UITableViewCellin general, and the multiplexing of cells reduces the performance. Best used for graphics with many layers of static content. Moreover, the size of the generated bitmap cache is limited, generally 2.5 screen sizes. If the cache is not used within 100ms, the cache will also be deleted. So we have to decide according to the usage scenario.

How to avoid off-screen rendering?

1. Optimization of rounded corners:

1: Use the Bezier curve UIBezierPath and the Core Graphics framework to draw a rounded corner
2. Use CAShapeLayer and UIBezierPath to set the rounded corner.
Generally speaking, using CAShapeLayer consumes less memory and renders faster. It is recommended to use optimization scheme 2.

2.shadow

For shadow, if the layer is a simple geometric figure or a rounded figure, we can optimize performance by setting shadowPath, which can greatly improve performance. Examples are as follows:

mageView.layer.shadowColor=[UIColorgrayColor].CGColor;
imageView.layer.shadowOpacity=1.0;
imageView.layer.shadowRadius=2.0;
UIBezierPath *path=[UIBezierPathbezierPathWithRect:imageView.frame];
imageView.layer.shadowPath=path.CGPath;

We can also force off-screen rendering by setting the shouldRasterize property value to YES. In fact, it is Rasterization.

Guess you like

Origin blog.csdn.net/m0_62386635/article/details/132019299