אובייקטים של Surface מאפשרים לאפליקציות ליצור תמונות להצגה במסכים. ממשקי SurfaceHolder מאפשרים לאפליקציות לערוך משטחים ולשלוט בהם.
Surface
משטח הוא ממשק שמאפשר למפיק להחליף מאגרים עם צרכן.
בדרך כלל, BufferQueue של משטח תצוגה מוגדר ל-triple-buffering. המאגרים מוקצים על פי דרישה, כך שאם היוצר יוצר מאגרים באיטיות מספקת, למשל בקצב של 30 פריימים לשנייה במסך של 60 פריימים לשנייה, יכול להיות שיהיו רק שני מאגרים שמוקצים בתור.
הקצאת מאגרים לפי דרישה עוזרת למזער את צריכת הזיכרון. אפשר לראות סיכום של מאגרי הנתונים שמשויכים לכל שכבה בפלט dumpsys SurfaceFlinger
.
רוב הלקוחות מבצעים רינדור על משטחים באמצעות OpenGL ES או Vulkan. עם זאת, חלק מהלקוחות מבצעים רינדור על משטחים באמצעות קנבס.
רינדור של קנבס
ההטמעה של הקנבס מסופקת על ידי Skia Graphics Library. אם רוצים לצייר מלבן, צריך לקרוא ל-Canvas API, שמגדיר בייטים במאגר בצורה מתאימה. כדי לוודא ששני לקוחות לא מעדכנים מאגר בו-זמנית, או שכותבים אליו בזמן שהוא מוצג, צריך לנעול את המאגר כדי לגשת אליו. משתמשים בפקודות הבאות כדי לעבוד עם מנעולים של קנבס:
lockCanvas()
נועל את המאגר לעיבוד ב-CPU ומחזיר משטח לציור.unlockCanvasAndPost()
פותח את המאגר ושולח אותו למעבד הקומפוזיציה.lockHardwareCanvas()
נועל את המאגר לעיבוד ב-GPU ומחזיר קנבס לשימוש בציור.
בפעם הראשונה שהמפיק מבקש מאגר מ-BufferQueue, המאגר מוקצה ומאופס. האיניציאליזציה נחוצה כדי למנוע שיתוף לא מכוון של נתונים בין תהליכים. עם זאת, אם משתמשים מחדש במאגר, התוכן הקודם עדיין נמצא בו. אם קוראים שוב ושוב ל-lockCanvas()
ול-unlockCanvasAndPost()
בלי לצייר שום דבר, ה-producer עובר בין הפריימים שעברתם עיבוד.
קוד הנעילה/הנעילה של פני השטח שומר על הפניה למאגר שעבר רינדור. אם מציינים אזור 'לא נקי' בזמן נעילת הפלטפורמה, המערכת מעתיקה את הפיקסלים 'נקיים' מהמאגר הקודם. בדרך כלל, SurfaceFlinger או HWC מטפלים במאגר, אבל מכיוון שאנחנו צריכים רק לקרוא מהמאגר, אין צורך להמתין לגישה בלעדית.
SurfaceHolder
SurfaceHolder הוא ממשק שבו המערכת משתמשת כדי לשתף בעלות על משטחים עם אפליקציות. לקוחות מסוימים שעובדים עם משטחים צריכים SurfaceHolder, כי ממשקי ה-API לקבלה ולהגדרה של פרמטרים של משטחים מיושמים באמצעות SurfaceHolder. רכיב SurfaceView מכיל SurfaceHolder.
רוב הרכיבים שמקיימים אינטראקציה עם תצוגה כוללים SurfaceHolder. ממשקי API אחרים, כמו MediaCodec, פועלים על פני השטח עצמו.