Android 12(S) 圖形顯示系統 – 基本概念(一)





 

1 前言

Android圖形系統是系統框架中一個非常重要的子系統,與其它子系統一樣,Android 框架提供了各種用於 2D 和 3D 圖形渲染的 API供開發者使用來創建絢麗多彩的應用APP。圖形渲染的 API的底層可與製造商的圖形驅動程式實現程式碼交互,了解這些API的工作原理及圖形系統框架層的處理邏輯可以幫助我們更好的使用這些功能。

本系列文章將側重於圖形系統BufferQueue的知識做分析講解。BufferQueues 是 Android 圖形組件之間的粘合劑,BufferQueue 類將生成圖形數據緩衝區的組件(producers)連接到接受數據以便進行顯示或進一步處理的組件(consumers)。幾乎所有在系統中移動圖形數據緩衝區的內容都依賴於 BufferQueue。理解BufferQueue的工作邏輯及圖形緩衝區移動流程對於我們學習Android圖形系統工作機制非常重要。

本篇作為該系列的開篇,我們將從Android圖形系統的一些基本概念入手。

接下來就開始我們的學習之旅。

註:本系列文章的分析及程式碼均基於Android 12(S) Source Code,可參考://aospxref.com/ //aosp.opersys.com/


 

2 Android圖形系統基本概述


 

2.1 Android 圖形組件

Android圖形系統涉及到非常多的組件,比如 Surface、SurfaceHolder、EGLSurface、SurfaceView、GLSurfaceView、SurfaceTexture、TextureView、SurfaceFlinger等,比如下圖展示的:

低級別組件

  • BufferQueue 和 gralloc。BufferQueue 將可生成圖形數據緩衝區的組件(生產者)連接到接受數據以便進行顯示或進一步處理的組件(消費者)。通過供應商專用 HAL 介面實現的 gralloc 記憶體分配器將用於執行緩衝區分配任務。
  • SurfaceFlinger、Hardware Composer 和虛擬顯示器。SurfaceFlinger 接受來自多個源的數據緩衝區,然後將它們進行合成並發送到顯示器。Hardware Composer HAL (HWC) 確定使用可用硬體合成緩衝區的最有效的方法,虛擬顯示器使合成輸出可在系統內使用(錄製螢幕或通過網路發送螢幕)。
  • Surface、Canvas 和 SurfaceHolder。Surface 可生成一個通常由 SurfaceFlinger 使用的緩衝區隊列。當渲染到 Surface 上時,結果最終將出現在傳送給消費者的緩衝區中。Canvas API 提供一種軟體實現方法(支援硬體加速),用於直接在 Surface 上繪圖(OpenGL ES 的低級別替代方案)。與視圖有關的任何內容均涉及到 SurfaceHolder,其 API 可用於獲取和設置 Surface 參數(如大小和格式)
  • EGLSurface 和 OpenGL ES。OpenGL ES (GLES) 定義了旨在與 EGL 結合使用的圖形渲染 API。EGI 是一個通過作業系統創建和訪問窗口的庫(要繪製紋理多邊形,請使用 GLES 調用;要將渲染應用到螢幕上,請使用 EGL 調用)。此頁還介紹了 ANativeWindow,它是 Java Surface 類的 C/C++ 等價類,用於通過原生程式碼創建 EGL 窗口表面。
  • Vulkan。Vulkan 是一種用於高性能 3D 圖形的低開銷、跨平台 API。與 OpenGL ES 一樣,Vulkan 提供用於在應用中創建高品質實時圖形的工具。Vulkan 的優勢包括降低 CPU 開銷以及支援 SPIR-V 二進位中間語言。

高級別組件

  • SurfaceView 和 GLSurfaceView。SurfaceView 結合了 Surface 和 View。SurfaceView 的 View 組件由 SurfaceFlinger(而不是應用)合成,從而可以通過單獨的執行緒/進程渲染,並與應用介面渲染隔離。GLSurfaceView 提供了用於管理 EGL 上下文、執行緒間通訊以及與 Activity 生命周期的交互的輔助程式類(但不是必須使用 GLES)。
  • SurfaceTexture。 SurfaceTexture 將 Surface 和 GLES 紋理相結合來創建 BufferQueue,而您的應用是 BufferQueue 的消費者。當生產者將新的緩衝區排入隊列時,它會通知您的應用。您的應用會依次釋放先前佔用的緩衝區,從隊列中獲取新緩衝區並執行 EGL 調用,從而使 GLES 可將此緩衝區作為外部紋理使用。Android 7.0 添加了對安全紋理影片播放的支援,以便對受保護的影片內容進行 GPU 後處理。
  • TextureView。 TextureView 結合了 View 和 SurfaceTexture。TextureView 對 SurfaceTexture 進行包裝,並負責響應回調以及獲取新的緩衝區。在繪圖時,TextureView 使用最近收到的緩衝區的內容作為其數據源,根據 View 狀態指示,在它應該渲染的任何位置和以它應該採用的任何渲染方式進行渲染。View 合成始終通過 GLES 來執行,這意味著內容更新可能會導致其他 View 元素重繪。

Android圖形組件相互配合、溝通,共同組成一個完善的圖形顯示子系統,同時在Java level與Native level面向開發者提供了可編程的介面。


 

2.2 Android 圖形組件協同工作

無論開發者使用什麼渲染 API,一切內容都會渲染到 Surface 上。Surface 表示緩衝區隊列中的生產者,而緩衝區隊列通常會被 SurfaceFlinger 消耗。在 Android 平台上創建的每個窗口都由 Surface 提供支援。所有被渲染的可見 Surface 都被 SurfaceFlinger 合成到螢幕。

下圖顯示了關鍵組件如何協同工作:

影像渲染組件

從工作流程的角度去看,主要組件如下所述:

影像流生產者(Image Stream Producers)

影像流生產者可以是生成圖形緩衝區以供消耗的任何內容。例如 OpenGL ES、Canvas 2D 和 mediaserver 影片解碼器。

影像流消費者(Image stream consumers)

影像流的最常見消費者是 SurfaceFlinger,該系統服務會消耗當前可見的 Surface,並使用窗口管理器中提供的資訊將它們合成到螢幕。SurfaceFlinger 是可以修改所顯示部分內容的唯一服務。SurfaceFlinger 使用 OpenGL 和 Hardware Composer 來合成一組 Surface。

其他 OpenGL ES 應用也可以消耗影像流,例如相機應用會消耗相機預覽影像流。非 GL 應用也可以是使用方,例如 ImageReader 類。

硬體混合渲染器(Hardware Composer)

顯示子系統的硬體抽象實現。SurfaceFlinger 可以將某些合成工作委託給硬體混合渲染器(HWC),以分擔 OpenGL 和 GPU 上的工作量。SurfaceFlinger 只是充當另一個 OpenGL ES 客戶端。因此,在 SurfaceFlinger 將一個或兩個緩衝區合成到第三個緩衝區中的過程中,它會使用 OpenGL ES。這會讓合成的功耗比通過 GPU 執行所有計算時更低。

硬體混合渲染器 HAL 則進行另一半的工作,是所有 Android 圖形渲染的中心點。Hardware Composer 必須支援事件,其中之一是 VSYNC(另一個是支援即插即用 HDMI 的熱插拔)。

Gralloc可以理解為圖形記憶體分配器,用來分配和管理影像生產者請求的記憶體(即圖形數據緩衝區Graphic Buffers)


 

有關 Android graphics pipeline的描述,請參見下圖:

圖形數據流

  • 左側的對象是生成圖形緩衝區的渲染器,如主螢幕、狀態欄和系統介面。
  • SurfaceFlinger 是合成器,接受多個來源的圖形顯示數據,將他們合成,然後發送到顯示設備。
  • 硬體混合渲染器HWC是製作器。SurfaceFlinger與HWC配合用來將 Surface 合成到螢幕

BufferQueues 是 Android 圖形組件之間的粘合劑。它們是一對影像緩衝區隊列,可以調解緩衝區從生產者到消費者的固定周期。一旦生產者移交其緩衝區,SurfaceFlinger 便會負責將所有內容合成到顯示部分。

有關 BufferQueue 通訊過程,請參見下圖。

BufferQueue 通訊過程

BufferQueue 包含將影像流生產者與影像流消費者結合在一起的邏輯。BufferQueue 類是 Android 中所有圖形處理操作的核心。它的作用很簡單:將生成圖形數據緩衝區的一方(生產方)連接到接受數據以進行顯示或進一步處理的一方(消耗方)。幾乎所有在系統中移動圖形數據緩衝區的內容都依賴於 BufferQueue。

通過上圖我們可以大概看到BufferQueue的工作過程:

  1. 影像生產者通過調用dequeue方法向BufferQueue請求一塊圖形緩衝區記憶體,即一塊GraphicBuffer;
  2. 影像生產者將產生的影像數據(比如相機預覽的影像或解碼器解碼出的影片幀)寫入圖形緩衝區GraphicBuffer,並通過queue方法提交給BufferQueue;
  3. BufferQueue收到圖形緩衝區GraphicBuffer的入隊列消息,通知影像消費者調用acquire方法取得已填充數據的buffer進行處理或顯示;
  4. 影像消費者處理完畢,調用release方法把buffer歸還給BufferQueue,這個buffer之後可再重複使用;
  5. 影像生產者、BufferQueue、影像消費者協調工作,圖形緩衝區buffer在三者之間協調流轉,影像便流暢的顯示或處理。

 

3 小結

通過上面的一些介紹,我們對Android圖形系統的一些基本組成及概念有了一個大概的了解。為了更深刻的理解這些抽象的內容,下一篇文章我們將從Native Level入手,基於Android圖形系統API寫作一個簡單的圖形處理小程式。

 


保持一份好心情

必讀:

Android 12(S) 圖形顯示系統 – 開篇


 

 

 

 


參考

//www.jianshu.com/p/824a9ddf68b9

//www.cnblogs.com/1996swg/p/9790209.html

//source.android.com/devices/graphics

//www.pianshen.com/article/98181094083/