2025년 3월 27일부터 AOSP를 빌드하고 기여하려면 aosp-main
대신 android-latest-release
를 사용하는 것이 좋습니다. 자세한 내용은 AOSP 변경사항을 참고하세요.
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()
인터페이스는 다음을 반환합니다.
현재 유니폼 생성 프로세스는 입력 및 출력 데이터 공간에 구애받지 않습니다.
맞춤설정
libtonemap
라이브러리의 참조 구현은 허용되는 결과를 생성합니다. 단, GPU 구성에서 사용하는 톤 매핑 알고리즘은 DPU 구성에서 사용하는 톤 매핑 알고리즘과 다를 수 있으므로 참조 구현을 사용하면 회전 애니메이션과 같은 일부 시나리오에서 깜박임이 발생할 수 있습니다. 맞춤설정은 이러한 공급업체별 이미지 품질 문제를 해결할 수 있습니다.
OEM은 libtonemap
의 구현을 재정의하여 getToneMapper()
에서 반환되는 ToneMapper
서브클래스를 자체적으로 정의하는 것이 좋습니다.
구현을 맞춤설정할 때 파트너는 다음 중 하나를 실행해야 합니다.
libtonemap
의 구현을 직접 수정합니다.
- 자체 정적 라이브러리를 정의하고 라이브러리를 독립형으로 컴파일한 후
libtonemap
라이브러리의 .a
파일을 커스텀 라이브러리에서 생성된 파일로 바꿉니다.
공급업체는 커널 코드를 수정할 필요가 없지만, 올바른 구현을 위해서는 여러 공급업체가 DPU 톤 매핑 알고리즘에 관한 세부정보를 서로 공유해야 합니다.
유효성 검사
구현의 유효성을 검사하려면 다음 단계를 따르세요.
HLG, HDR10, HDR10+, DolbyVision과 같이 디스플레이 시스템이 지원하는 모든 HDR 표준 화면에서 HDR 동영상을 재생합니다.
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와 다른 정밀도로 작동하는 경우 양자화 차이로 인해 미묘한 색상 차이가 발생합니다.
이러한 문제는 기본 하드웨어의 상대 정밀도 차이와 관련이 있습니다. 일반적인 해결 방법은 사용자가 정밀도 차이를 체감하지 못하도록 낮은 정밀도 경로에 디더링 단계를 구현하는 것입니다.
이 페이지에 나와 있는 콘텐츠와 코드 샘플에는 콘텐츠 라이선스에서 설명하는 라이선스가 적용됩니다. 자바 및 OpenJDK는 Oracle 및 Oracle 계열사의 상표 또는 등록 상표입니다.
최종 업데이트: 2024-02-01(UTC)
[[["이해하기 쉬움","easyToUnderstand","thumb-up"],["문제가 해결됨","solvedMyProblem","thumb-up"],["기타","otherUp","thumb-up"]],[["필요한 정보가 없음","missingTheInformationINeed","thumb-down"],["너무 복잡함/단계 수가 너무 많음","tooComplicatedTooManySteps","thumb-down"],["오래됨","outOfDate","thumb-down"],["번역 문제","translationIssue","thumb-down"],["샘플/코드 문제","samplesCodeIssue","thumb-down"],["기타","otherDown","thumb-down"]],["최종 업데이트: 2024-02-01(UTC)"],[],[],null,["# Tone Mapping HDR Luminance to an SDR-compatible Range\n\nAndroid 13 introduces a vendor-configurable static\nlibrary called `libtonemap`, which defines tone mapping operations and is shared\nwith the SurfaceFlinger process and Hardware Composer (HWC) implementations.\nThis feature enables OEMs to define and share their display tone mapping\nalgorithms between the framework and vendors, lessening a mismatch in tone\nmapping.\n\nPrior to Android 13, display-specific tone mapping\noperations weren't shared between the HWC, SurfaceFlinger, and apps. Depending\non the rendering path, for HDR content, this led to mismatches in image quality,\nwhere the HDR content was tone mapped to an output space in different ways. This\nwas perceptible in scenarios such as screen rotation, where the composition\nstrategy changes between the GPU and the DPU, and in differences in rendering\nbehavior between TextureView and SurfaceView.\n\nThis page describes the interface, customization, and validation details of the\n`libtonemap` library.\n| **Note:** Android 16 introduces a new HDR tone mapping method called Look-up Table (LUT) for HDR video outputs instead of using `libtonemap`. LUTs primarily resolve the fragmentation issue with HDR video outputs, especially for HLG and PQ, across a diverse range of Android devices. See the AIDL API [`android.hardware.graphics.composer3.DisplayLuts`](https://cs.android.com/android/platform/superproject/+/android-latest-release:hardware/interfaces/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayLuts.aidl) for more information.\n\nInterface to the tone mapping library\n-------------------------------------\n\nThe [`libtonemap`](https://android.googlesource.com/platform/frameworks/native/+/refs/heads/android16-release/libs/tonemap/)\nlibrary contains CPU-backed implementations and SkSL shaders, which can be\nplugged in by SurfaceFlinger for GPU-backend composition and by the HWC for\ngenerating a tone mapping look-up table (LUT). The entry point to `libtonemap`\nis [`android::tonemap::getToneMapper()`](https://android.googlesource.com/platform/frameworks/native/+/refs/heads/android16-release/libs/tonemap/tonemap.cpp#733), which returns an object that\nimplements the [`ToneMapper`](https://android.googlesource.com/platform/frameworks/native/+/refs/heads/android16-release/libs/tonemap/include/tonemap/tonemap.h#86) interface.\n\nThe `ToneMapper` interface supports the following capabilities:\n\n- Generate a tone-mapping LUT\n\n The interface [`ToneMapper::lookupTonemapGain`](https://android.googlesource.com/platform/frameworks/native/+/refs/heads/android16-release/libs/tonemap/include/tonemap/tonemap.h#147) is a CPU\n implementation of the shader defined in `libtonemap_LookupTonemapGain()`. This\n is used by unit tests in the framework, and can be used by partners for\n assistance with generating a tone-mapping LUT inside their color pipeline.\n\n `libtonemap_LookupTonemapGain()` takes in color values in absolute,\n unnormalized linear space, both in linear RGB and in XYZ, and returns a float\n describing how much to multiply the input colors in linear space.\n- Generate an SkSL shader\n\n The interface [`ToneMapper::generateTonemapGainShaderSkSL()`](https://android.googlesource.com/platform/frameworks/native/+/refs/heads/android16-release/libs/tonemap/include/tonemap/tonemap.h#122) returns an\n SkSL shader string, given a source and destination dataspace. The SkSL shader is\n plugged into the Skia implementation for [`RenderEngine`](https://cs.android.com/android/platform/superproject/+/android-latest-release:frameworks/native/libs/renderengine/),\n the GPU-accelerated compositing component for SurfaceFlinger. The shader is also\n plugged into [`libhwui`](https://cs.android.com/android/platform/superproject/+/android-latest-release:frameworks/base/libs/hwui),\n so that HDR-to-SDR tone mapping can be performed efficiently for `TextureView`.\n Because the generated string is in-lined into other SkSL shaders used by Skia,\n the shader must adhere to the following rules:\n - The shader string must have an entry point with the `float libtonemap_LookupTonemapGain(vec3 linearRGB, vec3 xyz)` signature, where `linearRGB` is the value of the absolute nits of the RGB pixels in linear space and `xyz` is `linearRGB` converted into XYZ.\n - Any helper methods used by the shader string must be prefixed with the string `libtonemap_` so that framework shader definitions don't conflict. Similarly, input uniforms must be prefixed with `in_libtonemap_`.\n- Generate SkSL uniforms\n\n The interface [`ToneMapper::generateShaderSkSLUniforms()`](https://android.googlesource.com/platform/frameworks/native/+/refs/heads/android16-release/libs/tonemap/include/tonemap/tonemap.h#136) returns the\n following, given a metadata `struct` describing metadata from different HDR\n standards and display conditions:\n - A list of uniforms that are bound by an SkSL shader.\n\n - The uniform values `in_libtonemap_displayMaxLuminance` and\n `in_libtonemap_inputMaxLuminance`. These values are used by framework shaders\n when scaling the input into `libtonemap`, and normalizing the output as\n applicable.\n\n Currently the process of generating uniforms is agnostic to the input and\n output dataspace.\n\n### Customization\n\nThe reference implementation of the [`libtonemap`](https://android.googlesource.com/platform/frameworks/native/+/refs/heads/android16-release/libs/tonemap/) library produces acceptable results. However,\nbecause the tone mapping algorithm used by GPU composition can differ from that\nused by the DPU composition, using the reference implementation can cause\nflicker in some scenarios such as the rotation animation. Customization can\nresolve such vendor-specific image quality issues.\n\nOEMs are strongly encouraged to override the implementation of `libtonemap` to\ndefine their own `ToneMapper` subclass, which is returned by `getToneMapper()`.\nWhen customizing the implementation, partners are expected to do one of the\nfollowing:\n\n- Modify the implementation of `libtonemap` directly.\n- Define their own static library, compile the library as a standalone, and replace `libtonemap` library's `.a` file with the one generated from their custom library.\n\nVendors don't need to modify any kernel code, but multiple vendors must\ncommunicate details about the DPU tone-mapping algorithms for proper\nimplementation.\n\n### Validation\n\nFollow these steps to validate your implementation:\n\n1. Play HDR videos on screen of any HDR standards that your [display system supports](https://developer.android.com/reference/android/view/Display#getHdrCapabilities()),\n such as HLG, HDR10, HDR10+, or DolbyVision.\n\n2. Toggle GPU composition to ensure that there's no user perceptible flicker.\n\n Use the following `adb` command to toggle the GPU composition: \n\n adb shell service call SurfaceFlinger 1008 i32 \u003c0 to enable HWC composition,\n 1 to force GPU composition\u003e\n\n### Common issues\n\nThe following issues can occur with this implementation:\n\n- Banding is caused when the render target used by GPU composition is of lower\n precision than the typical value for HDR content. For instance, banding can\n occur when an HWC implementation supports opaque 10-bit formats for HDR such as\n RGBA1010102 or P010, but requires that GPU composition writes to an 8-bit format\n like RGBA8888 to support alpha.\n\n- A subtle color shift is caused by quantization differences if the DPU\n operates at a different precision than the GPU.\n\nEach of these issues is related to the relative precision differences of the\nunderlying hardware. A typical workaround is to ensure that there's a dithering\nstep in the lower precision paths, making any precision differences less human\nperceptible."]]