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 ต่อ
- การเตรียมพร้อมสําหรับกรณีการใช้งานทั่วไป เช่น
- หน้าจอหลัก ซึ่งมีแถบสถานะ แถบระบบ หน้าต่างแอป และวอลเปเปอร์เคลื่อนไหว
- เกมแบบเต็มหน้าจอในโหมดแนวตั้งและแนวนอน
- วิดีโอแบบเต็มหน้าจอพร้อมคำบรรยายและการควบคุมการเล่น
- การเล่นวิดีโอที่ได้รับการคุ้มครอง
- แยกหน้าจอหลายหน้าต่าง
พรอมิเตี HWC
HWC มีองค์ประกอบพื้นฐาน 2 อย่าง ได้แก่ เลเยอร์และจอแสดงผล เพื่อแสดงการทํางานขององค์ประกอบและการทำงานร่วมกันกับฮาร์ดแวร์ของจอแสดงผล HWC ยังควบคุม VSYNC และมีการเรียกกลับไปยัง SurfaceFlinger เพื่อแจ้งเมื่อมีเหตุการณ์ VSYNC เกิดขึ้น
อินเทอร์เฟซ HIDL
Android 8.0 ขึ้นไปใช้อินเทอร์เฟซ HIDL ที่เรียกว่า Composer HAL สำหรับ IPC แบบ Binderized ระหว่าง HWC กับ SurfaceFlinger HAL ของ Composer จะมาแทนที่อินเทอร์เฟซ hwcomposer2.h
รุ่นเดิม หากผู้ให้บริการมีการใช้งาน Composer HAL ของ HWC อยู่ Composer HAL จะยอมรับการเรียก HIDL จาก SurfaceFlinger โดยตรง หากผู้ให้บริการมีการใช้งาน HWC แบบเดิม Composer HAL จะโหลดตัวชี้ฟังก์ชันจาก hwcomposer2.h
โดยส่งต่อการเรียก HIDL ไปยังการเรียกตัวชี้ฟังก์ชัน
HWC มีฟังก์ชันในการระบุคุณสมบัติของจอแสดงผลหนึ่งๆ เพื่อสลับระหว่างการกำหนดค่าจอแสดงผลต่างๆ (เช่น ความละเอียด 4K หรือ 1080p) และโหมดสี (เช่น สีดั้งเดิมหรือ sRGB จริง) รวมถึงเพื่อเปิด ปิด หรือเปลี่ยนจอแสดงผลเป็นโหมดพลังงานต่ำ (หากรองรับ)
ตัวชี้ฟังก์ชัน
หากผู้ให้บริการใช้ Composer HAL โดยตรง SurfaceFlinger จะเรียกใช้ฟังก์ชันผ่าน HIDL IPC ตัวอย่างเช่น ในการสร้างเลเยอร์ SurfaceFlinger จะเรียก createLayer()
ใน HAL ของ Composer
หากผู้ให้บริการใช้อินเทอร์เฟซ hwcomposer2.h
ทาง Composer HAL จะเรียกใช้ตัวชี้ฟังก์ชัน hwcomposer2.h
ในความคิดเห็น hwcomposer2.h
ฟังก์ชันอินเทอร์เฟซ HWC จะอ้างอิงโดยใช้ชื่อ bottomCamelCase ที่ไม่มีอยู่ในอินเทอร์เฟซเป็นช่องที่มีชื่อ ระบบจะโหลดฟังก์ชันเกือบทั้งหมดโดยขอเคอร์เซอร์ฟังก์ชันโดยใช้ 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
มีขนาดใหญ่พอที่จะเก็บตัวชี้หรือดัชนีได้
จอแสดงผลที่จับต้องได้สร้างขึ้นโดยการเสียบ/ถอดออกขณะที่อุปกรณ์ทำงานอยู่ เมื่อเสียบจอแสดงผลจริง HWC จะสร้างแฮนเดิลและส่งแฮนเดิลไปยัง SurfaceFlinger ผ่านคอลแบ็กการเสียบ/ถอด SurfaceFlinger จะสร้างจอแสดงผลเสมือนจริงโดยเรียกใช้ createVirtualDisplay()
เพื่อขอจอแสดงผล หาก HWCรองรับการคอมโพสิชันการแสดงผลเสมือนจริง ระบบจะแสดงผลแฮนเดิล จากนั้น SurfaceFlinger จะมอบหมายการจัดองค์ประกอบของจอแสดงผลให้กับ HWC หาก HWC ไม่รองรับการแสดงผลเสมือนจริง SurfaceFlinger จะสร้างแฮนเดิลและคอมโพสิตการแสดงผล
การดำเนินการจัดองค์ประกอบจอแสดงผล
SurfaceFlinger จะตื่นขึ้น 1 ครั้งต่อ VSYNC หากมีเนื้อหาใหม่ที่จะคอมโพส เนื้อหาใหม่นี้อาจเป็นบัฟเฟอร์รูปภาพใหม่จากแอปหรือการเปลี่ยนแปลงพร็อพเพอร์ตี้ของเลเยอร์อย่างน้อย 1 เลเยอร์ เมื่อ SurfaceFlinger ตื่นขึ้นมา
- จัดการธุรกรรม หากมี
- สลักบัฟเฟอร์กราฟิกใหม่ หากมี
- ดำเนินการจัดองค์ประกอบใหม่ หากขั้นตอนที่ 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 และอื่นๆ) จอแสดงผลเสมือนสามารถใช้แบบ 2 มิติ/การถ่ายโอนหรือการวางซ้อนหากไปป์ไลน์การแสดงผลเขียนไปยังหน่วยความจำ
โหมด
เฟรมแต่ละเฟรมจะอยู่ในโหมดใดโหมดหนึ่งต่อไปนี้หลังจากที่ 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 สามารถเขียนรูปแบบได้อย่างมีประสิทธิภาพ
รั้วการซิงค์
รั้วการซิงค์ (การซิงค์) เป็นองค์ประกอบที่สําคัญของระบบกราฟิก Android Fences ช่วยให้ CPU ทำงานได้อย่างอิสระจากการทำงานของ GPU แบบพร้อมกัน โดยจะบล็อกเฉพาะเมื่อมีการขึ้นต่อกันจริงเท่านั้น
เช่น เมื่อแอปส่งบัฟเฟอร์ที่สร้างขึ้นบน GPU ก็จะส่งออบเจ็กต์ Sync Fence ด้วย เฟนซ์นี้จะส่งสัญญาณเมื่อ GPU เขียนข้อมูลลงในบัฟเฟอร์เสร็จแล้ว
HWC กำหนดให้ GPU บัฟเฟอร์ในการเขียนก่อนที่จะแสดงบัฟเฟอร์ ระบบจะส่งรั้วการซิงค์ผ่านไปป์ไลน์กราฟิกพร้อมกับบัฟเฟอร์และสัญญาณเมื่อมีการเขียนบัฟเฟอร์ ก่อนที่บัฟเฟอร์จะปรากฏขึ้น HWC จะตรวจสอบว่ารั้วการซิงค์ส่งสัญญาณหรือไม่ และมีสัญญาณแสดงบัฟเฟอร์หรือไม่
ดูข้อมูลเพิ่มเติมเกี่ยวกับรั้วการซิงค์ได้ที่การผสานรวม Hardware Composer