硬體編寫器 (HWC) HAL 會將從 SurfaceFlinger 收到的圖層進行合成,進而減少 OpenGL ES (GLES) 和 GPU 執行的合成作業量。
HWC 會將重疊和 2D blit 等物件抽象化,以便合成介面,並與專門的視窗合成硬體通訊,以便合成視窗。使用 HWC 建立複合式視窗,而不是 採用 GPU 的 SurfaceFlinger 複合材質。大多數 GPU 並未針對合成進行最佳化,當 GPU 合成 SurfaceFlinger 的圖層時,應用程式無法使用 GPU 進行轉譯。
HWC 實作應支援:
- 至少四個疊加層:
- 狀態列
- 系統列
- 應用程式
- 桌布/背景
- 圖層大於螢幕 (例如桌布)
- 每個像素並行的 Alpha 混合和每個平面都預先相乘 Alpha 混合
- 受保護影片播放的硬體路徑
- RGBA 排序順序、YUV 格式,以及平鋪、轉換和步幅屬性
如要實作 HWC,請按照下列步驟操作:
- 實作非作業 HWC,並將所有合成工作傳送至 GLES。
- 執行演算法以逐步將組合委派給 HWC。 例如,只將前三或四個途徑委派給 HWC 的重疊硬體。
- 將硬體最佳化。這類資訊可能包括:
- 選擇能最大化 GPU 和 GPU 負載的介面 提供檔案給 HWC
- 正在偵測螢幕是否正在更新。如果不是,請將合成作業委派給 GLES 而非 HWC,以節省電力。當畫面再次更新時,請繼續將組合卸載至 HWC。
- 為常見用途做好準備,例如:
- 主畫面,包括狀態列、系統列、應用程式 視窗和動態桌布
- 直向和橫向模式的全螢幕遊戲
- 全螢幕影片,含隱藏式輔助字幕和播放控制項
- 受保護的影片播放
- 分割畫面多視窗模式
HWC 基本功能
HWC 提供兩種基本元素:圖層和螢幕,用來代表合成作業及其與顯示硬體的互動情形。 HWC 也提供 VSYNC 的控制,以及對 SurfaceFlinger 的回呼。 以在發生 VSYNC 事件時通知通知。
HIDL 介面
Android 8.0 以上版本使用
HIDL 介面,稱為 Composer HAL,用於:
HWC 和 SurfaceFlinger 之間的繫結化處理序間通訊 (IPC)。Composer HAL 會取代舊版 hwcomposer2.h
介面。如果供應商提供 Composer HAL
HWC 的實作,Composer HAL 可直接接受來自
SurfaceFlinger。如果供應商提供舊版 HWC 實作,Composer
HAL 從 hwcomposer2.h
載入函式指標。
將 HIDL 呼叫轉送至函式指標呼叫。
HWC 提供的函式可用於判斷特定螢幕的屬性,並在不同螢幕設定 (例如 4K 或 1080p 解析度) 和色彩模式 (例如原生色彩或真實 sRGB) 之間切換,以及開啟/關閉螢幕或進入省電模式 (如果支援的話)。
函式指標
如果廠商直接實作 Composer HAL,SurfaceFlinger 會透過 HIDL IPC 呼叫其函式。舉例來說,為了建立圖層,SurfaceFlinger 會呼叫 SurfaceFlinger
createLayer()
(Composer HAL)。
如果廠商實作 hwcomposer2.h
介面,Composer HAL 會呼叫 hwcomposer2.h
函式指標。在 hwcomposer2.h
註解中,HWC 介面函式會以 lowerCamelCase 名稱參照,這些名稱不會在介面中以已命名欄位的形式存在。幾乎每個函式都會透過要求
使用 getFunction
提供的函式指標
hwc2_device_t
。例如 createLayer
函式
是 HWC2_PFN_CREATE_LAYER
類型的函式指標,
當列舉值 HWC2_FUNCTION_CREATE_LAYER
完成
傳遞至 getFunction
。
詳細說明文件瞭解 Composer HAL 函式和 HWC 函式直通
函式,請參閱 composer
。如需詳細說明文件
HWC 函式指標,請參閱
hwcomposer2.h
。
圖層和顯示處理程序
圖層和顯示方式是由 HWC 產生的控點操控。 控點不適用於 SurfaceFlinger,
當 SurfaceFlinger 建立新圖層時,會呼叫 createLayer
。
這會針對直接交易傳回 Layer
類型
或 hwc2_layer_t
適用於直通式實作。當 SurfaceFlinger 修改該層的屬性時,SurfaceFlinger 會將 hwc2_layer_t
值傳遞至適當的修改函式,並附上進行修改所需的任何其他資訊。
hwc2_layer_t
類型夠大,足以包含指標或
索引。
實體螢幕是熱接上電源的製作,如果實體螢幕
HWC 建立控點,並將控點傳遞至 SurfaceFlinger,
重新傳送。虛擬螢幕是由 SurfaceFlinger 呼叫 createVirtualDisplay()
來要求螢幕而建立。如果 HWC 支援虛擬顯示組合,則會傳回句柄。接著,SurfaceFlinger 會將螢幕的組合委派給 HWC。如果 HWC 不支援虛擬顯示器合成,SurfaceFlinger 會建立句柄並合成顯示器。
顯示組合作業
每個 VSYNC 一次,如果 SurfaceFlinger 有新內容要合成,就會喚醒。這類新內容可以是應用程式中的新圖片緩衝區,或是一或多個圖層屬性的變更。SurfaceFlinger 時 喚醒它:
- 處理交易 (如有)。
- 替換新的圖形緩衝區 (如果有的話)。
- 如果步驟 1 或 2 產生變更,則執行新的組合 也不符合顯示內容的方法
如要執行新的合成作業,SurfaceFlinger 會視情況建立及銷毀圖層或修改圖層狀態。它也會使用 setLayerBuffer
或 setLayerColor
等呼叫,更新包含目前內容的圖層。在所有圖層都
SurfaceFlinger 會呼叫 validateDisplay
HWC 檢查圖層狀態,並判斷構成如何
繼續。根據預設,SurfaceFlinger 會嘗試設定每個圖層,以便由 HWC 合成圖層;不過在某些情況下,SurfaceFlinger 會透過 GPU 備用方案合成圖層。
呼叫 validateDisplay
後,SurfaceFlinger 會呼叫 getChangedCompositionTypes
,查看 HWC 是否希望在執行合成作業前變更任何圖層合成類型。為了接受變更,SurfaceFlinger 會呼叫
acceptDisplayChanges
。
如果任何圖層標示為 SurfaceFlinger 合成,SurfaceFlinger 就會將這些圖層合成至目標緩衝區。接著,SurfaceFlinger 會呼叫 setClientTarget
,將緩衝區提供給螢幕,以便在螢幕上顯示緩衝區,或進一步與尚未標示為 SurfaceFlinger 組合的圖層進行組合。如果沒有將任何圖層標示為
SurfaceFlinger 組合,SurfaceFlinger 會繞過組合步驟。
最後,SurfaceFlinger 會呼叫 presentDisplay
告知使用者
HWC 完成組成程序並顯示最終結果。
多重螢幕
Android 10 支援多個實體螢幕。設計適用於 Android 7.0 及 下方則是 HWC 定義中缺少的幾項限制:
- 假設只有一個「內部」螢幕。內部 螢幕上是顯示初始熱插頭報告的螢幕 啟動。內部螢幕熱插後,就無法中斷連線。
- 除了內部螢幕之外,在裝置正常運作期間,任何數量的外部螢幕都可能會熱插拔。架構會假設第一個內部螢幕之後的所有熱插拔都是外部螢幕,因此如果新增更多內部螢幕,這些螢幕會被錯誤分類為
Display.TYPE_HDMI
,而非Display.TYPE_BUILT_IN
。
雖然上述的 SurfaceFlinger 作業會依螢幕執行,但會依序為所有有效的螢幕執行,即使只有一台螢幕的內容更新也是如此。
舉例來說,如果外部螢幕更新,順序如下:
// 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>)
虛擬螢幕組合
虛擬顯示螢幕組合與外部顯示螢幕組合類似。虛擬螢幕組成和實體畫面之間的差異 螢幕組合是虛擬螢幕將輸出內容傳送至 Gralloc 緩衝區 而不是螢幕Hardware Composer (HWC) 會將輸出內容寫入緩衝區中。 提供完成圍欄,並將緩衝區傳送給取用端 (例如 例如影片編碼器、GPU、CPU 等如果顯示管道寫入記憶體,虛擬螢幕可以使用 2D/blitter 或覆蓋。
模式
在 SurfaceFlinger 呼叫 validateDisplay()
HWC 方法後,每個影格都會處於下列三種模式之一:
- GLES:GPU 會將所有圖層合成,並直接寫入輸出緩衝區。HWC 並不會參與組合。
- MIXED:GPU 將部分圖層合成至框架緩衝區,而 HWC 則合成框架緩衝區和其餘圖層,並直接寫入輸出緩衝區。
- HWC:HWC 會合成所有圖層,並直接寫入輸出緩衝區。
輸出格式
虛擬顯示器緩衝區輸出格式取決於其模式:
- GLES 模式 - EGL 驅動程式會設定輸出緩衝區
格式為
dequeueBuffer()
,通常是RGBA_8888
。 消費者必須能夠接受驅動程式設定的輸出格式,否則無法讀取緩衝區。 - MIXED 與 HWC 模式 - 如果消費者需要 CPU
存取,取用端會設定格式。否則格式為
IMPLEMENTATION_DEFINED
,而 Gralloc 會根據用法標記設定最佳格式。例如,如果消費者 和 HWC 都能有效率地編寫格式
同步處理圍欄
同步 (sync) 圍欄是 Android 圖形系統的重要部分。柵欄可讓 CPU 獨立於並行 GPU 工作進行,只有在存在真正的依附元件時才會阻斷。
舉例來說,當應用程式提交在 GPU 上產生的緩衝區時,也會提交同步化圍欄物件。這個圍欄可以發出信號, GPU 已完成寫入緩衝區。
HWC 要求 GPU 完成寫入緩衝區後,才能進行緩衝區 高度。同步圍欄透過緩衝區通過圖形管道傳遞 並在寫入緩衝區時發出訊號在顯示緩衝區前,HWC 檢查同步圍欄是否發出訊號,如果有,就會顯示 緩衝區。
如要進一步瞭解同步處理圍欄,請參閱 Hardware Composer 整合。