چارچوب همگام سازی به صراحت وابستگی های بین عملیات ناهمزمان مختلف در سیستم گرافیک اندروید را توصیف می کند. این فریم ورک یک API را ارائه میکند که اجزا را قادر میسازد زمان انتشار بافرها را نشان دهند. این فریم ورک همچنین اجازه می دهد تا اصول اولیه همگام سازی بین درایورها از هسته به فضای کاربر و بین خود فرآیندهای فضای کاربر منتقل شود.
به عنوان مثال، یک برنامه ممکن است کار را برای انجام در GPU در صف قرار دهد. GPU شروع به کشیدن آن تصویر می کند. اگرچه تصویر هنوز به حافظه کشیده نشده است، نشانگر بافر به همراه یک حصار به ترکیبکننده پنجره ارسال میشود که نشان میدهد چه زمانی کار GPU تمام میشود. سازنده پنجره زودتر شروع به پردازش می کند و کار را به کنترل کننده نمایش می دهد. به روشی مشابه، کار CPU زودتر از موعد انجام می شود. هنگامی که GPU تمام شد، کنترل کننده صفحه نمایش بلافاصله تصویر را نمایش می دهد.
چارچوب همگامسازی همچنین به پیادهکنندگان اجازه میدهد تا از منابع همگامسازی در اجزای سختافزاری خود استفاده کنند. در نهایت، این فریم ورک برای کمک به اشکال زدایی، قابلیت مشاهده را در خط لوله گرافیکی فراهم می کند.
همگام سازی صریح
همگامسازی صریح به تولیدکنندگان و مصرفکنندگان بافرهای گرافیکی امکان میدهد پس از پایان استفاده از بافر سیگنال دهند. همگام سازی صریح در kernel-space پیاده سازی شده است.
مزایای همگام سازی صریح عبارتند از:
- تغییرات رفتاری کمتر بین دستگاه ها
- پشتیبانی از اشکال زدایی بهتر
- معیارهای تست بهبود یافته
چارچوب همگام سازی دارای سه نوع شی است:
-
sync_timeline
-
sync_pt
-
sync_fence
sync_timeline
sync_timeline
یک جدول زمانی یکنواخت در حال افزایش است که فروشندگان باید برای هر نمونه درایور اجرا کنند، مانند زمینه GL، کنترل کننده نمایشگر، یا blitter 2 بعدی. sync_timeline
کارهای ارسال شده به هسته را برای یک قطعه سخت افزاری خاص می شمارد. sync_timeline
تضمین هایی را در مورد ترتیب عملیات ارائه می دهد و پیاده سازی های مخصوص سخت افزار را فعال می کند.
هنگام اجرای sync_timeline
این دستورالعمل ها را دنبال کنید:
- برای سادهسازی اشکالزدایی، نامهای مفیدی برای همه درایورها، جدولهای زمانی و حصارها ارائه کنید.
- عملگرهای
timeline_value_str
وpt_value_str
را در تایم لاینها پیادهسازی کنید تا خروجی اشکالزدایی خواناتر شود. - Fill
driver_data
پیاده سازی کنید تا در صورت تمایل به کتابخانه های فضای کاربران، مانند کتابخانه GL، دسترسی به داده های جدول زمانی خصوصی بدهید.data_driver
به فروشندگان اجازه می دهد اطلاعات مربوط بهsync_fence
تغییرناپذیر وsync_pts
برای ایجاد خطوط فرمان بر اساس آنها ارسال کنند. - اجازه ندهید که Userspace صریحاً حصاری ایجاد کند یا علامت دهد. ایجاد صریح سیگنال/حصار منجر به حمله انکار سرویس می شود که عملکرد خط لوله را متوقف می کند.
- به طور واضح به عناصر
sync_timeline
،sync_pt
یاsync_fence
دسترسی ندهید. API تمام توابع مورد نیاز را فراهم می کند.
sync_pt
sync_pt
یک مقدار یا نقطه در یک sync_timeline
است. یک نقطه سه حالت دارد: فعال، علامت دار و خطا. نقاط در حالت فعال شروع می شوند و به حالت های سیگنال یا خطا منتقل می شوند. به عنوان مثال، هنگامی که یک مصرف کننده تصویر دیگر نیازی به بافر ندارد، یک sync_pt
سیگنال داده می شود تا تولید کننده تصویر بداند که اشکالی ندارد که دوباره در بافر بنویسد.
sync_fence
sync_fence
مجموعهای از مقادیر sync_pt
است که اغلب دارای والدین sync_timeline
مختلفی هستند (مانند کنترلکننده نمایشگر و GPU). 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
) و پشتیبانی از حصار در درایور گرافیک.
مطالعه موردی: درایور نمایشگر را پیاده سازی کنید
برای استفاده از API که از عملکرد همگام سازی پشتیبانی می کند، یک درایور نمایشگر ایجاد کنید که دارای عملکرد بافر نمایشگر باشد. قبل از اینکه چارچوب همگامسازی وجود داشته باشد، این تابع اشیاء 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 پیروی کنید:
- اگر API یک توصیفگر فایل ارائه میکند که به
sync_pt
اشاره دارد، درایور فروشنده یا HAL با استفاده از API باید توصیفگر فایل را ببندد. - اگر درایور فروشنده یا HAL یک توصیفگر فایل حاوی
sync_pt
را به یک تابع API ارسال کند، درایور فروشنده یا 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
به جای CPU، امکان توقف در سمت GPU را فراهم می کند، و باعث می شود GPU منتظر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
ایجاد می کند.
از فراخوانی تابع DupNativeFenceFD()
برای استخراج شی EGLSyncKHR
از توصیفگر فایل حصار اصلی Android استفاده کنید. این همان نتیجه جستجوی ویژگی set است، اما به این قرارداد پایبند است که گیرنده حصار را میبندد (از این رو عملیات تکراری). در نهایت، از بین بردن شی EGLSyncKHR
باعث بسته شدن ویژگی حصار داخلی می شود.
یکپارچه سازی آهنگساز سخت افزار
Hardware Composer سه نوع حصار همگام سازی را مدیریت می کند:
- حصارهای Acquire به همراه بافرهای ورودی به فراخوانی
setLayerBuffer
وsetClientTarget
منتقل می شوند. اینها یک نوشتن معلق در بافر را نشان می دهند و باید قبل از اینکه SurfaceFlinger یا HWC برای خواندن از بافر مرتبط برای انجام ترکیب، سیگنال دهند. - حصارهای انتشار پس از تماس با
presentDisplay
با استفاده از تماسgetReleaseFences
بازیابی می شوند. اینها یک خواندن معلق از بافر قبلی در همان لایه را نشان می دهند. حصار رهاسازی سیگنال می دهد که HWC دیگر از بافر قبلی استفاده نمی کند زیرا بافر فعلی جایگزین بافر قبلی روی نمایشگر شده است. حصارهای انتشار به همراه بافرهای قبلی که در ترکیب فعلی جایگزین خواهند شد به برنامه بازگردانده می شوند. قبل از نوشتن محتوای جدید در بافری که به آن بازگردانده شده است، برنامه باید صبر کند تا حصار آزادسازی سیگنال دهد. - حصارهای حاضر ، یکی در هر فریم، به عنوان بخشی از تماس با
presentDisplay
بازگردانده می شوند. حصارهای فعلی نشان دهنده زمانی است که ترکیب این قاب کامل شده است، یا به طور متناوب، زمانی که نتیجه ترکیب بندی قاب قبلی دیگر مورد نیاز نیست. برای نمایشگرهای فیزیکی،presentDisplay
حصارهای فعلی را هنگامی که قاب فعلی روی صفحه ظاهر می شود، برمی گرداند. پس از بازگرداندن حصارهای فعلی، در صورت وجود، می توانید دوباره به بافر هدف SurfaceFlinger بنویسید. برای نمایشگرهای مجازی، حصارهای موجود زمانی برمی گردند که خواندن از بافر خروجی ایمن باشد.