探究iOS离屏渲染原理

2020-07-07  本文已影响0人  Sheisone

一、什么是离屏渲染?

在我前面的博客中对图像是如何显示到屏幕上有了详细的解读 传送门,这里在简单回顾下:

显示原理

主要有以下三步:

屏幕渲染的两种方式:

CoreGraphic通常是线程安全的,所以可以进行异步绘制,显示的时候再放回主线程,一个简单的异步绘制过程大致如下:

-(void)display { 
      dispatch_async(backgroundQueue, ^{ 
            CGContextRef ctx = CGBitmapContextCreate(...); // draw in context...         
            CGImageRef img = CGBitmapContextCreateImage(ctx);
            CFRelease(ctx); 
            dispatch_async(mainQueue, ^{ 
                  layer.contents = img; 
            }); 
       });
}

二、离屏渲染触发的原因

在使用 mask的时候,会分别绘制mask的内容和layer的内容并放入离屏缓存区,然后将二者混合给帧缓存区,然后再进行显示。

下图为CALayer的结构图:

image

如果你只是使用layer.cornerRadius:

layer.cornerRadius = 4;

只会设置backguroundColor和border的圆角,不会设置content的圆角,除非同时设置layer.masksToBounds或者view.clipsToBounds

//二者效果相同,使用任意一个即可
layer.masksToBounds = YES;
view.clipsToBounds = YES;

这个时候才会触发离屏渲染,所以并不是多个层级就一定会触发离屏渲染。

在苹果官方文档中对layer.shouldRasterize有如下解释:

When the value of this property is YES, the layer is rendered as a bitmap in its local coordinate space and then composited to the destination with any other content.

意思简单理解就是说,当开启这个属性后, 这个layer会渲染成位图存起来,需要等所有的要显示的内容全部渲染完毕后,再混合才能够显示到屏幕上。那layer的位图和其它渲染完成的内容放在哪里呢?只能放在离屏缓存区中了,所以光栅化也会触发离屏渲染。

layer.shouldRasterize使用建议如下:

三、为什么要使用离屏渲染?

帧缓存区只是暂存显示内容,内容显示到屏幕上后,就会被丢弃了。但是当使用圆角,阴影,遮罩的时候,图层属性的混合体被指定为在未预合成之前是不能直接在屏幕中绘制,也就是说没办法一次渲染完成直接显示的,所以就需要建立一个新的屏幕外渲染,使用离屏缓存区将内容分批保存,等待所有的内容渲染完成后再传到帧缓存区,以便显示。
屏幕外渲染并不意味着软件绘制,但是它意味着图层必须在被显示之前在一个屏幕外上下文中被渲染(不论CPU还是GPU)。
相比于当前屏幕渲染,离屏渲染的代价是很高的,主要体现在两个方面:

觉得不错记得点赞哦!听说看完点赞的人逢考必过,逢奖必中。ღ( ´・ᴗ・` )比心

上一篇 下一篇

猜你喜欢

热点阅读