/*
 * 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/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() : GrGeometryProcessor(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&,
                     FPCoordTransformIter&&) override {}
        void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override;
    };

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

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

    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");
    this->emitTransforms(v, varyingHandler, uniHandler, GrShaderVar("position", kFloat2_GrSLType),
                         SkMatrix::I(), args.fFPCoordTransformHandler);

    // 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&,
                     FPCoordTransformIter&&) 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;
    GrGLSLUniformHandler* uniHandler = args.fUniformHandler;

    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");
    this->emitTransforms(v, varyingHandler, uniHandler, GrShaderVar("position", kFloat2_GrSLType),
                         SkMatrix::I(), args.fFPCoordTransformHandler);

    // 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 = onFlushRP->makeBuffer(GrGpuBufferType::kVertex,
                                                endConicsIdx * sizeof(ConicInstance));
        if (!fInstanceBuffer) {
            SkDebugf("WARNING: failed to allocate CCPR stroke instance buffer.\n");
            return;
        }
        fInstanceBufferData = fInstanceBuffer->map();
    }

    bool isMapped() const { return SkToBool(fInstanceBufferData); }

    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->unmap();
        fInstanceBufferData = nullptr;
        SkASSERT(!this->isMapped());
        return std::move(fInstanceBuffer);
    }

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

        return reinterpret_cast<LinearStrokeInstance*>(fInstanceBufferData)[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*>(fInstanceBufferData)[instanceIdx];
    }

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

        return reinterpret_cast<TriangleInstance*>(fInstanceBufferData)[instanceIdx];
    }

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

        return reinterpret_cast<ConicInstance*>(fInstanceBufferData)[instanceIdx];
    }

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

    sk_sp<GrGpuBuffer> fInstanceBuffer;
    void* fInstanceBufferData = nullptr;
    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 = SkTMax(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;
                // fallthru
            case Verb::kMiterJoin:
                miterCapHeightOverWidth = params[paramsIdx++].fMiterCapHeightOverWidth;
                // fallthru
            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);

    fMeshesBuffer.reserve((1 + fMaxNumScissorSubBatches) * kMaxNumLinearSegmentsLog2);
    fScissorsBuffer.reserve((1 + fMaxNumScissorSubBatches) * kMaxNumLinearSegmentsLog2);
    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().outputSwizzle());

    // Draw linear strokes.
    this->appendStrokeMeshesToBuffers(0, batch, startIndices, startScissorSubBatch, drawBounds);
    if (!fMeshesBuffer.empty()) {
        LinearStrokeProcessor linearProc;
        this->flushBufferedMeshesAsStrokes(linearProc, flushState, pipeline, drawBounds);
    }

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

    // Draw triangles.
    proc->reset(PrimitiveType::kTriangles, flushState->resourceProvider());
    this->drawConnectingGeometry<&InstanceTallies::fTriangles>(
            flushState, pipeline, *proc, batch, startIndices, startScissorSubBatch, drawBounds);

    // Draw conics.
    proc->reset(PrimitiveType::kConics, flushState->resourceProvider());
    this->drawConnectingGeometry<&InstanceTallies::fConics>(
            flushState, pipeline, *proc, batch, startIndices, startScissorSubBatch, drawBounds);
}

void GrCCStroker::appendStrokeMeshesToBuffers(int numSegmentsLog2, const Batch& batch,
                                              const InstanceTallies* startIndices[2],
                                              int startScissorSubBatch,
                                              const SkIRect& drawBounds) const {
    // 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;

    // Append non-scissored meshes.
    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) {
        GrMesh& mesh = fMeshesBuffer.emplace_back(GrPrimitiveType::kTriangleStrip);
        mesh.setInstanced(fInstanceBuffer, instanceCount, baseInstance + startIdx,
                          numStripVertices);
        fScissorsBuffer.push_back(drawBounds);
    }

    // Append scissored meshes.
    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) {
            GrMesh& mesh = fMeshesBuffer.emplace_back(GrPrimitiveType::kTriangleStrip);
            mesh.setInstanced(fInstanceBuffer, instanceCount, baseInstance + startIdx,
                              numStripVertices);
            fScissorsBuffer.push_back(subBatch.fScissor);
            startIdx = endIdx;
        }
    }
}

void GrCCStroker::flushBufferedMeshesAsStrokes(const GrPrimitiveProcessor& processor,
                                               GrOpFlushState* flushState,
                                               const GrPipeline& pipeline,
                                               const SkIRect& drawBounds) const {
    SkASSERT(fMeshesBuffer.count() == fScissorsBuffer.count());
    GrPipeline::DynamicStateArrays dynamicStateArrays;
    dynamicStateArrays.fScissorRects = fScissorsBuffer.begin();

    GrProgramInfo programInfo(flushState->drawOpArgs().numSamples(),
                              flushState->drawOpArgs().origin(),
                              pipeline,
                              processor,
                              nullptr,
                              &dynamicStateArrays, 0);

    flushState->opsRenderPass()->draw(programInfo,
                                      fMeshesBuffer.begin(), fMeshesBuffer.count(),
                                      SkRect::Make(drawBounds));
    // Don't call reset(), as that also resets the reserve count.
    fMeshesBuffer.pop_back_n(fMeshesBuffer.count());
    fScissorsBuffer.pop_back_n(fScissorsBuffer.count());
}

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 {
    // 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) {
        processor.appendMesh(fInstanceBuffer, instanceCount, baseInstance + startIdx,
                             &fMeshesBuffer);
        fScissorsBuffer.push_back(drawBounds);
    }

    // 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) {
            processor.appendMesh(fInstanceBuffer, instanceCount, baseInstance + startIdx,
                                 &fMeshesBuffer);
            fScissorsBuffer.push_back(subBatch.fScissor);
            startIdx = endIdx;
        }
    }

    // Flush the geometry.
    if (!fMeshesBuffer.empty()) {
        SkASSERT(fMeshesBuffer.count() == fScissorsBuffer.count());
        processor.draw(flushState, pipeline, fScissorsBuffer.begin(), fMeshesBuffer.begin(),
                       fMeshesBuffer.count(), SkRect::Make(drawBounds));
        // Don't call reset(), as that also resets the reserve count.
        fMeshesBuffer.pop_back_n(fMeshesBuffer.count());
        fScissorsBuffer.pop_back_n(fScissorsBuffer.count());
    }
}
