iOS開發(fā)中,經(jīng)常創(chuàng)建很多視圖控件來進(jìn)行界面布局,那這些視圖控件是怎么顯示到屏幕上的呢?其實(shí)在設(shè)置了 UIView 的相關(guān)屬性后,是經(jīng)過了一個(gè)圖形渲染流程,才最終可以在屏幕上成像。本文主要介紹兩部分內(nèi)容:
- 介紹
iOS相關(guān)圖形渲染框架。 - 詳述
Core Animation Pipeline的工作原理。
一、圖形渲染技術(shù)棧
下圖所示為iOS圖形渲染技術(shù)棧,App使用Core Grapics、Core Animation、Core Image等框架來繪制可視化內(nèi)容。這些框架需要通過Metal(iOS12之前是通過OpenGL ES)來調(diào)用GPU進(jìn)行繪制,最后將繪制好的內(nèi)容顯示在屏幕上。

先來簡單認(rèn)識下這些渲染框架:
-
UIKit
UIKit是iOS的基礎(chǔ)視圖框架,可以用來構(gòu)建和管理界面可視化內(nèi)容,響應(yīng)用戶交互事件。
UIKit自身并不具備在屏幕成像的能力,其主要負(fù)責(zé)對用戶交互事件的響應(yīng)(后面有時(shí)間再補(bǔ)一篇事件的傳遞和響應(yīng))。
UIKit中的每一個(gè)視圖控件內(nèi)部都有一個(gè)關(guān)聯(lián)的 CALayer(后面有時(shí)間補(bǔ)一篇UIView和CALayer的聯(lián)系),對視圖控件的任何布局設(shè)置,本質(zhì)上都是對其關(guān)聯(lián)的CALayer進(jìn)行操作。CALayer是App界面可視化內(nèi)容的載體。
UIKit只支持iOS。
-
Core Aniamtion
Core Animation在開發(fā)中經(jīng)常被用來實(shí)現(xiàn)動畫效果,本質(zhì)上是一個(gè)復(fù)合引擎,主要功能包含:渲染、構(gòu)建和實(shí)現(xiàn)動畫。它的職責(zé)是盡可能快地組合屏幕上不同的可視內(nèi)容,這個(gè)組合過程是將這些內(nèi)容分解成一個(gè)個(gè)獨(dú)立的圖層,并存儲在一個(gè)叫做圖層樹的體系之中。和UIKit不同,Core Animation是直接作用于CALayer的。
Core Animation支持iOS和macOS。
-
Core Graphics
Core Graphics 是一個(gè)基于Quartz 2D的高級繪圖引擎,提供大量的低層次、輕量級的2D渲染API??梢杂脕硖幚砘诼窂降睦L圖,轉(zhuǎn)換,顏色管理,離屏渲染,圖案,漸變和陰影,圖像數(shù)據(jù)管理,圖像創(chuàng)建,圖像遮罩以及PDF文檔的生成和解析。
Core Graphics支持iOS和macOS,在Mac OS X中,Core Graphics 還包括用于處理顯示硬件,低級用戶輸入事件和窗口系統(tǒng)的服務(wù)。
-
Core Image
Core Image是iOS5中引入的一個(gè)圖片處理框架,里面提供了很多強(qiáng)大高效的圖像處理功能。Core Image 可以用來十分輕松地實(shí)現(xiàn)濾鏡以及圖像識別等功能。
-
OpenGL ES
OpenGL ES(OpenGL for Embedded Systems),是OpenGL三維圖形API的?集,針對?機(jī)、Pad和游戲主機(jī)等嵌?式設(shè)備?設(shè)計(jì),去除了許多不必要和性能較低的API接?。在 Metal 推出之前,iOS相關(guān)渲染框架都是基于 OpenGL ES 的。
-
Metal
Metal是Apple在WWDC 2014上為游戲開發(fā)者推出的新技術(shù)框架 ,只支持Apple相關(guān)平臺。和OpenGL相比,Metal 能夠?yàn)?D圖像提高10倍的渲染性能。從iOS12開始,渲染框架底層都是基于 Metal 實(shí)現(xiàn)的。
-
GPU
GPU(Graphics Processing Unit),是一種可進(jìn)行繪圖、運(yùn)算的專用微處理器,它的高度并行結(jié)構(gòu)使其在大塊數(shù)據(jù)并行處理的算法中比通用 CPU 更有效。
二、Core Animation Pipeline
前面提到過,對UIKit中視圖控件的任何布局設(shè)置,本質(zhì)上都是對其關(guān)聯(lián)的CALayer進(jìn)行操作,而對CALayer的屬性設(shè)置都是通過在圖層的內(nèi)容或幾何圖形上啟動不同的動畫來進(jìn)行的(即通過Core Animation來完成)。
因此,屏幕上的可視內(nèi)容都是需要先經(jīng)過Core Animation分解成不同的圖層并生成圖層樹, 然后再對這些圖層樹進(jìn)行渲染,最終顯示到屏幕上,這個(gè)過程被稱為Core Animation Pipeline(Core Animation流水線)。

上圖描繪了Core Animation流水線的大概流程:App處理完事件,由Core Animation將渲染任務(wù)及相關(guān)數(shù)據(jù)提交給Render Server。Render Server生成渲染指令后,再調(diào)用GPU渲染,最后由iOS的圖像設(shè)備進(jìn)行顯示。
接下來,詳細(xì)介紹Core Animation流水線中每個(gè)階段負(fù)責(zé)處理的任務(wù):
1. Application
在這個(gè)階段,App響應(yīng)用戶事件后(如點(diǎn)擊操作、滑動列表等),若需要更新界面內(nèi)容,會通過CPU完成對顯示內(nèi)容的計(jì)算,如:布局計(jì)算、圖片解碼、圖像繪制等。在完成對顯示內(nèi)容的計(jì)算之后,App將間接通過UIKit或直接通過Core Animation來更新圖層樹,最后將圖層編碼后的數(shù)據(jù)提交給Render Server。主要經(jīng)歷了下面兩個(gè)步驟:
1.1 Handle Events
App響應(yīng)事件,并進(jìn)行處理。
1.2 Commit Transaction
這個(gè)階段細(xì)分成下面4步:
-
Layout
構(gòu)建視圖,包括:layoutSubviews方法的重載,addSubview: 方法填充子視圖等。CPU在這里完成視圖布局的相關(guān)計(jì)算。
-
Display
繪制視圖,本質(zhì)是繪制位圖,設(shè)置最終成像的圖元數(shù)據(jù)。重載drawRect方法可以完成自定義視圖的繪制。CPU在這里完成圖像繪制的相關(guān)計(jì)算。
-
Prepare
這個(gè)步驟會做一些額外的Core Animation工作,比如圖像解碼和圖像轉(zhuǎn)換。CPU會在這里對View里的圖片進(jìn)行解碼,若CPU不支持該圖片格式,則會先進(jìn)行圖像轉(zhuǎn)換,再解碼。
-
Commit
將圖層進(jìn)行編碼打包,并提交給Render Server。由于圖層是以樹的結(jié)構(gòu)存在,所以打包操作會遞歸執(zhí)行。
2. Render Server
Render Server,即渲染服務(wù)器,主要完成兩個(gè)任務(wù):
-
Decode
解碼,將傳入的圖層信息進(jìn)行解析并反序列化成渲染樹(render tree)。
-
Draw Calls
根據(jù)渲染樹中圖層的相關(guān)設(shè)置屬性來生成相應(yīng)的渲染指令(Metal或OpenGL ES),并將渲染相關(guān)信息傳給GPU。
3. GPU
GPU接收到Render Server傳來的渲染信息后,會在收到顯示器發(fā)送新的VSync信號后才進(jìn)行渲染,并將渲染結(jié)果輸出到幀緩沖區(qū)(即顯存)。
4. Display
在接受到顯示器發(fā)出的新的VSync信號后,視頻控制器會逐行讀取幀緩沖區(qū)中的數(shù)據(jù),再經(jīng)過一定的數(shù)模轉(zhuǎn)換傳遞給顯示器顯示。這個(gè)階段的詳情步驟可閱讀iOS 屏幕圖像顯示原理。
三、總結(jié)
綜上可知,App界面內(nèi)容顯示到屏幕上的流程如下:
-
App響應(yīng)交互事件,如:用戶的點(diǎn)擊操作,需要更新界面布局。 -
App通過CPU完成對顯示內(nèi)容的計(jì)算,如:布局計(jì)算、圖片解碼、圖像繪制等。在完成計(jì)算后,App更新圖層樹,并將圖層樹進(jìn)行編碼打包,然后將數(shù)據(jù)提交給Render Server。 -
Render Server將圖層數(shù)據(jù)解碼后,生成相應(yīng)的渲染指令,然后將渲染信息傳給GPU。 -
GPU完成渲染后會將渲染結(jié)果存入幀緩存區(qū),再由視頻控制器逐行讀取數(shù)據(jù),經(jīng)由數(shù)模轉(zhuǎn)換后將圖像顯示在屏幕上。
參考
1. iOS 圖像渲染原理
2. 深入理解 iOS Rendering Process
3. Getting Pixels onto the Screen,中文版(iOS 開發(fā):繪制像素到屏幕)
4. Core Animation Programming Guide