กราฟิก

ไอคอน HAL กราฟิกของ Android

เฟรมเวิร์กของ Android มี API การแสดงกราฟิกที่หลากหลายสำหรับ 2 มิติและ 3 มิติ ซึ่งโต้ตอบกับการใช้งานไดรเวอร์กราฟิกของผู้ผลิต ดังนั้นจึงควรทำความเข้าใจวิธีการทำงานของ API เหล่านั้นในระดับที่สูงขึ้น หน้านี้จะแนะนำ Hardware Abstraction Layer (HAL) ของกราฟิกซึ่งเป็นเลเยอร์ที่ไดรเวอร์เหล่านั้นสร้างขึ้น โปรดทำความคุ้นเคยกับคำศัพท์ต่อไปนี้ก่อนอ่านส่วนนี้ต่อ

canvas (คำทั่วไป), Canvas (องค์ประกอบ API)
Canvas คือพื้นผิวการวาดที่จัดการการรวมบิตจริงกับ บิตแมปหรือออบเจ็กต์ Surface คลาส Canvas มีเมธอดสำหรับการวาดบิตแมป เส้น วงกลม สี่เหลี่ยมผืนผ้า ข้อความ และอื่นๆ ในคอมพิวเตอร์มาตรฐาน และผูกกับบิตแมปหรือพื้นผิว Canvas เป็นวิธีที่ง่ายที่สุดในการวาดออบเจ็กต์ 2 มิติบนหน้าจอ คลาสพื้นฐานคือ Canvas
drawable
Drawable คือทรัพยากรภาพที่คอมไพล์แล้วซึ่งใช้เป็นพื้นหลัง ชื่อ หรือ ส่วนอื่นๆ ของหน้าจอได้ โดยปกติแล้ว ระบบจะโหลด Drawable ลงในองค์ประกอบ UI อื่น เช่น เป็นภาพพื้นหลัง Drawable ไม่สามารถรับเหตุการณ์ได้ แต่จะกำหนดพร็อพเพอร์ตี้อื่นๆ ที่หลากหลาย เช่น สถานะ และการกำหนดเวลา เพื่อเปิดใช้คลาสย่อย เช่น ออบเจ็กต์ภาพเคลื่อนไหวหรือไลบรารีรูปภาพ ระบบจะโหลดออบเจ็กต์ Drawable จำนวนมากจากไฟล์ทรัพยากร Drawable — ซึ่งเป็นไฟล์ XML หรือบิตแมปที่อธิบายรูปภาพ ระบบจะคอมไพล์ทรัพยากร Drawable เป็นคลาสย่อยของ android.graphics.drawable ดูข้อมูลเพิ่มเติมเกี่ยวกับ Drawable และทรัพยากรอื่นๆ ได้ที่ ภาพรวมทรัพยากรของแอป
ทรัพยากรเลย์เอาต์
ทรัพยากรเลย์เอาต์คือไฟล์ XML ที่อธิบายเลย์เอาต์ของหน้าจอของกิจกรรม ดูข้อมูลเพิ่มเติมได้ที่ ทรัพยากรเลย์เอาต์
Nine-Patch (9-Patch, NinePatch)
Nine-Patch คือทรัพยากรบิตแมปที่ปรับขนาดได้ซึ่งใช้สำหรับพื้นหลังหรือ รูปภาพอื่นๆ ในอุปกรณ์ได้ ดูข้อมูลเพิ่มเติมได้ที่ Nine-patch
OpenGL ES
OpenGL ES คือ API แบบข้ามแพลตฟอร์มสำหรับการแสดงกราฟิก 2 มิติและ 3 มิติ Android มีไลบรารี OpenGL ES สำหรับการแสดง 3 มิติที่เร่งด้วยฮาร์ดแวร์ สำหรับการแสดง 2 มิติ Canvas เป็นตัวเลือกที่ง่ายกว่า OpenGL ES พร้อมใช้งานใน Android Native Development Kit (NDK) แพ็กเกจ android.opengl และ javax.microedition.khronos.opengles จะแสดงฟังก์ชันการทำงานของ OpenGL ES
Surface (คำทั่วไป), Surface (องค์ประกอบ API)
Surface แสดงถึงบล็อกหน่วยความจำที่รวมเข้ากับ หน้าจอ Surface มี Canvas สำหรับการวาด และมีเมธอดตัวช่วยต่างๆ สำหรับการวาดเลเยอร์ และปรับขนาดออบเจ็กต์ Surface ให้ใช้คลาส SurfaceView แทนคลาส Surface โดยตรง
Surface View (คำทั่วไป), SurfaceView (องค์ประกอบ API)
Surface View คือออบเจ็กต์ View ที่ห่อหุ้มออบเจ็กต์ Surface สำหรับการวาด และแสดงเมธอดเพื่อระบุขนาดและรูปแบบ แบบไดนามิก Surface View เป็นวิธีในการวาดแยกจากเทรด UI สำหรับการดำเนินการที่ใช้ทรัพยากรมาก เช่น เกมหรือการแสดงตัวอย่างกล้อง แต่จะใช้หน่วยความจำเพิ่มเติม Surface View รองรับทั้งกราฟิก Canvas และ OpenGL ES คลาสพื้นฐานสำหรับออบเจ็กต์ SurfaceView คือ SurfaceView
ธีม
ธีมคือชุดพร็อพเพอร์ตี้ เช่น ขนาดข้อความและสีพื้นหลัง ซึ่งรวมเข้าด้วยกัน เพื่อกำหนดการตั้งค่าการแสดงผลเริ่มต้นต่างๆ Android มีธีมมาตรฐาน 2-3 ธีม ซึ่งแสดงอยู่ในR.style และขึ้นต้นด้วย Theme_
View (คำทั่วไป), View (องค์ประกอบ API)
View จะวาดพื้นที่สี่เหลี่ยมผืนผ้าบนหน้าจอและจัดการ เหตุการณ์การคลิก การกดแป้น และเหตุการณ์การโต้ตอบอื่นๆ คลาส View เป็นคลาสพื้นฐาน สำหรับคอมโพเนนต์เลย์เอาต์ส่วนใหญ่ของหน้าจอกิจกรรมหรือกล่องโต้ตอบ เช่น กล่องข้อความ และหน้าต่าง ออบเจ็กต์ View จะรับการเรียกจากออบเจ็กต์ระดับบน (ดู ViewGroup) เพื่อวาดตัวเอง และแจ้งออบเจ็กต์ระดับบน เกี่ยวกับขนาดและตำแหน่งที่ต้องการ ซึ่งออบเจ็กต์ระดับบนอาจไม่สนใจ ดูข้อมูลเพิ่มเติมได้ที่ View
กลุ่มการแสดงผล (คำทั่วไป), ViewGroup (องค์ประกอบ API)
กลุ่มการแสดงผลจะจัดกลุ่มชุด View ย่อย กลุ่มการแสดงผลมีหน้าที่ตัดสินใจว่าจะวาง View ย่อยไว้ที่ใดและมีขนาดเท่าใด รวมถึงเรียกแต่ละ View ย่อยให้วาดตัวเองเมื่อเหมาะสม View Group บางรายการมองไม่เห็นและมีไว้สำหรับเลย์เอาต์เท่านั้น ขณะที่รายการอื่นๆ มี UI ในตัว เช่น กล่องรายการแบบเลื่อน View groups are in the android.widget package, but extend the ViewGroup class.
ลำดับชั้นการแสดงผล
ลำดับชั้นการแสดงผลคือการจัดเรียงออบเจ็กต์ View และกลุ่มการแสดงผลที่กำหนดอินเทอร์เฟซผู้ใช้สำหรับคอมโพเนนต์แต่ละรายการของแอป โดยลำดับชั้นประกอบด้วยกลุ่มการแสดงผลที่มี View หรือกลุ่มการแสดงผลย่อยอย่างน้อย 1 รายการ คุณสามารถรับการแสดงภาพลำดับชั้นการแสดงผลสำหรับการแก้ไขข้อบกพร่อง และการเพิ่มประสิทธิภาพได้โดยใช้ Hierarchy Viewer ที่มาพร้อมกับ Android SDK
Vulkan
Vulkan คือ API แบบข้ามแพลตฟอร์มที่มีค่าใช้จ่ายต่ำ สำหรับกราฟิก 3 มิติประสิทธิภาพสูง
วิดเจ็ต
วิดเจ็ตคือคลาสย่อยของ View ที่มีการใช้งานอย่างสมบูรณ์แล้ว ซึ่งแสดงองค์ประกอบแบบฟอร์ม องค์ประกอบและคอมโพเนนต์ UI อื่นๆ เช่น กล่องข้อความหรือเมนูป๊อปอัป เนื่องจากวิดเจ็ตมีการใช้งานอย่างสมบูรณ์แล้ว จึงจัดการการวัด การวาด ตัวเอง และการตอบสนองต่อเหตุการณ์บนหน้าจอ วิดเจ็ตอยู่ใน android.widget แพ็กเกจ
Window (คำทั่วไป), Window (องค์ประกอบ API)
ในแอป Android Window คือออบเจ็กต์ที่ได้มาจาก Window คลาส Abstract ซึ่งระบุองค์ประกอบของ Window ทั่วไป เช่น ลักษณะที่ปรากฏ ข้อความในแถบชื่อ รวมถึงตำแหน่งและเนื้อหาของ เมนู กล่องโต้ตอบและกิจกรรมใช้การใช้งานของ Window คลาสเพื่อแสดงออบเจ็กต์ Window คุณไม่จำเป็นต้องใช้คลาส Window หรือใช้ Window ในแอป

นักพัฒนาแอปวาดรูปภาพลงบนหน้าจอได้ 3 วิธี ได้แก่ Canvas, OpenGL ES หรือ Vulkan

คอมโพเนนต์กราฟิกของ Android

ไม่ว่านักพัฒนาซอฟต์แวร์จะใช้ API การแสดงผลใด ระบบจะแสดงทุกอย่างลงบน Surface Surface แสดงถึงฝั่งผู้ผลิตของคิวบัฟเฟอร์ ซึ่งมักจะใช้โดย SurfaceFlinger Window ทุกรายการที่สร้างขึ้นในแพลตฟอร์ม Android ได้รับการสนับสนุนจาก Surface SurfaceFlinger จะรวม Surface ที่แสดงทั้งหมดลงบนจอแสดงผล

แผนภาพต่อไปนี้แสดงวิธีที่คอมโพเนนต์หลักทำงานร่วมกัน

คอมโพเนนต์การแสดงรูปภาพ

รูปที่ 1 วิธีแสดง Surface

คอมโพเนนต์หลักมีคำอธิบายอยู่ในส่วนต่อไปนี้

ผู้ผลิตสตรีมรูปภาพ

ผู้ผลิตสตรีมรูปภาพอาจเป็นอะไรก็ได้ที่สร้างบัฟเฟอร์กราฟิกสำหรับการใช้งาน ตัวอย่าง ได้แก่ OpenGL ES, Canvas 2D และตัวถอดรหัสวิดีโอ mediaserver

ผู้ใช้สตรีมรูปภาพ

ผู้ใช้สตรีมรูปภาพที่พบบ่อยที่สุดคือ SurfaceFlinger ซึ่งเป็นบริการของระบบที่ใช้ Surface ที่มองเห็นได้ในปัจจุบันและรวม Surface เหล่านั้นลงบนจอแสดงผลโดยใช้ข้อมูลที่ Window Manager ให้ไว้ SurfaceFlinger เป็นบริการเดียวที่แก้ไขเนื้อหาของจอแสดงผลได้ SurfaceFlinger ใช้ OpenGL และ Hardware Composer (HWC) เพื่อรวมกลุ่ม Surface

แอป OpenGL ES อื่นๆ ก็ใช้สตรีมรูปภาพได้เช่นกัน เช่น แอปกล้องใช้สตรีมรูปภาพการแสดงตัวอย่างกล้อง แอปที่ไม่ใช่ GL ก็เป็นผู้ใช้ได้เช่นกัน เช่น คลาส ImageReader

Hardware Composer

Hardware Abstraction สำหรับระบบย่อยของจอแสดงผล SurfaceFlinger สามารถมอบหมายงานการรวมบางอย่างให้กับ HWC เพื่อลดภาระงานจาก OpenGL และ GPU SurfaceFlinger ทำหน้าที่เป็นเพียงไคลเอ็นต์ OpenGL ES อีกรายหนึ่ง ดังนั้น เมื่อ SurfaceFlinger รวมบัฟเฟอร์ 1 หรือ 2 รายการลงในบัฟเฟอร์ที่ 3 อย่างแข็งขัน เช่น SurfaceFlinger จะใช้ OpenGL ES ซึ่งทำให้การรวมใช้พลังงานน้อยกว่าการให้ GPU ทำการคำนวณทั้งหมด

Hardware Composer HAL จะทำงานอีกครึ่งหนึ่งและเป็นจุดศูนย์กลาง สำหรับการแสดงกราฟิกทั้งหมดของ Android HWC ต้องรองรับเหตุการณ์ ซึ่งเหตุการณ์หนึ่งคือ VSync (อีกเหตุการณ์หนึ่งคือ Hotplug สำหรับการรองรับ HDMI แบบ Plug and Play)

Gralloc

ตัวจัดสรรหน่วยความจำกราฟิก (Gralloc) จำเป็นสำหรับการจัดสรรหน่วยความจำที่ผู้ผลิตรูปภาพขอ ดูรายละเอียดได้ที่ BufferQueue และ Gralloc

โฟลว์ข้อมูล

แผนภาพต่อไปนี้แสดงไปป์ไลน์กราฟิกของ Android

โฟลว์ข้อมูลกราฟิก

รูปที่ 2 โฟลว์ข้อมูลกราฟิกผ่าน Android

ออบเจ็กต์ทางด้านซ้ายคือตัวแสดงผลที่สร้างบัฟเฟอร์กราฟิก เช่น หน้าจอหลัก แถบสถานะ และ UI ของระบบ SurfaceFlinger คือตัวรวม และ HWC คือตัวรวม

BufferQueue

BufferQueue เป็นตัวเชื่อมระหว่างคอมโพเนนต์กราฟิกของ Android ซึ่งเป็นคิว 2 คิวที่ทำหน้าที่เป็นตัวกลางในการวนรอบบัฟเฟอร์อย่างต่อเนื่องจากผู้ผลิตไปยังผู้ใช้ หลังจากที่ผู้ผลิตส่งบัฟเฟอร์แล้ว SurfaceFlinger จะมีหน้าที่รวมทุกอย่างลงบนจอแสดงผล

แผนภาพต่อไปนี้แสดงกระบวนการสื่อสารของ BufferQueue

กระบวนการสื่อสาร BufferQueue

รูปที่ 3 กระบวนการสื่อสารของ BufferQueue

BufferQueue มีตรรกะที่เชื่อมโยงผู้ผลิตสตรีมรูปภาพและผู้ใช้สตรีมรูปภาพเข้าด้วยกัน ตัวอย่างผู้ผลิตรูปภาพ ได้แก่ การแสดงตัวอย่างกล้องที่สร้างโดยกล้อง HAL หรือเกม OpenGL ES ตัวอย่างผู้ใช้รูปภาพ ได้แก่ SurfaceFlinger หรือแอปอื่นที่แสดงสตรีม OpenGL ES เช่น แอปกล้องที่แสดงช่องมองภาพของกล้อง

BufferQueue คือโครงสร้างข้อมูลที่รวมพูลบัฟเฟอร์เข้ากับคิว และใช้การสื่อสารระหว่างกระบวนการ (IPC) ของ Binder เพื่อส่งบัฟเฟอร์ระหว่างกระบวนการต่างๆ อินเทอร์เฟซผู้ผลิต หรือ สิ่งที่คุณส่งให้ผู้ที่ต้องการสร้างบัฟเฟอร์กราฟิกคือ IGraphicBufferProducer (ส่วนหนึ่งของ SurfaceTexture) โดยมักจะใช้ BufferQueue เพื่อแสดงผลไปยัง Surface และใช้กับ GL Consumer รวมถึงงานอื่นๆ

BufferQueue สามารถทำงานได้ 3 โหมด ได้แก่

โหมดคล้ายซิงโครนัส
โดยค่าเริ่มต้น BufferQueue จะทำงานในโหมดคล้ายซิงโครนัส ซึ่งบัฟเฟอร์ทุกรายการที่มาจากผู้ผลิตจะออกไปที่ผู้ใช้ ระบบจะไม่ทิ้งบัฟเฟอร์ในโหมดนี้ และหากผู้ผลิตเร็วเกินไปและสร้างบัฟเฟอร์เร็วกว่าที่ระบบจะระบายออก ผู้ผลิตจะบล็อกและรอให้บัฟเฟอร์ว่าง
โหมดไม่บล็อก
BufferQueue ยังทำงานในโหมดไม่บล็อกได้ด้วย ซึ่งจะสร้างข้อผิดพลาดแทนที่จะรอบัฟเฟอร์ในกรณีดังกล่าว ระบบจะไม่ทิ้งบัฟเฟอร์ในโหมดนี้เช่นกัน โหมดนี้มีประโยชน์สำหรับการหลีกเลี่ยงการล็อกตายที่อาจเกิดขึ้นในซอฟต์แวร์แอปพลิเคชันที่อาจไม่เข้าใจการพึ่งพาที่ซับซ้อนของเฟรมเวิร์กกราฟิก
โหมดทิ้ง
คุณกำหนดค่า BufferQueue ให้ทิ้งบัฟเฟอร์เก่าแทนที่จะสร้างข้อผิดพลาดหรือรอได้ เช่น หากทำการแสดงผล GL ไปยัง Texture View และวาดให้เร็วที่สุดเท่าที่จะทำได้ ระบบจะต้องทิ้งบัฟเฟอร์

SurfaceFlinger ทำหน้าที่เป็นเพียงไคลเอ็นต์ OpenGL ES อีกรายหนึ่งเพื่อทำงานส่วนใหญ่ ดังนั้น เมื่อ SurfaceFlinger รวมบัฟเฟอร์ 1 หรือ 2 รายการลงในบัฟเฟอร์ที่ 3 อย่างแข็งขัน เช่น SurfaceFlinger จะใช้ OpenGL ES

Hardware Composer HAL จะทำงานอีกครึ่งหนึ่ง HAL นี้ทำหน้าที่เป็นจุดศูนย์กลางสำหรับการแสดงกราฟิกทั้งหมดของ Android