กราฟิก

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

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

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

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

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

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

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

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

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

องค์ประกอบหลักมีคำอธิบายอยู่ด้านล่าง

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

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

ผู้บริโภคสตรีมรูปภาพ

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

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

เครื่องมือสร้างฮาร์ดแวร์

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

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

Gralloc

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

โฟลว์ข้อมูล

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

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

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

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

BufferQueue

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

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

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

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

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

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

BufferQueue ทำงานได้ 3 โหมด ดังนี้

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

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

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

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

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