Khung đồng bộ hoá

Khung đồng bộ hoá mô tả rõ ràng các phần phụ thuộc giữa các thao tác không đồng bộ khác nhau trong hệ thống đồ hoạ Android. Khung này cung cấp một API cho phép các thành phần cho biết thời điểm phát hành vùng đệm. Khung này cũng cho phép truyền dữ liệu đồng bộ hoá nguyên gốc giữa các trình điều khiển từ nhân đến không gian người dùng và giữa các quy trình của không gian người dùng.

Ví dụ: một ứng dụng có thể thêm công việc vào hàng đợi để thực hiện trong GPU. GPU bắt đầu vẽ hình ảnh đó. Mặc dù hình ảnh chưa được vẽ vào bộ nhớ, nhưng con trỏ vùng đệm sẽ được truyền đến trình kết hợp cửa sổ cùng với một hàng rào cho biết thời điểm công việc của GPU sẽ kết thúc. Trình kết hợp cửa sổ bắt đầu xử lý trước và chuyển công việc đến bộ điều khiển hiển thị. Tương tự, công việc của CPU được thực hiện trước. Sau khi GPU hoàn tất, bộ điều khiển hiển thị sẽ hiển thị hình ảnh ngay lập tức.

Khung đồng bộ hoá cũng cho phép người triển khai tận dụng các tài nguyên đồng bộ hoá trong các thành phần phần cứng của riêng họ. Cuối cùng, khung này cung cấp thông tin về quy trình đồ hoạ để giúp gỡ lỗi.

Đồng bộ hoá rõ ràng

Tính năng đồng bộ hoá rõ ràng cho phép nhà sản xuất và người dùng vùng đệm đồ hoạ báo hiệu khi họ đã sử dụng xong vùng đệm. Quá trình đồng bộ hoá rõ ràng được triển khai trong không gian hạt nhân.

Sau đây là một số lợi ích của tính năng đồng bộ hoá rõ ràng:

  • Ít sự khác biệt về hành vi giữa các thiết bị
  • Hỗ trợ gỡ lỗi hiệu quả hơn
  • Cải thiện chỉ số kiểm thử

Khung đồng bộ hoá có 3 loại đối tượng:

  • sync_timeline
  • sync_pt
  • sync_fence

sync_timeline

sync_timeline là dòng thời gian tăng dần mà nhà cung cấp nên triển khai cho từng thực thể trình điều khiển, chẳng hạn như bối cảnh GL, bộ điều khiển màn hình hoặc công cụ 2D. sync_timeline đếm số lượng công việc được gửi đến hạt nhân cho một phần cứng cụ thể. sync_timeline đảm bảo thứ tự các thao tác và cho phép triển khai theo phần cứng cụ thể.

Hãy tuân theo các nguyên tắc sau đây khi triển khai sync_timeline:

  • Cung cấp tên hữu ích cho tất cả trình điều khiển, dòng thời gian và hàng rào để đơn giản hoá việc gỡ lỗi.
  • Triển khai các toán tử timeline_value_strpt_value_str trong tiến trình để giúp kết quả gỡ lỗi dễ đọc hơn.
  • Triển khai driver_data điền để cấp cho các thư viện không gian người dùng, chẳng hạn như thư viện GL, quyền truy cập vào dữ liệu dòng thời gian riêng tư, nếu muốn. data_driver cho phép các nhà cung cấp truyền thông tin về sync_fencesync_pts không thể thay đổi để tạo các dòng lệnh dựa trên các giá trị này.
  • Không cho phép không gian người dùng tạo hoặc báo hiệu rõ ràng cho hàng rào. Việc tạo tín hiệu/hàng rào một cách rõ ràng sẽ dẫn đến một cuộc tấn công từ chối dịch vụ, khiến chức năng của quy trình bị tạm dừng.
  • Không truy cập rõ ràng vào các phần tử sync_timeline, sync_pt hoặc sync_fence. API cung cấp tất cả các hàm bắt buộc.

sync_pt

sync_pt là một giá trị hoặc điểm duy nhất trên sync_timeline. Một điểm có ba trạng thái: đang hoạt động, đã báo hiệu và lỗi. Điểm bắt đầu ở trạng thái đang hoạt động và chuyển sang trạng thái báo hiệu hoặc lỗi. Ví dụ: khi một trình dùng hình ảnh không còn cần vùng đệm, sync_pt sẽ được báo hiệu để trình tạo hình ảnh biết rằng có thể ghi lại vào vùng đệm.

hàng_bào_đồng_bộ

sync_fence là một tập hợp các giá trị sync_pt thường có nhiều thành phần mẹ sync_timeline (chẳng hạn như cho bộ điều khiển hiển thị và GPU). sync_fence, sync_ptsync_timeline là các nguyên hàm chính mà trình điều khiển và không gian người dùng sử dụng để giao tiếp các phần phụ thuộc của chúng. Khi một hàng rào được báo hiệu, tất cả các lệnh được đưa ra trước hàng rào đều được đảm bảo là hoàn tất vì trình điều khiển hạt nhân hoặc khối phần cứng thực thi các lệnh theo thứ tự.

Khung đồng bộ hoá cho phép nhiều thực thể tiêu thụ hoặc thực thể tạo tín hiệu khi hoàn tất việc sử dụng vùng đệm, thông báo thông tin phần phụ thuộc bằng một tham số hàm. Hàng rào được hỗ trợ bởi chỉ số mô tả tệp và được truyền từ không gian hạt nhân sang không gian người dùng. Ví dụ: một hàng rào có thể chứa hai giá trị sync_pt cho biết thời điểm hai trình sử dụng hình ảnh riêng biệt đã đọc xong vùng đệm. Khi hàng rào được báo hiệu, trình tạo hình ảnh sẽ biết rằng cả hai trình tiêu thụ đều đã tiêu thụ xong.

Hàng rào, chẳng hạn như giá trị sync_pt, bắt đầu hoạt động và thay đổi trạng thái dựa trên trạng thái của các điểm. Nếu tất cả giá trị sync_pt đều được báo hiệu, thì sync_fence sẽ được báo hiệu. Nếu một sync_pt rơi vào trạng thái lỗi, thì toàn bộ sync_fence sẽ có trạng thái lỗi.

Thành viên trong sync_fence là không thể thay đổi sau khi hàng rào được tạo. Để có nhiều điểm trong một hàng rào, quá trình hợp nhất sẽ được tiến hành, trong đó các điểm từ 2 hàng rào riêng biệt sẽ được thêm vào hàng rào thứ ba. Nếu một trong các điểm đó được báo hiệu trong hàng rào ban đầu và điểm còn lại không được báo hiệu, thì hàng rào thứ ba cũng sẽ không ở trạng thái được báo hiệu.

Để triển khai tính năng đồng bộ hoá rõ ràng, hãy cung cấp những thông tin sau:

  • Một hệ thống con trong không gian nhân triển khai khung đồng bộ hoá cho một trình điều khiển phần cứng cụ thể. Trình điều khiển cần nhận biết hàng rào thường là mọi thứ truy cập hoặc giao tiếp với Trình tổng hợp phần cứng. Các tệp chính bao gồm:
    • Triển khai phần cốt lõi:
      • kernel/common/include/linux/sync.h
      • kernel/common/drivers/base/sync.c
    • Tài liệu tại kernel/common/Documentation/sync.txt
    • Thư viện để giao tiếp với không gian hạt nhân trong platform/system/core/libsync
  • Nhà cung cấp phải cung cấp các hàng rào đồng bộ hoá thích hợp dưới dạng tham số cho các hàm validateDisplay()presentDisplay() trong HAL.
  • Hai tiện ích GL liên quan đến hàng rào (EGL_ANDROID_native_fence_syncEGL_ANDROID_wait_sync) và hỗ trợ hàng rào trong trình điều khiển đồ hoạ.

Nghiên cứu điển hình: Triển khai trình điều khiển màn hình

Để sử dụng API hỗ trợ chức năng đồng bộ hoá, hãy phát triển trình điều khiển màn hình có chức năng vùng đệm hiển thị. Trước khi có khung đồng bộ hoá, hàm này sẽ nhận các đối tượng dma-buf, đặt các vùng đệm đó trên màn hình và chặn trong khi vùng đệm hiển thị. Ví dụ:

/*
 * assumes buffer is ready to be displayed.  returns when buffer is no longer on
 * screen.
 */
void display_buffer(struct dma_buf *buffer);

Với khung đồng bộ hoá, hàm display_buffer sẽ phức tạp hơn. Khi hiển thị một bộ đệm, bộ đệm đó sẽ được liên kết với một hàng rào cho biết thời điểm bộ đệm sẽ sẵn sàng. Bạn có thể xếp hàng và bắt đầu công việc sau khi hàng rào dọn dẹp.

Việc xếp hàng đợi và bắt đầu công việc sau khi hàng rào được xoá sẽ không chặn bất kỳ nội dung nào. Bạn sẽ ngay lập tức trả về hàng rào của riêng mình, đảm bảo thời điểm vùng đệm sẽ tắt màn hình. Khi bạn đưa các vùng đệm vào hàng đợi, nhân sẽ liệt kê các phần phụ thuộc với khung đồng bộ hoá:

/*
 * displays buffer when fence is signaled.  returns immediately with a fence
 * that signals when buffer is no longer displayed.
 */
struct sync_fence* display_buffer(struct dma_buf *buffer, struct sync_fence
*fence);

Tích hợp tính năng đồng bộ hoá

Phần này giải thích cách tích hợp khung đồng bộ hoá không gian hạt nhân với các phần không gian người dùng của khung Android và các trình điều khiển phải giao tiếp với nhau. Các đối tượng không gian hạt nhân được biểu thị dưới dạng chỉ số mô tả tệp trong không gian người dùng.

Quy ước tích hợp

Tuân thủ các quy ước giao diện HAL (Lớp trừu tượng phần cứng) cho Android:

  • Nếu API cung cấp chỉ số mô tả tệp tham chiếu đến sync_pt, thì trình điều khiển của nhà cung cấp hoặc HAL (Lớp trừu tượng phần cứng) sử dụng API phải đóng chỉ số mô tả tệp.
  • Nếu trình điều khiển của nhà cung cấp hoặc HAL truyền một chỉ số mô tả tệp chứa sync_pt đến một hàm API, thì trình điều khiển của nhà cung cấp hoặc HAL không được đóng chỉ số mô tả tệp.
  • Để tiếp tục sử dụng chỉ số mô tả tệp hàng rào, trình điều khiển của nhà cung cấp hoặc HAL phải sao chép chỉ số mô tả đó.

Đối tượng hàng rào được đổi tên mỗi khi đối tượng đó đi qua BufferQueue. Tính năng hỗ trợ hàng rào hạt nhân cho phép hàng rào có chuỗi tên, vì vậy, khung đồng bộ hoá sử dụng tên cửa sổ và chỉ mục vùng đệm đang được đưa vào hàng đợi để đặt tên cho hàng rào, chẳng hạn như SurfaceView:0. Điều này rất hữu ích trong việc gỡ lỗi để xác định nguồn gốc của tắc nghẽn vì tên xuất hiện trong dữ liệu đầu ra của /d/sync và báo cáo lỗi.

Tích hợp ANativeWindow

ANativeWindow nhận biết được hàng rào. dequeueBuffer, queueBuffercancelBuffer có các tham số hàng rào.

Tích hợp OpenGL ES

Tính năng tích hợp đồng bộ hoá OpenGL ES dựa vào hai tiện ích EGL:

  • EGL_ANDROID_native_fence_sync cung cấp một cách gói hoặc tạo chỉ số mô tả tệp hàng rào Android gốc trong các đối tượng EGLSyncKHR.
  • EGL_ANDROID_wait_sync cho phép GPU bị tắc nghẽn thay vì CPU, khiến GPU chờ EGLSyncKHR. Phần mở rộng EGL_ANDROID_wait_sync giống với phần mở rộng EGL_KHR_wait_sync.

Để sử dụng các tiện ích này một cách độc lập, hãy triển khai tiện ích EGL_ANDROID_native_fence_sync cùng với tính năng hỗ trợ hạt nhân liên quan. Tiếp theo, hãy bật tiện ích EGL_ANDROID_wait_sync trong trình điều khiển. Tiện ích EGL_ANDROID_native_fence_sync bao gồm một loại đối tượng hàng rào gốc EGLSyncKHR riêng biệt. Do đó, các tiện ích áp dụng cho các loại đối tượng EGLSyncKHR hiện có không nhất thiết áp dụng cho các đối tượng EGL_ANDROID_native_fence, tránh các hoạt động tương tác không mong muốn.

Tiện ích EGL_ANDROID_native_fence_sync sử dụng thuộc tính chỉ số mô tả tệp hàng rào gốc tương ứng mà bạn chỉ có thể đặt tại thời điểm tạo và không thể truy vấn trực tiếp từ một đối tượng đồng bộ hoá hiện có. Bạn có thể đặt thuộc tính này thành một trong 2 chế độ:

  • Phần mô tả tệp hàng rào hợp lệ sẽ bao bọc chỉ số mô tả tệp hàng rào Android gốc hiện có trong một đối tượng EGLSyncKHR.
  • -1 tạo chỉ số mô tả tệp hàng rào gốc của Android từ đối tượng EGLSyncKHR.

Sử dụng lệnh gọi hàm DupNativeFenceFD() để trích xuất đối tượng EGLSyncKHR từ chỉ số mô tả tệp hàng rào gốc của Android. Cách này có kết quả tương tự như truy vấn thuộc tính đã đặt, nhưng tuân thủ quy ước là người nhận đóng hàng rào (do đó là thao tác trùng lặp). Cuối cùng, việc huỷ đối tượng EGLSyncKHR sẽ đóng thuộc tính hàng rào bên trong.

Tích hợp Hardware Composer

Trình tổng hợp phần cứng xử lý ba loại hàng rào đồng bộ hoá:

  • Có hàng rào được truyền cùng với vùng đệm đầu vào đến các lệnh gọi setLayerBuffersetClientTarget. Các đối tượng này đại diện cho một lệnh ghi đang chờ xử lý vào vùng đệm và phải báo hiệu trước khi SurfaceFlinger hoặc HWC cố gắng đọc từ vùng đệm liên kết để thực hiện quá trình kết hợp.
  • Release fence (Vùng phát hành) được truy xuất sau lệnh gọi đến presentDisplay bằng lệnh gọi getReleaseFences. Các đối tượng này đại diện cho hoạt động đọc đang chờ xử lý từ vùng đệm trước trên cùng một lớp. Hàng rào giải phóng báo hiệu khi HWC không còn sử dụng bộ đệm trước đó nữa vì bộ đệm hiện tại đã thay thế bộ đệm trước đó trên màn hình. Hàng rào phát hành được chuyển lại cho ứng dụng cùng với các vùng đệm trước đó sẽ được thay thế trong quá trình kết hợp hiện tại. Ứng dụng phải đợi cho đến khi phát hiện tín hiệu hàng rào phát hành trước khi ghi nội dung mới vào vùng đệm được trả về cho chúng.
  • Hàng rào trình bày được trả về, một hàng rào cho mỗi khung hình, như một phần của lệnh gọi đến presentDisplay. Hàng rào hiện tại thể hiện thời điểm kết hợp của khung này đã hoàn tất hoặc khi kết quả kết hợp của khung trước đó không còn cần thiết nữa. Đối với màn hình thực, presentDisplay trả về hàng rào hiện tại khi khung hình hiện tại xuất hiện trên màn hình. Sau khi các hàng rào hiện tại được trả về, bạn có thể an toàn ghi vào vùng đệm mục tiêu SurfaceFlinger nếu có. Đối với màn hình ảo, hàng rào hiện tại sẽ được trả về khi an toàn để đọc từ vùng đệm đầu ra.