What is off-screen rendering

Off-screen Rendering refers to off-screen Rendering, when the GPU creates a new buffer in addition to the current Screen buffer to render

Why do I need to render off-screen

Because rendering a view to the screen in the frame buffer is discarded. So when we have multiple sets of views that need to be combined and then processed uniformly. You need to create an additional off-screen buffer in the screen buffer to record these views. Then unified processing. Finally rendering display

How do I create an off-screen render

Let’s first analyze the off-screen rendering of rounded corners:

To recap, when we add a cornerRadius to a view. Which views are rounded?Copy the code

Apple’s official answer:

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.The default value of This property is 0.0.

That is, the background view and the border view, does not containcontentsView. So when we just setcornerRadiusIs not setmasksToBoundsFor YES. The view still does not have rounded corners visually

Then we rounded corners in the following four cases: A. Set pictures in the button view. And set the cornerRadius and cropped masksToBounds. B. Button view does not set images. Set the cornerRadius and cropped masksToBounds. C. The image view does not set the background color. Set the cornerRadius and cropped masksToBounds. D. Image view sets the background color. Set the cornerRadius and cropped masksToBounds. Produces an off-screen rendering

The relevant codes are as follows:

UIButton * btn1 = [UIButton buttonWithType:(UIButtonTypeCustom)]; btn1.frame = CGRectMake(100, 30, 100, 100); [btn1 setImage:[UIImage imageNamed:@"WX20201127-92813"] forState:UIControlStateNormal]; [self.view addSubview:btn1]; btn1.layer.cornerRadius = 50; btn1.layer.masksToBounds = YES; UIButton * btn2 = [UIButton buttonWithType:(UIButtonTypeCustom)]; btn2.frame = CGRectMake(100, 150, 100, 100); btn2.backgroundColor = UIColor.grayColor; [self.view addSubview:btn2]; btn2.layer.cornerRadius = 50; btn2.layer.masksToBounds = YES; // For images. Setting the background color and image creates an off-screen rendering. UIImageView * img1 = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@" wx20201127-92813 "]]; img1.frame = CGRectMake(100, 270, 100, 100); img1.backgroundColor = UIColor.blueColor; img1.layer.cornerRadius = 50; img1.layer.masksToBounds = YES; [self.view addSubview:img1]; UIImageView * img2 = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"WX20201127-92813"]]; img2.frame = CGRectMake(100, 390, 100, 100); img2.layer.cornerRadius = 50; img2.layer.masksToBounds = YES; [self.view addSubview:img2];Copy the code

The effect is as follows:

So when does an off-screen rendering happen? The superficial conclusions we draw are:

2. Image view rounded after adding background color and imageCopy the code

Next, we will improve img2: Adding no background color to tempView will not produce an off-screen rendering. Adding a background color to the tempView will still result in an off-screen rendering

    UIImageView * img3 = [[UIImageView alloc]init];
    img3.frame = CGRectMake(100, 510, 100, 100);
    img3.layer.cornerRadius = 50;
    img3.layer.masksToBounds = YES;
    [self.view addSubview:img3];
    
    UIView *tempView = [[UIView alloc]init];
    tempView.backgroundColor = UIColor.redColor;
    tempView.frame = img3.bounds;
    [img3 addSubview:tempView];
Copy the code

From this we can know: when we need to combine multiple layers, we need to use the off-screen rendering technology. After rendering multiple layers, place them in the frame buffer. Display to the screen

The thing to notice is that this is the combination. Not superposition.Copy the code

So what are some of the views that we normally use that are combinations. And need to do an off-screen rendering?

2. Mask mask 3. Raster 4. Set transparency for combined view 5. Gradient 7. Draw text 8. System ground glass effectCopy the code

How to avoid off-screen rendering?

1. Off-screen rendering for rounded corners. We can adopt four solutions: a. Cover it with a hollow view with rounded corners B. Use the rounded corner method in YYImage C. Use CALayer with UIBezierPath

UIGraphicsBeginImageContextWithOptions(size, false, scale) UIBezierPath.init(roundedRect: imgRect, cornerRadius: self.layer.cornerRadius).addClip() self.image? .draw(in: imgRect) self.image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext()Copy the code

2. If the view cannot be reused. It is not static. It is not recommended to enable rasterization when frequent modifications are required. Because this will turn on the off-screen rendering and affect efficiency 3. Use transparency as little as possible or not 4. Draw asynchronously. Reduce layers

Off-screen rendering cache content has a time limit. Cache content 100ms of content if not in use. Then it will be discarded. 2. Cache space for off-screen rendering is limited. More than 2.5 screen pixels. It’s not going to work. It’s not going to be reusable