1 /* 2 * Copyright 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <aidl/android/hardware/graphics/common/Dataspace.h> 20 #include <aidl/android/hardware/graphics/composer3/RenderIntent.h> 21 #include <android/hardware_buffer.h> 22 #include <math/vec3.h> 23 24 #include <string> 25 #include <vector> 26 27 namespace android::tonemap { 28 29 // Describes a shader uniform 30 // The shader uniform is intended to be passed into a SkRuntimeShaderBuilder, i.e.: 31 // 32 // SkRuntimeShaderBuilder builder; 33 // builder.uniform(<uniform name>).set(<uniform value>.data(), <uniform value>.size()); 34 struct ShaderUniform { 35 // The name of the uniform, used for binding into a shader. 36 // The shader must contain a uniform whose name matches this. 37 std::string name; 38 39 // The value for the uniform, which should be bound to the uniform identified by <name> 40 std::vector<uint8_t> value; 41 }; 42 43 // Describes metadata which may be used for constructing the shader uniforms. 44 // This metadata should not be used for manipulating the source code of the shader program directly, 45 // as otherwise caching by other parts of the system using these shaders may break. 46 struct Metadata { 47 // The maximum luminance of the display in nits 48 float displayMaxLuminance = 0.0; 49 50 // The maximum luminance of the content in nits 51 float contentMaxLuminance = 0.0; 52 53 // The current brightness of the display in nits 54 float currentDisplayLuminance = 0.0; 55 56 // Reference to an AHardwareBuffer. 57 // Devices that support gralloc 4.0 and higher may attach metadata onto a 58 // particular frame's buffer, including metadata used by HDR-standards like 59 // SMPTE 2086 or SMPTE 2094-40. 60 // Note that this parameter may be optional if there is no hardware buffer 61 // available, for instance if the source content is generated from a GL 62 // texture that does not have associated metadata. As such, implementations 63 // must support nullptr. 64 AHardwareBuffer* buffer = nullptr; 65 66 // RenderIntent of the destination display. 67 // Non-colorimetric render-intents may be defined in order to take advantage of the full display 68 // gamut. Various contrast-enhancement mechanisms may be employed on SDR content as a result, 69 // which means that HDR content may need to be compensated in order to achieve correct blending 70 // behavior. This default is effectively optional - the display render intent may not be 71 // available to clients such as HWUI which are display-agnostic. For those clients, tone-map 72 // colorimetric may be assumed so that the luminance range may be converted to the correct range 73 // based on the output dataspace. 74 aidl::android::hardware::graphics::composer3::RenderIntent renderIntent = 75 aidl::android::hardware::graphics::composer3::RenderIntent::TONE_MAP_COLORIMETRIC; 76 }; 77 78 // Utility class containing pre-processed conversions for a particular color 79 struct Color { 80 // RGB color in linear space 81 vec3 linearRGB; 82 // CIE 1931 XYZ representation of the color 83 vec3 xyz; 84 }; 85 86 class ToneMapper { 87 public: ~ToneMapper()88 virtual ~ToneMapper() {} 89 // Constructs a tonemap shader whose shader language is SkSL, which tonemaps from an 90 // input whose dataspace is described by sourceDataspace, to an output whose dataspace 91 // is described by destinationDataspace 92 // 93 // The returned shader string *must* contain a function with the following signature: 94 // float libtonemap_LookupTonemapGain(vec3 linearRGB, vec3 xyz); 95 // 96 // The arguments are: 97 // * linearRGB is the absolute nits of the RGB pixels in linear space 98 // * xyz is linearRGB converted into XYZ 99 // 100 // libtonemap_LookupTonemapGain() returns a float representing the amount by which to scale the 101 // absolute nits of the pixels. This function may be plugged into any existing SkSL shader, and 102 // is expected to look something like this: 103 // 104 // vec3 rgb = ...; 105 // // apply the EOTF based on the incoming dataspace to convert to linear nits. 106 // vec3 linearRGB = applyEOTF(rgb); 107 // // apply a RGB->XYZ matrix float3 108 // vec3 xyz = toXYZ(linearRGB); 109 // // Scale the luminance based on the content standard 110 // vec3 absoluteRGB = ScaleLuminance(linearRGB); 111 // vec3 absoluteXYZ = ScaleLuminance(xyz); 112 // float gain = libtonemap_LookupTonemapGain(absoluteRGB, absoluteXYZ); 113 // // Normalize the luminance back down to a [0, 1] range 114 // xyz = NormalizeLuminance(absoluteXYZ * gain); 115 // // apply a XYZ->RGB matrix and apply the output OETf. 116 // vec3 finalColor = applyOETF(ToRGB(xyz)); 117 // ... 118 // 119 // Helper methods in this shader should be prefixed with "libtonemap_". Accordingly, libraries 120 // which consume this shader must *not* contain any methods prefixed with "libtonemap_" to 121 // guarantee that there are no conflicts in name resolution. 122 virtual std::string generateTonemapGainShaderSkSL( 123 aidl::android::hardware::graphics::common::Dataspace sourceDataspace, 124 aidl::android::hardware::graphics::common::Dataspace destinationDataspace) = 0; 125 126 // Constructs uniform descriptions that correspond to those that are generated for the tonemap 127 // shader. Uniforms must be prefixed with "in_libtonemap_". Libraries which consume this shader 128 // must not bind any new uniforms that begin with this prefix. 129 // 130 // Downstream shaders may assume the existence of the uniform in_libtonemap_displayMaxLuminance 131 // and in_libtonemap_inputMaxLuminance, in order to assist with scaling and normalizing 132 // luminance as described in the documentation for generateTonemapGainShaderSkSL(). That is, 133 // shaders plugging in a tone-mapping shader returned by generateTonemapGainShaderSkSL() may 134 // assume that there are predefined floats in_libtonemap_displayMaxLuminance and 135 // in_libtonemap_inputMaxLuminance inside of the body of the tone-mapping shader. 136 virtual std::vector<ShaderUniform> generateShaderSkSLUniforms(const Metadata& metadata) = 0; 137 138 // CPU implementation of the tonemapping gain. This must match the GPU implementation returned 139 // by generateTonemapGainShaderSKSL() above, with some epsilon difference to account for 140 // differences in hardware precision. 141 // 142 // The gain is computed assuming an input described by sourceDataspace, tonemapped to an output 143 // described by destinationDataspace. To compute the gain, the input colors are provided by 144 // linearRGB, which is the RGB colors in linear space. The colors in XYZ space are also 145 // provided. Metadata is also provided for helping to compute the tonemapping curve. 146 using Gain = double; 147 virtual std::vector<Gain> lookupTonemapGain( 148 aidl::android::hardware::graphics::common::Dataspace sourceDataspace, 149 aidl::android::hardware::graphics::common::Dataspace destinationDataspace, 150 const std::vector<Color>& colors, const Metadata& metadata) = 0; 151 }; 152 153 // Retrieves a tonemapper instance. 154 // This instance is globally constructed. 155 ToneMapper* getToneMapper(); 156 157 } // namespace android::tonemap 158