blob: 2072175ef5ff55462f4b38dae6eec70581ee9c17 [file] [log] [blame]
ethannicholas6536ae52016-05-02 12:16:49 -07001/*
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 "GrBatchFlushState.h"
11#include "GrDefaultGeoProcFactory.h"
12#include "GrPathStencilSettings.h"
13#include "GrPathUtils.h"
14#include "GrPipelineBuilder.h"
15#include "GrMesh.h"
16#include "SkGeometry.h"
17#include "SkTraceEvent.h"
18#include "glsl/GrGLSLGeometryProcessor.h"
19#include "glsl/GrGLSLFragmentShaderBuilder.h"
20#include "glsl/GrGLSLVertexShaderBuilder.h"
21#include "glsl/GrGLSLProgramDataManager.h"
22#include "glsl/GrGLSLUtil.h"
23#include "gl/GrGLVaryingHandler.h"
24#include "batches/GrRectBatchFactory.h"
25#include "batches/GrVertexBatch.h"
26
27static const float kTolerance = 0.5f;
28
29////////////////////////////////////////////////////////////////////////////////
30// Helpers for drawPath
31
bsalomon6663acf2016-05-10 09:14:17 -070032static inline bool single_pass_path(const SkPath& path) {
ethannicholas6536ae52016-05-02 12:16:49 -070033 if (!path.isInverseFillType()) {
34 return path.isConvex();
35 }
36 return false;
37}
38
39GrPathRenderer::StencilSupport
bsalomond6f25bf2016-05-05 09:26:21 -070040GrMSAAPathRenderer::onGetStencilSupport(const SkPath& path) const {
bsalomon6663acf2016-05-10 09:14:17 -070041 if (single_pass_path(path)) {
ethannicholas6536ae52016-05-02 12:16:49 -070042 return GrPathRenderer::kNoRestriction_StencilSupport;
43 } else {
44 return GrPathRenderer::kStencilOnly_StencilSupport;
45 }
46}
47
48struct MSAALineVertices {
49 struct Vertex {
50 SkPoint fPosition;
51 SkColor fColor;
52 };
53 Vertex* vertices;
54 Vertex* nextVertex;
55#ifdef SK_DEBUG
56 Vertex* verticesEnd;
57#endif
58 uint16_t* indices;
59 uint16_t* nextIndex;
60};
61
62struct MSAAQuadVertices {
63 struct Vertex {
64 SkPoint fPosition;
65 SkPoint fUV;
66 SkColor fColor;
67 };
68 Vertex* vertices;
69 Vertex* nextVertex;
70#ifdef SK_DEBUG
71 Vertex* verticesEnd;
72#endif
73 uint16_t* indices;
74 uint16_t* nextIndex;
75};
76
77static inline void append_contour_edge_indices(uint16_t fanCenterIdx,
78 uint16_t edgeV0Idx,
79 MSAALineVertices& lines) {
80 *(lines.nextIndex++) = fanCenterIdx;
81 *(lines.nextIndex++) = edgeV0Idx;
82 *(lines.nextIndex++) = edgeV0Idx + 1;
83}
84
85static inline void add_quad(MSAALineVertices& lines, MSAAQuadVertices& quads, const SkPoint pts[],
86 SkColor color, bool indexed, uint16_t subpathLineIdxStart) {
87 SkASSERT(lines.nextVertex < lines.verticesEnd);
88 *lines.nextVertex = { pts[2], color };
89 if (indexed) {
90 int prevIdx = (uint16_t) (lines.nextVertex - lines.vertices - 1);
91 if (prevIdx > subpathLineIdxStart) {
92 append_contour_edge_indices(subpathLineIdxStart, prevIdx, lines);
93 }
94 }
95 lines.nextVertex++;
96
97 SkASSERT(quads.nextVertex + 2 < quads.verticesEnd);
98 // the texture coordinates are drawn from the Loop-Blinn rendering algorithm
99 *(quads.nextVertex++) = { pts[0], SkPoint::Make(0.0, 0.0), color };
100 *(quads.nextVertex++) = { pts[1], SkPoint::Make(0.5, 0.0), color };
101 *(quads.nextVertex++) = { pts[2], SkPoint::Make(1.0, 1.0), color };
102 if (indexed) {
103 uint16_t offset = (uint16_t) (quads.nextVertex - quads.vertices) - 3;
104 *(quads.nextIndex++) = offset++;
105 *(quads.nextIndex++) = offset++;
106 *(quads.nextIndex++) = offset++;
107 }
108}
109
110class MSAAQuadProcessor : public GrGeometryProcessor {
111public:
112 static GrGeometryProcessor* Create(const SkMatrix& viewMatrix) {
113 return new MSAAQuadProcessor(viewMatrix);
114 }
115
116 virtual ~MSAAQuadProcessor() {}
117
118 const char* name() const override { return "MSAAQuadProcessor"; }
119
120 const Attribute* inPosition() const { return fInPosition; }
121 const Attribute* inUV() const { return fInUV; }
122 const Attribute* inColor() const { return fInColor; }
123 const SkMatrix& viewMatrix() const { return fViewMatrix; }
124 const SkMatrix& localMatrix() const { return SkMatrix::I(); }
125
126 class GLSLProcessor : public GrGLSLGeometryProcessor {
127 public:
128 GLSLProcessor(const GrGeometryProcessor& qpr) {}
129
130 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
131 const MSAAQuadProcessor& qp = args.fGP.cast<MSAAQuadProcessor>();
132 GrGLSLVertexBuilder* vsBuilder = args.fVertBuilder;
133 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
134 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
135
136 // emit attributes
137 varyingHandler->emitAttributes(qp);
138 varyingHandler->addPassThroughAttribute(qp.inColor(), args.fOutputColor);
139
140 GrGLSLVertToFrag uv(kVec2f_GrSLType);
141 varyingHandler->addVarying("uv", &uv, kHigh_GrSLPrecision);
142 vsBuilder->codeAppendf("%s = %s;", uv.vsOut(), qp.inUV()->fName);
143
144 // Setup position
145 this->setupPosition(vsBuilder, uniformHandler, gpArgs, qp.inPosition()->fName,
146 qp.viewMatrix(), &fViewMatrixUniform);
147
148 // emit transforms
149 this->emitTransforms(vsBuilder, varyingHandler, uniformHandler, gpArgs->fPositionVar,
150 qp.inPosition()->fName, SkMatrix::I(), args.fTransformsIn,
151 args.fTransformsOut);
152
153 GrGLSLPPFragmentBuilder* fsBuilder = args.fFragBuilder;
154 fsBuilder->codeAppendf("if (%s.x * %s.x >= %s.y) discard;", uv.fsIn(), uv.fsIn(),
155 uv.fsIn());
156 fsBuilder->codeAppendf("%s = vec4(1.0);", args.fOutputCoverage);
157 }
158
159 static inline void GenKey(const GrGeometryProcessor& gp,
160 const GrGLSLCaps&,
161 GrProcessorKeyBuilder* b) {
162 const MSAAQuadProcessor& qp = gp.cast<MSAAQuadProcessor>();
163 uint32_t key = 0;
164 key |= qp.viewMatrix().hasPerspective() ? 0x1 : 0x0;
165 key |= qp.viewMatrix().isIdentity() ? 0x2: 0x0;
166 b->add32(key);
167 }
168
169 virtual void setData(const GrGLSLProgramDataManager& pdman,
170 const GrPrimitiveProcessor& gp) override {
171 const MSAAQuadProcessor& qp = gp.cast<MSAAQuadProcessor>();
172 if (!qp.viewMatrix().isIdentity()) {
173 float viewMatrix[3 * 3];
174 GrGLSLGetMatrix<3>(viewMatrix, qp.viewMatrix());
175 pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
176 }
177 }
178
179 void setTransformData(const GrPrimitiveProcessor& primProc,
180 const GrGLSLProgramDataManager& pdman,
181 int index,
182 const SkTArray<const GrCoordTransform*, true>& transforms) override {
183 this->setTransformDataHelper<MSAAQuadProcessor>(primProc, pdman, index, transforms);
184 }
185
186 private:
187 typedef GrGLSLGeometryProcessor INHERITED;
188
189 UniformHandle fViewMatrixUniform;
190 };
191
192 virtual void getGLSLProcessorKey(const GrGLSLCaps& caps,
193 GrProcessorKeyBuilder* b) const override {
194 GLSLProcessor::GenKey(*this, caps, b);
195 }
196
197 virtual GrGLSLPrimitiveProcessor* createGLSLInstance(const GrGLSLCaps&) const override {
198 return new GLSLProcessor(*this);
199 }
200
201private:
202 MSAAQuadProcessor(const SkMatrix& viewMatrix)
203 : fViewMatrix(viewMatrix) {
204 this->initClassID<MSAAQuadProcessor>();
205 fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType,
206 kHigh_GrSLPrecision));
207 fInUV = &this->addVertexAttrib(Attribute("inUV", kVec2f_GrVertexAttribType,
208 kHigh_GrSLPrecision));
209 fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexAttribType));
210 this->setSampleShading(1.0f);
211 }
212
213 const Attribute* fInPosition;
214 const Attribute* fInUV;
215 const Attribute* fInColor;
216 SkMatrix fViewMatrix;
217
218 GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
219
220 typedef GrGeometryProcessor INHERITED;
221};
222
223class MSAAPathBatch : public GrVertexBatch {
224public:
225 DEFINE_BATCH_CLASS_ID
226
227 struct Geometry {
228 GrColor fColor;
229 SkPath fPath;
230 SkScalar fTolerance;
231 };
232
233 static MSAAPathBatch* Create(const Geometry& geometry, const SkMatrix& viewMatrix,
234 const SkRect& devBounds) {
235 return new MSAAPathBatch(geometry, viewMatrix, devBounds);
236 }
237
238 const char* name() const override { return "MSAAPathBatch"; }
239
240 void computePipelineOptimizations(GrInitInvariantOutput* color,
241 GrInitInvariantOutput* coverage,
242 GrBatchToXPOverrides* overrides) const override {
243 // When this is called on a batch, there is only one geometry bundle
244 color->setKnownFourComponents(fGeoData[0].fColor);
245 coverage->setKnownSingleComponent(0xff);
246 }
247
248 bool isValid() const {
249 return !fIsIndexed || fMaxLineIndices <= SK_MaxU16;
250 }
251
252private:
253 void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
254 // Handle any color overrides
255 if (!overrides.readsColor()) {
256 fGeoData[0].fColor = GrColor_ILLEGAL;
257 }
258 overrides.getOverrideColorIfSet(&fGeoData[0].fColor);
259 }
260
261 void computeWorstCasePointCount(const SkPath& path, int* subpaths, SkScalar tol,
262 int* outLinePointCount, int* outQuadPointCount) const {
263 int linePointCount = 0;
264 int quadPointCount = 0;
265 *subpaths = 1;
266
267 bool first = true;
268
269 SkPath::Iter iter(path, false);
270 SkPath::Verb verb;
271
272 SkPoint pts[4];
273 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
274 switch (verb) {
275 case SkPath::kLine_Verb:
276 linePointCount += 1;
277 break;
278 case SkPath::kConic_Verb: {
279 SkScalar weight = iter.conicWeight();
280 SkAutoConicToQuads converter;
281 converter.computeQuads(pts, weight, kTolerance);
282 int quadPts = converter.countQuads();
283 linePointCount += quadPts;
284 quadPointCount += 3 * quadPts;
285 }
286 case SkPath::kQuad_Verb:
287 linePointCount += 1;
288 quadPointCount += 3;
289 break;
290 case SkPath::kCubic_Verb: {
291 SkSTArray<15, SkPoint, true> quadPts;
292 GrPathUtils::convertCubicToQuads(pts, kTolerance, &quadPts);
293 int count = quadPts.count();
294 linePointCount += count / 3;
295 quadPointCount += count;
296 break;
297 }
298 case SkPath::kMove_Verb:
299 linePointCount += 1;
300 if (!first) {
301 ++(*subpaths);
302 }
303 break;
304 default:
305 break;
306 }
307 first = false;
308 }
309 *outLinePointCount = linePointCount;
310 *outQuadPointCount = quadPointCount;
311 }
312
313 void onPrepareDraws(Target* target) const override {
314 SkASSERT(this->isValid());
315 if (fMaxLineVertices == 0) {
316 SkASSERT(fMaxQuadVertices == 0);
317 return;
318 }
319
320 GrPrimitiveType primitiveType = fIsIndexed ? kTriangles_GrPrimitiveType
321 : kTriangleFan_GrPrimitiveType;
322
323 // allocate vertex / index buffers
324 const GrBuffer* lineVertexBuffer;
325 int firstLineVertex;
326 MSAALineVertices lines;
327 size_t lineVertexStride = sizeof(MSAALineVertices::Vertex);
328 lines.vertices = (MSAALineVertices::Vertex*) target->makeVertexSpace(lineVertexStride,
329 fMaxLineVertices,
330 &lineVertexBuffer,
331 &firstLineVertex);
332 if (!lines.vertices) {
333 SkDebugf("Could not allocate vertices\n");
334 return;
335 }
336 lines.nextVertex = lines.vertices;
337 SkDEBUGCODE(lines.verticesEnd = lines.vertices + fMaxLineVertices;)
338
339 MSAAQuadVertices quads;
340 size_t quadVertexStride = sizeof(MSAAQuadVertices::Vertex);
341 SkAutoFree quadVertexPtr(sk_malloc_throw(fMaxQuadVertices * quadVertexStride));
342 quads.vertices = (MSAAQuadVertices::Vertex*) quadVertexPtr.get();
343 quads.nextVertex = quads.vertices;
344 SkDEBUGCODE(quads.verticesEnd = quads.vertices + fMaxQuadVertices;)
345
346 const GrBuffer* lineIndexBuffer = nullptr;
347 int firstLineIndex;
348 if (fIsIndexed) {
349 lines.indices = target->makeIndexSpace(fMaxLineIndices, &lineIndexBuffer,
350 &firstLineIndex);
351 if (!lines.indices) {
352 SkDebugf("Could not allocate indices\n");
353 return;
354 }
355 lines.nextIndex = lines.indices;
356 } else {
357 lines.indices = nullptr;
358 lines.nextIndex = nullptr;
359 }
360
361 SkAutoFree quadIndexPtr;
362 if (fIsIndexed) {
363 quads.indices = (uint16_t*) sk_malloc_throw(fMaxQuadIndices * sizeof(uint16_t));
364 quadIndexPtr.set(quads.indices);
365 quads.nextIndex = quads.indices;
366 } else {
367 quads.indices = nullptr;
368 quads.nextIndex = nullptr;
369 }
370
371 // fill buffers
372 for (int i = 0; i < fGeoData.count(); i++) {
373 const Geometry& args = fGeoData[i];
374
375 if (!this->createGeom(lines,
376 quads,
377 args.fPath,
378 args.fTolerance,
379 fViewMatrix,
380 args.fColor,
381 fIsIndexed)) {
382 return;
383 }
384 }
385 int lineVertexOffset = (int) (lines.nextVertex - lines.vertices);
386 int lineIndexOffset = (int) (lines.nextIndex - lines.indices);
387 SkASSERT(lineVertexOffset <= fMaxLineVertices && lineIndexOffset <= fMaxLineIndices);
388 int quadVertexOffset = (int) (quads.nextVertex - quads.vertices);
389 int quadIndexOffset = (int) (quads.nextIndex - quads.indices);
390 SkASSERT(quadVertexOffset <= fMaxQuadVertices && quadIndexOffset <= fMaxQuadIndices);
391
392 if (lineVertexOffset) {
393 SkAutoTUnref<const GrGeometryProcessor> lineGP;
394 {
395 using namespace GrDefaultGeoProcFactory;
396 lineGP.reset(GrDefaultGeoProcFactory::Create(Color(Color::kAttribute_Type),
397 Coverage(255),
398 LocalCoords(LocalCoords::kUnused_Type),
399 fViewMatrix));
400 }
401 SkASSERT(lineVertexStride == lineGP->getVertexStride());
402
403 GrMesh lineMeshes;
404 if (fIsIndexed) {
405 lineMeshes.initIndexed(primitiveType, lineVertexBuffer, lineIndexBuffer,
406 firstLineVertex, firstLineIndex, lineVertexOffset,
407 lineIndexOffset);
408 } else {
409 lineMeshes.init(primitiveType, lineVertexBuffer, firstLineVertex,
410 lineVertexOffset);
411 }
412 target->draw(lineGP, lineMeshes);
413 }
414
415 if (quadVertexOffset) {
416 SkAutoTUnref<const GrGeometryProcessor> quadGP(MSAAQuadProcessor::Create(fViewMatrix));
417 SkASSERT(quadVertexStride == quadGP->getVertexStride());
418
419 const GrBuffer* quadVertexBuffer;
420 int firstQuadVertex;
421 MSAAQuadVertices::Vertex* quadVertices = (MSAAQuadVertices::Vertex*)
422 target->makeVertexSpace(quadVertexStride, quadVertexOffset, &quadVertexBuffer,
423 &firstQuadVertex);
424 memcpy(quadVertices, quads.vertices, quadVertexStride * quadVertexOffset);
425 GrMesh quadMeshes;
426 if (fIsIndexed) {
427 const GrBuffer* quadIndexBuffer;
428 int firstQuadIndex;
429 uint16_t* quadIndices = (uint16_t*) target->makeIndexSpace(quadIndexOffset,
430 &quadIndexBuffer,
431 &firstQuadIndex);
432 memcpy(quadIndices, quads.indices, sizeof(uint16_t) * quadIndexOffset);
433 quadMeshes.initIndexed(kTriangles_GrPrimitiveType, quadVertexBuffer,
434 quadIndexBuffer, firstQuadVertex, firstQuadIndex,
435 quadVertexOffset, quadIndexOffset);
436 } else {
437 quadMeshes.init(kTriangles_GrPrimitiveType, quadVertexBuffer, firstQuadVertex,
438 quadVertexOffset);
439 }
440 target->draw(quadGP, quadMeshes);
441 }
442 }
443
444 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
445
446 MSAAPathBatch(const Geometry& geometry, const SkMatrix& viewMatrix, const SkRect& devBounds)
447 : INHERITED(ClassID())
448 , fViewMatrix(viewMatrix) {
449 fGeoData.push_back(geometry);
450 this->setBounds(devBounds);
451 int contourCount;
452 this->computeWorstCasePointCount(geometry.fPath, &contourCount, kTolerance,
453 &fMaxLineVertices, &fMaxQuadVertices);
454 fMaxLineIndices = fMaxLineVertices * 3;
455 fMaxQuadIndices = fMaxQuadVertices * 3;
456 fIsIndexed = contourCount > 1;
457 }
458
459 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
460 MSAAPathBatch* that = t->cast<MSAAPathBatch>();
461 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
462 that->bounds(), caps)) {
463 return false;
464 }
465
466 if (!fViewMatrix.cheapEqualTo(that->fViewMatrix)) {
467 return false;
468 }
469
470 if ((fMaxLineIndices + that->fMaxLineIndices > SK_MaxU16) ||
471 (fMaxQuadIndices + that->fMaxQuadIndices > SK_MaxU16)) {
472 return false;
473 }
474
475 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin());
476 this->joinBounds(that->bounds());
477 fIsIndexed = true;
478 fMaxLineVertices += that->fMaxLineVertices;
479 fMaxQuadVertices += that->fMaxQuadVertices;
480 fMaxLineIndices += that->fMaxLineIndices;
481 fMaxQuadIndices += that->fMaxQuadIndices;
482 return true;
483 }
484
485 bool createGeom(MSAALineVertices& lines,
486 MSAAQuadVertices& quads,
487 const SkPath& path,
488 SkScalar srcSpaceTol,
489 const SkMatrix& m,
490 SkColor color,
491 bool isIndexed) const {
492 {
493 uint16_t subpathIdxStart = (uint16_t) (lines.nextVertex - lines.vertices);
494
495 SkPoint pts[4];
496
497 bool first = true;
498 SkPath::Iter iter(path, false);
499
500 bool done = false;
501 while (!done) {
502 SkPath::Verb verb = iter.next(pts);
503 switch (verb) {
504 case SkPath::kMove_Verb:
505 if (!first) {
506 uint16_t currIdx = (uint16_t) (lines.nextVertex - lines.vertices);
507 subpathIdxStart = currIdx;
508 }
509 SkASSERT(lines.nextVertex < lines.verticesEnd);
510 *(lines.nextVertex++) = { pts[0], color };
511 break;
512 case SkPath::kLine_Verb:
513 if (isIndexed) {
514 uint16_t prevIdx = (uint16_t) (lines.nextVertex - lines.vertices - 1);
515 if (prevIdx > subpathIdxStart) {
516 append_contour_edge_indices(subpathIdxStart, prevIdx, lines);
517 }
518 }
519 SkASSERT(lines.nextVertex < lines.verticesEnd);
520 *(lines.nextVertex++) = { pts[1], color };
521 break;
522 case SkPath::kConic_Verb: {
523 SkScalar weight = iter.conicWeight();
524 SkAutoConicToQuads converter;
525 const SkPoint* quadPts = converter.computeQuads(pts, weight,
526 kTolerance);
527 for (int i = 0; i < converter.countQuads(); ++i) {
528 add_quad(lines, quads, quadPts + i * 2, color, isIndexed,
529 subpathIdxStart);
530 }
531 break;
532 }
533 case SkPath::kQuad_Verb: {
534 add_quad(lines, quads, pts, color, isIndexed, subpathIdxStart);
535 break;
536 }
537 case SkPath::kCubic_Verb: {
538 SkSTArray<15, SkPoint, true> quadPts;
539 GrPathUtils::convertCubicToQuads(pts, kTolerance, &quadPts);
540 int count = quadPts.count();
541 for (int i = 0; i < count; i += 3) {
542 add_quad(lines, quads, &quadPts[i], color, isIndexed, subpathIdxStart);
543 }
544 break;
545 }
546 case SkPath::kClose_Verb:
547 break;
548 case SkPath::kDone_Verb:
549 done = true;
550 }
551 first = false;
552 }
553 }
554 return true;
555 }
556
557 SkSTArray<1, Geometry, true> fGeoData;
558
559 SkMatrix fViewMatrix;
560 int fMaxLineVertices;
561 int fMaxQuadVertices;
562 int fMaxLineIndices;
563 int fMaxQuadIndices;
564 bool fIsIndexed;
565
566 typedef GrVertexBatch INHERITED;
567};
568
569bool GrMSAAPathRenderer::internalDrawPath(GrDrawTarget* target,
570 GrPipelineBuilder* pipelineBuilder,
cdalton862cff32016-05-12 15:09:48 -0700571 const GrClip& clip,
ethannicholas6536ae52016-05-02 12:16:49 -0700572 GrColor color,
573 const SkMatrix& viewMatrix,
574 const SkPath& path,
ethannicholas6536ae52016-05-02 12:16:49 -0700575 bool stencilOnly) {
ethannicholas6536ae52016-05-02 12:16:49 -0700576
577 const GrXPFactory* xpFactory = pipelineBuilder->getXPFactory();
578 SkAutoTUnref<const GrXPFactory> backupXPFactory(SkSafeRef(xpFactory));
579 // face culling doesn't make sense here
580 SkASSERT(GrPipelineBuilder::kBoth_DrawFace == pipelineBuilder->getDrawFace());
581
cdalton93a379b2016-05-11 13:58:08 -0700582 int passCount = 0;
583 const GrUserStencilSettings* passes[3];
584 GrPipelineBuilder::DrawFace drawFace[3];
585 bool reverse = false;
586 bool lastPassIsBounds;
ethannicholas6536ae52016-05-02 12:16:49 -0700587
bsalomon6663acf2016-05-10 09:14:17 -0700588 if (single_pass_path(path)) {
ethannicholas6536ae52016-05-02 12:16:49 -0700589 passCount = 1;
590 if (stencilOnly) {
591 passes[0] = &gDirectToStencil;
592 } else {
593 passes[0] = nullptr;
594 }
595 drawFace[0] = GrPipelineBuilder::kBoth_DrawFace;
596 lastPassIsBounds = false;
597 } else {
598 switch (path.getFillType()) {
599 case SkPath::kInverseEvenOdd_FillType:
600 reverse = true;
601 // fallthrough
602 case SkPath::kEvenOdd_FillType:
603 passes[0] = &gEOStencilPass;
604 if (stencilOnly) {
605 passCount = 1;
606 lastPassIsBounds = false;
607 } else {
608 passCount = 2;
609 lastPassIsBounds = true;
610 if (reverse) {
611 passes[1] = &gInvEOColorPass;
612 } else {
613 passes[1] = &gEOColorPass;
614 }
615 }
616 drawFace[0] = drawFace[1] = GrPipelineBuilder::kBoth_DrawFace;
617 break;
618
619 case SkPath::kInverseWinding_FillType:
620 reverse = true;
621 // fallthrough
622 case SkPath::kWinding_FillType:
623 passes[0] = &gWindStencilSeparateWithWrap;
624 passCount = 2;
625 drawFace[0] = GrPipelineBuilder::kBoth_DrawFace;
626 if (stencilOnly) {
627 lastPassIsBounds = false;
628 --passCount;
629 } else {
630 lastPassIsBounds = true;
631 drawFace[passCount-1] = GrPipelineBuilder::kBoth_DrawFace;
632 if (reverse) {
633 passes[passCount-1] = &gInvWindColorPass;
634 } else {
635 passes[passCount-1] = &gWindColorPass;
636 }
637 }
638 break;
639 default:
640 SkDEBUGFAIL("Unknown path fFill!");
641 return false;
642 }
643 }
644
645 SkRect devBounds;
646 GetPathDevBounds(path, pipelineBuilder->getRenderTarget(), viewMatrix, &devBounds);
647
648 for (int p = 0; p < passCount; ++p) {
649 pipelineBuilder->setDrawFace(drawFace[p]);
650 if (passes[p]) {
cdalton93a379b2016-05-11 13:58:08 -0700651 pipelineBuilder->setUserStencil(passes[p]);
ethannicholas6536ae52016-05-02 12:16:49 -0700652 }
653
654 if (lastPassIsBounds && (p == passCount-1)) {
655 // Reset the XP Factory on pipelineBuilder
656 pipelineBuilder->setXPFactory(backupXPFactory);
657 SkRect bounds;
658 SkMatrix localMatrix = SkMatrix::I();
659 if (reverse) {
660 SkASSERT(pipelineBuilder->getRenderTarget());
661 // draw over the dev bounds (which will be the whole dst surface for inv fill).
662 bounds = devBounds;
663 SkMatrix vmi;
664 // mapRect through persp matrix may not be correct
665 if (!viewMatrix.hasPerspective() && viewMatrix.invert(&vmi)) {
666 vmi.mapRect(&bounds);
667 } else {
668 if (!viewMatrix.invert(&localMatrix)) {
669 return false;
670 }
671 }
672 } else {
673 bounds = path.getBounds();
674 }
675 const SkMatrix& viewM = (reverse && viewMatrix.hasPerspective()) ? SkMatrix::I() :
676 viewMatrix;
677 SkAutoTUnref<GrDrawBatch> batch(
678 GrRectBatchFactory::CreateNonAAFill(color, viewM, bounds, nullptr,
679 &localMatrix));
cdalton862cff32016-05-12 15:09:48 -0700680 target->drawBatch(*pipelineBuilder, clip, batch);
ethannicholas6536ae52016-05-02 12:16:49 -0700681 } else {
682 if (passCount > 1) {
683 pipelineBuilder->setDisableColorXPFactory();
684 }
685
686 MSAAPathBatch::Geometry geometry;
687 geometry.fColor = color;
688 geometry.fPath = path;
689 geometry.fTolerance = kTolerance;
690
691 SkAutoTUnref<MSAAPathBatch> batch(MSAAPathBatch::Create(geometry, viewMatrix,
692 devBounds));
693 if (batch->isValid()) {
cdalton862cff32016-05-12 15:09:48 -0700694 target->drawBatch(*pipelineBuilder, clip, batch);
ethannicholas6536ae52016-05-02 12:16:49 -0700695 }
696 else {
697 return false;
698 }
699 }
700 }
701 return true;
702}
703
704bool GrMSAAPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
bsalomon6663acf2016-05-10 09:14:17 -0700705 // This path renderer does not support hairlines. We defer on anything that could be handled
706 // as a hairline by another path renderer. Also, arbitrary path effects could produce
707 // a hairline result.
708 return !IsStrokeHairlineOrEquivalent(*args.fStyle, *args.fViewMatrix, nullptr) &&
709 !args.fStyle->strokeRec().isHairlineStyle() &&
710 !args.fStyle->hasNonDashPathEffect() && !args.fAntiAlias;
ethannicholas6536ae52016-05-02 12:16:49 -0700711}
712
713bool GrMSAAPathRenderer::onDrawPath(const DrawPathArgs& args) {
714 GR_AUDIT_TRAIL_AUTO_FRAME(args.fTarget->getAuditTrail(), "GrMSAAPathRenderer::onDrawPath");
bsalomon6663acf2016-05-10 09:14:17 -0700715 SkPath tmpPath;
716 const SkPath* path;
717 if (args.fStyle->applies()) {
718 SkStrokeRec::InitStyle fill;
719 SkScalar styleScale = GrStyle::MatrixToScaleFactor(*args.fViewMatrix);
720 if (!args.fStyle->applyToPath(&tmpPath, &fill, *args.fPath, styleScale)) {
ethannicholas6536ae52016-05-02 12:16:49 -0700721 return false;
722 }
bsalomon6663acf2016-05-10 09:14:17 -0700723 // We don't accept styles that are hairlines or have path effects that could produce
724 // hairlines.
725 SkASSERT(SkStrokeRec::kFill_InitStyle == fill);
726 path = &tmpPath;
ethannicholas6536ae52016-05-02 12:16:49 -0700727 } else {
bsalomon6663acf2016-05-10 09:14:17 -0700728 path = args.fPath;
ethannicholas6536ae52016-05-02 12:16:49 -0700729 }
730 return this->internalDrawPath(args.fTarget,
731 args.fPipelineBuilder,
cdalton862cff32016-05-12 15:09:48 -0700732 *args.fClip,
ethannicholas6536ae52016-05-02 12:16:49 -0700733 args.fColor,
734 *args.fViewMatrix,
bsalomon6663acf2016-05-10 09:14:17 -0700735 *path,
ethannicholas6536ae52016-05-02 12:16:49 -0700736 false);
737}
738
739void GrMSAAPathRenderer::onStencilPath(const StencilPathArgs& args) {
740 GR_AUDIT_TRAIL_AUTO_FRAME(args.fTarget->getAuditTrail(),"GrMSAAPathRenderer::onStencilPath");
741 SkASSERT(SkPath::kInverseEvenOdd_FillType != args.fPath->getFillType());
742 SkASSERT(SkPath::kInverseWinding_FillType != args.fPath->getFillType());
cdalton862cff32016-05-12 15:09:48 -0700743 this->internalDrawPath(args.fTarget, args.fPipelineBuilder, *args.fClip, GrColor_WHITE,
744 *args.fViewMatrix, *args.fPath, true);
ethannicholas6536ae52016-05-02 12:16:49 -0700745}
746
747///////////////////////////////////////////////////////////////////////////////////////////////////