Hardware Composer HAL लागू करना

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

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

एचडब्ल्यूसी के लागू करने के तरीके में ये सुविधाएं होनी चाहिए:

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

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

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

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

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

एचआईडीएल इंटरफ़ेस

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

एचडब्ल्यूसी, किसी दिए गए डिसप्ले की प्रॉपर्टी तय करने के लिए फ़ंक्शन उपलब्ध कराता है. साथ ही, अलग-अलग डिसप्ले कॉन्फ़िगरेशन (जैसे, 4K या 1080p रिज़ॉल्यूशन) और कलर मोड (जैसे, नेटिव कलर या ट्रू sRGB) के बीच स्विच करने के लिए फ़ंक्शन उपलब्ध कराता है. इसके अलावा, अगर डिसप्ले में कम पावर मोड की सुविधा है, तो उसे चालू, बंद या कम पावर मोड में सेट करने के लिए फ़ंक्शन उपलब्ध कराता है.

फ़ंक्शन पॉइंटर

अगर वेंडर, Composer HAL को सीधे तौर पर लागू करते हैं, तो SurfaceFlinger, एचआईडीएल आईपीसी के ज़रिए इसके फ़ंक्शन को कॉल करता है. उदाहरण के लिए, कोई लेयर बनाने के लिए, SurfaceFlinger, Composer HAL पर createLayer() को कॉल करता है.

अगर वेंडर, hwcomposer2.h इंटरफ़ेस लागू करते हैं, तो Composer HAL, hwcomposer2.h फ़ंक्शन पॉइंटर को कॉल करता है. hwcomposer2.h टिप्पणियों में, एचडब्ल्यूसी इंटरफ़ेस फ़ंक्शन को लोअरकैमलकेस नामों से रेफ़र किया जाता है. ये नाम, इंटरफ़ेस में नाम वाले फ़ील्ड के तौर पर मौजूद नहीं होते. hwc2_device_t से मिले getFunction का इस्तेमाल करके, फ़ंक्शन पॉइंटर का अनुरोध करके, लगभग हर फ़ंक्शन लोड किया जाता है. उदाहरण के लिए, createLayer फ़ंक्शन, HWC2_PFN_CREATE_LAYER टाइप का फ़ंक्शन पॉइंटर है. जब HWC2_FUNCTION_CREATE_LAYER की गिनती की गई वैल्यू को getFunction में पास किया जाता है, तब यह वैल्यू मिलती है.

Composer HAL फ़ंक्शन और एचडब्ल्यूसी फ़ंक्शन पासथ्रू फ़ंक्शन के बारे में ज़्यादा जानकारी के लिए, composer देखें. एचडब्ल्यूसी फ़ंक्शन पॉइंटर के बारे में ज़्यादा जानकारी के लिए, देखें hwcomposer2.h.

लेयर और डिसप्ले हैंडल

लेयर और डिसप्ले को एचडब्ल्यूसी से जनरेट किए गए हैंडल से मैनेज किया जाता है. SurfaceFlinger के लिए, हैंडल ओपेक होते हैं.

जब SurfaceFlinger कोई नई लेयर बनाता है, तो वह createLayer को कॉल करता है. इससे डायरेक्ट इंप्लीमेंटेशन के लिए Layer टाइप या पासथ्रू इंप्लीमेंटेशन के लिए hwc2_layer_t टाइप की वैल्यू मिलती है. जब SurfaceFlinger, उस लेयर की किसी प्रॉपर्टी में बदलाव करता है, तो SurfaceFlinger, hwc2_layer_t वैल्यू को बदलाव करने वाले सही फ़ंक्शन में पास करता है. साथ ही, बदलाव करने के लिए ज़रूरी अन्य जानकारी भी पास करता है. hwc2_layer_t टाइप, पॉइंटर या इंडेक्स को सेव करने के लिए काफ़ी बड़ा होता है.

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

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

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

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

नया कंपोज़िशन करने के लिए, SurfaceFlinger, लेयर बनाता और मिटाता है. इसके अलावा, ज़रूरत के हिसाब से लेयर की स्थितियों में बदलाव करता है. यह लेयर को उनके मौजूदा कॉन्टेंट के साथ अपडेट भी करता है. इसके लिए, setLayerBuffer या setLayerColor जैसे कॉल का इस्तेमाल करता है. सभी लेयर अपडेट होने के बाद, SurfaceFlinger, validateDisplay को कॉल करता है. इससे एचडब्ल्यूसी को लेयर की स्थिति की जांच करने और यह तय करने के लिए कहा जाता है कि कंपोज़िशन की प्रोसेस कैसे आगे बढ़ेगी. डिफ़ॉल्ट रूप से, SurfaceFlinger हर लेयर को इस तरह कॉन्फ़िगर करने की कोशिश करता है कि लेयर को एचडब्ल्यूसी कंपोज़ करे. हालांकि, कुछ स्थितियों में, SurfaceFlinger, GPU फ़ॉलबैक के ज़रिए लेयर को कंपोज़ करता है.

validateDisplay को कॉल करने के बाद, SurfaceFlinger, getChangedCompositionTypes को कॉल करता है. इससे यह पता चलता है कि कंपोज़िशन करने से पहले, एचडब्ल्यूसी को लेयर कंपोज़िशन के किसी टाइप में बदलाव करना है या नहीं. बदलाव स्वीकार करने के लिए, SurfaceFlinger, acceptDisplayChanges को कॉल करता है.

अगर किसी लेयर को SurfaceFlinger कंपोज़िशन के लिए मार्क किया गया है, तो SurfaceFlinger उन्हें टारगेट बफ़र में कंपोज़ करता है. इसके बाद, SurfaceFlinger, setClientTarget को कॉल करके, बफ़र को डिसप्ले को देता है. इससे बफ़र को स्क्रीन पर दिखाया जा सकता है या उन लेयर के साथ कंपोज़ किया जा सकता है जिन्हें SurfaceFlinger कंपोज़िशन के लिए मार्क नहीं किया गया है. अगर किसी लेयर को SurfaceFlinger कंपोज़िशन के लिए मार्क नहीं किया गया है, तो SurfaceFlinger, कंपोज़िशन के चरण को छोड़ देता है.

आखिर में, SurfaceFlinger, presentDisplay को कॉल करके, एचडब्ल्यूसी को कंपोज़िशन की प्रोसेस पूरी करने और फ़ाइनल रिज़ल्ट दिखाने के लिए कहता है.

कई डिसप्ले

Android 10 में, कई फ़िज़िकल डिसप्ले इस्तेमाल किए जा सकते हैं. Android 7.0 और इसके बाद के वर्शन पर इस्तेमाल करने के लिए, एचडब्ल्यूसी लागू करने का तरीका डिज़ाइन करते समय, कुछ पाबंदियां होती हैं. ये पाबंदियां, एचडब्ल्यूसी की डेफ़िनिशन में मौजूद नहीं होतीं:

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

ऊपर बताई गई 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 बफ़र में भेजते हैं. हार्डवेयर कंपोज़र (एचडब्ल्यूसी), आउटपुट को बफ़र में लिखता है, कंपोज़िशन पूरा होने का सिग्नल देता है, और बफ़र को किसी कंज्यूमर (जैसे, वीडियो एन्कोडर, GPU, सीपीयू वगैरह) को भेजता है. अगर डिसप्ले पाइपलाइन, मेमोरी में लिखती है, तो वर्चुअल डिसप्ले, 2D/ब्लिटर या ओवरले का इस्तेमाल कर सकते हैं.

मोड

SurfaceFlinger के validateDisplay() एचडब्ल्यूसी तरीके को कॉल करने के बाद, हर फ़्रेम तीन में से किसी एक मोड में होता है:

  • GLES — GPU, सभी लेयर को कंपोज़ करता है और सीधे आउटपुट बफ़र में लिखता है. कंपोज़िशन में एचडब्ल्यूसी शामिल नहीं होता.
  • मिक्सड — जीपीयू, कुछ लेयर को फ़्रेमबफ़र में कंपोज़ करता है. वहीं, एचडब्ल्यूसी, फ़्रेमबफ़र और बाकी लेयर को कंपोज़ करता है और सीधे आउटपुट बफ़र में लिखता है.
  • HWC — एचडब्ल्यूसी, सभी लेयर को कंपोज़ करता है और सीधे आउटपुट बफ़र में लिखता है.

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

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

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

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

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

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

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

सिंक फ़ेंस के बारे में ज़्यादा जानकारी के लिए, हार्डवेयर कंपोज़र इंटिग्रेशन देखें.