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

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: improved batching, cut out some useless code 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
OLDNEW
(Empty)
1 /*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "GrMSAAPathRenderer.h"
9
10 #include "GrBatchFlushState.h"
11 #include "GrDefaultGeoProcFactory.h"
12 #include "GrDefaultPathRenderer.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
27 static const float kTolerance = 0.5f;
28
29 ////////////////////////////////////////////////////////////////////////////////
30 // Helpers for drawPath
31
32 static inline bool single_pass_path(const SkPath& path, const SkStrokeRec& strok e) {
33 if (!path.isInverseFillType()) {
34 return path.isConvex();
35 }
36 return false;
37 }
38
39 GrPathRenderer::StencilSupport
40 GrMSAAPathRenderer::onGetStencilSupport(const SkPath& path, const GrStrokeInfo& stroke) const {
41 if (single_pass_path(path, stroke)) {
42 return GrPathRenderer::kNoRestriction_StencilSupport;
43 } else {
44 return GrPathRenderer::kStencilOnly_StencilSupport;
45 }
46 }
47
48 struct 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
62 struct 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
77 static 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
85 static inline void add_quad(MSAALineVertices& lines, MSAAQuadVertices& quads, co nst SkPoint pts[],
86 SkColor color, bool indexed, uint16_t subpathLineIdx Start) {
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
110 class MSAAQuadProcessor : public GrGeometryProcessor {
111 public:
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.fOutputCo lor);
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, gpAr gs->fPositionVar,
150 qp.inPosition()->fName, SkMatrix::I(), args.fTr ansformsIn,
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>& tra nsforms) override {
183 this->setTransformDataHelper<MSAAQuadProcessor>(primProc, pdman, ind ex, 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&) cons t override {
198 return new GLSLProcessor(*this);
199 }
200
201 private:
202 MSAAQuadProcessor(const SkMatrix& viewMatrix)
203 : fViewMatrix(viewMatrix) {
204 this->initClassID<MSAAQuadProcessor>();
205 fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVe rtexAttribType,
206 kHigh_GrSLPrecision));
207 fInUV = &this->addVertexAttrib(Attribute("inUV", kVec2f_GrVertexAttribTy pe,
208 kHigh_GrSLPrecision));
209 fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexA ttribType));
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
223 class MSAAPathBatch : public GrVertexBatch {
224 public:
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& viewM atrix,
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 ove rride {
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
252 private:
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* outQuadPointCou nt) 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 SkAutoTUnref<const GrGeometryProcessor> lineGP;
321 {
322 using namespace GrDefaultGeoProcFactory;
323 lineGP.reset(GrDefaultGeoProcFactory::Create(Color(Color::kAttribute _Type),
324 Coverage(255),
325 LocalCoords(LocalCoords ::kUnused_Type),
326 fViewMatrix));
327 }
328
329
330 size_t lineVertexStride = lineGP->getVertexStride();
331 SkASSERT(lineVertexStride == sizeof(MSAALineVertices::Vertex));
332
333 SkAutoTUnref<const GrGeometryProcessor> quadGP(MSAAQuadProcessor::Create (fViewMatrix));
334 size_t quadVertexStride = quadGP->getVertexStride();
335 SkASSERT(quadVertexStride == sizeof(MSAAQuadVertices::Vertex));
336
337 GrPrimitiveType primitiveType = fIsIndexed ? kTriangles_GrPrimitiveType
338 : kTriangleFan_GrPrimitiveTyp e;
339
340 // allocate vertex / index buffers
341 const GrBuffer* lineVertexBuffer;
342 int firstLineVertex;
343 MSAALineVertices lines;
344 lines.vertices = (MSAALineVertices::Vertex*) target->makeVertexSpace(lin eVertexStride,
345 fMa xLineVertices,
346 &li neVertexBuffer,
347 &fi rstLineVertex);
348 if (!lines.vertices) {
349 SkDebugf("Could not allocate vertices\n");
350 return;
351 }
352 lines.nextVertex = lines.vertices;
353 SkDEBUGCODE(lines.verticesEnd = lines.vertices + fMaxLineVertices;)
354
355 MSAAQuadVertices quads;
356 SkAutoFree quadVertexPtr(sk_malloc_throw(fMaxQuadVertices * quadVertexSt ride));
357 quads.vertices = (MSAAQuadVertices::Vertex*) quadVertexPtr.get();
358 quads.nextVertex = quads.vertices;
359 SkDEBUGCODE(quads.verticesEnd = quads.vertices + fMaxQuadVertices;)
360
361 const GrBuffer* lineIndexBuffer = nullptr;
362 int firstLineIndex;
363 if (fIsIndexed) {
364 lines.indices = target->makeIndexSpace(fMaxLineIndices, &lineIndexBu ffer,
365 &firstLineIndex);
366 if (!lines.indices) {
367 SkDebugf("Could not allocate indices\n");
368 return;
369 }
370 lines.nextIndex = lines.indices;
371 } else {
372 lines.indices = nullptr;
373 lines.nextIndex = nullptr;
374 }
375
376 SkAutoFree quadIndexPtr;
377 if (fIsIndexed) {
378 quads.indices = (uint16_t*) sk_malloc_throw(fMaxQuadIndices * sizeof (uint16_t));
379 quadIndexPtr.set(quads.indices);
380 quads.nextIndex = quads.indices;
381 } else {
382 quads.indices = nullptr;
383 quads.nextIndex = nullptr;
384 }
385
386 // fill buffers
387 for (int i = 0; i < fGeoData.count(); i++) {
388 const Geometry& args = fGeoData[i];
389
390 if (!this->createGeom(lines,
391 quads,
392 args.fPath,
393 args.fTolerance,
394 fViewMatrix,
395 args.fColor,
396 fIsIndexed)) {
397 return;
398 }
399 }
400 int lineVertexOffset = lines.nextVertex - lines.vertices;
401 int lineIndexOffset = lines.nextIndex - lines.indices;
402 SkASSERT(lineVertexOffset <= fMaxLineVertices && lineIndexOffset <= fMax LineIndices);
403 int quadVertexOffset = quads.nextVertex - quads.vertices;
404 int quadIndexOffset = quads.nextIndex - quads.indices;
405 SkASSERT(quadVertexOffset <= fMaxQuadVertices && quadIndexOffset <= fMax QuadIndices);
406
407 if (lineVertexOffset) {
408 target->initDraw(lineGP);
bsalomon 2016/04/04 13:09:21 Heads up, I recently removed this initDraw() funti
409 GrMesh lineMeshes;
410 if (fIsIndexed) {
411 lineMeshes.initIndexed(primitiveType, lineVertexBuffer, lineInde xBuffer,
412 firstLineVertex, firstLineIndex, lineVe rtexOffset,
413 lineIndexOffset);
414 } else {
415 lineMeshes.init(primitiveType, lineVertexBuffer, firstLineVertex ,
416 lineVertexOffset);
417 }
418 target->draw(lineMeshes);
419 }
420
421 if (quadVertexOffset) {
422 const GrBuffer* quadVertexBuffer;
423 int firstQuadVertex;
424 MSAAQuadVertices::Vertex* quadVertices = (MSAAQuadVertices::Vertex*)
425 target->makeVertexSpace(quadVertexStride, quadVertexOffset, &quadVertexBuffer,
426 &firstQuadVertex);
427 memcpy(quadVertices, quads.vertices, quadVertexStride * quadVertexOf fset);
428 target->initDraw(quadGP);
429 GrMesh quadMeshes;
430 if (fIsIndexed) {
431 const GrBuffer* quadIndexBuffer;
432 int firstQuadIndex;
433 uint16_t* quadIndices = (uint16_t*) target->makeIndexSpace(quadI ndexOffset,
434 &quad IndexBuffer,
435 &firs tQuadIndex);
436 memcpy(quadIndices, quads.indices, sizeof(uint16_t) * quadIndexO ffset);
437 quadMeshes.initIndexed(kTriangles_GrPrimitiveType, quadVertexBuf fer,
438 quadIndexBuffer, firstQuadVertex, firstQu adIndex,
439 quadVertexOffset, quadIndexOffset);
440 } else {
441 quadMeshes.init(kTriangles_GrPrimitiveType, quadVertexBuffer, fi rstQuadVertex,
442 quadVertexOffset);
443 }
444 target->draw(quadMeshes);
445 }
446 }
447
448 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
449
450 MSAAPathBatch(const Geometry& geometry, const SkMatrix& viewMatrix, const Sk Rect& devBounds)
451 : INHERITED(ClassID())
452 , fViewMatrix(viewMatrix) {
453 fGeoData.push_back(geometry);
454 this->setBounds(devBounds);
455 int contourCount;
456 this->computeWorstCasePointCount(geometry.fPath, &contourCount, kToleran ce,
457 &fMaxLineVertices, &fMaxQuadVertices);
458 fMaxLineIndices = fMaxLineVertices * 3;
459 fMaxQuadIndices = fMaxQuadVertices * 3;
460 fIsIndexed = contourCount > 1;
461 }
462
463 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
464 MSAAPathBatch* that = t->cast<MSAAPathBatch>();
465 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi peline(),
466 that->bounds(), caps)) {
467 return false;
468 }
469
470 if (!fViewMatrix.cheapEqualTo(that->fViewMatrix)) {
471 return false;
472 }
473
474 if (fMaxLineIndices + that->fMaxLineIndices > SK_MaxU16) {
475 return false;
476 }
477 SkASSERT(fMaxQuadIndices + that->fMaxQuadIndices <= SK_MaxU16);
478
479 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()) ;
480 this->joinBounds(that->bounds());
481 fIsIndexed = true;
482 fMaxLineVertices += that->fMaxLineVertices;
483 fMaxQuadVertices += that->fMaxQuadVertices;
484 fMaxLineIndices += that->fMaxLineIndices;
485 fMaxQuadIndices += that->fMaxQuadIndices;
486 return true;
487 }
488
489 bool createGeom(MSAALineVertices& lines,
490 MSAAQuadVertices& quads,
491 const SkPath& path,
492 SkScalar srcSpaceTol,
493 const SkMatrix& m,
494 SkColor color,
495 bool isIndexed) const {
496 {
497 uint16_t subpathIdxStart = (uint16_t) (lines.nextVertex - lines.vert ices);
498
499 SkPoint pts[4];
500
501 bool first = true;
502 SkPath::Iter iter(path, false);
503
504 bool done = false;
505 while (!done) {
506 SkPath::Verb verb = iter.next(pts);
507 switch (verb) {
508 case SkPath::kMove_Verb:
509 if (!first) {
510 uint16_t currIdx = (uint16_t) (lines.nextVertex - li nes.vertices);
511 subpathIdxStart = currIdx;
512 }
513 SkASSERT(lines.nextVertex < lines.verticesEnd);
514 *(lines.nextVertex++) = { pts[0], color };
515 break;
516 case SkPath::kLine_Verb:
517 if (isIndexed) {
518 uint16_t prevIdx = (uint16_t) (lines.nextVertex - li nes.vertices - 1);
519 if (prevIdx > subpathIdxStart) {
520 append_contour_edge_indices(subpathIdxStart, pre vIdx, lines);
521 }
522 }
523 SkASSERT(lines.nextVertex < lines.verticesEnd);
524 *(lines.nextVertex++) = { pts[1], color };
525 break;
526 case SkPath::kConic_Verb: {
527 SkScalar weight = iter.conicWeight();
528 SkAutoConicToQuads converter;
529 const SkPoint* quadPts = converter.computeQuads(pts, wei ght,
530 kToleran ce);
531 for (int i = 0; i < converter.countQuads(); ++i) {
532 add_quad(lines, quads, quadPts + i * 2, color, isInd exed,
533 subpathIdxStart);
534 }
535 break;
536 }
537 case SkPath::kQuad_Verb: {
538 add_quad(lines, quads, pts, color, isIndexed, subpathIdx Start);
539 break;
540 }
541 case SkPath::kCubic_Verb: {
542 SkSTArray<15, SkPoint, true> quadPts;
543 GrPathUtils::convertCubicToQuads(pts, kTolerance, &quadP ts);
544 int count = quadPts.count();
545 for (int i = 0; i < count; i += 3) {
546 add_quad(lines, quads, &quadPts[i], color, isIndexed , subpathIdxStart);
547 }
548 break;
549 }
550 case SkPath::kClose_Verb:
551 break;
552 case SkPath::kDone_Verb:
553 done = true;
554 }
555 first = false;
556 }
557 }
558 return true;
559 }
560
561 SkSTArray<1, Geometry, true> fGeoData;
562
563 SkMatrix fViewMatrix;
564 int fMaxLineVertices;
565 int fMaxQuadVertices;
566 int fMaxLineIndices;
567 int fMaxQuadIndices;
568 int fIsIndexed;
569
570 typedef GrVertexBatch INHERITED;
571 };
572
573 bool GrMSAAPathRenderer::internalDrawPath(GrDrawTarget* target,
574 GrPipelineBuilder* pipelineBuilder,
575 GrColor color,
576 const SkMatrix& viewMatrix,
577 const SkPath& path,
578 const GrStrokeInfo& origStroke,
579 bool stencilOnly) {
580 SkTCopyOnFirstWrite<GrStrokeInfo> stroke(origStroke);
581
582 const GrXPFactory* xpFactory = pipelineBuilder->getXPFactory();
583 SkAutoTUnref<const GrXPFactory> backupXPFactory(SkSafeRef(xpFactory));
584 // face culling doesn't make sense here
585 SkASSERT(GrPipelineBuilder::kBoth_DrawFace == pipelineBuilder->getDrawFace() );
586
587 int passCount = 0;
588 const GrStencilSettings* passes[3];
589 GrPipelineBuilder::DrawFace drawFace[3];
590 bool reverse = false;
591 bool lastPassIsBounds;
592
593 if (single_pass_path(path, *stroke)) {
594 passCount = 1;
595 if (stencilOnly) {
596 passes[0] = &gDirectToStencil;
597 } else {
598 passes[0] = nullptr;
599 }
600 drawFace[0] = GrPipelineBuilder::kBoth_DrawFace;
601 lastPassIsBounds = false;
602 } else {
603 switch (path.getFillType()) {
604 case SkPath::kInverseEvenOdd_FillType:
605 reverse = true;
606 // fallthrough
607 case SkPath::kEvenOdd_FillType:
608 passes[0] = &gEOStencilPass;
609 if (stencilOnly) {
610 passCount = 1;
611 lastPassIsBounds = false;
612 } else {
613 passCount = 2;
614 lastPassIsBounds = true;
615 if (reverse) {
616 passes[1] = &gInvEOColorPass;
617 } else {
618 passes[1] = &gEOColorPass;
619 }
620 }
621 drawFace[0] = drawFace[1] = GrPipelineBuilder::kBoth_DrawFace;
622 break;
623
624 case SkPath::kInverseWinding_FillType:
625 reverse = true;
626 // fallthrough
627 case SkPath::kWinding_FillType:
628 passes[0] = &gWindStencilSeparateWithWrap;
629 passCount = 2;
630 drawFace[0] = GrPipelineBuilder::kBoth_DrawFace;
631 if (stencilOnly) {
632 lastPassIsBounds = false;
633 --passCount;
634 } else {
635 lastPassIsBounds = true;
636 drawFace[passCount-1] = GrPipelineBuilder::kBoth_DrawFace;
637 if (reverse) {
638 passes[passCount-1] = &gInvWindColorPass;
639 } else {
640 passes[passCount-1] = &gWindColorPass;
641 }
642 }
643 break;
644 default:
645 SkDEBUGFAIL("Unknown path fFill!");
646 return false;
647 }
648 }
649
650 SkRect devBounds;
651 GetPathDevBounds(path, pipelineBuilder->getRenderTarget(), viewMatrix, &devB ounds);
652
653 for (int p = 0; p < passCount; ++p) {
654 pipelineBuilder->setDrawFace(drawFace[p]);
655 if (passes[p]) {
656 *pipelineBuilder->stencil() = *passes[p];
657 }
658
659 if (lastPassIsBounds && (p == passCount-1)) {
660 // Reset the XP Factory on pipelineBuilder
661 pipelineBuilder->setXPFactory(backupXPFactory);
662 SkRect bounds;
663 SkMatrix localMatrix = SkMatrix::I();
664 if (reverse) {
665 SkASSERT(pipelineBuilder->getRenderTarget());
666 // draw over the dev bounds (which will be the whole dst surface for inv fill).
667 bounds = devBounds;
668 SkMatrix vmi;
669 // mapRect through persp matrix may not be correct
670 if (!viewMatrix.hasPerspective() && viewMatrix.invert(&vmi)) {
671 vmi.mapRect(&bounds);
672 } else {
673 if (!viewMatrix.invert(&localMatrix)) {
674 return false;
675 }
676 }
677 } else {
678 bounds = path.getBounds();
679 }
680 const SkMatrix& viewM = (reverse && viewMatrix.hasPerspective()) ? S kMatrix::I() :
681 v iewMatrix;
682 SkAutoTUnref<GrDrawBatch> batch(
683 GrRectBatchFactory::CreateNonAAFill(color, viewM, bounds, nu llptr,
684 &localMatrix));
685 target->drawBatch(*pipelineBuilder, batch);
686 } else {
687 if (passCount > 1) {
688 pipelineBuilder->setDisableColorXPFactory();
689 }
690
691 MSAAPathBatch::Geometry geometry;
692 geometry.fColor = color;
693 geometry.fPath = path;
694 geometry.fTolerance = kTolerance;
695
696 SkAutoTUnref<MSAAPathBatch> batch(MSAAPathBatch::Create(geometry, vi ewMatrix,
697 devBounds));
698 if (batch->isValid()) {
699 target->drawBatch(*pipelineBuilder, batch);
700 }
701 else {
702 return false;
703 }
704 }
705 }
706 return true;
707 }
708
709 bool GrMSAAPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
710 return !IsStrokeHairlineOrEquivalent(*args.fStroke, *args.fViewMatrix, nullp tr) &&
711 !args.fAntiAlias;
712 }
713
714 bool GrMSAAPathRenderer::onDrawPath(const DrawPathArgs& args) {
715 GR_AUDIT_TRAIL_AUTO_FRAME(args.fTarget->getAuditTrail(), "GrMSAAPathRenderer ::onDrawPath");
716 SkPath path;
717 GrStrokeInfo stroke(*args.fStroke);
718 if (stroke.isDashed()) {
719 if (!stroke.applyDashToPath(&path, &stroke, *args.fPath)) {
720 return false;
721 }
722 } else {
723 path = *args.fPath;
724 }
725 if (!stroke.isFillStyle()) {
726 stroke.setResScale(SkScalarAbs(args.fViewMatrix->getMaxScale()));
727 if (!stroke.applyToPath(&path, path)) {
728 return false;
729 }
730 stroke.setFillStyle();
731 }
732 return this->internalDrawPath(args.fTarget,
733 args.fPipelineBuilder,
734 args.fColor,
735 *args.fViewMatrix,
736 path,
737 stroke,
738 false);
739 }
740
741 void GrMSAAPathRenderer::onStencilPath(const StencilPathArgs& args) {
742 GR_AUDIT_TRAIL_AUTO_FRAME(args.fTarget->getAuditTrail(),"GrMSAAPathRenderer: :onStencilPath");
743 SkASSERT(SkPath::kInverseEvenOdd_FillType != args.fPath->getFillType());
744 SkASSERT(SkPath::kInverseWinding_FillType != args.fPath->getFillType());
745 this->internalDrawPath(args.fTarget, args.fPipelineBuilder, GrColor_WHITE, * args.fViewMatrix,
746 *args.fPath, *args.fStroke, true);
747 }
748
749 //////////////////////////////////////////////////////////////////////////////// ///////////////////
OLDNEW
« src/gpu/batches/GrDefaultPathRenderer.h ('K') | « src/gpu/batches/GrMSAAPathRenderer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698