/*
 * Copyright 2024 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/core/SkKnownRuntimeEffects.h"

#include "include/core/SkString.h"
#include "include/effects/SkRuntimeEffect.h"
#include "include/private/SkAssert.h"
#include "src/core/SkRuntimeEffectPriv.h"
#include "src/effects/imagefilters/SkMatrixConvolutionImageFilter.h"

namespace SkKnownRuntimeEffects {

namespace {

SkRuntimeEffect::Options get_options(StableKey stableKey) {
    SkRuntimeEffect::Options options;
    SkRuntimeEffectPriv::SetStableKeyOnOptions(&options, static_cast<uint32_t>(stableKey));
    SkRuntimeEffectPriv::AllowPrivateAccess(&options);
    return options;
}

// This must be kept in sync w/ the version in BlurUtils.h
static constexpr int kMaxBlurSamples = 28;

SkRuntimeEffect* make_blur_1D_shader(int kernelWidth, StableKey stableKey) {
    SkRuntimeEffect::Options options = get_options(stableKey);

    SkASSERT(kernelWidth <= kMaxBlurSamples);
    // The SkSL structure performs two kernel taps; if the kernel has an odd width the last
    // sample will be skipped with the current loop limit calculation.
    SkASSERT(kernelWidth % 2 == 0);
    return SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader,
            SkStringPrintf(
                    // The coefficients are always stored for the max radius to keep the
                    // uniform block consistent across all effects.
                    "const int kMaxUniformKernelSize = %d / 2;"
                    // But we generate an exact loop over the kernel size. Note that this
                    // program can be used for kernels smaller than the constructed max as long
                    // as the kernel weights for excess entries are set to 0.
                    "const int kMaxLoopLimit = %d / 2;"

                    "uniform half4 offsetsAndKernel[kMaxUniformKernelSize];"
                    "uniform half2 dir;"

                    "uniform shader child;"

                    "half4 main(float2 coord) {"
                        "half4 sum = half4(0);"
                        "for (int i = 0; i < kMaxLoopLimit; ++i) {"
                            "half4 s = offsetsAndKernel[i];"
                            "sum += s.y * child.eval(coord + s.x*dir);"
                            "sum += s.w * child.eval(coord + s.z*dir);"
                        "}"
                        "return sum;"
                    "}", kMaxBlurSamples, kernelWidth).c_str(),
                    options);
}

SkRuntimeEffect* make_blur_2D_shader(int maxKernelSize, StableKey stableKey) {
    SkRuntimeEffect::Options options = get_options(stableKey);

    SkASSERT(maxKernelSize % 4 == 0);
    return SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader,
            SkStringPrintf(
                    // The coefficients are always stored for the max radius to keep the
                    // uniform block consistent across all effects.
                    "const int kMaxUniformKernelSize = %d / 4;"
                    "const int kMaxUniformOffsetsSize = 2*kMaxUniformKernelSize;"
                    // But we generate an exact loop over the kernel size. Note that this
                    // program can be used for kernels smaller than the constructed max as long
                    // as the kernel weights for excess entries are set to 0.
                    "const int kMaxLoopLimit = %d / 4;"

                    // Pack scalar coefficients into half4 for better packing on std140, and
                    // upload offsets to avoid having to transform the 1D index into a 2D coord
                    "uniform half4 kernel[kMaxUniformKernelSize];"
                    "uniform half4 offsets[kMaxUniformOffsetsSize];"

                    "uniform shader child;"

                    "half4 main(float2 coord) {"
                        "half4 sum = half4(0);"

                        "for (int i = 0; i < kMaxLoopLimit; ++i) {"
                            "half4 k = kernel[i];"
                            "half4 o = offsets[2*i];"
                            "sum += k.x * child.eval(coord + o.xy);"
                            "sum += k.y * child.eval(coord + o.zw);"
                            "o = offsets[2*i + 1];"
                            "sum += k.z * child.eval(coord + o.xy);"
                            "sum += k.w * child.eval(coord + o.zw);"
                        "}"
                        "return sum;"
                    "}", kMaxBlurSamples, maxKernelSize).c_str(),
                    options);
}

SkRuntimeEffect* make_blend_shader() {
    SkRuntimeEffect::Options options = get_options(StableKey::kBlend);

    static constexpr char kBlendShaderCode[] =
        "uniform shader s, d;"
        "uniform blender b;"
        "half4 main(float2 xy) {"
            "return b.eval(s.eval(xy), d.eval(xy));"
        "}";

    return SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader,
                               kBlendShaderCode,
                               options);
}

SkRuntimeEffect* make_lerp_shader() {
    SkRuntimeEffect::Options options = get_options(StableKey::kLerp);

    static constexpr char kLerpFilterCode[] =
        "uniform colorFilter cf0;"
        "uniform colorFilter cf1;"
        "uniform half weight;"

        "half4 main(half4 color) {"
            "return mix(cf0.eval(color), cf1.eval(color), weight);"
        "}";

    return SkMakeRuntimeEffect(SkRuntimeEffect::MakeForColorFilter,
                               kLerpFilterCode,
                               options);
}

enum class MatrixConvolutionImpl {
    kUniformBased,
    kTextureBasedSm,
    kTextureBasedLg,
};

// There are three shader variants:
//    a smaller kernel version that stores the matrix in uniforms and iterates in 1D
//    a larger kernel version that stores the matrix in a 1D texture. The texture version has small
//    and large variants w/ the actual kernel size uploaded as a uniform.
SkRuntimeEffect* make_matrix_conv_shader(MatrixConvolutionImpl impl, StableKey stableKey) {
    SkRuntimeEffect::Options options = get_options(stableKey);

    // While the uniforms and kernel access are different, pieces of the algorithm are common and
    // defined statically for re-use in the two shaders:
    static const char* kHeaderAndBeginLoopSkSL =
        "uniform int2 size;"
        "uniform int2 offset;"
        "uniform half2 gainAndBias;"
        "uniform int convolveAlpha;" // FIXME not a full  int? Put in a half3 w/ gainAndBias?

        "uniform shader child;"

        "half4 main(float2 coord) {"
            "half4 sum = half4(0);"
            "half origAlpha = 0;"
            "int2 kernelPos = int2(0);"
            "for (int i = 0; i < kMaxKernelSize; ++i) {"
                "if (kernelPos.y >= size.y) { break; }";

    // Used in the inner loop to accumulate convolution sum and increment the kernel position
    static const char* kAccumulateAndIncrementSkSL =
                "half4 c = child.eval(coord + half2(kernelPos) - half2(offset));"
                "if (convolveAlpha == 0) {"
                    // When not convolving alpha, remember the original alpha for actual sample
                    // coord, and perform accumulation on unpremul colors.
                    "if (kernelPos == offset) {"
                        "origAlpha = c.a;"
                    "}"
                    "c = unpremul(c);"
                "}"
                "sum += c*k;"
                "kernelPos.x += 1;"
                "if (kernelPos.x >= size.x) {"
                    "kernelPos.x = 0;"
                    "kernelPos.y += 1;"
                "}";

    // Closes the loop and calculates final color
    static const char* kCloseLoopAndFooterSkSL =
            "}"
            "half4 color = sum*gainAndBias.x + gainAndBias.y;"
            "if (convolveAlpha == 0) {"
                // Reset the alpha to the original and convert to premul RGB
                "color = half4(color.rgb*origAlpha, origAlpha);"
            "} else {"
                // Ensure convolved alpha is within [0, 1]
                "color.a = saturate(color.a);"
            "}"
            // Make RGB valid premul w/ respect to the alpha (either original or convolved)
            "color.rgb = clamp(color.rgb, 0, color.a);"
            "return color;"
        "}";

    static const auto makeTextureEffect = [](int maxTextureKernelSize,
                                             const SkRuntimeEffect::Options& options) {
        return SkMakeRuntimeEffect(
                        SkRuntimeEffect::MakeForShader,
                        SkStringPrintf("const int kMaxKernelSize = %d;"
                                       "uniform shader kernel;"
                                       "uniform half2 innerGainAndBias;"
                                       "%s" // kHeaderAndBeginLoopSkSL
                                               "half k = kernel.eval(half2(half(i) + 0.5, 0.5)).a;"
                                               "k = k * innerGainAndBias.x + innerGainAndBias.y;"
                                               "%s" // kAccumulateAndIncrementSkSL
                                       "%s", // kCloseLoopAndFooterSkSL
                                       maxTextureKernelSize,
                                       kHeaderAndBeginLoopSkSL,
                                       kAccumulateAndIncrementSkSL,
                                       kCloseLoopAndFooterSkSL).c_str(),
                        options);
    };

    switch (impl) {
        case MatrixConvolutionImpl::kUniformBased: {
            return SkMakeRuntimeEffect(
                        SkRuntimeEffect::MakeForShader,
                        SkStringPrintf("const int kMaxKernelSize = %d / 4;"
                                       "uniform half4 kernel[kMaxKernelSize];"
                                       "%s" // kHeaderAndBeginLoopSkSL
                                                "half4 k4 = kernel[i];"
                                                "for (int j = 0; j < 4; ++j) {"
                                                    "if (kernelPos.y >= size.y) { break; }"
                                                    "half k = k4[j];"
                                                    "%s" // kAccumulateAndIncrementSkSL
                                                "}"
                                       "%s", // kCloseLoopAndFooterSkSL
                                       MatrixConvolutionImageFilter::kMaxUniformKernelSize,
                                       kHeaderAndBeginLoopSkSL,
                                       kAccumulateAndIncrementSkSL,
                                       kCloseLoopAndFooterSkSL).c_str(),
                        options);
        }
        case MatrixConvolutionImpl::kTextureBasedSm:
            return makeTextureEffect(MatrixConvolutionImageFilter::kSmallKernelSize, options);
        case MatrixConvolutionImpl::kTextureBasedLg:
            return makeTextureEffect(MatrixConvolutionImageFilter::kLargeKernelSize, options);
    }

    SkUNREACHABLE;
}

SkRuntimeEffect* make_decal_shader() {
    SkRuntimeEffect::Options options = get_options(StableKey::kDecal);

    static constexpr char kDecalShaderCode[] =
        "uniform shader image;"
        "uniform float4 decalBounds;"

        "half4 main(float2 coord) {"
            "return sk_decal(image, coord, decalBounds);"
        "}";

    return SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader,
                               kDecalShaderCode,
                               options);
}

SkRuntimeEffect* make_displacement_shader() {
    SkRuntimeEffect::Options options = get_options(StableKey::kDisplacement);

    // NOTE: This uses dot product selection to work on all GLES2 hardware (enforced by
    // public runtime effect restrictions). Otherwise, this would use a "uniform ivec2"
    // and component indexing to convert the displacement color into a vector.
    static constexpr char kDisplacementShaderCode[] =
        "uniform shader displMap;"
        "uniform shader colorMap;"
        "uniform half2 scale;"
        "uniform half4 xSelect;" // Only one of RGBA will be 1, the rest are 0
        "uniform half4 ySelect;"

        "half4 main(float2 coord) {"
            "return sk_displacement(displMap, colorMap, coord, scale, xSelect, ySelect);"
        "}";

    return SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader,
                               kDisplacementShaderCode,
                               options);
}

SkRuntimeEffect* make_lighting_shader() {
    SkRuntimeEffect::Options options = get_options(StableKey::kLighting);

   static constexpr char kLightingShaderCode[] =
        "uniform shader normalMap;"

        // Packs surface depth, shininess, material type (0 == diffuse) and light type
        // (< 0 = distant, 0 = point, > 0 = spot)
        "uniform half4 materialAndLightType;"

        "uniform half4 lightPosAndSpotFalloff;" // (x,y,z) are lightPos, w is spot falloff
                                                // exponent
        "uniform half4 lightDirAndSpotCutoff;" // (x,y,z) are lightDir,
                                               // w is spot cos(cutoffAngle)
        "uniform half3 lightColor;" // Material's k has already been multiplied in

        "half4 main(float2 coord) {"
            "return sk_lighting(normalMap, coord,"
                                /*depth=*/"materialAndLightType.x,"
                                /*shininess=*/"materialAndLightType.y,"
                                /*materialType=*/"materialAndLightType.z,"
                                /*lightType=*/"materialAndLightType.w,"
                                /*lightPos=*/"lightPosAndSpotFalloff.xyz,"
                                /*spotFalloff=*/"lightPosAndSpotFalloff.w,"
                                /*lightDir=*/"lightDirAndSpotCutoff.xyz,"
                                /*cosCutoffAngle=*/"lightDirAndSpotCutoff.w,"
                                "lightColor);"
        "}";

   return SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader,
                              kLightingShaderCode,
                              options);
}

SkRuntimeEffect* make_linear_morphology_shader() {
    SkRuntimeEffect::Options options = get_options(StableKey::kLinearMorphology);

    static constexpr char kLinearMorphologyShaderCode[] =
        "uniform shader child;"
        "uniform half2 offset;"
        "uniform half flip;" // -1 converts the max() calls to min()
        "uniform int radius;"

        "half4 main(float2 coord) {"
            "return sk_linear_morphology(child, coord, offset, flip, radius);"
        "}";

    return SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader,
                               kLinearMorphologyShaderCode,
                               options);
}

SkRuntimeEffect* make_magnifier_shader() {
    SkRuntimeEffect::Options options = get_options(StableKey::kMagnifier);

    static constexpr char kMagnifierShaderCode[] =
        "uniform shader src;"
        "uniform float4 lensBounds;"
        "uniform float4 zoomXform;"
        "uniform float2 invInset;"

        "half4 main(float2 coord) {"
            "return sk_magnifier(src, coord, lensBounds, zoomXform, invInset);"
        "}";

    return SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader,
                               kMagnifierShaderCode,
                               options);
}

SkRuntimeEffect* make_normal_shader() {
    SkRuntimeEffect::Options options = get_options(StableKey::kNormal);

    static constexpr char kNormalShaderCode[] =
        "uniform shader alphaMap;"
        "uniform float4 edgeBounds;"
        "uniform half negSurfaceDepth;"

        "half4 main(float2 coord) {"
           "return sk_normal(alphaMap, coord, edgeBounds, negSurfaceDepth);"
        "}";

    return SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader,
                               kNormalShaderCode,
                               options);
}

SkRuntimeEffect* make_sparse_morphology_shader() {
    SkRuntimeEffect::Options options = get_options(StableKey::kSparseMorphology);

    static constexpr char kSparseMorphologyShaderCode[] =
        "uniform shader child;"
        "uniform half2 offset;"
        "uniform half flip;"

        "half4 main(float2 coord) {"
            "return sk_sparse_morphology(child, coord, offset, flip);"
        "}";

    return SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader,
                               kSparseMorphologyShaderCode,
                               options);
}

SkRuntimeEffect* make_arithmetic_blender() {
    SkRuntimeEffect::Options options = get_options(StableKey::kArithmetic);

    static constexpr char kArithmeticBlenderCode[] =
        "uniform half4 k;"
        "uniform half pmClamp;"

        "half4 main(half4 src, half4 dst) {"
            "return sk_arithmetic_blend(src, dst, k, pmClamp);"
        "}";

    return SkMakeRuntimeEffect(SkRuntimeEffect::MakeForBlender,
                               kArithmeticBlenderCode,
                               options);
}

SkRuntimeEffect* make_high_contrast_color_filter() {
    SkRuntimeEffect::Options options = get_options(StableKey::kHighContrast);

    static constexpr char kHighContrastFilterCode[] =
        "uniform half grayscale, invertStyle, contrast;"
        "half4 main(half4 color) {"
            "return half4(sk_high_contrast(color.rgb, grayscale, invertStyle, contrast), color.a);"
        "}";

    return SkMakeRuntimeEffect(SkRuntimeEffect::MakeForColorFilter,
                               kHighContrastFilterCode,
                               options);
}

SkRuntimeEffect* make_luma_color_filter() {
    SkRuntimeEffect::Options options = get_options(StableKey::kLuma);

    static constexpr char kLumaFilterCode[] =
        "half4 main(half4 color) {"
            "return sk_luma(color.rgb);"
        "}";

    return SkMakeRuntimeEffect(SkRuntimeEffect::MakeForColorFilter,
                               kLumaFilterCode,
                               options);
}

SkRuntimeEffect* make_overdraw_color_filter() {
    SkRuntimeEffect::Options options = get_options(StableKey::kOverdraw);

    static constexpr char kOverdrawFilterCode[] =
        "uniform half4 color0, color1, color2, color3, color4, color5;"

        "half4 main(half4 color) {"
            "return sk_overdraw(color.a, color0, color1, color2, color3, color4, color5);"
        "}";

    return SkMakeRuntimeEffect(SkRuntimeEffect::MakeForColorFilter,
                               kOverdrawFilterCode,
                               options);
}

} // anonymous namespace

bool IsSkiaKnownRuntimeEffect(int candidate) {
    return (candidate >= static_cast<int>(StableKey::kStart) &&
            candidate <= static_cast<int>(StableKey::kLast));
}

bool IsUserDefinedRuntimeEffect(int candidate) {
    return candidate >= kUnknownRuntimeEffectIDStart;
}

bool IsViableUserDefinedKnownRuntimeEffect(int candidate) {
    return candidate >= kUserDefinedKnownRuntimeEffectsStart &&
           candidate < kUserDefinedKnownRuntimeEffectsEnd;
}

sk_sp<SkRuntimeEffect> MaybeGetKnownRuntimeEffect(uint32_t candidate) {
    if (IsSkiaKnownRuntimeEffect(candidate)) {
        SkKnownRuntimeEffects::StableKey stableKey =
                static_cast<SkKnownRuntimeEffects::StableKey>(candidate);

        return sk_ref_sp(GetKnownRuntimeEffect(stableKey));
    }

    return nullptr;
}

const SkRuntimeEffect* GetKnownRuntimeEffect(StableKey stableKey) {
    switch (stableKey) {
        case StableKey::kInvalid:
            return nullptr;

        // Shaders
        case StableKey::k1DBlur4: {
            static SkRuntimeEffect* s1DBlurEffect = make_blur_1D_shader(4, stableKey);
            return s1DBlurEffect;
        }
        case StableKey::k1DBlur8: {
            static SkRuntimeEffect* s1DBlurEffect = make_blur_1D_shader(8, stableKey);
            return s1DBlurEffect;
        }
        case StableKey::k1DBlur12: {
            static SkRuntimeEffect* s1DBlurEffect = make_blur_1D_shader(12, stableKey);
            return s1DBlurEffect;
        }
        case StableKey::k1DBlur16: {
            static SkRuntimeEffect* s1DBlurEffect = make_blur_1D_shader(16, stableKey);
            return s1DBlurEffect;
        }
        case StableKey::k1DBlur20: {
            static SkRuntimeEffect* s1DBlurEffect = make_blur_1D_shader(20, stableKey);
            return s1DBlurEffect;
        }
        case StableKey::k1DBlur28: {
            static SkRuntimeEffect* s1DBlurEffect = make_blur_1D_shader(28, stableKey);
            return s1DBlurEffect;
        }
        case StableKey::k2DBlur4: {
            static SkRuntimeEffect* s2DBlurEffect = make_blur_2D_shader(4, stableKey);
            return s2DBlurEffect;
        }
        case StableKey::k2DBlur8: {
            static SkRuntimeEffect* s2DBlurEffect = make_blur_2D_shader(8, stableKey);
            return s2DBlurEffect;
        }
        case StableKey::k2DBlur12: {
            static SkRuntimeEffect* s2DBlurEffect = make_blur_2D_shader(12, stableKey);
            return s2DBlurEffect;
        }
        case StableKey::k2DBlur16: {
            static SkRuntimeEffect* s2DBlurEffect = make_blur_2D_shader(16, stableKey);
            return s2DBlurEffect;
        }
        case StableKey::k2DBlur20: {
            static SkRuntimeEffect* s2DBlurEffect = make_blur_2D_shader(20, stableKey);
            return s2DBlurEffect;
        }
        case StableKey::k2DBlur28: {
            static SkRuntimeEffect* s2DBlurEffect = make_blur_2D_shader(28, stableKey);
            return s2DBlurEffect;
        }
        case StableKey::kBlend: {
            static const SkRuntimeEffect* sBlendEffect = make_blend_shader();
            return sBlendEffect;
        }
        case StableKey::kLerp: {
            static const SkRuntimeEffect* sLerpEffect = make_lerp_shader();
            return sLerpEffect;
        }
        case StableKey::kMatrixConvUniforms: {
            static const SkRuntimeEffect* sMatrixConvUniformsEffect =
                    make_matrix_conv_shader(MatrixConvolutionImpl::kUniformBased, stableKey);
            return sMatrixConvUniformsEffect;
        }
        case StableKey::kMatrixConvTexSm: {
            static const SkRuntimeEffect* sMatrixConvTexSmEffect =
                    make_matrix_conv_shader(MatrixConvolutionImpl::kTextureBasedSm, stableKey);
            return sMatrixConvTexSmEffect;
        }
        case StableKey::kMatrixConvTexLg: {
            static const SkRuntimeEffect* sMatrixConvTexMaxEffect =
                    make_matrix_conv_shader(MatrixConvolutionImpl::kTextureBasedLg, stableKey);
            return sMatrixConvTexMaxEffect;
        }
        case StableKey::kDecal: {
            static const SkRuntimeEffect* sDecalEffect = make_decal_shader();
            return sDecalEffect;
        }
        case StableKey::kDisplacement: {
            static const SkRuntimeEffect* sDisplacementEffect = make_displacement_shader();
            return sDisplacementEffect;
        }
        case StableKey::kLighting: {
            static const SkRuntimeEffect* sLightingEffect = make_lighting_shader();
            return sLightingEffect;
        }
        case StableKey::kLinearMorphology: {
            static const SkRuntimeEffect* sLinearMorphologyEffect = make_linear_morphology_shader();
            return sLinearMorphologyEffect;
        }
        case StableKey::kMagnifier: {
            static const SkRuntimeEffect* sMagnifierEffect = make_magnifier_shader();
            return sMagnifierEffect;
        }
        case StableKey::kNormal: {
            static const SkRuntimeEffect* sNormalEffect = make_normal_shader();
            return sNormalEffect;
        }
        case StableKey::kSparseMorphology: {
            static const SkRuntimeEffect* sSparseMorphologyEffect = make_sparse_morphology_shader();
            return sSparseMorphologyEffect;
        }

        // Blenders
        case StableKey::kArithmetic: {
            static const SkRuntimeEffect* sArithmeticEffect = make_arithmetic_blender();
            return sArithmeticEffect;
        }

        // Color Filters
        case StableKey::kHighContrast: {
            static const SkRuntimeEffect* sHighContrastEffect = make_high_contrast_color_filter();
            return sHighContrastEffect;
        }
        case StableKey::kLuma: {
            static const SkRuntimeEffect* sLumaEffect = make_luma_color_filter();
            return sLumaEffect;
        }
        case StableKey::kOverdraw: {
            static const SkRuntimeEffect* sOverdrawEffect = make_overdraw_color_filter();
            return sOverdrawEffect;
        }
    }

    SkUNREACHABLE;
}

} // namespace SkKnownRuntimeEffects
