שכבות ותצוגות הן שני פרימיטיביים שמייצגים עבודת הרכבה ואינטראקציות עם חומרת התצוגה.
שכבות
שכבה היא היחידה החשובה ביותר בתהליך היצירה. שכבה היא שילוב של Surface ומופע של SurfaceControl
. לכל שכבה יש קבוצה של מאפיינים שמגדירים את האינטראקציה שלה עם שכבות אחרות. מאפייני השכבות מתוארים בטבלה שלמטה.
נכס | תיאור |
---|---|
תלוי מיקום | הגדרת המיקום שבו השכבה מופיעה בתצוגה. כולל מידע כמו המיקומים של קצוות שכבה וסדר ה-Z שלה ביחס לשכבות אחרות (לפני או מאחורי שכבות אחרות). |
תוכן | הגדרת אופן הצגת התוכן בשכבה בתוך הגבולות שמוגדרים על ידי מאפייני המיקום. כולל מידע כמו חיתוך (כדי להרחיב חלק מהתוכן ולמלא את גבולות השכבה) וטרנספורמציה (כדי להציג תוכן שסובב או הופך). |
יצירה מוזיקלית | מגדירה את אופן הרכבת השכבה עם שכבות אחרות. כולל מידע כמו מצב מיזוג וערך אלפא ברמת השכבה לצורך מיזוג אלפא. |
אופטימיזציה | המידע הזה לא הכרחי ליצירת קומפוזיציה נכונה של השכבה, אבל הוא יכול לשמש את מכשיר ה-Hardware Composer (HWC) כדי לבצע אופטימיזציה של יצירת הקומפוזיציה. כולל מידע כמו האזור הגלוי של השכבה ואיזה חלק של השכבה עודכן מאז הפריים הקודם. |
מקרנים
תצוגה היא יחידה חשובה נוספת של קומפוזיציה. מערכת יכולה לכלול כמה מסכים, ואפשר להוסיף או להסיר מסכים במהלך הפעולות הרגילות של המערכת. הצגים מתווספים או מוסרם לפי בקשה של HWC או של המסגרת. הבקשות של מכשירי HWC מוצגות כבקשות להוספה או להסרה של מסך חיצוני שמחובר למכשיר או כשהוא מנותק ממנו. פעולה כזו נקראת hotplugging. לקוחות מבקשים מסכים וירטואליים, שהתוכן שלהם עובר עיבוד במאגר מחוץ למסך במקום במסך פיזי.
מסכים וירטואליים
SurfaceFlinger תומך במסך פנימי (שנמצא בטלפון או בטאבלט), במסכים חיצוניים (כמו טלוויזיה שמחוברת באמצעות HDMI) ובמסך וירטואלי אחד או יותר שמאפשרים להציג פלט מורכב בתוך המערכת. אפשר להשתמש במסכים וירטואליים כדי לצלם את המסך או לשלוח את המסך ברשת. פריימים שנוצרו בשביל תצוגה וירטואלית נכתבים ב-BufferQueue.
לתצוגות וירטואליות יכולה להיות אותה קבוצת שכבות כמו לתצוגה הראשית (מקבץ השכבות), או קבוצה משלהם. אין VSYNC למסך וירטואלי, ולכן ה-VSYNC של המסך הפנימי מפעיל את הרכבת התמונה בכל המסכים.
בהטמעות של HWC שתומכות בהן, אפשר ליצור קומפוזיציה של מסכים וירטואליים באמצעות OpenGL ES (GLES), HWC או גם GLES וגם HWC. בהטמעות ללא תמיכה, המסכים הווירטואליים תמיד מורכבים באמצעות GLES.
מקרה לדוגמה: screenrecord
הפקודה screenrecord
מאפשרת למשתמש להקליט את כל מה שמופיע במסך כקובץ .mp4
בדיסק. כדי ליישם זאת, המערכת מקבלת פריימים מורכבים מ-SurfaceFlinger, כותבת אותם במקודד הווידאו ולאחר מכן כותבת את נתוני הווידאו המקודדים בקובץ. קודקי הווידאו מנוהלים על ידי תהליך נפרד (mediaserver
), כך שמאגרי גרפיקה גדולים צריכים לנוע ברחבי המערכת. כדי להקשות על המשימה, המטרה היא לצלם סרטון בקצב של 60 FPS ברזולוציה מלאה. המפתח לכך הוא BufferQueue.
הכיתה MediaCodec
מאפשרת לאפליקציה לספק נתונים כבייט גולמיים במאגרים או דרך משטח. כש-screenrecord
מבקש גישה למקודד וידאו, התהליך mediaserver
יוצר BufferQueue, מתחבר לצד הצרכן ומעביר את הצד של היוצר בחזרה ל-screenrecord
כמשטח.
לאחר מכן, השירות screenrecord
מבקש מ-SurfaceFlinger ליצור מסך וירטואלי שמשקף את המסך הראשי (כלומר, יש לו את כל השכבות), ומורה לו לשלוח פלט למשטח שהגיע מהתהליך mediaserver
. במקרה כזה, SurfaceFlinger הוא היוצר של המאגרים ולא הצרכן שלהם.
אחרי השלמת ההגדרה, הקוד screenrecord
מופעל כשהנתונים המוצפנים מופיעים. כשאפליקציות מציירות, המאגרים שלהן עוברים אל SurfaceFlinger, שמרכיב אותם למאגר אחד שנשלח ישירות למקודד הווידאו בתהליך mediaserver
. התהליך screenrecord
אף פעם לא רואה את המסגרות המלאות. באופן פנימי, לתהליך mediaserver
יש דרך משלו להעביר מאגרים, שגם מעביר נתונים לפי הידית, וכך מצמצם את התקורה.
מקרה לדוגמה: הדמיה של תצוגות משניות
WindowManager יכול לבקש מ-SurfaceFlinger ליצור שכבה גלויה שבה SurfaceFlinger פועל כצרכן של BufferQueue. אפשר גם לבקש מ-SurfaceFlinger ליצור תצוגה וירטואלית, שבה SurfaceFlinger פועל בתור הבעלים של BufferQueue.
אם מחברים מסך וירטואלי לשכבה גלויה, נוצרת לולאה סגורה שבה המסך המשולב מופיע בחלון. החלון הזה הוא עכשיו חלק מהפלט המשולב, כך שברענון הבא התמונה המשולבת בתוך החלון תציג גם את תוכן החלון. כדי לראות איך זה עובד, מפעילים את האפשרויות למפתחים בהגדרות, בוחרים באפשרות סימולציה של מסכים משניים ומפעילים חלון. כדי לראות את המסכים המשניים בפעולה, משתמשים ב-screenrecord
כדי לתעד את הפעולה של הפעלת המסך ואז מפעילים אותו שוב, פריים אחרי פריים.