Surface 和 SurfaceHolder

應用程式可透過 Surface 物件算繪要在螢幕上顯示的圖像。 應用程式可透過 SurfaceHolder 介面編輯及控制 Surface。

Surface

介面是供應商與消費者交換緩衝區的介面。

顯示介面通常會使用為三緩衝區設定的 BufferQueue。緩衝區是依需求分配,因此如果製作工具產生緩衝區的速度不夠快,例如在 60 FPS 的螢幕上以 30 FPS 的速度產生緩衝區,佇列中可能只會分配到兩個緩衝區。視需要配置緩衝區有助於減少記憶體用量。您可以查看 dumpsys SurfaceFlinger 輸出內容中每個圖層相關聯的緩衝區摘要。

大多數用戶端都會使用 OpenGL ESVulkan,在介面上算繪內容。不過,部分用戶端會使用畫布在介面上算繪。

畫布算繪

Skia Graphics Library 提供畫布實作。如要繪製矩形,請呼叫 Canvas API,在緩衝區中適當設定位元組。為確保緩衝區不會同時由兩個用戶端更新,或在顯示時寫入,請鎖定緩衝區以存取緩衝區。請使用下列指令處理畫布鎖定:

  • lockCanvas() 會鎖定緩衝區,以便在 CPU 上進行轉譯,並傳回用於繪圖的 Canvas。
  • unlockCanvasAndPost() 會解鎖緩衝區,並傳送至合成器。
  • lockHardwareCanvas() 會鎖定緩衝區,以便在 GPU 上進行轉譯,並傳回用於繪圖的畫布。

生產者首次向 BufferQueue 要求緩衝區時,系統會分配緩衝區並初始化為零。初始化作業是必要步驟,可避免在程序之間不慎共用資料。不過,如果重複使用緩衝區,先前的內容仍會存在。如果重複呼叫 lockCanvas()unlockCanvasAndPost(),但未繪製任何內容,製作工具會在先前算繪的影格之間循環。

表面鎖定/解除鎖定程式碼會保留先前算繪緩衝區的參照。如果在鎖定表面時指定髒區,系統會從先前的緩衝區複製非髒區像素。SurfaceFlinger 或 HWC 通常會處理緩衝區,但由於您只需要從緩衝區讀取資料,因此不必等待專屬存取權。

SurfaceHolder

SurfaceHolder 是系統用來與應用程式共用 Surface 擁有權的介面。部分使用介面的用戶端需要 SurfaceHolder,因為取得及設定介面參數的 API 是透過 SurfaceHolder 實作。SurfaceView 包含 SurfaceHolder。

與檢視區塊互動的大多數元件都涉及 SurfaceHolder。其他 API (例如 MediaCodec) 則會在介面上運作。