iOS 屏幕渲染
iOS 屏幕渲染是双缓存机制, 有一个当前屏幕缓存, 另一个非当前屏幕缓存, 也就是离屏缓存。 屏幕显示过程, 是cpu负责计算, GPU负责渲染, 然后把渲染的结果,存储在缓存区, 然后显示器根据垂直同步信号,直接取缓存期的数据,进行显示。 在要显示的数据,不能直接计算并渲染完成时, 就会在非当前屏幕的缓冲区,进行渲染。屏幕显示,通过指向不同的缓冲区,依次取两个缓存区的数据, 但是从当前屏幕缓冲器,切换到离屏缓冲区, 要切换上下文,也会耗费一些资源
当前屏幕渲染不需要额外创建新的缓存,也不需要开启新的上下文,相对于离屏渲染性能更好。但是受当前屏幕渲染的局限因素限制(只有自身上下文、屏幕缓存有限等),当前屏幕渲染有些情况下的渲染解决不了的,就需要使用到离屏渲染。
相比于当前屏幕渲染,离屏渲染的代价是很高的,主要体现在两个方面:
创建新的缓冲区
要想进行离屏渲染,首先要创建一个新的缓冲区。
上下文切换
离屏渲染的整个过程,需要多次切换上下文环境:先是从当前屏幕(On-Screen)切换到离屏(Off-Screen),等到离屏渲染结束以后,将离屏缓冲区的渲染结果显示到屏幕上又需要将上下文从离屏切换到当前屏幕。而上下文环境的切换是要付出很大代价的。
- 既然离屏渲染这么耗性能,为什么有这套机制呢?
有些效果被认为不能直接呈现在屏幕,而需要在其他的地方进行预合成。图层属性的混合体在预合成之前不能在屏幕内绘制,就需要屏幕外渲染,屏幕外渲染不意味着软件绘制,但是他意味着图层在显示之前必须在一个屏幕外上下文被渲染。
离屏渲染的触发
以下情况或操作会触发离屏渲染:
1、masks(遮罩),为图层设置遮罩layer.mask
2、图层截取,将图层的layer.masksToBounds或view.clipsToBounds属性设置为true
3、透明设置,将图层layer.allowsGroupOpacity属性设置为YES和layer.opacity小于1.0
4、shadows(阴影),为图层设置阴影layer.shadow
5、开启光栅化,设置layer.shouldRasterize为true
6、设置圆角,layer.cornerRadius
7、设置抗锯齿,layer.edgeAntialiasingMask,layer.allowsEdgeAntialiasing
8、文本,(任何种类,包括UILabel, CATextLayer, Core Text等)
9、渐变
10、特殊的离屏渲染:CPU渲染
如果重写了drawRect方法,并且使用任何Core Graphics的技术进行了绘制操作,就涉及到了CPU渲染。整个渲染过程由CPU在App内同步的完成,渲染得到的bitmap最后再交由GPU用于显示。CoreGraphic通常是线程安全的,所以可以进行异步绘制,显示的时候再放回主线程。
网友评论