GPU屏幕渲染的方式有两种
-
On-Screen Rendering
(当前屏幕渲染)
GPU
的渲染操作是在当前用于显示的屏幕缓冲区进行,不需要创建新的缓存,也不需要开启新的上下文,所以性能较好.但是会受到缓存大小限制等因素,一些复杂的操作无法完成. -
Off-Screen Rendering
(离屏渲染)
GPU
在当前屏幕缓冲区外开辟新的缓冲区进行操作
离屏渲染的过程分解
- 创建新的缓冲区(offScreenBuffer空间大小有限制,为屏幕像素点的2.5倍)
- 切换上下文到离屏缓冲区(消耗资源较大)
- 在离屏缓冲区进行渲染
- 切换上下文到显示屏幕上(消耗资源较大)
- 将离屏缓冲区的渲染结果显示到哦屏幕上
离屏渲染存在的问题
-
Off-Screen Rendering
空间大小有限制,为屏幕像素的2.5倍 - 容易掉帧,产生性能问题
- 渲染需要时间,会产生性能问题
离屏渲染的触发情况
- 使用mask的 layer (layer.mask)
- 需要进行裁剪的layer(layer.masksToBounds / view.clipsToBounds)
- 设置了组透明度为 YES,并且透明度不为 1 的 layer (layer.allowsGroupOpacity/ layer.opacity)
- 添加了投影的layer(layer.shadow)
- 采用了 光栅化的layer(layer.shouldRasterize)
- 绘制了文字的layer(UILabel, CATextLayer, Core Text 等)
针对光栅化的使用,有以下几个建议:
- 如果layer不能被复用,则没有必要开启光栅化
- 如果layer不是静态,需要被频繁修改(例如动画过程中),此时开启光栅化反而影响效率
- 离屏渲染缓存内容有时间限制,如果100ms内没有被使用,那么就会丢弃,无法进行复用
- 离屏渲染的缓存空间有限,是屏幕的2.5倍,超过2.5倍屏幕像素大小的话也会失效,无法实现复用
圆角中触发离屏渲染的时机
//1.按钮存在背景图片
UIButton *btn1 = [UIButton buttonWithType:UIButtonTypeCustom];
btn1.frame = CGRectMake(100, 30, 100, 100);
btn1.layer.cornerRadius = 50;
[self.view addSubview:btn1];
[btn1 setImage:[UIImage imageNamed:@"btn.png"] forState:UIControlStateNormal];
btn1.clipsToBounds = YES;
图一
//2.按钮不存在背景图片
UIButton *btn2 = [UIButton buttonWithType:UIButtonTypeCustom];
btn2.frame = CGRectMake(100, 180, 100, 100);
btn2.layer.cornerRadius = 50;
btn2.backgroundColor = [UIColor blueColor];
[self.view addSubview:btn2];
btn2.clipsToBounds = YES;
图二
//3.UIImageView 设置了图片+背景色;
UIImageView *img1 = [[UIImageView alloc]init];
img1.frame = CGRectMake(100, 320, 100, 100);
img1.backgroundColor = [UIColor blueColor];
[self.view addSubview:img1];
img1.layer.cornerRadius = 50;
img1.layer.masksToBounds = YES;
img1.image = [UIImage imageNamed:@"btn.png"];
图三
//4.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;
img2.image = [UIImage imageNamed:@"btn.png"];
图四
从上面四个图可以发现图一和图三触发了离屏渲染,图二和图四没有,原因是为什么呢?
-
首先来说一下CALayer的构成,它是由
CALayer构成backgroundColor.content,borderColor和borderWith
构成
-
图一我们不设置
Apple官方文档描述btn2.clipsToBounds = YES;
显示结果不是圆角
-
官放文档描述设置
cornerRadius
只会对backgroundColor
和border
生效,不会设置content
圆角,将masksToBounds
属性设置为YES
将导致内容被剪切到圆角。 -
所以圆角不生效的原因是没有对
content
设置圆角,UIButton
设置image
是放在content
里面,所以按钮如果设置圆角必须要设置btn1.clipsToBounds = YES;/btn1.layer.masksToBounds = YES;
才行. -
同理图三触发离屏渲染也是对
CALayer
进行了裁剪,图四圆角但是没有触发离屏渲染 -
当content中有子视图,设置
cornerRadius
和layer.masksToBounds /clipsToBounds
就会触发离屏渲染,反之只设置backgroundColor/border
和content
中的一个,无论设置layer.masksToBounds /clipsToBounds
是否等于YES
都不会触发离屏渲染.
网友评论