美文网首页
iOS离屏渲染解析

iOS离屏渲染解析

作者: ugpass | 来源:发表于2020-07-07 15:55 被阅读0次

iOS渲染层级

image.png

CoreAnimation核心动画是由Layer Kit演变而来,所以它并不是只能做关于动画方面的,它可以理解为一个复合引擎,目的是更快的组合屏幕上不同的显示内容。

离屏渲染的定义

  • 没有离屏渲染时:
image.png

App通过CPU和GPU的配合,将渲染数据放入帧缓冲区,视频控制器不断的从帧缓冲区取出数据显示到显示屏上。

  • 离屏渲染时:
image.png

和未发生离屏渲染时相比,App并不是直接将数据放入帧缓冲区,而是额外先开辟一个离屏缓冲区(Offscreen Buffer),在离屏缓冲区将渲染内容进行额外渲染和合并之后,再将数据送入帧缓冲区。

Offscreen Buffer存储最大限制为屏幕像素的2.5倍

理解圆角CornerRadius和离屏渲染的关系

问题:btn.layer.cornerRadius = 5; btn.layer.maskToBounds = YES;一定会触发离屏渲染吗?

CornerRadius的官方文档解释:只对layer的background和border起作用,并不会作用于contents。但是设置masksToBounds对应UIView的clipsToBounds则会对内容进行裁剪。

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 
YES causes the content to be clipped to the rounded corners.

案例1:按钮设置图片 即在按钮上添加一个ImageView,则有两个图层,做圆角需要对两个图层进行裁剪,则会触发离屏渲染。

    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:按钮添加背景色、设置border,仍然只有按钮一个图层做圆角,并不会触发离屏渲染。

    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:ImageView设置图片和背景色,两个图层做圆角,则会触发离屏渲染。

    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:ImageView只设置图片,只有一个图层做圆角则不会触发离屏渲染。

    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"];

常见对触发离屏渲染的几种情况:

  • 使用了mask的layer (layer.mast)

  • 需要进行裁剪的layer (layer.mastToBounds / view.clipToBounds)

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

  • 添加了阴影的layer (layer.shadow)

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

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

总结:离屏渲染出现原因是由于多个图层需要进行裁剪/混合等处理,需要放入offscreen buffer所造成的。我理解的这里的一个图层并不等于一个CALayer,一个CALayer可以包含多个图层。

离屏渲染产生的问题

  • APP需要额外的开辟Offscreen Buffer空间,大量的离屏渲染可能造成内存的压力。
  • 需要在Offscreen Buffer和Frame Buffer之前进行频繁切换,需要长时间的处理

对应的造成性能问题以及掉帧

需要使用离屏渲染的场景

  • 特殊效果:需要使用offscreen Buffer保存中间状态,不得不使用离屏渲染,此时由系统自动触发,如圆角、阴影、组透明度等。

  • 提升效率:重复的、静态的资源打开光栅化(shouldRasterize)可以节约之后渲染的时间。打开光栅化需要注意以下几点:

    • 如果layer不能复用,则没有必要打开光栅化。

    • 如果layer不是静态的,需要被频繁修改。比如动画,打开光栅化反而影响效率。

    • 离屏渲染缓存内容有时间限制,如果超过100ms没有被使用,则被丢弃,无法复用。

    • 离屏渲染缓存空间最大为屏幕像素的2.5倍,超过则则会失效,无法复用。

相关文章

  • iOS离屏渲染解析

    iOS离屏渲染解析

  • iOS离屏渲染

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

  • iOS离屏渲染解析

    离屏渲染 我们都知道一般情况下离屏渲染是犹豫设置了圆角触发的。触发离屏渲染真的只需要设置圆角么?下来我们通过案例分...

  • iOS离屏渲染解析

    iOS渲染层级 CoreAnimation核心动画是由Layer Kit演变而来,所以它并不是只能做关于动画方面的...

  • iOS圆角的离屏渲染,你真的弄明白了吗

    iOS圆角的离屏渲染,你真的弄明白了吗iOS圆角的离屏渲染,你真的弄明白了吗

  • iOS-离屏渲染探索

    iOS项目性能优化时,不得不提到离屏渲染,为了提升性能,我们要求尽量减少离屏渲染的发生。 那,什么是离屏渲染?离屏...

  • iOS离屏渲染的检测和优化

    在iOS离屏渲染介绍了离屏渲染的逻辑和原理,我们知道离屏渲染对于性能会有较大的消耗,那么开发中怎么避免产生离屏渲染...

  • iOS离屏渲染相关值得看的博客

    博客链接 iOS离屏渲染优化 绘制像素到屏幕上 关于iOS离屏渲染的深入研究 https://texturegro...

  • 三、iOS离屏渲染

    iOS离屏渲染 圆角不一定会造成离屏渲染 GPU屏幕渲染方式 On-Screen Rendering 当前屏幕渲染...

  • iOS性能优化之图片圆角

    在Apple官方文档中多次提出开发时,避免触发离屏渲染效果.离屏渲染触发的情况有很多种,具体可参考iOS离屏渲染相...

网友评论

      本文标题:iOS离屏渲染解析

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