/*
 * Copyright 2022 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/graphite/ClipStack.h"

#include "include/core/SkBlendMode.h"
#include "include/core/SkClipOp.h"
#include "include/core/SkM44.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPath.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRRect.h"
#include "include/core/SkRect.h"
#include "include/core/SkScalar.h"
#include "include/core/SkShader.h"
#include "include/core/SkSpan.h"
#include "include/core/SkStrokeRec.h"
#include "include/gpu/graphite/Recorder.h"
#include "include/private/SkDebug.h"
#include "include/private/SkEnumBitMask.h"
#include "include/private/SkFloatingPoint.h"
#include "src/core/SkPathPriv.h"
#include "src/core/SkRRectPriv.h"
#include "src/core/SkRectPriv.h"
#include "src/core/SkVx.h"
#include "src/gpu/graphite/AtlasProvider.h"
#include "src/gpu/graphite/ClipAtlasManager.h"
#include "src/gpu/graphite/Device.h"
#include "src/gpu/graphite/DrawParams.h"
#include "src/gpu/graphite/RecorderPriv.h"
#include "src/gpu/graphite/RendererProvider.h"
#include "src/gpu/graphite/TextureProxy.h"
#include "src/gpu/graphite/geom/BoundsManager.h"
#include "src/gpu/graphite/geom/EdgeAAQuad.h"
#include "src/gpu/graphite/geom/Geometry.h"
#include "src/gpu/graphite/geom/NonMSAAClip.h"

#include <algorithm>
#include <atomic>
#include <utility>

namespace skgpu::graphite {

namespace {

Rect subtract(const Rect& a, const Rect& b, bool exact) {
    SkRect diff;
    if (SkRectPriv::Subtract(a.asSkRect(), b.asSkRect(), &diff) || !exact) {
        // Either A-B is exactly the rectangle stored in diff, or we don't need an exact answer
        // and can settle for the subrect of A excluded from B (which is also 'diff')
        return Rect{diff};
    } else {
        // For our purposes, we want the original A when A-B cannot be exactly represented
        return a;
    }
}

static constexpr uint32_t kInvalidGenID  = 0;
static constexpr uint32_t kEmptyGenID    = 1;
static constexpr uint32_t kWideOpenGenID = 2;

uint32_t next_gen_id() {
    // 0-2 are reserved for invalid, empty & wide-open
    static const uint32_t kFirstUnreservedGenID = 3;
    static std::atomic<uint32_t> nextID{kFirstUnreservedGenID};

    uint32_t id;
    do {
        id = nextID.fetch_add(1, std::memory_order_relaxed);
    } while (id < kFirstUnreservedGenID);
    return id;
}

bool oriented_bbox_intersection(const Rect& a, const Transform& aXform,
                                const Rect& b, const Transform& bXform) {
    // NOTE: We intentionally exclude projected bounds for two reasons:
    //   1. We can skip the division by w and worring about clipping to w = 0.
    //   2. W/o the projective case, the separating axes are simpler to compute (see below).
    SkASSERT(aXform.type() != Transform::Type::kPerspective &&
             bXform.type() != Transform::Type::kPerspective);
    SkV4 quadA[4], quadB[4];

    aXform.mapPoints(a, quadA);
    bXform.mapPoints(b, quadB);

    // There are 4 separating axes, defined by the two normals from quadA and from quadB, but
    // since they were produced by transforming a rectangle by an affine transform, we know the
    // normals are orthoganal to the basis vectors of upper 2x2 of their two transforms.
    auto axesX = skvx::float4(-aXform.matrix().rc(1,0), -aXform.matrix().rc(1,1),
                              -bXform.matrix().rc(1,0), -bXform.matrix().rc(1,1));
    auto axesY = skvx::float4(aXform.matrix().rc(0,0), aXform.matrix().rc(0,1),
                              bXform.matrix().rc(0,0), bXform.matrix().rc(0,1));

    // Projections of the 4 corners of each quadrilateral vs. the 4 axes. For orthonormal
    // transforms, the projections of a quad's corners to its own normal axes should work out
    // to the original dimensions of the rectangle, but this code handles skew and scale factors
    // without branching.
    auto aProj0 = quadA[0].x * axesX + quadA[0].y * axesY;
    auto aProj1 = quadA[1].x * axesX + quadA[1].y * axesY;
    auto aProj2 = quadA[2].x * axesX + quadA[2].y * axesY;
    auto aProj3 = quadA[3].x * axesX + quadA[3].y * axesY;

    auto bProj0 = quadB[0].x * axesX + quadB[0].y * axesY;
    auto bProj1 = quadB[1].x * axesX + quadB[1].y * axesY;
    auto bProj2 = quadB[2].x * axesX + quadB[2].y * axesY;
    auto bProj3 = quadB[3].x * axesX + quadB[3].y * axesY;

    // Minimum and maximum projected values against the 4 axes, for both quadA and quadB, which
    // gives us four pairs of intervals to test for separation.
    auto minA = min(min(aProj0, aProj1), min(aProj2, aProj3));
    auto maxA = max(max(aProj0, aProj1), max(aProj2, aProj3));
    auto minB = min(min(bProj0, bProj1), min(bProj2, bProj3));
    auto maxB = max(max(bProj0, bProj1), max(bProj2, bProj3));

    auto overlaps = (minB <= maxA) & (minA <= maxB);
    return all(overlaps); // any non-overlapping interval would imply no intersection
}

// LTRB are set in returned bitmask if other's LTRB edge is coincident or inside `shape`'s edge.
SkEnumBitMask<EdgeAAQuad::Flags> clipped_edges(const Rect& shape, const Rect& other) {
    // Since RB are stored negated in vals(), this works out to
    //     [other.LT >= shape.LT, other.RB <= shape.RB]
    auto insideMask = other.vals() >= shape.vals();
    return (insideMask[0] ? EdgeAAQuad::Flags::kLeft   : EdgeAAQuad::Flags::kNone) |
           (insideMask[1] ? EdgeAAQuad::Flags::kTop    : EdgeAAQuad::Flags::kNone) |
           (insideMask[2] ? EdgeAAQuad::Flags::kRight  : EdgeAAQuad::Flags::kNone) |
           (insideMask[3] ? EdgeAAQuad::Flags::kBottom : EdgeAAQuad::Flags::kNone);
}

// Tries to intersect `otherShape` transformed by `otherToDevice` directly into `shape` assuming
// that `shape` is transformed by localToDevice. If possible (true), `shape` represents the exact
// intersection of the two original shapes. Returns true if `shape` is modified, false otherwise.
bool intersect_shape(const Transform& otherToDevice, const Shape& otherShape,
                     const Transform& localToDevice, Shape* shape,
                     SkEnumBitMask<EdgeAAQuad::Flags>* edgeFlags) {
    // There are only a subset of shape types that we can analytically intersect with each other,
    // assuming a simple fill style (always the case for clip shapes):
    //
    //  rects, rrects, flood-fills (empty+inverse-fill)
    //
    // Flood-fills only appear as part of a draw, so it's only checked for `shape` and not
    // `otherShape`. In theory, per-edge AA quads could also be included but they do not appear as
    // clip shapes.
    //
    // Paths and arcs have complex intersection logic, so are skipped under the assumption that
    // simple cases have already been mapped to a rect or rrect. Lines are only ever stroked, so
    // are incompatible with this function.
    //
    // EdgeAAQuads that are rectangular can be intersected by being treated as a rect shape and
    // adjusting edge flags as non-AA edges are clipped out.
    bool shapeIntersectable = shape->isRect() ||
                              shape->isRRect() ||
                              shape->isFloodFill();
    bool otherIntersectable = otherShape.isRect() || otherShape.isRRect();
    // Only clip shapes are used for `otherShape`, so we shouldn't see any flood fills here
    SkASSERT(!otherShape.isFloodFill());
    // Only rects should have edge flags other than kAll
    SkASSERT(*edgeFlags == EdgeAAQuad::Flags::kAll || shape->isRect());

    if (!shapeIntersectable || !otherIntersectable) {
        // Technically if shapeIntersectable was true for empty+inverse, we could turn the flood
        // fill into `otherShape` regardless of its type, but those other types are more expensive
        // to render and in the situation where many draws fill against a clip path, we'd want to
        // draw the clip a single time vs. drawing the path multiple times.
        return false;
    }

    // In order to combine, otherShape must be able to map into `localToDevice` without changing
    // shape class (e.g. to a path when rotated) in order for shading to apply in the same
    // coordinate space. This is possible if the relative transform between otherToDevice and
    // localToDevice is rectStaysRect.
    Transform storage{SkM44::kUninitialized_Constructor};

    // We track `local` to `other` and use the `inverseMapRect` functions to map the `otherShape`
    // into local space when possible. Using `localToOther` instead of `otherToLocal` allows the
    // common case of a device-space clip (otherToDevice == I) and an axis-aligned draw to
    // simply use `localToDevice` as `localToOther`.
    const Transform* localToOther;

    if (otherToDevice == localToDevice) {
        // No coordinate space conversion, so set to null to signal identity mapping is skippable.
        // NOTE: This case arises in clip-clip combinations when both were axis-aligned and pre-
        // transformed to device space.
        localToOther = nullptr;
    } else if (otherToDevice.type() == Transform::Type::kIdentity &&
               localToDevice.type() <= Transform::Type::kRectStaysRect) {
        // Relative transform is (otherToDevice)^-1*localToDevice = localToDevice
        localToOther = &localToDevice;
    } else if (otherToDevice.type() <= Transform::Type::kRectStaysRect &&
               localToDevice.type() == Transform::Type::kIdentity) {
        // Relative transform is otherToDevice^-1*localToDevice = otherToDevice^-1
        // (which may not occur in a common scenario but is harmless). Inverse() is mostly
        // shuffling bytes around, not recomputing the inverse.
        storage = Transform::Inverse(otherToDevice);
        localToOther = &storage;
    } else {
        // Calculate (otherToDevice)^-1*localToDevice and see if the relative transform is
        // of the right type.
        storage = Transform(otherToDevice.inverse() * localToDevice);
        if (storage.type() <= Transform::Type::kRectStaysRect) {
            localToOther = &storage;
        } else {
            // `otherShape` can't be trivially mapped to the local coordinate space
            return false;
        }
    }

    // Since `otherShape` is either a rect or a round rect, bounds() is tight to the linear edges.
    Rect localOtherRect = otherShape.bounds();
    if (localToOther) {
        // In this block, `localOtherRect` is defined in the other coord space and `mapped` is in
        // the local coord space. At the end of the block, `localOtherRect` is set to `mapped` so
        // that afterwards it is always defined in local space.
        Rect mapped = localToOther->inverseMapRect(localOtherRect);
        // If we don't have enough precision, the other shape might not map back to the geometry.
        // Allow up to 1/1000th of a pixel in tolerance when mapping between coordinate spaces,
        // otherwise we'll have to clip the shapes independently.
        const float otherTol =
                Shape::kDefaultPixelTolerance * otherToDevice.localAARadius(localOtherRect);
        if (localOtherRect.isEmptyNegativeOrNaN() ||
            !localToOther->mapRect(mapped).nearlyEquals(localOtherRect, otherTol)) {
            return false;
        }
        localOtherRect = mapped;
    }
    // Remember the edges that get clipped by the intersection
    SkEnumBitMask<EdgeAAQuad::Flags> clippedEdges = clipped_edges(shape->bounds(), localOtherRect);
    if (!shape->isFloodFill()) {
        // And now it's tight to the intersection with `shape`, sans any corner rounding
        localOtherRect.intersect(shape->bounds());
    }
    // Make sure that the intersected shape does not become subpixel in size, since drawing a
    // subpixel/hairline shape produces a different result than something that's clipped.
    float localAARadius = localToDevice.localAARadius(localOtherRect);
    if (!std::isfinite(localAARadius) || any(localOtherRect.size() <= localAARadius)) {
        return false;
    }

    SkRRect localOtherRRect;
    if (otherShape.isRect()) {
        if (shape->isRect() || shape->isFloodFill()) {
            SkASSERT(*edgeFlags == EdgeAAQuad::Flags::kAll || !shape->isFloodFill());
            // Assuming that non-AA edges seam with non-AA edges other quads to create a uniform
            // coverage field, we turn on the AA edge flag when coincident or clipped. This will
            // create a nice AA edge from this draw while the other non-AA quad is discarded.
            *edgeFlags |= clippedEdges; // This is a no-op if shape was a flood fill
            shape->setRect(localOtherRect);
            return true;
        } else {
            // Fall back to rrect+rrect intersection
            localOtherRRect = SkRRect::MakeRect(localOtherRect.asSkRect());
        }
    } else {
        SkASSERT(otherShape.isRRect());
        if (localToOther) {
            if (auto rr = otherShape.rrect().transform(localToOther->inverse().asM33())) {
                localOtherRRect = *rr;
            } else {
                // Transformation produced invalid geometry
                return false;
            }
        } else {
            localOtherRRect = otherShape.rrect();
        }

        if (shape->isRect() && *edgeFlags != EdgeAAQuad::Flags::kAll) {
            // When combining a mixed edge AA quad with a rounded rectangle, we require that all
            // non-AA edges be clipped out entirely.
            if ((clippedEdges | *edgeFlags) != EdgeAAQuad::Flags::kAll) {
                // The intersection shows AA'ed round corners and non-AA'ed edges, which can't be
                // represented by just Geometry or Shape.
                return false;
            }
        } else if (shape->isFloodFill()) {
            SkASSERT(*edgeFlags == EdgeAAQuad::Flags::kAll);
            shape->setRRect(localOtherRRect);
            return true;
        } // Else continue with rrect+rrect intersection
    }

    // `shape` can only be rect or rrect at this point, flood fill should already have returned.
    // If we've made it this far, we've also determined that the edge flags should be set to kAll
    // on a successful rrect+rrect intersection.
    SkASSERT(shape->isRect() || shape->isRRect());

    SkRRect localRRect = SkRRectPriv::ConservativeIntersect(
            localOtherRRect,
            shape->isRect() ? SkRRect::MakeRect(shape->rect().asSkRect()) : shape->rrect());
    if (localRRect.isRect()) {
        // Valid shape that can be simplified to rect
        shape->setRect(localRRect.rect());
        *edgeFlags = EdgeAAQuad::Flags::kAll;
        return true;
    } else if (!localRRect.isEmpty()) {
        // Intersection is representable as a rrect still
        shape->setRRect(localRRect);
        *edgeFlags = EdgeAAQuad::Flags::kAll;
        return true;
    } else {
        // Intersection is complex, leave edge flags unmodified
        return false;
    }
}

Rect snap_scissor(const Rect& a, const Rect& deviceBounds) {
    // Snapping to 4 pixel boundaries seems to give a good tradeoff between rasterizing slightly
    // more (but being clipped by the depth test), vs. setting a tight scissor that forces a state
    // change.
    // NOTE: This rounds out to the *next* multiple of 4, so that if the input rectangle happens to
    // land on a multiple of 4 we still create some padding to avoid scissoring just AA outsets.
    static constexpr int kRes = 4;
    Rect snapped = a.makeOutset(kRes - 1.f);
    snapped = Rect::FromVals(snapped.vals() * (1.f / kRes)).makeRoundOut();
    return Rect::FromVals(snapped.vals() * kRes).makeIntersect(deviceBounds);
}

} // anonymous namespace

///////////////////////////////////////////////////////////////////////////////
// ClipStack::TransformedShape

// A flyweight object describing geometry, subject to a local-to-device transform.
// This can be used by SaveRecords, Elements, and draws to determine how two shape operations
// interact with each other, without needing to share a base class, friend each other, or have a
// template for each combination of two types.
struct ClipStack::TransformedShape {
    const Transform& fLocalToDevice;
    const Shape&     fShape;
    const Rect&      fOuterBounds;
    const Rect&      fInnerBounds;

    SkClipOp         fOp;

    // contains() performs a fair amount of work to be as accurate as possible since it can mean
    // greatly simplifying the clip stack. However, in some contexts this isn't worth doing because
    // the actual shape is only an approximation (save records), or there's no current way to take
    // advantage of knowing this shape contains another (draws containing a clip hypothetically
    // could replace their geometry to draw the clip directly, but that isn't implemented now).
    bool fContainsChecksOnlyBounds = false;

    bool intersects(const TransformedShape&) const;
    bool contains(const TransformedShape&) const;
};

bool ClipStack::TransformedShape::intersects(const TransformedShape& o) const {
    if (!fOuterBounds.intersects(o.fOuterBounds)) {
        return false;
    }

    if (fLocalToDevice.type() <= Transform::Type::kRectStaysRect &&
        o.fLocalToDevice.type() <= Transform::Type::kRectStaysRect) {
        // The two shape's coordinate spaces are different but both rect-stays-rect or simpler.
        // This means, though, that their outer bounds approximations are tight to their transormed
        // shape bounds. There's no point to do further tests given that and that we already found
        // that these outer bounds *do* intersect.
        return true;
    } else if (fLocalToDevice == o.fLocalToDevice) {
        // Since the two shape's local coordinate spaces are the same, we can compare shape
        // bounds directly for a more accurate intersection test. We intentionally do not go
        // further and do shape-specific intersection tests since these could have unknown
        // complexity (for paths) and limited utility (e.g. two round rects that are disjoint
        // solely from their corner curves).
        return fShape.bounds().intersects(o.fShape.bounds());
    } else if (fLocalToDevice.type() != Transform::Type::kPerspective &&
               o.fLocalToDevice.type() != Transform::Type::kPerspective) {
        // The shapes don't share the same coordinate system, and their approximate 'outer'
        // bounds in device space could have substantial outsetting to contain the transformed
        // shape (e.g. 45 degree rotation). Perform a more detailed check on their oriented
        // bounding boxes.
        return oriented_bbox_intersection(fShape.bounds(), fLocalToDevice,
                                          o.fShape.bounds(), o.fLocalToDevice);
    }
    // Else multiple perspective transforms are involved, so assume intersection and allow the
    // rasterizer to handle perspective clipping.
    return true;
}

bool ClipStack::TransformedShape::contains(const TransformedShape& o) const {
    if (fInnerBounds.contains(o.fOuterBounds)) {
        return true;
    }
    // Skip more expensive contains() checks if configured not to, or if the extent of 'o' exceeds
    // this shape's outer bounds. When that happens there must be some part of 'o' that cannot be
    // contained in this shape.
    if (fContainsChecksOnlyBounds || !fOuterBounds.contains(o.fOuterBounds)) {
        return false;
    }

    if (fContainsChecksOnlyBounds) {
        return false; // don't do any more work
    }

    if (fLocalToDevice == o.fLocalToDevice) {
        // Test the shapes directly against each other, with a special check for a rrect+rrect
        // containment (a intersect b == a implies b contains a) and paths (same gen ID, or same
        // path for small paths means they contain each other).
        static constexpr int kMaxPathComparePoints = 16;
        if (fShape.isRRect() && o.fShape.isRRect()) {
            return SkRRectPriv::ConservativeIntersect(fShape.rrect(), o.fShape.rrect())
                    == o.fShape.rrect();
        } else if (fShape.isPath() && o.fShape.isPath()) {
            // TODO: Is this worth doing still if clips only cost as much as a single draw?
            return (fShape.path().getGenerationID() == o.fShape.path().getGenerationID()) ||
                    (fShape.path().countPoints() <= kMaxPathComparePoints &&
                    fShape.path() == o.fShape.path());
        } else {
            return fShape.conservativeContains(o.fShape.bounds());
        }
    } else if (fLocalToDevice.type() <= Transform::Type::kRectStaysRect &&
               o.fLocalToDevice.type() <= Transform::Type::kRectStaysRect) {
        // Optimize the common case where o's bounds can be mapped tightly into this coordinate
        // space and then tested against our shape.
        Rect localBounds = fLocalToDevice.inverseMapRect(
                o.fLocalToDevice.mapRect(o.fShape.bounds()));
        return fShape.conservativeContains(localBounds);
    } else if (fShape.convex()) {
        // Since this shape is convex, if all four corners of o's bounding box are inside it
        // then the entirety of o is also guaranteed to be inside it.
        SkV4 deviceQuad[4];
        o.fLocalToDevice.mapPoints(o.fShape.bounds(), deviceQuad);
        SkV4 localQuad[4];
        fLocalToDevice.inverseMapPoints(deviceQuad, localQuad, 4);
        for (int i = 0; i < 4; ++i) {
            // TODO: Would be nice to make this consistent with how the GPU clips NDC w.
            if (deviceQuad[i].w < SkPathPriv::kW0PlaneDistance ||
                localQuad[i].w < SkPathPriv::kW0PlaneDistance) {
                // Something in O actually projects behind the W = 0 plane and would be clipped
                // to infinity, so it's extremely unlikely that this contains O.
                return false;
            }
            if (!fShape.conservativeContains(skvx::float2::Load(localQuad + i) / localQuad[i].w)) {
                return false;
            }
        }
        return true;
    }

    // Else not an easily comparable pair of shapes so assume this doesn't contain O
    return false;
}

ClipStack::SimplifyResult ClipStack::Simplify(const TransformedShape& a,
                                              const TransformedShape& b) {
    enum class ClipCombo {
        kDD = 0b00,
        kDI = 0b01,
        kID = 0b10,
        kII = 0b11
    };

    switch(static_cast<ClipCombo>(((int) a.fOp << 1) | (int) b.fOp)) {
        case ClipCombo::kII:
            // Intersect (A) + Intersect (B)
            if (!a.intersects(b)) {
                // Regions with non-zero coverage are disjoint, so intersection = empty
                return SimplifyResult::kEmpty;
            } else if (b.contains(a)) {
                // B's full coverage region contains entirety of A, so intersection = A
                return SimplifyResult::kAOnly;
            } else if (a.contains(b)) {
                // A's full coverage region contains entirety of B, so intersection = B
                return SimplifyResult::kBOnly;
            } else {
                // The shapes intersect in some non-trivial manner
                return SimplifyResult::kBoth;
            }
        case ClipCombo::kID:
            // Intersect (A) + Difference (B)
            if (!a.intersects(b)) {
                // A only intersects B's full coverage region, so intersection = A
                return SimplifyResult::kAOnly;
            } else if (b.contains(a)) {
                // B's zero coverage region completely contains A, so intersection = empty
                return SimplifyResult::kEmpty;
            } else {
                // Intersection cannot be simplified. Note that the combination of a intersect
                // and difference op in this order cannot produce kBOnly
                return SimplifyResult::kBoth;
            }
        case ClipCombo::kDI:
            // Difference (A) + Intersect (B) - the mirror of Intersect(A) + Difference(B),
            // but combining is commutative so this is equivalent barring naming.
            if (!b.intersects(a)) {
                // B only intersects A's full coverage region, so intersection = B
                return SimplifyResult::kBOnly;
            } else if (a.contains(b)) {
                // A's zero coverage region completely contains B, so intersection = empty
                return SimplifyResult::kEmpty;
            } else {
                // Cannot be simplified
                return SimplifyResult::kBoth;
            }
        case ClipCombo::kDD:
            // Difference (A) + Difference (B)
            if (a.contains(b)) {
                // A's zero coverage region contains B, so B doesn't remove any extra
                // coverage from their intersection.
                return SimplifyResult::kAOnly;
            } else if (b.contains(a)) {
                // Mirror of the above case, intersection = B instead
                return SimplifyResult::kBOnly;
            } else {
                // Intersection of the two differences cannot be simplified. Note that for
                // this op combination it is not possible to produce kEmpty.
                return SimplifyResult::kBoth;
            }
    }
    SkUNREACHABLE;
}

ClipStack::DrawInfluence ClipStack::SimplifyForDraw(const TransformedShape& clip,
                                                    const TransformedShape& draw) {
    // Given the asserts below, we can just recast the SimplifyResult returned from
    // Simplify(A=clip, B=draw):
    //
    // If the result is kEmpty, the draw is clipped out.
    static_assert((int) SimplifyResult::kEmpty == (int) DrawInfluence::kClipsOutDraw);
    // If the result is kAOnly, only the clip's shape provides coverage and the draw could be
    // replaced with something that just covers the clip bounds.
    static_assert((int) SimplifyResult::kAOnly == (int) DrawInfluence::kReplacesDraw);
    // If the result is kBOnly, the clip's shape doesn't impact the draw's coverage at all.
    static_assert((int) SimplifyResult::kBOnly == (int) DrawInfluence::kNone);
    // If the result is kBoth, the clip and the draw combine in a complex manner
    static_assert((int) SimplifyResult::kBoth == (int) DrawInfluence::kComplexInteraction);

    SimplifyResult result = Simplify(clip, draw);
    return static_cast<DrawInfluence>(result);
}

///////////////////////////////////////////////////////////////////////////////
// ClipStack::Element

ClipStack::RawElement::RawElement(const Rect& deviceBounds,
                                  const Transform& localToDevice,
                                  const Shape& shape,
                                  SkClipOp op,
                                  PixelSnapping snapping)
        : Element{shape, localToDevice, op}
        , fUsageBounds{Rect::InfiniteInverted()}
        , fOrder(DrawOrder::kNoIntersection)
        , fMaxZ(DrawOrder::kClearDepth)
        , fInvalidatedByIndex(-1)
        , fCaptureParams(nullptr) {
    // Discard shapes that don't have any area (including when a transform can't be inverted, since
    // it means the two dimensions are collapsed to 0 or 1 dimension in device space).
    if (fShape.isLine() || !localToDevice.valid()) {
        fShape.reset();
    }
    // Make sure the shape is not inverted. An inverted shape is equivalent to a non-inverted shape
    // with the clip op toggled.
    if (fShape.inverted()) {
        fOp = (fOp == SkClipOp::kIntersect) ? SkClipOp::kDifference : SkClipOp::kIntersect;
    }

    fOuterBounds = fLocalToDevice.mapRect(fShape.bounds()).makeIntersect(deviceBounds);
    fInnerBounds = Rect::InfiniteInverted();

    // Apply rect-stays-rect transforms to rects and round rects to reduce the number of unique
    // local coordinate systems that are in play.
    if (!fOuterBounds.isEmptyNegativeOrNaN() &&
        fLocalToDevice.type() <= Transform::Type::kRectStaysRect) {
        if (fShape.isRect()) {
            // The actual geometry can be updated to the device-intersected bounds and we know the
            // inner bounds are equal to the outer.
            if (snapping == PixelSnapping::kYes) {
                fOuterBounds.round();
            }
            fShape.setRect(fOuterBounds);
            fLocalToDevice = Transform::Identity();
            fInnerBounds = fOuterBounds;
        } else if (fShape.isRRect()) {
            // Can't transform in place and must still check transform result since some very
            // ill-formed scale+translate matrices can cause invalid rrect radii.
            if (auto xformed = fShape.rrect().transform(fLocalToDevice)) {
                if (snapping == PixelSnapping::kYes) {
                    // The rounded corners will still be anti-aliased, but snap the horizontal and
                    // vertical edges to pixel values.
                    xformed->setRectRadii(SkRect::Make(xformed->rect().round()),
                                          xformed->radii().data());
                }
                fShape.setRRect(*xformed);
                fLocalToDevice = Transform::Identity();
                // Refresh outer bounds to match the transformed round rect in case
                // SkRRect::transform produces slightly different results from Transform::mapRect.
                fOuterBounds = fShape.bounds().makeIntersect(deviceBounds);
                fInnerBounds = Rect{SkRRectPriv::InnerBounds(*xformed)}.makeIntersect(fOuterBounds);
            }
        }
    }

    if (fOuterBounds.isEmptyNegativeOrNaN()) {
        // Either was already an empty shape or a non-empty shape is offscreen, so treat it as such.
        fShape.reset();
        fInnerBounds = Rect::InfiniteInverted();
    }

    // Now that fOp and fShape are canonical, set the shape's fill type to match how it needs to be
    // drawn as a depth-only shape everywhere that is clipped out (intersect is thus inverse-filled)
    fShape.setInverted(fOp == SkClipOp::kIntersect);

    // Post-conditions on inner and outer bounds
    SkASSERT(fShape.isEmpty() || deviceBounds.contains(fOuterBounds));
    this->validate();
}

ClipStack::RawElement::operator ClipStack::TransformedShape() const {
    return {fLocalToDevice, fShape, fOuterBounds, fInnerBounds, fOp};
}

void ClipStack::RawElement::drawClip(Device* device) {
    this->validate();

    // Skip elements that have not affected any draws
    if (!this->hasPendingDraw()) {
        SkASSERT(fUsageBounds.isEmptyNegativeOrNaN());
        // TODO (thomsmit): worth to set scissor to empty and check downstream? or better to allow
        // noop draw?
        return;
    }

    SkASSERT(!fUsageBounds.isEmptyNegativeOrNaN());
    // For clip draws, the usage bounds is the scissor.
    const Rect deviceBounds = Rect::WH(device->width(), device->height());
    Rect scissor = fUsageBounds; // all joined usage bounds are pre-snapped

    // snappedOuterBounds was the rectangle used in updateForDraw() to query the Z order the clip's
    // draw will be inserted at. The scissor must enforce that rendering doesn't happen outside of
    // those bounds.
    Rect snappedOuterBounds = snap_scissor(fOuterBounds, deviceBounds);
    scissor.intersect(snappedOuterBounds);
    // But if the overlap is sufficiently large, just rasterize out to the snapped bounds instead of
    // adding a tight scissor. A factor of 1/2 is used because that corresponds to the area
    // change caused by a 45-degree rotation.
    if (0.5f * snappedOuterBounds.area() < scissor.area()) {
        scissor = snappedOuterBounds;
    }

    Rect drawBounds = fOp == SkClipOp::kIntersect ? scissor : fOuterBounds.makeIntersect(scissor);
    if (!drawBounds.isEmptyNegativeOrNaN()) {
        // Although we are recording this clip draw after all the draws it affects, 'fOrder' was
        // determined at the first usage, so after sorting by DrawOrder the clip draw will be in the
        // right place. Unlike regular draws that use their own "Z", by writing (1 + max Z this clip
        // affects), it will cause those draws to fail either GREATER and GEQUAL depth tests where
        // they need to be clipped.
        DrawOrder order{fMaxZ.next(), fOrder};
        // An element's clip op is encoded in the shape's fill type. Inverse fills are intersect ops
        // and regular fills are difference ops. This means fShape is already in the right state to
        // draw directly.
        SkASSERT((fOp == SkClipOp::kDifference && !fShape.inverted()) ||
                 (fOp == SkClipOp::kIntersect && fShape.inverted()));

        // NOTE: We use fOuterBounds as the transformed shape bounds as that hasn't been clipped by
        // the scissor. It has been clipped by the device bounds, but that shouldn't impact any
        // decisions at this point. If that becomes not the case, we can either recompute the
        // shape's device-space bounds (fLocalToDevice.mapRect(fShape.bounds())) or store a fully
        // unclipped shape bounds on the RawElement.
        if (device->fRecorder->priv().caps()->useDrawListLayer()) {
            //TODO (thomsmit), rename this function to updateDeferredClip when drawListLayer is used
            fCaptureParams->fOrder = order;
            fCaptureParams->fDrawBounds = drawBounds;
            fCaptureParams->fScissor = scissor.asSkIRect();
            device->updateNextDepthForClipping(fCaptureParams->fOrder.depth());
        } else {
            device->drawClipShape(fLocalToDevice,
                                  fShape,
                                  Clip{drawBounds, fOuterBounds, scissor.asSkIRect(),
                                       /* nonMSAAClip= */ {}, /* shader= */ nullptr},
                                  order);
        }
    }

    // After the clip shape is drawn, reset its state. If the clip element is being popped off the
    // stack or overwritten because a new clip invalidated it, this won't matter. But if the clips
    // were drawn because the Device had to flush pending work while the clip stack was not empty,
    // subsequent draws will still need to be clipped to the elements. In this case, the usage
    // accumulation process will begin again and automatically use the Device's post-flush Z values
    // and BoundsManager state.
    fUsageBounds = Rect::InfiniteInverted();
    fOrder = DrawOrder::kNoIntersection;
    fMaxZ = DrawOrder::kClearDepth;
    fCaptureParams = nullptr;
    fInsertion = {nullptr, nullptr};
}

void ClipStack::RawElement::drawClipImmediate(Device* device, const Rect& snappedOuterBounds) {
    // We can't call validate but we need to make sure we have something to draw here.
    SkASSERT(!fShape.isEmpty());

    // We shouldn't be drawing if we already drew this clip element
    SkASSERT(!fInsertion);
    SkASSERT(!fCaptureParams);

    // Note, passing fOuterBounds here may influence the preference for wedges here.
    std::tie(fCaptureParams, fInsertion) =
            device->drawClipShapeImmediate(fLocalToDevice,
                                           fShape,
                                           Clip{snappedOuterBounds,
                                                snappedOuterBounds,
                                                snappedOuterBounds.asSkIRect(),
                                                /* nonMSAAClip= */ {},
                                                /* shader= */ nullptr},
                                           {fMaxZ, fOrder});

    SkASSERT(fInsertion);
    SkASSERT(fCaptureParams);
}

void ClipStack::RawElement::validate() const {
    // If the shape type isn't empty, the outer bounds shouldn't be empty; if the inner bounds are
    // not empty, they must be contained in outer.
    SkASSERT((fShape.isEmpty() || !fOuterBounds.isEmptyNegativeOrNaN()) &&
             (fInnerBounds.isEmptyNegativeOrNaN() || fOuterBounds.contains(fInnerBounds)));
    SkASSERT((fOp == SkClipOp::kDifference && !fShape.inverted()) ||
             (fOp == SkClipOp::kIntersect && fShape.inverted()));
    SkASSERT(!this->hasPendingDraw() || !fUsageBounds.isEmptyNegativeOrNaN());
}

void ClipStack::RawElement::markInvalid(const SaveRecord& current) {
    SkASSERT(!this->isInvalid());
    fInvalidatedByIndex = current.firstActiveElementIndex();
    // NOTE: We don't draw the accumulated clip usage when the element is marked invalid. Some
    // invalidated elements are part of earlier save records so can become re-active after a restore
    // in which case they should continue to accumulate. Invalidated elements that are part of the
    // active save record are removed at the end of the stack modification, which is when they are
    // explicitly drawn.
}

void ClipStack::RawElement::restoreValid(const SaveRecord& current) {
    if (current.firstActiveElementIndex() < fInvalidatedByIndex) {
        fInvalidatedByIndex = -1;
    }
}

bool ClipStack::RawElement::combine(const RawElement& other, const SaveRecord& current) {
    // Don't combine elements that have collected draw usage, since that changes their geometry.
    if (this->hasPendingDraw() || other.hasPendingDraw()) {
        return false;
    }
    // To reduce the number of possibilities, only consider intersect+intersect. Difference and
    // mixed op cases could be analyzed to simplify one of the shapes, but that is a rare
    // occurrence and the math is much more complicated.
    if (other.fOp != SkClipOp::kIntersect || fOp != SkClipOp::kIntersect) {
        return false;
    }

    // NOTE: intersect_shape operates on the underlying geometry and ignores the fill rule, which
    // because these are intersect clip ops, is the inverse fill. If the shape is updated, the
    // resulting geometry is set to a regular fill so it must be re-inverted to represent the
    // pixels rasterized for a depth-only clip draw.
    SkEnumBitMask<EdgeAAQuad::Flags> edgeFlags = EdgeAAQuad::Flags::kAll;
    const bool shapeUpdated = intersect_shape(other.fLocalToDevice, other.fShape,
                                              fLocalToDevice, &fShape, &edgeFlags);
    SkASSERT(edgeFlags == EdgeAAQuad::Flags::kAll);

    if (shapeUpdated) {
        // This logic works under the assumption that both combined elements were intersect.
        SkASSERT(fOp == SkClipOp::kIntersect && other.fOp == SkClipOp::kIntersect);
        fOuterBounds.intersect(other.fOuterBounds);
        fInnerBounds.intersect(other.fInnerBounds);
        // Inner bounds can become empty, but outer bounds should not be able to.
        SkASSERT(!fOuterBounds.isEmptyNegativeOrNaN());
        fShape.setInverted(true); // Undo intersect_shape setting it to non-inverse
        this->validate();
        return true;
    } else {
        return false;
    }
}

void ClipStack::RawElement::updateForElement(RawElement* added, const SaveRecord& current) {
    if (this->isInvalid()) {
        // Already doesn't do anything, so skip this element
        return;
    }

    // 'A' refers to this element, 'B' refers to 'added'.
    switch (Simplify(*this, *added)) {
        case SimplifyResult::kEmpty:
            // Mark both elements as invalid to signal that the clip is fully empty
            this->markInvalid(current);
            added->markInvalid(current);
            break;

        case SimplifyResult::kAOnly:
            // This element already clips more than 'added', so mark 'added' is invalid to skip it
            added->markInvalid(current);
            break;

        case SimplifyResult::kBOnly:
            // 'added' clips more than this element, so mark this as invalid
            this->markInvalid(current);
            break;

        case SimplifyResult::kBoth:
            // Else the bounds checks think we need to keep both, but depending on the combination
            // of the ops and shape kinds, we may be able to do better.
            if (added->combine(*this, current)) {
                // 'added' now fully represents the combination of the two elements
                this->markInvalid(current);
            }
            break;
    }
}

ClipStack::DrawInfluence ClipStack::RawElement::testForDraw(const TransformedShape& draw) const {
    if (this->isInvalid()) {
        // Cannot affect the draw
        return DrawInfluence::kNone;
    }

    return SimplifyForDraw(*this, draw);
}

std::pair<CompressedPaintersOrder, Insertion> ClipStack::RawElement::updateForDraw(
        Device* device,
        const BoundsManager* boundsManager,
        const Rect& deviceBounds,
        const Rect& snappedDrawBounds,
        PaintersDepth drawZ) {
    SkASSERT(!this->isInvalid());

    if (!this->hasPendingDraw()) {
        // No usage yet so we need an order that we will use when drawing to just the depth
        // attachment. It is sufficient to use the next CompressedPaintersOrder after the
        // most recent draw under this clip's outer bounds. It is necessary to use the
        // entire clip's outer bounds because the order has to be determined before the
        // final usage bounds are known and a subsequent draw could require a completely
        // different portion of the clip than this triggering draw.
        //
        // Lazily determining the order has several benefits to computing it when the clip
        // element was first created:
        //  - Elements that are invalidated by nested clips before draws are made do not
        //    waste time in the BoundsManager.
        //  - Elements that never actually modify a draw (e.g. a defensive clip) do not
        //    waste time in the BoundsManager.
        //  - A draw that triggers clip usage on multiple elements will more likely assign
        //    the same order to those elements, meaning their depth-only draws are more
        //    likely to batch in the final DrawPass.
        //
        // However, it does mean that clip elements can have the same order as each other,
        // or as later draws (e.g. after the clip has been popped off the stack). Any
        // overlap between clips or draws is addressed when the clip is drawn by selecting
        // an appropriate DisjointStencilIndex value. Stencil-aside, this order assignment
        // logic, max Z tracking, and the depth test during rasterization are able to
        // resolve everything correctly even if clips have the same order value.
        // See go/clip-stack-order for a detailed analysis of why this works.
        Rect snappedOuterBounds = snap_scissor(fOuterBounds, deviceBounds);
        fUsageBounds = snappedDrawBounds;
        fMaxZ = drawZ;

        if (device->fRecorder->priv().caps()->useDrawListLayer()) {
            this->drawClipImmediate(device, snappedOuterBounds);
            // Use this value to force hasPendingDraw() to return true.
            // TODO (thomsmit): Change this to a bool when drawListLayer is implemented.
            fOrder = DrawOrder::kNoIntersection.next();
        } else {
            fOrder = boundsManager->getMostRecentDraw(snappedOuterBounds).next();
        }
    } else {
        // Earlier draws have already used this element so we cannot change where the
        // depth-only draw will be sorted to, but we need to ensure we cover the new draw's
        // bounds and use a Z value that will clip out its pixels as appropriate.
        fUsageBounds.join(snappedDrawBounds);
        if (drawZ > fMaxZ) {
            fMaxZ = drawZ;
        }
    }

    return {fOrder, fInsertion};
}

ClipStack::ClipState ClipStack::RawElement::clipType() const {
    // Map from the internal shape kind to the clip state enum
    switch (fShape.type()) {
        case Shape::Type::kEmpty:
            return ClipState::kEmpty;

        case Shape::Type::kRect:
            return fOp == SkClipOp::kIntersect &&
                   fLocalToDevice.type() == Transform::Type::kIdentity
                        ? ClipState::kDeviceRect : ClipState::kComplex;

        case Shape::Type::kRRect:
            return fOp == SkClipOp::kIntersect &&
                   fLocalToDevice.type() == Transform::Type::kIdentity
                        ? ClipState::kDeviceRRect : ClipState::kComplex;

        case Shape::Type::kArc:
        case Shape::Type::kLine:
            // These types should never become RawElements, but call them kComplex in release builds
            SkASSERT(false);
            [[fallthrough]];

        case Shape::Type::kPath:
            return ClipState::kComplex;
    }
    SkUNREACHABLE;
}

///////////////////////////////////////////////////////////////////////////////
// ClipStack::SaveRecord

ClipStack::SaveRecord::SaveRecord(const Rect& deviceBounds)
        : fInnerBounds(deviceBounds)
        , fOuterBounds(deviceBounds)
        , fShader(nullptr)
        , fStartingElementIndex(0)
        , fOldestValidIndex(0)
        , fDeferredSaveCount(0)
        , fStackOp(SkClipOp::kIntersect)
        , fState(ClipState::kWideOpen)
        , fGenID(kInvalidGenID) {}

ClipStack::SaveRecord::SaveRecord(const SaveRecord& prior,
                                  int startingElementIndex)
        : fInnerBounds(prior.fInnerBounds)
        , fOuterBounds(prior.fOuterBounds)
        , fShader(prior.fShader)
        , fStartingElementIndex(startingElementIndex)
        , fOldestValidIndex(prior.fOldestValidIndex)
        , fDeferredSaveCount(0)
        , fStackOp(prior.fStackOp)
        , fState(prior.fState)
        , fGenID(kInvalidGenID) {
    // If the prior record added an element, this one will insert into the same index
    // (that's okay since we'll remove it when this record is popped off the stack).
    SkASSERT(startingElementIndex >= prior.fStartingElementIndex);
}

uint32_t ClipStack::SaveRecord::genID() const {
    if (fState == ClipState::kEmpty) {
        return kEmptyGenID;
    } else if (fState == ClipState::kWideOpen) {
        return kWideOpenGenID;
    } else {
        // The gen ID shouldn't be empty or wide open, since they are reserved for the above
        // if-cases. It may be kInvalid if the record hasn't had any elements added to it yet.
        SkASSERT(fGenID != kEmptyGenID && fGenID != kWideOpenGenID);
        return fGenID;
    }
}

ClipStack::ClipState ClipStack::SaveRecord::state() const {
    if (fShader && fState != ClipState::kEmpty) {
        return ClipState::kComplex;
    } else {
        return fState;
    }
}

ClipStack::DrawInfluence ClipStack::SaveRecord::testForDraw(const TransformedShape& draw) const {
    Transform identity = Transform::Identity();
    Shape outerSaveBounds{fOuterBounds};
    TransformedShape save{identity, outerSaveBounds, fOuterBounds, fInnerBounds, fStackOp,
                          /*containsChecksOnlyBounds=*/true};

    return SimplifyForDraw(save, draw);
}

void ClipStack::SaveRecord::removeElements(RawElement::Stack* elements, Device* device) {
    while (elements->count() > fStartingElementIndex) {
        // Since the element is being deleted now, it won't be in the ClipStack when the Device
        // calls recordDeferredClipDraws(). Record the clip's draw now (if it needs it).
        elements->back().drawClip(device);
        elements->pop_back();
    }
}

void ClipStack::SaveRecord::restoreElements(RawElement::Stack* elements) {
    // Presumably this SaveRecord is the new top of the stack, and so it owns the elements
    // from its starting index to restoreCount - 1. Elements from the old save record have
    // been destroyed already, so their indices would have been >= restoreCount, and any
    // still-present element can be un-invalidated based on that.
    int i = elements->count() - 1;
    for (RawElement& e : elements->ritems()) {
        if (i < fOldestValidIndex) {
            break;
        }
        e.restoreValid(*this);
        --i;
    }
}

void ClipStack::SaveRecord::addShader(sk_sp<SkShader> shader) {
    SkASSERT(shader);
    SkASSERT(this->canBeUpdated());
    if (!fShader) {
        fShader = std::move(shader);
    } else {
        // The total coverage is computed by multiplying the coverage from each element (shape or
        // shader), but since multiplication is associative, we can use kSrcIn blending to make
        // a new shader that represents 'shader' * 'fShader'
        fShader = SkShaders::Blend(SkBlendMode::kSrcIn, std::move(shader), fShader);
    }
}

bool ClipStack::SaveRecord::addElement(RawElement&& toAdd,
                                       RawElement::Stack* elements,
                                       Device* device) {
    // Validity check the element's state first
    toAdd.validate();

    // And we shouldn't be adding an element if we have a deferred save
    SkASSERT(this->canBeUpdated());

    if (fState == ClipState::kEmpty) {
        // The clip is already empty, and we only shrink, so there's no need to record this element.
        return false;
    } else if (toAdd.shape().isEmpty()) {
        // An empty difference op should have been detected earlier, since it's a no-op
        SkASSERT(toAdd.op() == SkClipOp::kIntersect);
        fState = ClipState::kEmpty;
        this->removeElements(elements, device);
        return true;
    }

    // Here we treat the SaveRecord as a "TransformedShape" with the identity transform, and a shape
    // equal to its outer bounds. This lets us get accurate intersection tests against the new
    // element, but we pass true to skip more detailed contains checks because the SaveRecord's
    // shape is potentially very different from its aggregate outer bounds.
    Shape outerSaveBounds{fOuterBounds};
    Transform identity = Transform::Identity();
    TransformedShape save{identity, outerSaveBounds, fOuterBounds, fInnerBounds, fStackOp,
                          /*containsChecksOnlyBounds=*/true};

    // In this invocation, 'A' refers to the existing stack's bounds and 'B' refers to the new
    // element.
    switch (Simplify(save, toAdd)) {
        case SimplifyResult::kEmpty:
            // The combination results in an empty clip
            fState = ClipState::kEmpty;
            this->removeElements(elements, device);
            return true;

        case SimplifyResult::kAOnly:
            // The combination would not be any different than the existing clip
            return false;

        case SimplifyResult::kBOnly:
            // The combination would invalidate the entire existing stack and can be replaced with
            // just the new element.
            this->replaceWithElement(std::move(toAdd), elements, device);
            return true;

        case SimplifyResult::kBoth:
            // The new element combines in a complex manner, so update the stack's bounds based on
            // the combination of its and the new element's ops (handled below)
            break;
    }

    if (fState == ClipState::kWideOpen) {
        // When the stack was wide open and the clip effect was kBoth, the "complex" manner is
        // simply to keep the element and update the stack bounds to be the element's intersected
        // with the device.
        this->replaceWithElement(std::move(toAdd), elements, device);
        return true;
    }

    // Some form of actual clip element(s) to combine with.
    if (fStackOp == SkClipOp::kIntersect) {
        if (toAdd.op() == SkClipOp::kIntersect) {
            // Intersect (stack) + Intersect (toAdd)
            //  - Bounds updates is simply the paired intersections of outer and inner.
            fOuterBounds.intersect(toAdd.outerBounds());
            fInnerBounds.intersect(toAdd.innerBounds());
            // Outer should not have become empty, but is allowed to if there's no intersection.
            SkASSERT(!fOuterBounds.isEmptyNegativeOrNaN());
        } else {
            // Intersect (stack) + Difference (toAdd)
            //  - Shrink the stack's outer bounds if the difference op's inner bounds completely
            //    cuts off an edge.
            //  - Shrink the stack's inner bounds to completely exclude the op's outer bounds.
            fOuterBounds = subtract(fOuterBounds, toAdd.innerBounds(), /* exact */ true);
            fInnerBounds = subtract(fInnerBounds, toAdd.outerBounds(), /* exact */ false);
        }
    } else {
        if (toAdd.op() == SkClipOp::kIntersect) {
            // Difference (stack) + Intersect (toAdd)
            //  - Bounds updates are just the mirror of Intersect(stack) + Difference(toAdd)
            Rect oldOuter = fOuterBounds;
            fOuterBounds = subtract(toAdd.outerBounds(), fInnerBounds, /* exact */ true);
            fInnerBounds = subtract(toAdd.innerBounds(), oldOuter,     /* exact */ false);
        } else {
            // Difference (stack) + Difference (toAdd)
            //  - The updated outer bounds is the union of outer bounds and the inner becomes the
            //    largest of the two possible inner bounds
            fOuterBounds.join(toAdd.outerBounds());
            if (toAdd.innerBounds().area() > fInnerBounds.area()) {
                fInnerBounds = toAdd.innerBounds();
            }
        }
    }

    // If we get here, we're keeping the new element and the stack's bounds have been updated.
    // We ought to have caught the cases where the stack bounds resemble an empty or wide open
    // clip, so assert that's the case.
    SkASSERT(!fOuterBounds.isEmptyNegativeOrNaN() &&
             (fInnerBounds.isEmptyNegativeOrNaN() || fOuterBounds.contains(fInnerBounds)));

    return this->appendElement(std::move(toAdd), elements, device);
}

bool ClipStack::SaveRecord::appendElement(RawElement&& toAdd,
                                          RawElement::Stack* elements,
                                          Device* device) {
    // Update past elements to account for the new element
    int i = elements->count() - 1;

    // After the loop, elements between [max(youngestValid, startingIndex)+1, count-1] can be
    // removed from the stack (these are the active elements that have been invalidated by the
    // newest element; since it's the active part of the stack, no restore() can bring them back).
    int youngestValid = fStartingElementIndex - 1;
    // After the loop, elements between [0, oldestValid-1] are all invalid. The value of oldestValid
    // becomes the save record's new fLastValidIndex value.
    int oldestValid = elements->count();
    // After the loop, this is the earliest active element that was invalidated. It may be
    // older in the stack than earliestValid, so cannot be popped off, but can be used to store
    // the new element instead of allocating more.
    RawElement* oldestActiveInvalid = nullptr;
    int oldestActiveInvalidIndex = elements->count();

    for (RawElement& existing : elements->ritems()) {
        if (i < fOldestValidIndex) {
            break;
        }
        // We don't need to pass the actual index that toAdd will be saved to; just the minimum
        // index of this save record, since that will result in the same restoration behavior later.
        existing.updateForElement(&toAdd, *this);

        if (toAdd.isInvalid()) {
            if (existing.isInvalid()) {
                // Both new and old invalid implies the entire clip becomes empty
                fState = ClipState::kEmpty;
                return true;
            } else {
                // The new element doesn't change the clip beyond what the old element already does
                return false;
            }
        } else if (existing.isInvalid()) {
            // The new element cancels out the old element. The new element may have been modified
            // to account for the old element's geometry.
            if (i >= fStartingElementIndex) {
                // Still active, so the invalidated index could be used to store the new element
                oldestActiveInvalid = &existing;
                oldestActiveInvalidIndex = i;
            }
        } else {
            // Keep both new and old elements
            oldestValid = i;
            if (i > youngestValid) {
                youngestValid = i;
            }
        }

        --i;
    }

    // Post-iteration validity check
    SkASSERT(oldestValid == elements->count() ||
             (oldestValid >= fOldestValidIndex && oldestValid < elements->count()));
    SkASSERT(youngestValid == fStartingElementIndex - 1 ||
             (youngestValid >= fStartingElementIndex && youngestValid < elements->count()));
    SkASSERT((oldestActiveInvalid && oldestActiveInvalidIndex >= fStartingElementIndex &&
              oldestActiveInvalidIndex < elements->count()) || !oldestActiveInvalid);

    // Update final state
    SkASSERT(oldestValid >= fOldestValidIndex);
    fOldestValidIndex = std::min(oldestValid, oldestActiveInvalidIndex);
    fState = oldestValid == elements->count() ? toAdd.clipType() : ClipState::kComplex;
    if (fStackOp == SkClipOp::kDifference && toAdd.op() == SkClipOp::kIntersect) {
        // The stack remains in difference mode only as long as all elements are difference
        fStackOp = SkClipOp::kIntersect;
    }

    int targetCount = youngestValid + 1;
    if (!oldestActiveInvalid || oldestActiveInvalidIndex >= targetCount) {
        // toAdd will be stored right after youngestValid
        targetCount++;
        oldestActiveInvalid = nullptr;
    }
    while (elements->count() > targetCount) {
        SkASSERT(oldestActiveInvalid != &elements->back()); // shouldn't delete what we'll reuse
        elements->back().drawClip(device);
        elements->pop_back();
    }
    if (oldestActiveInvalid) {
        oldestActiveInvalid->drawClip(device);
        *oldestActiveInvalid = std::move(toAdd);
    } else if (elements->count() < targetCount) {
        elements->push_back(std::move(toAdd));
    } else {
        elements->back().drawClip(device);
        elements->back() = std::move(toAdd);
    }

    // Changing this will prompt ClipStack to invalidate any masks associated with this record.
    fGenID = next_gen_id();
    return true;
}

void ClipStack::SaveRecord::replaceWithElement(RawElement&& toAdd,
                                               RawElement::Stack* elements,
                                               Device* device) {
    // The aggregate state of the save record mirrors the element
    fInnerBounds = toAdd.innerBounds();
    fOuterBounds = toAdd.outerBounds();
    fStackOp = toAdd.op();
    fState = toAdd.clipType();

    // All prior active element can be removed from the stack: [startingIndex, count - 1]
    int targetCount = fStartingElementIndex + 1;
    while (elements->count() > targetCount) {
        elements->back().drawClip(device);
        elements->pop_back();
    }
    if (elements->count() < targetCount) {
        elements->push_back(std::move(toAdd));
    } else {
        elements->back().drawClip(device);
        elements->back() = std::move(toAdd);
    }

    SkASSERT(elements->count() == fStartingElementIndex + 1);

    // This invalidates all older elements that are owned by save records lower in the clip stack.
    fOldestValidIndex = fStartingElementIndex;
    fGenID = next_gen_id();
}

///////////////////////////////////////////////////////////////////////////////
// ClipStack::DrawShape

/**
 * DrawShape represents the approximate shape that is being drawn in order to compare it against
 * the clip stack's RawElements. It is able to map to a `TransformedShape` to be simplified with
 * either the SaveRecord or each element. For non-Shape geometries and stroked shapes, it
 * represents the oriented bounding box. For filled Shapes, it preserves the original shape for
 * more accurate contains/intersect checks and geometrically combining RawElements into the
 * shape.
 */
class ClipStack::DrawShape {
public:
    DrawShape(const Transform& localToDevice, const Geometry& geometry)
            : fLocalToDevice(geometry.maskToDevice() ? *geometry.maskToDevice() : localToDevice)
            , fEdgeFlags(EdgeAAQuad::Flags::kAll)
            , fScissor(Rect::Infinite())
            , fShapeWasModified(false) {
        if (geometry.isShape()) {
            fShape = geometry.shape();
            fShapeMatchesGeometry = true;
            SkASSERT(!geometry.maskToDevice()); // should be local
        } else {
            // The geometry is something special like text or vertices, in which case it's
            // definitely not a shape that could simplify cleanly with the clip stack, so just track
            // its bounds. The exception is EdgeAA quads that are rectangular, in which case we can
            // clip its edges and adjust edge flags.
            fShape.setRect(geometry.bounds());
            if (geometry.isEdgeAAQuad()) {
                fEdgeFlags = geometry.edgeAAQuad().edgeFlags();
                fShapeMatchesGeometry = geometry.edgeAAQuad().isRect();
                SkASSERT(!geometry.maskToDevice()); // should be local
            } else {
                fShapeMatchesGeometry = false;
            }
            // If geometry is not a shape, it is not inverted.
            SkASSERT(!fShape.inverted());
        }

        fShapeCompatibleWithIntersectShape = fShape.isFloodFill() ||
                                            (!fShape.inverted() && (fShape.isRect() ||
                                                                    fShape.isRRect()));
    }

    operator TransformedShape() const {
        // A regular draw is a transformed shape that "intersects" the clip. An inverse-filled draw
        // is equivalent to "difference". For simple convex shapes we provide an inner bounds
        // because we can geometrically intersect clip elements with the draw geometry and not
        // really impact the choice of Renderer (given the family of renderers used for simple
        // shapes). In theory any convex shape could provide an inner bounds and/or use the detailed
        // contains check, but that would cause path rendering draws to potentially change in hard
        // to predict ways.
        SkClipOp op = fShape.inverted() ? SkClipOp::kDifference : SkClipOp::kIntersect;
        return TransformedShape{fLocalToDevice, fShape, fOuterBounds, fInnerBounds, op,
                                /*containsChecksOnlyBounds=*/!this->shapeCanBeModified()};
    }

    bool shapeCanBeModified() const {
        return fShapeCompatibleWithIntersectShape && fShapeMatchesGeometry;
    }

    bool applyStyle(const SkStrokeRec& style, const Rect& deviceBounds);
    void applyScissor(const Rect& scissor);

    void resetToFloodFill();
    bool intersectClipElement(const RawElement& clip);

    // Sync any modifications back to `geometry` and return a Clip object encapsulating the
    // tracked bounds of the now-clipped draw.
    Clip toClip(Geometry* geometry, const NonMSAAClip& analyticClip, const SkShader* clipShader);

private:
    Transform fLocalToDevice;

    // When 'style' isn't fill, the original geometry describes the pre-stroked shape, so 'fShape'
    // is updated to include the bounds post-stroking. `fShape` may also include local AA outsets
    // under certain circumstances:
    //  1. If it's a hairline, the AA outset can be added in local space to preserve a tighter
    //     oriented bbox compared to device bounds outset by 1px.
    //  2. If it's subpixel, the rendered geometry is often treated as a hairline with an adjusted
    //     coverage ramp.
    // Notably, the local AA outset is not included in `styledShape` for other cases to maximize the
    // cases where a draw is contained in a clip, or can be clipped geometrically. This assumes that
    // rendering an AA'ed non-hairline/subpixel edge produces a 1px feathered edge that's not
    // qualitatively different from the 1px feathered edge a clip would enforce.
    Shape fShape;
    SkEnumBitMask<EdgeAAQuad::Flags> fEdgeFlags;

    // Not valid until after applyStyle() is called, although applyScissor() can shrink the inner
    // and outer bounds.
    Rect fTransformedShapeBounds;
    Rect fOuterBounds;
    Rect fInnerBounds;

    Rect fScissor;

    // Whether or not the shape matches the original geometry to draw (with style)
    bool fShapeMatchesGeometry;
    // Whether or not the clip stack can modify this shape in place (and if it has already done so).
    bool fShapeCompatibleWithIntersectShape;
    bool fShapeWasModified;
};

bool ClipStack::DrawShape::applyStyle(const SkStrokeRec& style, const Rect& deviceBounds) {
    fTransformedShapeBounds = fShape.bounds(); // not scissor'ed, regular fill rule bounds
    auto origSize = fTransformedShapeBounds.size();
    if (!SkIsFinite(origSize.x(), origSize.y())) {
        // Discard all non-finite geometry as if it were clipped out
        return false;
    }

    // Discard fills and strokes that cannot produce any coverage: an empty fill, or a
    // zero-length stroke that has butt caps. Otherwise the stroke style applies to a vertical
    // or horizontal line (making it non-empty), or it's a zero-length path segment that
    // must produce round or square caps (making it non-empty):
    //     https://www.w3.org/TR/SVG11/implnote.html#PathElementImplementationNotes
    if (!fShape.inverted() && (fShape.isLine() || any(origSize == 0.f))) {
        if (style.isFillStyle() || (style.getCap() == SkPaint::kButt_Cap && all(origSize == 0.f))) {
            return false;
        }
    }

    // Anti-aliasing makes shapes larger than their original coordinates, but we only care about
    // that for local clip checks in certain cases (see below).
    // NOTE: After this if-else block, `transformedShapeBounds` will be in device space.
    float localAAOutset = fLocalToDevice.localAARadius(fTransformedShapeBounds);
    if (!SkIsFinite(localAAOutset)) SK_UNLIKELY {
        // We cannot calculate an accurate local shape bounds, and transformedShapeBounds is meant
        // to be unclipped. This is to maximize atlas reuse for mostly unclipped draws and to detect
        // when a scissor state change is required. Setting transformedShapeBounds to deviceBounds
        // is harmless in this case as these benefits are unlikely to apply for this transform.
        fTransformedShapeBounds = deviceBounds;
        fShape.setRect(deviceBounds);
        fLocalToDevice = Transform::Identity();
        fShapeMatchesGeometry = false;
    } else {
        // SkStrokeRec::GetInflationRadius() returns a device-space inflation for hairlines.
        float localOutset = 0.f;
        if (!style.isFillStyle() && !style.isHairlineStyle()) {
            // Rectangles, rounded rectangles, and lines do not produce miters so don't count the
            // pessimistic limit against their draw bounds.
            const float effectiveMiterLimit = fShape.isPath() ? style.getMiter() : 1.f;
            // Rectangles and rounded rectangles don't have caps, so don't count that against their
            // draw bounds (if we could efficiently know a path was a closed contour, it could
            // be included here too).
            const SkPaint::Cap effectiveCap = fShape.isRect() || fShape.isRRect()
                    ? SkPaint::kButt_Cap : style.getCap();
            localOutset = SkStrokeRec::GetInflationRadius(style.getJoin(),
                                                          effectiveMiterLimit,
                                                          effectiveCap,
                                                          style.getWidth());
        }

        if (style.isHairlineStyle() ||
            (!style.isFillStyle() && style.getWidth() < localAAOutset) ||
            (style.isFillStyle() && !fShape.inverted() && any(origSize < localAAOutset))) {
            // The geometry is a hairline or projects to a subpixel shape, so rendering will not
            // follow the typical 1/2px outset anti-aliasing that is compatible with clipping.
            // In this case, apply the local AA radius to the shape to have a conservative clip
            // query while preserving the oriented bounding box.
            localOutset += localAAOutset;
        }

        if (localOutset > 0.f) {
            // Propagate style and AA outset into styledShape so clip queries reflect style.
            fTransformedShapeBounds.outset(localOutset);

            bool inverted = fShape.inverted();
            if (fShape.isRRect()) {
                // Try to preserve the rounded corners, which can reduce the chance of clipping
                // stroked rounded rects that are clipped to a round rect matching their outer edge.
                fShape.rrect().outset(localOutset, localOutset, &fShape.rrect());
            } else
            {
                fShape.setRect(fTransformedShapeBounds); // it's still local at this point
            }
            fShape.setInverted(inverted);  // preserve original inversion state
            fShapeMatchesGeometry = false;
        }

        fTransformedShapeBounds = fLocalToDevice.mapRect(fTransformedShapeBounds);
    }

    fOuterBounds = fTransformedShapeBounds;
    fInnerBounds = Rect::InfiniteInverted();

    if (this->shapeCanBeModified() && fLocalToDevice.type() <= Transform::Type::kRectStaysRect) {
        if (fShape.isRect()) {
            fInnerBounds = fOuterBounds;
        } else if (fShape.isRRect()) {
            SkRect rrectInnerBounds = SkRRectPriv::InnerBounds(fShape.rrect());
            if (!rrectInnerBounds.isEmpty()) {
                fInnerBounds = fLocalToDevice.mapRect(rrectInnerBounds);
            }
        }
        // Otherwise it's a flood fill, but should have empty bounds anyways
    }
    // Otherwise we either don't need the inner bounds, or the inner bounds can't be computed
    // for a non-axis-aligned transform

     return true; // Something can be drawn based on style (might still be clipped out)
}

void ClipStack::DrawShape::applyScissor(const Rect& scissor) {
    // Apply the scissor to the outer bounds because it restricts rasterization and will allow
    // the SaveRecord::testForDraw() case to detect no clip influence if only the scissor is
    // needed.
    SkASSERT(scissor == Rect(scissor.asSkIRect())); // `scissor` must be integer valued
    fScissor.intersect(scissor); // For first call, fScissor is infinite so this is assignment
    fOuterBounds.intersect(scissor);
    fInnerBounds.intersect(scissor);
}

Clip ClipStack::DrawShape::toClip(Geometry* geometry,
                                  const NonMSAAClip& analyticClip,
                                  const SkShader* clipShader) {
    if (fShapeWasModified) {
        // Sync back to the geometry that will be drawn
        SkASSERT(this->shapeCanBeModified());
        if (geometry->isEdgeAAQuad() && fShape.isRect()) {
            // Preserve the EdgeAAQuad geometry type and sync updated edge flags
            SkASSERT(geometry->edgeAAQuad().isRect());
            geometry->setEdgeAAQuad(EdgeAAQuad(fShape.rect(), fEdgeFlags));
        } else {
            SkASSERT(fEdgeFlags == EdgeAAQuad::Flags::kAll);
            geometry->setShape(fShape);
        }
        // Reconstruct new transformedShapeBounds and outer bounds
        fTransformedShapeBounds = fLocalToDevice.mapRect(fShape.bounds());
        fOuterBounds = fTransformedShapeBounds.makeIntersect(fScissor);
    }

    Rect drawBounds = fShape.inverted() ? fScissor : fOuterBounds;
    // If the draw isn't clipped out (empty drawBounds), it should be in the scissor rect
    SkASSERT(drawBounds.isEmptyNegativeOrNaN() || fScissor.contains(drawBounds));
    // If the scissor is empty, the draw bounds must also be empty
    SkASSERT(!fScissor.isEmptyNegativeOrNaN() || drawBounds.isEmptyNegativeOrNaN());
    // fScissor.asSkIRect() must be equivalent
    SkASSERT(fScissor == Rect(fScissor.asSkIRect()));
    return Clip(drawBounds, fTransformedShapeBounds,
                fScissor.asSkIRect(), analyticClip, clipShader);
}

void ClipStack::DrawShape::resetToFloodFill() {
    if (this->shapeCanBeModified() && !fShape.isFloodFill()) {
        fShape.reset();
        fShape.setInverted(true);
        fEdgeFlags = EdgeAAQuad::Flags::kAll;
        fOuterBounds = fInnerBounds = Rect::InfiniteInverted();
        fShapeWasModified = true;
    }
}

bool ClipStack::DrawShape::intersectClipElement(const RawElement& clip) {
    SkASSERT(clip.op() == SkClipOp::kIntersect);
    if (this->shapeCanBeModified() &&
        intersect_shape(clip.localToDevice(), clip.shape(),
                        fLocalToDevice, &fShape, &fEdgeFlags)) {
        SkASSERT(!fShape.inverted());
        if (fOuterBounds.isEmptyNegativeOrNaN()) {
            // Changing from a flood fill to the clip's shape
            fOuterBounds = clip.outerBounds();
            fInnerBounds = clip.innerBounds();
        } else {
            // Restricting the shape's geometry by the clip
            fOuterBounds.intersect(clip.outerBounds());
            fInnerBounds.intersect(clip.innerBounds());
            SkASSERT(!fOuterBounds.isEmptyNegativeOrNaN()); // Should have been caught earlier
        }

        fShapeWasModified = true;
        return true;
    }

    return false;
}

///////////////////////////////////////////////////////////////////////////////
// ClipStack

// NOTE: Based on draw calls in all GMs, SKPs, and SVGs as of 08/20, 98% use a clip stack with
// one Element and up to two SaveRecords, thus the inline size for RawElement::Stack and
// SaveRecord::Stack (this conveniently keeps the size of ClipStack manageable). The max
// encountered element stack depth was 5 and the max save depth was 6. Using an increment of 8 for
// these stacks means that clip management will incur a single allocation for the remaining 2%
// of the draws, with extra head room for more complex clips encountered in the wild.
static constexpr int kElementStackIncrement = 8;
static constexpr int kSaveStackIncrement = 8;

ClipStack::ClipStack(Device* owningDevice)
        : fElements(kElementStackIncrement)
        , fSaves(kSaveStackIncrement)
        , fDevice(owningDevice) {
    // Start with a save record that is wide open
    fSaves.emplace_back(this->deviceBounds());
}

ClipStack::~ClipStack() = default;

void ClipStack::save() {
    SkASSERT(!fSaves.empty());
    fSaves.back().pushSave();
}

void ClipStack::restore() {
    SkASSERT(!fSaves.empty());
    SaveRecord& current = fSaves.back();
    if (current.popSave()) {
        // This was just a deferred save being undone, so the record doesn't need to be removed yet
        return;
    }

    // When we remove a save record, we delete all elements >= its starting index and any masks
    // that were rasterized for it.
    current.removeElements(&fElements, fDevice);

    fSaves.pop_back();
    // Restore any remaining elements that were only invalidated by the now-removed save record.
    fSaves.back().restoreElements(&fElements);
}

Rect ClipStack::deviceBounds() const {
    return Rect::WH(fDevice->width(), fDevice->height());
}

Rect ClipStack::conservativeBounds() const {
    const SaveRecord& current = this->currentSaveRecord();
    if (current.state() == ClipState::kEmpty) {
        return Rect::InfiniteInverted();
    } else if (current.state() == ClipState::kWideOpen) {
        return this->deviceBounds();
    } else {
        if (current.op() == SkClipOp::kDifference) {
            // The outer/inner bounds represent what's cut out, so full bounds remains the device
            // bounds, minus any fully clipped content that spans the device edge.
            return subtract(this->deviceBounds(), current.innerBounds(), /* exact */ true);
        } else {
            SkASSERT(this->deviceBounds().contains(current.outerBounds()));
            return current.outerBounds();
        }
    }
}

ClipStack::SaveRecord& ClipStack::writableSaveRecord(bool* wasDeferred) {
    SaveRecord& current = fSaves.back();
    if (current.canBeUpdated()) {
        // Current record is still open, so it can be modified directly
        *wasDeferred = false;
        return current;
    } else {
        // Must undefer the save to get a new record.
        SkAssertResult(current.popSave());
        *wasDeferred = true;
        return fSaves.emplace_back(current, fElements.count());
    }
}

void ClipStack::clipShader(sk_sp<SkShader> shader) {
    // Shaders can't bring additional coverage
    if (this->currentSaveRecord().state() == ClipState::kEmpty) {
        return;
    }

    bool wasDeferred;
    this->writableSaveRecord(&wasDeferred).addShader(std::move(shader));
    // Geometry elements are not invalidated by updating the clip shader
    // TODO(b/238763003): Integrating clipShader into graphite needs more thought, particularly how
    // to handle the shader explosion and where to put the effects in the GraphicsPipelineDesc.
    // One idea is to use sample locations and draw the clipShader into the depth buffer.
    // Another is resolve the clip shader into an alpha mask image that is sampled by the draw.
}

void ClipStack::clipShape(const Transform& localToDevice,
                          const Shape& shape,
                          SkClipOp op,
                          PixelSnapping snapping) {
    if (this->currentSaveRecord().state() == ClipState::kEmpty) {
        return;
    }

    // This will apply the transform if it's shape-type preserving, and clip the element's bounds
    // to the device bounds (NOT the conservative clip bounds, since those are based on the net
    // effect of all elements while device bounds clipping happens implicitly. During addElement,
    // we may still be able to invalidate some older elements).
    // NOTE: Does not try to simplify the shape type by inspecting the SkPath.
    RawElement element{this->deviceBounds(), localToDevice, shape, op, snapping};

    // An empty op means do nothing (for difference), or close the save record, so we try and detect
    // that early before doing additional unnecessary save record allocation.
    if (element.shape().isEmpty()) {
        if (element.op() == SkClipOp::kDifference) {
            // If the shape is empty and we're subtracting, this has no effect on the clip
            return;
        }
        // else we will make the clip empty, but we need a new save record to record that change
        // in the clip state; fall through to below and updateForElement() will handle it.
    }

    bool wasDeferred;
    SaveRecord& save = this->writableSaveRecord(&wasDeferred);
    SkDEBUGCODE(int elementCount = fElements.count();)
    if (!save.addElement(std::move(element), &fElements, fDevice)) {
        if (wasDeferred) {
            // We made a new save record, but ended up not adding an element to the stack.
            // So instead of keeping an empty save record around, pop it off and restore the counter
            SkASSERT(elementCount == fElements.count());
            fSaves.pop_back();
            fSaves.back().pushSave();
        }
    }
}

// Decide whether we can use this shape to do analytic clipping. Only rects and certain
// rrects are supported. We assume these have been pre-transformed by the RawElement
// constructor, so only identity transforms are allowed.
namespace {

#if defined(SK_GRAPHITE_USE_LEGACY_RRECT_CLIP_SHADER)

AnalyticClip can_apply_analytic_clip(const Shape& shape, const Transform& localToDevice) {
    if (localToDevice.type() != Transform::Type::kIdentity) {
        return {};
    }

    // The circular rrect clip only handles rrect radii >= kRadiusMin, circular radii less than
    // this are coerced to be rectangular.
    static constexpr float kRadiusMin = SK_ScalarHalf;

    // Can handle Rect directly.
    if (shape.isRect()) {
        return {shape.rect(), kRadiusMin, AnalyticClip::kNone_EdgeFlag, shape.inverted()};
    }

    // Otherwise we only handle certain kinds of RRects, specifically only approximately simple
    // circular rrects (e.g. all 4 corners can be described by a single radius value).
    if (!shape.isRRect()) {
        return {};
    }

    const SkRRect& rrect = shape.rrect();
    if (rrect.isOval() || rrect.isSimple()) {
        SkVector radii = SkRRectPriv::GetSimpleRadii(rrect);
        if (radii.fX < kRadiusMin || radii.fY < kRadiusMin) {
            // In this case the corners are extremely close to rectangular and we collapse the
            // clip to a rectangular clip.
            return {rrect.rect(), kRadiusMin, AnalyticClip::kNone_EdgeFlag, shape.inverted()};
        }
        if (SkRRectPriv::IsRelativelyCircular(radii.fX, radii.fY, Shape::kDefaultPixelTolerance)) {
            return {rrect.rect(), radii.fX, AnalyticClip::kAll_EdgeFlag, shape.inverted()};
        } else {
            return {};
        }
    }

    // If rrect is not an oval or simple, it's either empty, rect, 9-patch, or complex. However,
    // empty should have been handled by the clip stack, and rect ought to have been simplified
    // into an explicit Rect shape (already handled above). That leaves 9-patch and complex,
    // so we check for the "tab" cases - two adjacent circular corners and two square corners.
    // It just so happens that if a rect RRect slipped through the cracks, we detect it here too.
    constexpr uint32_t kCornerFlags[4] = {
        AnalyticClip::kTop_EdgeFlag | AnalyticClip::kLeft_EdgeFlag,
        AnalyticClip::kTop_EdgeFlag | AnalyticClip::kRight_EdgeFlag,
        AnalyticClip::kBottom_EdgeFlag | AnalyticClip::kRight_EdgeFlag,
        AnalyticClip::kBottom_EdgeFlag | AnalyticClip::kLeft_EdgeFlag,
    };
    SkScalar circularRadius = 0;
    uint32_t edgeFlags = 0;
    int squareCount = 0;
    for (int corner = 0; corner < 4; ++corner) {
        SkVector radii = rrect.radii((SkRRect::Corner)corner);
        // Can only handle circular radii.
        // Also applies to corners with both zero and non-zero radii.
        if (!SkRRectPriv::IsRelativelyCircular(radii.fX, radii.fY, Shape::kDefaultPixelTolerance)) {
            return {};
        }
        if (radii.fX < kRadiusMin || radii.fY < kRadiusMin) {
            // The corner is square, so no need to flag as circular.
            squareCount++;
            continue;
        }
        // First circular corner seen
        if (!edgeFlags) {
            circularRadius = radii.fX;
        } else if (!SkRRectPriv::IsRelativelyCircular(radii.fX,
                                                      circularRadius,
                                                      Shape::kDefaultPixelTolerance)) {
            // Radius doesn't match previously seen circular radius
            return {};
        }
        edgeFlags |= kCornerFlags[corner];
    }

    if (edgeFlags == AnalyticClip::kNone_EdgeFlag) {
        // It's a rect (or coerced to a rect)
        return {rrect.rect(), kRadiusMin, edgeFlags, shape.inverted()};
    } else if (edgeFlags == AnalyticClip::kAll_EdgeFlag && squareCount != 0) {
        // If any rounded corner pairs are non-adjacent or if there are three rounded corners all
        // edge flags will be set, which is not valid.
        return {};
    } else {
        // At least one corner is rounded, or two adjacent corners are rounded, or all corners
        // are approximately the same (but not classified as simple due to inexactness).
        return {rrect.rect(), circularRadius, edgeFlags, shape.inverted()};
    }
}

#else

AnalyticClip can_apply_analytic_clip(const Shape& shape, const Transform& localToDevice) {
    if (localToDevice.type() > Transform::Type::kAffine) {
        return {};
    }

    // Since the transformation is affine, it can be represented as a 2x2 matrix and a translation.
    // To minimize data sent to the GPU, the translation is pre-applied to the rectangle coordinates
    // and only the 2x2 needs to be sent. The analytic clip is invoked with device coordinates so
    // the inverse's 2x2 is used.
    const SkM44& devToLocal = localToDevice.inverse();
    SkV4 xform = {devToLocal.rc(0,0), devToLocal.rc(1,0), // column-major
                  devToLocal.rc(0,1), devToLocal.rc(1,1)};
    // Applying this translation to the local rrect geometry moves it into a new coordinate space
    // where just the 2x2 of localToDevice is needed to map to device space (conversely, where
    // just `xform` is needed to map device coords to the rrect's new space).
    float tx = xform.x*localToDevice.matrix().rc(0,3) + xform.z*localToDevice.matrix().rc(1,3);
    float ty = xform.y*localToDevice.matrix().rc(0,3) + xform.w*localToDevice.matrix().rc(1,3);

    // Can handle Rect directly.
    if (shape.isRect()) {
        return {shape.rect().makeOffset({tx,ty}).asSkRect(),
                SkV4{0.f, 0.f, 0.f, 0.f},
                xform,
                shape.inverted()};
    }

    // Otherwise we only handle certain kinds of RRects, specifically only rrects with circular
    // corners (although each corner can differ). We don't just check AllCornersRelativelyCircular
    // because we can fold an Y-axis scale factor into the 2x2 transform if that non-uniform scaling
    // could make all corners effectively circular.
    if (!shape.isRRect()) {
        return {};
    }

    const float tolerance =
            localToDevice.localAARadius(shape.bounds()) * Shape::kDefaultPixelTolerance;

    const SkRRect& rrect = shape.rrect();
    std::optional<float> scaleYAxis;
    SkV4 radii;
    for (int i = 0; i < 4; ++i) {
        SkVector r = rrect.radii((SkRRect::Corner) i);
        float cornerScale = SkRRectPriv::IsRelativelyCircular(r.fX, r.fY, tolerance)
                ? 1.f : sk_ieee_float_divide(r.fX, r.fY);

        if (r.fX < tolerance || r.fY < tolerance) {
            radii[i] = 0.f; // Clamp to a square corner, so doesn't impact scale factor
        } else if (!scaleYAxis.has_value()) {
            // We haven't encountered a non-circular corner yet. Set the scale factor to the
            // current radii ratio (which will be 1 if it's already circular).
            scaleYAxis = cornerScale;
            radii[i] = r.fX;
        } else {
            // We already have a scale factor from some other corner, so we need to agree.
            if (!SkScalarNearlyEqual(cornerScale, *scaleYAxis, tolerance)) {
                return {}; // Would not pass AllCornersRelativelyCircular after scaling
            }
            radii[i] = r.fX;
        }
    }

    Rect rect = rrect.rect().makeOffset(tx, ty);
    if (scaleYAxis.has_value() && !SkScalarNearlyEqual(*scaleYAxis, 1.f, tolerance)) {
        const float s = *scaleYAxis;
        rect.setTop(rect.top() * s);
        rect.setBot(rect.bot() * s);

        // Since we scaled the rrect by s, we should scale its local-to-device matrix by 1/s to
        // remain the same shape. However, `xform` is the device-to-local matrix so as the inverse,
        // we also just have to multiply by s.
        xform.y *= s;
        xform.w *= s;
        SkASSERT(SkRRectPriv::AllCornersRelativelyCircular(
                 *rrect.transform(SkMatrix::Scale(1.f, s)), tolerance));
    } else {
        // The loop above should work out to be equivalent to this function if we didn't encounter
        // a non-uniform scale factor to push into `xform`.
        SkASSERT(SkRRectPriv::AllCornersRelativelyCircular(rrect, tolerance));
    }

    return {rect.asSkRect(), radii, xform, shape.inverted()};
}

#endif // SK_GRAPHITE_USE_LEGACY_RRECT_CLIP_SHADER

}  // anonymous namespace

Clip ClipStack::visitClipStackForDraw(const Transform& localToDevice,
                                      Geometry* geometry,
                                      const SkStrokeRec& style,
                                      ClipStack::ElementList* outEffectiveElements) const {
    static const Clip kClippedOut = {
            Rect::InfiniteInverted(), Rect::InfiniteInverted(), SkIRect::MakeEmpty(),
            /* nonMSAAClip= */ {}, /* shader= */ nullptr};

    const SaveRecord& cs = this->currentSaveRecord();
    if (cs.state() == ClipState::kEmpty) {
        // We know the draw is clipped out so don't bother computing the base draw bounds.
        return kClippedOut;
    }
    // Compute draw bounds, clipped only to our device bounds since we need to return that even if
    // the clip stack is known to be wide-open.
    const Rect deviceBounds = this->deviceBounds();

    DrawShape draw{localToDevice, *geometry};
    if (!draw.applyStyle(style, deviceBounds)) {
        return kClippedOut;
    }

    // For intersect clips, the scissor rectangle is snapped outer bounds (to loosely restrict
    // rasterization if absolutely necessary). Cases where the draw is fully inside the scissor are
    // automatically handled during GPU command generation.
    //
    // For difference clips, a tight scissor could be `subtract(drawBounds, cs.innerBounds())`
    // but this is only useful when the clip spans across an axis of the draw and can otherwise
    // lead to scissor state thrashing since it's connected to the draw's bounds as well. So just
    // use the device bounds for simplicity.
    draw.applyScissor(cs.op() == SkClipOp::kIntersect ? snap_scissor(cs.outerBounds(), deviceBounds)
                                                      : deviceBounds);

    switch (cs.testForDraw(draw)) {
        case DrawInfluence::kClipsOutDraw:
            // The draw is offscreen or clipped out, so there is no need to visit the clip elements.
            return kClippedOut;

        case DrawInfluence::kNone:
            // The draw is unaffected by the clip stack (except possibly `scissor`), and there's no
            // need to visit each clip element.
            return draw.toClip(geometry, {}, cs.shader());

        case DrawInfluence::kReplacesDraw:
            // The draw covers the clip entirely. Replace the shape with a flood fill, which can
            // intersect with shapes efficiently.
            draw.resetToFloodFill();
            [[fallthrough]];

        case DrawInfluence::kComplexInteraction:
            // Check each element's influence on the draw below
            break;
    }

    SkASSERT(outEffectiveElements);
    SkASSERT(outEffectiveElements->empty());
    int i = fElements.count();
    NonMSAAClip nonMSAAClip;
    for (const RawElement& e : fElements.ritems()) {
        --i;
        if (i < cs.oldestElementIndex()) {
            // All earlier elements have been invalidated by elements already processed so the draw
            // can't be affected by them and cannot contribute to their usage bounds.
            break;
        }

        switch (e.testForDraw(draw)) {
            case DrawInfluence::kClipsOutDraw:
                // Per-element check was able to completely reject the draw.
                outEffectiveElements->clear();
                return kClippedOut;

            case DrawInfluence::kNone:
                // This element does not interact, so continue to the next
                continue;

            case DrawInfluence::kReplacesDraw:
                // This element is covered entirely by the draw, so the draw's geometry can be
                // replaced assuming the coordinate spaces are compatible. To facilitate this, we
                // switch the drawn geometry to a flood fill and then fall through to intersection.
                // Even if the coordinate spaces aren't in alignment, this eliminates the draw's
                // source of analytic coverage.
                draw.resetToFloodFill();

                [[fallthrough]];

            case DrawInfluence::kComplexInteraction:
                // First try to handle the clip geometrically
                if (e.op() == SkClipOp::kIntersect && draw.intersectClipElement(e)) {
                    continue;
                }
                // Second try to tighten the scissor, which is lighter weight than adding an
                // analytic clip pipeline variation or triggering MSAA.
                if (e.clipType() == ClipState::kDeviceRect) {
                    Rect scissor = e.shape().rect().makeRound();
                    if (e.shape().rect().nearlyEquals(scissor, Shape::kDefaultPixelTolerance)) {
                        // Pass in `scissor` since these need to be integral values while
                        // nearlyEquals allows the original rect coordinates to be slightly
                        // different (causing problems later with asSkIRect()).
                        draw.applyScissor(scissor);
                        continue;
                    }
                }
                // Third try to handle the clip analytically in the shader
                if (nonMSAAClip.fAnalyticClip.isEmpty()) {
                    nonMSAAClip.fAnalyticClip = can_apply_analytic_clip(e.shape(),
                                                                        e.localToDevice());
                    if (!nonMSAAClip.fAnalyticClip.isEmpty()) {
                        continue;
                    }
                }

                // Fourth, remember the element for later, either to be a depth-only draw or to be
                // flattened into a clip mask.
                // Otherwise, accumulate it for later. Depending on how many elements are collected
                // we may use the scissor, analytic clip, or MSAA/atlas.
                outEffectiveElements->push_back(&e);
                break;
        }
    }

    // If there is no MSAA supported, rasterize any remaining elements by flattening them
    // into a single mask and storing in an atlas. Otherwise these will be handled by
    // Device::drawClip().
    ClipAtlasManager* clipAtlas =
            fDevice->recorder()->priv().atlasProvider()->getClipAtlasManager();
    if (clipAtlas && !outEffectiveElements->empty()) {
        AtlasClip* atlasClip = &nonMSAAClip.fAtlasClip;

        SkIRect iMaskBounds = cs.outerBounds().makeRoundOut().asSkIRect();
        sk_sp<TextureProxy> proxy = clipAtlas->findOrCreateEntry(cs.genID(),
                                                                 outEffectiveElements,
                                                                 iMaskBounds,
                                                                 &atlasClip->fOutPos);
        if (proxy) {
            // Add to Clip
            atlasClip->fMaskBounds = iMaskBounds;
            atlasClip->fAtlasTexture = std::move(proxy);

            // Elements are represented in the clip atlas, discard.
            outEffectiveElements->clear();
        }
    }

    return draw.toClip(geometry, nonMSAAClip, cs.shader());
}

std::pair<CompressedPaintersOrder, Insertion> ClipStack::updateClipStateForDraw(
        const Clip& clip,
        const ElementList& effectiveElements,
        const BoundsManager* boundsManager,
        PaintersDepth z) {
    if (clip.isClippedOut()) {
        return {DrawOrder::kNoIntersection, {}};
    }

    SkDEBUGCODE(const SaveRecord& cs = this->currentSaveRecord();)
    SkASSERT(cs.state() != ClipState::kEmpty);

    // In the drawListLayer approach, each clipped draw needs to know the *latest* insertion across
    // the depth only draws that affect it. (This is the layer pointer returned by this function).
    // To facilitate this, each clip element records the latest layer it inserted into across its
    // render steps. Although effectiveElements may contain a mixture of drawn and undrawn elements,
    // taking the max across the indexes (which are monotonically increasing) associated with each
    // fDeferredLayer yields the latest layer.
    Insertion latestInsertion;
    Rect deviceBounds = this->deviceBounds();
    SkASSERT(!clip.drawBounds().isEmptyNegativeOrNaN());

    // Always record snapped draw bounds to avoid scissor thrashing since these bounds will be used
    // to determine the scissor applied to the depth-only draw for the clip element.
    Rect snappedDrawBounds = snap_scissor(clip.drawBounds(), deviceBounds);
    CompressedPaintersOrder maxClipOrder = DrawOrder::kNoIntersection;
    for (int i = 0; i < effectiveElements.size(); ++i) {
        // ClipStack owns the elements in the `clipState` so it's OK to downcast and cast away
        // const.
        // TODO: Enforce the ownership? In debug builds we could invalidate a `ClipStateForDraw` if
        // its element pointers become dangling and assert validity here.
        const RawElement* e = static_cast<const RawElement*>(effectiveElements[i]);
        auto [order, insertion] =  const_cast<RawElement*>(e)->updateForDraw(
                fDevice, boundsManager, deviceBounds, snappedDrawBounds, z);
        maxClipOrder = std::max(order, maxClipOrder);
        // Note, the > operator on the insertion only considers the layer. In the case that both
        // insertions reside on the same layer, we arbitrarily skip the update, meaning that the
        // list is the one associated with the earlier draw. Because depth draws are added to the
        // head of each layer, and thus in reverse order, the insertion of an earlier draw will
        // always be the latest depth only draw in a layer, even in the case that the clip stack
        // draws elements out of order.
        //
        // (I.e. Even you get a clipstack traversal like DrawnA UndrawnB DrawnC, if B inserts into
        // A or C's layer it either does not match and is added to the head, and thus the existing
        // A or C insertion must be the latest bindingList, or it matches A or C and thus has an
        // identical insertion. Even if this reverse ordering property was not true, a clipped
        // shading draw cannot match on a depth draw, so it would either match on an existing draw
        // or is added to to the tail, preserving the ordering).
        if (insertion > latestInsertion) {
            latestInsertion = insertion;
        }
    }

    return {maxClipOrder, latestInsertion};
}

void ClipStack::recordDeferredClipDraws() {
    for (auto& e : fElements.items()) {
        e.drawClip(fDevice);
    }
}

}  // namespace skgpu::graphite
