本文檔系個人研究 Chromium 渲染管線的筆記記錄,本文介紹 Chromium 的一些基礎知識與渲染管線的主要流程。
本文分析的源碼基於當前最新版本
107
,每個版本類名 / 函數名和對應的具體實現或許有所差異,但主邏輯目前來看不會有所變動。
推薦閱讀本系列後續文章:
推薦前往 Airing Notes 閱讀本文,適配了特殊的筆記排版,閱讀體驗會更優。
Introduce to Blink#
Blink 是 Web 的渲染引擎,Chromium 和 Android Webview 都是用 Blink 作為渲染引擎。
Blink 包括以下特性:
- 實現了 Web 平台的規範(也就是 HTML 標準),包括 DOM,CSS 和 WebIDL;
- 內嵌 V8 運行 JavaScript;
- 通過底層的網絡棧請求資源;
- 構建 DOM 樹;
- 計算樣式和排版;
- 內嵌 Chrome Compositor 用於繪圖;
你可以閱讀 How Blink works 獲取更多關於 Blink 的知識。
從代碼結構的角度來看,"Blink" 指的是 //third_party/blink/ 目錄下的代碼。
從項目的角度來看,"Blink" 指的是實現 Web 平台特性的項目,實現這些 Web 特性的代碼分布在 //third_party/blink/, //content/renderer/,//content/browser/ 及其他相關依賴。
Renderer architecture overview#
本文中我們重點介紹渲染管線,它的代碼在 //third_party/blink/renderer下,目錄結構如下所示:
- controller/: 一些使用 core/ 和 modules/ 的高級庫。比如,devtools 的前端。
- core/and bindings/core: core/ 實現了跟 DOM 緊密相關的特性。bindings/core 屬於 core/ 的一部分,bindings 目錄獨立是因為它和 V8 強相關。
- modules/and bindings/modules: modules/ 實現一些與 DOM 無關的特性,如 WebAudio,IndexDB 等。bindings/modules/ 屬於 modules/ 的一部分,bindings 目錄獨立是因為它和 V8 強相關。
- platform/: Blink 的低階功能集合,從龐大的 core/ 中分解出來,包括 geometry 和 graphics 等相關的功能。
- extensions/
- public/web
- public/platform
- public/common
- //base: chromium 基礎庫,基礎庫的源碼解讀可見 Chromium //base
- //cc: chromium composite
- V8: JavaScript 解釋器
Renderer processes#
Chromium 擁有一個 browser processes 和 N 個沙盒 renderer processes,其中 Blink 運行在 renderer processes。browser 與 renderer 進程間通訊是由 Mojo來實現的。
過去進程間通信使用 Chromium IPC,現在還有很多代碼仍舊在使用 IPC。
Blink renderer processes 模型如下圖所示:
Renderer process 擁有一個 main thread, 多個 worker threads, 一個 compositor thread, 以及一個 raster thread。
而 Blink 幾乎所有的主要活動都發生在 main thread,如 JavaScript 調用,DOM 解析、CSS 樣式和排版計算,因此 Blink 的架構被認為主要是單線程的。
Rendering Pipeline#
Goals#
渲染管線的目的是將 WebContent 渲染到螢幕上,它會將 HTML 的內容經過層層處理,最後通過 Open GL 操作顯卡硬體驅動,將 HTML 內容光柵化輸出到螢幕上。
需要注意的是 WebContent 指的是下圖區域,即 HTML 的內容,不包括瀏覽器外殼:
除此之外,渲染管線還設計了優良的數據結構,目的是高效處理渲染內容的更新。
Pipeline#
Blink 渲染管線如下圖所示:
"impl" = compositor thread.
這張圖來自於 Life of a pixel,雖然描述了管線的關鍵流程,但不是很完整。此外也不是很準確,比如 Raster 階段是運行在專門的 Raster thread 而不是 Compositor thread 中。
因此,結合 cc 與 viz 的工作流,重新繪製了下圖:
完整的渲染管線經歷以下幾個階段:
- Parsing
- Style
- Layout
- Composting
- Paint
- Commit
- Tiling
- Raster
- Activate
- Submit
- Draw
- Display
渲染管線的前半程是在 Renderer process 中進行的,其中渲染管線的 1-5 階段運行在 Main thread 中,這也是 Blink 負責的內容;而 6-10 階段,除了 Raster 是運行在專門的 Raster thread 中,其它流程均是在 Compositor thread 中進行的,這也是 cc 的主要內容,其中 cc 的數據源由 Paint 產生。渲染管線的尾程則是在 GPU process 中進行的,跨進程的環節交給了 viz 負責。
在後續的文章,我們將逐個解析渲染管線的各個流程中 Chromium 是如何工作的。