圖層和顯示

圖層和螢幕是兩個基本元素,代表合成作業和與顯示器硬體的互動。

圖層

圖層是構成單位中最重要的部分,圖層是介面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 擷取啟用螢幕的動作,然後逐一播放影格。