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

#include "GrVSCoverageProcessor.h"

#include "GrMesh.h"
#include "glsl/GrGLSLVertexGeoBuilder.h"

// This class implements the coverage processor with vertex shaders.
class GrVSCoverageProcessor::Impl : public GrGLSLGeometryProcessor {
public:
    Impl(std::unique_ptr<Shader> shader, int numSides)
            : fShader(std::move(shader)), fNumSides(numSides) {}

private:
    void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor&,
                 FPCoordTransformIter&& transformIter) final {
        this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
    }

    void onEmitCode(EmitArgs&, GrGPArgs*) override;

    const std::unique_ptr<Shader> fShader;
    const int fNumSides;
};

static constexpr int kInstanceAttribIdx_X = 0;  // Transposed X values of all input points.
static constexpr int kInstanceAttribIdx_Y = 1;  // Transposed Y values of all input points.

// Vertex data tells the shader how to offset vertices for conservative raster, as well as how to
// calculate coverage values for corners and edges.
static constexpr int kVertexData_LeftNeighborIdShift = 10;
static constexpr int kVertexData_RightNeighborIdShift = 8;
static constexpr int kVertexData_BloatIdxShift = 6;
static constexpr int kVertexData_InvertNegativeCoverageBit = 1 << 5;
static constexpr int kVertexData_IsCornerBit = 1 << 4;
static constexpr int kVertexData_IsEdgeBit = 1 << 3;
static constexpr int kVertexData_IsHullBit = 1 << 2;

static constexpr int32_t pack_vertex_data(int32_t leftNeighborID, int32_t rightNeighborID,
                                          int32_t bloatIdx, int32_t cornerID,
                                          int32_t extraData = 0) {
    return (leftNeighborID << kVertexData_LeftNeighborIdShift) |
           (rightNeighborID << kVertexData_RightNeighborIdShift) |
           (bloatIdx << kVertexData_BloatIdxShift) |
           cornerID | extraData;
}

static constexpr int32_t hull_vertex_data(int32_t cornerID, int32_t bloatIdx, int n) {
    return pack_vertex_data((cornerID + n - 1) % n, (cornerID + 1) % n, bloatIdx, cornerID,
                            kVertexData_IsHullBit);
}

static constexpr int32_t edge_vertex_data(int32_t edgeID, int32_t endptIdx, int32_t bloatIdx,
                                          int n) {
    return pack_vertex_data(0 == endptIdx ? (edgeID + 1) % n : edgeID,
                            0 == endptIdx ? (edgeID + 1) % n : edgeID,
                            bloatIdx, 0 == endptIdx ? edgeID : (edgeID + 1) % n,
                            kVertexData_IsEdgeBit |
                            (!endptIdx ? kVertexData_InvertNegativeCoverageBit : 0));
}

static constexpr int32_t corner_vertex_data(int32_t leftID, int32_t cornerID, int32_t rightID,
                                            int32_t bloatIdx) {
    return pack_vertex_data(leftID, rightID, bloatIdx, cornerID, kVertexData_IsCornerBit);
}

static constexpr int32_t kTriangleVertices[] = {
    hull_vertex_data(0, 0, 3),
    hull_vertex_data(0, 1, 3),
    hull_vertex_data(0, 2, 3),
    hull_vertex_data(1, 0, 3),
    hull_vertex_data(1, 1, 3),
    hull_vertex_data(1, 2, 3),
    hull_vertex_data(2, 0, 3),
    hull_vertex_data(2, 1, 3),
    hull_vertex_data(2, 2, 3),

    edge_vertex_data(0, 0, 0, 3),
    edge_vertex_data(0, 0, 1, 3),
    edge_vertex_data(0, 0, 2, 3),
    edge_vertex_data(0, 1, 0, 3),
    edge_vertex_data(0, 1, 1, 3),
    edge_vertex_data(0, 1, 2, 3),

    edge_vertex_data(1, 0, 0, 3),
    edge_vertex_data(1, 0, 1, 3),
    edge_vertex_data(1, 0, 2, 3),
    edge_vertex_data(1, 1, 0, 3),
    edge_vertex_data(1, 1, 1, 3),
    edge_vertex_data(1, 1, 2, 3),

    edge_vertex_data(2, 0, 0, 3),
    edge_vertex_data(2, 0, 1, 3),
    edge_vertex_data(2, 0, 2, 3),
    edge_vertex_data(2, 1, 0, 3),
    edge_vertex_data(2, 1, 1, 3),
    edge_vertex_data(2, 1, 2, 3),

    corner_vertex_data(2, 0, 1, 0),
    corner_vertex_data(2, 0, 1, 1),
    corner_vertex_data(2, 0, 1, 2),
    corner_vertex_data(2, 0, 1, 3),

    corner_vertex_data(0, 1, 2, 0),
    corner_vertex_data(0, 1, 2, 1),
    corner_vertex_data(0, 1, 2, 2),
    corner_vertex_data(0, 1, 2, 3),

    corner_vertex_data(1, 2, 0, 0),
    corner_vertex_data(1, 2, 0, 1),
    corner_vertex_data(1, 2, 0, 2),
    corner_vertex_data(1, 2, 0, 3),
};

GR_DECLARE_STATIC_UNIQUE_KEY(gTriangleVertexBufferKey);

static constexpr uint16_t kRestartStrip = 0xffff;

static constexpr uint16_t kTriangleIndicesAsStrips[] =  {
    1, 2, 0, 3, 8, kRestartStrip, // First corner and main body of the hull.
    4, 5, 3, 6, 8, 7, kRestartStrip, // Opposite side and corners of the hull.
    10, 9, 11, 14, 12, 13, kRestartStrip, // First edge.
    16, 15, 17, 20, 18, 19, kRestartStrip, // Second edge.
    22, 21, 23, 26, 24, 25, kRestartStrip, // Third edge.
    28, 27, 29, 30, kRestartStrip, // First corner.
    32, 31, 33, 34, kRestartStrip, // Second corner.
    36, 35, 37, 38 // Third corner.
};

static constexpr uint16_t kTriangleIndicesAsTris[] =  {
    // First corner and main body of the hull.
    1, 2, 0,
    2, 3, 0,
    0, 3, 8, // Main body.

    // Opposite side and corners of the hull.
    4, 5, 3,
    5, 6, 3,
    3, 6, 8,
    6, 7, 8,

    // First edge.
    10,  9, 11,
     9, 14, 11,
    11, 14, 12,
    14, 13, 12,

    // Second edge.
    16, 15, 17,
    15, 20, 17,
    17, 20, 18,
    20, 19, 18,

    // Third edge.
    22, 21, 23,
    21, 26, 23,
    23, 26, 24,
    26, 25, 24,

    // First corner.
    28, 27, 29,
    27, 30, 29,

    // Second corner.
    32, 31, 33,
    31, 34, 33,

    // Third corner.
    36, 35, 37,
    35, 38, 37,
};

GR_DECLARE_STATIC_UNIQUE_KEY(gTriangleIndexBufferKey);

// Curves, including quadratics, are drawn with a four-sided hull.
static constexpr int32_t kCurveVertices[] = {
    hull_vertex_data(0, 0, 4),
    hull_vertex_data(0, 1, 4),
    hull_vertex_data(0, 2, 4),
    hull_vertex_data(1, 0, 4),
    hull_vertex_data(1, 1, 4),
    hull_vertex_data(1, 2, 4),
    hull_vertex_data(2, 0, 4),
    hull_vertex_data(2, 1, 4),
    hull_vertex_data(2, 2, 4),
    hull_vertex_data(3, 0, 4),
    hull_vertex_data(3, 1, 4),
    hull_vertex_data(3, 2, 4),

    corner_vertex_data(3, 0, 1, 0),
    corner_vertex_data(3, 0, 1, 1),
    corner_vertex_data(3, 0, 1, 2),
    corner_vertex_data(3, 0, 1, 3),

    corner_vertex_data(2, 3, 0, 0),
    corner_vertex_data(2, 3, 0, 1),
    corner_vertex_data(2, 3, 0, 2),
    corner_vertex_data(2, 3, 0, 3),
};

GR_DECLARE_STATIC_UNIQUE_KEY(gCurveVertexBufferKey);

static constexpr uint16_t kCurveIndicesAsStrips[] =  {
    1, 0, 2, 11, 3, 5, 4, kRestartStrip, // First half of the hull (split diagonally).
    7, 6, 8, 5, 9, 11, 10, kRestartStrip, // Second half of the hull.
    13, 12, 14, 15, kRestartStrip, // First corner.
    17, 16, 18, 19 // Final corner.
};

static constexpr uint16_t kCurveIndicesAsTris[] =  {
    // First half of the hull (split diagonally).
     1,  0,  2,
     0, 11,  2,
     2, 11,  3,
    11,  5,  3,
     3,  5,  4,

    // Second half of the hull.
    7,  6,  8,
    6,  5,  8,
    8,  5,  9,
    5, 11,  9,
    9, 11, 10,

    // First corner.
    13, 12, 14,
    12, 15, 14,

    // Final corner.
    17, 16, 18,
    16, 19, 18,
};

GR_DECLARE_STATIC_UNIQUE_KEY(gCurveIndexBufferKey);

// Generates a conservative raster hull around a triangle or curve. For triangles we generate
// additional conservative rasters with coverage ramps around the edges and corners.
//
// Triangles are drawn in three steps: (1) Draw a conservative raster of the entire triangle, with a
// coverage of +1. (2) Draw conservative rasters around each edge, with a coverage ramp from -1 to
// 0. These edge coverage values convert jagged conservative raster edges into smooth, antialiased
// ones. (3) Draw conservative rasters (aka pixel-size boxes) around each corner, replacing the
// previous coverage values with ones that ramp to zero in the bloat vertices that fall outside the
// triangle.
//
// Curve shaders handle the opposite edge and corners on their own. For curves we just generate a
// conservative raster here and the shader does the rest.
void GrVSCoverageProcessor::Impl::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
    const GrVSCoverageProcessor& proc = args.fGP.cast<GrVSCoverageProcessor>();
    GrGLSLVertexBuilder* v = args.fVertBuilder;
    int numInputPoints = proc.numInputPoints();

    int inputWidth = (4 == numInputPoints || proc.hasInputWeight()) ? 4 : 3;
    const char* swizzle = (4 == inputWidth) ? "xyzw" : "xyz";
    v->codeAppendf("float%ix2 pts = transpose(float2x%i(%s.%s, %s.%s));", inputWidth, inputWidth,
                   proc.fInputXAndYValues[kInstanceAttribIdx_X].name(), swizzle,
                   proc.fInputXAndYValues[kInstanceAttribIdx_Y].name(), swizzle);

    v->codeAppend ("half wind;");
    Shader::CalcWind(proc, v, "pts", "wind");
    if (PrimitiveType::kWeightedTriangles == proc.fPrimitiveType) {
        SkASSERT(3 == numInputPoints);
        SkASSERT(kFloat4_GrVertexAttribType ==
                 proc.fInputXAndYValues[kInstanceAttribIdx_X].cpuType());
        v->codeAppendf("wind *= half(%s.w);",
                       proc.fInputXAndYValues[kInstanceAttribIdx_X].name());
    }

    float bloat = kAABloatRadius;
#ifdef SK_DEBUG
    if (proc.debugBloatEnabled()) {
        bloat *= proc.debugBloat();
    }
#endif
    v->defineConstant("bloat", bloat);

    const char* hullPts = "pts";
    fShader->emitSetupCode(v, "pts", "wind", (4 == fNumSides) ? &hullPts : nullptr);

    // Reverse all indices if the wind is counter-clockwise: [0, 1, 2] -> [2, 1, 0].
    v->codeAppendf("int clockwise_indices = wind > 0 ? %s : 0x%x - %s;",
                   proc.fPerVertexData.name(),
                   ((fNumSides - 1) << kVertexData_LeftNeighborIdShift) |
                   ((fNumSides - 1) << kVertexData_RightNeighborIdShift) |
                   (((1 << kVertexData_RightNeighborIdShift) - 1) ^ 3) |
                   (fNumSides - 1),
                   proc.fPerVertexData.name());

    // Here we generate conservative raster geometry for the input polygon. It is the convex
    // hull of N pixel-size boxes, one centered on each the input points. Each corner has three
    // vertices, where one or two may cause degenerate triangles. The vertex data tells us how
    // to offset each vertex. Triangle edges and corners are also handled here using the same
    // concept. For more details on conservative raster, see:
    // https://developer.nvidia.com/gpugems/GPUGems2/gpugems2_chapter42.html
    v->codeAppendf("float2 corner = %s[clockwise_indices & 3];", hullPts);
    v->codeAppendf("float2 left = %s[clockwise_indices >> %i];",
                   hullPts, kVertexData_LeftNeighborIdShift);
    v->codeAppendf("float2 right = %s[(clockwise_indices >> %i) & 3];",
                   hullPts, kVertexData_RightNeighborIdShift);

    v->codeAppend ("float2 leftbloat = sign(corner - left);");
    v->codeAppend ("leftbloat = float2(0 != leftbloat.y ? leftbloat.y : leftbloat.x, "
                                      "0 != leftbloat.x ? -leftbloat.x : -leftbloat.y);");

    v->codeAppend ("float2 rightbloat = sign(right - corner);");
    v->codeAppend ("rightbloat = float2(0 != rightbloat.y ? rightbloat.y : rightbloat.x, "
                                       "0 != rightbloat.x ? -rightbloat.x : -rightbloat.y);");

    v->codeAppend ("bool2 left_right_notequal = notEqual(leftbloat, rightbloat);");

    v->codeAppend ("float2 bloatdir = leftbloat;");

    v->codeAppend ("float2 leftdir = corner - left;");
    v->codeAppend ("leftdir = (float2(0) != leftdir) ? normalize(leftdir) : float2(1, 0);");

    v->codeAppend ("float2 rightdir = right - corner;");
    v->codeAppend ("rightdir = (float2(0) != rightdir) ? normalize(rightdir) : float2(1, 0);");

    v->codeAppendf("if (0 != (%s & %i)) {",  // Are we a corner?
                   proc.fPerVertexData.name(), kVertexData_IsCornerBit);

                       // In corner boxes, all 4 coverage values will not map linearly.
                       // Therefore it is important to align the box so its diagonal shared
                       // edge points out of the triangle, in the direction that ramps to 0.
    v->codeAppend (    "bloatdir = float2(leftdir.x > rightdir.x ? +1 : -1, "
                                         "leftdir.y > rightdir.y ? +1 : -1);");

                       // For corner boxes, we hack left_right_notequal to always true. This
                       // in turn causes the upcoming code to always rotate, generating all
                       // 4 vertices of the corner box.
    v->codeAppendf(    "left_right_notequal = bool2(true);");
    v->codeAppend ("}");

    // At each corner of the polygon, our hull will have either 1, 2, or 3 vertices (or 4 if
    // it's a corner box). We begin with this corner's first raster vertex (leftbloat), then
    // continue rotating 90 degrees clockwise until we reach the desired raster vertex for this
    // invocation. Corners with less than 3 corresponding raster vertices will result in
    // redundant vertices and degenerate triangles.
    v->codeAppendf("int bloatidx = (%s >> %i) & 3;", proc.fPerVertexData.name(),
                   kVertexData_BloatIdxShift);
    v->codeAppend ("switch (bloatidx) {");
    v->codeAppend (    "case 3:");
                            // Only corners will have bloatidx=3, and corners always rotate.
    v->codeAppend (        "bloatdir = float2(-bloatdir.y, +bloatdir.x);"); // 90 deg CW.
                           // fallthru.
    v->codeAppend (    "case 2:");
    v->codeAppendf(        "if (all(left_right_notequal)) {");
    v->codeAppend (            "bloatdir = float2(-bloatdir.y, +bloatdir.x);"); // 90 deg CW.
    v->codeAppend (        "}");
                           // fallthru.
    v->codeAppend (    "case 1:");
    v->codeAppendf(        "if (any(left_right_notequal)) {");
    v->codeAppend (            "bloatdir = float2(-bloatdir.y, +bloatdir.x);"); // 90 deg CW.
    v->codeAppend (        "}");
                           // fallthru.
    v->codeAppend ("}");

    v->codeAppend ("float2 vertex = fma(bloatdir, float2(bloat), corner);");
    gpArgs->fPositionVar.set(kFloat2_GrSLType, "vertex");

    // Hulls have a coverage of +1 all around.
    v->codeAppend ("half coverage = +1;");

    if (3 == fNumSides) {
        v->codeAppend ("half left_coverage; {");
        Shader::CalcEdgeCoverageAtBloatVertex(v, "left", "corner", "bloatdir", "left_coverage");
        v->codeAppend ("}");

        v->codeAppend ("half right_coverage; {");
        Shader::CalcEdgeCoverageAtBloatVertex(v, "corner", "right", "bloatdir", "right_coverage");
        v->codeAppend ("}");

        v->codeAppendf("if (0 != (%s & %i)) {",  // Are we an edge?
                       proc.fPerVertexData.name(), kVertexData_IsEdgeBit);
        v->codeAppend (    "coverage = left_coverage;");
        v->codeAppend ("}");

        v->codeAppendf("if (0 != (%s & %i)) {",  // Invert coverage?
                       proc.fPerVertexData.name(),
                       kVertexData_InvertNegativeCoverageBit);
        v->codeAppend (    "coverage = -1 - coverage;");
        v->codeAppend ("}");
    }

    // Non-corner geometry should have zero effect from corner coverage.
    v->codeAppend ("half2 corner_coverage = half2(0);");

    v->codeAppendf("if (0 != (%s & %i)) {",  // Are we a corner?
                   proc.fPerVertexData.name(), kVertexData_IsCornerBit);
                       // We use coverage=-1 to erase what the hull geometry wrote.
                       //
                       // In the context of curves, this effectively means "wind = -wind" and
                       // causes the Shader to erase what it had written previously for the hull.
                       //
                       // For triangles it just erases the "+1" value written by the hull geometry.
    v->codeAppend (    "coverage = -1;");
    if (3 == fNumSides) {
                       // Triangle corners also have to erase what the edge geometry wrote.
        v->codeAppend ("coverage -= left_coverage + right_coverage;");
    }

                       // Corner boxes require attenuated coverage.
    v->codeAppend (    "half attenuation; {");
    Shader::CalcCornerAttenuation(v, "leftdir", "rightdir", "attenuation");
    v->codeAppend (    "}");

                       // Attenuate corner coverage towards the outermost vertex (where bloatidx=0).
                       // This is all that curves need: At each vertex of the corner box, the curve
                       // Shader will calculate the curve's local coverage value, interpolate it
                       // alongside our attenuation parameter, and multiply the two together for a
                       // final coverage value.
    v->codeAppend (    "corner_coverage = (0 == bloatidx) ? half2(0, attenuation) : half2(1);");

    if (3 == fNumSides) {
                       // For triangles we also provide the actual coverage values at each vertex of
                       // the corner box.
        v->codeAppend ("if (1 == bloatidx || 2 == bloatidx) {");
        v->codeAppend (    "corner_coverage.x += right_coverage;");
        v->codeAppend ("}");
        v->codeAppend ("if (bloatidx >= 2) {");
        v->codeAppend (    "corner_coverage.x += left_coverage;");
        v->codeAppend ("}");
    }
    v->codeAppend ("}");

    GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
    v->codeAppend ("coverage *= wind;");
    v->codeAppend ("corner_coverage.x *= wind;");
    fShader->emitVaryings(varyingHandler, GrGLSLVarying::Scope::kVertToFrag, &AccessCodeString(v),
                          gpArgs->fPositionVar.c_str(), "coverage", "corner_coverage");

    varyingHandler->emitAttributes(proc);
    SkASSERT(!args.fFPCoordTransformHandler->nextCoordTransform());

    // Fragment shader.
    fShader->emitFragmentCode(proc, args.fFragBuilder, args.fOutputColor, args.fOutputCoverage);
}

void GrVSCoverageProcessor::reset(PrimitiveType primitiveType, GrResourceProvider* rp) {
    const GrCaps& caps = *rp->caps();

    fPrimitiveType = primitiveType;
    switch (fPrimitiveType) {
        case PrimitiveType::kTriangles:
        case PrimitiveType::kWeightedTriangles: {
            GR_DEFINE_STATIC_UNIQUE_KEY(gTriangleVertexBufferKey);
            fVertexBuffer = rp->findOrMakeStaticBuffer(
                    GrGpuBufferType::kVertex, sizeof(kTriangleVertices), kTriangleVertices,
                    gTriangleVertexBufferKey);
            GR_DEFINE_STATIC_UNIQUE_KEY(gTriangleIndexBufferKey);
            if (caps.usePrimitiveRestart()) {
                fIndexBuffer = rp->findOrMakeStaticBuffer(
                        GrGpuBufferType::kIndex, sizeof(kTriangleIndicesAsStrips),
                        kTriangleIndicesAsStrips, gTriangleIndexBufferKey);
                fNumIndicesPerInstance = SK_ARRAY_COUNT(kTriangleIndicesAsStrips);
            } else {
                fIndexBuffer = rp->findOrMakeStaticBuffer(
                        GrGpuBufferType::kIndex, sizeof(kTriangleIndicesAsTris),
                        kTriangleIndicesAsTris, gTriangleIndexBufferKey);
                fNumIndicesPerInstance = SK_ARRAY_COUNT(kTriangleIndicesAsTris);
            }
            break;
        }

        case PrimitiveType::kQuadratics:
        case PrimitiveType::kCubics:
        case PrimitiveType::kConics: {
            GR_DEFINE_STATIC_UNIQUE_KEY(gCurveVertexBufferKey);
            fVertexBuffer = rp->findOrMakeStaticBuffer(
                    GrGpuBufferType::kVertex, sizeof(kCurveVertices), kCurveVertices,
                    gCurveVertexBufferKey);
            GR_DEFINE_STATIC_UNIQUE_KEY(gCurveIndexBufferKey);
            if (caps.usePrimitiveRestart()) {
                fIndexBuffer = rp->findOrMakeStaticBuffer(
                        GrGpuBufferType::kIndex, sizeof(kCurveIndicesAsStrips),
                        kCurveIndicesAsStrips, gCurveIndexBufferKey);
                fNumIndicesPerInstance = SK_ARRAY_COUNT(kCurveIndicesAsStrips);
            } else {
                fIndexBuffer = rp->findOrMakeStaticBuffer(
                        GrGpuBufferType::kIndex, sizeof(kCurveIndicesAsTris), kCurveIndicesAsTris,
                        gCurveIndexBufferKey);
                fNumIndicesPerInstance = SK_ARRAY_COUNT(kCurveIndicesAsTris);
            }
            break;
        }
    }

    GrVertexAttribType xyAttribType;
    GrSLType xySLType;
    if (4 == this->numInputPoints() || this->hasInputWeight()) {
        GR_STATIC_ASSERT(offsetof(QuadPointInstance, fX) == 0);
        GR_STATIC_ASSERT(sizeof(QuadPointInstance::fX) ==
                         GrVertexAttribTypeSize(kFloat4_GrVertexAttribType));
        GR_STATIC_ASSERT(sizeof(QuadPointInstance::fY) ==
                         GrVertexAttribTypeSize(kFloat4_GrVertexAttribType));
        xyAttribType = kFloat4_GrVertexAttribType;
        xySLType = kFloat4_GrSLType;
    } else {
        GR_STATIC_ASSERT(offsetof(TriPointInstance, fX) == 0);
        GR_STATIC_ASSERT(sizeof(TriPointInstance::fX) ==
                         GrVertexAttribTypeSize(kFloat3_GrVertexAttribType));
        GR_STATIC_ASSERT(sizeof(TriPointInstance::fY) ==
                         GrVertexAttribTypeSize(kFloat3_GrVertexAttribType));
        xyAttribType = kFloat3_GrVertexAttribType;
        xySLType = kFloat3_GrSLType;
    }
    fInputXAndYValues[kInstanceAttribIdx_X] = {"X", xyAttribType, xySLType};
    fInputXAndYValues[kInstanceAttribIdx_Y] = {"Y", xyAttribType, xySLType};
    this->setInstanceAttributes(fInputXAndYValues, 2);
    fPerVertexData = {"vertexdata", kInt_GrVertexAttribType, kInt_GrSLType};
    this->setVertexAttributes(&fPerVertexData, 1);

    if (caps.usePrimitiveRestart()) {
        fTriangleType = GrPrimitiveType::kTriangleStrip;
    } else {
        fTriangleType = GrPrimitiveType::kTriangles;
    }
}

void GrVSCoverageProcessor::appendMesh(sk_sp<const GrGpuBuffer> instanceBuffer, int instanceCount,
                                       int baseInstance, SkTArray<GrMesh>* out) const {
    GrMesh& mesh = out->emplace_back(fTriangleType);
    auto primitiveRestart = GrPrimitiveRestart(GrPrimitiveType::kTriangleStrip == fTriangleType);
    mesh.setIndexedInstanced(fIndexBuffer, fNumIndicesPerInstance, std::move(instanceBuffer),
                             instanceCount, baseInstance, primitiveRestart);
    mesh.setVertexData(fVertexBuffer, 0);
}

GrGLSLPrimitiveProcessor* GrVSCoverageProcessor::onCreateGLSLInstance(
        std::unique_ptr<Shader> shader) const {
    switch (fPrimitiveType) {
        case PrimitiveType::kTriangles:
        case PrimitiveType::kWeightedTriangles:
            return new Impl(std::move(shader), 3);
        case PrimitiveType::kQuadratics:
        case PrimitiveType::kCubics:
        case PrimitiveType::kConics:
            return new Impl(std::move(shader), 4);
    }
    SK_ABORT("Invalid PrimitiveType");
    return nullptr;
}
