Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(327)

Side by Side Diff: src/gpu/batches/GrMSAAPathRenderer.cpp

Issue 1834133003: added GrMSAAPathRenderer (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: fixed path complexity check Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gpu/batches/GrMSAAPathRenderer.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright 2011 Google Inc.
egdaniel 2016/03/29 20:57:39 2016
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 "GrPathUtils.h"
13 #include "GrPipelineBuilder.h"
14 #include "GrMesh.h"
15 #include "SkGeometry.h"
16 #include "SkTraceEvent.h"
17 #include "glsl/GrGLSLGeometryProcessor.h"
18 #include "glsl/GrGLSLFragmentShaderBuilder.h"
19 #include "glsl/GrGLSLVertexShaderBuilder.h"
20 #include "glsl/GrGLSLProgramDataManager.h"
21 #include "glsl/GrGLSLUtil.h"
22 #include "gl/GrGLVaryingHandler.h"
23 #include "batches/GrRectBatchFactory.h"
24 #include "batches/GrVertexBatch.h"
25
26 static const float kTolerance = 0.5f;
27
28 ////////////////////////////////////////////////////////////////////////////////
29 // Stencil rules for paths
egdaniel 2016/03/29 20:57:39 Can we share all these with default path renderer
30
31 ////// Even/Odd
32
33 GR_STATIC_CONST_SAME_STENCIL(gEOStencilPass,
34 kInvert_StencilOp,
35 kKeep_StencilOp,
36 kAlwaysIfInClip_StencilFunc,
37 0xffff,
38 0xffff,
39 0xffff);
40
41 // ok not to check clip b/c stencil pass only wrote inside clip
42 GR_STATIC_CONST_SAME_STENCIL(gEOColorPass,
43 kZero_StencilOp,
44 kZero_StencilOp,
45 kNotEqual_StencilFunc,
46 0xffff,
47 0x0000,
48 0xffff);
49
50 // have to check clip b/c outside clip will always be zero.
51 GR_STATIC_CONST_SAME_STENCIL(gInvEOColorPass,
52 kZero_StencilOp,
53 kZero_StencilOp,
54 kEqualIfInClip_StencilFunc,
55 0xffff,
56 0x0000,
57 0xffff);
58
59 ////// Winding
60
61 GR_STATIC_CONST_STENCIL(gWindStencil,
62 kIncWrap_StencilOp, kDecWrap_StencilOp,
63 kKeep_StencilOp, kKeep_StencilOp,
64 kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
65 0xffff, 0xffff,
66 0xffff, 0xffff,
67 0xffff, 0xffff);
68
69 // Color passes are the same whether we use the two-sided stencil or two passes
70
71 GR_STATIC_CONST_SAME_STENCIL(gWindColorPass,
72 kZero_StencilOp,
73 kZero_StencilOp,
74 kNonZeroIfInClip_StencilFunc,
75 0xffff,
76 0x0000,
77 0xffff);
78
79 GR_STATIC_CONST_SAME_STENCIL(gInvWindColorPass,
80 kZero_StencilOp,
81 kZero_StencilOp,
82 kEqualIfInClip_StencilFunc,
83 0xffff,
84 0x0000,
85 0xffff);
86
87 ////// Normal render to stencil
88
89 // Sometimes the renderer can draw a path directly to the stencil buffer without
90 // having to first resolve the interior / exterior.
91 GR_STATIC_CONST_SAME_STENCIL(gDirectToStencil,
92 kZero_StencilOp,
93 kIncClamp_StencilOp,
94 kAlwaysIfInClip_StencilFunc,
95 0xffff,
96 0x0000,
97 0xffff);
98
99 ////////////////////////////////////////////////////////////////////////////////
100 // Helpers for drawPath
101
102 static inline bool single_pass_path(const SkPath& path, const SkStrokeRec& strok e) {
103 if (!path.isInverseFillType()) {
104 return path.isConvex();
105 }
106 return false;
107 }
108
109 GrPathRenderer::StencilSupport
110 GrMSAAPathRenderer::onGetStencilSupport(const SkPath& path, const GrStrokeInfo& stroke) const {
111 if (single_pass_path(path, stroke)) {
112 return GrPathRenderer::kNoRestriction_StencilSupport;
113 } else {
114 return GrPathRenderer::kStencilOnly_StencilSupport;
115 }
116 }
117
118 struct MSAALineVertices {
119 SkPoint* vertices;
120 SkPoint* nextVertex;
121 #ifdef SK_DEBUG
122 SkPoint* verticesEnd;
123 #endif
124 uint16_t* indices;
125 uint16_t* nextIndex;
126 };
127
128 struct MSAAQuadVertices {
129 struct Vertex {
130 SkPoint position;
131 SkPoint uv;
132 };
133 Vertex* vertices;
134 Vertex* nextVertex;
135 #ifdef SK_DEBUG
136 Vertex* verticesEnd;
137 #endif
138 uint16_t* indices;
139 uint16_t* nextIndex;
140 };
141
142 static inline void append_contour_edge_indices(uint16_t fanCenterIdx,
143 uint16_t edgeV0Idx,
egdaniel 2016/03/29 20:57:39 align these
144 MSAALineVertices& lines) {
145 *(lines.nextIndex++) = fanCenterIdx;
146 *(lines.nextIndex++) = edgeV0Idx;
147 *(lines.nextIndex++) = edgeV0Idx + 1;
148 }
149
150 static inline void add_quad(MSAALineVertices& lines, MSAAQuadVertices& quads, co nst SkPoint pts[],
151 bool indexed, uint16_t subpathLineIdxStart) {
152 SkASSERT(lines.nextVertex < lines.verticesEnd);
153 *lines.nextVertex = pts[2];
154 if (indexed) {
155 int prevIdx = (uint16_t) (lines.nextVertex - lines.vertices - 1);
156 if (prevIdx > subpathLineIdxStart) {
157 append_contour_edge_indices(subpathLineIdxStart, prevIdx, lines);
158 }
159 }
160 lines.nextVertex++;
161
162 SkASSERT(quads.nextVertex + 2 < quads.verticesEnd);
163 // the texture coordinates are drawn from the Loop-Blinn rendering algorithm
164 *(quads.nextVertex++) = { pts[0], SkPoint::Make(0.0, 0.0) };
165 *(quads.nextVertex++) = { pts[1], SkPoint::Make(0.5, 0.0) };
166 *(quads.nextVertex++) = { pts[2], SkPoint::Make(1.0, 1.0) };
167 if (indexed) {
168 uint16_t offset = (uint16_t) (quads.nextVertex - quads.vertices) - 3;
169 *(quads.nextIndex++) = offset++;
170 *(quads.nextIndex++) = offset++;
171 *(quads.nextIndex++) = offset++;
172 }
173 }
174
175 class MSAAQuadProcessor : public GrGeometryProcessor {
176 public:
177 static GrGeometryProcessor* Create(GrColor color,
178 const SkMatrix& viewMatrix) {
179 return new MSAAQuadProcessor(color, viewMatrix);
180 }
181
182 virtual ~MSAAQuadProcessor() {}
183
184 const char* name() const override { return "MSAAQuadProcessor"; }
185
186 const Attribute* inPosition() const { return fInPosition; }
187 const Attribute* inUV() const { return fInUV; }
188 GrColor color() const { return fColor; }
189 bool colorIgnored() const { return GrColor_ILLEGAL == fColor; }
190 const SkMatrix& viewMatrix() const { return fViewMatrix; }
191 const SkMatrix& localMatrix() const { return SkMatrix::I(); }
192 bool usesLocalCoords() const { return fUsesLocalCoords; }
193
194 class GLSLProcessor : public GrGLSLGeometryProcessor {
195 public:
196 GLSLProcessor(const GrGeometryProcessor& qpr) {}
197
198 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
199 const MSAAQuadProcessor& qp = args.fGP.cast<MSAAQuadProcessor>();
200 GrGLSLVertexBuilder* vsBuilder = args.fVertBuilder;
201 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
202 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
203
204 // emit attributes
205 varyingHandler->emitAttributes(qp);
206
207 GrGLSLVertToFrag uv(kVec2f_GrSLType);
208 varyingHandler->addVarying("uv", &uv, kHigh_GrSLPrecision);
209 vsBuilder->codeAppendf("%s = %s;", uv.vsOut(), qp.inUV()->fName);
210
211 // Setup position
212 this->setupPosition(vsBuilder, uniformHandler, gpArgs, qp.inPosition ()->fName,
213 qp.viewMatrix(), &fViewMatrixUniform);
214
215 // emit transforms
216 this->emitTransforms(vsBuilder, varyingHandler, uniformHandler, gpAr gs->fPositionVar,
217 qp.inPosition()->fName, SkMatrix::I(), args.fTr ansformsIn,
218 args.fTransformsOut);
219
220 GrGLSLPPFragmentBuilder* fsBuilder = args.fFragBuilder;
221 fsBuilder->codeAppendf("if (%s.x * %s.x >= %s.y) discard;", uv.fsIn( ), uv.fsIn(),
222 uv.fsIn( ));
223 fsBuilder->codeAppendf("%s = vec4(1.0);", args.fOutputCoverage);
224 if (!qp.colorIgnored()) {
225 this->setupUniformColor(fsBuilder, uniformHandler, args.fOutputC olor,
226 &fColorUniform);
227 }
228 }
229
230 static inline void GenKey(const GrGeometryProcessor& gp,
231 const GrGLSLCaps&,
232 GrProcessorKeyBuilder* b) {
233 const MSAAQuadProcessor& qp = gp.cast<MSAAQuadProcessor>();
234 uint32_t key = 0;
235 key |= qp.viewMatrix().hasPerspective() ? 0x1 : 0x0;
egdaniel 2016/03/29 20:57:39 something feels wrong with having to check perspec
ethannicholas 2016/03/31 19:33:35 GrGLSLGeometryProcessor::setupPosition generates d
236 key |= qp.viewMatrix().isIdentity() ? 0x2: 0x0;
237 b->add32(key);
238 }
239
240 virtual void setData(const GrGLSLProgramDataManager& pdman,
241 const GrPrimitiveProcessor& gp) override {
242 const MSAAQuadProcessor& qp = gp.cast<MSAAQuadProcessor>();
243 if (!qp.colorIgnored()) {
244 GrGLfloat c[4];
245 GrColorToRGBAFloat(qp.color(), c);
246 pdman.set4fv(fColorUniform, 1, c);
247 fColor = qp.color();
248 }
249 if (!qp.viewMatrix().isIdentity()) {
250 float viewMatrix[3 * 3];
251 GrGLSLGetMatrix<3>(viewMatrix, qp.viewMatrix());
252 pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
253 }
254 }
255
256 void setTransformData(const GrPrimitiveProcessor& primProc,
257 const GrGLSLProgramDataManager& pdman,
258 int index,
259 const SkTArray<const GrCoordTransform*, true>& tra nsforms) override {
260 this->setTransformDataHelper<MSAAQuadProcessor>(primProc, pdman, ind ex, transforms);
261 }
262
263 private:
264 typedef GrGLSLGeometryProcessor INHERITED;
265
266 GrColor fColor;
egdaniel 2016/03/29 20:57:39 why are you storing fColor on the GLSLProcessor?
ethannicholas 2016/03/31 19:33:35 Cared about it at one point, forgot to remove the
267 UniformHandle fColorUniform;
268 UniformHandle fViewMatrixUniform;
269 };
270
271 virtual void getGLSLProcessorKey(const GrGLSLCaps& caps,
272 GrProcessorKeyBuilder* b) const override {
273 GLSLProcessor::GenKey(*this, caps, b);
274 }
275
276 virtual GrGLSLPrimitiveProcessor* createGLSLInstance(const GrGLSLCaps&) cons t override {
277 return new GLSLProcessor(*this);
278 }
279
280 private:
281 MSAAQuadProcessor(GrColor color, const SkMatrix& viewMatrix)
282 : fColor(color)
283 , fViewMatrix(viewMatrix) {
284 this->initClassID<MSAAQuadProcessor>();
285 fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVe rtexAttribType,
286 kHigh_GrSLPrecision));
287 fInUV = &this->addVertexAttrib(Attribute("inUV", kVec2f_GrVertexAttribTy pe,
288 kHigh_GrSLPrecision));
289 this->setSampleShading(1.0f);
290 }
291
292 const GrColor fColor;
293 const Attribute* fInPosition;
294 const Attribute* fInUV;
295 SkMatrix fViewMatrix;
296 bool fUsesLocalCoords;
297
298 GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
299
300 typedef GrGeometryProcessor INHERITED;
301 };
302
303 class MSAAPathBatch : public GrVertexBatch {
304 public:
305 DEFINE_BATCH_CLASS_ID
306
307 struct Geometry {
308 GrColor fColor;
309 SkPath fPath;
310 SkScalar fTolerance;
311 };
312
313 static GrDrawBatch* Create(const Geometry& geometry, uint8_t coverage,
314 const SkMatrix& viewMatrix, const SkRect& devBoun ds) {
315 return new MSAAPathBatch(geometry, coverage, viewMatrix, devBounds);
316 }
317
318 const char* name() const override { return "MSAAPathBatch"; }
319
320 void computePipelineOptimizations(GrInitInvariantOutput* color,
321 GrInitInvariantOutput* coverage,
322 GrBatchToXPOverrides* overrides) const ove rride {
323 // When this is called on a batch, there is only one geometry bundle
324 color->setKnownFourComponents(fGeoData[0].fColor);
325 coverage->setKnownSingleComponent(this->coverage());
326 }
327
328 private:
329 void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
330 // Handle any color overrides
331 if (!overrides.readsColor()) {
332 fGeoData[0].fColor = GrColor_ILLEGAL;
333 }
334 overrides.getOverrideColorIfSet(&fGeoData[0].fColor);
335
336 // setup batch properties
337 fBatch.fColorIgnored = !overrides.readsColor();
338 fBatch.fColor = fGeoData[0].fColor;
339 fBatch.fUsesLocalCoords = overrides.readsLocalCoords();
340 fBatch.fCoverageIgnored = !overrides.readsCoverage();
341 }
342
343 void computeWorstCasePointCount(const SkPath& path, int* subpaths, SkScalar tol,
344 int* outLinePointCount, int* outQuadPointCou nt) const {
345 int linePointCount = 0;
346 int quadPointCount = 0;
347 *subpaths = 1;
348
349 bool first = true;
350
351 SkPath::Iter iter(path, false);
352 SkPath::Verb verb;
353
354 SkPoint pts[4];
355 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
356 switch (verb) {
357 case SkPath::kLine_Verb:
358 linePointCount += 1;
359 break;
360 case SkPath::kConic_Verb: {
361 SkScalar weight = iter.conicWeight();
362 SkAutoConicToQuads converter;
363 converter.computeQuads(pts, weight, kTolerance);
364 int quadPts = converter.countQuads();
365 linePointCount += quadPts;
366 quadPointCount += 3 * quadPts;
367 }
368 case SkPath::kQuad_Verb:
369 linePointCount += 1;
370 quadPointCount += 3;
371 break;
372 case SkPath::kCubic_Verb: {
373 SkSTArray<15, SkPoint, true> quadPts;
374 GrPathUtils::convertCubicToQuads(pts, kTolerance, &quadPts);
375 int count = quadPts.count();
376 linePointCount += count / 3;
377 quadPointCount += count;
378 break;
379 }
380 case SkPath::kMove_Verb:
381 linePointCount += 1;
382 if (!first) {
383 ++(*subpaths);
384 }
385 break;
386 default:
387 break;
388 }
389 first = false;
390 }
391 *outLinePointCount = linePointCount;
392 *outQuadPointCount = quadPointCount;
393 }
394
395 void onPrepareDraws(Target* target) const override {
396 SkAutoTUnref<const GrGeometryProcessor> lineGP;
397 {
398 using namespace GrDefaultGeoProcFactory;
399 Color color(this->color());
400 Coverage coverage(this->coverage());
401 if (this->coverageIgnored()) {
402 coverage.fType = Coverage::kNone_Type;
403 }
404 LocalCoords localCoords(this->usesLocalCoords() ? LocalCoords::kUseP osition_Type :
405 LocalCoords::kUnus ed_Type);
406 lineGP.reset(GrDefaultGeoProcFactory::Create(color, coverage, localC oords,
407 this->viewMatrix()));
408 }
409
410 size_t lineVertexStride = lineGP->getVertexStride();
411 SkASSERT(lineVertexStride == sizeof(SkPoint));
412
413 SkAutoTUnref<const GrGeometryProcessor> quadGP;
414 {
415 using namespace GrDefaultGeoProcFactory;
416 Color color(this->color());
417 Coverage coverage(this->coverage());
418 if (this->coverageIgnored()) {
419 coverage.fType = Coverage::kNone_Type;
420 }
421 quadGP.reset(MSAAQuadProcessor::Create(this->color(), this->viewMatr ix()));
422 }
423 size_t quadVertexStride = quadGP->getVertexStride();
424 SkASSERT(quadVertexStride == sizeof(MSAAQuadVertices::Vertex));
425
426 int instanceCount = fGeoData.count();
427
428 // compute number of vertices
429 int maxLineVertices = 0;
430 int maxQuadVertices = 0;
431
432 // We will use index buffers if we have multiple paths or one path with multiple contours
433 bool isIndexed = instanceCount > 1;
434 for (int i = 0; i < instanceCount; i++) {
435 const Geometry& args = fGeoData[i];
436
437 int contourCount;
438 int lineVertices;
439 int quadVertices;
440 this->computeWorstCasePointCount(args.fPath, &contourCount, kToleran ce,
441 &lineVertices, &quadVertices);
442 maxLineVertices += lineVertices;
443 maxQuadVertices += quadVertices;
444 isIndexed = isIndexed || contourCount > 1;
445 }
446
447 if (maxLineVertices == 0) {
448 SkASSERT(maxQuadVertices == 0);
449 return;
450 }
451
452 // determine primitiveType
453 int maxLineIndices;
454 int maxQuadIndices;
455 GrPrimitiveType primitiveType;
456 if (isIndexed) {
457 maxLineIndices = maxLineVertices * 3;
458 maxQuadIndices = maxQuadVertices * 3;
459 primitiveType = kTriangles_GrPrimitiveType;
460 } else {
461 maxLineIndices = 0;
462 maxQuadIndices = 0;
463 primitiveType = kTriangleFan_GrPrimitiveType;
464 }
465
466 if (isIndexed && (maxLineIndices > SK_MaxU16 || maxQuadIndices > SK_MaxU 16)) {
467 SkDebugf("path too complex to render\n");
468 return;
469 }
470
471 // allocate vertex / index buffers
472 const GrBuffer* lineVertexBuffer;
473 int firstLineVertex;
474 MSAALineVertices lines;
475 lines.vertices = (SkPoint*) target->makeVertexSpace(lineVertexStride,
476 maxLineVertices,
477 &lineVertexBuffer, & firstLineVertex);
478 if (!lines.vertices) {
479 SkDebugf("Could not allocate vertices\n");
480 return;
481 }
482 lines.nextVertex = lines.vertices;
483 SkDEBUGCODE(lines.verticesEnd = lines.vertices + maxLineVertices;)
484
485 MSAAQuadVertices quads;
486 SkAutoFree quadVertexPtr(sk_malloc_throw(maxQuadVertices * quadVertexStr ide));
487 quads.vertices = (MSAAQuadVertices::Vertex*) quadVertexPtr.get();
488 quads.nextVertex = quads.vertices;
489 SkDEBUGCODE(quads.verticesEnd = quads.vertices + maxQuadVertices;)
490
491 const GrBuffer* lineIndexBuffer = nullptr;
492 int firstLineIndex;
493 if (isIndexed) {
494 lines.indices = target->makeIndexSpace(maxLineIndices, &lineIndexBuf fer,
495 &firstLineIndex);
496 if (!lines.indices) {
497 SkDebugf("Could not allocate indices\n");
498 return;
499 }
500 lines.nextIndex = lines.indices;
501 } else {
502 lines.indices = nullptr;
503 lines.nextIndex = nullptr;
504 }
505
506 SkAutoFree quadIndexPtr;
507 if (isIndexed) {
508 quads.indices = (uint16_t*) sk_malloc_throw(maxQuadIndices * sizeof( uint16_t));
509 quadIndexPtr.set(quads.indices);
510 quads.nextIndex = quads.indices;
511 } else {
512 quads.indices = nullptr;
513 quads.nextIndex = nullptr;
514 }
515
516 // fill buffers
517 for (int i = 0; i < instanceCount; i++) {
518 const Geometry& args = fGeoData[i];
519
520 if (!this->createGeom(lines,
521 quads,
522 args.fPath,
523 args.fTolerance,
524 this->viewMatrix(),
525 isIndexed)) {
526 return;
527 }
528 }
529 int lineVertexOffset = lines.nextVertex - lines.vertices;
530 int lineIndexOffset = lines.nextIndex - lines.indices;
531 SkASSERT(lineVertexOffset <= maxLineVertices && lineIndexOffset <= maxLi neIndices);
532 int quadVertexOffset = quads.nextVertex - quads.vertices;
533 int quadIndexOffset = quads.nextIndex - quads.indices;
534 SkASSERT(quadVertexOffset <= maxQuadVertices && quadIndexOffset <= maxQu adIndices);
535
536 if (lineVertexOffset) {
537 target->initDraw(lineGP);
538 GrMesh lineMeshes;
539 if (isIndexed) {
540 lineMeshes.initIndexed(primitiveType, lineVertexBuffer, lineInde xBuffer,
541 firstLineVertex, firstLineIndex, lineVe rtexOffset,
542 lineIndexOffset);
543 } else {
544 lineMeshes.init(primitiveType, lineVertexBuffer, firstLineVertex ,
545 lineVertexOffset);
546 }
547 target->draw(lineMeshes);
548 }
549
550 if (quadVertexOffset) {
551 const GrBuffer* quadVertexBuffer;
552 int firstQuadVertex;
553 MSAAQuadVertices::Vertex* quadVertices = (MSAAQuadVertices::Vertex*)
554 target->makeVertexSpace(quadVertexStride, quadVertexOffset, &quadVertexBuffer,
555 &firstQuadVertex);
556 memcpy(quadVertices, quads.vertices, quadVertexStride * quadVertexOf fset);
557 target->initDraw(quadGP);
558 GrMesh quadMeshes;
559 if (isIndexed) {
560 const GrBuffer* quadIndexBuffer;
561 int firstQuadIndex;
562 uint16_t* quadIndices = (uint16_t*) target->makeIndexSpace(maxQu adIndices,
563 &quad IndexBuffer,
564 &firs tQuadIndex);
565 memcpy(quadIndices, quads.indices, sizeof(uint16_t) * quadIndexO ffset);
566 quadMeshes.initIndexed(kTriangles_GrPrimitiveType, quadVertexBuf fer,
567 quadIndexBuffer, firstQuadVertex, first QuadIndex,
568 quadVertexOffset, quadIndexOffset);
569 } else {
570 quadMeshes.init(kTriangles_GrPrimitiveType, quadVertexBuffer, fi rstQuadVertex,
571 quadVertexOffset);
572 }
573 target->draw(quadMeshes);
574 }
575 }
576
577 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
578
579 MSAAPathBatch(const Geometry& geometry, uint8_t coverage, const SkMatrix& vi ewMatrix,
580 const SkRect& devBounds)
581 : INHERITED(ClassID()) {
582 fBatch.fCoverage = coverage;
583 fBatch.fViewMatrix = viewMatrix;
584 fGeoData.push_back(geometry);
585
586 this->setBounds(devBounds);
587 }
588
589 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
590 MSAAPathBatch* that = t->cast<MSAAPathBatch>();
591 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi peline(),
592 that->bounds(), caps)) {
593 return false;
594 }
595
bsalomon 2016/03/29 21:43:22 why not use vertex colors?
596 if (this->color() != that->color()) {
597 return false;
598 }
599
600 if (this->coverage() != that->coverage()) {
601 return false;
602 }
603
604 if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
605 return false;
606 }
607
608 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()) ;
609 this->joinBounds(that->bounds());
610 return true;
611 }
612
613 bool createGeom(MSAALineVertices& lines,
614 MSAAQuadVertices& quads,
615 const SkPath& path,
616 SkScalar srcSpaceTol,
617 const SkMatrix& m,
618 bool isIndexed) const {
619 {
620 uint16_t subpathIdxStart = (uint16_t) (lines.nextVertex - lines.vert ices);
621
622 SkPoint pts[4];
623
624 bool first = true;
625 SkPath::Iter iter(path, false);
626
627 bool done = false;
628 while (!done) {
629 SkPath::Verb verb = iter.next(pts);
630 switch (verb) {
631 case SkPath::kMove_Verb:
632 if (!first) {
633 uint16_t currIdx = (uint16_t) (lines.nextVertex - li nes.vertices);
634 subpathIdxStart = currIdx;
635 }
636 SkASSERT(lines.nextVertex < lines.verticesEnd);
637 *(lines.nextVertex++) = pts[0];
638 break;
639 case SkPath::kLine_Verb:
640 if (isIndexed) {
641 uint16_t prevIdx = (uint16_t) (lines.nextVertex - li nes.vertices - 1);
642 if (prevIdx > subpathIdxStart) {
643 append_contour_edge_indices(subpathIdxStart, pre vIdx, lines);
644 }
645 }
646 SkASSERT(lines.nextVertex < lines.verticesEnd);
647 *(lines.nextVertex++) = pts[1];
648 break;
649 case SkPath::kConic_Verb: {
650 SkScalar weight = iter.conicWeight();
651 SkAutoConicToQuads converter;
652 const SkPoint* quadPts = converter.computeQuads(pts, wei ght,
653 kToleran ce);
654 for (int i = 0; i < converter.countQuads(); ++i) {
655 add_quad(lines, quads, quadPts + i * 2, isIndexed, s ubpathIdxStart);
656 }
657 break;
658 }
659 case SkPath::kQuad_Verb: {
660 add_quad(lines, quads, pts, isIndexed, subpathIdxStart);
661 break;
662 }
663 case SkPath::kCubic_Verb: {
664 SkSTArray<15, SkPoint, true> quadPts;
665 GrPathUtils::convertCubicToQuads(pts, kTolerance, &quadP ts);
666 int count = quadPts.count();
667 for (int i = 0; i < count; i += 3) {
668 add_quad(lines, quads, &quadPts[i], isIndexed, subpa thIdxStart);
669 }
670 break;
671 }
672 case SkPath::kClose_Verb:
673 break;
674 case SkPath::kDone_Verb:
675 done = true;
676 }
677 first = false;
678 }
679 }
680 return true;
681 }
682
683 GrColor color() const { return fBatch.fColor; }
684 uint8_t coverage() const { return fBatch.fCoverage; }
bsalomon 2016/03/29 21:43:22 Why do you have a coverage?
685 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
686 const SkMatrix& viewMatrix() const { return fBatch.fViewMatrix; }
687 bool coverageIgnored() const { return fBatch.fCoverageIgnored; }
688
689 struct BatchTracker {
bsalomon 2016/03/29 21:43:22 Older batches use this batch tracker struct, but t
690 GrColor fColor;
691 uint8_t fCoverage;
692 SkMatrix fViewMatrix;
693 bool fUsesLocalCoords;
694 bool fColorIgnored;
bsalomon 2016/03/29 21:43:22 I think we should drop the color ignored stuff. It
695 bool fCoverageIgnored;
696 };
697
698 BatchTracker fBatch;
699 SkSTArray<1, Geometry, true> fGeoData;
700
701 typedef GrVertexBatch INHERITED;
702 };
703
704 bool GrMSAAPathRenderer::internalDrawPath(GrDrawTarget* target,
705 GrPipelineBuilder* pipelineBuilder,
706 GrColor color,
707 const SkMatrix& viewMatrix,
708 const SkPath& path,
709 const GrStrokeInfo& origStroke,
710 bool stencilOnly) {
711 SkTCopyOnFirstWrite<GrStrokeInfo> stroke(origStroke);
712
713 uint8_t newCoverage = 0xff;
bsalomon 2016/03/29 21:43:22 ?
714
715 // Save the current xp on the draw state so we can reset it if needed
bsalomon 2016/03/29 21:43:22 draw state?
716 const GrXPFactory* xpFactory = pipelineBuilder->getXPFactory();
717 SkAutoTUnref<const GrXPFactory> backupXPFactory(SkSafeRef(xpFactory));
718 // face culling doesn't make sense here
719 SkASSERT(GrPipelineBuilder::kBoth_DrawFace == pipelineBuilder->getDrawFace() );
720
721 int passCount = 0;
722 const GrStencilSettings* passes[3];
723 GrPipelineBuilder::DrawFace drawFace[3];
724 bool reverse = false;
725 bool lastPassIsBounds;
726
727 if (single_pass_path(path, *stroke)) {
728 passCount = 1;
729 if (stencilOnly) {
730 passes[0] = &gDirectToStencil;
731 } else {
732 passes[0] = nullptr;
733 }
734 drawFace[0] = GrPipelineBuilder::kBoth_DrawFace;
735 lastPassIsBounds = false;
736 } else {
737 switch (path.getFillType()) {
738 case SkPath::kInverseEvenOdd_FillType:
739 reverse = true;
740 // fallthrough
741 case SkPath::kEvenOdd_FillType:
742 passes[0] = &gEOStencilPass;
743 if (stencilOnly) {
744 passCount = 1;
745 lastPassIsBounds = false;
746 } else {
747 passCount = 2;
748 lastPassIsBounds = true;
749 if (reverse) {
750 passes[1] = &gInvEOColorPass;
751 } else {
752 passes[1] = &gEOColorPass;
753 }
754 }
755 drawFace[0] = drawFace[1] = GrPipelineBuilder::kBoth_DrawFace;
756 break;
757
758 case SkPath::kInverseWinding_FillType:
759 reverse = true;
760 // fallthrough
761 case SkPath::kWinding_FillType:
762 passes[0] = &gWindStencil;
763 passCount = 2;
764 drawFace[0] = GrPipelineBuilder::kBoth_DrawFace;
765 if (stencilOnly) {
766 lastPassIsBounds = false;
767 --passCount;
768 } else {
769 lastPassIsBounds = true;
770 drawFace[passCount-1] = GrPipelineBuilder::kBoth_DrawFace;
771 if (reverse) {
772 passes[passCount-1] = &gInvWindColorPass;
773 } else {
774 passes[passCount-1] = &gWindColorPass;
775 }
776 }
777 break;
778 default:
779 SkDEBUGFAIL("Unknown path fFill!");
780 return false;
781 }
782 }
783
784 SkRect devBounds;
785 GetPathDevBounds(path, pipelineBuilder->getRenderTarget(), viewMatrix, &devB ounds);
786
787 for (int p = 0; p < passCount; ++p) {
788 pipelineBuilder->setDrawFace(drawFace[p]);
789 if (passes[p]) {
790 *pipelineBuilder->stencil() = *passes[p];
791 }
792
793 if (lastPassIsBounds && (p == passCount-1)) {
794 // Reset the XP Factory on pipelineBuilder
795 pipelineBuilder->setXPFactory(backupXPFactory);
796 SkRect bounds;
797 SkMatrix localMatrix = SkMatrix::I();
798 if (reverse) {
799 SkASSERT(pipelineBuilder->getRenderTarget());
800 // draw over the dev bounds (which will be the whole dst surface for inv fill).
801 bounds = devBounds;
802 SkMatrix vmi;
803 // mapRect through persp matrix may not be correct
804 if (!viewMatrix.hasPerspective() && viewMatrix.invert(&vmi)) {
805 vmi.mapRect(&bounds);
806 } else {
807 if (!viewMatrix.invert(&localMatrix)) {
808 return false;
809 }
810 }
811 } else {
812 bounds = path.getBounds();
813 }
814 const SkMatrix& viewM = (reverse && viewMatrix.hasPerspective()) ? S kMatrix::I() :
815 v iewMatrix;
816 SkAutoTUnref<GrDrawBatch> batch(
817 GrRectBatchFactory::CreateNonAAFill(color, viewM, bounds, nu llptr,
818 &localMatrix));
819 target->drawBatch(*pipelineBuilder, batch);
820 } else {
821 if (passCount > 1) {
822 pipelineBuilder->setDisableColorXPFactory();
823 }
824
825 MSAAPathBatch::Geometry geometry;
826 geometry.fColor = color;
827 geometry.fPath = path;
828 geometry.fTolerance = kTolerance;
829
830 SkAutoTUnref<GrDrawBatch> batch(MSAAPathBatch::Create(geometry, newC overage,
831 viewMatrix, devBounds));
832
833 target->drawBatch(*pipelineBuilder, batch);
834 }
835 }
836 return true;
837 }
838
839 bool GrMSAAPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
840 return !IsStrokeHairlineOrEquivalent(*args.fStroke, *args.fViewMatrix, nullp tr) &&
841 !args.fAntiAlias;
842 }
843
844 bool GrMSAAPathRenderer::onDrawPath(const DrawPathArgs& args) {
845 GR_AUDIT_TRAIL_AUTO_FRAME(args.fTarget->getAuditTrail(), "GrMSAAPathRenderer ::onDrawPath");
846 SkPath path;
847 GrStrokeInfo stroke(*args.fStroke);
848 if (stroke.isDashed()) {
849 if (!stroke.applyDashToPath(&path, &stroke, *args.fPath)) {
850 return false;
851 }
852 } else {
853 path = *args.fPath;
854 }
855 if (!stroke.isFillStyle()) {
856 stroke.setResScale(SkScalarAbs(args.fViewMatrix->getMaxScale()));
857 if (!stroke.applyToPath(&path, path)) {
858 return false;
859 }
860 stroke.setFillStyle();
861 }
862 bool result = this->internalDrawPath(args.fTarget,
863 args.fPipelineBuilder,
864 args.fColor,
865 *args.fViewMatrix,
866 path,
867 stroke,
868 false);
869 return result;
870 }
871
872 void GrMSAAPathRenderer::onStencilPath(const StencilPathArgs& args) {
873 GR_AUDIT_TRAIL_AUTO_FRAME(args.fTarget->getAuditTrail(),"GrMSAAPathRenderer: :onStencilPath");
874 SkASSERT(SkPath::kInverseEvenOdd_FillType != args.fPath->getFillType());
875 SkASSERT(SkPath::kInverseWinding_FillType != args.fPath->getFillType());
876 this->internalDrawPath(args.fTarget, args.fPipelineBuilder, GrColor_WHITE, * args.fViewMatrix,
877 *args.fPath, *args.fStroke, true);
878 }
879
880 //////////////////////////////////////////////////////////////////////////////// ///////////////////
OLDNEW
« no previous file with comments | « src/gpu/batches/GrMSAAPathRenderer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698