/*
 * Copyright 2017 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 GrCircleEffect.fp; do not modify.
 **************************************************************************************************/
#include "GrCircleEffect.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 GrGLSLCircleEffect : public GrGLSLFragmentProcessor {
public:
    GrGLSLCircleEffect() {}
    void emitCode(EmitArgs& args) override {
        GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
        const GrCircleEffect& _outer = args.fFp.cast<GrCircleEffect>();
        (void)_outer;
        auto edgeType = _outer.edgeType;
        (void)edgeType;
        auto center = _outer.center;
        (void)center;
        auto radius = _outer.radius;
        (void)radius;
        prevRadius = -1.0;
        circleVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kFloat4_GrSLType,
                                                     "circle");
        fragBuilder->codeAppendf(
                "float2 prevCenter;\nfloat prevRadius = %f;\nhalf d;\n@if (%d == 2 || %d == 3) {\n "
                "   d = half((length((%s.xy - sk_FragCoord.xy) * %s.w) - 1.0) * %s.z);\n} else {\n "
                "   d = half((1.0 - length((%s.xy - sk_FragCoord.xy) * %s.w)) * %s.z);\n}\n@if "
                "((%d == 1 || %d == 3) || %d == 4) {\n    %s = %s * clamp(d, 0.0, 1.0);\n} else "
                "{\n    %s = d > 0.5 ? %s : half4(0.0);\n}\n",
                prevRadius, (int)_outer.edgeType, (int)_outer.edgeType,
                args.fUniformHandler->getUniformCStr(circleVar),
                args.fUniformHandler->getUniformCStr(circleVar),
                args.fUniformHandler->getUniformCStr(circleVar),
                args.fUniformHandler->getUniformCStr(circleVar),
                args.fUniformHandler->getUniformCStr(circleVar),
                args.fUniformHandler->getUniformCStr(circleVar), (int)_outer.edgeType,
                (int)_outer.edgeType, (int)_outer.edgeType, args.fOutputColor, args.fInputColor,
                args.fOutputColor, args.fInputColor);
    }

private:
    void onSetData(const GrGLSLProgramDataManager& pdman,
                   const GrFragmentProcessor& _proc) override {
        const GrCircleEffect& _outer = _proc.cast<GrCircleEffect>();
        auto edgeType = _outer.edgeType;
        (void)edgeType;
        auto center = _outer.center;
        (void)center;
        auto radius = _outer.radius;
        (void)radius;
        UniformHandle& circle = circleVar;
        (void)circle;

        if (radius != prevRadius || center != prevCenter) {
            SkScalar effectiveRadius = radius;
            if (GrProcessorEdgeTypeIsInverseFill((GrClipEdgeType)edgeType)) {
                effectiveRadius -= 0.5f;
                // When the radius is 0.5 effectiveRadius is 0 which causes an inf * 0 in the
                // shader.
                effectiveRadius = std::max(0.001f, effectiveRadius);
            } else {
                effectiveRadius += 0.5f;
            }
            pdman.set4f(circle, center.fX, center.fY, effectiveRadius,
                        SkScalarInvert(effectiveRadius));
            prevCenter = center;
            prevRadius = radius;
        }
    }
    SkPoint prevCenter = float2(0);
    float prevRadius = 0;
    UniformHandle circleVar;
};
GrGLSLFragmentProcessor* GrCircleEffect::onCreateGLSLInstance() const {
    return new GrGLSLCircleEffect();
}
void GrCircleEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
                                           GrProcessorKeyBuilder* b) const {
    b->add32((int32_t)edgeType);
}
bool GrCircleEffect::onIsEqual(const GrFragmentProcessor& other) const {
    const GrCircleEffect& that = other.cast<GrCircleEffect>();
    (void)that;
    if (edgeType != that.edgeType) return false;
    if (center != that.center) return false;
    if (radius != that.radius) return false;
    return true;
}
GrCircleEffect::GrCircleEffect(const GrCircleEffect& src)
        : INHERITED(kGrCircleEffect_ClassID, src.optimizationFlags())
        , edgeType(src.edgeType)
        , center(src.center)
        , radius(src.radius) {}
std::unique_ptr<GrFragmentProcessor> GrCircleEffect::clone() const {
    return std::unique_ptr<GrFragmentProcessor>(new GrCircleEffect(*this));
}
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrCircleEffect);
#if GR_TEST_UTILS
std::unique_ptr<GrFragmentProcessor> GrCircleEffect::TestCreate(GrProcessorTestData* testData) {
    SkPoint center;
    center.fX = testData->fRandom->nextRangeScalar(0.f, 1000.f);
    center.fY = testData->fRandom->nextRangeScalar(0.f, 1000.f);
    SkScalar radius = testData->fRandom->nextRangeF(1.f, 1000.f);
    GrClipEdgeType et;
    do {
        et = (GrClipEdgeType)testData->fRandom->nextULessThan(kGrClipEdgeTypeCnt);
    } while (GrClipEdgeType::kHairlineAA == et);
    return GrCircleEffect::Make(et, center, radius);
}
#endif
