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

#include "src/gpu/GrClipStack.h"
#include "tests/Test.h"

#include "include/core/SkPath.h"
#include "include/core/SkRRect.h"
#include "include/core/SkRect.h"
#include "include/core/SkRegion.h"
#include "include/core/SkShader.h"
#include "include/gpu/GrDirectContext.h"
#include "src/core/SkMatrixProvider.h"
#include "src/core/SkRRectPriv.h"
#include "src/core/SkRectPriv.h"
#include "src/gpu/GrDirectContextPriv.h"
#include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrSurfaceDrawContext.h"

namespace {

class TestCaseBuilder;
class ElementsBuilder;

enum class SavePolicy {
    kNever,
    kAtStart,
    kAtEnd,
    kBetweenEveryOp
};
// TODO: We could add a RestorePolicy enum that tests different places to restore, but that would
// make defining the test expectations and order independence more cumbersome.

class TestCase {
public:
    // Provides fluent API to describe actual clip commands and expected clip elements:
    // TestCase test = TestCase::Build("example", deviceBounds)
    //                          .actual().rect(r, GrAA::kYes, SkClipOp::kIntersect)
    //                                   .localToDevice(matrix)
    //                                   .nonAA()
    //                                   .difference()
    //                                   .path(p1)
    //                                   .path(p2)
    //                                   .finishElements()
    //                          .expectedState(kDeviceRect)
    //                          .expectedBounds(r.roundOut())
    //                          .expect().rect(r, GrAA::kYes, SkClipOp::kIntersect)
    //                                   .finishElements()
    //                          .finishTest();
    static TestCaseBuilder Build(const char* name, const SkIRect& deviceBounds);

    void run(const std::vector<int>& order, SavePolicy policy, skiatest::Reporter* reporter) const;

    const SkIRect& deviceBounds() const { return fDeviceBounds; }
    GrClipStack::ClipState expectedState() const { return fExpectedState; }
    const std::vector<GrClipStack::Element>& initialElements() const { return fElements; }
    const std::vector<GrClipStack::Element>& expectedElements() const { return fExpectedElements; }

private:
    friend class TestCaseBuilder;

    TestCase(SkString name,
             const SkIRect& deviceBounds,
             GrClipStack::ClipState expectedState,
             std::vector<GrClipStack::Element> actual,
             std::vector<GrClipStack::Element> expected)
        : fName(name)
        , fElements(std::move(actual))
        , fDeviceBounds(deviceBounds)
        , fExpectedElements(std::move(expected))
        , fExpectedState(expectedState) {}

    SkString getTestName(const std::vector<int>& order, SavePolicy policy) const;

    // This may be tighter than GrClipStack::getConservativeBounds() because this always accounts
    // for difference ops, whereas GrClipStack only sometimes can subtract the inner bounds for a
    // difference op.
    std::pair<SkIRect, bool> getOptimalBounds() const;

    SkString fName;

    // The input shapes+state to GrClipStack
    std::vector<GrClipStack::Element> fElements;
    SkIRect fDeviceBounds;

    // The expected output of iterating over the GrClipStack after all fElements are added, although
    // order is not important
    std::vector<GrClipStack::Element> fExpectedElements;
    GrClipStack::ClipState fExpectedState;
};

class ElementsBuilder {
public:
    // Update the default matrix, aa, and op state for elements that are added.
    ElementsBuilder& localToDevice(const SkMatrix& m) {  fLocalToDevice = m; return *this; }
    ElementsBuilder& aa() { fAA = GrAA::kYes; return *this; }
    ElementsBuilder& nonAA() { fAA = GrAA::kNo; return *this; }
    ElementsBuilder& intersect() { fOp = SkClipOp::kIntersect; return *this; }
    ElementsBuilder& difference() { fOp = SkClipOp::kDifference; return *this; }

    // Add rect, rrect, or paths to the list of elements, possibly overriding the last set
    // matrix, aa, and op state.
    ElementsBuilder& rect(const SkRect& rect) {
        return this->rect(rect, fLocalToDevice, fAA, fOp);
    }
    ElementsBuilder& rect(const SkRect& rect, GrAA aa, SkClipOp op) {
        return this->rect(rect, fLocalToDevice, aa, op);
    }
    ElementsBuilder& rect(const SkRect& rect, const SkMatrix& m, GrAA aa, SkClipOp op) {
        fElements->push_back({GrShape(rect), m, op, aa});
        return *this;
    }

    ElementsBuilder& rrect(const SkRRect& rrect) {
        return this->rrect(rrect, fLocalToDevice, fAA, fOp);
    }
    ElementsBuilder& rrect(const SkRRect& rrect, GrAA aa, SkClipOp op) {
        return this->rrect(rrect, fLocalToDevice, aa, op);
    }
    ElementsBuilder& rrect(const SkRRect& rrect, const SkMatrix& m, GrAA aa, SkClipOp op) {
        fElements->push_back({GrShape(rrect), m, op, aa});
        return *this;
    }

    ElementsBuilder& path(const SkPath& path) {
        return this->path(path, fLocalToDevice, fAA, fOp);
    }
    ElementsBuilder& path(const SkPath& path, GrAA aa, SkClipOp op) {
        return this->path(path, fLocalToDevice, aa, op);
    }
    ElementsBuilder& path(const SkPath& path, const SkMatrix& m, GrAA aa, SkClipOp op) {
        fElements->push_back({GrShape(path), m, op, aa});
        return *this;
    }

    // Finish and return the original test case builder
    TestCaseBuilder& finishElements() {
        return *fBuilder;
    }

private:
    friend class TestCaseBuilder;

    ElementsBuilder(TestCaseBuilder* builder, std::vector<GrClipStack::Element>* elements)
            : fBuilder(builder)
            , fElements(elements) {}

    SkMatrix fLocalToDevice = SkMatrix::I();
    GrAA     fAA = GrAA::kNo;
    SkClipOp fOp = SkClipOp::kIntersect;

    TestCaseBuilder*                   fBuilder;
    std::vector<GrClipStack::Element>* fElements;
};

class TestCaseBuilder {
public:
    ElementsBuilder actual() { return ElementsBuilder(this, &fActualElements); }
    ElementsBuilder expect() { return ElementsBuilder(this, &fExpectedElements); }

    TestCaseBuilder& expectActual() {
        fExpectedElements = fActualElements;
        return *this;
    }

    TestCaseBuilder& state(GrClipStack::ClipState state) {
        fExpectedState = state;
        return *this;
    }

    TestCase finishTest() {
        TestCase test(fName, fDeviceBounds, fExpectedState,
                      std::move(fActualElements), std::move(fExpectedElements));

        fExpectedState = GrClipStack::ClipState::kWideOpen;
        return test;
    }

private:
    friend class TestCase;

    explicit TestCaseBuilder(const char* name, const SkIRect& deviceBounds)
            : fName(name)
            , fDeviceBounds(deviceBounds)
            , fExpectedState(GrClipStack::ClipState::kWideOpen) {}

    SkString fName;
    SkIRect  fDeviceBounds;
    GrClipStack::ClipState fExpectedState;

    std::vector<GrClipStack::Element> fActualElements;
    std::vector<GrClipStack::Element> fExpectedElements;
};

TestCaseBuilder TestCase::Build(const char* name, const SkIRect& deviceBounds) {
    return TestCaseBuilder(name, deviceBounds);
}

SkString TestCase::getTestName(const std::vector<int>& order, SavePolicy policy) const {
    SkString name = fName;

    SkString policyName;
    switch(policy) {
        case SavePolicy::kNever:
            policyName = "never";
            break;
        case SavePolicy::kAtStart:
            policyName = "start";
            break;
        case SavePolicy::kAtEnd:
            policyName = "end";
            break;
        case SavePolicy::kBetweenEveryOp:
            policyName = "between";
            break;
    }

    name.appendf("(save %s, order [", policyName.c_str());
    for (size_t i = 0; i < order.size(); ++i) {
        if (i > 0) {
            name.append(",");
        }
        name.appendf("%d", order[i]);
    }
    name.append("])");
    return name;
}

std::pair<SkIRect, bool> TestCase::getOptimalBounds() const {
    if (fExpectedState == GrClipStack::ClipState::kEmpty) {
        return {SkIRect::MakeEmpty(), true};
    }

    bool expectOptimal = true;
    SkRegion region(fDeviceBounds);
    for (const GrClipStack::Element& e : fExpectedElements) {
        bool intersect = (e.fOp == SkClipOp::kIntersect && !e.fShape.inverted()) ||
                         (e.fOp == SkClipOp::kDifference && e.fShape.inverted());

        SkIRect elementBounds;
        SkRegion::Op op;
        if (intersect) {
            op = SkRegion::kIntersect_Op;
            expectOptimal &= e.fLocalToDevice.isIdentity();
            elementBounds = GrClip::GetPixelIBounds(e.fLocalToDevice.mapRect(e.fShape.bounds()),
                                                    e.fAA, GrClip::BoundsType::kExterior);
        } else {
            op = SkRegion::kDifference_Op;
            expectOptimal = false;
            if (e.fShape.isRect() && e.fLocalToDevice.isIdentity()) {
                elementBounds = GrClip::GetPixelIBounds(e.fShape.rect(), e.fAA,
                                                        GrClip::BoundsType::kInterior);
            } else if (e.fShape.isRRect() && e.fLocalToDevice.isIdentity()) {
                elementBounds = GrClip::GetPixelIBounds(SkRRectPriv::InnerBounds(e.fShape.rrect()),
                                                        e.fAA, GrClip::BoundsType::kInterior);
            } else {
                elementBounds = SkIRect::MakeEmpty();
            }
        }

        region.op(SkRegion(elementBounds), op);
    }
    return {region.getBounds(), expectOptimal};
}

static bool compare_elements(const GrClipStack::Element& a, const GrClipStack::Element& b) {
    if (a.fAA != b.fAA || a.fOp != b.fOp || a.fLocalToDevice != b.fLocalToDevice ||
        a.fShape.type() != b.fShape.type()) {
        return false;
    }
    switch(a.fShape.type()) {
        case GrShape::Type::kRect:
            return a.fShape.rect() == b.fShape.rect();
        case GrShape::Type::kRRect:
            return a.fShape.rrect() == b.fShape.rrect();
        case GrShape::Type::kPath:
            // A path's points are never transformed, the only modification is fill type which does
            // not change the generation ID. For convex polygons, we check == so that more complex
            // test cases can be evaluated.
            return a.fShape.path().getGenerationID() == b.fShape.path().getGenerationID() ||
                   (a.fShape.convex() &&
                    a.fShape.segmentMask() == SkPathSegmentMask::kLine_SkPathSegmentMask &&
                    a.fShape.path() == b.fShape.path());
        default:
            SkDEBUGFAIL("Shape type not handled by test case yet.");
            return false;
    }
}

void TestCase::run(const std::vector<int>& order, SavePolicy policy,
                   skiatest::Reporter* reporter) const {
    SkASSERT(fElements.size() == order.size());

    SkSimpleMatrixProvider matrixProvider(SkMatrix::I());
    GrClipStack cs(fDeviceBounds, &matrixProvider, false);

    if (policy == SavePolicy::kAtStart) {
        cs.save();
    }

    for (int i : order) {
        if (policy == SavePolicy::kBetweenEveryOp) {
            cs.save();
        }
        const GrClipStack::Element& e = fElements[i];
        switch(e.fShape.type()) {
            case GrShape::Type::kRect:
                cs.clipRect(e.fLocalToDevice, e.fShape.rect(), e.fAA, e.fOp);
                break;
            case GrShape::Type::kRRect:
                cs.clipRRect(e.fLocalToDevice, e.fShape.rrect(), e.fAA, e.fOp);
                break;
            case GrShape::Type::kPath:
                cs.clipPath(e.fLocalToDevice, e.fShape.path(), e.fAA, e.fOp);
                break;
            default:
                SkDEBUGFAIL("Shape type not handled by test case yet.");
        }
    }

    if (policy == SavePolicy::kAtEnd) {
        cs.save();
    }

    // Now validate
    SkString name = this->getTestName(order, policy);
    REPORTER_ASSERT(reporter, cs.clipState() == fExpectedState,
                    "%s, clip state expected %d, actual %d",
                    name.c_str(), (int) fExpectedState, (int) cs.clipState());
    SkIRect actualBounds = cs.getConservativeBounds();
    SkIRect optimalBounds;
    bool expectOptimal;
    std::tie(optimalBounds, expectOptimal) = this->getOptimalBounds();

    if (expectOptimal) {
        REPORTER_ASSERT(reporter, actualBounds == optimalBounds,
                "%s, bounds expected [%d %d %d %d], actual [%d %d %d %d]",
                name.c_str(), optimalBounds.fLeft, optimalBounds.fTop,
                optimalBounds.fRight, optimalBounds.fBottom,
                actualBounds.fLeft, actualBounds.fTop,
                actualBounds.fRight, actualBounds.fBottom);
    } else {
        REPORTER_ASSERT(reporter, actualBounds.contains(optimalBounds),
                "%s, bounds are not conservative, optimal [%d %d %d %d], actual [%d %d %d %d]",
                name.c_str(), optimalBounds.fLeft, optimalBounds.fTop,
                optimalBounds.fRight, optimalBounds.fBottom,
                actualBounds.fLeft, actualBounds.fTop,
                actualBounds.fRight, actualBounds.fBottom);
    }

    size_t matchedElements = 0;
    for (const GrClipStack::Element& a : cs) {
        bool found = false;
        for (const GrClipStack::Element& e : fExpectedElements) {
            if (compare_elements(a, e)) {
                // shouldn't match multiple expected elements or it's a bad test case
                SkASSERT(!found);
                found = true;
            }
        }

        REPORTER_ASSERT(reporter, found,
                        "%s, unexpected clip element in stack: shape %d, aa %d, op %d",
                        name.c_str(), (int) a.fShape.type(), (int) a.fAA, (int) a.fOp);
        matchedElements += found ? 1 : 0;
    }
    REPORTER_ASSERT(reporter, matchedElements == fExpectedElements.size(),
                    "%s, did not match all expected elements: expected %d but matched only %d",
                    name.c_str(), fExpectedElements.size(), matchedElements);

    // Validate restoration behavior
    if (policy == SavePolicy::kAtEnd) {
        GrClipStack::ClipState oldState = cs.clipState();
        cs.restore();
        REPORTER_ASSERT(reporter, cs.clipState() == oldState,
                        "%s, restoring an empty save record should not change clip state: "
                        "expected %d but got %d", (int) oldState, (int) cs.clipState());
    } else if (policy != SavePolicy::kNever) {
        int restoreCount = policy == SavePolicy::kAtStart ? 1 : (int) order.size();
        for (int i = 0; i < restoreCount; ++i) {
            cs.restore();
        }
        // Should be wide open if everything is restored to base state
        REPORTER_ASSERT(reporter, cs.clipState() == GrClipStack::ClipState::kWideOpen,
                        "%s, restore should make stack become wide-open, not %d",
                        (int) cs.clipState());
    }
}

// All clip operations are commutative so applying actual elements in every possible order should
// always produce the same set of expected elements.
static void run_test_case(skiatest::Reporter* r, const TestCase& test) {
    int n = (int) test.initialElements().size();
    std::vector<int> order(n);
    std::vector<int> stack(n);

    // Initial order sequence and zeroed stack
    for (int i = 0; i < n; ++i) {
        order[i] = i;
        stack[i] = 0;
    }

    auto runTest = [&]() {
        static const SavePolicy kPolicies[] = { SavePolicy::kNever, SavePolicy::kAtStart,
                                                SavePolicy::kAtEnd, SavePolicy::kBetweenEveryOp };
        for (auto policy : kPolicies) {
            test.run(order, policy, r);
        }
    };

    // Heap's algorithm (non-recursive) to generate every permutation over the test case's elements
    // https://en.wikipedia.org/wiki/Heap%27s_algorithm
    runTest();

    static constexpr int kMaxRuns = 720; // Don't run more than 6! configurations, even if n > 6
    int testRuns = 1;

    int i = 0;
    while (i < n && testRuns < kMaxRuns) {
        if (stack[i] < i) {
            using std::swap;
            if (i % 2 == 0) {
                swap(order[0], order[i]);
            } else {
                swap(order[stack[i]], order[i]);
            }

            runTest();
            stack[i]++;
            i = 0;
            testRuns++;
        } else {
            stack[i] = 0;
            ++i;
        }
    }
}

static SkPath make_octagon(const SkRect& r, SkScalar lr, SkScalar tb) {
    SkPath p;
    p.moveTo(r.fLeft + lr, r.fTop);
    p.lineTo(r.fRight - lr, r.fTop);
    p.lineTo(r.fRight, r.fTop + tb);
    p.lineTo(r.fRight, r.fBottom - tb);
    p.lineTo(r.fRight - lr, r.fBottom);
    p.lineTo(r.fLeft + lr, r.fBottom);
    p.lineTo(r.fLeft, r.fBottom - tb);
    p.lineTo(r.fLeft, r.fTop + tb);
    p.close();
    return p;
}

static SkPath make_octagon(const SkRect& r) {
    SkScalar lr = 0.3f * r.width();
    SkScalar tb = 0.3f * r.height();
    return make_octagon(r, lr, tb);
}

static constexpr SkIRect kDeviceBounds = {0, 0, 100, 100};

} // anonymous namespace

///////////////////////////////////////////////////////////////////////////////
// These tests use the TestCase infrastructure to define clip stacks and
// associated expectations.

// Tests that the initialized state of the clip stack is wide-open
DEF_TEST(GrClipStack_InitialState, r) {
    run_test_case(r, TestCase::Build("initial-state", SkIRect::MakeWH(100, 100)).finishTest());
}

// Tests that intersection of rects combine to a single element when they have the same AA type,
// or are pixel-aligned.
DEF_TEST(GrClipStack_RectRectAACombine, r) {
    SkRect pixelAligned = {0, 0, 10, 10};
    SkRect fracRect1 = pixelAligned.makeOffset(5.3f, 3.7f);
    SkRect fracRect2 = {fracRect1.fLeft + 0.75f * fracRect1.width(),
                        fracRect1.fTop + 0.75f * fracRect1.height(),
                        fracRect1.fRight, fracRect1.fBottom};

    SkRect fracIntersect;
    SkAssertResult(fracIntersect.intersect(fracRect1, fracRect2));
    SkRect alignedIntersect;
    SkAssertResult(alignedIntersect.intersect(pixelAligned, fracRect1));

    // Both AA combine to one element
    run_test_case(r, TestCase::Build("aa", kDeviceBounds)
                              .actual().aa().intersect()
                                       .rect(fracRect1).rect(fracRect2)
                                       .finishElements()
                              .expect().aa().intersect().rect(fracIntersect).finishElements()
                              .state(GrClipStack::ClipState::kDeviceRect)
                              .finishTest());

    // Both non-AA combine to one element
    run_test_case(r, TestCase::Build("nonaa", kDeviceBounds)
                              .actual().nonAA().intersect()
                                       .rect(fracRect1).rect(fracRect2)
                                       .finishElements()
                              .expect().nonAA().intersect().rect(fracIntersect).finishElements()
                              .state(GrClipStack::ClipState::kDeviceRect)
                              .finishTest());

    // Pixel-aligned AA and non-AA combine
    run_test_case(r, TestCase::Build("aligned-aa+nonaa", kDeviceBounds)
                             .actual().intersect()
                                      .aa().rect(pixelAligned).nonAA().rect(fracRect1)
                                      .finishElements()
                             .expect().nonAA().intersect().rect(alignedIntersect).finishElements()
                             .state(GrClipStack::ClipState::kDeviceRect)
                             .finishTest());

    // AA and pixel-aligned non-AA combine
    run_test_case(r, TestCase::Build("aa+aligned-nonaa", kDeviceBounds)
                              .actual().intersect()
                                       .aa().rect(fracRect1).nonAA().rect(pixelAligned)
                                       .finishElements()
                              .expect().aa().intersect().rect(alignedIntersect).finishElements()
                              .state(GrClipStack::ClipState::kDeviceRect)
                              .finishTest());

    // Other mixed AA modes do not combine
    run_test_case(r, TestCase::Build("aa+nonaa", kDeviceBounds)
                              .actual().intersect()
                                       .aa().rect(fracRect1).nonAA().rect(fracRect2)
                                       .finishElements()
                              .expectActual()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());
}

// Tests that an intersection and a difference op do not combine, even if they would have if both
// were intersection ops.
DEF_TEST(GrClipStack_DifferenceNoCombine, r) {
    SkRect r1 = {15.f, 14.f, 23.22f, 58.2f};
    SkRect r2 = r1.makeOffset(5.f, 8.f);
    SkASSERT(r1.intersects(r2));

    run_test_case(r, TestCase::Build("no-combine", kDeviceBounds)
                              .actual().aa().intersect().rect(r1)
                                       .difference().rect(r2)
                                       .finishElements()
                              .expectActual()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());
}

// Tests that intersection of rects in the same coordinate space can still be combined, but do not
// when the spaces differ.
DEF_TEST(GrClipStack_RectRectNonAxisAligned, r) {
    SkRect pixelAligned = {0, 0, 10, 10};
    SkRect fracRect1 = pixelAligned.makeOffset(5.3f, 3.7f);
    SkRect fracRect2 = {fracRect1.fLeft + 0.75f * fracRect1.width(),
                        fracRect1.fTop + 0.75f * fracRect1.height(),
                        fracRect1.fRight, fracRect1.fBottom};

    SkRect fracIntersect;
    SkAssertResult(fracIntersect.intersect(fracRect1, fracRect2));

    SkMatrix lm = SkMatrix::RotateDeg(45.f);

    // Both AA combine
    run_test_case(r, TestCase::Build("aa", kDeviceBounds)
                              .actual().aa().intersect().localToDevice(lm)
                                       .rect(fracRect1).rect(fracRect2)
                                       .finishElements()
                              .expect().aa().intersect().localToDevice(lm)
                                       .rect(fracIntersect).finishElements()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());

    // Both non-AA combine
    run_test_case(r, TestCase::Build("nonaa", kDeviceBounds)
                              .actual().nonAA().intersect().localToDevice(lm)
                                       .rect(fracRect1).rect(fracRect2)
                                       .finishElements()
                              .expect().nonAA().intersect().localToDevice(lm)
                                       .rect(fracIntersect).finishElements()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());

    // Integer-aligned coordinates under a local matrix with mixed AA don't combine, though
    run_test_case(r, TestCase::Build("local-aa", kDeviceBounds)
                              .actual().intersect().localToDevice(lm)
                                       .aa().rect(pixelAligned).nonAA().rect(fracRect1)
                                       .finishElements()
                              .expectActual()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());
}

// Tests that intersection of two round rects can simplify to a single round rect when they have
// the same AA type.
DEF_TEST(GrClipStack_RRectRRectAACombine, r) {
    SkRRect r1 = SkRRect::MakeRectXY(SkRect::MakeWH(12, 12), 2.f, 2.f);
    SkRRect r2 = r1.makeOffset(6.f, 6.f);

    SkRRect intersect = SkRRectPriv::ConservativeIntersect(r1, r2);
    SkASSERT(!intersect.isEmpty());

    // Both AA combine
    run_test_case(r, TestCase::Build("aa", kDeviceBounds)
                              .actual().aa().intersect()
                                       .rrect(r1).rrect(r2)
                                       .finishElements()
                              .expect().aa().intersect().rrect(intersect).finishElements()
                              .state(GrClipStack::ClipState::kDeviceRRect)
                              .finishTest());

    // Both non-AA combine
    run_test_case(r, TestCase::Build("nonaa", kDeviceBounds)
                              .actual().nonAA().intersect()
                                       .rrect(r1).rrect(r2)
                                       .finishElements()
                              .expect().nonAA().intersect().rrect(intersect).finishElements()
                              .state(GrClipStack::ClipState::kDeviceRRect)
                              .finishTest());

    // Mixed do not combine
    run_test_case(r, TestCase::Build("aa+nonaa", kDeviceBounds)
                              .actual().intersect()
                                       .aa().rrect(r1).nonAA().rrect(r2)
                                       .finishElements()
                              .expectActual()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());

    // Same AA state can combine in the same local coordinate space
    SkMatrix lm = SkMatrix::RotateDeg(45.f);
    run_test_case(r, TestCase::Build("local-aa", kDeviceBounds)
                              .actual().aa().intersect().localToDevice(lm)
                                       .rrect(r1).rrect(r2)
                                       .finishElements()
                              .expect().aa().intersect().localToDevice(lm)
                                       .rrect(intersect).finishElements()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());
    run_test_case(r, TestCase::Build("local-nonaa", kDeviceBounds)
                              .actual().nonAA().intersect().localToDevice(lm)
                                       .rrect(r1).rrect(r2)
                                       .finishElements()
                              .expect().nonAA().intersect().localToDevice(lm)
                                       .rrect(intersect).finishElements()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());
}

// Tests that intersection of a round rect and rect can simplify to a new round rect or even a rect.
DEF_TEST(GrClipStack_RectRRectCombine, r) {
    SkRRect rrect = SkRRect::MakeRectXY({0, 0, 10, 10}, 2.f, 2.f);
    SkRect cutTop = {-10, -10, 10, 4};
    SkRect cutMid = {-10, 3, 10, 7};

    // Rect + RRect becomes a round rect with some square corners
    SkVector cutCorners[4] = {{2.f, 2.f}, {2.f, 2.f}, {0, 0}, {0, 0}};
    SkRRect cutRRect;
    cutRRect.setRectRadii({0, 0, 10, 4}, cutCorners);
    run_test_case(r, TestCase::Build("still-rrect", kDeviceBounds)
                              .actual().intersect().aa().rrect(rrect).rect(cutTop).finishElements()
                              .expect().intersect().aa().rrect(cutRRect).finishElements()
                              .state(GrClipStack::ClipState::kDeviceRRect)
                              .finishTest());

    // Rect + RRect becomes a rect
    SkRect cutRect = {0, 3, 10, 7};
    run_test_case(r, TestCase::Build("to-rect", kDeviceBounds)
                               .actual().intersect().aa().rrect(rrect).rect(cutMid).finishElements()
                               .expect().intersect().aa().rect(cutRect).finishElements()
                               .state(GrClipStack::ClipState::kDeviceRect)
                               .finishTest());

    // But they can only combine when the intersecting shape is representable as a [r]rect.
    cutRect = {0, 0, 1.5f, 5.f};
    run_test_case(r, TestCase::Build("no-combine", kDeviceBounds)
                              .actual().intersect().aa().rrect(rrect).rect(cutRect).finishElements()
                              .expectActual()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());
}

// Tests that a rect shape is actually pre-clipped to the device bounds
DEF_TEST(GrClipStack_RectDeviceClip, r) {
    SkRect crossesDeviceEdge = {20.f, kDeviceBounds.fTop - 13.2f,
                                kDeviceBounds.fRight + 15.5f, 30.f};
    SkRect insideDevice = {20.f, kDeviceBounds.fTop, kDeviceBounds.fRight, 30.f};

    run_test_case(r, TestCase::Build("device-aa-rect", kDeviceBounds)
                              .actual().intersect().aa().rect(crossesDeviceEdge).finishElements()
                              .expect().intersect().aa().rect(insideDevice).finishElements()
                              .state(GrClipStack::ClipState::kDeviceRect)
                              .finishTest());

    run_test_case(r, TestCase::Build("device-nonaa-rect", kDeviceBounds)
                              .actual().intersect().nonAA().rect(crossesDeviceEdge).finishElements()
                              .expect().intersect().nonAA().rect(insideDevice).finishElements()
                              .state(GrClipStack::ClipState::kDeviceRect)
                              .finishTest());
}

// Tests that other shapes' bounds are contained by the device bounds, even if their shape is not.
DEF_TEST(GrClipStack_ShapeDeviceBoundsClip, r) {
    SkRect crossesDeviceEdge = {20.f, kDeviceBounds.fTop - 13.2f,
                                kDeviceBounds.fRight + 15.5f, 30.f};

    // RRect
    run_test_case(r, TestCase::Build("device-rrect", kDeviceBounds)
                              .actual().intersect().aa()
                                       .rrect(SkRRect::MakeRectXY(crossesDeviceEdge, 4.f, 4.f))
                                       .finishElements()
                              .expectActual()
                              .state(GrClipStack::ClipState::kDeviceRRect)
                              .finishTest());

    // Path
    run_test_case(r, TestCase::Build("device-path", kDeviceBounds)
                              .actual().intersect().aa()
                                       .path(make_octagon(crossesDeviceEdge))
                                       .finishElements()
                              .expectActual()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());
}

// Tests that a simplifiable path turns into a simpler element type
DEF_TEST(GrClipStack_PathSimplify, r) {
    // Empty, point, and line paths -> empty
    SkPath empty;
    run_test_case(r, TestCase::Build("empty", kDeviceBounds)
                              .actual().path(empty).finishElements()
                              .state(GrClipStack::ClipState::kEmpty)
                              .finishTest());
    SkPath point;
    point.moveTo({0.f, 0.f});
    run_test_case(r, TestCase::Build("point", kDeviceBounds)
                              .actual().path(point).finishElements()
                              .state(GrClipStack::ClipState::kEmpty)
                              .finishTest());

    SkPath line;
    line.moveTo({0.f, 0.f});
    line.lineTo({10.f, 5.f});
    run_test_case(r, TestCase::Build("line", kDeviceBounds)
                              .actual().path(line).finishElements()
                              .state(GrClipStack::ClipState::kEmpty)
                              .finishTest());

    // Rect path -> rect element
    SkRect rect = {0.f, 2.f, 10.f, 15.4f};
    SkPath rectPath;
    rectPath.addRect(rect);
    run_test_case(r, TestCase::Build("rect", kDeviceBounds)
                              .actual().path(rectPath).finishElements()
                              .expect().rect(rect).finishElements()
                              .state(GrClipStack::ClipState::kDeviceRect)
                              .finishTest());

    // Oval path -> rrect element
    SkPath ovalPath;
    ovalPath.addOval(rect);
    run_test_case(r, TestCase::Build("oval", kDeviceBounds)
                              .actual().path(ovalPath).finishElements()
                              .expect().rrect(SkRRect::MakeOval(rect)).finishElements()
                              .state(GrClipStack::ClipState::kDeviceRRect)
                              .finishTest());

    // RRect path -> rrect element
    SkRRect rrect = SkRRect::MakeRectXY(rect, 2.f, 2.f);
    SkPath rrectPath;
    rrectPath.addRRect(rrect);
    run_test_case(r, TestCase::Build("rrect", kDeviceBounds)
                              .actual().path(rrectPath).finishElements()
                              .expect().rrect(rrect).finishElements()
                              .state(GrClipStack::ClipState::kDeviceRRect)
                              .finishTest());
}

// Tests that repeated identical clip operations are idempotent
DEF_TEST(GrClipStack_RepeatElement, r) {
    // Same rect
    SkRect rect = {5.3f, 62.f, 20.f, 85.f};
    run_test_case(r, TestCase::Build("same-rects", kDeviceBounds)
                              .actual().rect(rect).rect(rect).rect(rect).finishElements()
                              .expect().rect(rect).finishElements()
                              .state(GrClipStack::ClipState::kDeviceRect)
                              .finishTest());
    SkMatrix lm;
    lm.setRotate(30.f, rect.centerX(), rect.centerY());
    run_test_case(r, TestCase::Build("same-local-rects", kDeviceBounds)
                              .actual().localToDevice(lm).rect(rect).rect(rect).rect(rect)
                                       .finishElements()
                              .expect().localToDevice(lm).rect(rect).finishElements()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());

    // Same rrect
    SkRRect rrect = SkRRect::MakeRectXY(rect, 5.f, 2.5f);
    run_test_case(r, TestCase::Build("same-rrects", kDeviceBounds)
                              .actual().rrect(rrect).rrect(rrect).rrect(rrect).finishElements()
                              .expect().rrect(rrect).finishElements()
                              .state(GrClipStack::ClipState::kDeviceRRect)
                              .finishTest());
    run_test_case(r, TestCase::Build("same-local-rrects", kDeviceBounds)
                              .actual().localToDevice(lm).rrect(rrect).rrect(rrect).rrect(rrect)
                                       .finishElements()
                              .expect().localToDevice(lm).rrect(rrect).finishElements()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());

    // Same convex path, by ==
    run_test_case(r, TestCase::Build("same-convex", kDeviceBounds)
                              .actual().path(make_octagon(rect)).path(make_octagon(rect))
                                       .finishElements()
                              .expect().path(make_octagon(rect)).finishElements()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());
    run_test_case(r, TestCase::Build("same-local-convex", kDeviceBounds)
                              .actual().localToDevice(lm)
                                       .path(make_octagon(rect)).path(make_octagon(rect))
                                       .finishElements()
                              .expect().localToDevice(lm).path(make_octagon(rect))
                                       .finishElements()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());

    // Same complicated path by gen-id but not ==
    SkPath path; // an hour glass
    path.moveTo({0.f, 0.f});
    path.lineTo({20.f, 20.f});
    path.lineTo({0.f, 20.f});
    path.lineTo({20.f, 0.f});
    path.close();

    run_test_case(r, TestCase::Build("same-path", kDeviceBounds)
                              .actual().path(path).path(path).path(path).finishElements()
                              .expect().path(path).finishElements()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());
    run_test_case(r, TestCase::Build("same-local-path", kDeviceBounds)
                              .actual().localToDevice(lm)
                                       .path(path).path(path).path(path).finishElements()
                              .expect().localToDevice(lm).path(path)
                                       .finishElements()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());
}

// Tests that inverse-filled paths are canonicalized to a regular fill and a swapped clip op
DEF_TEST(GrClipStack_InverseFilledPath, r) {
    SkRect rect = {0.f, 0.f, 16.f, 17.f};
    SkPath rectPath;
    rectPath.addRect(rect);

    SkPath inverseRectPath = rectPath;
    inverseRectPath.toggleInverseFillType();

    SkPath complexPath = make_octagon(rect);
    SkPath inverseComplexPath = complexPath;
    inverseComplexPath.toggleInverseFillType();

    // Inverse filled rect + intersect -> diff rect
    run_test_case(r, TestCase::Build("inverse-rect-intersect", kDeviceBounds)
                              .actual().aa().intersect().path(inverseRectPath).finishElements()
                              .expect().aa().difference().rect(rect).finishElements()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());

    // Inverse filled rect + difference -> int. rect
    run_test_case(r, TestCase::Build("inverse-rect-difference", kDeviceBounds)
                              .actual().aa().difference().path(inverseRectPath).finishElements()
                              .expect().aa().intersect().rect(rect).finishElements()
                              .state(GrClipStack::ClipState::kDeviceRect)
                              .finishTest());

    // Inverse filled path + intersect -> diff path
    run_test_case(r, TestCase::Build("inverse-path-intersect", kDeviceBounds)
                              .actual().aa().intersect().path(inverseComplexPath).finishElements()
                              .expect().aa().difference().path(complexPath).finishElements()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());

    // Inverse filled path + difference -> int. path
    run_test_case(r, TestCase::Build("inverse-path-difference", kDeviceBounds)
                              .actual().aa().difference().path(inverseComplexPath).finishElements()
                              .expect().aa().intersect().path(complexPath).finishElements()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());
}

// Tests that clip operations that are offscreen either make the clip empty or stay wide open
DEF_TEST(GrClipStack_Offscreen, r) {
    SkRect offscreenRect = {kDeviceBounds.fRight + 10.f, kDeviceBounds.fTop + 20.f,
                            kDeviceBounds.fRight + 40.f, kDeviceBounds.fTop + 60.f};
    SkASSERT(!offscreenRect.intersects(SkRect::Make(kDeviceBounds)));

    SkRRect offscreenRRect = SkRRect::MakeRectXY(offscreenRect, 5.f, 5.f);
    SkPath offscreenPath = make_octagon(offscreenRect);

    // Intersect -> empty
    run_test_case(r, TestCase::Build("intersect-combo", kDeviceBounds)
                              .actual().aa().intersect()
                                       .rect(offscreenRect)
                                       .rrect(offscreenRRect)
                                       .path(offscreenPath)
                                       .finishElements()
                              .state(GrClipStack::ClipState::kEmpty)
                              .finishTest());
    run_test_case(r, TestCase::Build("intersect-rect", kDeviceBounds)
                              .actual().aa().intersect()
                                       .rect(offscreenRect)
                                       .finishElements()
                              .state(GrClipStack::ClipState::kEmpty)
                              .finishTest());
    run_test_case(r, TestCase::Build("intersect-rrect", kDeviceBounds)
                              .actual().aa().intersect()
                                       .rrect(offscreenRRect)
                                       .finishElements()
                              .state(GrClipStack::ClipState::kEmpty)
                              .finishTest());
    run_test_case(r, TestCase::Build("intersect-path", kDeviceBounds)
                              .actual().aa().intersect()
                                       .path(offscreenPath)
                                       .finishElements()
                              .state(GrClipStack::ClipState::kEmpty)
                              .finishTest());

    // Difference -> wide open
    run_test_case(r, TestCase::Build("difference-combo", kDeviceBounds)
                              .actual().aa().difference()
                                       .rect(offscreenRect)
                                       .rrect(offscreenRRect)
                                       .path(offscreenPath)
                                       .finishElements()
                              .state(GrClipStack::ClipState::kWideOpen)
                              .finishTest());
    run_test_case(r, TestCase::Build("difference-rect", kDeviceBounds)
                              .actual().aa().difference()
                                       .rect(offscreenRect)
                                       .finishElements()
                              .state(GrClipStack::ClipState::kWideOpen)
                              .finishTest());
    run_test_case(r, TestCase::Build("difference-rrect", kDeviceBounds)
                              .actual().aa().difference()
                                       .rrect(offscreenRRect)
                                       .finishElements()
                              .state(GrClipStack::ClipState::kWideOpen)
                              .finishTest());
    run_test_case(r, TestCase::Build("difference-path", kDeviceBounds)
                              .actual().aa().difference()
                                       .path(offscreenPath)
                                       .finishElements()
                              .state(GrClipStack::ClipState::kWideOpen)
                              .finishTest());
}

// Tests that an empty shape updates the clip state directly without needing an element
DEF_TEST(GrClipStack_EmptyShape, r) {
    // Intersect -> empty
    run_test_case(r, TestCase::Build("empty-intersect", kDeviceBounds)
                              .actual().intersect().rect(SkRect::MakeEmpty()).finishElements()
                              .state(GrClipStack::ClipState::kEmpty)
                              .finishTest());

    // Difference -> no-op
    run_test_case(r, TestCase::Build("empty-difference", kDeviceBounds)
                              .actual().difference().rect(SkRect::MakeEmpty()).finishElements()
                              .state(GrClipStack::ClipState::kWideOpen)
                              .finishTest());

    SkRRect rrect = SkRRect::MakeRectXY({4.f, 10.f, 16.f, 32.f}, 2.f, 2.f);
    run_test_case(r, TestCase::Build("noop-difference", kDeviceBounds)
                              .actual().difference().rrect(rrect).rect(SkRect::MakeEmpty())
                                       .finishElements()
                              .expect().difference().rrect(rrect).finishElements()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());
}

// Tests that sufficiently large difference operations can shrink the conservative bounds
DEF_TEST(GrClipStack_DifferenceBounds, r) {
    SkRect rightSide = {50.f, -10.f, 2.f * kDeviceBounds.fRight, kDeviceBounds.fBottom + 10.f};
    SkRect clipped = rightSide;
    SkAssertResult(clipped.intersect(SkRect::Make(kDeviceBounds)));

    run_test_case(r, TestCase::Build("difference-cut", kDeviceBounds)
                              .actual().nonAA().difference().rect(rightSide).finishElements()
                              .expect().nonAA().difference().rect(clipped).finishElements()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());
}

// Tests that intersections can combine even if there's a difference operation in the middle
DEF_TEST(GrClipStack_NoDifferenceInterference, r) {
    SkRect intR1 = {0.f, 0.f, 30.f, 30.f};
    SkRect intR2 = {15.f, 15.f, 45.f, 45.f};
    SkRect intCombo = {15.f, 15.f, 30.f, 30.f};
    SkRect diff = {20.f, 6.f, 50.f, 50.f};

    run_test_case(r, TestCase::Build("cross-diff-combine", kDeviceBounds)
                              .actual().rect(intR1, GrAA::kYes, SkClipOp::kIntersect)
                                       .rect(diff, GrAA::kYes, SkClipOp::kDifference)
                                       .rect(intR2, GrAA::kYes, SkClipOp::kIntersect)
                                       .finishElements()
                              .expect().rect(intCombo, GrAA::kYes, SkClipOp::kIntersect)
                                       .rect(diff, GrAA::kYes, SkClipOp::kDifference)
                                       .finishElements()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());
}

// Tests that multiple path operations are all recorded, but not otherwise consolidated
DEF_TEST(GrClipStack_MultiplePaths, r) {
    // Chosen to be greater than the number of inline-allocated elements and save records of the
    // GrClipStack so that we test heap allocation as well.
    static constexpr int kNumOps = 16;

    auto b = TestCase::Build("many-paths-difference", kDeviceBounds);
    SkRect d = {0.f, 0.f, 12.f, 12.f};
    for (int i = 0; i < kNumOps; ++i) {
        b.actual().path(make_octagon(d), GrAA::kNo, SkClipOp::kDifference);

        d.offset(15.f, 0.f);
        if (d.fRight > kDeviceBounds.fRight) {
            d.fLeft = 0.f;
            d.fRight = 12.f;
            d.offset(0.f, 15.f);
        }
    }

    run_test_case(r, b.expectActual()
                      .state(GrClipStack::ClipState::kComplex)
                      .finishTest());

    b = TestCase::Build("many-paths-intersect", kDeviceBounds);
    d = {0.f, 0.f, 12.f, 12.f};
    for (int i = 0; i < kNumOps; ++i) {
        b.actual().path(make_octagon(d), GrAA::kYes, SkClipOp::kIntersect);
        d.offset(0.01f, 0.01f);
    }

    run_test_case(r, b.expectActual()
                      .state(GrClipStack::ClipState::kComplex)
                      .finishTest());
}

// Tests that a single rect is treated as kDeviceRect state when it's axis-aligned and intersect.
DEF_TEST(GrClipStack_DeviceRect, r) {
    // Axis-aligned + intersect -> kDeviceRect
    SkRect rect = {0, 0, 20, 20};
    run_test_case(r, TestCase::Build("device-rect", kDeviceBounds)
                              .actual().intersect().aa().rect(rect).finishElements()
                              .expectActual()
                              .state(GrClipStack::ClipState::kDeviceRect)
                              .finishTest());

    // Not axis-aligned -> kComplex
    SkMatrix lm = SkMatrix::RotateDeg(15.f);
    run_test_case(r, TestCase::Build("unaligned-rect", kDeviceBounds)
                              .actual().localToDevice(lm).intersect().aa().rect(rect)
                                       .finishElements()
                              .expectActual()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());

    // Not intersect -> kComplex
    run_test_case(r, TestCase::Build("diff-rect", kDeviceBounds)
                              .actual().difference().aa().rect(rect).finishElements()
                              .expectActual()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());
}

// Tests that a single rrect is treated as kDeviceRRect state when it's axis-aligned and intersect.
DEF_TEST(GrClipStack_DeviceRRect, r) {
    // Axis-aligned + intersect -> kDeviceRRect
    SkRect rect = {0, 0, 20, 20};
    SkRRect rrect = SkRRect::MakeRectXY(rect, 5.f, 5.f);
    run_test_case(r, TestCase::Build("device-rrect", kDeviceBounds)
                              .actual().intersect().aa().rrect(rrect).finishElements()
                              .expectActual()
                              .state(GrClipStack::ClipState::kDeviceRRect)
                              .finishTest());

    // Not axis-aligned -> kComplex
    SkMatrix lm = SkMatrix::RotateDeg(15.f);
    run_test_case(r, TestCase::Build("unaligned-rrect", kDeviceBounds)
                              .actual().localToDevice(lm).intersect().aa().rrect(rrect)
                                       .finishElements()
                              .expectActual()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());

    // Not intersect -> kComplex
    run_test_case(r, TestCase::Build("diff-rrect", kDeviceBounds)
                              .actual().difference().aa().rrect(rrect).finishElements()
                              .expectActual()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());
}

// Tests that scale+translate matrices are pre-applied to rects and rrects, which also then allows
// elements with different scale+translate matrices to be consolidated as if they were in the same
// coordinate space.
DEF_TEST(GrClipStack_ScaleTranslate, r) {
    SkMatrix lm = SkMatrix::Scale(2.f, 4.f);
    lm.postTranslate(15.5f, 14.3f);
    SkASSERT(lm.preservesAxisAlignment() && lm.isScaleTranslate());

    // Rect -> matrix is applied up front
    SkRect rect = {0.f, 0.f, 10.f, 10.f};
    run_test_case(r, TestCase::Build("st+rect", kDeviceBounds)
                              .actual().rect(rect, lm, GrAA::kYes, SkClipOp::kIntersect)
                                       .finishElements()
                              .expect().rect(lm.mapRect(rect), GrAA::kYes, SkClipOp::kIntersect)
                                       .finishElements()
                              .state(GrClipStack::ClipState::kDeviceRect)
                              .finishTest());

    // RRect -> matrix is applied up front
    SkRRect localRRect = SkRRect::MakeRectXY(rect, 2.f, 2.f);
    SkRRect deviceRRect;
    SkAssertResult(localRRect.transform(lm, &deviceRRect));
    run_test_case(r, TestCase::Build("st+rrect", kDeviceBounds)
                              .actual().rrect(localRRect, lm, GrAA::kYes, SkClipOp::kIntersect)
                                       .finishElements()
                              .expect().rrect(deviceRRect, GrAA::kYes, SkClipOp::kIntersect)
                                       .finishElements()
                              .state(GrClipStack::ClipState::kDeviceRRect)
                              .finishTest());

    // Path -> matrix is NOT applied
    run_test_case(r, TestCase::Build("st+path", kDeviceBounds)
                              .actual().intersect().localToDevice(lm).path(make_octagon(rect))
                                       .finishElements()
                              .expectActual()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());
}

// Tests that rect-stays-rect matrices that are not scale+translate matrices are pre-applied.
DEF_TEST(GrClipStack_PreserveAxisAlignment, r) {
    SkMatrix lm = SkMatrix::RotateDeg(90.f);
    lm.postTranslate(15.5f, 14.3f);
    SkASSERT(lm.preservesAxisAlignment() && !lm.isScaleTranslate());

    // Rect -> matrix is applied up front
    SkRect rect = {0.f, 0.f, 10.f, 10.f};
    run_test_case(r, TestCase::Build("r90+rect", kDeviceBounds)
                              .actual().rect(rect, lm, GrAA::kYes, SkClipOp::kIntersect)
                                       .finishElements()
                              .expect().rect(lm.mapRect(rect), GrAA::kYes, SkClipOp::kIntersect)
                                       .finishElements()
                              .state(GrClipStack::ClipState::kDeviceRect)
                              .finishTest());

    // RRect -> matrix is applied up front
    SkRRect localRRect = SkRRect::MakeRectXY(rect, 2.f, 2.f);
    SkRRect deviceRRect;
    SkAssertResult(localRRect.transform(lm, &deviceRRect));
    run_test_case(r, TestCase::Build("r90+rrect", kDeviceBounds)
                              .actual().rrect(localRRect, lm, GrAA::kYes, SkClipOp::kIntersect)
                                       .finishElements()
                              .expect().rrect(deviceRRect, GrAA::kYes, SkClipOp::kIntersect)
                                       .finishElements()
                              .state(GrClipStack::ClipState::kDeviceRRect)
                              .finishTest());

    // Path -> matrix is NOT applied
    run_test_case(r, TestCase::Build("r90+path", kDeviceBounds)
                              .actual().intersect().localToDevice(lm).path(make_octagon(rect))
                                       .finishElements()
                              .expectActual()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());
}

// Tests that a convex path element can contain a rect or round rect, allowing the stack to be
// simplified
DEF_TEST(GrClipStack_ConvexPathContains, r) {
    SkRect rect = {15.f, 15.f, 30.f, 30.f};
    SkRRect rrect = SkRRect::MakeRectXY(rect, 5.f, 5.f);
    SkPath bigPath = make_octagon(rect.makeOutset(10.f, 10.f), 5.f, 5.f);

    // Intersect -> path element isn't kept
    run_test_case(r, TestCase::Build("convex+rect-intersect", kDeviceBounds)
                              .actual().aa().intersect().rect(rect).path(bigPath).finishElements()
                              .expect().aa().intersect().rect(rect).finishElements()
                              .state(GrClipStack::ClipState::kDeviceRect)
                              .finishTest());
    run_test_case(r, TestCase::Build("convex+rrect-intersect", kDeviceBounds)
                              .actual().aa().intersect().rrect(rrect).path(bigPath).finishElements()
                              .expect().aa().intersect().rrect(rrect).finishElements()
                              .state(GrClipStack::ClipState::kDeviceRRect)
                              .finishTest());

    // Difference -> path element is the only one left
    run_test_case(r, TestCase::Build("convex+rect-difference", kDeviceBounds)
                              .actual().aa().difference().rect(rect).path(bigPath).finishElements()
                              .expect().aa().difference().path(bigPath).finishElements()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());
    run_test_case(r, TestCase::Build("convex+rrect-difference", kDeviceBounds)
                              .actual().aa().difference().rrect(rrect).path(bigPath)
                                       .finishElements()
                              .expect().aa().difference().path(bigPath).finishElements()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());

    // Intersect small shape + difference big path -> empty
    run_test_case(r, TestCase::Build("convex-diff+rect-int", kDeviceBounds)
                              .actual().aa().intersect().rect(rect)
                                       .difference().path(bigPath).finishElements()
                              .state(GrClipStack::ClipState::kEmpty)
                              .finishTest());
    run_test_case(r, TestCase::Build("convex-diff+rrect-int", kDeviceBounds)
                              .actual().aa().intersect().rrect(rrect)
                                       .difference().path(bigPath).finishElements()
                              .state(GrClipStack::ClipState::kEmpty)
                              .finishTest());

    // Diff small shape + intersect big path -> both
    run_test_case(r, TestCase::Build("convex-int+rect-diff", kDeviceBounds)
                              .actual().aa().intersect().path(bigPath).difference().rect(rect)
                                       .finishElements()
                              .expectActual()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());
    run_test_case(r, TestCase::Build("convex-int+rrect-diff", kDeviceBounds)
                              .actual().aa().intersect().path(bigPath).difference().rrect(rrect)
                                       .finishElements()
                              .expectActual()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());
}

// Tests that rects/rrects in different coordinate spaces can be consolidated when one is fully
// contained by the other.
DEF_TEST(GrClipStack_NonAxisAlignedContains, r) {
    SkMatrix lm1 = SkMatrix::RotateDeg(45.f);
    SkRect bigR = {-20.f, -20.f, 20.f, 20.f};
    SkRRect bigRR = SkRRect::MakeRectXY(bigR, 1.f, 1.f);

    SkMatrix lm2 = SkMatrix::RotateDeg(-45.f);
    SkRect smR = {-10.f, -10.f, 10.f, 10.f};
    SkRRect smRR = SkRRect::MakeRectXY(smR, 1.f, 1.f);

    // I+I should select the smaller 2nd shape (r2 or rr2)
    run_test_case(r, TestCase::Build("rect-rect-ii", kDeviceBounds)
                              .actual().rect(bigR, lm1, GrAA::kYes, SkClipOp::kIntersect)
                                       .rect(smR, lm2, GrAA::kYes, SkClipOp::kIntersect)
                                       .finishElements()
                              .expect().rect(smR, lm2, GrAA::kYes, SkClipOp::kIntersect)
                                       .finishElements()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());
    run_test_case(r, TestCase::Build("rrect-rrect-ii", kDeviceBounds)
                              .actual().rrect(bigRR, lm1, GrAA::kYes, SkClipOp::kIntersect)
                                       .rrect(smRR, lm2, GrAA::kYes, SkClipOp::kIntersect)
                                       .finishElements()
                              .expect().rrect(smRR, lm2, GrAA::kYes, SkClipOp::kIntersect)
                                       .finishElements()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());
    run_test_case(r, TestCase::Build("rect-rrect-ii", kDeviceBounds)
                              .actual().rect(bigR, lm1, GrAA::kYes, SkClipOp::kIntersect)
                                       .rrect(smRR, lm2, GrAA::kYes, SkClipOp::kIntersect)
                                       .finishElements()
                              .expect().rrect(smRR, lm2, GrAA::kYes, SkClipOp::kIntersect)
                                       .finishElements()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());
    run_test_case(r, TestCase::Build("rrect-rect-ii", kDeviceBounds)
                              .actual().rrect(bigRR, lm1, GrAA::kYes, SkClipOp::kIntersect)
                                       .rect(smR, lm2, GrAA::kYes, SkClipOp::kIntersect)
                                       .finishElements()
                              .expect().rect(smR, lm2, GrAA::kYes, SkClipOp::kIntersect)
                                       .finishElements()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());

    // D+D should select the larger shape (r1 or rr1)
    run_test_case(r, TestCase::Build("rect-rect-dd", kDeviceBounds)
                              .actual().rect(bigR, lm1, GrAA::kYes, SkClipOp::kDifference)
                                       .rect(smR, lm2, GrAA::kYes, SkClipOp::kDifference)
                                       .finishElements()
                              .expect().rect(bigR, lm1, GrAA::kYes, SkClipOp::kDifference)
                                       .finishElements()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());
    run_test_case(r, TestCase::Build("rrect-rrect-dd", kDeviceBounds)
                              .actual().rrect(bigRR, lm1, GrAA::kYes, SkClipOp::kDifference)
                                       .rrect(smRR, lm2, GrAA::kYes, SkClipOp::kDifference)
                                       .finishElements()
                              .expect().rrect(bigRR, lm1, GrAA::kYes, SkClipOp::kDifference)
                                       .finishElements()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());
    run_test_case(r, TestCase::Build("rect-rrect-dd", kDeviceBounds)
                              .actual().rect(bigR, lm1, GrAA::kYes, SkClipOp::kDifference)
                                       .rrect(smRR, lm2, GrAA::kYes, SkClipOp::kDifference)
                                       .finishElements()
                              .expect().rect(bigR, lm1, GrAA::kYes, SkClipOp::kDifference)
                                         .finishElements()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());
    run_test_case(r, TestCase::Build("rrect-rect-dd", kDeviceBounds)
                              .actual().rrect(bigRR, lm1, GrAA::kYes, SkClipOp::kDifference)
                                       .rect(smR, lm2, GrAA::kYes, SkClipOp::kDifference)
                                       .finishElements()
                              .expect().rrect(bigRR, lm1, GrAA::kYes, SkClipOp::kDifference)
                                       .finishElements()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());

    // D(1)+I(2) should result in empty
    run_test_case(r, TestCase::Build("rectD-rectI", kDeviceBounds)
                              .actual().rect(bigR, lm1, GrAA::kYes, SkClipOp::kDifference)
                                       .rect(smR, lm2, GrAA::kYes, SkClipOp::kIntersect)
                                       .finishElements()
                              .state(GrClipStack::ClipState::kEmpty)
                              .finishTest());
    run_test_case(r, TestCase::Build("rrectD-rrectI", kDeviceBounds)
                              .actual().rrect(bigRR, lm1, GrAA::kYes, SkClipOp::kDifference)
                                       .rrect(smRR, lm2, GrAA::kYes, SkClipOp::kIntersect)
                                       .finishElements()
                              .state(GrClipStack::ClipState::kEmpty)
                              .finishTest());
    run_test_case(r, TestCase::Build("rectD-rrectI", kDeviceBounds)
                              .actual().rect(bigR, lm1, GrAA::kYes, SkClipOp::kDifference)
                                       .rrect(smRR, lm2, GrAA::kYes, SkClipOp::kIntersect)
                                       .finishElements()
                              .state(GrClipStack::ClipState::kEmpty)
                              .finishTest());
    run_test_case(r, TestCase::Build("rrectD-rectI", kDeviceBounds)
                              .actual().rrect(bigRR, lm1, GrAA::kYes, SkClipOp::kDifference)
                                       .rect(smR, lm2, GrAA::kYes, SkClipOp::kIntersect)
                                       .finishElements()
                              .state(GrClipStack::ClipState::kEmpty)
                              .finishTest());

    // I(1)+D(2) should result in both shapes
    run_test_case(r, TestCase::Build("rectI+rectD", kDeviceBounds)
                              .actual().rect(bigR, lm1, GrAA::kYes, SkClipOp::kIntersect)
                                       .rect(smR, lm2, GrAA::kYes, SkClipOp::kDifference)
                                       .finishElements()
                              .expectActual()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());
    run_test_case(r, TestCase::Build("rrectI+rrectD", kDeviceBounds)
                              .actual().rrect(bigRR, lm1, GrAA::kYes, SkClipOp::kIntersect)
                                       .rrect(smRR, lm2, GrAA::kYes, SkClipOp::kDifference)
                                       .finishElements()
                              .expectActual()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());
    run_test_case(r, TestCase::Build("rrectI+rectD", kDeviceBounds)
                              .actual().rrect(bigRR, lm1, GrAA::kYes, SkClipOp::kIntersect)
                                       .rect(smR, lm2, GrAA::kYes, SkClipOp::kDifference)
                                       .finishElements()
                              .expectActual()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());
    run_test_case(r, TestCase::Build("rectI+rrectD", kDeviceBounds)
                              .actual().rect(bigR, lm1, GrAA::kYes, SkClipOp::kIntersect)
                                       .rrect(smRR, lm2, GrAA::kYes, SkClipOp::kDifference)
                                       .finishElements()
                              .expectActual()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());
}

// Tests that shapes with mixed AA state that contain each other can still be consolidated,
// unless they are too close to the edge and non-AA snapping can't be predicted
DEF_TEST(GrClipStack_MixedAAContains, r) {
    SkMatrix lm1 = SkMatrix::RotateDeg(45.f);
    SkRect r1 = {-20.f, -20.f, 20.f, 20.f};

    SkMatrix lm2 = SkMatrix::RotateDeg(-45.f);
    SkRect r2Safe = {-10.f, -10.f, 10.f, 10.f};
    SkRect r2Unsafe = {-19.5f, -19.5f, 19.5f, 19.5f};

    // Non-AA sufficiently inside AA element can discard the outer AA element
    run_test_case(r, TestCase::Build("mixed-outeraa-combine", kDeviceBounds)
                              .actual().rect(r1, lm1, GrAA::kYes, SkClipOp::kIntersect)
                                       .rect(r2Safe, lm2, GrAA::kNo, SkClipOp::kIntersect)
                                       .finishElements()
                              .expect().rect(r2Safe, lm2, GrAA::kNo, SkClipOp::kIntersect)
                                       .finishElements()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());
    // Vice versa
    run_test_case(r, TestCase::Build("mixed-inneraa-combine", kDeviceBounds)
                              .actual().rect(r1, lm1, GrAA::kNo, SkClipOp::kIntersect)
                                       .rect(r2Safe, lm2, GrAA::kYes, SkClipOp::kIntersect)
                                       .finishElements()
                              .expect().rect(r2Safe, lm2, GrAA::kYes, SkClipOp::kIntersect)
                                       .finishElements()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());

    // Non-AA too close to AA edges keeps both
    run_test_case(r, TestCase::Build("mixed-outeraa-nocombine", kDeviceBounds)
                              .actual().rect(r1, lm1, GrAA::kYes, SkClipOp::kIntersect)
                                       .rect(r2Unsafe, lm2, GrAA::kNo, SkClipOp::kIntersect)
                                       .finishElements()
                              .expectActual()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());
    run_test_case(r, TestCase::Build("mixed-inneraa-nocombine", kDeviceBounds)
                              .actual().rect(r1, lm1, GrAA::kNo, SkClipOp::kIntersect)
                                       .rect(r2Unsafe, lm2, GrAA::kYes, SkClipOp::kIntersect)
                                       .finishElements()
                              .expectActual()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());
}

// Tests that a shape that contains the device bounds updates the clip state directly
DEF_TEST(GrClipStack_ShapeContainsDevice, r) {
    SkRect rect = SkRect::Make(kDeviceBounds).makeOutset(10.f, 10.f);
    SkRRect rrect = SkRRect::MakeRectXY(rect, 10.f, 10.f);
    SkPath convex = make_octagon(rect, 10.f, 10.f);

    // Intersect -> no-op
    run_test_case(r, TestCase::Build("rect-intersect", kDeviceBounds)
                              .actual().intersect().rect(rect).finishElements()
                              .state(GrClipStack::ClipState::kWideOpen)
                              .finishTest());
    run_test_case(r, TestCase::Build("rrect-intersect", kDeviceBounds)
                              .actual().intersect().rrect(rrect).finishElements()
                              .state(GrClipStack::ClipState::kWideOpen)
                              .finishTest());
    run_test_case(r, TestCase::Build("convex-intersect", kDeviceBounds)
                              .actual().intersect().path(convex).finishElements()
                              .state(GrClipStack::ClipState::kWideOpen)
                              .finishTest());

    // Difference -> empty
    run_test_case(r, TestCase::Build("rect-difference", kDeviceBounds)
                              .actual().difference().rect(rect).finishElements()
                              .state(GrClipStack::ClipState::kEmpty)
                              .finishTest());
    run_test_case(r, TestCase::Build("rrect-difference", kDeviceBounds)
                              .actual().difference().rrect(rrect).finishElements()
                              .state(GrClipStack::ClipState::kEmpty)
                              .finishTest());
    run_test_case(r, TestCase::Build("convex-difference", kDeviceBounds)
                              .actual().difference().path(convex).finishElements()
                              .state(GrClipStack::ClipState::kEmpty)
                              .finishTest());
}

// Tests that shapes that do not overlap make for an empty clip (when intersecting), pick just the
// intersecting op (when mixed), or are all kept (when diff'ing).
DEF_TEST(GrClipStack_DisjointShapes, r) {
    SkRect rt = {10.f, 10.f, 20.f, 20.f};
    SkRRect rr = SkRRect::MakeOval(rt.makeOffset({20.f, 0.f}));
    SkPath p = make_octagon(rt.makeOffset({0.f, 20.f}));

    // I+I
    run_test_case(r, TestCase::Build("iii", kDeviceBounds)
                              .actual().aa().intersect().rect(rt).rrect(rr).path(p).finishElements()
                              .state(GrClipStack::ClipState::kEmpty)
                              .finishTest());

    // D+D
    run_test_case(r, TestCase::Build("ddd", kDeviceBounds)
                              .actual().nonAA().difference().rect(rt).rrect(rr).path(p)
                                       .finishElements()
                              .expectActual()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());

    // I+D from rect
    run_test_case(r, TestCase::Build("idd", kDeviceBounds)
                              .actual().aa().intersect().rect(rt)
                                       .nonAA().difference().rrect(rr).path(p)
                                       .finishElements()
                              .expect().aa().intersect().rect(rt).finishElements()
                              .state(GrClipStack::ClipState::kDeviceRect)
                              .finishTest());

    // I+D from rrect
    run_test_case(r, TestCase::Build("did", kDeviceBounds)
                              .actual().aa().intersect().rrect(rr)
                                       .nonAA().difference().rect(rt).path(p)
                                       .finishElements()
                              .expect().aa().intersect().rrect(rr).finishElements()
                              .state(GrClipStack::ClipState::kDeviceRRect)
                              .finishTest());

    // I+D from path
    run_test_case(r, TestCase::Build("ddi", kDeviceBounds)
                              .actual().aa().intersect().path(p)
                                       .nonAA().difference().rect(rt).rrect(rr)
                                       .finishElements()
                              .expect().aa().intersect().path(p).finishElements()
                              .state(GrClipStack::ClipState::kComplex)
                              .finishTest());
}

DEF_TEST(GrClipStack_ComplexClip, r) {
    static constexpr float kN = 10.f;
    static constexpr float kR = kN / 3.f;

    // 4 rectangles that overlap by kN x 2kN (horiz), 2kN x kN (vert), or kN x kN (diagonal)
    static const SkRect kTL = {0.f, 0.f, 2.f * kN, 2.f * kN};
    static const SkRect kTR = {kN,  0.f, 3.f * kN, 2.f * kN};
    static const SkRect kBL = {0.f, kN,  2.f * kN, 3.f * kN};
    static const SkRect kBR = {kN,  kN,  3.f * kN, 3.f * kN};

    enum ShapeType { kRect, kRRect, kConvex };

    SkRect rects[] = { kTL, kTR, kBL, kBR };
    for (ShapeType type : { kRect, kRRect, kConvex }) {
        for (int opBits = 6; opBits < 16; ++opBits) {
            SkString name;
            name.appendf("complex-%d-%d", (int) type, opBits);

            SkRect expectedRectIntersection = SkRect::Make(kDeviceBounds);
            SkRRect expectedRRectIntersection = SkRRect::MakeRect(expectedRectIntersection);

            auto b = TestCase::Build(name.c_str(), kDeviceBounds);
            for (int i = 0; i < 4; ++i) {
                SkClipOp op = (opBits & (1 << i)) ? SkClipOp::kIntersect : SkClipOp::kDifference;
                switch(type) {
                    case kRect: {
                        SkRect r = rects[i];
                        if (op == SkClipOp::kDifference) {
                            // Shrink the rect for difference ops, otherwise in the rect testcase
                            // any difference op would remove the intersection of the other ops
                            // given how the rects are defined, and that's just not interesting.
                            r.inset(kR, kR);
                        }
                        b.actual().rect(r, GrAA::kYes, op);
                        if (op == SkClipOp::kIntersect) {
                            SkAssertResult(expectedRectIntersection.intersect(r));
                        } else {
                            b.expect().rect(r, GrAA::kYes, SkClipOp::kDifference);
                        }
                        break; }
                    case kRRect: {
                        SkRRect rrect = SkRRect::MakeRectXY(rects[i], kR, kR);
                        b.actual().rrect(rrect, GrAA::kYes, op);
                        if (op == SkClipOp::kIntersect) {
                            expectedRRectIntersection = SkRRectPriv::ConservativeIntersect(
                                    expectedRRectIntersection, rrect);
                            SkASSERT(!expectedRRectIntersection.isEmpty());
                        } else {
                            b.expect().rrect(rrect, GrAA::kYes, SkClipOp::kDifference);
                        }
                        break; }
                    case kConvex:
                        b.actual().path(make_octagon(rects[i], kR, kR), GrAA::kYes, op);
                        // NOTE: We don't set any expectations here, since convex just calls
                        // expectActual() at the end.
                        break;
                }
            }

            // The expectations differ depending on the shape type
            GrClipStack::ClipState state = GrClipStack::ClipState::kComplex;
            if (type == kConvex) {
                // The simplest case is when the paths cannot be combined together, so we expect
                // the actual elements to be unmodified (both intersect and difference).
                b.expectActual();
            } else if (opBits) {
                // All intersection ops were pre-computed into expectedR[R]ectIntersection
                // - difference ops already added in the for loop
                if (type == kRect) {
                    SkASSERT(expectedRectIntersection != SkRect::Make(kDeviceBounds) &&
                             !expectedRectIntersection.isEmpty());
                    b.expect().rect(expectedRectIntersection, GrAA::kYes, SkClipOp::kIntersect);
                    if (opBits == 0xf) {
                        state = GrClipStack::ClipState::kDeviceRect;
                    }
                } else {
                    SkASSERT(expectedRRectIntersection !=
                                    SkRRect::MakeRect(SkRect::Make(kDeviceBounds)) &&
                             !expectedRRectIntersection.isEmpty());
                    b.expect().rrect(expectedRRectIntersection, GrAA::kYes, SkClipOp::kIntersect);
                    if (opBits == 0xf) {
                        state = GrClipStack::ClipState::kDeviceRRect;
                    }
                }
            }

            run_test_case(r, b.state(state).finishTest());
        }
    }
}

// ///////////////////////////////////////////////////////////////////////////////
// // These tests do not use the TestCase infrastructure and manipulate a
// // GrClipStack directly.

// Tests that replaceClip() works as expected across save/restores
DEF_TEST(GrClipStack_ReplaceClip, r) {
    GrClipStack cs(kDeviceBounds, nullptr, false);

    SkRRect rrect = SkRRect::MakeRectXY({15.f, 12.25f, 40.3f, 23.5f}, 4.f, 6.f);
    cs.clipRRect(SkMatrix::I(), rrect, GrAA::kYes, SkClipOp::kIntersect);

    SkIRect replace = {50, 25, 75, 40}; // Is disjoint from the rrect element
    cs.save();
    cs.replaceClip(replace);

    REPORTER_ASSERT(r, cs.clipState() == GrClipStack::ClipState::kDeviceRect,
                    "Clip did not become a device rect");
    REPORTER_ASSERT(r, cs.getConservativeBounds() == replace, "Unexpected replaced clip bounds");
    const GrClipStack::Element& replaceElement = *cs.begin();
    REPORTER_ASSERT(r, replaceElement.fShape.rect() == SkRect::Make(replace) &&
                       replaceElement.fAA == GrAA::kNo &&
                       replaceElement.fOp == SkClipOp::kIntersect &&
                       replaceElement.fLocalToDevice == SkMatrix::I(),
                    "Unexpected replace element state");

    // Restore should undo the replaced clip and bring back the rrect
    cs.restore();
    REPORTER_ASSERT(r, cs.clipState() == GrClipStack::ClipState::kDeviceRRect,
                    "Unexpected state after restore, not kDeviceRRect");
    const GrClipStack::Element& rrectElem = *cs.begin();
    REPORTER_ASSERT(r, rrectElem.fShape.rrect() == rrect &&
                       rrectElem.fAA == GrAA::kYes &&
                       rrectElem.fOp == SkClipOp::kIntersect &&
                       rrectElem.fLocalToDevice == SkMatrix::I(),
                    "RRect element state not restored properly after replace clip undone");
}

// Try to overflow the number of allowed window rects (see skbug.com/10989)
DEF_TEST(GrClipStack_DiffRects, r) {
    GrMockOptions options;
    options.fMaxWindowRectangles = 8;

    SkSimpleMatrixProvider matrixProvider = SkMatrix::I();
    sk_sp<GrDirectContext> context = GrDirectContext::MakeMock(&options);
    std::unique_ptr<GrSurfaceDrawContext> rtc = GrSurfaceDrawContext::Make(
            context.get(), GrColorType::kRGBA_8888, SkColorSpace::MakeSRGB(),
            SkBackingFit::kExact, kDeviceBounds.size(), SkSurfaceProps());

    GrClipStack cs(kDeviceBounds, &matrixProvider, false);

    cs.save();
    for (int y = 0; y < 10; ++y) {
        for (int x = 0; x < 10; ++x) {
            cs.clipRect(SkMatrix::I(), SkRect::MakeXYWH(10*x+1, 10*y+1, 8, 8),
                        GrAA::kNo, SkClipOp::kDifference);
        }
    }

    GrAppliedClip out(kDeviceBounds.size());
    SkRect drawBounds = SkRect::Make(kDeviceBounds);
    GrClip::Effect effect = cs.apply(context.get(), rtc.get(), GrAAType::kCoverage, &out,
                                     &drawBounds);

    REPORTER_ASSERT(r, effect == GrClip::Effect::kClipped);
    REPORTER_ASSERT(r, out.windowRectsState().numWindows() == 8);

    cs.restore();
}

// Tests that when a stack is forced to always be AA, non-AA elements become AA
DEF_TEST(GrClipStack_ForceAA, r) {
    GrClipStack cs(kDeviceBounds, nullptr, true);

    // AA will remain AA
    SkRect aaRect = {0.25f, 12.43f, 25.2f, 23.f};
    cs.clipRect(SkMatrix::I(), aaRect, GrAA::kYes, SkClipOp::kIntersect);

    // Non-AA will become AA
    SkPath nonAAPath = make_octagon({2.f, 10.f, 16.f, 20.f});
    cs.clipPath(SkMatrix::I(), nonAAPath, GrAA::kNo, SkClipOp::kIntersect);

    // Non-AA rects remain non-AA so they can be applied as a scissor
    SkRect nonAARect = {4.5f, 5.f, 17.25f, 18.23f};
    cs.clipRect(SkMatrix::I(), nonAARect, GrAA::kNo, SkClipOp::kIntersect);

    // The stack reports elements newest first, but the non-AA rect op was combined in place with
    // the first aa rect, so we should see nonAAPath as AA, and then the intersection of rects.
    auto elements = cs.begin();

    const GrClipStack::Element& nonAARectElement = *elements;
    REPORTER_ASSERT(r, nonAARectElement.fShape.isRect(), "Expected rect element");
    REPORTER_ASSERT(r, nonAARectElement.fAA == GrAA::kNo,
                    "Axis-aligned non-AA rect ignores forceAA");
    REPORTER_ASSERT(r, nonAARectElement.fShape.rect() == nonAARect,
                    "Mixed AA rects should not combine");

    ++elements;
    const GrClipStack::Element& aaPathElement = *elements;
    REPORTER_ASSERT(r, aaPathElement.fShape.isPath(), "Expected path element");
    REPORTER_ASSERT(r, aaPathElement.fShape.path() == nonAAPath, "Wrong path element");
    REPORTER_ASSERT(r, aaPathElement.fAA == GrAA::kYes, "Path element not promoted to AA");

    ++elements;
    const GrClipStack::Element& aaRectElement = *elements;
    REPORTER_ASSERT(r, aaRectElement.fShape.isRect(), "Expected rect element");
    REPORTER_ASSERT(r, aaRectElement.fShape.rect() == aaRect,
                    "Mixed AA rects should not combine");
    REPORTER_ASSERT(r, aaRectElement.fAA == GrAA::kYes, "Rect element stays AA");

    ++elements;
    REPORTER_ASSERT(r, !(elements != cs.end()), "Expected only three clip elements");
}

// Tests preApply works as expected for device rects, rrects, and reports clipped-out, etc. as
// expected.
DEF_TEST(GrClipStack_PreApply, r) {
    GrClipStack cs(kDeviceBounds, nullptr, false);

    // Offscreen is kClippedOut
    GrClip::PreClipResult result = cs.preApply({-10.f, -10.f, -1.f, -1.f}, GrAA::kYes);
    REPORTER_ASSERT(r, result.fEffect == GrClip::Effect::kClippedOut,
                    "Offscreen draw is kClippedOut");

    // Intersecting screen with wide-open clip is kUnclipped
    result = cs.preApply({-10.f, -10.f, 10.f, 10.f}, GrAA::kYes);
    REPORTER_ASSERT(r, result.fEffect == GrClip::Effect::kUnclipped,
                    "Wide open screen intersection is still kUnclipped");

    // Empty clip is clipped out
    cs.save();
    cs.clipRect(SkMatrix::I(), SkRect::MakeEmpty(), GrAA::kNo, SkClipOp::kIntersect);
    result = cs.preApply({0.f, 0.f, 20.f, 20.f}, GrAA::kYes);
    REPORTER_ASSERT(r, result.fEffect == GrClip::Effect::kClippedOut,
                    "Empty clip stack preApplies as kClippedOut");
    cs.restore();

    // Contained inside clip is kUnclipped (using rrect for the outer clip element since paths
    // don't support an inner bounds and anything complex is otherwise skipped in preApply).
    SkRect rect = {10.f, 10.f, 40.f, 40.f};
    SkRRect bigRRect = SkRRect::MakeRectXY(rect.makeOutset(5.f, 5.f), 5.f, 5.f);
    cs.save();
    cs.clipRRect(SkMatrix::I(), bigRRect, GrAA::kYes, SkClipOp::kIntersect);
    result = cs.preApply(rect, GrAA::kYes);
    REPORTER_ASSERT(r, result.fEffect == GrClip::Effect::kUnclipped,
                    "Draw contained within clip is kUnclipped");

    // Disjoint from clip (but still on screen) is kClippedOut
    result = cs.preApply({50.f, 50.f, 60.f, 60.f}, GrAA::kYes);
    REPORTER_ASSERT(r, result.fEffect == GrClip::Effect::kClippedOut,
                    "Draw not intersecting clip is kClippedOut");
    cs.restore();

    // Intersecting clip is kClipped for complex shape
    cs.save();
    SkPath path = make_octagon(rect.makeOutset(5.f, 5.f), 5.f, 5.f);
    cs.clipPath(SkMatrix::I(), path, GrAA::kYes, SkClipOp::kIntersect);
    result = cs.preApply(path.getBounds(), GrAA::kNo);
    REPORTER_ASSERT(r, result.fEffect == GrClip::Effect::kClipped && !result.fIsRRect,
                    "Draw with complex clip is kClipped, but is not an rrect");
    cs.restore();

    // Intersecting clip is kDeviceRect for axis-aligned rect clip
    cs.save();
    cs.clipRect(SkMatrix::I(), rect, GrAA::kYes, SkClipOp::kIntersect);
    result = cs.preApply(rect.makeOffset(2.f, 2.f), GrAA::kNo);
    REPORTER_ASSERT(r, result.fEffect == GrClip::Effect::kClipped &&
                       result.fAA == GrAA::kYes &&
                       result.fIsRRect &&
                       result.fRRect == SkRRect::MakeRect(rect),
                    "kDeviceRect clip stack should be reported by preApply");
    cs.restore();

    // Intersecting clip is kDeviceRRect for axis-aligned rrect clip
    cs.save();
    SkRRect clipRRect = SkRRect::MakeRectXY(rect, 5.f, 5.f);
    cs.clipRRect(SkMatrix::I(), clipRRect, GrAA::kYes, SkClipOp::kIntersect);
    result = cs.preApply(rect.makeOffset(2.f, 2.f), GrAA::kNo);
    REPORTER_ASSERT(r, result.fEffect == GrClip::Effect::kClipped &&
                       result.fAA == GrAA::kYes &&
                       result.fIsRRect &&
                       result.fRRect == clipRRect,
                    "kDeviceRRect clip stack should be reported by preApply");
    cs.restore();
}

// Tests the clip shader entry point
DEF_TEST(GrClipStack_Shader, r) {
    sk_sp<SkShader> shader = SkShaders::Color({0.f, 0.f, 0.f, 0.5f}, nullptr);

    SkSimpleMatrixProvider matrixProvider = SkMatrix::I();
    sk_sp<GrDirectContext> context = GrDirectContext::MakeMock(nullptr);
    std::unique_ptr<GrSurfaceDrawContext> rtc = GrSurfaceDrawContext::Make(
            context.get(), GrColorType::kRGBA_8888, SkColorSpace::MakeSRGB(),
            SkBackingFit::kExact, kDeviceBounds.size(), SkSurfaceProps());

    GrClipStack cs(kDeviceBounds, &matrixProvider, false);
    cs.save();
    cs.clipShader(shader);

    REPORTER_ASSERT(r, cs.clipState() == GrClipStack::ClipState::kComplex,
                    "A clip shader should be reported as a complex clip");

    GrAppliedClip out(kDeviceBounds.size());
    SkRect drawBounds = {10.f, 11.f, 16.f, 32.f};
    GrClip::Effect effect = cs.apply(context.get(), rtc.get(), GrAAType::kCoverage, &out,
                                     &drawBounds);

    REPORTER_ASSERT(r, effect == GrClip::Effect::kClipped,
                    "apply() should return kClipped for a clip shader");
    REPORTER_ASSERT(r, out.hasCoverageFragmentProcessor(),
                    "apply() should have converted clip shader to a coverage FP");

    GrAppliedClip out2(kDeviceBounds.size());
    drawBounds = {-15.f, -10.f, -1.f, 10.f}; // offscreen
    effect = cs.apply(context.get(), rtc.get(), GrAAType::kCoverage, &out2, &drawBounds);
    REPORTER_ASSERT(r, effect == GrClip::Effect::kClippedOut,
                    "apply() should still discard offscreen draws with a clip shader");

    cs.restore();
    REPORTER_ASSERT(r, cs.clipState() == GrClipStack::ClipState::kWideOpen,
                    "restore() should get rid of the clip shader");


    // Adding a clip shader on top of a device rect clip should prevent preApply from reporting
    // it as a device rect
    cs.clipRect(SkMatrix::I(), {10, 15, 30, 30}, GrAA::kNo, SkClipOp::kIntersect);
    SkASSERT(cs.clipState() == GrClipStack::ClipState::kDeviceRect); // test precondition
    cs.clipShader(shader);
    GrClip::PreClipResult result = cs.preApply(SkRect::Make(kDeviceBounds), GrAA::kYes);
    REPORTER_ASSERT(r, result.fEffect == GrClip::Effect::kClipped && !result.fIsRRect,
                    "A clip shader should not produce a device rect from preApply");
}

// Tests apply() under simple circumstances, that don't require actual rendering of masks, or
// atlases. This lets us define the test regularly instead of a GPU-only test.
// - This is not exhaustive and is challenging to unit test, so apply() is predominantly tested by
//   the GMs instead.
DEF_TEST(GrClipStack_SimpleApply, r) {
    SkSimpleMatrixProvider matrixProvider = SkMatrix::I();
    sk_sp<GrDirectContext> context = GrDirectContext::MakeMock(nullptr);
    std::unique_ptr<GrSurfaceDrawContext> rtc = GrSurfaceDrawContext::Make(
            context.get(), GrColorType::kRGBA_8888, SkColorSpace::MakeSRGB(),
            SkBackingFit::kExact, kDeviceBounds.size(), SkSurfaceProps());

    GrClipStack cs(kDeviceBounds, &matrixProvider, false);

    // Offscreen draw is kClippedOut
    {
        SkRect drawBounds = {-15.f, -15.f, -1.f, -1.f};

        GrAppliedClip out(kDeviceBounds.size());
        GrClip::Effect effect = cs.apply(context.get(), rtc.get(), GrAAType::kCoverage, &out,
                                         &drawBounds);
        REPORTER_ASSERT(r, effect == GrClip::Effect::kClippedOut, "Offscreen draw is clipped out");
    }

    // Draw contained in clip is kUnclipped
    {
        SkRect drawBounds = {15.4f, 16.3f, 26.f, 32.f};
        cs.save();
        cs.clipPath(SkMatrix::I(), make_octagon(drawBounds.makeOutset(5.f, 5.f), 5.f, 5.f),
                    GrAA::kYes, SkClipOp::kIntersect);

        GrAppliedClip out(kDeviceBounds.size());
        GrClip::Effect effect = cs.apply(context.get(), rtc.get(), GrAAType::kCoverage, &out,
                                         &drawBounds);
        REPORTER_ASSERT(r, effect == GrClip::Effect::kUnclipped, "Draw inside clip is unclipped");
        cs.restore();
    }

    // Draw bounds are cropped to device space before checking contains
    {
        SkRect clipRect = {kDeviceBounds.fRight - 20.f, 10.f, kDeviceBounds.fRight, 20.f};
        SkRect drawRect = clipRect.makeOffset(10.f, 0.f);

        cs.save();
        cs.clipRect(SkMatrix::I(), clipRect, GrAA::kNo, SkClipOp::kIntersect);

        GrAppliedClip out(kDeviceBounds.size());
        GrClip::Effect effect = cs.apply(context.get(), rtc.get(), GrAAType::kCoverage, &out,
                                         &drawRect);
        REPORTER_ASSERT(r, SkRect::Make(kDeviceBounds).contains(drawRect),
                        "Draw rect should be clipped to device rect");
        REPORTER_ASSERT(r, effect == GrClip::Effect::kUnclipped,
                        "After device clipping, this should be detected as contained within clip");
        cs.restore();
    }

    // Non-AA device rect intersect is just a scissor
    {
        SkRect clipRect = {15.3f, 17.23f, 30.2f, 50.8f};
        SkRect drawRect = clipRect.makeOutset(10.f, 10.f);
        SkIRect expectedScissor = clipRect.round();

        cs.save();
        cs.clipRect(SkMatrix::I(), clipRect, GrAA::kNo, SkClipOp::kIntersect);

        GrAppliedClip out(kDeviceBounds.size());
        GrClip::Effect effect = cs.apply(context.get(), rtc.get(), GrAAType::kCoverage, &out,
                                         &drawRect);
        REPORTER_ASSERT(r, effect == GrClip::Effect::kClipped, "Draw should be clipped by rect");
        REPORTER_ASSERT(r, !out.hasCoverageFragmentProcessor(), "Clip should not use coverage FPs");
        REPORTER_ASSERT(r, !out.hardClip().hasStencilClip(), "Clip should not need stencil");
        REPORTER_ASSERT(r, !out.hardClip().windowRectsState().enabled(),
                        "Clip should not need window rects");
        REPORTER_ASSERT(r, out.scissorState().enabled() &&
                           out.scissorState().rect() == expectedScissor,
                        "Clip has unexpected scissor rectangle");
        cs.restore();
    }

    // Analytic coverage FPs
    auto testHasCoverageFP = [&](SkRect drawBounds) {
        GrAppliedClip out(kDeviceBounds.size());
        GrClip::Effect effect = cs.apply(context.get(), rtc.get(), GrAAType::kCoverage, &out,
                                         &drawBounds);
        REPORTER_ASSERT(r, effect == GrClip::Effect::kClipped, "Draw should be clipped");
        REPORTER_ASSERT(r, out.scissorState().enabled(), "Coverage FPs should still set scissor");
        REPORTER_ASSERT(r, out.hasCoverageFragmentProcessor(), "Clip should use coverage FP");
    };

    // Axis-aligned rect can be an analytic FP
    {
        cs.save();
        cs.clipRect(SkMatrix::I(), {10.2f, 8.342f, 63.f, 23.3f}, GrAA::kYes,
                    SkClipOp::kDifference);
        testHasCoverageFP({9.f, 10.f, 30.f, 18.f});
        cs.restore();
    }

    // Axis-aligned round rect can be an analytic FP
    {
        SkRect rect = {4.f, 8.f, 20.f, 20.f};
        cs.save();
        cs.clipRRect(SkMatrix::I(), SkRRect::MakeRectXY(rect, 3.f, 3.f), GrAA::kYes,
                     SkClipOp::kIntersect);
        testHasCoverageFP(rect.makeOffset(2.f, 2.f));
        cs.restore();
    }

    // Transformed rect can be an analytic FP
    {
        SkRect rect = {14.f, 8.f, 30.f, 22.34f};
        SkMatrix rot = SkMatrix::RotateDeg(34.f);
        cs.save();
        cs.clipRect(rot, rect, GrAA::kNo, SkClipOp::kIntersect);
        testHasCoverageFP(rot.mapRect(rect));
        cs.restore();
    }

    // Convex polygons can be an analytic FP
    {
        SkRect rect = {15.f, 15.f, 45.f, 45.f};
        cs.save();
        cs.clipPath(SkMatrix::I(), make_octagon(rect), GrAA::kYes, SkClipOp::kIntersect);
        testHasCoverageFP(rect.makeOutset(2.f, 2.f));
        cs.restore();
    }
}

// Must disable tessellation in order to trigger SW mask generation when the clip stack is applied.
static void disable_tessellation_atlas(GrContextOptions* options) {
    options->fGpuPathRenderers = GpuPathRenderers::kNone;
    options->fAvoidStencilBuffers = true;
}

DEF_GPUTEST_FOR_CONTEXTS(GrClipStack_SWMask,
                         sk_gpu_test::GrContextFactory::IsRenderingContext,
                         r, ctxInfo, disable_tessellation_atlas) {
    GrDirectContext* context = ctxInfo.directContext();
    std::unique_ptr<GrSurfaceDrawContext> rtc = GrSurfaceDrawContext::Make(
            context, GrColorType::kRGBA_8888, nullptr, SkBackingFit::kExact, kDeviceBounds.size(),
            SkSurfaceProps());

    SkSimpleMatrixProvider matrixProvider = SkMatrix::I();
    std::unique_ptr<GrClipStack> cs(new GrClipStack(kDeviceBounds, &matrixProvider, false));

    auto addMaskRequiringClip = [&](SkScalar x, SkScalar y, SkScalar radius) {
        SkPath path;
        path.addCircle(x, y, radius);
        path.addCircle(x + radius / 2.f, y + radius / 2.f, radius);
        path.setFillType(SkPathFillType::kEvenOdd);

        // Use AA so that clip application does not route through the stencil buffer
        cs->clipPath(SkMatrix::I(), path, GrAA::kYes, SkClipOp::kIntersect);
    };

    auto drawRect = [&](SkRect drawBounds) {
        GrPaint paint;
        paint.setColor4f({1.f, 1.f, 1.f, 1.f});
        rtc->drawRect(cs.get(), std::move(paint), GrAA::kYes, SkMatrix::I(), drawBounds);
    };

    auto generateMask = [&](SkRect drawBounds) {
        GrUniqueKey priorKey = cs->testingOnly_getLastSWMaskKey();
        drawRect(drawBounds);
        GrUniqueKey newKey = cs->testingOnly_getLastSWMaskKey();
        REPORTER_ASSERT(r, priorKey != newKey, "Did not generate a new SW mask key as expected");
        return newKey;
    };

    auto verifyKeys = [&](const std::vector<GrUniqueKey>& expectedKeys,
                          const std::vector<GrUniqueKey>& releasedKeys) {
        context->flush();
        GrProxyProvider* proxyProvider = context->priv().proxyProvider();

#ifdef SK_DEBUG
        // The proxy providers key count fluctuates based on proxy lifetime, but we want to
        // verify the resource count, and that requires using key tags that are debug-only.
        SkASSERT(expectedKeys.size() > 0 || releasedKeys.size() > 0);
        const char* tag = expectedKeys.size() > 0 ? expectedKeys[0].tag() : releasedKeys[0].tag();
        GrResourceCache* cache = context->priv().getResourceCache();
        int numProxies = cache->countUniqueKeysWithTag(tag);
        REPORTER_ASSERT(r, (int) expectedKeys.size() == numProxies,
                        "Unexpected proxy count, got %d, not %d",
                        numProxies, (int) expectedKeys.size());
#endif

        for (const auto& key : expectedKeys) {
            auto proxy = proxyProvider->findOrCreateProxyByUniqueKey(key);
            REPORTER_ASSERT(r, SkToBool(proxy), "Unable to find resource for expected mask key");
        }
        for (const auto& key : releasedKeys) {
            auto proxy = proxyProvider->findOrCreateProxyByUniqueKey(key);
            REPORTER_ASSERT(r, !SkToBool(proxy), "SW mask not released as expected");
        }
    };

    // Creates a mask for a complex clip
    cs->save();
    addMaskRequiringClip(5.f, 5.f, 20.f);
    GrUniqueKey keyADepth1 = generateMask({0.f, 0.f, 20.f, 20.f});
    GrUniqueKey keyBDepth1 = generateMask({10.f, 10.f, 30.f, 30.f});
    verifyKeys({keyADepth1, keyBDepth1}, {});

    // Creates a new mask for a new save record, but doesn't delete the old records
    cs->save();
    addMaskRequiringClip(6.f, 6.f, 15.f);
    GrUniqueKey keyADepth2 = generateMask({0.f, 0.f, 20.f, 20.f});
    GrUniqueKey keyBDepth2 = generateMask({10.f, 10.f, 30.f, 30.f});
    verifyKeys({keyADepth1, keyBDepth1, keyADepth2, keyBDepth2}, {});

    // Release after modifying the current record (even if we don't draw anything)
    addMaskRequiringClip(4.f, 4.f, 15.f);
    GrUniqueKey keyCDepth2 = generateMask({4.f, 4.f, 16.f, 20.f});
    verifyKeys({keyADepth1, keyBDepth1, keyCDepth2}, {keyADepth2, keyBDepth2});

    // Release after restoring an older record
    cs->restore();
    verifyKeys({keyADepth1, keyBDepth1}, {keyCDepth2});

    // Drawing finds the old masks at depth 1 still w/o making new ones
    drawRect({0.f, 0.f, 20.f, 20.f});
    drawRect({10.f, 10.f, 30.f, 30.f});
    verifyKeys({keyADepth1, keyBDepth1}, {});

    // Drawing something contained within a previous mask also does not make a new one
    drawRect({5.f, 5.f, 15.f, 15.f});
    verifyKeys({keyADepth1, keyBDepth1}, {});

    // Release on destruction
    cs = nullptr;
    verifyKeys({}, {keyADepth1, keyBDepth1});
}
