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

/**************************************************************************************************
 *** This file was autogenerated from GrHighContrastFilterEffect.fp; do not modify.
 **************************************************************************************************/
#include "GrHighContrastFilterEffect.h"

#include "src/core/SkUtils.h"
#include "src/gpu/GrTexture.h"
#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
#include "src/gpu/glsl/GrGLSLProgramBuilder.h"
#include "src/sksl/SkSLCPP.h"
#include "src/sksl/SkSLUtil.h"
class GrGLSLHighContrastFilterEffect : public GrGLSLFragmentProcessor {
public:
    GrGLSLHighContrastFilterEffect() {}
    void emitCode(EmitArgs& args) override {
        GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
        const GrHighContrastFilterEffect& _outer = args.fFp.cast<GrHighContrastFilterEffect>();
        (void)_outer;
        auto contrastMod = _outer.contrastMod;
        (void)contrastMod;
        auto hasContrast = _outer.hasContrast;
        (void)hasContrast;
        auto grayscale = _outer.grayscale;
        (void)grayscale;
        auto invertBrightness = _outer.invertBrightness;
        (void)invertBrightness;
        auto invertLightness = _outer.invertLightness;
        (void)invertLightness;
        auto linearize = _outer.linearize;
        (void)linearize;
        contrastModVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag,
                                                          kHalf_GrSLType, "contrastMod");
        SkString HSLToRGB_name;
        const GrShaderVar HSLToRGB_args[] = {GrShaderVar("p", kHalf_GrSLType),
                                             GrShaderVar("q", kHalf_GrSLType),
                                             GrShaderVar("t", kHalf_GrSLType)};
        fragBuilder->emitFunction(kHalf_GrSLType, "HSLToRGB", 3, HSLToRGB_args,
                                  R"SkSL(if (t < 0.0) t += 1.0;
if (t > 1.0) t -= 1.0;
return t < 0.16666666666666666 ? p + ((q - p) * 6.0) * t : (t < 0.5 ? q : (t < 0.66666666666666663 ? p + ((q - p) * (0.66666666666666663 - t)) * 6.0 : p));
)SkSL",
                                  &HSLToRGB_name);
        SkString _sample896 = this->invokeChild(0, args);
        fragBuilder->codeAppendf(
                R"SkSL(
half4 inColor = %s;
half4 _0_unpremul;
{
    _0_unpremul = half4(inColor.xyz / max(inColor.w, 9.9999997473787516e-05), inColor.w);
}

half4 color = _0_unpremul;

@if (%s) {
    color.xyz = color.xyz * color.xyz;
}
@if (%s) {
    color = half4(half3(dot(color.xyz, half3(0.2125999927520752, 0.71520000696182251, 0.072200000286102295))), 0.0);
}
@if (%s) {
    color = half4(1.0) - color;
}
@if (%s) {
    half fmax = max(color.x, max(color.y, color.z));
    half fmin = min(color.x, min(color.y, color.z));
    half l = fmax + fmin;
    half h;
    half s;
    if (fmax == fmin) {
        h = 0.0;
        s = 0.0;
    } else {
        half d = fmax - fmin;
        s = l > 1.0 ? d / (2.0 - l) : d / l;
        if (color.x >= color.y && color.x >= color.z) {
            h = (color.y - color.z) / d + half(color.y < color.z ? 6 : 0);
        } else if (color.y >= color.z) {
            h = (color.z - color.x) / d + 2.0;
        } else {
            h = (color.x - color.y) / d + 4.0;
        }
        h *= 0.16666666666666666;
    }
    l = 1.0 + l * -0.5;
    if (s == 0.0) {
        color = half4(l, l, l, 0.0);
    } else {
        half q = l < 0.5 ? l * (1.0 + s) : (l + s) - l * s;
        half p = 2.0 * l - q;
        color.x = %s(p, q, h + 0.33333333333333331);
        color.y = %s(p, q, h);
        color.z = %s(p, q, h - 0.33333333333333331);
    }
}
@if (%s) {
    half off = -0.5 * %s + 0.5;
    color = %s * color + off;
}
color = clamp(color, 0.0, 1.0);
@if (%s) {
    color.xyz = sqrt(color.xyz);
}
%s = half4(color.xyz, 1.0) * inColor.w;
)SkSL",
                _sample896.c_str(), (_outer.linearize ? "true" : "false"),
                (_outer.grayscale ? "true" : "false"), (_outer.invertBrightness ? "true" : "false"),
                (_outer.invertLightness ? "true" : "false"), HSLToRGB_name.c_str(),
                HSLToRGB_name.c_str(), HSLToRGB_name.c_str(),
                (_outer.hasContrast ? "true" : "false"),
                args.fUniformHandler->getUniformCStr(contrastModVar),
                args.fUniformHandler->getUniformCStr(contrastModVar),
                (_outer.linearize ? "true" : "false"), args.fOutputColor);
    }

private:
    void onSetData(const GrGLSLProgramDataManager& pdman,
                   const GrFragmentProcessor& _proc) override {
        const GrHighContrastFilterEffect& _outer = _proc.cast<GrHighContrastFilterEffect>();
        { pdman.set1f(contrastModVar, (_outer.contrastMod)); }
    }
    UniformHandle contrastModVar;
};
GrGLSLFragmentProcessor* GrHighContrastFilterEffect::onCreateGLSLInstance() const {
    return new GrGLSLHighContrastFilterEffect();
}
void GrHighContrastFilterEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
                                                       GrProcessorKeyBuilder* b) const {
    b->add32((uint32_t)hasContrast);
    b->add32((uint32_t)grayscale);
    b->add32((uint32_t)invertBrightness);
    b->add32((uint32_t)invertLightness);
    b->add32((uint32_t)linearize);
}
bool GrHighContrastFilterEffect::onIsEqual(const GrFragmentProcessor& other) const {
    const GrHighContrastFilterEffect& that = other.cast<GrHighContrastFilterEffect>();
    (void)that;
    if (contrastMod != that.contrastMod) return false;
    if (hasContrast != that.hasContrast) return false;
    if (grayscale != that.grayscale) return false;
    if (invertBrightness != that.invertBrightness) return false;
    if (invertLightness != that.invertLightness) return false;
    if (linearize != that.linearize) return false;
    return true;
}
bool GrHighContrastFilterEffect::usesExplicitReturn() const { return false; }
GrHighContrastFilterEffect::GrHighContrastFilterEffect(const GrHighContrastFilterEffect& src)
        : INHERITED(kGrHighContrastFilterEffect_ClassID, src.optimizationFlags())
        , contrastMod(src.contrastMod)
        , hasContrast(src.hasContrast)
        , grayscale(src.grayscale)
        , invertBrightness(src.invertBrightness)
        , invertLightness(src.invertLightness)
        , linearize(src.linearize) {
    this->cloneAndRegisterAllChildProcessors(src);
}
std::unique_ptr<GrFragmentProcessor> GrHighContrastFilterEffect::clone() const {
    return std::make_unique<GrHighContrastFilterEffect>(*this);
}
#if GR_TEST_UTILS
SkString GrHighContrastFilterEffect::onDumpInfo() const {
    return SkStringPrintf(
            "(contrastMod=%f, hasContrast=%s, grayscale=%s, invertBrightness=%s, "
            "invertLightness=%s, linearize=%s)",
            contrastMod, (hasContrast ? "true" : "false"), (grayscale ? "true" : "false"),
            (invertBrightness ? "true" : "false"), (invertLightness ? "true" : "false"),
            (linearize ? "true" : "false"));
}
#endif
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrHighContrastFilterEffect);
#if GR_TEST_UTILS
std::unique_ptr<GrFragmentProcessor> GrHighContrastFilterEffect::TestCreate(
        GrProcessorTestData* d) {
    using InvertStyle = SkHighContrastConfig::InvertStyle;
    SkHighContrastConfig config{/*grayscale=*/d->fRandom->nextBool(),
                                InvertStyle(d->fRandom->nextRangeU(0, int(InvertStyle::kLast))),
                                /*contrast=*/d->fRandom->nextF()};
    return GrHighContrastFilterEffect::Make(d->inputFP(), config,
                                            /*linearize=*/d->fRandom->nextBool());
}
#endif
