1.先认识一下CPU和GPU在计算机的作用
1.1 CPU
看到这个图你可能有点茫然,我们换种方法
CPU(中央处理器),是电子计算机的主要设备之一,电脑中的核心配件。其功能主要是解释计算机指令以及处理计算机软件中的数据。CPU是计算机中负责读取指令,对指令译码并执行指令的核心部件. 运算核心和控制核心
1.2 GPU
GPU(图形处理器),又称显示核心、视觉处理器、显示芯片,是一种专门在个人电脑、工作站、游戏机和一些移动设备(如平板电脑、智能手机等)上做图像和图形相关运算工作的微处理器。可进⾏绘图运算⼯作的专⽤微处理器,是连接计算机和显示终端的纽带。
2.iOS图形渲染的技术栈
APP通过Core Graphics ,Core Animation ,Core Image 等框架进行可视化的绘制,这些框架相互依赖,并通过OpenGL ES /Metal 调度GPU进行视图的渲染最终显示在屏幕上。
3.iOS渲染框架
UIKit
1.UIKitk框架提供一系列的Class(类)来建立和管理iPhone OS应用程序的用户界面( UI )接口、应用程序对象、事件控制、绘图模型、窗口、视图和用于控制触摸屏等的接口。
2.开发者一般直接使用UIKit进行视图的布局和对用户事件的响应,事件响应的传递是通过视图树逐级遍历实现的。
Core Animation
1.CoreAnimation 源自于 Layer Kit ,是苹果提供的一套基于绘图的动画框架
2.Core Animation是一个复合引擎,它的职责就是尽可能快地组合屏幕上不同的可 视内容,这个内容是被分解成独立的图层,存储在一个叫做图层树的体系之中。于 是这个树形成了UIKit以及在iOS应用程序当中你所能在屏幕上看见的一切的基础。
Core Graphics
1.Core Graphics是Quartz 2D的一个高级绘图引擎,常用与iOS,tvOS,macOS的图形绘制应用开发。Core Graphics是对底层C语言的一个简单封装,其中提供大量的低层次,轻量级的2D渲染API。
2.Core GraphicsAPI简单易于使用,并且提供了强大的功能访问,如透明层,基于路径的涂层绘制,屏幕外呈现,高级色彩管理,抗锯齿已经PDF文档的生成解析操作
3.Core Graphics是创建运行时图形,可以对图片进行解压。
Core Image
1.Core Image是IOS5中新加入的一个框架,里面提供了强大高效的图像处理功能,用来对基于像素的图像进行操作与分析。还提供了很多强大的滤镜,可以实现你想要的效果。
2. 相对于Core Graphics,Core Image是处理运行前的创建的图像。Core Image会在GPU中完成工作,如果GPU忙,会使用CPU进行处理。
UIView和CALayer 千丝万缕的关系。
1.iOS屏幕显示的所有视图都是依赖CALayer 的。每个UIKit控件下都有一个关联的CALayer,即backing layer。视图层级拥有 视图树 的树形结构,对应 CALayer 层级也拥有 图层树 的树形结构。视图树中添加或者删除视图,相对应的图层树也会添加或者删除图层保证视图树和图层树一一对应。
2.视图树和图层树是一一对应,我们为什么要保留两个这样的树呢?其原因是 职责分离,在 iOS 和 Mac OS X 两个平台上,事件和用户交互有很多地方的不同,基于多点触控的用户界面和基于鼠标键盘的交互有着本质的区别,这就是为什么 iOS 有 UIKit 和 UIView,对应 Mac OS X 有 AppKit 和 NSView 的原因。它们在功能上很相似,但是在实现上有着显著的区别。
3.视图树 和 图层树,还有 呈现树 和 渲染树,每一个都扮演着不同的角色。
CALayer
1.CALayer是一个对象,该对象管理基于图像的内容,并允许您对该内容执行动画。
2. CALayer 中包含一个 contents 属性指向一块缓存区,称为 backing store,可以存放位图(Bitmap)。iOS 中将该缓存区保存的图片称为 寄宿图。
3.在图形渲染中有两种方式一是顶点进行绘制,二是通过纹理。在绘制图形中也有两种方式,一是手动绘制(对应图形渲染中的顶点绘制),二是使用图片(图形渲染中的通过纹理)
Contents Image
1.Contents Image 是指通过 CALayer 的 contents 属性来配置图片。然而,contents 属性的类型为 id。在这种情况下,可以给 contents 属性赋予任何值,app 仍可以编译通过。但是在实践中,如果 content 的值不是 CGImage ,得到的图层将是空白的。因为在 Mac OS 系统中,该属性对 CGImage 和 NSImage 类型的值都起作用,而在 iOS 系统中,该属性只对 CGImage 起作用。
2.CALayer 的contents 属性指向的一块缓存区域,称为 backing store,可以存放 bitmap 数据
Custom Drawing
1.Custom Drawing是使用Core Graphics 直接绘制寄宿图。在开发中我们一般是通过实现UIView的- (void)drawRect:完成绘制的
2.-drawRect: 是一个 UIView 方法,但事实上都是底层的 CALayer 完成了重绘工作并保存了产生的图片。下图所示为 -drawRect: 绘制定义寄宿图的基本原理
3.UIView 有一个关联图层,即 CALayer,CALayer 有一个可选的 delegate 属性,实现了 CALayerDelegate 协议。UIView 作为 CALayer 的代理实现了 CALayerDelegae 协议。当需要重绘时,即调用 -drawRect:,CALayer 请求其代理给予一个寄宿图来显示。CALayer 首先会尝试调用 -displayLayer: 方法,此时代理可以直接设置 contents 属性。如果代理没有实现 -displayLayer: 方法,CALayer 则会尝试调用 -drawLayer:inContext: 方法。在调用该方法前,CALayer 会创建一个空的寄宿图(尺寸由 bounds 和 contentScale 决定)和一个 Core Graphics 的绘制上下文,为绘制寄宿图做准备,作为 ctx 参数传入。最后,由 Core Graphics 绘制生成的寄宿图会存入 backing store。
Core Animation 流水线
1.app 本身并不负责渲染,渲染则是由一个独立的进程负责,即 Render Server 进程.App 通过 IPC 将渲染任务及相关数据提交给 Render Server。Render Server 处理完数据后,再传递至 GPU。最后由 GPU 调用 iOS 的图像设备进行显示。
2.Core Animation 流水线的详细过程如下:
首先,由 app 处理事件(Handle Events),如:用户的点击操作,在此过程中 app 可能需要更新 视图树,相应地,图层树 也会被更新。
其次,app 通过 CPU 完成对显示内容的计算,如:视图的创建、布局计算、图片解码、文本绘制等。在完成对显示内容的计算之后,app 对图层进行打包,并在下一次 RunLoop 时将其发送至 Render Server,即完成了一次 Commit Transaction 操作。
Render Server 主要执行 Open GL、Core Graphics 相关程序,并调用 GPU
GPU 则在物理层上完成了对图像的渲染。
最终,GPU 通过 Frame Buffer、视频控制器等相关部件,将图像显示在屏幕上。
对上述步骤进行串联,它们执行所消耗的时间远远超过 16.67 ms,因此为了满足对屏幕的 60 FPS 刷新率的支持,需要将这些步骤进行分解,通过流水线的方式进行并行执行,如下图所示。
Commit Transaction
在 Core Animation 流水线中,app 调用 Render Server 前的最后一步 Commit Transaction 其实可以细分为 4 个步骤:Layout,Display,Prepare,Commit
Layout
Layout 阶段主要进行视图构建,包括:LayoutSubviews 方法的重载,addSubview: 方法填充子视图等。
Display
Display 阶段主要进行视图绘制,这里仅仅是设置最要成像的图元数据。重载视图的 drawRect: 方法可以自定义 UIView 的显示,其原理是在 drawRect: 方法内部绘制寄宿图,该过程使用 CPU 和内存。
Prepare
Prepare 阶段属于附加步骤,一般处理图像的解码和转换等操作。
Commit
Commit 阶段主要将图层进行打包,并将它们发送至 Render Server。该过程会递归执行,因为图层和视图都是以树形结构存在.
动画渲染原理
iOS 动画的渲染也是基于上述 Core Animation 流水线完成的。这里我们重点关注 app 与 Render Server 的执行流程。
日常开发中,如果不是特别复杂的动画,一般使用 UIView Animation 实现,iOS 将其处理过程分为如下三部阶段:
Step 1:调用 animationWithDuration:animations: 方法
Step 2:在 Animation Block 中进行 Layout,Display,Prepare,Commit 等步骤。
Step 3:Render Server 根据 Animation 逐帧进行渲染。