这是我参与8月更文挑战的第31天,活动详情查看:8月更文挑战
1. iOS中的渲染
在iOS中渲染的整体流程如下所示
- App通过调用CoreGraphics、CoreAnimation、CoreImage等框架的接口触发图形渲染操作
- CoreGraphics、CoreAnimation、CoreImage等框架将渲染交由OpenGL ES,由OpenGL ES来驱动GPU做渲染,最后显示到屏幕上
- 由于OpenGL ES 是跨平台的,所以在他的实现中,是不能有任何窗口相关的代码,而是让各自的平台为OpenGL ES提供载体。在ios中,如果需要使用OpenGL ES,就是通过CoreAnimation提供窗口,让App可以去调用。
2. iOS中渲染框架总结
主要由以下六种框架,表格中已经说明了,就不再详细解释了
3. View与CALayer的关系
首先分别简单说下UIView和CALayer各自的作用
3.1 UIView
- UIView属于UIKIt
- 负责绘制图形和动画操作
- 用于界面布局和子视图的管理
- 处理用户的点击事件
3.2 CALayer
- CALayer属于CoreAnimation
- 只负责显示,且显示的是位图
- CALayer既用于UIKit,也用于APPKit,
==> UIKit是iOS平台的渲染框架,APPKit是Mac OSX系统下的渲染框架,
==> 由于iOS和Mac两个系统的界面布局并不是一致的,iOS是基于多点触控的交互方式,而Mac OSX是基于鼠标键盘的交互方式,且分别在对应的框架中做了布局的操作,所以并不需要layer载体去布局,且不用迎合任何布局方式。
3.3 UIView和CALayer的关系
- UIView基于UIKit框架,可以处理用户触摸事件,并管理子视图
- CALayer基于CoreAnimation,而CoreAnimation是基于QuartzCode的。所以CALayer只负责显示,不能处理用户的触摸事件
- 从父类来说,CALayer继承的是NSObject,而UIView是直接继承自UIResponder的,所以UIVIew相比CALayer而言,只是多了事件处理功能,
- 从底层来说,UIView属于UIKit的组件,而UIKit的组件到最后都会被分解成layer,存储到图层树中
- 在应用层面来说,需要与用户交互时,使用UIView,不需要交互时,使用两者都可以
3.4 UIView和CALayer的渲染
下图可以说明view 和 layer之间是如何渲染的
- 界面触发的方式有两种
==> 通过loadView中子View的drawRect方法触发:会回调CoreAnimation中监听Runloop的BeforeWaiting的RunloopObserver
,通过RunloopObserver来进一步调用CoreAnimation内部的CA::Transaction::commit()
,进而一步步走到drawRect
方法
==> 用户点击事件触发:唤醒Runloop,由source1处理(__IOHIDEventSystemClientQueueCallback)
,并且在下一个runloop里由source0转发给UIApplication(_UIApplicationHandleEventQueue)
,从而能通过source0里的事件队列来调用CoreAnimation内部的CA::Transaction::commit()
;方法,进而一步一步的调用drawRect
。
最终都会走到CoreAnimation中的CA::Transaction::commit()
方法,从而来触发UIView和CALayer的渲染 - 这时,已经到了CoreAnimation的内部,即调用
CA::Transaction::commit()
;来创建CATrasaction,然后进一步调用CALayer drawInContext:()
- 回调CALayer的Delegate(UIView),问UIView没有需要画的内容,即回调到
drawRect:
方法 - 在drawRect:方法里可以通过CoreGraphics函数或UIKit中对CoreGraphics封装的方法进行画图操作
- 将绘制好的位图交由CALayer,由OpenGL ES 传送到GPU的帧缓冲区
- 等屏幕接收到垂直信号后,就读取帧缓冲区的数据,显示到屏幕上
4. CoreAnimation
在苹果官方的描述中,Render、Compose,and animate visual elements
,CoreAnimationg中的动画只是一部分,它其实是一个复合引擎,主要的职责包括 渲染、构建和动画实现。
ios中CoreAnimation如图所示
- ios中基于CoreAnimation构建的框架有两个:UIKit和APPKit
- CoreAnimation 又是基于Metal 、CoreGraphics封装的 苹果为什么要基于UIView和CALayer提供两个平行的层级关系(UIKit 和APPKit)?
职责分离
,可以避免大量重复代码两个系统交互规则不一致
,虽然功能上类似,但实现上有显著区别
4.1 CoreAnimation中的渲染流水线
CoreAnimation中渲染的流程如图所示
主要分为两部分:
- CoreAnimation部分
- GPU部分
4.1.1 CoreAnimation部分
- App处理UIView、UIButton等载体的事件,然后通过CPU完成对显示内容的计算,并将计算后的图层进行打包,在下一次runloop时,发送到渲染服务器
- Render Server中主要对收到的准备显示的内容进行解码,然后执行OpenGL等相关程序,并调用GPU进行渲染
==> Render Server 操作分析
4.1.2 GPU部分
-
GPU中通过顶点着色器、片元着色器完成对显示内容的渲染,将结果存入帧缓存区
-
GPU通过帧缓存区、视频控制器等相关部件,将其显示到屏幕上