กราฟิก

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

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

Canvas (คำทั่วไป), Canvas (องค์ประกอบ API)
Canvas คือพื้นผิวการวาดภาพที่จัดการการคอมโพสิตบิตจริงกับบิตแมปหรือออบเจ็กต์ Surface Canvas คลาสมี เมธอดสำหรับการวาดภาพบิตแมป เส้น วงกลม สี่เหลี่ยมผืนผ้า ข้อความ และอื่นๆ บนคอมพิวเตอร์มาตรฐาน และ เชื่อมโยงกับบิตแมปหรือพื้นผิว Canvas เป็นวิธีที่ง่ายที่สุดในการวาดออบเจ็กต์ 2 มิติ บนหน้าจอ คลาสพื้นฐานคือ Canvas
ถอนออกได้
Drawable คือทรัพยากรภาพที่คอมไพล์แล้วซึ่งใช้เป็นพื้นหลัง ชื่อ หรือ ส่วนอื่นๆ ของหน้าจอได้ โดยปกติแล้ว ระบบจะโหลด Drawable ลงในองค์ประกอบ UI อื่น เช่น เป็นภาพพื้นหลัง Drawable รับเหตุการณ์ไม่ได้ แต่กำหนดพร็อพเพอร์ตี้อื่นๆ เช่น สถานะ และการจัดกำหนดการ เพื่อเปิดใช้คลาสย่อย เช่น ออบเจ็กต์ภาพเคลื่อนไหวหรือไลบรารีรูปภาพ ระบบจะโหลดออบเจ็กต์ที่วาดได้จำนวนมากจากไฟล์ทรัพยากรที่วาดได้ ซึ่งเป็นไฟล์ XML หรือบิตแมปที่อธิบายรูปภาพ ระบบจะคอมไพล์ทรัพยากร Drawable เป็นคลาสย่อยของ android.graphics.drawable ดูข้อมูลเพิ่มเติมเกี่ยวกับ Drawable และทรัพยากรอื่นๆ ได้ที่ ภาพรวมของทรัพยากรแอป
ทรัพยากรเลย์เอาต์
ทรัพยากรเลย์เอาต์คือไฟล์ XML ที่อธิบายเลย์เอาต์ของหน้าจอกิจกรรม ดูข้อมูลเพิ่มเติมได้ที่ แหล่งข้อมูลเลย์เอาต์
9 แพตช์ (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 (องค์ประกอบ API)
Surface คือบล็อกหน่วยความจำที่ได้รับการคอมโพสิตไปยัง หน้าจอ Surface มี Canvas สำหรับวาดภาพ และมีเมธอดตัวช่วยต่างๆ สำหรับวาดเลเยอร์ และปรับขนาดออบเจ็กต์ Surface ใช้คลาส SurfaceView แทนคลาส Surface โดยตรง
มุมมองพื้นผิว (คำทั่วไป), SurfaceView (องค์ประกอบ API)
SurfaceView คือออบเจ็กต์ View ที่ห่อหุ้มออบเจ็กต์ Surface สำหรับการวาด และแสดงเมธอดเพื่อระบุขนาดและรูปแบบของออบเจ็กต์ แบบไดนามิก SurfaceView เป็นวิธีวาดภาพโดยไม่ขึ้นกับเทรด UI สำหรับการดำเนินการที่ใช้ทรัพยากรมาก เช่น เกมหรือตัวอย่างกล้อง แต่จะใช้หน่วยความจำเพิ่มเติม ด้วย SurfaceView รองรับทั้ง Canvas และกราฟิก OpenGL ES คลาสพื้นฐานสำหรับออบเจ็กต์ SurfaceView คือ SurfaceView
ธีม [theme]
ธีมคือชุดคุณสมบัติ เช่น ขนาดข้อความและสีพื้นหลัง ที่รวมกัน เพื่อกำหนดการตั้งค่าการแสดงผลเริ่มต้นต่างๆ Android มีธีมมาตรฐาน 2-3 ธีมที่แสดงอยู่ใน R.style และขึ้นต้นด้วย Theme_
ดู (คำทั่วไป), View (องค์ประกอบ API)
View จะวาดพื้นที่สี่เหลี่ยมผืนผ้าบนหน้าจอและจัดการ เหตุการณ์การคลิก การกดแป้น และการโต้ตอบอื่นๆ คลาส View เป็นคลาสฐาน สำหรับคอมโพเนนต์เลย์เอาต์ส่วนใหญ่ของหน้าจอกิจกรรมหรือกล่องโต้ตอบ เช่น กล่องข้อความ และหน้าต่าง ออบเจ็กต์ View จะรับการเรียกจากออบเจ็กต์หลัก (ดู ViewGroup) เพื่อวาดตัวเอง และแจ้งออบเจ็กต์หลัก เกี่ยวกับขนาดที่ต้องการและตำแหน่ง ซึ่งออบเจ็กต์หลักอาจไม่สนใจ ดูข้อมูลเพิ่มเติมได้ที่ View
กลุ่มมุมมอง (คำทั่วไป), ViewGroup (องค์ประกอบ API)
กลุ่มมุมมองจะจัดกลุ่มชุดมุมมองย่อย กลุ่มมุมมองมีหน้าที่ตัดสินใจว่าจะวางตำแหน่งมุมมองย่อยไว้ที่ใดและมีขนาดเท่าใด รวมถึงเรียกแต่ละมุมมองให้วาดตัวเองเมื่อเหมาะสม กลุ่มมุมมองบางกลุ่มจะมองไม่เห็นและใช้สำหรับการจัดเลย์เอาต์เท่านั้น ขณะที่กลุ่มอื่นๆ มี UI โดยธรรมชาติ เช่น กล่องรายการแบบเลื่อน View Groups อยู่ใน แพ็กเกจ android.widget แต่ขยายคลาส ViewGroup
ดูลำดับชั้น
ลำดับชั้นการแสดงผลคือการจัดเรียงออบเจ็กต์การแสดงผลและกลุ่มการแสดงผลที่กำหนดอินเทอร์เฟซผู้ใช้สำหรับแต่ละคอมโพเนนต์ของแอป ลำดับชั้นประกอบด้วยกลุ่มการแสดงผลที่มีการแสดงผลย่อยหรือกลุ่มการแสดงผลอย่างน้อย 1 รายการ คุณสามารถดูภาพแทนลำดับชั้นของ View เพื่อการแก้ไขข้อบกพร่อง และการเพิ่มประสิทธิภาพได้โดยใช้ Hierarchy Viewer ที่มาพร้อมกับ Android SDK
Vulkan
Vulkan เป็น API แบบข้ามแพลตฟอร์มที่มีค่าใช้จ่ายต่ำ สำหรับกราฟิก 3 มิติที่มีประสิทธิภาพสูง
วิดเจ็ต
วิดเจ็ตคือคลาสย่อยของมุมมองที่ใช้งานได้อย่างสมบูรณ์ชุดหนึ่งซึ่งแสดงผลองค์ประกอบของแบบฟอร์ม และคอมโพเนนต์ UI อื่นๆ เช่น กล่องข้อความหรือเมนูป๊อปอัป เนื่องจากวิดเจ็ตได้รับการติดตั้งใช้งานอย่างเต็มรูปแบบ จึงจัดการการวัดผล การวาด ตัววิดเจ็ตเอง และการตอบสนองต่อเหตุการณ์บนหน้าจอ วิดเจ็ตอยู่ในแพ็กเกจ android.widget
หน้าต่าง (คำทั่วไป), Window (องค์ประกอบ API)
ในแอป Android หน้าต่างคือออบเจ็กต์ที่ได้มาจากคลาส Window abstract ซึ่งระบุองค์ประกอบของหน้าต่างทั่วไป เช่น ลักษณะที่ปรากฏ ข้อความในแถบชื่อ ตำแหน่งและเนื้อหาของเมนู กล่องโต้ตอบและกิจกรรมใช้การติดตั้งใช้งานคลาส Window เพื่อแสดงออบเจ็กต์ Window คุณไม่จำเป็นต้องใช้คลาส Window หรือใช้หน้าต่างในแอป

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

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

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

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

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

รูปที่ 1 วิธีแสดงผลแพลตฟอร์ม

องค์ประกอบหลักจะอธิบายไว้ในส่วนต่อไปนี้

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

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

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

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

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

ฮาร์ดแวร์คอมโพสเซอร์

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

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

Gralloc

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

โฟลว์ข้อมูล

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

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

รูปที่ 2 การไหลของข้อมูลกราฟิกผ่าน Android

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

BufferQueue

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

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

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

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

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

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

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

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

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

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