iOS渲染流程

屏幕顯示圖像的原理

位圖.png
  • 位圖(Bitmap) : 是一種數(shù)據(jù)結(jié)構(gòu)。一個(gè)位圖是由若干個(gè)像素組成,每個(gè)像素的顏色信息由RGB組合或者灰度值表示。根據(jù)位深度,可將位圖分為1、4、8、16、24及32位圖像等。每個(gè)像素使用的信息位數(shù)越多,可用的顏色就越多,顏色表現(xiàn)就越逼真,相應(yīng)的數(shù)據(jù)量越大。
掃描.png

顯示器顯示的圖像就是將位圖中的數(shù)據(jù)映射到屏幕上,映射的過程是有一個(gè)電子槍,從屏幕的左上角開始進(jìn)行逐行的掃描,當(dāng)右下角的最后一個(gè)像素被顯示在屏幕上之后,電子槍又會(huì)回到左上角進(jìn)行下一幀圖片的顯示。屏幕的刷新頻率是固定的,通常是60Hz,即一秒鐘會(huì)刷新60次。

畫面撕裂產(chǎn)生的原因是由于顯卡的性能提升,輸出的幀率非常高,如果顯卡輸出的幀率超過60fps,兩者不同步,就會(huì)產(chǎn)生畫面撕裂。

如果電子槍掃描到屏幕的一半時(shí),這時(shí)新一幀要顯示的畫面數(shù)據(jù)已經(jīng)準(zhǔn)備好了,就會(huì)將舊的數(shù)據(jù)給替換掉,那么此時(shí)電子槍掃描出來(lái)的數(shù)據(jù)就是新的一幀畫面。屏幕的上下兩個(gè)部分顯示的畫面就不是同一幀的數(shù)據(jù),就會(huì)造成畫面撕裂。

ios_vsync_off.jpg

垂直同步+雙緩沖

為了解決畫面撕裂的問題,這里引入了一個(gè)新的技術(shù),垂直同步和雙緩沖區(qū)。

  • 垂直同步:而當(dāng)一幀畫面繪制完成后,電子槍回復(fù)到原位,準(zhǔn)備畫下一幀前,顯示器會(huì)發(fā)出一個(gè)垂直同步信號(hào)(vertical synchronization),簡(jiǎn)稱 VSync。
ios_screen_display.png

通常來(lái)說(shuō),計(jì)算機(jī)系統(tǒng)中 CPU、GPU、顯示器是以上面這種方式協(xié)同工作的。CPU 計(jì)算好顯示內(nèi)容提交到 GPU,GPU 渲染完成后將渲染結(jié)果放入幀緩沖區(qū),隨后視頻控制器會(huì)逐行讀取幀緩沖區(qū)的數(shù)據(jù),經(jīng)過數(shù)模轉(zhuǎn)換傳遞給顯示器顯示。

有了雙緩沖區(qū),兩個(gè)緩沖區(qū)協(xié)同工作,視頻控制器先從一個(gè)緩沖區(qū)中讀取數(shù)據(jù),新的一幀的數(shù)據(jù)會(huì)被放在另一個(gè)緩沖區(qū)中,當(dāng)視頻控制器收到VSync后,視頻控制器就會(huì)交換兩個(gè)緩沖區(qū),讀取新的畫面。

通過垂直同步和雙緩沖解決了畫面撕裂的問題,但是又引出了一個(gè)新的問題,那就是掉幀。當(dāng)我們的手機(jī)在快速滑動(dòng)的過程中感覺到卡頓的現(xiàn)象就是掉幀引起的。

frame_loss.jpg

我們知道每一幀畫面計(jì)算都是由CPU和GPU一同計(jì)算得到的,在刷新率為60Hz設(shè)備上,每個(gè)刷新周期是16.7ms, 如果在這段時(shí)間內(nèi)新的一幀應(yīng)該顯示的內(nèi)容還沒有被計(jì)算出來(lái),那么這一幀就會(huì)被丟棄,顯示器顯示的內(nèi)容依然是上一幀的內(nèi)容。知道下一幀被計(jì)算出來(lái),才會(huì)在下個(gè)VSync顯示。

圖像渲染過程

Core Animation 流水線

在介紹 Core Animation 流水線之前,我們先了解一下 Core Animation。

Core Animation

Core Animation 源自于 Layer Kit,動(dòng)畫只是 Core Animation 特性的冰山一角。

Core Animation 是一個(gè)復(fù)合引擎,其職責(zé)是 盡可能快地組合屏幕上不同的可視內(nèi)容,這些可視內(nèi)容可被分解成獨(dú)立的圖層(即 CALayer),這些圖層會(huì)被存儲(chǔ)在一個(gè)叫做圖層樹的體系之中。從本質(zhì)上而言,CALayer 是用戶所能在屏幕上看見的一切的基礎(chǔ)。

ios-core-animation-pipeline-steps.png

事實(shí)上,App本身不負(fù)責(zé)渲染,渲染是由一個(gè)獨(dú)立的進(jìn)程 Render Server 負(fù)責(zé)。

App通過IPC(進(jìn)程間通信)將渲染任務(wù)和相關(guān)數(shù)據(jù)提交給 Render ServerRender Server 處理完數(shù)據(jù)后,在傳遞給GPU。最后由GPU調(diào)用iOS的圖像設(shè)備進(jìn)行顯示。

Core Animation 流水線的詳細(xì)過程如下:

  • 首先,App處理事件,如:用戶點(diǎn)擊事件,在此過程中App可能需要更新 視圖樹,相應(yīng)地,圖層樹 也會(huì)被更新。
  • 接著,App通過CPU完成對(duì)需要顯示內(nèi)容的計(jì)算,如:視圖的創(chuàng)建、布局計(jì)算、圖片解碼、文本繪制等,在完成其內(nèi)容的顯示計(jì)算之后,App對(duì)圖層進(jìn)行打包,并在下一次Runloop 將其發(fā)送至Render Server, 即完成了一次Comit Transaction操作。
  • Render Server 主要執(zhí)行 OpenGL、 Core Graphics相關(guān)程序,并調(diào)用GPU
  • GPU在物理層上完成對(duì)圖形的渲染。
  • 最終,GPU通過 Frame Buffer、視頻控制器等相關(guān)部件, 將圖像顯示在屏幕上。

Commit Transaction

App將渲染相關(guān)的數(shù)據(jù)提交給 Render Server 前的最后一步 Commit Transaction 可以細(xì)分為4個(gè)步驟:

  1. Layout

Layout階段主要包括視圖構(gòu)建,包括:layoutSubviews方法的重載, addSubview: 方法填充子視圖等。

  1. Display

Display階段主要進(jìn)行視圖繪制,這里僅僅設(shè)置要成像的圖元數(shù)據(jù)。重載視圖的drawRect:方法自定義UIView的顯示,其原理是在drawRect:方法內(nèi)部繪制寄宿圖,該過程使用CPU和內(nèi)存。

  1. Prepare

Prepare階段屬于附加步驟,一般用于圖像的解碼和轉(zhuǎn)換操作。

  1. Commit

Commit 階段主要將圖層進(jìn)行打包,并將它們發(fā)送至 Render Server。該過程會(huì)遞歸執(zhí)行,因?yàn)閳D層和視圖都是以樹形結(jié)構(gòu)存在。

GPU渲染過程

ios_gpu_render.jpg

頂點(diǎn)數(shù)據(jù) -> 頂點(diǎn)著色器 -> 圖元裝配 -> 光柵化 -> 片元著色器 -> 位圖 -> 顯示

extension

iOS 保持界面流暢的技巧

iOS 圖像渲染原理

離屏渲染優(yōu)化詳解:實(shí)例示范+性能測(cè)試

iOS Core Animation: Advanced Techniques中文譯本

iOS 開發(fā):繪制像素到屏幕

深入理解 iOS Rendering Process

畫面撕裂

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容