/*
 * 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 GrTwoPointConicalGradientLayout.fp; do not modify.
 **************************************************************************************************/
#include "GrTwoPointConicalGradientLayout.h"
#include "glsl/GrGLSLFragmentProcessor.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLProgramBuilder.h"
#include "GrTexture.h"
#include "SkSLCPP.h"
#include "SkSLUtil.h"
class GrGLSLTwoPointConicalGradientLayout : public GrGLSLFragmentProcessor {
public:
    GrGLSLTwoPointConicalGradientLayout() {}
    void emitCode(EmitArgs& args) override {
        GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
        const GrTwoPointConicalGradientLayout& _outer =
                args.fFp.cast<GrTwoPointConicalGradientLayout>();
        (void)_outer;
        auto gradientMatrix = _outer.gradientMatrix();
        (void)gradientMatrix;
        auto type = _outer.type();
        (void)type;
        auto isRadiusIncreasing = _outer.isRadiusIncreasing();
        (void)isRadiusIncreasing;
        auto isFocalOnCircle = _outer.isFocalOnCircle();
        (void)isFocalOnCircle;
        auto isWellBehaved = _outer.isWellBehaved();
        (void)isWellBehaved;
        auto isSwapped = _outer.isSwapped();
        (void)isSwapped;
        auto isNativelyFocal = _outer.isNativelyFocal();
        (void)isNativelyFocal;
        auto focalParams = _outer.focalParams();
        (void)focalParams;
        fFocalParamsVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
                                                           kDefault_GrSLPrecision, "focalParams");
        SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
        fragBuilder->codeAppendf(
                "float2 p = %s;\nfloat t = -1.0;\nhalf v = 1.0;\n@switch (%d) {\n    case 1:\n     "
                "   {\n            half r0_2 = %s.y;\n            t = float(float(r0_2) - p.y * "
                "p.y);\n            if (t >= 0.0) {\n                t = p.x + sqrt(t);\n          "
                "  } else {\n                v = -1.0;\n            }\n        }\n        break;\n "
                "   case 0:\n        {\n            half r0 = %s.x;\n            @if (%s) {\n      "
                "          t = length(p) - float(r0);\n            } else {\n                t = "
                "-length(p) - float(r0);\n",
                sk_TransformedCoords2D_0.c_str(), (int)_outer.type(),
                args.fUniformHandler->getUniformCStr(fFocalParamsVar),
                args.fUniformHandler->getUniformCStr(fFocalParamsVar),
                (_outer.isRadiusIncreasing() ? "true" : "false"));
        fragBuilder->codeAppendf(
                "            }\n        }\n        break;\n    case 2:\n        {\n            "
                "half invR1 = %s.x;\n            half fx = %s.y;\n            float x_t = -1.0;\n  "
                "          @if (%s) {\n                x_t = dot(p, p) / p.x;\n            } else "
                "if (%s) {\n                x_t = length(p) - p.x * float(invR1);\n            } "
                "else {\n                float temp = p.x * p.x - p.y * p.y;\n                if "
                "(temp >= 0.0) {\n                    @if (%s || !%s) {\n                        "
                "x_t = -sqrt(temp) - p.x * float",
                args.fUniformHandler->getUniformCStr(fFocalParamsVar),
                args.fUniformHandler->getUniformCStr(fFocalParamsVar),
                (_outer.isFocalOnCircle() ? "true" : "false"),
                (_outer.isWellBehaved() ? "true" : "false"),
                (_outer.isSwapped() ? "true" : "false"),
                (_outer.isRadiusIncreasing() ? "true" : "false"));
        fragBuilder->codeAppendf(
                "(invR1);\n                    } else {\n                        x_t = sqrt(temp) "
                "- p.x * float(invR1);\n                    }\n                }\n            }\n  "
                "          @if (!%s) {\n                if (x_t <= 0.0) {\n                    v = "
                "-1.0;\n                }\n            }\n            @if (%s) {\n                "
                "@if (%s) {\n                    t = x_t;\n                } else {\n              "
                "      t = x_t + float(fx);\n                }\n            } else {\n             "
                "   @if (%s) {\n       ",
                (_outer.isWellBehaved() ? "true" : "false"),
                (_outer.isRadiusIncreasing() ? "true" : "false"),
                (_outer.isNativelyFocal() ? "true" : "false"),
                (_outer.isNativelyFocal() ? "true" : "false"));
        fragBuilder->codeAppendf(
                "             t = -x_t;\n                } else {\n                    t = -x_t + "
                "float(fx);\n                }\n            }\n            @if (%s) {\n            "
                "    t = 1.0 - t;\n            }\n        }\n        break;\n}\n%s = "
                "half4(half(t), v, 0.0, 0.0);\n",
                (_outer.isSwapped() ? "true" : "false"), args.fOutputColor);
    }

private:
    void onSetData(const GrGLSLProgramDataManager& pdman,
                   const GrFragmentProcessor& _proc) override {
        const GrTwoPointConicalGradientLayout& _outer =
                _proc.cast<GrTwoPointConicalGradientLayout>();
        {
            const SkPoint& focalParamsValue = _outer.focalParams();
            if (fFocalParamsPrev != focalParamsValue) {
                fFocalParamsPrev = focalParamsValue;
                pdman.set2f(fFocalParamsVar, focalParamsValue.fX, focalParamsValue.fY);
            }
        }
    }
    SkPoint fFocalParamsPrev = SkPoint::Make(SK_FloatNaN, SK_FloatNaN);
    UniformHandle fFocalParamsVar;
};
GrGLSLFragmentProcessor* GrTwoPointConicalGradientLayout::onCreateGLSLInstance() const {
    return new GrGLSLTwoPointConicalGradientLayout();
}
void GrTwoPointConicalGradientLayout::onGetGLSLProcessorKey(const GrShaderCaps& caps,
                                                            GrProcessorKeyBuilder* b) const {
    b->add32((int32_t)fType);
    b->add32((int32_t)fIsRadiusIncreasing);
    b->add32((int32_t)fIsFocalOnCircle);
    b->add32((int32_t)fIsWellBehaved);
    b->add32((int32_t)fIsSwapped);
    b->add32((int32_t)fIsNativelyFocal);
}
bool GrTwoPointConicalGradientLayout::onIsEqual(const GrFragmentProcessor& other) const {
    const GrTwoPointConicalGradientLayout& that = other.cast<GrTwoPointConicalGradientLayout>();
    (void)that;
    if (fGradientMatrix != that.fGradientMatrix) return false;
    if (fType != that.fType) return false;
    if (fIsRadiusIncreasing != that.fIsRadiusIncreasing) return false;
    if (fIsFocalOnCircle != that.fIsFocalOnCircle) return false;
    if (fIsWellBehaved != that.fIsWellBehaved) return false;
    if (fIsSwapped != that.fIsSwapped) return false;
    if (fIsNativelyFocal != that.fIsNativelyFocal) return false;
    if (fFocalParams != that.fFocalParams) return false;
    return true;
}
GrTwoPointConicalGradientLayout::GrTwoPointConicalGradientLayout(
        const GrTwoPointConicalGradientLayout& src)
        : INHERITED(kGrTwoPointConicalGradientLayout_ClassID, src.optimizationFlags())
        , fGradientMatrix(src.fGradientMatrix)
        , fType(src.fType)
        , fIsRadiusIncreasing(src.fIsRadiusIncreasing)
        , fIsFocalOnCircle(src.fIsFocalOnCircle)
        , fIsWellBehaved(src.fIsWellBehaved)
        , fIsSwapped(src.fIsSwapped)
        , fIsNativelyFocal(src.fIsNativelyFocal)
        , fFocalParams(src.fFocalParams)
        , fCoordTransform0(src.fCoordTransform0) {
    this->addCoordTransform(&fCoordTransform0);
}
std::unique_ptr<GrFragmentProcessor> GrTwoPointConicalGradientLayout::clone() const {
    return std::unique_ptr<GrFragmentProcessor>(new GrTwoPointConicalGradientLayout(*this));
}
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrTwoPointConicalGradientLayout);
#if GR_TEST_UTILS
std::unique_ptr<GrFragmentProcessor> GrTwoPointConicalGradientLayout::TestCreate(
        GrProcessorTestData* d) {
    SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
    SkPoint center2 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
    SkScalar radius1 = d->fRandom->nextUScalar1();
    SkScalar radius2 = d->fRandom->nextUScalar1();

    constexpr int kTestTypeMask = (1 << 2) - 1, kTestNativelyFocalBit = (1 << 2),
                  kTestFocalOnCircleBit = (1 << 3), kTestSwappedBit = (1 << 4);
    // We won't treat isWellDefined and isRadiusIncreasing specially because they
    // should have high probability to be turned on and off as we're getting random
    // radii and centers.

    int mask = d->fRandom->nextU();
    int type = mask & kTestTypeMask;
    if (type == static_cast<int>(Type::kRadial)) {
        center2 = center1;
        // Make sure that the radii are different
        if (SkScalarNearlyZero(radius1 - radius2)) {
            radius2 += .1f;
        }
    } else if (type == static_cast<int>(Type::kStrip)) {
        radius1 = SkTMax(radius1, .1f);  // Make sure that the radius is non-zero
        radius2 = radius1;
        // Make sure that the centers are different
        if (SkScalarNearlyZero(SkPoint::Distance(center1, center2))) {
            center2.fX += .1f;
        }
    } else {  // kFocal_Type
        // Make sure that the centers are different
        if (SkScalarNearlyZero(SkPoint::Distance(center1, center2))) {
            center2.fX += .1f;
        }

        if (kTestNativelyFocalBit & mask) {
            radius1 = 0;
        }
        if (kTestFocalOnCircleBit & mask) {
            radius2 = radius1 + SkPoint::Distance(center1, center2);
        }
        if (kTestSwappedBit & mask) {
            std::swap(radius1, radius2);
            radius2 = 0;
        }

        // Make sure that the radii are different
        if (SkScalarNearlyZero(radius1 - radius2)) {
            radius2 += .1f;
        }
    }

    if (SkScalarNearlyZero(radius1 - radius2) &&
        SkScalarNearlyZero(SkPoint::Distance(center1, center2))) {
        radius2 += .1f;  // make sure that we're not degenerated
    }

    GrGradientShader::RandomParams params(d->fRandom);
    auto shader = params.fUseColors4f
                          ? SkGradientShader::MakeTwoPointConical(
                                    center1, radius1, center2, radius2, params.fColors4f,
                                    params.fColorSpace, params.fStops, params.fColorCount,
                                    params.fTileMode)
                          : SkGradientShader::MakeTwoPointConical(
                                    center1, radius1, center2, radius2, params.fColors,
                                    params.fStops, params.fColorCount, params.fTileMode);
    GrTest::TestAsFPArgs asFPArgs(d);
    std::unique_ptr<GrFragmentProcessor> fp = as_SB(shader)->asFragmentProcessor(asFPArgs.args());

    GrAlwaysAssert(fp);
    return fp;
}
#endif

// .fp files do not let you reference outside enum definitions, so we have to explicitly map
// between the two compatible enum defs
GrTwoPointConicalGradientLayout::Type convert_type(SkTwoPointConicalGradient::Type type) {
    switch (type) {
        case SkTwoPointConicalGradient::Type::kRadial:
            return GrTwoPointConicalGradientLayout::Type::kRadial;
        case SkTwoPointConicalGradient::Type::kStrip:
            return GrTwoPointConicalGradientLayout::Type::kStrip;
        case SkTwoPointConicalGradient::Type::kFocal:
            return GrTwoPointConicalGradientLayout::Type::kFocal;
    }
    SkDEBUGFAIL("Should not be reachable");
    return GrTwoPointConicalGradientLayout::Type::kRadial;
}

std::unique_ptr<GrFragmentProcessor> GrTwoPointConicalGradientLayout::Make(
        const SkTwoPointConicalGradient& grad, const GrFPArgs& args) {
    GrTwoPointConicalGradientLayout::Type grType = convert_type(grad.getType());

    // The focalData struct is only valid if isFocal is true
    const SkTwoPointConicalGradient::FocalData& focalData = grad.getFocalData();
    bool isFocal = grType == Type::kFocal;

    // Calculate optimization switches from gradient specification
    bool isFocalOnCircle = isFocal && focalData.isFocalOnCircle();
    bool isWellBehaved = isFocal && focalData.isWellBehaved();
    bool isSwapped = isFocal && focalData.isSwapped();
    bool isNativelyFocal = isFocal && focalData.isNativelyFocal();

    // Type-specific calculations: isRadiusIncreasing, focalParams, and the gradient matrix.
    // However, all types start with the total inverse local matrix calculated from the shader
    // and args
    bool isRadiusIncreasing;
    SkPoint focalParams;  // really just a 2D tuple
    SkMatrix matrix;

    // Initialize the base matrix
    if (!grad.totalLocalMatrix(args.fPreLocalMatrix, args.fPostLocalMatrix)->invert(&matrix)) {
        return nullptr;
    }

    if (isFocal) {
        isRadiusIncreasing = (1 - focalData.fFocalX) > 0;

        focalParams.set(1.0 / focalData.fR1, focalData.fFocalX);

        matrix.postConcat(grad.getGradientMatrix());
    } else if (grType == Type::kRadial) {
        SkScalar dr = grad.getDiffRadius();
        isRadiusIncreasing = dr >= 0;

        SkScalar r0 = grad.getStartRadius() / dr;
        focalParams.set(r0, r0 * r0);

        // GPU radial matrix is different from the original matrix, since we map the diff radius
        // to have |dr| = 1, so manually compute the final gradient matrix here.

        // Map center to (0, 0)
        matrix.postTranslate(-grad.getStartCenter().fX, -grad.getStartCenter().fY);

        // scale |diffRadius| to 1
        matrix.postScale(1 / dr, 1 / dr);
    } else {                         // kStrip
        isRadiusIncreasing = false;  // kStrip doesn't use this flag

        SkScalar r0 = grad.getStartRadius() / grad.getCenterX1();
        focalParams.set(r0, r0 * r0);

        matrix.postConcat(grad.getGradientMatrix());
    }

    return std::unique_ptr<GrFragmentProcessor>(new GrTwoPointConicalGradientLayout(
            matrix, grType, isRadiusIncreasing, isFocalOnCircle, isWellBehaved, isSwapped,
            isNativelyFocal, focalParams));
}
