Triển khai HAL của Trình soạn nhạc phần cứng

Các lớp tổng hợp HAL Phần cứng (HWC) nhận được từ SurfaceFlinger, giảm lượng thành phần kết hợp OpenGL ES (GLES) và GPU thực hiện.

HWC tóm tắt các đối tượng, chẳng hạn như lớp phủ và bóng 2D thành thành phần tổng hợp bề mặt và giao tiếp bằng phần cứng bố cục cửa sổ chuyên dụng để cửa sổ tổng hợp. Sử dụng HWC cho các cửa sổ tổng hợp thay vì phải Kết hợp SurfaceFlinger với GPU. Hầu hết GPU không được tối ưu hoá cho việc kết hợp 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 để kết xuất riêng.

Quá trình triển khai HWC cần hỗ trợ:

  • Ít nhất 4 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)
  • Phối alpha đồng thời nhân trước trên mỗi pixel và trên mỗi mặt phẳng trộn alpha
  • Đường dẫn phần cứng để phát video được bảo vệ
  • Thứ tự đóng gói RGBA, định dạng YUV và các thuộc tính xếp kề, xáo trộn và bước

Cách triển khai HWC:

  1. Triển khai một HWC không hoạt động và gửi tất cả công việc kết hợp đến GLES.
  2. Triển khai một thuật toán để uỷ quyền thành phần kết hợp cho HWC theo cách tăng dần. Ví dụ: chỉ uỷ quyền 3 hoặc 4 nền tảng đầu tiên cho lớp phủ phần cứng của HWC.
  3. Tối ưu hoá HWC. Những nội dung này có thể bao gồm:
    • Chọn các bề mặt có thể tăng tối đa tải trọng lượng giảm đi từ 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 uỷ quyền cho thành phần hiển thị với GLES thay vì HWC để tiết kiệm pin. Khi màn hình cập nhật lại, hãy tiếp tục chuyển tải thành phần kết hợp sang 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, ứng dụng cửa sổ và hình nền động
      • Trò chơi chạy ở chế độ toàn màn hình theo hướng dọc và ngang
      • Video ở chế độ toàn màn hình có phụ đề và chế độ điều khiển phát
      • Phát video được bảo vệ
      • Chế độ nhiều cửa sổ chia đôi màn hình

Dữ liệu gốc HWC

HWC cung cấp hai lớp gốc là lớpmàn hình để biểu thị công việc kết hợp và hoạt động tương tác của công việc đó với phần cứng hiển thị. Chiến lược phát hành đĩa đơn HWC cũng cung cấp chức năng kiểm soát VSYNC và lệnh gọi lại đến SurfaceFlinger để thông báo khi sự kiện VSYNC xảy ra.

Giao diện HIDL

Android 8.0 trở lên sử dụng Giao diện HIDL có tên là Composer HAL (Lớp trừu tượng phần cứng) cho IPC liên kết giữa HWC và SurfaceFlinger. HAL của Compose thay thế giao diện hwcomposer2.h cũ. Nếu nhà cung cấp cung cấp HAL (Lớp trừu tượng phần cứng) cho nhà soạn thảo triển khai HWC, HAL của Trình soạn thảo trực tiếp chấp nhận các lệnh gọi HIDL từ SurfaceFlinger. Nếu nhà cung cấp cung cấp phương thức triển khai cũ của HWC, Composer HAL sẽ tải con trỏ hàm từ hwcomposer2.h, chuyển tiếp các lệnh gọi HIDL vào lệnh gọi con trỏ hàm.

HWC cung cấp các hàm để xác định 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 màn hình khác nhau (chẳng hạn như độ phân giải 4k hoặc 1080p) và chế độ màu (chẳng hạn như màu gốc hoặc sRGB thực); và để bật, tắt hoặc chuyển màn hình sang chế độ tiết kiệm pin nếu được hỗ trợ.

Con trỏ hàm

Nếu nhà cung cấp trực tiếp triển khai HAL (Lớp trừu tượng phần cứng) cho Composer, SurfaceFlinger sẽ gọi các hàm tương ứng thông qua HIDL IPC. Ví dụ: để tạo một lớp, SurfaceFlinger gọi createLayer() trên HAL (Lớp trừu tượng phần cứng) cho Composer.

Nếu nhà cung cấp triển khai giao diện hwcomposer2.h, thì Composer HAL sẽ gọi vào con trỏ hàm hwcomposer2.h. Trong hwcomposer2.h nhận xét, Các hàm của giao diện HWC tham chiếu bằng các tên lowerCamelCase 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 con trỏ hàm bằng getFunction do hwc2_device_t cung cấp. Ví dụ: hàm createLayer là con trỏ hàm thuộc loại HWC2_PFN_CREATE_LAYER, được trả về khi giá trị được 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 trình soạn thảo và truyề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.

Tay cầm lớp và màn hình

Các lớp và màn hình được thao tác bằng các tên người dùng do HWC tạo. Các ô điều khiển được làm mờ so với SurfaceFlinger.

Khi tạo một lớp mới, SurfaceFlinger sẽ gọi createLayer. Lớp này sẽ 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 sẽ truyền giá trị hwc2_layer_t vào hàm sửa đổi thích hợp cùng với mọi thông tin 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 thực được tạo bằng cách cắm nóng. Khi màn hình thực được cắm nóng, HWC sẽ tạo một tay điều khiển và truyền tay điều khiển đó đến SurfaceFlinger thông qua lệnh gọi lại hotplug. Màn hình ảo do SurfaceFlinger tạo ra đang gọi createVirtualDisplay() để yêu cầu một màn hình. Nếu HWC hỗ trợ thành phần hiển thị ảo, thì thành phần này sẽ trả về một handle. Sau đó, SurfaceFlinger sẽ uỷ quyền thành phần của màn hình cho HWC. Nếu HWC không hỗ trợ cấu trúc hiển thị, SurfaceFlinger sẽ tạo tay cầm và kết hợp màn hình.

Hiển thị các thao tác kết hợp

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

  1. Xử lý giao dịch, nếu có.
  2. Khoá các bộ đệm đồ hoạ mới nếu có.
  3. Thực hiện quá trình kết hợp mới, nếu bước 1 hoặc 2 dẫn đến sự thay đổi vào nội dung hiển thị.

Để thực hiện cấu trúc mới, SurfaceFlinger sẽ tạo và huỷ các lớp hoặc sửa đổi trạng thái của lớp, nếu có. Ứng dụng này cũng cập nhật 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ập nhật, SurfaceFlinger sẽ gọi validateDisplay để cho biết HWC để kiểm tra trạng thái của các lớp và xác định cách thành phần tiếp tục. Theo mặc định, SurfaceFlinger cố gắng định cấu hình mọi lớp sao cho lớp được kết hợp bởi HWC; mặc dù trong một số trường hợp, SurfaceFlinger kết hợp các lớp thông qua phương thức dự phòng GPU.

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

Nếu có lớp nào được đánh dấu cho thành phần SurfaceFlinger, thì SurfaceFlinger sẽ kết hợp các lớp đó vào vùng đệm mục tiêu. Sau đó, SurfaceFlinger gọi setClientTarget để cung cấp vùng đệm cho màn hình để vùng đệm có thể hiển thị trên màn hình hoặc kết 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 thành phần SurfaceFlinger, thì SurfaceFlinger sẽ bỏ qua bước kết hợp.

Cuối cùng, SurfaceFlinger gọi presentDisplay để cho biết HWC để hoàn tất quá trình kết 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 thực. Khi thiết kế cách triển khai HWC để 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:

  • Giả định rằng có đúng một màn hình nội bộ. Dữ liệu nội bộ là màn hình mà các báo cáo nóng ban đầu trong khởi động. Sau khi màn hình nội bộ được cắm nóng, màn hình sẽ không thể bị ngắt kết nối.
  • Ngoài màn hình trong, bạn có thể cắm nóng bất kỳ số lượng màn hình ngoài nào 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ả phích cắm nóng sau màn hình nội bộ đầu tiên là màn hình bên ngoài, vì vậy, nếu có nếu thêm màn hình nội bộ, chúng sẽ bị phân loại không chính xác là 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 cho mỗi màn hình, nhưng các thao tác này được thực hiện tuần tự cho tất 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, 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>)

Cấu trúc màn hình ảo

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

Chế độ

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

  • 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 liên quan đến thành phần hiển thị.
  • MIXED – GPU kết hợp một số lớp với vùng đệm khung và HWC kết hợp vùng đệm khung và các lớp còn lại, ghi trực tiếp vào bộ đệm đầu ra.
  • HWC – HWC kết hợp tất cả các lớp và ghi trực tiếp vào vùng đệm đầu ra.

Định dạng đầu ra

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

  • Chế độ GLES – Trình điều khiển EGL thiết lập vùng đệm đầu ra ở dequeueBuffer(), thường là RGBA_8888. Người tiêu dùng phải chấp nhận định dạng đầu ra do 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 CPU quyền truy cập, người tiêu dùng đặt định dạng. Nếu không, định dạng sẽ 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 bộ mã hoá video và HWC có thể ghi định dạng hiệu quả.

Hàng rào đồng bộ hoá

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

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

HWC yêu cầu GPU ghi xong vùng đệm trước khi vùng đệm được được hiển thị. Hàng rào đồng bộ hoá được truyền qua quy trình đồ hoạ bằng các vùng đệm và tín hiệu khi ghi vùng đệm. Trước khi hiển thị một vùng đệm, HWC kiểm tra xem hàng rào đồng bộ hoá đã được báo hiệu chưa và nếu có, hàng rào đồng bộ hoá sẽ hiển thị vùng đệm.

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