लेयर और डिसप्ले

लेयर और डिसप्ले, दो प्रिमिटिव हैं. ये कंपोज़िशन और डिसप्ले हार्डवेयर के साथ इंटरैक्शन को दिखाते हैं.

परतें

लेयर, कंपोज़िशन की सबसे अहम यूनिट होती है. लेयर, सरफ़ेस और SurfaceControl के इंस्टेंस का कॉम्बिनेशन होती है. हर लेयर में प्रॉपर्टी का एक सेट होता है. इससे यह तय होता है कि लेयर, दूसरी लेयर के साथ कैसे इंटरैक्ट करेगी. लेयर की प्रॉपर्टी के बारे में यहां दी गई टेबल में बताया गया है:

प्रॉपर्टी ब्यौरा
पोज़िशनल इससे यह तय होता है कि लेयर, डिसप्ले पर कहां दिखेगी. इसमें लेयर की सीमाओं की पोज़िशन और अन्य लेयर के मुकाबले उसका Z क्रम जैसी जानकारी शामिल होती है. इससे यह तय होता है कि लेयर को अन्य लेयर के आगे या पीछे होना चाहिए.
कॉन्टेंट इससे यह तय होता है कि लेयर पर दिखने वाले कॉन्टेंट को, पोज़िशन से जुड़ी प्रॉपर्टी के तय किए गए दायरे में कैसे दिखाया जाना चाहिए. इसमें क्रॉप करने (कॉन्टेंट के किसी हिस्से को बड़ा करके लेयर की सीमाओं में फ़िट करने के लिए) और ट्रांसफ़ॉर्म करने (घुमाया गया या फ़्लिप किया गया कॉन्टेंट दिखाने के लिए) जैसी जानकारी शामिल होती है.
कंपोज़िशन इससे यह तय किया जाता है कि लेयर को दूसरी लेयर के साथ कैसे कंपोज़ किया जाना चाहिए. इसमें अल्फ़ा कंपोज़िटिंग के लिए, ब्लेंडिंग मोड और लेयर-वाइड अल्फ़ा वैल्यू जैसी जानकारी शामिल होती है.
ऑप्टिमाइज़ेशन यह ऐसी जानकारी देता है जो लेयर को सही तरीके से कंपोज़ करने के लिए ज़रूरी नहीं है. हालांकि, इसका इस्तेमाल हार्डवेयर कंपोज़र (एचडब्ल्यूसी) डिवाइस कर सकता है, ताकि कंपोज़िशन की परफ़ॉर्मेंस को ऑप्टिमाइज़ किया जा सके. इसमें लेयर के दिखने वाले हिस्से और पिछले फ़्रेम के बाद लेयर के किस हिस्से को अपडेट किया गया है, जैसी जानकारी शामिल होती है.

डिसप्ले

डिसप्ले, कंपोज़िशन की एक और अहम यूनिट है. किसी सिस्टम में एक से ज़्यादा डिसप्ले हो सकते हैं. साथ ही, सिस्टम के सामान्य ऑपरेशन के दौरान डिसप्ले जोड़े या हटाए जा सकते हैं. डिस्प्ले, एचडब्ल्यूसी के अनुरोध पर या फ़्रेमवर्क के अनुरोध पर जोड़े या हटाए जाते हैं. जब किसी डिवाइस से कोई बाहरी डिसप्ले कनेक्ट या डिसकनेक्ट किया जाता है, तो HWC डिवाइस, डिसप्ले को जोड़ने या हटाने का अनुरोध करता है. इसे हॉटप्लगिंग कहा जाता है. क्लाइंट, वर्चुअल डिसप्ले का अनुरोध करते हैं. इनका कॉन्टेंट, फ़िज़िकल डिसप्ले के बजाय, ऑफ़-स्क्रीन बफ़र में रेंडर किया जाता है.

वर्चुअल डिसप्ले

SurfaceFlinger इनके साथ काम करता है: फ़ोन या टैबलेट में बना इंटरनल डिसप्ले, एचडीएमआई से कनेक्ट किए गए टीवी जैसे एक्सटर्नल डिसप्ले, और एक या उससे ज़्यादा वर्चुअल डिसप्ले. ये वर्चुअल डिसप्ले, सिस्टम में कंपोज़िट आउटपुट उपलब्ध कराते हैं. वर्चुअल डिसप्ले का इस्तेमाल, स्क्रीन रिकॉर्ड करने या स्क्रीन को नेटवर्क पर भेजने के लिए किया जा सकता है. वर्चुअल डिसप्ले के लिए जनरेट किए गए फ़्रेम, BufferQueue में लिखे जाते हैं.

वर्चुअल डिसप्ले, मुख्य डिसप्ले (लेयर स्टैक) के साथ लेयर का एक ही सेट शेयर कर सकते हैं या उनका अपना सेट हो सकता है. वर्चुअल डिसप्ले के लिए कोई VSync नहीं है. इसलिए, इंटरनल डिसप्ले के लिए VSync, सभी डिसप्ले के लिए कंपोज़िशन को ट्रिगर करता है.

एचडब्ल्यूसी के ऐसे वर्शन जिन पर ये सुविधाएं काम करती हैं उनमें वर्चुअल डिसप्ले को OpenGL ES (GLES), एचडब्ल्यूसी या GLES और एचडब्ल्यूसी, दोनों के साथ कंपोज़ किया जा सकता है. जिन डिवाइसों पर वर्चुअल डिसप्ले काम नहीं करते हैं उन पर, वर्चुअल डिसप्ले को हमेशा GLES का इस्तेमाल करके कंपोज़ किया जाता है.

केस स्टडी: screenrecord

screenrecord कमांड की मदद से उपयोगकर्ता, स्क्रीन पर दिखने वाली हर चीज़ को डिस्क पर MP4 फ़ाइल के तौर पर रिकॉर्ड कर सकता है. इसे लागू करने के लिए, सिस्टम को SurfaceFlinger से कंपोज़ किए गए फ़्रेम मिलते हैं. इसके बाद, सिस्टम उन्हें वीडियो एन्कोडर में लिखता है. इसके बाद, एन्कोड किए गए वीडियो डेटा को फ़ाइल में लिखता है. वीडियो कोडेक को एक अलग प्रोसेस (mediaserver) मैनेज करती है. इसलिए, बड़े ग्राफ़िक बफ़र को सिस्टम में इधर-उधर ले जाना पड़ता है. इसे और भी मुश्किल बनाने के लिए, फ़ुल रिज़ॉल्यूशन पर 60 एफ़पीएस वाला वीडियो रिकॉर्ड करना है. BufferQueue की मदद से, इस सुविधा को बेहतर तरीके से इस्तेमाल किया जा सकता है.

MediaCodec क्लास की मदद से, कोई ऐप्लिकेशन डेटा को बफ़र में रॉ बाइट के तौर पर या किसी सर्फ़ेस के ज़रिए उपलब्ध करा सकता है. जब screenrecord किसी वीडियो एनकोडर के ऐक्सेस का अनुरोध करता है, तो mediaserver प्रोसेस एक BufferQueue बनाती है. इसके बाद, यह खुद को उपभोक्ता पक्ष से कनेक्ट करती है. इसके बाद, यह प्रोड्यूसर साइड को screenrecord को एक सरफेस के तौर पर वापस भेजती है.

इसके बाद, screenrecord यूटिलिटी, SurfaceFlinger से एक वर्चुअल डिसप्ले बनाने के लिए कहती है. यह वर्चुअल डिसप्ले, मुख्य डिसप्ले की तरह ही काम करता है. इसका मतलब है कि इसमें मुख्य डिसप्ले की सभी लेयर होती हैं. साथ ही, यह वर्चुअल डिसप्ले को mediaserver प्रोसेस से मिले सर्फ़ेस पर आउटपुट भेजने का निर्देश देती है. इस मामले में, SurfaceFlinger, बफ़र का प्रोड्यूसर है, न कि कंज्यूमर.

कॉन्फ़िगरेशन पूरा होने के बाद, कोड में बदला गया डेटा दिखने पर screenrecord ट्रिगर होता है. ऐप्लिकेशन के ड्रॉ करने पर, उनके बफ़र SurfaceFlinger पर जाते हैं. SurfaceFlinger, इन बफ़र को एक बफ़र में कंपोज़ करता है. इसके बाद, इस बफ़र को सीधे mediaserver प्रोसेस में वीडियो एन्कोडर को भेजा जाता है. पूरे फ़्रेम, screenrecord प्रोसेस को कभी नहीं दिखते. आंतरिक तौर पर, mediaserver प्रोसेस में बफ़र को इधर-उधर ले जाने का अपना तरीका होता है. यह हैंडल के ज़रिए भी डेटा पास करता है, जिससे ओवरहेड कम हो जाता है.

केस स्टडी: अतिरिक्त वर्चुअल डिसप्ले बनाने की सेटिंग

WindowManager, SurfaceFlinger से एक ऐसी लेयर बनाने के लिए कह सकता है जो दिखती हो. इसके लिए, SurfaceFlinger, BufferQueue उपभोक्ता के तौर पर काम करता है. SurfaceFlinger से वर्चुअल डिसप्ले बनाने के लिए भी कहा जा सकता है. इसके लिए, SurfaceFlinger BufferQueue प्रोड्यूसर के तौर पर काम करता है.

अगर किसी वर्चुअल डिसप्ले को दिखने वाली लेयर से कनेक्ट किया जाता है, तो एक क्लोज़्ड लूप बनता है. इसमें कंपोज़िट की गई स्क्रीन, विंडो में दिखती है. अब वह विंडो, कंपोज़िट किए गए आउटपुट का हिस्सा है. इसलिए, अगली बार रीफ़्रेश करने पर, विंडो के अंदर कंपोज़िट की गई इमेज में विंडो का कॉन्टेंट भी दिखेगा. इसे आज़माने के लिए, सेटिंग में जाकर डेवलपर के लिए सेटिंग और टूल चालू करें. इसके बाद, सेकंडरी डिसप्ले सिम्युलेट करें को चुनें और कोई विंडो चालू करें. सेकंडरी डिसप्ले को ऐक्शन में देखने के लिए, screenrecord का इस्तेमाल करके डिसप्ले चालू करने की प्रोसेस को कैप्चर करें. इसके बाद, इसे फ़्रेम-दर-फ़्रेम चलाएं.