आइए, मुख्य डेटा स्ट्रक्चर पर नज़र डालें. ये रेंडरिंग पाइपलाइन के इनपुट और आउटपुट होते हैं.
ये डेटा स्ट्रक्चर हैं:
- फ़्रेम ट्री, लोकल और रिमोट नोड से बने होते हैं. इनसे पता चलता है कि कौनसे वेब दस्तावेज़ किस रेंडर प्रोसेस में हैं और कौनसे 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 कभी-कभी, क्रॉस-ऑरिजिन फ़्रेम को अपने पैरंट फ़्रेम से अलग रेंडर प्रोसेस में रेंडर कर सकता है.
उदाहरण के तौर पर दिए गए कोड में, कुल तीन फ़्रेम हैं:
साइट आइसोलेशन की सुविधा के साथ, Chromium इस वेब पेज को रेंडर करने के लिए, दो रेंडर प्रोसेस का इस्तेमाल करता है. हर रेंडर प्रोसेस में, उस वेब पेज के लिए फ़्रेम ट्री का अपना तरीका होता है:
किसी दूसरी प्रोसेस में रेंडर किए गए फ़्रेम को रिमोट फ़्रेम के तौर पर दिखाया जाता है. रिमोट फ़्रेम में, रेंडरिंग में प्लेसहोल्डर के तौर पर काम करने के लिए ज़रूरी कम से कम जानकारी होती है. उदाहरण के लिए, इसके डाइमेंशन. अगर ऐसा नहीं किया जाता है, तो रिमोट फ़्रेम में अपने असल कॉन्टेंट को रेंडर करने के लिए ज़रूरी जानकारी नहीं होती.
इसके उलट, लोकल फ़्रेम उस फ़्रेम को दिखाता है जो स्टैंडर्ड रेंडरिंग पाइपलाइन से गुज़रता है. लोकल फ़्रेम में, उस फ़्रेम के डेटा (जैसे, डीओएम ट्री और स्टाइल डेटा) को रेंडर और दिखाए जाने लायक बनाने के लिए ज़रूरी सारी जानकारी होती है.
रेंडरिंग पाइपलाइन, लोकल फ़्रेम ट्री फ़्रैगमेंट की बारीकी के हिसाब से काम करती है.
foo.com
को मुख्य फ़्रेम के तौर पर इस्तेमाल करके, ज़्यादा मुश्किल उदाहरण देखें:
<iframe src="bar.com"></iframe>
और यह bar.com
सबफ़्रेम:
<iframe src="foo.com/etc"></iframe>
हालांकि, अब भी सिर्फ़ दो रेंडरर हैं, लेकिन अब तीन लोकल फ़्रेम ट्री फ़्रैगमेंट हैं. इनमें से दो foo.com
के लिए रेंडर प्रोसेस में और एक bar.com
के लिए रेंडर प्रोसेस में है:
वेब पेज के लिए एक कंपोजिटर फ़्रेम बनाने के लिए, Viz एक साथ तीनों लोकल फ़्रेम ट्री के रूट फ़्रेम से कंपोजिटर फ़्रेम का अनुरोध करता है. इसके बाद, उन्हें एग्रीगेट करता है. कंपोज़र फ़्रेम सेक्शन भी देखें.
foo.com
मुख्य फ़्रेम और foo.com/other-page
सब-फ़्रेम, एक ही फ़्रेम ट्री का हिस्सा होते हैं और एक ही प्रोसेस में रेंडर किए जाते हैं.
हालांकि, दोनों फ़्रेम के दस्तावेज़ के लाइफ़साइकल अलग-अलग होते हैं, क्योंकि वे अलग-अलग लोकल फ़्रेम ट्री फ़्रैगमेंट का हिस्सा होते हैं.
इस वजह से, एक ही अपडेट में दोनों के लिए एक कंपोजिटर फ़्रेम जनरेट नहीं किया जा सकता.
रेंडर करने की प्रोसेस में, foo.com/other-page
के लिए जनरेट किए गए कंपोज़िटर फ़्रेम को सीधे foo.com
के मुख्य फ़्रेम के कंपोज़िटर फ़्रेम में कंपोज़ करने के लिए ज़रूरी जानकारी मौजूद नहीं है.
उदाहरण के लिए, प्रोसेस से बाहर का bar.com
पैरंट फ़्रेम, foo.com/other-url
iframe के डिसप्ले पर असर डाल सकता है. ऐसा, सीएसएस की मदद से iframe को बदलकर या उसके DOM में मौजूद दूसरे एलिमेंट की मदद से iframe के कुछ हिस्सों को छिपाकर किया जा सकता है.
विज़ुअल प्रॉपर्टी अपडेट वॉटरफ़ॉल
डिवाइस स्केल फ़ैक्टर और व्यूपोर्ट साइज़ जैसी विज़ुअल प्रॉपर्टी, रेंडर किए गए आउटपुट पर असर डालती हैं. साथ ही, इन्हें लोकल फ़्रेम ट्री फ़्रैगमेंट के बीच सिंक करना ज़रूरी है. हर लोकल फ़्रेम ट्री फ़्रैगमेंट के रूट में, एक विजेट ऑब्जेक्ट जुड़ा होता है. विज़ुअल प्रॉपर्टी के अपडेट, सबसे ऊपर से सबसे नीचे तक बाकी विजेट में भेजे जाने से पहले, मुख्य फ़्रेम के विजेट में जाते हैं.
उदाहरण के लिए, जब व्यूपोर्ट का साइज़ बदलता है, तो:
यह प्रोसेस तुरंत नहीं होती. इसलिए, डुप्लीकेट की गई विज़ुअल प्रॉपर्टी में सिंक टोकन भी शामिल होता है. विज़ कंपोजर इस सिंक टोकन का इस्तेमाल करके, सभी लोकल फ़्रेम ट्री फ़्रैगमेंट के इंतज़ार करता है, ताकि मौजूदा सिंक टोकन के साथ कंपोजर फ़्रेम सबमिट किया जा सके. इस प्रोसेस से, कॉम्पोज़िटर फ़्रेम को अलग-अलग विज़ुअल प्रॉपर्टी के साथ मिक्स होने से रोका जाता है.
इम्यूटेबल फ़्रैगमेंट ट्री
बदलाव न किए जा सकने वाला फ़्रैगमेंट ट्री, रेंडरिंग पाइपलाइन के लेआउट चरण का आउटपुट होता है. यह पेज पर मौजूद सभी एलिमेंट की पोज़िशन और साइज़ दिखाता है. हालांकि, इसमें ट्रांसफ़ॉर्म लागू नहीं होते.
हर फ़्रैगमेंट, किसी DOM एलिमेंट के हिस्से को दिखाता है. आम तौर पर, हर एलिमेंट में सिर्फ़ एक फ़्रैगमेंट होता है. हालांकि, अगर प्रिंट करते समय इसे अलग-अलग पेजों में बांटा जाता है या एक से ज़्यादा कॉलम वाले कॉन्टेक्स्ट में कॉलम में बांटा जाता है, तो एक से ज़्यादा फ़्रैगमेंट हो सकते हैं.
लेआउट के बाद, हर फ़्रैगमेंट में बदलाव नहीं किया जा सकता और उसे फिर कभी नहीं बदला जाता. अहम बात यह है कि हम कुछ और पाबंदियां भी लगाते हैं. हम ये काम नहीं करते:
- ट्री में किसी भी "अप" रेफ़रंस की अनुमति दें. (किसी चाइल्ड में अपने पैरंट का पॉइंटर नहीं हो सकता.)
- ट्री में "बबल" डेटा (एक बच्चा सिर्फ़ अपने बच्चों से जानकारी पढ़ता है, न कि अपने पैरंट से).
इन पाबंदियों की मदद से, हम किसी फ़्रेगमेंट को अगले लेआउट के लिए फिर से इस्तेमाल कर सकते हैं. इन पाबंदियों के बिना, हमें अक्सर पूरे ट्री को फिर से जनरेट करना पड़ता है. यह प्रोसेस महंगी होती है.
ज़्यादातर लेआउट, आम तौर पर इंक्रीमेंटल अपडेट होते हैं. उदाहरण के लिए, कोई वेब ऐप्लिकेशन, उपयोगकर्ता के किसी एलिमेंट पर क्लिक करने पर यूज़र इंटरफ़ेस (यूआई) के छोटे हिस्से को अपडेट करता है. आम तौर पर, लेआउट सिर्फ़ उसी हिस्से में बदलाव करना चाहिए जो स्क्रीन पर बदला है. ऐसा करने के लिए, हम पिछले ट्री के ज़्यादा से ज़्यादा हिस्सों का फिर से इस्तेमाल करते हैं. इसका मतलब है कि आम तौर पर, हमें सिर्फ़ ट्री स्ट्रक्चर को फिर से बनाना होगा.
आने वाले समय में, इस डिज़ाइन की मदद से कई दिलचस्प काम किए जा सकते हैं. जैसे, ज़रूरत पड़ने पर, थ्रेड की सीमाओं के बीच में, बदलाव न किए जा सकने वाले फ़्रैगमेंट ट्री को पास करना (किसी दूसरे थ्रेड पर अगले चरणों को पूरा करने के लिए), बेहतर लेआउट ऐनिमेशन के लिए कई ट्री जनरेट करना या एक साथ कई अनुमानित लेआउट बनाना. इससे हमें मल्टी-थ्रेडिंग लेआउट की सुविधा भी मिलती है.
इनलाइन फ़्रैगमेंट आइटम
इनलाइन कॉन्टेंट (मुख्य रूप से स्टाइल किया गया टेक्स्ट) थोड़े अलग तरीके से दिखाया जाता है. हम बॉक्स और पॉइंटर वाले ट्री स्ट्रक्चर के बजाय, इनलाइन कॉन्टेंट को ट्री दिखाने वाली फ़्लैट सूची में दिखाते हैं. इसका मुख्य फ़ायदा यह है कि इनलाइन के लिए फ़्लैट सूची का रेप्रज़ेंटेशन तेज़ होता है. साथ ही, यह इनलाइन डेटा-स्ट्रक्चर की जांच करने या उनसे क्वेरी करने के लिए भी मददगार होता है. साथ ही, यह मेमोरी के लिहाज़ से भी बेहतर होता है. यह वेब रेंडरिंग की परफ़ॉर्मेंस के लिए बहुत ज़रूरी है, क्योंकि टेक्स्ट को रेंडर करना बहुत मुश्किल होता है. साथ ही, अगर इसे ज़्यादा ऑप्टिमाइज़ नहीं किया जाता है, तो यह आसानी से पाइपलाइन का सबसे धीमा हिस्सा बन सकता है.
फ़्लैट सूची, हर इनलाइन फ़ॉर्मैटिंग कॉन्टेक्स्ट के लिए बनाई जाती है. यह सूची, इनलाइन लेआउट के सबट्री की डीप-फ़र्स्ट सर्च के क्रम में बनाई जाती है. सूची में मौजूद हर एंट्री, (ऑब्जेक्ट, वंशजों की संख्या) का टुपल होती है. उदाहरण के लिए, इस डीओएम को देखें:
<div style="width: 0;">
<span style="color: blue; position: relative;">Hi</span> <b>there</b>.
</div>
width
प्रॉपर्टी को 0 पर सेट किया गया है, ताकि लाइन "नमस्ते" और "वहां" के बीच रैप हो जाए.
जब इस स्थिति के लिए इनलाइन फ़ॉर्मैटिंग कॉन्टेक्स्ट को ट्री के तौर पर दिखाया जाता है, तो यह इस तरह दिखता है:
{
"Line box": {
"Box <span>": {
"Text": "Hi"
}
},
"Line box": {
"Box <b>": {
"Text": "There"
}
},
{
"Text": "."
}
}
फ़्लैट सूची इस तरह दिखती है:
- (लाइन बॉक्स, 2)
- (Box <span>, 1)
- (टेक्स्ट "नमस्ते", 0)
- (लाइन बॉक्स, 3)
- (बॉक्स <b>, 1)
- (Text "there", 0)
- (टेक्स्ट ".", 0)
इस डेटा स्ट्रक्चर का इस्तेमाल कई लोग करते हैं: ऐक्सेसibililty API,
और ज्यामिति एपीआई, जैसे कि
getClientRects
और contenteditable
.
हर चैनल के लिए ज़रूरी शर्तें अलग-अलग होती हैं.
ये कॉम्पोनेंट, सुविधाजनक कर्सर की मदद से फ़्लैट डेटा स्ट्रक्चर को ऐक्सेस करते हैं.
क cursor में MoveToNext
, MoveToNextLine
, CursorForChildren
जैसे एपीआई होते हैं.
टेक्स्ट कॉन्टेंट के लिए, कर्सर का यह तरीका कई वजहों से काफ़ी असरदार है:
- डीप-फ़र्स्ट सर्च ऑर्डर में, बहुत तेज़ी से दोहराव किया जा सकता है. इसका इस्तेमाल अक्सर किया जाता है, क्योंकि यह कर्सर की तरह ही काम करता है. यह एक फ़्लैट सूची है, इसलिए डीप-फ़र्स्ट सर्च सिर्फ़ ऐरे ऑफ़सेट को बढ़ा रही है. इससे, तेज़ी से दोहराव और मेमोरी लोकलिटी मिलती है.
- यह ब्रॉड-फ़र्स्ट सर्च की सुविधा देता है. उदाहरण के लिए, लाइन और इनलाइन बॉक्स का बैकग्राउंड पेंट करते समय, यह सुविधा ज़रूरी होती है.
- वंशजों की संख्या जानने से, अगले सिबलिंग पर तेज़ी से जाने में मदद मिलती है. इसके लिए, सिर्फ़ ऐरे ऑफ़सेट को उस संख्या से बढ़ाएं.
प्रॉपर्टी ट्री
डीओएम, एलिमेंट (साथ ही टेक्स्ट नोड) का ट्री होता है. सीएसएस, एलिमेंट पर अलग-अलग स्टाइल लागू कर सकती है.
यह चार तरीकों से दिखता है:
- लेआउट: लेआउट की पाबंदी वाले एल्गोरिदम के इनपुट.
- पेंट: एलिमेंट को पेंट और रेस्टर करने का तरीका (हालांकि, इसके वंशजों को नहीं).
- विज़ुअल: रेस्टर/ड्रॉ इफ़ेक्ट, जो डीओएम सबट्री पर लागू किए जाते हैं. जैसे, ट्रांसफ़ॉर्म, फ़िल्टर, और क्लिपिंग.
- स्क्रोल करना: अक्ष के साथ अलाइन किए गए और राउंड किए गए कोने वाले सबट्री को क्लिप करना और स्क्रोल करना.
प्रॉपर्टी ट्री, डेटा स्ट्रक्चर होते हैं. इनसे यह पता चलता है कि डीओएम एलिमेंट पर विज़ुअल और स्क्रोलिंग इफ़ेक्ट कैसे लागू होते हैं. इनसे इन सवालों के जवाब मिलते हैं: स्क्रीन के हिसाब से, कोई DOM एलिमेंट कहां है, उसका लेआउट साइज़ और पोज़िशन क्या है? और: विज़ुअल और स्क्रोलिंग इफ़ेक्ट लागू करने के लिए, जीपीयू के ऑपरेशन के किस क्रम का इस्तेमाल किया जाना चाहिए?
वेब पर विज़ुअल और स्क्रोलिंग इफ़ेक्ट का इस्तेमाल करना काफ़ी मुश्किल है. इसलिए, प्रॉपर्टी ट्री की सबसे अहम भूमिका, इस जटिलता को एक डेटा स्ट्रक्चर में बदलना है. यह स्ट्रक्चर, प्रॉपर्टी के स्ट्रक्चर और मतलब को सटीक तरीके से दिखाता है. साथ ही, डीओएम और सीएसएस की बाकी जटिलताओं को हटा देता है. इससे, कॉम्पोज़ करने और स्क्रोल करने के लिए एल्गोरिदम को ज़्यादा भरोसे के साथ लागू किया जा सकता है. खास तौर पर:
- गड़बड़ी की आशंका वाली ज्यामिति और अन्य गणनाओं को एक ही जगह पर केंद्रित किया जा सकता है.
- प्रॉपर्टी ट्री बनाने और अपडेट करने की जटिलता को रेंडरिंग पाइपलाइन के एक चरण में अलग कर दिया गया है.
- पूरी DOM स्थिति के मुकाबले, प्रॉपर्टी ट्री को अलग-अलग थ्रेड और प्रोसेस में भेजना ज़्यादा आसान और तेज़ है. इससे, कई कामों के लिए इनका इस्तेमाल किया जा सकता है.
- इस्तेमाल के जितने ज़्यादा उदाहरण होंगे, उतना ही ज़्यादा फ़ायदा हमें ऊपर बनाई गई ज्यामिति कैश मेमोरी से मिलेगा. ऐसा इसलिए, क्योंकि वे एक-दूसरे के कैश मेमोरी का फिर से इस्तेमाल कर सकते हैं.
RenderingNG कई कामों के लिए प्रॉपर्टी ट्री का इस्तेमाल करता है. इनमें ये काम शामिल हैं:
- पेंट और मुख्य थ्रेड से कॉम्पोज़िटिंग को अलग करना.
- कॉम्पोज़ करने / ड्रॉ करने की सबसे सही रणनीति तय करना.
- IntersectionObserver की ज्यामिति को मेज़र करना.
- ऑफ़स्क्रीन एलिमेंट और जीपीयू टेक्सचर टाइल के लिए काम न करना.
- पेंट और रेस्टर को असरदार और सटीक तरीके से अमान्य करना.
- वेबसाइट की परफ़ॉर्मेंस की अहम जानकारी देने वाली मेट्रिक में, लेआउट शिफ़्ट और सबसे बड़े एलिमेंट को रेंडर करने में लगने वाला समय मेज़र करना.
हर वेब दस्तावेज़ में चार अलग-अलग प्रॉपर्टी ट्री होते हैं: ट्रांसफ़ॉर्म, क्लिप, इफ़ेक्ट, और स्क्रोल.(*) ट्रांसफ़ॉर्म ट्री, सीएसएस ट्रांसफ़ॉर्म और स्क्रोलिंग को दिखाता है. (स्क्रोल ट्रांसफ़ॉर्म को 2D ट्रांसफ़ॉर्म मैट्रिक्स के तौर पर दिखाया जाता है.) क्लिप ट्री में ओवरफ़्लो क्लिप दिखती हैं. इफ़ेक्ट ट्री में, अन्य सभी विज़ुअल इफ़ेक्ट दिखते हैं: ओपैसिटी, फ़िल्टर, मास्क, ब्लेंड मोड, और क्लिप-पाथ जैसी अन्य तरह की क्लिप. स्क्रोल ट्री से स्क्रोल करने के बारे में जानकारी मिलती है. जैसे, स्क्रोल एक-दूसरे से कैसे जुड़े होते हैं. यह जानकारी, कंपोज़िटर थ्रेड पर स्क्रोल करने के लिए ज़रूरी है. प्रॉपर्टी ट्री में मौजूद हर नोड, किसी DOM एलिमेंट से लागू किए गए स्क्रोल या विज़ुअल इफ़ेक्ट को दिखाता है. अगर एक से ज़्यादा असर होते हैं, तो एक ही एलिमेंट के लिए हर ट्री में एक से ज़्यादा प्रॉपर्टी ट्री नोड हो सकते हैं.
हर ट्री की टोपोलॉजी, डीओएम के स्पैर्स रिप्रज़ेंटेशन की तरह होती है. उदाहरण के लिए, अगर ओवरफ़्लो क्लिप वाले तीन डीओएम एलिमेंट हैं, तो तीन क्लिप ट्री नोड होंगे. साथ ही, क्लिप ट्री का स्ट्रक्चर, ओवरफ़्लो क्लिप के बीच मौजूद ब्लॉक के संबंध के हिसाब से होगा. पेड़ों के बीच भी लिंक हैं. ये लिंक, नोड की रिलेटिव DOM हैरारकी और इसलिए, नोड के लागू होने के क्रम को दिखाते हैं. उदाहरण के लिए, अगर किसी DOM एलिमेंट पर ट्रांसफ़ॉर्म, फ़िल्टर वाले किसी दूसरे DOM एलिमेंट के नीचे है, तो ट्रांसफ़ॉर्म, फ़िल्टर से पहले लागू होता है.
हर DOM एलिमेंट में एक प्रॉपर्टी ट्री स्टेटस होता है, जो चार-टपल (ट्रांसफ़ॉर्म, क्लिप, इफ़ेक्ट, स्क्रोल) होता है. इससे, उस एलिमेंट पर असर डालने वाले सबसे नज़दीकी एलिमेंट की क्लिप, ट्रांसफ़ॉर्म, और इफ़ेक्ट ट्री नोड की जानकारी मिलती है. यह काफ़ी सुविधाजनक है, क्योंकि इस जानकारी से हमें उस एलिमेंट पर लागू होने वाली क्लिप, ट्रांसफ़ॉर्मेशन, और इफ़ेक्ट की सूची और उनके क्रम के बारे में सटीक जानकारी मिलती है. इससे हमें पता चलता है कि यह स्क्रीन पर कहां है और इसे कैसे ड्रॉ किया जाए.
उदाहरण
(source)
<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>
पिछले उदाहरण (जो शुरुआत में दिए गए उदाहरण से थोड़ा अलग है) के लिए, जनरेट किए गए प्रॉपर्टी ट्री के मुख्य एलिमेंट यहां दिए गए हैं:
में 3 पिक्सल का ब्लर लागू होता है.सूचियां और पेंट के हिस्से दिखाना
डिसप्ले आइटम में, कम लेवल के ड्रॉइंग कमांड होते हैं (यहां देखें). इन्हें Skia की मदद से रेस्टर किया जा सकता है. डिसप्ले आइटम आम तौर पर आसान होते हैं. इनमें सिर्फ़ कुछ ड्रॉइंग कमांड होते हैं, जैसे कि बॉर्डर या बैकग्राउंड बनाना. डिसप्ले आइटम की सूची बनाने के लिए, पेंट ट्री वॉक, लेआउट ट्री और उससे जुड़े फ़्रैगमेंट पर सीएसएस पेंटिंग के क्रम के हिसाब से, बार-बार जाता है.
उदाहरण के लिए:
<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>
इस एचटीएमएल और सीएसएस से, यहां दी गई डिसप्ले सूची बनेगी, जिसमें हर सेल एक डिसप्ले आइटम है:
व्यू का बैकग्राउंड | #blue बैकग्राउंड |
#green बैकग्राउंड |
#green इनलाइन टेक्स्ट |
---|---|---|---|
drawRect का साइज़ 800x600 और रंग सफ़ेद हो. |
drawRect , जिसका साइज़ 100x100 है और जो 0,0 पोज़िशन पर है और नीले रंग का है. |
drawRect , जिसका साइज़ 80x18 है और जो 8,8 पोज़िशन पर है. साथ ही, इसका रंग हरा है. |
drawTextBlob , जिसकी पोज़िशन 8,8 है और टेक्स्ट "Hello world" है. |
डिसप्ले आइटम की सूची को पीछे से आगे के क्रम में लगाया जाता है. ऊपर दिए गए उदाहरण में, हरे रंग का डायव ब्लू रंग के डायव से पहले डीओएम क्रम में है. हालांकि, सीएसएस पेंट ऑर्डर के लिए ज़रूरी है कि नेगेटिव z-index वाला ब्लू डायव, हरे डायव (चरण 4.1) से पहले (चरण 3) पेंट करे. डिसप्ले आइटम, सीएसएस पेंट ऑर्डर स्पेसिफ़िकेशन के एटॉमिक चरणों से मिलते-जुलते होते हैं. एक डीओएम एलिमेंट से कई डिसप्ले आइटम बन सकते हैं. उदाहरण के लिए, #green में बैकग्राउंड के लिए एक डिसप्ले आइटम और इनलाइन टेक्स्ट के लिए एक और डिसप्ले आइटम है. सीएसएस पेंट ऑर्डर की पूरी जानकारी देने के लिए, इस तरह की जानकारी देना ज़रूरी है. जैसे, नेगेटिव मार्जिन की वजह से इंटरलेविंग:
<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 है और टेक्स्ट "Hello world" है. |
डिसप्ले आइटम की सूची को सेव किया जाता है और बाद के अपडेट में उसका फिर से इस्तेमाल किया जाता है. अगर पेंट ट्री वॉक के दौरान कोई लेआउट ऑब्जेक्ट नहीं बदला है, तो उसके डिसप्ले आइटम को पिछली सूची से कॉपी कर लिया जाता है. एक और ऑप्टिमाइज़ेशन, सीएसएस पेंट ऑर्डर स्पेसिफ़िकेशन की प्रॉपर्टी पर निर्भर करता है: स्टैकिंग कॉन्टेक्स्ट, एटॉमिक तौर पर पेंट करते हैं. अगर स्टैकिंग कॉन्टेक्स्ट में कोई लेआउट ऑब्जेक्ट नहीं बदला है, तो पेंट ट्री वॉक, स्टैकिंग कॉन्टेक्स्ट को स्किप कर देता है और पिछली सूची से डिसप्ले आइटम के पूरे क्रम को कॉपी कर लेता है.
पेंट ट्री वॉक के दौरान, प्रॉपर्टी ट्री की मौजूदा स्थिति को बनाए रखा जाता है और डिसप्ले आइटम की सूची को डिसप्ले आइटम के "चंक" में बांटा जाता है. ये चंक, प्रॉपर्टी ट्री की एक ही स्थिति के साथ शेयर होते हैं. इसका उदाहरण यहां दिया गया है:
<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 है और टेक्स्ट "मैं गिर रहा/रही हूं" है. |
ट्रांसफ़ॉर्म प्रॉपर्टी ट्री और पेंट चंक इस तरह दिखेंगे (कम शब्दों में बताया गया है):
पेंट चंक की क्रम से लगाई गई सूची, रेंडरिंग पाइपलाइन के लेयराइज़ेशन चरण के इनपुट होते हैं. ये चंक, डिसप्ले आइटम और प्रॉपर्टी ट्री की स्थिति के ग्रुप होते हैं. पेंट चंक की पूरी सूची को एक कॉम्पोज़िट लेयर में मर्ज किया जा सकता है और एक साथ रेस्टर किया जा सकता है. हालांकि, हर बार जब उपयोगकर्ता स्क्रोल करता है, तो इसके लिए ज़्यादा रेस्टर करने की ज़रूरत होगी. हर पेंट चंक के लिए एक कंपोजिट लेयर बनाई जा सकती है और फिर उसे अलग-अलग रेस्टर किया जा सकता है, ताकि फिर से रेस्टर करने की ज़रूरत न पड़े. हालांकि, इससे जीपीयू मेमोरी जल्दी खत्म हो जाएगी. लेयर बनाने के चरण में, जीपीयू मेमोरी और खर्च को कम करने के बीच समझौता करना पड़ता है. आम तौर पर, चंक को डिफ़ॉल्ट रूप से मर्ज करना एक अच्छा तरीका है. साथ ही, ऐसे पेंट चंक को मर्ज नहीं करना चाहिए जिनमें प्रॉपर्टी ट्री की ऐसी स्थितियां हों जो कॉम्पोज़र थ्रेड पर बदल सकती हैं. जैसे, कॉम्पोज़र-थ्रेड स्क्रोलिंग या कॉम्पोज़र-थ्रेड ट्रांसफ़ॉर्म एनिमेशन.
ऊपर दिए गए उदाहरण में, दो कॉम्पोज़िट लेयर बननी चाहिए:
- 800x600 वाली एक कंपोज़िट लेयर, जिसमें ड्रॉइंग के कमांड शामिल हैं:
drawRect
का साइज़ 800x600 और रंग सफ़ेद होdrawRect
का साइज़ 100x100, पोज़िशन 0,0, और रंग गुलाबी
- 144x224 वाली कंपोजिट लेयर, जिसमें ड्रॉइंग के निर्देश शामिल हैं:
drawTextBlob
की पोज़िशन 0,0 और टेक्स्ट "नमस्ते दुनिया"- 0,18 का अनुवाद
rotateZ(25deg)
drawRect
का साइज़ 75x200, पोज़िशन 0,0, और रंग नारंगीdrawTextBlob
, जिसकी पोज़िशन 0,0 है और टेक्स्ट "मैं गिर रहा/रही हूं" है
अगर उपयोगकर्ता #scroll
को स्क्रोल करता है, तो दूसरी कंपोजिट लेयर को दूसरी जगह ले जाया जाता है. हालांकि, इसके लिए रेस्टराइज़ेशन की ज़रूरत नहीं होती.
उदाहरण के लिए, प्रॉपर्टी ट्री के पिछले सेक्शन में, छह पेंट चंक हैं. प्रॉपर्टी ट्री की स्थितियों (ट्रांसफ़ॉर्म, क्लिप, इफ़ेक्ट, स्क्रोल) के साथ-साथ, ये भी हैं:
- दस्तावेज़ का बैकग्राउंड: दस्तावेज़ स्क्रोल, दस्तावेज़ क्लिप, रूट, दस्तावेज़ स्क्रोल.
- डिव के लिए हॉरिज़ॉन्टल, वर्टिकल, और स्क्रोल कॉर्नर (तीन अलग-अलग पेंट चंक):
दस्तावेज़ स्क्रोल, दस्तावेज़ क्लिप,
#one
ब्लर, दस्तावेज़ स्क्रोल. - iframe
#one
:#one
घुमाएं, ओवरफ़्लो स्क्रोल क्लिप,#one
धुंधला करें, div स्क्रोल. - iframe
#two
:#two
स्केल, दस्तावेज़ क्लिप, रूट, दस्तावेज़ स्क्रोल.
कंपोजिटर फ़्रेम: सर्फ़ेस, रेंडर सर्फ़ेस, और जीपीयू टेक्स्चर टाइल
ब्राउज़र और रेंडर प्रोसेस, कॉन्टेंट को रेस्टर में बदलने की प्रोसेस को मैनेज करती हैं. इसके बाद, स्क्रीन पर दिखाने के लिए, विज़ प्रोसेस में कंपोजिटर फ़्रेम सबमिट करती हैं. कंपोजिटर फ़्रेम से पता चलता है कि रेस्टर किए गए कॉन्टेंट को एक साथ कैसे जोड़ा जाए और जीपीयू का इस्तेमाल करके उसे बेहतर तरीके से कैसे ड्रॉ किया जाए.
टाइल
सिद्धांत रूप से, रेंडर प्रोसेस या ब्राउज़र प्रोसेस कंपोजिटर, पिक्सल को रेंडरर व्यूपोर्ट के पूरे साइज़ के एक टेक्सचर में रेस्टर कर सकता है और उस टेक्सचर को विज़ में सबमिट कर सकता है. इसे दिखाने के लिए, डिसप्ले कंपोजिटर को उस एक टेक्सचर से पिक्सल को कॉपी करके, फ़्रेम बफ़र (उदाहरण के लिए, स्क्रीन) में सही जगह पर चिपकाना होगा. हालांकि, अगर उस कंपोजिटर को एक पिक्सल भी अपडेट करना है, तो उसे पूरे व्यूपोर्ट को फिर से रेस्टर करना होगा और Viz में एक नया टेक्सचर सबमिट करना होगा.
इसके बजाय, व्यूपोर्ट को टाइल में बांटा जाता है. व्यूपोर्ट के हिस्से के लिए, हर टाइल को रेस्टर किए गए पिक्सल के साथ एक अलग जीपीयू टेक्सचर टाइल बैक करती है. इसके बाद, रेंडरर अलग-अलग टाइल अपडेट कर सकता है या मौजूदा टाइल की स्क्रीन पर मौजूद जगह बदल सकता है. उदाहरण के लिए, किसी वेबसाइट को स्क्रोल करते समय, मौजूदा टाइल की पोज़िशन ऊपर की ओर शिफ़्ट हो जाएगी. साथ ही, पेज पर नीचे मौजूद कॉन्टेंट के लिए, सिर्फ़ कभी-कभी नई टाइल को रेस्टर करने की ज़रूरत होगी.
क्वाड और प्लैटफ़ॉर्म
जीपीयू टेक्स्चर टाइल, एक खास तरह की क्वाड होती हैं. यह टेक्स्चर की किसी कैटगरी का एक फैंसी नाम है. क्वॉड, इनपुट टेक्सचर की पहचान करता है. साथ ही, उस पर विज़ुअल इफ़ेक्ट लागू करने और उसे बदलने का तरीका बताता है. उदाहरण के लिए, सामान्य कॉन्टेंट टाइल में एक ट्रांसफ़ॉर्म होता है, जो टाइल ग्रिड में उनकी x, y पोज़िशन दिखाता है.
रेस्टर की गई इन टाइलों को रेंडर पास में लपेटा जाता है. यह क्वाड की सूची होती है. रेंडर पास में पिक्सल की कोई जानकारी नहीं होती. इसके बजाय, इसमें यह जानकारी होती है कि पिक्सल का मनचाहा आउटपुट पाने के लिए, हर क्वॉड को कहां और कैसे ड्रॉ करना है. हर जीपीयू टेक्सचर टाइल के लिए एक ड्रॉ क्वॉड होता है. रेंडर पास के लिए, डिसप्ले कंपोजिटर को सिर्फ़ क्वाड की सूची में बदलाव करना होता है. इसके लिए, वह हर क्वाड को तय किए गए विज़ुअल इफ़ेक्ट के साथ ड्रॉ करता है. रेंडर पास के लिए ड्रॉ क्वॉड को कॉम्पोज़ करने का काम, जीपीयू पर बेहतर तरीके से किया जा सकता है. ऐसा इसलिए, क्योंकि इस्तेमाल किए जा सकने वाले विज़ुअल इफ़ेक्ट को ध्यान से चुना जाता है, ताकि वे सीधे जीपीयू की सुविधाओं पर मैप हो सकें.
रेस्टर की गई टाइल के अलावा, ड्रॉ क्वाड के अन्य टाइप भी होते हैं. उदाहरण के लिए, ऐसे सॉलिड कलर ड्रॉ क्वाड होते हैं जिनमें कोई टेक्सचर नहीं होता. इसके अलावा, वीडियो या कैनवस जैसे टाइल टेक्सचर के लिए टेक्चर ड्रॉ क्वाड भी होते हैं.
किसी कंपोजिटर फ़्रेम में, दूसरे कंपोजिटर फ़्रेम को भी एम्बेड किया जा सकता है. उदाहरण के लिए, ब्राउज़र कंपोजिटर, ब्राउज़र यूज़र इंटरफ़ेस (यूआई) के साथ एक कंपोजिटर फ़्रेम बनाता है. साथ ही, एक खाली रेक्टैंगल बनाता है, जहां रेंडर कंपोजिटर कॉन्टेंट को एम्बेड किया जाएगा. साइट से अलग iframes भी एक उदाहरण है. सर्फ़ेस की मदद से, कॉन्टेंट को एम्बेड किया जाता है.
जब कोई कंपोजिटर कोई कंपोजिटर फ़्रेम सबमिट करता है, तो उसके साथ एक आइडेंटिफ़ायर होता है. इसे सर्फ़ेस आईडी कहा जाता है. इससे दूसरे कंपोजिटर फ़्रेम, रेफ़रंस के ज़रिए इसे एम्बेड कर सकते हैं. किसी खास सरफ़ेस आईडी के साथ सबमिट किया गया नया कंपोजिटर फ़्रेम, Viz सेव करता है. इसके बाद, कोई दूसरा कंपोजिटर फ़्रेम, सरफ़ेस ड्रॉ क्वॉड के ज़रिए इसका रेफ़रंस दे सकता है. इसलिए, Viz को पता होता है कि क्या ड्रॉ करना है. ध्यान दें कि सरफ़ेस ड्रॉ क्वॉड में सिर्फ़ सरफ़ेस आईडी होते हैं, न कि टेक्सचर.
बीच के रेंडर पास
कुछ विज़ुअल इफ़ेक्ट, जैसे कि कई फ़िल्टर या बेहतर ब्लेंड मोड के लिए, ज़रूरी है कि इंटरमीडिएट टेक्स्चर में दो या उससे ज़्यादा क्वाड ड्रॉ किए जाएं. इसके बाद, इंटरमीडिएट टेक्चर को जीपीयू (या किसी अन्य इंटरमीडिएट टेक्चर) पर डेस्टिनेशन बफ़र में खींचा जाता है. साथ ही, उस पर विज़ुअल इफ़ेक्ट भी लागू किया जाता है. ऐसा करने के लिए, कंपोजिटर फ़्रेम में रेंडर पास की सूची होती है. हमेशा एक रूट रेंडर पास होता है, जो आखिर में ड्रॉ किया जाता है और जिसका डेस्टिनेशन फ़्रेम बफ़र से जुड़ा होता है. इसके अलावा, और भी पास हो सकते हैं.
एक से ज़्यादा रेंडर पास की संभावना होने की वजह से, इसे "रेंडर पास" कहा जाता है. हर पास को जीपीयू पर क्रम से, कई "पास" में चलाया जाना चाहिए, जबकि एक पास को एक बड़े पैमाने पर पैरलल जीपीयू कंप्यूटेशन में पूरा किया जा सकता है.
एग्रीगेशन
कई कंपोजिटर फ़्रेम, विज़ में सबमिट किए जाते हैं और उन्हें स्क्रीन पर एक साथ ड्रॉ किया जाना चाहिए. ऐसा एग्रीगेशन फ़ेज़ की मदद से किया जाता है, जो इन्हें एक साथ एग्रीगेट करके, एक कंपोज़िटर फ़्रेम में बदल देता है. एग्रीगेशन, सर्फ़ेस ड्रॉ क्वॉड को उन कॉम्पोज़िटर फ़्रेम से बदल देता है जिन्हें वे तय करते हैं. इससे, बीच में आने वाले अनचाहे टेक्सचर या ऑफ़स्क्रीन कॉन्टेंट को ऑप्टिमाइज़ करने का भी मौका मिलता है. उदाहरण के लिए, कई मामलों में साइट से अलग किए गए iframe के लिए, कॉम्पोज़र फ़्रेम को अपने इंटरमीडिएट टेक्सचर की ज़रूरत नहीं होती. साथ ही, इसे सही ड्रॉ क्वाड की मदद से सीधे फ़्रेम बफ़र में ड्रॉ किया जा सकता है. एग्रीगेशन फ़ेज़ में, ऐसे ऑप्टिमाइज़ेशन का पता लगाया जाता है और उन्हें लागू किया जाता है. ऐसा, दुनिया भर के डेटा के आधार पर किया जाता है. इस डेटा को अलग-अलग रेंडर कंपोजर ऐक्सेस नहीं कर सकते.
उदाहरण
यहां कॉम्पोज़िटर फ़्रेम दिए गए हैं, जो इस पोस्ट की शुरुआत में दिए गए उदाहरण को दिखाते हैं.
foo.com/index.html
surface: id=0- रेंडर पास 0: आउटपुट में ड्रॉ करें.
- रेंडर पास ड्रॉ क्वॉड: 3 पिक्सल ब्लर के साथ ड्रॉ करें और रेंडर पास 0 में क्लिप करें.
- पहला रेंडर पास:
#one
iframe के टाइल कॉन्टेंट के लिए क्वाड बनाएं. साथ ही, हर क्वाड के लिए x और y पोज़िशन दें.
- पहला रेंडर पास:
- सरफ़ेस ड्रॉ क्वॉड: आईडी 2 के साथ, स्केल और ट्रांसलेट ट्रांसफ़ॉर्म के साथ ड्रॉ किया गया.
- रेंडर पास ड्रॉ क्वॉड: 3 पिक्सल ब्लर के साथ ड्रॉ करें और रेंडर पास 0 में क्लिप करें.
- रेंडर पास 0: आउटपुट में ड्रॉ करें.
- ब्राउज़र यूज़र इंटरफ़ेस (यूआई) का प्लैटफ़ॉर्म: आईडी=1
- रेंडर पास 0: आउटपुट में ड्रॉ करें.
- ब्राउज़र यूज़र इंटरफ़ेस (यूआई) के लिए क्वाड ड्रॉ करना (टाइल भी)
- रेंडर पास 0: आउटपुट में ड्रॉ करें.
bar.com/index.html
surface: ID=2- रेंडर पास 0: आउटपुट में ड्रॉ करें.
#two
iframe के कॉन्टेंट के लिए क्वाड बनाएं. साथ ही, हर क्वाड के लिए x और y पोज़िशन दें.
- रेंडर पास 0: आउटपुट में ड्रॉ करें.
इलस्ट्रेशन: यूना क्रेवेट.