सिंक करने का फ़्रेमवर्क

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

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

सिंक करने की सुविधा देने वाले फ़्रेमवर्क की मदद से, सिंक करने के संसाधनों का इस्तेमाल, अपने हार्डवेयर कॉम्पोनेंट में भी किया जा सकता है. आखिर में, फ़्रेमवर्क की मदद से ग्राफ़िक्स पाइपलाइन को देखा जा सकता है, ताकि डीबग करने में मदद मिल सके.

साफ़ तौर पर सिंक करना

साफ़ तौर पर सिंक करने की सुविधा से, ग्राफ़िक बफ़र के प्रोड्यूसर और उपभोक्ता, बफ़र का इस्तेमाल खत्म होने पर सिग्नल दे सकते हैं. एक्सप्लिसिट सिंकिंग यह है कर्नेल-स्पेस में लागू किया गया है.

सिंक करने के ये फ़ायदे हैं:

  • डिवाइसों के काम करने के तरीके में कम बदलाव
  • डीबग करने के लिए बेहतर सहायता
  • बेहतर टेस्टिंग मेट्रिक

सिंक फ़्रेमवर्क में तीन ऑब्जेक्ट टाइप होते हैं:

  • sync_timeline
  • sync_pt
  • sync_fence

sync_timeline

sync_timeline एक बेहद तेज़ी से बढ़ने वाली टाइमलाइन है, वेंडर को हर ड्राइवर इंस्टेंस के लिए लागू करना चाहिए, जैसे कि जीएल कॉन्टेक्स्ट, डिसप्ले कंट्रोलर या 2D ब्लिटर का इस्तेमाल किया जा सकता है. sync_timeline की संख्या हार्डवेयर के किसी खास हिस्से के लिए कर्नेल को सबमिट किए गए जॉब. sync_timeline, ऑपरेशन के क्रम के बारे में गारंटी देता है और हार्डवेयर के हिसाब से लागू करने की सुविधा देता है.

sync_timeline लागू करते समय इन दिशा-निर्देशों का पालन करें:

  • आसान बनाने के लिए सभी ड्राइवरों, टाइमलाइन, और फ़ेंस के नाम बताएं डीबग करना.
  • डीबगिंग आउटपुट को पढ़ने में आसान बनाने के लिए, टाइमलाइन में timeline_value_str और pt_value_str ऑपरेटर लागू करें.
  • यूज़रस्पेस लाइब्रेरी देने के लिए, फ़िल driver_data को लागू करें. जैसे कि जीएल लाइब्रेरी, निजी टाइमलाइन डेटा का ऐक्सेस, अगर ज़रूरत हो. data_driver की मदद से वेंडर, बदले न जा सकने वाले sync_fence और sync_pts के बारे में जानकारी दे सकते हैं, ताकि उन पर आधारित कमांड लाइन बनाई जा सकें.
  • यूज़रस्पेस को साफ़ तौर पर बाड़ बनाने या सिग्नल देने की अनुमति न दें. साफ़ तौर पर जानकारी देना सिग्नल/फ़ेंस बनाने से, डिनायल ऑफ़ सर्विस अटैक होता है, जो पाइपलाइन की सुविधाओं को रोकता है.
  • sync_timeline, sync_pt या sync_fence एलिमेंट को साफ़ तौर पर ऐक्सेस न करें. एपीआई सभी ज़रूरी सुविधाएं देता है फ़ंक्शन.

sync_pt

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

sync_fence

sync_fence, sync_pt वैल्यू का कलेक्शन है अक्सर इनके sync_timeline पैरंट हैं (जैसे कि डिसप्ले के लिए कंट्रोलर और जीपीयू का ऐक्सेस मिलता है. sync_fence, sync_pt, और sync_timeline ड्राइवर और यूज़रस्पेस के लिए मुख्य बातें हैं का इस्तेमाल उनकी डिपेंडेंसी के लिए किया जाता है. जब फ़ेंस का सिग्नल मिलता है, तो फ़ेंस से पहले दिए गए सभी निर्देश पूरे हो जाते हैं. ऐसा इसलिए होता है, क्योंकि कोर ड्राइवर या हार्डवेयर ब्लॉक, निर्देशों को क्रम से पूरा करता है.

सिंक फ़्रेमवर्क की मदद से, कई उपभोक्ता या प्रोड्यूसर, बफ़र का इस्तेमाल करके, काम पूरा होने का सिग्नल दे सकते हैं. साथ ही, एक फ़ंक्शन पैरामीटर की मदद से, डिपेंडेंसी की जानकारी दे सकते हैं. फ़ेंस, फ़ाइल डिस्क्रिप्टर पर आधारित होते हैं और इन्हें यहां से पास किया जाता है कर्नेल स्पेस को यूज़रस्पेस में बदलें. उदाहरण के लिए, एक बाड़ में दो sync_pt ऐसी वैल्यू जो दो अलग-अलग इमेज इस्तेमाल करने वालों के काम करने पर दिखती हैं बफ़र पढ़ रहा है. फ़ेंस का सिग्नल मिलने पर, इमेज बनाने वाले लोगों को पता चल जाता है कि दोनों उपभोक्ताओं ने इमेज का इस्तेमाल कर लिया है.

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

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

साफ़ तौर पर सिंक करने के लिए, यह जानकारी दें:

  • कर्नेल-स्पेस सबसिस्टम, जो सिंक फ़्रेमवर्क को लागू करता है एक खास हार्डवेयर ड्राइवर के लिए. आम तौर पर, ऐसे सभी ड्राइवर फ़ेंस-अवेयर होने चाहिए जो हार्डवेयर कंपोज़र को ऐक्सेस करते हैं या उससे संपर्क करते हैं. मुख्य फ़ाइलों में ये शामिल हैं:
    • मुख्य लागू करने का तरीका:
      • kernel/common/include/linux/sync.h
      • kernel/common/drivers/base/sync.c
    • kernel/common/Documentation/sync.txt पर दस्तावेज़
    • कर्नेल स्पेस के साथ संचार करने के लिए लाइब्रेरी platform/system/core/libsync अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है
  • वेंडर को HAL में validateDisplay() और presentDisplay() फ़ंक्शन के पैरामीटर के तौर पर, सही सिंक करने के लिए फ़ेंस देने होंगे.
  • फ़ेंस से जुड़े दो GL एक्सटेंशन (EGL_ANDROID_native_fence_sync और EGL_ANDROID_wait_sync) और ग्राफ़िक्स ड्राइवर में फ़ेंस की सुविधा.

केस स्टडी: डिसप्ले ड्राइवर लागू करना

सिंक करने की सुविधा के साथ काम करने वाले एपीआई का इस्तेमाल करने के लिए, ऐसा डिसप्ले ड्राइवर बनाएं जिसमें डिसप्ले बफ़र फ़ंक्शन हो. इस तारीख से पहले सिंक्रोनाइज़ेशन फ़्रेमवर्क मौजूद है, इस फ़ंक्शन को dma-buf मिलेगा ऑब्जेक्ट से, उन बफ़र को डिसप्ले पर रखा जा सकता है और बफ़र के दिखने पर ब्लॉक किया जा सकता है. उदाहरण के लिए:

/*
 * assumes buffer is ready to be displayed.  returns when buffer is no longer on
 * screen.
 */
void display_buffer(struct dma_buf *buffer);

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

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

/*
 * displays buffer when fence is signaled.  returns immediately with a fence
 * that signals when buffer is no longer displayed.
 */
struct sync_fence* display_buffer(struct dma_buf *buffer, struct sync_fence
*fence);

सिंक इंटिग्रेशन

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

इंटिग्रेशन कन्वेंशन

Android HAL इंटरफ़ेस के तौर-तरीकों का पालन करें:

  • अगर एपीआई, sync_pt का रेफ़रंस देने वाला फ़ाइल डिस्क्रिप्टर उपलब्ध कराता है, तो एपीआई का इस्तेमाल करने वाले वेंडर के ड्राइवर या एचएएल को फ़ाइल डिस्क्रिप्टर बंद करना होगा.
  • अगर वेंडर ड्राइवर या एचएएल, किसी एपीआई फ़ंक्शन को sync_pt वाला फ़ाइल डिस्क्रिप्टर पास करता है, तो वेंडर ड्राइवर या एचएएल को फ़ाइल डिस्क्रिप्टर को बंद नहीं करना चाहिए.
  • फ़ेंस फ़ाइल डिस्क्रिप्टर का इस्तेमाल जारी रखने के लिए, वेंडर ड्राइवर या एचएएल को डिस्क्रिप्टर का डुप्लीकेट बनाना होगा.

फ़ेंस ऑब्जेक्ट को हर बार BufferQueue से गुज़रने पर उसका नाम बदल दिया जाता है. कर्नेल फ़ेंस की सुविधा की मदद से, फ़ेंस के नाम के लिए स्ट्रिंग का इस्तेमाल किया जा सकता है. इसलिए, सिंक फ़्रेमवर्क, फ़ेंस के नाम के लिए, SurfaceView:0 जैसी विंडो के नाम और बफ़र इंडेक्स का इस्तेमाल करता है. यह नाम के दिखने पर, डेडलॉक सोर्स की पहचान करने के लिए, डीबग करने में मदद मिलती है /d/sync और गड़बड़ी की रिपोर्ट के आउटपुट में मिलेगी.

ANativeWindow इंटिग्रेशन

ANativeWindow फ़ेंस को जानता है. dequeueBuffer, queueBuffer और cancelBuffer में फ़ेंस पैरामीटर हैं.

OpenGL ES इंटिग्रेशन

OpenGL ES सिंक इंटिग्रेशन, दो EGL एक्सटेंशन पर निर्भर करता है:

  • EGL_ANDROID_native_fence_sync यह करने का तरीका है नेटिव Android फ़ेंस फ़ाइल डिस्क्रिप्टर को रैप करें या बनाएं EGLSyncKHR ऑब्जेक्ट.
  • EGL_ANDROID_wait_sync, सीपीयू के बजाय जीपीयू-साइड स्टॉल की अनुमति देता है. इससे जीपीयू को EGLSyncKHR के लिए इंतज़ार करना पड़ता है. कॉन्टेंट बनाने EGL_ANDROID_wait_sync एक्सटेंशन, EGL_KHR_wait_sync एक्सटेंशन.

इन एक्सटेंशन का अलग से इस्तेमाल करने के लिए, EGL_ANDROID_native_fence_sync एक्सटेंशन और इससे जुड़ा एक्सटेंशन कर्नेल सहायता. इसके बाद, अपने ड्राइवर में EGL_ANDROID_wait_sync एक्सटेंशन चालू करें. EGL_ANDROID_native_fence_sync एक्सटेंशन में, नेटिव फ़ेंस EGLSyncKHR ऑब्जेक्ट का एक अलग टाइप होता है. इस वजह से, मौजूदा EGLSyncKHR पर लागू होने वाले एक्सटेंशन यह ज़रूरी नहीं है कि ऑब्जेक्ट टाइप EGL_ANDROID_native_fence पर लागू हों साथ ही, अनचाही बातचीत से बचें.

EGL_ANDROID_native_fence_sync एक्सटेंशन, फ़ेंस फ़ाइल के ब्यौरे से जुड़े नेटिव एट्रिब्यूट का इस्तेमाल करता है. इसे सिर्फ़ फ़ाइल बनाने के समय सेट किया जा सकता है. साथ ही, किसी मौजूदा सिंक ऑब्जेक्ट से सीधे तौर पर इसकी क्वेरी नहीं की जा सकती. यह एट्रिब्यूट इनमें से किसी एक मोड पर सेट किया जा सकता है:

  • मान्य फ़ेंस फ़ाइल डिस्क्रिप्टर, किसी मौजूदा नेटिव Android फ़ेंस फ़ाइल डिस्क्रिप्टर को EGLSyncKHR ऑब्जेक्ट में रैप करता है.
  • -1, EGLSyncKHR ऑब्जेक्ट से नेटिव Android फ़ेंस फ़ाइल डिस्क्रिप्टर बनाता है.

एक्सट्रैक्ट करने के लिए DupNativeFenceFD() फ़ंक्शन कॉल का इस्तेमाल करें नेटिव Android फ़ेंस फ़ाइल डिस्क्रिप्टर से लिया गया EGLSyncKHR ऑब्जेक्ट. इसका नतीजा, सेट एट्रिब्यूट की क्वेरी करने जैसा ही होता है. हालांकि, यह इस कॉन्वेंशन का पालन करता है कि फ़ेंस को पाने वाला व्यक्ति उसे बंद करता है (इसलिए, डुप्लीकेट ऑपरेशन). आखिर में, EGLSyncKHR ऑब्जेक्ट को मिटाने पर, इंटरनल फ़ेंस एट्रिब्यूट बंद हो जाता है.

हार्डवेयर कंपोज़र इंटिग्रेशन

हार्डवेयर कंपोजर, सिंक फ़ेंस के तीन टाइप को मैनेज करता है:

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