/*
 * 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, "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(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(invR1)",
                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(
                ";\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) {
    SkScalar scale  = GrGradientShader::RandomParams::kGradientScale;
    SkScalar offset = scale / 32.0f;

    SkPoint  center1 = {d->fRandom->nextRangeScalar(0.0f, scale),
                       d->fRandom->nextRangeScalar(0.0f, scale)};
    SkPoint  center2 = {d->fRandom->nextRangeScalar(0.0f, scale),
                       d->fRandom->nextRangeScalar(0.0f, scale)};
    SkScalar radius1 = d->fRandom->nextRangeScalar(0.0f, scale);
    SkScalar radius2 = d->fRandom->nextRangeScalar(0.0f, scale);

    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 += offset;
        }
    } 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 += offset;
        }
    } else {  // kFocal_Type
        // Make sure that the centers are different
        if (SkScalarNearlyZero(SkPoint::Distance(center1, center2))) {
            center2.fX += offset;
        }

        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 += offset;
        }
    }

    if (SkScalarNearlyZero(radius1 - radius2) &&
        SkScalarNearlyZero(SkPoint::Distance(center1, center2))) {
        radius2 += offset;  // 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));
}
