OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "GrDefaultPathRenderer.h" | 8 #include "GrDefaultPathRenderer.h" |
9 | 9 |
10 #include "GrContext.h" | 10 #include "GrContext.h" |
11 #include "GrDefaultGeoProcFactory.h" | 11 #include "GrDefaultGeoProcFactory.h" |
12 #include "GrDrawState.h" | |
13 #include "GrPathUtils.h" | 12 #include "GrPathUtils.h" |
| 13 #include "GrPipelineBuilder.h" |
14 #include "SkGeometry.h" | 14 #include "SkGeometry.h" |
15 #include "SkString.h" | 15 #include "SkString.h" |
16 #include "SkStrokeRec.h" | 16 #include "SkStrokeRec.h" |
17 #include "SkTLazy.h" | 17 #include "SkTLazy.h" |
18 #include "SkTraceEvent.h" | 18 #include "SkTraceEvent.h" |
19 | 19 |
20 GrDefaultPathRenderer::GrDefaultPathRenderer(bool separateStencilSupport, | 20 GrDefaultPathRenderer::GrDefaultPathRenderer(bool separateStencilSupport, |
21 bool stencilWrapOpsSupport) | 21 bool stencilWrapOpsSupport) |
22 : fSeparateStencil(separateStencilSupport) | 22 : fSeparateStencil(separateStencilSupport) |
23 , fStencilWrapOps(stencilWrapOpsSupport) { | 23 , fStencilWrapOps(stencilWrapOpsSupport) { |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 #else | 158 #else |
159 if (!stroke.isHairlineStyle() && !path.isInverseFillType()) { | 159 if (!stroke.isHairlineStyle() && !path.isInverseFillType()) { |
160 return path.isConvex(); | 160 return path.isConvex(); |
161 } | 161 } |
162 return false; | 162 return false; |
163 #endif | 163 #endif |
164 } | 164 } |
165 | 165 |
166 GrPathRenderer::StencilSupport | 166 GrPathRenderer::StencilSupport |
167 GrDefaultPathRenderer::onGetStencilSupport(const GrDrawTarget*, | 167 GrDefaultPathRenderer::onGetStencilSupport(const GrDrawTarget*, |
168 const GrDrawState*, | 168 const GrPipelineBuilder*, |
169 const SkPath& path, | 169 const SkPath& path, |
170 const SkStrokeRec& stroke) const { | 170 const SkStrokeRec& stroke) const { |
171 if (single_pass_path(path, stroke)) { | 171 if (single_pass_path(path, stroke)) { |
172 return GrPathRenderer::kNoRestriction_StencilSupport; | 172 return GrPathRenderer::kNoRestriction_StencilSupport; |
173 } else { | 173 } else { |
174 return GrPathRenderer::kStencilOnly_StencilSupport; | 174 return GrPathRenderer::kStencilOnly_StencilSupport; |
175 } | 175 } |
176 } | 176 } |
177 | 177 |
178 static inline void append_countour_edge_indices(bool hairLine, | 178 static inline void append_countour_edge_indices(bool hairLine, |
(...skipping 22 matching lines...) Expand all Loading... |
201 GrPathUtils::quadraticPointCount(pts, srcSpaceTol)); | 201 GrPathUtils::quadraticPointCount(pts, srcSpaceTol)); |
202 if (indexed) { | 202 if (indexed) { |
203 for (uint16_t i = 0; i < numPts; ++i) { | 203 for (uint16_t i = 0; i < numPts; ++i) { |
204 append_countour_edge_indices(isHairline, subpathIdxStart, | 204 append_countour_edge_indices(isHairline, subpathIdxStart, |
205 firstQPtIdx + i, idx); | 205 firstQPtIdx + i, idx); |
206 } | 206 } |
207 } | 207 } |
208 } | 208 } |
209 | 209 |
210 bool GrDefaultPathRenderer::createGeom(GrDrawTarget* target, | 210 bool GrDefaultPathRenderer::createGeom(GrDrawTarget* target, |
211 GrDrawState* drawState, | 211 GrPipelineBuilder* pipelineBuilder, |
212 GrPrimitiveType* primType, | 212 GrPrimitiveType* primType, |
213 int* vertexCnt, | 213 int* vertexCnt, |
214 int* indexCnt, | 214 int* indexCnt, |
215 GrDrawTarget::AutoReleaseGeometry* arg, | 215 GrDrawTarget::AutoReleaseGeometry* arg, |
216 const SkPath& path, | 216 const SkPath& path, |
217 const SkStrokeRec& stroke, | 217 const SkStrokeRec& stroke, |
218 SkScalar srcSpaceTol) { | 218 SkScalar srcSpaceTol) { |
219 { | 219 { |
220 SkScalar srcSpaceTolSqd = SkScalarMul(srcSpaceTol, srcSpaceTol); | 220 SkScalar srcSpaceTolSqd = SkScalarMul(srcSpaceTol, srcSpaceTol); |
221 int contourCnt; | 221 int contourCnt; |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
335 SkASSERT((idx - idxBase) <= maxIdxs); | 335 SkASSERT((idx - idxBase) <= maxIdxs); |
336 | 336 |
337 *vertexCnt = static_cast<int>(vert - base); | 337 *vertexCnt = static_cast<int>(vert - base); |
338 *indexCnt = static_cast<int>(idx - idxBase); | 338 *indexCnt = static_cast<int>(idx - idxBase); |
339 | 339 |
340 } | 340 } |
341 return true; | 341 return true; |
342 } | 342 } |
343 | 343 |
344 bool GrDefaultPathRenderer::internalDrawPath(GrDrawTarget* target, | 344 bool GrDefaultPathRenderer::internalDrawPath(GrDrawTarget* target, |
345 GrDrawState* drawState, | 345 GrPipelineBuilder* pipelineBuilder, |
346 GrColor color, | 346 GrColor color, |
347 const SkMatrix& viewMatrix, | 347 const SkMatrix& viewMatrix, |
348 const SkPath& path, | 348 const SkPath& path, |
349 const SkStrokeRec& origStroke, | 349 const SkStrokeRec& origStroke, |
350 bool stencilOnly) { | 350 bool stencilOnly) { |
351 SkTCopyOnFirstWrite<SkStrokeRec> stroke(origStroke); | 351 SkTCopyOnFirstWrite<SkStrokeRec> stroke(origStroke); |
352 | 352 |
353 SkScalar hairlineCoverage; | 353 SkScalar hairlineCoverage; |
354 uint8_t newCoverage = 0xff; | 354 uint8_t newCoverage = 0xff; |
355 if (IsStrokeHairlineOrEquivalent(*stroke, viewMatrix, &hairlineCoverage)) { | 355 if (IsStrokeHairlineOrEquivalent(*stroke, viewMatrix, &hairlineCoverage)) { |
356 newCoverage = SkScalarRoundToInt(hairlineCoverage * 0xff); | 356 newCoverage = SkScalarRoundToInt(hairlineCoverage * 0xff); |
357 | 357 |
358 if (!stroke->isHairlineStyle()) { | 358 if (!stroke->isHairlineStyle()) { |
359 stroke.writable()->setHairlineStyle(); | 359 stroke.writable()->setHairlineStyle(); |
360 } | 360 } |
361 } | 361 } |
362 | 362 |
363 SkScalar tol = SK_Scalar1; | 363 SkScalar tol = SK_Scalar1; |
364 tol = GrPathUtils::scaleToleranceToSrc(tol, viewMatrix, path.getBounds()); | 364 tol = GrPathUtils::scaleToleranceToSrc(tol, viewMatrix, path.getBounds()); |
365 | 365 |
366 int vertexCnt; | 366 int vertexCnt; |
367 int indexCnt; | 367 int indexCnt; |
368 GrPrimitiveType primType; | 368 GrPrimitiveType primType; |
369 GrDrawTarget::AutoReleaseGeometry arg; | 369 GrDrawTarget::AutoReleaseGeometry arg; |
370 if (!this->createGeom(target, | 370 if (!this->createGeom(target, |
371 drawState, | 371 pipelineBuilder, |
372 &primType, | 372 &primType, |
373 &vertexCnt, | 373 &vertexCnt, |
374 &indexCnt, | 374 &indexCnt, |
375 &arg, | 375 &arg, |
376 path, | 376 path, |
377 *stroke, | 377 *stroke, |
378 tol)) { | 378 tol)) { |
379 return false; | 379 return false; |
380 } | 380 } |
381 // Save the current xp on the draw state so we can reset it if needed | 381 // Save the current xp on the draw state so we can reset it if needed |
382 SkAutoTUnref<const GrXPFactory> backupXPFactory(SkRef(drawState->getXPFactor
y())); | 382 SkAutoTUnref<const GrXPFactory> backupXPFactory(SkRef(pipelineBuilder->getXP
Factory())); |
383 // face culling doesn't make sense here | 383 // face culling doesn't make sense here |
384 SkASSERT(GrDrawState::kBoth_DrawFace == drawState->getDrawFace()); | 384 SkASSERT(GrPipelineBuilder::kBoth_DrawFace == pipelineBuilder->getDrawFace()
); |
385 | 385 |
386 int passCount = 0; | 386 int passCount = 0; |
387 const GrStencilSettings* passes[3]; | 387 const GrStencilSettings* passes[3]; |
388 GrDrawState::DrawFace drawFace[3]; | 388 GrPipelineBuilder::DrawFace drawFace[3]; |
389 bool reverse = false; | 389 bool reverse = false; |
390 bool lastPassIsBounds; | 390 bool lastPassIsBounds; |
391 | 391 |
392 if (stroke->isHairlineStyle()) { | 392 if (stroke->isHairlineStyle()) { |
393 passCount = 1; | 393 passCount = 1; |
394 if (stencilOnly) { | 394 if (stencilOnly) { |
395 passes[0] = &gDirectToStencil; | 395 passes[0] = &gDirectToStencil; |
396 } else { | 396 } else { |
397 passes[0] = NULL; | 397 passes[0] = NULL; |
398 } | 398 } |
399 lastPassIsBounds = false; | 399 lastPassIsBounds = false; |
400 drawFace[0] = GrDrawState::kBoth_DrawFace; | 400 drawFace[0] = GrPipelineBuilder::kBoth_DrawFace; |
401 } else { | 401 } else { |
402 if (single_pass_path(path, *stroke)) { | 402 if (single_pass_path(path, *stroke)) { |
403 passCount = 1; | 403 passCount = 1; |
404 if (stencilOnly) { | 404 if (stencilOnly) { |
405 passes[0] = &gDirectToStencil; | 405 passes[0] = &gDirectToStencil; |
406 } else { | 406 } else { |
407 passes[0] = NULL; | 407 passes[0] = NULL; |
408 } | 408 } |
409 drawFace[0] = GrDrawState::kBoth_DrawFace; | 409 drawFace[0] = GrPipelineBuilder::kBoth_DrawFace; |
410 lastPassIsBounds = false; | 410 lastPassIsBounds = false; |
411 } else { | 411 } else { |
412 switch (path.getFillType()) { | 412 switch (path.getFillType()) { |
413 case SkPath::kInverseEvenOdd_FillType: | 413 case SkPath::kInverseEvenOdd_FillType: |
414 reverse = true; | 414 reverse = true; |
415 // fallthrough | 415 // fallthrough |
416 case SkPath::kEvenOdd_FillType: | 416 case SkPath::kEvenOdd_FillType: |
417 passes[0] = &gEOStencilPass; | 417 passes[0] = &gEOStencilPass; |
418 if (stencilOnly) { | 418 if (stencilOnly) { |
419 passCount = 1; | 419 passCount = 1; |
420 lastPassIsBounds = false; | 420 lastPassIsBounds = false; |
421 } else { | 421 } else { |
422 passCount = 2; | 422 passCount = 2; |
423 lastPassIsBounds = true; | 423 lastPassIsBounds = true; |
424 if (reverse) { | 424 if (reverse) { |
425 passes[1] = &gInvEOColorPass; | 425 passes[1] = &gInvEOColorPass; |
426 } else { | 426 } else { |
427 passes[1] = &gEOColorPass; | 427 passes[1] = &gEOColorPass; |
428 } | 428 } |
429 } | 429 } |
430 drawFace[0] = drawFace[1] = GrDrawState::kBoth_DrawFace; | 430 drawFace[0] = drawFace[1] = GrPipelineBuilder::kBoth_DrawFac
e; |
431 break; | 431 break; |
432 | 432 |
433 case SkPath::kInverseWinding_FillType: | 433 case SkPath::kInverseWinding_FillType: |
434 reverse = true; | 434 reverse = true; |
435 // fallthrough | 435 // fallthrough |
436 case SkPath::kWinding_FillType: | 436 case SkPath::kWinding_FillType: |
437 if (fSeparateStencil) { | 437 if (fSeparateStencil) { |
438 if (fStencilWrapOps) { | 438 if (fStencilWrapOps) { |
439 passes[0] = &gWindStencilSeparateWithWrap; | 439 passes[0] = &gWindStencilSeparateWithWrap; |
440 } else { | 440 } else { |
441 passes[0] = &gWindStencilSeparateNoWrap; | 441 passes[0] = &gWindStencilSeparateNoWrap; |
442 } | 442 } |
443 passCount = 2; | 443 passCount = 2; |
444 drawFace[0] = GrDrawState::kBoth_DrawFace; | 444 drawFace[0] = GrPipelineBuilder::kBoth_DrawFace; |
445 } else { | 445 } else { |
446 if (fStencilWrapOps) { | 446 if (fStencilWrapOps) { |
447 passes[0] = &gWindSingleStencilWithWrapInc; | 447 passes[0] = &gWindSingleStencilWithWrapInc; |
448 passes[1] = &gWindSingleStencilWithWrapDec; | 448 passes[1] = &gWindSingleStencilWithWrapDec; |
449 } else { | 449 } else { |
450 passes[0] = &gWindSingleStencilNoWrapInc; | 450 passes[0] = &gWindSingleStencilNoWrapInc; |
451 passes[1] = &gWindSingleStencilNoWrapDec; | 451 passes[1] = &gWindSingleStencilNoWrapDec; |
452 } | 452 } |
453 // which is cw and which is ccw is arbitrary. | 453 // which is cw and which is ccw is arbitrary. |
454 drawFace[0] = GrDrawState::kCW_DrawFace; | 454 drawFace[0] = GrPipelineBuilder::kCW_DrawFace; |
455 drawFace[1] = GrDrawState::kCCW_DrawFace; | 455 drawFace[1] = GrPipelineBuilder::kCCW_DrawFace; |
456 passCount = 3; | 456 passCount = 3; |
457 } | 457 } |
458 if (stencilOnly) { | 458 if (stencilOnly) { |
459 lastPassIsBounds = false; | 459 lastPassIsBounds = false; |
460 --passCount; | 460 --passCount; |
461 } else { | 461 } else { |
462 lastPassIsBounds = true; | 462 lastPassIsBounds = true; |
463 drawFace[passCount-1] = GrDrawState::kBoth_DrawFace; | 463 drawFace[passCount-1] = GrPipelineBuilder::kBoth_DrawFac
e; |
464 if (reverse) { | 464 if (reverse) { |
465 passes[passCount-1] = &gInvWindColorPass; | 465 passes[passCount-1] = &gInvWindColorPass; |
466 } else { | 466 } else { |
467 passes[passCount-1] = &gWindColorPass; | 467 passes[passCount-1] = &gWindColorPass; |
468 } | 468 } |
469 } | 469 } |
470 break; | 470 break; |
471 default: | 471 default: |
472 SkDEBUGFAIL("Unknown path fFill!"); | 472 SkDEBUGFAIL("Unknown path fFill!"); |
473 return false; | 473 return false; |
474 } | 474 } |
475 } | 475 } |
476 } | 476 } |
477 | 477 |
478 SkRect devBounds; | 478 SkRect devBounds; |
479 GetPathDevBounds(path, drawState->getRenderTarget(), viewMatrix, &devBounds)
; | 479 GetPathDevBounds(path, pipelineBuilder->getRenderTarget(), viewMatrix, &devB
ounds); |
480 | 480 |
481 for (int p = 0; p < passCount; ++p) { | 481 for (int p = 0; p < passCount; ++p) { |
482 drawState->setDrawFace(drawFace[p]); | 482 pipelineBuilder->setDrawFace(drawFace[p]); |
483 if (passes[p]) { | 483 if (passes[p]) { |
484 *drawState->stencil() = *passes[p]; | 484 *pipelineBuilder->stencil() = *passes[p]; |
485 } | 485 } |
486 | 486 |
487 if (lastPassIsBounds && (p == passCount-1)) { | 487 if (lastPassIsBounds && (p == passCount-1)) { |
488 // Reset the XP Factory on drawState | 488 // Reset the XP Factory on pipelineBuilder |
489 drawState->setXPFactory(backupXPFactory); | 489 pipelineBuilder->setXPFactory(backupXPFactory); |
490 SkRect bounds; | 490 SkRect bounds; |
491 SkMatrix localMatrix = SkMatrix::I(); | 491 SkMatrix localMatrix = SkMatrix::I(); |
492 if (reverse) { | 492 if (reverse) { |
493 SkASSERT(drawState->getRenderTarget()); | 493 SkASSERT(pipelineBuilder->getRenderTarget()); |
494 // draw over the dev bounds (which will be the whole dst surface
for inv fill). | 494 // draw over the dev bounds (which will be the whole dst surface
for inv fill). |
495 bounds = devBounds; | 495 bounds = devBounds; |
496 SkMatrix vmi; | 496 SkMatrix vmi; |
497 // mapRect through persp matrix may not be correct | 497 // mapRect through persp matrix may not be correct |
498 if (!viewMatrix.hasPerspective() && viewMatrix.invert(&vmi)) { | 498 if (!viewMatrix.hasPerspective() && viewMatrix.invert(&vmi)) { |
499 vmi.mapRect(&bounds); | 499 vmi.mapRect(&bounds); |
500 } else { | 500 } else { |
501 if (!viewMatrix.invert(&localMatrix)) { | 501 if (!viewMatrix.invert(&localMatrix)) { |
502 return false; | 502 return false; |
503 } | 503 } |
504 } | 504 } |
505 } else { | 505 } else { |
506 bounds = path.getBounds(); | 506 bounds = path.getBounds(); |
507 } | 507 } |
508 GrDrawTarget::AutoGeometryPush agp(target); | 508 GrDrawTarget::AutoGeometryPush agp(target); |
509 const SkMatrix& viewM = (reverse && viewMatrix.hasPerspective()) ? S
kMatrix::I() : | 509 const SkMatrix& viewM = (reverse && viewMatrix.hasPerspective()) ? S
kMatrix::I() : |
510 v
iewMatrix; | 510 v
iewMatrix; |
511 target->drawRect(drawState, color, viewM, bounds, NULL, &localMatrix
); | 511 target->drawRect(pipelineBuilder, color, viewM, bounds, NULL, &local
Matrix); |
512 } else { | 512 } else { |
513 if (passCount > 1) { | 513 if (passCount > 1) { |
514 drawState->setDisableColorXPFactory(); | 514 pipelineBuilder->setDisableColorXPFactory(); |
515 } | 515 } |
516 GrDrawState::AutoRestoreEffects are(drawState); | 516 GrPipelineBuilder::AutoRestoreEffects are(pipelineBuilder); |
517 SkAutoTUnref<const GrGeometryProcessor> gp( | 517 SkAutoTUnref<const GrGeometryProcessor> gp( |
518 GrDefaultGeoProcFactory::Create(GrDefaultGeoProcFactory::kPo
sition_GPType, | 518 GrDefaultGeoProcFactory::Create(GrDefaultGeoProcFactory::kPo
sition_GPType, |
519 color, | 519 color, |
520 viewMatrix, | 520 viewMatrix, |
521 SkMatrix::I(), | 521 SkMatrix::I(), |
522 false, | 522 false, |
523 newCoverage)); | 523 newCoverage)); |
524 if (indexCnt) { | 524 if (indexCnt) { |
525 target->drawIndexed(drawState, | 525 target->drawIndexed(pipelineBuilder, |
526 gp, | 526 gp, |
527 primType, | 527 primType, |
528 0, | 528 0, |
529 0, | 529 0, |
530 vertexCnt, | 530 vertexCnt, |
531 indexCnt, | 531 indexCnt, |
532 &devBounds); | 532 &devBounds); |
533 } else { | 533 } else { |
534 target->drawNonIndexed(drawState, gp, primType, 0, vertexCnt, &d
evBounds); | 534 target->drawNonIndexed(pipelineBuilder, gp, primType, 0, vertexC
nt, &devBounds); |
535 } | 535 } |
536 } | 536 } |
537 } | 537 } |
538 return true; | 538 return true; |
539 } | 539 } |
540 | 540 |
541 bool GrDefaultPathRenderer::canDrawPath(const GrDrawTarget* target, | 541 bool GrDefaultPathRenderer::canDrawPath(const GrDrawTarget* target, |
542 const GrDrawState* drawState, | 542 const GrPipelineBuilder* pipelineBuilder
, |
543 const SkMatrix& viewMatrix, | 543 const SkMatrix& viewMatrix, |
544 const SkPath& path, | 544 const SkPath& path, |
545 const SkStrokeRec& stroke, | 545 const SkStrokeRec& stroke, |
546 bool antiAlias) const { | 546 bool antiAlias) const { |
547 // this class can draw any path with any fill but doesn't do any anti-aliasi
ng. | 547 // this class can draw any path with any fill but doesn't do any anti-aliasi
ng. |
548 return !antiAlias && (stroke.isFillStyle() || IsStrokeHairlineOrEquivalent(s
troke, | 548 return !antiAlias && (stroke.isFillStyle() || IsStrokeHairlineOrEquivalent(s
troke, |
549 v
iewMatrix, | 549 v
iewMatrix, |
550 N
ULL)); | 550 N
ULL)); |
551 } | 551 } |
552 | 552 |
553 bool GrDefaultPathRenderer::onDrawPath(GrDrawTarget* target, | 553 bool GrDefaultPathRenderer::onDrawPath(GrDrawTarget* target, |
554 GrDrawState* drawState, | 554 GrPipelineBuilder* pipelineBuilder, |
555 GrColor color, | 555 GrColor color, |
556 const SkMatrix& viewMatrix, | 556 const SkMatrix& viewMatrix, |
557 const SkPath& path, | 557 const SkPath& path, |
558 const SkStrokeRec& stroke, | 558 const SkStrokeRec& stroke, |
559 bool antiAlias) { | 559 bool antiAlias) { |
560 return this->internalDrawPath(target, | 560 return this->internalDrawPath(target, |
561 drawState, | 561 pipelineBuilder, |
562 color, | 562 color, |
563 viewMatrix, | 563 viewMatrix, |
564 path, | 564 path, |
565 stroke, | 565 stroke, |
566 false); | 566 false); |
567 } | 567 } |
568 | 568 |
569 void GrDefaultPathRenderer::onStencilPath(GrDrawTarget* target, | 569 void GrDefaultPathRenderer::onStencilPath(GrDrawTarget* target, |
570 GrDrawState* drawState, | 570 GrPipelineBuilder* pipelineBuilder, |
571 const SkMatrix& viewMatrix, | 571 const SkMatrix& viewMatrix, |
572 const SkPath& path, | 572 const SkPath& path, |
573 const SkStrokeRec& stroke) { | 573 const SkStrokeRec& stroke) { |
574 SkASSERT(SkPath::kInverseEvenOdd_FillType != path.getFillType()); | 574 SkASSERT(SkPath::kInverseEvenOdd_FillType != path.getFillType()); |
575 SkASSERT(SkPath::kInverseWinding_FillType != path.getFillType()); | 575 SkASSERT(SkPath::kInverseWinding_FillType != path.getFillType()); |
576 this->internalDrawPath(target, drawState, GrColor_WHITE, viewMatrix, path, s
troke, true); | 576 this->internalDrawPath(target, pipelineBuilder, GrColor_WHITE, viewMatrix, p
ath, stroke, true); |
577 } | 577 } |
OLD | NEW |