1 2 /* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 #include "GrDefaultPathRenderer.h" 10 11 #include "GrContext.h" 12 #include "GrDrawState.h" 13 #include "GrPathUtils.h" 14 #include "SkString.h" 15 #include "SkTrace.h" 16 17 18 GrDefaultPathRenderer::GrDefaultPathRenderer(bool separateStencilSupport, 19 bool stencilWrapOpsSupport) 20 : fSeparateStencil(separateStencilSupport) 21 , fStencilWrapOps(stencilWrapOpsSupport) { 22 } 23 24 25 //////////////////////////////////////////////////////////////////////////////// 26 // Stencil rules for paths 27 28 ////// Even/Odd 29 30 GR_STATIC_CONST_SAME_STENCIL(gEOStencilPass, 31 kInvert_StencilOp, 32 kKeep_StencilOp, 33 kAlwaysIfInClip_StencilFunc, 34 0xffff, 35 0xffff, 36 0xffff); 37 38 // ok not to check clip b/c stencil pass only wrote inside clip 39 GR_STATIC_CONST_SAME_STENCIL(gEOColorPass, 40 kZero_StencilOp, 41 kZero_StencilOp, 42 kNotEqual_StencilFunc, 43 0xffff, 44 0x0000, 45 0xffff); 46 47 // have to check clip b/c outside clip will always be zero. 48 GR_STATIC_CONST_SAME_STENCIL(gInvEOColorPass, 49 kZero_StencilOp, 50 kZero_StencilOp, 51 kEqualIfInClip_StencilFunc, 52 0xffff, 53 0x0000, 54 0xffff); 55 56 ////// Winding 57 58 // when we have separate stencil we increment front faces / decrement back faces 59 // when we don't have wrap incr and decr we use the stencil test to simulate 60 // them. 61 62 GR_STATIC_CONST_STENCIL(gWindStencilSeparateWithWrap, 63 kIncWrap_StencilOp, kDecWrap_StencilOp, 64 kKeep_StencilOp, kKeep_StencilOp, 65 kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc, 66 0xffff, 0xffff, 67 0xffff, 0xffff, 68 0xffff, 0xffff); 69 70 // if inc'ing the max value, invert to make 0 71 // if dec'ing zero invert to make all ones. 72 // we can't avoid touching the stencil on both passing and 73 // failing, so we can't resctrict ourselves to the clip. 74 GR_STATIC_CONST_STENCIL(gWindStencilSeparateNoWrap, 75 kInvert_StencilOp, kInvert_StencilOp, 76 kIncClamp_StencilOp, kDecClamp_StencilOp, 77 kEqual_StencilFunc, kEqual_StencilFunc, 78 0xffff, 0xffff, 79 0xffff, 0x0000, 80 0xffff, 0xffff); 81 82 // When there are no separate faces we do two passes to setup the winding rule 83 // stencil. First we draw the front faces and inc, then we draw the back faces 84 // and dec. These are same as the above two split into the incrementing and 85 // decrementing passes. 86 GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilWithWrapInc, 87 kIncWrap_StencilOp, 88 kKeep_StencilOp, 89 kAlwaysIfInClip_StencilFunc, 90 0xffff, 91 0xffff, 92 0xffff); 93 94 GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilWithWrapDec, 95 kDecWrap_StencilOp, 96 kKeep_StencilOp, 97 kAlwaysIfInClip_StencilFunc, 98 0xffff, 99 0xffff, 100 0xffff); 101 102 GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilNoWrapInc, 103 kInvert_StencilOp, 104 kIncClamp_StencilOp, 105 kEqual_StencilFunc, 106 0xffff, 107 0xffff, 108 0xffff); 109 110 GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilNoWrapDec, 111 kInvert_StencilOp, 112 kDecClamp_StencilOp, 113 kEqual_StencilFunc, 114 0xffff, 115 0x0000, 116 0xffff); 117 118 // Color passes are the same whether we use the two-sided stencil or two passes 119 120 GR_STATIC_CONST_SAME_STENCIL(gWindColorPass, 121 kZero_StencilOp, 122 kZero_StencilOp, 123 kNonZeroIfInClip_StencilFunc, 124 0xffff, 125 0x0000, 126 0xffff); 127 128 GR_STATIC_CONST_SAME_STENCIL(gInvWindColorPass, 129 kZero_StencilOp, 130 kZero_StencilOp, 131 kEqualIfInClip_StencilFunc, 132 0xffff, 133 0x0000, 134 0xffff); 135 136 ////// Normal render to stencil 137 138 // Sometimes the default path renderer can draw a path directly to the stencil 139 // buffer without having to first resolve the interior / exterior. 140 GR_STATIC_CONST_SAME_STENCIL(gDirectToStencil, 141 kZero_StencilOp, 142 kIncClamp_StencilOp, 143 kAlwaysIfInClip_StencilFunc, 144 0xffff, 145 0x0000, 146 0xffff); 147 148 //////////////////////////////////////////////////////////////////////////////// 149 // Helpers for drawPath 150 151 #define STENCIL_OFF 0 // Always disable stencil (even when needed) 152 153 static inline bool single_pass_path(const GrPath& path, GrPathFill fill) { 154 #if STENCIL_OFF 155 return true; 156 #else 157 if (kEvenOdd_PathFill == fill || kWinding_PathFill == fill) { 158 return path.isConvex(); 159 } 160 return false; 161 #endif 162 } 163 164 bool GrDefaultPathRenderer::requiresStencilPass(const SkPath& path, 165 GrPathFill fill, 166 const GrDrawTarget* target) const { 167 return !single_pass_path(path, fill); 168 } 169 170 static inline void append_countour_edge_indices(GrPathFill fillType, 171 uint16_t fanCenterIdx, 172 uint16_t edgeV0Idx, 173 uint16_t** indices) { 174 // when drawing lines we're appending line segments along 175 // the contour. When applying the other fill rules we're 176 // drawing triangle fans around fanCenterIdx. 177 if (kHairLine_PathFill != fillType) { 178 *((*indices)++) = fanCenterIdx; 179 } 180 *((*indices)++) = edgeV0Idx; 181 *((*indices)++) = edgeV0Idx + 1; 182 } 183 184 bool GrDefaultPathRenderer::createGeom(const SkPath& path, 185 GrPathFill fill, 186 const GrVec* translate, 187 GrScalar srcSpaceTol, 188 GrDrawTarget* target, 189 GrDrawState::StageMask stageMask, 190 GrPrimitiveType* primType, 191 int* vertexCnt, 192 int* indexCnt) { 193 { 194 SK_TRACE_EVENT0("GrDefaultPathRenderer::createGeom"); 195 196 GrScalar srcSpaceTolSqd = GrMul(srcSpaceTol, srcSpaceTol); 197 int contourCnt; 198 int maxPts = GrPathUtils::worstCasePointCount(path, &contourCnt, 199 srcSpaceTol); 200 201 if (maxPts <= 0) { 202 return false; 203 } 204 if (maxPts > ((int)SK_MaxU16 + 1)) { 205 GrPrintf("Path not rendered, too many verts (%d)\n", maxPts); 206 return false; 207 } 208 209 GrVertexLayout layout = 0; 210 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 211 if ((1 << s) & stageMask) { 212 layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s); 213 } 214 } 215 216 bool indexed = contourCnt > 1; 217 218 int maxIdxs = 0; 219 if (kHairLine_PathFill == fill) { 220 if (indexed) { 221 maxIdxs = 2 * maxPts; 222 *primType = kLines_PrimitiveType; 223 } else { 224 *primType = kLineStrip_PrimitiveType; 225 } 226 } else { 227 if (indexed) { 228 maxIdxs = 3 * maxPts; 229 *primType = kTriangles_PrimitiveType; 230 } else { 231 *primType = kTriangleFan_PrimitiveType; 232 } 233 } 234 235 GrPoint* base; 236 if (!target->reserveVertexSpace(layout, maxPts, (void**)&base)) { 237 return false; 238 } 239 GrAssert(NULL != base); 240 GrPoint* vert = base; 241 242 uint16_t* idxBase = NULL; 243 uint16_t* idx = NULL; 244 uint16_t subpathIdxStart = 0; 245 if (indexed) { 246 if (!target->reserveIndexSpace(maxIdxs, (void**)&idxBase)) { 247 target->resetVertexSource(); 248 return false; 249 } 250 GrAssert(NULL != idxBase); 251 idx = idxBase; 252 } 253 254 GrPoint pts[4]; 255 256 bool first = true; 257 int subpath = 0; 258 259 SkPath::Iter iter(path, false); 260 261 for (;;) { 262 GrPathCmd cmd = (GrPathCmd)iter.next(pts); 263 switch (cmd) { 264 case kMove_PathCmd: 265 if (!first) { 266 uint16_t currIdx = (uint16_t) (vert - base); 267 subpathIdxStart = currIdx; 268 ++subpath; 269 } 270 *vert = pts[0]; 271 vert++; 272 break; 273 case kLine_PathCmd: 274 if (indexed) { 275 uint16_t prevIdx = (uint16_t)(vert - base) - 1; 276 append_countour_edge_indices(fill, subpathIdxStart, 277 prevIdx, &idx); 278 } 279 *(vert++) = pts[1]; 280 break; 281 case kQuadratic_PathCmd: { 282 // first pt of quad is the pt we ended on in previous step 283 uint16_t firstQPtIdx = (uint16_t)(vert - base) - 1; 284 uint16_t numPts = (uint16_t) 285 GrPathUtils::generateQuadraticPoints( 286 pts[0], pts[1], pts[2], 287 srcSpaceTolSqd, &vert, 288 GrPathUtils::quadraticPointCount(pts, srcSpaceTol)); 289 if (indexed) { 290 for (uint16_t i = 0; i < numPts; ++i) { 291 append_countour_edge_indices(fill, subpathIdxStart, 292 firstQPtIdx + i, &idx); 293 } 294 } 295 break; 296 } 297 case kCubic_PathCmd: { 298 // first pt of cubic is the pt we ended on in previous step 299 uint16_t firstCPtIdx = (uint16_t)(vert - base) - 1; 300 uint16_t numPts = (uint16_t) GrPathUtils::generateCubicPoints( 301 pts[0], pts[1], pts[2], pts[3], 302 srcSpaceTolSqd, &vert, 303 GrPathUtils::cubicPointCount(pts, srcSpaceTol)); 304 if (indexed) { 305 for (uint16_t i = 0; i < numPts; ++i) { 306 append_countour_edge_indices(fill, subpathIdxStart, 307 firstCPtIdx + i, &idx); 308 } 309 } 310 break; 311 } 312 case kClose_PathCmd: 313 break; 314 case kEnd_PathCmd: 315 uint16_t currIdx = (uint16_t) (vert - base); 316 goto FINISHED; 317 } 318 first = false; 319 } 320 FINISHED: 321 GrAssert((vert - base) <= maxPts); 322 GrAssert((idx - idxBase) <= maxIdxs); 323 324 *vertexCnt = vert - base; 325 *indexCnt = idx - idxBase; 326 327 if (NULL != translate && 328 (translate->fX || translate->fY)) { 329 int count = vert - base; 330 for (int i = 0; i < count; i++) { 331 base[i].offset(translate->fX, translate->fY); 332 } 333 } 334 } 335 return true; 336 } 337 338 bool GrDefaultPathRenderer::internalDrawPath(const SkPath& path, 339 GrPathFill fill, 340 const GrVec* translate, 341 GrDrawTarget* target, 342 GrDrawState::StageMask stageMask, 343 bool stencilOnly) { 344 345 GrMatrix viewM = target->getDrawState().getViewMatrix(); 346 GrScalar tol = GR_Scalar1; 347 tol = GrPathUtils::scaleToleranceToSrc(tol, viewM, path.getBounds()); 348 GrDrawState* drawState = target->drawState(); 349 350 int vertexCnt; 351 int indexCnt; 352 GrPrimitiveType primType; 353 if (!this->createGeom(path, 354 fill, 355 translate, 356 tol, 357 target, 358 stageMask, 359 &primType, 360 &vertexCnt, 361 &indexCnt)) { 362 return false; 363 } 364 365 GrAssert(NULL != target); 366 GrDrawTarget::AutoStateRestore asr(target); 367 bool colorWritesWereDisabled = drawState->isColorWriteDisabled(); 368 // face culling doesn't make sense here 369 GrAssert(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 (kHairLine_PathFill == fill) { 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, fill)) { 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 (fill) { 398 case kInverseEvenOdd_PathFill: 399 reverse = true; 400 // fallthrough 401 case kEvenOdd_PathFill: 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 kInverseWinding_PathFill: 419 reverse = true; 420 // fallthrough 421 case kWinding_PathFill: 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 GrAssert(!"Unknown path fFill!"); 458 return false; 459 } 460 } 461 } 462 463 { 464 for (int p = 0; p < passCount; ++p) { 465 drawState->setDrawFace(drawFace[p]); 466 if (NULL != passes[p]) { 467 *drawState->stencil() = *passes[p]; 468 } 469 470 if (lastPassIsBounds && (p == passCount-1)) { 471 if (!colorWritesWereDisabled) { 472 drawState->disableState(GrDrawState::kNoColorWrites_StateBit); 473 } 474 GrRect bounds; 475 if (reverse) { 476 GrAssert(NULL != drawState->getRenderTarget()); 477 // draw over the whole world. 478 bounds.setLTRB(0, 0, 479 GrIntToScalar(drawState->getRenderTarget()->width()), 480 GrIntToScalar(drawState->getRenderTarget()->height())); 481 GrMatrix vmi; 482 // mapRect through persp matrix may not be correct 483 if (!drawState->getViewMatrix().hasPerspective() && 484 drawState->getViewInverse(&vmi)) { 485 vmi.mapRect(&bounds); 486 } else { 487 if (stageMask) { 488 if (!drawState->getViewInverse(&vmi)) { 489 GrPrintf("Could not invert matrix."); 490 return false; 491 } 492 drawState->preConcatSamplerMatrices(stageMask, vmi); 493 } 494 drawState->setViewMatrix(GrMatrix::I()); 495 } 496 } else { 497 bounds = path.getBounds(); 498 if (NULL != translate) { 499 bounds.offset(*translate); 500 } 501 } 502 GrDrawTarget::AutoGeometryPush agp(target); 503 target->drawSimpleRect(bounds, NULL, stageMask); 504 } else { 505 if (passCount > 1) { 506 drawState->enableState(GrDrawState::kNoColorWrites_StateBit); 507 } 508 if (indexCnt) { 509 target->drawIndexed(primType, 0, 0, 510 vertexCnt, indexCnt); 511 } else { 512 target->drawNonIndexed(primType, 0, vertexCnt); 513 } 514 } 515 } 516 } 517 return true; 518 } 519 520 bool GrDefaultPathRenderer::canDrawPath(const SkPath& path, 521 GrPathFill fill, 522 const GrDrawTarget* target, 523 bool antiAlias) const { 524 // this class can draw any path with any fill but doesn't do any 525 // anti-aliasing. 526 return !antiAlias; 527 } 528 529 bool GrDefaultPathRenderer::onDrawPath(const SkPath& path, 530 GrPathFill fill, 531 const GrVec* translate, 532 GrDrawTarget* target, 533 GrDrawState::StageMask stageMask, 534 bool antiAlias) { 535 return this->internalDrawPath(path, 536 fill, 537 translate, 538 target, 539 stageMask, 540 false); 541 } 542 543 void GrDefaultPathRenderer::drawPathToStencil(const SkPath& path, 544 GrPathFill fill, 545 GrDrawTarget* target) { 546 GrAssert(kInverseEvenOdd_PathFill != fill); 547 GrAssert(kInverseWinding_PathFill != fill); 548 this->internalDrawPath(path, fill, NULL, target, 0, true); 549 } 550