1 /* 2 * Copyright 2011 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 "GrDefaultPathRenderer.h" 9 10 #include "GrContext.h" 11 #include "GrDrawState.h" 12 #include "GrPathUtils.h" 13 #include "SkString.h" 14 #include "SkStrokeRec.h" 15 #include "SkTLazy.h" 16 #include "SkTraceEvent.h" 17 18 19 GrDefaultPathRenderer::GrDefaultPathRenderer(bool separateStencilSupport, 20 bool stencilWrapOpsSupport) 21 : fSeparateStencil(separateStencilSupport) 22 , fStencilWrapOps(stencilWrapOpsSupport) { 23 } 24 25 26 //////////////////////////////////////////////////////////////////////////////// 27 // Stencil rules for paths 28 29 ////// Even/Odd 30 31 GR_STATIC_CONST_SAME_STENCIL(gEOStencilPass, 32 kInvert_StencilOp, 33 kKeep_StencilOp, 34 kAlwaysIfInClip_StencilFunc, 35 0xffff, 36 0xffff, 37 0xffff); 38 39 // ok not to check clip b/c stencil pass only wrote inside clip 40 GR_STATIC_CONST_SAME_STENCIL(gEOColorPass, 41 kZero_StencilOp, 42 kZero_StencilOp, 43 kNotEqual_StencilFunc, 44 0xffff, 45 0x0000, 46 0xffff); 47 48 // have to check clip b/c outside clip will always be zero. 49 GR_STATIC_CONST_SAME_STENCIL(gInvEOColorPass, 50 kZero_StencilOp, 51 kZero_StencilOp, 52 kEqualIfInClip_StencilFunc, 53 0xffff, 54 0x0000, 55 0xffff); 56 57 ////// Winding 58 59 // when we have separate stencil we increment front faces / decrement back faces 60 // when we don't have wrap incr and decr we use the stencil test to simulate 61 // them. 62 63 GR_STATIC_CONST_STENCIL(gWindStencilSeparateWithWrap, 64 kIncWrap_StencilOp, kDecWrap_StencilOp, 65 kKeep_StencilOp, kKeep_StencilOp, 66 kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc, 67 0xffff, 0xffff, 68 0xffff, 0xffff, 69 0xffff, 0xffff); 70 71 // if inc'ing the max value, invert to make 0 72 // if dec'ing zero invert to make all ones. 73 // we can't avoid touching the stencil on both passing and 74 // failing, so we can't resctrict ourselves to the clip. 75 GR_STATIC_CONST_STENCIL(gWindStencilSeparateNoWrap, 76 kInvert_StencilOp, kInvert_StencilOp, 77 kIncClamp_StencilOp, kDecClamp_StencilOp, 78 kEqual_StencilFunc, kEqual_StencilFunc, 79 0xffff, 0xffff, 80 0xffff, 0x0000, 81 0xffff, 0xffff); 82 83 // When there are no separate faces we do two passes to setup the winding rule 84 // stencil. First we draw the front faces and inc, then we draw the back faces 85 // and dec. These are same as the above two split into the incrementing and 86 // decrementing passes. 87 GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilWithWrapInc, 88 kIncWrap_StencilOp, 89 kKeep_StencilOp, 90 kAlwaysIfInClip_StencilFunc, 91 0xffff, 92 0xffff, 93 0xffff); 94 95 GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilWithWrapDec, 96 kDecWrap_StencilOp, 97 kKeep_StencilOp, 98 kAlwaysIfInClip_StencilFunc, 99 0xffff, 100 0xffff, 101 0xffff); 102 103 GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilNoWrapInc, 104 kInvert_StencilOp, 105 kIncClamp_StencilOp, 106 kEqual_StencilFunc, 107 0xffff, 108 0xffff, 109 0xffff); 110 111 GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilNoWrapDec, 112 kInvert_StencilOp, 113 kDecClamp_StencilOp, 114 kEqual_StencilFunc, 115 0xffff, 116 0x0000, 117 0xffff); 118 119 // Color passes are the same whether we use the two-sided stencil or two passes 120 121 GR_STATIC_CONST_SAME_STENCIL(gWindColorPass, 122 kZero_StencilOp, 123 kZero_StencilOp, 124 kNonZeroIfInClip_StencilFunc, 125 0xffff, 126 0x0000, 127 0xffff); 128 129 GR_STATIC_CONST_SAME_STENCIL(gInvWindColorPass, 130 kZero_StencilOp, 131 kZero_StencilOp, 132 kEqualIfInClip_StencilFunc, 133 0xffff, 134 0x0000, 135 0xffff); 136 137 ////// Normal render to stencil 138 139 // Sometimes the default path renderer can draw a path directly to the stencil 140 // buffer without having to first resolve the interior / exterior. 141 GR_STATIC_CONST_SAME_STENCIL(gDirectToStencil, 142 kZero_StencilOp, 143 kIncClamp_StencilOp, 144 kAlwaysIfInClip_StencilFunc, 145 0xffff, 146 0x0000, 147 0xffff); 148 149 //////////////////////////////////////////////////////////////////////////////// 150 // Helpers for drawPath 151 152 #define STENCIL_OFF 0 // Always disable stencil (even when needed) 153 154 static inline bool single_pass_path(const SkPath& path, const SkStrokeRec& stroke) { 155 #if STENCIL_OFF 156 return true; 157 #else 158 if (!stroke.isHairlineStyle() && !path.isInverseFillType()) { 159 return path.isConvex(); 160 } 161 return false; 162 #endif 163 } 164 165 GrPathRenderer::StencilSupport GrDefaultPathRenderer::onGetStencilSupport( 166 const SkPath& path, 167 const SkStrokeRec& stroke, 168 const GrDrawTarget*) const { 169 if (single_pass_path(path, stroke)) { 170 return GrPathRenderer::kNoRestriction_StencilSupport; 171 } else { 172 return GrPathRenderer::kStencilOnly_StencilSupport; 173 } 174 } 175 176 static inline void append_countour_edge_indices(bool hairLine, 177 uint16_t fanCenterIdx, 178 uint16_t edgeV0Idx, 179 uint16_t** indices) { 180 // when drawing lines we're appending line segments along 181 // the contour. When applying the other fill rules we're 182 // drawing triangle fans around fanCenterIdx. 183 if (!hairLine) { 184 *((*indices)++) = fanCenterIdx; 185 } 186 *((*indices)++) = edgeV0Idx; 187 *((*indices)++) = edgeV0Idx + 1; 188 } 189 190 bool GrDefaultPathRenderer::createGeom(const SkPath& path, 191 const SkStrokeRec& stroke, 192 SkScalar srcSpaceTol, 193 GrDrawTarget* target, 194 GrPrimitiveType* primType, 195 int* vertexCnt, 196 int* indexCnt, 197 GrDrawTarget::AutoReleaseGeometry* arg) { 198 { 199 SkScalar srcSpaceTolSqd = SkScalarMul(srcSpaceTol, srcSpaceTol); 200 int contourCnt; 201 int maxPts = GrPathUtils::worstCasePointCount(path, &contourCnt, 202 srcSpaceTol); 203 204 if (maxPts <= 0) { 205 return false; 206 } 207 if (maxPts > ((int)SK_MaxU16 + 1)) { 208 GrPrintf("Path not rendered, too many verts (%d)\n", maxPts); 209 return false; 210 } 211 212 bool indexed = contourCnt > 1; 213 214 const bool isHairline = stroke.isHairlineStyle(); 215 216 int maxIdxs = 0; 217 if (isHairline) { 218 if (indexed) { 219 maxIdxs = 2 * maxPts; 220 *primType = kLines_GrPrimitiveType; 221 } else { 222 *primType = kLineStrip_GrPrimitiveType; 223 } 224 } else { 225 if (indexed) { 226 maxIdxs = 3 * maxPts; 227 *primType = kTriangles_GrPrimitiveType; 228 } else { 229 *primType = kTriangleFan_GrPrimitiveType; 230 } 231 } 232 233 target->drawState()->setDefaultVertexAttribs(); 234 if (!arg->set(target, maxPts, maxIdxs)) { 235 return false; 236 } 237 238 uint16_t* idxBase = reinterpret_cast<uint16_t*>(arg->indices()); 239 uint16_t* idx = idxBase; 240 uint16_t subpathIdxStart = 0; 241 242 SkPoint* base = reinterpret_cast<SkPoint*>(arg->vertices()); 243 SkASSERT(base); 244 SkPoint* vert = base; 245 246 SkPoint pts[4]; 247 248 bool first = true; 249 int subpath = 0; 250 251 SkPath::Iter iter(path, false); 252 253 for (;;) { 254 SkPath::Verb verb = iter.next(pts); 255 switch (verb) { 256 case SkPath::kConic_Verb: 257 SkASSERT(0); 258 break; 259 case SkPath::kMove_Verb: 260 if (!first) { 261 uint16_t currIdx = (uint16_t) (vert - base); 262 subpathIdxStart = currIdx; 263 ++subpath; 264 } 265 *vert = pts[0]; 266 vert++; 267 break; 268 case SkPath::kLine_Verb: 269 if (indexed) { 270 uint16_t prevIdx = (uint16_t)(vert - base) - 1; 271 append_countour_edge_indices(isHairline, subpathIdxStart, 272 prevIdx, &idx); 273 } 274 *(vert++) = pts[1]; 275 break; 276 case SkPath::kQuad_Verb: { 277 // first pt of quad is the pt we ended on in previous step 278 uint16_t firstQPtIdx = (uint16_t)(vert - base) - 1; 279 uint16_t numPts = (uint16_t) 280 GrPathUtils::generateQuadraticPoints( 281 pts[0], pts[1], pts[2], 282 srcSpaceTolSqd, &vert, 283 GrPathUtils::quadraticPointCount(pts, srcSpaceTol)); 284 if (indexed) { 285 for (uint16_t i = 0; i < numPts; ++i) { 286 append_countour_edge_indices(isHairline, subpathIdxStart, 287 firstQPtIdx + i, &idx); 288 } 289 } 290 break; 291 } 292 case SkPath::kCubic_Verb: { 293 // first pt of cubic is the pt we ended on in previous step 294 uint16_t firstCPtIdx = (uint16_t)(vert - base) - 1; 295 uint16_t numPts = (uint16_t) GrPathUtils::generateCubicPoints( 296 pts[0], pts[1], pts[2], pts[3], 297 srcSpaceTolSqd, &vert, 298 GrPathUtils::cubicPointCount(pts, srcSpaceTol)); 299 if (indexed) { 300 for (uint16_t i = 0; i < numPts; ++i) { 301 append_countour_edge_indices(isHairline, subpathIdxStart, 302 firstCPtIdx + i, &idx); 303 } 304 } 305 break; 306 } 307 case SkPath::kClose_Verb: 308 break; 309 case SkPath::kDone_Verb: 310 // uint16_t currIdx = (uint16_t) (vert - base); 311 goto FINISHED; 312 } 313 first = false; 314 } 315 FINISHED: 316 SkASSERT((vert - base) <= maxPts); 317 SkASSERT((idx - idxBase) <= maxIdxs); 318 319 *vertexCnt = static_cast<int>(vert - base); 320 *indexCnt = static_cast<int>(idx - idxBase); 321 322 } 323 return true; 324 } 325 326 bool GrDefaultPathRenderer::internalDrawPath(const SkPath& path, 327 const SkStrokeRec& origStroke, 328 GrDrawTarget* target, 329 bool stencilOnly) { 330 331 SkMatrix viewM = target->getDrawState().getViewMatrix(); 332 SkTCopyOnFirstWrite<SkStrokeRec> stroke(origStroke); 333 334 SkScalar hairlineCoverage; 335 if (IsStrokeHairlineOrEquivalent(*stroke, target->getDrawState().getViewMatrix(), 336 &hairlineCoverage)) { 337 uint8_t newCoverage = SkScalarRoundToInt(hairlineCoverage * 338 target->getDrawState().getCoverage()); 339 target->drawState()->setCoverage(newCoverage); 340 341 if (!stroke->isHairlineStyle()) { 342 stroke.writable()->setHairlineStyle(); 343 } 344 } 345 346 SkScalar tol = SK_Scalar1; 347 tol = GrPathUtils::scaleToleranceToSrc(tol, viewM, path.getBounds()); 348 349 int vertexCnt; 350 int indexCnt; 351 GrPrimitiveType primType; 352 GrDrawTarget::AutoReleaseGeometry arg; 353 if (!this->createGeom(path, 354 *stroke, 355 tol, 356 target, 357 &primType, 358 &vertexCnt, 359 &indexCnt, 360 &arg)) { 361 return false; 362 } 363 364 SkASSERT(target); 365 GrDrawTarget::AutoStateRestore asr(target, GrDrawTarget::kPreserve_ASRInit); 366 GrDrawState* drawState = target->drawState(); 367 bool colorWritesWereDisabled = drawState->isColorWriteDisabled(); 368 // face culling doesn't make sense here 369 SkASSERT(GrDrawState::kBoth_DrawFace == drawState->getDrawFace()); 370 371 int passCount = 0; 372 const GrStencilSettings* passes[3]; 373 GrDrawState::DrawFace drawFace[3]; 374 bool reverse = false; 375 bool lastPassIsBounds; 376 377 if (stroke->isHairlineStyle()) { 378 passCount = 1; 379 if (stencilOnly) { 380 passes[0] = &gDirectToStencil; 381 } else { 382 passes[0] = NULL; 383 } 384 lastPassIsBounds = false; 385 drawFace[0] = GrDrawState::kBoth_DrawFace; 386 } else { 387 if (single_pass_path(path, *stroke)) { 388 passCount = 1; 389 if (stencilOnly) { 390 passes[0] = &gDirectToStencil; 391 } else { 392 passes[0] = NULL; 393 } 394 drawFace[0] = GrDrawState::kBoth_DrawFace; 395 lastPassIsBounds = false; 396 } else { 397 switch (path.getFillType()) { 398 case SkPath::kInverseEvenOdd_FillType: 399 reverse = true; 400 // fallthrough 401 case SkPath::kEvenOdd_FillType: 402 passes[0] = &gEOStencilPass; 403 if (stencilOnly) { 404 passCount = 1; 405 lastPassIsBounds = false; 406 } else { 407 passCount = 2; 408 lastPassIsBounds = true; 409 if (reverse) { 410 passes[1] = &gInvEOColorPass; 411 } else { 412 passes[1] = &gEOColorPass; 413 } 414 } 415 drawFace[0] = drawFace[1] = GrDrawState::kBoth_DrawFace; 416 break; 417 418 case SkPath::kInverseWinding_FillType: 419 reverse = true; 420 // fallthrough 421 case SkPath::kWinding_FillType: 422 if (fSeparateStencil) { 423 if (fStencilWrapOps) { 424 passes[0] = &gWindStencilSeparateWithWrap; 425 } else { 426 passes[0] = &gWindStencilSeparateNoWrap; 427 } 428 passCount = 2; 429 drawFace[0] = GrDrawState::kBoth_DrawFace; 430 } else { 431 if (fStencilWrapOps) { 432 passes[0] = &gWindSingleStencilWithWrapInc; 433 passes[1] = &gWindSingleStencilWithWrapDec; 434 } else { 435 passes[0] = &gWindSingleStencilNoWrapInc; 436 passes[1] = &gWindSingleStencilNoWrapDec; 437 } 438 // which is cw and which is ccw is arbitrary. 439 drawFace[0] = GrDrawState::kCW_DrawFace; 440 drawFace[1] = GrDrawState::kCCW_DrawFace; 441 passCount = 3; 442 } 443 if (stencilOnly) { 444 lastPassIsBounds = false; 445 --passCount; 446 } else { 447 lastPassIsBounds = true; 448 drawFace[passCount-1] = GrDrawState::kBoth_DrawFace; 449 if (reverse) { 450 passes[passCount-1] = &gInvWindColorPass; 451 } else { 452 passes[passCount-1] = &gWindColorPass; 453 } 454 } 455 break; 456 default: 457 SkDEBUGFAIL("Unknown path fFill!"); 458 return false; 459 } 460 } 461 } 462 463 SkRect devBounds; 464 GetPathDevBounds(path, drawState->getRenderTarget(), viewM, &devBounds); 465 466 for (int p = 0; p < passCount; ++p) { 467 drawState->setDrawFace(drawFace[p]); 468 if (passes[p]) { 469 *drawState->stencil() = *passes[p]; 470 } 471 472 if (lastPassIsBounds && (p == passCount-1)) { 473 if (!colorWritesWereDisabled) { 474 drawState->disableState(GrDrawState::kNoColorWrites_StateBit); 475 } 476 SkRect bounds; 477 GrDrawState::AutoViewMatrixRestore avmr; 478 if (reverse) { 479 SkASSERT(drawState->getRenderTarget()); 480 // draw over the dev bounds (which will be the whole dst surface for inv fill). 481 bounds = devBounds; 482 SkMatrix vmi; 483 // mapRect through persp matrix may not be correct 484 if (!drawState->getViewMatrix().hasPerspective() && 485 drawState->getViewInverse(&vmi)) { 486 vmi.mapRect(&bounds); 487 } else { 488 avmr.setIdentity(drawState); 489 } 490 } else { 491 bounds = path.getBounds(); 492 } 493 GrDrawTarget::AutoGeometryAndStatePush agasp(target, GrDrawTarget::kPreserve_ASRInit); 494 target->drawSimpleRect(bounds); 495 } else { 496 if (passCount > 1) { 497 drawState->enableState(GrDrawState::kNoColorWrites_StateBit); 498 } 499 if (indexCnt) { 500 target->drawIndexed(primType, 0, 0, 501 vertexCnt, indexCnt, &devBounds); 502 } else { 503 target->drawNonIndexed(primType, 0, vertexCnt, &devBounds); 504 } 505 } 506 } 507 return true; 508 } 509 510 bool GrDefaultPathRenderer::canDrawPath(const SkPath& path, 511 const SkStrokeRec& stroke, 512 const GrDrawTarget* target, 513 bool antiAlias) const { 514 // this class can draw any path with any fill but doesn't do any anti-aliasing. 515 516 return !antiAlias && !(SkPath::kConic_SegmentMask & path.getSegmentMasks()) && 517 (stroke.isFillStyle() || 518 IsStrokeHairlineOrEquivalent(stroke, target->getDrawState().getViewMatrix(), NULL)); 519 } 520 521 bool GrDefaultPathRenderer::onDrawPath(const SkPath& path, 522 const SkStrokeRec& stroke, 523 GrDrawTarget* target, 524 bool antiAlias) { 525 return this->internalDrawPath(path, 526 stroke, 527 target, 528 false); 529 } 530 531 void GrDefaultPathRenderer::onStencilPath(const SkPath& path, 532 const SkStrokeRec& stroke, 533 GrDrawTarget* target) { 534 SkASSERT(SkPath::kInverseEvenOdd_FillType != path.getFillType()); 535 SkASSERT(SkPath::kInverseWinding_FillType != path.getFillType()); 536 this->internalDrawPath(path, stroke, target, true); 537 } 538