| 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, | |
| 366 GrTexture* target, | 342 GrTexture* target, |
| 367 const SkClipStack::Element* element, | 343 const SkClipStack::Element* element, |
| 368 GrPathRenderer* pr) { | 344 GrPathRenderer* pr) { |
| 369 GrDrawTarget::AutoGeometryPush agp(fClipTarget); | 345 GrDrawTarget::AutoGeometryPush agp(fClipTarget); |
| 370 | 346 |
| 371 drawState->setRenderTarget(target->asRenderTarget()); | 347 drawState->setRenderTarget(target->asRenderTarget()); |
| 372 | 348 |
| 349 // The color we use to draw does not matter since we will always be using a
GrCoverageSetOpXP |
| 350 // which ignores color. |
| 351 GrColor color = GrColor_WHITE; |
| 352 |
| 373 // TODO: Draw rrects directly here. | 353 // TODO: Draw rrects directly here. |
| 374 switch (element->getType()) { | 354 switch (element->getType()) { |
| 375 case Element::kEmpty_Type: | 355 case Element::kEmpty_Type: |
| 376 SkDEBUGFAIL("Should never get here with an empty element."); | 356 SkDEBUGFAIL("Should never get here with an empty element."); |
| 377 break; | 357 break; |
| 378 case Element::kRect_Type: | 358 case Element::kRect_Type: |
| 379 // TODO: Do rects directly to the accumulator using a aa-rect GrProc
essor that covers | 359 // TODO: Do rects directly to the accumulator using a aa-rect GrProc
essor that covers |
| 380 // the entire mask bounds and writes 0 outside the rect. | 360 // the entire mask bounds and writes 0 outside the rect. |
| 381 if (element->isAA()) { | 361 if (element->isAA()) { |
| 382 this->getContext()->getAARectRenderer()->fillAARect(fClipTarget, | 362 this->getContext()->getAARectRenderer()->fillAARect(fClipTarget, |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 444 void GrClipMaskManager::mergeMask(GrDrawState* drawState, | 424 void GrClipMaskManager::mergeMask(GrDrawState* drawState, |
| 445 GrTexture* dstMask, | 425 GrTexture* dstMask, |
| 446 GrTexture* srcMask, | 426 GrTexture* srcMask, |
| 447 SkRegion::Op op, | 427 SkRegion::Op op, |
| 448 const SkIRect& dstBound, | 428 const SkIRect& dstBound, |
| 449 const SkIRect& srcBound) { | 429 const SkIRect& srcBound) { |
| 450 SkAssertResult(drawState->setIdentityViewMatrix()); | 430 SkAssertResult(drawState->setIdentityViewMatrix()); |
| 451 | 431 |
| 452 drawState->setRenderTarget(dstMask->asRenderTarget()); | 432 drawState->setRenderTarget(dstMask->asRenderTarget()); |
| 453 | 433 |
| 454 setup_boolean_blendcoeffs(op, drawState); | 434 // We want to invert the coverage here |
| 435 set_coverage_drawing_xpf(op, false, drawState); |
| 455 | 436 |
| 456 SkMatrix sampleM; | 437 SkMatrix sampleM; |
| 457 sampleM.setIDiv(srcMask->width(), srcMask->height()); | 438 sampleM.setIDiv(srcMask->width(), srcMask->height()); |
| 458 | 439 |
| 459 drawState->addColorProcessor( | 440 drawState->addCoverageProcessor( |
| 460 GrTextureDomainEffect::Create(srcMask, | 441 GrTextureDomainEffect::Create(srcMask, |
| 461 sampleM, | 442 sampleM, |
| 462 GrTextureDomain::MakeTexelDomain(srcMask,
srcBound), | 443 GrTextureDomain::MakeTexelDomain(srcMask,
srcBound), |
| 463 GrTextureDomain::kDecal_Mode, | 444 GrTextureDomain::kDecal_Mode, |
| 464 GrTextureParams::kNone_FilterMode))->unref
(); | 445 GrTextureParams::kNone_FilterMode))->unref
(); |
| 446 // The color passed in here does not matter since the coverageSetOpXP won't
read it. |
| 465 fClipTarget->drawSimpleRect(drawState, GrColor_WHITE, SkRect::Make(dstBound)
); | 447 fClipTarget->drawSimpleRect(drawState, GrColor_WHITE, SkRect::Make(dstBound)
); |
| 466 } | 448 } |
| 467 | 449 |
| 468 GrTexture* GrClipMaskManager::createTempMask(int width, int height) { | 450 GrTexture* GrClipMaskManager::createTempMask(int width, int height) { |
| 469 GrSurfaceDesc desc; | 451 GrSurfaceDesc desc; |
| 470 desc.fFlags = kRenderTarget_GrSurfaceFlag|kNoStencil_GrSurfaceFlag; | 452 desc.fFlags = kRenderTarget_GrSurfaceFlag|kNoStencil_GrSurfaceFlag; |
| 471 desc.fWidth = width; | 453 desc.fWidth = width; |
| 472 desc.fHeight = height; | 454 desc.fHeight = height; |
| 473 desc.fConfig = kAlpha_8_GrPixelConfig; | 455 desc.fConfig = kAlpha_8_GrPixelConfig; |
| 474 | 456 |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 560 GrDrawTarget::AutoClipRestore acr(fClipTarget, maskSpaceIBounds); | 542 GrDrawTarget::AutoClipRestore acr(fClipTarget, maskSpaceIBounds); |
| 561 SkAutoTUnref<GrTexture> temp; | 543 SkAutoTUnref<GrTexture> temp; |
| 562 | 544 |
| 563 // walk through each clip element and perform its set op | 545 // walk through each clip element and perform its set op |
| 564 for (GrReducedClip::ElementList::Iter iter = elements.headIter(); iter.get()
; iter.next()) { | 546 for (GrReducedClip::ElementList::Iter iter = elements.headIter(); iter.get()
; iter.next()) { |
| 565 const Element* element = iter.get(); | 547 const Element* element = iter.get(); |
| 566 SkRegion::Op op = element->getOp(); | 548 SkRegion::Op op = element->getOp(); |
| 567 bool invert = element->isInverseFilled(); | 549 bool invert = element->isInverseFilled(); |
| 568 if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDiffere
nce_Op == op) { | 550 if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDiffere
nce_Op == op) { |
| 569 GrDrawState drawState(translate); | 551 GrDrawState drawState(translate); |
| 570 // We're drawing a coverage mask and want coverage to be run through
the blend function. | 552 drawState.enableState(GrDrawState::kClip_StateBit); |
| 571 drawState.enableState(GrDrawState::kCoverageDrawing_StateBit | | |
| 572 GrDrawState::kClip_StateBit); | |
| 573 | 553 |
| 574 GrPathRenderer* pr = NULL; | 554 GrPathRenderer* pr = NULL; |
| 575 bool useTemp = !this->canStencilAndDrawElement(&drawState, result, &
pr, element); | 555 bool useTemp = !this->canStencilAndDrawElement(&drawState, result, &
pr, element); |
| 576 GrTexture* dst; | 556 GrTexture* dst; |
| 577 // This is the bounds of the clip element in the space of the alpha-
mask. The temporary | 557 // 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 | 558 // 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 | 559 // touch the minimum number of pixels necessary and use decal mode t
o combine it with |
| 580 // the accumulator. | 560 // the accumulator. |
| 581 SkIRect maskSpaceElementIBounds; | 561 SkIRect maskSpaceElementIBounds; |
| 582 | 562 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 596 fAACache.reset(); | 576 fAACache.reset(); |
| 597 return NULL; | 577 return NULL; |
| 598 } | 578 } |
| 599 } | 579 } |
| 600 dst = temp; | 580 dst = temp; |
| 601 // clear the temp target and set blend to replace | 581 // clear the temp target and set blend to replace |
| 602 fClipTarget->clear(&maskSpaceElementIBounds, | 582 fClipTarget->clear(&maskSpaceElementIBounds, |
| 603 invert ? 0xffffffff : 0x00000000, | 583 invert ? 0xffffffff : 0x00000000, |
| 604 true, | 584 true, |
| 605 dst->asRenderTarget()); | 585 dst->asRenderTarget()); |
| 606 setup_boolean_blendcoeffs(SkRegion::kReplace_Op, &drawState); | 586 set_coverage_drawing_xpf(SkRegion::kReplace_Op, invert, &drawSta
te); |
| 607 } else { | 587 } else { |
| 608 // draw directly into the result with the stencil set to make th
e pixels affected | 588 // draw directly into the result with the stencil set to make th
e pixels affected |
| 609 // by the clip shape be non-zero. | 589 // by the clip shape be non-zero. |
| 610 dst = result; | 590 dst = result; |
| 611 GR_STATIC_CONST_SAME_STENCIL(kStencilInElement, | 591 GR_STATIC_CONST_SAME_STENCIL(kStencilInElement, |
| 612 kReplace_StencilOp, | 592 kReplace_StencilOp, |
| 613 kReplace_StencilOp, | 593 kReplace_StencilOp, |
| 614 kAlways_StencilFunc, | 594 kAlways_StencilFunc, |
| 615 0xffff, | 595 0xffff, |
| 616 0xffff, | 596 0xffff, |
| 617 0xffff); | 597 0xffff); |
| 618 drawState.setStencil(kStencilInElement); | 598 drawState.setStencil(kStencilInElement); |
| 619 setup_boolean_blendcoeffs(op, &drawState); | 599 set_coverage_drawing_xpf(op, invert, &drawState); |
| 620 } | 600 } |
| 621 | 601 |
| 622 // We have to backup the drawstate because the drawElement call may
call into | 602 if (!this->drawElement(&drawState, dst, element, pr)) { |
| 623 // renderers which consume it. | |
| 624 GrDrawState backupDrawState(drawState); | |
| 625 | |
| 626 if (!this->drawElement(&drawState, invert ? GrColor_TRANS_BLACK : | |
| 627 GrColor_WHITE, dst, elem
ent, pr)) { | |
| 628 fAACache.reset(); | 603 fAACache.reset(); |
| 629 return NULL; | 604 return NULL; |
| 630 } | 605 } |
| 631 | 606 |
| 607 GrDrawState backgroundDrawState(translate); |
| 608 backgroundDrawState.enableState(GrDrawState::kClip_StateBit); |
| 609 backgroundDrawState.setRenderTarget(result->asRenderTarget()); |
| 610 |
| 632 if (useTemp) { | 611 if (useTemp) { |
| 633 // Now draw into the accumulator using the real operation and th
e temp buffer as a | 612 // Now draw into the accumulator using the real operation and th
e temp buffer as a |
| 634 // texture | 613 // texture |
| 635 this->mergeMask(&backupDrawState, | 614 this->mergeMask(&backgroundDrawState, |
| 636 result, | 615 result, |
| 637 temp, | 616 temp, |
| 638 op, | 617 op, |
| 639 maskSpaceIBounds, | 618 maskSpaceIBounds, |
| 640 maskSpaceElementIBounds); | 619 maskSpaceElementIBounds); |
| 641 } else { | 620 } else { |
| 621 set_coverage_drawing_xpf(op, !invert, &backgroundDrawState); |
| 642 // Draw to the exterior pixels (those with a zero stencil value)
. | 622 // Draw to the exterior pixels (those with a zero stencil value)
. |
| 643 GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement, | 623 GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement, |
| 644 kZero_StencilOp, | 624 kZero_StencilOp, |
| 645 kZero_StencilOp, | 625 kZero_StencilOp, |
| 646 kEqual_StencilFunc, | 626 kEqual_StencilFunc, |
| 647 0xffff, | 627 0xffff, |
| 648 0x0000, | 628 0x0000, |
| 649 0xffff); | 629 0xffff); |
| 650 backupDrawState.setStencil(kDrawOutsideElement); | 630 backgroundDrawState.setStencil(kDrawOutsideElement); |
| 651 fClipTarget->drawSimpleRect(&backupDrawState, | 631 // The color passed in here does not matter since the coverageSe
tOpXP won't read it. |
| 652 invert ? GrColor_WHITE : GrColor_TRA
NS_BLACK, | 632 fClipTarget->drawSimpleRect(&backgroundDrawState, GrColor_WHITE,
clipSpaceIBounds); |
| 653 clipSpaceIBounds); | |
| 654 } | 633 } |
| 655 } else { | 634 } else { |
| 656 GrDrawState drawState(translate); | 635 GrDrawState drawState(translate); |
| 657 drawState.enableState(GrDrawState::kCoverageDrawing_StateBit | | 636 drawState.enableState(GrDrawState::kClip_StateBit); |
| 658 GrDrawState::kClip_StateBit); | |
| 659 | 637 |
| 660 // all the remaining ops can just be directly draw into the accumula
tion buffer | 638 // all the remaining ops can just be directly draw into the accumula
tion buffer |
| 661 setup_boolean_blendcoeffs(op, &drawState); | 639 set_coverage_drawing_xpf(op, false, &drawState); |
| 662 this->drawElement(&drawState, GrColor_WHITE, result, element); | 640 // The color passed in here does not matter since the coverageSetOpX
P won't read it. |
| 641 this->drawElement(&drawState, result, element); |
| 663 } | 642 } |
| 664 } | 643 } |
| 665 | 644 |
| 666 fCurrClipMaskType = kAlpha_ClipMaskType; | 645 fCurrClipMaskType = kAlpha_ClipMaskType; |
| 667 return result; | 646 return result; |
| 668 } | 647 } |
| 669 | 648 |
| 670 //////////////////////////////////////////////////////////////////////////////// | 649 //////////////////////////////////////////////////////////////////////////////// |
| 671 // Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device | 650 // Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device |
| 672 // (as opposed to canvas) coordinates | 651 // (as opposed to canvas) coordinates |
| (...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1081 } | 1060 } |
| 1082 | 1061 |
| 1083 void GrClipMaskManager::adjustPathStencilParams(const GrStencilBuffer* stencilBu
ffer, | 1062 void GrClipMaskManager::adjustPathStencilParams(const GrStencilBuffer* stencilBu
ffer, |
| 1084 GrStencilSettings* settings) { | 1063 GrStencilSettings* settings) { |
| 1085 // TODO: dynamically attach a stencil buffer | 1064 // TODO: dynamically attach a stencil buffer |
| 1086 if (stencilBuffer) { | 1065 if (stencilBuffer) { |
| 1087 int stencilBits = stencilBuffer->bits(); | 1066 int stencilBits = stencilBuffer->bits(); |
| 1088 this->adjustStencilParams(settings, fClipMode, stencilBits); | 1067 this->adjustStencilParams(settings, fClipMode, stencilBits); |
| 1089 } | 1068 } |
| 1090 } | 1069 } |
| OLD | NEW |