/*
 * 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 "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 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;
        weightVar =
                args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "weight");
        SkString _input1278 = SkStringPrintf("%s", args.fInputColor);
        SkString _sample1278;
        _sample1278 = this->invokeChild(_outer.fp0_index, _input1278.c_str(), args);
        fragBuilder->codeAppendf("half4 in0 = %s;", _sample1278.c_str());
        SkString _input1335 = SkStringPrintf("%s", args.fInputColor);
        SkString _sample1335;
        if (_outer.fp1_index >= 0) {
            _sample1335 = this->invokeChild(_outer.fp1_index, _input1335.c_str(), args);
        } else {
            _sample1335 = "half4(1)";
        }
        fragBuilder->codeAppendf("\nhalf4 in1 = %s ? %s : %s;\n%s = mix(in0, in1, %s);\n",
                                 _outer.fp1_index >= 0 ? "true" : "false", _sample1335.c_str(),
                                 args.fInputColor, args.fOutputColor,
                                 args.fUniformHandler->getUniformCStr(weightVar));
    }

private:
    void onSetData(const GrGLSLProgramDataManager& pdman,
                   const GrFragmentProcessor& _proc) override {
        const GrMixerEffect& _outer = _proc.cast<GrMixerEffect>();
        { pdman.set1f(weightVar, (_outer.weight)); }
    }
    UniformHandle weightVar;
};
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 (weight != that.weight) return false;
    return true;
}
GrMixerEffect::GrMixerEffect(const GrMixerEffect& src)
        : INHERITED(kGrMixerEffect_ClassID, src.optimizationFlags())
        , fp0_index(src.fp0_index)
        , fp1_index(src.fp1_index)
        , weight(src.weight) {
    {
        auto clone = src.childProcessor(fp0_index).clone();
        clone->setSampledWithExplicitCoords(
                src.childProcessor(fp0_index).isSampledWithExplicitCoords());
        this->registerChildProcessor(std::move(clone));
    }
    if (fp1_index >= 0) {
        auto clone = src.childProcessor(fp1_index).clone();
        clone->setSampledWithExplicitCoords(
                src.childProcessor(fp1_index).isSampledWithExplicitCoords());
        this->registerChildProcessor(std::move(clone));
    }
}
std::unique_ptr<GrFragmentProcessor> GrMixerEffect::clone() const {
    return std::unique_ptr<GrFragmentProcessor>(new GrMixerEffect(*this));
}
