Triển khai Trình soạn thảo phần cứng HAL

Các lớp tổng hợp HAL của Trình soạn thảo phần cứng (HWC) nhận được từ SurfaceFlinger, làm giảm lượng thành phần OpenGL ES (GLES) và GPU hoạt động.

HWC trừu tượng hóa các đối tượng, chẳng hạn như lớp phủ và các khối 2D, thành các bề mặt tổng hợp và giao tiếp với phần cứng bố cục cửa sổ chuyên dụng tới các cửa sổ tổng hợp. Sử dụng HWC để kết hợp các cửa sổ thay vì kết hợp SurfaceFlinger với GPU. Hầu hết các GPU không được tối ưu hóa cho thành phần và khi GPU kết hợp các lớp từ SurfaceFlinger, các ứng dụng không thể sử dụng GPU để hiển thị riêng.

Việc triển khai HWC sẽ hỗ trợ:

  • Ít nhất bốn lớp phủ:
    • Thanh trạng thái
    • Thanh hệ thống
    • Ứng dụng
    • Hình nền/nền
  • Các lớp lớn hơn màn hình (ví dụ: hình nền)
  • Trộn alpha trên mỗi pixel và trộn alpha trên mỗi mặt phẳng đồng thời
  • Đường dẫn phần cứng để phát lại video được bảo vệ
  • Thứ tự đóng gói RGBA, định dạng YUV và các thuộc tính xếp lớp, làm mờ và sải bước

Để thực hiện CTNH:

  1. Triển khai HWC không hoạt động và gửi tất cả công việc tổng hợp tới GLES.
  2. Triển khai thuật toán để ủy quyền thành phần cho HWC theo từng bước. Ví dụ: chỉ ủy quyền ba hoặc bốn bề mặt đầu tiên cho phần cứng lớp phủ của HWC.
  3. Tối ưu hóa HWC. Điều này có thể bao gồm:
    • Chọn các bề mặt giúp tối đa hóa tải cho GPU và gửi chúng đến HWC.
    • Phát hiện xem màn hình có đang cập nhật hay không. Nếu không, hãy ủy quyền sáng tác cho GLES thay vì HWC để tiết kiệm năng lượng. Khi màn hình cập nhật lại, hãy tiếp tục tải thành phần xuống HWC.
    • Chuẩn bị cho các trường hợp sử dụng phổ biến như:
      • Màn hình chính, bao gồm thanh trạng thái, thanh hệ thống, cửa sổ ứng dụng và hình nền động
      • Trò chơi toàn màn hình ở chế độ dọc và ngang
      • Video toàn màn hình với phụ đề chi tiết và điều khiển phát lại
      • Phát lại video được bảo vệ
      • Chia màn hình đa cửa sổ

HWC nguyên thủy

HWC cung cấp hai nguyên hàm, lớphiển thị , để thể hiện công việc tổng hợp và sự tương tác của nó với phần cứng hiển thị. HWC cũng cung cấp quyền kiểm soát VSYNC và gọi lại SurfaceFlinger để thông báo cho nó khi xảy ra sự kiện VSYNC.

Giao diện HIDL

Android 8.0 trở lên sử dụng giao diện HIDL có tên Composer HAL cho IPC được liên kết giữa HWC và SurfaceFlinger. Composer HAL thay thế giao diện hwcomposer2.h cũ. Nếu nhà cung cấp cung cấp triển khai Composer HAL cho HWC, Composer HAL trực tiếp chấp nhận lệnh gọi HIDL từ SurfaceFlinger. Nếu nhà cung cấp cung cấp cách triển khai HWC kế thừa, Composer HAL sẽ tải các con trỏ hàm từ hwcomposer2.h , chuyển tiếp lệnh gọi HIDL thành lệnh gọi con trỏ hàm.

HWC cung cấp các chức năng để xác định các thuộc tính của một màn hình nhất định; để chuyển đổi giữa các cấu hình hiển thị khác nhau (chẳng hạn như độ phân giải 4k hoặc 1080p) và các chế độ màu (chẳng hạn như màu gốc hoặc sRGB thực); và bật, tắt màn hình hoặc chuyển sang chế độ tiết kiệm năng lượng nếu được hỗ trợ.

Con trỏ hàm

Nếu các nhà cung cấp triển khai trực tiếp Composer HAL, SurfaceFlinger sẽ gọi các chức năng của nó thông qua HIDL IPC. Ví dụ: để tạo một lớp, SurfaceFlinger gọi createLayer() trên Composer HAL.

Nếu nhà cung cấp triển khai giao diện hwcomposer2.h , Composer HAL sẽ gọi các con trỏ hàm hwcomposer2.h . Trong nhận xét hwcomposer2.h , các hàm giao diện HWC được gọi bằng tên lowCamelCase không tồn tại trong giao diện dưới dạng các trường được đặt tên. Hầu hết mọi hàm đều được tải bằng cách yêu cầu một con trỏ hàm sử dụng getFunction do hwc2_device_t cung cấp. Ví dụ: hàm createLayer là một con trỏ hàm kiểu HWC2_PFN_CREATE_LAYER , được trả về khi giá trị liệt kê HWC2_FUNCTION_CREATE_LAYER được truyền vào getFunction .

Để biết tài liệu chi tiết về các hàm HAL của Composer và các hàm chuyển qua hàm HWC, hãy xem composer . Để biết tài liệu chi tiết về con trỏ hàm HWC, hãy xem hwcomposer2.h .

Xử lý lớp và hiển thị

Các lớp và màn hình được thao tác bằng các tay cầm do HWC tạo ra. Tay cầm mờ đục đối với SurfaceFlinger.

Khi SurfaceFlinger tạo một lớp mới, nó gọi createLayer , trả về loại Layer để triển khai trực tiếp hoặc hwc2_layer_t để triển khai chuyển tiếp. Khi SurfaceFlinger sửa đổi một thuộc tính của lớp đó, SurfaceFlinger chuyển giá trị hwc2_layer_t vào hàm sửa đổi thích hợp cùng với bất kỳ thông tin nào khác cần thiết để thực hiện sửa đổi. Loại hwc2_layer_t đủ lớn để chứa con trỏ hoặc chỉ mục.

Màn hình vật lý được tạo ra bằng cách cắm nóng. Khi màn hình vật lý được cắm nóng, HWC sẽ tạo một tay cầm và chuyển tay cầm đó cho SurfaceFlinger thông qua lệnh gọi lại phích cắm nóng. Màn hình ảo được tạo bởi SurfaceFlinger gọi createVirtualDisplay() để yêu cầu hiển thị. Nếu HWC hỗ trợ thành phần hiển thị ảo, nó sẽ trả về một điều khiển. Sau đó, SurfaceFlinger ủy quyền thành phần của màn hình cho HWC. Nếu HWC không hỗ trợ bố cục màn hình ảo, SurfaceFlinger sẽ tạo tay cầm và kết hợp màn hình.

Hiển thị các thao tác thành phần

Một lần cho mỗi VSYNC, SurfaceFlinger sẽ thức dậy nếu nó có nội dung mới cần tổng hợp. Nội dung mới này có thể là bộ đệm hình ảnh mới từ ứng dụng hoặc thay đổi thuộc tính của một hoặc nhiều lớp. Khi SurfaceFlinger đánh thức nó:

  1. Xử lý các giao dịch, nếu có.
  2. Chốt bộ đệm đồ họa mới, nếu có.
  3. Thực hiện một bố cục mới nếu bước 1 hoặc 2 dẫn đến thay đổi nội dung hiển thị.

Để thực hiện một bố cục mới, SurfaceFlinger tạo và hủy các lớp hoặc sửa đổi trạng thái lớp, nếu có. Nó cũng cập nhật các lớp với nội dung hiện tại của chúng, sử dụng các lệnh gọi như setLayerBuffer hoặc setLayerColor . Sau khi tất cả các lớp được cập nhật, SurfaceFlinger gọi validateDisplay , yêu cầu HWC kiểm tra trạng thái của các lớp và xác định cách thức thành phần sẽ tiến hành. Theo mặc định, SurfaceFlinger cố gắng định cấu hình mọi lớp sao cho lớp đó được HWC tổng hợp; mặc dù trong một số trường hợp, SurfaceFlinger kết hợp các lớp thông qua dự phòng GPU.

Sau lệnh gọi validateDisplay , SurfaceFlinger gọi getChangedCompositionTypes để xem liệu HWC có muốn thay đổi bất kỳ loại thành phần lớp nào trước khi thực hiện thành phần hay không. Để chấp nhận các thay đổi, SurfaceFlinger gọi acceptDisplayChanges .

Nếu bất kỳ lớp nào được đánh dấu cho thành phần SurfaceFlinger, SurfaceFlinger sẽ tổng hợp chúng vào bộ đệm đích. SurfaceFlinger sau đó gọi setClientTarget để cung cấp bộ đệm cho màn hình để bộ đệm có thể được hiển thị trên màn hình hoặc được tổng hợp thêm với các lớp chưa được đánh dấu cho thành phần SurfaceFlinger. Nếu không có lớp nào được đánh dấu cho bố cục SurfaceFlinger, SurfaceFlinger sẽ bỏ qua bước bố cục.

Cuối cùng, SurfaceFlinger gọi presentDisplay để yêu cầu HWC hoàn tất quá trình tổng hợp và hiển thị kết quả cuối cùng.

Nhiều màn hình

Android 10 hỗ trợ nhiều màn hình vật lý. Khi thiết kế triển khai HWC nhằm sử dụng trên Android 7.0 trở lên, có một số hạn chế không có trong định nghĩa HWC:

  • Người ta cho rằng có chính xác một màn hình bên trong . Màn hình bên trong là màn hình mà hotplug ban đầu báo cáo trong quá trình khởi động. Sau khi màn hình bên trong được cắm nóng, nó không thể ngắt kết nối được.
  • Ngoài màn hình bên trong, bất kỳ số lượng màn hình bên ngoài nào cũng có thể bị cắm nóng trong quá trình hoạt động bình thường của thiết bị. Khung này giả định rằng tất cả các phích cắm nóng sau màn hình bên trong đầu tiên đều là màn hình bên ngoài, vì vậy nếu thêm bất kỳ màn hình bên trong nào nữa, chúng sẽ được phân loại không chính xác thành Display.TYPE_HDMI thay vì Display.TYPE_BUILT_IN .

Mặc dù các thao tác SurfaceFlinger được mô tả ở trên được thực hiện trên mỗi màn hình nhưng chúng được thực hiện tuần tự cho tất cả các màn hình đang hoạt động, ngay cả khi nội dung của chỉ một màn hình được cập nhật.

Ví dụ: nếu màn hình ngoài được cập nhật thì trình tự sẽ là:

// 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>)

Thành phần hiển thị ảo

Thành phần hiển thị ảo tương tự như thành phần hiển thị bên ngoài. Sự khác biệt giữa thành phần hiển thị ảo và thành phần hiển thị vật lý là màn hình ảo gửi đầu ra tới bộ đệm Gralloc thay vì tới màn hình. Trình soạn thảo phần cứng (HWC) ghi đầu ra vào bộ đệm, cung cấp hàng rào hoàn thiện và gửi bộ đệm đến người tiêu dùng (chẳng hạn như bộ mã hóa video, GPU, CPU, v.v.). Màn hình ảo có thể sử dụng 2D/blitter hoặc lớp phủ nếu đường dẫn hiển thị ghi vào bộ nhớ.

Chế độ

Mỗi khung hình ở một trong ba chế độ sau khi SurfaceFlinger gọi phương thức validateDisplay() HWC:

  • GLES — GPU tổng hợp tất cả các lớp, ghi trực tiếp vào bộ đệm đầu ra. HWC không tham gia vào việc sáng tác.
  • HỖN HỢP - GPU kết hợp một số lớp vào bộ đệm khung và HWC kết hợp bộ đệm khung và các lớp còn lại, ghi trực tiếp vào bộ đệm đầu ra.
  • HWC - HWC tổng hợp tất cả các lớp và ghi trực tiếp vào bộ đệm đầu ra.

Định dạng đầu ra

Các định dạng đầu ra của bộ đệm hiển thị ảo phụ thuộc vào chế độ của chúng:

  • Chế độ GLES - Trình điều khiển EGL đặt định dạng bộ đệm đầu ra trong dequeueBuffer() , thường là RGBA_8888 . Người tiêu dùng phải có khả năng chấp nhận định dạng đầu ra mà trình điều khiển đặt hoặc bộ đệm không thể đọc được.
  • Chế độ MIXED và HWC - Nếu người tiêu dùng cần quyền truy cập CPU, người tiêu dùng sẽ đặt định dạng. Mặt khác, định dạng là IMPLEMENTATION_DEFINED và Gralloc đặt định dạng tốt nhất dựa trên cờ sử dụng. Ví dụ: Gralloc đặt định dạng YCbCr nếu người tiêu dùng là người mã hóa video và HWC có thể ghi định dạng này một cách hiệu quả.

Hàng rào đồng bộ

Hàng rào đồng bộ hóa (sync) là một khía cạnh quan trọng của hệ thống đồ họa Android. Hàng rào cho phép CPU hoạt động độc lập với hoạt động đồng thời của GPU, chỉ chặn khi có sự phụ thuộc thực sự.

Ví dụ: khi một ứng dụng gửi bộ đệm đang được tạo trên GPU, ứng dụng đó cũng gửi đối tượng hàng rào đồng bộ hóa. Hàng rào này báo hiệu khi GPU ghi xong vào bộ đệm.

HWC yêu cầu GPU hoàn tất việc ghi bộ đệm trước khi bộ đệm được hiển thị. Hàng rào đồng bộ hóa được chuyển qua đường ống đồ họa với bộ đệm và tín hiệu khi bộ đệm được ghi. Trước khi bộ đệm được hiển thị, HWC sẽ kiểm tra xem hàng rào đồng bộ đã có tín hiệu hay chưa và nếu có thì nó sẽ hiển thị bộ đệm.

Để biết thêm thông tin về hàng rào đồng bộ, hãy xem Tích hợp trình soạn thảo phần cứng .