ใช้ HAL ของเครื่องมือแต่งเพลงฮาร์ดแวร์

Hardware Composer (HWC) HAL จะรวมเลเยอร์ที่ได้รับจาก SurfaceFlinger ซึ่งจะช่วยลดปริมาณการรวม OpenGL ES (GLES) และ GPU

HWC จะแยกออบเจ็กต์ เช่น การซ้อนทับและ Blitter 2 มิติ เพื่อสร้างพื้นผิวแบบผสม และสื่อสารกับฮาร์ดแวร์การจัดองค์ประกอบหน้าต่างเฉพาะทางเพื่อ จัดองค์ประกอบหน้าต่าง ใช้ HWC เพื่อคอมโพสิตหน้าต่างแทนการให้ SurfaceFlinger คอมโพสิตกับ GPU GPU ส่วนใหญ่ไม่ได้ปรับให้เหมาะกับ การจัดองค์ประกอบ และเมื่อ GPU จัดองค์ประกอบเลเยอร์จาก SurfaceFlinger แอปจะใช้ GPU สำหรับการแสดงผลของตัวเองไม่ได้

การติดตั้งใช้งาน HWC ควรมีคุณสมบัติดังนี้

  • ภาพซ้อนทับอย่างน้อย 4 รายการ
    • แถบสถานะ
    • แถบระบบ
    • แอป
    • วอลเปเปอร์/พื้นหลัง
  • เลเยอร์ที่มีขนาดใหญ่กว่าจอแสดงผล (เช่น วอลเปเปอร์)
  • การผสมอัลฟ่าต่อพิกเซลแบบคูณล่วงหน้าพร้อมกันและการผสมอัลฟ่าต่อระนาบ
  • เส้นทางฮาร์ดแวร์สำหรับการเล่นวิดีโอที่มีการป้องกัน
  • ลำดับการแพ็ก RGBA, รูปแบบ YUV และการแบ่งเป็นไทล์ การสลับ และพร็อพเพอร์ตี้ระยะก้าวย่าง

วิธีติดตั้งใช้งาน HWC

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

องค์ประกอบพื้นฐานของ HWC

HWC มี 2 องค์ประกอบพื้นฐาน ได้แก่ เลเยอร์และจอแสดงผล เพื่อ แสดงงานการจัดองค์ประกอบและการโต้ตอบกับฮาร์ดแวร์จอแสดงผล HWC ยังให้การควบคุม VSync และการเรียกกลับไปยัง SurfaceFlinger เพื่อแจ้งให้ทราบเมื่อมีเหตุการณ์ VSync เกิดขึ้น

อินเทอร์เฟซ HIDL

Android 8.0 ขึ้นไปใช้ อินเทอร์เฟซ HIDL ที่เรียกว่า Composer HAL สำหรับ IPC ที่ใช้ Binder ระหว่าง HWC กับ SurfaceFlinger Composer HAL จะแทนที่อินเทอร์เฟซ hwcomposer2.h รุ่นเดิม หากผู้ให้บริการมี HAL ของ Composer ที่ใช้ HWC อยู่ HAL ของ Composer จะยอมรับการเรียก HIDL จาก SurfaceFlinger โดยตรง หากผู้ให้บริการมีการใช้งาน HWC แบบเดิม Composer HAL จะโหลดตัวชี้ฟังก์ชันจาก hwcomposer2.h การส่งต่อการเรียก HIDL ไปยังการเรียกตัวชี้ฟังก์ชัน

HWC มีฟังก์ชันในการกำหนดคุณสมบัติของจอแสดงผลที่ต้องการ สลับระหว่างการกำหนดค่าจอแสดงผลต่างๆ (เช่น ความละเอียด 4K หรือ 1080p) และโหมดสี (เช่น สีดั้งเดิมหรือ sRGB จริง) รวมถึงเปิด ปิด หรือเปลี่ยนจอแสดงผลเป็นโหมดประหยัดพลังงาน (หากรองรับ)

ตัวชี้ฟังก์ชัน

หากผู้ให้บริการใช้ Composer HAL โดยตรง SurfaceFlinger จะเรียกฟังก์ชันของ Composer HAL ผ่าน HIDL IPC เช่น หากต้องการสร้างเลเยอร์ SurfaceFlinger จะเรียกใช้ createLayer() ใน Composer HAL

หากผู้ให้บริการใช้hwcomposer2.hอินเทอร์เฟซ Composer HAL จะเรียกตัวชี้ฟังก์ชัน hwcomposer2.h ในhwcomposer2.hความคิดเห็น ฟังก์ชันอินเทอร์เฟซ HWC จะ อ้างอิงตามชื่อ lowerCamelCase ที่ไม่มีอยู่ในอินเทอร์เฟซ เป็นฟิลด์ที่มีชื่อ ฟังก์ชันเกือบทั้งหมดจะโหลดโดยการขอ ตัวชี้ฟังก์ชันโดยใช้ getFunction ที่จัดทำโดย hwc2_device_t ตัวอย่างเช่น ฟังก์ชัน createLayer คือตัวชี้ฟังก์ชันประเภท HWC2_PFN_CREATE_LAYER ซึ่งจะ แสดงผลเมื่อส่งค่าที่แจงนับ HWC2_FUNCTION_CREATE_LAYER ไปยัง getFunction

ดูเอกสารประกอบโดยละเอียดเกี่ยวกับฟังก์ชัน Composer HAL และฟังก์ชัน HWC function passthrough ได้ที่ composer ดูเอกสารประกอบแบบละเอียดเกี่ยวกับ ตัวชี้ฟังก์ชัน HWC ได้ที่ hwcomposer2.h

เลเยอร์และแฮนเดิลที่แสดง

เลเยอร์และจอแสดงผลจะได้รับการจัดการโดยแฮนเดิลที่ HWC สร้างขึ้น แฮนเดิลจะไม่ชัดเจนสำหรับ SurfaceFlinger

เมื่อ SurfaceFlinger สร้างเลเยอร์ใหม่ จะเรียก createLayer, ซึ่งจะแสดงผลประเภท Layer สำหรับการใช้งานโดยตรง หรือ hwc2_layer_t สำหรับการใช้งานแบบส่งผ่าน เมื่อ SurfaceFlinger แก้ไขพร็อพเพอร์ตี้ของเลเยอร์นั้น SurfaceFlinger จะส่งhwc2_layer_tค่าไปยังฟังก์ชันการแก้ไขที่เหมาะสม พร้อมกับข้อมูลอื่นๆ ที่จำเป็นต่อการแก้ไข hwc2_layer_tประเภทมีขนาดใหญ่พอที่จะเก็บทั้งพอยน์เตอร์หรือดัชนี

ระบบจะสร้างจอแสดงผลจริงโดยการเสียบปลั๊กร้อน เมื่อเสียบจอแสดงผลจริง แบบ Hotplug HWC จะสร้างแฮนเดิลและส่งแฮนเดิลไปยัง SurfaceFlinger ผ่านการเรียกกลับของ Hotplug SurfaceFlinger สร้างจอแสดงผลเสมือนโดยการเรียกใช้ createVirtualDisplay() เพื่อขอจอแสดงผล หาก HWC รองรับการเขียนจอแสดงผลเสมือน ระบบจะแสดงผลแฮนเดิล จากนั้น SurfaceFlinger จะมอบหมายการคอมโพสจอแสดงผลให้กับ HWC หาก HWC ไม่รองรับการจัดองค์ประกอบจอแสดงผลเสมือน SurfaceFlinger จะสร้างแฮนเดิลและจัดองค์ประกอบจอแสดงผล

การดำเนินการกับองค์ประกอบของโฆษณา Display

SurfaceFlinger จะตื่นขึ้น 1 ครั้งต่อ VSync หากมีเนื้อหาใหม่ที่จะ คอมโพสิต เนื้อหาใหม่นี้อาจเป็นบัฟเฟอร์รูปภาพใหม่จากแอปหรือการเปลี่ยนแปลงพร็อพเพอร์ตี้ของเลเยอร์อย่างน้อย 1 เลเยอร์ เมื่อ SurfaceFlinger ปลุกขึ้นมา

  1. จัดการธุรกรรม หากมี
  2. ล็อกบัฟเฟอร์กราฟิกใหม่ หากมี
  3. สร้างองค์ประกอบใหม่ หากขั้นตอนที่ 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 ดังนี้

  • ระบบจะถือว่ามีจอแสดงผลภายในเพียงจอเดียว จอแสดงผลภายในคือจอแสดงผลที่รายงานการเสียบปลั๊กร้อนครั้งแรกระหว่างการบูต หลังจากเสียบจอแสดงผลภายในแบบ Hotplug แล้ว คุณจะ ยกเลิกการเชื่อมต่อไม่ได้
  • นอกจากจอแสดงผลภายในแล้ว คุณยังสามารถเสียบจอแสดงผลภายนอกกี่จอก็ได้ ขณะที่อุปกรณ์ทำงานตามปกติ เฟรมเวิร์กจะถือว่าการ เสียบร้อนทั้งหมดหลังจากจอแสดงผลภายในเครื่องแรกเป็นจอแสดงผลภายนอก ดังนั้นหากมีการเพิ่มจอแสดงผลภายในเครื่องอีก ระบบจะจัดหมวดหมู่เป็น 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 แทนที่จะส่งไปยังหน้าจอ Hardware Composer (HWC) จะเขียนเอาต์พุตไปยังบัฟเฟอร์ ระบุรั้วการเสร็จสิ้น และส่งบัฟเฟอร์ไปยังผู้ใช้ (เช่น ตัวเข้ารหัสวิดีโอ, GPU, CPU และอื่นๆ) จอแสดงผลเสมือนสามารถใช้ 2D/blitter หรือ การวางซ้อนได้หากไปป์ไลน์การแสดงผลเขียนลงในหน่วยความจำ

โหมด

แต่ละเฟรมจะอยู่ในโหมดใดโหมดหนึ่งต่อไปนี้หลังจากที่ SurfaceFlinger เรียกใช้ validateDisplay() วิธี HWC

  • GLES — GPU จะรวมเลเยอร์ทั้งหมดและเขียนลงในบัฟเฟอร์เอาต์พุตโดยตรง HWC ไม่มีส่วนเกี่ยวข้องกับการเรียบเรียง
  • MIXED - GPU จะคอมโพสิตเลเยอร์บางส่วนไปยัง เฟรมบัฟเฟอร์ และ HWC จะคอมโพสิตเฟรมบัฟเฟอร์และเลเยอร์ที่เหลือ โดยเขียนไปยังบัฟเฟอร์เอาต์พุตโดยตรง
  • HWC - HWC จะรวมเลเยอร์ทั้งหมดและเขียนลงในบัฟเฟอร์เอาต์พุตโดยตรง

รูปแบบเอาต์พุต

รูปแบบเอาต์พุตบัฟเฟอร์การแสดงผลเสมือนจะขึ้นอยู่กับโหมดของบัฟเฟอร์

  • โหมด GLES - ไดรเวอร์ EGL จะตั้งค่ารูปแบบบัฟเฟอร์เอาต์พุต ใน dequeueBuffer() โดยปกติคือ RGBA_8888 ผู้ใช้ต้องยอมรับรูปแบบเอาต์พุตที่ไดรเวอร์ตั้งค่าไว้ มิฉะนั้นระบบจะอ่านบัฟเฟอร์ไม่ได้
  • โหมด MIXED และ HWC - หากผู้บริโภคต้องการสิทธิ์เข้าถึง CPU ผู้บริโภคจะเป็นผู้กำหนดรูปแบบ หรือรูปแบบจะเป็น IMPLEMENTATION_DEFINED และ Gralloc จะตั้งค่ารูปแบบที่ดีที่สุดตาม แฟล็กการใช้งาน เช่น Gralloc จะตั้งค่ารูปแบบ YCbCr หากผู้ใช้เป็นตัวเข้ารหัสวิดีโอและ HWC สามารถเขียนรูปแบบได้อย่างมีประสิทธิภาพ

รั้วการซิงโครไนซ์

รั้วการซิงโครไนซ์ (ซิงค์) เป็นส่วนสำคัญของระบบกราฟิกของ Android รั้วช่วยให้ CPU ทำงานได้อย่างอิสระจากงาน GPU ที่พร้อมกัน โดยจะบล็อกเฉพาะเมื่อมีการขึ้นต่อกันจริงๆ เท่านั้น

เช่น เมื่อแอปส่งบัฟเฟอร์ที่กำลังสร้างใน GPU แอปจะส่งออบเจ็กต์รั้วการซิงค์ด้วย รั้วนี้จะส่งสัญญาณเมื่อ GPU เขียนลงในบัฟเฟอร์เสร็จแล้ว

HWC กำหนดให้ GPU เขียนบัฟเฟอร์ให้เสร็จก่อนที่จะแสดงบัฟเฟอร์ ระบบจะส่งผ่าน Sync Fence ผ่านไปป์ไลน์กราฟิกพร้อมบัฟเฟอร์ และส่งสัญญาณเมื่อมีการเขียนบัฟเฟอร์ ก่อนที่จะแสดงบัฟเฟอร์ HWC จะตรวจสอบว่ารั้วการซิงค์ส่งสัญญาณหรือไม่ หากส่งสัญญาณแล้ว HWC จะแสดงบัฟเฟอร์

ดูข้อมูลเพิ่มเติมเกี่ยวกับ Sync Fence ได้ที่การผสานรวม Hardware Composer