پیاده‌سازی «لایه انتزاع سخت‌افزار آهنگ‌ساز»

Hardware Composer (HWC) HAL لایه‌های دریافتی از SurfaceFlinger را ترکیب می‌کند و میزان ترکیب‌بندی انجام‌شده توسط OpenGL ES (GLES) و واحد پردازش گرافیکی را کاهش می‌دهد.

‫HWC اشیایی مانند رونهادها و blitterهای دوبعدی را به سطوح ترکیبی انتزاع می‌کند و برای ترکیب کردن پنجره‌ها با سخت‌افزار ترکیب پنجره تخصصی ارتباط برقرار می‌کند. از HWC برای ترکیب کردن پنجره‌ها به‌جای ترکیب کردن SurfaceFlinger با GPU استفاده کنید. اکثر واحدهای پردازش گرافیکی برای ترکیب بهینه‌سازی نشده‌اند، و وقتی واحد پردازش گرافیکی لایه‌ها را از SurfaceFlinger ترکیب می‌کند، برنامه‌ها نمی‌توانند از واحد پردازش گرافیکی برای رندر کردن خودشان استفاده کنند.

پیاده‌سازی‌های HWC باید از موارد زیر پشتیبانی کنند:

  • حداقل چهار رونهاد:
    • نوار وضعیت
    • نوار سیستم
    • برنامه
    • کاغذدیواری/پس‌زمینه
  • لایه‌هایی که بزرگ‌تر از نمایشگر هستند (برای مثال، کاغذدیواری)
  • ترکیب آلفای پیش‌ضرب‌شده هم‌زمان برای هر پیکسل و ترکیب آلفا برای هر صفحه
  • مسیر سخت‌افزاری برای بازپخش ویدیو حفاظت‌شده
  • ترتیب بسته‌بندی RGBA، قالب‌های YUV، و ویژگی‌های کاشی‌بندی، جابه‌جایی، و گام

برای پیاده‌سازی HWC:

  1. یک HWC غیرعملیاتی را پیاده‌سازی کنید و تمام کارهای ترکیب‌بندی را به GLES ارسال کنید.
  2. الگوریتمی را پیاده‌سازی کنید که ترکیب‌بندی را به‌صورت افزایشی به HWC واگذار کند. برای مثال، فقط سه یا چهار سطح اول را به سخت‌افزار هم‌پوشانی HWC واگذار کنید.
  3. «کنترل‌کننده سخت‌افزاری» را بهینه‌سازی کنید. این امر ممکن است شامل موارد زیر باشد:
    • انتخاب سطوحی که بار برداشته‌شده از GPU را به حداکثر می‌رساند و ارسال آن‌ها به HWC.
    • درحال تشخیص اینکه آیا صفحه درحال به‌روزرسانی است یا نه. اگر این‌طور نیست، ترکیب‌بندی را به‌جای HWC به GLES واگذار کنید تا در مصرف برق صرفه‌جویی شود. وقتی صفحه دوباره به‌روز شد، به واگذاری ترکیب به HWC ادامه دهید.
    • آماده‌سازی برای موارد استفاده رایج، مانند:
      • صفحه اصلی، که شامل نوار وضعیت، نوار سیستم، پنجره برنامه، و کاغذدیواری‌های پویا است
      • بازی‌های تمام‌صفحه در حالت عمودی و افقی
      • ویدیو تمام‌صفحه با زیرنویس ناشنوایان و کنترل بازپخش
      • بازپخش ویدیو محافظت‌شده
      • چندپنجره‌ای صفحه دونیمه

اصول HWC

‫HWC دو عنصر اولیه، لایه‌ها و نمایشگرها، را برای نمایش کار ترکیب و تعامل آن با سخت‌افزار نمایشگر ارائه می‌دهد. HWC همچنین کنترل VSync و یک فراخوانی برگشتی به SurfaceFlinger را فراهم می‌کند تا هنگام وقوع رویداد VSync به آن اطلاع دهد.

میانای HIDL

‫Android 8.0 و بالاتر از میانای HIDL به‌نام Composer HAL برای IPC پیوندی بین 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 در Composer HAL createLayer() فراخوانی می‌کند.

اگر فروشندگان رابط 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 منتقل می‌کند. نمایشگرهای مجازی توسط SurfaceFlinger با فراخوانی createVirtualDisplay() برای درخواست نمایشگر ایجاد می‌شوند. اگر HWC از ترکیب‌بندی نمایشگر مجازی پشتیبانی کند، یک دسته برمی‌گرداند. سپس SurfaceFlinger ترکیب‌بندی نمایشگر را به HWC واگذار می‌کند. اگر HWC از ترکیب نمایشگر مجازی پشتیبانی نکند، SurfaceFlinger دستگیره را ایجاد می‌کند و نمایشگر را ترکیب می‌کند.

نمایش عملیات ترکیب‌بندی

یک‌بار در هر VSync، اگر SurfaceFlinger محتوای جدیدی برای ترکیب داشته باشد بیدار می‌شود. این محتوای جدید می‌تواند میانگیرهای تصویر جدید از برنامه‌ها یا تغییری در ویژگی‌های یک یا چند لایه باشد. وقتی SurfaceFlinger آن را بیدار می‌کند:

  1. درصورت وجود، تراکنش‌ها را مدیریت می‌کند.
  2. بافرهای گرافیکی جدید را، درصورت وجود، قفل می‌کند.
  3. اگر مرحله ۱ یا ۲ منجر به تغییر در محتوای نمایشگر شود، ترکیب جدیدی انجام می‌دهد.

برای انجام ترکیب‌بندی جدید، 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 که برای استفاده در Android 7.0 و بالاتر درنظر گرفته شده است، محدودیت‌هایی وجود دارد که در تعریف 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 ارسال می‌کنند. «ترکیب‌کننده سخت‌افزاری» (HWC) برونداد را در بافر می‌نویسد، نرده تکمیل را ارائه می‌دهد، و بافر را به مصرف‌کننده (مثل کدبند ویدیو، GPU،‏ CPU، و غیره) ارسال می‌کند. نمایشگرهای مجازی می‌توانند از 2D/blitter یا هم‌پوشانی‌ها استفاده کنند اگر خط لوله نمایشگر در حافظه بنویسد.

حالت‌ها

هر قاب پس‌از اینکه SurfaceFlinger روش validateDisplay() HWC را فراخوانی می‌کند در یکی از سه حالت زیر قرار می‌گیرد:

  • GLES — واحد پردازش گرافیکی همه لایه‌ها را ترکیب می‌کند و مستقیماً در بافر برونداد می‌نویسد. «کمیته ارزیابی آهنگ‌سازی» در آهنگ‌سازی دخیل نیست.
  • ترکیبی — واحد پردازش گرافیکی برخی‌از لایه‌ها را در قاب‌بافر ترکیب می‌کند و HWC قاب‌بافر و لایه‌های باقی‌مانده را ترکیب می‌کند و مستقیماً در بافر برونداد می‌نویسد.
  • HWC — HWC همه لایه‌ها را ترکیب می‌کند و مستقیماً در میان‌گیر خروجی می‌نویسد.

قالب برونداد

قالب‌های برونداد بافر نمایشگر مجازی به حالت آن‌ها بستگی دارد:

  • حالت GLES — درایور EGL قالب میان‌گیر خروجی را در dequeueBuffer() تنظیم می‌کند، معمولاً RGBA_8888. مصرف‌کننده باید بتواند قالب خروجی‌ای را که درایور تنظیم می‌کند بپذیرد، درغیراین‌صورت میان‌گیر خوانده نمی‌شود.
  • حالت‌های «مختلط» و «سخت‌افزاری» — اگر مصرف‌کننده به CPU دسترسی داشته باشد، مصرف‌کننده قالب را تنظیم می‌کند. درغیراین‌صورت، قالب IMPLEMENTATION_DEFINED است و Gralloc بهترین قالب را براساس پرچم‌های استفاده تنظیم می‌کند. برای مثال، اگر مصرف‌کننده کدبند ویدیو باشد و HWC بتواند قالب را به‌طور کارآمد بنویسد، Gralloc قالب YCbCr را تنظیم می‌کند.

نرده‌های همگام‌سازی

نرده‌های همگام‌سازی (همگام‌سازی) جنبه‌ای حیاتی از سیستم گرافیک Android هستند. حصارها به CPU اجازه می‌دهند کار را مستقل از کار هم‌زمان GPU ادامه دهد، و فقط زمانی مسدود می‌شود که وابستگی واقعی وجود داشته باشد.

برای مثال، وقتی برنامه‌ای بافری را که درحال تولید در GPU است ارسال می‌کند، شیء نرده همگام‌سازی را نیز ارسال می‌کند. این حصار زمانی را نشان می‌دهد که GPU نوشتن در میان‌گیر را به‌پایان رسانده است.

«کنترل‌کننده سخت‌افزاری ترکیب» (HWC) لازم می‌داند که واحد پردازش گرافیکی (GPU) نوشتن بافرها را قبل‌از نمایش بافرها به‌پایان برساند. حصار همگام‌سازی ازطریق خط لوله گرافیک با میان‌گیرها عبور می‌کند و وقتی میان‌گیرها نوشته می‌شوند سیگنال می‌دهد. قبل‌از نمایش بافر، HWC بررسی می‌کند که آیا نرده همگام‌سازی علامت داده است یا نه، و اگر علامت داده باشد، بافر را نمایش می‌دهد.

برای اطلاعات بیشتر درباره حصارهای همگام‌سازی، یکپارچه‌سازی آهنگ‌ساز سخت‌افزاری را ببینید.