Hardware Composer HAL लागू करना

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

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

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

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

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

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

HWC प्राइमिटिव

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

HIDL इंटरफ़ेस

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

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

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

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

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

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

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

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

डिसप्ले कंपोज़िशन के ऑपरेशन

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

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

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

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

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

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

एक से ज़्यादा डिसप्ले

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

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

मोड

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

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

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

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

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

सिंक करने के लिए फ़ेंस

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

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

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

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