HDR 휘도를 SDR 호환 범위에 톤 매핑하기

Android 13에는 공급업체에서 구성 가능한 정적 라이브러리인 libtonemap이 도입되었습니다. 이 라이브러리는 톤 매핑 작업을 정의하며 SurfaceFlinger 프로세스 구현 및 하드웨어 컴포저(HWC) 구현과 공유됩니다. 이 기능을 사용하면 OEM이 디스플레이 톤 매핑 알고리즘을 정의하고 프레임워크와 공급업체 간에 공유하여 톤 매핑의 불일치를 줄일 수 있습니다.

Android 13 이전에는 디스플레이별 톤 매핑 작업이 HWC, SurfaceFlinger, 앱 간에 공유되지 않았습니다. 이로 인해 HDR 콘텐츠의 경우 렌더링 경로에 따라 이미지 품질의 불일치가 발생해 HDR 콘텐츠가 출력 공간에 여러 가지 방식으로 톤 매핑되었습니다. 이러한 현상은 GPU와 DPU의 구성 전략이 서로 다른 화면 회전과 같은 시나리오 상에서나 TextureView와 SurfaceView 간의 렌더링 동작의 차이 등을 통해 체감할 수 있었습니다.

이 페이지에서는 libtonemap 라이브러리의 인터페이스, 맞춤설정, 유효성 검사 세부정보를 설명합니다.

톤 매핑 라이브러리의 인터페이스

libtonemap 라이브러리에는 GPU 백엔드 구성을 위한 SurfaceFlinger나 톤 매핑 룩업 테이블(LUT)의 생성을 위한 HWC에 의해 연결될 수 있는 CPU 기반 구현 및 SkSL 셰이더가 포함되어 있습니다. libtonemap의 진입점은 android::tonemap::getToneMapper()로, ToneMapper 인터페이스를 구현하는 객체를 반환합니다.

ToneMapper 인터페이스는 다음 기능을 지원합니다.

  • 톤 매핑 LUT 생성

    ToneMapper::lookupTonemapGain 인터페이스는 libtonemap_LookupTonemapGain()에 정의된 셰이더의 CPU 구현입니다. 이 인터페이스는 프레임워크의 단위 테스트에서 사용되며, 파트너가 색상 파이프라인 내에서 톤 매핑 LUT를 생성하는 데 지원을 받는 용도로 사용할 수 있습니다.

    libtonemap_LookupTonemapGain()은 선형 RGB와 XYZ의 비정규화된 절댓값 선형 공간에서 색상 값을 가져오고 선형 공간에서 입력 색상에 곱할 값을 설명하는 부동 소수점 수를 반환합니다.

  • SkSL 셰이더 생성

    ToneMapper::generateTonemapGainShaderSkSL() 인터페이스는 소스 및 대상 데이터 공간이 주어진 경우 SkSL 셰이더 문자열을 반환합니다. SkSL 셰이더는 SurfaceFlinger용 GPU 가속 합성 구성요소인 RenderEngine의 Skia 구현에 연결됩니다. 셰이더는 TextureView용으로 HDR-SDR 톤 매핑이 효율적으로 이루어질 수 있도록 libhwui에도 연결됩니다. 생성된 문자열이 Skia에서 사용하는 다른 SkSL 셰이더에 인라인 적용되므로 셰이더는 다음 규칙을 준수해야 합니다.

    • 셰이더 문자열에는 float libtonemap_LookupTonemapGain(vec3 linearRGB, vec3 xyz) 서명이 있는 진입점이 있어야 합니다. 여기서 linearRGB는 선형 공간에서 RGB 픽셀의 nit 절댓값이고 xyz는 XYZ로 변환된 linearRGB입니다.
    • 셰이더 문자열이 사용하는 모든 도우미 메서드의 앞에는 프레임워크 셰이더 정의가 충돌하지 않도록 libtonemap_ 문자열을 접두사로 추가해야 합니다. 마찬가지로 입력 유니폼의 앞에도 in_libtonemap_ 접두사를 추가해야 합니다.
  • SkSL 유니폼 생성

    여러 HDR 표준 및 디스플레이 조건의 메타데이터를 설명하는 메타데이터 struct가 제공된 경우 ToneMapper::generateShaderSkSLUniforms() 인터페이스는 다음을 반환합니다.

    • SkSL 셰이더에 의해 바인딩된 유니폼 목록

    • 유니폼 값 in_libtonemap_displayMaxLuminancein_libtonemap_inputMaxLuminance. 이러한 값은 프레임워크 셰이더가 입력을 libtonemap으로 확장하고 출력을 적정한 값으로 정규화하는 데 사용됩니다.

    현재 유니폼 생성 프로세스는 입력 및 출력 데이터 공간에 구애받지 않습니다.

맞춤설정

libtonemap 라이브러리의 참조 구현은 허용되는 결과를 생성합니다. 단, GPU 구성에서 사용하는 톤 매핑 알고리즘은 DPU 구성에서 사용하는 톤 매핑 알고리즘과 다를 수 있으므로 참조 구현을 사용하면 회전 애니메이션과 같은 일부 시나리오에서 깜박임이 발생할 수 있습니다. 맞춤설정은 이러한 공급업체별 이미지 품질 문제를 해결할 수 있습니다.

OEM은 libtonemap의 구현을 재정의하여 getToneMapper()에서 반환되는 ToneMapper 서브클래스를 자체적으로 정의하는 것이 좋습니다. 구현을 맞춤설정할 때 파트너는 다음 중 하나를 실행해야 합니다.

  • libtonemap의 구현을 직접 수정합니다.
  • 자체 정적 라이브러리를 정의하고 라이브러리를 독립형으로 컴파일한 후 libtonemap 라이브러리의 .a 파일을 커스텀 라이브러리에서 생성된 파일로 바꿉니다.

공급업체는 커널 코드를 수정할 필요가 없지만, 올바른 구현을 위해서는 여러 공급업체가 DPU 톤 매핑 알고리즘에 관한 세부정보를 서로 공유해야 합니다.

유효성 검사

구현의 유효성을 검사하려면 다음 단계를 따르세요.

  1. HLG, HDR10, HDR10+, DolbyVision과 같이 디스플레이 시스템이 지원하는 모든 HDR 표준 화면에서 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에서 RGBA1010102 또는 P010과 같은 불투명한 10비트 형식을 지원하지만 알파를 지원하려면 GPU 구성이 RGBA8888과 같은 8비트 형식에 써야 하는 경우 밴딩이 발생할 수 있습니다.

  • DPU가 GPU와 다른 정밀도로 작동하는 경우 양자화 차이로 인해 미묘한 색상 차이가 발생합니다.

이러한 문제는 기본 하드웨어의 상대 정밀도 차이와 관련이 있습니다. 일반적인 해결 방법은 사용자가 정밀도 차이를 체감하지 못하도록 낮은 정밀도 경로에 디더링 단계를 구현하는 것입니다.