Schlüsseldatenstrukturen in RenderingNG

Chris Harrelson
Chris Harrelson
Daniel Cheng
Daniel Cheng
Philip Rogers
Philip Rogers
Koji Ishi
Koji Ishi
Ian Kilpatrick
Ian Kilpatrick
Kyle Charbonneau
Kyle Charbonneau

Sehen wir uns die wichtigsten Datenstrukturen an: Rendering-Pipeline haben.

Diese Datenstrukturen sind:

  • Frame-Bäume bestehen aus lokalen und Remote-Knoten, die darstellen, welches Web in welchem Renderprozess und in welchem Blink-Renderer sich befinden.
  • Die unveränderliche Fragmentstruktur stellt die Ausgabe des (und die Eingabe) des Algorithmus für Layouteinschränkung.
  • Property-Bäume stellen die Transformations-, Clip-, Effekt- und Scroll-Hierarchien dar. eines Webdokuments. Diese werden in der gesamten Pipeline verwendet.
  • Anzeigelisten und Farbblöcke sind die Eingaben für die Raster- und Ebenenalgorithmen.
  • Compositor-Frames umschließen Oberflächen, Renderingflächen und GPU-Texturen. Kacheln, die zum Zeichnen mit der GPU verwendet werden.

Bevor wir diese Datenstrukturen durchgehen, baut das folgende Beispiel auf eine aus architecture review. Dieses wird in diesem Dokument mit Demonstrationen, die zeigen, wie die Daten Strukturen anwenden.

<!-- 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>

Rahmen für Bäume

Chrome rendert manchmal einen ursprungsübergreifenden Frame als der übergeordnete Frame.

Im Beispielcode gibt es insgesamt drei Frames:

Ein übergeordneter Frame &quot;foo.com&quot; mit zwei iFrames.

Bei der Website-Isolierung verwendet Chromium zum Rendern dieser Webseite zwei Renderingprozesse. Jeder Renderingprozess hat eine eigene Darstellung der Frame-Baumstruktur der Webseite:

Zwei Frame-Bäume, die die beiden Renderingprozesse darstellen.

Ein Frame, der in einem anderen Prozess gerendert wird, wird als Remote-Frame dargestellt. Ein Remote-Frame enthält mindestens die Informationen, die für das Rendern als Platzhalter verwendet werden. z. B. die Abmessungen. Andernfalls enthält der Remote-Frame keine Informationen, die zum Rendern seines eigentlichen Inhalts erforderlich sind.

Im Gegensatz dazu stellt ein lokaler Frame einen Frame dar, der den standardmäßigen Rendering-Pipeline. Der lokale Frame enthält alle Informationen, die zum die Daten für diesen Frame (wie den DOM-Baum und die Stildaten) in etwas die gerendert und dargestellt werden können.

Die Rendering-Pipeline arbeitet mit dem Detaillierungsgrad eines lokales Frame-Baumfragment. Sehen Sie sich ein etwas komplizierteres Beispiel mit foo.com als Hauptframe an:

<iframe src="bar.com"></iframe>

Und den folgenden bar.com-Subframe:

<iframe src="foo.com/etc"></iframe>

Obwohl es immer noch nur zwei Renderer gibt, gibt es jetzt drei lokale Frames. Baumfragmente, wobei zwei im Renderingprozess für foo.com und ein Fragment im Renderingprozess für bar.com:

Darstellung der beiden Renderings und der drei Frame-Baumfragmente

Um einen zusammengesetzten Frame für die Webseite zu erstellen, Viz fordert gleichzeitig einen zusammengesetzten Frame aus dem Stammframe jedes der den drei lokalen Rahmenbäumen. sie zusammenfassen. Weitere Informationen finden Sie im Abschnitt Compositor Frames.

Der Hauptframe foo.com und der Subframe foo.com/other-page Teil desselben Frame-Baums sind und im selben Prozess gerendert werden. Die beiden Frames haben dennoch unabhängige Dokumentlebenszyklen da sie Teil verschiedener lokaler Frame Tree-Fragmente sind. Aus diesem Grund ist es unmöglich, einen einzigen zusammengesetzten Frame für beide in einer Aktualisierung zu generieren. Der Renderingprozess enthält nicht genügend Informationen zum Zusammensetzen des für foo.com/other-page generierten zusammengesetzten Frames in den Compositor-Frame für den foo.com-Hauptframe. Beispielsweise kann sich der übergeordnete Frame bar.com Out-of-Process auf die Darstellung des iFrames foo.com/other-url auswirken. indem der iFrame mit CSS umgewandelt oder Teile des iFrames mit anderen Elementen in seinem DOM verdeckt werden.

Wasserfall für die Aktualisierung visueller Eigenschaften

Visuelle Eigenschaften wie der Skalierungsfaktor des Geräts und die Größe des Darstellungsbereichs beeinflussen die gerenderte Ausgabe. Außerdem muss zwischen den lokalen Frame-Baumfragmenten synchronisiert werden. Dem Stamm jedes lokalen Frame-Baumfragments ist ein Widget-Objekt zugeordnet. Aktualisierungen visueller Eigenschaften werden vor der Übertragung an das Widget des Hauptframes gesendet die restlichen Widgets von oben nach unten.

Wenn sich die Größe des Darstellungsbereichs ändert, geschieht beispielsweise Folgendes:

Diagramm des im vorherigen Text erläuterten Prozesses.

Dieser Vorgang erfolgt nicht unverzüglich, sodass die replizierten visuellen Eigenschaften auch ein Synchronisierungstoken enthalten. Der Viz-Compositor verwendet dieses Synchronisierungstoken, um auf alle lokalen Frame-Baumfragmente zu warten um einen zusammengesetzten Frame mit dem aktuellen Synchronisierungstoken zu senden. Dadurch wird vermieden, dass zusammengesetzte Frames mit unterschiedlichen visuellen Eigenschaften vermischt werden.

Der unveränderliche Fragmentbaum

Die unveränderliche Fragmentstruktur ist die Ausgabe der Layoutphase des Renderings. zu erstellen. Er stellt die Position und Größe aller Elemente auf der Seite dar. (ohne angewendete Transformationen).

Darstellung der Fragmente in jedem Baum, wobei ein Fragment als erforderliches Layout markiert wird.

Jedes Fragment stellt einen Teil eines DOM-Elements dar. Normalerweise gibt es nur ein Fragment pro Element, aber mehr, wenn sie beim Drucken auf verschiedene Seiten aufgeteilt werden, oder Spalten in einem mehrspaltigen Kontext.

Nach dem Layout ist jedes Fragment unveränderlich und nie wieder geändert. Außerdem weisen wir einige zusätzliche Einschränkungen auf. Was wir nicht tun:

  • Beliebiges „Auf“ zulassen Referenzen in der Baumstruktur. Ein untergeordnetes Element darf keinen Verweis auf das übergeordnete Element haben.
  • "Bubble" Daten in einem Baum (Ein untergeordnetes Element liest nur Informationen von seinen untergeordneten Elementen, nicht von seinem übergeordneten Element).

Diese Einschränkungen ermöglichen es uns, ein Fragment für ein nachfolgendes Layout wiederzuverwenden. Ohne diese Einschränkungen müssten wir häufig den gesamten Baum neu generieren, was teuer ist.

Die meisten Layouts sind in der Regel schrittweise Updates, wie z. B. Eine Webanwendung, die einen kleinen Teil der Benutzeroberfläche aktualisiert, nachdem der Nutzer auf ein Element geklickt hat. Idealerweise sollte das Layout nur proportional zu den Änderungen auf dem Bildschirm passen. Das erreichen wir, indem wir so viele Teile des vorherigen Baums wie möglich wiederverwenden. Das bedeutet in der Regel, dass wir nur die Wirbelsäule des Baums neu aufbauen müssen.

Künftig könnten wir mit diesem unveränderlichen Design interessante Dinge z. B. wenn der unveränderliche Fragmentbaum bei Bedarf über Thread-Grenzen weitergegeben wird. (um nachfolgende Phasen in einem anderen Thread auszuführen) mehrere Bäume für eine flüssige Layout-Animation generieren, oder parallele spekulative Layouts durchführen. Es bietet uns auch das Potenzial eines Multithreading-Layouts selbst.

Fragmentierte Inline-Elemente

Bei Inline-Inhalten (hauptsächlich formatierter Text) wird eine etwas andere Darstellung verwendet. Statt einer Baumstruktur mit Kästen und Zeigern stellen wir Inline-Inhalte in einer flachen Liste dar, die den Baum darstellt. Der Hauptvorteil besteht darin, dass eine einfache Listendarstellung ist nützlich für die Prüfung oder Abfrage von Inline-Datenstrukturen, und speichereffizient. Dies ist für die Rendering-Leistung im Web äußerst wichtig, da das Rendern von Text sehr komplex ist. und kann ohne große Optimierung schnell zum langsamsten Teil der Pipeline werden.

Für jedes Element wird eine einfache Liste Inline-Formatierungskontext in der Reihenfolge der Tiefensuche in ihrer Inline-Layout-Unterstruktur. Jeder Eintrag in der Liste ist ein Tupel von (Objekt, Anzahl der Nachfolgerelemente). Betrachten Sie zum Beispiel dieses DOM:

<div style="width: 0;">
  <span style="color: blue; position: relative;">Hi</span> <b>there</b>.
</div>

Das Attribut width ist auf 0 gesetzt, sodass die Linie zwischen „Hi“ verläuft. und „da“.

Wenn der Inline-Formatierungskontext für diese Situation als Baumstruktur dargestellt wird, sieht das so aus:

{
  "Line box": {
    "Box <span>": {
      "Text": "Hi"
    }
  },
  "Line box": {
    "Box <b>": {
      "Text": "There"
    }
  },
  {
    "Text": "."
  }
}

Die einfache Liste sieht so aus:

  • (Linienfeld, 2)
  • (Feld <span>, 1)
  • (SMS an „Hallo“, 0)
  • (Zeilenfeld, 3)
  • (Feld <b>, 1)
  • (Text "an", 0)
  • (Text ".", 0)

Es gibt viele Nutzer dieser Datenstruktur: APIs für Barrierefreiheit, und Geometrie-APIs wie getClientRects, und contenteditable. Jede App hat unterschiedliche Anforderungen. Diese Komponenten greifen über einen Convenience-Cursor auf die flache Datenstruktur zu.

Den Cursor hat APIs wie MoveToNext, MoveToNextLine und CursorForChildren. Diese Cursordarstellung ist aus mehreren Gründen sehr leistungsfähig für Textinhalte:

  • Die Iteration in der Reihenfolge der Tiefensuche geht sehr schnell. Diese Methode wird sehr oft verwendet, weil sie den Caret-Bewegungen ähnelt. Da es sich um eine flache Liste handelt, wird bei der Tiefensuche nur das Array-Offset erhöht, schnelle Iterationen und Speicherlokalität ermöglichen.
  • Sie ermöglicht eine breit angelegte Suche, was beispielsweise erforderlich ist, wenn den Hintergrund von Linien- und Inline-Boxen bemalen.
  • Wenn du die Anzahl der Nachkommen kennst, kannst du schnell zum nächsten Geschwisterteil wechseln (Erhöhen Sie einfach das Array-Offset um diese Zahl).

Immobilienbäume

Das DOM ist eine Baumstruktur aus Elementen (plus Textknoten) und CSS kann verschiedene Stile zu Elementen hinzu.

Dies wird auf vier Arten angezeigt:

  • Layout:Eingaben in den Algorithmus für die Layouteinschränkung.
  • Paint:Hier erfahren Sie, wie das Element gezeichnet und gerastert wird. (aber nicht für Nachfolgerelemente).
  • Visuell: Raster-/Zeicheneffekte, die auf die DOM-Unterstruktur angewendet wurden wie Transformationen, Filter und Clipping.
  • Scrollen:achsenorientierte und abgerundete Ecke zum Beschneiden und Scrollen der enthaltenen Unterstruktur.

Eigenschaftsbäume sind Datenstrukturen, die erklären, wie visuelle und Scrolleffekte auf DOM-Elemente angewendet werden. Sie bieten die Möglichkeit, Fragen zu beantworten wie: Wo, ein bestimmtes DOM-Element, Layoutgröße und -position? Und: Welche Reihenfolge von GPU-Vorgängen sollten verwendet werden, um visuelle und Scroll-Effekte anzuwenden?

Visuelle und Scroll-Effekte im Web sind in ihrer vollen Pracht sehr kompliziert. Das Wichtigste bei Property-Bäumen ist es, diese Komplexität in einer einzigen Datenstruktur zusammenfassen, die ihre Struktur und Bedeutung genau abbildet, während gleichzeitig der Rest der Komplexität von DOM und CSS reduziert wird. Dadurch können wir Algorithmen für Compositing und Scrollen viel zuverlässiger implementieren. Wichtig ist insbesondere:

  • Potenziell fehleranfällige Geometrie und andere Berechnungen an einem zentralen Ort gespeichert werden.
  • Komplexität der Erstellung und Aktualisierung von Immobilienbäumen in eine Rendering-Pipeline-Phase unterteilt.
  • Es ist viel einfacher und schneller, Eigenschaftsbäume an verschiedene Threads und Prozesse zu senden als den vollständigen DOM-Status. sodass sie für viele Anwendungsfälle eingesetzt werden können.
  • Je mehr Anwendungsfälle es gibt, desto mehr Vorteile können wir mit aufgebautem Geometrie-Caching erzielen, da sie die Funktionen der anderen Caches.

RenderingNG verwendet Eigenschaftsbäume für viele Zwecke, unter anderem für:

  • Komposition von Farbe trennen und vom Hauptthread trennen
  • Ermitteln einer optimalen Compositing-/Draw-Strategie.
  • Messen IntersectionObserver Geometrie.
  • Vermeiden Sie die Arbeit mit nicht sichtbaren Elementen und GPU-Texturkacheln.
  • Paint und Raster werden effizient und genau entwertet.
  • Messen Layout Shift und Largest Contentful Paint in den Core Web Vitals.

Jedes Webdokument verfügt über vier separate Eigenschaftenstrukturen: Transformieren, Abschneiden, Effekt und Scrollen.(*) Der Transformationsbaum repräsentiert CSS-Transformationen und das Scrollen. (Eine Scroll-Transformation wird als 2D-Transformationsmatrix dargestellt.) Der Clip-Baum steht für Clips mit Überlauf. Die Effektstruktur stellt alle anderen visuellen Effekte dar: Deckkraft, Filter, Masken, Mischmodi und andere Arten von Clips, etwa "clip-path", Der Scroll-Baum stellt Informationen zum Scrollen, wie zum Beispiel das Scrollen verketten. um im Compositor-Thread zu scrollen. Jeder Knoten in einer Eigenschaftsstruktur stellt einen Scroll- oder visuellen Effekt dar, der von einem DOM-Element angewendet wird. Hat es mehrere Auswirkungen, kann es in jedem Baum für dasselbe Element mehr als einen Eigenschaftsbaumknoten geben.

Die Topologie der einzelnen Bäume ist wie eine dünnbesetzte Darstellung des DOM. Wenn es z. B. drei DOM-Elemente mit Überlauf-Clips gibt, gibt es drei Clipbaumknoten, und die Struktur des Clip-Baums die Beziehung des Containers zwischen den Überlauf-Clips. Es gibt auch Verbindungen zwischen den Bäumen. Diese Links geben die relative DOM-Hierarchie an, und damit auch die Reihenfolge der Anwendung, der Knoten. Wenn beispielsweise eine Transformation bei einem DOM-Element unter einem anderen DOM-Element mit einem Filter liegt, wird die Transformation natürlich vor dem Filter angewendet.

Jedes DOM-Element hat einen Eigenschaftsstrukturstatus, ein 4-Tupel (Transformieren, Abschneiden, Effekt, Scrollen) der den nächstgelegenen Ancestor-Clip angibt. Transformations- und Effektstrukturknoten, die auf dieses Element angewendet werden. Das ist sehr praktisch, da wir anhand dieser Informationen genau die Liste der Clips kennen, Transformationen und Effekte, die auf dieses Element angewendet werden, und in welcher Reihenfolge. So wissen wir, wo es sich auf dem Bildschirm befindet und wie es gezeichnet werden soll.

Beispiel

(Quelle)

<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>

Für das vorherige Beispiel (das sich geringfügig von dem in der Einleitung unterscheidet) Dies sind die wichtigsten Elemente der generierten Eigenschaftsbäume:

Ein Beispiel für die verschiedenen Elemente in der Eigenschaftsstruktur.

Listen und Farbblöcke anzeigen

Ein Anzeigeelement enthält Zeichenbefehle auf niedriger Ebene (siehe hier) die mit verschiedenen Skia. Anzeigeelemente sind in der Regel einfach und erfordern nur wenige Zeichenbefehle, z. B. das Zeichnen eines Rahmens oder eines Hintergrunds. Der Paint Tree Walk durchläuft die Layoutstruktur und die zugehörigen Fragmente gemäß der CSS-Painting-Reihenfolge. um eine Liste mit Anzeigeelementen zu erstellen.

Beispiel:

Ein blaues Feld mit den Worten „Hallo Welt“ innerhalb eines grünen Rechtecks.

<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>

Dieser HTML- und CSS-Code erzeugt die folgende Anzeigeliste: wobei jede Zelle ein Anzeigeelement ist:

Hintergrund der Ansicht #blue (Hintergrund) #green (Hintergrund) #green Inline-Text
drawRect mit der Größe 800 × 600 und der Farbe Weiß. drawRect mit der Größe 100 × 100 an Position 0,0 und der Farbe Blau. drawRect mit der Größe 80 × 18 an Position 8,8 und der Farbe Grün. drawTextBlob mit Position 8,8 und dem Text „Hello world“.

Die Liste der Anzeigeelemente ist von hinten nach vorne geordnet. Im obigen Beispiel befindet sich das grüne div-Element in der DOM-Reihenfolge vor dem blauen div-Element, Bei der CSS-Paint-Reihenfolge muss das blaue div-Element mit negativem Z-Index vor (Schritt 3) dem grünen div-Element (Schritt 4.1) Anzeigeelemente entsprechen in etwa den atomaren Schritten der CSS-Spezifikation für die Farbreihenfolge. Ein einzelnes DOM-Element kann zu mehreren Anzeigeelementen führen, wie zum Beispiel, wie #green ein Anzeigeelement für den Hintergrund und ein anderes Anzeigeelement für den Inline-Text hat. Dieser Detaillierungsgrad ist wichtig, um die gesamte Komplexität der CSS-Paintorder-Spezifikation abzubilden. wie z. B. durch einen negativen Rand erstellte Verschränkung:

Ein grünes Rechteck mit einem teilweise überlagerten grauen Feld und den Worten „Hallo Welt“.

<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>

Daraufhin wird die folgende Anzeigeliste angezeigt, wobei jede Zelle ein Anzeigeelement ist:

Hintergrund der Ansicht #green (Hintergrund) #gray (Hintergrund) #green Inline-Text
drawRect mit der Größe 800 × 600 und der Farbe Weiß. drawRect mit der Größe 80 × 18 an Position 8,8 und der Farbe Grün. drawRect mit den Maßen 35 × 20 an Position 8,16 und grau. drawTextBlob mit Position 8,8 und dem Text „Hello world“.

Die Liste der Anzeigeelemente wird gespeichert und bei späteren Aktualisierungen wiederverwendet. Wenn ein Layoutobjekt beim Paint Tree Walk nicht geändert wurde, Die angezeigten Elemente wurden aus der vorherigen Liste kopiert. Eine weitere Optimierung stützt sich auf eine Eigenschaft der CSS-Paintorder-Spezifikation: werden in Stapelkontexten atomar dargestellt. Wenn sich innerhalb eines Stapelkontexts kein Layoutobjekt geändert hat, Beim Paint Tree Walk wird der Stapelkontext übersprungen. und kopiert die gesamte Reihenfolge der Anzeigeelemente aus der vorherigen Liste.

Der aktuelle Zustand der Immobilienstruktur wird während des Paint Trees beibehalten. und die Liste der Anzeigeelemente ist in Blöcke unterteilt. von Anzeigeelementen, die den gleichen Status der Eigenschaftsstruktur aufweisen. Dies wird im folgenden Beispiel veranschaulicht:

Ein rosa Kasten mit einem orangefarbenen, geneigten Kasten.

<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>

Daraufhin wird die folgende Anzeigeliste angezeigt, wobei jede Zelle ein Anzeigeelement ist:

Hintergrund der Ansicht #scroll (Hintergrund) #scroll Inline-Text #orange (Hintergrund) #orange Inline-Text
drawRect mit der Größe 800 × 600 und der Farbe Weiß. drawRect mit der Größe 100 × 100 an Position 0,0 und der Farbe Pink. drawTextBlob mit Position 0,0 und dem Text „Hello world“. drawRect mit der Größe 75 × 200 an Position 0,0 und der Farbe Orange. drawTextBlob mit Position 0,0 und dem Text „I'm Falling“.

Die Transformationseigenschaftsstruktur und die Paint-Blöcke wären dann (zur Übersichtlichkeit vereinfacht):

Ein Bild der vorhergehenden Tabelle: die ersten beiden Zellen in Block 1, die dritte in Block 2 und die letzten beiden Zellen in Block 3.

Die geordnete Liste der Farbblöcke Gruppen von Anzeigeelementen und dem Status der Eigenschaftsstruktur, sind die Eingaben für den Layerize-Schritt der Rendering-Pipeline. Die gesamte Liste der Farbblöcke könnte zu einer einzigen zusammengesetzten Ebene zusammengeführt und zusammen gerastert werden. Allerdings wäre dafür jedes Mal eine aufwendige Rasterung erforderlich, wenn der Nutzer scrollt. Für jeden Farbblock könnte eine zusammengesetzte Ebene erstellt werden. und einzeln gerastert werden, um eine erneute Rasterung zu vermeiden. Dadurch würde jedoch schnell der GPU-Arbeitsspeicher erschöpft sein. Bei diesem Schritt müssen Kompromisse zwischen dem GPU-Arbeitsspeicher und der Reduzierung der Kosten eingegangen werden, wenn sich etwas ändert. Ein guter allgemeiner Ansatz besteht darin, Blöcke standardmäßig zusammenzuführen, und keine Paint-Chunks mit Eigenschaftsstrukturstatus zusammenführen, die sich im Compositor-Thread wahrscheinlich ändern. z. B. durch Scrollen durch Compositor-Thread oder Compositor-Thread-Transformationsanimationen.

Das obige Beispiel sollte idealerweise zwei zusammengesetzte Ebenen erzeugen:

  • Eine zusammengesetzte Ebene im Format 800 x 600, die die Zeichenbefehle enthält: <ph type="x-smartling-placeholder">
      </ph>
    1. drawRect mit der Größe 800 x 600 und der Farbe Weiß
    2. drawRect mit der Größe 100 × 100 an Position 0,0 und der Farbe Pink
  • Eine zusammengesetzte Ebene im Format 144 x 224, die die Zeichenbefehle enthält: <ph type="x-smartling-placeholder">
      </ph>
    1. drawTextBlob mit Position 0,0 und dem Text „Hello world“
    2. übersetzen 0,18
    3. rotateZ(25deg)
    4. drawRect mit der Größe 75 × 200 an Position 0,0 und der Farbe Orange
    5. drawTextBlob mit Position 0,0 und dem Text „I'm Falling“ (Ich fällt fallen)

Wenn der Nutzer nach #scroll scrollt, wird die zweite zusammengesetzte Ebene verschoben, aber es ist keine Rasterung erforderlich.

Für das Beispiel aus dem vorherigen Abschnitt über Immobilienbäume. gibt es sechs Farbblöcke. Zusammen mit den Status der Eigenschaftsstruktur (Transformieren, Abschneiden, Effekt, Scrollen) sind sie:

  • Dokumenthintergrund: Scrollen von Dokumenten, Dokumentclip, Stamm, Scrollen von Dokumenten
  • Horizontale, vertikale und Scroll-Ecke für div (drei separate Paint-Blöcke): Scrollen von Dokumenten, Dokumentclip, #one Weichzeichnen, Scrollen von Dokumenten.
  • iFrame #one: #one drehen, Scroll-Clip mit Überlauf, #one Weichzeichnen, div-Scrollen
  • iFrame #two: #two Skalierung, Dokumentclip, Stamm, Dokumentscrollen.

Compositor-Frames: Oberflächen, Renderingflächen und GPU-Texturkacheln

Der Browser und die Rendering-Prozesse verwalten die Rasterung von Inhalten, und stellen Sie dann Compositor-Frames zur Präsentation an den Viz-Prozess bereit. Compositor-Frames zeigen, wie gerasterte Inhalte zusammengefügt werden und effizient mit der GPU zeichnen.

Ansichten

Theoretisch Ein Renderprozess oder ein Browserprozess-Compositor könnte Pixel rastern. die gesamte Größe des Renderer-Darstellungsbereichs in eine einzelne Textur zu übertragen und diese Textur an Viz zu übermitteln. Für die Anzeige müsste der Compositor lediglich die Pixel aus dieser Textur an die entsprechende Position im Frame-Zwischenspeicher. (z. B. den Bildschirm). Möchte dieser Compositor jedoch auch ein einzelnes Pixel, müsste der gesamte Darstellungsbereich neu gerastert und eine neue Textur an Viz gesendet werden.

Stattdessen wird der Darstellungsbereich in Kacheln unterteilt. Eine separate GPU-Texturkachel unterstützt jede Kachel mit den Rasterpixeln für einen Teil des Darstellungsbereichs. Der Renderer kann dann einzelne Kacheln oder sogar ändern Sie einfach die Position der vorhandenen Kacheln auf dem Bildschirm. Wenn Sie z. B. auf einer Website scrollen, änderte sich die Position vorhandener Kacheln nur gelegentlich nach oben. müsste eine neue Kachel für die Inhalte weiter unten auf der Seite gerastert werden.

<ph type="x-smartling-placeholder">
</ph> Vier Kacheln.
Dieses Bild zeigt ein Bild eines sonnigen Tages mit vier Kacheln. Beim Scrollen wird eine fünfte Kachel angezeigt. Eine der Kacheln hat zufällig nur eine Farbe (himmelblau), Ein Video und ein iFrame darüber.

Quads und Oberflächen

GPU-Texturkacheln sind eine spezielle Art von Quad, ein ausgefallener Name für eine Texturkategorie. Ein Quad identifiziert die Eingabetextur und gibt an, wie sie transformiert und visuelle Effekte angewendet werden soll. Zum Beispiel verfügen reguläre Inhaltskacheln über eine Transformation, die ihre x- und y-Position im Kachelraster angibt.

GPU-Texturkacheln

Diese gerasterten Kacheln werden in einen Rendering-Pass eingebunden, also eine Liste von Quadraten. Die Rendering-Karte enthält keine Pixelinformationen. Stattdessen enthält es Anweisungen, wo und wie jedes Quad gezeichnet werden soll, um die gewünschte Pixelausgabe zu erzeugen. Für jede GPU-Texturkachel gibt es ein Draw Quad. Der Display-Zusammengesetzte muss einfach die Liste der Quad-Elemente durchlaufen, mit den angegebenen visuellen Effekten, um die gewünschte Pixelausgabe für den Renderingpass zu generieren. Das Zusammenstellen von Zeichnungsquadern für einen Rendering-Pass kann auf der GPU effizient durchgeführt werden. da die zulässigen visuellen Effekte sorgfältig ausgewählt werden, die direkt GPU-Features zugeordnet sind.

Neben den gerasterten Kacheln gibt es noch weitere Arten von Zeichenquadraten. Es gibt beispielsweise einfarbige Zeichenquadrate, die überhaupt keine Textur haben. oder Textur-Zeichenquadrate für nicht-kachelbasierte Texturen wie Video oder Canvas.

Es ist auch möglich, dass ein zusammengesetzter Frame einen weiteren zusammengesetzten Frame einbetten kann. Der Browser-Compositor erstellt beispielsweise einen Compositor-Frame mit der Browser-Benutzeroberfläche. und ein leeres Rechteck, in das der Render-Compositor-Inhalt eingebettet ist. Ein weiteres Beispiel sind Website-isolierte iFrames. Diese Einbettung erfolgt mithilfe von Oberflächen.

Wenn ein zusammengesetzter Frame einen zusammengesetzten Frame einreicht, wird eine Kennung hinzugefügt. auch Oberflächen-ID genannt. Dadurch können andere zusammengesetzte Frames sie durch Verweis einbetten. Der neueste zusammengesetzte Frame, der mit einer bestimmten Oberflächen-ID eingereicht wurde, wird von Viz gespeichert. Ein anderer zusammengesetzter Frame kann später über ein Oberflächen-Zeichen-Quad darauf verweisen. sodass Viz weiß, was zu zeichnen ist. Beachten Sie, dass Flächen-Zeichen-Quadrate nur Oberflächen-IDs und keine Texturen enthalten.

Render-Zwischenfälle

Einige visuelle Effekte, z. B. viele Filter oder erweiterte Mischmodi, erfordern, dass zwei oder mehr Quadrate auf eine Zwischentextur gezogen werden. Dann wird die Zwischentextur in einen Zielpuffer auf der GPU (oder möglicherweise eine andere Zwischentextur) gezeichnet. den visuellen Effekt anwenden. Um dies zu ermöglichen, enthält ein zusammengesetzter Frame eigentlich eine Liste von Rendering-Durchgängen. Es gibt immer einen Root-Rendering-Pass, die zuletzt gezeichnet wird und deren Ziel dem Frame-Zwischenspeicher entspricht, und es gibt noch mehr.

Die Möglichkeit mehrerer Rendering-Pässe erklärt den Namen „render pass“. Jede Karte / jedes Ticket muss in mehreren „Karten/Tickets“ nacheinander auf der GPU ausgeführt werden. Ein einzelner Durchlauf kann dagegen mit einer einzigen massiv parallelen GPU-Berechnung abgeschlossen werden.

Aggregation

Mehrere zusammengesetzte Frames werden an Viz gesendet, und müssen zusammen zum Bildschirm gezogen werden. Dies wird durch eine Aggregationsphase erreicht, die sie in eine einzige, aggregierten Compositor-Frames. Die Aggregation ersetzt Oberflächenzeichnungs-Quads durch die von ihnen angegebenen Compositor-Frames. Es bietet auch die Möglichkeit, unnötige Zwischentexturen oder nicht sichtbare Inhalte zu entfernen. Häufig ist z. B. der Compositor-Frame für einen Website-isolierten iFrame benötigt keine eigene Zwischentextur, und kann über entsprechende Zeichenquadrate direkt in den Frame-Zwischenspeicher gezogen werden. In der Aggregationsphase werden solche Optimierungen und wendet sie basierend auf globalem Wissen an, das für einzelne Rendering-Kompositoren nicht zugänglich ist.

Beispiel

Hier sind die zusammengesetzten Frames, die das Beispiel vom Anfang des diesem Beitrag.

  • foo.com/index.html-Oberfläche: id=0 <ph type="x-smartling-placeholder">
      </ph>
    • Renderübergabe 0:Bis zur Ausgabe zeichnen.
      • Render-Pass-Zeichnungs-Quad: Mit 3-Pixel-Weichzeichnen zeichnen und in Rendering-Pass 0 fixieren.
        • Render-Pass 1: <ph type="x-smartling-placeholder">
            </ph>
          • Zeichnen Sie Vierecke für Kachelinhalte von #one iFrame mit jeweils X- und Y-Positionen.
      • Flächendiagramm mit der ID 2, mit der Transformation „Scale“ und „Translate“.
  • Oberfläche der Browseroberfläche: ID=1 <ph type="x-smartling-placeholder">
      </ph>
    • Renderübergabe 0:Bis zur Ausgabe zeichnen.
      • Vierecke für Browser-Benutzeroberfläche zeichnen (auch gekachelt)
  • bar.com/index.html-Oberfläche: ID=2 <ph type="x-smartling-placeholder">
      </ph>
    • Renderübergabe 0:Bis zur Ausgabe zeichnen.
      • Zeichnen Sie Vierecke für den Inhalt von #two iFrame mit jeweils X- und Y-Positionen.

Illustrationen von Una Kravets