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 |