Home | History | Annotate | Download | only in ops
      1 /*
      2  * Copyright 2016 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "GrMSAAPathRenderer.h"
      9 
     10 #include "GrAuditTrail.h"
     11 #include "GrClip.h"
     12 #include "GrDefaultGeoProcFactory.h"
     13 #include "GrFixedClip.h"
     14 #include "GrMesh.h"
     15 #include "GrOpFlushState.h"
     16 #include "GrPathStencilSettings.h"
     17 #include "GrPathUtils.h"
     18 #include "GrPipelineBuilder.h"
     19 #include "SkAutoMalloc.h"
     20 #include "SkGeometry.h"
     21 #include "SkTraceEvent.h"
     22 #include "gl/GrGLVaryingHandler.h"
     23 #include "glsl/GrGLSLFragmentShaderBuilder.h"
     24 #include "glsl/GrGLSLGeometryProcessor.h"
     25 #include "glsl/GrGLSLProgramDataManager.h"
     26 #include "glsl/GrGLSLUtil.h"
     27 #include "glsl/GrGLSLVertexShaderBuilder.h"
     28 #include "ops/GrMeshDrawOp.h"
     29 #include "ops/GrRectOpFactory.h"
     30 
     31 static const float kTolerance = 0.5f;
     32 
     33 ////////////////////////////////////////////////////////////////////////////////
     34 // Helpers for drawPath
     35 
     36 static inline bool single_pass_shape(const GrShape& shape) {
     37     if (!shape.inverseFilled()) {
     38         return shape.knownToBeConvex();
     39     }
     40     return false;
     41 }
     42 
     43 GrPathRenderer::StencilSupport GrMSAAPathRenderer::onGetStencilSupport(const GrShape& shape) const {
     44     if (single_pass_shape(shape)) {
     45         return GrPathRenderer::kNoRestriction_StencilSupport;
     46     } else {
     47         return GrPathRenderer::kStencilOnly_StencilSupport;
     48     }
     49 }
     50 
     51 struct MSAALineVertices {
     52     struct Vertex {
     53         SkPoint fPosition;
     54         SkColor fColor;
     55     };
     56     Vertex* vertices;
     57     Vertex* nextVertex;
     58 #ifdef SK_DEBUG
     59     Vertex* verticesEnd;
     60 #endif
     61     uint16_t* indices;
     62     uint16_t* nextIndex;
     63 };
     64 
     65 struct MSAAQuadVertices {
     66     struct Vertex {
     67         SkPoint fPosition;
     68         SkPoint fUV;
     69         SkColor fColor;
     70     };
     71     Vertex* vertices;
     72     Vertex* nextVertex;
     73 #ifdef SK_DEBUG
     74     Vertex* verticesEnd;
     75 #endif
     76     uint16_t* indices;
     77     uint16_t* nextIndex;
     78 };
     79 
     80 static inline void append_contour_edge_indices(uint16_t fanCenterIdx,
     81                                                uint16_t edgeV0Idx,
     82                                                MSAALineVertices& lines) {
     83     *(lines.nextIndex++) = fanCenterIdx;
     84     *(lines.nextIndex++) = edgeV0Idx;
     85     *(lines.nextIndex++) = edgeV0Idx + 1;
     86 }
     87 
     88 static inline void add_quad(MSAALineVertices& lines, MSAAQuadVertices& quads, const SkPoint pts[],
     89                             SkColor color, bool indexed, uint16_t subpathLineIdxStart) {
     90     SkASSERT(lines.nextVertex < lines.verticesEnd);
     91     *lines.nextVertex = { pts[2], color };
     92     if (indexed) {
     93         int prevIdx = (uint16_t) (lines.nextVertex - lines.vertices - 1);
     94         if (prevIdx > subpathLineIdxStart) {
     95             append_contour_edge_indices(subpathLineIdxStart, prevIdx, lines);
     96         }
     97     }
     98     lines.nextVertex++;
     99 
    100     SkASSERT(quads.nextVertex + 2 < quads.verticesEnd);
    101     // the texture coordinates are drawn from the Loop-Blinn rendering algorithm
    102     *(quads.nextVertex++) = { pts[0], SkPoint::Make(0.0, 0.0), color };
    103     *(quads.nextVertex++) = { pts[1], SkPoint::Make(0.5, 0.0), color };
    104     *(quads.nextVertex++) = { pts[2], SkPoint::Make(1.0, 1.0), color };
    105     if (indexed) {
    106         uint16_t offset = (uint16_t) (quads.nextVertex - quads.vertices) - 3;
    107         *(quads.nextIndex++) = offset++;
    108         *(quads.nextIndex++) = offset++;
    109         *(quads.nextIndex++) = offset++;
    110     }
    111 }
    112 
    113 class MSAAQuadProcessor : public GrGeometryProcessor {
    114 public:
    115     static GrGeometryProcessor* Create(const SkMatrix& viewMatrix) {
    116         return new MSAAQuadProcessor(viewMatrix);
    117     }
    118 
    119     ~MSAAQuadProcessor() override {}
    120 
    121     const char* name() const override { return "MSAAQuadProcessor"; }
    122 
    123     const Attribute* inPosition() const { return fInPosition; }
    124     const Attribute* inUV() const { return fInUV; }
    125     const Attribute* inColor() const { return fInColor; }
    126     const SkMatrix& viewMatrix() const { return fViewMatrix; }
    127 
    128     class GLSLProcessor : public GrGLSLGeometryProcessor {
    129     public:
    130         GLSLProcessor(const GrGeometryProcessor& qpr) {}
    131 
    132         void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
    133             const MSAAQuadProcessor& qp = args.fGP.cast<MSAAQuadProcessor>();
    134             GrGLSLVertexBuilder* vsBuilder = args.fVertBuilder;
    135             GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
    136             GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
    137 
    138             // emit attributes
    139             varyingHandler->emitAttributes(qp);
    140             varyingHandler->addPassThroughAttribute(qp.inColor(), args.fOutputColor);
    141 
    142             GrGLSLVertToFrag uv(kVec2f_GrSLType);
    143             varyingHandler->addVarying("uv", &uv, kHigh_GrSLPrecision);
    144             vsBuilder->codeAppendf("%s = %s;", uv.vsOut(), qp.inUV()->fName);
    145 
    146             // Setup position
    147             this->setupPosition(vsBuilder, uniformHandler, gpArgs, qp.inPosition()->fName,
    148                                 qp.viewMatrix(), &fViewMatrixUniform);
    149 
    150             // emit transforms
    151             this->emitTransforms(vsBuilder, varyingHandler, uniformHandler, gpArgs->fPositionVar,
    152                                  qp.inPosition()->fName, SkMatrix::I(),
    153                                  args.fFPCoordTransformHandler);
    154 
    155             GrGLSLPPFragmentBuilder* fsBuilder = args.fFragBuilder;
    156             fsBuilder->codeAppendf("if (%s.x * %s.x >= %s.y) discard;", uv.fsIn(), uv.fsIn(),
    157                                                                         uv.fsIn());
    158             fsBuilder->codeAppendf("%s = vec4(1.0);", args.fOutputCoverage);
    159         }
    160 
    161         static inline void GenKey(const GrGeometryProcessor& gp,
    162                                   const GrShaderCaps&,
    163                                   GrProcessorKeyBuilder* b) {
    164             const MSAAQuadProcessor& qp = gp.cast<MSAAQuadProcessor>();
    165             uint32_t key = 0;
    166             key |= qp.viewMatrix().hasPerspective() ? 0x1 : 0x0;
    167             key |= qp.viewMatrix().isIdentity() ? 0x2: 0x0;
    168             b->add32(key);
    169         }
    170 
    171         void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& gp,
    172                      FPCoordTransformIter&& transformIter) override {
    173             const MSAAQuadProcessor& qp = gp.cast<MSAAQuadProcessor>();
    174             if (!qp.viewMatrix().isIdentity()) {
    175                 float viewMatrix[3 * 3];
    176                 GrGLSLGetMatrix<3>(viewMatrix, qp.viewMatrix());
    177                 pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
    178             }
    179             this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
    180         }
    181 
    182     private:
    183         typedef GrGLSLGeometryProcessor INHERITED;
    184 
    185         UniformHandle fViewMatrixUniform;
    186     };
    187 
    188     virtual void getGLSLProcessorKey(const GrShaderCaps& caps,
    189                                    GrProcessorKeyBuilder* b) const override {
    190         GLSLProcessor::GenKey(*this, caps, b);
    191     }
    192 
    193     virtual GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override {
    194         return new GLSLProcessor(*this);
    195     }
    196 
    197 private:
    198     MSAAQuadProcessor(const SkMatrix& viewMatrix)
    199         : fViewMatrix(viewMatrix) {
    200         this->initClassID<MSAAQuadProcessor>();
    201         fInPosition = &this->addVertexAttrib("inPosition", kVec2f_GrVertexAttribType,
    202                                              kHigh_GrSLPrecision);
    203         fInUV = &this->addVertexAttrib("inUV", kVec2f_GrVertexAttribType, kHigh_GrSLPrecision);
    204         fInColor = &this->addVertexAttrib("inColor", kVec4ub_GrVertexAttribType);
    205         this->setSampleShading(1.0f);
    206     }
    207 
    208     const Attribute* fInPosition;
    209     const Attribute* fInUV;
    210     const Attribute* fInColor;
    211     SkMatrix         fViewMatrix;
    212 
    213     GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
    214 
    215     typedef GrGeometryProcessor INHERITED;
    216 };
    217 
    218 class MSAAPathOp final : public GrMeshDrawOp {
    219 public:
    220     DEFINE_OP_CLASS_ID
    221     static std::unique_ptr<GrMeshDrawOp> Make(GrColor color, const SkPath& path,
    222                                               const SkMatrix& viewMatrix, const SkRect& devBounds) {
    223         int contourCount;
    224         int maxLineVertices;
    225         int maxQuadVertices;
    226         ComputeWorstCasePointCount(path, &contourCount, &maxLineVertices, &maxQuadVertices);
    227         bool isIndexed = contourCount > 1;
    228         if (isIndexed &&
    229             (maxLineVertices > kMaxIndexedVertexCnt || maxQuadVertices > kMaxIndexedVertexCnt)) {
    230             return nullptr;
    231         }
    232 
    233         return std::unique_ptr<GrMeshDrawOp>(new MSAAPathOp(
    234                 color, path, viewMatrix, devBounds, maxLineVertices, maxQuadVertices, isIndexed));
    235     }
    236 
    237     const char* name() const override { return "MSAAPathOp"; }
    238 
    239     SkString dumpInfo() const override {
    240         SkString string;
    241         string.appendf("Indexed: %d\n", fIsIndexed);
    242         for (const auto& path : fPaths) {
    243             string.appendf("Color: 0x%08x\n", path.fColor);
    244         }
    245         string.append(DumpPipelineInfo(*this->pipeline()));
    246         string.append(INHERITED::dumpInfo());
    247         return string;
    248     }
    249 
    250 private:
    251     MSAAPathOp(GrColor color, const SkPath& path, const SkMatrix& viewMatrix,
    252                const SkRect& devBounds, int maxLineVertices, int maxQuadVertices, bool isIndexed)
    253             : INHERITED(ClassID())
    254             , fViewMatrix(viewMatrix)
    255             , fMaxLineVertices(maxLineVertices)
    256             , fMaxQuadVertices(maxQuadVertices)
    257             , fIsIndexed(isIndexed) {
    258         fPaths.emplace_back(PathInfo{color, path});
    259         this->setBounds(devBounds, HasAABloat::kNo, IsZeroArea::kNo);
    260     }
    261 
    262     void getFragmentProcessorAnalysisInputs(GrPipelineAnalysisColor* color,
    263                                             GrPipelineAnalysisCoverage* coverage) const override {
    264         color->setToConstant(fPaths[0].fColor);
    265         *coverage = GrPipelineAnalysisCoverage::kNone;
    266     }
    267 
    268     void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override {
    269         optimizations.getOverrideColorIfSet(&fPaths[0].fColor);
    270     }
    271 
    272     static void ComputeWorstCasePointCount(const SkPath& path, int* subpaths,
    273                                            int* outLinePointCount, int* outQuadPointCount) {
    274         int linePointCount = 0;
    275         int quadPointCount = 0;
    276         *subpaths = 1;
    277 
    278         bool first = true;
    279 
    280         SkPath::Iter iter(path, true);
    281         SkPath::Verb verb;
    282 
    283         SkPoint pts[4];
    284         while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
    285             switch (verb) {
    286                 case SkPath::kLine_Verb:
    287                     linePointCount += 1;
    288                     break;
    289                 case SkPath::kConic_Verb: {
    290                     SkScalar weight = iter.conicWeight();
    291                     SkAutoConicToQuads converter;
    292                     converter.computeQuads(pts, weight, kTolerance);
    293                     int quadPts = converter.countQuads();
    294                     linePointCount += quadPts;
    295                     quadPointCount += 3 * quadPts;
    296                 }
    297                 case SkPath::kQuad_Verb:
    298                     linePointCount += 1;
    299                     quadPointCount += 3;
    300                     break;
    301                 case SkPath::kCubic_Verb: {
    302                     SkSTArray<15, SkPoint, true> quadPts;
    303                     GrPathUtils::convertCubicToQuads(pts, kTolerance, &quadPts);
    304                     int count = quadPts.count();
    305                     linePointCount += count / 3;
    306                     quadPointCount += count;
    307                     break;
    308                 }
    309                 case SkPath::kMove_Verb:
    310                     linePointCount += 1;
    311                     if (!first) {
    312                         ++(*subpaths);
    313                     }
    314                     break;
    315                 default:
    316                     break;
    317             }
    318             first = false;
    319         }
    320         *outLinePointCount = linePointCount;
    321         *outQuadPointCount = quadPointCount;
    322     }
    323 
    324     void onPrepareDraws(Target* target) const override {
    325         if (fMaxLineVertices == 0) {
    326             SkASSERT(fMaxQuadVertices == 0);
    327             return;
    328         }
    329 
    330         GrPrimitiveType primitiveType = fIsIndexed ? kTriangles_GrPrimitiveType
    331                                                    : kTriangleFan_GrPrimitiveType;
    332 
    333         // allocate vertex / index buffers
    334         const GrBuffer* lineVertexBuffer;
    335         int firstLineVertex;
    336         MSAALineVertices lines;
    337         size_t lineVertexStride = sizeof(MSAALineVertices::Vertex);
    338         lines.vertices = (MSAALineVertices::Vertex*) target->makeVertexSpace(lineVertexStride,
    339                                                                              fMaxLineVertices,
    340                                                                              &lineVertexBuffer,
    341                                                                              &firstLineVertex);
    342         if (!lines.vertices) {
    343             SkDebugf("Could not allocate vertices\n");
    344             return;
    345         }
    346         lines.nextVertex = lines.vertices;
    347         SkDEBUGCODE(lines.verticesEnd = lines.vertices + fMaxLineVertices;)
    348 
    349         MSAAQuadVertices quads;
    350         size_t quadVertexStride = sizeof(MSAAQuadVertices::Vertex);
    351         SkAutoMalloc quadVertexPtr(fMaxQuadVertices * quadVertexStride);
    352         quads.vertices = (MSAAQuadVertices::Vertex*) quadVertexPtr.get();
    353         quads.nextVertex = quads.vertices;
    354         SkDEBUGCODE(quads.verticesEnd = quads.vertices + fMaxQuadVertices;)
    355 
    356         const GrBuffer* lineIndexBuffer = nullptr;
    357         int firstLineIndex;
    358         if (fIsIndexed) {
    359             lines.indices =
    360                     target->makeIndexSpace(3 * fMaxLineVertices, &lineIndexBuffer, &firstLineIndex);
    361             if (!lines.indices) {
    362                 SkDebugf("Could not allocate indices\n");
    363                 return;
    364             }
    365             lines.nextIndex = lines.indices;
    366         } else {
    367             lines.indices = nullptr;
    368             lines.nextIndex = nullptr;
    369         }
    370 
    371         SkAutoFree quadIndexPtr;
    372         if (fIsIndexed) {
    373             quads.indices = (uint16_t*)sk_malloc_throw(3 * fMaxQuadVertices * sizeof(uint16_t));
    374             quadIndexPtr.reset(quads.indices);
    375             quads.nextIndex = quads.indices;
    376         } else {
    377             quads.indices = nullptr;
    378             quads.nextIndex = nullptr;
    379         }
    380 
    381         // fill buffers
    382         for (int i = 0; i < fPaths.count(); i++) {
    383             const PathInfo& pathInfo = fPaths[i];
    384 
    385             if (!this->createGeom(lines,
    386                                   quads,
    387                                   pathInfo.fPath,
    388                                   fViewMatrix,
    389                                   pathInfo.fColor,
    390                                   fIsIndexed)) {
    391                 return;
    392             }
    393         }
    394         int lineVertexOffset = (int) (lines.nextVertex - lines.vertices);
    395         int lineIndexOffset = (int) (lines.nextIndex - lines.indices);
    396         SkASSERT(lineVertexOffset <= fMaxLineVertices && lineIndexOffset <= 3 * fMaxLineVertices);
    397         int quadVertexOffset = (int) (quads.nextVertex - quads.vertices);
    398         int quadIndexOffset = (int) (quads.nextIndex - quads.indices);
    399         SkASSERT(quadVertexOffset <= fMaxQuadVertices && quadIndexOffset <= 3 * fMaxQuadVertices);
    400 
    401         if (lineVertexOffset) {
    402             sk_sp<GrGeometryProcessor> lineGP;
    403             {
    404                 using namespace GrDefaultGeoProcFactory;
    405                 lineGP = GrDefaultGeoProcFactory::Make(Color(Color::kPremulGrColorAttribute_Type),
    406                                                        Coverage::kSolid_Type,
    407                                                        LocalCoords(LocalCoords::kUnused_Type),
    408                                                        fViewMatrix);
    409             }
    410             SkASSERT(lineVertexStride == lineGP->getVertexStride());
    411 
    412             GrMesh lineMeshes;
    413             if (fIsIndexed) {
    414                 lineMeshes.initIndexed(primitiveType, lineVertexBuffer, lineIndexBuffer,
    415                                          firstLineVertex, firstLineIndex, lineVertexOffset,
    416                                          lineIndexOffset);
    417             } else {
    418                 lineMeshes.init(primitiveType, lineVertexBuffer, firstLineVertex,
    419                                   lineVertexOffset);
    420             }
    421             target->draw(lineGP.get(), lineMeshes);
    422         }
    423 
    424         if (quadVertexOffset) {
    425             sk_sp<const GrGeometryProcessor> quadGP(MSAAQuadProcessor::Create(fViewMatrix));
    426             SkASSERT(quadVertexStride == quadGP->getVertexStride());
    427 
    428             const GrBuffer* quadVertexBuffer;
    429             int firstQuadVertex;
    430             MSAAQuadVertices::Vertex* quadVertices = (MSAAQuadVertices::Vertex*)
    431                     target->makeVertexSpace(quadVertexStride, quadVertexOffset, &quadVertexBuffer,
    432                                             &firstQuadVertex);
    433             memcpy(quadVertices, quads.vertices, quadVertexStride * quadVertexOffset);
    434             GrMesh quadMeshes;
    435             if (fIsIndexed) {
    436                 const GrBuffer* quadIndexBuffer;
    437                 int firstQuadIndex;
    438                 uint16_t* quadIndices = (uint16_t*) target->makeIndexSpace(quadIndexOffset,
    439                                                                            &quadIndexBuffer,
    440                                                                            &firstQuadIndex);
    441                 memcpy(quadIndices, quads.indices, sizeof(uint16_t) * quadIndexOffset);
    442                 quadMeshes.initIndexed(kTriangles_GrPrimitiveType, quadVertexBuffer,
    443                                        quadIndexBuffer, firstQuadVertex, firstQuadIndex,
    444                                        quadVertexOffset, quadIndexOffset);
    445             } else {
    446                 quadMeshes.init(kTriangles_GrPrimitiveType, quadVertexBuffer, firstQuadVertex,
    447                                 quadVertexOffset);
    448             }
    449             target->draw(quadGP.get(), quadMeshes);
    450         }
    451     }
    452 
    453     bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
    454         MSAAPathOp* that = t->cast<MSAAPathOp>();
    455         if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
    456                                     that->bounds(), caps)) {
    457             return false;
    458         }
    459 
    460         if (this->bounds().intersects(that->bounds())) {
    461             return false;
    462         }
    463 
    464         if (!fViewMatrix.cheapEqualTo(that->fViewMatrix)) {
    465             return false;
    466         }
    467 
    468         // If we grow to include 2+ paths we will be indexed.
    469         if (((fMaxLineVertices + that->fMaxLineVertices) > kMaxIndexedVertexCnt) ||
    470             ((fMaxQuadVertices + that->fMaxQuadVertices) > kMaxIndexedVertexCnt)) {
    471             return false;
    472         }
    473 
    474         fPaths.push_back_n(that->fPaths.count(), that->fPaths.begin());
    475         this->joinBounds(*that);
    476         fIsIndexed = true;
    477         fMaxLineVertices += that->fMaxLineVertices;
    478         fMaxQuadVertices += that->fMaxQuadVertices;
    479         return true;
    480     }
    481 
    482     bool createGeom(MSAALineVertices& lines,
    483                     MSAAQuadVertices& quads,
    484                     const SkPath& path,
    485                     const SkMatrix& m,
    486                     SkColor color,
    487                     bool isIndexed) const {
    488         {
    489             uint16_t subpathIdxStart = (uint16_t) (lines.nextVertex - lines.vertices);
    490 
    491             SkPoint pts[4];
    492 
    493             bool first = true;
    494             SkPath::Iter iter(path, true);
    495 
    496             bool done = false;
    497             while (!done) {
    498                 SkPath::Verb verb = iter.next(pts);
    499                 switch (verb) {
    500                     case SkPath::kMove_Verb:
    501                         if (!first) {
    502                             uint16_t currIdx = (uint16_t) (lines.nextVertex - lines.vertices);
    503                             subpathIdxStart = currIdx;
    504                         }
    505                         SkASSERT(lines.nextVertex < lines.verticesEnd);
    506                         *(lines.nextVertex++) = { pts[0], color };
    507                         break;
    508                     case SkPath::kLine_Verb:
    509                         if (isIndexed) {
    510                             uint16_t prevIdx = (uint16_t) (lines.nextVertex - lines.vertices - 1);
    511                             if (prevIdx > subpathIdxStart) {
    512                                 append_contour_edge_indices(subpathIdxStart, prevIdx, lines);
    513                             }
    514                         }
    515                         SkASSERT(lines.nextVertex < lines.verticesEnd);
    516                         *(lines.nextVertex++) = { pts[1], color };
    517                         break;
    518                     case SkPath::kConic_Verb: {
    519                         SkScalar weight = iter.conicWeight();
    520                         SkAutoConicToQuads converter;
    521                         const SkPoint* quadPts = converter.computeQuads(pts, weight, kTolerance);
    522                         for (int i = 0; i < converter.countQuads(); ++i) {
    523                             add_quad(lines, quads, quadPts + i * 2, color, isIndexed,
    524                                      subpathIdxStart);
    525                         }
    526                         break;
    527                     }
    528                     case SkPath::kQuad_Verb: {
    529                         add_quad(lines, quads, pts, color, isIndexed, subpathIdxStart);
    530                         break;
    531                     }
    532                     case SkPath::kCubic_Verb: {
    533                         SkSTArray<15, SkPoint, true> quadPts;
    534                         GrPathUtils::convertCubicToQuads(pts, kTolerance, &quadPts);
    535                         int count = quadPts.count();
    536                         for (int i = 0; i < count; i += 3) {
    537                             add_quad(lines, quads, &quadPts[i], color, isIndexed, subpathIdxStart);
    538                         }
    539                         break;
    540                     }
    541                     case SkPath::kClose_Verb:
    542                         break;
    543                     case SkPath::kDone_Verb:
    544                         done = true;
    545                 }
    546                 first = false;
    547             }
    548         }
    549         return true;
    550     }
    551 
    552     // Lines and quads may render with an index buffer. However, we don't have any support for
    553     // overflowing the max index.
    554     static constexpr int kMaxIndexedVertexCnt = SK_MaxU16 / 3;
    555     struct PathInfo {
    556         GrColor  fColor;
    557         SkPath   fPath;
    558     };
    559 
    560     SkSTArray<1, PathInfo, true> fPaths;
    561 
    562     SkMatrix fViewMatrix;
    563     int fMaxLineVertices;
    564     int fMaxQuadVertices;
    565     bool fIsIndexed;
    566 
    567     typedef GrMeshDrawOp INHERITED;
    568 };
    569 
    570 bool GrMSAAPathRenderer::internalDrawPath(GrRenderTargetContext* renderTargetContext,
    571                                           GrPaint&& paint,
    572                                           GrAAType aaType,
    573                                           const GrUserStencilSettings& userStencilSettings,
    574                                           const GrClip& clip,
    575                                           const SkMatrix& viewMatrix,
    576                                           const GrShape& shape,
    577                                           bool stencilOnly) {
    578     SkASSERT(shape.style().isSimpleFill());
    579     SkPath path;
    580     shape.asPath(&path);
    581 
    582     const GrUserStencilSettings* passes[2] = {nullptr, nullptr};
    583     bool                         reverse = false;
    584 
    585     if (single_pass_shape(shape)) {
    586         if (stencilOnly) {
    587             passes[0] = &gDirectToStencil;
    588         } else {
    589             passes[0] = &userStencilSettings;
    590         }
    591     } else {
    592         switch (path.getFillType()) {
    593             case SkPath::kInverseEvenOdd_FillType:
    594                 reverse = true;
    595                 // fallthrough
    596             case SkPath::kEvenOdd_FillType:
    597                 passes[0] = &gEOStencilPass;
    598                 if (!stencilOnly) {
    599                     passes[1] = reverse ? &gInvEOColorPass : &gEOColorPass;
    600                 }
    601                 break;
    602 
    603             case SkPath::kInverseWinding_FillType:
    604                 reverse = true;
    605                 // fallthrough
    606             case SkPath::kWinding_FillType:
    607                 passes[0] = &gWindStencilSeparateWithWrap;
    608                 if (!stencilOnly) {
    609                     passes[1] = reverse ? &gInvWindColorPass : &gWindColorPass;
    610                 }
    611                 break;
    612             default:
    613                 SkDEBUGFAIL("Unknown path fFill!");
    614                 return false;
    615         }
    616     }
    617 
    618     SkRect devBounds;
    619     GetPathDevBounds(path, renderTargetContext->width(), renderTargetContext->height(), viewMatrix,
    620                      &devBounds);
    621 
    622     SkASSERT(passes[0]);
    623     {  // First pass
    624         std::unique_ptr<GrMeshDrawOp> op =
    625                 MSAAPathOp::Make(paint.getColor(), path, viewMatrix, devBounds);
    626         if (!op) {
    627             return false;
    628         }
    629         bool firstPassIsStencil = stencilOnly || passes[1];
    630         // If we have a cover pass then we ignore the paint in the first pass and apply it in the
    631         // second.
    632         GrPaint::MoveOrNew firstPassPaint(paint, firstPassIsStencil);
    633         if (firstPassIsStencil) {
    634             firstPassPaint.paint().setXPFactory(GrDisableColorXPFactory::Get());
    635         }
    636         GrPipelineBuilder pipelineBuilder(std::move(firstPassPaint), aaType);
    637         pipelineBuilder.setUserStencil(passes[0]);
    638         renderTargetContext->addMeshDrawOp(pipelineBuilder, clip, std::move(op));
    639     }
    640 
    641     if (passes[1]) {
    642         SkRect bounds;
    643         SkMatrix localMatrix = SkMatrix::I();
    644         if (reverse) {
    645             // draw over the dev bounds (which will be the whole dst surface for inv fill).
    646             bounds = devBounds;
    647             SkMatrix vmi;
    648             // mapRect through persp matrix may not be correct
    649             if (!viewMatrix.hasPerspective() && viewMatrix.invert(&vmi)) {
    650                 vmi.mapRect(&bounds);
    651             } else {
    652                 if (!viewMatrix.invert(&localMatrix)) {
    653                     return false;
    654                 }
    655             }
    656         } else {
    657             bounds = path.getBounds();
    658         }
    659         const SkMatrix& viewM =
    660                 (reverse && viewMatrix.hasPerspective()) ? SkMatrix::I() : viewMatrix;
    661         std::unique_ptr<GrMeshDrawOp> op(GrRectOpFactory::MakeNonAAFill(
    662                 paint.getColor(), viewM, bounds, nullptr, &localMatrix));
    663 
    664         GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
    665         pipelineBuilder.setUserStencil(passes[1]);
    666 
    667         renderTargetContext->addMeshDrawOp(pipelineBuilder, clip, std::move(op));
    668     }
    669     return true;
    670 }
    671 
    672 bool GrMSAAPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
    673     // This path renderer only fills and relies on MSAA for antialiasing. Stroked shapes are
    674     // handled by passing on the original shape and letting the caller compute the stroked shape
    675     // which will have a fill style.
    676     return args.fShape->style().isSimpleFill() && (GrAAType::kCoverage != args.fAAType);
    677 }
    678 
    679 bool GrMSAAPathRenderer::onDrawPath(const DrawPathArgs& args) {
    680     GR_AUDIT_TRAIL_AUTO_FRAME(args.fRenderTargetContext->auditTrail(),
    681                               "GrMSAAPathRenderer::onDrawPath");
    682     SkTLazy<GrShape> tmpShape;
    683     const GrShape* shape = args.fShape;
    684     if (shape->style().applies()) {
    685         SkScalar styleScale = GrStyle::MatrixToScaleFactor(*args.fViewMatrix);
    686         tmpShape.init(args.fShape->applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec, styleScale));
    687         shape = tmpShape.get();
    688     }
    689     return this->internalDrawPath(args.fRenderTargetContext,
    690                                   std::move(args.fPaint),
    691                                   args.fAAType,
    692                                   *args.fUserStencilSettings,
    693                                   *args.fClip,
    694                                   *args.fViewMatrix,
    695                                   *shape,
    696                                   false);
    697 }
    698 
    699 void GrMSAAPathRenderer::onStencilPath(const StencilPathArgs& args) {
    700     GR_AUDIT_TRAIL_AUTO_FRAME(args.fRenderTargetContext->auditTrail(),
    701                               "GrMSAAPathRenderer::onStencilPath");
    702     SkASSERT(args.fShape->style().isSimpleFill());
    703     SkASSERT(!args.fShape->mayBeInverseFilledAfterStyling());
    704 
    705     GrPaint paint;
    706     paint.setXPFactory(GrDisableColorXPFactory::Get());
    707 
    708     this->internalDrawPath(args.fRenderTargetContext, std::move(paint), args.fAAType,
    709                            GrUserStencilSettings::kUnused, *args.fClip, *args.fViewMatrix,
    710                            *args.fShape, true);
    711 }
    712 
    713 ///////////////////////////////////////////////////////////////////////////////////////////////////
    714