9619e2ad4487b3fc4d8242992e55e034af68ff2d
[platform/upstream/libSkiaSharp.git] / src / gpu / GrDefaultPathRenderer.cpp
1 /*
2  * Copyright 2011 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 "GrDefaultPathRenderer.h"
9
10 #include "GrBatch.h"
11 #include "GrBatchTarget.h"
12 #include "GrBufferAllocPool.h"
13 #include "GrContext.h"
14 #include "GrDefaultGeoProcFactory.h"
15 #include "GrPathUtils.h"
16 #include "GrPipelineBuilder.h"
17 #include "SkGeometry.h"
18 #include "SkString.h"
19 #include "SkStrokeRec.h"
20 #include "SkTLazy.h"
21 #include "SkTraceEvent.h"
22
23 GrDefaultPathRenderer::GrDefaultPathRenderer(bool separateStencilSupport,
24                                              bool stencilWrapOpsSupport)
25     : fSeparateStencil(separateStencilSupport)
26     , fStencilWrapOps(stencilWrapOpsSupport) {
27 }
28
29
30 ////////////////////////////////////////////////////////////////////////////////
31 // Stencil rules for paths
32
33 ////// Even/Odd
34
35 GR_STATIC_CONST_SAME_STENCIL(gEOStencilPass,
36     kInvert_StencilOp,
37     kKeep_StencilOp,
38     kAlwaysIfInClip_StencilFunc,
39     0xffff,
40     0xffff,
41     0xffff);
42
43 // ok not to check clip b/c stencil pass only wrote inside clip
44 GR_STATIC_CONST_SAME_STENCIL(gEOColorPass,
45     kZero_StencilOp,
46     kZero_StencilOp,
47     kNotEqual_StencilFunc,
48     0xffff,
49     0x0000,
50     0xffff);
51
52 // have to check clip b/c outside clip will always be zero.
53 GR_STATIC_CONST_SAME_STENCIL(gInvEOColorPass,
54     kZero_StencilOp,
55     kZero_StencilOp,
56     kEqualIfInClip_StencilFunc,
57     0xffff,
58     0x0000,
59     0xffff);
60
61 ////// Winding
62
63 // when we have separate stencil we increment front faces / decrement back faces
64 // when we don't have wrap incr and decr we use the stencil test to simulate
65 // them.
66
67 GR_STATIC_CONST_STENCIL(gWindStencilSeparateWithWrap,
68     kIncWrap_StencilOp,             kDecWrap_StencilOp,
69     kKeep_StencilOp,                kKeep_StencilOp,
70     kAlwaysIfInClip_StencilFunc,    kAlwaysIfInClip_StencilFunc,
71     0xffff,                         0xffff,
72     0xffff,                         0xffff,
73     0xffff,                         0xffff);
74
75 // if inc'ing the max value, invert to make 0
76 // if dec'ing zero invert to make all ones.
77 // we can't avoid touching the stencil on both passing and
78 // failing, so we can't resctrict ourselves to the clip.
79 GR_STATIC_CONST_STENCIL(gWindStencilSeparateNoWrap,
80     kInvert_StencilOp,              kInvert_StencilOp,
81     kIncClamp_StencilOp,            kDecClamp_StencilOp,
82     kEqual_StencilFunc,             kEqual_StencilFunc,
83     0xffff,                         0xffff,
84     0xffff,                         0x0000,
85     0xffff,                         0xffff);
86
87 // When there are no separate faces we do two passes to setup the winding rule
88 // stencil. First we draw the front faces and inc, then we draw the back faces
89 // and dec. These are same as the above two split into the incrementing and
90 // decrementing passes.
91 GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilWithWrapInc,
92     kIncWrap_StencilOp,
93     kKeep_StencilOp,
94     kAlwaysIfInClip_StencilFunc,
95     0xffff,
96     0xffff,
97     0xffff);
98
99 GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilWithWrapDec,
100     kDecWrap_StencilOp,
101     kKeep_StencilOp,
102     kAlwaysIfInClip_StencilFunc,
103     0xffff,
104     0xffff,
105     0xffff);
106
107 GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilNoWrapInc,
108     kInvert_StencilOp,
109     kIncClamp_StencilOp,
110     kEqual_StencilFunc,
111     0xffff,
112     0xffff,
113     0xffff);
114
115 GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilNoWrapDec,
116     kInvert_StencilOp,
117     kDecClamp_StencilOp,
118     kEqual_StencilFunc,
119     0xffff,
120     0x0000,
121     0xffff);
122
123 // Color passes are the same whether we use the two-sided stencil or two passes
124
125 GR_STATIC_CONST_SAME_STENCIL(gWindColorPass,
126     kZero_StencilOp,
127     kZero_StencilOp,
128     kNonZeroIfInClip_StencilFunc,
129     0xffff,
130     0x0000,
131     0xffff);
132
133 GR_STATIC_CONST_SAME_STENCIL(gInvWindColorPass,
134     kZero_StencilOp,
135     kZero_StencilOp,
136     kEqualIfInClip_StencilFunc,
137     0xffff,
138     0x0000,
139     0xffff);
140
141 ////// Normal render to stencil
142
143 // Sometimes the default path renderer can draw a path directly to the stencil
144 // buffer without having to first resolve the interior / exterior.
145 GR_STATIC_CONST_SAME_STENCIL(gDirectToStencil,
146     kZero_StencilOp,
147     kIncClamp_StencilOp,
148     kAlwaysIfInClip_StencilFunc,
149     0xffff,
150     0x0000,
151     0xffff);
152
153 ////////////////////////////////////////////////////////////////////////////////
154 // Helpers for drawPath
155
156 #define STENCIL_OFF     0   // Always disable stencil (even when needed)
157
158 static inline bool single_pass_path(const SkPath& path, const SkStrokeRec& stroke) {
159 #if STENCIL_OFF
160     return true;
161 #else
162     if (!stroke.isHairlineStyle() && !path.isInverseFillType()) {
163         return path.isConvex();
164     }
165     return false;
166 #endif
167 }
168
169 GrPathRenderer::StencilSupport
170 GrDefaultPathRenderer::onGetStencilSupport(const GrDrawTarget*,
171                                            const GrPipelineBuilder*,
172                                            const SkPath& path,
173                                            const SkStrokeRec& stroke) const {
174     if (single_pass_path(path, stroke)) {
175         return GrPathRenderer::kNoRestriction_StencilSupport;
176     } else {
177         return GrPathRenderer::kStencilOnly_StencilSupport;
178     }
179 }
180
181 static inline void append_countour_edge_indices(bool hairLine,
182                                                 uint16_t fanCenterIdx,
183                                                 uint16_t edgeV0Idx,
184                                                 uint16_t** indices) {
185     // when drawing lines we're appending line segments along
186     // the contour. When applying the other fill rules we're
187     // drawing triangle fans around fanCenterIdx.
188     if (!hairLine) {
189         *((*indices)++) = fanCenterIdx;
190     }
191     *((*indices)++) = edgeV0Idx;
192     *((*indices)++) = edgeV0Idx + 1;
193 }
194
195 static inline void add_quad(SkPoint** vert, const SkPoint* base, const SkPoint pts[],
196                             SkScalar srcSpaceTolSqd, SkScalar srcSpaceTol, bool indexed,
197                             bool isHairline, uint16_t subpathIdxStart, int offset, uint16_t** idx) {
198     // first pt of quad is the pt we ended on in previous step
199     uint16_t firstQPtIdx = (uint16_t)(*vert - base) - 1 + offset;
200     uint16_t numPts =  (uint16_t)
201         GrPathUtils::generateQuadraticPoints(
202             pts[0], pts[1], pts[2],
203             srcSpaceTolSqd, vert,
204             GrPathUtils::quadraticPointCount(pts, srcSpaceTol));
205     if (indexed) {
206         for (uint16_t i = 0; i < numPts; ++i) {
207             append_countour_edge_indices(isHairline, subpathIdxStart,
208                                          firstQPtIdx + i, idx);
209         }
210     }
211 }
212
213 class DefaultPathBatch : public GrBatch {
214 public:
215     struct Geometry {
216         GrColor fColor;
217         SkPath fPath;
218         SkScalar fTolerance;
219         SkDEBUGCODE(SkRect fDevBounds;)
220     };
221
222     static GrBatch* Create(const Geometry& geometry, uint8_t coverage, const SkMatrix& viewMatrix,
223                            bool isHairline) {
224         return SkNEW_ARGS(DefaultPathBatch, (geometry, coverage, viewMatrix, isHairline));
225     }
226
227     const char* name() const SK_OVERRIDE { return "DefaultPathBatch"; }
228
229     void getInvariantOutputColor(GrInitInvariantOutput* out) const SK_OVERRIDE {
230         // When this is called on a batch, there is only one geometry bundle
231         out->setKnownFourComponents(fGeoData[0].fColor);
232     }
233     void getInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRIDE {
234         out->setKnownSingleComponent(this->coverage());
235     }
236
237     void initBatchTracker(const GrPipelineInfo& init) SK_OVERRIDE {
238         // Handle any color overrides
239         if (init.fColorIgnored) {
240             fGeoData[0].fColor = GrColor_ILLEGAL;
241         } else if (GrColor_ILLEGAL != init.fOverrideColor) {
242             fGeoData[0].fColor = init.fOverrideColor;
243         }
244
245         // setup batch properties
246         fBatch.fColorIgnored = init.fColorIgnored;
247         fBatch.fColor = fGeoData[0].fColor;
248         fBatch.fUsesLocalCoords = init.fUsesLocalCoords;
249         fBatch.fCoverageIgnored = init.fCoverageIgnored;
250     }
251
252     void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) SK_OVERRIDE {
253         SkAutoTUnref<const GrGeometryProcessor> gp(
254                 GrDefaultGeoProcFactory::Create(GrDefaultGeoProcFactory::kPosition_GPType,
255                                                 this->color(),
256                                                 this->viewMatrix(),
257                                                 SkMatrix::I(),
258                                                 false,
259                                                 this->coverage()));
260
261         size_t vertexStride = gp->getVertexStride();
262         SkASSERT(vertexStride == sizeof(SkPoint));
263
264         batchTarget->initDraw(gp, pipeline);
265
266         // TODO this is hacky, but the only way we have to initialize the GP is to use the
267         // GrPipelineInfo struct so we can generate the correct shader.  Once we have GrBatch
268         // everywhere we can remove this nastiness
269         GrPipelineInfo init;
270         init.fColorIgnored = fBatch.fColorIgnored;
271         init.fOverrideColor = GrColor_ILLEGAL;
272         init.fCoverageIgnored = fBatch.fCoverageIgnored;
273         init.fUsesLocalCoords = this->usesLocalCoords();
274         gp->initBatchTracker(batchTarget->currentBatchTracker(), init);
275
276         int instanceCount = fGeoData.count();
277
278         // compute number of vertices
279         int maxVertices = 0;
280
281         // We will use index buffers if we have multiple paths or one path with multiple contours
282         bool isIndexed = instanceCount > 1;
283         for (int i = 0; i < instanceCount; i++) {
284             Geometry& args = fGeoData[i];
285
286             int contourCount;
287             maxVertices += GrPathUtils::worstCasePointCount(args.fPath, &contourCount,
288                                                             args.fTolerance);
289
290             isIndexed = isIndexed || contourCount > 1;
291         }
292
293         if (maxVertices == 0 || maxVertices > ((int)SK_MaxU16 + 1)) {
294             SkDebugf("Cannot render path (%d)\n", maxVertices);
295             return;
296         }
297
298         // determine primitiveType
299         int maxIndices = 0;
300         GrPrimitiveType primitiveType;
301         if (this->isHairline()) {
302             if (isIndexed) {
303                 maxIndices = 2 * maxVertices;
304                 primitiveType = kLines_GrPrimitiveType;
305             } else {
306                 primitiveType = kLineStrip_GrPrimitiveType;
307             }
308         } else {
309             if (isIndexed) {
310                 maxIndices = 3 * maxVertices;
311                 primitiveType = kTriangles_GrPrimitiveType;
312             } else {
313                 primitiveType = kTriangleFan_GrPrimitiveType;
314             }
315         }
316
317         // allocate vertex / index buffers
318         const GrVertexBuffer* vertexBuffer;
319         int firstVertex;
320
321         void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
322                                                               maxVertices,
323                                                               &vertexBuffer,
324                                                               &firstVertex);
325
326         if (!vertices) {
327             SkDebugf("Could not allocate vertices\n");
328             return;
329         }
330
331         const GrIndexBuffer* indexBuffer;
332         int firstIndex;
333
334         void* indices = NULL;
335         if (isIndexed) {
336             indices = batchTarget->indexPool()->makeSpace(maxIndices,
337                                                           &indexBuffer,
338                                                           &firstIndex);
339
340             if (!indices) {
341                 SkDebugf("Could not allocate indices\n");
342                 return;
343             }
344         }
345
346         // fill buffers
347         int vertexOffset = 0;
348         int indexOffset = 0;
349         for (int i = 0; i < instanceCount; i++) {
350             Geometry& args = fGeoData[i];
351
352             int vertexCnt = 0;
353             int indexCnt = 0;
354             if (!this->createGeom(vertices,
355                                   vertexOffset,
356                                   indices,
357                                   indexOffset,
358                                   &vertexCnt,
359                                   &indexCnt,
360                                   args.fPath,
361                                   args.fTolerance,
362                                   isIndexed)) {
363                 return;
364             }
365
366             vertexOffset += vertexCnt;
367             indexOffset += indexCnt;
368             SkASSERT(vertexOffset <= maxVertices && indexOffset <= maxIndices);
369         }
370
371         GrDrawTarget::DrawInfo drawInfo;
372         drawInfo.setPrimitiveType(primitiveType);
373         drawInfo.setVertexBuffer(vertexBuffer);
374         drawInfo.setStartVertex(firstVertex);
375         drawInfo.setVertexCount(vertexOffset);
376         if (isIndexed) {
377             drawInfo.setIndexBuffer(indexBuffer);
378             drawInfo.setStartIndex(firstIndex);
379             drawInfo.setIndexCount(indexOffset);
380         } else {
381             drawInfo.setStartIndex(0);
382             drawInfo.setIndexCount(0);
383         }
384         batchTarget->draw(drawInfo);
385
386         // put back reserves
387         batchTarget->putBackIndices((size_t)(maxIndices - indexOffset));
388         batchTarget->putBackVertices((size_t)(maxVertices - vertexOffset), (size_t)vertexStride);
389     }
390
391     SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
392
393 private:
394     DefaultPathBatch(const Geometry& geometry, uint8_t coverage, const SkMatrix& viewMatrix,
395                      bool isHairline) {
396         this->initClassID<DefaultPathBatch>();
397         fBatch.fCoverage = coverage;
398         fBatch.fIsHairline = isHairline;
399         fBatch.fViewMatrix = viewMatrix;
400         fGeoData.push_back(geometry);
401     }
402
403     bool onCombineIfPossible(GrBatch* t) SK_OVERRIDE {
404         DefaultPathBatch* that = t->cast<DefaultPathBatch>();
405
406         if (this->color() != that->color()) {
407             return false;
408         }
409
410         if (this->coverage() != that->coverage()) {
411             return false;
412         }
413
414         if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
415             return false;
416         }
417
418         if (this->isHairline() != that->isHairline()) {
419             return false;
420         }
421
422         fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin());
423         return true;
424     }
425
426     bool createGeom(void* vertices,
427                     size_t vertexOffset,
428                     void* indices,
429                     size_t indexOffset,
430                     int* vertexCnt,
431                     int* indexCnt,
432                     const SkPath& path,
433                     SkScalar srcSpaceTol,
434                     bool isIndexed)  {
435         {
436             SkScalar srcSpaceTolSqd = SkScalarMul(srcSpaceTol, srcSpaceTol);
437
438             uint16_t indexOffsetU16 = (uint16_t)indexOffset;
439             uint16_t vertexOffsetU16 = (uint16_t)vertexOffset;
440
441             uint16_t* idxBase = reinterpret_cast<uint16_t*>(indices) + indexOffsetU16;
442             uint16_t* idx = idxBase;
443             uint16_t subpathIdxStart = vertexOffsetU16;
444
445             SkPoint* base = reinterpret_cast<SkPoint*>(vertices) + vertexOffset;
446             SkPoint* vert = base;
447
448             SkPoint pts[4];
449
450             bool first = true;
451             int subpath = 0;
452
453             SkPath::Iter iter(path, false);
454
455             bool done = false;
456             while (!done) {
457                 SkPath::Verb verb = iter.next(pts);
458                 switch (verb) {
459                     case SkPath::kMove_Verb:
460                         if (!first) {
461                             uint16_t currIdx = (uint16_t) (vert - base) + vertexOffsetU16;
462                             subpathIdxStart = currIdx;
463                             ++subpath;
464                         }
465                         *vert = pts[0];
466                         vert++;
467                         break;
468                     case SkPath::kLine_Verb:
469                         if (isIndexed) {
470                             uint16_t prevIdx = (uint16_t)(vert - base) - 1 + vertexOffsetU16;
471                             append_countour_edge_indices(this->isHairline(), subpathIdxStart,
472                                                          prevIdx, &idx);
473                         }
474                         *(vert++) = pts[1];
475                         break;
476                     case SkPath::kConic_Verb: {
477                         SkScalar weight = iter.conicWeight();
478                         SkAutoConicToQuads converter;
479                         // Converting in src-space, hance the finer tolerance (0.25)
480                         // TODO: find a way to do this in dev-space so the tolerance means something
481                         const SkPoint* quadPts = converter.computeQuads(pts, weight, 0.25f);
482                         for (int i = 0; i < converter.countQuads(); ++i) {
483                             add_quad(&vert, base, quadPts + i*2, srcSpaceTolSqd, srcSpaceTol,
484                                      isIndexed, this->isHairline(), subpathIdxStart,
485                                      (int)vertexOffset, &idx);
486                         }
487                         break;
488                     }
489                     case SkPath::kQuad_Verb:
490                         add_quad(&vert, base, pts, srcSpaceTolSqd, srcSpaceTol, isIndexed,
491                                  this->isHairline(), subpathIdxStart, (int)vertexOffset, &idx);
492                         break;
493                     case SkPath::kCubic_Verb: {
494                         // first pt of cubic is the pt we ended on in previous step
495                         uint16_t firstCPtIdx = (uint16_t)(vert - base) - 1 + vertexOffsetU16;
496                         uint16_t numPts = (uint16_t) GrPathUtils::generateCubicPoints(
497                                         pts[0], pts[1], pts[2], pts[3],
498                                         srcSpaceTolSqd, &vert,
499                                         GrPathUtils::cubicPointCount(pts, srcSpaceTol));
500                         if (isIndexed) {
501                             for (uint16_t i = 0; i < numPts; ++i) {
502                                 append_countour_edge_indices(this->isHairline(), subpathIdxStart,
503                                                              firstCPtIdx + i, &idx);
504                             }
505                         }
506                         break;
507                     }
508                     case SkPath::kClose_Verb:
509                         break;
510                     case SkPath::kDone_Verb:
511                         done = true;
512                 }
513                 first = false;
514             }
515
516             *vertexCnt = static_cast<int>(vert - base);
517             *indexCnt = static_cast<int>(idx - idxBase);
518
519         }
520         return true;
521     }
522
523     GrColor color() const { return fBatch.fColor; }
524     uint8_t coverage() const { return fBatch.fCoverage; }
525     bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
526     const SkMatrix& viewMatrix() const { return fBatch.fViewMatrix; }
527     bool isHairline() const { return fBatch.fIsHairline; }
528
529     struct BatchTracker {
530         GrColor fColor;
531         uint8_t fCoverage;
532         SkMatrix fViewMatrix;
533         bool fUsesLocalCoords;
534         bool fColorIgnored;
535         bool fCoverageIgnored;
536         bool fIsHairline;
537     };
538
539     BatchTracker fBatch;
540     SkSTArray<1, Geometry, true> fGeoData;
541 };
542
543 bool GrDefaultPathRenderer::internalDrawPath(GrDrawTarget* target,
544                                              GrPipelineBuilder* pipelineBuilder,
545                                              GrColor color,
546                                              const SkMatrix& viewMatrix,
547                                              const SkPath& path,
548                                              const SkStrokeRec& origStroke,
549                                              bool stencilOnly) {
550     SkTCopyOnFirstWrite<SkStrokeRec> stroke(origStroke);
551
552     SkScalar hairlineCoverage;
553     uint8_t newCoverage = 0xff;
554     if (IsStrokeHairlineOrEquivalent(*stroke, viewMatrix, &hairlineCoverage)) {
555         newCoverage = SkScalarRoundToInt(hairlineCoverage * 0xff);
556
557         if (!stroke->isHairlineStyle()) {
558             stroke.writable()->setHairlineStyle();
559         }
560     }
561
562     const bool isHairline = stroke->isHairlineStyle();
563
564     // Save the current xp on the draw state so we can reset it if needed
565     SkAutoTUnref<const GrXPFactory> backupXPFactory(SkRef(pipelineBuilder->getXPFactory()));
566     // face culling doesn't make sense here
567     SkASSERT(GrPipelineBuilder::kBoth_DrawFace == pipelineBuilder->getDrawFace());
568
569     int                         passCount = 0;
570     const GrStencilSettings*    passes[3];
571     GrPipelineBuilder::DrawFace drawFace[3];
572     bool                        reverse = false;
573     bool                        lastPassIsBounds;
574
575     if (isHairline) {
576         passCount = 1;
577         if (stencilOnly) {
578             passes[0] = &gDirectToStencil;
579         } else {
580             passes[0] = NULL;
581         }
582         lastPassIsBounds = false;
583         drawFace[0] = GrPipelineBuilder::kBoth_DrawFace;
584     } else {
585         if (single_pass_path(path, *stroke)) {
586             passCount = 1;
587             if (stencilOnly) {
588                 passes[0] = &gDirectToStencil;
589             } else {
590                 passes[0] = NULL;
591             }
592             drawFace[0] = GrPipelineBuilder::kBoth_DrawFace;
593             lastPassIsBounds = false;
594         } else {
595             switch (path.getFillType()) {
596                 case SkPath::kInverseEvenOdd_FillType:
597                     reverse = true;
598                     // fallthrough
599                 case SkPath::kEvenOdd_FillType:
600                     passes[0] = &gEOStencilPass;
601                     if (stencilOnly) {
602                         passCount = 1;
603                         lastPassIsBounds = false;
604                     } else {
605                         passCount = 2;
606                         lastPassIsBounds = true;
607                         if (reverse) {
608                             passes[1] = &gInvEOColorPass;
609                         } else {
610                             passes[1] = &gEOColorPass;
611                         }
612                     }
613                     drawFace[0] = drawFace[1] = GrPipelineBuilder::kBoth_DrawFace;
614                     break;
615
616                 case SkPath::kInverseWinding_FillType:
617                     reverse = true;
618                     // fallthrough
619                 case SkPath::kWinding_FillType:
620                     if (fSeparateStencil) {
621                         if (fStencilWrapOps) {
622                             passes[0] = &gWindStencilSeparateWithWrap;
623                         } else {
624                             passes[0] = &gWindStencilSeparateNoWrap;
625                         }
626                         passCount = 2;
627                         drawFace[0] = GrPipelineBuilder::kBoth_DrawFace;
628                     } else {
629                         if (fStencilWrapOps) {
630                             passes[0] = &gWindSingleStencilWithWrapInc;
631                             passes[1] = &gWindSingleStencilWithWrapDec;
632                         } else {
633                             passes[0] = &gWindSingleStencilNoWrapInc;
634                             passes[1] = &gWindSingleStencilNoWrapDec;
635                         }
636                         // which is cw and which is ccw is arbitrary.
637                         drawFace[0] = GrPipelineBuilder::kCW_DrawFace;
638                         drawFace[1] = GrPipelineBuilder::kCCW_DrawFace;
639                         passCount = 3;
640                     }
641                     if (stencilOnly) {
642                         lastPassIsBounds = false;
643                         --passCount;
644                     } else {
645                         lastPassIsBounds = true;
646                         drawFace[passCount-1] = GrPipelineBuilder::kBoth_DrawFace;
647                         if (reverse) {
648                             passes[passCount-1] = &gInvWindColorPass;
649                         } else {
650                             passes[passCount-1] = &gWindColorPass;
651                         }
652                     }
653                     break;
654                 default:
655                     SkDEBUGFAIL("Unknown path fFill!");
656                     return false;
657             }
658         }
659     }
660
661     SkScalar tol = SK_Scalar1;
662     SkScalar srcSpaceTol = GrPathUtils::scaleToleranceToSrc(tol, viewMatrix, path.getBounds());
663
664     SkRect devBounds;
665     GetPathDevBounds(path, pipelineBuilder->getRenderTarget(), viewMatrix, &devBounds);
666
667     for (int p = 0; p < passCount; ++p) {
668         pipelineBuilder->setDrawFace(drawFace[p]);
669         if (passes[p]) {
670             *pipelineBuilder->stencil() = *passes[p];
671         }
672
673         if (lastPassIsBounds && (p == passCount-1)) {
674             // Reset the XP Factory on pipelineBuilder
675             pipelineBuilder->setXPFactory(backupXPFactory);
676             SkRect bounds;
677             SkMatrix localMatrix = SkMatrix::I();
678             if (reverse) {
679                 SkASSERT(pipelineBuilder->getRenderTarget());
680                 // draw over the dev bounds (which will be the whole dst surface for inv fill).
681                 bounds = devBounds;
682                 SkMatrix vmi;
683                 // mapRect through persp matrix may not be correct
684                 if (!viewMatrix.hasPerspective() && viewMatrix.invert(&vmi)) {
685                     vmi.mapRect(&bounds);
686                 } else {
687                     if (!viewMatrix.invert(&localMatrix)) {
688                         return false;
689                     }
690                 }
691             } else {
692                 bounds = path.getBounds();
693             }
694             GrDrawTarget::AutoGeometryPush agp(target);
695             const SkMatrix& viewM = (reverse && viewMatrix.hasPerspective()) ? SkMatrix::I() :
696                                                                                viewMatrix;
697             target->drawRect(pipelineBuilder, color, viewM, bounds, NULL, &localMatrix);
698         } else {
699             if (passCount > 1) {
700                 pipelineBuilder->setDisableColorXPFactory();
701             }
702
703             DefaultPathBatch::Geometry geometry;
704             geometry.fColor = color;
705             geometry.fPath = path;
706             geometry.fTolerance = srcSpaceTol;
707             SkDEBUGCODE(geometry.fDevBounds = devBounds;)
708
709             SkAutoTUnref<GrBatch> batch(DefaultPathBatch::Create(geometry, newCoverage, viewMatrix,
710                                                                  isHairline));
711
712             target->drawBatch(pipelineBuilder, batch, &devBounds);
713         }
714     }
715     return true;
716 }
717
718 bool GrDefaultPathRenderer::canDrawPath(const GrDrawTarget* target,
719                                         const GrPipelineBuilder* pipelineBuilder,
720                                         const SkMatrix& viewMatrix,
721                                         const SkPath& path,
722                                         const SkStrokeRec& stroke,
723                                         bool antiAlias) const {
724     // this class can draw any path with any fill but doesn't do any anti-aliasing.
725     return !antiAlias && (stroke.isFillStyle() || IsStrokeHairlineOrEquivalent(stroke,
726                                                                                viewMatrix,
727                                                                                NULL));
728 }
729
730 bool GrDefaultPathRenderer::onDrawPath(GrDrawTarget* target,
731                                        GrPipelineBuilder* pipelineBuilder,
732                                        GrColor color,
733                                        const SkMatrix& viewMatrix,
734                                        const SkPath& path,
735                                        const SkStrokeRec& stroke,
736                                        bool antiAlias) {
737     return this->internalDrawPath(target,
738                                   pipelineBuilder,
739                                   color,
740                                   viewMatrix,
741                                   path,
742                                   stroke,
743                                   false);
744 }
745
746 void GrDefaultPathRenderer::onStencilPath(GrDrawTarget* target,
747                                           GrPipelineBuilder* pipelineBuilder,
748                                           const SkMatrix& viewMatrix,
749                                           const SkPath& path,
750                                           const SkStrokeRec& stroke) {
751     SkASSERT(SkPath::kInverseEvenOdd_FillType != path.getFillType());
752     SkASSERT(SkPath::kInverseWinding_FillType != path.getFillType());
753     this->internalDrawPath(target, pipelineBuilder, GrColor_WHITE, viewMatrix, path, stroke, true);
754 }