iOS 底层探究:iOS中的渲染流程解析

2,680 阅读4分钟

这是我参与8月更文挑战的第31天,活动详情查看:8月更文挑战

1. iOS中的渲染

在iOS中渲染的整体流程如下所示

image.png

  • App通过调用CoreGraphics、CoreAnimation、CoreImage等框架的接口触发图形渲染操作
  • CoreGraphics、CoreAnimation、CoreImage等框架将渲染交由OpenGL ES,由OpenGL ES来驱动GPU做渲染,最后显示到屏幕上
  • 由于OpenGL ES 是跨平台的,所以在他的实现中,是不能有任何窗口相关的代码,而是让各自的平台为OpenGL ES提供载体。在ios中,如果需要使用OpenGL ES,就是通过CoreAnimation提供窗口,让App可以去调用。

2. iOS中渲染框架总结

主要由以下六种框架,表格中已经说明了,就不再详细解释了

2251862-3352012635c47e77.png

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之间是如何渲染的

2251862-1023aed5f7fa5d34.png

  • 界面触发的方式有两种
    ==> 通过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如图所示

image.png

  • ios中基于CoreAnimation构建的框架有两个:UIKit和APPKit
  • CoreAnimation 又是基于Metal 、CoreGraphics封装的 苹果为什么要基于UIView和CALayer提供两个平行的层级关系(UIKit 和APPKit)?
  • 职责分离,可以避免大量重复代码
  • 两个系统交互规则不一致,虽然功能上类似,但实现上有显著区别

4.1 CoreAnimation中的渲染流水线

CoreAnimation中渲染的流程如图所示

image.png 主要分为两部分:

  • CoreAnimation部分
  • GPU部分

4.1.1 CoreAnimation部分

  • App处理UIView、UIButton等载体的事件,然后通过CPU完成对显示内容的计算,并将计算后的图层进行打包,在下一次runloop时,发送到渲染服务器
  • Render Server中主要对收到的准备显示的内容进行解码,然后执行OpenGL等相关程序,并调用GPU进行渲染
    ==> Render Server 操作分析

image.png

4.1.2 GPU部分

  • GPU中通过顶点着色器、片元着色器完成对显示内容的渲染,将结果存入帧缓存区

  • GPU通过帧缓存区、视频控制器等相关部件,将其显示到屏幕上