/*
 * 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 GrOverrideInputFragmentProcessor.fp; do not modify.
 **************************************************************************************************/
#include "GrOverrideInputFragmentProcessor.h"

#include "src/core/SkUtils.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 GrGLSLOverrideInputFragmentProcessor : public GrGLSLFragmentProcessor {
public:
    GrGLSLOverrideInputFragmentProcessor() {}
    void emitCode(EmitArgs& args) override {
        GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
        const GrOverrideInputFragmentProcessor& _outer =
                args.fFp.cast<GrOverrideInputFragmentProcessor>();
        (void)_outer;
        auto useUniform = _outer.useUniform;
        (void)useUniform;
        auto uniformColor = _outer.uniformColor;
        (void)uniformColor;
        auto literalColor = _outer.literalColor;
        (void)literalColor;
        if (useUniform) {
            uniformColorVar = args.fUniformHandler->addUniform(
                    &_outer, kFragment_GrShaderFlag, kHalf4_GrSLType, "uniformColor");
        }
        SkString _input0 = SkStringPrintf(
                "%s ? %s : half4(%f, %f, %f, %f)",
                (_outer.useUniform ? "true" : "false"),
                uniformColorVar.isValid() ? args.fUniformHandler->getUniformCStr(uniformColorVar)
                                          : "half4(0)",
                _outer.literalColor.fR,
                _outer.literalColor.fG,
                _outer.literalColor.fB,
                _outer.literalColor.fA);
        SkString _sample0 = this->invokeChild(0, _input0.c_str(), args);
        fragBuilder->codeAppendf(
                R"SkSL(return %s;
)SkSL",
                _sample0.c_str());
    }

private:
    void onSetData(const GrGLSLProgramDataManager& pdman,
                   const GrFragmentProcessor& _proc) override {
        const GrOverrideInputFragmentProcessor& _outer =
                _proc.cast<GrOverrideInputFragmentProcessor>();
        {
            if (uniformColorVar.isValid()) {
                pdman.set4fv(uniformColorVar, 1, (_outer.uniformColor).vec());
            }
        }
    }
    UniformHandle uniformColorVar;
};
std::unique_ptr<GrGLSLFragmentProcessor> GrOverrideInputFragmentProcessor::onMakeProgramImpl()
        const {
    return std::make_unique<GrGLSLOverrideInputFragmentProcessor>();
}
void GrOverrideInputFragmentProcessor::onGetGLSLProcessorKey(const GrShaderCaps& caps,
                                                             GrProcessorKeyBuilder* b) const {
    b->addBool(useUniform, "useUniform");
    if (!useUniform) {
        uint16_t red = SkFloatToHalf(literalColor.fR);
        uint16_t green = SkFloatToHalf(literalColor.fG);
        uint16_t blue = SkFloatToHalf(literalColor.fB);
        uint16_t alpha = SkFloatToHalf(literalColor.fA);
        b->add32(((uint32_t)red << 16) | green, "literalColor.rg");
        b->add32(((uint32_t)blue << 16) | alpha, "literalColor.ba");
    }
}
bool GrOverrideInputFragmentProcessor::onIsEqual(const GrFragmentProcessor& other) const {
    const GrOverrideInputFragmentProcessor& that = other.cast<GrOverrideInputFragmentProcessor>();
    (void)that;
    if (useUniform != that.useUniform) return false;
    if (uniformColor != that.uniformColor) return false;
    if (literalColor != that.literalColor) return false;
    return true;
}
GrOverrideInputFragmentProcessor::GrOverrideInputFragmentProcessor(
        const GrOverrideInputFragmentProcessor& src)
        : INHERITED(kGrOverrideInputFragmentProcessor_ClassID, src.optimizationFlags())
        , useUniform(src.useUniform)
        , uniformColor(src.uniformColor)
        , literalColor(src.literalColor) {
    this->cloneAndRegisterAllChildProcessors(src);
}
std::unique_ptr<GrFragmentProcessor> GrOverrideInputFragmentProcessor::clone() const {
    return std::make_unique<GrOverrideInputFragmentProcessor>(*this);
}
#if GR_TEST_UTILS
SkString GrOverrideInputFragmentProcessor::onDumpInfo() const {
    return SkStringPrintf(
            "(useUniform=%s, uniformColor=half4(%f, %f, %f, %f), literalColor=half4(%f, %f, %f, "
            "%f))",
            (useUniform ? "true" : "false"),
            uniformColor.fR,
            uniformColor.fG,
            uniformColor.fB,
            uniformColor.fA,
            literalColor.fR,
            literalColor.fG,
            literalColor.fB,
            literalColor.fA);
}
#endif
