ใช้ 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 ที่เชื่อมโยงระหว่าง HWC กับ SurfaceFlinger Composer HAL จะแทนที่อินเทอร์เฟซ hwcomposer2.h เดิม หากผู้ให้บริการมี การติดตั้งใช้งาน Composer HAL ของ HWC Composer HAL จะยอมรับการเรียก 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

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

เลเยอร์และแฮนเดิลการแสดงผล

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

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

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

การดำเนินการกับองค์ประกอบของจอแสดงผล

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 จะรวมเลเยอร์บางส่วนเข้ากับ FrameBuffer และ HWC จะรวม FrameBuffer กับเลเยอร์ที่เหลือ โดยเขียนลงในบัฟเฟอร์เอาต์พุตโดยตรง
  • 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