/*
 * 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 GrArithmeticFP.fp; do not modify.
 **************************************************************************************************/
#include "GrArithmeticFP.h"
#include "glsl/GrGLSLFragmentProcessor.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLProgramBuilder.h"
#include "GrTexture.h"
#include "SkSLCPP.h"
#include "SkSLUtil.h"
class GrGLSLArithmeticFP : public GrGLSLFragmentProcessor {
public:
    GrGLSLArithmeticFP() {}
    void emitCode(EmitArgs& args) override {
        GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
        const GrArithmeticFP& _outer = args.fFp.cast<GrArithmeticFP>();
        (void)_outer;
        auto k1 = _outer.k1();
        (void)k1;
        auto k2 = _outer.k2();
        (void)k2;
        auto k3 = _outer.k3();
        (void)k3;
        auto k4 = _outer.k4();
        (void)k4;
        auto enforcePMColor = _outer.enforcePMColor();
        (void)enforcePMColor;
        fKVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kFloat4_GrSLType,
                                                 kDefault_GrSLPrecision, "k");
        SkString _child0("_child0");
        this->emitChild(0, &_child0, args);
        fragBuilder->codeAppendf(
                "half4 dst = %s;\n%s = half4(clamp(float4(float4(((%s.x * float4(%s)) * dst + %s.y "
                "* float4(%s)) + %s.z * float4(dst)) + %s.w), 0.0, 1.0));\nif (%s) {\n    %s.xyz = "
                "half3(min(float3(%s.xyz), float(%s.w)));\n}\n",
                _child0.c_str(), args.fOutputColor, args.fUniformHandler->getUniformCStr(fKVar),
                args.fInputColor ? args.fInputColor : "half4(1)",
                args.fUniformHandler->getUniformCStr(fKVar),
                args.fInputColor ? args.fInputColor : "half4(1)",
                args.fUniformHandler->getUniformCStr(fKVar),
                args.fUniformHandler->getUniformCStr(fKVar),
                (_outer.enforcePMColor() ? "true" : "false"), args.fOutputColor, args.fOutputColor,
                args.fOutputColor);
    }

private:
    void onSetData(const GrGLSLProgramDataManager& pdman,
                   const GrFragmentProcessor& _proc) override {
        const GrArithmeticFP& _outer = _proc.cast<GrArithmeticFP>();
        auto k1 = _outer.k1();
        (void)k1;
        auto k2 = _outer.k2();
        (void)k2;
        auto k3 = _outer.k3();
        (void)k3;
        auto k4 = _outer.k4();
        (void)k4;
        auto enforcePMColor = _outer.enforcePMColor();
        (void)enforcePMColor;
        UniformHandle& k = fKVar;
        (void)k;

        pdman.set4f(k, k1, k2, k3, k4);
    }
    UniformHandle fKVar;
};
GrGLSLFragmentProcessor* GrArithmeticFP::onCreateGLSLInstance() const {
    return new GrGLSLArithmeticFP();
}
void GrArithmeticFP::onGetGLSLProcessorKey(const GrShaderCaps& caps,
                                           GrProcessorKeyBuilder* b) const {
    b->add32((int32_t)fEnforcePMColor);
}
bool GrArithmeticFP::onIsEqual(const GrFragmentProcessor& other) const {
    const GrArithmeticFP& that = other.cast<GrArithmeticFP>();
    (void)that;
    if (fK1 != that.fK1) return false;
    if (fK2 != that.fK2) return false;
    if (fK3 != that.fK3) return false;
    if (fK4 != that.fK4) return false;
    if (fEnforcePMColor != that.fEnforcePMColor) return false;
    return true;
}
GrArithmeticFP::GrArithmeticFP(const GrArithmeticFP& src)
        : INHERITED(kGrArithmeticFP_ClassID, src.optimizationFlags())
        , fK1(src.fK1)
        , fK2(src.fK2)
        , fK3(src.fK3)
        , fK4(src.fK4)
        , fEnforcePMColor(src.fEnforcePMColor) {
    this->registerChildProcessor(src.childProcessor(0).clone());
}
std::unique_ptr<GrFragmentProcessor> GrArithmeticFP::clone() const {
    return std::unique_ptr<GrFragmentProcessor>(new GrArithmeticFP(*this));
}
