/*
 * 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.1666666716337204 ? p + ((q - p) * 6.0) * t : (t < 0.5 ? q : (t < 0.66666668653488159 ? p + ((q - p) * (0.66666668653488159 - 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.1666666716337204;
    }
    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.3333333432674408);
        color.y = %s(p, q, h);
        color.z = %s(p, q, h - 0.3333333432674408);
    }
}
@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
