/*
 * 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 GrArithmeticProcessor.fp; do not modify.
 **************************************************************************************************/
#include "GrArithmeticProcessor.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 GrGLSLArithmeticProcessor : public GrGLSLFragmentProcessor {
public:
    GrGLSLArithmeticProcessor() {}
    void emitCode(EmitArgs& args) override {
        GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
        const GrArithmeticProcessor& _outer = args.fFp.cast<GrArithmeticProcessor>();
        (void)_outer;
        auto k = _outer.k;
        (void)k;
        auto enforcePMColor = _outer.enforcePMColor;
        (void)enforcePMColor;
        kVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, kFloat4_GrSLType,
                                                "k");
        SkString _sample0 = this->invokeChild(0, args);
        fragBuilder->codeAppendf(
                R"SkSL(half4 src = %s;)SkSL", _sample0.c_str());
        SkString _sample1 = this->invokeChild(1, args);
        fragBuilder->codeAppendf(
                R"SkSL(
half4 dst = %s;
half4 color = clamp((((half(%s.x) * src) * dst + half(%s.y) * src) + half(%s.z) * dst) + half(%s.w), 0.0, 1.0);
@if (%s) {
    color.xyz = min(color.xyz, color.w);
}
return color;
)SkSL",
                _sample1.c_str(), args.fUniformHandler->getUniformCStr(kVar),
                args.fUniformHandler->getUniformCStr(kVar),
                args.fUniformHandler->getUniformCStr(kVar),
                args.fUniformHandler->getUniformCStr(kVar),
                (_outer.enforcePMColor ? "true" : "false"));
    }

private:
    void onSetData(const GrGLSLProgramDataManager& pdman,
                   const GrFragmentProcessor& _proc) override {
        const GrArithmeticProcessor& _outer = _proc.cast<GrArithmeticProcessor>();
        { pdman.set4fv(kVar, 1, (_outer.k).ptr()); }
    }
    UniformHandle kVar;
};
std::unique_ptr<GrGLSLFragmentProcessor> GrArithmeticProcessor::onMakeProgramImpl() const {
    return std::make_unique<GrGLSLArithmeticProcessor>();
}
void GrArithmeticProcessor::onGetGLSLProcessorKey(const GrShaderCaps& caps,
                                                  GrProcessorKeyBuilder* b) const {
    b->add32((uint32_t)enforcePMColor);
}
bool GrArithmeticProcessor::onIsEqual(const GrFragmentProcessor& other) const {
    const GrArithmeticProcessor& that = other.cast<GrArithmeticProcessor>();
    (void)that;
    if (k != that.k) return false;
    if (enforcePMColor != that.enforcePMColor) return false;
    return true;
}
GrArithmeticProcessor::GrArithmeticProcessor(const GrArithmeticProcessor& src)
        : INHERITED(kGrArithmeticProcessor_ClassID, src.optimizationFlags())
        , k(src.k)
        , enforcePMColor(src.enforcePMColor) {
    this->cloneAndRegisterAllChildProcessors(src);
}
std::unique_ptr<GrFragmentProcessor> GrArithmeticProcessor::clone() const {
    return std::make_unique<GrArithmeticProcessor>(*this);
}
#if GR_TEST_UTILS
SkString GrArithmeticProcessor::onDumpInfo() const {
    return SkStringPrintf("(k=float4(%f, %f, %f, %f), enforcePMColor=%s)", k.x, k.y, k.z, k.w,
                          (enforcePMColor ? "true" : "false"));
}
#endif
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrArithmeticProcessor);
#if GR_TEST_UTILS
std::unique_ptr<GrFragmentProcessor> GrArithmeticProcessor::TestCreate(GrProcessorTestData* d) {
    return GrArithmeticProcessor::Make(
            GrProcessorUnitTest::MakeChildFP(d), GrProcessorUnitTest::MakeChildFP(d),
            {d->fRandom->nextF(), d->fRandom->nextF(), d->fRandom->nextF(), d->fRandom->nextF()},
            d->fRandom->nextBool());
}
#endif
