[TOC]
preface
When we explored the relevant principles of iOS animation and rendering in the early stage, we successively understood the principles of computer graphics rendering, mobile terminal screen imaging and Caton principle, each rendering framework of iOS and iOS layer rendering principle.
As a programmer, we have several learning methods to improve our technical ability, such as chain learning, ring learning, comparative learning and so on. Obviously, we are using chain learning to explore the principles of iOS animation and rendering. Then, in order to broaden our knowledge and have a relatively systematic understanding of the same subject, we will adopt the loop learning method to explore several topics related to iOS:
- IOS -OffScreenRendering off-screen rendering principle
- Causes and solutions of iOS CPU and GPU resource consumption
So let’s jump right into our first new topic today,OffScreenRendering principles
1. Specific process of off-screen rendering
First, we need to understand the rendering process and the off-screen rendering process to prepare for the following knowledge:
- The usualApply colours to a drawing
- To simplify things, the usual rendering flow looks like this:
- Through the cooperation of CPU and GPU, App continuously completes the content rendering and puts it into the Framebuffer Framebuffer, while the display screen continuously obtains the content from the Framebuffer and displays the real-time content
- Off-screen rendering
- The off-screen rendering process looks like this:
- Different from the normal situation where GPU directly puts the rendered content into the Framebuffer, it needs to create an additional Offscreen rendering Buffer to put the rendered content in advance into it. Wait until the appropriate time to further overlay and render the contents of the Offscreen Buffer, and then switch the results to the Framebuffer
Second, the efficiency of off-screen rendering
- According to the above process, when off-screen rendering, the App needs to render some content in advance and save it to Offscreen Buffer, as well as switch Offscreen Buffer and Framebuffer when necessary. Therefore, it takes longer processing time (in fact, both steps are very costly in terms of buffer switching).
- In addition, the Offscreen Buffer itself needs extra space, and a large number of off-screen rendering may cause too much pressure on memory
- At the same time, the total size of the Offscreen Buffer is also limited and cannot exceed 2.5 times the total pixels of the screen
- visible
The overhead of off-screen rendering is very high. Once too much content needs to be rendered off-screen, it is easy to cause the problem of dropping frames
- so
In most cases, off-screen rendering should be avoided as much as possible
Why use off-screen rendering
So why use an off-screen rendering? Mainly because of the following two reasons:
- Some special effects require an extra Offscreen Buffer to hold the intermediate state of the render, so off-screen rendering is necessary.
- For efficiency purposes, the content can be rendered in advance and saved in Offscreen Buffer to achieve reuse purposes.
Passive trigger
-
For the first case, where off-screen rendering has to be used, it is usually triggered automatically by the system, such as shadows, rounded corners, etc
- One of the most common situations is when a mask is used
- As shown in the figure, since the final content is superimposed by two layers of render results, extra memory space must be used to save the intermediate render results, so the system will trigger the off-screen render by default.
- Here’s another example: iOS 8 started offering a blur effect UIBlurEffectView:
- The whole fuzzy process is divided into several steps:
- Pass 1 first renders the content itself that needs to be blurred
- Pass 2 scales the content
- In Pass 3 and 4, the content of the previous step is respectively blurred in horizontal and vertical directions. In the last step, the blurred results are superimposed and synthesized, and the complete fuzzy special effects are finally realized
Take the initiative to use
- In the second case, the use of off-screen rendering for reuse and efficiency is generally an active action, achieved by CALayer’s shouldRasterize rasterization operation.
shouldRasterize
When rasterization is enabled, off-screen rendering is triggered
, Render Server will force CALayer’s Render bitmap result bitmap to be saved, so that it can be reused directly next time when rendering is needed, thus improving efficiency- whileThe saved bitmap contains layer subLayer, rounded corners, shadows, and group opacityAnd so on, so
If the layer consists of the above elements, and the structure is complex and requires repeated use, then rasterization can be considered
- Rounded corners, shadows, group transparency, etc. are automatically triggered by the system for off-screen rendering, so turning on rasterization saves the second and subsequent rendering time. In the case of multi-layer subLayer, since off-screen rendering will not be triggered automatically, it will take more time for the first off-screen rendering, but it can save the cost of subsequent repeated rendering
- However, the following points should be noted when using rasterization:
-
- if
Layer is not necessary if it cannot be reused
Turn on rasterization
- if
-
If layer is not static, it needs to be modified frequently
For example, in animation, thenTurning on off-screen rendering actually affects efficiency
-
Off-screen rendering of cached content has a time limit
If the cached content is not used within 100ms, it will be discarded and cannot be reused
-
Off-screen rendering has limited cache space and will fail to be reusable if it is larger than 2.5 screen pixels
-
5. Off-screen rendering of rounded corners
-
In general, the off screen rendering is triggered automatically after the layer rounded effect is set. But when exactly does rounded corners trigger an off-screen rendering?
-
As shown above, layer is made up of three layers, and we usually set the rounded corners first like this line:
view.layer.cornerRadius = 2 Copy the code
-
As described by the Cornerradius-apple, this code only sets the backgroundColor and border corners by default, not the content corners. Unless layer.masksToBounds is set to true (corresponding to UIView clipsToBounds)
-
If a cornerRadius is set and masksToBounds is not set, off-screen rendering will not be triggered because there is no need to overlay cropping. When clipping is set, masksToBounds will crop the layer and all subLayer content, so off-screen rendering must be triggered
View.layer. masksToBounds = true // Trigger the off-screen render reasonCopy the code
-
So Texture also suggests that you try not to trigger an off-screen rendering if rounded cropping isn’t necessary:
Six, the specific logic of off-screen rendering
-
Rounded corners and masksToBounds will crop everything on the layer and trigger the off-screen rendering
-
The overlay of layers roughly follows the “painter’s algorithm,” which draws layers by layers, first drawing scenes that are farther away and then covering them with scenes that are farther away
-
In ordinary layer drawing, the upper sublayer will cover the lower sublayer, and the lower sublayer can be discarded after drawing, thus saving space and improving efficiency. \
-
After all the sublayers have been drawn, the entire drawing process is complete, and the subsequent rendering is ready. Suppose we wanted to draw a three-layer sublayer, with no clipping and rounded corners, and the entire drawing process would look like this:
-
When the cornerRadius is set and the masksToBounds clipping property is applied to all sublayer as described above. This means that all sublayer must be applied once again, which means that all sublayer cannot be discarded immediately after being drawn for the first time, but must be stored in Offscreen buffer to wait for the next round of sublayer + clipping. This also induces off-screen rendering, the specific process is as follows:
-
Opacity+ opacity (layer.allowsGroupOpacity+layer.opacity) and shadowOffset (opacity, opacity, opacity, opacity, opacity, opacity, opacity, opacity, opacity, opacity, opacity, opacity, opacity, opacity, opacity, opacity, opacity, opacity, opacity, opacity, opacity, opacity, opacity) Applies to layer and all of its sublayers, which inevitably causes an off-screen rendering
7. Avoid off-screen rendering of rounded corners
- Besides minimizing the use of rounded clipping, is there any other way to avoid the off-screen rendering caused by rounded corners + clipping?
- As we mentioned earlier,Rounded corners cause the nature of off-screen renderingis
Clipping stack
, causing masksToBounds to perform secondary processing on layer and all sublayer. Then weAs long as you avoid using masksToBounds for secondary processing and instead preprocess all sublayer, you can just do the "painter algorithm"
, using a single stack to complete the drawing - Then the possible implementation methods are as follows:
- 1. [Resource exchange]
Use rounded images directly
Or,Replace the background color with a solid background with rounded corners
To avoid the use of rounded corners.However, this method depends on the situation and is not universal
. - 2. The “mask”
Add a mask with the same color as the background to cover the top layer and cover the four corners
, creating a rounded shape. But this wayDifficult to resolve cases where the background color is a picture or gradient
. - 3. 【 UIBezierPath 】
Draw closed rectangles with rounded corners using Bezier curves
, set only the interior visible in the context, then render layer without rounded corners as a picture and add it to the Bezier rectangle.This method is more efficient, but once the layout of the layer changes, the Bezier curve needs to be manually redrawn, so the frame, color, etc., need to be manually monitored and redrawn.
- 4. CoreGraphics: drawRect:,
Draw manually when rounded corners need to be applied using core Graphics-related methods
. However,CoreGraphics is also very inefficient and can be problematic if multiple calls are required
.
- 1. [Resource exchange]
Summary of reasons for triggering off-screen rendering
-
To summarize, there are several situations that trigger off-screen rendering:
-
Layer with mask (layer.mask)
-
Layer (layer.maskstobounds/view.clipstobounds)
-
Set up a group to YES, transparency and transparency of 1 layer (layer. AllowsGroupOpacity/layer. Opacity)
-
Added layer of shadow (layer.shadow)
-
ShouldRasterize (layer. ShouldRasterize)
-
Layer with Text drawn (UILabel, CATextLayer, Core Text, etc.)
-
-
Note, however, that overriding the drawRect: method does not trigger an off-screen rendering. As mentioned earlier, overwriting drawRect will transfer the rendering operation from the GPU to the CPU and require additional memory space. According to Apple engineers, this won’t be a standard off-screen render, and it won’t be rendered off-screen when the Color offscreen Rendered yellow debugging is turned on in Instrument.
reading
- On principle of 01 – computer | computer graphics rendering this article
- 02 – | mobile terminal screen computer imaging and caton
IOS related Topics
- 01 – iOS | the underlying principle of iOS rendering framework and principle of iOS layer rendering
- 02 – iOS underlying principle | iOS animation rendering principle
- 03 – iOS underlying principle | iOS OffScreen Rendering off-screen Rendering principle
[TOC]