xref: /aosp_15_r20/frameworks/native/libs/renderengine/skia/filters/GainmapFactory.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1 /*
2  * Copyright 2024 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 "GainmapFactory.h"
18 
19 #include <log/log.h>
20 
21 namespace android {
22 namespace renderengine {
23 namespace skia {
24 namespace {
25 
makeEffect(const SkString & sksl)26 sk_sp<SkRuntimeEffect> makeEffect(const SkString& sksl) {
27     auto [effect, error] = SkRuntimeEffect::MakeForShader(sksl);
28     LOG_ALWAYS_FATAL_IF(!effect, "RuntimeShader error: %s", error.c_str());
29     return effect;
30 }
31 
32 // Please refer to https://developer.android.com/media/platform/hdr-image-format#gain_map-generation
33 static const SkString kGainmapShader = SkString(R"(
34     uniform shader sdr;
35     uniform shader hdr;
36     uniform float mapMaxLog2;
37 
38     const float mapMinLog2 = 0.0;
39     const float mapGamma = 1.0;
40     const float offsetSdr = 0.015625;
41     const float offsetHdr = 0.015625;
42 
43     float luminance(vec3 linearColor) {
44         return 0.2126 * linearColor.r + 0.7152 * linearColor.g + 0.0722 * linearColor.b;
45     }
46 
47     vec4 main(vec2 xy) {
48         float sdrY = luminance(toLinearSrgb(sdr.eval(xy).rgb));
49         float hdrY = luminance(toLinearSrgb(hdr.eval(xy).rgb));
50         float pixelGain = (hdrY + offsetHdr) / (sdrY + offsetSdr);
51         float logRecovery = (log2(pixelGain) - mapMinLog2) / (mapMaxLog2 - mapMinLog2);
52         return vec4(pow(clamp(logRecovery, 0.0, 1.0), mapGamma));
53     }
54 )");
55 } // namespace
56 
57 const float INTERPOLATION_STRENGTH_VALUE = 0.7f;
58 
GainmapFactory()59 GainmapFactory::GainmapFactory() : mEffect(makeEffect(kGainmapShader)) {}
60 
createSkShader(const sk_sp<SkShader> & sdr,const sk_sp<SkShader> & hdr,float hdrSdrRatio)61 sk_sp<SkShader> GainmapFactory::createSkShader(const sk_sp<SkShader>& sdr,
62                                                const sk_sp<SkShader>& hdr, float hdrSdrRatio) {
63     SkRuntimeShaderBuilder shaderBuilder(mEffect);
64     shaderBuilder.child("sdr") = sdr;
65     shaderBuilder.child("hdr") = hdr;
66     shaderBuilder.uniform("mapMaxLog2") = std::log2(hdrSdrRatio);
67     return shaderBuilder.makeShader();
68 }
69 
70 } // namespace skia
71 } // namespace renderengine
72 } // namespace android
73