हार्डवेयर कंपोज़र एचएएल लागू करना

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

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

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

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

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

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

HWC प्राइमिटिव

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

HIDL इंटरफ़ेस

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

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

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

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

अगर वेंडर hwcomposer2.h इंटरफ़ेस लागू करते हैं, तो Composer HAL hwcomposer2.h फ़ंक्शन पॉइंटर को कॉल करता है. hwcomposer2.h टिप्पणियों में, एचडब्ल्यूसी इंटरफ़ेस फ़ंक्शन को, कमरे के नाम वाले फ़ील्ड के तौर पर इंटरफ़ेस में मौजूद न होने वाले, lowerCamelCase नामों से रेफ़र किया जाता है. 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 को कॉल करती है कि एचडब्ल्यूसी को कंपोज़िशन परफ़ॉर्म करने से पहले किसी लेयर कंपोज़िशन के टाइप में बदलाव हुआ है या नहीं. बदलावों को स्वीकार करने के लिए, SurfaceFlinger acceptDisplayChanges को कॉल करता है.

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

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

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

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

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

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

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

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

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

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

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

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

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