/*
 * 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 _sample292;
        if (_outer.child1_index >= 0) {
            _sample292 = this->invokeChild(_outer.child1_index, args);
        } else {
            _sample292 = "half4(1)";
        }
        SkString _sample360;
        if (_outer.child2_index >= 0) {
            _sample360 = this->invokeChild(_outer.child2_index, args);
        } else {
            _sample360 = "half4(1)";
        }
        SkString _sample411;
        _sample411 = this->invokeChild(_outer.lerp_index, args);
        fragBuilder->codeAppendf("%s = mix(%s ? %s : %s, %s ? %s : %s, %s.x);\n", args.fOutputColor,
                                 _outer.child1_index >= 0 ? "true" : "false", _sample292.c_str(),
                                 args.fInputColor, _outer.child2_index >= 0 ? "true" : "false",
                                 _sample360.c_str(), args.fInputColor, _sample411.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) {
        auto clone = src.childProcessor(child1_index).clone();
        clone->setSampledWithExplicitCoords(
                src.childProcessor(child1_index).isSampledWithExplicitCoords());
        this->registerChildProcessor(std::move(clone));
    }
    if (child2_index >= 0) {
        auto clone = src.childProcessor(child2_index).clone();
        clone->setSampledWithExplicitCoords(
                src.childProcessor(child2_index).isSampledWithExplicitCoords());
        this->registerChildProcessor(std::move(clone));
    }
    {
        auto clone = src.childProcessor(lerp_index).clone();
        clone->setSampledWithExplicitCoords(
                src.childProcessor(lerp_index).isSampledWithExplicitCoords());
        this->registerChildProcessor(std::move(clone));
    }
}
std::unique_ptr<GrFragmentProcessor> GrComposeLerpRedEffect::clone() const {
    return std::unique_ptr<GrFragmentProcessor>(new GrComposeLerpRedEffect(*this));
}
