/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "GainmapRenderer.h"

#include <SkGainmapShader.h>

#include "Gainmap.h"
#include "Rect.h"
#include "utils/Trace.h"

#ifdef __ANDROID__
#include "include/core/SkColorSpace.h"
#include "include/core/SkImage.h"
#include "include/core/SkShader.h"
#include "include/effects/SkRuntimeEffect.h"
#include "include/private/SkGainmapInfo.h"
#include "renderthread/CanvasContext.h"
#include "src/core/SkColorFilterPriv.h"
#include "src/core/SkImageInfoPriv.h"
#include "src/core/SkRuntimeEffectPriv.h"
#endif

namespace android::uirenderer {

using namespace renderthread;

float getTargetHdrSdrRatio(const SkColorSpace* destColorspace) {
    // We should always have a known destination colorspace. If we don't we must be in some
    // legacy mode where we're lost and also definitely not going to HDR
    if (destColorspace == nullptr) {
        return 1.f;
    }

    constexpr float GenericSdrWhiteNits = 203.f;
    constexpr float maxPQLux = 10000.f;
    constexpr float maxHLGLux = 1000.f;
    skcms_TransferFunction destTF;
    destColorspace->transferFn(&destTF);
    if (skcms_TransferFunction_isPQish(&destTF)) {
        return maxPQLux / GenericSdrWhiteNits;
    } else if (skcms_TransferFunction_isHLGish(&destTF)) {
        return maxHLGLux / GenericSdrWhiteNits;
#ifdef __ANDROID__
    } else if (RenderThread::isCurrent()) {
        CanvasContext* context = CanvasContext::getActiveContext();
        return context ? context->targetSdrHdrRatio() : 1.f;
#endif
    }
    return 1.f;
}

void DrawGainmapBitmap(SkCanvas* c, const sk_sp<const SkImage>& image, const SkRect& src,
                       const SkRect& dst, const SkSamplingOptions& sampling, const SkPaint* paint,
                       SkCanvas::SrcRectConstraint constraint,
                       const sk_sp<const SkImage>& gainmapImage, const SkGainmapInfo& gainmapInfo) {
    ATRACE_CALL();
#ifdef __ANDROID__
    auto destColorspace = c->imageInfo().refColorSpace();
    float targetSdrHdrRatio = getTargetHdrSdrRatio(destColorspace.get());
    if (targetSdrHdrRatio > 1.f && gainmapImage) {
        SkPaint gainmapPaint = *paint;
        float sX = gainmapImage->width() / (float)image->width();
        float sY = gainmapImage->height() / (float)image->height();
        SkRect gainmapSrc = src;
        // TODO: Tweak rounding?
        gainmapSrc.fLeft *= sX;
        gainmapSrc.fRight *= sX;
        gainmapSrc.fTop *= sY;
        gainmapSrc.fBottom *= sY;
        auto shader =
                SkGainmapShader::Make(image, src, sampling, gainmapImage, gainmapSrc, sampling,
                                      gainmapInfo, dst, targetSdrHdrRatio, destColorspace);
        gainmapPaint.setShader(shader);
        c->drawRect(dst, gainmapPaint);
    } else
#endif
        c->drawImageRect(image.get(), src, dst, sampling, paint, constraint);
}

#ifdef __ANDROID__

static constexpr char gGainmapSKSL[] = R"SKSL(
    uniform shader base;
    uniform shader gainmap;
    uniform colorFilter workingSpaceToLinearSrgb;
    uniform half4 logRatioMin;
    uniform half4 logRatioMax;
    uniform half4 gainmapGamma;
    uniform half4 epsilonSdr;
    uniform half4 epsilonHdr;
    uniform half W;
    uniform int gainmapIsAlpha;
    uniform int gainmapIsRed;
    uniform int singleChannel;
    uniform int noGamma;

    half4 toDest(half4 working) {
        half4 ls = workingSpaceToLinearSrgb.eval(working);
        vec3 dest = fromLinearSrgb(ls.rgb);
        return half4(dest.r, dest.g, dest.b, ls.a);
    }

    half4 main(float2 coord) {
        half4 S = base.eval(coord);
        half4 G = gainmap.eval(coord);
        if (gainmapIsAlpha == 1) {
            G = half4(G.a, G.a, G.a, 1.0);
        }
        if (gainmapIsRed == 1) {
            G = half4(G.r, G.r, G.r, 1.0);
        }
        if (singleChannel == 1) {
            half L;
            if (noGamma == 1) {
                L = mix(logRatioMin.r, logRatioMax.r, G.r);
            } else {
                L = mix(logRatioMin.r, logRatioMax.r, pow(G.r, gainmapGamma.r));
            }
            half3 H = (S.rgb + epsilonSdr.rgb) * exp(L * W) - epsilonHdr.rgb;
            return toDest(half4(H.r, H.g, H.b, S.a));
        } else {
            half3 L;
            if (noGamma == 1) {
                L = mix(logRatioMin.rgb, logRatioMax.rgb, G.rgb);
            } else {
                L = mix(logRatioMin.rgb, logRatioMax.rgb, pow(G.rgb, gainmapGamma.rgb));
            }
            half3 H = (S.rgb + epsilonSdr.rgb) * exp(L * W) - epsilonHdr.rgb;
            return toDest(half4(H.r, H.g, H.b, S.a));
        }
    }
)SKSL";

static sk_sp<SkRuntimeEffect> gainmap_apply_effect() {
    static const SkRuntimeEffect* effect = []() -> SkRuntimeEffect* {
        auto buildResult = SkRuntimeEffect::MakeForShader(SkString(gGainmapSKSL), {});
        if (buildResult.effect) {
            return buildResult.effect.release();
        } else {
            LOG_ALWAYS_FATAL("Failed to build gainmap shader: %s", buildResult.errorText.c_str());
        }
    }();
    SkASSERT(effect);
    return sk_ref_sp(effect);
}

static bool all_channels_equal(const SkColor4f& c) {
    return c.fR == c.fG && c.fR == c.fB;
}

class DeferredGainmapShader {
private:
    sk_sp<SkRuntimeEffect> mShader{gainmap_apply_effect()};
    SkRuntimeShaderBuilder mBuilder{mShader};
    SkGainmapInfo mGainmapInfo;
    std::mutex mUniformGuard;

    void setupChildren(const sk_sp<const SkImage>& baseImage,
                       const sk_sp<const SkImage>& gainmapImage, SkTileMode tileModeX,
                       SkTileMode tileModeY, const SkSamplingOptions& samplingOptions) {
        sk_sp<SkColorSpace> baseColorSpace =
                baseImage->colorSpace() ? baseImage->refColorSpace() : SkColorSpace::MakeSRGB();

        // Determine the color space in which the gainmap math is to be applied.
        sk_sp<SkColorSpace> gainmapMathColorSpace = baseColorSpace->makeLinearGamma();

        // Create a color filter to transform from the base image's color space to the color space
        // in which the gainmap is to be applied.
        auto colorXformSdrToGainmap =
                SkColorFilterPriv::MakeColorSpaceXform(baseColorSpace, gainmapMathColorSpace);

        // The base image shader will convert into the color space in which the gainmap is applied.
        auto baseImageShader = baseImage->makeRawShader(tileModeX, tileModeY, samplingOptions)
                                       ->makeWithColorFilter(colorXformSdrToGainmap);

        // The gainmap image shader will ignore any color space that the gainmap has.
        const SkMatrix gainmapRectToDstRect =
                SkMatrix::RectToRect(SkRect::MakeWH(gainmapImage->width(), gainmapImage->height()),
                                     SkRect::MakeWH(baseImage->width(), baseImage->height()));
        auto gainmapImageShader = gainmapImage->makeRawShader(tileModeX, tileModeY, samplingOptions,
                                                              &gainmapRectToDstRect);

        // Create a color filter to transform from the color space in which the gainmap is applied
        // to the intermediate destination color space.
        auto colorXformGainmapToDst = SkColorFilterPriv::MakeColorSpaceXform(
                gainmapMathColorSpace, SkColorSpace::MakeSRGBLinear());

        mBuilder.child("base") = std::move(baseImageShader);
        mBuilder.child("gainmap") = std::move(gainmapImageShader);
        mBuilder.child("workingSpaceToLinearSrgb") = std::move(colorXformGainmapToDst);
    }

    void setupGenericUniforms(const sk_sp<const SkImage>& gainmapImage,
                              const SkGainmapInfo& gainmapInfo) {
        const SkColor4f logRatioMin({sk_float_log(gainmapInfo.fGainmapRatioMin.fR),
                                     sk_float_log(gainmapInfo.fGainmapRatioMin.fG),
                                     sk_float_log(gainmapInfo.fGainmapRatioMin.fB), 1.f});
        const SkColor4f logRatioMax({sk_float_log(gainmapInfo.fGainmapRatioMax.fR),
                                     sk_float_log(gainmapInfo.fGainmapRatioMax.fG),
                                     sk_float_log(gainmapInfo.fGainmapRatioMax.fB), 1.f});
        const int noGamma = gainmapInfo.fGainmapGamma.fR == 1.f &&
                            gainmapInfo.fGainmapGamma.fG == 1.f &&
                            gainmapInfo.fGainmapGamma.fB == 1.f;
        const uint32_t colorTypeFlags = SkColorTypeChannelFlags(gainmapImage->colorType());
        const int gainmapIsAlpha = colorTypeFlags == kAlpha_SkColorChannelFlag;
        const int gainmapIsRed = colorTypeFlags == kRed_SkColorChannelFlag;
        const int singleChannel = all_channels_equal(gainmapInfo.fGainmapGamma) &&
                                  all_channels_equal(gainmapInfo.fGainmapRatioMin) &&
                                  all_channels_equal(gainmapInfo.fGainmapRatioMax) &&
                                  (colorTypeFlags == kGray_SkColorChannelFlag ||
                                   colorTypeFlags == kAlpha_SkColorChannelFlag ||
                                   colorTypeFlags == kRed_SkColorChannelFlag);
        mBuilder.uniform("logRatioMin") = logRatioMin;
        mBuilder.uniform("logRatioMax") = logRatioMax;
        mBuilder.uniform("gainmapGamma") = gainmapInfo.fGainmapGamma;
        mBuilder.uniform("epsilonSdr") = gainmapInfo.fEpsilonSdr;
        mBuilder.uniform("epsilonHdr") = gainmapInfo.fEpsilonHdr;
        mBuilder.uniform("noGamma") = noGamma;
        mBuilder.uniform("singleChannel") = singleChannel;
        mBuilder.uniform("gainmapIsAlpha") = gainmapIsAlpha;
        mBuilder.uniform("gainmapIsRed") = gainmapIsRed;
    }

    sk_sp<const SkData> build(float targetHdrSdrRatio) {
        sk_sp<const SkData> uniforms;
        {
            // If we are called concurrently from multiple threads, we need to guard the call
            // to writableUniforms() which mutates mUniform. This is otherwise safe because
            // writeableUniforms() will make a copy if it's not unique before mutating
            // This can happen if a BitmapShader is used on multiple canvas', such as a
            // software + hardware canvas, which is otherwise valid as SkShader is "immutable"
            std::lock_guard _lock(mUniformGuard);
            // Compute the weight parameter that will be used to blend between the images.
            float W = 0.f;
            if (targetHdrSdrRatio > mGainmapInfo.fDisplayRatioSdr) {
                if (targetHdrSdrRatio < mGainmapInfo.fDisplayRatioHdr) {
                    W = (sk_float_log(targetHdrSdrRatio) -
                         sk_float_log(mGainmapInfo.fDisplayRatioSdr)) /
                        (sk_float_log(mGainmapInfo.fDisplayRatioHdr) -
                         sk_float_log(mGainmapInfo.fDisplayRatioSdr));
                } else {
                    W = 1.f;
                }
            }
            mBuilder.uniform("W") = W;
            uniforms = mBuilder.uniforms();
        }
        return uniforms;
    }

public:
    explicit DeferredGainmapShader(const sk_sp<const SkImage>& image,
                                   const sk_sp<const SkImage>& gainmapImage,
                                   const SkGainmapInfo& gainmapInfo, SkTileMode tileModeX,
                                   SkTileMode tileModeY, const SkSamplingOptions& sampling) {
        mGainmapInfo = gainmapInfo;
        setupChildren(image, gainmapImage, tileModeX, tileModeY, sampling);
        setupGenericUniforms(gainmapImage, gainmapInfo);
    }

    static sk_sp<SkShader> Make(const sk_sp<const SkImage>& image,
                                const sk_sp<const SkImage>& gainmapImage,
                                const SkGainmapInfo& gainmapInfo, SkTileMode tileModeX,
                                SkTileMode tileModeY, const SkSamplingOptions& sampling) {
        auto deferredHandler = std::make_shared<DeferredGainmapShader>(
                image, gainmapImage, gainmapInfo, tileModeX, tileModeY, sampling);
        auto callback =
                [deferredHandler](const SkRuntimeEffectPriv::UniformsCallbackContext& renderContext)
                -> sk_sp<const SkData> {
            return deferredHandler->build(getTargetHdrSdrRatio(renderContext.fDstColorSpace));
        };
        return SkRuntimeEffectPriv::MakeDeferredShader(deferredHandler->mShader.get(), callback,
                                                       deferredHandler->mBuilder.children());
    }
};

sk_sp<SkShader> MakeGainmapShader(const sk_sp<const SkImage>& image,
                                  const sk_sp<const SkImage>& gainmapImage,
                                  const SkGainmapInfo& gainmapInfo, SkTileMode tileModeX,
                                  SkTileMode tileModeY, const SkSamplingOptions& sampling) {
    return DeferredGainmapShader::Make(image, gainmapImage, gainmapInfo, tileModeX, tileModeY,
                                       sampling);
}

#else  // __ANDROID__

sk_sp<SkShader> MakeGainmapShader(const sk_sp<const SkImage>& image,
                                  const sk_sp<const SkImage>& gainmapImage,
                                  const SkGainmapInfo& gainmapInfo, SkTileMode tileModeX,
                                  SkTileMode tileModeY, const SkSamplingOptions& sampling) {
        return nullptr;
}

#endif  // __ANDROID__

}  // namespace android::uirenderer