APP -> FrameBuffer -> Display
APP -> offscreenBuffer -> FrameBuffer -> Display
mask layer 渲染完毕,不能单独立即显示,要等待 contents layer 渲染完毕进行混合,等待过程中,先存在 离屏渲染缓冲区。
等待内容都渲染完毕,传递到 帧缓冲区,等待显示。
app 进行额外的渲染和合并 -> offscreenBuffer 组合 -> FrameBuffer -> Display
离屏渲染空间限制:屏幕的 2.5 倍
1、获取图像 -> Render Content
2、缩放处理 -> Capture Content
3、水平毛玻璃 -> Horizontal Blur Content
4、垂直毛玻璃 -> Vertical Blur Content
5、合成 -> Compositing Content
6、输出到 FrameBuffer
由于两个 帧缓冲区 空间有限,所以不能存在 帧缓冲区。
处理过程中的 content 存储在 offscreenBuffer。
开启光栅化,layer 渲染为位图后, 会保存在缓冲区,可以复用在其他内容。
不建议开启的场景:
layer 渲染的时候分为三层
Apple 文档
文档显示:
layer.cornerRadius 只会设置 backgroundColor 和 border 的圆角。不会设置 contents 的圆角。
除非同时设置了 layer.masksToBounds 为 YES(对应 view.clipsToBounds)。
简单理解:
layer.cornerRadius 会修改 backgroundColor 和 border 两个图层。
layer.masksToBounds 会让上述切圆角扩张到修改 contents 图层,子视图的图层也在这里。 此时,绘制完 backgroundColor 层后,需要暂存到 offscreenBuffer,等待 contents 层渲染完毕,再进行 裁剪操作,然后输出到 FrameBuffer。这就是就是离屏渲染。
UIButton *btn1 = [UIButton buttonWithType:UIButtonTypeCustom]; btn1.frame = CGRectMake(100, 30, 100, 100); btn1.layer.cornerRadius = 50; [self.view addSubview:btn1]; btn1.clipsToBounds = YES; [btn1 setImage:[UIImage imageNamed:@"btn.png"] forState:UIControlStateNormal]; 复制代码
解析
设置 image 后,触发离屏渲染。
如果不设置 image, contents = nil,系统进行了优化, 不用切圆角,因此直接对 backgroundColor 层操作后,输出到 FrameBuffer 即可。
// UIImageView 设置了切圆角,设置了背景色,设置了图片 UIImageView *img1 = [[UIImageView alloc]init]; img1.frame = CGRectMake(100, 320, 100, 100); [self.view addSubview:img1]; img1.layer.cornerRadius = 50; img1.layer.masksToBounds = YES; img1.backgroundColor = [UIColor blueColor]; img1.image = [UIImage imageNamed:@"btn.png"]; 复制代码
解析
如果不设置 backgroundColor,不会触发离屏渲染。
因为 backgroundColor 图层为空,不要渲染,因此,只需要对 contents 层操作后,输出到 FrameBuffer 即可。
// UIImageView 设置了切圆角,没有设置背景色,但是加了一个子视图 UIImageView *img2 = [[UIImageView alloc]init]; img2.frame = CGRectMake(100, 480, 100, 100); [self.view addSubview:img2]; img2.layer.cornerRadius = 50; img2.layer.masksToBounds = YES; UIView *subView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)]; subView.backgroundColor = [UIColor redColor]; [img2 addSubview:subView]; 复制代码
解析
案例二中,如果没有背景色,img2.layer.contents 直接是位图,可以直接裁剪,输出到 FrameBuffer。
但是案例三中,img2.layer.contents 其实是子视图的渲染出来的位图,如果要给 contents 加圆角,则必须等待子视图渲染完成,存到 offscreenBuffer,然后再对缓冲区中的渲染结果进行裁剪,因此产生了离屏渲染。
案例二中,UIImageView 不设置背景色,只设置 image,就不会触发背景色。
那为什么在案例一中,UIButton 只是设置了 image,没有设置背景色,却触发了离屏渲染呢?
其实是因为 UIButton 设置 image 的时候,是把 image 添加到了 UIButton 的一个 UIImageView 子视图上,就变成了案例三的这种情况,会触发离屏渲染。
离屏渲染本质:要等待对多个非空图层的渲染结果进行操作,过程中的图层需要储存起来,这个存储位置就是 offscreenBuffer(离屏渲染缓冲区),整个过程就叫做离屏渲染。
// UIImageView 设置了切圆角,不设置背景色 imageView.backgroundColor = [UIColor clearColor]; imageView.layer.cornerRadius = 50; imageView.layer.masksToBounds = YES; 复制代码
UI 切图带圆角
使用 贝塞尔曲线,裁剪 UIImage,绘制一个带圆角的 UIImage。
增加一个带圆角,中间镂空的切图,盖在需要圆角的视图上面。