同步處理架構會明確說明 Android 圖形系統中不同非同步作業之間的依附元件。架構 這類 API 可讓元件指出緩衝區釋放時間。架構還 可讓同步處理基元從核心之間傳遞到驅動程式 以及使用者空間程序本身
舉例來說,應用程式可能會將要執行的作業排入 GPU 工作佇列。GPU 會開始繪製該圖片。雖然圖片尚未繪製到記憶體中,但緩衝區指標會連同表示 GPU 工作何時完成的柵欄傳遞至視窗合成器。視窗合成器會提前開始處理作業,並將工作傳遞至顯示控制器。CPU 運作時 就完成了GPU 完成後,顯示控制器會立即顯示圖片。
同步處理架構也能讓實作者 共用硬體元件最後,該架構會提供圖形處理管道的可視性,以利偵錯。
明確同步
明確同步處理可讓圖形緩衝區的製作者和取用者 在停止使用緩衝區時發出信號。明確同步處理為 並在核心空間中實作。
明確同步的優點包括:
- 裝置間的行為差異較小
- 提供更完善的偵錯支援
- 經過改良的測試指標
同步處理架構有三種物件類型:
sync_timeline
sync_pt
sync_fence
sync_timeline
sync_timeline
是單調遞增的時間軸,供應商應為每個驅動程式例項 (例如 GL 內容、顯示控制器或 2D blit 器) 實作此時間軸。次數:sync_timeline
傳送到特定硬體的核心工作。
sync_timeline
可保證作業順序,並啟用硬體專屬的實作項目。
實作 sync_timeline
時,請遵循下列準則:
- 為所有驅動程式、時間表和柵欄提供實用的名稱,以簡化偵錯作業。
- 導入
timeline_value_str
和pt_value_str
時間軸中的運算子,讓輸出的偵錯更容易理解。 - 實作填充
driver_data
,讓使用者空間程式庫 (例如 GL 程式庫) 存取私人時間軸資料 (如有需要)。data_driver
可讓供應商傳遞無法變更的資訊 使用sync_fence
和sync_pts
建構指令列 據此做出調整 - 請勿允許使用者空間明確建立或發出邊界信號。明確 建立信號/圍欄會導致阻斷服務攻擊, 能終止管道的功能
- 請勿存取
sync_timeline
、sync_pt
或sync_fence
元素。這個 API 提供了 函式。
Sync_pt
sync_pt
是 sync_timeline
上的單一值或點。點有三種狀態:有效、已發出信號和錯誤。積分會以有效狀態開始
並轉換成信號或錯誤狀態舉例來說,當圖片使用者不再需要緩衝區時,系統會發出 sync_pt
信號,讓圖片產生者知道可以再次寫入緩衝區。
sync_fence
sync_fence
是一組 sync_pt
值
經常
有不同的 sync_timeline
父項 (例如針對螢幕)
和 GPU)。sync_fence
、sync_pt
和 sync_timeline
是驅動程式和使用者空間用來傳達其依附元件的必要元素。當邊界發出信號時,系統會保證邊界前發出的所有指令都已完成,因為核心驅動程式或硬體區塊會依序執行指令。
同步處理架構可讓多個消費者或生產者在使用緩衝區後傳送信號,藉此透過一個函式參數傳達依附元件資訊。柵欄由檔案描述元支援,並從核心空間傳遞至使用者空間。例如,一個圍欄可以包含兩個
sync_pt
值,用於表示兩張圖片消費者分別完成的操作
讀取緩衝區圍欄發出訊號時,圖片生產者會知道兩者皆是
包括所得體驗
柵欄與 sync_pt
值一樣,會在啟用後根據其點的狀態變更狀態。如果所有 sync_pt
值都變成信號,系統就會判定
sync_fence
已發出訊號。如果一個 sync_pt
下降
變成錯誤狀態,整個 sync_fence
都有錯誤狀態。
建立柵欄後,sync_fence
的成員資格即無法變更。如要在一個圍欄中取得多個資料點,合併作業是
執行時,會將兩個不同圍欄的點新增到第三個圍欄。
如果有其中一個點收到了原圍欄的訊號,另一個定點則沒有。
也不會處於訊號狀態。
如要實作明確的同步處理,請提供下列資訊:
- 實作同步處理架構的核心空間子系統
特定硬體驅動程式的安裝記錄需要支援邊界功能的驅動程式,通常是指任何會存取或與硬體編譯器通訊的驅動程式。主要檔案包括:
- 核心實作:
kernel/common/include/linux/sync.h
kernel/common/drivers/base/sync.c
kernel/common/Documentation/sync.txt
的說明文件- 可與
platform/system/core/libsync
中的核心空間通訊的程式庫
- 核心實作:
- 供應商必須提供適當的同步處理作業
做為
validateDisplay()
和 HAL 中使用presentDisplay()
函式。 - 兩個圍欄相關 GL 擴充功能 (
EGL_ANDROID_native_fence_sync
和EGL_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 時,Fence 物件都會重新命名。
核心圍欄支援可讓 Fences 擁有名稱字串,因此同步處理
架構會使用目前正在排入佇列的視窗名稱和緩衝區索引
圍欄,例如 SurfaceView:0
。這個
有助偵錯在名稱顯示時,找出死結的來源
會列於 /d/sync
和錯誤報告的輸出內容中。
ANativeWindow 整合
ANativeWindow 會偵測圍欄。dequeueBuffer
,
queueBuffer
和 cancelBuffer
具有圍欄參數。
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
擴充功能採用對應的原生圍欄檔案描述元屬性,只能在建立時設定,且無法直接從現有的同步物件查詢。這個屬性可設為下列兩種模式之一:
- 有效的圍欄檔案描述元會包裝現有的原生檔案
EGLSyncKHR
物件中的 Android 圍欄檔案描述元。 - -1 會根據
EGLSyncKHR
物件。
使用 DupNativeFenceFD()
函式呼叫,從原生 Android 圍欄檔案描述元中擷取 EGLSyncKHR
物件。這與查詢 set 屬性所產生的結果相同,但會遵循收件者關閉圍欄的慣例 (因此是重複作業)。最後,銷毀 EGLSyncKHR
物件會關閉內部柵欄屬性。
硬體 Composer 整合
Hardware Composer 會處理三種類型的同步圍欄:
- 取得圍欄會連同輸入緩衝區一併傳遞給
setLayerBuffer
和setClientTarget
呼叫。 這些代表緩衝區的待寫入資料,必須在 SurfaceFlinger 或 HWC 嘗試從相關聯的緩衝區讀取資料以執行合成作業之前,先發出信號。 - 使用
getReleaseFences
呼叫對presentDisplay
的呼叫後,系統會擷取釋放柵欄。這些代表來自相同圖層上前一個緩衝區的待處理讀取。當 HWC 不再使用先前的緩衝區,因為目前的緩衝區已取代顯示器上的先前緩衝區,此時會發出釋放柵欄信號。釋放柵欄會連同先前的緩衝區傳回應用程式,這些緩衝區會在目前的組合期間替換。應用程式必須等待 先釋放柵欄信號,再將新內容寫入緩衝區 傳回的訊息。 - 系統會在呼叫
presentDisplay
時傳回Present 柵欄,每個影格一個。圍欄 是指 這個影格完成 或 相反地 不再需要前一個影格的組合結果。實體適用 螢幕,presentDisplay
會在 螢幕上就會顯示目前的畫面當現況柵欄傳回後,如果適用,您可以放心再次寫入 SurfaceFlinger 目標緩衝區。對於虛擬螢幕,當從輸出緩衝區讀取資料時,系統會傳回目前的邊界。