映射 HDR 亮度與 SDR 相容範圍

Android 13 導入了由供應商可設定的靜態程式庫,稱為 libtonemap,該程式庫會定義色調對應作業,並與 SurfaceFlinger 程序和 Hardware Composer (HWC) 實作共用。這項功能可讓原始設備製造商在架構和供應商之間定義及分享顯示色調對應演算法,減少色調對應不相符的情況。

在 Android 13 之前,HWC、SurfaceFlinger 和應用程式之間並未共用螢幕專屬的色調對應作業。視轉譯路徑而定,這會導致影像品質不相符,即 HDR 內容是以不同方式對應到輸出空間。這在螢幕旋轉等情境中可見一斑,因為在這些情境中,GPU 和 DPU 之間的組合策略會有所變更,而 TextureView 和 SurfaceView 的算繪行為也有所差異。

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

色調對應程式庫的介面

libtonemap 程式庫包含 CPU 支援的實作項目和 SkSL 著色器,可由 SurfaceFlinger 插入,用於 GPU 後端合成,並由 HWC 插入,用於產生色調對應查詢表 (LUT)。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 像素的絕對尼特值,而 xyz 是轉換為 XYZ 的 linearRGB
    • 著色器字串使用的任何輔助方法,都必須在字串前方加上 libtonemap_,以免架構著色器定義發生衝突。同樣地,輸入統一變數必須以 in_libtonemap_ 做為前置字串。
  • 產生 SkSL 統一

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

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

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

    目前,產生均一化程序的過程不會考量輸入和輸出資料空間。

自訂

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

強烈建議原始設備製造商覆寫 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 合成作業寫入 8 位元格式 (例如 RGBA8888) 來支援 alpha 值,就可能會發生帶狀現象。

  • 如果 DPU 以與 GPU 不同的精確度運作,則會因量化差異而造成微妙的顏色偏移。

這些問題都與基礎硬體的相對精確度差異有關。一般解決方法是確保較低精度路徑中包含抖動步驟,讓人類較不易察覺精度差異。