הטמעת Hardware Composer HAL

שכבות ה-HWC) HAL מרוכבות שהתקבלו מ-SurfaceFlinger, מצמצמות את כמות הקומפוזיציה של OpenGL ES (GLES) וה-GPU.

ה-HWC מפשט אובייקטים, כגון שכבות על ו-2D bliters, למשטחים מרוכבים ומתקשר עם חומרה מיוחדת של הרכב חלונות לחלונות מרוכבים. השתמש ב-HWC כדי להרכיב חלונות במקום להשתמש ב-SurfaceFlinger מורכב עם ה-GPU. רוב ה-GPUs אינם מותאמים להרכב, וכאשר ה-GPU מרכיב שכבות מ-SurfaceFlinger, אפליקציות לא יכולות להשתמש ב-GPU לעיבוד משלהן.

יישומי HWC צריכים לתמוך ב:

  • לפחות ארבע שכבות-על:
    • שורת מצב
    • סרגל מערכת
    • אפליקציה
    • טפט/רקע
  • שכבות גדולות מהתצוגה (לדוגמה, טפט)
  • מיזוג אלפא מוכפל מראש סימולטני לכל פיקסל ומיזוג אלפא לכל מישור
  • נתיב חומרה להפעלת וידאו מוגנת
  • סדר אריזה RGBA, פורמטים של YUV, ומאפייני ריצוף, סיבוב וצעד

כדי ליישם את HWC:

  1. הטמעת HWC לא מבצעית ושלח את כל עבודת ההרכב ל-GLES.
  2. הטמעת אלגוריתם להאצלת הרכב ל-HWC בהדרגה. לדוגמה, האצל רק את שלושת או ארבעת המשטחים הראשונים לחומרת השכבה של ה-HWC.
  3. בצע אופטימיזציה של HWC. זה עשוי לכלול:
    • בחירת משטחים שממקסמים את העומס המוריד מה-GPU ושולחים אותם ל-HWC.
    • מזהה אם המסך מתעדכן. אם לא, האצול הרכב ל-GLES במקום ל-HWC כדי לחסוך בחשמל. כאשר המסך מתעדכן שוב, המשך להוריד את הרכב ל-HWC.
    • הכנה למקרי שימוש נפוצים כגון:
      • מסך הבית, הכולל את שורת המצב, שורת המערכת, חלון האפליקציה וטפטים חיים
      • משחקי מסך מלא במצב דיוקן ונוף
      • וידאו במסך מלא עם כתוביות ובקרת השמעה
      • הפעלת וידאו מוגנת
      • מרובה חלונות במסך מפוצל

הפרימיטיבים של HWC

ה-HWC מספק שני פרימיטיבים, שכבות ותצוגות , כדי לייצג עבודת קומפוזיציה והאינטראקציה שלה עם חומרת התצוגה. ה-HWC מספק גם שליטה על VSYNC והתקשרות חזרה ל- SurfaceFlinger כדי להודיע ​​לו כאשר מתרחש אירוע VSYNC.

ממשק HIDL

אנדרואיד 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 קורא 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 callback. תצוגות וירטואליות נוצרות על ידי SurfaceFlinger שקורא createVirtualDisplay() כדי לבקש תצוגה. אם ה-HWC תומך בהרכב תצוגה וירטואלית, הוא מחזיר ידית אחיזה. לאחר מכן, SurfaceFlinger מאציל את הרכב התצוגות ל-HWC. אם ה-HWC אינו תומך בהרכב תצוגה וירטואלית, SurfaceFlinger יוצר את הידית ומרכיב את התצוגה.

הצגת פעולות קומפוזיציה

פעם אחת לכל VSYNC, SurfaceFlinger מתעורר אם יש לו תוכן חדש למרוכב. תוכן חדש זה יכול להיות מאגרי תמונה חדשים מאפליקציות או שינוי במאפיינים של שכבה אחת או יותר. כאשר SurfaceFlinger מעיר אותו:

  1. מטפל בעסקאות, אם קיימות.
  2. חוסם מאגרים גרפיים חדשים, אם קיימים.
  3. מבצע קומפוזיציה חדשה, אם שלב 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 להשלים את תהליך ההרכב ולהציג את התוצאה הסופית.

תצוגות מרובות

אנדרואיד 10 תומך במספר צגים פיזיים. בעת תכנון מימוש HWC המיועד לשימוש ב-Android 7.0 ואילך, קיימות כמה הגבלות שאינן קיימות בהגדרת HWC:

  • ההנחה היא שיש בדיוק תצוגה פנימית אחת. התצוגה הפנימית היא התצוגה שעליה מדווח ה-hotplug הראשוני במהלך האתחול. לאחר שהתצוגה הפנימית מחוברת לחיבור חם, לא ניתן לנתק אותה.
  • בנוסף לתצוגה הפנימית, כל מספר של צגים חיצוניים עשויים להיות מחוברים לחיבור חם במהלך פעולה רגילה של המכשיר. המסגרת מניחה שכל התקעים החמים לאחר התצוגה הפנימית הראשונה הם צגים חיצוניים, כך שאם נוספים צגים פנימיים נוספים, הם מסווגים באופן שגוי כ- 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) כותב את הפלט למאגר, מספק את גדר ההשלמה ושולח את המאגר לצרכן (כגון מקודד הווידאו, GPU, CPU וכן הלאה). תצוגות וירטואליות יכולות להשתמש ב-2D/בליטר או בשכבות-על אם צינור התצוגה כותב לזיכרון.

מצבים

כל פריים נמצא באחד משלושה מצבים לאחר ש- SurfaceFlinger קורא לשיטת validateDisplay() HWC:

  • GLES - ה-GPU מורכב מכל השכבות, כותב ישירות למאגר הפלט. HWC לא מעורב בהרכב.
  • MIXED — ה-GPU מרכיב כמה שכבות למאגר המסגרת ו-HWC מרכיב את ה-framebuffer ואת השכבות הנותרות, כותב ישירות למאגר הפלט.
  • HWC - HWC מרכיב את כל השכבות וכותב ישירות למאגר הפלט.

פורמט פלט

פורמטים של פלט מאגר תצוגה וירטואלי תלויים במצב שלהם:

  • מצב GLES - מנהל ההתקן של EGL מגדיר את פורמט מאגר הפלט ב- dequeueBuffer() , בדרך כלל RGBA_8888 . הצרכן חייב להיות מסוגל לקבל את פורמט הפלט שמנהל ההתקן מגדיר אחרת לא ניתן לקרוא את המאגר.
  • מצבי MIXED ו-HWC - אם הצרכן זקוק לגישה למעבד, הצרכן מגדיר את הפורמט. אחרת, הפורמט הוא IMPLEMENTATION_DEFINED , ו- Gralloc מגדיר את הפורמט הטוב ביותר על סמך דגלי השימוש. לדוגמה, Gralloc מגדיר פורמט YCbCr אם הצרכן הוא מקודד וידאו ו-HWC יכול לכתוב את הפורמט ביעילות.

גדרות סנכרון

גדרות סנכרון (סנכרון) הן היבט מכריע של מערכת הגרפיקה של אנדרואיד. גדרות מאפשרות לעבודת מעבד להתקדם באופן עצמאי מעבודת GPU במקביל, חוסמות רק כאשר יש תלות אמיתית.

לדוגמה, כאשר אפליקציה שולחת מאגר שמיוצר ב-GPU, היא שולחת גם אובייקט של גדר סינכרון. גדר זו מסמנת כאשר ה-GPU סיים לכתוב לתוך המאגר.

ה-HWC דורש שה-GPU יסיים לכתוב מאגרים לפני הצגת מאגרים. גדרות סינכרון מועברות דרך צינור הגרפיקה עם חוצצים ומאותות כאשר מאגרים נכתבים. לפני הצגת מאגר, ה-HWC בודק אם גדר הסנכרון סימנה, ואם כן, הוא מציג את המאגר.

למידע נוסף על גדרות סנכרון, ראה שילוב חומרה מלחין .