1.什么是离屏渲染
gpu(图形学处理器)屏幕渲染有两种方式:
On-Screen Rendering 当前屏幕渲染,指的是GPU的渲染操作是在当前用于显示的屏幕缓冲区中进行。
Off-Screen Rendering 离屏渲染,指的是GPU在当前屏幕缓冲区以外新开辟一个缓冲区进行渲染操作。
2.为什么离屏渲染的代价很大
离屏渲染需要在当前屏幕缓冲区以外创建一个新的缓冲区。
整个离屏渲染的过程中,需要进行多次上下文切换。
首先从将上下文环境从当前屏幕切换到离屏进行离屏渲染。渲染结束以后,需要将离屏渲染缓冲区的结果显示到屏幕上。然后再将上下文环境从离屏切换到当前屏幕。然而,上下文切换的代价是很大的。
3.离屏渲染的触发方式
在设置了以下属性以后,都会触发离屏渲染:
shouldRasterize(光栅化)//光栅化和离屏渲染的问题再研究
masks(遮罩)
ps:设置圆角语句本身并不会触发离屏渲染。view.layer.cornerRadius = 5;
但是设置圆角属性只在一些特定情况下有效,即视图的背景和边界。如果要给UILabel设置圆角属性,就需要两行代码:
label.layer.cornerRadius = 5;
label.layer.masksToBounds = true;
而第二行代码设置masksToBounds就会触发离屏渲染。
shadows(阴影)
edge antialiasing(抗锯齿)
group opacity(不透明)
4.特殊的离屏渲染
按照之前的说法,如果将不在GPU的当前屏幕缓冲区中进行的渲染都称为离屏渲染,那么就还有另一种特殊的“离屏渲染”方式:CPU渲染。
如果我们重写了drawRect方法,并且使用任何Core Graphics的技术进行了绘制操作,就涉及到了CPU渲染。整个渲染过程由CPU在App内同步地完成,渲染得到的bitmap最后再交由GPU用于显示。
5.屏幕渲染的选择
现在有三种屏幕渲染方式:当前屏幕渲染方式、离屏渲染、CPU渲染。
尽量使用当前屏幕渲染
鉴于离屏渲染、CPU渲染可能带来的性能问题,一般情况下,我们要尽量使用当前屏幕渲染。
离屏渲染 VS CPU渲染
由于GPU的浮点运算能力比CPU强,CPU渲染的效率可能不如离屏渲染;但如果仅仅是实现一个简单的效果,直接使用CPU渲染的效率又可能比离屏渲染好,毕竟离屏渲染要涉及到缓冲区创建和上下文切换等耗时操作。
6.通过设置CALayer的mask
设置view.layer.mask同样会引发离屏渲染问题,从而降低fps(每秒传输帧数量)。
有两种生成遮罩的方式:
// 通过图片生成遮罩
UIImage*maskImage = [UIImageimageNamed:@"someimg"];
CALayer*mask = [CALayernew];mask.frame =CGRectMake(0,0, maskImage.size.width, maskImage.size.height);
mask.contents = (__bridgeid_Nullable)(maskImage.CGImage);
view.layer.mask = mask;
//通过贝塞尔曲线生成
CAShapeLayer*mask = [CAShapeLayernew];
mask.path = [UIBezierPathbezierPathWithOvalInRect:view.bounds].CGPath;
view.layer.mask = mask;
7.利用Core Graphics手动画出圆角
这个方法是在CPU中重新绘制一份圆角视图以达到圆角效果,这样做会增加CPU的开销,。但是这种方式不会触发离屏渲染,不会降低fps。
代码我就不写了,因为我不会用那个什么down 。。。
参考:绘制圆角的四种方法
8.混合图层
在要添加圆角的视图上添加一个部分透明的视图,只对圆角进行遮挡。这种方法不会引起离屏渲染,也不需要占据CPU资源,但是应用场景有限。
参考:
网友评论