/*
 * Copyright 2020 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "tests/Test.h"

#include "include/private/SkFloatingPoint.h"
#include "src/core/SkGeometry.h"
#include "src/gpu/geometry/GrPathUtils.h"
#include "src/gpu/mock/GrMockOpTarget.h"
#include "src/gpu/tessellate/GrStrokeIndirectOp.h"
#include "src/gpu/tessellate/GrStrokeTessellateShader.h"
#include "src/gpu/tessellate/GrTessellationPathRenderer.h"
#include "src/gpu/tessellate/GrWangsFormula.h"

static sk_sp<GrDirectContext> make_mock_context() {
    GrMockOptions mockOptions;
    mockOptions.fDrawInstancedSupport = true;
    mockOptions.fMaxTessellationSegments = 64;
    mockOptions.fMapBufferFlags = GrCaps::kCanMap_MapFlag;
    mockOptions.fConfigOptions[(int)GrColorType::kAlpha_8].fRenderability =
            GrMockOptions::ConfigOptions::Renderability::kMSAA;
    mockOptions.fConfigOptions[(int)GrColorType::kAlpha_8].fTexturable = true;
    mockOptions.fIntegerSupport = true;

    GrContextOptions ctxOptions;
    ctxOptions.fGpuPathRenderers = GpuPathRenderers::kTessellation;

    return GrDirectContext::MakeMock(&mockOptions, ctxOptions);
}

static void test_stroke(skiatest::Reporter* r, GrDirectContext* ctx, GrMeshDrawOp::Target* target,
                        const SkPath& path, SkRandom& rand) {
    SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
    stroke.setStrokeStyle(.1f);
    for (auto join : {SkPaint::kMiter_Join, SkPaint::kRound_Join}) {
        stroke.setStrokeParams(SkPaint::kButt_Cap, join, 4);
        for (int i = 0; i < 16; ++i) {
            float scale = ldexpf(rand.nextF() + 1, i);
            auto op = GrOp::Make<GrStrokeIndirectOp>(ctx, GrAAType::kMSAA,
                                                     SkMatrix::Scale(scale, scale), path, stroke,
                                                     GrPaint());
            auto strokeIndirectOp = op->cast<GrStrokeIndirectOp>();
            strokeIndirectOp->verifyPrePrepareResolveLevels(r, target);
            strokeIndirectOp->verifyPrepareBuffers(r, target);
        }
    }
}

DEF_TEST(tessellate_GrStrokeIndirectOp, r) {
    auto ctx = make_mock_context();
    auto target = std::make_unique<GrMockOpTarget>(ctx);
    SkRandom rand;

    // Empty strokes.
    SkPath path = SkPath();
    test_stroke(r, ctx.get(), target.get(), path, rand);
    path.moveTo(1,1);
    test_stroke(r, ctx.get(), target.get(), path, rand);
    path.moveTo(1,1);
    test_stroke(r, ctx.get(), target.get(), path, rand);
    path.close();
    test_stroke(r, ctx.get(), target.get(), path, rand);
    path.moveTo(1,1);
    test_stroke(r, ctx.get(), target.get(), path, rand);

    // Single line.
    path = SkPath().lineTo(1,1);
    test_stroke(r, ctx.get(), target.get(), path, rand);
    path.close();
    test_stroke(r, ctx.get(), target.get(), path, rand);

    // Single quad.
    path = SkPath().quadTo(1,0,1,1);
    test_stroke(r, ctx.get(), target.get(), path, rand);
    path.close();
    test_stroke(r, ctx.get(), target.get(), path, rand);

    // Single cubic.
    path = SkPath().cubicTo(1,0,0,1,1,1);
    test_stroke(r, ctx.get(), target.get(), path, rand);
    path.close();
    test_stroke(r, ctx.get(), target.get(), path, rand);

    // All types of lines.
    path.reset();
    for (int i = 0; i < (1 << 4); ++i) {
        path.moveTo((i>>0)&1, (i>>1)&1);
        path.lineTo((i>>2)&1, (i>>3)&1);
        path.close();
    }
    test_stroke(r, ctx.get(), target.get(), path, rand);

    // All types of quads.
    path.reset();
    for (int i = 0; i < (1 << 6); ++i) {
        path.moveTo((i>>0)&1, (i>>1)&1);
        path.quadTo((i>>2)&1, (i>>3)&1, (i>>4)&1, (i>>5)&1);
        path.close();
    }
    test_stroke(r, ctx.get(), target.get(), path, rand);

    // All types of cubics.
    path.reset();
    for (int i = 0; i < (1 << 8); ++i) {
        path.moveTo((i>>0)&1, (i>>1)&1);
        path.cubicTo((i>>2)&1, (i>>3)&1, (i>>4)&1, (i>>5)&1, (i>>6)&1, (i>>7)&1);
        path.close();
    }
    test_stroke(r, ctx.get(), target.get(), path, rand);

    {
        // This cubic has a convex-180 chop at T=1-"epsilon"
        static const uint32_t hexPts[] = {0x3ee0ac74, 0x3f1e061a, 0x3e0fc408, 0x3f457230,
                                          0x3f42ac7c, 0x3f70d76c, 0x3f4e6520, 0x3f6acafa};
        SkPoint pts[4];
        memcpy(pts, hexPts, sizeof(pts));
        test_stroke(r, ctx.get(), target.get(),
                    SkPath().moveTo(pts[0]).cubicTo(pts[1], pts[2], pts[3]).close(), rand);
    }

    // Random paths.
    for (int j = 0; j < 50; ++j) {
        path.reset();
        // Empty contours behave differently if closed.
        path.moveTo(0,0);
        path.moveTo(0,0);
        path.close();
        path.moveTo(0,0);
        SkPoint startPoint = {rand.nextF(), rand.nextF()};
        path.moveTo(startPoint);
        // Degenerate curves get skipped.
        path.lineTo(startPoint);
        path.quadTo(startPoint, startPoint);
        path.cubicTo(startPoint, startPoint, startPoint);
        for (int i = 0; i < 100; ++i) {
            switch (rand.nextRangeU(0, 4)) {
                case 0:
                    path.lineTo(rand.nextF(), rand.nextF());
                    break;
                case 1:
                    path.quadTo(rand.nextF(), rand.nextF(), rand.nextF(), rand.nextF());
                    break;
                case 2:
                case 3:
                case 4:
                    path.cubicTo(rand.nextF(), rand.nextF(), rand.nextF(), rand.nextF(),
                                 rand.nextF(), rand.nextF());
                    break;
                default:
                    SkUNREACHABLE;
            }
            if (i % 19 == 0) {
                switch (i/19 % 4) {
                    case 0:
                        break;
                    case 1:
                        path.lineTo(startPoint);
                        break;
                    case 2:
                        path.quadTo(SkPoint::Make(1.1f, 1.1f), startPoint);
                        break;
                    case 3:
                        path.cubicTo(SkPoint::Make(1.1f, 1.1f), SkPoint::Make(1.1f, 1.1f),
                                     startPoint);
                        break;
                }
                path.close();
                if (rand.nextU() & 1) {  // Implicit or explicit move?
                    startPoint = {rand.nextF(), rand.nextF()};
                    path.moveTo(startPoint);
                }
            }
        }
        test_stroke(r, ctx.get(), target.get(), path, rand);
    }
}

// Returns the control point for the first/final join of a contour.
// If the contour is not closed, returns the start point.
static SkPoint get_contour_closing_control_point(SkPathPriv::RangeIter iter,
                                                 const SkPathPriv::RangeIter& end) {
    auto [verb, p, w] = *iter;
    SkASSERT(verb == SkPathVerb::kMove);
    // Peek ahead to find the last control point.
    SkPoint startPoint=p[0], lastControlPoint=p[0];
    for (++iter; iter != end; ++iter) {
        auto [verb, p, w] = *iter;
        switch (verb) {
            case SkPathVerb::kMove:
                return startPoint;
            case SkPathVerb::kCubic:
                if (p[2] != p[3]) {
                    lastControlPoint = p[2];
                    break;
                }
                [[fallthrough]];
            case SkPathVerb::kQuad:
                if (p[1] != p[2]) {
                    lastControlPoint = p[1];
                    break;
                }
                [[fallthrough]];
            case SkPathVerb::kLine:
                if (p[0] != p[1]) {
                    lastControlPoint = p[0];
                }
                break;
            case SkPathVerb::kConic:
                SkUNREACHABLE;
            case SkPathVerb::kClose:
                return (p[0] == startPoint) ? lastControlPoint : p[0];
        }
    }
    return startPoint;
}

static bool check_resolve_level(skiatest::Reporter* r,  float numCombinedSegments,
                                int8_t actualLevel, float tolerance, bool printError = true) {
    int8_t expectedLevel = sk_float_nextlog2(numCombinedSegments);
    if ((actualLevel > expectedLevel &&
         actualLevel > sk_float_nextlog2(numCombinedSegments + tolerance)) ||
        (actualLevel < expectedLevel &&
         actualLevel < sk_float_nextlog2(numCombinedSegments - tolerance))) {
        if (printError) {
            ERRORF(r, "expected %f segments => resolveLevel=%i (got %i)\n",
                   numCombinedSegments, expectedLevel, actualLevel);
        }
        return false;
    }
    return true;
}

static bool check_first_resolve_levels(skiatest::Reporter* r,
                                       const SkTArray<float>& firstNumSegments,
                                       int8_t** nextResolveLevel, float tolerance) {
    for (float numSegments : firstNumSegments) {
        if (numSegments < 0) {
            REPORTER_ASSERT(r, *(*nextResolveLevel)++ == (int)numSegments);
            continue;
        }
        // The first stroke's resolve levels aren't  written out until the end of
        // the contour.
        if (!check_resolve_level(r, numSegments, *(*nextResolveLevel)++, tolerance)) {
            return false;
        }
    }
    return true;
}

static float test_tolerance(SkPaint::Join joinType) {
    // Ensure our fast approximation falls within 1.15 tessellation segments of the "correct"
    // answer. This is more than good enough when our matrix scale can go up to 2^17.
    float tolerance = 1.15f;
    if (joinType == SkPaint::kRound_Join) {
        // We approximate two different angles when there are round joins. Double the tolerance.
        tolerance *= 2;
    }
    return tolerance;
}

void GrStrokeIndirectOp::verifyPrePrepareResolveLevels(skiatest::Reporter* r,
                                                       GrMeshDrawOp::Target* target) {
    GrStrokeTessellateShader::Tolerances tolerances(fViewMatrix.getMaxScale(), fStroke.getWidth());
    float tolerance = test_tolerance(fStroke.getJoin());
    // Fill in fResolveLevels with our resolve levels for each curve.
    this->prePrepareResolveLevels(target->allocator());
    int8_t* nextResolveLevel = fResolveLevels;
    // Now check out answers.
    for (const SkPath& path : fPathList) {
        auto iterate = SkPathPriv::Iterate(path);
        SkSTArray<3, float> firstNumSegments;
        bool isFirstStroke = true;
        SkPoint startPoint = {0,0};
        SkPoint lastControlPoint;
        for (auto iter = iterate.begin(); iter != iterate.end(); ++iter) {
            auto [verb, pts, w] = *iter;
            switch (verb) {
                int n;
                SkPoint chops[10];
                case SkPathVerb::kMove:
                    startPoint = pts[0];
                    lastControlPoint = get_contour_closing_control_point(iter, iterate.end());
                    if (!check_first_resolve_levels(r, firstNumSegments, &nextResolveLevel,
                                                    tolerance)) {
                        return;
                    }
                    firstNumSegments.reset();
                    isFirstStroke = true;
                    break;
                case SkPathVerb::kLine:
                    if (pts[0] == pts[1]) {
                        break;
                    }
                    if (fStroke.getJoin() == SkPaint::kRound_Join) {
                        float rotation = SkMeasureAngleBetweenVectors(pts[0] - lastControlPoint,
                                                                      pts[1] - pts[0]);
                        float numSegments = rotation * tolerances.fNumRadialSegmentsPerRadian;
                        if (isFirstStroke) {
                            firstNumSegments.push_back(numSegments);
                        } else if (!check_resolve_level(r, numSegments, *nextResolveLevel++,
                                                        tolerance)) {
                            return;
                        }
                    }
                    lastControlPoint = pts[0];
                    isFirstStroke = false;
                    break;
                case SkPathVerb::kQuad: {
                    if (pts[0] == pts[1] && pts[1] == pts[2]) {
                        break;
                    }
                    SkVector a = pts[1] - pts[0];
                    SkVector b = pts[2] - pts[1];
                    bool hasCusp = (a.cross(b) == 0 && a.dot(b) < 0);
                    if (hasCusp) {
                        // The quad has a cusp. Make sure we wrote out a -1 to signal that.
                        if (isFirstStroke) {
                            firstNumSegments.push_back(-1);
                        } else {
                            REPORTER_ASSERT(r, *nextResolveLevel++ == -1);
                        }
                    }
                    float numParametricSegments = (hasCusp) ? 0 : GrWangsFormula::quadratic(
                            tolerances.fParametricIntolerance, pts);
                    float rotation = (hasCusp) ? 0 : SkMeasureQuadRotation(pts);
                    if (fStroke.getJoin() == SkPaint::kRound_Join) {
                        SkVector controlPoint = (pts[0] == pts[1]) ? pts[2] : pts[1];
                        rotation += SkMeasureAngleBetweenVectors(pts[0] - lastControlPoint,
                                                                 controlPoint - pts[0]);
                    }
                    float numRadialSegments = rotation * tolerances.fNumRadialSegmentsPerRadian;
                    float numSegments = numParametricSegments + numRadialSegments;
                    if (!hasCusp || fStroke.getJoin() == SkPaint::kRound_Join) {
                        if (isFirstStroke) {
                            firstNumSegments.push_back(numSegments);
                        } else if (!check_resolve_level(r, numSegments, *nextResolveLevel++,
                                                        tolerance)) {
                            return;
                        }
                    }
                    lastControlPoint = (pts[2] == pts[1]) ? pts[0] : pts[1];
                    isFirstStroke = false;
                    break;
                }
                case SkPathVerb::kCubic: {
                    if (pts[0] == pts[1] && pts[1] == pts[2] && pts[2] == pts[3]) {
                        break;
                    }
                    float T[2];
                    bool areCusps = false;
                    n = GrPathUtils::findCubicConvex180Chops(pts, T, &areCusps);
                    SkChopCubicAt(pts, chops, T, n);
                    if (n > 0) {
                        int signal = -((n << 1) | (int)areCusps);
                        if (isFirstStroke) {
                            firstNumSegments.push_back((float)signal);
                        } else {
                            REPORTER_ASSERT(r, *nextResolveLevel++ == signal);
                        }
                    }
                    for (int i = 0; i <= n; ++i) {
                        // Find the number of segments with our unoptimized approach and make sure
                        // it matches the answer we got already.
                        SkPoint* p = chops + i*3;
                        float numParametricSegments =
                                GrWangsFormula::cubic(tolerances.fParametricIntolerance, p);
                        SkVector tan0 =
                                ((p[0] == p[1]) ? (p[1] == p[2]) ? p[3] : p[2] : p[1]) - p[0];
                        SkVector tan1 =
                                p[3] - ((p[3] == p[2]) ? (p[2] == p[1]) ? p[0] : p[1] : p[2]);
                        float rotation = SkMeasureAngleBetweenVectors(tan0, tan1);
                        if (i == 0 && fStroke.getJoin() == SkPaint::kRound_Join) {
                            rotation += SkMeasureAngleBetweenVectors(p[0] - lastControlPoint, tan0);
                        }
                        float numRadialSegments = rotation * tolerances.fNumRadialSegmentsPerRadian;
                        float numSegments = numParametricSegments + numRadialSegments;
                        if (isFirstStroke) {
                            firstNumSegments.push_back(numSegments);
                        } else if (!check_resolve_level(r, numSegments, *nextResolveLevel++,
                                                        tolerance)) {
                            return;
                        }
                    }
                    lastControlPoint =
                            (pts[3] == pts[2]) ? (pts[2] == pts[1]) ? pts[0] : pts[1] : pts[2];
                    isFirstStroke = false;
                    break;
                }
                case SkPathVerb::kConic:
                    SkUNREACHABLE;
                case SkPathVerb::kClose:
                    if (pts[0] != startPoint) {
                        SkASSERT(!isFirstStroke);
                        if (fStroke.getJoin() == SkPaint::kRound_Join) {
                            // Line from pts[0] to startPoint, with a preceding join.
                            float rotation = SkMeasureAngleBetweenVectors(pts[0] - lastControlPoint,
                                                                          startPoint - pts[0]);
                            if (!check_resolve_level(
                                    r, rotation * tolerances.fNumRadialSegmentsPerRadian,
                                    *nextResolveLevel++, tolerance)) {
                                return;
                            }
                        }
                    }
                    if (!check_first_resolve_levels(r, firstNumSegments, &nextResolveLevel,
                                                    tolerance)) {
                        return;
                    }
                    firstNumSegments.reset();
                    isFirstStroke = true;
                    break;
            }
        }
        if (!check_first_resolve_levels(r, firstNumSegments, &nextResolveLevel, tolerance)) {
            return;
        }
        firstNumSegments.reset();
    }
    SkASSERT(nextResolveLevel == fResolveLevels + fResolveLevelArrayCount);
}

void GrStrokeIndirectOp::verifyPrepareBuffers(skiatest::Reporter* r, GrMeshDrawOp::Target* target) {
    using IndirectInstance = GrStrokeTessellateShader::IndirectInstance;
    GrStrokeTessellateShader::Tolerances tolerances(fViewMatrix.getMaxScale(), fStroke.getWidth());
    float tolerance = test_tolerance(fStroke.getJoin());
    // Make sure the resolve level we assign to each instance agrees with the actual data.
    this->prepareBuffers(target);
    // GrMockOpTarget returns the same pointers every time.
    int _;
    auto instance = (const IndirectInstance*)target->makeVertexSpace(0, 0, nullptr, &_);
    size_t __;
    auto indirect = target->makeDrawIndirectSpace(0, nullptr, &__);
    for (int i = 0; i < fDrawIndirectCount; ++i) {
        int numExtraEdgesInJoin = (fStroke.getJoin() == SkPaint::kMiter_Join) ? 4 : 3;
        int numStrokeEdges = indirect->fVertexCount/2 - numExtraEdgesInJoin;
        int numSegments = numStrokeEdges - 1;
        bool isPow2 = !(numSegments & (numSegments - 1));
        REPORTER_ASSERT(r, isPow2);
        int resolveLevel = sk_float_nextlog2(numSegments);
        REPORTER_ASSERT(r, 1 << resolveLevel == numSegments);
        for (unsigned j = 0; j < indirect->fInstanceCount; ++j) {
            SkASSERT(fabsf(instance->fNumTotalEdges) == indirect->fVertexCount/2);
            const SkPoint* p = instance->fPts.data();
            float numParametricSegments = GrWangsFormula::cubic(
                    tolerances.fParametricIntolerance, p);
            float alternateNumParametricSegments = numParametricSegments;
            if (p[0] == p[1] && p[2] == p[3]) {
                // We articulate lines as "p0,p0,p1,p1". This one might actually expect 0 parametric
                // segments.
                alternateNumParametricSegments = 0;
            }
            SkVector tan0 = ((p[0] == p[1]) ? (p[1] == p[2]) ? p[3] : p[2] : p[1]) - p[0];
            SkVector tan1 = p[3] - ((p[3] == p[2]) ? (p[2] == p[1]) ? p[0] : p[1] : p[2]);
            float rotation = SkMeasureAngleBetweenVectors(tan0, tan1);
            // Negative fNumTotalEdges means the curve is a chop, and chops always get treated as a
            // bevel join.
            if (fStroke.getJoin() == SkPaint::kRound_Join && instance->fNumTotalEdges > 0) {
                SkVector lastTangent = p[0] - instance->fLastControlPoint;
                rotation += SkMeasureAngleBetweenVectors(lastTangent, tan0);
            }
            // Degenerate strokes are a special case that actually mean the GPU should draw a cusp
            // (i.e. circle).
            if (p[0] == p[1] && p[1] == p[2] && p[2] == p[3]) {
                rotation = SK_ScalarPI;
            }
            float numRadialSegments = rotation * tolerances.fNumRadialSegmentsPerRadian;
            float numSegments = numParametricSegments + numRadialSegments;
            float alternateNumSegments = alternateNumParametricSegments + numRadialSegments;
            if (!check_resolve_level(r, numSegments, resolveLevel, tolerance, false) &&
                !check_resolve_level(r, alternateNumSegments, resolveLevel, tolerance, true)) {
                return;
            }
            ++instance;
        }
        ++indirect;
    }
}
