UIView渲染
iOS渲染视图的核心是Core Animation 其渲染层次依次为:图层树->呈现树->渲染树
CPU阶段
- 布局(Frame)
- 显示(Core Graphics)
- 准备(QuartzCore/Core Animation)
- 通过IPC提交(打包好的图层树以及动画属性)
OpenGL ES阶段
- 生成(Generate)
- 绑定(Bind)
- 缓存数据(Buffer Data)
- 启用(Enable)
- 设置指针(Set Pointers)
- 绘图(Draw)
- 清除(Delete)
GPU阶段
- 接收提交的纹理(Texture)和顶点描述(三角形)
- 应用变换(transform)
- 合并渲染(离屏渲染等)
总结
- 首先一个视图由CPU进行Frame布局,准备视图和图层的层级关系,查询是否有重写drawRect:或drawLayer:inContext:方法,注意:如果有重写的话,这里的渲染是会占用CPU进行处理的。
- CPU会将处理好的视图和图层的层级关系打包,通过IPC(内部处理通信)通道提交给渲染服务,渲染服务由OpenGL ES和GPU组成。
- 渲染服务首先将图层数据交给OpenGL ES进行纹理生成和着色。生成前后帧缓存,再根据显示硬件的刷新频率,一般以设备的VSync信号和CADisplayLink为标准,进行前后帧缓存的切换。
- 最后,将最终要显示在画面上的后帧缓存交给GPU,进行采集图片和形状,运行变换,应用纹理和混合。最终显示在屏幕上。 iOS平台渲染核心原理的重点主要围绕前后帧缓存、Vsync信号、CADisplayLink
Core Animation
core Animation不仅仅是字面意思的核心动画,而是整个显示核心QuartzCore框架中的Core Animation
Core Animation是依赖于OpenGL ES做GPU渲染,CoreGraphics做CPU渲染
Core Animation 在 RunLoop 中注册了一个 Observer,监听了 BeforeWaiting 和 Exit 事件。这个Observer的 优先级是2000000,低于常见的其他 Observer。当一个触摸事件到来时,RunLoop 被唤醒,App 中的代码会执行一些操 作,比如创建和调整视图层级、设置UIView的frame、修改CALayer的透明度、为视图添加一个动画;这些操作最终都会被 CALayer 捕获,并通过CATransaction提交到一个中间状态去(CATransaction 的文档略有提到这些内容,但并不完 整)。当上面所有操作结束后,RunLoop 即将进入休眠(或者退出)时,关注该事件的 Observer 都会得到通知。这时 CA 注册的那个 Observer 就会在回调中,把所有的中间状态合并提交到GPU去显示;如果此处有动画,CA会通过DisplayLink 等机制多次触发相关流程。
CPU渲染职能
CPU渲染职能主要体现在以下5个方面:
- 布局计算
- 视图懒加载
- Core Graphics绘制
- 如果对视图实现了drawRect:或drawLayer:inContext:方法,或者 CALayerDelegate 的 方法,那么在绘制任何东 西之前都会产生一个巨大的性能开销。为了支持对图层内容的任意绘制,Core Animation必须创建一个内存中等大小的寄宿图片。然后一旦绘制结束之后, 必须把图片数据通过IPC传到渲染服务器。在此基础上,Core Graphics绘制就会变得十分缓慢,所以在一个对性能十分挑剔的场景下这样做十分不好。
- 解压图片
- 图层打包
OpenGL ES渲染职能
简单来说,OpenGL ES是对图层进行取色,采样,生成纹理,绑定数据,生成前后帧缓存。
GPU渲染职能
GPU会根据生成的前后帧缓存数据,根据实际情况进行合成,其中造成GPU渲染负担的一般是:离屏渲染,图层混合,延迟加载。
前后帧缓存 & Vsync信号
iOS 的显示系统是由 VSync 信号驱动的,VSync 信号由硬件时钟生成,每秒钟发出 60 次(这个值取决设备硬件,比如 iPhone 真机上通常是 59.97)。iOS 图形服务接收到 VSync 信号后,会通过 IPC 通知到 App 内。App 的 Runloop 在启动后会注册对应的 CFRunLoopSource 通过 mach_port 接收传过来的时钟信号通知,随后 Source 的回调会驱动整个 App 的动画与显示。
帧缓存:接收渲染结果的缓冲区,为GPU指定存储渲染结果的区域
帧缓存可以同时存在多个,但是屏幕显示像素受到保存在前帧缓存(front frame buffer)的特定帧缓存中的像素颜色元素的控制。程序的渲染结果通常保存在后帧缓存(back frame buffer)在内的其他帧缓存,当渲染后的后帧缓存完成后,前后帧缓存会互换。(OS完成)
前帧缓存决定了屏幕上显示的像素颜色,会在适当的时候与后帧缓存切换。
Core Animation的合成器会联合OpenGL ES层和UIView层、StatusBar层等,在后帧缓存混合产生最终的颜色,并切换前后帧缓存; OpenGL ES坐标是以浮点数来存储,即使是其他数据类型的顶点数据也会被转化成浮点型。