レンダリング パイプラインへの入出力である、重要なデータ構造について見てみましょう。
これらのデータ構造は次のとおりです。
- フレームツリーは、どのレンダリング プロセスとどの Blink レンダラにあるウェブドキュメントを表すローカルノードとリモートノードで構成されています。
- 不変のフラグメント ツリーは、レイアウト制約アルゴリズム(およびその入力)の出力を表します。
- プロパティ ツリーは、ウェブドキュメントの変換、クリップ、エフェクト、スクロールの階層を表します。これらはパイプライン全体で使用されます。
- ディスプレイ リストとペイント チャンクは、ラスター化アルゴリズムとレイヤ化アルゴリズムの入力です。
- コンポジタ フレームは、GPU を使用して描画するために使用されるサーフェス、レンダリング サーフェス、GPU テクスチャ タイルをカプセル化します。
これらのデータ構造を確認する前に、次の例ではアーキテクチャの確認の例を基に説明します。この例は、データ構造がどのように適用されるかを示すために、このドキュメント全体で使用されます。
<!-- Example code -->
<html>
<div style="overflow: hidden; width: 100px; height: 100px;">
<iframe style="filter: blur(3px);
transform: rotateZ(1deg);
width: 100px; height: 300px"
id="one" src="foo.com/etc"></iframe>
</div>
<iframe style="top:200px;
transform: scale(1.1) translateX(200px)"
id="two" src="bar.com"></iframe>
</html>
フレームツリー
Chrome は、クロスオリジン フレームを親フレームとは異なるレンダリング プロセスでレンダリングすることがあります。
サンプルコードでは、合計 3 つのフレームがあります。
サイト分離では、Chromium は 2 つのレンダリング プロセスを使用してこのウェブページをレンダリングします。各レンダリング プロセスには、そのウェブページのフレームツリーの独自の表現があります。
別のプロセスでレンダリングされたフレームは、リモート フレームとして表されます。リモート フレームは、レンダリングでプレースホルダとして機能するために必要な最小限の情報(サイズなど)を保持します。そうでない場合、リモート フレームには実際のコンテンツのレンダリングに必要な情報は含まれません。
一方、ローカル フレームは、標準レンダリング パイプラインを通過するフレームを表します。ローカル フレームには、そのフレームのデータ(DOM ツリーやスタイルデータなど)をレンダリングして表示できるものにするために必要なすべての情報が含まれています。
レンダリング パイプラインは、ローカル フレームツリー フラグメントの粒度で動作します。foo.com
をメインフレームとする、より複雑な例について考えてみましょう。
<iframe src="bar.com"></iframe>
次の bar.com
サブフレームも追加します。
<iframe src="foo.com/etc"></iframe>
レンダラは引き続き 2 つですが、ローカル フレームツリー フラグメントは 3 つあります。2 つは foo.com
のレンダリング プロセスにあり、1 つは bar.com
のレンダリング プロセスにあります。
ウェブページの 1 つのコンポジタ フレームを生成するために、Viz は 3 つのローカル フレームツリーの各ルートフレームからコンポジタ フレームを同時にリクエストし、それらを集約します。コンポーザ フレーム セクションも参照してください。
foo.com
メインフレームと foo.com/other-page
サブフレームは同じフレームツリーの一部であり、同じプロセスでレンダリングされます。ただし、2 つのフレームは異なるローカル フレームツリー フラグメントの一部であるため、独立したドキュメント ライフサイクルを持ちます。このため、1 回の更新で両方のコンポジタ フレームを生成することはできません。レンダリング プロセスには、foo.com/other-page
用に生成されたコンポジタ フレームを foo.com
メインフレームのコンポジタ フレームに直接合成するための十分な情報がありません。たとえば、プロセス外の bar.com
親フレームは、CSS で iframe を変換したり、DOM 内の他の要素で iframe の一部を隠したりすることで、foo.com/other-url
iframe の表示に影響する可能性があります。
ビジュアル プロパティの更新ウォーターフォール
デバイスのスケール ファクタやビューポートのサイズなどの視覚的なプロパティは、レンダリングされた出力に影響するため、ローカル フレームツリー フラグメント間で同期する必要があります。各ローカル フレーム ツリー フラグメントのルートには、ウィジェット オブジェクトが関連付けられています。ビジュアル プロパティの更新は、メインフレームのウィジェットに送信された後、残りのウィジェットに上から下に伝播されます。
たとえば、ビューポートのサイズが変更された場合:
このプロセスは瞬時に行われないため、複製されたビジュアル プロパティには同期トークンも含まれます。Viz コンポジタは、この同期トークンを使用して、すべてのローカル フレームツリー フラグメントが現在の同期トークンを使用してコンポジタ フレームを送信するのを待ちます。このプロセスにより、異なる視覚プロパティのコンポジット フレームが混在するのを回避できます。
不変のフラグメント ツリー
不変のフラグメント ツリーは、レンダリング パイプラインのレイアウト ステージの出力です。ページ上のすべての要素の位置とサイズを表します(変換は適用されません)。
各フラグメントは DOM 要素の一部を表します。通常、要素ごとに 1 つのフラグメントのみが存在しますが、印刷時に異なるページに分割されている場合や、複数列のコンテキストで列に分割されている場合は、複数のフラグメントが存在することもあります。
レイアウト後、各フラグメントは不変になり、変更されなくなります。また、いくつかの追加制限も設けています。Google は以下のことは行いません。
- ツリー内の「上」の参照を許可します。(子に親へのポインタを設定することはできません)。
- データをツリーに沿って「バブルアップ」します(子は親からではなく、子からのみ情報を読み取ります)。
これらの制限により、フラグメントを後続のレイアウトで再利用できます。これらの制限がないと、ツリー全体を頻繁に再生成する必要があり、費用がかかります。
ほとんどのレイアウトは通常、段階的な更新です。たとえば、ユーザーが要素をクリックしたときに UI のごく一部を更新するウェブアプリなどです。理想的には、レイアウトは画面上で実際に変更されたものに比例した作業のみを行う必要があります。これは、以前のツリーのできるだけ多くの部分を再利用することで実現できます。つまり、通常はツリーのスパインを再ビルドするだけで済みます。
将来的には、この不変の設計により、必要に応じてスレッド境界を越えて不変のフラグメント ツリーを渡す(別のスレッドで後続のフェーズを実行するため)、スムーズなレイアウト アニメーションのために複数のツリーを生成する、並列推測レイアウトを実行するなどの興味深いことができます。また、レイアウト自体をマルチスレッド化することもできます。
インライン フラグメント アイテム
インライン コンテンツ(主にスタイル設定されたテキスト)では、少し異なる表現が使用されます。ボックスとポインタを含むツリー構造ではなく、ツリーを表すフラットなリストでインライン コンテンツを表します。主な利点は、インラインのフラットなリスト表現が高速で、インライン データ構造の検査やクエリに役立ち、メモリ効率が高いことです。これは、テキストのレンダリングは非常に複雑であり、高度に最適化されていない限り、パイプラインで最も遅い部分になりやすいため、ウェブレンダリングのパフォーマンスにとって非常に重要です。
フラットリストは、インライン レイアウト サブツリーの深さ優先探索の順序で、インライン フォーマット コンテキストごとに作成されます。リスト内の各エントリは、(オブジェクト、子孫の数)のタプルです。たとえば、次の DOM について考えてみましょう。
<div style="width: 0;">
<span style="color: blue; position: relative;">Hi</span> <b>there</b>.
</div>
width
プロパティが 0 に設定されているため、行は「Hi」と「there」の間に折り返されます。
この状況のインライン フォーマット コンテキストをツリーとして表すと、次のようになります。
{
"Line box": {
"Box <span>": {
"Text": "Hi"
}
},
"Line box": {
"Box <b>": {
"Text": "There"
}
},
{
"Text": "."
}
}
フラット リストは次のようになります。
- (線のボックス、2)
- (Box <span>, 1)
- (テキスト「Hi」、0)
- (線のボックス、3)
- (Box <b>、1)
- (テキスト「there」、0)
- (テキスト「.」、0)
このデータ構造を使用するコンシューマは、ユーザー補助 API、getClientRects
や contenteditable
などのジオメトリ API など、多数あります。それぞれ要件が異なります。これらのコンポーネントは、便利なカーソルを介してフラット データ構造にアクセスします。
カーソルには、MoveToNext
、MoveToNextLine
、CursorForChildren
などの API があります。このカーソルの表現は、次のような理由からテキスト コンテンツに非常に強力です。
- 深さ優先探索順序で反復処理すると、非常に高速です。これはカーソルの移動に似ているため、非常によく使用されます。フラットなリストであるため、深さ優先探索では配列オフセットをインクリメントするだけで、高速な反復処理とメモリ局所性が実現されます。
- 幅優先検索を提供します。これは、線とインライン ボックスの背景をペイントする場合などに必要です。
- 子孫の数がわかれば、次の兄弟に素早く移動できます(配列オフセットをその数だけ増やします)。
プロパティ ツリー
DOM は要素(およびテキストノード)のツリーであり、CSS では要素にさまざまなスタイルを適用できます。
4 つの方法で表示されます。
- レイアウト: レイアウト制約アルゴリズムの入力。
- Paint: 要素(その子孫は除く)をペイントしてラスタ化する方法。
- 視覚効果: 変換、フィルタ、クリッピングなど、DOM サブツリーに適用されるラスター/描画効果。
- スクロール: 軸に沿った丸い角のクリッピングと、含まれるサブツリーのスクロール。
プロパティ ツリーは、視覚効果とスクロール効果が DOM 要素に適用される仕組みを説明するデータ構造です。レイアウトのサイズと位置が指定された DOM 要素が画面に対してどこにあるかなど、さまざまな質問に答える手段を提供します。また、視覚効果とスクロール エフェクトを適用するために、どのような順序で GPU オペレーションを使用すればよいですか?
ウェブ上の視覚効果とスクロール効果は、その全容が非常に複雑です。プロパティ ツリーが行う最も重要なことは、その複雑さを、構造と意味を正確に表す単一のデータ構造に変換し、同時に DOM と CSS の複雑さを排除することです。これにより、コンポジットとスクロールのアルゴリズムをより確実に実装できるようになります。具体的には、次のとおりです。
- エラーが発生する可能性のあるジオメトリやその他の計算を 1 か所に集約できます。
- プロパティ ツリーの構築と更新の複雑さは、1 つのレンダリング パイプライン ステージに分離されます。
- プロパティ ツリーをさまざまなスレッドやプロセスに送信するのは、完全な DOM 状態よりもはるかに簡単で高速です。そのため、多くのユースケースで使用できます。
- ユースケースが多いほど、相互のキャッシュを再利用できる上、構築されたジオメトリ キャッシュから得られるメリットが大きくなります。
RenderingNG では、次のような多くの目的でプロパティ ツリーを使用します。
- コンポジットをペイントから分離し、コンポジットをメインスレッドから分離。
- 最適な合成 / 描画戦略を決定する。
- IntersectionObserver ジオメトリの測定。
- オフスクリーン要素と GPU テクスチャ タイルの処理を回避する。
- ペイントとラスタを効率的かつ正確に無効にする。
- Core Web Vitals でレイアウト シフトとLargest Contentful Paint を測定する。
すべてのウェブドキュメントには、transform、clip、effect、scroll の 4 つの個別のプロパティ ツリーがあります。(*)transform ツリーは CSS 変換とスクロールを表します。(スクロール変換は 2D 変換行列として表されます)。クリップツリーは、オーバーフロー クリップを表します。エフェクト ツリーは、他のすべての視覚効果(不透明度、フィルタ、マスク、ブレンドモード、clip-path などの他の種類のクリップ)を表します。スクロール ツリーは、スクロールの連結方法など、スクロールに関する情報を表します。コンポジタ スレッドでスクロールを実行するために必要です。プロパティ ツリーの各ノードは、DOM 要素によって適用されるスクロールまたは視覚効果を表します。複数の効果がある場合は、同じ要素の各ツリーに複数のプロパティ ツリーノードがある場合があります。
各ツリーのトポロジは、DOM のスパース表現に似ています。たとえば、オーバーフロー クリップを持つ DOM 要素が 3 つある場合、クリップツリー ノードは 3 つあり、クリップツリーの構造はオーバーフロー クリップ間の包含ブロックの関係に従います。ツリー間のリンクもあります。これらのリンクは、ノードの相対 DOM 階層、つまり適用順序を示しています。たとえば、DOM 要素の変換がフィルタを含む別の DOM 要素の下にある場合、変換はフィルタの前に適用されます。
各 DOM 要素にはプロパティ ツリー状態があります。これは、その要素に適用される最も近い祖先のクリップ、変換、エフェクト ツリーノードを示す 4 タプル(変換、クリップ、エフェクト、スクロール)です。この情報があれば、その要素に適用されるクリップ、変換、エフェクトのリストと順序を正確に把握できるため、非常に便利です。これにより、画面上の位置と描画方法が決まります。
例
(出典)
<html>
<div style="overflow: scroll; width: 100px; height: 100px;">
<iframe style="filter: blur(3px);
transform: rotateZ(1deg);
width: 100px; height: 300px"
id="one" srcdoc="iframe one"></iframe>
</div>
<iframe style="top:200px;
transform: scale(1.1) translateX(200px)" id=two
srcdoc="iframe two"></iframe>
</html>
上記の例(導入の例とは若干異なります)で生成されたプロパティ ツリーの主な要素は次のとおりです。
ディスプレイ リストとペイント チャンクを表示する
ディスプレイ アイテムには、Skia でラスタライズできる低レベルの描画コマンド(こちらを参照)が含まれています。ディスプレイ アイテムは通常、境界や背景の描画など、数個の描画コマンドのみを使用します。ペイント ツリー ウォークは、CSS ペイント順序に従ってレイアウト ツリーと関連するフラグメントを反復処理し、表示アイテムリストを生成します。
次に例を示します。
<div id="green" style="background:green; width:80px;">
Hello world
</div>
<div id="blue" style="width:100px;
height:100px; background:blue;
position:absolute;
top:0; left:0; z-index:-1;">
</div>
この HTML と CSS は、次の表示リストを生成します。各セルは表示アイテムです。
ビューの背景 | #blue のバックグラウンド |
#green のバックグラウンド |
#green インライン テキスト |
---|---|---|---|
サイズが 800x600 で色が白の drawRect 。 |
drawRect : サイズ 100x100、位置 0,0、色は青。 |
drawRect : サイズ 80x18、位置 8,8、色は緑。 |
drawTextBlob (位置 8,8、テキスト「Hello world」)。 |
ディスプレイ アイテムのリストは後ろから順に並べられます。上の例では、DOM 順序では緑色の div が青色の div の前にありますが、CSS ペイント順序では、負の z-index の青色の div が緑色の div(ステップ 4.1)の前にペイントされます(ステップ 3)。ディスプレイ アイテムは、CSS ペイント順序仕様のアトミック ステップに対応しています。1 つの DOM 要素で複数の表示アイテムが生成される場合があります。たとえば、#green には背景の表示アイテムとインライン テキストの表示アイテムがあります。この粒度は、負のマージンによって作成されたインターリーブなど、CSS ペイント順序仕様の複雑さを完全に表すために重要です。
<div id="green" style="background:green; width:80px;">
Hello world
</div>
<div id="gray" style="width:35px; height:20px;
background:gray;margin-top:-10px;"></div>
これにより、次の表示リストが生成されます。各セルが表示アイテムです。
ビューの背景 | #green のバックグラウンド |
#gray のバックグラウンド |
#green インライン テキスト |
---|---|---|---|
サイズが 800x600 で色が白の drawRect 。 |
drawRect : サイズ 80x18、位置 8,8、色は緑。 |
drawRect : サイズ 35x20、位置 8,16、色グレー。 |
drawTextBlob (位置 8,8、テキスト「Hello world」)。 |
ディスプレイ アイテム リストは保存され、後続の更新で再利用されます。ペイント ツリー ウォーク中にレイアウト オブジェクトが変更されていない場合、そのディスプレイ アイテムは前のリストからコピーされます。追加の最適化は、CSS ペイント順序仕様のプロパティ(スタッキング コンテキストがアトミックにペイントされる)に依存しています。スタッキング コンテキスト内でレイアウト オブジェクトが変更されていない場合、ペイント ツリー ウォークはスタッキング コンテキストをスキップし、前のリストからディスプレイ アイテムのシーケンス全体をコピーします。
現在のプロパティ ツリー状態はペイント ツリー ウォーク中に維持され、ディスプレイ アイテム リストは、同じプロパティ ツリー状態を共有するディスプレイ アイテムの「チャンク」にグループ化されます。次の例で説明します。
<div id="scroll" style="background:pink; width:100px;
height:100px; overflow:scroll;
position:absolute; top:0; left:0;">
Hello world
<div id="orange" style="width:75px; height:200px;
background:orange; transform:rotateZ(25deg);">
I'm falling
</div>
</div>
これにより、次の表示リストが生成されます。各セルが表示アイテムです。
ビューの背景 | #scroll のバックグラウンド |
#scroll インライン テキスト |
#orange のバックグラウンド |
#orange インライン テキスト |
---|---|---|---|---|
サイズが 800x600 で色が白の drawRect 。 |
drawRect : サイズ 100x100、位置 0,0、色ピンク。 |
drawTextBlob : 位置 0,0、テキスト「Hello world」 |
drawRect : サイズ 75x200、位置 0,0、色オレンジ。 |
drawTextBlob (位置 0,0、テキスト「I'm falling」)。 |
変換プロパティ ツリーとペイント チャンクは次のようになります(簡潔にするため簡略化しています)。
ペイント チャンクの順序付きリスト(ディスプレイ アイテムとプロパティ ツリー状態のグループ)は、レンダリング パイプラインのレイヤ化ステップへの入力です。ペイント チャンクのリスト全体を 1 つの合成レイヤに統合して一緒にラスタライズすることもできますが、この場合、ユーザーがスクロールするたびに高負荷のラスタライズが必要になります。ペイント チャンクごとに合成レイヤを作成し、個別にラスタライズして、すべての再ラスタライズを回避することもできますが、GPU メモリがすぐに使い果たされます。レイヤ化のステップでは、GPU メモリと変更時の費用削減のトレードオフを行う必要があります。一般的なアプローチとしては、デフォルトでチャンクを統合し、コンポジタ スレッドで変更が予想されるプロパティ ツリー状態を持つペイント チャンクを統合しないことをおすすめします(コンポジタ スレッドのスクロールやコンポジタ スレッドの変換アニメーションなど)。
上記の例では、理想的には 2 つの合成レイヤが生成されます。
- 描画コマンドを含む 800 x 600 の合成レイヤ:
drawRect
(サイズ 800x600、色: 白)drawRect
: サイズ 100x100、位置 0,0、色ピンク
- 描画コマンドを含む 144x224 の合成レイヤ:
- 位置 0,0 でテキスト「Hello world」の
drawTextBlob
- 0.18 を翻訳
rotateZ(25deg)
drawRect
(サイズ 75x200、位置 0,0、色オレンジ)drawTextBlob
(位置 0,0、テキスト「I'm falling」)
- 位置 0,0 でテキスト「Hello world」の
ユーザーが #scroll
をスクロールすると、2 番目の合成レイヤは移動されますが、ラスタライズは必要ありません。
例として、プロパティ ツリーに関する前のセクションでは、ペイント チャンクが 6 つあります。プロパティ ツリー状態(変換、クリップ、エフェクト、スクロール)とともに、次のように分類されます。
- ドキュメントの背景: ドキュメントのスクロール、ドキュメントのクリップ、ルート、ドキュメントのスクロール。
- div の水平方向、垂直方向、スクロールの角(3 つの個別のペイント チャンク): ドキュメントのスクロール、ドキュメントのクリップ、
#one
ぼかし、ドキュメントのスクロール。 - iframe
#one
:#one
回転、オーバーフロー スクロール クリップ、#one
ぼかし、div スクロール。 - フレーム
#two
:#two
スケール、ドキュメント クリップ、ルート、ドキュメント スクロール。
コンポジタ フレーム: サーフェス、レンダリング サーフェス、GPU テクスチャタイル
ブラウザ プロセスとレンダリング プロセスはコンテンツのラスタライズを管理し、コンポジタ フレームを Viz プロセスに送信して画面に表示します。コンポジター フレームは、ラスタライズされたコンテンツをどのようにつなぎ合わせて、GPU を使用して効率的に描画するかを表します。
タイル
理論的には、レンダリング プロセスまたはブラウザ プロセスのコンポーザーは、ピクセルをレンダラ ビューポートのフルサイズの単一テクスチャにラスタライズし、そのテクスチャを Viz に送信できます。表示するには、ディスプレイ コンポーザーがその単一テクスチャからフレームバッファの適切な位置(画面など)にピクセルをコピーするだけです。ただし、そのコンポーザが 1 ピクセルでも更新する場合は、ビューポート全体を再ラスタライズし、新しいテクスチャを Viz に送信する必要があります。
代わりに、ビューポートはタイルに分割されます。個別の GPU テクスチャ タイルが、ビューポートの一部のラスタ化されたピクセルで各タイルをバックアップします。レンダラは、個々のタイルを更新したり、既存のタイルの画面上の位置を変更したりできます。たとえば、ウェブサイトをスクロールすると、既存のタイルは上に移動し、ページの下部にあるコンテンツに対して新しいタイルをラスタライズする必要があるのはまれです。
四角形とサーフェス
GPU テクスチャ タイルは特別な種類の四角形です。これは、テクスチャのカテゴリを示すおしゃれな名前にすぎません。四角形は入力テクスチャを識別し、変換して視覚効果を適用する方法を指定します。たとえば、通常のコンテンツ タイルには、タイル グリッド内の x 座標と y 座標を示す変換があります。
これらのラスター化されたタイルは、四角形のリストであるレンダリング パスでラップされます。レンダリング パスにはピクセル情報は含まれません。代わりに、目的のピクセル出力を生成するために各四角形をどこにどのように描画するかに関する命令が含まれています。GPU テクスチャタイルごとに描画四角形があります。ディスプレイ コンポーザは、四角形のリストを反復処理し、指定された視覚効果でそれぞれを描画して、レンダリング パスに必要なピクセル出力を生成します。レンダリング パスの描画四角形の合成は、GPU 機能に直接マッピングされるように許可される視覚効果が慎重に選択されているため、GPU で効率的に行うことができます。
ラスター化されたタイル以外にも、描画四角形の種類があります。たとえば、テクスチャでバッキングされていない単色の描画四角形や、動画やキャンバスなどのタイル以外のテクスチャ用のテクスチャ描画四角形があります。
コンポジット フレームに別のコンポジット フレームを埋め込むこともできます。たとえば、ブラウザのコンポーザは、ブラウザ UI と、レンダリング コンポーザのコンテンツが埋め込まれる空の長方形を含むコンポーザ フレームを生成します。別の例として、サイト分離された iframe があります。このエンベディングは、サーフェスによって実現されます。
コンポーザがコンポーザ フレームを送信すると、サーフェス ID と呼ばれる識別子が付加され、他のコンポーザ フレームが参照によってそのフレームを埋め込むことができます。特定のサーフェス ID で送信された最新のコンポジタ フレームは Viz によって保存されます。別のコンポジタ フレームは、後でサーフェス描画四角形を介してそのフレームを参照できるため、Viz は描画する内容を把握できます。(サーフェス描画四角形には、サーフェス ID のみが含まれ、テクスチャは含まれません)。
中間レンダリング パス
多くのフィルタや高度なブレンドモードなどの視覚効果では、2 つ以上の四角形を中間テクスチャに描画する必要があります。次に、中間テクスチャが GPU 上の宛先バッファ(または別の中間テクスチャ)に描画され、同時に視覚効果が適用されます。これを可能にするために、コンポジタ フレームにはレンダリング パスのリストが実際に含まれています。常にルート レンダリング パスがあり、これは最後に描画され、フレームバッファに対応する宛先があります。また、複数のパスがある場合もあります。
複数のレンダリング パスが存在する可能性があるため、このパスは「レンダリング パス」と呼ばれます。各パスは GPU で複数の「パス」で順番に実行する必要がありますが、単一のパスは一度の超並列 GPU 計算で完了できます。
集計
複数のコンポジタ フレームが Viz に送信され、それらは一緒に画面に描画する必要があります。これは、それらを単一の集約コンポジタ フレームに変換する集計フェーズによって実現されます。集計では、サーフェス描画クアッドに指定されたコンポジター フレームが置き換えられます。また、不要な中間テクスチャや画面外にあるコンテンツを最適化して削除することもできます。たとえば、多くの場合、サイトの分離された iframe のコンポジタ フレームは独自の中間テクスチャを必要とせず、適切な描画四角形を介してフレームバッファに直接描画できます。集約フェーズでは、このような最適化を特定し、個々のレンダラ コンポーザにアクセスできないグローバルな知識に基づいて適用します。
例
以下に、この記事の冒頭の例を表すコンポジタ フレームを示します。
foo.com/index.html
サーフェス: id=0- レンダリング パス 0: 出力に描画します。
- レンダリング パス描画四角形: 3 ピクセルのぼかしで描画し、レンダリング パス 0 にクリップします。
- レンダリング パス 1:
#one
iframe のタイル コンテンツの四角形を、それぞれ x 位置と y 位置を指定して描画します。
- レンダリング パス 1:
- サーフェス描画四角形: ID 2、スケールと移動変換で描画。
- レンダリング パス描画四角形: 3 ピクセルのぼかしで描画し、レンダリング パス 0 にクリップします。
- レンダリング パス 0: 出力に描画します。
- ブラウザ UI サーフェス: ID=1
- レンダリング パス 0: 出力に描画します。
- ブラウザ UI のクアッド(タイリングも)を描画する
- レンダリング パス 0: 出力に描画します。
bar.com/index.html
サーフェス: ID=2- レンダリング パス 0: 出力に描画します。
#two
iframe のコンテンツの四角形を、それぞれ x 位置と y 位置を指定して描画します。
- レンダリング パス 0: 出力に描画します。
イラスト: Una Kravets