/*
 * 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 GrEllipseEffect.fp; do not modify.
 */
#include "GrEllipseEffect.h"
#if SK_SUPPORT_GPU
#include "glsl/GrGLSLColorSpaceXformHelper.h"
#include "glsl/GrGLSLFragmentProcessor.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLProgramBuilder.h"
#include "SkSLCPP.h"
#include "SkSLUtil.h"
class GrGLSLEllipseEffect : public GrGLSLFragmentProcessor {
public:
    GrGLSLEllipseEffect() {}
    void emitCode(EmitArgs& args) override {
        GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
        const GrEllipseEffect& _outer = args.fFp.cast<GrEllipseEffect>();
        (void) _outer;
prevRadii = vec2(-1.0);
useScale = sk_Caps.floatPrecisionVaries;
        fEllipseVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kVec4f_GrSLType, kHigh_GrSLPrecision, "ellipse");
        if (useScale) {
            fScaleVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kVec2f_GrSLType, kDefault_GrSLPrecision, "scale");
        }
        fragBuilder->codeAppendf("vec2 prevCenter;\nvec2 prevRadii = vec2(%f, %f);\nbool useScale = %s;\nvec2 d = sk_FragCoord.xy - %s.xy;\n@if (useScale) {\n    d *= %s.y;\n}\nvec2 Z = d * %s.zw;\nfloat implicit = dot(Z, d) - 1.0;\nfloat grad_dot = 4.0 * dot(Z, Z);\ngrad_dot = max(grad_dot, 0.0001);\nfloat approx_dist = implicit * inversesqrt(grad_dot);\n@if (useScale) {\n    approx_dist *= %s.x;\n}\nfloat alpha;\n@switch (%d) {\n    case 0:\n        alpha = approx_dist > 0.0 ? 0.0 : 1.0;\n        break;\n    case 1:\n        alpha = clamp(0.5 - approx_dist, 0.0, 1.0);\n        break;\n    case 2:\n        alpha = approx_dist > 0.0 ? 1.0 : 0.0;\n        break;\n    case 3:\n        alpha = clamp(0.5 + approx_dist, 0.0, 1.0);\n        break;\n    default:\n        discard;\n}\n%s = %s * alpha;\n", prevRadii.fX, prevRadii.fY, (useScale ? "true" : "false"), args.fUniformHandler->getUniformCStr(fEllipseVar), fScaleVar.isValid() ? args.fUniformHandler->getUniformCStr(fScaleVar) : "vec2(0.0)", args.fUniformHandler->getUniformCStr(fEllipseVar), fScaleVar.isValid() ? args.fUniformHandler->getUniformCStr(fScaleVar) : "vec2(0.0)", _outer.edgeType(), args.fOutputColor, args.fInputColor ? args.fInputColor : "vec4(1)");
    }
private:
    void onSetData(const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& _proc) override {
        const GrEllipseEffect& _outer = _proc.cast<GrEllipseEffect>();
        auto edgeType = _outer.edgeType();
        (void) edgeType;
        auto center = _outer.center();
        (void) center;
        auto radii = _outer.radii();
        (void) radii;
        UniformHandle& ellipse = fEllipseVar;
        (void) ellipse;
        UniformHandle& scale = fScaleVar;
        (void) scale;

    if (radii != prevRadii || center != prevCenter) {
        float invRXSqd;
        float invRYSqd;
        
        
        if (scale.isValid()) {
            if (radii.fX > radii.fY) {
                invRXSqd = 1.f;
                invRYSqd = (radii.fX * radii.fX) /
                           (radii.fY * radii.fY);
                pdman.set2f(scale, radii.fX, 1.f / radii.fX);
            } else {
                invRXSqd = (radii.fY * radii.fY) /
                           (radii.fX * radii.fX);
                invRYSqd = 1.f;
                pdman.set2f(scale, radii.fY, 1.f / radii.fY);
            }
        } else {
            invRXSqd = 1.f / (radii.fX * radii.fX);
            invRYSqd = 1.f / (radii.fY * radii.fY);
        }
        pdman.set4f(ellipse, center.fX, center.fY, invRXSqd, invRYSqd);
        prevCenter = center;
        prevRadii = radii;
    }
    }
SkPoint prevCenter;
SkPoint prevRadii;
bool useScale;
    UniformHandle fEllipseVar;
    UniformHandle fScaleVar;
};
GrGLSLFragmentProcessor* GrEllipseEffect::onCreateGLSLInstance() const {
    return new GrGLSLEllipseEffect();
}
void GrEllipseEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const {
    b->add32(fEdgeType);
}
bool GrEllipseEffect::onIsEqual(const GrFragmentProcessor& other) const {
    const GrEllipseEffect& that = other.cast<GrEllipseEffect>();
    (void) that;
    if (fEdgeType != that.fEdgeType) return false;
    if (fCenter != that.fCenter) return false;
    if (fRadii != that.fRadii) return false;
    return true;
}
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrEllipseEffect);
#if GR_TEST_UTILS
sk_sp<GrFragmentProcessor> GrEllipseEffect::TestCreate(GrProcessorTestData* testData) {

    SkPoint center;
    center.fX = testData->fRandom->nextRangeScalar(0.f, 1000.f);
    center.fY = testData->fRandom->nextRangeScalar(0.f, 1000.f);
    SkScalar rx = testData->fRandom->nextRangeF(0.f, 1000.f);
    SkScalar ry = testData->fRandom->nextRangeF(0.f, 1000.f);
    GrPrimitiveEdgeType et;
    do {
        et = (GrPrimitiveEdgeType) testData->fRandom->nextULessThan(kGrProcessorEdgeTypeCnt);
    } while (kHairlineAA_GrProcessorEdgeType == et);
    return GrEllipseEffect::Make(et, center, SkPoint::Make(rx, ry));
}
#endif
#endif
