同步框架

同步框架明確描述了 Android 圖形系統中不同異步操作之間的依賴關係。該框架提供了一個 API,使組件能夠指示何時釋放緩衝區。該框架還允許在從內核到用戶空間的驅動程序之間以及在用戶空間進程本身之間傳遞同步原語。

例如,應用程序可能會將要在 GPU 中執行的工作排隊。 GPU 開始繪製該圖像。雖然圖像還沒有被繪製到內存中,但是緩衝區指針與指示 GPU 工作何時完成的柵欄一起傳遞給窗口合成器。窗口合成器提前開始處理並將工作傳遞給顯示控制器。以類似的方式,CPU 工作提前完成。 GPU完成後,顯示控制器立即顯示圖像。

同步框架還允許實施者在他們自己的硬件組件中利用同步資源。最後,該框架提供了圖形管道的可見性以幫助調試。

顯式同步

顯式同步使圖形緩衝區的生產者和消費者能夠在他們完成使用緩衝區時發出信號。顯式同步是在內核空間中實現的。

顯式同步的好處包括:

  • 設備之間的行為差異較小
  • 更好的調試支持
  • 改進的測試指標

同步框架具有三種對像類型:

  • sync_timeline
  • sync_pt
  • sync_fence

同步時間線

sync_timeline是廠商應該執行用於每個驅動程序實例,諸如GL上下文,顯示控制器,或2D阻擊器單調增加的時間線。 sync_timeline計數作業提交到內核特定的硬件。 sync_timeline提供關於操作的順序,擔保,使硬件的具體實現。

實施時請遵循這些準則sync_timeline

  • 為所有驅動程序、時間線和柵欄提供有用的名稱以簡化調試。
  • 實施timeline_value_strpt_value_str在時間表運營商能夠調試輸出可讀性更強。
  • 落實填充driver_data給用戶空間庫,如GL庫,進入私人時間表數據,如果需要的話。 data_driver允許供應商傳遞有關的不可變信息sync_fencesync_pts至基於它們生成的命令行。
  • 不允許用戶空間顯式創建或發出圍欄信號。顯式創建信號/圍欄會導致停止管道功能的拒絕服務攻擊。
  • 請勿訪問sync_timelinesync_pt ,或sync_fence要素作了明確規定。 API 提供了所有必需的功能。

同步點

sync_pt是在一個單一的值或點sync_timeline 。一個點具有三種狀態:活動狀態、信號狀態和錯誤狀態。點從活動狀態開始並轉換到信號狀態或錯誤狀態。例如,當圖像消費者不再需要一個緩衝,一個sync_pt發出信號使圖像製片人都知道它的好再次寫入緩衝區。

同步柵欄

sync_fence是集合sync_pt經常具有不同的值sync_timeline父母(諸如用於在顯示控制器和GPU)。 sync_fencesync_ptsync_timeline是主要的原語,司機和用戶空間的使用來傳達他們的依賴。當柵欄發出信號時,在柵欄之前發出的所有命令都保證是完整的,因為內核驅動程序或硬件塊按順序執行命令。

同步框架允許多個消費者或生產者在他們完成使用緩衝區時發出信號,用一個函數參數傳達依賴信息。柵欄由文件描述符支持,並從內核空間傳遞到用戶空間。例如,柵欄可以包含兩個sync_pt當兩個分開的圖像消費者讀完的緩衝區表示的值。當柵欄發出信號時,圖像生產者知道兩個消費者都完成了消費。

柵欄,像sync_pt值的基礎上,他們點的狀態開始積極改變狀態。如果所有sync_pt值成為信號,該sync_fence變成信號。如果一個sync_pt陷入錯誤狀態,整個sync_fence有錯誤狀態。

會員在sync_fence創建柵欄後是不可改變的。為了在圍欄中獲得多個點,進行合併,將來自兩個不同圍欄的點添加到第三個圍欄。如果這些點之一在始發圍欄中發出信號而另一個沒有,則第三圍欄也不會處於信號狀態。

要實現顯式同步,請提供以下內容:

  • 為特定硬件驅動程序實現同步框架的內核空間子系統。需要識別柵欄的驅動程序通常是訪問 Hardware Composer 或與 Hardware Composer 通信的任何東西。關鍵文件包括:
    • 核心實現:
      • kernel/common/include/linux/sync.h
      • kernel/common/drivers/base/sync.c
    • 在文件kernel/common/Documentation/sync.txt
    • 圖書館在內核空間通信platform/system/core/libsync
  • 供應商必須提供適當的同步柵欄作為參數傳遞給validateDisplay()presentDisplay()在HAL功能。
  • 兩個柵欄相關的GL擴展( EGL_ANDROID_native_fence_syncEGL_ANDROID_wait_sync )和顯卡驅動籬笆支撐。

案例研究:實現顯示驅動程序

要使用支持同步功能的 API,請開發具有顯示緩衝功能的顯示驅動程序。同步框架出現之前,這個功能將收到dma-buf對象,把那些緩衝區顯示屏上,塊,而緩存是可見的。例如:

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

與同步框架中, display_buffer功能更複雜。在顯示緩衝區時,緩衝區與指示緩衝區何時準備就緒的圍欄相關聯。您可以在圍欄清除後排隊並開始工作。

在圍欄清除後排隊和開始工作不會阻止任何事情。您立即返回自己的圍欄,這保證了緩衝區何時會離開顯示器。當您排隊緩衝區時,內核會列出與同步框架的依賴關係:

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

同步集成

本節介紹如何將內核空間同步框架與 Android 框架的用戶空間部分以及必須相互通信的驅動程序集成。內核空間對像在用戶空間中表示為文件描述符。

集成約定

遵循 Android HAL 接口約定:

  • 如果API提供了指文件描述符sync_pt ,供應商的驅動程序或使用API的HAL必須關閉文件描述符。
  • 如果供應商驅動程序或HAL通過包含一個文件描述符sync_pt一個API函數,供應商的驅動程序或HAL不得關閉文件描述符。
  • 要繼續使用隔離文件描述符,供應商驅動程序或 HAL 必須複製描述符。

柵欄對象每次通過 BufferQueue 時都會被重命名。內核柵欄支持允許圍欄有名稱的字符串,所以同步框架使用的窗口名稱和緩衝區多數民眾贊成排隊命名柵欄,如指數SurfaceView:0 。這是在調試,以確定死鎖的來源十分有幫助的名字出現在輸出/d/sync和錯誤報告。

ANativeWindow 集成

ANativeWindow 是圍欄感知的。 dequeueBufferqueueBuffercancelBuffer有圍欄的參數。

OpenGL ES 集成

OpenGL ES 同步集成依賴於兩個 EGL 擴展:

  • EGL_ANDROID_native_fence_sync提供了一種包裝或者製作在原生Android圍欄文件描述符EGLSyncKHR對象。
  • EGL_ANDROID_wait_sync允許GPU-側檔,而不是CPU方面,使得GPU等待EGLSyncKHR 。該EGL_ANDROID_wait_sync擴展名是一樣的EGL_KHR_wait_sync擴展。

可以單獨使用這些擴展,實現EGL_ANDROID_native_fence_sync與相關的內核支持一起擴展。接下來,使EGL_ANDROID_wait_sync在驅動程序擴展。所述EGL_ANDROID_native_fence_sync擴展包括一個獨特的天然柵欄EGLSyncKHR對象類型。其結果是,適用於現有的擴展EGLSyncKHR對象類型不一定適用於EGL_ANDROID_native_fence對象,避免了不必要的互動。

所述EGL_ANDROID_native_fence_sync擴展採用只能在創建時被設置,並且不能直接從現有的同步對象向前查詢對應的天然圍欄文件描述符屬性。此屬性可以設置為以下兩種模式之一:

  • 一個有效的柵欄文件描述符包裝在一個現有的原生Android圍欄文件描述符EGLSyncKHR對象。
  • -1創建從一個原生的Android圍欄文件描述符EGLSyncKHR對象。

使用DupNativeFenceFD()函數調用來提取EGLSyncKHR從原生的Android圍欄文件描述符對象。這與查詢 set 屬性的結果相同,但遵守接收者關閉圍欄的約定(因此重複操作)。最後,破壞EGLSyncKHR對象關閉內部圍欄屬性。

硬件作曲家集成

Hardware Composer 處理三種類型的同步柵欄:

  • 採集圍欄與輸入緩衝器到一起傳遞setLayerBuffersetClientTarget電話。這些表示對緩衝區的掛起寫入,並且必須在 SurfaceFlinger 或 HWC 嘗試從關聯緩衝區讀取以執行組合之前發出信號。
  • 發布圍欄調用後檢索presentDisplay使用getReleaseFences通話。這些表示來自同一層上的前一個緩衝區的未決讀取。當 HWC 不再使用前一個緩衝區時,釋放柵欄發出信號,因為當前緩衝區已替換了顯示器上的前一個緩衝區。釋放柵欄與將在當前組合期間替換的先前緩衝區一起傳遞回應用程序。在將新內容寫入返回給它們的緩衝區之前,應用程序必須等到釋放柵欄發出信號。
  • 本柵欄被返回,每幀的一個,作為呼叫到的一部分presentDisplay 。當前柵欄表示該幀的合成何時完成,或者當不再需要前一幀的合成結果時。對於物理顯示器, presentDisplay當當前幀中的屏幕上顯示返回本圍欄。返回當前圍欄後,再次寫入 SurfaceFlinger 目標緩衝區是安全的(如果適用)。對於虛擬顯示器,當可以安全地從輸出緩衝區讀取時,會返回當前圍欄。