สิ่งที่นักพัฒนาแอปทุกคนควรรู้เกี่ยวกับ Surface, SurfaceHolder, EGLSurface, SurfaceView, GLSurfaceView, SurfaceTexture, TextureView, SurfaceFlinger และ Vulkan
หน้านี้อธิบายองค์ประกอบที่สำคัญของสถาปัตยกรรมกราฟิกที่ระดับระบบของ Android และวิธีที่เฟรมเวิร์กของแอปและระบบมัลติมีเดีย ใช้ โดยจะเน้นที่วิธีที่บัฟเฟอร์ของข้อมูลกราฟิกเคลื่อนที่ผ่านระบบ หากคุณเคยสงสัยว่าทำไม SurfaceView และ TextureView ถึงทำงานในลักษณะที่เป็นอยู่ หรือสงสัยว่า Surface และ EGLSurface ทำงานร่วมกันอย่างไร คุณมาถูกที่แล้ว
เราถือว่าคุณมีความคุ้นเคยกับอุปกรณ์ Android และการพัฒนาแอปอยู่บ้าง คุณไม่จำเป็นต้องมีความรู้โดยละเอียดเกี่ยวกับเฟรมเวิร์กของแอปและมีการกล่าวถึงการเรียก API เพียงเล็กน้อย แต่เนื้อหาจะไม่ซ้ำซ้อนกับเอกสารประกอบอื่นๆ ที่เป็นแบบสาธารณะ เป้าหมายคือการให้รายละเอียดเกี่ยวกับเหตุการณ์สำคัญ ที่เกี่ยวข้องกับการแสดงผลเฟรมสำหรับการเอาต์พุต เพื่อช่วยให้คุณเลือกได้อย่างชาญฉลาด เมื่อออกแบบแอป เอกสารนี้จึงอธิบายการทำงานของคลาส UI จากล่าง ขึ้นบนแทนที่จะอธิบายวิธีใช้
ส่วนนี้มีหลายหน้าซึ่งครอบคลุมทุกอย่างตั้งแต่ข้อมูลพื้นฐานไปจนถึงรายละเอียด HAL และกรณีการใช้งาน โดยเริ่มจากการอธิบายบัฟเฟอร์กราฟิกของ Android อธิบายกลไกการคอมโพสิตและการแสดงผล จากนั้นจึงไปยังกลไกระดับสูงกว่าที่ให้ข้อมูลแก่ Compositor เราขอแนะนำให้คุณอ่านหน้าต่างๆ ตามลำดับต่อไปนี้แทนการข้ามไปยังหัวข้อที่น่าสนใจ
คอมโพเนนต์ระดับล่าง
- BufferQueue และ gralloc BufferQueue เชื่อมต่อสิ่งที่สร้างบัฟเฟอร์ของข้อมูลกราฟิก (Producer) กับสิ่งที่ยอมรับข้อมูลเพื่อแสดงหรือประมวลผลเพิ่มเติม (Consumer) การจัดสรรบัฟเฟอร์จะดำเนินการ ผ่านตัวจัดสรรหน่วยความจำ gralloc ที่ใช้งานผ่าน อินเทอร์เฟซ HAL เฉพาะของผู้ให้บริการ
- SurfaceFlinger, Hardware Composer และจอแสดงผลเสมือน SurfaceFlinger ยอมรับบัฟเฟอร์ของ ข้อมูลจากหลายแหล่งที่มา คอมโพสิตบัฟเฟอร์ และส่งไปยังจอแสดงผล Hardware Composer HAL (HWC) จะกำหนดวิธีที่มีประสิทธิภาพมากที่สุดในการคอมโพสิต บัฟเฟอร์ด้วยฮาร์ดแวร์ที่มีอยู่ และจอแสดงผลเสมือนจะทำให้เอาต์พุตที่คอมโพสิต พร้อมใช้งานภายในระบบ (บันทึกหน้าจอหรือส่งหน้าจอผ่านเครือข่าย)
- Surface, Canvas และ SurfaceHolder Surface จะสร้างคิวบัฟเฟอร์ที่มักใช้โดย SurfaceFlinger เมื่อทำการเรนเดอร์บนพื้นผิว ผลลัพธ์จะอยู่ในบัฟเฟอร์ ที่จัดส่งไปยังผู้บริโภค Canvas API มีการติดตั้งใช้งานซอฟต์แวร์ (พร้อมการรองรับการเร่งด้วยฮาร์ดแวร์) สำหรับการวาดบนพื้นผิวโดยตรง (ทางเลือกแทน OpenGL ES ระดับต่ำ) ทุกอย่างที่เกี่ยวข้องกับมุมมองจะเกี่ยวข้องกับ SurfaceHolder ซึ่ง API ของ SurfaceHolder ช่วยให้สามารถรับและตั้งค่าพารามิเตอร์ของ Surface เช่น ขนาดและรูปแบบ
- EGLSurface และ OpenGL ES OpenGL ES (GLES) กำหนด API การแสดงผลกราฟิกที่ออกแบบมาเพื่อ ใช้ร่วมกับ EGL ซึ่งเป็นไลบรารีที่ สร้างและเข้าถึงหน้าต่างผ่าน ระบบปฏิบัติการได้ (หากต้องการวาดรูปหลายเหลี่ยมที่มีพื้นผิว ให้ใช้การเรียก GLES หากต้องการแสดงผลบนหน้าจอ ให้ใช้การเรียก EGL) หน้านี้ยังครอบคลุมถึง ANativeWindow ซึ่งเป็น เทียบเท่า C/C++ ของคลาส Surface ของ Java ที่ใช้สร้างพื้นผิวหน้าต่าง EGL จากโค้ดเนทีฟ
- Vulkan Vulkan เป็น API แบบข้ามแพลตฟอร์มที่มีค่าใช้จ่ายต่ำสำหรับกราฟิก 3 มิติที่มีประสิทธิภาพสูง Vulkan มีเครื่องมือสำหรับสร้างกราฟิกคุณภาพสูงแบบเรียลไทม์ในแอปเช่นเดียวกับ OpenGL ES ข้อดีของ Vulkan ได้แก่ การลดค่าใช้จ่ายของ CPU และการรองรับภาษา SPIR-V Binary Intermediate
คอมโพเนนต์ระดับสูง
- SurfaceView และ GLSurfaceView SurfaceView รวมพื้นผิวและมุมมองเข้าด้วยกัน SurfaceFlinger (ไม่ใช่แอป) จะคอมโพสิตคอมโพเนนต์มุมมองของ SurfaceView ซึ่งช่วยให้ การแสดงผลจากเธรด/กระบวนการแยกต่างหากและการแยกจากการแสดงผล UI ของแอป GLSurfaceView มีคลาสตัวช่วยในการจัดการบริบท EGL, การสื่อสารระหว่างเธรด และการโต้ตอบกับวงจรของกิจกรรม (แต่ไม่จำเป็นต้องใช้ GLES)
- SurfaceTexture SurfaceTexture จะรวม Surface และเท็กซ์เจอร์ GLES เพื่อสร้าง BufferQueue สำหรับ ซึ่งแอปของคุณเป็นผู้ใช้ เมื่อโปรดิวเซอร์จัดคิวบัฟเฟอร์ใหม่ ระบบจะแจ้งให้แอปของคุณทราบ ซึ่งจะปล่อยบัฟเฟอร์ที่ถือไว้ก่อนหน้านี้ รับบัฟเฟอร์ใหม่ จากคิว และทำการเรียก EGL เพื่อให้บัฟเฟอร์พร้อมใช้งานกับ GLES เป็นเท็กซ์เจอร์ภายนอก Android 7.0 เพิ่มการรองรับการเล่นวิดีโอพื้นผิวที่ปลอดภัย ซึ่งช่วยให้ GPU ประมวลผลเนื้อหาวิดีโอที่ได้รับการปกป้องภายหลังได้
- TextureView TextureView รวมมุมมองกับ SurfaceTexture TextureView จะห่อหุ้ม SurfaceTexture และรับผิดชอบในการตอบกลับการเรียกกลับและ รับบัฟเฟอร์ใหม่ เมื่อวาดภาพ TextureView จะใช้เนื้อหาของบัฟเฟอร์ที่ได้รับล่าสุดเป็นแหล่งข้อมูล โดยจะแสดงผลทุกที่และทุกเมื่อที่สถานะของ View ระบุว่าควรแสดง การจัดวางมุมมองจะดำเนินการด้วย GLES เสมอ ซึ่งหมายความว่าการอัปเดตเนื้อหาอาจทำให้องค์ประกอบมุมมองอื่นๆ วาดใหม่ด้วย