映射 HDR 亮度與 SDR 相容範圍

Android 13 推出了供應商可設定的靜態程式庫 libtonemap,用於定義色調對應作業,並與 SurfaceFlinger 程序和硬體編譯器 (HWC) 實作項目共用。這項功能可讓原始設備製造商在架構和供應商之間定義及分享顯示色調對應演算法,減少色調對應不相符的情況。

在 Android 13 之前,HWC、SurfaceFlinger 和應用程式之間並未共用螢幕專屬的色調對應作業。這會導致 HDR 內容的圖像品質不一致,因為 HDR 內容會以不同方式將色調對應至輸出空間。這適用於螢幕旋轉等情況,因為在 GPU 和 DPU 之間,組合策略會改變,以及 TextureView 和 SurfaceView 之間的算繪行為差異。

本頁說明 libtonemap 程式庫的介面、自訂和驗證詳細資料。

色調對應程式庫的介面

libtonemap 程式庫包含採用 CPU 的實作項目和 SkSL 著色器,可插入的 SurfaceFlinger 進行 GPU 後端組合,以及由 HWC 產生色調對應查詢表 (LUT) 的 SkSL 著色器。libtonemap 的進入點是 android::tonemap::getToneMapper(),會傳回實作 ToneMapper 介面的物件。

ToneMapper 介面支援下列功能:

  • 產生色調對應 LUT

    介面 ToneMapper::lookupTonemapGainlibtonemap_LookupTonemapGain() 中定義著色器的 CPU 實作項目。這個檔案會由架構中的單元測試使用,合作夥伴也可以使用這個檔案,協助在其色彩管道中產生色調對應 LUT。

    libtonemap_LookupTonemapGain() 會以絕對值和未標準化的線性空間 (線性 RGB 和 XYZ) 接收顏色值,並傳回浮點值,說明在線性空間中乘上輸入顏色的倍數。

  • 產生 SkSL 著色器

    介面 ToneMapper::generateTonemapGainShaderSkSL() 會在指定來源和目的地資料空間的情況下,傳回 SkSL 著色器字串。SkSL 著色器會插入 RenderEngine 的 Skia 實作項目,這是 SurfaceFlinger 的 GPU 加速合成元件。著色器也會插入 libhwui,以便為 TextureView 有效執行 HDR 至 SDR 的色調對應。由於產生的字串會內嵌至 Skia 使用的其他 SkSL 著色器,因此著色器必須遵守下列規則:

    • 著色器字串必須包含具有 float libtonemap_LookupTonemapGain(vec3 linearRGB, vec3 xyz) 簽章的進入點,其中 linearRGB 是線性空間中 RGB 像素的絕對 nit 值,xyz 則是linearRGB轉換為 XYZ。
    • 著色器字串使用的所有輔助方法都必須以 libtonemap_ 字串做為前置字串,以確保架構著色器定義不會發生衝突。同樣地,輸入統一編號的開頭必須加上 in_libtonemap_
  • 產生 SkSL 統一

    介面 ToneMapper::generateShaderSkSLUniforms() 會傳回以下內容,其中中繼資料 struct 會描述不同 HDR 標準和顯示條件的中繼資料:

    • 受 SkSL 著色器繫結的製服清單。

    • 統一值 in_libtonemap_displayMaxLuminancein_libtonemap_inputMaxLuminance。將輸入縮放為 libtonemap 並視需求將輸出內容正規化時,架構著色器會使用這些值。

    目前,產生統一變數的程序適用於輸入和輸出資料空間。

自訂

libtonemap 程式庫的參考實作項目可產生可接受的結果。不過,由於 GPU 合成的色調對應演算法可能與 DPU 合成的演算法不同,因此在某些情況下 (例如旋轉動畫),使用參考實作項目可能會造成閃爍。自訂可以解決這類供應商特有的圖片品質問題。

強烈建議原始設備製造商 (OEM) 覆寫 libtonemap 的實作方式,定義自己的 ToneMapper 子類別,由 getToneMapper() 傳回。自訂實作項目時,合作夥伴應採取下列任一做法:

  • 直接修改 libtonemap 的實作方式。
  • 定義自己的靜態資料庫、將程式庫編譯為獨立程式庫,然後將 libtonemap 程式庫的 .a 檔案取代為自訂程式庫產生的檔案。

供應商不需要修改任何核心程式碼,但多個供應商必須提供有關 DPU 色調對應演算法的詳細資料,以便正確導入。

驗證

請按照下列步驟驗證導入狀態:

  1. 螢幕系統支援的任何 HDR 標準 (例如 HLG、HDR10、HDR10+ 或 DolbyVision) 上播放 HDR 影片。

  2. 切換 GPU 合成功能,確保使用者不會看到閃爍。

    使用下列 adb 指令切換 GPU 合成:

    adb shell service call SurfaceFlinger 1008 i32 <0 to enable HWC composition,
    1 to force GPU composition>
    
    

常見問題

這種導入方式可能發生下列問題:

  • 當 GPU 合成作業使用的算繪目標精確度低於 HDR 內容的一般值時,就會產生條紋。舉例來說,如果 HWC 實作支援 HDR 的不透明 10 位元格式 (如 RGBA1010102 或 P010),但 GPU 組合必須寫入 RGBA8888 等 8 位元格式,才能支援 Alpha 值,這時就會發生帶狀現象。

  • 如果 DPU 的運算精度與 GPU 不同,就會因量化差異而導致色彩偏移。

這些問題都與基礎硬體的相對精確度差異有關。一般的解決方法是確保較低精確度路徑中具有遞迴步驟,使任何精確度差異較不人能察覺。