/*
 * Copyright 2019 Google LLC.
 *
 * 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 GrComposeLerpRedEffect.fp; do not modify.
 **************************************************************************************************/
#include "GrComposeLerpRedEffect.h"

#include "include/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 GrGLSLComposeLerpRedEffect : public GrGLSLFragmentProcessor {
public:
    GrGLSLComposeLerpRedEffect() {}
    void emitCode(EmitArgs& args) override {
        GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
        const GrComposeLerpRedEffect& _outer = args.fFp.cast<GrComposeLerpRedEffect>();
        (void)_outer;
        SkString _child0("_child0");
        if (_outer.child1_index >= 0) {
            this->emitChild(_outer.child1_index, &_child0, args);
        } else {
            fragBuilder->codeAppendf("half4 %s;", _child0.c_str());
        }
        SkString _child1("_child1");
        if (_outer.child2_index >= 0) {
            this->emitChild(_outer.child2_index, &_child1, args);
        } else {
            fragBuilder->codeAppendf("half4 %s;", _child1.c_str());
        }
        SkString _child2("_child2");
        this->emitChild(_outer.lerp_index, &_child2, args);
        fragBuilder->codeAppendf("%s = mix(%s ? %s : %s, %s ? %s : %s, %s.x);\n", args.fOutputColor,
                                 _outer.child1_index >= 0 ? "true" : "false", _child0.c_str(),
                                 args.fInputColor, _outer.child2_index >= 0 ? "true" : "false",
                                 _child1.c_str(), args.fInputColor, _child2.c_str());
    }

private:
    void onSetData(const GrGLSLProgramDataManager& pdman,
                   const GrFragmentProcessor& _proc) override {}
};
GrGLSLFragmentProcessor* GrComposeLerpRedEffect::onCreateGLSLInstance() const {
    return new GrGLSLComposeLerpRedEffect();
}
void GrComposeLerpRedEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
                                                   GrProcessorKeyBuilder* b) const {}
bool GrComposeLerpRedEffect::onIsEqual(const GrFragmentProcessor& other) const {
    const GrComposeLerpRedEffect& that = other.cast<GrComposeLerpRedEffect>();
    (void)that;
    return true;
}
GrComposeLerpRedEffect::GrComposeLerpRedEffect(const GrComposeLerpRedEffect& src)
        : INHERITED(kGrComposeLerpRedEffect_ClassID, src.optimizationFlags())
        , child1_index(src.child1_index)
        , child2_index(src.child2_index)
        , lerp_index(src.lerp_index) {
    if (child1_index >= 0) {
        this->registerChildProcessor(src.childProcessor(child1_index).clone());
    }
    if (child2_index >= 0) {
        this->registerChildProcessor(src.childProcessor(child2_index).clone());
    }
    this->registerChildProcessor(src.childProcessor(lerp_index).clone());
}
std::unique_ptr<GrFragmentProcessor> GrComposeLerpRedEffect::clone() const {
    return std::unique_ptr<GrFragmentProcessor>(new GrComposeLerpRedEffect(*this));
}
