/*
 * 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 GrTiledGradientEffect.fp; do not modify.
 **************************************************************************************************/
#include "GrTiledGradientEffect.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 GrGLSLTiledGradientEffect : public GrGLSLFragmentProcessor {
public:
    GrGLSLTiledGradientEffect() {}
    void emitCode(EmitArgs& args) override {
        GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
        const GrTiledGradientEffect& _outer = args.fFp.cast<GrTiledGradientEffect>();
        (void)_outer;
        auto mirror = _outer.mirror;
        (void)mirror;
        auto makePremul = _outer.makePremul;
        (void)makePremul;
        auto colorsAreOpaque = _outer.colorsAreOpaque;
        (void)colorsAreOpaque;
        auto layoutPreservesOpacity = _outer.layoutPreservesOpacity;
        (void)layoutPreservesOpacity;
        SkString _sample0 = this->invokeChild(1, args);
        fragBuilder->codeAppendf(
                R"SkSL(half4 t = %s;
if (!%s && t.y < 0.0) {
    return half4(0.0);
} else {
    @if (%s) {
        half t_1 = t.x - 1.0;
        half tiled_t = (t_1 - 2.0 * floor(t_1 * 0.5)) - 1.0;
        if (sk_Caps.mustDoOpBetweenFloorAndAbs) {
            tiled_t = clamp(tiled_t, -1.0, 1.0);
        }
        t.x = abs(tiled_t);
    } else {
        t.x = fract(t.x);
    }
    @if (!%s) {)SkSL",
                _sample0.c_str(),
                (_outer.layoutPreservesOpacity ? "true" : "false"),
                (_outer.mirror ? "true" : "false"),
                (_outer.makePremul ? "true" : "false"));
        SkString _coords1("float2(half2(t.x, 0.0))");
        SkString _sample1 = this->invokeChild(0, args, _coords1.c_str());
        fragBuilder->codeAppendf(
                R"SkSL(
        return %s;
    } else {)SkSL",
                _sample1.c_str());
        SkString _coords2("float2(half2(t.x, 0.0))");
        SkString _sample2 = this->invokeChild(0, args, _coords2.c_str());
        fragBuilder->codeAppendf(
                R"SkSL(
        half4 outColor = %s;
        return outColor * half4(outColor.www, 1.0);
    }
}
)SkSL",
                _sample2.c_str());
    }

private:
    void onSetData(const GrGLSLProgramDataManager& pdman,
                   const GrFragmentProcessor& _proc) override {}
};
std::unique_ptr<GrGLSLFragmentProcessor> GrTiledGradientEffect::onMakeProgramImpl() const {
    return std::make_unique<GrGLSLTiledGradientEffect>();
}
void GrTiledGradientEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
                                                  GrProcessorKeyBuilder* b) const {
    b->addBool(mirror, "mirror");
    b->addBool(makePremul, "makePremul");
    b->addBool(layoutPreservesOpacity, "layoutPreservesOpacity");
}
bool GrTiledGradientEffect::onIsEqual(const GrFragmentProcessor& other) const {
    const GrTiledGradientEffect& that = other.cast<GrTiledGradientEffect>();
    (void)that;
    if (mirror != that.mirror) return false;
    if (makePremul != that.makePremul) return false;
    if (colorsAreOpaque != that.colorsAreOpaque) return false;
    if (layoutPreservesOpacity != that.layoutPreservesOpacity) return false;
    return true;
}
GrTiledGradientEffect::GrTiledGradientEffect(const GrTiledGradientEffect& src)
        : INHERITED(kGrTiledGradientEffect_ClassID, src.optimizationFlags())
        , mirror(src.mirror)
        , makePremul(src.makePremul)
        , colorsAreOpaque(src.colorsAreOpaque)
        , layoutPreservesOpacity(src.layoutPreservesOpacity) {
    this->cloneAndRegisterAllChildProcessors(src);
}
std::unique_ptr<GrFragmentProcessor> GrTiledGradientEffect::clone() const {
    return std::make_unique<GrTiledGradientEffect>(*this);
}
#if GR_TEST_UTILS
SkString GrTiledGradientEffect::onDumpInfo() const {
    return SkStringPrintf(
            "(mirror=%s, makePremul=%s, colorsAreOpaque=%s, layoutPreservesOpacity=%s)",
            (mirror ? "true" : "false"),
            (makePremul ? "true" : "false"),
            (colorsAreOpaque ? "true" : "false"),
            (layoutPreservesOpacity ? "true" : "false"));
}
#endif
