Hardware Composer HAL लागू करना

हार्डवेयर कंपोज़र (एचडब्ल्यूसी) एचएएल, SurfaceFlinger से मिली कंपोज़िट लेयर को कंपोज़ करता है. इससे कंपोज़िशन OpenGL ES (GLES) और जीपीयू के काम करने की क्षमता कम हो जाती है.

एचडब्ल्यूसी, कंपोज़िट सर्फ़ेस के लिए ओवरले और 2D ब्लिटर जैसे ऑब्जेक्ट को ऐब्स्ट्रैक्ट करता है. साथ ही, विंडो कंपोज़िट करने के लिए, विंडो कंपोज़िशन के खास हार्डवेयर के साथ कम्यूनिकेट करता है. विंडो को कंपोज़िट करने के लिए, SurfaceFlinger के बजाय HWC का इस्तेमाल करें. ज़्यादातर GPU, कंपोज़िशन के लिए ऑप्टिमाइज़ नहीं किए जाते. साथ ही, जब GPU, SurfaceFlinger से लेयर कंपोज़ करता है, तब ऐप्लिकेशन अपने रेंडरिंग के लिए GPU का इस्तेमाल नहीं कर पाते.

एचडब्ल्यूसी लागू करने के लिए, इन बातों का ध्यान रखना ज़रूरी है:

  • कम से कम चार ओवरले:
    • स्टेटस बार
    • सिस्टम बार
    • ऐप्लिकेशन
    • वॉलपेपर/बैकग्राउंड
  • ऐसी लेयर जो डिसप्ले से बड़ी होती हैं. उदाहरण के लिए, वॉलपेपर
  • हर पिक्सल के हिसाब से पहले से गुणा किए गए ऐल्फ़ा ब्लेंडिंग और हर प्लेन के हिसाब से ऐल्फ़ा ब्लेंडिंग की सुविधा एक साथ उपलब्ध है
  • सुरक्षित वीडियो चलाने के लिए हार्डवेयर पाथ
  • RGBA पैकिंग ऑर्डर, YUV फ़ॉर्मैट, और टाइलिंग, स्विलिंग, और स्ट्राइड प्रॉपर्टी

एचडब्ल्यूसी लागू करने के लिए:

  1. नॉनऑपरेशनल एचडब्ल्यूसी लागू करें और कंपोज़िशन से जुड़ा सारा काम GLES को भेजें.
  2. एचडब्ल्यूसी को कंपोज़िशन सौंपने के लिए, एल्गोरिदम लागू करें. उदाहरण के लिए, एचडब्ल्यूसी के ओवरले हार्डवेयर को सिर्फ़ पहले तीन या चार डिसप्ले डेलिगेट करें.
  3. एचडब्ल्यूसी को ऑप्टिमाइज़ करें. इसमें यह जानकारी शामिल हो सकती है:
    • ऐसे डिसप्ले चुनना जिनसे जीपीयू पर पड़ने वाला लोड कम हो जाता है और उन्हें एचडब्ल्यूसी को भेजना.
    • यह कुकी यह पता लगाती है कि स्क्रीन अपडेट हो रही है या नहीं. अगर ऐसा नहीं है, तो बैटरी बचाने के लिए, कंपोज़िशन को HWC के बजाय GLES को सौंपें. स्क्रीन के फिर से अपडेट होने पर, कंपोज़िशन को एचडब्ल्यूसी पर ऑफ़लोड करना जारी रखें.
    • इस्तेमाल के सामान्य उदाहरणों के लिए तैयारी करना. जैसे:
      • होम स्क्रीन, जिसमें स्टेटस बार, सिस्टम बार, ऐप्लिकेशन विंडो, और लाइव वॉलपेपर शामिल हैं
      • पोर्ट्रेट और लैंडस्केप मोड में फ़ुल-स्क्रीन गेम
      • सबटाइटल और वीडियो चलाने के कंट्रोल के साथ फ़ुल-स्क्रीन वीडियो
      • सुरक्षित वीडियो चलाने की सुविधा
      • स्प्लिट स्क्रीन मल्टीविंडो

एचडब्ल्यूसी प्रिमिटिव

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

HIDL इंटरफ़ेस

Android 8.0 और इसके बाद के वर्शन में, HWC और SurfaceFlinger के बीच बाइंडर वाले आईपीसी के लिए, कंपोज़र एचएएल नाम के एचआईडीएल इंटरफ़ेस का इस्तेमाल किया जाता है. Composer HAL, लेगसी hwcomposer2.h इंटरफ़ेस की जगह लेता है. अगर वेंडर, एचडब्ल्यूसी का कंपोज़र एचएएल लागू करते हैं, तो कंपोज़र एचएएल सीधे तौर पर SurfaceFlinger से HIDL कॉल स्वीकार करता है. अगर वेंडर, HWC का लेगसी वर्शन उपलब्ध कराते हैं, तो कंपोज़र HAL, hwcomposer2.h से फ़ंक्शन पॉइंटर लोड करता है. साथ ही, HIDL कॉल को फ़ंक्शन पॉइंटर कॉल में फ़ॉरवर्ड करता है.

एचडब्ल्यूसी, किसी डिसप्ले की प्रॉपर्टी तय करने के लिए फ़ंक्शन उपलब्ध कराता है. साथ ही, अलग-अलग डिसप्ले कॉन्फ़िगरेशन (जैसे, 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() को कॉल करके बनाए जाते हैं, ताकि डिसप्ले का अनुरोध किया जा सके. अगर HWC, वर्चुअल डिसप्ले कंपोज़िशन के साथ काम करता है, तो यह एक हैंडल दिखाता है. इसके बाद, SurfaceFlinger, डिसप्ले की कंपोज़िशन को HWC को सौंप देता है. अगर एचडब्ल्यूसी, वर्चुअल डिसप्ले कंपोज़िशन के साथ काम नहीं करता है, तो SurfaceFlinger हैंडल बनाता है और डिसप्ले को कंपोज़ करता है.

डिसप्ले कंपोज़िशन से जुड़ी कार्रवाइयां

अगर SurfaceFlinger के पास कंपोज़ करने के लिए नया कॉन्टेंट है, तो वह हर VSync पर चालू हो जाता है. यह नया कॉन्टेंट, ऐप्लिकेशन से मिले नए इमेज बफ़र या एक या उससे ज़्यादा लेयर की प्रॉपर्टी में बदलाव हो सकता है. SurfaceFlinger के चालू होने पर:

  1. अगर मौजूद हो, तो लेन-देन मैनेज करता है.
  2. अगर नए ग्राफ़िक बफ़र मौजूद हैं, तो उन्हें लैच करता है.
  3. अगर पहले या दूसरे चरण में डिसप्ले कॉन्टेंट में बदलाव हुआ है, तो नई कंपोज़िशन बनाता है.

नई कंपोज़िशन बनाने के लिए, 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 — इस मोड में, जीपीयू कुछ लेयर को फ़्रेमबफ़र में कंपोज़िट करता है. इसके बाद, एचडब्ल्यूसी फ़्रेमबफ़र और बाकी लेयर को कंपोज़िट करता है. साथ ही, आउटपुट बफ़र में सीधे तौर पर लिखता है.
  • HWC — HWC, सभी लेयर को कंपोज़ करता है और सीधे तौर पर आउटपुट बफ़र में लिखता है.

आउटपुट फ़ॉर्मैट

वर्चुअल डिसप्ले बफ़र के आउटपुट फ़ॉर्मैट, उनके मोड पर निर्भर करते हैं:

  • GLES मोड — EGL ड्राइवर, आउटपुट बफ़र के फ़ॉर्मैट को dequeueBuffer() में सेट करता है. आम तौर पर, यह RGBA_8888 होता है. उपयोगकर्ता को, ड्राइवर के सेट किए गए आउटपुट फ़ॉर्मैट को स्वीकार करना होगा. ऐसा न करने पर, बफ़र को नहीं पढ़ा जा सकेगा.
  • मिक्स और एचडब्ल्यूसी मोड — अगर उपभोक्ता को सीपीयू ऐक्सेस करने की ज़रूरत है, तो उपभोक्ता फ़ॉर्मैट सेट करता है. इसके अलावा, फ़ॉर्मैट IMPLEMENTATION_DEFINED होता है. साथ ही, Gralloc, इस्तेमाल के फ़्लैग के आधार पर सबसे सही फ़ॉर्मैट सेट करता है. उदाहरण के लिए, अगर उपभोक्ता वीडियो एन्कोडर है और HWC फ़ॉर्मैट को बेहतर तरीके से लिख सकता है, तो Gralloc YCbCr फ़ॉर्मैट सेट करता है.

सिंक्रनाइज़ेशन फ़ेंस

सिंक्रनाइज़ेशन (सिंक) फ़ेंस, Android ग्राफ़िक्स सिस्टम का एक अहम हिस्सा हैं. फ़ेंस की मदद से, सीपीयू का काम जीपीयू के काम से अलग होता है. इसलिए, सीपीयू का काम सिर्फ़ तब रुकता है, जब जीपीयू के काम पर निर्भरता होती है.

उदाहरण के लिए, जब कोई ऐप्लिकेशन GPU पर बनाए जा रहे बफ़र को सबमिट करता है, तो वह सिंक फ़ेंस ऑब्जेक्ट भी सबमिट करता है. यह फ़ेंस तब सिग्नल देता है, जब जीपीयू बफ़र में डेटा लिख लेता है.

एचडब्ल्यूसी को यह ज़रूरी है कि जीपीयू, बफ़र को दिखाने से पहले बफ़र में लिखना पूरा कर ले. सिंक फ़ेंस को ग्राफ़िक्स पाइपलाइन के ज़रिए बफ़र के साथ पास किया जाता है. साथ ही, बफ़र लिखे जाने पर सिग्नल भी पास किया जाता है. बफ़र दिखने से पहले, एचडब्ल्यूसी यह देखता है कि सिंक फ़ेंस ने सिग्नल दिया है या नहीं. अगर सिग्नल दिया गया है, तो वह बफ़र दिखाता है.

सिंक फ़ेंस के बारे में ज़्यादा जानकारी के लिए, Hardware Composer Integration देखें.