מבני נתונים מרכזיים ב-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

בואו נבחן את מבני הנתונים העיקריים, שהם קלט ופלט בצינור עיבוד הנתונים לעיבוד.

מבני הנתונים הבאים הם:

  • עצי מסגרת מורכבים מצמתים מקומיים ומרוחקים, שמייצגים את מסמכי האינטרנט שבהם נמצאים תהליכי העיבוד ואיזה כלי של רינדור בלינקים.
  • עץ המקטעים שאינם ניתנים לשינוי מייצג את הפלט של (והקלט) של האלגוריתם של אילוצי הפריסה.
  • עצי הנכס מייצגים את היררכיות הטרנספורמציה, הקליפ, האפקט והגלילה של מסמך אינטרנט. המערכת משתמשת בהם לאורך צינור עיבוד הנתונים.
  • רשימות תצוגה ומקטעי צבע הם הקלט לאלגוריתמים של רשת המדיה ושל יצירת השכבות.
  • פריימים של קומפוזיטור כוללים משטחים, משטחים לעיבוד ומשבצות טקסטורה של 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 עשוי לבצע רינדור של מסגרת ממקורות שונים בתהליך רינדור שונה ממסגרת ההורה שלו.

בקוד לדוגמה, קיימות שלוש פריימים בסך הכול:

מסגרת הורה foo.com, שמכילה שני iframes.

באמצעות הבידוד של אתרים, Chromium משתמש בשני תהליכי רינדור כדי לעבד את דף האינטרנט הזה. לכל תהליך עיבוד יש ייצוג משלו של עץ המסגרות של אותו דף אינטרנט:

שני עצי מסגרת שמייצגים את שני תהליכי העיבוד.

מסגרת שמעובדת בתהליך אחר מיוצגת כמסגרת מרוחקת. מסגרת מרוחקת מכילה את המידע המינימלי שדרוש כדי לשמש כ-placeholder ברינדור, כמו המידות שלה, לדוגמה. אחרת, המסגרת המרוחקת לא מכילה מידע שנדרש לעיבוד התוכן שלה בפועל.

לעומת זאת, מסגרת מקומית מייצגת מסגרת שעוברת דרך צינור עיבוד הנתונים הסטנדרטי לעיבוד. הפריים המקומי מכיל את כל המידע שצריך כדי להפוך את הנתונים של אותה פריים (כמו עץ ה-DOM ונתוני הסגנון) למשהו שאפשר לעבד ולהציג.

צינור עיבוד הנתונים פועל על רמת הפירוט של מקטע עץ מסגרת מקומי. דוגמה מורכבת יותר שבה המסגרת הראשית היא foo.com:

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

וגם תת-המסגרת הבאה: bar.com:

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

למרות שעדיין יש רק שני כלי רינדור, יש עכשיו שלושה מקטעים של עץ המסגרת המקומי, אחד מהם בתהליך העיבוד של foo.com ואחד בתהליך העיבוד של bar.com:

ייצוג של שני העיבודים ושלושה קטעי עץ של פריימים.

כדי ליצור מסגרת קומפוזבילית אחת לדף האינטרנט, Viiz מבקש בו-זמנית מסגרת קומפוזיציה ממסגרת הבסיס של כל אחד משלושת העצים של המסגרת המקומית, ואז צובר אותם. כדאי לעיין גם בקטע 'מסגרות של קומפוזבילי'.

הפריים הראשי foo.com ותת-המסגרת foo.com/other-page הם חלק מאותו עץ פריימים שמעובדות באותו תהליך. עם זאת, לשתי הפריימים עדיין יש מחזורי חיים של מסמכים עצמאיים כי הם חלק מקטעים שונים של עץ מסגרת מקומי. לכן אין אפשרות ליצור מסגרת קומפוזיציה אחת עבור שניהם בעדכון אחד. בתהליך העיבוד אין מספיק מידע כדי להרכיב את מסגרת הקומפוזיציה שנוצרה עבור foo.com/other-page ישירות למסגרת הקומפוזיציה של הפריים הראשי foo.com. לדוגמה, מסגרת ההורה bar.com שלא נמצאת בתהליך עשויה להשפיע על התצוגה של ה-iframe foo.com/other-url על ידי טרנספורמציה של ה-iframe באמצעות CSS או הסתרה של חלקים מה-iframe עם רכיבים אחרים ב-DOM שלו.

Waterfall עדכון הנכסים החזותי

מאפיינים חזותיים כמו גורם קנה המידה של המכשיר וגודל אזור התצוגה משפיעים על הפלט המעובד, וצריך לסנכרן אותם בין המקטעים של עץ המסגרת המקומי. הרמה הבסיסית (root) של כל מקטע של עץ מסגרת מקומי כוללת אובייקט ווידג'ט שמשויך אליו. עדכוני מאפיינים חזותיים עוברים לווידג'ט של המסגרת הראשית לפני שהם מופצים לשאר הווידג'טים מלמעלה למטה.

לדוגמה, כשהגודל של אזור התצוגה משתנה:

תרשים של התהליך המוסבר בטקסט הקודם.

התהליך הזה לא מיידי, ולכן המאפיינים החזותיים המשוכפלים כוללים גם אסימון סנכרון. הרכיב Viz משתמש באסימון הסנכרון הזה כדי להמתין שכל המקטעים של עץ המסגרת המקומי ישלחו מסגרת קומפוזיציה עם אסימון הסנכרון הנוכחי. התהליך הזה מונע שילוב של פריימים של קומפוזבילי עם מאפיינים ויזואליים שונים.

עץ המקטעים שלא ניתן לשינוי

עץ המקטעים שלא ניתן לשינוי הוא הפלט של שלב הפריסה של צינור עיבוד הנתונים לעיבוד. הוא מייצג את המיקום והגודל של כל הרכיבים בדף (בלי לבצע שינויים).

ייצוג של המקטעים בכל עץ, כשמקטע אחד מסומן כדרוש פריסה.

כל מקטע מייצג חלק של רכיב DOM. בדרך כלל יש רק מקטע אחד לכל רכיב, אבל יכול להיות שיהיו עוד מקטעים אם הם מפוצלים בין דפים שונים בזמן ההדפסה, או עמודות בהקשר של כמה עמודות.

אחרי הפריסה, כל מקטע הופך לבלתי ניתן לשינוי ולא משתנה שוב. חשוב לציין גם כמה הגבלות נוספות. מה אנחנו לא עושים:

  • לאפשר כל הפניה מסוג 'למעלה' בעץ. (לילדים לא יכול להיות מצביע אל ההורה שלהם).
  • "להוציא" נתונים במורד העץ (ילד קורא מידע רק מהילדים שלו, ולא מההורים שלו).

ההגבלות האלה מאפשרות לנו לעשות שימוש חוזר במקטע בפריסה הבאה. בלי ההגבלות האלה, לעיתים קרובות נצטרך לייצר מחדש את העץ כולו, וזה יקר.

רוב הפריסות הן בדרך כלל עדכונים מצטברים. לדוגמה, אפליקציית אינטרנט שמעדכנת חלק קטן מממשק המשתמש בתגובה למשתמש שלוחץ על אלמנט. באופן אידיאלי, הפריסה צריכה לפעול רק באופן יחסי למה שהשתנה בפועל במסך. נוכל לעשות זאת על ידי שימוש חוזר בכמה שיותר חלקים מהעץ הקודם. כלומר (בדרך כלל) אנחנו צריכים לבנות מחדש את עמוד השדרה של העץ.

בעתיד, העיצוב הבלתי משתנה הזה יוכל לאפשר לנו לעשות דברים מעניינים, כמו העברת עץ המקטע שלא ניתן לשינוי דרך גבולות השרשור במקרה הצורך (כדי לבצע את השלבים הבאים בשרשור אחר), ליצור מספר עצים לאנימציה של פריסה חלקה, או לבצע פריסות ספקולטיביות מקבילות. הוא גם נותן לנו את הפוטנציאל של פריסת ריבוי שרשורים עצמה.

פריטי מקטע מוטבעים

בתוכן מוטבע (הטקסט המעוצב בעיקר) יש ייצוג קצת שונה. במקום מבנה עץ עם תיבות ומצביעים, אנחנו מייצגים תוכן מוטבע ברשימה שטוחה שמייצגת את העץ. היתרון העיקרי הוא שהייצוג של רשימה שטוחה לשורות הוא מהיר, הוא שימושי לבדיקת מבני נתונים מוטבעים או לשליחת שאילתות לגביו, והוא יעיל בזיכרון. זה חשוב מאוד לביצועי הרינדור באינטרנט, כי עיבוד הטקסט הוא מורכב מאוד, והוא יכול להפוך בקלות לחלק האיטי ביותר בצינור עיבוד הנתונים, אלא אם מתבצעת בו אופטימיזציה גבוהה.

הרשימה השטוחה נוצרת לכל הקשר עיצוב מוטבע, לפי סדר של חיפוש בעומק ראש של עץ המשנה לפריסה המוטבע. כל ערך ברשימה הוא מספר (אובייקט, מספר צאצאים). לדוגמה, נבחן את ה-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)
  • (תיבה <span>, 1)
  • (יש להזין "שלום", 0)
  • (תיבת שורה, 3)
  • (תיבה <b>, 1)
  • (הטקסט "שם", 0)
  • (טקסט ".", 0)

קיימים צרכנים רבים של מבנה הנתונים הזה: ממשקי API לנגישות וממשקי API גיאומטריים כמו getClientRects ו-contenteditable. לכל אחד מהם יש דרישות שונות. הרכיבים האלה ניגשים למבנה הנתונים השטוח באמצעות סמן נוחות.

לאתר הסמן יש ממשקי API כמו MoveToNext, MoveToNextLine ו-CursorForChildren. הייצוג הזה של הסמן חזק מאוד לתוכן של טקסט, מכמה סיבות:

  • הצגת האיטרציות לפי סדר החיפוש הראשון עולה מאוד, והיא מהירה מאוד. ומשתמשים בו לעיתים קרובות כי הוא דומה לתנועות סמן טקסט. מכיוון שזו רשימה שטוחה, חיפוש מבוסס עומק רק מגדיל את ההיסט של המערך, ומספק איטרציות מהירות וסביבת הזיכרון.
  • הוא מספק חיפוש עם עדיפות לרוחב, שנדרש כאשר, למשל, צובעים את הרקע של קו ותיבות בתוך השורה.
  • כשיודעים כמה צאצאים, אפשר לעבור במהירות לאח הבא (פשוט להגדיל את ההיסט של המערך במספר הזה).

עץ הנכסים

ה-DOM הוא עץ של רכיבים (וגם צומתי טקסט), ו-CSS יכול להחיל סגנונות שונים על רכיבים.

יש ארבע דרכים לכך:

  • פריסה: ערכי הקלט לאלגוריתם של מגבלת הפריסה.
  • צבע: איך לצבוע וליצור רשת נקודות של הרכיב (אבל לא את הצאצאים שלו).
  • ויזואלי: אפקטים של רסטר או שרטוט שהוחלו על עץ המשנה DOM, כמו טרנספורמציות, פילטרים וחיתוך.
  • גלילה: החלקה וגלילה של פינות המשנה ביישור לציר וגלילה של עץ המשנה.

עצי מאפיינים הם מבני נתונים שמסבירים איך אפקטים חזותיים ואפקטים גלילה חלים על רכיבי DOM. הם מספקים את האמצעים למענה על שאלות, למשל: איפה, ביחס למסך, רכיב DOM נתון, בהתחשב בגודל הפריסה ובמיקום שלו? בנוסף: באיזה רצף של פעולות GPU יש להשתמש כדי להחיל אפקטים חזותיים ואפקטים של גלילה?

אפקטים ויזואליים ואפקטים נגללים באינטרנט מורכבים מאוד ואפשרו להם תהילה מלאה. הדבר החשוב ביותר שעצים של מאפיינים הם לעשות הוא לתרגם את המורכבות הזו למבנה נתונים יחיד שמייצג במדויק את המבנה והמשמעות שלהם, ובמקביל להסיר את שאר המורכבות של ה-DOM וה-CSS. כך אנחנו יכולים להטמיע אלגוריתמים להרכבת וגלילה בביטחון רב יותר. הקפידו במיוחד על הדברים הבאים:

  • אפשר לרכז במקום אחד גיאומטריה שעלולה להיות מועדת לשגיאות וחישובים אחרים.
  • המורכבות של הבנייה והעדכון של עץ הנכסים מבודדת לשלב אחד של צינור עיבוד הנתונים.
  • הרבה יותר קל ומהיר לשלוח עצי מאפיינים לשרשורים ותהליכים שונים מאשר למצב DOM מלא, וכך אפשר להשתמש בהם בתרחישים לדוגמה רבים.
  • ככל שיהיו יותר תרחישים לדוגמה, כך נוכל להשיג יותר ניצחונות משמירה במטמון בגיאומטריה מראש, כי הם יוכלו להשתמש מחדש במטמון של כל אחד מהם.

בתהליך עיבוד התמונה (RenderingNG) משתמשים בעצי מאפיין למטרות רבות, כולל:

לכל מסמך אינטרנט יש ארבעה עצי מאפיין נפרדים: טרנספורמציה, חיתוך, אפקט וגלילה.(*) עץ הטרנספורמציה מייצג המרות וגלילה ב-CSS. (טרנספורמציה של גלילה מיוצגת כמטריצת טרנספורמציה דו-ממדית). עץ הקליפים מייצג קליפים נוספים. עץ האפקטים מייצג את כל האפקטים החזותיים האחרים: אטימוּת, פילטרים, מסכות, מצבי שילוב וסוגים אחרים של קליפים כמו קליפ. עץ הגלילה מייצג מידע על גלילה, למשל איך גלילות משורשרות יחד. הוא נדרש כדי לבצע גלילה בשרשור של המחבר. כל צומת בעץ מאפיינים מייצג גלילה או אפקט חזותי שהוחל על ידי רכיב DOM. אם במקרה יש מספר השפעות, יכול להיות שבכל עץ יהיה יותר מצומת אחד של עץ הנכס לאותו רכיב.

הטופולוגיה של כל עץ דומה לייצוג דל של ה-DOM. לדוגמה, אם יש שלושה רכיבי DOM עם קליפים נוספים, יהיו שלושה צמתים של עץ קליפ, והמבנה של עץ הקליפ יהיה עוקב אחרי קשר הבלוקים המכיל בין הקליפים לאפשרויות נוספות. יש גם קישורים בין העצים. הקישורים האלה מציינים את היררכיית ה-DOM היחסית, ומכאן גם את סדר היישום של הצמתים. לדוגמה, אם טרנספורמציה ברכיב DOM נמצאת מתחת לרכיב DOM אחר עם מסנן, אז כמובן שהטרנספורמציה תחול לפני המסנן.

לכל רכיב DOM יש מצב עץ מאפיינים (property) שהוא מצב 4-tuple (טרנספורמציה, קליפ, אפקט, גלילה) שמציין את קליפ ישות האב הקרוב ביותר, טרנספורמציה וצומתי עץ משפיעים על הרכיב הזה. זה מאוד נוח, כי בעזרת המידע הזה אנחנו יודעים בדיוק אילו קליפים, שינויים ואפקטים רלוונטיים לאלמנט הזה, ובאיזה סדר. התכונה הזו מאפשרת לנו לדעת איפה הוא נמצא על המסך ואיך לצייר אותו.

דוגמה

(מקור)

<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 כדי ליצור רשימת פריטים לתצוגה.

למשל:

תיבה כחולה, עם המילים &#39;שלום עולם&#39; בתוך מלבן ירוק.

<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
drawRect בגודל 800x600 ובצבע לבן. drawRect בגודל 100x100 במיקום 0,0 ובצבע כחול. drawRect בגודל 80x18 במיקום 8 ו-8 ובצבע ירוק. drawTextBlob במיקום 8,8 והטקסט "שלום עולם".

רשימת הפריטים בתצוגה מסודרת משני הכיוונים. בדוגמה שלמעלה, ה-div הירוק מופיע לפני ה-div הכחול בסדר DOM, אבל סדר הציור של CSS מחייב שה-div הכחול z-index בצבע כחול לפני (שלב 3) ה-div הירוק (שלב 4.1). פריטים בתצוגה תואמים בקירוב לשלבים אטומיים במפרט הזמנת הצבע של שירות ה-CSS. רכיב DOM יחיד עשוי לגרום למספר פריטי תצוגה, למשל, האופן שבו #green . יש פריט תצוגה בשביל הרקע ופריט תצוגה אחר עבור הטקסט המוטבע. רמת הפירוט הזו חשובה לייצוג המורכבות המלאה של מפרט הזמנת הצבע ב-CSS, למשל שילוב התוכן שנוצר על ידי שוליים שליליים:

מלבן ירוק עם תיבה אפורה בשכבת-על בחלקה והמילים &#39;שלום עולם&#39;.

<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
drawRect בגודל 800x600 ובצבע לבן. drawRect בגודל 80x18 במיקום 8 ו-8 ובצבע ירוק. drawRect בגודל 35x20 במיקום 8,16 ובצבע אפור. drawTextBlob במיקום 8,8 והטקסט "שלום עולם".

רשימת הפריטים ברשת המדיה מאוחסנת ונעשה בה שימוש חוזר בעדכונים עתידיים. אם אובייקט פריסה לא השתנה במהלך הליכה של עץ הצבע, פריטי התצוגה שלו יועתקו מהרשימה הקודמת. אופטימיזציה נוספת מסתמכת על מאפיין של מפרט הזמנת הצבע ב-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
drawRect בגודל 800x600 ובצבע לבן. drawRect בגודל 100x100 במיקום 0.0 ובצבע ורוד. drawTextBlob במיקום 0,0 והטקסט "שלום עולם". drawRect בגודל 75x200 במיקום 0.0 ובצבע כתום. drawTextBlob במיקום 0,0 והטקסט "אני נופל".

במצב כזה, מקטעי עץ הטרנספורמציה ומקטעי הצבע יהיו (פשוטים לצורך קיצור):

תמונה של הטבלה הקודמת, שני התאים הראשונים במקטע 1, השלישי במקטע 2, שני התאים האחרונים במקטע 3.

הרשימה המסודרת של מקטעי צבע, שהן קבוצות של פריטי תצוגה ומצב עץ נכסים, הם הקלט לשלב השכבות של צינור עיבוד הנתונים. אפשר למזג את כל הרשימה של מקטעי הצבע לשכבה מורכבת אחת וליצור רסטר יחד, אבל יהיה צורך לבצע רסטרזציה יקרה בכל פעם שהמשתמש גולל. אפשר ליצור שכבה מורכבת לכל מקטעי צבע וליצור רסטר בנפרד כדי למנוע עיבוד מחדש של רסטר, אבל הפעולה הזו תגרום לניצול מהיר של הזיכרון של ה-GPU. שלב השכבות צריך לפצות על זיכרון ה-GPU והפחתת העלויות כששינויים משתנים. גישה כללית טובה היא למזג מקטעים כברירת מחדל, ולא למזג מקטעי צבע שיש להם מצבי עץ מאפיינים (property) שצפויים להשתנות בשרשור של המרכיב, למשל באמצעות גלילה ב-thread של קומפוזיטור או באנימציות טרנספורמציה של שרשור קומפוזיטור.

הדוגמה שלמעלה אמורה ליצור שתי שכבות מורכבות:

  • שכבה מורכבת בגודל 800x600 המכילה את פקודות השרטוט:
    1. drawRect בגודל 800x600 ובצבע לבן
    2. drawRect בגודל 100x100 במיקום 0.0 ובצבע ורוד
  • שכבה מורכבת בגודל 144x224, המכילה את פקודות השרטוט:
    1. drawTextBlob במיקום 0,0 והטקסט "שלום עולם"
    2. תרגום ל-0,18
    3. rotateZ(25deg)
    4. drawRect בגודל 75x200 במיקום 0.0 ובצבע כתום
    5. drawTextBlob עם מיקום 0,0 והטקסט "אני נופל"

אם המשתמש גולל ב-#scroll, השכבה המורכבת השנייה מועברת, אבל לא צריך ליצור רסטר.

בדוגמה, בקטע הקודם על עצי המאפיינים, יש שישה מקטעים של צבע. ביחד עם מצבי עץ המאפיין (טרנספורמציה, קליפ, אפקט, גלילה) הם:

  • רקע המסמך: גלילה במסמך, קליפ, שורש, גלילת מסמך.
  • פינה אופקית, אנכית וגלילה ל-div (שלוש מקטעי צבע נפרדים): גלילת מסמכים, קליפ מסמכים, טשטוש #one, גלילה במסמך.
  • iframe #one: #one סיבוב, קליפ גלילה לאפשרויות נוספות, #one טשטוש, גלילה ב-div.
  • iframe #two: קנה מידה של #two, קליפ של מסמך, בסיס, גלילה במסמך.

פריימים של קומפוזיציה: משטחים, משטחים, משטחים ומשבצות טקסטורה של GPU

תהליכי הדפדפן והעיבוד מנהלים רסטריזציה של תוכן, ואז שולחים פריימים של קומפוזיציה לתהליך Viz כדי להציג אותם במסך. פריימים של קומפוזיציה מייצגים איך לחבר תוכן שעבר רשת נקודות ולצייר אותו ביעילות באמצעות ה-GPU.

כרטיס מידע

בתיאוריה, רכיב עיבוד של תהליך רינדור או מרכיב של תהליך דפדפן יכול ליצור רסטריזציה של פיקסלים לטקסטורה אחת בגודל מלא של אזור התצוגה של כלי הרינדור, ולשלוח את הטקסטורה הזו ל-Viz. כדי להציג אותו, מרכיב התצוגה צריך להעתיק את הפיקסלים מהטקסטורה הבודדת למיקום המתאים במאגר הנתונים הזמני של המסגרת (לדוגמה, המסך). עם זאת, אם המרכיב הזה ירצו לעדכן אפילו פיקסל אחד, הוא יצטרך לרסטר מחדש את אזור התצוגה המלא ולשלוח טקסטורה חדשה ל-Viz.

במקום זאת, אזור התצוגה מחולק למשבצות. קטע נפרד של מרקם של GPU מגבה כל משבצת עם הפיקסלים שעברו עיבוד רסטר עבור חלק מאזור התצוגה. הכלי יכול לעדכן משבצות ספציפיות או אפילו לשנות את המיקום של המשבצות הקיימות במסך. לדוגמה, כשגוללים באתר, המיקום של המשבצות הקיימות משתנה למעלה ורק מדי פעם צריך לעבד משבצת חדשה כדי להציג תוכן שנמצא בחלק התחתון של הדף.

ארבע משבצות.
בתמונה מוצגת תמונה של יום שמשי עם ארבע משבצות. כשמתבצעת גלילה, מתחיל להופיע משבצת חמישית. במקרה של אחת מהמשבצות יש רק צבע אחד (כחול שמיים), ויש סרטון ו-iframe מעליה.

ארבעה ופלטפורמות

משבצות של טקסטורה GPU הן סוג מיוחד של מרובע, שהוא פשוט שם מהודר לקטגוריה אחת של מרקם או לקטגוריה אחרת. מקש ארבע מזהה את טקסטורת הקלט ומציין איך לשנות אותה ולהשתמש באפקטים חזותיים. לדוגמה, למשבצות תוכן רגילות יש טרנספורמציה שמציינת את המיקום שלהן ב-x ו-y ברשת המשבצות.

משבצות של טקסטורה של GPU.

המשבצות האלה מעובדות בתוך רסטר וארוזות בכרטיס עיבוד, שהוא רשימה של ריבועים. כרטיס העיבוד לא מכיל מידע על פיקסלים. במקום זאת, הוא כולל הוראות לגבי איפה ואיך לשרטט כל מרובע כדי להפיק את פלט הפיקסלים הרצוי. לכל משבצת של טקסטורה של GPU יש ריבוע. מחבר התצוגה צריך רק לבצע איטרציה ברשימת הריבועים, תוך ציור של כל אחת עם האפקטים החזותיים שצוינו, כדי להפיק את פלט הפיקסלים הרצוי למעבר העיבוד. הרכבה של מרובעות ציור של מעבר רינדור יכולה להתבצע ביעילות ב-GPU, כי האפקטים החזותיים שמותרים נבחרים בקפידה להיות אלה שממופים ישירות לתכונות של GPU.

יש סוגים נוספים של שורות משיכה מעבר למשבצות רסטר. לדוגמה, יש Quads בצבע אחיד שלא מגובים בכלל במרקם, או Quads של מרקם לשרטוט של טקסטורות שלא קשורות לאריחים, כמו סרטון או קנבס.

יכולה להיות גם שמסגרת קומפוזיציה תטמיע מסגרת נוספת של קומפוזבילי. לדוגמה, קומפוזיציה של הדפדפן יוצר מסגרת קומפוזבילי עם ממשק המשתמש של הדפדפן, ומלבן ריק שבו יוטמע התוכן של קומפוזבילי עיבוד. דוגמה נוספת היא מסגרות iframe מבודדות מאתרים. ההטמעה הזו מתבצעת באמצעות פלטפורמות.

כאשר קומפוזיטור שולח מסגרת קומפוזבילי, הוא מלווה במזהה, שנקרא מזהה שטח, שמאפשר למסגרות של קומפוזביליות אחרות להטמיע אותה לפי הפניה. מסגרת הקומפוזיציה החדשה ביותר שנשלחה עם מזהה משטח מסוים נשמרת על ידי Viz. לאחר מכן, מסגרת קומפוזיציה נוספת יכולה להתייחס אליה מאוחר יותר באמצעות Surface quad, ולכן Viz יודעת מה לצייר. (חשוב לשים לב שהמרובעים של ציור פני השטח מכילים רק מזהי משטחים, ולא מרקמים).

אישורים לעיבוד ביניים

כדי להשתמש בחלק מהאפקטים החזותיים, כמו פילטרים או מצבי שילוב מתקדמים, צריך למשוך שתי ריבועים או יותר למרקם ביניים. לאחר מכן טקסטורת הביניים משורטטת למאגר נתונים זמני של יעד ב-GPU (או אולי טקסטורה ביניים אחרת), תוך שימוש באפקט החזותי באותו הזמן. כדי לאפשר זאת, מסגרת קומפוזיציה מכילה למעשה רשימה של אישורי רינדור. תמיד יש אישור מעבר של רינדור ברמה הבסיסית (root), שנכתב לאחרונה והיעד שלו תואם למאגר הנתונים הזמני של הפריים, ויכול להיות שיש עוד.

האפשרות לקבל כמה אישורים של רינדור מוסברת השם 'כרטיס עיבוד'. צריך להריץ כל כרטיס ברצף ב-GPU, במספר 'כרטיסים', אבל אפשר להשלים כרטיס אחד בחישוב של GPU אחד מקביל וחריף.

צבירה

כמה פריימים של קומפוזיטור נשלחים ל-Viz, וצריך לצייר אותם יחד למסך. ניתן לעשות זאת באמצעות שלב צבירה שממיר אותם למסגרת אחת ומצטברת אחת של הרכב. פונקציית הצבירה מחליפה את קווי השרטוט (quads) של פני השטח לפי הפריימים של המרכיב שהם מציינים. זו גם הזדמנות להעלים מרקמים מתווכים מיותרים או תוכן שאינו מוצג במסך. לדוגמה, במקרים רבים למסגרת הקומפוזיציה של iframe מבודד של אתר אין צורך במרקם ביניים משלו, וניתן לשרטט אותו ישירות למאגר הנתונים הזמני של המסגרת באמצעות קווי משיכה מתאימים. שלב הצבירה קובע אופטימיזציות כאלה ומיישם אותן על סמך ידע גלובלי שאינו נגיש למחבר אחד של רינדור.

דוגמה

אלה פריימים של הקומפוזיציה שמייצגים את הדוגמה מתחילת הפוסט הזה.

  • הפלטפורמה של foo.com/index.html: id=0
    • עיבוד אישור 0: משרטטים כדי להציג את הפלט.
      • עיבוד הנתונים ב-Qud Pass: משרטטים עם טשטוש של 3 פיקסלים וחיתוך של כרטיס רינדור 0.
        • עיבוד כרטיס 1:
          • משרטטים מרובעים לתוכן של קטע #one ב-iframe, עם מיקומי x ו-y בכל אחד מהם.
      • סוג ציור משטח: עם מזהה 2, מצויר עם קנה מידה ותרגום של טרנספורמציה.
  • הפלטפורמה של ממשק המשתמש בדפדפן: ID=1
    • עיבוד אישור 0: משרטטים כדי להציג את הפלט.
      • שרטטו ריבועים בממשק המשתמש של הדפדפן (גם אריחים)
  • הפלטפורמה של bar.com/index.html: ID=2
    • עיבוד אישור 0: משרטטים כדי להציג את הפלט.
      • משרטטים מרובעים לתוכן של #two iframe, כאשר מיקומי x ו-y בכל אחד מהם.

איורים של Una Kravets.