iOS 渲染框架

栏目: IOS · 发布时间: 5年前

内容简介:事实上,

UIKit 是iOS开发最常用的框架,可以通过设置 UIKit 组件的布局以及相关属性来绘制界面。

事实上, UIKit 自身并不具备在屏幕成像的能力,其主要负责对用户操作事件的响应( UIView 继承自 UIResponder ),事件响应的传递大体是经过逐层的 视图树 遍历实现的。

Core Animation

Core Animation 源自于 Layer Kit ,动画只是 Core Animation 的冰山一角。 Core Animation 是一个复合引擎,其职责是 尽可能快地组合屏幕上不同的可视内容,这些可视内容可被分解成独立的图层(即CALayer),这些图层会被存储在一个叫做图层树的体系之中 。从本质上而言, CALayer 是用户所能在屏幕上看见的一切的基础。

Core Graphics

Core Graphics 基于 Quartz 高级绘图引擎,主要用于运行时绘制图像。开发者可以使用此框架来处理基于路径的绘图,转换,颜色管理,离屏渲染,图案,渐变和阴影,图像数据管理,图像创建和图像遮罩以及PDF文档创建,显示和分析。

当开发者需要在运行时创建图像时,可以使用 Core Graphics 去绘制。与之相对的是运行前创建图像,例如用Photoshop提前做好图片素材直接导入应用。相比之下,我们更需要 Core Graphics 去在运行时实时计算、绘制一系列图像帧来实现动画。

Core Image

Core ImageCore Graphics 恰恰相反, Core Graphics 用于在运行时创建图像,而 Core Image 用于处理运行前创建的图像。 Core Image 框架拥有一系列现成的图像过滤器,能对一寸照的图像进行高效的处理。

大部分情况下, Core Image 会在GPU中完成工作,如果GPU忙,会使用CPU进行处理。

OpenGL ES

OpenGL ESOpenGL 的子集。在图形渲染原理一文中提到过 OpenGL 是一套第三方标准,函数的内部实现由对应的GPU厂商开发实现。

UIView与CALayer的关系

CALayer 事实上是用户所能在屏幕上看见的一切的基础。为什么 UIKit 中的视图能够呈现可视化内容,就是因为 UIKit 中的每一个UI视图控件其实内部都有一个关联的 CALayer ,即 backing layer

由于这种一一对应的关系,视图层级有用 视图树 的树形结构,对应 CALayer 层级也拥有 图层树 的树形结构。

其中,视图的职责是创建并管理图层,以确保当子视图在层级关系中添加或被移除时,其关联的图层在图层树中也有相同的操作,即保证视图树和图层树在结构上的一致性。

为什么iOS要基于UIView和CALayer提供两个平行的层级关系呢?

其原因在于要做 职责分离 ,这样也能避免很多重复代码。在iOS和Mac OSX两个平台上,事件和用户交互有很多地方的不同,基于多点触控的用户界面和基于鼠标键盘的交互有着本质的区别,这就是为什么iOS有 UIKitUIView ,对应Mac OSX有 AppKitNSView 的原因。它们在功能上很相似,但是在实现上有着显著的区别。

实际上,这里并不是两个层级关系,而是四个。每一个都扮演着不同的角色。除了 视图树图层树 ,还有 呈现树渲染树

CALayer

那么为什么 CALayer 可以呈现可视化内容呢?因为 CALayer 基本等同于一个 纹理 。纹理是GPU进行图像渲染的重要依据。

在图形渲染原理中提到纹理本质上就是一张图片,因此 CALayer 也包含一个 contents 属性指向一块缓存区,称为 backing store ,可以存放位图(Bitmap)。iOS中将该缓存区保存的图片称为 寄宿图

iOS 渲染框架

图形渲染流水线支持从顶点开始进行绘制(在流水线中,顶点会被处理生成纹理),也支持直接使用纹理(图片)进行渲染。相应地,在实际开发中,绘制界面也有两种方式: 一种是 手动绘制 ;另一种是 使用图片

对此,iOS中也有两种相应的实现方式:

  • 使用图片: contents image
  • 手动绘制: custom drawing

Contents Image

Contents Image 是指通过 CALayercontents 属性来配置图片。然而, contents 属性的类型为 id ,在这种情况下,可以给 contents 属性赋予任何值,app仍可以编译通过。但是在实践中,如果 contents 的值不是 CGImage ,得到的图层将是空白的。

既然如此,为什么要将 contents 的属性类型定义为 id 而非 CGImage 。因为在Mac OS系统中,该属性对 CGImageNSImage 类型的值都起作用,而在iOS系统中,该属性只对 CGImage 起作用。

本质上, contents 属性指向的一块缓存区域,称为 backing store ,可以存放bitmap数据。

Custom Drawing

Custom Drawing 是指使用 Core Graphics 直接绘制寄宿图。实际开发中,一般通过继承 UIView 并实现 -drawRect: 方法来自定义绘制。

虽然 -drawRect: 是一个 UIView 方法,但事实上都是底层的 CALayer 完成了重绘工作并保存了产生的图片。 下图所示为 drawRect: 绘制定义寄宿图的基本原理

iOS 渲染框架
  • UIView 有一个关联图层,即 CALayer
  • CALayer 有一个可选的 delegate 属性,实现了 CALayerDelegate 协议。 UIView 作为 CALayer 的代理实现了 CALayerDelegate 协议。
  • 当需要重绘时,即调用 -drawRect:CALayer 请求其代理给予一个寄宿图来显示。
  • CALayer 首先会尝试调用 -displayLayer: 方法,此时代理可以直接设置 contents 属性。
- (void)displayLayer:(CALayer *)layer;
复制代码
  • 如果代理没有实现 -displayLayer: 方法, CALayer 则会尝试调用 -drawLayer:inContext: 方法。在调用该方法前, CALayer 会创建一个空的寄宿图(尺寸由 boundscontentScale 决定)和一个 Core Graphics 的绘制上下文,为绘制寄宿图做准备,作为 ctx 参数传入。
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx;
复制代码
  • 最后,有 Core Graphics 绘制生成的寄宿图会存入 backing store

Core Animation 流水线

介绍一下 Core Animation 流水线的工作原理:

iOS 渲染框架
事实上,app本身并不负责渲染,渲染则是由一个独立的进程负责,即 Render Server

进程。

App通过IPC将渲染任务及相关数据提交给 Render ServerRender Server 处理完数据后,再传递至GPU。最后由GPU调用iOS的图像设备进行显示。

Core Animation 流水线的详细过程如下:

  • 首先,由app处理事件(Handle Events),如:用户点击操作,在此过程中app可能需要更新 视图树 ,相应地, 图层树 也会被更新。
  • 其次,app通过CPU完成对显示内容的计算,如:视图的创建、布局计算、图片解码、文本绘制等。在完成对现实内容的计算之后,app对图层进行打包,并在下一次RunLoop时将其发送至 Render Server ,即完成了一次 commit Transaction 操作。
  • Render Server 主要执行OpenGL、Core Graphics相关程序,并调用GPU。
  • GPU则在物理层上完成了对图像的渲染。
  • 最终,GPU通过 Frame Buffer 、视频控制器等相关部件,将图像显示在屏幕上。

对上述步骤进行串联,他们执行所消耗的时间圆圆超过16.67ms,因此为了满足对屏幕的60FPS刷新率的支持,需要将这些步骤进行分解,通过流水线的方式并行执行,如下图:

iOS 渲染框架

Commit Transaction

Core Animation 流水线中,app调用 Render Server 前的最后一步 Commit Transaction 其实可以细分为4个步骤:

Layout
Display
Prepare
Commit

Layout

Layout 阶段主要进行视图构建,包括: LayoutSubviews 方法的重载, addSubview: 方法填充子视图等。

Display

Display 阶段主要进行视图绘制,这里仅仅是设置成像的图元数据。重载视图的 drawRect: 方法可以自定义 UIView 的显示,其原理是在 drawRect: 方法内部绘制寄宿图,该过程使用GPU和内存。

Prepare

Prepare 阶段属于附加步骤,一般处理图像的解码和转码等操作。

Commit

commit 阶段主要将图层进行打包,并将它们发送至 Render Server 。该过程会递归执行,因为图层和视图都是以树形结构存在。

动画渲染原理

iOS动画的渲染也是基于上述 Core Animation 流水线完成的。这里我们重点关注app与 Render Server 的执行流程。

日常开发中,如果不是特别的复杂动画,一般使用 UIView Animation实现,iOS将其处理过程分为如下三部阶段:

animationWithDuration:animations:
Layout,Display,Prepare,Commit
Render Server
iOS 渲染框架

参考博客iOS图像渲染原理


以上所述就是小编给大家介绍的《iOS 渲染框架》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Programming Concurrency on the JVM

Programming Concurrency on the JVM

Venkat Subramaniam / The Pragmatic Bookshelf / 2011-6-1 / USD 35.00

Concurrency on the Java platform has evolved, from the synchronization model of JDK to software transactional memory (STM) and actor-based concurrency. This book is the first to show you all these con......一起来看看 《Programming Concurrency on the JVM》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

MD5 加密
MD5 加密

MD5 加密工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试