圖層和顯示是代表合成工作以及與顯示硬體互動的兩個基元。
層數
層是最重要的組成單元。圖層是表面和SurfaceControl
實例的組合。每個層都有一組屬性,用於定義它如何與其他層互動。圖層屬性如下表所述。
財產 | 描述 |
---|---|
位置性 | 定義圖層在其顯示幕上的顯示位置。包括層邊緣的位置及其相對於其他層的Z 順序等資訊(是否應位於其他層的前面或後面)。 |
內容 | 定義在位置屬性定義的範圍內應如何呈現圖層上顯示的內容。包括裁切(擴展部分內容以填滿圖層邊界)和變換(顯示旋轉或翻轉的內容)等資訊。 |
作品 | 定義該圖層應如何與其他圖層合成。包括混合模式和用於alpha 合成的圖層範圍 alpha 值等資訊。 |
最佳化 | 提供正確合成層並非嚴格必需的信息,但硬體合成器 (HWC) 設備可以使用這些資訊來優化其執行合成的方式。包括圖層的可見區域以及自上一幀以來圖層的哪一部分已更新等資訊。 |
顯示器
顯示器是另一個重要的構圖單元。一個系統可以有多個顯示器,並且可以在正常系統操作期間新增或刪除顯示器。應 HWC 的請求或框架的請求新增/刪除顯示。當外部顯示器與裝置連接或斷開連接時,HWC 裝置要求新增或刪除顯示器,稱為熱插拔。客戶端請求虛擬顯示器,其內容被渲染到離屏緩衝區而不是實體顯示器。
虛擬展示
SurfaceFlinger支援內部顯示器(內建於手機或平板電腦中)、外部顯示器(例如透過 HDMI 連接的電視)以及一個或多個可在系統內提供合成輸出的虛擬顯示器。虛擬顯示器可用於記錄螢幕或透過網路傳送螢幕。為虛擬顯示產生的幀被寫入 BufferQueue。
虛擬顯示器可以與主顯示器共用同一組圖層(圖層堆疊),也可以擁有自己的圖層群組。虛擬顯示器沒有 VSYNC,因此內部顯示器的 VSYNC 會觸發所有顯示器的合成。
在支援它們的 HWC 實作上,虛擬顯示可以與 OpenGL ES (GLES)、HWC 或 GLES 和 HWC 組合。在不支援的實作中,虛擬顯示始終使用 GLES 進行合成。
案例研究:螢幕記錄
screenrecord
指令允許使用者將螢幕上出現的所有內容記錄為磁碟上的.mp4
檔案。為了實現這一點,系統從 SurfaceFlinger 接收合成幀,將它們寫入視訊編碼器,然後將編碼後的視訊資料寫入檔案。視訊編解碼器由單獨的進程( mediaserver
)管理,因此大型圖形緩衝區必須在系統中移動。為了使其更具挑戰性,我們的目標是以全解析度錄製 60 fps 的影片。讓這項工作有效率地工作的關鍵是 BufferQueue。
MediaCodec
類別允許應用程式在緩衝區中或透過表面以原始位元組形式提供資料。當screenrecord
請求存取視訊編碼器時, mediaserver
進程會建立一個 BufferQueue,將自身連接到消費者端,然後將生產者端作為表面傳遞回screenrecord
。
然後, screenrecord
實用程式要求 SurfaceFlinger 建立一個鏡像主顯示器的虛擬顯示器(即,它具有所有相同的層),並指示它將輸出發送到來自mediaserver
進程的表面。在這種情況下,SurfaceFlinger 是緩衝區的生產者而不是消費者。
配置完成後,當編碼資料出現時, screenrecord
就會觸發。當應用程式繪製時,它們的緩衝區會傳輸到 SurfaceFlinger,後者將它們合成為單一緩衝區,並直接發送到mediaserver
進程中的視訊編碼器。 screenrecord
過程永遠不會看到完整的畫面。在內部, mediaserver
程序有自己的行動緩衝區的方式,也可以透過句柄傳遞數據,從而最大限度地減少開銷。
案例研究:模擬輔助顯示器
WindowManager 可以要求 SurfaceFlinger 建立一個可見層,SurfaceFlinger 充當 BufferQueue 使用者。也可以要求 SurfaceFlinger 建立虛擬顯示器,SurfaceFlinger 充當該虛擬顯示器的 BufferQueue 生產者。
如果將虛擬顯示器連接到可見層,則會在視窗中顯示合成螢幕的位置處建立閉環。該視窗現在是合成輸出的一部分,因此下次刷新視窗內的合成影像時也會顯示視窗內容。若要查看此操作的實際效果,請在「設定」中啟用「開發人員選項」 ,選擇「類比輔助顯示器」 ,然後啟用一個視窗。若要查看正在運行的輔助顯示器,請使用screenrecord
擷取啟用顯示器的操作,然後逐幀回放。