/*
 * 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 GrRectBlurEffect.fp; do not modify.
 **************************************************************************************************/
#include "GrRectBlurEffect.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 GrGLSLRectBlurEffect : public GrGLSLFragmentProcessor {
public:
    GrGLSLRectBlurEffect() {}
    void emitCode(EmitArgs& args) override {
        GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
        const GrRectBlurEffect& _outer = args.fFp.cast<GrRectBlurEffect>();
        (void)_outer;
        auto rect = _outer.rect;
        (void)rect;
        auto sigma = _outer.sigma;
        (void)sigma;
        highp = ((abs(rect.left()) > 16000.0 || abs(rect.top()) > 16000.0) ||
                 abs(rect.right()) > 16000.0) ||
                abs(rect.bottom()) > 16000.0;
        if (highp) {
            rectFVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kFloat4_GrSLType,
                                                        "rectF");
        }
        if (!highp) {
            rectHVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
                                                        "rectH");
        }
        sigmaVar =
                args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "sigma");
        fragBuilder->codeAppendf(
                "/* key */ bool highp = %s;\nhalf invr = 1.0 / (2.0 * %s);\nhalf x;\n@if (highp) "
                "{\n    float lDiff = %s.x - sk_FragCoord.x;\n    float rDiff = sk_FragCoord.x - "
                "%s.z;\n    x = half(max(lDiff, rDiff) * float(invr));\n} else {\n    half lDiff = "
                "half(float(%s.x) - sk_FragCoord.x);\n    half rDiff = half(sk_FragCoord.x - "
                "float(%s.z));\n    x = max(lDiff, rDiff) * invr;\n}\nhalf xCoverage;\nif (x > "
                "1.5) {\n    xCoverage = 0.0;\n} else if (x < -1.5) {\n    xCoverage = 1.0;\n} "
                "else {\n    half x2 = x * x;\n    half",
                (highp ? "true" : "false"), args.fUniformHandler->getUniformCStr(sigmaVar),
                rectFVar.isValid() ? args.fUniformHandler->getUniformCStr(rectFVar) : "float4(0)",
                rectFVar.isValid() ? args.fUniformHandler->getUniformCStr(rectFVar) : "float4(0)",
                rectHVar.isValid() ? args.fUniformHandler->getUniformCStr(rectHVar) : "half4(0)",
                rectHVar.isValid() ? args.fUniformHandler->getUniformCStr(rectHVar) : "half4(0)");
        fragBuilder->codeAppendf(
                " x3 = x2 * x;\n    if (x > 0.5) {\n        xCoverage = 0.5625 - ((x3 / 6.0 - (3.0 "
                "* x2) * 0.25) + 1.125 * x);\n    } else if (x > -0.5) {\n        xCoverage = 0.5 "
                "- (0.75 * x - x3 / 3.0);\n    } else {\n        xCoverage = 0.4375 + ((-x3 / 6.0 "
                "- (3.0 * x2) * 0.25) - 1.125 * x);\n    }\n}\nhalf y;\n@if (highp) {\n    float "
                "tDiff = %s.y - sk_FragCoord.y;\n    float bDiff = sk_FragCoord.y - %s.w;\n    y = "
                "half(max(tDiff, bDiff) * float(invr));\n} else {\n    half tDiff = "
                "half(float(%s.y) - sk_FragCoord.y);\n  ",
                rectFVar.isValid() ? args.fUniformHandler->getUniformCStr(rectFVar) : "float4(0)",
                rectFVar.isValid() ? args.fUniformHandler->getUniformCStr(rectFVar) : "float4(0)",
                rectHVar.isValid() ? args.fUniformHandler->getUniformCStr(rectHVar) : "half4(0)");
        fragBuilder->codeAppendf(
                "  half bDiff = half(sk_FragCoord.y - float(%s.w));\n    y = max(tDiff, bDiff) * "
                "invr;\n}\nhalf yCoverage;\nif (y > 1.5) {\n    yCoverage = 0.0;\n} else if (y < "
                "-1.5) {\n    yCoverage = 1.0;\n} else {\n    half y2 = y * y;\n    half y3 = y2 * "
                "y;\n    if (y > 0.5) {\n        yCoverage = 0.5625 - ((y3 / 6.0 - (3.0 * y2) * "
                "0.25) + 1.125 * y);\n    } else if (y > -0.5) {\n        yCoverage = 0.5 - (0.75 "
                "* y - y3 / 3.0);\n    } else {\n        yCoverage = 0.4375 + ((-y3 / 6.0 - (3.0 * "
                "y2) * 0.25) - 1.125 * y);\n ",
                rectHVar.isValid() ? args.fUniformHandler->getUniformCStr(rectHVar) : "half4(0)");
        fragBuilder->codeAppendf("   }\n}\n%s = (%s * xCoverage) * yCoverage;\n", args.fOutputColor,
                                 args.fInputColor);
    }

private:
    void onSetData(const GrGLSLProgramDataManager& pdman,
                   const GrFragmentProcessor& _proc) override {
        const GrRectBlurEffect& _outer = _proc.cast<GrRectBlurEffect>();
        { pdman.set1f(sigmaVar, (_outer.sigma)); }
        auto rect = _outer.rect;
        (void)rect;
        UniformHandle& rectF = rectFVar;
        (void)rectF;
        UniformHandle& rectH = rectHVar;
        (void)rectH;
        UniformHandle& sigma = sigmaVar;
        (void)sigma;

        float r[]{rect.fLeft, rect.fTop, rect.fRight, rect.fBottom};
        pdman.set4fv(highp ? rectF : rectH, 1, r);
    }
    bool highp = false;
    UniformHandle rectFVar;
    UniformHandle rectHVar;
    UniformHandle sigmaVar;
};
GrGLSLFragmentProcessor* GrRectBlurEffect::onCreateGLSLInstance() const {
    return new GrGLSLRectBlurEffect();
}
void GrRectBlurEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
                                             GrProcessorKeyBuilder* b) const {
    bool highp = ((abs(rect.left()) > 16000.0 || abs(rect.top()) > 16000.0) ||
                  abs(rect.right()) > 16000.0) ||
                 abs(rect.bottom()) > 16000.0;
    b->add32((int32_t)highp);
}
bool GrRectBlurEffect::onIsEqual(const GrFragmentProcessor& other) const {
    const GrRectBlurEffect& that = other.cast<GrRectBlurEffect>();
    (void)that;
    if (rect != that.rect) return false;
    if (sigma != that.sigma) return false;
    return true;
}
GrRectBlurEffect::GrRectBlurEffect(const GrRectBlurEffect& src)
        : INHERITED(kGrRectBlurEffect_ClassID, src.optimizationFlags())
        , rect(src.rect)
        , sigma(src.sigma) {}
std::unique_ptr<GrFragmentProcessor> GrRectBlurEffect::clone() const {
    return std::unique_ptr<GrFragmentProcessor>(new GrRectBlurEffect(*this));
}
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrRectBlurEffect);
#if GR_TEST_UTILS
std::unique_ptr<GrFragmentProcessor> GrRectBlurEffect::TestCreate(GrProcessorTestData* data) {
    float sigma = data->fRandom->nextRangeF(3, 8);
    float width = data->fRandom->nextRangeF(200, 300);
    float height = data->fRandom->nextRangeF(200, 300);
    return GrRectBlurEffect::Make(data->proxyProvider(), *data->caps()->shaderCaps(),
                                  SkRect::MakeWH(width, height), sigma);
}
#endif
