/*
 * Copyright 2019 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 GrMixerEffect.fp; do not modify.
 **************************************************************************************************/
#include "GrMixerEffect.h"
#include "glsl/GrGLSLFragmentProcessor.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLProgramBuilder.h"
#include "GrTexture.h"
#include "SkSLCPP.h"
#include "SkSLUtil.h"
class GrGLSLMixerEffect : public GrGLSLFragmentProcessor {
public:
    GrGLSLMixerEffect() {}
    void emitCode(EmitArgs& args) override {
        GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
        const GrMixerEffect&     _outer      = args.fFp.cast<GrMixerEffect>();
        (void)_outer;
        auto weight = _outer.weight();
        (void)weight;
        fWeightVar =
                args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "weight");
        SkString _input0 = SkStringPrintf("%s", args.fInputColor);
        SkString _child0("_child0");
        this->emitChild(_outer.fp0_index(), _input0.c_str(), &_child0, args);
        fragBuilder->codeAppendf("half4 in0 = %s;", _child0.c_str());
        SkString _input1 = SkStringPrintf("%s", args.fInputColor);
        SkString _child1("_child1");
        if (_outer.fp1_index() >= 0) {
            this->emitChild(_outer.fp1_index(), _input1.c_str(), &_child1, args);
        } else {
            fragBuilder->codeAppendf("half4 %s;", _child1.c_str());
        }
        fragBuilder->codeAppendf("\nhalf4 in1 = %s ? %s : %s;\n%s = mix(in0, in1, %s);\n",
                                 _outer.fp1_index() >= 0 ? "true" : "false",
                                 _child1.c_str(),
                                 args.fInputColor,
                                 args.fOutputColor,
                                 args.fUniformHandler->getUniformCStr(fWeightVar));
    }

private:
    void onSetData(const GrGLSLProgramDataManager& pdman,
                   const GrFragmentProcessor&      _proc) override {
        const GrMixerEffect& _outer = _proc.cast<GrMixerEffect>();
        { pdman.set1f(fWeightVar, (_outer.weight())); }
    }
    UniformHandle fWeightVar;
};
GrGLSLFragmentProcessor* GrMixerEffect::onCreateGLSLInstance() const {
    return new GrGLSLMixerEffect();
}
void GrMixerEffect::onGetGLSLProcessorKey(const GrShaderCaps&    caps,
                                          GrProcessorKeyBuilder* b) const {}
bool GrMixerEffect::onIsEqual(const GrFragmentProcessor& other) const {
    const GrMixerEffect& that = other.cast<GrMixerEffect>();
    (void)that;
    if (fWeight != that.fWeight)
        return false;
    return true;
}
GrMixerEffect::GrMixerEffect(const GrMixerEffect& src)
        : INHERITED(kGrMixerEffect_ClassID, src.optimizationFlags())
        , fFp0_index(src.fFp0_index)
        , fFp1_index(src.fFp1_index)
        , fWeight(src.fWeight) {
    this->registerChildProcessor(src.childProcessor(fFp0_index).clone());
    if (fFp1_index >= 0) {
        this->registerChildProcessor(src.childProcessor(fFp1_index).clone());
    }
}
std::unique_ptr<GrFragmentProcessor> GrMixerEffect::clone() const {
    return std::unique_ptr<GrFragmentProcessor>(new GrMixerEffect(*this));
}
