BufferQueue และ Gralloc

คลาส BufferQueue จะเชื่อมต่อคอมโพเนนต์ที่สร้างบัฟเฟอร์ของข้อมูลกราฟิก (ผู้ผลิต) กับคอมโพเนนต์ที่รับข้อมูลเพื่อแสดงผลหรือประมวลผลเพิ่มเติม (ผู้บริโภค) เกือบทุกอย่างที่ย้ายบัฟเฟอร์ของข้อมูลกราฟิกผ่านระบบจะอาศัย BufferQueue

ตัวจัดสรรหน่วยความจำ Gralloc จะจัดสรรบัฟเฟอร์และติดตั้งใช้งานผ่านอินเทอร์เฟซ HIDL เฉพาะของผู้ให้บริการ 2 รายการ (ดูhardware/interfaces/graphics/allocator/และhardware/interfaces/graphics/mapper/) ฟังก์ชันallocate()จะรับอาร์กิวเมนต์ที่คาดไว้ (ความกว้าง ความสูง รูปแบบพิกเซล) รวมถึงชุด Flag การใช้งาน

ผู้ผลิตและผู้บริโภค BufferQueue

ผู้บริโภคจะสร้างและเป็นเจ้าของโครงสร้างข้อมูล BufferQueue และสามารถอยู่ในกระบวนการอื่นที่แตกต่างจากผู้ผลิตได้ เมื่อผู้ผลิตต้องการบัฟเฟอร์ ก็จะขอบัฟเฟอร์ว่างจาก BufferQueue โดยการเรียกใช้ dequeueBuffer() โดยระบุความกว้าง ความสูง รูปแบบพิกเซล และ Flag การใช้งานของบัฟเฟอร์ จากนั้นโปรดิวเซอร์จะป้อนข้อมูลลงในบัฟเฟอร์และส่งคืนบัฟเฟอร์ไปยังคิวโดยการเรียกใช้ queueBuffer() จากนั้นผู้บริโภคจะรับบัฟเฟอร์ด้วย acquireBuffer() และใช้เนื้อหาบัฟเฟอร์ เมื่อผู้บริโภคดำเนินการเสร็จแล้ว ระบบจะส่งบัฟเฟอร์กลับไปยังคิวโดยเรียกใช้ releaseBuffer() เฟรมเวิร์กการซิงค์จะควบคุมวิธีที่บัฟเฟอร์ย้ายผ่านไปป์ไลน์กราฟิก Android

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

BufferQueue จะไม่คัดลอกเนื้อหาบัฟเฟอร์ เนื่องจากการย้ายข้อมูลจำนวนมากนั้นไม่มีประสิทธิภาพ แต่ระบบจะส่งบัฟเฟอร์ด้วยแฮนเดิลเสมอ

ติดตาม BufferQueue ด้วย Systrace

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

หากต้องการใช้ Systrace ให้เปิดใช้แท็ก gfx, view และ sched ออบเจ็กต์ BufferQueue จะแสดงในการติดตาม ตัวอย่างเช่น หากคุณทำการติดตามขณะที่วิดีโอ Play (SurfaceView) ของ Grafika ทำงานอยู่ แถวที่มีป้ายกำกับ SurfaceView จะบอกจำนวนบัฟเฟอร์ที่อยู่ในคิว ณ เวลาหนึ่งๆ

ค่าจะเพิ่มขึ้นขณะที่แอปทำงานอยู่ ซึ่งจะทริกเกอร์การแสดงผลเฟรมโดยโปรแกรมถอดรหัส MediaCodec ค่าจะลดลงขณะที่ SurfaceFlinger ทำงานและใช้บัฟเฟอร์ เมื่อแสดงวิดีโอที่ 30 เฟรมต่อวินาที ค่าของคิวจะอยู่ระหว่าง 0 ถึง 1 เนื่องจากการแสดงผลที่ประมาณ 60 เฟรมต่อวินาทีจะทันกับแหล่งที่มา SurfaceFlinger จะตื่นขึ้นเฉพาะเมื่อมีงานต้องทำ ไม่ใช่ 60 ครั้งต่อวินาที ระบบจะพยายามหลีกเลี่ยงการทำงานและปิดใช้ VSYNC หากไม่มีสิ่งใดอัปเดตหน้าจอ

หากเปลี่ยนไปใช้วิดีโอการเล่นของ Grafika (TextureView) และจับการติดตามใหม่ คุณจะเห็นแถวที่มีป้ายกำกับว่า com.android.grafika / com.android.grafika.PlayMovieActivity นี่คือเลเยอร์ UI หลัก ซึ่งเป็น BufferQueue อีกรายการหนึ่ง เนื่องจาก TextureView จะแสดงผลในเลเยอร์ UI แทนที่จะเป็นเลเยอร์แยกต่างหาก การอัปเดตทั้งหมดที่ขับเคลื่อนโดยวิดีโอจึงแสดงที่นี่

Gralloc

HAL ของตัวจัดสรร Gralloc hardware/libhardware/include/hardware/gralloc.h จะจัดสรรบัฟเฟอร์ผ่าน Flag การใช้งาน Flag การใช้งานประกอบด้วยแอตทริบิวต์ต่างๆ เช่น

  • ความถี่ในการเข้าถึงหน่วยความจำจากซอฟต์แวร์ (CPU)
  • ความถี่ในการเข้าถึงหน่วยความจำจากฮาร์ดแวร์ (GPU)
  • จะใช้หน่วยความจําเป็นพื้นผิว OpenGL ES (GLES) หรือไม่
  • โปรแกรมเข้ารหัสวิดีโอจะใช้หน่วยความจำหรือไม่

ตัวอย่างเช่น หากรูปแบบบัฟเฟอร์ของผู้ผลิตระบุพิกเซล RGBA_8888 และผู้ผลิตระบุว่าระบบจะเข้าถึงบัฟเฟอร์จากซอฟต์แวร์ (หมายความว่าแอปจะเข้าถึงพิกเซลใน CPU) Gralloc จะสร้างบัฟเฟอร์ที่มี 4 ไบต์ต่อพิกเซลในลำดับ R-G-B-A หากผู้ผลิตระบุให้เข้าถึงบัฟเฟอร์จากฮาร์ดแวร์และเป็นพื้นผิว GLES เท่านั้น Gralloc จะทำทุกอย่างที่โปรแกรมควบคุม GLES ต้องการได้ เช่น การจัดเรียง BGRA, เลย์เอาต์ที่เปลี่ยนรูปแบบแบบไม่เชิงเส้น และรูปแบบสีอื่น การให้ฮาร์ดแวร์ใช้รูปแบบที่ต้องการจะช่วยปรับปรุงประสิทธิภาพได้

บางค่าใช้ร่วมกันในบางแพลตฟอร์มไม่ได้ เช่น Flag โปรแกรมเปลี่ยนไฟล์วิดีโออาจต้องใช้พิกเซล YUV ดังนั้นการเพิ่มสิทธิ์เข้าถึงซอฟต์แวร์และระบุRGBA_8888จึงดำเนินการไม่สำเร็จ

แฮนเดิลที่ Gralloc แสดงผลสามารถส่งผ่านระหว่างกระบวนการต่างๆ ได้ผ่าน Binder

บัฟเฟอร์ที่มีการป้องกัน

Flag การใช้งาน Gralloc GRALLOC_USAGE_PROTECTED อนุญาตให้แสดงบัฟเฟอร์กราฟิกผ่านเส้นทางที่ได้รับการปกป้องด้วยฮาร์ดแวร์เท่านั้น ระนาบการวางซ้อนเหล่านี้เป็นวิธีเดียวในการแสดงเนื้อหา DRM (SurfaceFlinger หรือไดรเวอร์ OpenGL ES เข้าถึงบัฟเฟอร์ที่ได้รับการคุ้มครอง DRM ไม่ได้)

วิดีโอที่มีการป้องกัน DRM จะแสดงได้ในระนาบการวางซ้อนเท่านั้น โปรแกรมเล่นวิดีโอที่รองรับเนื้อหาที่ได้รับการคุ้มครองต้องติดตั้งใช้งานด้วย SurfaceView ซอฟต์แวร์ที่ทำงานบนฮาร์ดแวร์ที่ไม่มีการป้องกันจะอ่านหรือเขียนบัฟเฟอร์ไม่ได้ โดยเส้นทางที่ได้รับการปกป้องจากฮาร์ดแวร์ต้องปรากฏในการวางซ้อนของโปรแกรมแต่งภาพฮาร์ดแวร์ (กล่าวคือ วิดีโอที่ได้รับการปกป้องจะหายไปจากจอแสดงผลหากโปรแกรมแต่งภาพฮาร์ดแวร์เปลี่ยนไปใช้การคอมโพสิชัน OpenGL ES)

ดูรายละเอียดเกี่ยวกับเนื้อหาที่ได้รับการคุ้มครองได้ที่ DRM