מסגרת הסנכרון מתארת באופן מפורש יחסי תלות בין פעולות אסינכרוניות שונות במערכת הגרפיקה של Android. המסגרת מספקת ממשק API שמאפשר לרכיבים לציין מתי מאגרים מתפנים. המסגרת מאפשרת גם להעביר פרימיטיבים של סנכרון בין מנהלי התקנים מהליבה למרחב המשתמש, ובין תהליכים במרחב המשתמש עצמם.
לדוגמה, אפליקציה עשויה להוסיף לתור פעולות לביצוע ב-GPU. המעבד הגרפי מתחיל לצייר את התמונה הזו. התמונה עדיין לא נוצרה בזיכרון, אבל מצביע המאגר מועבר למרכיב המרכזי של החלון יחד עם פס שמציין מתי העבודה של ה-GPU תסתיים. מחבר החלונות מתחיל לעבד מראש את הזמן מעביר את העבודה לבקר התצוגה. באותו אופן, ה-CPU מתבצעת מראש. אחרי שה-GPU מסיים, בקר התצוגה מציג את התמונה באופן מיידי.
מסגרת הסנכרון מאפשרת למטמיעים גם לנצל משאבי סנכרון ברכיבי החומרה שלהם. לבסוף, המסגרת מספקת שקיפות בצינור עיבוד הנתונים של הגרפיקה כדי לעזור בניפוי באגים.
סנכרון מפורש
סנכרון מפורש מאפשר ליוצרים ולצרכנים של מאגרי גרפיקה לסמן מתי הם סיימו להשתמש במאגר. סנכרון מפורש הוא הוטמעו בליבה (kernel-space).
היתרונות של סנכרון מפורש כוללים:
- פחות הבדלים בהתנהגות בין מכשירים
- תמיכה טובה יותר בניפוי באגים
- מדדי בדיקה משופרים
יש שלושה סוגים של אובייקטים במסגרת הסנכרון:
sync_timeline
sync_pt
sync_fence
sync_timeline
sync_timeline
הוא ציר זמן בעלייה מונוטונית
על הספקים להטמיע עבור כל מופע של מנהל התקן, כמו הקשר GL,
שלט רחוק או נצנצים בדו-ממד. sync_timeline
מונה את המשימות שנשלחו לליבה עבור חומרה מסוימת.
הספק sync_timeline
מספק אחריות לגבי סדר הפעילות
ומאפשרת הטמעות ספציפיות לחומרה.
יש לפעול לפי ההנחיות הבאות כשמטמיעים את sync_timeline
:
- מספקים שמות שימושיים לכל הנהגים, צירי הזמן והגדרות כדי לפשט את התהליך ניפוי באגים.
- מטמיעים את האופרטורים
timeline_value_str
ו-pt_value_str
בזמני ציר כדי להקל על הקריאה של הפלט של ניפוי הבאגים. - הטמעת המילוי
driver_data
כדי לתת לספריות של מרחב משתמשים, כמו ספריית GL, גישה לנתונים פרטיים בציר הזמן, אם רוצים.data_driver
מאפשר לספקים להעביר מידע על הפריטים שלא ניתנים לשינויsync_fence
ו-sync_pts
כדי לבנות שורות פקודה שמבוססים עליהם. - אסור לאפשר למרחב המשתמש ליצור גדר או לסמן אותה באופן מפורש. יצירת אותות או גדרות באופן מפורש גורמת להתקפת מניעת שירות (DoS) שגורמת להפסקה של הפונקציונליות של צינור עיבוד הנתונים.
- אין גישה אל
sync_timeline
,sync_pt
אוsync_fence
באופן מפורש. ה-API מספק את כל הפונקציות הנדרשות.
Sync_pt
sync_pt
הוא ערך יחיד או נקודה יחידה ב-sync_timeline
. לנקודה יש שלושה מצבים: פעיל, אות ושיגיאה. הנקודות מתחילות במצב פעיל ומעברות למצבים 'התקבל אות' או 'שגיאה'. לדוגמה, כשצרכן תמונה כבר לא זקוק למאגר, הוא שולח אות sync_pt
כדי ליידע את יוצר התמונה שאפשר לכתוב שוב במאגר.
סנכרון_גדר
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
- ספרייה שמשמשת לתקשורת עם מרחב הליבה (kernel) שבה
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 ב-Android:
- אם ה-API מספק מתאר קובץ שמתייחס ל-
sync_pt
, הנהג של הספק או ה-HAL שמשתמש ב-API חייבים לסגור את מתאר הקובץ. - אם מנהל ההתקן של הספק או ה-HAL מעבירים מתאר קובץ שמכיל
sync_pt
לפונקציית API, מנהל התקן של הספק או HAL לא יכולים סוגרים את מתאר הקובץ. - כדי להמשיך להשתמש במתאר קובץ הגדר, במנהל ההתקן של הספק או HAL חייב לשכפל את המתאר.
השם של אובייקט גדר משתנה בכל פעם שהוא עובר דרך BufferQueue.
תמיכה בגדר ליבה מאפשרת לגדרות לקבל מחרוזות לשמות, כך שהסנכרון
framework משתמש בשם החלון ובאינדקס מאגר הנתונים הזמני שממתינים בתור לשם
גדר, למשל 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
מאפשר דוכנים בצד ה-GPU במקום בצד המעבד (CPU), ולגרום ל-GPU להמתין ל-EGLSyncKHR
. התוסףEGL_ANDROID_wait_sync
זהה לתוסףEGL_KHR_wait_sync
.
כדי להשתמש בתוספים האלה בנפרד, מטמיעים את
תוסף EGL_ANDROID_native_fence_sync
עם הנכס המשויך
תמיכה בליבה (kernel). בשלב הבא, מפעילים את 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.
התוצאה זהה לזו של שאילתה על המאפיין שהוגדר, אבל היא פועלת לפי
המוסכמה שהנמען סוגר את הגדרות (כלומר, הכפילות
). לבסוף, השמדת האובייקט EGLSyncKHR
סוגרת את מאפיין הגדרת ההיקף הפנימי.
שילוב של Hardware Composer
הכלי ליצירת חומרה מטפל בשלושה סוגים של גדרות סנכרון:
- הגדרות רכישה מועברות יחד עם חוצצי קלט אל
השיחות
setLayerBuffer
ו-setClientTarget
. הם מייצגים כתיבה בהמתנה למאגר, וצריך לסמן אותם לפני ש-SurfaceFlinger או ה-HWC מנסים לקרוא מהמאגר המשויך כדי לבצע קומפוזיציה. - גדרות שחרור מאוחזרות אחרי הקריאה ל-
presentDisplay
באמצעות הקריאהgetReleaseFences
. המחרוזות האלה מייצגות קריאה בהמתנה מהמאגר הקודם באותה שכבה. א' לשחרור אותות הגדר כשמערכת HWC כבר לא משתמשת במאגר הנתונים הזמני כי מאגר הנתונים הזמני החליף את המאגר הקודם במסך. הגדרות החסימה מועברות בחזרה לאפליקציה יחד עם מאגרי הנתונים הזמניים הקודמים יוחלף במהלך היצירה הנוכחית. האפליקציה צריכה להמתין עד שתקבל אות מ-release fence כדי לכתוב תוכן חדש במאגר שקיבלתם בחזרה. - הגדרות הקיימות מוחזרות, אחת לכל פריים, כחלק מ
את הקריאה אל
presentDisplay
. גדרות נוכחיות מייצגות כאשר של המסגרת הזו הסתיים, או לחילופין, לאחר אין יותר צורך בתוצאת חיבור של הפריים הקודם. לפיזי מוצגת,presentDisplay
מחזירה את גדרות הקיימות המסגרת הנוכחית מופיעה במסך. אחרי שהגדרות הגדרת המכשול הקיימות מוחזרות, אפשר לכתוב שוב במאגר היעד של SurfaceFlinger, אם הדבר רלוונטי. במסכים וירטואליים, גדרות נוכחיות מוחזרות אפשר לקרוא אותו ממאגר הנתונים הזמני של הפלט.