iOS-CoreAnimation在iOS渲染中充当的角色

关于Core Animation

Core Animation is a graphics rendering and animation infrastructure available on both iOS and OS X that you use to animate the views and other visual elements of your app. With Core Animation, most of the work required to draw each frame of an animation is done for you. All you have to do is configure a few animation parameters (such as the start and end points) and tell Core Animation to start. Core Animation does the rest, handing most of the actual drawing work off to the onboard graphics hardware to accelerate the rendering. This automatic graphics acceleration results in high frame rates and smooth animations without burdening the CPU and slowing down your app.

CoreAnimation是一个在iOS和OS X均可使用的图形渲染和动画的基础框架,可以使用该框架为app中的视图和可视元素提供动画效果。借助CoreAnimation,大多数的帧动画已经由框架完成。你所需要做的只是设置动画的一些属性(如动画的起点和终点)和启动动画。其余部分由CoreAnimation完成,将大部分实际绘图工作交给板载图形硬件以加快渲染速度。这种自动图形加速功能可实现高帧率和流畅的动画效果,而不会给CPU造成负担并降低应用程序的运行速度。

简单点说,Core Animation 本质上可以理解为是一个复合引擎,不单单只负责动画,还包括渲染和构建。

CoreAnimation在渲染中的位置

iOS的渲染核心是CoreAnimation。从上到下依次是UIKit -> Core Animation -> (Metal / Core Graphics) -> Graphics Hardware 。
在apple发布metal框架以前,第三层是(OpenGL ES / Core Graphics) ,现在已经替换为(OpenGL ES / Core Graphics)。

在上图中,UIKit/AppKit所处的位置是在应用层,即application,主要是负责视图的布局和处理事件响应等工作,CoreAnimation、 (Metal / Core Graphics) 和Graphics Hardware所处的位置,是iOS视图的渲染和动画所处的另一个进程完成,这个进程称为RenderServer。

CALayer

本质上而言,CALayer 是用户所能在屏幕上看见的一切的基础。UIKit之所以能显示可视化内容是因为每一个UIIKit的UI控件内部都关联一个CALayer,即backing layer。
那么为什么 CALayer 可以呈现可视化内容呢?因为 CALayer 基本等同于一个 纹理。纹理是 GPU 进行图像渲染的重要依据。
纹理本质上就是一张图片,因此 CALayer 也包含一个 contents 属性指向一块缓存区,称为 backing store,可以存放位图(Bitmap)。iOS 中将该缓存区保存的图片称为 寄宿图。


UIView & CALayer & Bitmap

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

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

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

Contents Image

Contents Image 是指通过 CALayer 的 contents 属性来配置图片。contents 属性的类型为 Any,因为在UIKit(iOS)中contents是CGImage,在AppKit()中contents是NSImage。

//CALayer
var contents: Any? { get set }

## Discussion
The default value of this property is `nil`.
If you are using the layer to display a static image, you can set this property to 
the CGImage containing the image you want to display. 
(In macOS 10.6 and later, you can also set the property to an NSImage object.)

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

在CALayer的contents 属性官方文档介绍中有这样一段话:

If the layer object is tied to a view object, you should avoid setting the contents of this property directly. The interplay between views and layers usually results in the view replacing the contents of this property during a subsequent update.

也就是说,一般情况下layer总是被view持有,保持一一对应的关系,如果layer不是单独增加进layer tree,应避免直接设置contents属性。

Custom Drawing

Custom Drawing 是指使用 Core Graphics 直接绘制寄宿图。实际开发中,一般通过继承 UIView 并实现 -drawRect: 方法来自定义绘制。
虽然 -drawRect: 是一个 UIView 方法,但事实上都是底层的 CALayer 完成了重绘工作并保存了产生的图片。

UIView和CALayer的关系

前面说过渲染图形是由CALayer完成,那为什么还需要UIView呢?其原因在于要做 职责分离。
UIView的主要职责是创建并管理图层、布局和子View的管理以及处理事件响应(如屏幕点击事件),CALayer的主要职责是管理用户提供的可视化内容,即渲染和动画。

A layer’s main job is to manage the visual content that you provide but the layer itself has visual attributes that can be set, such as a background color, border, and shadow.

layers make it easier and more efficient to draw and animate the contents of views and maintain high frame rates while doing so. However, there are many things that layers do not do. Layers do not handle events, draw content, participate in the responder chain, or do many other things

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

其实不单单只有视图树和图层树,还有表示树和渲染树。


layer tree

Core Animation 流水线

了解UIView和CALayer的区别以及CALayer本质后,下面介绍Core Animation 流水线的工作原理。
上面说过,app本身并不负责渲染,仅仅是布局、管理视图层以及处理事件(HandleEvent),真正的渲染工作是在一个叫Render Server进程中完成的。

Core Animation Pipeline

app通过IPC将渲染任务和相关数据提交给render serverrender server处理完数据后,再传递给GPU,最后由GPU调用iOS的图像硬件(Graphics Hardware)进行显示。

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

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

Commit Transaction

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

  • Layout
  • Display
  • Prepare
  • Commit


    Commit Transaction

Layout

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

Display

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

Prepare

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

Commit

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

参考

  1. iOS 图像渲染原理
  2. iOS 视图、动画渲染机制探究
  3. 关于iOS离屏渲染的深入研究
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,295评论 6 512
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,928评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,682评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,209评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,237评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,965评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,586评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,487评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,016评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,136评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,271评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,948评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,619评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,139评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,252评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,598评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,267评论 2 358