void GrAAHairLinePathRenderer::drawPath(GrDrawState::StageMask stageMask) {

    if (!this->createGeom(stageMask)) {
        return;
    }

    GrDrawState* drawState = fTarget->drawState();

    GrDrawTarget::AutoStateRestore asr;
    if (!drawState->getViewMatrix().hasPerspective()) {
        asr.set(fTarget);
        GrMatrix ivm;
        if (drawState->getViewInverse(&ivm)) {
            drawState->preConcatSamplerMatrices(stageMask, ivm);
        }
        drawState->setViewMatrix(GrMatrix::I());
    }

    // TODO: See whether rendering lines as degenerate quads improves perf
    // when we have a mix
    fTarget->setIndexSourceToBuffer(fLinesIndexBuffer);
    int lines = 0;
    int nBufLines = fLinesIndexBuffer->maxQuads();
    while (lines < fLineSegmentCnt) {
        int n = GrMin(fLineSegmentCnt-lines, nBufLines);
        drawState->setVertexEdgeType(GrDrawState::kHairLine_EdgeType);
        fTarget->drawIndexed(kTriangles_PrimitiveType,
                             kVertsPerLineSeg*lines,    // startV
                             0,                         // startI
                             kVertsPerLineSeg*n,        // vCount
                             kIdxsPerLineSeg*n);        // iCount
        lines += n;
    }

    fTarget->setIndexSourceToBuffer(fQuadsIndexBuffer);
    int quads = 0;
    while (quads < fQuadCnt) {
        int n = GrMin(fQuadCnt-quads, kNumQuadsInIdxBuffer);
        drawState->setVertexEdgeType(GrDrawState::kHairQuad_EdgeType);
        fTarget->drawIndexed(kTriangles_PrimitiveType,
                             4*fLineSegmentCnt + kVertsPerQuad*quads, // startV
                             0,                                       // startI
                             kVertsPerQuad*n,                         // vCount
                             kIdxsPerQuad*n);                         // iCount
        quads += n;
    }

}
bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path,
                                          const SkStrokeRec& stroke,
                                          GrDrawTarget* target,
                                          bool antiAlias) {
    GrDrawState* drawState = target->drawState();

    SkScalar hairlineCoverage;
    if (IsStrokeHairlineOrEquivalent(stroke,
                                     target->getDrawState().getViewMatrix(),
                                     &hairlineCoverage)) {
        uint8_t newCoverage = SkScalarRoundToInt(hairlineCoverage *
                                                 target->getDrawState().getCoverage());
        target->drawState()->setCoverage(newCoverage);
    }

    SkIRect devClipBounds;
    target->getClip()->getConservativeBounds(drawState->getRenderTarget(), &devClipBounds);

    int lineCnt;
    int quadCnt;
    int conicCnt;
    PREALLOC_PTARRAY(128) lines;
    PREALLOC_PTARRAY(128) quads;
    PREALLOC_PTARRAY(128) conics;
    IntArray qSubdivs;
    FloatArray cWeights;
    quadCnt = generate_lines_and_quads(path, drawState->getViewMatrix(), devClipBounds,
                                       &lines, &quads, &conics, &qSubdivs, &cWeights);
    lineCnt = lines.count() / 2;
    conicCnt = conics.count() / 3;

    // do lines first
    if (lineCnt) {
        GrDrawTarget::AutoReleaseGeometry arg;
        SkRect devBounds;

        if (!this->createLineGeom(path,
                                  target,
                                  lines,
                                  lineCnt,
                                  &arg,
                                  &devBounds)) {
            return false;
        }

        GrDrawTarget::AutoStateRestore asr;

        // createLineGeom transforms the geometry to device space when the matrix does not have
        // perspective.
        if (target->getDrawState().getViewMatrix().hasPerspective()) {
            asr.set(target, GrDrawTarget::kPreserve_ASRInit);
        } else if (!asr.setIdentity(target, GrDrawTarget::kPreserve_ASRInit)) {
            return false;
        }
        GrDrawState* drawState = target->drawState();

        // Check devBounds
        SkASSERT(check_bounds<LineVertex>(drawState, devBounds, arg.vertices(),
                                          kVertsPerLineSeg * lineCnt));

        {
            GrDrawState::AutoRestoreEffects are(drawState);
            target->setIndexSourceToBuffer(fLinesIndexBuffer);
            int lines = 0;
            while (lines < lineCnt) {
                int n = SkTMin(lineCnt - lines, kNumLineSegsInIdxBuffer);
                target->drawIndexed(kTriangles_GrPrimitiveType,
                                    kVertsPerLineSeg*lines,     // startV
                                    0,                          // startI
                                    kVertsPerLineSeg*n,         // vCount
                                    kIdxsPerLineSeg*n,          // iCount
                                    &devBounds);
                lines += n;
            }
        }
    }

    // then quadratics/conics
    if (quadCnt || conicCnt) {
        GrDrawTarget::AutoReleaseGeometry arg;
        SkRect devBounds;

        if (!this->createBezierGeom(path,
                                    target,
                                    quads,
                                    quadCnt,
                                    conics,
                                    conicCnt,
                                    qSubdivs,
                                    cWeights,
                                    &arg,
                                    &devBounds)) {
            return false;
        }

        GrDrawTarget::AutoStateRestore asr;

        // createGeom transforms the geometry to device space when the matrix does not have
        // perspective.
        if (target->getDrawState().getViewMatrix().hasPerspective()) {
            asr.set(target, GrDrawTarget::kPreserve_ASRInit);
        } else if (!asr.setIdentity(target, GrDrawTarget::kPreserve_ASRInit)) {
            return false;
        }
        GrDrawState* drawState = target->drawState();

        static const int kEdgeAttrIndex = 1;

        // Check devBounds
        SkASSERT(check_bounds<BezierVertex>(drawState, devBounds, arg.vertices(),
                                            kVertsPerQuad * quadCnt + kVertsPerQuad * conicCnt));

        if (quadCnt > 0) {
            GrEffect* hairQuadEffect = GrQuadEffect::Create(kHairlineAA_GrEffectEdgeType,
                                                            *target->caps());
            SkASSERT(hairQuadEffect);
            GrDrawState::AutoRestoreEffects are(drawState);
            target->setIndexSourceToBuffer(fQuadsIndexBuffer);
            drawState->setGeometryProcessor(hairQuadEffect, kEdgeAttrIndex)->unref();
            int quads = 0;
            while (quads < quadCnt) {
                int n = SkTMin(quadCnt - quads, kNumQuadsInIdxBuffer);
                target->drawIndexed(kTriangles_GrPrimitiveType,
                                    kVertsPerQuad*quads,               // startV
                                    0,                                 // startI
                                    kVertsPerQuad*n,                   // vCount
                                    kIdxsPerQuad*n,                    // iCount
                                    &devBounds);
                quads += n;
            }
        }

        if (conicCnt > 0) {
            GrDrawState::AutoRestoreEffects are(drawState);
            GrEffect* hairConicEffect = GrConicEffect::Create(kHairlineAA_GrEffectEdgeType,
                                                              *target->caps());
            SkASSERT(hairConicEffect);
            drawState->setGeometryProcessor(hairConicEffect, 1, 2)->unref();
            int conics = 0;
            while (conics < conicCnt) {
                int n = SkTMin(conicCnt - conics, kNumQuadsInIdxBuffer);
                target->drawIndexed(kTriangles_GrPrimitiveType,
                                    kVertsPerQuad*(quadCnt + conics),  // startV
                                    0,                                 // startI
                                    kVertsPerQuad*n,                   // vCount
                                    kIdxsPerQuad*n,                    // iCount
                                    &devBounds);
                conics += n;
            }
        }
    }

    target->resetIndexSource();

    return true;
}
bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path,
                                          GrPathFill fill,
                                          const GrVec* translate,
                                          GrDrawTarget* target,
                                          GrDrawState::StageMask stageMask,
                                          bool antiAlias) {

    int lineCnt;
    int quadCnt;
    GrDrawTarget::AutoReleaseGeometry arg;
    if (!this->createGeom(path,
                          translate,
                          target,
                          stageMask,
                          &lineCnt,
                          &quadCnt,
                          &arg)) {
        return false;
    }

    GrDrawTarget::AutoStateRestore asr;
    GrDrawState* drawState = target->drawState();
    if (!drawState->getViewMatrix().hasPerspective()) {
        // we are going to whack the view matrix to identity to remove
        // perspective.
        asr.set(target,
                GrDrawTarget::kPreserve_ASRInit);
        drawState = target->drawState();
        GrMatrix ivm;
        if (drawState->getViewInverse(&ivm)) {
            drawState->preConcatSamplerMatrices(stageMask, ivm);
        }
        drawState->viewMatrix()->reset();
    }
    

    // TODO: See whether rendering lines as degenerate quads improves perf
    // when we have a mix
    target->setIndexSourceToBuffer(fLinesIndexBuffer);
    int lines = 0;
    int nBufLines = fLinesIndexBuffer->maxQuads();
    while (lines < lineCnt) {
        int n = GrMin(lineCnt - lines, nBufLines);
        drawState->setVertexEdgeType(GrDrawState::kHairLine_EdgeType);
        target->drawIndexed(kTriangles_GrPrimitiveType,
                            kVertsPerLineSeg*lines,    // startV
                            0,                         // startI
                            kVertsPerLineSeg*n,        // vCount
                            kIdxsPerLineSeg*n);        // iCount
        lines += n;
    }

    target->setIndexSourceToBuffer(fQuadsIndexBuffer);
    int quads = 0;
    while (quads < quadCnt) {
        int n = GrMin(quadCnt - quads, kNumQuadsInIdxBuffer);
        drawState->setVertexEdgeType(GrDrawState::kHairQuad_EdgeType);
        target->drawIndexed(kTriangles_GrPrimitiveType,
                            4 * lineCnt + kVertsPerQuad*quads, // startV
                            0,                                 // startI
                            kVertsPerQuad*n,                   // vCount
                            kIdxsPerQuad*n);                   // iCount
        quads += n;
    }
    return true;
}