/*
 * Copyright 2018 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 GrAlphaThresholdFragmentProcessor.fp; do not modify.
 **************************************************************************************************/
#include "GrAlphaThresholdFragmentProcessor.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 GrGLSLAlphaThresholdFragmentProcessor : public GrGLSLFragmentProcessor {
public:
    GrGLSLAlphaThresholdFragmentProcessor() {}
    void emitCode(EmitArgs& args) override {
        GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
        const GrAlphaThresholdFragmentProcessor& _outer =
                args.fFp.cast<GrAlphaThresholdFragmentProcessor>();
        (void)_outer;
        auto innerThreshold = _outer.innerThreshold;
        (void)innerThreshold;
        auto outerThreshold = _outer.outerThreshold;
        (void)outerThreshold;
        innerThresholdVar = args.fUniformHandler->addUniform(
                &_outer, kFragment_GrShaderFlag, kHalf_GrSLType, "innerThreshold");
        outerThresholdVar = args.fUniformHandler->addUniform(
                &_outer, kFragment_GrShaderFlag, kHalf_GrSLType, "outerThreshold");
        SkString _sample0 = this->invokeChild(0, args);
        fragBuilder->codeAppendf(
                R"SkSL(half4 color = %s;)SkSL", _sample0.c_str());
        SkString _sample1 = this->invokeChild(1, args);
        fragBuilder->codeAppendf(
                R"SkSL(
half4 mask_color = %s;
if (mask_color.w < 0.5) {
    if (color.w > %s) {
        half scale = %s / color.w;
        color.xyz *= scale;
        color.w = %s;
    }
} else if (color.w < %s) {
    half scale = %s / max(0.0010000000474974513, color.w);
    color.xyz *= scale;
    color.w = %s;
}
return color;
)SkSL",
                _sample1.c_str(),
                args.fUniformHandler->getUniformCStr(outerThresholdVar),
                args.fUniformHandler->getUniformCStr(outerThresholdVar),
                args.fUniformHandler->getUniformCStr(outerThresholdVar),
                args.fUniformHandler->getUniformCStr(innerThresholdVar),
                args.fUniformHandler->getUniformCStr(innerThresholdVar),
                args.fUniformHandler->getUniformCStr(innerThresholdVar));
    }

private:
    void onSetData(const GrGLSLProgramDataManager& pdman,
                   const GrFragmentProcessor& _proc) override {
        const GrAlphaThresholdFragmentProcessor& _outer =
                _proc.cast<GrAlphaThresholdFragmentProcessor>();
        {
            pdman.set1f(innerThresholdVar, _outer.innerThreshold);
            pdman.set1f(outerThresholdVar, _outer.outerThreshold);
        }
    }
    UniformHandle innerThresholdVar;
    UniformHandle outerThresholdVar;
};
std::unique_ptr<GrGLSLFragmentProcessor> GrAlphaThresholdFragmentProcessor::onMakeProgramImpl()
        const {
    return std::make_unique<GrGLSLAlphaThresholdFragmentProcessor>();
}
void GrAlphaThresholdFragmentProcessor::onGetGLSLProcessorKey(const GrShaderCaps& caps,
                                                              GrProcessorKeyBuilder* b) const {}
bool GrAlphaThresholdFragmentProcessor::onIsEqual(const GrFragmentProcessor& other) const {
    const GrAlphaThresholdFragmentProcessor& that = other.cast<GrAlphaThresholdFragmentProcessor>();
    (void)that;
    if (innerThreshold != that.innerThreshold) return false;
    if (outerThreshold != that.outerThreshold) return false;
    return true;
}
GrAlphaThresholdFragmentProcessor::GrAlphaThresholdFragmentProcessor(
        const GrAlphaThresholdFragmentProcessor& src)
        : INHERITED(kGrAlphaThresholdFragmentProcessor_ClassID, src.optimizationFlags())
        , innerThreshold(src.innerThreshold)
        , outerThreshold(src.outerThreshold) {
    this->cloneAndRegisterAllChildProcessors(src);
}
std::unique_ptr<GrFragmentProcessor> GrAlphaThresholdFragmentProcessor::clone() const {
    return std::make_unique<GrAlphaThresholdFragmentProcessor>(*this);
}
#if GR_TEST_UTILS
SkString GrAlphaThresholdFragmentProcessor::onDumpInfo() const {
    return SkStringPrintf("(innerThreshold=%f, outerThreshold=%f)", innerThreshold, outerThreshold);
}
#endif
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrAlphaThresholdFragmentProcessor);
#if GR_TEST_UTILS
std::unique_ptr<GrFragmentProcessor> GrAlphaThresholdFragmentProcessor::TestCreate(
        GrProcessorTestData* testData) {
    // Make the inner and outer thresholds be in [0, 1].
    float outerThresh = testData->fRandom->nextUScalar1();
    float innerThresh = testData->fRandom->nextUScalar1();
    std::unique_ptr<GrFragmentProcessor> inputChild, maskChild;
    if (testData->fRandom->nextBool()) {
        inputChild = GrProcessorUnitTest::MakeChildFP(testData);
    }
    maskChild = GrProcessorUnitTest::MakeChildFP(testData);

    return GrAlphaThresholdFragmentProcessor::Make(
            std::move(inputChild), std::move(maskChild), innerThresh, outerThresh);
}
#endif
