blob: cd039ece8d3349a40bf5702371d6dfbe476e3d7a [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
robertphillips976f5f02016-06-03 10:59:20 -070010#include "GrAuditTrail.h"
ethannicholas6536ae52016-05-02 12:16:49 -070011#include "GrBatchFlushState.h"
robertphillips976f5f02016-06-03 10:59:20 -070012#include "GrClip.h"
ethannicholas6536ae52016-05-02 12:16:49 -070013#include "GrDefaultGeoProcFactory.h"
14#include "GrPathStencilSettings.h"
15#include "GrPathUtils.h"
16#include "GrPipelineBuilder.h"
17#include "GrMesh.h"
18#include "SkGeometry.h"
19#include "SkTraceEvent.h"
20#include "glsl/GrGLSLGeometryProcessor.h"
21#include "glsl/GrGLSLFragmentShaderBuilder.h"
22#include "glsl/GrGLSLVertexShaderBuilder.h"
23#include "glsl/GrGLSLProgramDataManager.h"
24#include "glsl/GrGLSLUtil.h"
25#include "gl/GrGLVaryingHandler.h"
26#include "batches/GrRectBatchFactory.h"
27#include "batches/GrVertexBatch.h"
28
29static const float kTolerance = 0.5f;
30
31////////////////////////////////////////////////////////////////////////////////
32// Helpers for drawPath
33
bsalomon8acedde2016-06-24 10:42:16 -070034static inline bool single_pass_shape(const GrShape& shape) {
35 if (!shape.inverseFilled()) {
36 return shape.knownToBeConvex();
ethannicholas6536ae52016-05-02 12:16:49 -070037 }
38 return false;
39}
40
bsalomon8acedde2016-06-24 10:42:16 -070041GrPathRenderer::StencilSupport GrMSAAPathRenderer::onGetStencilSupport(const GrShape& shape) const {
42 if (single_pass_shape(shape)) {
ethannicholas6536ae52016-05-02 12:16:49 -070043 return GrPathRenderer::kNoRestriction_StencilSupport;
44 } else {
45 return GrPathRenderer::kStencilOnly_StencilSupport;
46 }
47}
48
49struct MSAALineVertices {
50 struct Vertex {
51 SkPoint fPosition;
52 SkColor fColor;
53 };
54 Vertex* vertices;
55 Vertex* nextVertex;
56#ifdef SK_DEBUG
57 Vertex* verticesEnd;
58#endif
59 uint16_t* indices;
60 uint16_t* nextIndex;
61};
62
63struct MSAAQuadVertices {
64 struct Vertex {
65 SkPoint fPosition;
66 SkPoint fUV;
67 SkColor fColor;
68 };
69 Vertex* vertices;
70 Vertex* nextVertex;
71#ifdef SK_DEBUG
72 Vertex* verticesEnd;
73#endif
74 uint16_t* indices;
75 uint16_t* nextIndex;
76};
77
78static inline void append_contour_edge_indices(uint16_t fanCenterIdx,
79 uint16_t edgeV0Idx,
80 MSAALineVertices& lines) {
81 *(lines.nextIndex++) = fanCenterIdx;
82 *(lines.nextIndex++) = edgeV0Idx;
83 *(lines.nextIndex++) = edgeV0Idx + 1;
84}
85
bungeman06ca8ec2016-06-09 08:01:03 -070086static inline void add_quad(MSAALineVertices& lines, MSAAQuadVertices& quads, const SkPoint pts[],
ethannicholas6536ae52016-05-02 12:16:49 -070087 SkColor color, bool indexed, uint16_t subpathLineIdxStart) {
88 SkASSERT(lines.nextVertex < lines.verticesEnd);
89 *lines.nextVertex = { pts[2], color };
90 if (indexed) {
91 int prevIdx = (uint16_t) (lines.nextVertex - lines.vertices - 1);
92 if (prevIdx > subpathLineIdxStart) {
93 append_contour_edge_indices(subpathLineIdxStart, prevIdx, lines);
94 }
95 }
96 lines.nextVertex++;
97
98 SkASSERT(quads.nextVertex + 2 < quads.verticesEnd);
99 // the texture coordinates are drawn from the Loop-Blinn rendering algorithm
100 *(quads.nextVertex++) = { pts[0], SkPoint::Make(0.0, 0.0), color };
101 *(quads.nextVertex++) = { pts[1], SkPoint::Make(0.5, 0.0), color };
102 *(quads.nextVertex++) = { pts[2], SkPoint::Make(1.0, 1.0), color };
103 if (indexed) {
104 uint16_t offset = (uint16_t) (quads.nextVertex - quads.vertices) - 3;
105 *(quads.nextIndex++) = offset++;
106 *(quads.nextIndex++) = offset++;
107 *(quads.nextIndex++) = offset++;
108 }
109}
110
111class MSAAQuadProcessor : public GrGeometryProcessor {
112public:
113 static GrGeometryProcessor* Create(const SkMatrix& viewMatrix) {
114 return new MSAAQuadProcessor(viewMatrix);
115 }
116
117 virtual ~MSAAQuadProcessor() {}
118
119 const char* name() const override { return "MSAAQuadProcessor"; }
120
121 const Attribute* inPosition() const { return fInPosition; }
122 const Attribute* inUV() const { return fInUV; }
123 const Attribute* inColor() const { return fInColor; }
124 const SkMatrix& viewMatrix() const { return fViewMatrix; }
125 const SkMatrix& localMatrix() const { return SkMatrix::I(); }
126
127 class GLSLProcessor : public GrGLSLGeometryProcessor {
128 public:
129 GLSLProcessor(const GrGeometryProcessor& qpr) {}
130
131 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
132 const MSAAQuadProcessor& qp = args.fGP.cast<MSAAQuadProcessor>();
133 GrGLSLVertexBuilder* vsBuilder = args.fVertBuilder;
134 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
135 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
136
137 // emit attributes
138 varyingHandler->emitAttributes(qp);
139 varyingHandler->addPassThroughAttribute(qp.inColor(), args.fOutputColor);
140
141 GrGLSLVertToFrag uv(kVec2f_GrSLType);
142 varyingHandler->addVarying("uv", &uv, kHigh_GrSLPrecision);
143 vsBuilder->codeAppendf("%s = %s;", uv.vsOut(), qp.inUV()->fName);
144
145 // Setup position
bungeman06ca8ec2016-06-09 08:01:03 -0700146 this->setupPosition(vsBuilder, uniformHandler, gpArgs, qp.inPosition()->fName,
ethannicholas6536ae52016-05-02 12:16:49 -0700147 qp.viewMatrix(), &fViewMatrixUniform);
148
149 // emit transforms
bungeman06ca8ec2016-06-09 08:01:03 -0700150 this->emitTransforms(vsBuilder, varyingHandler, uniformHandler, gpArgs->fPositionVar,
151 qp.inPosition()->fName, SkMatrix::I(), args.fTransformsIn,
ethannicholas6536ae52016-05-02 12:16:49 -0700152 args.fTransformsOut);
153
154 GrGLSLPPFragmentBuilder* fsBuilder = args.fFragBuilder;
bungeman06ca8ec2016-06-09 08:01:03 -0700155 fsBuilder->codeAppendf("if (%s.x * %s.x >= %s.y) discard;", uv.fsIn(), uv.fsIn(),
ethannicholas6536ae52016-05-02 12:16:49 -0700156 uv.fsIn());
157 fsBuilder->codeAppendf("%s = vec4(1.0);", args.fOutputCoverage);
158 }
159
160 static inline void GenKey(const GrGeometryProcessor& gp,
161 const GrGLSLCaps&,
162 GrProcessorKeyBuilder* b) {
163 const MSAAQuadProcessor& qp = gp.cast<MSAAQuadProcessor>();
164 uint32_t key = 0;
165 key |= qp.viewMatrix().hasPerspective() ? 0x1 : 0x0;
166 key |= qp.viewMatrix().isIdentity() ? 0x2: 0x0;
167 b->add32(key);
168 }
169
170 virtual void setData(const GrGLSLProgramDataManager& pdman,
171 const GrPrimitiveProcessor& gp) override {
172 const MSAAQuadProcessor& qp = gp.cast<MSAAQuadProcessor>();
173 if (!qp.viewMatrix().isIdentity()) {
174 float viewMatrix[3 * 3];
175 GrGLSLGetMatrix<3>(viewMatrix, qp.viewMatrix());
176 pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
177 }
178 }
179
180 void setTransformData(const GrPrimitiveProcessor& primProc,
181 const GrGLSLProgramDataManager& pdman,
182 int index,
183 const SkTArray<const GrCoordTransform*, true>& transforms) override {
184 this->setTransformDataHelper<MSAAQuadProcessor>(primProc, pdman, index, transforms);
185 }
186
187 private:
188 typedef GrGLSLGeometryProcessor INHERITED;
189
190 UniformHandle fViewMatrixUniform;
191 };
192
193 virtual void getGLSLProcessorKey(const GrGLSLCaps& caps,
194 GrProcessorKeyBuilder* b) const override {
195 GLSLProcessor::GenKey(*this, caps, b);
196 }
197
198 virtual GrGLSLPrimitiveProcessor* createGLSLInstance(const GrGLSLCaps&) const override {
199 return new GLSLProcessor(*this);
200 }
201
202private:
203 MSAAQuadProcessor(const SkMatrix& viewMatrix)
204 : fViewMatrix(viewMatrix) {
205 this->initClassID<MSAAQuadProcessor>();
bungeman06ca8ec2016-06-09 08:01:03 -0700206 fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType,
ethannicholas6536ae52016-05-02 12:16:49 -0700207 kHigh_GrSLPrecision));
bungeman06ca8ec2016-06-09 08:01:03 -0700208 fInUV = &this->addVertexAttrib(Attribute("inUV", kVec2f_GrVertexAttribType,
ethannicholas6536ae52016-05-02 12:16:49 -0700209 kHigh_GrSLPrecision));
210 fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexAttribType));
211 this->setSampleShading(1.0f);
212 }
213
214 const Attribute* fInPosition;
215 const Attribute* fInUV;
216 const Attribute* fInColor;
217 SkMatrix fViewMatrix;
bungeman06ca8ec2016-06-09 08:01:03 -0700218
ethannicholas6536ae52016-05-02 12:16:49 -0700219 GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
220
221 typedef GrGeometryProcessor INHERITED;
222};
223
224class MSAAPathBatch : public GrVertexBatch {
225public:
226 DEFINE_BATCH_CLASS_ID
227
bsalomon50c56a32016-06-30 12:05:32 -0700228 MSAAPathBatch(GrColor color, const SkPath& path, const SkMatrix& viewMatrix,
229 const SkRect& devBounds)
230 : INHERITED(ClassID())
231 , fViewMatrix(viewMatrix) {
232 fPaths.emplace_back(PathInfo{color, path});
233 this->setBounds(devBounds);
234 int contourCount;
235 this->computeWorstCasePointCount(path, &contourCount, &fMaxLineVertices, &fMaxQuadVertices);
236 fMaxLineIndices = fMaxLineVertices * 3;
237 fMaxQuadIndices = fMaxQuadVertices * 3;
238 fIsIndexed = contourCount > 1;
ethannicholas6536ae52016-05-02 12:16:49 -0700239 }
240
241 const char* name() const override { return "MSAAPathBatch"; }
242
bungeman06ca8ec2016-06-09 08:01:03 -0700243 void computePipelineOptimizations(GrInitInvariantOutput* color,
ethannicholas6536ae52016-05-02 12:16:49 -0700244 GrInitInvariantOutput* coverage,
245 GrBatchToXPOverrides* overrides) const override {
bsalomon50c56a32016-06-30 12:05:32 -0700246 // When this is called on a batch, there is only one path
247 color->setKnownFourComponents(fPaths[0].fColor);
ethannicholas6536ae52016-05-02 12:16:49 -0700248 coverage->setKnownSingleComponent(0xff);
249 }
250
251 bool isValid() const {
252 return !fIsIndexed || fMaxLineIndices <= SK_MaxU16;
253 }
254
255private:
256 void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
257 // Handle any color overrides
258 if (!overrides.readsColor()) {
bsalomon50c56a32016-06-30 12:05:32 -0700259 fPaths[0].fColor = GrColor_ILLEGAL;
ethannicholas6536ae52016-05-02 12:16:49 -0700260 }
bsalomon50c56a32016-06-30 12:05:32 -0700261 overrides.getOverrideColorIfSet(&fPaths[0].fColor);
ethannicholas6536ae52016-05-02 12:16:49 -0700262 }
263
bsalomon50c56a32016-06-30 12:05:32 -0700264 void computeWorstCasePointCount(const SkPath& path, int* subpaths, int* outLinePointCount,
265 int* outQuadPointCount) const {
ethannicholas6536ae52016-05-02 12:16:49 -0700266 int linePointCount = 0;
267 int quadPointCount = 0;
268 *subpaths = 1;
269
270 bool first = true;
271
272 SkPath::Iter iter(path, false);
273 SkPath::Verb verb;
274
275 SkPoint pts[4];
276 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
277 switch (verb) {
278 case SkPath::kLine_Verb:
279 linePointCount += 1;
280 break;
281 case SkPath::kConic_Verb: {
282 SkScalar weight = iter.conicWeight();
283 SkAutoConicToQuads converter;
284 converter.computeQuads(pts, weight, kTolerance);
285 int quadPts = converter.countQuads();
286 linePointCount += quadPts;
287 quadPointCount += 3 * quadPts;
288 }
289 case SkPath::kQuad_Verb:
290 linePointCount += 1;
291 quadPointCount += 3;
292 break;
293 case SkPath::kCubic_Verb: {
294 SkSTArray<15, SkPoint, true> quadPts;
295 GrPathUtils::convertCubicToQuads(pts, kTolerance, &quadPts);
296 int count = quadPts.count();
297 linePointCount += count / 3;
298 quadPointCount += count;
299 break;
300 }
301 case SkPath::kMove_Verb:
302 linePointCount += 1;
303 if (!first) {
304 ++(*subpaths);
305 }
306 break;
307 default:
308 break;
309 }
310 first = false;
311 }
312 *outLinePointCount = linePointCount;
313 *outQuadPointCount = quadPointCount;
314 }
315
316 void onPrepareDraws(Target* target) const override {
317 SkASSERT(this->isValid());
318 if (fMaxLineVertices == 0) {
319 SkASSERT(fMaxQuadVertices == 0);
320 return;
321 }
322
bungeman06ca8ec2016-06-09 08:01:03 -0700323 GrPrimitiveType primitiveType = fIsIndexed ? kTriangles_GrPrimitiveType
ethannicholas6536ae52016-05-02 12:16:49 -0700324 : kTriangleFan_GrPrimitiveType;
325
326 // allocate vertex / index buffers
327 const GrBuffer* lineVertexBuffer;
328 int firstLineVertex;
329 MSAALineVertices lines;
330 size_t lineVertexStride = sizeof(MSAALineVertices::Vertex);
bungeman06ca8ec2016-06-09 08:01:03 -0700331 lines.vertices = (MSAALineVertices::Vertex*) target->makeVertexSpace(lineVertexStride,
ethannicholas6536ae52016-05-02 12:16:49 -0700332 fMaxLineVertices,
bungeman06ca8ec2016-06-09 08:01:03 -0700333 &lineVertexBuffer,
ethannicholas6536ae52016-05-02 12:16:49 -0700334 &firstLineVertex);
335 if (!lines.vertices) {
336 SkDebugf("Could not allocate vertices\n");
337 return;
338 }
339 lines.nextVertex = lines.vertices;
340 SkDEBUGCODE(lines.verticesEnd = lines.vertices + fMaxLineVertices;)
341
342 MSAAQuadVertices quads;
343 size_t quadVertexStride = sizeof(MSAAQuadVertices::Vertex);
344 SkAutoFree quadVertexPtr(sk_malloc_throw(fMaxQuadVertices * quadVertexStride));
345 quads.vertices = (MSAAQuadVertices::Vertex*) quadVertexPtr.get();
346 quads.nextVertex = quads.vertices;
347 SkDEBUGCODE(quads.verticesEnd = quads.vertices + fMaxQuadVertices;)
348
349 const GrBuffer* lineIndexBuffer = nullptr;
350 int firstLineIndex;
351 if (fIsIndexed) {
bungeman06ca8ec2016-06-09 08:01:03 -0700352 lines.indices = target->makeIndexSpace(fMaxLineIndices, &lineIndexBuffer,
ethannicholas6536ae52016-05-02 12:16:49 -0700353 &firstLineIndex);
354 if (!lines.indices) {
355 SkDebugf("Could not allocate indices\n");
356 return;
357 }
358 lines.nextIndex = lines.indices;
359 } else {
360 lines.indices = nullptr;
361 lines.nextIndex = nullptr;
362 }
363
364 SkAutoFree quadIndexPtr;
365 if (fIsIndexed) {
366 quads.indices = (uint16_t*) sk_malloc_throw(fMaxQuadIndices * sizeof(uint16_t));
367 quadIndexPtr.set(quads.indices);
368 quads.nextIndex = quads.indices;
369 } else {
370 quads.indices = nullptr;
371 quads.nextIndex = nullptr;
372 }
373
374 // fill buffers
bsalomon50c56a32016-06-30 12:05:32 -0700375 for (int i = 0; i < fPaths.count(); i++) {
376 const PathInfo& pathInfo = fPaths[i];
ethannicholas6536ae52016-05-02 12:16:49 -0700377
378 if (!this->createGeom(lines,
379 quads,
bsalomon50c56a32016-06-30 12:05:32 -0700380 pathInfo.fPath,
ethannicholas6536ae52016-05-02 12:16:49 -0700381 fViewMatrix,
bsalomon50c56a32016-06-30 12:05:32 -0700382 pathInfo.fColor,
ethannicholas6536ae52016-05-02 12:16:49 -0700383 fIsIndexed)) {
384 return;
385 }
386 }
387 int lineVertexOffset = (int) (lines.nextVertex - lines.vertices);
388 int lineIndexOffset = (int) (lines.nextIndex - lines.indices);
389 SkASSERT(lineVertexOffset <= fMaxLineVertices && lineIndexOffset <= fMaxLineIndices);
390 int quadVertexOffset = (int) (quads.nextVertex - quads.vertices);
391 int quadIndexOffset = (int) (quads.nextIndex - quads.indices);
392 SkASSERT(quadVertexOffset <= fMaxQuadVertices && quadIndexOffset <= fMaxQuadIndices);
393
394 if (lineVertexOffset) {
bungeman06ca8ec2016-06-09 08:01:03 -0700395 sk_sp<GrGeometryProcessor> lineGP;
ethannicholas6536ae52016-05-02 12:16:49 -0700396 {
397 using namespace GrDefaultGeoProcFactory;
bungeman06ca8ec2016-06-09 08:01:03 -0700398 lineGP = GrDefaultGeoProcFactory::Make(Color(Color::kAttribute_Type),
399 Coverage(255),
400 LocalCoords(LocalCoords::kUnused_Type),
401 fViewMatrix);
ethannicholas6536ae52016-05-02 12:16:49 -0700402 }
403 SkASSERT(lineVertexStride == lineGP->getVertexStride());
404
405 GrMesh lineMeshes;
406 if (fIsIndexed) {
bungeman06ca8ec2016-06-09 08:01:03 -0700407 lineMeshes.initIndexed(primitiveType, lineVertexBuffer, lineIndexBuffer,
408 firstLineVertex, firstLineIndex, lineVertexOffset,
ethannicholas6536ae52016-05-02 12:16:49 -0700409 lineIndexOffset);
410 } else {
bungeman06ca8ec2016-06-09 08:01:03 -0700411 lineMeshes.init(primitiveType, lineVertexBuffer, firstLineVertex,
ethannicholas6536ae52016-05-02 12:16:49 -0700412 lineVertexOffset);
413 }
bungeman06ca8ec2016-06-09 08:01:03 -0700414 target->draw(lineGP.get(), lineMeshes);
ethannicholas6536ae52016-05-02 12:16:49 -0700415 }
416
417 if (quadVertexOffset) {
418 SkAutoTUnref<const GrGeometryProcessor> quadGP(MSAAQuadProcessor::Create(fViewMatrix));
419 SkASSERT(quadVertexStride == quadGP->getVertexStride());
420
421 const GrBuffer* quadVertexBuffer;
422 int firstQuadVertex;
bungeman06ca8ec2016-06-09 08:01:03 -0700423 MSAAQuadVertices::Vertex* quadVertices = (MSAAQuadVertices::Vertex*)
ethannicholas6536ae52016-05-02 12:16:49 -0700424 target->makeVertexSpace(quadVertexStride, quadVertexOffset, &quadVertexBuffer,
425 &firstQuadVertex);
426 memcpy(quadVertices, quads.vertices, quadVertexStride * quadVertexOffset);
427 GrMesh quadMeshes;
428 if (fIsIndexed) {
429 const GrBuffer* quadIndexBuffer;
430 int firstQuadIndex;
bungeman06ca8ec2016-06-09 08:01:03 -0700431 uint16_t* quadIndices = (uint16_t*) target->makeIndexSpace(quadIndexOffset,
432 &quadIndexBuffer,
ethannicholas6536ae52016-05-02 12:16:49 -0700433 &firstQuadIndex);
434 memcpy(quadIndices, quads.indices, sizeof(uint16_t) * quadIndexOffset);
bungeman06ca8ec2016-06-09 08:01:03 -0700435 quadMeshes.initIndexed(kTriangles_GrPrimitiveType, quadVertexBuffer,
436 quadIndexBuffer, firstQuadVertex, firstQuadIndex,
ethannicholas6536ae52016-05-02 12:16:49 -0700437 quadVertexOffset, quadIndexOffset);
438 } else {
bungeman06ca8ec2016-06-09 08:01:03 -0700439 quadMeshes.init(kTriangles_GrPrimitiveType, quadVertexBuffer, firstQuadVertex,
ethannicholas6536ae52016-05-02 12:16:49 -0700440 quadVertexOffset);
441 }
442 target->draw(quadGP, quadMeshes);
443 }
444 }
445
ethannicholas6536ae52016-05-02 12:16:49 -0700446 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
447 MSAAPathBatch* that = t->cast<MSAAPathBatch>();
448 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
449 that->bounds(), caps)) {
450 return false;
451 }
452
453 if (!fViewMatrix.cheapEqualTo(that->fViewMatrix)) {
454 return false;
455 }
456
bungeman06ca8ec2016-06-09 08:01:03 -0700457 if ((fMaxLineIndices + that->fMaxLineIndices > SK_MaxU16) ||
ethannicholas6536ae52016-05-02 12:16:49 -0700458 (fMaxQuadIndices + that->fMaxQuadIndices > SK_MaxU16)) {
459 return false;
460 }
461
bsalomon50c56a32016-06-30 12:05:32 -0700462 fPaths.push_back_n(that->fPaths.count(), that->fPaths.begin());
ethannicholas6536ae52016-05-02 12:16:49 -0700463 this->joinBounds(that->bounds());
464 fIsIndexed = true;
465 fMaxLineVertices += that->fMaxLineVertices;
466 fMaxQuadVertices += that->fMaxQuadVertices;
467 fMaxLineIndices += that->fMaxLineIndices;
468 fMaxQuadIndices += that->fMaxQuadIndices;
469 return true;
470 }
471
472 bool createGeom(MSAALineVertices& lines,
473 MSAAQuadVertices& quads,
474 const SkPath& path,
ethannicholas6536ae52016-05-02 12:16:49 -0700475 const SkMatrix& m,
476 SkColor color,
477 bool isIndexed) const {
478 {
479 uint16_t subpathIdxStart = (uint16_t) (lines.nextVertex - lines.vertices);
480
481 SkPoint pts[4];
482
483 bool first = true;
484 SkPath::Iter iter(path, false);
485
486 bool done = false;
487 while (!done) {
488 SkPath::Verb verb = iter.next(pts);
489 switch (verb) {
490 case SkPath::kMove_Verb:
491 if (!first) {
492 uint16_t currIdx = (uint16_t) (lines.nextVertex - lines.vertices);
493 subpathIdxStart = currIdx;
494 }
495 SkASSERT(lines.nextVertex < lines.verticesEnd);
496 *(lines.nextVertex++) = { pts[0], color };
497 break;
498 case SkPath::kLine_Verb:
499 if (isIndexed) {
500 uint16_t prevIdx = (uint16_t) (lines.nextVertex - lines.vertices - 1);
501 if (prevIdx > subpathIdxStart) {
502 append_contour_edge_indices(subpathIdxStart, prevIdx, lines);
503 }
504 }
505 SkASSERT(lines.nextVertex < lines.verticesEnd);
506 *(lines.nextVertex++) = { pts[1], color };
507 break;
508 case SkPath::kConic_Verb: {
509 SkScalar weight = iter.conicWeight();
510 SkAutoConicToQuads converter;
bsalomon50c56a32016-06-30 12:05:32 -0700511 const SkPoint* quadPts = converter.computeQuads(pts, weight, kTolerance);
ethannicholas6536ae52016-05-02 12:16:49 -0700512 for (int i = 0; i < converter.countQuads(); ++i) {
bungeman06ca8ec2016-06-09 08:01:03 -0700513 add_quad(lines, quads, quadPts + i * 2, color, isIndexed,
ethannicholas6536ae52016-05-02 12:16:49 -0700514 subpathIdxStart);
515 }
516 break;
517 }
518 case SkPath::kQuad_Verb: {
519 add_quad(lines, quads, pts, color, isIndexed, subpathIdxStart);
bungeman06ca8ec2016-06-09 08:01:03 -0700520 break;
ethannicholas6536ae52016-05-02 12:16:49 -0700521 }
522 case SkPath::kCubic_Verb: {
523 SkSTArray<15, SkPoint, true> quadPts;
524 GrPathUtils::convertCubicToQuads(pts, kTolerance, &quadPts);
525 int count = quadPts.count();
526 for (int i = 0; i < count; i += 3) {
527 add_quad(lines, quads, &quadPts[i], color, isIndexed, subpathIdxStart);
528 }
529 break;
530 }
531 case SkPath::kClose_Verb:
532 break;
533 case SkPath::kDone_Verb:
534 done = true;
535 }
536 first = false;
537 }
538 }
539 return true;
540 }
541
bsalomon50c56a32016-06-30 12:05:32 -0700542 struct PathInfo {
543 GrColor fColor;
544 SkPath fPath;
545 };
546
547 SkSTArray<1, PathInfo, true> fPaths;
ethannicholas6536ae52016-05-02 12:16:49 -0700548
549 SkMatrix fViewMatrix;
550 int fMaxLineVertices;
551 int fMaxQuadVertices;
552 int fMaxLineIndices;
553 int fMaxQuadIndices;
554 bool fIsIndexed;
555
556 typedef GrVertexBatch INHERITED;
557};
558
robertphillips976f5f02016-06-03 10:59:20 -0700559bool GrMSAAPathRenderer::internalDrawPath(GrDrawContext* drawContext,
560 const GrPaint& paint,
561 const GrUserStencilSettings* userStencilSettings,
cdalton862cff32016-05-12 15:09:48 -0700562 const GrClip& clip,
ethannicholas6536ae52016-05-02 12:16:49 -0700563 GrColor color,
564 const SkMatrix& viewMatrix,
bsalomon8acedde2016-06-24 10:42:16 -0700565 const GrShape& shape,
ethannicholas6536ae52016-05-02 12:16:49 -0700566 bool stencilOnly) {
bsalomon8acedde2016-06-24 10:42:16 -0700567 SkASSERT(shape.style().isSimpleFill());
568 SkPath path;
569 shape.asPath(&path);
570
cdalton93a379b2016-05-11 13:58:08 -0700571 int passCount = 0;
572 const GrUserStencilSettings* passes[3];
573 GrPipelineBuilder::DrawFace drawFace[3];
574 bool reverse = false;
575 bool lastPassIsBounds;
ethannicholas6536ae52016-05-02 12:16:49 -0700576
bsalomon8acedde2016-06-24 10:42:16 -0700577 if (single_pass_shape(shape)) {
ethannicholas6536ae52016-05-02 12:16:49 -0700578 passCount = 1;
579 if (stencilOnly) {
580 passes[0] = &gDirectToStencil;
581 } else {
582 passes[0] = nullptr;
583 }
584 drawFace[0] = GrPipelineBuilder::kBoth_DrawFace;
585 lastPassIsBounds = false;
586 } else {
587 switch (path.getFillType()) {
588 case SkPath::kInverseEvenOdd_FillType:
589 reverse = true;
590 // fallthrough
591 case SkPath::kEvenOdd_FillType:
592 passes[0] = &gEOStencilPass;
593 if (stencilOnly) {
594 passCount = 1;
595 lastPassIsBounds = false;
596 } else {
597 passCount = 2;
598 lastPassIsBounds = true;
599 if (reverse) {
600 passes[1] = &gInvEOColorPass;
601 } else {
602 passes[1] = &gEOColorPass;
603 }
604 }
605 drawFace[0] = drawFace[1] = GrPipelineBuilder::kBoth_DrawFace;
606 break;
607
608 case SkPath::kInverseWinding_FillType:
609 reverse = true;
610 // fallthrough
611 case SkPath::kWinding_FillType:
612 passes[0] = &gWindStencilSeparateWithWrap;
613 passCount = 2;
614 drawFace[0] = GrPipelineBuilder::kBoth_DrawFace;
615 if (stencilOnly) {
616 lastPassIsBounds = false;
617 --passCount;
618 } else {
619 lastPassIsBounds = true;
620 drawFace[passCount-1] = GrPipelineBuilder::kBoth_DrawFace;
621 if (reverse) {
622 passes[passCount-1] = &gInvWindColorPass;
623 } else {
624 passes[passCount-1] = &gWindColorPass;
625 }
626 }
627 break;
628 default:
629 SkDEBUGFAIL("Unknown path fFill!");
630 return false;
631 }
632 }
633
634 SkRect devBounds;
robertphillips976f5f02016-06-03 10:59:20 -0700635 GetPathDevBounds(path, drawContext->width(), drawContext->height(), viewMatrix, &devBounds);
ethannicholas6536ae52016-05-02 12:16:49 -0700636
637 for (int p = 0; p < passCount; ++p) {
ethannicholas6536ae52016-05-02 12:16:49 -0700638 if (lastPassIsBounds && (p == passCount-1)) {
ethannicholas6536ae52016-05-02 12:16:49 -0700639 SkRect bounds;
640 SkMatrix localMatrix = SkMatrix::I();
641 if (reverse) {
ethannicholas6536ae52016-05-02 12:16:49 -0700642 // draw over the dev bounds (which will be the whole dst surface for inv fill).
643 bounds = devBounds;
644 SkMatrix vmi;
645 // mapRect through persp matrix may not be correct
646 if (!viewMatrix.hasPerspective() && viewMatrix.invert(&vmi)) {
647 vmi.mapRect(&bounds);
648 } else {
649 if (!viewMatrix.invert(&localMatrix)) {
650 return false;
651 }
652 }
653 } else {
654 bounds = path.getBounds();
655 }
656 const SkMatrix& viewM = (reverse && viewMatrix.hasPerspective()) ? SkMatrix::I() :
657 viewMatrix;
658 SkAutoTUnref<GrDrawBatch> batch(
659 GrRectBatchFactory::CreateNonAAFill(color, viewM, bounds, nullptr,
660 &localMatrix));
robertphillips976f5f02016-06-03 10:59:20 -0700661
csmartdaltonecbc12b2016-06-08 10:08:43 -0700662 GrPipelineBuilder pipelineBuilder(paint, drawContext->mustUseHWAA(paint));
robertphillips976f5f02016-06-03 10:59:20 -0700663 pipelineBuilder.setDrawFace(drawFace[p]);
664 if (passes[p]) {
665 pipelineBuilder.setUserStencil(passes[p]);
666 } else {
667 pipelineBuilder.setUserStencil(userStencilSettings);
ethannicholas6536ae52016-05-02 12:16:49 -0700668 }
669
robertphillips976f5f02016-06-03 10:59:20 -0700670 drawContext->drawBatch(pipelineBuilder, clip, batch);
671 } else {
bsalomon50c56a32016-06-30 12:05:32 -0700672 SkAutoTUnref<MSAAPathBatch> batch(new MSAAPathBatch(color, path, viewMatrix,
673 devBounds));
robertphillips976f5f02016-06-03 10:59:20 -0700674 if (!batch->isValid()) {
ethannicholas6536ae52016-05-02 12:16:49 -0700675 return false;
676 }
robertphillips976f5f02016-06-03 10:59:20 -0700677
csmartdaltonecbc12b2016-06-08 10:08:43 -0700678 GrPipelineBuilder pipelineBuilder(paint, drawContext->mustUseHWAA(paint));
robertphillips976f5f02016-06-03 10:59:20 -0700679 pipelineBuilder.setDrawFace(drawFace[p]);
680 if (passes[p]) {
681 pipelineBuilder.setUserStencil(passes[p]);
682 } else {
683 pipelineBuilder.setUserStencil(userStencilSettings);
684 }
685 if (passCount > 1) {
686 pipelineBuilder.setDisableColorXPFactory();
687 }
688
689 drawContext->drawBatch(pipelineBuilder, clip, batch);
ethannicholas6536ae52016-05-02 12:16:49 -0700690 }
691 }
692 return true;
693}
694
695bool GrMSAAPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
bsalomonee432412016-06-27 07:18:18 -0700696 // This path renderer only fills and relies on MSAA for antialiasing. Stroked shapes are
697 // handled by passing on the original shape and letting the caller compute the stroked shape
698 // which will have a fill style.
699 return args.fShape->style().isSimpleFill() && !args.fAntiAlias;
ethannicholas6536ae52016-05-02 12:16:49 -0700700}
701
702bool GrMSAAPathRenderer::onDrawPath(const DrawPathArgs& args) {
robertphillips976f5f02016-06-03 10:59:20 -0700703 GR_AUDIT_TRAIL_AUTO_FRAME(args.fDrawContext->auditTrail(),
704 "GrMSAAPathRenderer::onDrawPath");
bsalomon8acedde2016-06-24 10:42:16 -0700705 SkTLazy<GrShape> tmpShape;
706 const GrShape* shape = args.fShape;
707 if (shape->style().applies()) {
bsalomon6663acf2016-05-10 09:14:17 -0700708 SkScalar styleScale = GrStyle::MatrixToScaleFactor(*args.fViewMatrix);
bsalomon8acedde2016-06-24 10:42:16 -0700709 tmpShape.init(args.fShape->applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec, styleScale));
710 shape = tmpShape.get();
ethannicholas6536ae52016-05-02 12:16:49 -0700711 }
robertphillips976f5f02016-06-03 10:59:20 -0700712 return this->internalDrawPath(args.fDrawContext,
713 *args.fPaint,
714 args.fUserStencilSettings,
cdalton862cff32016-05-12 15:09:48 -0700715 *args.fClip,
ethannicholas6536ae52016-05-02 12:16:49 -0700716 args.fColor,
717 *args.fViewMatrix,
bsalomon8acedde2016-06-24 10:42:16 -0700718 *shape,
ethannicholas6536ae52016-05-02 12:16:49 -0700719 false);
720}
721
722void GrMSAAPathRenderer::onStencilPath(const StencilPathArgs& args) {
robertphillips976f5f02016-06-03 10:59:20 -0700723 GR_AUDIT_TRAIL_AUTO_FRAME(args.fDrawContext->auditTrail(),
724 "GrMSAAPathRenderer::onStencilPath");
bsalomon8acedde2016-06-24 10:42:16 -0700725 SkASSERT(args.fShape->style().isSimpleFill());
726 SkASSERT(!args.fShape->mayBeInverseFilledAfterStyling());
robertphillips976f5f02016-06-03 10:59:20 -0700727
728 GrPaint paint;
bungeman06ca8ec2016-06-09 08:01:03 -0700729 paint.setXPFactory(GrDisableColorXPFactory::Make());
robertphillips976f5f02016-06-03 10:59:20 -0700730 paint.setAntiAlias(args.fIsAA);
731
bsalomon8acedde2016-06-24 10:42:16 -0700732 this->internalDrawPath(args.fDrawContext, paint, &GrUserStencilSettings::kUnused, *args.fClip,
733 GrColor_WHITE, *args.fViewMatrix, *args.fShape, true);
ethannicholas6536ae52016-05-02 12:16:49 -0700734}
735
736///////////////////////////////////////////////////////////////////////////////////////////////////