HAL ของเครื่องมือจัดองค์ประกอบฮาร์ดแวร์ (HWC) จะคอมโพสเลเยอร์ที่ได้รับจาก SurfaceFlinger ซึ่งจะลดจำนวนองค์ประกอบ OpenGL ES (GLES) และ GPU ทำงาน
HWC จะแยกแยะออบเจ็กต์ เช่น การวางซ้อนและโปรแกรมแสดงผลภาพ 2 มิติ เพื่อคอมโพสพื้นผิวและสื่อสารกับฮาร์ดแวร์การจัดองค์ประกอบหน้าต่างเฉพาะเพื่อคอมโพสหน้าต่าง ใช้ HWC เพื่อคอมโพสหน้าต่างแทนการคอมโพส SurfaceFlinger กับ GPU GPU ส่วนใหญ่ไม่ได้เพิ่มประสิทธิภาพเพื่อ และเมื่อ GPU เขียนเลเยอร์จาก แพลตฟอร์ม SurfaceFlinger แอปจะใช้ GPU เพื่อแสดงผลของตนเองไม่ได้
การติดตั้งใช้งาน HWC ควรรองรับสิ่งต่อไปนี้
- การวางซ้อนอย่างน้อย 4 รายการ:
- แถบสถานะ
- แถบระบบ
- แอป
- วอลเปเปอร์/พื้นหลัง
- เลเยอร์ที่ใหญ่กว่าจอแสดงผล (เช่น วอลเปเปอร์)
- การผสมอัลฟ่าแบบคูณล่วงหน้าต่อพิกเซลและการผสมอัลฟ่าต่อระนาบพร้อมกัน
- เส้นทางฮาร์ดแวร์สำหรับการเล่นวิดีโอที่ได้รับการคุ้มครอง
- ลำดับการบรรจุหีบห่อ RGBA, รูปแบบ YUV และการปูกระเบื้อง การรวบรัด และการเดินเร็ว พร็อพเพอร์ตี้
วิธีติดตั้งใช้งาน HWC
- ใช้ HWC แบบไม่ดำเนินการและส่งงานการเรียบเรียงทั้งหมดไปที่ GLES
- ใช้อัลกอริทึมเพื่อมอบสิทธิ์ในการเรียบเรียงให้แก่ HWC แบบค่อยเป็นค่อยไป เช่น มอบสิทธิ์เฉพาะ 3 หรือ 4 พื้นผิวแรกให้กับการวางซ้อน ฮาร์ดแวร์ของ HWC
- เพิ่มประสิทธิภาพ HWC ซึ่งอาจรวมถึงสิ่งต่างๆ ต่อไปนี้
- การเลือกแพลตฟอร์มที่ลดภาระของ GPU ให้ได้มากที่สุดและส่งไปยัง HWC
- กำลังตรวจจับว่าหน้าจอกำลังอัปเดตหรือไม่ หากไม่ใช่ ให้มอบหมายการจัดองค์ประกอบให้กับ GLES แทน HWC เพื่อประหยัดพลังงาน เมื่อหน้าจออัปเดตอีกครั้ง ให้โอนการคอมโพสไปให้ HWC ต่อ
- การเตรียมพร้อมสำหรับ Use Case ทั่วไป เช่น
- หน้าจอหลัก ซึ่งรวมถึงแถบสถานะ แถบระบบ และแอป หน้าต่าง และวอลเปเปอร์เคลื่อนไหว
- เกมแบบเต็มหน้าจอในโหมดแนวตั้งและแนวนอน
- วิดีโอแบบเต็มหน้าจอพร้อมคำบรรยายและการควบคุมการเล่น
- การเล่นวิดีโอที่มีการคุ้มครอง
- หลายหน้าต่างในโหมดแยกหน้าจอ
HWC แบบเดิม
HWC มีองค์ประกอบพื้นฐาน 2 อย่าง ได้แก่ เลเยอร์และจอแสดงผล เพื่อแสดงการคอมโพสและการทำงานร่วมกันกับฮาร์ดแวร์จอแสดงผล HWC ยังควบคุม VSYNC และมีการเรียกกลับไปยัง SurfaceFlinger เพื่อแจ้งให้ทราบเมื่อมีเหตุการณ์ VSYNC เกิดขึ้น
อินเทอร์เฟซ HIDL
Android 8.0 ขึ้นไปใช้
อินเทอร์เฟซ HIDL ที่เรียกว่า Composer HAL สำหรับ
IPC แบบผูกมัดระหว่าง HWC และ SurfaceFlinger HAL ของ Composer จะมาแทนที่อินเทอร์เฟซ hwcomposer2.h
รุ่นเดิม กรณีที่ผู้ให้บริการมี HAL ของ Composer
ติดตั้งใช้งาน HWC แล้ว Composer HAL จะยอมรับการเรียกใช้ HIDL โดยตรงจาก
SurfaceFlinger หากผู้ให้บริการมีการใช้งาน HWC แบบเดิม Composer HAL จะโหลดตัวชี้ฟังก์ชันจาก hwcomposer2.h
โดยส่งต่อการเรียก HIDL ไปยังการเรียกตัวชี้ฟังก์ชัน
HWC มีฟังก์ชันสำหรับระบุคุณสมบัติของจอแสดงผลหนึ่งๆ ถึง สลับระหว่างการกำหนดค่าการแสดงผลต่างๆ (เช่น 4K หรือ 1080p ความละเอียด) และโหมดสี (เช่น สีดั้งเดิมหรือ sRGB จริง) และเปลี่ยน หน้าจอจะเปิดหรือปิด หรือเข้าสู่โหมดใช้พลังงานต่ำ (หากรองรับ)
ตัวชี้ฟังก์ชัน
หากผู้ให้บริการใช้ HAL ของ Composer โดยตรง SurfaceFlinger จะเรียกใช้ฟังก์ชันของ Composer โดยตรง
ผ่าน HIDL IPC ตัวอย่างเช่น ในการสร้างเลเยอร์ จะเรียก SurfaceFlinger
createLayer()
ใน HAL ของ Composer
หากผู้ให้บริการใช้อินเทอร์เฟซ hwcomposer2.h
แล้ว Composer HAL
เข้าสู่เคอร์เซอร์ฟังก์ชัน hwcomposer2.h
ในความคิดเห็น hwcomposer2.h
ระบบจะอ้างอิงฟังก์ชันอินเทอร์เฟซ HWC ด้วยชื่อรูปแบบ lowerCamelCase ซึ่งไม่มีอยู่ในอินเทอร์เฟซเป็นช่องที่มีชื่อ เกือบทุกฟังก์ชันจะโหลดโดยขอตัวชี้ฟังก์ชันโดยใช้ getFunction
ที่ได้จาก hwc2_device_t
เช่น ฟังก์ชัน createLayer
เป็นพอยน์เตอร์ฟังก์ชันประเภท HWC2_PFN_CREATE_LAYER
ซึ่งจะแสดงผลเมื่อมีการผ่านค่าที่ระบุ HWC2_FUNCTION_CREATE_LAYER
ไปยัง getFunction
ดูเอกสารประกอบโดยละเอียดเกี่ยวกับฟังก์ชัน HAL ของ Composer และฟังก์ชันการส่งผ่านฟังก์ชัน HWC ได้ที่ composer
หากต้องการดูเอกสารโดยละเอียดเกี่ยวกับ
ตัวชี้ฟังก์ชัน HWC โปรดดู
hwcomposer2.h
ที่จับเลเยอร์และจอแสดงผล
เลเยอร์และจอแสดงผลจะควบคุมโดยแฮนเดิลที่ HWC สร้างขึ้น แฮนเดิลจะมองไม่เห็นสำหรับ SurfaceFlinger
เมื่อ SurfaceFlinger สร้างเลเยอร์ใหม่ ระบบจะเรียก createLayer
ซึ่งแสดงผลประเภท Layer
สำหรับการเข้าชมโดยตรง
หรือ hwc2_layer_t
สำหรับการใช้งาน Passthrough เมื่อ SurfaceFlinger แก้ไขพร็อพเพอร์ตี้ของเลเยอร์นั้น SurfaceFlinger จะส่งค่า hwc2_layer_t
ไปยังฟังก์ชันการแก้ไขที่เหมาะสม พร้อมกับข้อมูลอื่นๆ ที่จําเป็นสําหรับการแก้ไข ประเภท hwc2_layer_t
มีขนาดใหญ่พอที่จะเก็บตัวชี้หรือดัชนี
จอแสดงผลที่จับต้องได้สร้างขึ้นด้วยการ Hotplugged เมื่อจอแสดงผล
HWC จะสร้างแฮนเดิล และส่งไปยัง SurfaceFlinger
ผ่าน HotPlug Callback SurfaceFlinger จะสร้างจอแสดงผลเสมือนจริงโดยเรียกใช้ createVirtualDisplay()
เพื่อขอจอแสดงผล หาก HWC
รองรับองค์ประกอบการแสดงผลแบบเสมือน และจะแสดงแฮนเดิล จากนั้น SurfaceFlinger
มอบสิทธิ์องค์ประกอบของจอแสดงผลให้กับ HWC หาก HWC ไม่รองรับการสนับสนุนทางออนไลน์
การจัดวางองค์ประกอบการแสดงผล SurfaceFlinger จะสร้างแฮนเดิลและประกอบการแสดงผล
การดำเนินการจัดองค์ประกอบจอแสดงผล
SurfaceFlinger จะตื่นขึ้น 1 ครั้งต่อ VSYNC หากมีเนื้อหาใหม่ที่จะคอมโพส เนื้อหาใหม่นี้อาจเป็นบัฟเฟอร์รูปภาพใหม่จากแอปหรือการเปลี่ยนแปลงในพร็อพเพอร์ตี้ของเลเยอร์อย่างน้อย 1 เลเยอร์ เมื่อแพลตฟอร์มFlinger ปลุกระบบ:
- จัดการธุรกรรม หากมี
- ล็อกบัฟเฟอร์กราฟิกใหม่ (หากมี)
- ดำเนินการจัดองค์ประกอบใหม่ หากขั้นตอนที่ 1 หรือ 2 ส่งผลให้มีการเปลี่ยนแปลงเนื้อหาที่แสดง
สำหรับการจัดองค์ประกอบใหม่ SurfaceFlinger จะสร้างและ
ทำลายเลเยอร์หรือแก้ไขสถานะของเลเยอร์ตามความเหมาะสม และยังเป็นการอัปเดต
กับเนื้อหาปัจจุบันด้วยการเรียก เช่น
setLayerBuffer
หรือ setLayerColor
หลังจากอัปเดตเลเยอร์ทั้งหมดแล้ว SurfaceFlinger จะเรียกใช้ validateDisplay
ซึ่งจะบอกให้ HWC ตรวจสอบสถานะของเลเยอร์และกำหนดวิธีดำเนินการคอมโพส โดยค่าเริ่มต้น SurfaceFlinger จะพยายามกำหนดค่าเลเยอร์ทุกเลเยอร์เพื่อให้ HWC คอมโพสเลเยอร์ แต่ในกรณีบางประการ SurfaceFlinger จะคอมโพสเลเยอร์ผ่าน GPU สำรอง
หลังจากโทรหา validateDisplay
แล้ว SurfaceFlinger จะโทรหา
getChangedCompositionTypes
เพื่อดูว่า HWC
ต้องการให้มีการเปลี่ยนแปลงประเภทองค์ประกอบของเลเยอร์ก่อนที่จะดำเนินการ
องค์ประกอบ หากต้องการยอมรับการเปลี่ยนแปลง SurfaceFlinger จะเรียกใช้
acceptDisplayChanges
หากมีการทําเครื่องหมายเลเยอร์สําหรับการคอมโพสิชัน SurfaceFlinger ไว้ SurfaceFlinger จะคอมโพสิชันเลเยอร์เหล่านั้นลงในบัฟเฟอร์เป้าหมาย จากนั้น SurfaceFlinger จะเรียกใช้ setClientTarget
เพื่อส่งบัฟเฟอร์ไปยังจอแสดงผลเพื่อให้บัฟเฟอร์แสดงบนหน้าจอหรือคอมโพสิตเพิ่มเติมกับเลเยอร์ที่ไม่ได้ทำเครื่องหมายไว้สำหรับคอมโพสิตของ SurfaceFlinger ถ้าไม่ได้ทำเครื่องหมายเลเยอร์ไว้
พื้นผิว SurfaceFlinger โปรแกรม SurfaceFlinger ข้ามขั้นตอนการจัดวาง
สุดท้าย SurfaceFlinger ก็โทรหา presentDisplay
เพื่อแจ้ง
HWC เพื่อดำเนินกระบวนการแต่งเพลงให้เสร็จสมบูรณ์และแสดงผลสุดท้าย
จอแสดงผลหลายจอ
Android 10 รองรับหน้าจอจริงหลายชิ้น เมื่อออกแบบการใช้งาน HWC เพื่อใช้กับ Android 7.0 และ สูงกว่า มีข้อจำกัดบางประการที่ไม่มีอยู่ในคำจำกัดความของ HWC ดังนี้
- ระบบจะถือว่ามีจอแสดงผลภายในเพียง 1 จอ จอแสดงผลภายในคือจอแสดงผลที่การเสียบปลั๊กร้อนเริ่มต้นรายงานระหว่างการบูต หลังจากเสียบจอแสดงผลภายในแบบฮอตปลั๊กแล้ว จะถอดออกไม่ได้
- นอกจากจอแสดงผลภายในแล้ว อาจเสียบปลั๊กจอแสดงผลภายนอกกี่จอก็ได้
ระหว่างการทำงานตามปกติของอุปกรณ์ เฟรมเวิร์กนี้จะถือว่า
ปลั๊กฮอตหลังจากจอแสดงผลภายในเครื่องแรกเป็นจอแสดงผลภายนอก ดังนั้นหากมี
ระบบจะเพิ่มจอแสดงผลภายใน แต่จะได้รับการจัดหมวดหมู่ไม่ถูกต้องตาม
Display.TYPE_HDMI
แทนที่จะเป็นDisplay.TYPE_BUILT_IN
แม้ว่าการดำเนินการ SurfaceFlinger ที่อธิบายไว้ข้างต้นจะดำเนินการต่อจอแสดงผลแต่ละจอ แต่การดำเนินการดังกล่าวจะดำเนินการตามลำดับสำหรับจอแสดงผลที่ใช้งานอยู่ทั้งหมด แม้ว่าจะมีการอัปเดตเนื้อหาของจอแสดงผลเพียงจอเดียวก็ตาม
ตัวอย่างเช่น หากจอแสดงผลภายนอกได้รับการอัปเดต ลำดับการทำงานจะเป็นดังนี้
// In Android 9 and lower: // Update state for internal display // Update state for external display validateDisplay(<internal display>) validateDisplay(<external display>) presentDisplay(<internal display>) presentDisplay(<external display>) // In Android 10 and higher: // Update state for internal display // Update state for external display validateInternal(<internal display>) presentInternal(<internal display>) validateExternal(<external display>) presentExternal(<external display>)
องค์ประกอบของจอแสดงผลเสมือนจริง
การจัดวางองค์ประกอบของจอแสดงผลเสมือนจริงคล้ายกับการจัดวางองค์ประกอบของจอแสดงผลภายนอก ความแตกต่างระหว่างองค์ประกอบของการแสดงผลแบบเสมือนกับลักษณะทางกายภาพ การจัดวางองค์ประกอบการแสดงผล คือการที่จอแสดงผลเสมือนจะส่งเอาต์พุตไปยังบัฟเฟอร์ Gralloc แทนหน้าจอ เครื่องมือจัดระเบียบฮาร์ดแวร์ (HWC) จะเขียนเอาต์พุตลงในบัฟเฟอร์ ระบุรั้วการเสร็จสมบูรณ์ และส่งบัฟเฟอร์ไปยังผู้บริโภค (เช่น ตัวแปลงรหัสวิดีโอ, GPU, CPU และอื่นๆ) จอแสดงผลเสมือนสามารถใช้ 2D/Blitter หรือการวางซ้อนได้หากไปป์ไลน์การแสดงผลเขียนไปยังหน่วยความจำ
โหมด
เฟรมแต่ละเฟรมจะอยู่ในโหมดใดโหมดหนึ่งต่อไปนี้หลังจากที่ SurfaceFlinger เรียกใช้validateDisplay()
เมธอด HWC
- GLES — GPU ทำการผสมเลเยอร์ทั้งหมด กำลังเขียน ไปยังบัฟเฟอร์เอาต์พุตโดยตรง HWC ไม่เกี่ยวข้องกับการเรียบเรียง
- ผสม — GPU จะคอมโพสเลเยอร์บางรายการลงในเฟรมบัฟเฟอร์ และ HWC จะคอมโพสเฟรมบัฟเฟอร์และเลเยอร์ที่เหลือ โดยเขียนลงในบัฟเฟอร์เอาต์พุตโดยตรง
- HWC — HWC จะคอมโพสิตเลเยอร์ทั้งหมดและเขียนโดยตรง ไปยังบัฟเฟอร์เอาต์พุต
รูปแบบเอาต์พุต
รูปแบบเอาต์พุตของบัฟเฟอร์จอแสดงผลเสมือนจะขึ้นอยู่กับโหมดต่อไปนี้
- โหมด GLES — ไดรเวอร์ EGL จะตั้งค่าบัฟเฟอร์เอาต์พุต
ใน
dequeueBuffer()
ซึ่งโดยทั่วไปจะเป็นRGBA_8888
ผู้บริโภคต้องยอมรับรูปแบบเอาต์พุตที่ไดรเวอร์กำหนด มิฉะนั้นระบบจะอ่านบัฟเฟอร์ไม่ได้ - โหมด MIXED และ HWC - หากผู้บริโภคต้องการ CPU
การเข้าถึง ผู้บริโภคจะเป็นผู้กำหนดรูปแบบเอง มิเช่นนั้น รูปแบบจะเป็น
IMPLEMENTATION_DEFINED
และ Gralloc จะตั้งค่ารูปแบบที่ดีที่สุดตาม Flag การใช้งาน เช่น Gralloc จะตั้งค่ารูปแบบ YCbCr หากผู้บริโภคเป็นโปรแกรมเปลี่ยนรูปแบบวิดีโอและ HWC สามารถเขียนรูปแบบได้อย่างมีประสิทธิภาพ
รั้วการซิงค์
การซิงค์ (Sync) รั้วเป็นมุมมองที่สำคัญในกราฟิก Android ระบบ รั้วช่วยให้ CPU ทำงานได้อย่างอิสระจากการทำงานของ GPU พร้อมกัน บล็อกเฉพาะเมื่อมีทรัพยากร Dependency ที่แท้จริงเท่านั้น
เช่น เมื่อแอปส่งบัฟเฟอร์ที่สร้างขึ้นบน GPU ก็จะส่งออบเจ็กต์ Sync Fence ด้วย เฟนซ์นี้จะส่งสัญญาณเมื่อ GPU เขียนข้อมูลลงในบัฟเฟอร์เสร็จแล้ว
HWC กำหนดให้ GPU เขียนบัฟเฟอร์จนเสร็จก่อนจึงจะแสดงบัฟเฟอร์ได้ Sync Fences จะถูกส่งผ่านไปป์ไลน์ของกราฟิกที่มีบัฟเฟอร์ และส่งสัญญาณเมื่อมีการเขียนบัฟเฟอร์ ก่อนที่จะแสดงบัฟเฟอร์ HWC จะตรวจสอบว่ารั้วการซิงค์ส่งสัญญาณหรือไม่ หากส่งสัญญาณ ก็จะแสดงบัฟเฟอร์
ดูข้อมูลเพิ่มเติมเกี่ยวกับรั้วการซิงค์ได้ที่การผสานรวม Hardware Composer