一、什么是离屏渲染
正常情况下,经过CPU的计算和GPU的渲染之后,会将结果存放到帧缓存区,随后显示控制器会读取帧缓存区的数据,显示到屏幕上。并且在GPU渲染的过程中,会遵循‘画家算法’按次序由远及近的一层一层将结果放置到帧缓存区中,当当前帧缓存区的数据显示到屏幕上之后,就会将该帧丢弃,周而复始。
但是,在某些特殊情况下,比如某些圆角效果,光栅化等,这些操作需要分别对不同的图层进行处理,最后再合并渲染,只通过帧缓冲区没办法达到这个效果,就需要开启屏幕外缓冲区去保存中间状态。它的一个渲染流程就是先通过离屏缓冲区做图层处理,再合并渲染,然后提交到帧缓冲区,等待下一个刷新信号到来的时候显示到屏幕上,这就是离屏渲染。
离屏渲染会开启离屏缓冲区,它需要额外的存储空间,即屏幕像素点的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 等)
光栅化也会造成离屏渲染
开启光栅化后,会触发离屏渲染,Render Server 会强制将 CALayer的渲染位图结果bitmap保存下
来,这样下次再需要渲染时就可以直接复用,从而提高效率。而保存的 bitmap 包含 layer 的
subLayer、圆角、阴影、组透明度 group opacity 等,所以如果 layer 的构成包含上述几种元素,
结构复杂且需要反复利用,那么就可以考虑打开光栅化。
圆角、阴影、组透明度等会由系统自动触发离屏渲染,那么打开光栅化可以节约第二次及以后的渲染时间。
而多层 subLayer 的情况由于不会自动触发离屏渲染,所以相比之下会多花费第一次离屏渲染的时间,
但是可以节约后续的重复渲染的开销。
使用光栅化的时候需要注意以下几点:
如果 layer 不能被复用,则没有必要打开光栅化
如果 layer 不是静态,需要被频繁修改,比如处于动画之中,那么开启离屏渲染反而影响效率
离屏渲染缓存内容有时间限制,缓存内容 100ms 内如果没有被使用,那么就会被丢弃,无法进行复用
离屏渲染缓存空间有限,超过 2.5 倍屏幕像素大小的话也会失效,无法复用
三、怎么处理离屏渲染问题
方案一、
_imageView.clipsToBounds=YES;
_imageView.layer.cornerRadius=4.0
方案二、
方案四、