इस सीरीज़ की पिछली पोस्ट में pingNG आर्किटेक्चर के लक्ष्यों, मुख्य प्रॉपर्टी, और हाई-लेवल कॉम्पोनेंट के के बारे में खास जानकारी दी गई है. आइए, अब उन मुख्य डेटा स्ट्रक्चर के बारे में जानते हैं जो रेंडरिंग पाइपलाइन के लिए इनपुट और आउटपुट हैं.
ये डेटा स्ट्रक्चर हैं:
- फ़्रेम ट्री, जो लोकल और रिमोट नोड से बने होते हैं, जिनसे पता चलता है कि कौनसे वेब दस्तावेज़ में रेंडर करने की प्रोसेस है और कौनसे ब्लिंक रेंडरर हैं.
- इम्यूटेबल फ़्रैगमेंट ट्री, लेआउट कंस्ट्रेंट एल्गोरिदम के आउटपुट (और इनपुट को) को दिखाता है.
- प्रॉपर्टी ट्री, जो किसी वेब दस्तावेज़ को बदलने, क्लिप, इफ़ेक्ट और स्क्रोल करने की हैरारकी को दिखाते हैं. इनका इस्तेमाल पूरी पाइपलाइन में किया जाता है.
- डिसप्ले लिस्ट और पेंट के हिस्से, रास्टर और लेयराइज़ेशन एल्गोरिदम के इनपुट हैं.
- कंपोज़िट फ़्रेम में सरफ़ेस, इमेज, और जीपीयू टेक्सचर टाइल शामिल होती हैं. इनका इस्तेमाल जीपीयू का इस्तेमाल करके ड्रॉ करने के लिए किया जाता है.
इन डेटा स्ट्रक्चर के बारे में बताने से पहले, मुझे यह सामान्य उदाहरण दिखाना है कि पिछली पोस्ट के आधार पर क्या होता है. मैं इस पोस्ट में इस उदाहरण का कई बार इस्तेमाल करूँगी और यह दिखा दूँगी कि डेटा स्ट्रक्चर उस पर कैसे लागू होते हैं.
<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 के कुछ हिस्सों को रोककर करने पर हो सकता है.
विज़ुअल प्रॉपर्टी अपडेट करने वाला वॉटरफ़ॉल
डिवाइस स्केल फ़ैक्टर और व्यूपोर्ट के साइज़ जैसी विज़ुअल प्रॉपर्टी, रेंडर किए गए आउटपुट पर असर डालती हैं. इन प्रॉपर्टी को लोकल फ़्रेम ट्री के फ़्रैगमेंट के बीच सिंक करना ज़रूरी है. हर लोकल फ़्रेम ट्री फ़्रैगमेंट के रूट में, एक विजेट ऑब्जेक्ट होता है. विज़ुअल प्रॉपर्टी के अपडेट, बाकी बचे विजेट को ऊपर से नीचे तक लागू करने से पहले, मुख्य फ़्रेम के विजेट में जाते हैं. उदाहरण के लिए, जब व्यूपोर्ट का साइज़ बदलता है, तो:
यह प्रोसेस तुरंत नहीं होती, इसलिए दोहराई गई विज़ुअल प्रॉपर्टी में सिंक टोकन भी शामिल होता है. Viz कंपोज़िटर इस सिंक टोकन का इस्तेमाल सभी लोकल फ़्रेम ट्री फ़्रैगमेंट के लिए तब तक इंतज़ार करने के लिए करता है, जब तक कि मौजूदा सिंक टोकन वाला कंपोज़िटर फ़्रेम सबमिट न हो. इस प्रोसेस से, कंपोज़िटर फ़्रेम को अलग-अलग विज़ुअल प्रॉपर्टी के साथ मिलाने से बचा जा सकता है.
ऐसा फ़्रैगमेंट ट्री जिसे बदला नहीं जा सकता
नहीं बदला जा सकने वाला फ़्रैगमेंट ट्री, रेंडरिंग पाइपलाइन के लेआउट स्टेज का आउटपुट है. यह पेज पर मौजूद सभी एलिमेंट की पोज़िशन और साइज़ को दिखाता है (बदलाव लागू किए बिना).
हर फ़्रैगमेंट, डीओएम एलिमेंट के किसी हिस्से को दिखाता है. आम तौर पर, हर एलिमेंट में सिर्फ़ एक फ़्रैगमेंट होता है. हालांकि, ऐसा तब भी हो सकता है, जब प्रिंट करते समय इसे अलग-अलग पेज या कई कॉलम वाले कॉन्टेक्स्ट में कॉलम में बांटा गया हो.
लेआउट के बाद, हर फ़्रैगमेंट में बदलाव नहीं किया जा सकता और उसे फिर कभी बदला नहीं जाता. अहम बात यह है कि हम कुछ और पाबंदियां भी लगाते हैं. हम ये काम नहीं करते हैं:
- ट्री में किसी भी "अप" रेफ़रंस को अनुमति दें. (कोई बच्चा अपने पैरंट के लिए पॉइंटर नहीं बना सकता.)
- ट्री का "बबल" डेटा (बब्बल सिर्फ़ अपने बच्चों से जुड़ी जानकारी पढ़ता है, अपने माता-पिता से नहीं).
इन पाबंदियों की मदद से, हम बाद के लेआउट के लिए, फ़्रैगमेंट का फिर से इस्तेमाल कर सकते हैं. इन पाबंदियों के बिना, हमें अक्सर पूरे पेड़ को फिर से जनरेट करना होता है, जो कि महंगा है.
ज़्यादातर लेआउट आम तौर पर इंंक्रीमेंटल अपडेट होते हैं. उदाहरण के लिए, ऐसा वेब ऐप्लिकेशन जो उपयोगकर्ता के किसी एलिमेंट पर क्लिक करने की वजह से, यूज़र इंटरफ़ेस (यूआई) के छोटे हिस्से को अपडेट करता है. आम तौर पर, लेआउट को स्क्रीन पर असल में हुए बदलावों के अनुपात में ही काम करना चाहिए. ऐसा करने के लिए, हम पिछले ट्री के ज़्यादा से ज़्यादा हिस्सों का फिर से इस्तेमाल कर सकते हैं. इसका मतलब है (आम तौर पर) हमें सिर्फ़ पेड़ की रीढ़ की हड्डी को फिर से बनाना है.
आने वाले समय में, नहीं बदले जा सकने वाले इस डिज़ाइन से, हम कुछ दिलचस्प काम कर पाएंगे. जैसे, ज़रूरत पड़ने पर, नहीं बदले जा सकने वाले फ़्रैगमेंट ट्री को थ्रेड की सीमाओं में पास करने, स्मूद लेआउट ऐनिमेशन के लिए, बाद के चरण पूरे करने, स्मूद लेआउट ऐनिमेशन के लिए, कई ट्री जनरेट करने या अनुमान पर आधारित लेआउट इस्तेमाल करने की सुविधा. इससे हमें मल्टी-थ्रेडिंग लेआउट की संभावना भी बढ़ जाती है.
इनलाइन फ़्रैगमेंट आइटम
इनलाइन कॉन्टेंट (खास तौर पर किसी स्टाइल वाले टेक्स्ट में) में थोड़ा अलग तरीके से दिखाया जाता है. बॉक्स और पॉइंटर वाली ट्री संरचना के बजाय, हम ट्री को दर्शाने वाली फ़्लैट सूची में इनलाइन कॉन्टेंट को दिखाते हैं. इसका मुख्य फ़ायदा यह है कि इनलाइन के लिए फ़्लैट लिस्ट दिखाई गई है, तेज़ी से काम करती है, इनलाइन डेटा स्ट्रक्चर की जांच या क्वेरी करने में मदद करती है, और मेमोरी की बचत होती है. वेब रेंडरिंग की परफ़ॉर्मेंस के लिए यह बेहद ज़रूरी है, क्योंकि टेक्स्ट की रेंडरिंग बहुत जटिल होती है. साथ ही, अगर इसे पूरी तरह ऑप्टिमाइज़ नहीं किया गया है, तो यह पाइपलाइन का सबसे धीमा हिस्सा बन सकती है.
दिलचस्प ऐतिहासिक जानकारी के तौर पर, यह काफ़ी हद तक Internet Explorer में अपने डीओएम को दिखाने से काफ़ी मिलता-जुलता है, क्योंकि इसे शुरुआत में टेक्स्ट एडिटर की तरह ही बनाया गया था.
फ़्लैट लिस्ट, हर इनलाइन फ़ॉर्मैटिंग के कॉन्टेक्स्ट के लिए बनाई जाती है. यह इनलाइन लेआउट सबट्री की डेप्थ-फ़र्स्ट खोज के हिसाब से बनाई जाती है. सूची की हर एंट्री, (ऑब्जेक्ट, डिसेंडेंट की संख्या) का टपल है. उदाहरण के लिए, इस 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)
- (बॉक्स <span>, 1)
- (टेक्स्ट "नमस्ते", 0)
- (लाइन बॉक्स, 3)
- (बॉक्स <b>, 1)
- (टेक्स्ट "वहां", 0)
- (टेक्स्ट ".", 0)
इस डेटा स्ट्रक्चर को इस्तेमाल करने वाले कई लोग हैं: सुलभता एपीआई और ज्यामिति वाले एपीआई, जैसे कि getClientRects, और contentEdit. हर प्रॉडक्ट या सेवा की ज़रूरी शर्तें अलग-अलग होती हैं. ये कॉम्पोनेंट, सुविधा कर्सर का इस्तेमाल करके फ़्लैट डेटा स्ट्रक्चर को ऐक्सेस करते हैं.
कर्सर में MoveToNext
,
MoveToNextLine
,
CursorForChildren
जैसे एपीआई मौजूद हैं.
कर्सर को यह टेक्स्ट कॉन्टेंट के लिए बहुत असरदार तरीके से दिखाता है. इसकी कई वजहें हो सकती हैं:
- डेप्थ-फ़र्स्ट सर्च ऑर्डर में इटरेशन बहुत तेज़ी से काम करता है. इसका इस्तेमाल बहुत बार किया जाता है, क्योंकि यह कैरेट मूवमेंट के जैसा होता है. यह एक सपाट सूची है, इसलिए डेप्थ-फ़र्स्ट सर्च, ऐरे ऑफ़सेट को बढ़ा रहा है, और तेज़ दोहराव और मेमोरी का शहर भी बढ़ा रहा है.
- यह बेहतर तरीके से खोजने की सुविधा देता है, जिसकी ज़रूरत तब पड़ती है, जब लाइन और इनलाइन बॉक्स के बैकग्राउंड में पेंटिंग की गई हो.
- डिसेंडेंट की संख्या पता होने से, अगले सिबलिंग पर तेज़ी से जाया जाता है (सिर्फ़ उस संख्या से अरे ऑफ़सेट बढ़ाएं).
प्रॉपर्टी ट्री
जैसा कि आपको पता है, DOM एलिमेंट का एक ट्री (प्लस टेक्स्ट नोड) है और सीएसएस, एलिमेंट पर कई तरह की स्टाइल लागू कर सकती है.
ये ज़्यादातर, इफ़ेक्ट के चार फ़्लेवर में उपलब्ध हैं:
- लेआउट: लेआउट कंस्ट्रेंट एल्गोरिदम के लिए इनपुट.
- पेंट: एलिमेंट को कैसे पेंट और रास्टर करना है (लेकिन उसके डिसेंडेंट नहीं).
- विज़ुअल: डीओएम सबट्री पर लागू किए गए रास्टर/ड्रॉ इफ़ेक्ट, जैसे कि ट्रांसफ़ॉर्म, फ़िल्टर, और क्लिपिंग.
- स्क्रोल करना: ऐक्सिस-अलाइन्ड और गोल कोने में शामिल सबट्री को क्लिप करना और स्क्रोल करना.
प्रॉपर्टी ट्री, डेटा स्ट्रक्चर होते हैं. इनसे यह पता चलता है कि डीओएम एलिमेंट पर विज़ुअल और स्क्रोलिंग इफ़ेक्ट कैसे लागू होते हैं. इनसे इन सवालों के जवाब मिल पाते हैं: स्क्रीन के हिसाब से, कोई डीओएम एलिमेंट कहां, इसके लेआउट साइज़ और पोज़िशन के हिसाब से दिया गया है? साथ ही: विज़ुअल और स्क्रोलिंग इफ़ेक्ट लागू करने के लिए जीपीयू की कार्रवाइयों के किस क्रम का इस्तेमाल किया जाना चाहिए?
वेब पर विज़ुअल और स्क्रोलिंग इफ़ेक्ट, पूरी तरह से बेहद जटिल हैं. इसलिए, प्रॉपर्टी ट्री के लिए सबसे ज़रूरी काम यह है कि उस जटिलता को एक ही डेटा स्ट्रक्चर में बदला जाए जो उनके स्ट्रक्चर और मतलब को सटीक तौर पर दिखाता हो. साथ ही, साथ ही, डीओएम और सीएसएस की बाकी जटिलता को हटाता है. इससे हम ज़्यादा भरोसे के साथ कंपोज़िटिंग और स्क्रोलिंग के लिए एल्गोरिदम लागू कर पाते हैं. खास तौर पर:
- ऐसी ज्यामिति और अन्य कैलकुलेशन को एक ही जगह पर रखा जा सकता है जिनमें गड़बड़ी हो सकती है.
- प्रॉपर्टी ट्री बनाने और उसे अपडेट करने में आने वाली जटिलता को रेंडर करने वाले एक ही पाइपलाइन चरण में दिखाया जाता है.
- फ़ुल डीओएम स्थिति के मुकाबले, प्रॉपर्टी ट्री को अलग-अलग थ्रेड और प्रोसेस पर भेजना ज़्यादा आसान और तेज़ होता है. इससे, कई तरह के मामलों में प्रॉपर्टी ट्री का इस्तेमाल किया जा सकता है.
- जितने ज़्यादा इस्तेमाल के उदाहरण होंगे हम सबसे ऊपर मौजूद ज्यामिति कैशिंग से उतनी ही ज़्यादा जीत हासिल कर सकेंगे. ऐसा इसलिए, क्योंकि वे एक-दूसरे की कैश मेमोरी का फिर से इस्तेमाल कर सकते हैं.
रेंडरिंगNG कई कामों के लिए प्रॉपर्टी ट्री का इस्तेमाल करता है. इनमें ये शामिल हैं:
- कंपोज़िट को पेंट से अलग करना और मुख्य थ्रेड से कंपोज़िट करना.
- बेहतर कंपोज़िटिंग / ड्रॉ की रणनीति तय करना.
- IntersectionObserver ज्यामिति को मापा जा रहा है.
- ऑफ़स्क्रीन एलिमेंट और जीपीयू टेक्सचर टाइल के लिए काम करने से बचना.
- पेंट और रास्टर को कुशलता और सही तरीके से अमान्य कर रहा है.
- वेबसाइट की परफ़ॉर्मेंस की अहम जानकारी में, लेआउट में बदलाव और सबसे बड़े कॉन्टेंटफ़ुल पेंट को मेज़र करना.
हर वेब दस्तावेज़ में चार अलग-अलग प्रॉपर्टी ट्री होती हैं: ट्रांसफ़ॉर्म, क्लिप, इफ़ेक्ट, और स्क्रोल.(*) ट्रांसफ़ॉर्म ट्री, सीएसएस ट्रांसफ़ॉर्म और स्क्रोलिंग के बारे में बताता है. (स्क्रोल ट्रांसफ़ॉर्म को 2D ट्रांसफ़ॉर्म मैट्रिक्स के तौर पर दिखाया जाता है.) क्लिप ट्री, ओवरफ़्लो क्लिप दिखाता है. इफ़ेक्ट ट्री में सभी विज़ुअल इफ़ेक्ट दिखते हैं: ओपैसिटी, फ़िल्टर, मास्क, ब्लेंड मोड, और क्लिप-पाथ जैसे अन्य क्लिप. स्क्रोल ट्री, स्क्रोल करने के बारे में जानकारी दिखाता है, जैसे कि चेन को एक साथ कैसे स्क्रोल करता है; कंपोज़िटर थ्रेड पर स्क्रोल करने के लिए इसकी ज़रूरत होती है. प्रॉपर्टी ट्री का हर नोड, स्क्रोल या विज़ुअल इफ़ेक्ट को दिखाता है, जिसे DOM एलिमेंट से लागू किया जाता है. अगर ऐसा कई इफ़ेक्ट से होता है, तो हर ट्री में एक ही एलिमेंट के लिए एक से ज़्यादा प्रॉपर्टी ट्री नोड हो सकते हैं.
हर पेड़ की टोपोलॉजी, डीओएम को सीमित जानकारी के तौर पर दिखाती है. उदाहरण के लिए, अगर ओवरफ़्लो क्लिप वाले तीन डीओएम एलिमेंट हैं, तो तीन क्लिप ट्री नोड होंगे और क्लिप ट्री का स्ट्रक्चर, ओवरफ़्लो क्लिप के बीच वाले ब्लॉक संबंध को फ़ॉलो करेगा. इन पेड़ों के बीच में भी लिंक हैं. ये लिंक, रिलेटिव DOM हैरारकी को दिखाते हैं. इसलिए, नोड के ऐप्लिकेशन के क्रम को दिखाते हैं. उदाहरण के लिए, अगर किसी डीओएम एलिमेंट में कोई ट्रांसफ़ॉर्म ऐक्शन, फ़िल्टर वाले दूसरे डीओएम एलिमेंट से नीचे है, तो फ़िल्टर से पहले ट्रांसफ़ॉर्म करता है.
हर डीओएम एलिमेंट में प्रॉपर्टी ट्री स्टेट होता है. यह चार टपल (ट्रांसफ़ॉर्म, क्लिप, इफ़ेक्ट, स्क्रोल) होता है. यह एलिमेंट उस एलिमेंट पर लागू होने वाले सबसे नज़दीकी एंसेस्टर क्लिप, ट्रांसफ़ॉर्म, और इफ़ेक्ट ट्री नोड को दिखाता है. यह बहुत आसान है, क्योंकि इस जानकारी से हमें उस एलिमेंट पर लागू होने वाली क्लिप, ट्रांसफ़ॉर्म, और इफ़ेक्ट की सही सूची और उनके क्रम का पता चलता है. इससे हमें पता चलता है कि यह स्क्रीन पर कहां है और इसे कैसे ड्रॉ करना है.
उदाहरण
(सोर्स)
<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 की मदद से रास्टर किया जा सकता है. डिसप्ले आइटम आम तौर पर आसान होते हैं. इनमें ड्रॉइंग के लिए कुछ निर्देश दिए जाते हैं, जैसे कि बॉर्डर या बैकग्राउंड बनाना. पेंट ट्री वॉक, सीएसएस पेंटिंग ऑर्डर के बाद, लेआउट ट्री और उससे जुड़े फ़्रैगमेंट के बार-बार दोहराता है और डिसप्ले आइटम की सूची बनाता है.
उदाहरण के लिए:
<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 की जगह 0,0 पर साइज़ 100x100 और नीला रंग. |
drawRect का साइज़ 80x18, पोज़िशन 8,8 पर और हरा रंग. |
drawTextBlob की पोज़िशन 8,8 है और टेक्स्ट "नमस्ते दुनिया" है. |
डिसप्ले आइटम की सूची का क्रम आगे की ओर होता है. ऊपर दिए गए उदाहरण में, हरा div DOM क्रम में नीले div से पहले है, लेकिन सीएसएस पेंट ऑर्डर के लिए यह ज़रूरी है कि नेगेटिव z-इंडेक्स नीले div पेंट पहले (चरण 3) हरे div (चरण 4.1) से पहले हो. डिसप्ले आइटम, मोटे तौर पर सीएसएस पेंट ऑर्डर की खास बातों के ऐटॉमिक चरणों के मुताबिक हैं. एक डीओएम एलिमेंट में कई डिसप्ले आइटम हो सकते हैं, जैसे कि किस तरह #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 है और टेक्स्ट "नमस्ते दुनिया" है. |
डिसप्ले आइटम की सूची को बाद के अपडेट में सेव और फिर से इस्तेमाल किया जाता है. अगर पेंट ट्री वॉक के दौरान किसी लेआउट ऑब्जेक्ट में बदलाव नहीं होता है, तो उसके डिसप्ले आइटम पिछली सूची से कॉपी किए जाते हैं. एक और ऑप्टिमाइज़ेशन, सीएसएस पेंट ऑर्डर स्पेसिफ़िकेशन की प्रॉपर्टी पर निर्भर करता है: कॉन्टेक्स्ट को स्टैक करने के दौरान, ऐटॉमली तरीके से पेंट किया जाता है. अगर स्टैकिंग कॉन्टेक्स्ट में कोई भी लेआउट ऑब्जेक्ट नहीं बदला गया है, तो पेंट ट्री वॉक, स्टैकिंग कॉन्टेक्स्ट को स्किप कर देता है और पिछली सूची से डिसप्ले आइटम के पूरे क्रम को कॉपी कर लेता है.
पेंट ट्री वॉक के दौरान मौजूदा प्रॉपर्टी ट्री की स्थिति बनी रहती है और डिसप्ले आइटम की सूची को डिसप्ले आइटम के "अलग-अलग हिस्सों" में बांटा जाता है जो एक ही प्रॉपर्टी ट्री की स्थिति शेयर करते हैं. नीचे दिए गए उदाहरण में इसे दिखाया गया है:
<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 की जगह 0,0 पर 100x100 का साइज़ और गुलाबी रंग. |
drawTextBlob में जगह 0,0 है और टेक्स्ट "नमस्ते दुनिया" है. |
drawRect की जगह 0,0 पर 75x200 साइज़ और नारंगी रंग. |
drawTextBlob की जगह 0,0 है और "मैं गिर रहा/रही हूं" टेक्स्ट. |
इसके बाद, प्रॉपर्टी ट्री और पेंट समूहों में बदलाव करना (कम शब्दों में सटीक जानकारी के लिए आसान) होगा:
डिसप्ले आइटम के ग्रुप और प्रॉपर्टी ट्री स्टेट के तौर पर पेंट हिस्सों की क्रम वाली सूची होती है. ये रेंडरिंग पाइपलाइन के लेयर वाले चरण के इनपुट हैं. पेंट के हिस्सों की पूरी सूची को एक कंपोज़िट लेयर में मर्ज करके रास्टराइज़ किया जा सकता है. हालांकि, इसके लिए हर बार उपयोगकर्ता को स्क्रोल करने पर महंगे रास्टराइज़ेशन की ज़रूरत होगी. हर पेंट समूह के लिए एक कंपोज़िट लेयर बनाई जा सकती है और उसे अलग-अलग रास्टराइज़ किया जा सकता है, ताकि सभी रास्टराइज़ेशन से बचा जा सके. हालांकि, इससे जीपीयू की मेमोरी जल्दी खत्म हो जाएगी. लेयराइज़्ड चरण में जीपीयू मेमोरी और चीज़ों के बदलने पर लागत कम करने के बीच संतुलन बनाना पड़ता है. एक अच्छा सामान्य तरीका यह है कि कई हिस्सों को डिफ़ॉल्ट रूप से मर्ज किया जाए. साथ ही, उन पेंट हिस्सों को मर्ज न करें जिनमें प्रॉपर्टी ट्री स्टेट हैं और जिनसे कंपोज़िटर थ्रेड पर बदलाव होने की उम्मीद होती है, जैसे कि कंपोज़िटर-थ्रेड स्क्रोलिंग या कंपोज़िटर-थ्रेड से हुए ट्रांसफ़ॉर्म ऐनिमेशन.
पिछले उदाहरण में, आम तौर पर दो कंपोज़िट लेयर बनाई जानी चाहिए:
- ड्रॉइंग के निर्देशों वाली 800x600 की कंपोज़िट की गई लेयर:
- 800x600 साइज़ और सफ़ेद रंग वाला
drawRect
- स्थिति 0,0 पर और गुलाबी रंग पर 100x100 साइज़ वाला
drawRect
- 800x600 साइज़ और सफ़ेद रंग वाला
- ड्रॉइंग के निर्देशों वाली 144x224 कंपोज़िट की गई लेयर:
drawTextBlob
की जगह 0,0 है और टेक्स्ट "नमस्ते दुनिया" है- 0,18 का अनुवाद करें
rotateZ(25deg)
drawRect
की जगह 0,0 पर 75x200 का साइज़ और नारंगी रंगdrawTextBlob
की जगह 0,0 है और "मैं गिर रहा/रही हूं" टेक्स्ट
अगर उपयोगकर्ता #scroll
को स्क्रोल करता है,
तो दूसरी कंपोज़िट की गई लेयर को ट्रांसफ़र कर दिया जाता है, लेकिन रास्टराइज़ेशन की ज़रूरत नहीं होती.
उदाहरण के लिए यहां, प्रॉपर्टी ट्री के पिछले सेक्शन से, पेंट के छह हिस्से दिए गए हैं. प्रॉपर्टी ट्री की स्थितियों (ट्रांसफ़ॉर्म, क्लिप, इफ़ेक्ट, स्क्रोल) के साथ, वे इस तरह होती हैं:
- दस्तावेज़ का बैकग्राउंड: दस्तावेज़ स्क्रोल, दस्तावेज़ की क्लिप, रूट, दस्तावेज़ स्क्रोल.
- डीव के लिए हॉरिज़ॉन्टल, वर्टिकल, और स्क्रोल कॉर्नर (तीन अलग-अलग पेंट समूह):
दस्तावेज़ स्क्रोल, दस्तावेज़ क्लिप,
#one
ब्लर, दस्तावेज़ स्क्रोल. - Iframe
#one
:#one
घुमाएं, ओवरफ़्लो स्क्रोल क्लिप,#one
ब्लर, डीआईवी स्क्रोल. - Iframe
#two
:#two
स्केल, दस्तावेज़ क्लिप, रूट, दस्तावेज़ स्क्रोल.
कंपोज़िटर फ़्रेम: सरफ़ेस, रेंडर सरफ़ेस और जीपीयू टेक्स्चर टाइल
जैसा कि पिछली पोस्ट में बताया गया था (यहां दिया गया है), ब्राउज़र और रेंडर करने की प्रोसेस, कॉन्टेंट के रास्टराइज़ेशन को मैनेज करती हैं. इसके बाद, स्क्रीन पर प्रज़ेंटेशन के लिए कंपोज़िटर फ़्रेम को Viz प्रोसेस में सबमिट करें. कंपोज़िटर फ़्रेम की मदद से RenderingNG का इस्तेमाल करके, रास्टराइज़ किए गए कॉन्टेंट को एक साथ जोड़ने और जीपीयू का इस्तेमाल करके उसे बेहतर तरीके से ड्रॉ करने का तरीका पता चलता है.
टाइल
सिद्धांत में, रेंडर प्रोसेस या ब्राउज़र प्रोसेस कंपोज़िटर, रेंडरर व्यूपोर्ट के पूरे साइज़ की एक बनावट में पिक्सल की वैल्यू बढ़ा सकता है और उस टेक्सचर को Viz पर सबमिट कर सकता है. इसे दिखाने के लिए, डिसप्ले कंपोज़िटर को उस एक टेक्सचर से फ़्रेम बफ़र में सही जगह पर पिक्सल कॉपी करना होगा (उदाहरण के लिए, स्क्रीन). हालांकि, अगर उस कंपोज़िटर को एक पिक्सल भी अपडेट करना हो, तो उसे पूरे व्यूपोर्ट को फिर से तय करना होगा और Viz पर एक नया टेक्सचर सबमिट करना होगा.
इसके बजाय, व्यूपोर्ट को टाइल में बांट दिया जाता है. एक अलग जीपीयू टेक्सचर टाइल, हर टाइल को व्यूपोर्ट के हिस्से के लिए रास्टराइज़्ड पिक्सल के साथ बैक करती है. उसके बाद रेंडरर अलग-अलग टाइल को अपडेट कर सकता है या स्क्रीन पर मौजूद टाइल की जगह भी बदल सकता है. उदाहरण के लिए, किसी वेबसाइट को स्क्रोल करते समय, मौजूदा टाइल की जगह ऊपर बदल जाएगी और कभी-कभी पेज पर और नीचे कॉन्टेंट डालने के लिए, नई टाइल को रास्टराइज़ करने की ज़रूरत होती है.
ऊपर दी गई इमेज में, चार टाइल के साथ खिली धूप का दिन दिखाया गया है. स्क्रोल करने पर पांचवीं टाइल दिखने लगती है. इनमें से एक टाइल का सिर्फ़ एक रंग (आसमान नीला) है और उसके सबसे ऊपर एक वीडियो और एक iframe है. जो अगले विषय पर ले जाता है.
क्वाड और सरफ़ेस
जीपीयू टेक्सचर टाइल एक खास तरह की क्वाड होती हैं, जो किसी एक कैटगरी की या किसी दूसरी कैटगरी के लिए सिर्फ़ एक फ़ैंसी नाम है. क्वाड इनपुट टेक्सचर की पहचान करता है और यह बताता है कि विज़ुअल इफ़ेक्ट को कैसे बदलना और उसमें कैसे लागू करना है. उदाहरण के लिए, सामान्य कॉन्टेंट टाइल में एक ट्रांसफ़ॉर्म होता है जो टाइल ग्रिड में उनकी x, y स्थिति को दिखाता है.
रास्टराइज़ की गई इन टाइल को रेंडर पास में रैप किया जाता है, जो क्वाड की सूची होता है. रेंडर पास में पिक्सल की कोई जानकारी नहीं होती; इसके बजाय, इसमें यह निर्देश होता है कि पसंद के मुताबिक पिक्सल आउटपुट बनाने के लिए हर क्वाड को कहां और कैसे ड्रॉ करना है. हर जीपीयू टेक्सचर टाइल के लिए ड्रॉ क्वाड होता है. रेंडर पास के लिए मनमुताबिक पिक्सल आउटपुट पाने के लिए, डिसप्ले कंपोज़िटर को बस क्वाड की सूची को दोहराना होता है और हर को तय विज़ुअल इफ़ेक्ट के साथ बनाना होता है. रेंडर पास के लिए कंपोज़िटिंग ड्रॉ क्वाड, जीपीयू पर बेहतर तरीके से किए जा सकते हैं. क्योंकि अनुमति वाले विज़ुअल इफ़ेक्ट को ध्यान से चुना जाता है, जो सीधे जीपीयू सुविधाओं से मैप करते हैं.
रास्टराइज़्ड टाइल के अलावा, कई तरह के ड्रॉ क्वाड भी होते हैं. उदाहरण के लिए, ऐसे सॉलिड कलर ड्रॉ क्वाड होते हैं जो किसी भी टेक्सचर के साथ काम नहीं करते या वीडियो या कैनवस जैसी नॉन-टाइल टेक्सचर के लिए टेक्स्ट ड्रॉ क्वाड.
किसी कंपोज़िटर फ़्रेम के लिए भी एक अन्य कंपोज़िटर फ़्रेम को एम्बेड करना संभव है. उदाहरण के लिए, ब्राउज़र कंपोज़िटर, ब्राउज़र यूज़र इंटरफ़ेस (यूआई) के साथ एक कंपोज़िटर फ़्रेम बनाता है. साथ ही, एक खाली रेक्टैंगल, जहां रेंडर कंपोज़िटर कॉन्टेंट को एम्बेड किया जाएगा. दूसरा उदाहरण, साइट के लिए आइसोलेटेड iframe है. वीडियो को प्लैटफ़ॉर्म से एम्बेड किया जाता है.
जब कोई कंपोज़िटर फ़्रेम सबमिट करता है, तो उसके साथ एक आइडेंटिफ़ायर जुड़ा होता है, जिसे सरफ़ेस आईडी कहा जाता है. इसकी मदद से, दूसरे कंपोज़िटर फ़्रेम रेफ़रंस के हिसाब से उसे एम्बेड कर सकते हैं. किसी खास सरफ़ेस आईडी के साथ सबमिट किया गया सबसे नया कंपोज़िटर फ़्रेम Viz स्टोर करता है. इसके बाद, कोई दूसरा कंपोज़िटर फ़्रेम सरफ़ेस ड्रॉ क्वाड के ज़रिए इसका इस्तेमाल कर सकता है, इसलिए Viz को पता है कि क्या बनाना है. (ध्यान दें कि सरफ़ेस ड्रॉ क्वाड में सिर्फ़ सरफ़ेस आईडी होते हैं, न कि टेक्सचर.)
बीच के लेवल पर रेंडर होने वाले पास
कुछ विज़ुअल इफ़ेक्ट, जैसे कि कई फ़िल्टर या ऐडवांस ब्लेंड मोड के लिए ज़रूरी होता है कि दो या उससे ज़्यादा क्वाड इंटरमीडिएट टेक्सचर की ओर खींचें. इसके बाद, विज़ुअल इफ़ेक्ट को उसी समय लागू करते हुए इंटरमीडिएट टेक्सचर को जीपीयू पर (या किसी अन्य इंटरमीडिएट टेक्सचर) पर, डेस्टिनेशन बफ़र में ड्रॉ किया जाता है. इसकी अनुमति देने के लिए, कंपोज़िटर फ़्रेम में असल में रेंडर पास की सूची होती है. इसमें हमेशा एक रूट रेंडर पास होता है, जिसे सबसे आखिर में खींचा जाता है और जिसका डेस्टिनेशन फ़्रेम बफ़र से मेल खाता है. इसके अलावा, और भी ज़्यादा हो सकते हैं.
एक से ज़्यादा रेंडर पास होने की संभावना के बारे में पता चलता है कि "रेंडर पास" क्या है. हर पास को जीपीयू पर एक साथ कई "पास" में लागू किया जाता है. इसमें एक पास को बहुत ज़्यादा पैरलल जीपीयू कंप्यूटेशन में पूरा किया जा सकता है.
एक साथ दिखाना
Viz को कई कंपोज़िटर फ़्रेम सबमिट किए गए हैं, और उन्हें एक साथ स्क्रीन पर ड्रॉ करना होगा. यह एग्रीगेशन चरण से पूरा किया जाता है जो उन्हें एक ही, एग्रीगेट किए गए कंपोज़िटर फ़्रेम में बदल देता है. एग्रीगेशन, सरफ़ेस ड्रॉ क्वाड को उनके तय किए गए कंपोज़िटर फ़्रेम से बदल देता है. इसकी मदद से, ग़ैर-ज़रूरी इंटरमीडिएट टेक्सचर या ऑफ़स्क्रीन कॉन्टेंट को भी बेहतर तरीके से ऑप्टिमाइज़ किया जा सकता है. उदाहरण के लिए, कई मामलों में किसी साइट से अलग किए गए iframe के लिए कंपोज़िटर फ़्रेम को अपनी खुद की इंटरमीडिएट बनावट की ज़रूरत नहीं होती. साथ ही, इसे सही ड्रॉ क्वाड के ज़रिए सीधे फ़्रेम बफ़र में खींचा जा सकता है. एग्रीगेशन फ़ेज़ में ऐसे ऑप्टिमाइज़ेशन का पता लगाया जाता है और उन्हें ग्लोबल उस जानकारी के आधार पर लागू किया जाता है जो अलग-अलग रेंडर कंपोज़िटर की पहुंच से बाहर होती हैं.
उदाहरण
यहां असल कंपोज़िटर फ़्रेम दिए गए हैं जो इस पोस्ट की शुरुआत से उदाहरण को दिखाते हैं.
foo.com/index.html
प्लैटफ़ॉर्म: id=0- रेंडर पास 0: आउटपुट पर ड्रॉ करें.
- पास ड्रॉ क्वाड रेंडर करें: 3 पिक्सल ब्लर और क्लिप को रेंडर पास 0 में बनाएं.
- रेंडर पास 1:
#one
iframe की टाइल के कॉन्टेंट के लिए, क्वाड बनाएं. इसमें हर एक के लिए x और y की पोज़िशन का इस्तेमाल करें.
- रेंडर पास 1:
- सर्फ़ेस ड्रॉ क्वॉड: आईडी 2 के साथ, स्केल से बनाया गया और ट्रांसलेट ट्रांसफ़ॉर्म किया गया.
- पास ड्रॉ क्वाड रेंडर करें: 3 पिक्सल ब्लर और क्लिप को रेंडर पास 0 में बनाएं.
- रेंडर पास 0: आउटपुट पर ड्रॉ करें.
- ब्राउज़र के यूज़र इंटरफ़ेस (यूआई) का प्लैटफ़ॉर्म: आईडी=1
- रेंडर पास 0: आउटपुट पर ड्रॉ करें.
- ब्राउज़र के यूज़र इंटरफ़ेस (यूआई) के लिए क्वाड ड्रॉ करें (टाइल भी किया गया)
- रेंडर पास 0: आउटपुट पर ड्रॉ करें.
bar.com/index.html
प्लैटफ़ॉर्म: आईडी=2- रेंडर पास 0: आउटपुट पर ड्रॉ करें.
#two
iframe के कॉन्टेंट के लिए क्वाड बनाएं. इसमें हर एक के लिए x और y की पोज़िशन का इस्तेमाल करें.
- रेंडर पास 0: आउटपुट पर ड्रॉ करें.
नतीजा
पढ़ने के लिए धन्यवाद! पिछली दो पोस्ट को ध्यान में रखते हुए, यह अच्छा परफ़ॉर्म करने से जुड़ी खास जानकारी को खत्म करता है. इसके बाद, हम रेंडरिंग पाइपलाइन के कई सब-कॉम्पोनेंट में मौजूद चुनौतियों और टेक्नोलॉजी के बारे में, शुरुआत से लेकर आखिर तक जानेंगे. यह सुविधा जल्द ही उपलब्ध होगी!
यूना क्रावेट्स के चित्र.