Surface 對象使應用程序能夠渲染要在屏幕上呈現的圖像。 SurfaceHolder 接口使應用程序能夠編輯和控製表面。
表面
表面是生產者與消費者交換緩衝區的接口。
顯示表面的 BufferQueue 通常配置為三重緩衝。緩衝區是按需分配的,因此如果生產者生成緩衝區的速度足夠慢,例如在 60 fps 的顯示器上以 30 fps 的速度生成緩衝區,則隊列中可能只有兩個分配的緩衝區。按需分配緩衝區有助於最大限度地減少內存消耗。您可以在dumpsys SurfaceFlinger
輸出中查看與每一層關聯的緩衝區的摘要。
大多數客戶端使用OpenGL ES或Vulkan渲染到表面上。但是,一些客戶端使用畫布渲染到表面上。
畫布渲染
畫布實現由Skia 圖形庫提供。如果要繪製矩形,請調用 Canvas API,它會在緩衝區中適當地設置字節。為確保緩衝區不會被兩個客戶端同時更新或在顯示時寫入,請鎖定緩衝區以訪問它。使用以下命令來處理畫布鎖:
-
lockCanvas()
鎖定緩衝區以在 CPU 上進行渲染,並返回一個 Canvas 用於繪圖。 -
unlockCanvasAndPost()
解鎖緩衝區並將其發送到合成器。 -
lockHardwareCanvas()
鎖定緩衝區以在 GPU 上進行渲染,並返回用於繪圖的畫布。
生產者第一次從 BufferQueue 請求緩衝區時,緩衝區被分配並初始化為零。初始化是必要的,以避免無意中在進程之間共享數據。但是,如果您重用緩衝區,之前的內容仍然存在。如果您重複調用lockCanvas()
和unlockCanvasAndPost()
而不繪製任何內容,則生產者會在先前渲染的幀之間循環。
表面鎖定/解鎖代碼保留對先前渲染緩衝區的引用。如果在鎖定表面時指定臟區域,它會從前一個緩衝區復制非臟像素。 SurfaceFlinger 或 HWC 通常處理緩衝區;但是因為我們只需要從緩衝區中讀取,所以不需要等待獨占訪問。
表面支架
SurfaceHolder是系統用來與應用程序共享表面所有權的接口。一些使用表面的客戶端需要 SurfaceHolder,因為獲取和設置表面參數的 API 是通過 SurfaceHolder 實現的。 SurfaceView包含一個 SurfaceHolder。
大多數與視圖交互的組件都涉及 SurfaceHolder。其他一些 API,例如 MediaCodec,在表面本身上運行。