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 "GrAuditTrail.h" 11 #include "GrClip.h" 12 #include "GrDefaultGeoProcFactory.h" 13 #include "GrFixedClip.h" 14 #include "GrMesh.h" 15 #include "GrOpFlushState.h" 16 #include "GrPathStencilSettings.h" 17 #include "GrPathUtils.h" 18 #include "GrPipelineBuilder.h" 19 #include "SkAutoMalloc.h" 20 #include "SkGeometry.h" 21 #include "SkTraceEvent.h" 22 #include "gl/GrGLVaryingHandler.h" 23 #include "glsl/GrGLSLFragmentShaderBuilder.h" 24 #include "glsl/GrGLSLGeometryProcessor.h" 25 #include "glsl/GrGLSLProgramDataManager.h" 26 #include "glsl/GrGLSLUtil.h" 27 #include "glsl/GrGLSLVertexShaderBuilder.h" 28 #include "ops/GrMeshDrawOp.h" 29 #include "ops/GrRectOpFactory.h" 30 31 static const float kTolerance = 0.5f; 32 33 //////////////////////////////////////////////////////////////////////////////// 34 // Helpers for drawPath 35 36 static inline bool single_pass_shape(const GrShape& shape) { 37 if (!shape.inverseFilled()) { 38 return shape.knownToBeConvex(); 39 } 40 return false; 41 } 42 43 GrPathRenderer::StencilSupport GrMSAAPathRenderer::onGetStencilSupport(const GrShape& shape) const { 44 if (single_pass_shape(shape)) { 45 return GrPathRenderer::kNoRestriction_StencilSupport; 46 } else { 47 return GrPathRenderer::kStencilOnly_StencilSupport; 48 } 49 } 50 51 struct MSAALineVertices { 52 struct Vertex { 53 SkPoint fPosition; 54 SkColor fColor; 55 }; 56 Vertex* vertices; 57 Vertex* nextVertex; 58 #ifdef SK_DEBUG 59 Vertex* verticesEnd; 60 #endif 61 uint16_t* indices; 62 uint16_t* nextIndex; 63 }; 64 65 struct MSAAQuadVertices { 66 struct Vertex { 67 SkPoint fPosition; 68 SkPoint fUV; 69 SkColor fColor; 70 }; 71 Vertex* vertices; 72 Vertex* nextVertex; 73 #ifdef SK_DEBUG 74 Vertex* verticesEnd; 75 #endif 76 uint16_t* indices; 77 uint16_t* nextIndex; 78 }; 79 80 static inline void append_contour_edge_indices(uint16_t fanCenterIdx, 81 uint16_t edgeV0Idx, 82 MSAALineVertices& lines) { 83 *(lines.nextIndex++) = fanCenterIdx; 84 *(lines.nextIndex++) = edgeV0Idx; 85 *(lines.nextIndex++) = edgeV0Idx + 1; 86 } 87 88 static inline void add_quad(MSAALineVertices& lines, MSAAQuadVertices& quads, const SkPoint pts[], 89 SkColor color, bool indexed, uint16_t subpathLineIdxStart) { 90 SkASSERT(lines.nextVertex < lines.verticesEnd); 91 *lines.nextVertex = { pts[2], color }; 92 if (indexed) { 93 int prevIdx = (uint16_t) (lines.nextVertex - lines.vertices - 1); 94 if (prevIdx > subpathLineIdxStart) { 95 append_contour_edge_indices(subpathLineIdxStart, prevIdx, lines); 96 } 97 } 98 lines.nextVertex++; 99 100 SkASSERT(quads.nextVertex + 2 < quads.verticesEnd); 101 // the texture coordinates are drawn from the Loop-Blinn rendering algorithm 102 *(quads.nextVertex++) = { pts[0], SkPoint::Make(0.0, 0.0), color }; 103 *(quads.nextVertex++) = { pts[1], SkPoint::Make(0.5, 0.0), color }; 104 *(quads.nextVertex++) = { pts[2], SkPoint::Make(1.0, 1.0), color }; 105 if (indexed) { 106 uint16_t offset = (uint16_t) (quads.nextVertex - quads.vertices) - 3; 107 *(quads.nextIndex++) = offset++; 108 *(quads.nextIndex++) = offset++; 109 *(quads.nextIndex++) = offset++; 110 } 111 } 112 113 class MSAAQuadProcessor : public GrGeometryProcessor { 114 public: 115 static GrGeometryProcessor* Create(const SkMatrix& viewMatrix) { 116 return new MSAAQuadProcessor(viewMatrix); 117 } 118 119 ~MSAAQuadProcessor() override {} 120 121 const char* name() const override { return "MSAAQuadProcessor"; } 122 123 const Attribute* inPosition() const { return fInPosition; } 124 const Attribute* inUV() const { return fInUV; } 125 const Attribute* inColor() const { return fInColor; } 126 const SkMatrix& viewMatrix() const { return fViewMatrix; } 127 128 class GLSLProcessor : public GrGLSLGeometryProcessor { 129 public: 130 GLSLProcessor(const GrGeometryProcessor& qpr) {} 131 132 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override { 133 const MSAAQuadProcessor& qp = args.fGP.cast<MSAAQuadProcessor>(); 134 GrGLSLVertexBuilder* vsBuilder = args.fVertBuilder; 135 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; 136 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 137 138 // emit attributes 139 varyingHandler->emitAttributes(qp); 140 varyingHandler->addPassThroughAttribute(qp.inColor(), args.fOutputColor); 141 142 GrGLSLVertToFrag uv(kVec2f_GrSLType); 143 varyingHandler->addVarying("uv", &uv, kHigh_GrSLPrecision); 144 vsBuilder->codeAppendf("%s = %s;", uv.vsOut(), qp.inUV()->fName); 145 146 // Setup position 147 this->setupPosition(vsBuilder, uniformHandler, gpArgs, qp.inPosition()->fName, 148 qp.viewMatrix(), &fViewMatrixUniform); 149 150 // emit transforms 151 this->emitTransforms(vsBuilder, varyingHandler, uniformHandler, gpArgs->fPositionVar, 152 qp.inPosition()->fName, SkMatrix::I(), 153 args.fFPCoordTransformHandler); 154 155 GrGLSLPPFragmentBuilder* fsBuilder = args.fFragBuilder; 156 fsBuilder->codeAppendf("if (%s.x * %s.x >= %s.y) discard;", uv.fsIn(), uv.fsIn(), 157 uv.fsIn()); 158 fsBuilder->codeAppendf("%s = vec4(1.0);", args.fOutputCoverage); 159 } 160 161 static inline void GenKey(const GrGeometryProcessor& gp, 162 const GrShaderCaps&, 163 GrProcessorKeyBuilder* b) { 164 const MSAAQuadProcessor& qp = gp.cast<MSAAQuadProcessor>(); 165 uint32_t key = 0; 166 key |= qp.viewMatrix().hasPerspective() ? 0x1 : 0x0; 167 key |= qp.viewMatrix().isIdentity() ? 0x2: 0x0; 168 b->add32(key); 169 } 170 171 void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& gp, 172 FPCoordTransformIter&& transformIter) override { 173 const MSAAQuadProcessor& qp = gp.cast<MSAAQuadProcessor>(); 174 if (!qp.viewMatrix().isIdentity()) { 175 float viewMatrix[3 * 3]; 176 GrGLSLGetMatrix<3>(viewMatrix, qp.viewMatrix()); 177 pdman.setMatrix3f(fViewMatrixUniform, viewMatrix); 178 } 179 this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter); 180 } 181 182 private: 183 typedef GrGLSLGeometryProcessor INHERITED; 184 185 UniformHandle fViewMatrixUniform; 186 }; 187 188 virtual void getGLSLProcessorKey(const GrShaderCaps& caps, 189 GrProcessorKeyBuilder* b) const override { 190 GLSLProcessor::GenKey(*this, caps, b); 191 } 192 193 virtual GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override { 194 return new GLSLProcessor(*this); 195 } 196 197 private: 198 MSAAQuadProcessor(const SkMatrix& viewMatrix) 199 : fViewMatrix(viewMatrix) { 200 this->initClassID<MSAAQuadProcessor>(); 201 fInPosition = &this->addVertexAttrib("inPosition", kVec2f_GrVertexAttribType, 202 kHigh_GrSLPrecision); 203 fInUV = &this->addVertexAttrib("inUV", kVec2f_GrVertexAttribType, kHigh_GrSLPrecision); 204 fInColor = &this->addVertexAttrib("inColor", kVec4ub_GrVertexAttribType); 205 this->setSampleShading(1.0f); 206 } 207 208 const Attribute* fInPosition; 209 const Attribute* fInUV; 210 const Attribute* fInColor; 211 SkMatrix fViewMatrix; 212 213 GR_DECLARE_GEOMETRY_PROCESSOR_TEST; 214 215 typedef GrGeometryProcessor INHERITED; 216 }; 217 218 class MSAAPathOp final : public GrMeshDrawOp { 219 public: 220 DEFINE_OP_CLASS_ID 221 static std::unique_ptr<GrMeshDrawOp> Make(GrColor color, const SkPath& path, 222 const SkMatrix& viewMatrix, const SkRect& devBounds) { 223 int contourCount; 224 int maxLineVertices; 225 int maxQuadVertices; 226 ComputeWorstCasePointCount(path, &contourCount, &maxLineVertices, &maxQuadVertices); 227 bool isIndexed = contourCount > 1; 228 if (isIndexed && 229 (maxLineVertices > kMaxIndexedVertexCnt || maxQuadVertices > kMaxIndexedVertexCnt)) { 230 return nullptr; 231 } 232 233 return std::unique_ptr<GrMeshDrawOp>(new MSAAPathOp( 234 color, path, viewMatrix, devBounds, maxLineVertices, maxQuadVertices, isIndexed)); 235 } 236 237 const char* name() const override { return "MSAAPathOp"; } 238 239 SkString dumpInfo() const override { 240 SkString string; 241 string.appendf("Indexed: %d\n", fIsIndexed); 242 for (const auto& path : fPaths) { 243 string.appendf("Color: 0x%08x\n", path.fColor); 244 } 245 string.append(DumpPipelineInfo(*this->pipeline())); 246 string.append(INHERITED::dumpInfo()); 247 return string; 248 } 249 250 private: 251 MSAAPathOp(GrColor color, const SkPath& path, const SkMatrix& viewMatrix, 252 const SkRect& devBounds, int maxLineVertices, int maxQuadVertices, bool isIndexed) 253 : INHERITED(ClassID()) 254 , fViewMatrix(viewMatrix) 255 , fMaxLineVertices(maxLineVertices) 256 , fMaxQuadVertices(maxQuadVertices) 257 , fIsIndexed(isIndexed) { 258 fPaths.emplace_back(PathInfo{color, path}); 259 this->setBounds(devBounds, HasAABloat::kNo, IsZeroArea::kNo); 260 } 261 262 void getFragmentProcessorAnalysisInputs(GrPipelineAnalysisColor* color, 263 GrPipelineAnalysisCoverage* coverage) const override { 264 color->setToConstant(fPaths[0].fColor); 265 *coverage = GrPipelineAnalysisCoverage::kNone; 266 } 267 268 void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override { 269 optimizations.getOverrideColorIfSet(&fPaths[0].fColor); 270 } 271 272 static void ComputeWorstCasePointCount(const SkPath& path, int* subpaths, 273 int* outLinePointCount, int* outQuadPointCount) { 274 int linePointCount = 0; 275 int quadPointCount = 0; 276 *subpaths = 1; 277 278 bool first = true; 279 280 SkPath::Iter iter(path, true); 281 SkPath::Verb verb; 282 283 SkPoint pts[4]; 284 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { 285 switch (verb) { 286 case SkPath::kLine_Verb: 287 linePointCount += 1; 288 break; 289 case SkPath::kConic_Verb: { 290 SkScalar weight = iter.conicWeight(); 291 SkAutoConicToQuads converter; 292 converter.computeQuads(pts, weight, kTolerance); 293 int quadPts = converter.countQuads(); 294 linePointCount += quadPts; 295 quadPointCount += 3 * quadPts; 296 } 297 case SkPath::kQuad_Verb: 298 linePointCount += 1; 299 quadPointCount += 3; 300 break; 301 case SkPath::kCubic_Verb: { 302 SkSTArray<15, SkPoint, true> quadPts; 303 GrPathUtils::convertCubicToQuads(pts, kTolerance, &quadPts); 304 int count = quadPts.count(); 305 linePointCount += count / 3; 306 quadPointCount += count; 307 break; 308 } 309 case SkPath::kMove_Verb: 310 linePointCount += 1; 311 if (!first) { 312 ++(*subpaths); 313 } 314 break; 315 default: 316 break; 317 } 318 first = false; 319 } 320 *outLinePointCount = linePointCount; 321 *outQuadPointCount = quadPointCount; 322 } 323 324 void onPrepareDraws(Target* target) const override { 325 if (fMaxLineVertices == 0) { 326 SkASSERT(fMaxQuadVertices == 0); 327 return; 328 } 329 330 GrPrimitiveType primitiveType = fIsIndexed ? kTriangles_GrPrimitiveType 331 : kTriangleFan_GrPrimitiveType; 332 333 // allocate vertex / index buffers 334 const GrBuffer* lineVertexBuffer; 335 int firstLineVertex; 336 MSAALineVertices lines; 337 size_t lineVertexStride = sizeof(MSAALineVertices::Vertex); 338 lines.vertices = (MSAALineVertices::Vertex*) target->makeVertexSpace(lineVertexStride, 339 fMaxLineVertices, 340 &lineVertexBuffer, 341 &firstLineVertex); 342 if (!lines.vertices) { 343 SkDebugf("Could not allocate vertices\n"); 344 return; 345 } 346 lines.nextVertex = lines.vertices; 347 SkDEBUGCODE(lines.verticesEnd = lines.vertices + fMaxLineVertices;) 348 349 MSAAQuadVertices quads; 350 size_t quadVertexStride = sizeof(MSAAQuadVertices::Vertex); 351 SkAutoMalloc quadVertexPtr(fMaxQuadVertices * quadVertexStride); 352 quads.vertices = (MSAAQuadVertices::Vertex*) quadVertexPtr.get(); 353 quads.nextVertex = quads.vertices; 354 SkDEBUGCODE(quads.verticesEnd = quads.vertices + fMaxQuadVertices;) 355 356 const GrBuffer* lineIndexBuffer = nullptr; 357 int firstLineIndex; 358 if (fIsIndexed) { 359 lines.indices = 360 target->makeIndexSpace(3 * fMaxLineVertices, &lineIndexBuffer, &firstLineIndex); 361 if (!lines.indices) { 362 SkDebugf("Could not allocate indices\n"); 363 return; 364 } 365 lines.nextIndex = lines.indices; 366 } else { 367 lines.indices = nullptr; 368 lines.nextIndex = nullptr; 369 } 370 371 SkAutoFree quadIndexPtr; 372 if (fIsIndexed) { 373 quads.indices = (uint16_t*)sk_malloc_throw(3 * fMaxQuadVertices * sizeof(uint16_t)); 374 quadIndexPtr.reset(quads.indices); 375 quads.nextIndex = quads.indices; 376 } else { 377 quads.indices = nullptr; 378 quads.nextIndex = nullptr; 379 } 380 381 // fill buffers 382 for (int i = 0; i < fPaths.count(); i++) { 383 const PathInfo& pathInfo = fPaths[i]; 384 385 if (!this->createGeom(lines, 386 quads, 387 pathInfo.fPath, 388 fViewMatrix, 389 pathInfo.fColor, 390 fIsIndexed)) { 391 return; 392 } 393 } 394 int lineVertexOffset = (int) (lines.nextVertex - lines.vertices); 395 int lineIndexOffset = (int) (lines.nextIndex - lines.indices); 396 SkASSERT(lineVertexOffset <= fMaxLineVertices && lineIndexOffset <= 3 * fMaxLineVertices); 397 int quadVertexOffset = (int) (quads.nextVertex - quads.vertices); 398 int quadIndexOffset = (int) (quads.nextIndex - quads.indices); 399 SkASSERT(quadVertexOffset <= fMaxQuadVertices && quadIndexOffset <= 3 * fMaxQuadVertices); 400 401 if (lineVertexOffset) { 402 sk_sp<GrGeometryProcessor> lineGP; 403 { 404 using namespace GrDefaultGeoProcFactory; 405 lineGP = GrDefaultGeoProcFactory::Make(Color(Color::kPremulGrColorAttribute_Type), 406 Coverage::kSolid_Type, 407 LocalCoords(LocalCoords::kUnused_Type), 408 fViewMatrix); 409 } 410 SkASSERT(lineVertexStride == lineGP->getVertexStride()); 411 412 GrMesh lineMeshes; 413 if (fIsIndexed) { 414 lineMeshes.initIndexed(primitiveType, lineVertexBuffer, lineIndexBuffer, 415 firstLineVertex, firstLineIndex, lineVertexOffset, 416 lineIndexOffset); 417 } else { 418 lineMeshes.init(primitiveType, lineVertexBuffer, firstLineVertex, 419 lineVertexOffset); 420 } 421 target->draw(lineGP.get(), lineMeshes); 422 } 423 424 if (quadVertexOffset) { 425 sk_sp<const GrGeometryProcessor> quadGP(MSAAQuadProcessor::Create(fViewMatrix)); 426 SkASSERT(quadVertexStride == quadGP->getVertexStride()); 427 428 const GrBuffer* quadVertexBuffer; 429 int firstQuadVertex; 430 MSAAQuadVertices::Vertex* quadVertices = (MSAAQuadVertices::Vertex*) 431 target->makeVertexSpace(quadVertexStride, quadVertexOffset, &quadVertexBuffer, 432 &firstQuadVertex); 433 memcpy(quadVertices, quads.vertices, quadVertexStride * quadVertexOffset); 434 GrMesh quadMeshes; 435 if (fIsIndexed) { 436 const GrBuffer* quadIndexBuffer; 437 int firstQuadIndex; 438 uint16_t* quadIndices = (uint16_t*) target->makeIndexSpace(quadIndexOffset, 439 &quadIndexBuffer, 440 &firstQuadIndex); 441 memcpy(quadIndices, quads.indices, sizeof(uint16_t) * quadIndexOffset); 442 quadMeshes.initIndexed(kTriangles_GrPrimitiveType, quadVertexBuffer, 443 quadIndexBuffer, firstQuadVertex, firstQuadIndex, 444 quadVertexOffset, quadIndexOffset); 445 } else { 446 quadMeshes.init(kTriangles_GrPrimitiveType, quadVertexBuffer, firstQuadVertex, 447 quadVertexOffset); 448 } 449 target->draw(quadGP.get(), quadMeshes); 450 } 451 } 452 453 bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { 454 MSAAPathOp* that = t->cast<MSAAPathOp>(); 455 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(), 456 that->bounds(), caps)) { 457 return false; 458 } 459 460 if (this->bounds().intersects(that->bounds())) { 461 return false; 462 } 463 464 if (!fViewMatrix.cheapEqualTo(that->fViewMatrix)) { 465 return false; 466 } 467 468 // If we grow to include 2+ paths we will be indexed. 469 if (((fMaxLineVertices + that->fMaxLineVertices) > kMaxIndexedVertexCnt) || 470 ((fMaxQuadVertices + that->fMaxQuadVertices) > kMaxIndexedVertexCnt)) { 471 return false; 472 } 473 474 fPaths.push_back_n(that->fPaths.count(), that->fPaths.begin()); 475 this->joinBounds(*that); 476 fIsIndexed = true; 477 fMaxLineVertices += that->fMaxLineVertices; 478 fMaxQuadVertices += that->fMaxQuadVertices; 479 return true; 480 } 481 482 bool createGeom(MSAALineVertices& lines, 483 MSAAQuadVertices& quads, 484 const SkPath& path, 485 const SkMatrix& m, 486 SkColor color, 487 bool isIndexed) const { 488 { 489 uint16_t subpathIdxStart = (uint16_t) (lines.nextVertex - lines.vertices); 490 491 SkPoint pts[4]; 492 493 bool first = true; 494 SkPath::Iter iter(path, true); 495 496 bool done = false; 497 while (!done) { 498 SkPath::Verb verb = iter.next(pts); 499 switch (verb) { 500 case SkPath::kMove_Verb: 501 if (!first) { 502 uint16_t currIdx = (uint16_t) (lines.nextVertex - lines.vertices); 503 subpathIdxStart = currIdx; 504 } 505 SkASSERT(lines.nextVertex < lines.verticesEnd); 506 *(lines.nextVertex++) = { pts[0], color }; 507 break; 508 case SkPath::kLine_Verb: 509 if (isIndexed) { 510 uint16_t prevIdx = (uint16_t) (lines.nextVertex - lines.vertices - 1); 511 if (prevIdx > subpathIdxStart) { 512 append_contour_edge_indices(subpathIdxStart, prevIdx, lines); 513 } 514 } 515 SkASSERT(lines.nextVertex < lines.verticesEnd); 516 *(lines.nextVertex++) = { pts[1], color }; 517 break; 518 case SkPath::kConic_Verb: { 519 SkScalar weight = iter.conicWeight(); 520 SkAutoConicToQuads converter; 521 const SkPoint* quadPts = converter.computeQuads(pts, weight, kTolerance); 522 for (int i = 0; i < converter.countQuads(); ++i) { 523 add_quad(lines, quads, quadPts + i * 2, color, isIndexed, 524 subpathIdxStart); 525 } 526 break; 527 } 528 case SkPath::kQuad_Verb: { 529 add_quad(lines, quads, pts, color, isIndexed, subpathIdxStart); 530 break; 531 } 532 case SkPath::kCubic_Verb: { 533 SkSTArray<15, SkPoint, true> quadPts; 534 GrPathUtils::convertCubicToQuads(pts, kTolerance, &quadPts); 535 int count = quadPts.count(); 536 for (int i = 0; i < count; i += 3) { 537 add_quad(lines, quads, &quadPts[i], color, isIndexed, subpathIdxStart); 538 } 539 break; 540 } 541 case SkPath::kClose_Verb: 542 break; 543 case SkPath::kDone_Verb: 544 done = true; 545 } 546 first = false; 547 } 548 } 549 return true; 550 } 551 552 // Lines and quads may render with an index buffer. However, we don't have any support for 553 // overflowing the max index. 554 static constexpr int kMaxIndexedVertexCnt = SK_MaxU16 / 3; 555 struct PathInfo { 556 GrColor fColor; 557 SkPath fPath; 558 }; 559 560 SkSTArray<1, PathInfo, true> fPaths; 561 562 SkMatrix fViewMatrix; 563 int fMaxLineVertices; 564 int fMaxQuadVertices; 565 bool fIsIndexed; 566 567 typedef GrMeshDrawOp INHERITED; 568 }; 569 570 bool GrMSAAPathRenderer::internalDrawPath(GrRenderTargetContext* renderTargetContext, 571 GrPaint&& paint, 572 GrAAType aaType, 573 const GrUserStencilSettings& userStencilSettings, 574 const GrClip& clip, 575 const SkMatrix& viewMatrix, 576 const GrShape& shape, 577 bool stencilOnly) { 578 SkASSERT(shape.style().isSimpleFill()); 579 SkPath path; 580 shape.asPath(&path); 581 582 const GrUserStencilSettings* passes[2] = {nullptr, nullptr}; 583 bool reverse = false; 584 585 if (single_pass_shape(shape)) { 586 if (stencilOnly) { 587 passes[0] = &gDirectToStencil; 588 } else { 589 passes[0] = &userStencilSettings; 590 } 591 } else { 592 switch (path.getFillType()) { 593 case SkPath::kInverseEvenOdd_FillType: 594 reverse = true; 595 // fallthrough 596 case SkPath::kEvenOdd_FillType: 597 passes[0] = &gEOStencilPass; 598 if (!stencilOnly) { 599 passes[1] = reverse ? &gInvEOColorPass : &gEOColorPass; 600 } 601 break; 602 603 case SkPath::kInverseWinding_FillType: 604 reverse = true; 605 // fallthrough 606 case SkPath::kWinding_FillType: 607 passes[0] = &gWindStencilSeparateWithWrap; 608 if (!stencilOnly) { 609 passes[1] = reverse ? &gInvWindColorPass : &gWindColorPass; 610 } 611 break; 612 default: 613 SkDEBUGFAIL("Unknown path fFill!"); 614 return false; 615 } 616 } 617 618 SkRect devBounds; 619 GetPathDevBounds(path, renderTargetContext->width(), renderTargetContext->height(), viewMatrix, 620 &devBounds); 621 622 SkASSERT(passes[0]); 623 { // First pass 624 std::unique_ptr<GrMeshDrawOp> op = 625 MSAAPathOp::Make(paint.getColor(), path, viewMatrix, devBounds); 626 if (!op) { 627 return false; 628 } 629 bool firstPassIsStencil = stencilOnly || passes[1]; 630 // If we have a cover pass then we ignore the paint in the first pass and apply it in the 631 // second. 632 GrPaint::MoveOrNew firstPassPaint(paint, firstPassIsStencil); 633 if (firstPassIsStencil) { 634 firstPassPaint.paint().setXPFactory(GrDisableColorXPFactory::Get()); 635 } 636 GrPipelineBuilder pipelineBuilder(std::move(firstPassPaint), aaType); 637 pipelineBuilder.setUserStencil(passes[0]); 638 renderTargetContext->addMeshDrawOp(pipelineBuilder, clip, std::move(op)); 639 } 640 641 if (passes[1]) { 642 SkRect bounds; 643 SkMatrix localMatrix = SkMatrix::I(); 644 if (reverse) { 645 // draw over the dev bounds (which will be the whole dst surface for inv fill). 646 bounds = devBounds; 647 SkMatrix vmi; 648 // mapRect through persp matrix may not be correct 649 if (!viewMatrix.hasPerspective() && viewMatrix.invert(&vmi)) { 650 vmi.mapRect(&bounds); 651 } else { 652 if (!viewMatrix.invert(&localMatrix)) { 653 return false; 654 } 655 } 656 } else { 657 bounds = path.getBounds(); 658 } 659 const SkMatrix& viewM = 660 (reverse && viewMatrix.hasPerspective()) ? SkMatrix::I() : viewMatrix; 661 std::unique_ptr<GrMeshDrawOp> op(GrRectOpFactory::MakeNonAAFill( 662 paint.getColor(), viewM, bounds, nullptr, &localMatrix)); 663 664 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType); 665 pipelineBuilder.setUserStencil(passes[1]); 666 667 renderTargetContext->addMeshDrawOp(pipelineBuilder, clip, std::move(op)); 668 } 669 return true; 670 } 671 672 bool GrMSAAPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const { 673 // This path renderer only fills and relies on MSAA for antialiasing. Stroked shapes are 674 // handled by passing on the original shape and letting the caller compute the stroked shape 675 // which will have a fill style. 676 return args.fShape->style().isSimpleFill() && (GrAAType::kCoverage != args.fAAType); 677 } 678 679 bool GrMSAAPathRenderer::onDrawPath(const DrawPathArgs& args) { 680 GR_AUDIT_TRAIL_AUTO_FRAME(args.fRenderTargetContext->auditTrail(), 681 "GrMSAAPathRenderer::onDrawPath"); 682 SkTLazy<GrShape> tmpShape; 683 const GrShape* shape = args.fShape; 684 if (shape->style().applies()) { 685 SkScalar styleScale = GrStyle::MatrixToScaleFactor(*args.fViewMatrix); 686 tmpShape.init(args.fShape->applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec, styleScale)); 687 shape = tmpShape.get(); 688 } 689 return this->internalDrawPath(args.fRenderTargetContext, 690 std::move(args.fPaint), 691 args.fAAType, 692 *args.fUserStencilSettings, 693 *args.fClip, 694 *args.fViewMatrix, 695 *shape, 696 false); 697 } 698 699 void GrMSAAPathRenderer::onStencilPath(const StencilPathArgs& args) { 700 GR_AUDIT_TRAIL_AUTO_FRAME(args.fRenderTargetContext->auditTrail(), 701 "GrMSAAPathRenderer::onStencilPath"); 702 SkASSERT(args.fShape->style().isSimpleFill()); 703 SkASSERT(!args.fShape->mayBeInverseFilledAfterStyling()); 704 705 GrPaint paint; 706 paint.setXPFactory(GrDisableColorXPFactory::Get()); 707 708 this->internalDrawPath(args.fRenderTargetContext, std::move(paint), args.fAAType, 709 GrUserStencilSettings::kUnused, *args.fClip, *args.fViewMatrix, 710 *args.fShape, true); 711 } 712 713 /////////////////////////////////////////////////////////////////////////////////////////////////// 714