تدمج طبقات Hardware Composer (HWC) HAL التي تم تلقّيها من SurfaceFlinger، ما يقلّل من مقدار الدمج OpenGL ES (GLES) وأداء وحدة معالجة الرسومات.
تجرِّد HWC الكائنات، مثل التراكبات و2D blitters، لإنشاء أسطح مركّبة والتواصل مع أجهزة متخصصة لتركيب النوافذ. استخدِم HWC لتركيب النوافذ بدلاً من أن يقوم SurfaceFlinger بالتركيب باستخدام وحدة معالجة الرسومات. معظم وحدات معالجة الرسومات غير محسّنة للتركيب، وعندما تركّب وحدة معالجة الرسومات الطبقات من SurfaceFlinger، لا يمكن للتطبيقات استخدام وحدة معالجة الرسومات في العرض الخاص بها.
يجب أن تتوافق عمليات تنفيذ HWC مع ما يلي:
- أربع تراكبات على الأقل:
- شريط الحالة
- شريط النظام
- التطبيق
- الخلفية
- الطبقات الأكبر من الشاشة (مثل خلفية الشاشة)
- المزج المتزامن لقنوات ألفا المضاعفة مسبقًا على مستوى كل بكسل والمزج على مستوى كل مستوى
- مسار الأجهزة لتشغيل الفيديو المحمي
- ترتيب حزم RGBA وتنسيقات YUV وخصائص التجانب والخلط والخطوة
لتنفيذ HWC، اتّبِع الخطوات التالية:
- نفِّذ HWC غير تشغيلي وأرسِل جميع أعمال التركيب إلى GLES.
- تنفيذ خوارزمية لتفويض عملية الإنشاء إلى HWC بشكل تدريجي على سبيل المثال، تفويض أول ثلاثة أو أربعة أسطح فقط إلى أجهزة تراكب HWC.
- تحسين HWC قد يشمل ذلك ما يلي:
- اختيار المساحات التي تقلّل الحمل على وحدة معالجة الرسومات إلى أقصى حد وإرسالها إلى HWC
- رصد ما إذا كانت الشاشة يتم تحديثها إذا لم يكن كذلك، فوِّض عملية إنشاء الصورة إلى GLES بدلاً من HWC لتوفير الطاقة. عندما يتم تحديث الشاشة مرة أخرى، واصِل نقل عملية إنشاء الصورة إلى HWC.
- الاستعداد لحالات الاستخدام الشائعة، مثل:
- الشاشة الرئيسية، التي تتضمّن شريط الحالة وشريط النظام ونافذة التطبيق والخلفيات المتحركة
- الألعاب بملء الشاشة في الوضعَين العمودي والأفقي
- فيديو بملء الشاشة مع ترجمة وشرح وأزرار تحكّم في التشغيل
- تشغيل الفيديو المحمي
- النوافذ المتعددة في وضع تقسيم الشاشة
عناصر HWC الأساسية
توفّر HWC عنصرَين أساسيَّين، هما الطبقات وشاشات العرض، لتمثيل عملية الدمج والتفاعل مع أجهزة العرض. توفّر طبقة HWC أيضًا إمكانية التحكّم في VSync ووظيفة ردّ الاتصال إلى SurfaceFlinger لإعلامها عند حدوث حدث VSync.
واجهة HIDL
يستخدم الإصدار 8.0 من نظام التشغيل Android والإصدارات الأحدث واجهة HIDL تُسمى Composer HAL لإجراء عملية IPC مستندة إلى Binder بين HWC وSurfaceFlinger. يحلّ Composer HAL محل واجهة hwcomposer2.h
القديمة. إذا كان المورّدون يوفّرون تنفيذًا لواجهة Composer HAL
لـ HWC، تقبل واجهة Composer HAL مباشرةً طلبات HIDL من
SurfaceFlinger. إذا كان المورّدون يوفّرون عملية تنفيذ قديمة لواجهة HWC، سيحمّل Composer
HAL مؤشرات الدوال من hwcomposer2.h
،
ويوجّه استدعاءات HIDL إلى استدعاءات مؤشرات الدوال.
توفّر طبقة HWC وظائف لتحديد خصائص شاشة معيّنة، وللتبديل بين إعدادات الشاشة المختلفة (مثل دقة 4K أو 1080p) وأوضاع الألوان (مثل الألوان الأصلية أو sRGB الحقيقية)، ولتشغيل الشاشة أو إيقافها أو وضعها في وضع توفير الطاقة إذا كان ذلك متاحًا.
مؤشرات الدوال
إذا نفّذ البائعون Composer HAL مباشرةً، ستستدعي SurfaceFlinger وظائفه من خلال HIDL IPC. على سبيل المثال، لإنشاء طبقة، يستدعي SurfaceFlinger
createLayer()
في Composer HAL.
إذا نفّذ البائعون واجهة hwcomposer2.h
، ستتضمّن استدعاءات Composer HAL
مؤشرات دالة hwcomposer2.h
. في تعليقات hwcomposer2.h
،
يُشار إلى دوال واجهة HWC
بأسماء lowerCamelCase غير متوفّرة في الواجهة
كحقول مُسمّاة. يتم تحميل كل دالة تقريبًا من خلال طلب مؤشر دالة باستخدام getFunction
المقدَّم من hwc2_device_t
. على سبيل المثال، الدالة createLayer
هي مؤشر دالة من النوع HWC2_PFN_CREATE_LAYER
، ويتم عرضها عند تمرير القيمة المُعدَّدة HWC2_FUNCTION_CREATE_LAYER
إلى getFunction
.
للحصول على مستندات تفصيلية حول وظائف Composer HAL ووظائف تمرير وظائف HWC، راجِع composer
. للحصول على مستندات تفصيلية حول مؤشرات وظائف HWC، يُرجى الاطّلاع على hwcomposer2.h
.
مقابض الطبقات والعرض
يتم التعامل مع الطبقات والعروض من خلال مقابض تنشئها HWC. تكون الأسماء المعرِّفة غير قابلة للوصول إلى SurfaceFlinger.
عندما ينشئ SurfaceFlinger طبقة جديدة، يستدعي createLayer
،
الذي يعرض النوع Layer
للتنفيذات المباشرة أو hwc2_layer_t
للتنفيذات التي تستخدم مسارًا مباشرًا. عندما يعدّل SurfaceFlinger إحدى خصائص الطبقة، يمرّر SurfaceFlinger القيمة hwc2_layer_t
إلى دالة التعديل المناسبة مع أي معلومات أخرى مطلوبة لإجراء التعديل. النوع
hwc2_layer_t
كبير بما يكفي لتخزين مؤشر أو فهرس.
يتم إنشاء شاشات العرض الفعلية من خلال توصيلها أثناء التشغيل. عند توصيل شاشة خارجية، ينشئ HWC معرّفًا ويمرّره إلى SurfaceFlinger من خلال دالة hotplug. يتم إنشاء الشاشات الافتراضية من خلال استدعاء SurfaceFlinger للدالة createVirtualDisplay()
لطلب شاشة. إذا كان HWC يتيح إنشاء شاشة عرض افتراضية، سيعرض مقبضًا. بعد ذلك، يفوّض SurfaceFlinger عملية إنشاء الصور المعروضة إلى HWC. إذا كان HWC لا يتيح إنشاء تركيبة العرض الافتراضي، ينشئ SurfaceFlinger المقبض ويجمع العرض.
عمليات إنشاء شاشة العرض
يتم تنشيط SurfaceFlinger مرة واحدة لكل VSync إذا كان يتضمّن محتوًى جديدًا لدمجه. يمكن أن يكون هذا المحتوى الجديد عبارة عن مخازن مؤقتة جديدة للصور من التطبيقات أو تغيير في خصائص طبقة واحدة أو أكثر. عندما يفعّل SurfaceFlinger شاشة الجهاز:
- تعالج هذه السمة المعاملات، إذا كانت متوفّرة.
- يتم إغلاق مخازن مؤقتة جديدة للرسومات، إذا كانت متوفرة.
- تُجري عملية إنشاء جديدة إذا أدّت الخطوة 1 أو 2 إلى تغيير في المحتوى المعروض.
لتنفيذ عملية دمج جديدة، ينشئ SurfaceFlinger طبقات أو يتلفها أو يعدّل حالات الطبقات، حسب الاقتضاء. ويعدّل أيضًا الطبقات بمحتواها الحالي، وذلك باستخدام طلبات مثل setLayerBuffer
أو setLayerColor
. بعد تعديل جميع الطبقات، يستدعي SurfaceFlinger الدالة validateDisplay
، التي تخبر HWC بفحص حالة الطبقات وتحديد كيفية إجراء عملية الدمج. يحاول SurfaceFlinger تلقائيًا ضبط كل طبقة
بحيث يتم تركيب الطبقة بواسطة HWC، ولكن في بعض
الحالات، يركّب SurfaceFlinger الطبقات من خلال خيار GPU الاحتياطي.
بعد استدعاء validateDisplay
، يستدعي SurfaceFlinger الدالة getChangedCompositionTypes
لمعرفة ما إذا كان HWC يريد تغيير أي من أنواع تركيب الطبقات قبل إجراء عملية التركيب. لقبول التغييرات، يستدعي SurfaceFlinger
acceptDisplayChanges
.
إذا تم وضع علامة على أي طبقات لتكوينها باستخدام SurfaceFlinger، يدمجها SurfaceFlinger في المخزن المؤقت المستهدف. بعد ذلك، يستدعي SurfaceFlinger الدالة
setClientTarget
لمنح المخزن المؤقت لجهاز العرض حتى يمكن عرض المخزن المؤقت على الشاشة أو دمجه بشكل أكبر مع الطبقات التي لم يتم وضع علامة عليها لدمجها باستخدام SurfaceFlinger. إذا لم يتم وضع علامة على أي طبقات لتكوين SurfaceFlinger، سيتجاوز SurfaceFlinger خطوة التكوين.
أخيرًا، يستدعي SurfaceFlinger الدالة presentDisplay
لإخبار HWC بإكمال عملية الدمج وعرض النتيجة النهائية.
إعلانات صورية متعددة
يتيح نظام التشغيل Android 10 استخدام شاشات عرض فعلية متعددة. عند تصميم عملية تنفيذ HWC مخصّصة للاستخدام على الإصدار 7.0 من نظام التشغيل Android والإصدارات الأحدث، هناك بعض القيود غير المتوفّرة في تعريف HWC:
- يُفترض أنّ هناك شاشة داخلية واحدة فقط. الشاشة الداخلية هي الشاشة التي تُبلغ عن عملية التوصيل السريع أثناء عملية التشغيل. بعد توصيل الشاشة الداخلية، لا يمكن فصلها.
- بالإضافة إلى الشاشة الداخلية، يمكن توصيل أي عدد من الشاشات الخارجية أثناء التشغيل العادي للجهاز. يفترض إطار العمل أنّ جميع عمليات التوصيل السريع بعد شاشة العرض الداخلية الأولى هي شاشات عرض خارجية، لذا إذا تمت إضافة أي شاشات عرض داخلية أخرى، سيتم تصنيفها بشكل غير صحيح على أنّها
Display.TYPE_HDMI
بدلاً منDisplay.TYPE_BUILT_IN
.
على الرغم من أنّ عمليات 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 بدلاً من إرساله إلى الشاشة. تكتب أداة Hardware Composer (HWC) الناتج في مخزن مؤقت، وتوفّر سياج الإكمال، وترسل المخزن المؤقت إلى مستهلك (مثل برنامج ترميز الفيديو ووحدة معالجة الرسومات ووحدة المعالجة المركزية وما إلى ذلك). يمكن للشاشات الافتراضية استخدام 2D/blitter أو التراكبات إذا كانت عملية عرض الشاشة تكتب في الذاكرة.
الأوضاع
يكون كل إطار في أحد الأوضاع الثلاثة التالية بعد أن يستدعي SurfaceFlinger طريقة validateDisplay()
HWC:
- GLES: تدمج وحدة معالجة الرسومات جميع الطبقات، وتكتب مباشرةً في مخزن الإخراج المؤقت. لا يشارك رمز HWC في تأليف الأغنية.
- MIXED: تدمج وحدة معالجة الرسومات بعض الطبقات في مخزن مؤقت للّقطات، وتدمج خدمة HWC المخزن المؤقت للّقطات والطبقات المتبقية، وتكتب مباشرةً في المخزن المؤقت للإخراج.
- HWC: يجمع HWC كل الطبقات ويكتب مباشرةً في المخزن المؤقت للإخراج.
تنسيق الإخراج
تعتمد تنسيقات إخراج مخزن مؤقت للعرض الافتراضي على الوضع الذي يتم استخدامه:
- وضع GLES: يضبط برنامج تشغيل EGL تنسيق المخزن المؤقت للإخراج في
dequeueBuffer()
، وعادةً ما يكونRGBA_8888
. يجب أن يتمكّن المستهلك من قبول تنسيق الإخراج الذي يحدّده برنامج التشغيل، وإلا لن يتمكّن من قراءة المخزن المؤقت. - الوضعَان MIXED وHWC: إذا كان المستهلك بحاجة إلى الوصول إلى وحدة المعالجة المركزية (CPU)، يحدّد المستهلك التنسيق. وفي الحالات الأخرى، يكون التنسيق
IMPLEMENTATION_DEFINED
، ويضبط Gralloc أفضل تنسيق استنادًا إلى علامات الاستخدام. على سبيل المثال، يضبط Gralloc تنسيق YCbCr إذا كان المستهلك هو برنامج ترميز الفيديو ويمكن لـ HWC كتابة التنسيق بكفاءة.
حواجز المزامنة
تُعدّ حواجز المزامنة (sync) جانبًا مهمًا من نظام الرسومات في Android. تسمح الحواجز لوحدة المعالجة المركزية (CPU) بمواصلة العمل بشكل مستقل عن عمل وحدة معالجة الرسومات (GPU) المتزامن، ولا يتم الحظر إلا عند وجود تبعية حقيقية.
على سبيل المثال، عندما يرسل تطبيق مخزنًا مؤقتًا يتم إنتاجه على وحدة معالجة الرسومات، يرسل أيضًا عنصر سياج مزامنة. يشير هذا السياج إلى الوقت الذي تنتهي فيه وحدة معالجة الرسومات من الكتابة في المخزن المؤقت.
يتطلّب HWC أن تُنهي وحدة معالجة الرسومات كتابة المخازن المؤقتة قبل عرضها. يتم تمرير حواجز المزامنة عبر مسار عرض الرسومات مع المخازن المؤقتة، ويتم إرسال إشارة عند كتابة المخازن المؤقتة. قبل عرض المخزن المؤقت، تتحقّق HWC مما إذا كان سياج المزامنة قد أرسل إشارة، وإذا كان قد أرسل إشارة، تعرض المخزن المؤقت.
لمزيد من المعلومات حول حواجز المزامنة، يُرجى الاطّلاع على دمج Hardware Composer.