يصف إطار المزامنة بشكل صريح التبعيات بين العمليات غير المتزامنة المختلفة في نظام الرسومات في Android. يوفّر إطار العمل واجهة برمجة تطبيقات تتيح للمكوّنات الإشارة إلى وقت تحرير المخازن المؤقتة. يسمح إطار العمل أيضًا بنقل عناصر المزامنة الأساسية بين برامج التشغيل من النواة إلى مساحة المستخدمين وبين عمليات مساحة المستخدمين نفسها.
على سبيل المثال، قد يضع أحد التطبيقات العمل المطلوب تنفيذه في وحدة معالجة الرسومات في قائمة انتظار. تبدأ وحدة معالجة الرسومات في رسم تلك الصورة. على الرغم من أنّه لم يتم رسم الصورة في الذاكرة بعد، يتم تمرير مؤشر المخزن المؤقت إلى برنامج تجميع النوافذ مع حاجز يشير إلى وقت انتهاء عمل وحدة معالجة الرسومات. يبدأ برنامج إنشاء الصور المركّبة في النافذة المعالجة مسبقًا وينقل العمل إلى وحدة التحكّم في الشاشة. وبطريقة مماثلة، يتم إنجاز عمل وحدة المعالجة المركزية مسبقًا. بعد انتهاء وحدة معالجة الرسومات، يعرض جهاز التحكّم في الشاشة الصورة على الفور.
يتيح إطار المزامنة أيضًا للمنفّذين الاستفادة من موارد المزامنة في مكونات الأجهزة الخاصة بهم. أخيرًا، يوفّر إطار العمل إمكانية الاطّلاع على مسار عرض الرسومات للمساعدة في تصحيح الأخطاء.
المزامنة الصريحة
تتيح المزامنة الصريحة لمنتجي مخازن مؤقتة للرسومات ومستهلكيها الإشارة إلى وقت الانتهاء من استخدام مخزن مؤقت. يتم تنفيذ المزامنة الصريحة في مساحة النواة.
تشمل مزايا المزامنة الواضحة ما يلي:
- تفاوت أقل في السلوك بين الأجهزة
- تحسين إمكانات تصحيح الأخطاء
- مقاييس الاختبار المحسّنة
يتضمّن إطار المزامنة ثلاثة أنواع من العناصر:
sync_timeline
sync_pt
sync_fence
sync_timeline
sync_timeline
هو مخطط زمني يتزايد بشكلٍ منتظم يجب أن ينفّذه المورّدون لكل مثيل برنامج تشغيل، مثل سياق GL أو وحدة التحكّم في العرض أو أداة blitter ثنائية الأبعاد. تعرض sync_timeline
عدد
المهام التي تم إرسالها إلى النواة لجزء معيّن من الأجهزة.
توفّر sync_timeline
ضمانات بشأن ترتيب العمليات وتتيح عمليات تنفيذ خاصة بالأجهزة.
اتّبِع الإرشادات التالية عند تنفيذ sync_timeline
:
- قدِّم أسماء مفيدة لجميع برامج التشغيل والمخططات الزمنية والحدود لتسهيل عملية تصحيح الأخطاء.
- استخدِم عاملَي التشغيل
timeline_value_str
وpt_value_str
في المخططات الزمنية لجعل ناتج تصحيح الأخطاء أكثر قابلية للقراءة. - نفِّذ عملية التعبئة
driver_data
لمنح مكتبات مساحة المستخدم، مثل مكتبة GL، إمكانية الوصول إلى بيانات المخطط الزمني الخاص، إذا أردت ذلك. تسمح السمة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
بعد إنشاء السياج الجغرافي. للحصول على أكثر من نقطة واحدة في سياج جغرافي، يتم دمج النقاط من سياجين جغرافيين مختلفين وإضافتها إلى سياج جغرافي ثالث.
إذا تم الإشارة إلى إحدى هاتين النقطتين في السياج الأصلي ولم يتم الإشارة إلى النقطة الأخرى، لن يكون السياج الثالث في حالة تم الإشارة إليها أيضًا.
لتنفيذ المزامنة الضمنية، قدِّم ما يلي:
- نظام فرعي في مساحة النواة ينفّذ إطار عمل المزامنة لبرنامج تشغيل أجهزة معيّن. إنّ برامج التشغيل التي يجب أن تكون على دراية بالحواجز هي بشكل عام أي برامج تصل إلى Hardware Composer أو تتواصل معه.
تشمل الملفات الرئيسية ما يلي:
- التنفيذ الأساسي:
kernel/common/include/linux/sync.h
kernel/common/drivers/base/sync.c
- المستندات في
kernel/common/Documentation/sync.txt
- مكتبة للتواصل مع مساحة النواة في
platform/system/core/libsync
- التنفيذ الأساسي:
- يجب أن يوفّر المورّد حواجز المزامنة المناسبة كمعلَمات للدالتَين
validateDisplay()
وpresentDisplay()
في طبقة HAL. - إضافتان مرتبطتان بالحواجز في 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 وبرامج التشغيل التي يجب أن تتواصل مع بعضها البعض. يتم تمثيل عناصر مساحة النواة كواصفات ملفات في مساحة المستخدم.
اتّفاقيات الدمج
اتّبِع اصطلاحات واجهة HAL لنظام التشغيل Android:
- إذا كانت واجهة برمجة التطبيقات توفّر واصف ملف يشير إلى
sync_pt
، يجب أن يغلق برنامج التشغيل الخاص بالمورّد أو طبقة تجريد الأجهزة (HAL) التي تستخدم واجهة برمجة التطبيقات واصف الملف. - إذا مرَّر برنامج تشغيل المورّد أو طبقة HAL واصف ملف يحتوي على
sync_pt
إلى دالة في واجهة برمجة التطبيقات، يجب ألا يغلق برنامج تشغيل المورّد أو طبقة HAL واصف الملف. - لمواصلة استخدام واصف ملف السياج، يجب أن يكرّر برنامج التشغيل الخاص بالمورّد أو طبقة تجريد الأجهزة (HAL) الواصف.
تتم إعادة تسمية عنصر السياج في كل مرة يمر فيها عبر 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 واصف ملف سياج Android أصليًا من عنصر
EGLSyncKHR
.
استخدِم استدعاء الدالة DupNativeFenceFD()
لاستخراج الكائن EGLSyncKHR
من واصف ملف السياج الأصلي لنظام التشغيل Android.
ويؤدي ذلك إلى النتيجة نفسها التي يؤدي إليها طلب البحث عن السمة set، ولكنّه يلتزم بالاتفاقية التي تنص على أنّ المستلِم يغلق السياج (وبالتالي تتكرر العملية). وأخيرًا، يؤدي تدمير الكائن EGLSyncKHR
إلى إغلاق سمة السياج الداخلي.
دمج Hardware Composer
يتعامل Hardware Composer مع ثلاثة أنواع من حواجز المزامنة:
- يتم تمرير Acquire fences مع مخازن الإدخال المؤقتة إلى استدعاءات
setLayerBuffer
وsetClientTarget
. تمثّل هذه العلامات عملية كتابة معلّقة في المخزن المؤقت، ويجب إرسال إشارة قبل أن تحاول SurfaceFlinger أو HWC القراءة من المخزن المؤقت المرتبط لتنفيذ عملية الدمج. - يتم استرداد حواجز الإصدار بعد الاتصال بـ
presentDisplay
باستخدام طلبgetReleaseFences
. تمثّل هذه القيم قراءة معلّقة من المخزن المؤقت السابق على الطبقة نفسها. يشير حاجز الإصدار إلى أنّ HWC لم يعُد يستخدم المخزن المؤقت السابق لأنّ المخزن المؤقت الحالي حلّ محل المخزن المؤقت السابق على الشاشة. يتم إرجاع حواجز الإصدار إلى التطبيق مع المخازن المؤقتة السابقة التي سيتم استبدالها أثناء عملية الإنشاء الحالية. يجب أن ينتظر التطبيق إلى أن يتم تلقّي إشارات سياج الإصدار قبل كتابة محتوى جديد في المخزن المؤقت الذي تم إرجاعه إليه. - يتم عرض أسوار العرض الحالية، واحد لكل إطار، كجزء من استدعاء
presentDisplay
. تمثّل الأسوار الحالية الوقت الذي اكتمل فيه تركيب هذه اللقطة، أو بدلاً من ذلك، الوقت الذي لم تعُد فيه هناك حاجة إلى نتيجة التركيب الخاصة باللقطة السابقة. بالنسبة إلى الشاشات الفعلية، تعرض الدالةpresentDisplay
الحواجز الحالية عندما يظهر الإطار الحالي على الشاشة. بعد عرض سياجات العرض الحالية، يمكن الكتابة في المخزن المؤقت المستهدف في SurfaceFlinger مرة أخرى، إذا كان ذلك منطبقًا. بالنسبة إلى الشاشات الافتراضية، يتم عرض سياجات العرض الحالية عندما يكون من الآمن القراءة من المخزن المؤقت للإخراج.