SurfaceFlinger จะยอมรับบัฟเฟอร์ คอมโพสิทบัฟเฟอร์ และส่งบัฟเฟอร์ไปยังจอแสดงผล WindowManager
มอบบัฟเฟอร์และข้อมูลเมตาของหน้าต่างให้กับ SurfaceFlinger ซึ่ง SurfaceFlinger จะใช้เพื่อคอมโพสิทพื้นผิวไปยังจอแสดงผล
SurfaceFlinger
SurfaceFlinger ยอมรับบัฟเฟอร์ได้ 2 วิธี ได้แก่ ผ่าน BufferQueue และ SurfaceControl
หรือผ่าน ASurfaceControl
วิธีที่ SurfaceFlinger ยอมรับบัฟเฟอร์คือผ่าน BufferQueue และ SurfaceControl
เมื่อแอปปรากฏขึ้นที่เบื้องหน้า แอปจะขอบัฟเฟอร์จาก WindowManager
WindowManager
จากนั้นจะขอเลเยอร์จาก SurfaceFlinger เลเยอร์คือชุดค่าผสมของ surface ซึ่งมี BufferQueue และอินสแตนซ์ SurfaceControl
ซึ่งมีข้อมูลเมตาของเลเยอร์ เช่น เฟรมการแสดงผล
SurfaceFlinger จะสร้างเลเยอร์และส่งไปยัง WindowManager
WindowManager
จากนั้นส่ง Surface ไปยังแอป แต่เก็บอินสแตนซ์ SurfaceControl
ไว้เพื่อควบคุมลักษณะที่ปรากฏของแอปบนหน้าจอ
Android 10 เพิ่ม ASurfaceControl
ซึ่งเป็นอีกวิธีหนึ่งที่ SurfaceFlinger ยอมรับบัฟเฟอร์ ASurfaceControl
รวมอินสแตนซ์ SurfaceControl
และอินสแตนซ์ Surface เข้าเป็นแพ็กเกจธุรกรรมเดียวที่ส่งไปยัง SurfaceFlinger ASurfaceControl
เชื่อมโยงกับเลเยอร์ที่แอปอัปเดตผ่านอินสแตนซ์ ASurfaceTransaction
จากนั้นแอปจะได้รับข้อมูลเกี่ยวกับASurfaceTransaction
อินสแตนซ์ผ่านคอลแบ็กที่ส่ง ASurfaceTransactionStats
ที่มีข้อมูล เช่น เวลาแตะ เวลารับ และอื่นๆ
ตารางต่อไปนี้มีรายละเอียดเพิ่มเติมเกี่ยวกับ ASurfaceControl
และคอมโพเนนต์ที่เกี่ยวข้อง
ส่วนประกอบ | คำอธิบาย |
---|---|
ASurfaceControl |
ตัด SurfaceControl และช่วยให้แอปสร้างอินสแตนซ์ SurfaceControl ที่สอดคล้องกับเลเยอร์บนจอแสดงผลได้สร้างเป็นอินสแตนซ์ย่อยของ ANativeWindow หรือเป็นอินสแตนซ์ย่อยของอินสแตนซ์ ASurfaceControl อื่นได้ |
ASurfaceTransaction |
ตัด Transaction เพื่อช่วยให้ไคลเอ็นต์แก้ไขพร็อพเพอร์ตี้ที่อธิบายของเลเยอร์ได้ เช่น เรขาคณิต และส่งบัฟเฟอร์ที่อัปเดตแล้วไปยัง SurfaceFlinger |
ASurfaceTransactionStats
| ส่งข้อมูลเกี่ยวกับธุรกรรมที่แสดง เช่น เวลาแตะ เวลารับ และรั้วการปล่อยก่อนหน้า ไปยังแอปผ่านการเรียกกลับที่ลงทะเบียนไว้ล่วงหน้า |
แม้ว่าแอปจะส่งบัฟเฟอร์ได้ทุกเมื่อ แต่ SurfaceFlinger จะตื่นขึ้นมาเพื่อรับบัฟเฟอร์ระหว่างการรีเฟรชจอแสดงผลเท่านั้น ซึ่งอาจแตกต่างกันไปตามอุปกรณ์ วิธีนี้ช่วยลดการใช้หน่วยความจำและหลีกเลี่ยงการฉีกขาดที่มองเห็นได้บนหน้าจอ ซึ่งอาจเกิดขึ้นเมื่ออัปเดตการแสดงผลระหว่างการรีเฟรช
เมื่อจอแสดงผลอยู่ระหว่างการรีเฟรช จอแสดงผลจะส่งสัญญาณ VSync ไปยัง SurfaceFlinger สัญญาณ VSync บ่งบอกว่าจอแสดงผลจะรีเฟรชได้โดยไม่ฉีกขาด เมื่อ SurfaceFlinger ได้รับสัญญาณ VSync ก็จะเรียกดูรายการเลเยอร์เพื่อหาบัฟเฟอร์ใหม่ หาก SurfaceFlinger พบบัฟเฟอร์ใหม่ ก็จะรับบัฟเฟอร์นั้น หากไม่พบ ก็จะใช้บัฟเฟอร์ที่รับไว้ก่อนหน้านี้ต่อไป SurfaceFlinger ต้องแสดงข้อมูลบางอย่างเสมอ จึงจะยึดบัฟเฟอร์ไว้ 1 รายการ หากไม่เคยส่งบัฟเฟอร์ในเลเยอร์ ระบบจะไม่สนใจเลเยอร์นั้น
หลังจาก SurfaceFlinger รวบรวมบัฟเฟอร์ทั้งหมดสําหรับเลเยอร์ที่มองเห็นแล้ว ก็จะถามเครื่องมือคอมโพสิตฮาร์ดแวร์ (HWC) ว่าควรใช้การคอมโพสอย่างไร หาก HWC ระบุว่าประเภทการคอมโพสิชันเลเยอร์เป็นการคอมโพสิชันไคลเอ็นต์ SurfaceFlinger จะคอมโพสิชันเลเยอร์เหล่านั้น จากนั้น SurfaceFlinger จะส่งบัฟเฟอร์เอาต์พุตไปยัง HWC
WindowManager
WindowManager
ควบคุมออบเจ็กต์ Window
ซึ่งเป็นคอนเทนเนอร์สำหรับออบเจ็กต์ View
ออบเจ็กต์ Window
จะสำรองข้อมูลโดยออบเจ็กต์ Surface
เสมอ
WindowManager
ดูแลวงจร อินพุต และโฟกัส เหตุการณ์ การวางแนวหน้าจอ ทรานซิชัน ภาพเคลื่อนไหว ตำแหน่ง การเปลี่ยนรูปแบบ ลําดับ z และอีกหลายแง่มุมของหน้าต่าง WindowManager
จะส่งข้อมูลเมตาของหน้าต่างทั้งหมดไปยัง SurfaceFlinger เพื่อให้ SurfaceFlinger ใช้ข้อมูลดังกล่าวในการคอมโพสิทพื้นผิวบนจอแสดงผลได้
ก่อนการหมุนเวียน
การวางซ้อนฮาร์ดแวร์จำนวนมากไม่รองรับการหมุน (และแม้ว่าจะรองรับ ก็ยังต้องใช้พลังงานในการประมวลผล) ทางออกคือการเปลี่ยนรูปแบบบัฟเฟอร์ก่อนที่จะไปถึง SurfaceFlinger Android รองรับคำแนะนำการค้นหา (NATIVE_WINDOW_TRANSFORM_HINT
) ใน ANativeWindow
เพื่อแสดงการเปลี่ยนรูปแบบที่มีแนวโน้มมากที่สุดที่จะใช้กับบัฟเฟอร์โดย SurfaceFlinger ไดรเวอร์ GL สามารถใช้คำแนะนำนี้เพื่อเปลี่ยนรูปแบบบัฟเฟอร์ล่วงหน้าก่อนที่จะส่งไปยัง SurfaceFlinger เพื่อให้บัฟเฟอร์ได้รับการเปลี่ยนรูปแบบอย่างถูกต้องเมื่อมาถึง
เช่น เมื่อได้รับคำแนะนำให้หมุน 90 องศา ให้สร้างและใช้เมทริกซ์กับบัฟเฟอร์เพื่อป้องกันไม่ให้แสดงที่ส่วนท้ายของหน้า โปรดดำเนินการนี้ก่อนการโรเตชันเพื่อประหยัดพลังงาน โปรดดูรายละเอียดที่อินเทอร์เฟซ ANativeWindow
ที่กําหนดไว้ใน system/core/include/system/window.h