美文网首页
iOS离屏渲染相关探索

iOS离屏渲染相关探索

作者: 星星1024 | 来源:发表于2020-07-07 23:09 被阅读0次

    GPU屏幕渲染的方式有两种

    • On-Screen Rendering (当前屏幕渲染)
      GPU的渲染操作是在当前用于显示的屏幕缓冲区进行,不需要创建新的缓存,也不需要开启新的上下文,所以性能较好.但是会受到缓存大小限制等因素,一些复杂的操作无法完成.
    • Off-Screen Rendering(离屏渲染)
      GPU在当前屏幕缓冲区外开辟新的缓冲区进行操作
    渲染流程对比.png

    离屏渲染的过程分解

    1. 创建新的缓冲区(offScreenBuffer空间大小有限制,为屏幕像素点的2.5倍)
    2. 切换上下文到离屏缓冲区(消耗资源较大)
    3. 在离屏缓冲区进行渲染
    4. 切换上下文到显示屏幕上(消耗资源较大)
    5. 将离屏缓冲区的渲染结果显示到哦屏幕上

    离屏渲染存在的问题

    1. Off-Screen Rendering空间大小有限制,为屏幕像素的2.5倍
    2. 容易掉帧,产生性能问题
    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 等)
    针对光栅化的使用,有以下几个建议:
    • 如果layer不能被复用,则没有必要开启光栅化
    • 如果layer不是静态,需要被频繁修改(例如动画过程中),此时开启光栅化反而影响效率
    • 离屏渲染缓存内容有时间限制,如果100ms内没有被使用,那么就会丢弃,无法进行复用
    • 离屏渲染的缓存空间有限,是屏幕的2.5倍,超过2.5倍屏幕像素大小的话也会失效,无法实现复用

    圆角中触发离屏渲染的时机

        //1.按钮存在背景图片
        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.按钮不存在背景图片
        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.UIImageView 设置了图片+背景色;
        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.UIImageView 只设置了图片,无背景色;
        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"];
    
    图四

    从上面四个图可以发现图一和图三触发了离屏渲染,图二和图四没有,原因是为什么呢?

    • 首先来说一下CALayer的构成,它是由backgroundColor.content,borderColor和borderWith构成

      CALayer构成
    • 图一我们不设置btn2.clipsToBounds = YES;显示结果不是圆角

      Apple官方文档描述
    • 官放文档描述设置cornerRadius只会对backgroundColorborder生效,不会设置content圆角,将masksToBounds属性设置为YES将导致内容被剪切到圆角。

    • 所以圆角不生效的原因是没有对content设置圆角,UIButton设置image是放在content里面,所以按钮如果设置圆角必须要设置btn1.clipsToBounds = YES;/btn1.layer.masksToBounds = YES;才行.

    • 同理图三触发离屏渲染也是对CALayer进行了裁剪,图四圆角但是没有触发离屏渲染

    • 当content中有子视图,设置cornerRadiuslayer.masksToBounds /clipsToBounds就会触发离屏渲染,反之只设置backgroundColor/bordercontent中的一个,无论设置layer.masksToBounds /clipsToBounds是否等于YES都不会触发离屏渲染.

    相关文章

      网友评论

          本文标题:iOS离屏渲染相关探索

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