| 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 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 353 break; | 353 break; |
| 354 default: | 354 default: |
| 355 SkASSERT(false); | 355 SkASSERT(false); |
| 356 break; | 356 break; |
| 357 } | 357 } |
| 358 } | 358 } |
| 359 } | 359 } |
| 360 | 360 |
| 361 //////////////////////////////////////////////////////////////////////////////// | 361 //////////////////////////////////////////////////////////////////////////////// |
| 362 bool GrClipMaskManager::drawElement(GrDrawState* drawState, | 362 bool GrClipMaskManager::drawElement(GrDrawState* drawState, |
| 363 GrColor color, |
| 363 GrTexture* target, | 364 GrTexture* target, |
| 364 const SkClipStack::Element* element, | 365 const SkClipStack::Element* element, |
| 365 GrPathRenderer* pr) { | 366 GrPathRenderer* pr) { |
| 366 GrDrawTarget::AutoGeometryPush agp(fClipTarget); | 367 GrDrawTarget::AutoGeometryPush agp(fClipTarget); |
| 367 | 368 |
| 368 drawState->setRenderTarget(target->asRenderTarget()); | 369 drawState->setRenderTarget(target->asRenderTarget()); |
| 369 | 370 |
| 370 // TODO: Draw rrects directly here. | 371 // TODO: Draw rrects directly here. |
| 371 switch (element->getType()) { | 372 switch (element->getType()) { |
| 372 case Element::kEmpty_Type: | 373 case Element::kEmpty_Type: |
| 373 SkDEBUGFAIL("Should never get here with an empty element."); | 374 SkDEBUGFAIL("Should never get here with an empty element."); |
| 374 break; | 375 break; |
| 375 case Element::kRect_Type: | 376 case Element::kRect_Type: |
| 376 // TODO: Do rects directly to the accumulator using a aa-rect GrProc
essor that covers | 377 // TODO: Do rects directly to the accumulator using a aa-rect GrProc
essor that covers |
| 377 // the entire mask bounds and writes 0 outside the rect. | 378 // the entire mask bounds and writes 0 outside the rect. |
| 378 if (element->isAA()) { | 379 if (element->isAA()) { |
| 379 this->getContext()->getAARectRenderer()->fillAARect(fClipTarget, | 380 this->getContext()->getAARectRenderer()->fillAARect(fClipTarget, |
| 380 drawState, | 381 drawState, |
| 382 color, |
| 381 element->get
Rect(), | 383 element->get
Rect(), |
| 382 SkMatrix::I(
), | 384 SkMatrix::I(
), |
| 383 element->get
Rect()); | 385 element->get
Rect()); |
| 384 } else { | 386 } else { |
| 385 fClipTarget->drawSimpleRect(drawState, element->getRect()); | 387 fClipTarget->drawSimpleRect(drawState, color, element->getRect()
); |
| 386 } | 388 } |
| 387 return true; | 389 return true; |
| 388 default: { | 390 default: { |
| 389 SkPath path; | 391 SkPath path; |
| 390 element->asPath(&path); | 392 element->asPath(&path); |
| 391 path.setIsVolatile(true); | 393 path.setIsVolatile(true); |
| 392 if (path.isInverseFillType()) { | 394 if (path.isInverseFillType()) { |
| 393 path.toggleInverseFillType(); | 395 path.toggleInverseFillType(); |
| 394 } | 396 } |
| 395 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); | 397 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); |
| 396 if (NULL == pr) { | 398 if (NULL == pr) { |
| 397 GrPathRendererChain::DrawType type; | 399 GrPathRendererChain::DrawType type; |
| 398 type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_Dr
awType : | 400 type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_Dr
awType : |
| 399 GrPathRendererChain::kColor_DrawType; | 401 GrPathRendererChain::kColor_DrawType; |
| 400 pr = this->getContext()->getPathRenderer(fClipTarget, drawState,
path, stroke, | 402 pr = this->getContext()->getPathRenderer(fClipTarget, drawState,
path, stroke, |
| 401 false, type); | 403 false, type); |
| 402 } | 404 } |
| 403 if (NULL == pr) { | 405 if (NULL == pr) { |
| 404 return false; | 406 return false; |
| 405 } | 407 } |
| 406 | 408 |
| 407 pr->drawPath(fClipTarget, drawState, path, stroke, element->isAA()); | 409 pr->drawPath(fClipTarget, drawState, color, path, stroke, element->i
sAA()); |
| 408 break; | 410 break; |
| 409 } | 411 } |
| 410 } | 412 } |
| 411 return true; | 413 return true; |
| 412 } | 414 } |
| 413 | 415 |
| 414 bool GrClipMaskManager::canStencilAndDrawElement(GrDrawState* drawState, | 416 bool GrClipMaskManager::canStencilAndDrawElement(GrDrawState* drawState, |
| 415 GrTexture* target, | 417 GrTexture* target, |
| 416 GrPathRenderer** pr, | 418 GrPathRenderer** pr, |
| 417 const SkClipStack::Element* ele
ment) { | 419 const SkClipStack::Element* ele
ment) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 451 | 453 |
| 452 SkMatrix sampleM; | 454 SkMatrix sampleM; |
| 453 sampleM.setIDiv(srcMask->width(), srcMask->height()); | 455 sampleM.setIDiv(srcMask->width(), srcMask->height()); |
| 454 | 456 |
| 455 drawState->addColorProcessor( | 457 drawState->addColorProcessor( |
| 456 GrTextureDomainEffect::Create(srcMask, | 458 GrTextureDomainEffect::Create(srcMask, |
| 457 sampleM, | 459 sampleM, |
| 458 GrTextureDomain::MakeTexelDomain(srcMask,
srcBound), | 460 GrTextureDomain::MakeTexelDomain(srcMask,
srcBound), |
| 459 GrTextureDomain::kDecal_Mode, | 461 GrTextureDomain::kDecal_Mode, |
| 460 GrTextureParams::kNone_FilterMode))->unref
(); | 462 GrTextureParams::kNone_FilterMode))->unref
(); |
| 461 fClipTarget->drawSimpleRect(drawState, SkRect::Make(dstBound)); | 463 fClipTarget->drawSimpleRect(drawState, GrColor_WHITE, SkRect::Make(dstBound)
); |
| 462 } | 464 } |
| 463 | 465 |
| 464 GrTexture* GrClipMaskManager::createTempMask(int width, int height) { | 466 GrTexture* GrClipMaskManager::createTempMask(int width, int height) { |
| 465 GrSurfaceDesc desc; | 467 GrSurfaceDesc desc; |
| 466 desc.fFlags = kRenderTarget_GrSurfaceFlag|kNoStencil_GrSurfaceFlag; | 468 desc.fFlags = kRenderTarget_GrSurfaceFlag|kNoStencil_GrSurfaceFlag; |
| 467 desc.fWidth = width; | 469 desc.fWidth = width; |
| 468 desc.fHeight = height; | 470 desc.fHeight = height; |
| 469 desc.fConfig = kAlpha_8_GrPixelConfig; | 471 desc.fConfig = kAlpha_8_GrPixelConfig; |
| 470 | 472 |
| 471 return this->getContext()->refScratchTexture(desc, GrContext::kApprox_Scratc
hTexMatch); | 473 return this->getContext()->refScratchTexture(desc, GrContext::kApprox_Scratc
hTexMatch); |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 608 kReplace_StencilOp, | 610 kReplace_StencilOp, |
| 609 kReplace_StencilOp, | 611 kReplace_StencilOp, |
| 610 kAlways_StencilFunc, | 612 kAlways_StencilFunc, |
| 611 0xffff, | 613 0xffff, |
| 612 0xffff, | 614 0xffff, |
| 613 0xffff); | 615 0xffff); |
| 614 drawState.setStencil(kStencilInElement); | 616 drawState.setStencil(kStencilInElement); |
| 615 setup_boolean_blendcoeffs(op, &drawState); | 617 setup_boolean_blendcoeffs(op, &drawState); |
| 616 } | 618 } |
| 617 | 619 |
| 618 drawState.setAlpha(invert ? 0x00 : 0xff); | |
| 619 | |
| 620 // We have to backup the drawstate because the drawElement call may
call into | 620 // We have to backup the drawstate because the drawElement call may
call into |
| 621 // renderers which consume it. | 621 // renderers which consume it. |
| 622 GrDrawState backupDrawState(drawState); | 622 GrDrawState backupDrawState(drawState); |
| 623 | 623 |
| 624 if (!this->drawElement(&drawState, dst, element, pr)) { | 624 if (!this->drawElement(&drawState, invert ? GrColor_BLACK : GrColor_
WHITE, dst, element, |
| 625 pr)) { |
| 625 fAACache.reset(); | 626 fAACache.reset(); |
| 626 return NULL; | 627 return NULL; |
| 627 } | 628 } |
| 628 | 629 |
| 629 if (useTemp) { | 630 if (useTemp) { |
| 630 // Now draw into the accumulator using the real operation and th
e temp buffer as a | 631 // Now draw into the accumulator using the real operation and th
e temp buffer as a |
| 631 // texture | 632 // texture |
| 632 this->mergeMask(&backupDrawState, | 633 this->mergeMask(&backupDrawState, |
| 633 result, | 634 result, |
| 634 temp, | 635 temp, |
| 635 op, | 636 op, |
| 636 maskSpaceIBounds, | 637 maskSpaceIBounds, |
| 637 maskSpaceElementIBounds); | 638 maskSpaceElementIBounds); |
| 638 } else { | 639 } else { |
| 639 // Draw to the exterior pixels (those with a zero stencil value)
. | 640 // Draw to the exterior pixels (those with a zero stencil value)
. |
| 640 backupDrawState.setAlpha(invert ? 0xff : 0x00); | |
| 641 GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement, | 641 GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement, |
| 642 kZero_StencilOp, | 642 kZero_StencilOp, |
| 643 kZero_StencilOp, | 643 kZero_StencilOp, |
| 644 kEqual_StencilFunc, | 644 kEqual_StencilFunc, |
| 645 0xffff, | 645 0xffff, |
| 646 0x0000, | 646 0x0000, |
| 647 0xffff); | 647 0xffff); |
| 648 backupDrawState.setStencil(kDrawOutsideElement); | 648 backupDrawState.setStencil(kDrawOutsideElement); |
| 649 fClipTarget->drawSimpleRect(&backupDrawState, clipSpaceIBounds); | 649 fClipTarget->drawSimpleRect(&backupDrawState, |
| 650 invert ? GrColor_WHITE : GrColor_BLA
CK, |
| 651 clipSpaceIBounds); |
| 650 } | 652 } |
| 651 } else { | 653 } else { |
| 652 GrDrawState drawState(translate); | 654 GrDrawState drawState(translate); |
| 653 drawState.enableState(GrDrawState::kCoverageDrawing_StateBit | | 655 drawState.enableState(GrDrawState::kCoverageDrawing_StateBit | |
| 654 GrDrawState::kClip_StateBit); | 656 GrDrawState::kClip_StateBit); |
| 655 | 657 |
| 656 // all the remaining ops can just be directly draw into the accumula
tion buffer | 658 // all the remaining ops can just be directly draw into the accumula
tion buffer |
| 657 drawState.setAlpha(0xff); | |
| 658 setup_boolean_blendcoeffs(op, &drawState); | 659 setup_boolean_blendcoeffs(op, &drawState); |
| 659 this->drawElement(&drawState, result, element); | 660 this->drawElement(&drawState, GrColor_WHITE, result, element); |
| 660 } | 661 } |
| 661 } | 662 } |
| 662 | 663 |
| 663 fCurrClipMaskType = kAlpha_ClipMaskType; | 664 fCurrClipMaskType = kAlpha_ClipMaskType; |
| 664 return result; | 665 return result; |
| 665 } | 666 } |
| 666 | 667 |
| 667 //////////////////////////////////////////////////////////////////////////////// | 668 //////////////////////////////////////////////////////////////////////////////// |
| 668 // Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device | 669 // Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device |
| 669 // (as opposed to canvas) coordinates | 670 // (as opposed to canvas) coordinates |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 774 if (!canDrawDirectToClip) { | 775 if (!canDrawDirectToClip) { |
| 775 GR_STATIC_CONST_SAME_STENCIL(gDrawToStencil, | 776 GR_STATIC_CONST_SAME_STENCIL(gDrawToStencil, |
| 776 kIncClamp_StencilOp, | 777 kIncClamp_StencilOp, |
| 777 kIncClamp_StencilOp, | 778 kIncClamp_StencilOp, |
| 778 kAlways_StencilFunc, | 779 kAlways_StencilFunc, |
| 779 0xffff, | 780 0xffff, |
| 780 0x0000, | 781 0x0000, |
| 781 0xffff); | 782 0xffff); |
| 782 if (Element::kRect_Type == element->getType()) { | 783 if (Element::kRect_Type == element->getType()) { |
| 783 *drawState.stencil() = gDrawToStencil; | 784 *drawState.stencil() = gDrawToStencil; |
| 784 fClipTarget->drawSimpleRect(&drawState, element->getRect()); | 785 fClipTarget->drawSimpleRect(&drawState, GrColor_WHITE, eleme
nt->getRect()); |
| 785 } else { | 786 } else { |
| 786 if (!clipPath.isEmpty()) { | 787 if (!clipPath.isEmpty()) { |
| 787 GrDrawTarget::AutoGeometryPush agp(fClipTarget); | 788 GrDrawTarget::AutoGeometryPush agp(fClipTarget); |
| 788 if (canRenderDirectToStencil) { | 789 if (canRenderDirectToStencil) { |
| 789 *drawState.stencil() = gDrawToStencil; | 790 *drawState.stencil() = gDrawToStencil; |
| 790 pr->drawPath(fClipTarget, &drawState, clipPath, stro
ke, false); | 791 pr->drawPath(fClipTarget, &drawState, GrColor_WHITE,
clipPath, stroke, |
| 792 false); |
| 791 } else { | 793 } else { |
| 792 pr->stencilPath(fClipTarget, &drawState, clipPath, s
troke); | 794 pr->stencilPath(fClipTarget, &drawState, clipPath, s
troke); |
| 793 } | 795 } |
| 794 } | 796 } |
| 795 } | 797 } |
| 796 } | 798 } |
| 797 | 799 |
| 798 // now we modify the clip bit by rendering either the clip | 800 // now we modify the clip bit by rendering either the clip |
| 799 // element directly or a bounding rect of the entire clip. | 801 // element directly or a bounding rect of the entire clip. |
| 800 fClipMode = kModifyClip_StencilClipMode; | 802 fClipMode = kModifyClip_StencilClipMode; |
| 801 for (int p = 0; p < passes; ++p) { | 803 for (int p = 0; p < passes; ++p) { |
| 802 GrDrawState drawStateCopy(drawState); | 804 GrDrawState drawStateCopy(drawState); |
| 803 *drawStateCopy.stencil() = stencilSettings[p]; | 805 *drawStateCopy.stencil() = stencilSettings[p]; |
| 804 | 806 |
| 805 if (canDrawDirectToClip) { | 807 if (canDrawDirectToClip) { |
| 806 if (Element::kRect_Type == element->getType()) { | 808 if (Element::kRect_Type == element->getType()) { |
| 807 fClipTarget->drawSimpleRect(&drawStateCopy, element->get
Rect()); | 809 fClipTarget->drawSimpleRect(&drawStateCopy, GrColor_WHIT
E, |
| 810 element->getRect()); |
| 808 } else { | 811 } else { |
| 809 GrDrawTarget::AutoGeometryPush agp(fClipTarget); | 812 GrDrawTarget::AutoGeometryPush agp(fClipTarget); |
| 810 pr->drawPath(fClipTarget, &drawStateCopy, clipPath, stro
ke, false); | 813 pr->drawPath(fClipTarget, &drawStateCopy, GrColor_WHITE,
clipPath, stroke, false); |
| 811 } | 814 } |
| 812 } else { | 815 } else { |
| 813 // The view matrix is setup to do clip space -> stencil spac
e translation, so | 816 // The view matrix is setup to do clip space -> stencil spac
e translation, so |
| 814 // draw rect in clip space. | 817 // draw rect in clip space. |
| 815 fClipTarget->drawSimpleRect(&drawStateCopy, SkRect::Make(cli
pSpaceIBounds)); | 818 fClipTarget->drawSimpleRect(&drawStateCopy, GrColor_WHITE, |
| 819 SkRect::Make(clipSpaceIBounds)); |
| 816 } | 820 } |
| 817 } | 821 } |
| 818 } | 822 } |
| 819 } | 823 } |
| 820 // set this last because recursive draws may overwrite it back to kNone. | 824 // set this last because recursive draws may overwrite it back to kNone. |
| 821 SkASSERT(kNone_ClipMaskType == fCurrClipMaskType); | 825 SkASSERT(kNone_ClipMaskType == fCurrClipMaskType); |
| 822 fCurrClipMaskType = kStencil_ClipMaskType; | 826 fCurrClipMaskType = kStencil_ClipMaskType; |
| 823 fClipMode = kRespectClip_StencilClipMode; | 827 fClipMode = kRespectClip_StencilClipMode; |
| 824 return true; | 828 return true; |
| 825 } | 829 } |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1075 } | 1079 } |
| 1076 | 1080 |
| 1077 void GrClipMaskManager::adjustPathStencilParams(const GrStencilBuffer* stencilBu
ffer, | 1081 void GrClipMaskManager::adjustPathStencilParams(const GrStencilBuffer* stencilBu
ffer, |
| 1078 GrStencilSettings* settings) { | 1082 GrStencilSettings* settings) { |
| 1079 // TODO: dynamically attach a stencil buffer | 1083 // TODO: dynamically attach a stencil buffer |
| 1080 if (stencilBuffer) { | 1084 if (stencilBuffer) { |
| 1081 int stencilBits = stencilBuffer->bits(); | 1085 int stencilBits = stencilBuffer->bits(); |
| 1082 this->adjustStencilParams(settings, fClipMode, stencilBits); | 1086 this->adjustStencilParams(settings, fClipMode, stencilBits); |
| 1083 } | 1087 } |
| 1084 } | 1088 } |
| OLD | NEW |