/*
 * Copyright 2018 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/ccpr/GrCCStroker.h"

#include "include/core/SkStrokeRec.h"
#include "src/core/SkPathPriv.h"
#include "src/gpu/GrOnFlushResourceProvider.h"
#include "src/gpu/GrOpsRenderPass.h"
#include "src/gpu/GrProgramInfo.h"
#include "src/gpu/ccpr/GrAutoMapVertexBuffer.h"
#include "src/gpu/ccpr/GrCCCoverageProcessor.h"
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
#include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h"

static constexpr int kMaxNumLinearSegmentsLog2 = GrCCStrokeGeometry::kMaxNumLinearSegmentsLog2;
using TriangleInstance = GrCCCoverageProcessor::TriPointInstance;
using ConicInstance = GrCCCoverageProcessor::QuadPointInstance;

namespace {

struct LinearStrokeInstance {
    float fEndpoints[4];
    float fStrokeRadius;

    inline void set(const SkPoint[2], float dx, float dy, float strokeRadius);
};

inline void LinearStrokeInstance::set(const SkPoint P[2], float dx, float dy, float strokeRadius) {
    Sk2f X, Y;
    Sk2f::Load2(P, &X, &Y);
    Sk2f::Store2(fEndpoints, X + dx, Y + dy);
    fStrokeRadius = strokeRadius;
}

struct CubicStrokeInstance {
    float fX[4];
    float fY[4];
    float fStrokeRadius;
    float fNumSegments;

    inline void set(const SkPoint[4], float dx, float dy, float strokeRadius, int numSegments);
    inline void set(const Sk4f& X, const Sk4f& Y, float dx, float dy, float strokeRadius,
                    int numSegments);
};

inline void CubicStrokeInstance::set(const SkPoint P[4], float dx, float dy, float strokeRadius,
                                     int numSegments) {
    Sk4f X, Y;
    Sk4f::Load2(P, &X, &Y);
    this->set(X, Y, dx, dy, strokeRadius, numSegments);
}

inline void CubicStrokeInstance::set(const Sk4f& X, const Sk4f& Y, float dx, float dy,
                                     float strokeRadius, int numSegments) {
    (X + dx).store(&fX);
    (Y + dy).store(&fY);
    fStrokeRadius = strokeRadius;
    fNumSegments = static_cast<float>(numSegments);
}

// This class draws stroked lines in post-transform device space (a.k.a. rectangles). Rigid-body
// transforms can be achieved by transforming the line ahead of time and adjusting the stroke
// width. Skews of the stroke itself are not yet supported.
//
// Corner coverage is AA-correct, meaning, n^2 attenuation along the diagonals. This is important
// for seamless integration with the connecting geometry.
class LinearStrokeProcessor : public GrGeometryProcessor {
public:
    LinearStrokeProcessor() : INHERITED(kLinearStrokeProcessor_ClassID) {
        this->setInstanceAttributes(kInstanceAttribs, 2);
#ifdef SK_DEBUG
        using Instance = LinearStrokeInstance;
        SkASSERT(this->instanceStride() == sizeof(Instance));
#endif
    }

private:
    const char* name() const override { return "LinearStrokeProcessor"; }
    void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}

    static constexpr Attribute kInstanceAttribs[2] = {
            {"endpts", kFloat4_GrVertexAttribType, kFloat4_GrSLType},
            {"stroke_radius", kFloat_GrVertexAttribType, kFloat_GrSLType}
    };

    class Impl : public GrGLSLGeometryProcessor {
        void setData(const GrGLSLProgramDataManager&, const GrPrimitiveProcessor&,
                     const CoordTransformRange&) override {}
        void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override;
    };

    GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override {
        return new Impl();
    }

    typedef GrGeometryProcessor INHERITED;
};

void LinearStrokeProcessor::Impl::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
    GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;

    varyingHandler->emitAttributes(args.fGP.cast<LinearStrokeProcessor>());

    GrGLSLVertexBuilder* v = args.fVertBuilder;
    v->codeAppend ("float2 tan = normalize(endpts.zw - endpts.xy);");
    v->codeAppend ("float2 n = float2(tan.y, -tan.x);");
    v->codeAppend ("float nwidth = abs(n.x) + abs(n.y);");

    // Outset the vertex position for AA butt caps.
    v->codeAppend ("float2 outset = tan*nwidth/2;");
    v->codeAppend ("float2 position = (sk_VertexID < 2) "
                           "? endpts.xy - outset : endpts.zw + outset;");

    // Calculate Manhattan distance from both butt caps, where distance=0 on the actual endpoint and
    // distance=-.5 on the outset edge.
    GrGLSLVarying edgeDistances(kFloat4_GrSLType);
    varyingHandler->addVarying("edge_distances", &edgeDistances);
    v->codeAppendf("%s.xz = float2(-.5, dot(endpts.zw - endpts.xy, tan) / nwidth + .5);",
                   edgeDistances.vsOut());
    v->codeAppendf("%s.xz = (sk_VertexID < 2) ? %s.xz : %s.zx;",
                   edgeDistances.vsOut(), edgeDistances.vsOut(), edgeDistances.vsOut());

    // Outset the vertex position for stroke radius plus edge AA.
    v->codeAppend ("outset = n * (stroke_radius + nwidth/2);");
    v->codeAppend ("position += (0 == (sk_VertexID & 1)) ? +outset : -outset;");

    // Calculate Manhattan distance from both edges, where distance=0 on the actual edge and
    // distance=-.5 on the outset.
    v->codeAppendf("%s.yw = float2(-.5, 2*stroke_radius / nwidth + .5);", edgeDistances.vsOut());
    v->codeAppendf("%s.yw = (0 == (sk_VertexID & 1)) ? %s.yw : %s.wy;",
                   edgeDistances.vsOut(), edgeDistances.vsOut(), edgeDistances.vsOut());

    gpArgs->fPositionVar.set(kFloat2_GrSLType, "position");
    // Leave fLocalCoordVar uninitialized; this GP is not combined with frag processors

    // Use the 4 edge distances to calculate coverage in the fragment shader.
    GrGLSLFPFragmentBuilder* f = args.fFragBuilder;
    f->codeAppendf("half2 coverages = half2(min(%s.xy, .5) + min(%s.zw, .5));",
                   edgeDistances.fsIn(), edgeDistances.fsIn());
    f->codeAppendf("%s = half4(coverages.x * coverages.y);", args.fOutputColor);

    // This shader doesn't use the built-in Ganesh coverage.
    f->codeAppendf("%s = half4(1);", args.fOutputCoverage);
}

constexpr GrPrimitiveProcessor::Attribute LinearStrokeProcessor::kInstanceAttribs[];

// This class draws stroked cubics in post-transform device space. Rigid-body transforms can be
// achieved by transforming the curve ahead of time and adjusting the stroke width. Skews of the
// stroke itself are not yet supported. Quadratics can be drawn by converting them to cubics.
//
// This class works by finding stroke-width line segments orthogonal to the curve at a
// pre-determined number of evenly spaced points along the curve (evenly spaced in the parametric
// sense). It then connects the segments with a triangle strip. As for common in CCPR, clockwise-
// winding triangles from the strip emit positive coverage, counter-clockwise triangles emit
// negative, and we use SkBlendMode::kPlus.
class CubicStrokeProcessor : public GrGeometryProcessor {
public:
    CubicStrokeProcessor() : GrGeometryProcessor(kCubicStrokeProcessor_ClassID) {
        this->setInstanceAttributes(kInstanceAttribs, 3);
#ifdef SK_DEBUG
        using Instance = CubicStrokeInstance;
        SkASSERT(this->instanceStride() == sizeof(Instance));
#endif
    }

private:
    const char* name() const override { return "CubicStrokeProcessor"; }
    void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}

    static constexpr Attribute kInstanceAttribs[3] = {
            {"X", kFloat4_GrVertexAttribType, kFloat4_GrSLType},
            {"Y", kFloat4_GrVertexAttribType, kFloat4_GrSLType},
            {"stroke_info", kFloat2_GrVertexAttribType, kFloat2_GrSLType}
    };

    class Impl : public GrGLSLGeometryProcessor {
        void setData(const GrGLSLProgramDataManager&, const GrPrimitiveProcessor&,
                     const CoordTransformRange&) override {}
        void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override;
    };

    GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override {
        return new Impl();
    }
};

void CubicStrokeProcessor::Impl::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
    GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;

    varyingHandler->emitAttributes(args.fGP.cast<CubicStrokeProcessor>());

    GrGLSLVertexBuilder* v = args.fVertBuilder;
    v->codeAppend ("float4x2 P = transpose(float2x4(X, Y));");
    v->codeAppend ("float stroke_radius = stroke_info[0];");
    v->codeAppend ("float num_segments = stroke_info[1];");

    // Find the parametric T value at which we will emit our orthogonal line segment. We emit two
    // line segments at T=0 and double at T=1 as well for AA butt caps.
    v->codeAppend ("float point_id = float(sk_VertexID/2);");
    v->codeAppend ("float T = max((point_id - 1) / num_segments, 0);");
    v->codeAppend ("T = (point_id >= num_segments + 1) ? 1 : T;");  // In case x/x !== 1.

    // Use De Casteljau's algorithm to find the position and tangent for our orthogonal line
    // segment. De Casteljau's is more numerically stable than evaluating the curve and derivative
    // directly.
    v->codeAppend ("float2 ab = mix(P[0], P[1], T);");
    v->codeAppend ("float2 bc = mix(P[1], P[2], T);");
    v->codeAppend ("float2 cd = mix(P[2], P[3], T);");
    v->codeAppend ("float2 abc = mix(ab, bc, T);");
    v->codeAppend ("float2 bcd = mix(bc, cd, T);");
    v->codeAppend ("float2 position = mix(abc, bcd, T);");
    v->codeAppend ("float2 tan = bcd - abc;");

    // Find actual tangents for the corner cases when De Casteljau's yields tan=0. (We shouldn't
    // encounter other numerically unstable cases where tan ~= 0, because GrCCStrokeGeometry snaps
    // control points to endpoints in curves where they are almost equal.)
    v->codeAppend ("if (0 == T && P[0] == P[1]) {");
    v->codeAppend (    "tan = P[2] - P[0];");
    v->codeAppend ("}");
    v->codeAppend ("if (1 == T && P[2] == P[3]) {");
    v->codeAppend (    "tan = P[3] - P[1];");
    v->codeAppend ("}");
    v->codeAppend ("tan = normalize(tan);");
    v->codeAppend ("float2 n = float2(tan.y, -tan.x);");
    v->codeAppend ("float nwidth = abs(n.x) + abs(n.y);");

    // Outset the vertex position for stroke radius plus edge AA.
    v->codeAppend ("float2 outset = n * (stroke_radius + nwidth/2);");
    v->codeAppend ("position += (0 == (sk_VertexID & 1)) ? -outset : +outset;");

    // Calculate the Manhattan distance from both edges, where distance=0 on the actual edge and
    // distance=-.5 on the outset.
    GrGLSLVarying coverages(kFloat3_GrSLType);
    varyingHandler->addVarying("coverages", &coverages);
    v->codeAppendf("%s.xy = float2(-.5, 2*stroke_radius / nwidth + .5);", coverages.vsOut());
    v->codeAppendf("%s.xy = (0 == (sk_VertexID & 1)) ? %s.xy : %s.yx;",
                   coverages.vsOut(), coverages.vsOut(), coverages.vsOut());

    // Adjust the orthogonal line segments on the endpoints so they straddle the actual endpoint
    // at a Manhattan distance of .5 on either side.
    v->codeAppend ("if (0 == point_id || num_segments+1 == point_id) {");
    v->codeAppend (    "position -= tan*nwidth/2;");
    v->codeAppend ("}");
    v->codeAppend ("if (1 == point_id || num_segments+2 == point_id) {");
    v->codeAppend (    "position += tan*nwidth/2;");
    v->codeAppend ("}");

    // Interpolate coverage for butt cap AA from 0 on the outer segment to 1 on the inner.
    v->codeAppendf("%s.z = (0 == point_id || num_segments+2 == point_id) ? 0 : 1;",
                   coverages.vsOut());

    gpArgs->fPositionVar.set(kFloat2_GrSLType, "position");
    // Leave fLocalCoordVar uninitialized; this GP is not combined with frag processors

    // Use the 2 edge distances and interpolated butt cap AA to calculate fragment coverage.
    GrGLSLFPFragmentBuilder* f = args.fFragBuilder;
    f->codeAppendf("half2 edge_coverages = min(half2(%s.xy), .5);", coverages.fsIn());
    f->codeAppend ("half coverage = edge_coverages.x + edge_coverages.y;");
    f->codeAppendf("coverage *= half(%s.z);", coverages.fsIn());  // Butt cap AA.

    // As is common for CCPR, clockwise-winding triangles from the strip emit positive coverage, and
    // counter-clockwise triangles emit negative.
    f->codeAppendf("%s = half4(sk_Clockwise ? +coverage : -coverage);", args.fOutputColor);

    // This shader doesn't use the built-in Ganesh coverage.
    f->codeAppendf("%s = half4(1);", args.fOutputCoverage);
}

constexpr GrPrimitiveProcessor::Attribute CubicStrokeProcessor::kInstanceAttribs[];

}  // anonymous namespace

void GrCCStroker::parseDeviceSpaceStroke(const SkPath& path, const SkPoint* deviceSpacePts,
                                         const SkStrokeRec& stroke, float strokeDevWidth,
                                         GrScissorTest scissorTest,
                                         const SkIRect& clippedDevIBounds,
                                         const SkIVector& devToAtlasOffset) {
    SkASSERT(SkStrokeRec::kStroke_Style == stroke.getStyle() ||
             SkStrokeRec::kHairline_Style == stroke.getStyle());
    SkASSERT(!fInstanceBuffer);
    SkASSERT(!path.isEmpty());

    if (!fHasOpenBatch) {
        fBatches.emplace_back(&fTalliesAllocator, *fInstanceCounts[(int)GrScissorTest::kDisabled],
                              fScissorSubBatches.count());
        fInstanceCounts[(int)GrScissorTest::kDisabled] = fBatches.back().fNonScissorEndInstances;
        fHasOpenBatch = true;
    }

    InstanceTallies* currStrokeEndIndices;
    if (GrScissorTest::kEnabled == scissorTest) {
        SkASSERT(fBatches.back().fEndScissorSubBatch == fScissorSubBatches.count());
        fScissorSubBatches.emplace_back(&fTalliesAllocator,
                                        *fInstanceCounts[(int)GrScissorTest::kEnabled],
                                        clippedDevIBounds.makeOffset(devToAtlasOffset));
        fBatches.back().fEndScissorSubBatch = fScissorSubBatches.count();
        fInstanceCounts[(int)GrScissorTest::kEnabled] =
                currStrokeEndIndices = fScissorSubBatches.back().fEndInstances;
    } else {
        currStrokeEndIndices = fBatches.back().fNonScissorEndInstances;
    }

    fGeometry.beginPath(stroke, strokeDevWidth, currStrokeEndIndices);

    fPathInfos.push_back() = {devToAtlasOffset, strokeDevWidth/2, scissorTest};

    int devPtsIdx = 0;
    SkPath::Verb previousVerb = SkPath::kClose_Verb;

    for (SkPath::Verb verb : SkPathPriv::Verbs(path)) {
        SkASSERT(SkPath::kDone_Verb != previousVerb);
        const SkPoint* P = &deviceSpacePts[devPtsIdx - 1];
        switch (verb) {
            case SkPath::kMove_Verb:
                if (devPtsIdx > 0 && SkPath::kClose_Verb != previousVerb) {
                    fGeometry.capContourAndExit();
                }
                fGeometry.moveTo(deviceSpacePts[devPtsIdx]);
                ++devPtsIdx;
                break;
            case SkPath::kClose_Verb:
                SkASSERT(SkPath::kClose_Verb != previousVerb);
                fGeometry.closeContour();
                break;
            case SkPath::kLine_Verb:
                SkASSERT(SkPath::kClose_Verb != previousVerb);
                fGeometry.lineTo(P[1]);
                ++devPtsIdx;
                break;
            case SkPath::kQuad_Verb:
                SkASSERT(SkPath::kClose_Verb != previousVerb);
                fGeometry.quadraticTo(P);
                devPtsIdx += 2;
                break;
            case SkPath::kCubic_Verb: {
                SkASSERT(SkPath::kClose_Verb != previousVerb);
                fGeometry.cubicTo(P);
                devPtsIdx += 3;
                break;
            }
            case SkPath::kConic_Verb:
                SkASSERT(SkPath::kClose_Verb != previousVerb);
                SK_ABORT("Stroked conics not supported.");
                break;
            case SkPath::kDone_Verb:
                break;
        }
        previousVerb = verb;
    }

    if (devPtsIdx > 0 && SkPath::kClose_Verb != previousVerb) {
        fGeometry.capContourAndExit();
    }
}

// This class encapsulates the process of expanding ready-to-draw geometry from GrCCStrokeGeometry
// directly into GPU instance buffers.
class GrCCStroker::InstanceBufferBuilder {
public:
    InstanceBufferBuilder(GrOnFlushResourceProvider* onFlushRP, GrCCStroker* stroker) {
        memcpy(fNextInstances, stroker->fBaseInstances, sizeof(fNextInstances));
#ifdef SK_DEBUG
        fEndInstances[0] = stroker->fBaseInstances[0] + *stroker->fInstanceCounts[0];
        fEndInstances[1] = stroker->fBaseInstances[1] + *stroker->fInstanceCounts[1];
#endif

        int endConicsIdx = stroker->fBaseInstances[1].fConics +
                           stroker->fInstanceCounts[1]->fConics;
        fInstanceBuffer.resetAndMapBuffer(onFlushRP, endConicsIdx * sizeof(ConicInstance));
        if (!fInstanceBuffer.gpuBuffer()) {
            SkDebugf("WARNING: failed to allocate CCPR stroke instance buffer.\n");
            return;
        }
    }

    bool isMapped() const { return fInstanceBuffer.isMapped(); }

    void updateCurrentInfo(const PathInfo& pathInfo) {
        SkASSERT(this->isMapped());
        fCurrDX = static_cast<float>(pathInfo.fDevToAtlasOffset.x());
        fCurrDY = static_cast<float>(pathInfo.fDevToAtlasOffset.y());
        fCurrStrokeRadius = pathInfo.fStrokeRadius;
        fCurrNextInstances = &fNextInstances[(int)pathInfo.fScissorTest];
        SkDEBUGCODE(fCurrEndInstances = &fEndInstances[(int)pathInfo.fScissorTest]);
    }

    void appendLinearStroke(const SkPoint endpts[2]) {
        SkASSERT(this->isMapped());
        this->appendLinearStrokeInstance().set(endpts, fCurrDX, fCurrDY, fCurrStrokeRadius);
    }

    void appendQuadraticStroke(const SkPoint P[3], int numLinearSegmentsLog2) {
        SkASSERT(this->isMapped());
        SkASSERT(numLinearSegmentsLog2 > 0);

        Sk4f ptsT[2];
        Sk2f p0 = Sk2f::Load(P);
        Sk2f p1 = Sk2f::Load(P+1);
        Sk2f p2 = Sk2f::Load(P+2);

        // Convert the quadratic to cubic.
        Sk2f c1 = SkNx_fma(Sk2f(2/3.f), p1 - p0, p0);
        Sk2f c2 = SkNx_fma(Sk2f(1/3.f), p2 - p1, p1);
        Sk2f::Store4(ptsT, p0, c1, c2, p2);

        this->appendCubicStrokeInstance(numLinearSegmentsLog2).set(
                ptsT[0], ptsT[1], fCurrDX, fCurrDY, fCurrStrokeRadius, 1 << numLinearSegmentsLog2);
    }

    void appendCubicStroke(const SkPoint P[3], int numLinearSegmentsLog2) {
        SkASSERT(this->isMapped());
        SkASSERT(numLinearSegmentsLog2 > 0);
        this->appendCubicStrokeInstance(numLinearSegmentsLog2).set(
                P, fCurrDX, fCurrDY, fCurrStrokeRadius, 1 << numLinearSegmentsLog2);
    }

    void appendJoin(Verb joinVerb, const SkPoint& center, const SkVector& leftNorm,
                    const SkVector& rightNorm, float miterCapHeightOverWidth, float conicWeight) {
        SkASSERT(this->isMapped());

        Sk2f offset = Sk2f::Load(&center) + Sk2f(fCurrDX, fCurrDY);
        Sk2f n0 = Sk2f::Load(&leftNorm);
        Sk2f n1 = Sk2f::Load(&rightNorm);

        // Identify the outer edge.
        Sk2f cross = n0 * SkNx_shuffle<1,0>(n1);
        if (cross[0] < cross[1]) {
            Sk2f tmp = n0;
            n0 = -n1;
            n1 = -tmp;
        }

        if (!GrCCStrokeGeometry::IsInternalJoinVerb(joinVerb)) {
            // Normal joins are a triangle that connects the outer corners of two adjoining strokes.
            this->appendTriangleInstance().set(
                    n1 * fCurrStrokeRadius, Sk2f(0, 0), n0 * fCurrStrokeRadius, offset,
                    TriangleInstance::Ordering::kXYTransposed);
            if (Verb::kBevelJoin == joinVerb) {
                return;
            }
        } else {
            // Internal joins are coverage-counted, self-intersecting quadrilaterals that tie the
            // four corners of two adjoining strokes together a like a shoelace. Coverage is
            // negative on the inside half. We implement this geometry with a pair of triangles.
            this->appendTriangleInstance().set(
                    -n0 * fCurrStrokeRadius, n0 * fCurrStrokeRadius, n1 * fCurrStrokeRadius,
                    offset, TriangleInstance::Ordering::kXYTransposed);
            if (Verb::kBevelJoin == joinVerb) {
                return;
            }
            this->appendTriangleInstance().set(
                    -n0 * fCurrStrokeRadius, n1 * fCurrStrokeRadius, -n1 * fCurrStrokeRadius,
                    offset, TriangleInstance::Ordering::kXYTransposed);
            if (Verb::kBevelJoin == joinVerb) {
                return;
            }
            if (Verb::kInternalBevelJoin == joinVerb) {
                return;
            }
        }

        // For miter and round joins, we place an additional triangle cap on top of the bevel. This
        // triangle is literal for miters and is conic control points for round joins.
        SkASSERT(miterCapHeightOverWidth >= 0 || SkScalarIsNaN(miterCapHeightOverWidth));
        Sk2f base = n1 - n0;
        Sk2f baseNorm = Sk2f(base[1], -base[0]);
        Sk2f c = (n0 + n1) * .5f + baseNorm * miterCapHeightOverWidth;

        if (Verb::kMiterJoin == joinVerb) {
            this->appendTriangleInstance().set(
                    n0 * fCurrStrokeRadius, c * fCurrStrokeRadius, n1 * fCurrStrokeRadius, offset,
                    TriangleInstance::Ordering::kXYTransposed);
        } else {
            SkASSERT(Verb::kRoundJoin == joinVerb || Verb::kInternalRoundJoin == joinVerb);
            this->appendConicInstance().setW(n0 * fCurrStrokeRadius, c * fCurrStrokeRadius,
                                             n1 * fCurrStrokeRadius, offset, conicWeight);
            if (Verb::kInternalRoundJoin == joinVerb) {
                this->appendConicInstance().setW(-n1 * fCurrStrokeRadius, c * -fCurrStrokeRadius,
                                                 -n0 * fCurrStrokeRadius, offset, conicWeight);
            }
        }
    }

    void appendCap(Verb capType, const SkPoint& pt, const SkVector& norm) {
        SkASSERT(this->isMapped());

        Sk2f n = Sk2f::Load(&norm) * fCurrStrokeRadius;
        Sk2f v = Sk2f(-n[1], n[0]);
        Sk2f offset = Sk2f::Load(&pt) + Sk2f(fCurrDX, fCurrDY);

        if (Verb::kSquareCap == capType) {
            SkPoint endPts[2] = {{0, 0}, {v[0], v[1]}};
            this->appendLinearStrokeInstance().set(endPts, offset[0], offset[1], fCurrStrokeRadius);
        } else {
            SkASSERT(Verb::kRoundCap == capType);
            this->appendTriangleInstance().set(
                    n, v, -n, offset, TriangleInstance::Ordering::kXYTransposed);
            this->appendConicInstance().setW(n, n + v, v, offset, SK_ScalarRoot2Over2);
            this->appendConicInstance().setW(v, v - n, -n, offset, SK_ScalarRoot2Over2);
        }
    }

    sk_sp<GrGpuBuffer> finish() {
        SkASSERT(this->isMapped());
        SkASSERT(!memcmp(fNextInstances, fEndInstances, sizeof(fNextInstances)));
        fInstanceBuffer.unmapBuffer();
        SkASSERT(!this->isMapped());
        return sk_ref_sp(fInstanceBuffer.gpuBuffer());
    }

private:
    LinearStrokeInstance& appendLinearStrokeInstance() {
        int instanceIdx = fCurrNextInstances->fStrokes[0]++;
        SkASSERT(instanceIdx < fCurrEndInstances->fStrokes[0]);

        return reinterpret_cast<LinearStrokeInstance*>(fInstanceBuffer.data())[instanceIdx];
    }

    CubicStrokeInstance& appendCubicStrokeInstance(int numLinearSegmentsLog2) {
        SkASSERT(numLinearSegmentsLog2 > 0);
        SkASSERT(numLinearSegmentsLog2 <= kMaxNumLinearSegmentsLog2);

        int instanceIdx = fCurrNextInstances->fStrokes[numLinearSegmentsLog2]++;
        SkASSERT(instanceIdx < fCurrEndInstances->fStrokes[numLinearSegmentsLog2]);

        return reinterpret_cast<CubicStrokeInstance*>(fInstanceBuffer.data())[instanceIdx];
    }

    TriangleInstance& appendTriangleInstance() {
        int instanceIdx = fCurrNextInstances->fTriangles++;
        SkASSERT(instanceIdx < fCurrEndInstances->fTriangles);

        return reinterpret_cast<TriangleInstance*>(fInstanceBuffer.data())[instanceIdx];
    }

    ConicInstance& appendConicInstance() {
        int instanceIdx = fCurrNextInstances->fConics++;
        SkASSERT(instanceIdx < fCurrEndInstances->fConics);

        return reinterpret_cast<ConicInstance*>(fInstanceBuffer.data())[instanceIdx];
    }

    float fCurrDX, fCurrDY;
    float fCurrStrokeRadius;
    InstanceTallies* fCurrNextInstances;
    SkDEBUGCODE(const InstanceTallies* fCurrEndInstances);

    GrAutoMapVertexBuffer fInstanceBuffer;
    InstanceTallies fNextInstances[2];
    SkDEBUGCODE(InstanceTallies fEndInstances[2]);
};

GrCCStroker::BatchID GrCCStroker::closeCurrentBatch() {
    if (!fHasOpenBatch) {
        return kEmptyBatchID;
    }
    int start = (fBatches.count() < 2) ? 0 : fBatches[fBatches.count() - 2].fEndScissorSubBatch;
    int end = fBatches.back().fEndScissorSubBatch;
    fMaxNumScissorSubBatches = std::max(fMaxNumScissorSubBatches, end - start);
    fHasOpenBatch = false;
    return fBatches.count() - 1;
}

bool GrCCStroker::prepareToDraw(GrOnFlushResourceProvider* onFlushRP) {
    SkASSERT(!fInstanceBuffer);
    SkASSERT(!fHasOpenBatch);  // Call closeCurrentBatch() first.

    // Here we layout a single instance buffer to share with every internal batch.
    //
    // Rather than place each instance array in its own GPU buffer, we allocate a single
    // megabuffer and lay them all out side-by-side. We can offset the "baseInstance" parameter in
    // our draw calls to direct the GPU to the applicable elements within a given array.
    fBaseInstances[0].fStrokes[0] = 0;
    fBaseInstances[1].fStrokes[0] = fInstanceCounts[0]->fStrokes[0];
    int endLinearStrokesIdx = fBaseInstances[1].fStrokes[0] + fInstanceCounts[1]->fStrokes[0];

    int cubicStrokesIdx = GrSizeDivRoundUp(endLinearStrokesIdx * sizeof(LinearStrokeInstance),
                                           sizeof(CubicStrokeInstance));
    for (int i = 1; i <= kMaxNumLinearSegmentsLog2; ++i) {
        for (int j = 0; j < kNumScissorModes; ++j) {
            fBaseInstances[j].fStrokes[i] = cubicStrokesIdx;
            cubicStrokesIdx += fInstanceCounts[j]->fStrokes[i];
        }
    }

    int trianglesIdx = GrSizeDivRoundUp(cubicStrokesIdx * sizeof(CubicStrokeInstance),
                                        sizeof(TriangleInstance));
    fBaseInstances[0].fTriangles = trianglesIdx;
    fBaseInstances[1].fTriangles =
            fBaseInstances[0].fTriangles + fInstanceCounts[0]->fTriangles;
    int endTrianglesIdx =
            fBaseInstances[1].fTriangles + fInstanceCounts[1]->fTriangles;

    int conicsIdx =
            GrSizeDivRoundUp(endTrianglesIdx * sizeof(TriangleInstance), sizeof(ConicInstance));
    fBaseInstances[0].fConics = conicsIdx;
    fBaseInstances[1].fConics = fBaseInstances[0].fConics + fInstanceCounts[0]->fConics;

    InstanceBufferBuilder builder(onFlushRP, this);
    if (!builder.isMapped()) {
        return false;  // Buffer allocation failed.
    }

    // Now parse the GrCCStrokeGeometry and expand it into the instance buffer.
    int pathIdx = 0;
    int ptsIdx = 0;
    int paramsIdx = 0;
    int normalsIdx = 0;

    const SkTArray<GrCCStrokeGeometry::Parameter, true>& params = fGeometry.params();
    const SkTArray<SkPoint, true>& pts = fGeometry.points();
    const SkTArray<SkVector, true>& normals = fGeometry.normals();

    float miterCapHeightOverWidth=0, conicWeight=0;

    for (Verb verb : fGeometry.verbs()) {
        switch (verb) {
            case Verb::kBeginPath:
                builder.updateCurrentInfo(fPathInfos[pathIdx]);
                ++pathIdx;
                continue;

            case Verb::kLinearStroke:
                builder.appendLinearStroke(&pts[ptsIdx]);
                ++ptsIdx;
                continue;
            case Verb::kQuadraticStroke:
                builder.appendQuadraticStroke(&pts[ptsIdx],
                                              params[paramsIdx++].fNumLinearSegmentsLog2);
                ptsIdx += 2;
                ++normalsIdx;
                continue;
            case Verb::kCubicStroke:
                builder.appendCubicStroke(&pts[ptsIdx], params[paramsIdx++].fNumLinearSegmentsLog2);
                ptsIdx += 3;
                ++normalsIdx;
                continue;

            case Verb::kRoundJoin:
            case Verb::kInternalRoundJoin:
                conicWeight = params[paramsIdx++].fConicWeight;
                [[fallthrough]];
            case Verb::kMiterJoin:
                miterCapHeightOverWidth = params[paramsIdx++].fMiterCapHeightOverWidth;
                [[fallthrough]];
            case Verb::kBevelJoin:
            case Verb::kInternalBevelJoin:
                builder.appendJoin(verb, pts[ptsIdx], normals[normalsIdx], normals[normalsIdx + 1],
                                   miterCapHeightOverWidth, conicWeight);
                ++normalsIdx;
                continue;

            case Verb::kSquareCap:
            case Verb::kRoundCap:
                builder.appendCap(verb, pts[ptsIdx], normals[normalsIdx]);
                continue;

            case Verb::kEndContour:
                ++ptsIdx;
                ++normalsIdx;
                continue;
        }
        SK_ABORT("Invalid CCPR stroke element.");
    }

    fInstanceBuffer = builder.finish();
    SkASSERT(fPathInfos.count() == pathIdx);
    SkASSERT(pts.count() == ptsIdx);
    SkASSERT(normals.count() == normalsIdx);
    return true;
}

void GrCCStroker::drawStrokes(GrOpFlushState* flushState, GrCCCoverageProcessor* proc,
                              BatchID batchID, const SkIRect& drawBounds) const {
    using PrimitiveType = GrCCCoverageProcessor::PrimitiveType;
    SkASSERT(fInstanceBuffer);

    if (kEmptyBatchID == batchID) {
        return;
    }
    const Batch& batch = fBatches[batchID];
    int startScissorSubBatch = (!batchID) ? 0 : fBatches[batchID - 1].fEndScissorSubBatch;

    const InstanceTallies* startIndices[2];
    startIndices[(int)GrScissorTest::kDisabled] = (!batchID)
            ? &fZeroTallies : fBatches[batchID - 1].fNonScissorEndInstances;
    startIndices[(int)GrScissorTest::kEnabled] = (!startScissorSubBatch)
            ? &fZeroTallies : fScissorSubBatches[startScissorSubBatch - 1].fEndInstances;

    GrPipeline pipeline(GrScissorTest::kEnabled, SkBlendMode::kPlus,
                        flushState->drawOpArgs().writeSwizzle());

    // Draw linear strokes.
    this->drawLog2Strokes(0, flushState, LinearStrokeProcessor(), pipeline, batch, startIndices,
                          startScissorSubBatch, drawBounds);

    // Draw cubic strokes. (Quadratics were converted to cubics for GPU processing.)
    CubicStrokeProcessor cubicProc;
    for (int i = 1; i <= kMaxNumLinearSegmentsLog2; ++i) {
        this->drawLog2Strokes(i, flushState, cubicProc, pipeline, batch, startIndices,
                              startScissorSubBatch, drawBounds);
    }

    int numConnectingGeometrySubpasses = proc->numSubpasses();

    // Draw triangles.
    for (int i = 0; i < numConnectingGeometrySubpasses; ++i) {
        proc->reset(PrimitiveType::kTriangles, i, flushState->resourceProvider());
        this->drawConnectingGeometry<&InstanceTallies::fTriangles>(
                flushState, pipeline, *proc, batch, startIndices, startScissorSubBatch, drawBounds);
    }

    // Draw conics.
    for (int i = 0; i < numConnectingGeometrySubpasses; ++i) {
        proc->reset(PrimitiveType::kConics, i, flushState->resourceProvider());
        this->drawConnectingGeometry<&InstanceTallies::fConics>(
                flushState, pipeline, *proc, batch, startIndices, startScissorSubBatch, drawBounds);
    }
}

void GrCCStroker::drawLog2Strokes(int numSegmentsLog2, GrOpFlushState* flushState,
                                  const GrPrimitiveProcessor& processor, const GrPipeline& pipeline,
                                  const Batch& batch, const InstanceTallies* startIndices[2],
                                  int startScissorSubBatch, const SkIRect& drawBounds) const {
    GrProgramInfo programInfo(flushState->proxy()->numSamples(),
                              flushState->proxy()->numStencilSamples(),
                              flushState->proxy()->backendFormat(),
                              flushState->writeView()->origin(), &pipeline, &processor,
                              GrPrimitiveType::kTriangleStrip);

    flushState->bindPipeline(programInfo, SkRect::Make(drawBounds));
    flushState->bindBuffers(nullptr, fInstanceBuffer.get(), nullptr);

    // Linear strokes draw a quad. Cubic strokes emit a strip with normals at "numSegments"
    // evenly-spaced points along the curve, plus one more for the final endpoint, plus two more for
    // AA butt caps. (i.e., 2 vertices * (numSegments + 3).)
    int numStripVertices = (0 == numSegmentsLog2) ? 4 : ((1 << numSegmentsLog2) + 3) * 2;

    // Draw non-scissored strokes.
    int baseInstance = fBaseInstances[(int)GrScissorTest::kDisabled].fStrokes[numSegmentsLog2];
    int startIdx = startIndices[(int)GrScissorTest::kDisabled]->fStrokes[numSegmentsLog2];
    int endIdx = batch.fNonScissorEndInstances->fStrokes[numSegmentsLog2];
    SkASSERT(endIdx >= startIdx);
    if (int instanceCount = endIdx - startIdx) {
        flushState->setScissorRect(drawBounds);
        flushState->drawInstanced(instanceCount, baseInstance + startIdx, numStripVertices, 0);
    }

    // Draw scissored strokes.
    baseInstance = fBaseInstances[(int)GrScissorTest::kEnabled].fStrokes[numSegmentsLog2];
    startIdx = startIndices[(int)GrScissorTest::kEnabled]->fStrokes[numSegmentsLog2];
    for (int i = startScissorSubBatch; i < batch.fEndScissorSubBatch; ++i) {
        const ScissorSubBatch& subBatch = fScissorSubBatches[i];
        endIdx = subBatch.fEndInstances->fStrokes[numSegmentsLog2];
        SkASSERT(endIdx >= startIdx);
        if (int instanceCount = endIdx - startIdx) {
            flushState->setScissorRect(subBatch.fScissor);
            flushState->drawInstanced(instanceCount, baseInstance + startIdx, numStripVertices, 0);
            startIdx = endIdx;
        }
    }
}

template<int GrCCStrokeGeometry::InstanceTallies::* InstanceType>
void GrCCStroker::drawConnectingGeometry(GrOpFlushState* flushState, const GrPipeline& pipeline,
                                         const GrCCCoverageProcessor& processor,
                                         const Batch& batch, const InstanceTallies* startIndices[2],
                                         int startScissorSubBatch,
                                         const SkIRect& drawBounds) const {
    processor.bindPipeline(flushState, pipeline, SkRect::Make(drawBounds));
    processor.bindBuffers(flushState->opsRenderPass(), fInstanceBuffer.get());

    // Append non-scissored meshes.
    int baseInstance = fBaseInstances[(int)GrScissorTest::kDisabled].*InstanceType;
    int startIdx = startIndices[(int)GrScissorTest::kDisabled]->*InstanceType;
    int endIdx = batch.fNonScissorEndInstances->*InstanceType;
    SkASSERT(endIdx >= startIdx);
    if (int instanceCount = endIdx - startIdx) {
        flushState->setScissorRect(drawBounds);
        processor.drawInstances(flushState->opsRenderPass(), instanceCount,
                                baseInstance + startIdx);
    }

    // Append scissored meshes.
    baseInstance = fBaseInstances[(int)GrScissorTest::kEnabled].*InstanceType;
    startIdx = startIndices[(int)GrScissorTest::kEnabled]->*InstanceType;
    for (int i = startScissorSubBatch; i < batch.fEndScissorSubBatch; ++i) {
        const ScissorSubBatch& subBatch = fScissorSubBatches[i];
        endIdx = subBatch.fEndInstances->*InstanceType;
        SkASSERT(endIdx >= startIdx);
        if (int instanceCount = endIdx - startIdx) {
            flushState->setScissorRect(subBatch.fScissor);
            processor.drawInstances(flushState->opsRenderPass(), instanceCount,
                                    baseInstance + startIdx);
            startIdx = endIdx;
        }
    }
}
