Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 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 "GrClipMaskManager.h" | 8 #include "GrClipMaskManager.h" |
| 9 #include "GrAAConvexPathRenderer.h" | 9 #include "GrAAConvexPathRenderer.h" |
| 10 #include "GrAAHairLinePathRenderer.h" | 10 #include "GrAAHairLinePathRenderer.h" |
| (...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 323 // use both stencil and scissor test to the bounds for the final draw. | 323 // use both stencil and scissor test to the bounds for the final draw. |
| 324 SkIRect scissorSpaceIBounds(clipSpaceIBounds); | 324 SkIRect scissorSpaceIBounds(clipSpaceIBounds); |
| 325 scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset); | 325 scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset); |
| 326 scissorState->set(scissorSpaceIBounds); | 326 scissorState->set(scissorSpaceIBounds); |
| 327 this->setDrawStateStencil(drawState, ars); | 327 this->setDrawStateStencil(drawState, ars); |
| 328 return true; | 328 return true; |
| 329 } | 329 } |
| 330 | 330 |
| 331 namespace { | 331 namespace { |
| 332 //////////////////////////////////////////////////////////////////////////////// | 332 //////////////////////////////////////////////////////////////////////////////// |
| 333 // set up the OpenGL blend function to perform the specified | 333 // Set a coverage drawing XPF on the drawState for the given op and invertCovera ge mode |
| 334 // boolean operation for alpha clip mask creation | 334 void set_coverage_drawing_xpf(SkRegion::Op op, bool invertCoverage, GrDrawState* drawState) { |
| 335 void setup_boolean_blendcoeffs(SkRegion::Op op, GrDrawState* drawState) { | 335 SkASSERT(op <= SkRegion::kLastOp); |
| 336 // TODO: once we have a coverageDrawing XP this will all use that instead of PD | 336 drawState->setCoverageSetOpXPFactory(op, invertCoverage); |
| 337 switch (op) { | |
| 338 case SkRegion::kReplace_Op: | |
| 339 drawState->setPorterDuffXPFactory(kOne_GrBlendCoeff, kZero_GrBlendCo eff); | |
| 340 break; | |
| 341 case SkRegion::kIntersect_Op: | |
| 342 drawState->setPorterDuffXPFactory(kDC_GrBlendCoeff, kZero_GrBlendCoe ff); | |
| 343 break; | |
| 344 case SkRegion::kUnion_Op: | |
| 345 drawState->setPorterDuffXPFactory(kOne_GrBlendCoeff, kISC_GrBlendCoe ff); | |
| 346 break; | |
| 347 case SkRegion::kXOR_Op: | |
| 348 drawState->setPorterDuffXPFactory(kIDC_GrBlendCoeff, kISC_GrBlendCoe ff); | |
| 349 break; | |
| 350 case SkRegion::kDifference_Op: | |
| 351 drawState->setPorterDuffXPFactory(kZero_GrBlendCoeff, kISC_GrBlendCo eff); | |
| 352 break; | |
| 353 case SkRegion::kReverseDifference_Op: | |
| 354 drawState->setPorterDuffXPFactory(kIDC_GrBlendCoeff, kZero_GrBlendCo eff); | |
| 355 break; | |
| 356 default: | |
| 357 SkASSERT(false); | |
| 358 break; | |
| 359 } | |
| 360 } | 337 } |
| 361 } | 338 } |
| 362 | 339 |
| 363 //////////////////////////////////////////////////////////////////////////////// | 340 //////////////////////////////////////////////////////////////////////////////// |
| 364 bool GrClipMaskManager::drawElement(GrDrawState* drawState, | 341 bool GrClipMaskManager::drawElement(GrDrawState* drawState, |
| 365 GrColor color, | 342 GrColor color, |
| 366 GrTexture* target, | 343 GrTexture* target, |
| 367 const SkClipStack::Element* element, | 344 const SkClipStack::Element* element, |
| 368 GrPathRenderer* pr) { | 345 GrPathRenderer* pr) { |
| 369 GrDrawTarget::AutoGeometryPush agp(fClipTarget); | 346 GrDrawTarget::AutoGeometryPush agp(fClipTarget); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 444 void GrClipMaskManager::mergeMask(GrDrawState* drawState, | 421 void GrClipMaskManager::mergeMask(GrDrawState* drawState, |
| 445 GrTexture* dstMask, | 422 GrTexture* dstMask, |
| 446 GrTexture* srcMask, | 423 GrTexture* srcMask, |
| 447 SkRegion::Op op, | 424 SkRegion::Op op, |
| 448 const SkIRect& dstBound, | 425 const SkIRect& dstBound, |
| 449 const SkIRect& srcBound) { | 426 const SkIRect& srcBound) { |
| 450 SkAssertResult(drawState->setIdentityViewMatrix()); | 427 SkAssertResult(drawState->setIdentityViewMatrix()); |
| 451 | 428 |
| 452 drawState->setRenderTarget(dstMask->asRenderTarget()); | 429 drawState->setRenderTarget(dstMask->asRenderTarget()); |
| 453 | 430 |
| 454 setup_boolean_blendcoeffs(op, drawState); | 431 // We want to invert the coverage here |
|
bsalomon
2014/12/16 17:35:56
we do??
egdaniel
2014/12/17 21:12:37
changed to false and changed to use coverageProces
| |
| 432 set_coverage_drawing_xpf(op, true, drawState); | |
| 455 | 433 |
| 456 SkMatrix sampleM; | 434 SkMatrix sampleM; |
| 457 sampleM.setIDiv(srcMask->width(), srcMask->height()); | 435 sampleM.setIDiv(srcMask->width(), srcMask->height()); |
| 458 | 436 |
| 459 drawState->addColorProcessor( | 437 drawState->addColorProcessor( |
| 460 GrTextureDomainEffect::Create(srcMask, | 438 GrTextureDomainEffect::Create(srcMask, |
| 461 sampleM, | 439 sampleM, |
| 462 GrTextureDomain::MakeTexelDomain(srcMask, srcBound), | 440 GrTextureDomain::MakeTexelDomain(srcMask, srcBound), |
| 463 GrTextureDomain::kDecal_Mode, | 441 GrTextureDomain::kDecal_Mode, |
| 464 GrTextureParams::kNone_FilterMode))->unref (); | 442 GrTextureParams::kNone_FilterMode))->unref (); |
| 443 // The color passed in here does not matter since the coverageSetOpXP won't read it. | |
| 465 fClipTarget->drawSimpleRect(drawState, GrColor_WHITE, SkRect::Make(dstBound) ); | 444 fClipTarget->drawSimpleRect(drawState, GrColor_WHITE, SkRect::Make(dstBound) ); |
| 466 } | 445 } |
| 467 | 446 |
| 468 GrTexture* GrClipMaskManager::createTempMask(int width, int height) { | 447 GrTexture* GrClipMaskManager::createTempMask(int width, int height) { |
| 469 GrSurfaceDesc desc; | 448 GrSurfaceDesc desc; |
| 470 desc.fFlags = kRenderTarget_GrSurfaceFlag|kNoStencil_GrSurfaceFlag; | 449 desc.fFlags = kRenderTarget_GrSurfaceFlag|kNoStencil_GrSurfaceFlag; |
| 471 desc.fWidth = width; | 450 desc.fWidth = width; |
| 472 desc.fHeight = height; | 451 desc.fHeight = height; |
| 473 desc.fConfig = kAlpha_8_GrPixelConfig; | 452 desc.fConfig = kAlpha_8_GrPixelConfig; |
| 474 | 453 |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 560 GrDrawTarget::AutoClipRestore acr(fClipTarget, maskSpaceIBounds); | 539 GrDrawTarget::AutoClipRestore acr(fClipTarget, maskSpaceIBounds); |
| 561 SkAutoTUnref<GrTexture> temp; | 540 SkAutoTUnref<GrTexture> temp; |
| 562 | 541 |
| 563 // walk through each clip element and perform its set op | 542 // walk through each clip element and perform its set op |
| 564 for (GrReducedClip::ElementList::Iter iter = elements.headIter(); iter.get() ; iter.next()) { | 543 for (GrReducedClip::ElementList::Iter iter = elements.headIter(); iter.get() ; iter.next()) { |
| 565 const Element* element = iter.get(); | 544 const Element* element = iter.get(); |
| 566 SkRegion::Op op = element->getOp(); | 545 SkRegion::Op op = element->getOp(); |
| 567 bool invert = element->isInverseFilled(); | 546 bool invert = element->isInverseFilled(); |
| 568 if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDiffere nce_Op == op) { | 547 if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDiffere nce_Op == op) { |
| 569 GrDrawState drawState(translate); | 548 GrDrawState drawState(translate); |
| 570 // We're drawing a coverage mask and want coverage to be run through the blend function. | 549 drawState.enableState(GrDrawState::kClip_StateBit); |
| 571 drawState.enableState(GrDrawState::kCoverageDrawing_StateBit | | |
| 572 GrDrawState::kClip_StateBit); | |
| 573 | 550 |
| 574 GrPathRenderer* pr = NULL; | 551 GrPathRenderer* pr = NULL; |
| 575 bool useTemp = !this->canStencilAndDrawElement(&drawState, result, & pr, element); | 552 bool useTemp = !this->canStencilAndDrawElement(&drawState, result, & pr, element); |
| 576 GrTexture* dst; | 553 GrTexture* dst; |
| 577 // This is the bounds of the clip element in the space of the alpha- mask. The temporary | 554 // This is the bounds of the clip element in the space of the alpha- mask. The temporary |
| 578 // mask buffer can be substantially larger than the actually clip st ack element. We | 555 // mask buffer can be substantially larger than the actually clip st ack element. We |
| 579 // touch the minimum number of pixels necessary and use decal mode t o combine it with | 556 // touch the minimum number of pixels necessary and use decal mode t o combine it with |
| 580 // the accumulator. | 557 // the accumulator. |
| 581 SkIRect maskSpaceElementIBounds; | 558 SkIRect maskSpaceElementIBounds; |
| 582 | 559 |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 596 fAACache.reset(); | 573 fAACache.reset(); |
| 597 return NULL; | 574 return NULL; |
| 598 } | 575 } |
| 599 } | 576 } |
| 600 dst = temp; | 577 dst = temp; |
| 601 // clear the temp target and set blend to replace | 578 // clear the temp target and set blend to replace |
| 602 fClipTarget->clear(&maskSpaceElementIBounds, | 579 fClipTarget->clear(&maskSpaceElementIBounds, |
| 603 invert ? 0xffffffff : 0x00000000, | 580 invert ? 0xffffffff : 0x00000000, |
| 604 true, | 581 true, |
| 605 dst->asRenderTarget()); | 582 dst->asRenderTarget()); |
| 606 setup_boolean_blendcoeffs(SkRegion::kReplace_Op, &drawState); | 583 set_coverage_drawing_xpf(SkRegion::kReplace_Op, invert, &drawSta te); |
| 607 } else { | 584 } else { |
| 608 // draw directly into the result with the stencil set to make th e pixels affected | 585 // draw directly into the result with the stencil set to make th e pixels affected |
| 609 // by the clip shape be non-zero. | 586 // by the clip shape be non-zero. |
| 610 dst = result; | 587 dst = result; |
| 611 GR_STATIC_CONST_SAME_STENCIL(kStencilInElement, | 588 GR_STATIC_CONST_SAME_STENCIL(kStencilInElement, |
| 612 kReplace_StencilOp, | 589 kReplace_StencilOp, |
| 613 kReplace_StencilOp, | 590 kReplace_StencilOp, |
| 614 kAlways_StencilFunc, | 591 kAlways_StencilFunc, |
| 615 0xffff, | 592 0xffff, |
| 616 0xffff, | 593 0xffff, |
| 617 0xffff); | 594 0xffff); |
| 618 drawState.setStencil(kStencilInElement); | 595 drawState.setStencil(kStencilInElement); |
| 619 setup_boolean_blendcoeffs(op, &drawState); | 596 set_coverage_drawing_xpf(op, invert, &drawState); |
| 620 } | 597 } |
| 621 | 598 |
| 622 // We have to backup the drawstate because the drawElement call may call into | 599 // The color passed in here does not matter since the coverageSetOpX P won't read it. |
| 623 // renderers which consume it. | 600 if (!this->drawElement(&drawState, GrColor_WHITE, dst, element, pr)) { |
|
bsalomon
2014/12/16 17:35:56
Can drawElement just not take a color then?
egdaniel
2014/12/17 21:12:37
Done.
| |
| 624 GrDrawState backupDrawState(drawState); | |
| 625 | |
| 626 if (!this->drawElement(&drawState, invert ? GrColor_TRANS_BLACK : | |
| 627 GrColor_WHITE, dst, elem ent, pr)) { | |
| 628 fAACache.reset(); | 601 fAACache.reset(); |
| 629 return NULL; | 602 return NULL; |
| 630 } | 603 } |
| 631 | 604 |
| 605 // We have to make a new drawstate because the drawElement call may call into | |
|
bsalomon
2014/12/16 17:35:56
I'm not sure this comment adds much value. A new d
egdaniel
2014/12/17 21:12:37
removed
| |
| 606 // renderers which consume it. We also need to use a different cover age drawing xp which | |
| 607 // inverts the coverage. | |
| 608 GrDrawState backgroundDrawState(translate); | |
| 609 backgroundDrawState.enableState(GrDrawState::kClip_StateBit); | |
| 610 backgroundDrawState.setRenderTarget(result->asRenderTarget()); | |
| 611 | |
| 632 if (useTemp) { | 612 if (useTemp) { |
| 633 // Now draw into the accumulator using the real operation and th e temp buffer as a | 613 // Now draw into the accumulator using the real operation and th e temp buffer as a |
| 634 // texture | 614 // texture |
| 635 this->mergeMask(&backupDrawState, | 615 this->mergeMask(&backgroundDrawState, |
| 636 result, | 616 result, |
| 637 temp, | 617 temp, |
| 638 op, | 618 op, |
| 639 maskSpaceIBounds, | 619 maskSpaceIBounds, |
| 640 maskSpaceElementIBounds); | 620 maskSpaceElementIBounds); |
| 641 } else { | 621 } else { |
| 622 set_coverage_drawing_xpf(op, !invert, &backgroundDrawState); | |
| 642 // Draw to the exterior pixels (those with a zero stencil value) . | 623 // Draw to the exterior pixels (those with a zero stencil value) . |
| 643 GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement, | 624 GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement, |
| 644 kZero_StencilOp, | 625 kZero_StencilOp, |
| 645 kZero_StencilOp, | 626 kZero_StencilOp, |
| 646 kEqual_StencilFunc, | 627 kEqual_StencilFunc, |
| 647 0xffff, | 628 0xffff, |
| 648 0x0000, | 629 0x0000, |
| 649 0xffff); | 630 0xffff); |
| 650 backupDrawState.setStencil(kDrawOutsideElement); | 631 backgroundDrawState.setStencil(kDrawOutsideElement); |
| 651 fClipTarget->drawSimpleRect(&backupDrawState, | 632 // The color passed in here does not matter since the coverageSe tOpXP won't read it. |
| 652 invert ? GrColor_WHITE : GrColor_TRA NS_BLACK, | 633 fClipTarget->drawSimpleRect(&backgroundDrawState, GrColor_WHITE, clipSpaceIBounds); |
| 653 clipSpaceIBounds); | |
| 654 } | 634 } |
| 655 } else { | 635 } else { |
| 656 GrDrawState drawState(translate); | 636 GrDrawState drawState(translate); |
| 657 drawState.enableState(GrDrawState::kCoverageDrawing_StateBit | | 637 drawState.enableState(GrDrawState::kClip_StateBit); |
| 658 GrDrawState::kClip_StateBit); | |
| 659 | 638 |
| 660 // all the remaining ops can just be directly draw into the accumula tion buffer | 639 // all the remaining ops can just be directly draw into the accumula tion buffer |
| 661 setup_boolean_blendcoeffs(op, &drawState); | 640 set_coverage_drawing_xpf(op, false, &drawState); |
| 641 // The color passed in here does not matter since the coverageSetOpX P won't read it. | |
| 662 this->drawElement(&drawState, GrColor_WHITE, result, element); | 642 this->drawElement(&drawState, GrColor_WHITE, result, element); |
| 663 } | 643 } |
| 664 } | 644 } |
| 665 | 645 |
| 666 fCurrClipMaskType = kAlpha_ClipMaskType; | 646 fCurrClipMaskType = kAlpha_ClipMaskType; |
| 667 return result; | 647 return result; |
| 668 } | 648 } |
| 669 | 649 |
| 670 //////////////////////////////////////////////////////////////////////////////// | 650 //////////////////////////////////////////////////////////////////////////////// |
| 671 // Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device | 651 // Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device |
| (...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1081 } | 1061 } |
| 1082 | 1062 |
| 1083 void GrClipMaskManager::adjustPathStencilParams(const GrStencilBuffer* stencilBu ffer, | 1063 void GrClipMaskManager::adjustPathStencilParams(const GrStencilBuffer* stencilBu ffer, |
| 1084 GrStencilSettings* settings) { | 1064 GrStencilSettings* settings) { |
| 1085 // TODO: dynamically attach a stencil buffer | 1065 // TODO: dynamically attach a stencil buffer |
| 1086 if (stencilBuffer) { | 1066 if (stencilBuffer) { |
| 1087 int stencilBits = stencilBuffer->bits(); | 1067 int stencilBits = stencilBuffer->bits(); |
| 1088 this->adjustStencilParams(settings, fClipMode, stencilBits); | 1068 this->adjustStencilParams(settings, fClipMode, stencilBits); |
| 1089 } | 1069 } |
| 1090 } | 1070 } |
| OLD | NEW |