/*
 * 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/GrStrokeIndirectTessellator.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, GrMockOpTarget* 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 matrix = SkMatrix::Scale(scale, scale);
            GrStrokeTessellator::PathStrokeList pathStrokeList(path, stroke, SK_PMColor4fWHITE);
            GrStrokeIndirectTessellator tessellator(GrStrokeTessellateShader::ShaderFlags::kNone,
                                                    matrix, &pathStrokeList, path.countVerbs(),
                                                    target->allocator());
            tessellator.verifyResolveLevels(r, target, matrix, path, stroke);
            tessellator.prepare(target, matrix, path.countVerbs());
            tessellator.verifyBuffers(r, target, matrix, stroke);
        }
    }
}

DEF_TEST(tessellate_GrStrokeIndirectTessellator, 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) {
            int8_t val = *(*nextResolveLevel)++;
            REPORTER_ASSERT(r, val == (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 GrStrokeIndirectTessellator::verifyResolveLevels(skiatest::Reporter* r,
                                                      GrMockOpTarget* target,
                                                      const SkMatrix& viewMatrix,
                                                      const SkPath& path,
                                                      const SkStrokeRec& stroke) {
    auto tolerances = GrStrokeTolerances::MakeNonHairline(viewMatrix.getMaxScale(),
                                                          stroke.getWidth());
    int8_t resolveLevelForCircles = SkTPin<float>(
            sk_float_nextlog2(tolerances.fNumRadialSegmentsPerRadian * SK_ScalarPI),
            1, kMaxResolveLevel);
    float tolerance = test_tolerance(stroke.getJoin());
    int8_t* nextResolveLevel = fResolveLevels;
    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 (stroke.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 -resolveLevelForCircles.
                    if (isFirstStroke) {
                        firstNumSegments.push_back(-resolveLevelForCircles);
                    } else {
                        REPORTER_ASSERT(r, *nextResolveLevel++ == -resolveLevelForCircles);
                    }
                }
                float numParametricSegments = (hasCusp) ? 0 : GrWangsFormula::quadratic(
                        tolerances.fParametricPrecision, pts);
                float rotation = (hasCusp) ? 0 : SkMeasureQuadRotation(pts);
                if (stroke.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 || stroke.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 cuspResolveLevel = (areCusps) ? resolveLevelForCircles : 0;
                    int signal = -((n << 4) | cuspResolveLevel);
                    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.fParametricPrecision, 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 && stroke.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 (stroke.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 GrStrokeIndirectTessellator::verifyBuffers(skiatest::Reporter* r, GrMockOpTarget* target,
                                                const SkMatrix& viewMatrix,
                                                const SkStrokeRec& stroke) {
    // Make sure the resolve level we assigned to each instance agrees with the actual data.
    struct IndirectInstance {
        SkPoint fPts[4];
        SkPoint fLastControlPoint;
        float fNumTotalEdges;
    };
    auto instance = static_cast<const IndirectInstance*>(target->peekStaticVertexData());
    auto* indirect = static_cast<const GrDrawIndirectCommand*>(target->peekStaticIndirectData());
    auto tolerances = GrStrokeTolerances::MakeNonHairline(viewMatrix.getMaxScale(),
                                                          stroke.getWidth());
    float tolerance = test_tolerance(stroke.getJoin());
    for (int i = 0; i < fChainedDrawIndirectCount; ++i) {
        int numExtraEdgesInJoin = (stroke.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;
            float numParametricSegments = GrWangsFormula::cubic(tolerances.fParametricPrecision, 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 (stroke.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;
    }
}
