渲染原理學后簡短筆記

UIView和CALayer的關系

其中,視圖的職責是 創(chuàng)建并管理 圖層,以確保當子視圖在層級關系中 添加或被移除 時,其關聯(lián)的圖層在圖層樹中也有相同的操作,即保證視圖樹和圖層樹在結構上的一致性。
那么為什么 iOS 要基于 UIView 和 CALayer 提供兩個平行的層級關系呢?

其原因在于要做 職責分離,這樣也能避免很多重復代碼。在 iOS 和 Mac OS X 兩個平臺上,事件和用戶交互有很多地方的不同,基于多點觸控的用戶界面和基于鼠標鍵盤的交互有著本質的區(qū)別,這就是為什么 iOS 有 UIKit 和 UIView,對應 Mac OS X 有 AppKit 和 NSView 的原因。它們在功能上很相似,但是在實現(xiàn)上有著顯著的區(qū)別。

事實上, UIKit 自身并不具備在屏幕成像的能力,其主要負責對用戶操作事件的響應(UIView 繼承自 UIResponder),事件響應的傳遞大體是經(jīng)過逐層的 視圖樹 遍歷實現(xiàn)的

CALayer的介紹

image.png

那么為什么 CALayer 可以呈現(xiàn)可視化內容呢?因為 CALayer 基本等同于一個 紋理。紋理是 GPU 進行圖像渲染的重要依據(jù)。
在 圖形渲染原理 中提到紋理本質上就是一張圖片,因此 CALayer 也包含一個 contents 屬性指向一塊緩存區(qū),稱為 backing store,可以存放位圖(Bitmap)。iOS 中將該緩存區(qū)保存的圖片稱為 寄宿圖。

image.png

使用圖片:contents image
手動繪制:custom drawing

Custom Drawing 是指使用 Core Graphics 直接繪制寄宿圖。實際開發(fā)中,一般通過繼承 UIView 并實現(xiàn) -drawRect: 方法來自定義繪制。
雖然 -drawRect: 是一個 UIView 方法,但事實上都是底層的 CALayer 完成了重繪工作并保存了產(chǎn)生的圖片。下圖所示為 -drawRect: 繪制定義寄宿圖的基本原理。

Contents Image
Contents Image 是指通過 CALayer 的 contents 屬性來配置圖片(例如用 Photoshop 提前做好圖片素材直接導入應用)。然而,contents 屬性的類型為 id。在這種情況下,可以給 contents 屬性賦予任何值,app 仍可以編譯通過。但是在實踐中,如果 content 的值不是 CGImage ,得到的圖層將是空白的。
既然如此,為什么要將 contents 的屬性類型定義為 id 而非 CGImage。這是因為在 Mac OS 系統(tǒng)中,該屬性對 CGImage 和 NSImage 類型的值都起作用,而在 iOS 系統(tǒng)中,該屬性只對 CGImage 起作用。
本質上,contents 屬性指向的一塊緩存區(qū)域,稱為 backing store,可以存放 bitmap 數(shù)據(jù)。

CPU和GPU的區(qū)別

image.png

從代碼寫的UI到展示到屏幕上的大概過程

image.png
image.png

事實上,app 本身并不負責渲染,渲染則是由一個獨立的進程負責,即 Render Server 進程。
App 通過 IPC 將渲染任務及相關數(shù)據(jù)提交給 Render Server。Render Server 處理完數(shù)據(jù)后,再傳遞至 GPU。最后由 GPU 調用 iOS 的圖像設備進行顯示。
Core Animation 流水線的詳細過程如下:

  • 首先,由 app 處理事件(Handle Events),如:用戶的點擊操作,在此過程中 app 可能需要更新 視圖樹,相應地,圖層樹 也會被更新。

  • 其次,app 通過 CPU 完成對顯示內容的計算,如:視圖的創(chuàng)建、布局計算、圖片解碼、文本繪制等。在完成對顯示內容的計算之后,app 對圖層進行打包,并在下一次 RunLoop 時將其發(fā)送至 Render Server,即完成了一次 Commit Transaction 操作。

  • Render Server 主要執(zhí)行 Open GL、Core Graphics 相關程序,并調用 GPU, GPU 則在物理層上完成了對圖像的渲染。

  • 最終,GPU 通過 Frame Buffer、視頻控制器等相關部件,將圖像顯示在屏幕上。

屏幕上顯示圖像的原理

  • 在內存開辟一塊和屏幕對應大小的空間,用來把當前屏幕需要展示的內容放到這塊內存,然后需要顯示的圖像經(jīng)過CRT電子槍(以前的屏幕的機制,這里只是原理)以極快的速度一行一行的掃描,掃描出來就呈現(xiàn)了一幀畫面,隨后電子槍又會回到初始位置循環(huán)掃描,形成了我們看到的圖片或視頻


    image.png
  • 最初設計只有一塊內存,當內存中的數(shù)據(jù)更新的頻率與渲染到屏幕上的頻率不一致時(太快或者太慢)就會出現(xiàn)如下斷層,如下

image.png

后來為了提高渲染效率和同步問題變成了雙緩存,加標志位

  • 補充:CRT顯示器是靠電子束激發(fā)屏幕內表面的熒光粉來顯示圖像的,由于熒光粉被點亮后很快會熄滅,所以電子槍必須循環(huán)地不斷激發(fā)這些點。
    首先,在熒光屏上涂滿了按一定方式緊密排列的紅、綠、藍三種顏色的熒光粉點或熒光粉條,稱為熒光粉單元,相鄰的紅、綠、藍熒光粉單元各一個為一組,學名稱之為像素。每個像素中都擁有紅、綠、藍(R、G、B)三基色。
    工作原理
    CRT顯示器用電子束來進行控制和表現(xiàn)三原色原理。電子槍工作原理是由燈絲加熱陰極,陰極發(fā)射電子,然后在加速極電場的作用下,經(jīng)聚焦極聚成很細的電子束,在陽極高壓作用下,獲得巨大的能量,以極高的速度去轟擊熒光粉層。這些電子束轟擊的目標就是熒光屏上的三基色。為此,電子槍發(fā)射的電子束不是一束,而是三束,它們分別受電腦顯卡R、 G、 B三個基色視頻信號電壓的控制,去轟擊各自的熒光粉單元。受到高速電子束的激發(fā),這些熒光粉單元分別發(fā)出強弱不同的紅、綠、藍三種光。根據(jù)空間混色法(將三個基色光同時照射同一表面相鄰很近的三個點上進行混色的方法)產(chǎn)生豐富的色彩,這種方法利用人們眼睛在超過一定距離后分辨力不高的特性,產(chǎn)生與直接混色法相同的效果。用這種方法可以產(chǎn)生不同色彩的像素,而大量的不同色彩的像素可以組成一張漂亮的畫面,而不斷變換的畫面就成為可動的圖像。

我寫的UI是怎么渲染到內存上的

  • 咱們寫的界面會有很多層,就和一棵樹一樣,渲染的時候會按照從根到葉的順序,假如我寫的界面有三層,那繪制到內存的順序如下


    image.png

那每一層是怎么寫到內存的?如下圖

image.png

光柵化需要做的就是如下圖


image.png

不透明 VS 透明

當源紋理是完全不透明,最終的顏色和源紋理一樣。這就可以節(jié)省GPU的很多工作,因為GPU可以簡單的復制源紋理而不用合成所有像素值。但是GPU沒有辦法區(qū)別紋理中的像素是不透明的還是透明。

透明的話需要計算
R = S + D * (1 - Sa)
最后的結果是通過源的顏色(最上面的紋理)加目標顏色(下面的紋理) 乘以(1 – 源顏色的透明度)公式里面所有的顏色就假定已經(jīng)預先乘以了他們的透明度。

離屏渲染(Offscreen rendering)

GPU屏幕渲染有兩種方式:

(1)On-Screen Rendering (當前屏幕渲染)

指的是GPU的渲染操作是在當前用于顯示的屏幕緩沖區(qū)進行。

(2)Off-Screen Rendering (離屏渲染)
指的是在GPU在當前屏幕緩沖區(qū)以外開辟一個緩沖區(qū)進行渲染操作。

當前屏幕渲染不需要額外創(chuàng)建新的緩存,也不需要開啟新的上下文,相對于離屏渲染性能更好。但是受當前屏幕渲染的局限因素限制(只有自身上下文、屏幕緩存有限等),當前屏幕渲染有些情況下的渲染解決不了的,就使用到離屏渲染。

相比于當前屏幕渲染,離屏渲染的代價是很高的,主要體現(xiàn)在兩個方面:

(1)創(chuàng)建新緩沖區(qū)

要想進行離屏渲染,首先要創(chuàng)建一個新的緩沖區(qū)。

(2)上下文切換

離屏渲染的整個過程,需要多次切換上下文環(huán)境:先是從當前屏幕(On-Screen)切換到離屏(Off-Screen),等到離屏渲染結束以后,將離屏緩沖區(qū)的渲染結果顯示到屏幕上有需要將上下文環(huán)境從離屏切換到當前屏幕。而上下文環(huán)境的切換是要付出很大代價的。

OpenGL 嚴格來說并不是常規(guī)意義上的 API,而是一個第三方標準(由 khronos 組織制定并維護),其嚴格定義了每個函數(shù)該如何執(zhí)行,以及它們的輸出值。至于每個函數(shù)內部具體是如何實現(xiàn)的,則由 OpenGL 庫的開發(fā)者自行決定。實際 OpenGL 庫的開發(fā)者通常是顯卡的生產(chǎn)商。DirectX 則是由 Microsoft 提供一套第三方標準。

速度對比

http://www.itdecent.cn/p/8b0572f2c23a

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

相關閱讀更多精彩內容

友情鏈接更多精彩內容