हार्डवेयर कंपोज़र (एचडब्ल्यूसी) एचएएल, SurfaceFlinger से मिली लेयर को कंपोज़ करता है. इससे कंपोज़िशन OpenGL ES (GLES) और जीपीयू के काम करने की क्षमता कम हो जाती है.
एचडब्ल्यूसी, ऑब्जेक्ट को ऐब्स्ट्रैक्ट करता है. जैसे, ओवरले और 2D ब्लिटर, कंपोज़िट सर्फ़ेस में. साथ ही, विंडो कंपोज़िशन के लिए खास हार्डवेयर के साथ कम्यूनिकेट करता है, ताकि विंडो कंपोज़िट की जा सकें. विंडो को कंपोज़िट करने के लिए, SurfaceFlinger को GPU के साथ कंपोज़िट करने के बजाय, HWC का इस्तेमाल करें. ज़्यादातर जीपीयू, कंपोज़िशन के लिए ऑप्टिमाइज़ नहीं किए जाते. साथ ही, जब जीपीयू, SurfaceFlinger से लेयर कंपोज़ करता है, तब ऐप्लिकेशन अपने रेंडरिंग के लिए जीपीयू का इस्तेमाल नहीं कर पाते.
HWC लागू करने के लिए, इन बातों का ध्यान रखना ज़रूरी है:
- कम से कम चार ओवरले:
- स्टेटस बार
- सिस्टम बार
- ऐप्लिकेशन
- वॉलपेपर/बैकग्राउंड
- ऐसी लेयर जो डिसप्ले से बड़ी होती हैं. उदाहरण के लिए, वॉलपेपर
- हर पिक्सल के हिसाब से पहले से गुणा किए गए ऐल्फ़ा ब्लेंडिंग और हर प्लेन के हिसाब से ऐल्फ़ा ब्लेंडिंग की सुविधा एक साथ उपलब्ध है
- सुरक्षित वीडियो चलाने के लिए हार्डवेयर पाथ
- RGBA पैकिंग ऑर्डर, YUV फ़ॉर्मैट, और टाइलिंग, स्वज़लिंग, और स्ट्राइड प्रॉपर्टी
एचडब्ल्यूसी लागू करने के लिए:
- नॉनऑपरेशनल एचडब्ल्यूसी लागू करें और कंपोज़िशन से जुड़ा सारा काम जीएलईएस को भेजें.
- एचडब्ल्यूसी को कंपोज़िशन सौंपने के लिए, एल्गोरिदम लागू करें. उदाहरण के लिए, एचडब्ल्यूसी के ओवरले हार्डवेयर को सिर्फ़ पहले तीन या चार डिसप्ले असाइन करें.
- एचडब्ल्यूसी को ऑप्टिमाइज़ करें. इसमें यह जानकारी शामिल हो सकती है:
- ऐसे डिसप्ले चुनना जिनसे जीपीयू पर पड़ने वाला लोड कम हो जाता है और उन्हें एचडब्ल्यूसी को भेजना.
- यह कुकी यह पता लगाती है कि स्क्रीन अपडेट हो रही है या नहीं. अगर ऐसा नहीं है, तो बैटरी बचाने के लिए, कंपोज़िशन को HWC के बजाय GLES को सौंपें. स्क्रीन के फिर से अपडेट होने पर, कंपोज़िशन को एचडब्ल्यूसी पर ऑफ़लोड करना जारी रखें.
- इस्तेमाल के सामान्य उदाहरणों के लिए तैयारी करना. जैसे:
- होम स्क्रीन, जिसमें स्टेटस बार, सिस्टम बार, ऐप्लिकेशन विंडो, और लाइव वॉलपेपर शामिल हैं
- पोर्ट्रेट और लैंडस्केप मोड में फ़ुल-स्क्रीन गेम
- सबटाइटल और वीडियो चलाने के कंट्रोल के साथ फ़ुल-स्क्रीन वीडियो
- सुरक्षित वीडियो चलाने की सुविधा
- स्प्लिट स्क्रीन मल्टीविंडो
HWC प्रिमिटिव
एचडब्ल्यूसी, कंपोज़िशन के काम और डिसप्ले हार्डवेयर के साथ इसके इंटरैक्शन को दिखाने के लिए, दो प्रिमिटिव उपलब्ध कराता है: लेयर और डिसप्ले. एचडब्ल्यूसी, वीसिंक को कंट्रोल करने की सुविधा भी देता है. साथ ही, SurfaceFlinger को एक कॉलबैक देता है, ताकि वीसिंक इवेंट होने पर उसे सूचना दी जा सके.
HIDL इंटरफ़ेस
Android 8.0 और इसके बाद के वर्शन में, HWC और SurfaceFlinger के बीच बाइंडर वाले आईपीसी के लिए, कंपोज़र एचएएल नाम के एचआईडीएल इंटरफ़ेस का इस्तेमाल किया जाता है. Composer HAL, लेगसी hwcomposer2.h इंटरफ़ेस की जगह लेता है. अगर वेंडर, एचडब्ल्यूसी का कंपोज़र एचएएल
लागू करते हैं, तो कंपोज़र एचएएल सीधे तौर पर SurfaceFlinger से HIDL कॉल स्वीकार करता है. अगर वेंडर, एचडब्ल्यूसी का लेगसी वर्शन उपलब्ध कराते हैं, तो कंपोज़र एचएएल, hwcomposer2.h से फ़ंक्शन पॉइंटर लोड करता है. साथ ही, एचआईडीएल कॉल को फ़ंक्शन पॉइंटर कॉल में फ़ॉरवर्ड करता है.
एचडब्ल्यूसी, किसी डिसप्ले की प्रॉपर्टी तय करने के लिए फ़ंक्शन उपलब्ध कराता है. साथ ही, यह अलग-अलग डिसप्ले कॉन्फ़िगरेशन (जैसे, 4K या 1080p रिज़ॉल्यूशन) और कलर मोड (जैसे, नेटिव कलर या ट्रू sRGB) के बीच स्विच करने की सुविधा देता है. इसके अलावा, अगर डिसप्ले में यह सुविधा काम करती है, तो एचडब्ल्यूसी डिसप्ले को चालू, बंद या कम पावर वाले मोड में सेट कर सकता है.
फ़ंक्शन पॉइंटर
अगर वेंडर, कंपोज़र एचएएल को सीधे तौर पर लागू करते हैं, तो SurfaceFlinger, HIDL IPC के ज़रिए इसके फ़ंक्शन को कॉल करता है. उदाहरण के लिए, लेयर बनाने के लिए SurfaceFlinger, Composer HAL पर createLayer() कॉल करता है.
अगर वेंडर hwcomposer2.h इंटरफ़ेस लागू करते हैं, तो कंपोज़र HAL, hwcomposer2.h फ़ंक्शन पॉइंटर को कॉल करता है. hwcomposer2.h टिप्पणियों में, HWC इंटरफ़ेस फ़ंक्शन को lowerCamelCase नामों से रेफ़र किया जाता है. ये नाम, इंटरफ़ेस में नाम वाले फ़ील्ड के तौर पर मौजूद नहीं होते. getFunction की मदद से फ़ंक्शन पॉइंटर का अनुरोध करके, करीब-करीब हर फ़ंक्शन को लोड किया जाता है.hwc2_device_t उदाहरण के लिए, createLayer फ़ंक्शन, HWC2_PFN_CREATE_LAYER टाइप का फ़ंक्शन पॉइंटर है. यह तब दिखता है, जब HWC2_FUNCTION_CREATE_LAYER की गिनती की गई वैल्यू को getFunction में पास किया जाता है.
Composer HAL फ़ंक्शन और HWC फ़ंक्शन पासथ्रू फ़ंक्शन के बारे में ज़्यादा जानकारी के लिए, composer देखें. एचडब्ल्यूसी फ़ंक्शन पॉइंटर के बारे में ज़्यादा जानकारी के लिए, hwcomposer2.h देखें.
लेयर और डिसप्ले हैंडल
लेयर और डिसप्ले को HWC से जनरेट किए गए हैंडल से कंट्रोल किया जाता है. हैंडल, SurfaceFlinger के लिए ओपेक होते हैं.
जब SurfaceFlinger कोई नई लेयर बनाता है, तो वह createLayer को कॉल करता है. यह डायरेक्ट इंप्लीमेंटेशन के लिए Layer या पासथ्रू इंप्लीमेंटेशन के लिए hwc2_layer_t टाइप दिखाता है. जब SurfaceFlinger उस लेयर की किसी प्रॉपर्टी में बदलाव करता है, तब SurfaceFlinger, hwc2_layer_t वैल्यू को बदलाव करने वाले फ़ंक्शन में भेजता है. साथ ही, बदलाव करने के लिए ज़रूरी अन्य जानकारी भी भेजता है. hwc2_layer_t टाइप इतना बड़ा होता है कि इसमें पॉइंटर या इंडेक्स, दोनों को सेव किया जा सकता है.
फ़िजिकल डिसप्ले, हॉटप्लग करके बनाए जाते हैं. जब किसी फ़िज़िकल डिसप्ले को हॉटप्लग किया जाता है, तब एचडब्ल्यूसी एक हैंडल बनाता है और हॉटप्लग कॉलबैक के ज़रिए, उस हैंडल को SurfaceFlinger को पास करता है. वर्चुअल डिसप्ले, SurfaceFlinger createVirtualDisplay() को कॉल करके बनाए जाते हैं, ताकि डिसप्ले का अनुरोध किया जा सके. अगर एचडब्ल्यूसी, वर्चुअल डिसप्ले कंपोज़िशन के साथ काम करता है, तो यह एक हैंडल दिखाता है. इसके बाद, SurfaceFlinger, डिसप्ले की कंपोज़िशन को HWC को सौंप देता है. अगर एचडब्ल्यूसी, वर्चुअल डिसप्ले कंपोज़िशन के साथ काम नहीं करता है, तो SurfaceFlinger हैंडल बनाता है और डिसप्ले को कंपोज़ करता है.
डिसप्ले कंपोज़िशन से जुड़ी कार्रवाइयां
हर VSync पर, SurfaceFlinger तब चालू होता है, जब उसके पास कंपोज़ करने के लिए नया कॉन्टेंट होता है. यह नया कॉन्टेंट, ऐप्लिकेशन से मिले नए इमेज बफ़र या एक या उससे ज़्यादा लेयर की प्रॉपर्टी में बदलाव हो सकता है. SurfaceFlinger के चालू होने पर:
- अगर मौजूद हो, तो लेन-देन मैनेज करता है.
- अगर नए ग्राफ़िक बफ़र मौजूद हैं, तो उन्हें लैच करता है.
- अगर पहले या दूसरे चरण में डिसप्ले कॉन्टेंट में बदलाव हुआ है, तो नई कंपोज़िशन बनाता है.
नई कंपोज़िशन बनाने के लिए, SurfaceFlinger ज़रूरत के हिसाब से लेयर बनाता है और उन्हें मिटाता है या लेयर की स्थितियों में बदलाव करता है. यह setLayerBuffer या setLayerColor जैसे कॉल का इस्तेमाल करके, लेयर को उनके मौजूदा कॉन्टेंट के साथ अपडेट भी करता है. सभी लेयर अपडेट होने के बाद, SurfaceFlinger, validateDisplay को कॉल करता है. इससे HWC को लेयर की स्थिति की जांच करने और यह तय करने के लिए कहा जाता है कि कंपोज़िशन कैसे आगे बढ़ेगी. डिफ़ॉल्ट रूप से, SurfaceFlinger हर लेयर को इस तरह से कॉन्फ़िगर करने की कोशिश करता है कि लेयर को HWC कंपोज़िट करे. हालांकि, कुछ मामलों में SurfaceFlinger, GPU फ़ॉलबैक के ज़रिए लेयर कंपोज़िट करता है.
validateDisplay को कॉल करने के बाद, SurfaceFlinger getChangedCompositionTypes को कॉल करता है. इससे यह पता चलता है कि कंपोज़िशन करने से पहले, HWC को लेयर कंपोज़िशन के किसी टाइप में बदलाव करना है या नहीं. बदलावों को स्वीकार करने के लिए, SurfaceFlinger acceptDisplayChanges को कॉल करता है.
अगर किसी लेयर को SurfaceFlinger कंपोज़िशन के लिए मार्क किया गया है, तो SurfaceFlinger उन्हें टारगेट बफ़र में कंपोज़ करता है. इसके बाद, SurfaceFlinger, डिसप्ले को बफ़र देने के लिए setClientTarget को कॉल करता है, ताकि बफ़र को स्क्रीन पर दिखाया जा सके या उन लेयर के साथ कंपोज़ किया जा सके जिन्हें SurfaceFlinger कंपोज़िशन के लिए मार्क नहीं किया गया है. अगर किसी लेयर को SurfaceFlinger कंपोज़िशन के लिए मार्क नहीं किया गया है, तो SurfaceFlinger कंपोज़िशन वाले चरण को छोड़ देता है.
आखिर में, SurfaceFlinger, HWC को presentDisplay कॉल करता है, ताकि वह कंपोज़िशन की प्रोसेस पूरी कर सके और फ़ाइनल नतीजे को दिखा सके.
एक से ज़्यादा डिसप्ले
Android 10 में, एक से ज़्यादा फ़िज़िकल डिसप्ले इस्तेमाल किए जा सकते हैं. Android 7.0 और इसके बाद के वर्शन पर इस्तेमाल करने के लिए, HWC लागू करते समय कुछ पाबंदियां होती हैं. ये पाबंदियां, HWC की परिभाषा में मौजूद नहीं होतीं:
- यह माना जाता है कि सिर्फ़ एक इंटरनल डिसप्ले होता है. इंटरनल डिसप्ले वह डिसप्ले होता है जिसकी जानकारी, बूट के दौरान हॉटप्लग की शुरुआती रिपोर्ट में दी जाती है. इंटरनल डिसप्ले को हॉटप्लग करने के बाद, इसे डिसकनेक्ट नहीं किया जा सकता.
- डिवाइस के सामान्य तौर पर काम करने के दौरान, इंटरनल डिसप्ले के अलावा, किसी भी संख्या में बाहरी डिसप्ले को हॉटप्लग किया जा सकता है. फ़्रेमवर्क यह मानता है कि पहले इंटरनल डिसप्ले के बाद सभी हॉटप्लग, बाहरी डिसप्ले होते हैं. इसलिए, अगर कोई और इंटरनल डिसप्ले जोड़ा जाता है, तो उसे
Display.TYPE_HDMIके बजायDisplay.TYPE_BUILT_INके तौर पर गलत तरीके से कैटगरी में रखा जाता है.
ऊपर बताई गई SurfaceFlinger कार्रवाइयां, हर डिसप्ले के लिए की जाती हैं. हालांकि, ये सभी चालू डिसप्ले के लिए क्रम से की जाती हैं. भले ही, सिर्फ़ एक डिसप्ले का कॉन्टेंट अपडेट किया गया हो.
उदाहरण के लिए, अगर बाहरी डिसप्ले को अपडेट किया जाता है, तो क्रम इस तरह होगा:
// In Android 9 and lower: // Update state for internal display // Update state for external display validateDisplay(<internal display>) validateDisplay(<external display>) presentDisplay(<internal display>) presentDisplay(<external display>) // In Android 10 and higher: // Update state for internal display // Update state for external display validateInternal(<internal display>) presentInternal(<internal display>) validateExternal(<external display>) presentExternal(<external display>)
वर्चुअल डिसप्ले कंपोज़िशन
वर्चुअल डिसप्ले कंपोज़िशन, बाहरी डिसप्ले कंपोज़िशन की तरह ही होता है. वर्चुअल डिसप्ले कंपोज़िशन और फ़िज़िकल डिसप्ले कंपोज़िशन के बीच का अंतर यह है कि वर्चुअल डिसप्ले, स्क्रीन के बजाय Gralloc बफ़र को आउटपुट भेजते हैं. हार्डवेयर कंपोज़र (एचडब्ल्यूसी) आउटपुट को बफ़र में लिखता है, पूरा होने की जानकारी देता है, और बफ़र को किसी उपभोक्ता (जैसे कि वीडियो एन्कोडर, जीपीयू, सीपीयू वगैरह) को भेजता है. अगर डिसप्ले पाइपलाइन मेमोरी में लिखती है, तो वर्चुअल डिसप्ले 2D/ब्लिटर या ओवरले का इस्तेमाल कर सकते हैं.
मोड
SurfaceFlinger के validateDisplay() HWC तरीके को कॉल करने के बाद, हर फ़्रेम तीन में से किसी एक मोड में होता है:
- GLES — इस मोड में, जीपीयू सभी लेयर को कंपोज़ करता है और सीधे आउटपुट बफ़र में लिखता है. एचडब्ल्यूसी, कंपोज़िशन में शामिल नहीं है.
- MIXED — इस मोड में, GPU कुछ लेयर को फ़्रेमबफ़र में कंपोज़ करता है. वहीं, HWC फ़्रेमबफ़र और बाकी लेयर को कंपोज़ करता है. साथ ही, आउटपुट बफ़र में सीधे तौर पर लिखता है.
- HWC — HWC, सभी लेयर को कंपोज़ करता है और सीधे तौर पर आउटपुट बफ़र में लिखता है.
आउटपुट फ़ॉर्मैट
वर्चुअल डिसप्ले बफ़र के आउटपुट फ़ॉर्मैट, उनके मोड पर निर्भर करते हैं:
- GLES मोड — EGL ड्राइवर, आउटपुट बफ़र के फ़ॉर्मैट को
dequeueBuffer()में सेट करता है. आम तौर पर, यहRGBA_8888होता है. उपयोगकर्ता को, ड्राइवर के सेट किए गए आउटपुट फ़ॉर्मैट को स्वीकार करना होगा. ऐसा न करने पर, बफ़र को नहीं पढ़ा जा सकेगा. - मिक्स और एचडब्ल्यूसी मोड — अगर उपभोक्ता को सीपीयू ऐक्सेस करने की ज़रूरत है, तो उपभोक्ता फ़ॉर्मैट सेट करता है. इसके अलावा, फ़ॉर्मैट
IMPLEMENTATION_DEFINEDहै. साथ ही, Gralloc, इस्तेमाल के फ़्लैग के आधार पर सबसे सही फ़ॉर्मैट सेट करता है. उदाहरण के लिए, अगर उपभोक्ता वीडियो एन्कोडर है और HWC इस फ़ॉर्मैट को बेहतर तरीके से लिख सकता है, तो Gralloc YCbCr फ़ॉर्मैट सेट करता है.
सिंक्रनाइज़ेशन फ़ेंस
सिंक्रनाइज़ेशन (सिंक) फ़ेंस, Android ग्राफ़िक्स सिस्टम का एक अहम हिस्सा हैं. फ़ेंस की मदद से, सीपीयू का काम जीपीयू के काम से अलग होता है. इसलिए, सीपीयू का काम सिर्फ़ तब रुकता है, जब जीपीयू के काम पर निर्भरता होती है.
उदाहरण के लिए, जब कोई ऐप्लिकेशन GPU पर बनाए जा रहे बफ़र को सबमिट करता है, तो वह सिंक फ़ेंस ऑब्जेक्ट भी सबमिट करता है. यह फ़ेंस तब सिग्नल देता है, जब जीपीयू बफ़र में डेटा लिख लेता है.
एचडब्ल्यूसी को यह ज़रूरी है कि जीपीयू, बफ़र को दिखाने से पहले बफ़र में लिखना पूरा कर ले. सिंक फ़ेंस को ग्राफ़िक्स पाइपलाइन के ज़रिए बफ़र और सिग्नल के साथ पास किया जाता है. ऐसा तब होता है, जब बफ़र लिखे जाते हैं. बफ़र दिखने से पहले, एचडब्ल्यूसी यह देखता है कि सिंक फ़ेंस ने सिग्नल दिया है या नहीं. अगर सिग्नल दिया गया है, तो वह बफ़र दिखाता है.
सिंक फ़ेंस के बारे में ज़्यादा जानकारी के लिए, Hardware Composer Integration देखें.