本文書は、Chromium のレンダリングパイプラインに関する個人的な研究のメモです。本文では、Chromium の基礎知識とレンダリングパイプラインの主要なプロセスについて説明します。
このシリーズの次の記事をおすすめします:
この記事を読むためには、Airing Notes にアクセスしてください。特別なノートのレイアウトに対応しており、より優れた読書体験ができます。
Blink の紹介#
Blink は Web のレンダリングエンジンであり、Chromium と Android Webview はいずれも Blink を使用しています。
Blink には次の特徴があります:
- Web プラットフォームの仕様(つまり、HTML 標準)の実装、DOM、CSS、WebIDL を含む。
- V8 を埋め込んで JavaScript を実行する。
- ネットワークスタックを介してリソースをリクエストする。
- DOM ツリーの構築。
- スタイルの計算とレイアウト。
- 描画には Chrome Compositor を使用する。
詳細な Blink の情報については、How Blink works を参照してください。
コードの構造的な観点から見ると、"Blink" は //third_party/blink/ ディレクトリ内のコードを指します。
プロジェクトの観点から見ると、"Blink" は Web プラットフォームの機能を実装するプロジェクトを指し、これらの Web 機能のコードは //third_party/blink/、//content/renderer/、//content/browser/ などに分散しています。
レンダラーアーキテクチャの概要#
この記事では、レンダリングパイプラインに重点を置いて説明します。そのコードは //third_party/blink/renderer にあり、ディレクトリ構造は次のようになっています:
- controller/: core/ と modules/ を使用するいくつかの高度なライブラリ。たとえば、devtools のフロントエンドなど。
- core/ と bindings/core: core/ は DOM に密接に関連する機能を実装しています。bindings/core は core/ の一部であり、bindings ディレクトリは V8 と密接に関連しているため独立しています。
- modules/ と 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 のコンポジット
- V8: JavaScript インタプリタ
レンダラープロセス#
Chromium には、1 つのブラウザプロセスと N 個のサンドボックスレンダラープロセスがあり、Blink はレンダラープロセスで実行されます。ブラウザとレンダラープロセスの間の通信は Mojo を使用して行われます。
過去には、プロセス間通信に Chromium IPC が使用されていましたが、現在でも多くのコードが IPC を使用しています。
Blink レンダラープロセスのモデルは次の図のようになります:
レンダラープロセスにはメインスレッド、複数のワーカースレッド、コンポジタースレッド、およびラスタースレッドがあります。
Blink のほとんどの主要な処理はメインスレッドで行われます。JavaScript の呼び出し、DOM の解析、CSS スタイルとレイアウトの計算などがメインスレッドで行われるため、Blink のアーキテクチャは主にシングルスレッドと見なされています。
レンダリングパイプライン#
目標#
レンダリングパイプラインの目的は、Web コンテンツを画面にレンダリングすることであり、HTML のコンテンツを段階的に処理し、最終的には Open GL を使用してハードウェアドライバに HTML コンテンツをラスタ化して画面に出力します。
なお、Web コンテンツとは、以下の図に示す領域を指します。つまり、HTML のコンテンツであり、ブラウザの外枠は含まれません。
さらに、レンダリングパイプラインは、レンダリングコンテンツの更新を効率的に処理するために、優れたデータ構造を設計しています。
パイプライン#
Blink のレンダリングパイプラインは、次の図のようになります:
"impl" = コンポジタースレッド。
この図は Life of a pixel から取得したものであり、パイプラインの主要なプロセスを説明していますが、完全ではありません。また、正確ではありません。たとえば、Raster フェーズはコンポジタースレッドではなく、専用のラスタースレッドで実行されます。
そのため、cc と viz のワークフローを組み合わせて、次の図を再描画しました:
完全なレンダリングパイプラインは、次のような段階を経ます:
- パース
- スタイル
- レイアウト
- コンポジット
- ペイント
- コミット
- タイリング
- ラスター
- アクティベート
- サブミット
- 描画
- 表示
レンダリングパイプラインの前半部分は Renderer プロセスで実行され、パイプラインの 1-5 の段階はメインスレッドで実行されます。これが Blink の担当する内容です。一方、6-10 の段階では、Raster は専用のラスタースレッドで実行され、その他のプロセスはコンポジタースレッドで実行されます。これが cc の主な内容であり、cc のデータソースはペイントによって生成されます。パイプラインの後半部分は GPU プロセスで実行され、プロセス間のステップは viz によって処理されます。
次の記事では、Chromium が各プロセスでどのように動作するかを詳しく解説します。