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

#include "GrDefaultPathRenderer.h"
#include "GrContext.h"
#include "GrDefaultGeoProcFactory.h"
#include "GrDrawOpTest.h"
#include "GrFixedClip.h"
#include "GrMesh.h"
#include "GrOpFlushState.h"
#include "GrPathUtils.h"
#include "GrSimpleMeshDrawOpHelper.h"
#include "SkGeometry.h"
#include "SkString.h"
#include "SkStrokeRec.h"
#include "SkTLazy.h"
#include "SkTraceEvent.h"
#include "ops/GrMeshDrawOp.h"
#include "ops/GrRectOpFactory.h"

GrDefaultPathRenderer::GrDefaultPathRenderer() {
}

////////////////////////////////////////////////////////////////////////////////
// Helpers for drawPath

#define STENCIL_OFF     0   // Always disable stencil (even when needed)

static inline bool single_pass_shape(const GrShape& shape) {
#if STENCIL_OFF
    return true;
#else
    // Inverse fill is always two pass.
    if (shape.inverseFilled()) {
        return false;
    }
    // This path renderer only accepts simple fill paths or stroke paths that are either hairline
    // or have a stroke width small enough to treat as hairline. Hairline paths are always single
    // pass. Filled paths are single pass if they're convex.
    if (shape.style().isSimpleFill()) {
        return shape.knownToBeConvex();
    }
    return true;
#endif
}

GrPathRenderer::StencilSupport
GrDefaultPathRenderer::onGetStencilSupport(const GrShape& shape) const {
    if (single_pass_shape(shape)) {
        return GrPathRenderer::kNoRestriction_StencilSupport;
    } else {
        return GrPathRenderer::kStencilOnly_StencilSupport;
    }
}

namespace {

class PathGeoBuilder {
public:
    PathGeoBuilder(GrPrimitiveType primitiveType, GrMeshDrawOp::Target* target,
                   GrGeometryProcessor* geometryProcessor, const GrPipeline* pipeline)
            : fMesh(primitiveType)
            , fTarget(target)
            , fVertexStride(sizeof(SkPoint))
            , fGeometryProcessor(geometryProcessor)
            , fPipeline(pipeline)
            , fIndexBuffer(nullptr)
            , fFirstIndex(0)
            , fIndicesInChunk(0)
            , fIndices(nullptr) {
        this->allocNewBuffers();
    }

    ~PathGeoBuilder() {
        this->emitMeshAndPutBackReserve();
    }

    /**
     *  Path verbs
     */
    void moveTo(const SkPoint& p) {
        needSpace(1);

        fSubpathIndexStart = this->currentIndex();
        *(fCurVert++) = p;
    }

    void addLine(const SkPoint& p) {
        needSpace(1, this->indexScale());

        if (this->isIndexed()) {
            uint16_t prevIdx = this->currentIndex() - 1;
            appendCountourEdgeIndices(prevIdx);
        }
        *(fCurVert++) = p;
    }

    void addQuad(const SkPoint pts[], SkScalar srcSpaceTolSqd, SkScalar srcSpaceTol) {
        this->needSpace(GrPathUtils::kMaxPointsPerCurve,
                        GrPathUtils::kMaxPointsPerCurve * this->indexScale());

        // First pt of quad is the pt we ended on in previous step
        uint16_t firstQPtIdx = this->currentIndex() - 1;
        uint16_t numPts = (uint16_t)GrPathUtils::generateQuadraticPoints(
                pts[0], pts[1], pts[2], srcSpaceTolSqd, &fCurVert,
                GrPathUtils::quadraticPointCount(pts, srcSpaceTol));
        if (this->isIndexed()) {
            for (uint16_t i = 0; i < numPts; ++i) {
                appendCountourEdgeIndices(firstQPtIdx + i);
            }
        }
    }

    void addConic(SkScalar weight, const SkPoint pts[], SkScalar srcSpaceTolSqd,
                  SkScalar srcSpaceTol) {
        SkAutoConicToQuads converter;
        const SkPoint* quadPts = converter.computeQuads(pts, weight, srcSpaceTol);
        for (int i = 0; i < converter.countQuads(); ++i) {
            this->addQuad(quadPts + i * 2, srcSpaceTolSqd, srcSpaceTol);
        }
    }

    void addCubic(const SkPoint pts[], SkScalar srcSpaceTolSqd, SkScalar srcSpaceTol) {
        this->needSpace(GrPathUtils::kMaxPointsPerCurve,
                        GrPathUtils::kMaxPointsPerCurve * this->indexScale());

        // First pt of cubic is the pt we ended on in previous step
        uint16_t firstCPtIdx = this->currentIndex() - 1;
        uint16_t numPts = (uint16_t) GrPathUtils::generateCubicPoints(
                pts[0], pts[1], pts[2], pts[3], srcSpaceTolSqd, &fCurVert,
                GrPathUtils::cubicPointCount(pts, srcSpaceTol));
        if (this->isIndexed()) {
            for (uint16_t i = 0; i < numPts; ++i) {
                appendCountourEdgeIndices(firstCPtIdx + i);
            }
        }
    }

    void addPath(const SkPath& path, SkScalar srcSpaceTol) {
        SkScalar srcSpaceTolSqd = srcSpaceTol * srcSpaceTol;

        SkPath::Iter iter(path, false);
        SkPoint pts[4];

        bool done = false;
        while (!done) {
            SkPath::Verb verb = iter.next(pts, false);
            switch (verb) {
                case SkPath::kMove_Verb:
                    this->moveTo(pts[0]);
                    break;
                case SkPath::kLine_Verb:
                    this->addLine(pts[1]);
                    break;
                case SkPath::kConic_Verb:
                    this->addConic(iter.conicWeight(), pts, srcSpaceTolSqd, srcSpaceTol);
                    break;
                case SkPath::kQuad_Verb:
                    this->addQuad(pts, srcSpaceTolSqd, srcSpaceTol);
                    break;
                case SkPath::kCubic_Verb:
                    this->addCubic(pts, srcSpaceTolSqd, srcSpaceTol);
                    break;
                case SkPath::kClose_Verb:
                    break;
                case SkPath::kDone_Verb:
                    done = true;
            }
        }
    }

    static bool PathHasMultipleSubpaths(const SkPath& path) {
        bool first = true;

        SkPath::Iter iter(path, false);
        SkPath::Verb verb;

        SkPoint pts[4];
        while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
            if (SkPath::kMove_Verb == verb && !first) {
                return true;
            }
            first = false;
        }
        return false;
    }

private:
    /**
     *  Derived properties
     *  TODO: Cache some of these for better performance, rather than re-computing?
     */
    bool isIndexed() const {
        return GrPrimitiveType::kLines == fMesh.primitiveType() ||
               GrPrimitiveType::kTriangles == fMesh.primitiveType();
    }
    bool isHairline() const {
        return GrPrimitiveType::kLines == fMesh.primitiveType() ||
               GrPrimitiveType::kLineStrip == fMesh.primitiveType();
    }
    int indexScale() const {
        switch (fMesh.primitiveType()) {
            case GrPrimitiveType::kLines:
                return 2;
            case GrPrimitiveType::kTriangles:
                return 3;
            default:
                return 0;
        }
    }

    uint16_t currentIndex() const { return fCurVert - fVertices; }

    // Allocate vertex and (possibly) index buffers
    void allocNewBuffers() {
        // Ensure that we always get enough verts for a worst-case quad/cubic, plus leftover points
        // from previous mesh piece (up to two verts to continue fanning). If we can't get that
        // many, ask for a much larger number. This needs to be fairly big to handle  quads/cubics,
        // which have a worst-case of 1k points.
        static const int kMinVerticesPerChunk = GrPathUtils::kMaxPointsPerCurve + 2;
        static const int kFallbackVerticesPerChunk = 16384;

        fVertices = static_cast<SkPoint*>(fTarget->makeVertexSpaceAtLeast(fVertexStride,
                                                                          kMinVerticesPerChunk,
                                                                          kFallbackVerticesPerChunk,
                                                                          &fVertexBuffer,
                                                                          &fFirstVertex,
                                                                          &fVerticesInChunk));

        if (this->isIndexed()) {
            // Similar to above: Ensure we get enough indices for one worst-case quad/cubic.
            // No extra indices are needed for stitching, though. If we can't get that many, ask
            // for enough to match our large vertex request.
            const int kMinIndicesPerChunk = GrPathUtils::kMaxPointsPerCurve * this->indexScale();
            const int kFallbackIndicesPerChunk = kFallbackVerticesPerChunk * this->indexScale();

            fIndices = fTarget->makeIndexSpaceAtLeast(kMinIndicesPerChunk, kFallbackIndicesPerChunk,
                                                      &fIndexBuffer, &fFirstIndex,
                                                      &fIndicesInChunk);
        }

        fCurVert = fVertices;
        fCurIdx = fIndices;
        fSubpathIndexStart = 0;
    }

    void appendCountourEdgeIndices(uint16_t edgeV0Idx) {
        // When drawing lines we're appending line segments along the countour. When applying the
        // other fill rules we're drawing triangle fans around the start of the current (sub)path.
        if (!this->isHairline()) {
            *(fCurIdx++) = fSubpathIndexStart;
        }
        *(fCurIdx++) = edgeV0Idx;
        *(fCurIdx++) = edgeV0Idx + 1;
    }

    // Emits a single draw with all accumulated vertex/index data
    void emitMeshAndPutBackReserve() {
        int vertexCount = fCurVert - fVertices;
        int indexCount = fCurIdx - fIndices;
        SkASSERT(vertexCount <= fVerticesInChunk);
        SkASSERT(indexCount <= fIndicesInChunk);

        if (vertexCount > 0) {
            if (!this->isIndexed()) {
                fMesh.setNonIndexedNonInstanced(vertexCount);
            } else {
                fMesh.setIndexed(fIndexBuffer, indexCount, fFirstIndex, 0, vertexCount - 1);
            }
            fMesh.setVertexData(fVertexBuffer, fFirstVertex);
            fTarget->draw(fGeometryProcessor, fPipeline, fMesh);
        }

        fTarget->putBackIndices((size_t)(fIndicesInChunk - indexCount));
        fTarget->putBackVertices((size_t)(fVerticesInChunk - vertexCount), fVertexStride);
    }

    void needSpace(int vertsNeeded, int indicesNeeded = 0) {
        if (fCurVert + vertsNeeded > fVertices + fVerticesInChunk ||
            fCurIdx + indicesNeeded > fIndices + fIndicesInChunk) {
            // We are about to run out of space (possibly)

            // To maintain continuity, we need to remember one or two points from the current mesh.
            // Lines only need the last point, fills need the first point from the current contour.
            // We always grab both here, and append the ones we need at the end of this process.
            SkPoint lastPt = *(fCurVert - 1);
            SkASSERT(fSubpathIndexStart < fVerticesInChunk);
            SkPoint subpathStartPt = fVertices[fSubpathIndexStart];

            // Draw the mesh we've accumulated, and put back any unused space
            this->emitMeshAndPutBackReserve();

            // Get new buffers
            this->allocNewBuffers();

            // Append copies of the points we saved so the two meshes will weld properly
            if (!this->isHairline()) {
                *(fCurVert++) = subpathStartPt;
            }
            *(fCurVert++) = lastPt;
        }
    }

    GrMesh fMesh;
    GrMeshDrawOp::Target* fTarget;
    size_t fVertexStride;
    GrGeometryProcessor* fGeometryProcessor;
    const GrPipeline* fPipeline;

    const GrBuffer* fVertexBuffer;
    int fFirstVertex;
    int fVerticesInChunk;
    SkPoint* fVertices;
    SkPoint* fCurVert;

    const GrBuffer* fIndexBuffer;
    int fFirstIndex;
    int fIndicesInChunk;
    uint16_t* fIndices;
    uint16_t* fCurIdx;
    uint16_t fSubpathIndexStart;
};

class DefaultPathOp final : public GrMeshDrawOp {
private:
    using Helper = GrSimpleMeshDrawOpHelperWithStencil;

public:
    DEFINE_OP_CLASS_ID

    static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const SkPath& path, SkScalar tolerance,
                                          uint8_t coverage, const SkMatrix& viewMatrix,
                                          bool isHairline, GrAAType aaType, const SkRect& devBounds,
                                          const GrUserStencilSettings* stencilSettings) {
        return Helper::FactoryHelper<DefaultPathOp>(std::move(paint), path, tolerance, coverage,
                                                    viewMatrix, isHairline, aaType, devBounds,
                                                    stencilSettings);
    }

    const char* name() const override { return "DefaultPathOp"; }

    void visitProxies(const VisitProxyFunc& func) const override {
        fHelper.visitProxies(func);
    }

    SkString dumpInfo() const override {
        SkString string;
        string.appendf("Color: 0x%08x Count: %d\n", fColor, fPaths.count());
        for (const auto& path : fPaths) {
            string.appendf("Tolerance: %.2f\n", path.fTolerance);
        }
        string += fHelper.dumpInfo();
        string += INHERITED::dumpInfo();
        return string;
    }

    DefaultPathOp(const Helper::MakeArgs& helperArgs, GrColor color, const SkPath& path,
                  SkScalar tolerance, uint8_t coverage, const SkMatrix& viewMatrix, bool isHairline,
                  GrAAType aaType, const SkRect& devBounds,
                  const GrUserStencilSettings* stencilSettings)
            : INHERITED(ClassID())
            , fHelper(helperArgs, aaType, stencilSettings)
            , fColor(color)
            , fCoverage(coverage)
            , fViewMatrix(viewMatrix)
            , fIsHairline(isHairline) {
        fPaths.emplace_back(PathData{path, tolerance});

        this->setBounds(devBounds, HasAABloat::kNo,
                        isHairline ? IsZeroArea::kYes : IsZeroArea::kNo);
    }

    FixedFunctionFlags fixedFunctionFlags() const override { return fHelper.fixedFunctionFlags(); }

    RequiresDstTexture finalize(const GrCaps& caps, const GrAppliedClip* clip,
                                GrPixelConfigIsClamped dstIsClamped) override {
        GrProcessorAnalysisCoverage gpCoverage =
                this->coverage() == 0xFF ? GrProcessorAnalysisCoverage::kNone
                                         : GrProcessorAnalysisCoverage::kSingleChannel;
        return fHelper.xpRequiresDstTexture(caps, clip, dstIsClamped, gpCoverage, &fColor);
    }

private:
    void onPrepareDraws(Target* target) override {
        sk_sp<GrGeometryProcessor> gp;
        {
            using namespace GrDefaultGeoProcFactory;
            Color color(this->color());
            Coverage coverage(this->coverage());
            LocalCoords localCoords(fHelper.usesLocalCoords() ? LocalCoords::kUsePosition_Type
                                                              : LocalCoords::kUnused_Type);
            gp = GrDefaultGeoProcFactory::Make(color, coverage, localCoords, this->viewMatrix());
        }

        SkASSERT(gp->getVertexStride() == sizeof(SkPoint));

        int instanceCount = fPaths.count();

        // We will use index buffers if we have multiple paths or one path with multiple contours
        bool isIndexed = instanceCount > 1;
        for (int i = 0; !isIndexed && i < instanceCount; i++) {
            const PathData& args = fPaths[i];
            isIndexed = isIndexed || PathGeoBuilder::PathHasMultipleSubpaths(args.fPath);
        }

        // determine primitiveType
        GrPrimitiveType primitiveType;
        if (this->isHairline()) {
            primitiveType = isIndexed ? GrPrimitiveType::kLines : GrPrimitiveType::kLineStrip;
        } else {
            primitiveType = isIndexed ? GrPrimitiveType::kTriangles : GrPrimitiveType::kTriangleFan;
        }

        PathGeoBuilder pathGeoBuilder(primitiveType, target, gp.get(),
                                      fHelper.makePipeline(target));

        // fill buffers
        for (int i = 0; i < instanceCount; i++) {
            const PathData& args = fPaths[i];
            pathGeoBuilder.addPath(args.fPath, args.fTolerance);
        }
    }

    bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
        DefaultPathOp* that = t->cast<DefaultPathOp>();
        if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
            return false;
        }

        if (this->color() != that->color()) {
            return false;
        }

        if (this->coverage() != that->coverage()) {
            return false;
        }

        if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
            return false;
        }

        if (this->isHairline() != that->isHairline()) {
            return false;
        }

        fPaths.push_back_n(that->fPaths.count(), that->fPaths.begin());
        this->joinBounds(*that);
        return true;
    }

    GrColor color() const { return fColor; }
    uint8_t coverage() const { return fCoverage; }
    const SkMatrix& viewMatrix() const { return fViewMatrix; }
    bool isHairline() const { return fIsHairline; }

    struct PathData {
        SkPath fPath;
        SkScalar fTolerance;
    };

    SkSTArray<1, PathData, true> fPaths;
    Helper fHelper;
    GrColor fColor;
    uint8_t fCoverage;
    SkMatrix fViewMatrix;
    bool fIsHairline;

    typedef GrMeshDrawOp INHERITED;
};

}  // anonymous namespace

bool GrDefaultPathRenderer::internalDrawPath(GrRenderTargetContext* renderTargetContext,
                                             GrPaint&& paint,
                                             GrAAType aaType,
                                             const GrUserStencilSettings& userStencilSettings,
                                             const GrClip& clip,
                                             const SkMatrix& viewMatrix,
                                             const GrShape& shape,
                                             bool stencilOnly) {
    SkASSERT(GrAAType::kCoverage != aaType);
    SkPath path;
    shape.asPath(&path);

    SkScalar hairlineCoverage;
    uint8_t newCoverage = 0xff;
    bool isHairline = false;
    if (IsStrokeHairlineOrEquivalent(shape.style(), viewMatrix, &hairlineCoverage)) {
        newCoverage = SkScalarRoundToInt(hairlineCoverage * 0xff);
        isHairline = true;
    } else {
        SkASSERT(shape.style().isSimpleFill());
    }

    int                          passCount = 0;
    const GrUserStencilSettings* passes[2];
    bool                         reverse = false;
    bool                         lastPassIsBounds;

    if (isHairline) {
        passCount = 1;
        if (stencilOnly) {
            passes[0] = &gDirectToStencil;
        } else {
            passes[0] = &userStencilSettings;
        }
        lastPassIsBounds = false;
    } else {
        if (single_pass_shape(shape)) {
            passCount = 1;
            if (stencilOnly) {
                passes[0] = &gDirectToStencil;
            } else {
                passes[0] = &userStencilSettings;
            }
            lastPassIsBounds = false;
        } else {
            switch (path.getFillType()) {
                case SkPath::kInverseEvenOdd_FillType:
                    reverse = true;
                    // fallthrough
                case SkPath::kEvenOdd_FillType:
                    passes[0] = &gEOStencilPass;
                    if (stencilOnly) {
                        passCount = 1;
                        lastPassIsBounds = false;
                    } else {
                        passCount = 2;
                        lastPassIsBounds = true;
                        if (reverse) {
                            passes[1] = &gInvEOColorPass;
                        } else {
                            passes[1] = &gEOColorPass;
                        }
                    }
                    break;

                case SkPath::kInverseWinding_FillType:
                    reverse = true;
                    // fallthrough
                case SkPath::kWinding_FillType:
                    passes[0] = &gWindStencilPass;
                    passCount = 2;
                    if (stencilOnly) {
                        lastPassIsBounds = false;
                        --passCount;
                    } else {
                        lastPassIsBounds = true;
                        if (reverse) {
                            passes[passCount-1] = &gInvWindColorPass;
                        } else {
                            passes[passCount-1] = &gWindColorPass;
                        }
                    }
                    break;
                default:
                    SkDEBUGFAIL("Unknown path fFill!");
                    return false;
            }
        }
    }

    SkScalar tol = GrPathUtils::kDefaultTolerance;
    SkScalar srcSpaceTol = GrPathUtils::scaleToleranceToSrc(tol, viewMatrix, path.getBounds());

    SkRect devBounds;
    GetPathDevBounds(path, renderTargetContext->width(), renderTargetContext->height(), viewMatrix,
                     &devBounds);

    for (int p = 0; p < passCount; ++p) {
        if (lastPassIsBounds && (p == passCount-1)) {
            SkRect bounds;
            SkMatrix localMatrix = SkMatrix::I();
            if (reverse) {
                // draw over the dev bounds (which will be the whole dst surface for inv fill).
                bounds = devBounds;
                SkMatrix vmi;
                // mapRect through persp matrix may not be correct
                if (!viewMatrix.hasPerspective() && viewMatrix.invert(&vmi)) {
                    vmi.mapRect(&bounds);
                } else {
                    if (!viewMatrix.invert(&localMatrix)) {
                        return false;
                    }
                }
            } else {
                bounds = path.getBounds();
            }
            const SkMatrix& viewM = (reverse && viewMatrix.hasPerspective()) ? SkMatrix::I() :
                                                                               viewMatrix;
            renderTargetContext->addDrawOp(
                    clip,
                    GrRectOpFactory::MakeNonAAFillWithLocalMatrix(
                            std::move(paint), viewM, localMatrix, bounds, aaType, passes[p]));
        } else {
            bool stencilPass = stencilOnly || passCount > 1;
            std::unique_ptr<GrDrawOp> op;
            if (stencilPass) {
                GrPaint stencilPaint;
                stencilPaint.setXPFactory(GrDisableColorXPFactory::Get());
                op = DefaultPathOp::Make(std::move(stencilPaint), path, srcSpaceTol, newCoverage,
                                         viewMatrix, isHairline, aaType, devBounds, passes[p]);
            } else {
                op = DefaultPathOp::Make(std::move(paint), path, srcSpaceTol, newCoverage,
                                         viewMatrix, isHairline, aaType, devBounds, passes[p]);
            }
            renderTargetContext->addDrawOp(clip, std::move(op));
        }
    }
    return true;
}

GrPathRenderer::CanDrawPath
GrDefaultPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
    bool isHairline = IsStrokeHairlineOrEquivalent(args.fShape->style(), *args.fViewMatrix, nullptr);
    // If we aren't a single_pass_shape or hairline, we require stencil buffers.
    if (!(single_pass_shape(*args.fShape) || isHairline) && args.fCaps->avoidStencilBuffers()) {
        return CanDrawPath::kNo;
    }
    // This can draw any path with any simple fill style but doesn't do coverage-based antialiasing.
    if (GrAAType::kCoverage == args.fAAType ||
        (!args.fShape->style().isSimpleFill() && !isHairline)) {
        return CanDrawPath::kNo;
    }
    // This is the fallback renderer for when a path is too complicated for the others to draw.
    return CanDrawPath::kAsBackup;
}

bool GrDefaultPathRenderer::onDrawPath(const DrawPathArgs& args) {
    GR_AUDIT_TRAIL_AUTO_FRAME(args.fRenderTargetContext->auditTrail(),
                              "GrDefaultPathRenderer::onDrawPath");
    return this->internalDrawPath(args.fRenderTargetContext,
                                  std::move(args.fPaint),
                                  args.fAAType,
                                  *args.fUserStencilSettings,
                                  *args.fClip,
                                  *args.fViewMatrix,
                                  *args.fShape,
                                  false);
}

void GrDefaultPathRenderer::onStencilPath(const StencilPathArgs& args) {
    GR_AUDIT_TRAIL_AUTO_FRAME(args.fRenderTargetContext->auditTrail(),
                              "GrDefaultPathRenderer::onStencilPath");
    SkASSERT(!args.fShape->inverseFilled());

    GrPaint paint;
    paint.setXPFactory(GrDisableColorXPFactory::Get());

    this->internalDrawPath(args.fRenderTargetContext, std::move(paint), args.fAAType,
                           GrUserStencilSettings::kUnused, *args.fClip, *args.fViewMatrix,
                           *args.fShape, true);
}

///////////////////////////////////////////////////////////////////////////////////////////////////

#if GR_TEST_UTILS

GR_DRAW_OP_TEST_DEFINE(DefaultPathOp) {
    SkMatrix viewMatrix = GrTest::TestMatrix(random);

    // For now just hairlines because the other types of draws require two ops.
    // TODO we should figure out a way to combine the stencil and cover steps into one op.
    GrStyle style(SkStrokeRec::kHairline_InitStyle);
    SkPath path = GrTest::TestPath(random);

    // Compute srcSpaceTol
    SkRect bounds = path.getBounds();
    SkScalar tol = GrPathUtils::kDefaultTolerance;
    SkScalar srcSpaceTol = GrPathUtils::scaleToleranceToSrc(tol, viewMatrix, bounds);

    viewMatrix.mapRect(&bounds);
    uint8_t coverage = GrRandomCoverage(random);
    GrAAType aaType = GrAAType::kNone;
    if (GrFSAAType::kUnifiedMSAA == fsaaType && random->nextBool()) {
        aaType = GrAAType::kMSAA;
    }
    return DefaultPathOp::Make(std::move(paint), path, srcSpaceTol, coverage, viewMatrix, true,
                               aaType, bounds, GrGetRandomStencil(random, context));
}

#endif
