/*
 * 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 "src/gpu/ganesh/ops/AAHairLinePathRenderer.h"

#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPath.h"
#include "include/core/SkPoint.h"
#include "include/core/SkPoint3.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSpan.h"
#include "include/core/SkString.h"
#include "include/core/SkStrokeRec.h"
#include "include/gpu/ganesh/GrRecordingContext.h"
#include "include/private/SkAlignedStorage.h"
#include "include/private/SkAssert.h"
#include "include/private/SkDebug.h"
#include "include/private/SkFloatingPoint.h"
#include "include/private/SkMacros.h"
#include "include/private/SkMath.h"
#include "include/private/SkOnce.h"
#include "include/private/SkTArray.h"
#include "include/private/gpu/ganesh/GrTypesPriv.h"
#include "src/core/SkColorData.h"
#include "src/core/SkGeometry.h"
#include "src/core/SkMatrixPriv.h"
#include "src/core/SkPointPriv.h"
#include "src/core/SkSafeMath.h"
#include "src/gpu/ResourceKey.h"
#include "src/gpu/ganesh/GrAppliedClip.h"
#include "src/gpu/ganesh/GrAuditTrail.h"
#include "src/gpu/ganesh/GrBuffer.h"
#include "src/gpu/ganesh/GrCaps.h"
#include "src/gpu/ganesh/GrColor.h"
#include "src/gpu/ganesh/GrDefaultGeoProcFactory.h"
#include "src/gpu/ganesh/GrDrawOpTest.h"
#include "src/gpu/ganesh/GrGeometryProcessor.h"
#include "src/gpu/ganesh/GrMeshDrawTarget.h"
#include "src/gpu/ganesh/GrOpFlushState.h"
#include "src/gpu/ganesh/GrPaint.h"
#include "src/gpu/ganesh/GrProcessorAnalysis.h"
#include "src/gpu/ganesh/GrProcessorSet.h"
#include "src/gpu/ganesh/GrProgramInfo.h"
#include "src/gpu/ganesh/GrRecordingContextPriv.h"
#include "src/gpu/ganesh/GrRenderTargetProxy.h"
#include "src/gpu/ganesh/GrResourceProvider.h"
#include "src/gpu/ganesh/GrShaderCaps.h"
#include "src/gpu/ganesh/GrSimpleMesh.h"
#include "src/gpu/ganesh/GrStyle.h"
#include "src/gpu/ganesh/GrSurfaceProxyView.h"
#include "src/gpu/ganesh/GrTestUtils.h"
#include "src/gpu/ganesh/GrUtil.h"
#include "src/gpu/ganesh/SurfaceDrawContext.h"
#include "src/gpu/ganesh/effects/GrBezierEffect.h"
#include "src/gpu/ganesh/geometry/GrPathUtils.h"
#include "src/gpu/ganesh/geometry/GrStyledShape.h"
#include "src/gpu/ganesh/ops/GrMeshDrawOp.h"
#include "src/gpu/ganesh/ops/GrOp.h"
#include "src/gpu/ganesh/ops/GrSimpleMeshDrawOpHelper.h"
#include "src/gpu/ganesh/ops/GrSimpleMeshDrawOpHelperWithStencil.h"

#include <algorithm>
#include <array>
#include <cstdint>
#include <cstring>
#include <utility>

class GrDstProxyView;
class GrPipeline;
class SkArenaAlloc;
class SkRandom;
enum class GrXferBarrierFlags;
struct GrUserStencilSettings;

using namespace skia_private;

#define PREALLOC_PTARRAY(N) STArray<(N),SkPoint, true>

using PtArray = TArray<SkPoint, true>;
using IntArray = TArray<int, true>;
using FloatArray = TArray<float, true>;

namespace {

// quadratics are rendered as 5-sided polys in order to bound the
// AA stroke around the center-curve. See comments in push_quad_index_buffer and
// bloat_quad. Quadratics and conics share an index buffer

// lines are rendered as:
//      *______________*
//      |\ -_______   /|
//      | \        \ / |
//      |  *--------*  |
//      | /  ______/ \ |
//      */_-__________\*
// For: 6 vertices and 18 indices (for 6 triangles)

// Each quadratic is rendered as a five sided polygon. This poly bounds
// the quadratic's bounding triangle but has been expanded so that the
// 1-pixel wide area around the curve is inside the poly.
// If a,b,c are the original control points then the poly a0,b0,c0,c1,a1
// that is rendered would look like this:
//              b0
//              b
//
//     a0              c0
//      a            c
//       a1       c1
// Each is drawn as three triangles ((a0,a1,b0), (b0,c1,c0), (a1,c1,b0))
// specified by these 9 indices:
static const uint16_t kQuadIdxBufPattern[] = {
    0, 1, 2,
    2, 4, 3,
    1, 4, 2
};

static const int kIdxsPerQuad = std::size(kQuadIdxBufPattern);
static const int kQuadNumVertices = 5;
static const int kQuadsNumInIdxBuffer = 256;
SKGPU_DECLARE_STATIC_UNIQUE_KEY(gQuadsIndexBufferKey);

sk_sp<const GrBuffer> get_quads_index_buffer(GrResourceProvider* resourceProvider) {
    SKGPU_DEFINE_STATIC_UNIQUE_KEY(gQuadsIndexBufferKey);
    return resourceProvider->findOrCreatePatternedIndexBuffer(
        kQuadIdxBufPattern, kIdxsPerQuad, kQuadsNumInIdxBuffer, kQuadNumVertices,
        gQuadsIndexBufferKey);
}


// Each line segment is rendered as two quads and two triangles.
// p0 and p1 have alpha = 1 while all other points have alpha = 0.
// The four external points are offset 1 pixel perpendicular to the
// line and half a pixel parallel to the line.
//
// p4                  p5
//      p0         p1
// p2                  p3
//
// Each is drawn as six triangles specified by these 18 indices:

static const uint16_t kLineSegIdxBufPattern[] = {
    0, 1, 3,
    0, 3, 2,
    0, 4, 5,
    0, 5, 1,
    0, 2, 4,
    1, 5, 3
};

static const int kIdxsPerLineSeg = std::size(kLineSegIdxBufPattern);
static const int kLineSegNumVertices = 6;
static const int kLineSegsNumInIdxBuffer = 256;

SKGPU_DECLARE_STATIC_UNIQUE_KEY(gLinesIndexBufferKey);

sk_sp<const GrBuffer> get_lines_index_buffer(GrResourceProvider* resourceProvider) {
    SKGPU_DEFINE_STATIC_UNIQUE_KEY(gLinesIndexBufferKey);
    return resourceProvider->findOrCreatePatternedIndexBuffer(
        kLineSegIdxBufPattern, kIdxsPerLineSeg,  kLineSegsNumInIdxBuffer, kLineSegNumVertices,
        gLinesIndexBufferKey);
}

// Takes 178th time of logf on Z600 / VC2010
int get_float_exp(float x) {
    static_assert(sizeof(int) == sizeof(float));
#ifdef SK_DEBUG
    static bool tested;
    if (!tested) {
        tested = true;
        SkASSERT(get_float_exp(0.25f) == -2);
        SkASSERT(get_float_exp(0.3f) == -2);
        SkASSERT(get_float_exp(0.5f) == -1);
        SkASSERT(get_float_exp(1.f) == 0);
        SkASSERT(get_float_exp(2.f) == 1);
        SkASSERT(get_float_exp(2.5f) == 1);
        SkASSERT(get_float_exp(8.f) == 3);
        SkASSERT(get_float_exp(100.f) == 6);
        SkASSERT(get_float_exp(1000.f) == 9);
        SkASSERT(get_float_exp(1024.f) == 10);
        SkASSERT(get_float_exp(3000000.f) == 21);
    }
#endif
    const int* iptr = (const int*)&x;
    return (((*iptr) & 0x7f800000) >> 23) - 127;
}

// Uses the max curvature function for quads to estimate
// where to chop the conic. If the max curvature is not
// found along the curve segment it will return 1 and
// dst[0] is the original conic. If it returns 2 the dst[0]
// and dst[1] are the two new conics.
int split_conic(const SkPoint src[3], SkConic dst[2], const SkScalar weight) {
    SkScalar t = SkFindQuadMaxCurvature(src);
    // SkFindQuadMaxCurvature() returns either a value in [0, 1) or NaN.
    // However, passing NaN to conic.chopAt() will assert. Checking to see if
    // t is in (0,1) will also cover the NaN case since NaN comparisons are always
    // false, so we'll drop down into the else block in that case.
    if (0 < t && t < 1) {
        if (dst) {
            SkConic conic;
            conic.set(src, weight);
            if (!conic.chopAt(t, dst)) {
                dst[0].set(src, weight);
                return 1;
            }
        }
        return 2;
    } else {
        if (dst) {
            dst[0].set(src, weight);
        }
        return 1;
    }
}

// Calls split_conic on the entire conic and then once more on each subsection.
// Most cases will result in either 1 conic (chop point is not within t range)
// or 3 points (split once and then one subsection is split again).
int chop_conic(const SkPoint src[3], SkConic dst[4], const SkScalar weight) {
    SkConic dstTemp[2];
    int conicCnt = split_conic(src, dstTemp, weight);
    if (2 == conicCnt) {
        int conicCnt2 = split_conic(dstTemp[0].fPts, dst, dstTemp[0].fW);
        conicCnt = conicCnt2 + split_conic(dstTemp[1].fPts, &dst[conicCnt2], dstTemp[1].fW);
    } else {
        dst[0] = dstTemp[0];
    }
    return conicCnt;
}

// returns 0 if quad/conic is degen or close to it
// in this case approx the path with lines
// otherwise returns 1
int is_degen_quad_or_conic(const SkPoint p[3], SkScalar* dsqd) {
    static const SkScalar gDegenerateToLineTol = GrPathUtils::kDefaultTolerance;
    static const SkScalar gDegenerateToLineTolSqd =
        gDegenerateToLineTol * gDegenerateToLineTol;

    if (SkPointPriv::DistanceToSqd(p[0], p[1]) < gDegenerateToLineTolSqd ||
        SkPointPriv::DistanceToSqd(p[1], p[2]) < gDegenerateToLineTolSqd) {
        return 1;
    }

    *dsqd = SkPointPriv::DistanceToLineBetweenSqd(p[1], p[0], p[2]);
    if (*dsqd < gDegenerateToLineTolSqd) {
        return 1;
    }

    if (SkPointPriv::DistanceToLineBetweenSqd(p[2], p[1], p[0]) < gDegenerateToLineTolSqd) {
        return 1;
    }
    return 0;
}

int is_degen_quad_or_conic(const SkPoint p[3]) {
    SkScalar dsqd;
    return is_degen_quad_or_conic(p, &dsqd);
}

// we subdivide the quads to avoid huge overfill
// if it returns -1 then should be drawn as lines
int num_quad_subdivs(const SkPoint p[3]) {
    SkScalar dsqd;
    if (is_degen_quad_or_conic(p, &dsqd)) {
        return -1;
    }

    // tolerance of triangle height in pixels
    // tuned on windows  Quadro FX 380 / Z600
    // trade off of fill vs cpu time on verts
    // maybe different when do this using gpu (geo or tess shaders)
    static const SkScalar gSubdivTol = 175 * SK_Scalar1;

    if (dsqd <= gSubdivTol * gSubdivTol) {
        return 0;
    } else {
        static const int kMaxSub = 4;
        // subdividing the quad reduces d by 4. so we want x = log4(d/tol)
        // = log4(d*d/tol*tol)/2
        // = log2(d*d/tol*tol)

        // +1 since we're ignoring the mantissa contribution.
        int log = get_float_exp(dsqd/(gSubdivTol*gSubdivTol)) + 1;
        log = std::min(std::max(0, log), kMaxSub);
        return log;
    }
}

/**
 * Generates the lines and quads to be rendered. Lines are always recorded in
 * device space. We will do a device space bloat to account for the 1pixel
 * thickness.
 * Quads are recorded in device space unless m contains
 * perspective, then in they are in src space. We do this because we will
 * subdivide large quads to reduce over-fill. This subdivision has to be
 * performed before applying the perspective matrix.
 */
int gather_lines_and_quads(const SkPath& path,
                           const SkMatrix& m,
                           const SkIRect& devClipBounds,
                           SkScalar capLength,
                           bool convertConicsToQuads,
                           PtArray* lines,
                           PtArray* quads,
                           PtArray* conics,
                           IntArray* quadSubdivCnts,
                           FloatArray* conicWeights) {
    int totalQuadCount = 0;
    bool persp = m.hasPerspective();

    // Whenever a degenerate, zero-length contour is encountered, this code will insert a
    // 'capLength' x-aligned line segment. Since this is rendering hairlines it is hoped this will
    // suffice for AA square & circle capping.
    int verbsInContour = 0; // Does not count moves
    bool seenZeroLengthVerb = false;
    SkPoint zeroVerbPt;

    auto safeIBounds = [](SkSpan<const SkPoint> pts) {
        return SkRect::BoundsOrEmpty(pts).makeOutset(1, 1).roundOut();
    };

    // Adds a quad that has already been chopped to the list and checks for quads that are close to
    // lines. Also does a bounding box check. It takes points that are in src space and device
    // space. The src points are only required if the view matrix has perspective.
    auto addChoppedQuad = [&](const SkPoint srcPts[3], const SkPoint devPts[4],
                              bool isContourStart) {
        // We only need the src space space pts when not in perspective.
        SkASSERT(srcPts || !persp);
        if (SkIRect::Intersects(devClipBounds, safeIBounds({devPts, 3}))) {
            int subdiv = num_quad_subdivs(devPts);
            SkASSERT(subdiv >= -1);
            if (-1 == subdiv) {
                SkPoint* pts = lines->push_back_n(4);
                pts[0] = devPts[0];
                pts[1] = devPts[1];
                pts[2] = devPts[1];
                pts[3] = devPts[2];
                if (isContourStart && pts[0] == pts[1] && pts[2] == pts[3]) {
                    seenZeroLengthVerb = true;
                    zeroVerbPt = pts[0];
                }
            } else {
                // when in perspective keep quads in src space
                const SkPoint* qPts = persp ? srcPts : devPts;
                SkPoint* pts = quads->push_back_n(3);
                pts[0] = qPts[0];
                pts[1] = qPts[1];
                pts[2] = qPts[2];
                quadSubdivCnts->push_back() = subdiv;
                totalQuadCount += 1 << subdiv;
            }
        }
    };

    // common code for handline lines
    auto handleLineVerb = [&](SkSpan<const SkPoint> pathPts) {
        SkPoint devPts[2];
        m.mapPoints(devPts, pathPts);
        if (SkIRect::Intersects(devClipBounds, safeIBounds({devPts, 2}))) {
            SkPoint* pts = lines->push_back_n(2);
            pts[0] = devPts[0];
            pts[1] = devPts[1];
            if (verbsInContour == 0 && pts[0] == pts[1]) {
                seenZeroLengthVerb = true;
                zeroVerbPt = pts[0];
            }
        }
        verbsInContour++;
    };

    // Applies the view matrix to quad src points and calls the above helper.
    auto addSrcChoppedQuad = [&](const SkPoint srcSpaceQuadPts[3], bool isContourStart) {
        SkPoint devPts[3];
        m.mapPoints(devPts, {srcSpaceQuadPts, 3});
        addChoppedQuad(srcSpaceQuadPts, devPts, isContourStart);
    };

    SkPoint pathPts[4] = {{0, 0}, {0, 0}, {0, 0}, {0, 0}};
    for (auto iter = path.iter(); auto rec = iter.next();) {
        std::copy(rec->fPoints.begin(), rec->fPoints.end(), pathPts);
        switch (rec->fVerb) {
            case SkPathVerb::kConic:
                if (convertConicsToQuads) {
                    SkScalar weight = rec->conicWeight();
                    SkAutoConicToQuads converter;
                    const SkPoint* quadPts = converter.computeQuads(pathPts, weight, 0.25f);
                    for (int i = 0; i < converter.countQuads(); ++i) {
                        addSrcChoppedQuad(quadPts + 2 * i, !verbsInContour && 0 == i);
                    }
                } else {
                    SkConic dst[4];
                    // We chop the conics to create tighter clipping to hide error
                    // that appears near max curvature of very thin conics. Thin
                    // hyperbolas with high weight still show error.
                    int conicCnt = chop_conic(pathPts, dst, rec->conicWeight());
                    for (int i = 0; i < conicCnt; ++i) {
                        SkPoint devPts[4];
                        SkPoint* chopPnts = dst[i].fPts;
                        m.mapPoints({devPts, 3}, {chopPnts, 3});
                        if (SkIRect::Intersects(devClipBounds, safeIBounds({devPts, 3}))) {
                            if (is_degen_quad_or_conic(devPts)) {
                                SkPoint* pts = lines->push_back_n(4);
                                pts[0] = devPts[0];
                                pts[1] = devPts[1];
                                pts[2] = devPts[1];
                                pts[3] = devPts[2];
                                if (verbsInContour == 0 && i == 0 && pts[0] == pts[1] &&
                                    pts[2] == pts[3]) {
                                    seenZeroLengthVerb = true;
                                    zeroVerbPt = pts[0];
                                }
                            } else {
                                // when in perspective keep conics in src space
                                SkPoint* cPts = persp ? chopPnts : devPts;
                                SkPoint* pts = conics->push_back_n(3);
                                pts[0] = cPts[0];
                                pts[1] = cPts[1];
                                pts[2] = cPts[2];
                                conicWeights->push_back() = dst[i].fW;
                            }
                        }
                    }
                }
                verbsInContour++;
                break;
            case SkPathVerb::kMove:
                // New contour (and last one was unclosed). If it was just a zero length drawing
                // operation, and we're supposed to draw caps, then add a tiny line.
                if (seenZeroLengthVerb && verbsInContour == 1 && capLength > 0) {
                    SkPoint* pts = lines->push_back_n(2);
                    pts[0] = SkPoint::Make(zeroVerbPt.fX - capLength, zeroVerbPt.fY);
                    pts[1] = SkPoint::Make(zeroVerbPt.fX + capLength, zeroVerbPt.fY);
                }
                verbsInContour = 0;
                seenZeroLengthVerb = false;
                break;
            case SkPathVerb::kLine:
                handleLineVerb({pathPts, 2});
                break;
            case SkPathVerb::kQuad: {
                SkPoint choppedPts[5];
                // Chopping the quad helps when the quad is either degenerate or nearly degenerate.
                // When it is degenerate it allows the approximation with lines to work since the
                // chop point (if there is one) will be at the parabola's vertex. In the nearly
                // degenerate the QuadUVMatrix computed for the points is almost singular which
                // can cause rendering artifacts.
                int n = SkChopQuadAtMaxCurvature(pathPts, choppedPts);
                for (int i = 0; i < n; ++i) {
                    addSrcChoppedQuad(choppedPts + i * 2, !verbsInContour && 0 == i);
                }
                verbsInContour++;
                break;
            }
            case SkPathVerb::kCubic: {
                SkPoint devPts[4];
                m.mapPoints(devPts, {pathPts, 4});
                if (SkIRect::Intersects(devClipBounds, safeIBounds({devPts, 4}))) {
                    PREALLOC_PTARRAY(32) q;
                    // We convert cubics to quadratics (for now).
                    // In perspective have to do conversion in src space.
                    if (persp) {
                        SkScalar tolScale =
                            GrPathUtils::scaleToleranceToSrc(SK_Scalar1, m, path.getBounds());
                        GrPathUtils::convertCubicToQuads(pathPts, tolScale, &q);
                    } else {
                        GrPathUtils::convertCubicToQuads(devPts, SK_Scalar1, &q);
                    }
                    for (int i = 0; i < q.size(); i += 3) {
                        if (persp) {
                            addSrcChoppedQuad(&q[i], !verbsInContour && 0 == i);
                        } else {
                            addChoppedQuad(nullptr, &q[i], !verbsInContour && 0 == i);
                        }
                    }
                }
                verbsInContour++;
                break;
            }
            case SkPathVerb::kClose:
                if (pathPts[0] != pathPts[1]) {
                    handleLineVerb({pathPts, 2});
                }
                // Contour is closed, so we don't need to grow the starting line, unless it's
                // *just* a zero length subpath. (SVG Spec 11.4, 'stroke').
                if (capLength > 0) {
                    if (seenZeroLengthVerb && verbsInContour == 1) {
                        SkPoint* pts = lines->push_back_n(2);
                        pts[0] = SkPoint::Make(zeroVerbPt.fX - capLength, zeroVerbPt.fY);
                        pts[1] = SkPoint::Make(zeroVerbPt.fX + capLength, zeroVerbPt.fY);
                    } else if (verbsInContour == 0) {
                        // Contour was (moveTo, close). Add a line.
                        SkPoint devPts[2];
                        m.mapPoints({devPts, 1}, {pathPts, 1});
                        devPts[1] = devPts[0];
                        if (SkIRect::Intersects(devClipBounds, safeIBounds({devPts, 2}))) {
                            SkPoint* pts = lines->push_back_n(2);
                            pts[0] = SkPoint::Make(devPts[0].fX - capLength, devPts[0].fY);
                            pts[1] = SkPoint::Make(devPts[1].fX + capLength, devPts[1].fY);
                        }
                    }
                }
                break;
        }
    }
    if (seenZeroLengthVerb && verbsInContour == 1 && capLength > 0) {
        // Path ended with a dangling (moveTo, line|quad|etc). If the final verb is
        // degenerate, we need to draw a line.
        SkPoint* pts = lines->push_back_n(2);
        pts[0] = SkPoint::Make(zeroVerbPt.fX - capLength, zeroVerbPt.fY);
        pts[1] = SkPoint::Make(zeroVerbPt.fX + capLength, zeroVerbPt.fY);
    }
    return totalQuadCount;
}

struct LineVertex {
    SkPoint fPos;
    float fCoverage;
};

struct BezierVertex {
    SkPoint fPos;
    union {
        struct {
            SkScalar fKLM[3];
        } fConic;
        SkVector   fQuadCoord;
        struct {
            SkScalar fBogus[4];
        };
    };
};

static_assert(sizeof(BezierVertex) == 3 * sizeof(SkPoint));

void intersect_lines(const SkPoint& ptA, const SkVector& normA,
                     const SkPoint& ptB, const SkVector& normB,
                     SkPoint* result) {

    SkScalar lineAW = -normA.dot(ptA);
    SkScalar lineBW = -normB.dot(ptB);

    SkScalar wInv = normA.fX * normB.fY - normA.fY * normB.fX;
    wInv = sk_ieee_float_divide(1.0f, wInv);
    if (!SkIsFinite(wInv)) {
        // lines are parallel, pick the point in between
        *result = (ptA + ptB)*SK_ScalarHalf;
        *result += normA;
    } else {
        result->fX = normA.fY * lineBW - lineAW * normB.fY;
        result->fX *= wInv;

        result->fY = lineAW * normB.fX - normA.fX * lineBW;
        result->fY *= wInv;
    }
}

void set_uv_quad(const SkPoint qpts[3], BezierVertex verts[kQuadNumVertices]) {
    // this should be in the src space, not dev coords, when we have perspective
    GrPathUtils::QuadUVMatrix DevToUV(qpts);
    DevToUV.apply(verts, kQuadNumVertices, sizeof(BezierVertex), sizeof(SkPoint));
}

bool bloat_quad(const SkPoint qpts[3],
                const SkMatrix* toDevice,
                const SkMatrix* toSrc,
                BezierVertex verts[kQuadNumVertices]) {
    SkASSERT(!toDevice == !toSrc);
    // original quad is specified by tri a,b,c
    SkPoint a = qpts[0];
    SkPoint b = qpts[1];
    SkPoint c = qpts[2];

    if (toDevice) {
        a = toDevice->mapPoint(a);
        b = toDevice->mapPoint(b);
        c = toDevice->mapPoint(c);
    }
    // make a new poly where we replace a and c by a 1-pixel wide edges orthog
    // to edges ab and bc:
    //
    //   before       |        after
    //                |              b0
    //         b      |
    //                |
    //                |     a0            c0
    // a         c    |        a1       c1
    //
    // edges a0->b0 and b0->c0 are parallel to original edges a->b and b->c,
    // respectively.
    BezierVertex& a0 = verts[0];
    BezierVertex& a1 = verts[1];
    BezierVertex& b0 = verts[2];
    BezierVertex& c0 = verts[3];
    BezierVertex& c1 = verts[4];

    SkVector ab = b;
    ab -= a;
    SkVector ac = c;
    ac -= a;
    SkVector cb = b;
    cb -= c;

    // After the transform (or due to floating point math) we might have a line,
    // try to do something reasonable

    bool abNormalized = ab.normalize();
    bool cbNormalized = cb.normalize();

    if (!abNormalized) {
        if (!cbNormalized) {
            return false;          // Quad is degenerate so we won't add it.
        }

        ab = cb;
    }

    if (!cbNormalized) {
        cb = ab;
    }

    // We should have already handled degenerates
    SkASSERT(ab.length() > 0 && cb.length() > 0);

    SkVector abN = SkPointPriv::MakeOrthog(ab, SkPointPriv::kLeft_Side);
    if (abN.dot(ac) > 0) {
        abN.negate();
    }

    SkVector cbN = SkPointPriv::MakeOrthog(cb, SkPointPriv::kLeft_Side);
    if (cbN.dot(ac) < 0) {
        cbN.negate();
    }

    a0.fPos = a;
    a0.fPos += abN;
    a1.fPos = a;
    a1.fPos -= abN;

    if (toDevice && SkPointPriv::LengthSqd(ac) <= SK_ScalarNearlyZero*SK_ScalarNearlyZero) {
        c = b;
    }
    c0.fPos = c;
    c0.fPos += cbN;
    c1.fPos = c;
    c1.fPos -= cbN;

    intersect_lines(a0.fPos, abN, c0.fPos, cbN, &b0.fPos);

    if (toSrc) {
        SkMatrixPriv::MapPointsWithStride(*toSrc, &verts[0].fPos, sizeof(BezierVertex),
                                          kQuadNumVertices);
    }

    return true;
}

// Equations based off of Loop-Blinn Quadratic GPU Rendering
// Input Parametric:
// P(t) = (P0*(1-t)^2 + 2*w*P1*t*(1-t) + P2*t^2) / (1-t)^2 + 2*w*t*(1-t) + t^2)
// Output Implicit:
// f(x, y, w) = f(P) = K^2 - LM
// K = dot(k, P), L = dot(l, P), M = dot(m, P)
// k, l, m are calculated in function GrPathUtils::getConicKLM
void set_conic_coeffs(const SkPoint p[3],
                      BezierVertex verts[kQuadNumVertices],
                      const SkScalar weight) {
    SkMatrix klm;

    GrPathUtils::getConicKLM(p, weight, &klm);

    for (int i = 0; i < kQuadNumVertices; ++i) {
        const SkPoint3 pt3 = {verts[i].fPos.x(), verts[i].fPos.y(), 1.f};
        klm.mapHomogeneousPoints({(SkPoint3* ) verts[i].fConic.fKLM, 1},
                                 {&pt3, 1});
    }
}

static void backfill_degenerate_bezier(BezierVertex** vert) {
    memset(*vert, 0, kQuadNumVertices * sizeof(BezierVertex));
    for (int i = 0; i < kQuadNumVertices; ++i) {
        (*vert)[i].fPos.set(SK_ScalarMax, SK_ScalarMax);
    }
    *vert += kQuadNumVertices;
}

void add_conics(const SkPoint p[3],
                const SkScalar weight,
                const SkMatrix* toDevice,
                const SkMatrix* toSrc,
                BezierVertex** vert) {
    if (bloat_quad(p, toDevice, toSrc, *vert)) {
        set_conic_coeffs(p, *vert, weight);
        *vert += kQuadNumVertices;
    } else {
        backfill_degenerate_bezier(vert);
    }
}

void add_quads(const SkPoint p[3],
               int subdiv,
               const SkMatrix* toDevice,
               const SkMatrix* toSrc,
               BezierVertex** vert) {
    SkASSERT(subdiv >= 0);
    // temporary vertex storage to avoid reading the vertex buffer
    BezierVertex outVerts[kQuadNumVertices] = {};

    // storage for the chopped quad
    // pts 0,1,2 are the first quad, and 2,3,4 the second quad
    SkPoint choppedQuadPts[5];
    // start off with our original curve in the second quad slot
    memcpy(&choppedQuadPts[2], p, 3*sizeof(SkPoint));

    int stepCount = 1 << subdiv;
    while (stepCount > 1) {
        // The general idea is:
        // * chop the quad using pts 2,3,4 as the input
        // * write out verts using pts 0,1,2
        // * now 2,3,4 is the remainder of the curve, chop again until all subdivisions are done
        SkScalar h = 1.f / stepCount;
        SkChopQuadAt(&choppedQuadPts[2], choppedQuadPts, h);

        if (bloat_quad(choppedQuadPts, toDevice, toSrc, outVerts)) {
            set_uv_quad(choppedQuadPts, outVerts);
            memcpy(*vert, outVerts, kQuadNumVertices * sizeof(BezierVertex));
            *vert += kQuadNumVertices;
        } else {
            backfill_degenerate_bezier(vert);
        }
        --stepCount;
    }

    // finish up, write out the final quad
    if (bloat_quad(&choppedQuadPts[2], toDevice, toSrc, outVerts)) {
        set_uv_quad(&choppedQuadPts[2], outVerts);
        memcpy(*vert, outVerts, kQuadNumVertices * sizeof(BezierVertex));
        *vert += kQuadNumVertices;
    } else {
        backfill_degenerate_bezier(vert);
    }
}

void add_line(const SkPoint p[2],
              const SkMatrix* toSrc,
              uint8_t coverage,
              LineVertex** vert) {
    const SkPoint& a = p[0];
    const SkPoint& b = p[1];

    SkVector ortho, vec = b;
    vec -= a;

    SkScalar lengthSqd = SkPointPriv::LengthSqd(vec);

    if (vec.setLength(SK_ScalarHalf)) {
        // Create a vector orthogonal to 'vec' and of unit length
        ortho.fX = 2.0f * vec.fY;
        ortho.fY = -2.0f * vec.fX;

        float floatCoverage = GrNormalizeByteToFloat(coverage);

        if (lengthSqd >= 1.0f) {
            // Relative to points a and b:
            // The inner vertices are inset half a pixel along the line a,b
            (*vert)[0].fPos = a + vec;
            (*vert)[0].fCoverage = floatCoverage;
            (*vert)[1].fPos = b - vec;
            (*vert)[1].fCoverage = floatCoverage;
        } else {
            // The inner vertices are inset a distance of length(a,b) from the outer edge of
            // geometry. For the "a" inset this is the same as insetting from b by half a pixel.
            // The coverage is then modulated by the length. This gives us the correct
            // coverage for rects shorter than a pixel as they get translated subpixel amounts
            // inside of a pixel.
            SkScalar length = SkScalarSqrt(lengthSqd);
            (*vert)[0].fPos = b - vec;
            (*vert)[0].fCoverage = floatCoverage * length;
            (*vert)[1].fPos = a + vec;
            (*vert)[1].fCoverage = floatCoverage * length;
        }
        // Relative to points a and b:
        // The outer vertices are outset half a pixel along the line a,b and then a whole pixel
        // orthogonally.
        (*vert)[2].fPos = a - vec + ortho;
        (*vert)[2].fCoverage = 0;
        (*vert)[3].fPos = b + vec + ortho;
        (*vert)[3].fCoverage = 0;
        (*vert)[4].fPos = a - vec - ortho;
        (*vert)[4].fCoverage = 0;
        (*vert)[5].fPos = b + vec - ortho;
        (*vert)[5].fCoverage = 0;

        if (toSrc) {
            SkMatrixPriv::MapPointsWithStride(*toSrc, &(*vert)->fPos, sizeof(LineVertex),
                                              kLineSegNumVertices);
        }
    } else {
        // just make it degenerate and likely offscreen
        for (int i = 0; i < kLineSegNumVertices; ++i) {
            (*vert)[i].fPos.set(SK_ScalarMax, SK_ScalarMax);
        }
    }

    *vert += kLineSegNumVertices;
}

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

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

public:
    DEFINE_OP_CLASS_ID

    static GrOp::Owner Make(GrRecordingContext* context,
                            GrPaint&& paint,
                            const SkMatrix& viewMatrix,
                            const SkPath& path,
                            const GrStyle& style,
                            const SkIRect& devClipBounds,
                            const GrUserStencilSettings* stencilSettings) {
        SkScalar hairlineCoverage;
        uint8_t newCoverage = 0xff;
        if (GrIsStrokeHairlineOrEquivalent(style, viewMatrix, &hairlineCoverage)) {
            newCoverage = SkScalarRoundToInt(hairlineCoverage * 0xff);
        }

        const SkStrokeRec& stroke = style.strokeRec();
        SkScalar capLength = SkPaint::kButt_Cap != stroke.getCap() ? hairlineCoverage * 0.5f : 0.0f;

        return Helper::FactoryHelper<AAHairlineOp>(context, std::move(paint), newCoverage,
                                                   viewMatrix, path,
                                                   devClipBounds, capLength, stencilSettings);
    }

    AAHairlineOp(GrProcessorSet* processorSet,
                 const SkPMColor4f& color,
                 uint8_t coverage,
                 const SkMatrix& viewMatrix,
                 const SkPath& path,
                 SkIRect devClipBounds,
                 SkScalar capLength,
                 const GrUserStencilSettings* stencilSettings)
            : INHERITED(ClassID())
            , fHelper(processorSet, GrAAType::kCoverage, stencilSettings)
            , fColor(color)
            , fCoverage(coverage) {
        fPaths.emplace_back(PathData{viewMatrix, path, devClipBounds, capLength});

        this->setTransformedBounds(path.getBounds(), viewMatrix, HasAABloat::kYes,
                                   IsHairline::kYes);
    }

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

    void visitProxies(const GrVisitProxyFunc& func) const override {

        bool visited = false;
        for (int i = 0; i < 3; ++i) {
            if (fProgramInfos[i]) {
                fProgramInfos[i]->visitFPProxies(func);
                visited = true;
            }
        }

        if (!visited) {
            fHelper.visitProxies(func);
        }
    }

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

    GrProcessorSet::Analysis finalize(const GrCaps& caps, const GrAppliedClip* clip,
                                      GrClampType clampType) override {
        // This Op uses uniform (not vertex) color, so doesn't need to track wide color.
        return fHelper.finalizeProcessors(caps, clip, clampType,
                                          GrProcessorAnalysisCoverage::kSingleChannel, &fColor,
                                          nullptr);
    }

    enum class Program : uint8_t {
        kNone  = 0x0,
        kLine  = 0x1,
        kQuad  = 0x2,
        kConic = 0x4,
    };

private:
    void makeLineProgramInfo(const GrCaps&, SkArenaAlloc*, const GrPipeline*,
                             const GrSurfaceProxyView& writeView,
                             bool usesMSAASurface,
                             const SkMatrix* geometryProcessorViewM,
                             const SkMatrix* geometryProcessorLocalM,
                             GrXferBarrierFlags renderPassXferBarriers,
                             GrLoadOp colorLoadOp);
    void makeQuadProgramInfo(const GrCaps&, SkArenaAlloc*, const GrPipeline*,
                             const GrSurfaceProxyView& writeView,
                             bool usesMSAASurface,
                             const SkMatrix* geometryProcessorViewM,
                             const SkMatrix* geometryProcessorLocalM,
                             GrXferBarrierFlags renderPassXferBarriers,
                             GrLoadOp colorLoadOp);
    void makeConicProgramInfo(const GrCaps&, SkArenaAlloc*, const GrPipeline*,
                              const GrSurfaceProxyView& writeView,
                              bool usesMSAASurface,
                              const SkMatrix* geometryProcessorViewM,
                              const SkMatrix* geometryProcessorLocalM,
                              GrXferBarrierFlags renderPassXferBarriers,
                              GrLoadOp colorLoadOp);

    GrProgramInfo* programInfo() override {
        // This Op has 3 programInfos and implements its own onPrePrepareDraws so this entry point
        // should really never be called.
        SkASSERT(0);
        return nullptr;
    }

    Program predictPrograms(const GrCaps*) const;

    void onCreateProgramInfo(const GrCaps*,
                             SkArenaAlloc*,
                             const GrSurfaceProxyView& writeView,
                             bool usesMSAASurface,
                             GrAppliedClip&&,
                             const GrDstProxyView&,
                             GrXferBarrierFlags renderPassXferBarriers,
                             GrLoadOp colorLoadOp) override;

    void onPrePrepareDraws(GrRecordingContext*,
                           const GrSurfaceProxyView& writeView,
                           GrAppliedClip*,
                           const GrDstProxyView&,
                           GrXferBarrierFlags renderPassXferBarriers,
                           GrLoadOp colorLoadOp) override;

    void onPrepareDraws(GrMeshDrawTarget*) override;
    void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;

    CombineResult onCombineIfPossible(GrOp* t, SkArenaAlloc*, const GrCaps& caps) override {
        AAHairlineOp* that = t->cast<AAHairlineOp>();

        if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
            return CombineResult::kCannotCombine;
        }

        if (this->viewMatrix().hasPerspective() != that->viewMatrix().hasPerspective()) {
            return CombineResult::kCannotCombine;
        }

        // We go to identity if we don't have perspective
        if (this->viewMatrix().hasPerspective() &&
            !SkMatrixPriv::CheapEqual(this->viewMatrix(), that->viewMatrix())) {
            return CombineResult::kCannotCombine;
        }

        // TODO we can actually combine hairlines if they are the same color in a kind of bulk
        // method but we haven't implemented this yet
        // TODO investigate going to vertex color and coverage?
        if (this->coverage() != that->coverage()) {
            return CombineResult::kCannotCombine;
        }

        if (this->color() != that->color()) {
            return CombineResult::kCannotCombine;
        }

        if (fHelper.usesLocalCoords() && !SkMatrixPriv::CheapEqual(this->viewMatrix(),
                                                                   that->viewMatrix())) {
            return CombineResult::kCannotCombine;
        }

        fPaths.push_back_n(that->fPaths.size(), that->fPaths.begin());
        return CombineResult::kMerged;
    }

#if defined(GPU_TEST_UTILS)
    SkString onDumpInfo() const override {
        return SkStringPrintf("Color: 0x%08x Coverage: 0x%02x, Count: %d\n%s",
                              fColor.toBytes_RGBA(), fCoverage, fPaths.size(),
                              fHelper.dumpInfo().c_str());
    }
#endif

    const SkPMColor4f& color() const { return fColor; }
    uint8_t coverage() const { return fCoverage; }
    const SkMatrix& viewMatrix() const { return fPaths[0].fViewMatrix; }

    struct PathData {
        SkMatrix fViewMatrix;
        SkPath fPath;
        SkIRect fDevClipBounds;
        SkScalar fCapLength;
    };

    STArray<1, PathData, true> fPaths;
    Helper fHelper;
    SkPMColor4f fColor;
    uint8_t fCoverage;

    Program        fCharacterization = Program::kNone;       // holds a mask of required programs
    std::array<GrSimpleMesh*, 3> fMeshes = {};
    std::array<GrProgramInfo*, 3> fProgramInfos = {};

    using INHERITED = GrMeshDrawOp;
};

SK_MAKE_BITFIELD_CLASS_OPS(AAHairlineOp::Program)

void AAHairlineOp::makeLineProgramInfo(const GrCaps& caps, SkArenaAlloc* arena,
                                       const GrPipeline* pipeline,
                                       const GrSurfaceProxyView& writeView,
                                       bool usesMSAASurface,
                                       const SkMatrix* geometryProcessorViewM,
                                       const SkMatrix* geometryProcessorLocalM,
                                       GrXferBarrierFlags renderPassXferBarriers,
                                       GrLoadOp colorLoadOp) {
    if (fProgramInfos[0]) {
        return;
    }

    GrGeometryProcessor* lineGP;
    {
        using namespace GrDefaultGeoProcFactory;

        Color color(this->color());
        LocalCoords localCoords(fHelper.usesLocalCoords() ? LocalCoords::kUsePosition_Type
                                                          : LocalCoords::kUnused_Type);
        localCoords.fMatrix = geometryProcessorLocalM;

        lineGP = GrDefaultGeoProcFactory::Make(arena,
                                               color,
                                               Coverage::kAttribute_Type,
                                               localCoords,
                                               *geometryProcessorViewM);
        SkASSERT(sizeof(LineVertex) == lineGP->vertexStride());
    }

    fProgramInfos[0] = GrSimpleMeshDrawOpHelper::CreateProgramInfo(
            &caps, arena, pipeline, writeView, usesMSAASurface, lineGP, GrPrimitiveType::kTriangles,
            renderPassXferBarriers, colorLoadOp, fHelper.stencilSettings());
}

void AAHairlineOp::makeQuadProgramInfo(const GrCaps& caps, SkArenaAlloc* arena,
                                       const GrPipeline* pipeline,
                                       const GrSurfaceProxyView& writeView,
                                       bool usesMSAASurface,
                                       const SkMatrix* geometryProcessorViewM,
                                       const SkMatrix* geometryProcessorLocalM,
                                       GrXferBarrierFlags renderPassXferBarriers,
                                       GrLoadOp colorLoadOp) {
    if (fProgramInfos[1]) {
        return;
    }

    GrGeometryProcessor* quadGP = GrQuadEffect::Make(arena,
                                                     this->color(),
                                                     *geometryProcessorViewM,
                                                     caps,
                                                     *geometryProcessorLocalM,
                                                     fHelper.usesLocalCoords(),
                                                     this->coverage());
    SkASSERT(sizeof(BezierVertex) == quadGP->vertexStride());

    fProgramInfos[1] = GrSimpleMeshDrawOpHelper::CreateProgramInfo(
            &caps, arena, pipeline, writeView, usesMSAASurface, quadGP, GrPrimitiveType::kTriangles,
            renderPassXferBarriers, colorLoadOp, fHelper.stencilSettings());
}

void AAHairlineOp::makeConicProgramInfo(const GrCaps& caps, SkArenaAlloc* arena,
                                        const GrPipeline* pipeline,
                                        const GrSurfaceProxyView& writeView,
                                        bool usesMSAASurface,
                                        const SkMatrix* geometryProcessorViewM,
                                        const SkMatrix* geometryProcessorLocalM,
                                        GrXferBarrierFlags renderPassXferBarriers,
                                        GrLoadOp colorLoadOp) {
    if (fProgramInfos[2]) {
        return;
    }

    GrGeometryProcessor* conicGP = GrConicEffect::Make(arena,
                                                       this->color(),
                                                       *geometryProcessorViewM,
                                                       caps,
                                                       *geometryProcessorLocalM,
                                                       fHelper.usesLocalCoords(),
                                                       this->coverage());
    SkASSERT(sizeof(BezierVertex) == conicGP->vertexStride());

    fProgramInfos[2] = GrSimpleMeshDrawOpHelper::CreateProgramInfo(
            &caps, arena, pipeline, writeView, usesMSAASurface, conicGP,
            GrPrimitiveType::kTriangles, renderPassXferBarriers, colorLoadOp,
            fHelper.stencilSettings());
}

AAHairlineOp::Program AAHairlineOp::predictPrograms(const GrCaps* caps) const {
    bool convertConicsToQuads = !caps->shaderCaps()->fFloatIs32Bits;

    // When predicting the programs we always include the lineProgram bc it is used as a fallback
    // for quads and conics. In non-DDL mode there are cases where it sometimes isn't needed for a
    // given path.
    Program neededPrograms = Program::kLine;

    for (int i = 0; i < fPaths.size(); i++) {
        uint32_t mask = fPaths[i].fPath.getSegmentMasks();

        if (mask & (SkPath::kQuad_SegmentMask | SkPath::kCubic_SegmentMask)) {
            neededPrograms |= Program::kQuad;
        }
        if (mask & SkPath::kConic_SegmentMask) {
            if (convertConicsToQuads) {
                neededPrograms |= Program::kQuad;
            } else {
                neededPrograms |= Program::kConic;
            }
        }
    }

    return neededPrograms;
}

void AAHairlineOp::onCreateProgramInfo(const GrCaps* caps,
                                       SkArenaAlloc* arena,
                                       const GrSurfaceProxyView& writeView,
                                       bool usesMSAASurface,
                                       GrAppliedClip&& appliedClip,
                                       const GrDstProxyView& dstProxyView,
                                       GrXferBarrierFlags renderPassXferBarriers,
                                       GrLoadOp colorLoadOp) {
    // Setup the viewmatrix and localmatrix for the GrGeometryProcessor.
    auto inverse = this->viewMatrix().invert();
    if (!inverse) {
        return;
    }

    // we will transform to identity space if the viewmatrix does not have perspective
    bool hasPerspective = this->viewMatrix().hasPerspective();
    const SkMatrix* geometryProcessorViewM = &SkMatrix::I();
    const SkMatrix* geometryProcessorLocalM = &inverse.value();
    if (hasPerspective) {
        geometryProcessorViewM = &this->viewMatrix();
        geometryProcessorLocalM = &SkMatrix::I();
    }

    auto pipeline = fHelper.createPipeline(caps, arena, writeView.swizzle(),
                                           std::move(appliedClip), dstProxyView);

    if (fCharacterization & Program::kLine) {
        this->makeLineProgramInfo(*caps, arena, pipeline, writeView, usesMSAASurface,
                                  geometryProcessorViewM, geometryProcessorLocalM,
                                  renderPassXferBarriers, colorLoadOp);
    }
    if (fCharacterization & Program::kQuad) {
        this->makeQuadProgramInfo(*caps, arena, pipeline, writeView, usesMSAASurface,
                                  geometryProcessorViewM, geometryProcessorLocalM,
                                  renderPassXferBarriers, colorLoadOp);
    }
    if (fCharacterization & Program::kConic) {
        this->makeConicProgramInfo(*caps, arena, pipeline, writeView, usesMSAASurface,
                                   geometryProcessorViewM, geometryProcessorLocalM,
                                   renderPassXferBarriers, colorLoadOp);

    }
}

void AAHairlineOp::onPrePrepareDraws(GrRecordingContext* context,
                                     const GrSurfaceProxyView& writeView,
                                     GrAppliedClip* clip,
                                     const GrDstProxyView& dstProxyView,
                                     GrXferBarrierFlags renderPassXferBarriers,
                                     GrLoadOp colorLoadOp) {
    SkArenaAlloc* arena = context->priv().recordTimeAllocator();
    const GrCaps* caps = context->priv().caps();

    // skbug.com/40043298 -- DDL does not yet support DMSAA.
    bool usesMSAASurface = writeView.asRenderTargetProxy()->numSamples() > 1;

    // This is equivalent to a GrOpFlushState::detachAppliedClip
    GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip::Disabled();

    // Conservatively predict which programs will be required
    fCharacterization = this->predictPrograms(caps);

    this->createProgramInfo(caps, arena, writeView, usesMSAASurface, std::move(appliedClip),
                            dstProxyView, renderPassXferBarriers, colorLoadOp);

    context->priv().recordProgramInfo(fProgramInfos[0]);
    context->priv().recordProgramInfo(fProgramInfos[1]);
    context->priv().recordProgramInfo(fProgramInfos[2]);
}

void AAHairlineOp::onPrepareDraws(GrMeshDrawTarget* target) {
    // Setup the viewmatrix and localmatrix for the GrGeometryProcessor.
    auto inverse = this->viewMatrix().invert();
    if (!inverse) {
        return;
    }

    // we will transform to identity space if the viewmatrix does not have perspective
    const SkMatrix* toDevice = nullptr;
    const SkMatrix* toSrc = nullptr;
    if (this->viewMatrix().hasPerspective()) {
        toDevice = &this->viewMatrix();
        toSrc = &inverse.value();
    }

    SkDEBUGCODE(Program predictedPrograms = this->predictPrograms(&target->caps()));
    Program actualPrograms = Program::kNone;

    // This is hand inlined for maximum performance.
    PREALLOC_PTARRAY(128) lines;
    PREALLOC_PTARRAY(128) quads;
    PREALLOC_PTARRAY(128) conics;
    IntArray qSubdivs;
    FloatArray cWeights;
    int quadCount = 0;

    int instanceCount = fPaths.size();
    bool convertConicsToQuads = !target->caps().shaderCaps()->fFloatIs32Bits;
    SkSafeMath safeMath;
    for (int i = 0; i < instanceCount && safeMath.ok(); i++) {
        const PathData& args = fPaths[i];
        quadCount = safeMath.addInt(quadCount,
                                    gather_lines_and_quads(args.fPath,
                                                           args.fViewMatrix,
                                                           args.fDevClipBounds,
                                                           args.fCapLength,
                                                           convertConicsToQuads,
                                                           &lines,
                                                           &quads,
                                                           &conics,
                                                           &qSubdivs,
                                                           &cWeights));
    }

    int lineCount = lines.size() / 2;
    int conicCount = conics.size() / 3;
    int quadAndConicCount = safeMath.addInt(conicCount, quadCount);
    if (!safeMath.ok()) {
        return;
    }

    static constexpr int kMaxLines = SK_MaxS32 / kLineSegNumVertices;
    static constexpr int kMaxQuadsAndConics = SK_MaxS32 / kQuadNumVertices;
    if (lineCount > kMaxLines || quadAndConicCount > kMaxQuadsAndConics) {
        return;
    }

    // do lines first
    if (lineCount) {
        SkASSERT(predictedPrograms & Program::kLine);
        actualPrograms |= Program::kLine;

        sk_sp<const GrBuffer> linesIndexBuffer = get_lines_index_buffer(target->resourceProvider());

        GrMeshDrawOp::PatternHelper helper(target, GrPrimitiveType::kTriangles, sizeof(LineVertex),
                                           std::move(linesIndexBuffer), kLineSegNumVertices,
                                           kIdxsPerLineSeg, lineCount, kLineSegsNumInIdxBuffer);

        LineVertex* verts = reinterpret_cast<LineVertex*>(helper.vertices());
        if (!verts) {
            SkDebugf("Could not allocate vertices\n");
            return;
        }

        for (int i = 0; i < lineCount; ++i) {
            add_line(&lines[2*i], toSrc, this->coverage(), &verts);
        }

        fMeshes[0] = helper.mesh();
    }

    if (quadCount || conicCount) {
        sk_sp<const GrBuffer> vertexBuffer;
        int firstVertex;

        sk_sp<const GrBuffer> quadsIndexBuffer = get_quads_index_buffer(target->resourceProvider());

        int vertexCount = kQuadNumVertices * quadAndConicCount;
        void* vertices = target->makeVertexSpace(sizeof(BezierVertex), vertexCount, &vertexBuffer,
                                                 &firstVertex);

        if (!vertices || !quadsIndexBuffer) {
            SkDebugf("Could not allocate vertices\n");
            return;
        }

        // Setup vertices
        BezierVertex* bezVerts = reinterpret_cast<BezierVertex*>(vertices);

        int unsubdivQuadCnt = quads.size() / 3;
        for (int i = 0; i < unsubdivQuadCnt; ++i) {
            SkASSERT(qSubdivs[i] >= 0);
            if (!quads[3*i].isFinite() || !quads[3*i+1].isFinite() || !quads[3*i+2].isFinite()) {
                return;
            }
            add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &bezVerts);
        }

        // Start Conics
        for (int i = 0; i < conicCount; ++i) {
            add_conics(&conics[3*i], cWeights[i], toDevice, toSrc, &bezVerts);
        }

        if (quadCount > 0) {
            SkASSERT(predictedPrograms & Program::kQuad);
            actualPrograms |= Program::kQuad;

            fMeshes[1] = target->allocMesh();
            fMeshes[1]->setIndexedPatterned(quadsIndexBuffer, kIdxsPerQuad, quadCount,
                                            kQuadsNumInIdxBuffer, vertexBuffer, kQuadNumVertices,
                                            firstVertex);
            firstVertex += quadCount * kQuadNumVertices;
        }

        if (conicCount > 0) {
            SkASSERT(predictedPrograms & Program::kConic);
            actualPrograms |= Program::kConic;

            fMeshes[2] = target->allocMesh();
            fMeshes[2]->setIndexedPatterned(std::move(quadsIndexBuffer), kIdxsPerQuad, conicCount,
                                            kQuadsNumInIdxBuffer, std::move(vertexBuffer),
                                            kQuadNumVertices, firstVertex);
        }
    }

    // In DDL mode this will replace the predicted program requirements with the actual ones.
    // However, we will already have surfaced the predicted programs to the DDL.
    fCharacterization = actualPrograms;
}

void AAHairlineOp::onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) {
    this->createProgramInfo(flushState);

    for (int i = 0; i < 3; ++i) {
        if (fProgramInfos[i] && fMeshes[i]) {
            flushState->bindPipelineAndScissorClip(*fProgramInfos[i], chainBounds);
            flushState->bindTextures(fProgramInfos[i]->geomProc(), nullptr,
                                     fProgramInfos[i]->pipeline());
            flushState->drawMesh(*fMeshes[i]);
        }
    }
}

} // anonymous namespace

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

#if defined(GPU_TEST_UTILS)

GR_DRAW_OP_TEST_DEFINE(AAHairlineOp) {
    SkMatrix viewMatrix = GrTest::TestMatrix(random);
    const SkPath& path = GrTest::TestPath(random);
    SkIRect devClipBounds;
    devClipBounds.setEmpty();
    return AAHairlineOp::Make(context, std::move(paint), viewMatrix, path,
                              GrStyle::SimpleHairline(), devClipBounds,
                              GrGetRandomStencil(random, context));
}

#endif

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

namespace skgpu::ganesh {

PathRenderer::CanDrawPath AAHairLinePathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
    if (GrAAType::kCoverage != args.fAAType) {
        return CanDrawPath::kNo;
    }

    if (!GrIsStrokeHairlineOrEquivalent(args.fShape->style(), *args.fViewMatrix, nullptr)) {
        return CanDrawPath::kNo;
    }

    // We don't currently handle dashing in this class though perhaps we should.
    if (args.fShape->style().pathEffect()) {
        return CanDrawPath::kNo;
    }

    if (SkPath::kLine_SegmentMask == args.fShape->segmentMask() ||
        args.fCaps->shaderCaps()->fShaderDerivativeSupport) {
        return CanDrawPath::kYes;
    }

    return CanDrawPath::kNo;
}


bool AAHairLinePathRenderer::onDrawPath(const DrawPathArgs& args) {
    GR_AUDIT_TRAIL_AUTO_FRAME(args.fContext->priv().auditTrail(),
                              "AAHairlinePathRenderer::onDrawPath");
    SkASSERT(args.fSurfaceDrawContext->numSamples() <= 1);

    SkPath path = args.fShape->asPath();
    GrOp::Owner op =
            AAHairlineOp::Make(args.fContext, std::move(args.fPaint), *args.fViewMatrix, path,
                               args.fShape->style(), *args.fClipConservativeBounds,
                               args.fUserStencilSettings);
    args.fSurfaceDrawContext->addDrawOp(args.fClip, std::move(op));
    return true;
}

}  // namespace skgpu::ganesh
