Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 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 | #include <shaders/shaders.h> |
| 18 | |
| 19 | #include <tonemap/tonemap.h> |
| 20 | |
Alec Mouri | 5a49372 | 2022-01-26 16:43:02 -0800 | [diff] [blame] | 21 | #include <cmath> |
Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 22 | #include <optional> |
| 23 | |
| 24 | #include <math/mat4.h> |
| 25 | #include <system/graphics-base-v1.0.h> |
| 26 | #include <ui/ColorSpace.h> |
| 27 | |
| 28 | namespace android::shaders { |
| 29 | |
Alec Mouri | 5a49372 | 2022-01-26 16:43:02 -0800 | [diff] [blame] | 30 | namespace { |
| 31 | |
| 32 | aidl::android::hardware::graphics::common::Dataspace toAidlDataspace(ui::Dataspace dataspace) { |
Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 33 | return static_cast<aidl::android::hardware::graphics::common::Dataspace>(dataspace); |
| 34 | } |
| 35 | |
Alec Mouri | 5a49372 | 2022-01-26 16:43:02 -0800 | [diff] [blame] | 36 | void generateXYZTransforms(std::string& shader) { |
Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 37 | shader.append(R"( |
Alec Mouri | 8a18610 | 2023-04-25 00:34:30 +0000 | [diff] [blame] | 38 | uniform float3x3 in_rgbToXyz; |
| 39 | uniform float3x3 in_xyzToSrcRgb; |
| 40 | uniform float4x4 in_colorTransform; |
Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 41 | float3 ToXYZ(float3 rgb) { |
Alec Mouri | 8a18610 | 2023-04-25 00:34:30 +0000 | [diff] [blame] | 42 | return in_rgbToXyz * rgb; |
Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 43 | } |
| 44 | |
Alec Mouri | 8a18610 | 2023-04-25 00:34:30 +0000 | [diff] [blame] | 45 | float3 ToSrcRGB(float3 xyz) { |
| 46 | return in_xyzToSrcRgb * xyz; |
| 47 | } |
| 48 | |
| 49 | float3 ApplyColorTransform(float3 rgb) { |
| 50 | return (in_colorTransform * float4(rgb, 1.0)).rgb; |
Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 51 | } |
| 52 | )"); |
| 53 | } |
| 54 | |
Alec Mouri | 8a18610 | 2023-04-25 00:34:30 +0000 | [diff] [blame] | 55 | // Conversion from relative light to absolute light |
| 56 | // Note that 1.0 == 203 nits. |
| 57 | void generateLuminanceScalesForOOTF(ui::Dataspace inputDataspace, std::string& shader) { |
Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 58 | switch (inputDataspace & HAL_DATASPACE_TRANSFER_MASK) { |
Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 59 | case HAL_DATASPACE_TRANSFER_HLG: |
Alec Mouri | 8a18610 | 2023-04-25 00:34:30 +0000 | [diff] [blame] | 60 | // BT. 2408 says that a signal level of 0.75 == 203 nits for HLG, but that's after |
| 61 | // applying OOTF. But we haven't applied OOTF yet, so we need to scale by a different |
| 62 | // constant instead. |
Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 63 | shader.append(R"( |
Alec Mouri | 8a18610 | 2023-04-25 00:34:30 +0000 | [diff] [blame] | 64 | float3 ScaleLuminance(float3 xyz) { |
| 65 | return xyz * 264.96; |
| 66 | } |
| 67 | )"); |
Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 68 | break; |
| 69 | default: |
Alec Mouri | 8a18610 | 2023-04-25 00:34:30 +0000 | [diff] [blame] | 70 | shader.append(R"( |
| 71 | float3 ScaleLuminance(float3 xyz) { |
| 72 | return xyz * 203.0; |
| 73 | } |
| 74 | )"); |
| 75 | break; |
Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 76 | } |
| 77 | } |
| 78 | |
| 79 | // Normalizes from absolute light back to relative light (maps from [0, maxNits] back to [0, 1]) |
Alec Mouri | 3e5965f | 2023-04-07 18:00:58 +0000 | [diff] [blame] | 80 | static void generateLuminanceNormalizationForOOTF(ui::Dataspace inputDataspace, |
| 81 | ui::Dataspace outputDataspace, |
Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 82 | std::string& shader) { |
| 83 | switch (outputDataspace & HAL_DATASPACE_TRANSFER_MASK) { |
| 84 | case HAL_DATASPACE_TRANSFER_ST2084: |
| 85 | shader.append(R"( |
Alec Mouri | 8a18610 | 2023-04-25 00:34:30 +0000 | [diff] [blame] | 86 | float3 NormalizeLuminance(float3 xyz) { |
| 87 | return xyz / 203.0; |
| 88 | } |
| 89 | )"); |
Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 90 | break; |
| 91 | case HAL_DATASPACE_TRANSFER_HLG: |
Alec Mouri | 3e5965f | 2023-04-07 18:00:58 +0000 | [diff] [blame] | 92 | switch (inputDataspace & HAL_DATASPACE_TRANSFER_MASK) { |
| 93 | case HAL_DATASPACE_TRANSFER_HLG: |
| 94 | shader.append(R"( |
| 95 | float3 NormalizeLuminance(float3 xyz) { |
Alec Mouri | 8a18610 | 2023-04-25 00:34:30 +0000 | [diff] [blame] | 96 | return xyz / 264.96; |
Alec Mouri | 3e5965f | 2023-04-07 18:00:58 +0000 | [diff] [blame] | 97 | } |
| 98 | )"); |
| 99 | break; |
| 100 | default: |
| 101 | // Transcoding to HLG requires applying the inverse OOTF |
| 102 | // with the expectation that the OOTF is then applied during |
| 103 | // tonemapping downstream. |
Alec Mouri | 8a18610 | 2023-04-25 00:34:30 +0000 | [diff] [blame] | 104 | // BT. 2100-2 operates on normalized luminances, so renormalize to the input to |
| 105 | // correctly adjust gamma. |
Alec Mouri | 792b150 | 2023-05-02 00:03:08 +0000 | [diff] [blame] | 106 | // Note that following BT. 2408 for HLG OETF actually maps 0.75 == ~264.96 nits, |
| 107 | // rather than 203 nits, because 203 nits == OOTF(invOETF(0.75)), so even though |
| 108 | // we originally scaled by 203 nits we need to re-normalize to 264.96 nits when |
| 109 | // converting to the correct brightness range. |
Alec Mouri | 3e5965f | 2023-04-07 18:00:58 +0000 | [diff] [blame] | 110 | shader.append(R"( |
| 111 | float3 NormalizeLuminance(float3 xyz) { |
Alec Mouri | 8a18610 | 2023-04-25 00:34:30 +0000 | [diff] [blame] | 112 | float ootfGain = pow(xyz.y / 1000.0, -0.2 / 1.2); |
Alec Mouri | 792b150 | 2023-05-02 00:03:08 +0000 | [diff] [blame] | 113 | return xyz * ootfGain / 264.96; |
Alec Mouri | 3e5965f | 2023-04-07 18:00:58 +0000 | [diff] [blame] | 114 | } |
| 115 | )"); |
| 116 | break; |
| 117 | } |
Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 118 | break; |
| 119 | default: |
Alec Mouri | 8a18610 | 2023-04-25 00:34:30 +0000 | [diff] [blame] | 120 | switch (inputDataspace & HAL_DATASPACE_TRANSFER_MASK) { |
| 121 | case HAL_DATASPACE_TRANSFER_HLG: |
| 122 | case HAL_DATASPACE_TRANSFER_ST2084: |
| 123 | // libtonemap outputs a range [0, in_libtonemap_displayMaxLuminance], so |
| 124 | // normalize back to [0, 1] when the output is SDR. |
| 125 | shader.append(R"( |
| 126 | float3 NormalizeLuminance(float3 xyz) { |
| 127 | return xyz / in_libtonemap_displayMaxLuminance; |
| 128 | } |
| 129 | )"); |
| 130 | break; |
| 131 | default: |
| 132 | // Otherwise normalize back down to the range [0, 1] |
| 133 | // TODO: get this working for extended range outputs |
| 134 | shader.append(R"( |
| 135 | float3 NormalizeLuminance(float3 xyz) { |
| 136 | return xyz / 203.0; |
| 137 | } |
| 138 | )"); |
| 139 | break; |
| 140 | } |
Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 141 | } |
| 142 | } |
| 143 | |
Alec Mouri | 5a49372 | 2022-01-26 16:43:02 -0800 | [diff] [blame] | 144 | void generateOOTF(ui::Dataspace inputDataspace, ui::Dataspace outputDataspace, |
| 145 | std::string& shader) { |
Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 146 | shader.append(tonemap::getToneMapper() |
| 147 | ->generateTonemapGainShaderSkSL(toAidlDataspace(inputDataspace), |
| 148 | toAidlDataspace(outputDataspace)) |
| 149 | .c_str()); |
| 150 | |
Alec Mouri | 8a18610 | 2023-04-25 00:34:30 +0000 | [diff] [blame] | 151 | generateLuminanceScalesForOOTF(inputDataspace, shader); |
Alec Mouri | 3e5965f | 2023-04-07 18:00:58 +0000 | [diff] [blame] | 152 | generateLuminanceNormalizationForOOTF(inputDataspace, outputDataspace, shader); |
Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 153 | |
Alec Mouri | 8a18610 | 2023-04-25 00:34:30 +0000 | [diff] [blame] | 154 | // Some tonemappers operate on CIE luminance, other tonemappers operate on linear rgb |
| 155 | // luminance in the source gamut. |
Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 156 | shader.append(R"( |
Alec Mouri | 8a18610 | 2023-04-25 00:34:30 +0000 | [diff] [blame] | 157 | float3 OOTF(float3 linearRGB) { |
Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 158 | float3 scaledLinearRGB = ScaleLuminance(linearRGB); |
Alec Mouri | 8a18610 | 2023-04-25 00:34:30 +0000 | [diff] [blame] | 159 | float3 scaledXYZ = ToXYZ(scaledLinearRGB); |
Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 160 | |
Alec Mouri | 8a18610 | 2023-04-25 00:34:30 +0000 | [diff] [blame] | 161 | float gain = libtonemap_LookupTonemapGain(ToSrcRGB(scaledXYZ), scaledXYZ); |
Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 162 | |
| 163 | return NormalizeLuminance(scaledXYZ * gain); |
| 164 | } |
| 165 | )"); |
| 166 | } |
| 167 | |
Alec Mouri | 8a18610 | 2023-04-25 00:34:30 +0000 | [diff] [blame] | 168 | void generateOETF(std::string& shader) { |
| 169 | // Only support gamma 2.2 for now |
| 170 | shader.append(R"( |
Alec Mouri | e0bb6f4 | 2023-08-02 22:41:52 +0000 | [diff] [blame^] | 171 | float3 OETF(float3 linear) { |
| 172 | return sign(linear) * pow(abs(linear), float3(1.0 / 2.2)); |
Alec Mouri | 8a18610 | 2023-04-25 00:34:30 +0000 | [diff] [blame] | 173 | } |
| 174 | )"); |
Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 175 | } |
| 176 | |
Alec Mouri | 3c51bc5 | 2022-11-04 01:28:55 +0000 | [diff] [blame] | 177 | void generateEffectiveOOTF(bool undoPremultipliedAlpha, LinearEffect::SkSLType type, |
Alec Mouri | 8a18610 | 2023-04-25 00:34:30 +0000 | [diff] [blame] | 178 | bool needsCustomOETF, std::string& shader) { |
Alec Mouri | 3c51bc5 | 2022-11-04 01:28:55 +0000 | [diff] [blame] | 179 | switch (type) { |
| 180 | case LinearEffect::SkSLType::ColorFilter: |
| 181 | shader.append(R"( |
| 182 | half4 main(half4 inputColor) { |
| 183 | float4 c = float4(inputColor); |
| 184 | )"); |
| 185 | break; |
| 186 | case LinearEffect::SkSLType::Shader: |
| 187 | shader.append(R"( |
| 188 | uniform shader child; |
| 189 | half4 main(float2 xy) { |
| 190 | float4 c = float4(child.eval(xy)); |
| 191 | )"); |
| 192 | break; |
| 193 | } |
Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 194 | if (undoPremultipliedAlpha) { |
| 195 | shader.append(R"( |
| 196 | c.rgb = c.rgb / (c.a + 0.0019); |
| 197 | )"); |
| 198 | } |
Alec Mouri | 8a18610 | 2023-04-25 00:34:30 +0000 | [diff] [blame] | 199 | // We are using linear sRGB as a working space, with 1.0 == 203 nits |
Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 200 | shader.append(R"( |
Alec Mouri | 8a18610 | 2023-04-25 00:34:30 +0000 | [diff] [blame] | 201 | c.rgb = ApplyColorTransform(OOTF(toLinearSrgb(c.rgb))); |
Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 202 | )"); |
Alec Mouri | 8a18610 | 2023-04-25 00:34:30 +0000 | [diff] [blame] | 203 | if (needsCustomOETF) { |
| 204 | shader.append(R"( |
| 205 | c.rgb = OETF(c.rgb); |
| 206 | )"); |
| 207 | } else { |
| 208 | shader.append(R"( |
| 209 | c.rgb = fromLinearSrgb(c.rgb); |
| 210 | )"); |
| 211 | } |
Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 212 | if (undoPremultipliedAlpha) { |
| 213 | shader.append(R"( |
| 214 | c.rgb = c.rgb * (c.a + 0.0019); |
| 215 | )"); |
| 216 | } |
| 217 | shader.append(R"( |
| 218 | return c; |
| 219 | } |
| 220 | )"); |
| 221 | } |
Sally Qi | 2019fd2 | 2021-11-22 10:19:04 -0800 | [diff] [blame] | 222 | |
Alec Mouri | 5a49372 | 2022-01-26 16:43:02 -0800 | [diff] [blame] | 223 | template <typename T, std::enable_if_t<std::is_trivially_copyable<T>::value, bool> = true> |
| 224 | std::vector<uint8_t> buildUniformValue(T value) { |
| 225 | std::vector<uint8_t> result; |
| 226 | result.resize(sizeof(value)); |
| 227 | std::memcpy(result.data(), &value, sizeof(value)); |
| 228 | return result; |
| 229 | } |
| 230 | |
Alec Mouri | 5a49372 | 2022-01-26 16:43:02 -0800 | [diff] [blame] | 231 | } // namespace |
| 232 | |
Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 233 | std::string buildLinearEffectSkSL(const LinearEffect& linearEffect) { |
| 234 | std::string shaderString; |
Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 235 | generateXYZTransforms(shaderString); |
| 236 | generateOOTF(linearEffect.inputDataspace, linearEffect.outputDataspace, shaderString); |
Alec Mouri | 8a18610 | 2023-04-25 00:34:30 +0000 | [diff] [blame] | 237 | |
| 238 | const bool needsCustomOETF = (linearEffect.fakeOutputDataspace & HAL_DATASPACE_TRANSFER_MASK) == |
| 239 | HAL_DATASPACE_TRANSFER_GAMMA2_2; |
| 240 | if (needsCustomOETF) { |
| 241 | generateOETF(shaderString); |
| 242 | } |
| 243 | generateEffectiveOOTF(linearEffect.undoPremultipliedAlpha, linearEffect.type, needsCustomOETF, |
| 244 | shaderString); |
Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 245 | return shaderString; |
| 246 | } |
| 247 | |
Alec Mouri | 8a18610 | 2023-04-25 00:34:30 +0000 | [diff] [blame] | 248 | ColorSpace toColorSpace(ui::Dataspace dataspace) { |
| 249 | switch (dataspace & HAL_DATASPACE_STANDARD_MASK) { |
| 250 | case HAL_DATASPACE_STANDARD_BT709: |
| 251 | return ColorSpace::sRGB(); |
| 252 | case HAL_DATASPACE_STANDARD_DCI_P3: |
| 253 | return ColorSpace::DisplayP3(); |
| 254 | case HAL_DATASPACE_STANDARD_BT2020: |
| 255 | case HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE: |
| 256 | return ColorSpace::BT2020(); |
| 257 | case HAL_DATASPACE_STANDARD_ADOBE_RGB: |
| 258 | return ColorSpace::AdobeRGB(); |
| 259 | // TODO(b/208290320): BT601 format and variants return different primaries |
| 260 | case HAL_DATASPACE_STANDARD_BT601_625: |
| 261 | case HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED: |
| 262 | case HAL_DATASPACE_STANDARD_BT601_525: |
| 263 | case HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED: |
| 264 | // TODO(b/208290329): BT407M format returns different primaries |
| 265 | case HAL_DATASPACE_STANDARD_BT470M: |
| 266 | // TODO(b/208290904): FILM format returns different primaries |
| 267 | case HAL_DATASPACE_STANDARD_FILM: |
| 268 | case HAL_DATASPACE_STANDARD_UNSPECIFIED: |
| 269 | default: |
| 270 | return ColorSpace::sRGB(); |
| 271 | } |
| 272 | } |
| 273 | |
Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 274 | // Generates a list of uniforms to set on the LinearEffect shader above. |
Alec Mouri | fcedb9c | 2022-04-11 20:02:17 +0000 | [diff] [blame] | 275 | std::vector<tonemap::ShaderUniform> buildLinearEffectUniforms( |
| 276 | const LinearEffect& linearEffect, const mat4& colorTransform, float maxDisplayLuminance, |
| 277 | float currentDisplayLuminanceNits, float maxLuminance, AHardwareBuffer* buffer, |
| 278 | aidl::android::hardware::graphics::composer3::RenderIntent renderIntent) { |
Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 279 | std::vector<tonemap::ShaderUniform> uniforms; |
Alec Mouri | 6ba7f2b | 2022-06-02 22:55:05 +0000 | [diff] [blame] | 280 | |
Alec Mouri | 8a18610 | 2023-04-25 00:34:30 +0000 | [diff] [blame] | 281 | auto inputColorSpace = toColorSpace(linearEffect.inputDataspace); |
| 282 | auto outputColorSpace = toColorSpace(linearEffect.outputDataspace); |
Alec Mouri | 6ba7f2b | 2022-06-02 22:55:05 +0000 | [diff] [blame] | 283 | |
Alec Mouri | 8a18610 | 2023-04-25 00:34:30 +0000 | [diff] [blame] | 284 | uniforms.push_back( |
| 285 | {.name = "in_rgbToXyz", |
| 286 | .value = buildUniformValue<mat3>(ColorSpace::linearExtendedSRGB().getRGBtoXYZ())}); |
| 287 | uniforms.push_back({.name = "in_xyzToSrcRgb", |
| 288 | .value = buildUniformValue<mat3>(inputColorSpace.getXYZtoRGB())}); |
| 289 | // Transforms xyz colors to linear source colors, then applies the color transform, then |
| 290 | // transforms to linear extended RGB for skia to color manage. |
| 291 | uniforms.push_back({.name = "in_colorTransform", |
| 292 | .value = buildUniformValue<mat4>( |
| 293 | mat4(ColorSpace::linearExtendedSRGB().getXYZtoRGB()) * |
| 294 | // TODO: the color transform ideally should be applied |
| 295 | // in the source colorspace, but doing that breaks |
| 296 | // renderengine tests |
| 297 | mat4(outputColorSpace.getRGBtoXYZ()) * colorTransform * |
| 298 | mat4(outputColorSpace.getXYZtoRGB()))}); |
Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 299 | |
| 300 | tonemap::Metadata metadata{.displayMaxLuminance = maxDisplayLuminance, |
Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 301 | // If the input luminance is unknown, use display luminance (aka, |
Alec Mouri | 3e5965f | 2023-04-07 18:00:58 +0000 | [diff] [blame] | 302 | // no-op any luminance changes). |
| 303 | // This is expected to only be meaningful for PQ content |
Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 304 | .contentMaxLuminance = |
Alec Mouri | 1a3c545 | 2022-03-04 22:44:51 +0000 | [diff] [blame] | 305 | maxLuminance > 0 ? maxLuminance : maxDisplayLuminance, |
Alec Mouri | 7a57745 | 2022-03-04 23:41:38 +0000 | [diff] [blame] | 306 | .currentDisplayLuminance = currentDisplayLuminanceNits > 0 |
| 307 | ? currentDisplayLuminanceNits |
| 308 | : maxDisplayLuminance, |
Alec Mouri | fcedb9c | 2022-04-11 20:02:17 +0000 | [diff] [blame] | 309 | .buffer = buffer, |
| 310 | .renderIntent = renderIntent}; |
Alec Mouri | 492c85c | 2021-11-19 15:58:10 -0800 | [diff] [blame] | 311 | |
| 312 | for (const auto uniform : tonemap::getToneMapper()->generateShaderSkSLUniforms(metadata)) { |
| 313 | uniforms.push_back(uniform); |
| 314 | } |
| 315 | |
| 316 | return uniforms; |
| 317 | } |
| 318 | |
Alec Mouri | 1a3c545 | 2022-03-04 22:44:51 +0000 | [diff] [blame] | 319 | } // namespace android::shaders |