美文网首页
离屏渲染的分析

离屏渲染的分析

作者: 卡布奇诺_95d2 | 来源:发表于2020-08-06 17:14 被阅读0次

什么是离屏渲染

离屏渲染顾名思义就是屏幕外的渲染,即渲染的结果不会立即呈现到显示屏上。
正常情况下,当GPU渲染完成后将数据放在屏幕的帧缓冲区,不需要额外的渲染空间,我们知道iPhone的屏幕刷新率是60Hz,也就是说刷新一帧的时间约为16.7ms,每隔这段时间视频控制器就会去读一次帧缓冲区的内容来显示。
离屏渲染的触发是提前将比较消耗性能的视图提前渲染好,这样能减少卡顿现象。

如何触发离屏渲染

当问到如何会触发离屏渲染时,经常会看到“设置了cornerRadius就会触发离屏渲染”的回答,其实这种说法是不完全正确的。
接下来,我们通过一个实例来看看,到底是什么情况才会出现离屏渲染。打开模拟器离屏渲染显示的,Simulator->Debug->Color Off-scrren Rendered。

  //定义了一个button,将button的背景颜色设置成红色并给button设置圆角
    UIButton *btn1 = [UIButton buttonWithType:UIButtonTypeCustom];
    btn1.frame = CGRectMake(0, 0, 100, 100);
    [btn1 setCenter:CGPointMake(SCREENWIDTH/2,SCREENHEIGHT/2)];
    btn1.backgroundColor = [UIColor redColor];
    btn1.layer.cornerRadius = 50;
    //YES:剪裁超出父视图范围的子视图部分。NO:不剪裁超出父视图范围的子视图
    btn1.clipsToBounds = YES;
    [self.view addSubview:btn1];

执行结果如下图:


image.png

从图片的效果看,这并没有触发离屏渲染,可是代码中有设置button的圆角啊。这是怎么回事呢?先来看官方文档对于cornerRadius的描述。

Setting the radius to a value greater than 0.0 causes the layer to begin drawing rounded corners on its background. By default, the corner radius does not apply to the image in the layer’s contents property; it applies only to the background color and border of the layer. However, setting the masksToBounds property to true causes the content to be clipped to the rounded corners.

从文中描述可以看到,当设置cornerRadius大于0时,默认情况只会对layer的背景和边框设置圆角,而不会对layer的contents设置圆角,除非同时设置layer.masksToBunds为true。
根据官方文档的提示,我们修改上面的代码,增加layer.masksToBunds=true,再来看看效果。

    UIButton *btn1 = [UIButton buttonWithType:UIButtonTypeCustom];
    btn1.frame = CGRectMake(0, 0, 100, 100);
    [btn1 setCenter:CGPointMake(SCREENWIDTH/2,SCREENHEIGHT/2)];
    btn1.backgroundColor = [UIColor redColor];
    btn1.layer.cornerRadius = 50;
    //YES:剪裁超出父视图范围的子视图部分。NO:不剪裁超出父视图范围的子视图
    btn1.clipsToBounds = YES;
    btn1.layer.masksToBounds = YES;
    [self.view addSubview:btn1];

效果如下:


image.png

此时,仍然没有触发离屏渲染,这是为什么呢?会不会是因为我们button的layer上没图片导致呢?在上面的基础上,给button添加图片试试。

    UIButton *btn1 = [UIButton buttonWithType:UIButtonTypeCustom];
    btn1.frame = CGRectMake(0, 0, 100, 100);
    [btn1 setCenter:CGPointMake(SCREENWIDTH/2,SCREENHEIGHT/2)];
    [btn1 setImage:[UIImage imageNamed:@"btn.png"] forState:UIControlStateNormal];
    btn1.layer.cornerRadius = 50;
    //YES:剪裁超出父视图范围的子视图部分。NO:不剪裁超出父视图范围的子视图
    btn1.clipsToBounds = YES;
    btn1.layer.masksToBounds = YES;
    [self.view addSubview:btn1];

效果如下:


image.png

从效果图可以看到,当设置了masksToBounds且同时设置图片,就会触发离屏渲染。
其实不光是图片,我们为当前视图添加有颜色、内容、边框等图像信息的子视图时也会触发离屏渲染。

触发离屏渲染的原因是什么?

首先,来说明一下CALayer,CALayer是由backgroundColor、contents、borderWidth&borderColor组成,如下图所示:


image.png

本来我们从后往前的绘制,绘制完一个图层之后就可以丢弃了,但是现在需要依次在offscreen buffer中保存,等待圆角、裁剪处理,即引发离屏渲染。
当没有contents时,绘制背景色、边框、背景色+边框,再加上圆角+裁剪,此时不管有没有设置masksToBounds。
当有contents时,需要先将背景色、边框、contents放在离屏缓冲区里面,再进行圆角、裁剪处理。此时就触发了离屏渲染。

图层的绘制是遵循“画家算法”,即先绘制场景中较远的物体,再绘制场景中较近的物体。


image.png

离屏渲染给我们带来方便的同时,也带来了严重的性能问题。由于离屏渲染中的离屏缓冲区是额外开辟的一个空间,当数据转存到Frame Buffer时,也是需要耗费时间的,所以转存的过程中也会存在掉帧的可能。另外,离屏缓冲区也不是无限大的,它的最大限制是屏幕的2.5倍。
既然知道离屏渲染会带来性能消耗,那为什么还要使用离屏渲染呢?

  • 可以处理一些特殊的效果,这种效果并不是一次性能完成的,需要使用离屏缓冲区保存中间状态。这种情况的离屏渲染是系统自动触发的,如圆角、阴影、光栅化、高斯模糊等。
  • 部分情况下可以提升渲染的效率,如果一个效果是多次实现,可以提前渲染保存在离屏缓冲区,以备复用,这种情况一般是开发者手动触发的。

iOS9系统之后,苹果对此进行优化。当没有设置backgroundColor且设置content时,是不会触发离屏渲染的。

    UIImageView *img2 = [[UIImageView alloc]init];
    img2.frame = CGRectMake(0, 0, 100, 100);
    [img2 setCenter:CGPointMake(SCREENWIDTH/2, SCREENHEIGHT/2)];
    img2.layer.cornerRadius = 50;
    img2.layer.masksToBounds = YES;
    img2.image = [UIImage imageNamed:@"btn.png"];
    [self.view addSubview:img2];

效果如下:


image.png

如果只有单层layer需要进行圆角、裁剪处理,可以直接在缓冲区里面对数据进行处理,不需要额外使用离屏缓冲区。只有当多图层都需要进行圆角、裁剪处理时,才需要使用离屏缓冲区。

相关文章

  • iOS离屏渲染

    iOS-离屏渲染详解关于iOS离屏渲染的深入研究关于离屏渲染这两片文章分析的很详细。 渲染过程 根据渲染流水线示意...

  • 离屏渲染的原理和分析

    1.常见触发离屏渲染的情况 在分析离屏渲染的原因之前先介绍几种常见的触发离屏渲染的情况 使⽤了 mask (遮罩...

  • iOS--离屏渲染

    离屏渲染(Offscreen rendering) 离屏渲染的定义 离屏渲染(offscreen-renderin...

  • 关于离屏渲染

    1.什么是离屏渲染 2.离屏渲染的触发方式 3.离屏渲染的意义 4.离屏渲染的不足 1.什么是离屏渲染 要了解离屏...

  • 图层性能-离屏渲染、光栅化等

    一.离屏渲染 1.在屏渲染、离屏渲染: On-Screen Rendering/在屏渲染:在屏渲染:指的是GPU的...

  • 四、iOS离屏渲染

    一、开启图层是否触发离屏渲染问题 注:离屏渲染的图层会标记为黄色 二、离屏渲染的渲染流程 三、离屏渲染触发的原因 ...

  • iOS下对离屏渲染的理解

    离屏渲染定义 离屏渲染的流程如图: GPU把渲染好的的内容存放到离屏渲染缓冲区中,在离屏渲染缓冲区(Offscre...

  • UI视图及UITableView流畅性优化

    一.离屏渲染 1. 在屏渲染和离屏渲染 在屏渲染是指在当前用于显示的屏幕缓冲区进行GPU渲染操作 离屏渲染是指在当...

  • 离屏渲染的分析

    什么是离屏渲染 离屏渲染顾名思义就是屏幕外的渲染,即渲染的结果不会立即呈现到显示屏上。正常情况下,当GPU渲染完成...

  • 003-iOS离屏渲染产生的原因

    离屏渲染产生的原因 在讨论离屏渲染之前我们先要搞清楚正常的渲染流程是怎样的 非离屏渲染流程: 我们可以看到在非离屏...

网友评论

      本文标题:离屏渲染的分析

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