圖層和螢幕是兩個基本元素,代表合成作業和與顯示器硬體的互動。
圖層
圖層是構成單位中最重要的部分,圖層是介面和 SurfaceControl
執行個體的組合。每個圖層都有一組屬性,可定義與其他圖層的互動方式。下表說明圖層屬性:
屬性 | 說明 |
---|---|
位置 | 定義圖層在螢幕上的顯示位置。包括圖層邊緣的位置,以及相對於其他圖層的 Z 順序 (應位於其他圖層前方或後方)。 |
內容 | 定義圖層上顯示的內容在位置屬性定義的界線內呈現方式。包括裁剪 (擴展部分內容以填滿圖層界線) 和變形 (顯示旋轉或翻轉的內容) 等資訊。 |
樂曲 | 定義圖層應如何與其他圖層合成。包括Alpha 合成的混合模式和圖層 Alpha 值等資訊。 |
最佳化 | 提供並非正確合成圖層的必要資訊,但可供硬體合成器 (HWC) 裝置用來最佳化合成作業。包括圖層的可見區域,以及自前一個影格以來更新的圖層部分等資訊。 |
螢幕
顯示是另一個重要的組成單位。一個系統可以有多個螢幕,且在系統正常運作期間,可以新增或移除螢幕。應 HWC 或架構要求新增或移除螢幕。當外部螢幕連線或中斷與裝置的連線時,HWC 裝置會要求新增或移除螢幕,這稱為熱插拔。用戶端會要求虛擬螢幕,其內容會轉譯到螢幕外緩衝區,而不是實體螢幕。
虛擬螢幕
SurfaceFlinger 支援內部螢幕 (內建於手機或平板電腦)、外部螢幕 (例如透過 HDMI 連接的電視),以及一或多個虛擬螢幕,可在系統內提供合成輸出內容。虛擬螢幕可用於錄製螢幕畫面或透過網路傳送畫面。系統會將為虛擬螢幕產生的影格寫入 BufferQueue。
虛擬螢幕可以與主螢幕共用同一組圖層 (圖層堆疊),也可以使用自己的圖層組。虛擬螢幕沒有 VSync,因此內部螢幕的 VSync 會觸發所有螢幕的合成作業。
在支援虛擬螢幕的 HWC 實作中,虛擬螢幕可以與 OpenGL ES (GLES)、HWC 或 GLES 和 HWC 兩者組合。在不支援的實作項目中,虛擬螢幕一律會使用 GLES 合成。
個案研究:screenrecord
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
擷取啟用螢幕的動作,然後逐一播放影格。