/*
 * Copyright 2018 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 GrClampedGradientEffect.fp; do not modify.
 **************************************************************************************************/
#include "GrClampedGradientEffect.h"
#include "glsl/GrGLSLFragmentProcessor.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLProgramBuilder.h"
#include "GrTexture.h"
#include "SkSLCPP.h"
#include "SkSLUtil.h"
class GrGLSLClampedGradientEffect : public GrGLSLFragmentProcessor {
public:
    GrGLSLClampedGradientEffect() {}
    void emitCode(EmitArgs& args) override {
        GrGLSLFPFragmentBuilder*       fragBuilder = args.fFragBuilder;
        const GrClampedGradientEffect& _outer      = args.fFp.cast<GrClampedGradientEffect>();
        (void)_outer;
        auto leftBorderColor = _outer.leftBorderColor();
        (void)leftBorderColor;
        auto rightBorderColor = _outer.rightBorderColor();
        (void)rightBorderColor;
        auto makePremul = _outer.makePremul();
        (void)makePremul;
        auto colorsAreOpaque = _outer.colorsAreOpaque();
        (void)colorsAreOpaque;
        fLeftBorderColorVar = args.fUniformHandler->addUniform(
                kFragment_GrShaderFlag, kHalf4_GrSLType, "leftBorderColor");
        fRightBorderColorVar = args.fUniformHandler->addUniform(
                kFragment_GrShaderFlag, kHalf4_GrSLType, "rightBorderColor");
        SkString _child1("_child1");
        this->emitChild(_outer.gradLayout_index(), &_child1, args);
        fragBuilder->codeAppendf(
                "half4 t = %s;\nif (!%s && t.y < 0.0) {\n    %s = half4(0.0);\n} else if (t.x < "
                "0.0) {\n    %s = %s;\n} else if (t.x > 1.0) {\n    %s = %s;\n} else {",
                _child1.c_str(),
                (_outer.childProcessor(_outer.gradLayout_index()).preservesOpaqueInput() ? "true"
                                                                                         : "false"),
                args.fOutputColor,
                args.fOutputColor,
                args.fUniformHandler->getUniformCStr(fLeftBorderColorVar),
                args.fOutputColor,
                args.fUniformHandler->getUniformCStr(fRightBorderColorVar));
        SkString _input0("t");
        SkString _child0("_child0");
        this->emitChild(_outer.colorizer_index(), _input0.c_str(), &_child0, args);
        fragBuilder->codeAppendf("\n    %s = %s;\n}\n@if (%s) {\n    %s.xyz *= %s.w;\n}\n",
                                 args.fOutputColor,
                                 _child0.c_str(),
                                 (_outer.makePremul() ? "true" : "false"),
                                 args.fOutputColor,
                                 args.fOutputColor);
    }

private:
    void onSetData(const GrGLSLProgramDataManager& pdman,
                   const GrFragmentProcessor&      _proc) override {
        const GrClampedGradientEffect& _outer = _proc.cast<GrClampedGradientEffect>();
        {
            const SkPMColor4f& leftBorderColorValue = _outer.leftBorderColor();
            if (fLeftBorderColorPrev != leftBorderColorValue) {
                fLeftBorderColorPrev = leftBorderColorValue;
                pdman.set4fv(fLeftBorderColorVar, 1, leftBorderColorValue.vec());
            }
            const SkPMColor4f& rightBorderColorValue = _outer.rightBorderColor();
            if (fRightBorderColorPrev != rightBorderColorValue) {
                fRightBorderColorPrev = rightBorderColorValue;
                pdman.set4fv(fRightBorderColorVar, 1, rightBorderColorValue.vec());
            }
        }
    }
    SkPMColor4f   fLeftBorderColorPrev  = {SK_FloatNaN, SK_FloatNaN, SK_FloatNaN, SK_FloatNaN};
    SkPMColor4f   fRightBorderColorPrev = {SK_FloatNaN, SK_FloatNaN, SK_FloatNaN, SK_FloatNaN};
    UniformHandle fLeftBorderColorVar;
    UniformHandle fRightBorderColorVar;
};
GrGLSLFragmentProcessor* GrClampedGradientEffect::onCreateGLSLInstance() const {
    return new GrGLSLClampedGradientEffect();
}
void GrClampedGradientEffect::onGetGLSLProcessorKey(const GrShaderCaps&    caps,
                                                    GrProcessorKeyBuilder* b) const {
    b->add32((int32_t)fMakePremul);
}
bool GrClampedGradientEffect::onIsEqual(const GrFragmentProcessor& other) const {
    const GrClampedGradientEffect& that = other.cast<GrClampedGradientEffect>();
    (void)that;
    if (fLeftBorderColor != that.fLeftBorderColor)
        return false;
    if (fRightBorderColor != that.fRightBorderColor)
        return false;
    if (fMakePremul != that.fMakePremul)
        return false;
    if (fColorsAreOpaque != that.fColorsAreOpaque)
        return false;
    return true;
}
GrClampedGradientEffect::GrClampedGradientEffect(const GrClampedGradientEffect& src)
        : INHERITED(kGrClampedGradientEffect_ClassID, src.optimizationFlags())
        , fColorizer_index(src.fColorizer_index)
        , fGradLayout_index(src.fGradLayout_index)
        , fLeftBorderColor(src.fLeftBorderColor)
        , fRightBorderColor(src.fRightBorderColor)
        , fMakePremul(src.fMakePremul)
        , fColorsAreOpaque(src.fColorsAreOpaque) {
    this->registerChildProcessor(src.childProcessor(fColorizer_index).clone());
    this->registerChildProcessor(src.childProcessor(fGradLayout_index).clone());
}
std::unique_ptr<GrFragmentProcessor> GrClampedGradientEffect::clone() const {
    return std::unique_ptr<GrFragmentProcessor>(new GrClampedGradientEffect(*this));
}
