美文网首页前端开发性能优化
iOS离屏渲染以及切圆角所产生的离屏渲染

iOS离屏渲染以及切圆角所产生的离屏渲染

作者: Miraclely | 来源:发表于2020-07-07 20:50 被阅读0次

    1. 什么是离屏渲染

    在正常情况下,经过CPU的计算以及GPU的渲染之后,会将结果存放到帧缓存区,随后视频控制器会读取帧缓存区的数据,经过数模转换,再逐行显示到屏幕上(如下图)。


    image.png

    并且在GPU渲染的过程中,一般情况下,会遵循‘画家算法’按次序由远及近的一层一层将结果放置到帧缓存区中,当当前帧缓存区的数据显示到屏幕上之后,就会将该帧丢弃,周而复始。(如下图)


    image.png
    但是,在某些特殊情况下(对一个多图层的view设置了圆角等),当我们一层层的渲染完图层,要应用一些操作,比如裁剪的时候,之前放置在帧缓存区的数据早已经被丢弃或者说是被覆盖了,这个时候也就不可能对所有图层做这些操作了。
    因此,我们需要开辟一些离屏缓存区来存放一些中间状态的数据,等待全部的图层都渲染到离屏缓存区之后,分别从各个离屏缓存区取出数据,分别做相应的操作(裁剪等)之后,组合存入帧缓存区,再等待屏幕控制器的读取和屏幕刷新。大致流程如下图。
    image.png

    2.离屏渲染的利弊

    劣势

    离屏渲染其实是加大了系统的负担,确实会造成性能上的损耗。主要表现在以下几个方面。

    离屏渲染需要额外的存储空间,存储空间大小的上限是2.5倍的屏幕像素大小,一旦超过,则无法使用离屏渲染
    容易掉帧:一旦因为离屏渲染导致最终存入帧缓存区的时候,已经超过了16.67ms,则会出现掉帧的情况

    优势

    虽然离屏渲染会需要多开辟出新的临时缓存区来存储中间状态,但是对于多次出现在屏幕上的数据,可以提前渲染好,从而达到复用的目的,这样CPU/GPU就不用做一些重复的计算。

    其实在很多iOS开发的需求背景之下,比如 一些特殊动画效果的开发,此时需要多图层以及离屏缓存区保存中间状态,这种情况下就不得不使用离屏渲染。

    3.常见的几种出发离屏渲染的情况

    1.使用了 mask 的 layer (layer.mask)

    2.需要进行裁剪的 layer (layer.masksToBounds /view.clipsToBounds)

    3.设置了组透明度为 YES,并且透明度不为 1 的layer (layer.allowsGroupOpacity/ layer.opacity)

    4.添加了投影的 layer (layer.shadow*)

    5.采用了光栅化的 layer (layer.shouldRasterize)

    6.绘制了文字的 layer (UILabel, CATextLayer, Core Text 等)

    4.切圆角所产生的离屏渲染

    我们先打开模拟器的离屏渲染颜色标记:


    image.png

    代码如下:


    image.png
    此时,我们将看到
    image.png

    其中黄色的就代表发生了离屏渲染,也即1和3发生了离屏渲染。

    当我们设置了cornerRadius以及masksToBounds(或者clipsToBounds)进行圆角+裁剪时,masksToBounds裁剪属性会应用到所有的图层上。


    image.png

    本来我们从后往前绘制,绘制完一个图层就可以丢弃了。但现在需要依次在 Offscreen Buffer中保存,等待圆角+裁剪处理,即引发了 离屏渲染 。

    此时我们看一下cornerRadius的文档说明


    image.png

    cornerRadius的文档中明确说明对cornerRadius的设置只对 CALayer 的backgroundColor和borderWidth&borderColor起作用,不会对content进行圆角设置,除非同时设置了masksToBounds为YES(对应view中的clipsToBounds属性)此时两个属性相结合,产生离屏渲染。这也就说明了上面代码为什么1和3触发了离屏渲染,而2和4没有触发离屏渲染

    几种解决办法:

    方案1.
    针对button上的imageView,改为
    // 设置圆角
    button.imageView.layer.cornerRadius = 100.0;
    // 设置裁剪
    button.imageView.clipsToBounds = YES;
    方案2.


    image.png

    方案3.


    image.png
    方案4.
    image.png
    方案5.使用YYImage的对于圆角的处理代码
    image.png

    相关文章

      网友评论

        本文标题:iOS离屏渲染以及切圆角所产生的离屏渲染

        本文链接:https://www.haomeiwen.com/subject/ibbzqktx.html