Basic concepts of off-screen rendering
Off-screen Rendering is when the GPU creates a buffer outside of the current Screen buffer to render.
Generally speaking, off-screen rendering is very performance consuming in two ways:
- Create new buffers: To render off-screen, you first create a new buffer (iOS uses the dual FrameBuffer policy, so this is the buffer created except for these two buffers)
- Rendering context switch: Making two context switches, first to the off-screen environment and then to the current screen after the off-screen rendering is complete, can be expensive.
The reason for off-screen rendering is that some layers cannot be drawn directly on the screen, but instead are rendered into additional textures, which must be pre-composited from multiple rendered intermediate texture results. In addition, this transition occurs on every frame after off-screen rendering is triggered, which can seriously affect the frame rate if there is a large amount of off-screen rendering occurring during the scrolling of the interface.
Tips: Be careful to distinguish between two off-screen renderings
Core Graphics’ rendering API does trigger off-screen rendering, but not the kind that gpus do. The rendering API using Core Graphics is executed on the CPU, triggering the CPU version of the off-screen rendering.
What we are studying here is more GPU off-screen rendering. In Core Animation Debug, Color offscreen-renderd Yellow is used to detect such content
Why off-screen rendering exists
This is mainly because of two reasons:
- Some special effects require extra use
Offscreen Buffer
To save the intermediate state of the render, so you had to use off-screen rendering. Like mask, UIBlurEffectView and so on - For efficiency purposes, if it is a very complex static page, the content can be rendered ahead of time and saved in
Offscreen Buffer
To achieve the purpose of reuse. For example, when CALayer shouldRasterize attribute is enabled, the Render Server will force CALayer’s rendering bitmap result to be saved, so that it can be reused directly next time when it needs to Render, thus improving efficiency
Which common scenes trigger off-screen rendering
In Apple’s WWDC 2011-Session 121 Understanding UIKit Rendering, it is explained that the following four properties of a CALayer cause off-screen rendering: Mask, Shadow, Group Opacity, Edge Antialiasing. The other one is the most common scene in our development — rounded corners:
backgroundColor, layer.content, layer.cornerRadius, layer.masksToBounds
Is in the (UIViewclipToBounds
) Combination scene!!- Set a mask for the layer. This can be referenced
Off-screen rendering in Article 1 -- MASK
- Layer of the
allowsGroupOpacity
Property is YES andopacity
Less than 1.0, GroupOpacity means that the opacity of the child layer cannot be greater than that of the parent layer - I’m going to set shadow
The cornerRadius is described separately below
Top priority: UIView rounded scene!!
Here’s a look at where this sentence leads:
view.layer.cornerRadius = 5
Copy the code
Setting the radius to a value greater than 0.0 causes the layer to begin drawing rounded corners on its background. By default, the corner radius does not apply to the image in the layer’s contents property; it applies only to the background color and border of the layer. However, setting the masksToBounds property to YES causes the content to be clipped to the rounded corners.
Copy the code
The relationship between the background color border of the layer and the layer content is as follows:
To sum up:
-
Layer. cornerRadius will only work with background color and border of the layer, but not with layer.content!!
-
CornerRaidus adds layer.masksToBounds if it needs to work on layer.content
In addition, some articles have analyzed whether layer.content and the above attributes can be rendered off-screen in various situations, as follows:
-
Setting backgroundColor, borderWidth, borderColor, cornerRadius=> does not trigger off-screen rendering
-
Adding masksToBounds under 1 => will not trigger off-screen rendering
-
Add layer. Content to 2 ==> trigger off-screen rendering
-
Or add a subLayer with a graph to the view…. ==> Render off screen
Specific practical articles can be referred to:
Have you really figured out the off-screen rendering of iOS rounded corners
The real reason for off-screen rendering is summarized in this article:
The layer overlay generally follows the “painter’s algorithm”, which refers to the oil painting algorithm: first draw the objects in the scene that are farther away from the observer, then draw the objects that are closer to the observer. Originally, we draw from the back to the front, and once we’ve drawn one layer, we can discard it. But now you need to save it in the Offscreen Buffer in turn, waiting for rounded corners + clipping, which triggers off-screen rendering
- Background color, border, background color + border, plus rounded corners + cropped, according to the documentation, becausecontents = nilThere’s nothing to crop, so
masksToBounds
Set toYES
orNO
It doesn’t matter. - Once we set content for contents, whether it’s an image, draw content, subview with image information, etc., plus rounded corners + cropping, it triggers off-screen rendering.
Optimizations after iOS9
layer.contents/imageView.image Copy the code
We’re just going to set contents or UIImageView’s image, and we’re going to add rounded corners and crop, and we’re not going to render off screen.
However, adding a backgroundColor, borderWidth/color, or any other layer will result in off-screen rendering
A special case of UIButton, adding a graph to UIButton will add a UIImageView, so iOS9 will still produce off-screen rendering
In one sentence:
Offscreen Rendering is triggered whenever the cropped content requires the participation of content before the artist’s algorithm is complete
In addition, UIView rounded corner content solution:
- If you don’t need rounded corners from outside sources, it’s most convenient for the designer to draw them directly
- Blend Layer: Overlay a partially transparent view on top of the view to which you want to add rounded corners, masking only the rounded corners
- The above two methods do not work, in the use of the image, use CoreGraphic directly asynchronous redraw a rounded picture!!
Rendering of other scenes
For shadow, if the layer is a simple geometric shape or rounded shape, we can optimize the performance by setting shadowPath, which can greatly improve the performance. The following is an example:
imageView.layer.shadowColor = [UIColor grayColor].CGColor; ImageView. Layer. ShadowOpacity = 1.0; ImageView. Layer. ShadowRadius = 2.0; UIBezierPath *path = [UIBezierPath bezierPathWithRect:imageView.frame]; imageView.layer.shadowPath = path.CGPath;Copy the code