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