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