【テクニカル・上級編】 ペイント(描画)の仕組み – Webブラウザの仕組み実践ガイド

お決まりの「リフロー(再レイアウト)を避けてリペイント(再描画)に留めよ、できればコンポジット(合成)だけで済ませよ」という、入門書に書かれているようなアドバイスに、私はいつも少しだけ苦笑してしまいます。

実務における大規模・高グラフィックなWebアプリケーション開発において、真のボトルネックとなるのは、その先にある「ペイント(Paint)の深淵」です。ブラウザがどのように描画命令を組み立て、いつラスタライズ(ピクセル化)し、どのようにGPUメモリ(VRAM)へとテクスチャを送り込んでいるのか。この物理的な挙動を理解せずして、秒間60フレーム(あるいは120Hzディスプレイでの滑らかな描画)を維持する堅牢なアプリケーションを構築することは不可能です。

今回は、Blink(Chrome/Edge)、WebKit(Safari)、Gecko(Firefox)などのモダンブラウザ内部で蠢く「ペイント」の仕組みを解剖し、メモリ効率、非同期描画の競合、そして実務で遭遇する致命的な描画バグの回避策までを徹底的に深掘りします。

—

1. ペイントプロセスの解剖学:レイアウトからピクセルへの変換

DOMとCSSが解析され、要素の配置(Layout)が決定した瞬間、ブラウザは「どこに何があるか」を知っています。しかし、それを「どう描くか」はまだ決まっていません。ここからがペイントの領域です。

ペイントは、単に画面に色を塗る処理ではありません。大きく分けて「ペイントレコードの生成(ペイント操作の記録)」と「ラスタライズ(ビットマップへの変換)」という2つのフェーズを経ています。

[ Layout Tree ]
│
▼
[ Paint (Main Thread) ] ── ペイントレコード (Display List) の生成
│
▼ (Commit)
[ Compositor Thread ] ── タイル分割 (Tiling)
│
▼
[ Raster (GPU/CPU) ] ─── ピクセル(ビットマップ)化、GPUテクスチャへ転送
│
▼
[ GPU (Draw) ] ───────── 画面への出力 (Display)

1-1. ペイントレコード(Display List)の生成

メインスレッドは、レイアウトツリーをスキャンし、Display List(またはPaint Record)と呼ばれる「描画命令のリスト」を生成します。
これは「座標 (10, 10) に幅 100×100 の矩形を #FFF で描け」「その上に太さ 2px の黒い境界線を描け」「次にテキスト『Hello』をフォントサイズ 16px で描け」といった、グラフィックAPI(SkiaやGraphite、CoreGraphicsなど)に対する命令書の並びです。

ここで極めて重要なのが、CSSの重ね合わせ文脈(Stacking Context)の解決です。`z-index`、`opacity`、`transform`、`mix-blend-mode` などが複雑に絡み合う現代のUIにおいて、ブラウザは描画する順番(ペイントオーダー)を厳密に決定しなければなりません。このオーダーが1つでも狂うと、UIの前後関係が崩れるバグ(Ghostingや不正な重なり)が発生します。

1-2. ラスタライズ(Rasterization)の真実

ペイントレコードはただの命令書であり、ディスプレイが表示できる「ピクセル(赤・緑・青・アルファ値の配列)」ではありません。この命令書を元に、実際のビットマップ画像を生成する処理をラスタライズと呼びます。

古くはCPUだけでこのラスタライズを行っていましたが、現代のブラウザは基本的にGPUラスタライズを採用しています。
Blinkエンジンを例に取ると、メインスレッドが生成したペイントレコードは、コンポジタースレッド(Compositor Thread)へと「コミット(Commit)」されます。コンポジタースレッドは、画面をタイル(Tiling)と呼ばれる小さな領域(通常 256×256 や 512×512 ピクセル)に分割し、画面に表示される領域(およびその周辺の「予備領域」)のタイルから優先的に、GPUのシェーダープログラムを利用して高速にラスタライズを実行します。

—

2. メモリ効率とレンダリング負荷のトレードオフ:レイヤー昇格の光と影

「アニメーションを滑らかにするために `will-change: transform` や `translate3d(0, 0, 0)` を使ってレイヤーを分ければいい」

このナイーブなアプローチは、モバイルデバイスやメモリ制限の厳しい環境において、アプリをクラッシュさせる最大の引き金になります。

2-1. レイヤー昇格(Layer Promotion)とは何か

コメント

タイトルとURLをコピーしました