OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 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 "GrClipStackClip.h" | 8 #include "GrClipStackClip.h" |
9 | 9 |
10 #include "GrAppliedClip.h" | 10 #include "GrAppliedClip.h" |
(...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
461 reducedClip.width(), | 461 reducedClip.width(), |
462 reducedClip.height(), | 462 reducedClip.height(), |
463 config, nullptr)); | 463 config, nullptr)); |
464 if (!dc) { | 464 if (!dc) { |
465 return nullptr; | 465 return nullptr; |
466 } | 466 } |
467 | 467 |
468 // The texture may be larger than necessary, this rect represents the part o f the texture | 468 // The texture may be larger than necessary, this rect represents the part o f the texture |
469 // we populate with a rasterization of the clip. | 469 // we populate with a rasterization of the clip. |
470 SkIRect maskSpaceIBounds = SkIRect::MakeWH(reducedClip.width(), reducedClip. height()); | 470 SkIRect maskSpaceIBounds = SkIRect::MakeWH(reducedClip.width(), reducedClip. height()); |
471 GrFixedClip clip(maskSpaceIBounds); | |
471 | 472 |
472 // The scratch texture that we are drawing into can be substantially larger than the mask. Only | 473 // The scratch texture that we are drawing into can be substantially larger than the mask. Only |
473 // clear the part that we care about. | 474 // clear the part that we care about. |
474 dc->clear(&maskSpaceIBounds, InitialState::kAllIn == reducedClip.initialStat e() ? -1 : 0, true); | 475 GrColor initialCoverage = InitialState::kAllIn == reducedClip.initialState() ? -1 : 0; |
476 dc->drawContextPriv().clear(clip, initialCoverage, true); | |
475 | 477 |
476 // Set the matrix so that rendered clip elements are transformed to mask spa ce from clip | 478 // Set the matrix so that rendered clip elements are transformed to mask spa ce from clip |
477 // space. | 479 // space. |
478 const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMa skOffset.fY); | 480 const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMa skOffset.fY); |
479 | 481 |
480 // It is important that we use maskSpaceIBounds as the stencil rect in the b elow loop. | 482 // It is important that we use maskSpaceIBounds as the stencil rect in the b elow loop. |
481 // The second pass that zeros the stencil buffer renders the rect maskSpaceI Bounds so the first | 483 // The second pass that zeros the stencil buffer renders the rect maskSpaceI Bounds so the first |
482 // pass must not set values outside of this bounds or stencil values outside the rect won't be | 484 // pass must not set values outside of this bounds or stencil values outside the rect won't be |
483 // cleared. | 485 // cleared. |
484 | 486 |
485 // walk through each clip element and perform its set op | 487 // walk through each clip element and perform its set op |
486 for (ElementList::Iter iter(reducedClip.elements()); iter.get(); iter.next() ) { | 488 for (ElementList::Iter iter(reducedClip.elements()); iter.get(); iter.next() ) { |
487 const Element* element = iter.get(); | 489 const Element* element = iter.get(); |
488 SkRegion::Op op = element->getOp(); | 490 SkRegion::Op op = element->getOp(); |
489 bool invert = element->isInverseFilled(); | 491 bool invert = element->isInverseFilled(); |
490 if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDiffere nce_Op == op) { | 492 if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDiffere nce_Op == op) { |
491 GrFixedClip clip(maskSpaceIBounds); | |
492 | |
493 // draw directly into the result with the stencil set to make the pi xels affected | 493 // draw directly into the result with the stencil set to make the pi xels affected |
494 // by the clip shape be non-zero. | 494 // by the clip shape be non-zero. |
495 static constexpr GrUserStencilSettings kStencilInElement( | 495 static constexpr GrUserStencilSettings kStencilInElement( |
496 GrUserStencilSettings::StaticInit< | 496 GrUserStencilSettings::StaticInit< |
497 0xffff, | 497 0xffff, |
498 GrUserStencilTest::kAlways, | 498 GrUserStencilTest::kAlways, |
499 0xffff, | 499 0xffff, |
500 GrUserStencilOp::kReplace, | 500 GrUserStencilOp::kReplace, |
501 GrUserStencilOp::kReplace, | 501 GrUserStencilOp::kReplace, |
502 0xffff>() | 502 0xffff>() |
(...skipping 29 matching lines...) Expand all Loading... | |
532 } | 532 } |
533 } | 533 } |
534 | 534 |
535 sk_sp<GrTexture> texture(dc->asTexture()); | 535 sk_sp<GrTexture> texture(dc->asTexture()); |
536 SkASSERT(texture); | 536 SkASSERT(texture); |
537 texture->resourcePriv().setUniqueKey(key); | 537 texture->resourcePriv().setUniqueKey(key); |
538 return texture; | 538 return texture; |
539 } | 539 } |
540 | 540 |
541 //////////////////////////////////////////////////////////////////////////////// | 541 //////////////////////////////////////////////////////////////////////////////// |
542 // Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device | 542 // Create a 1-bit clip mask in the stencil buffer. |
543 // (as opposed to canvas) coordinates | 543 |
544 class StencilClip final : public GrClip { | |
545 public: | |
546 StencilClip(const SkIRect& scissorRect) : fFixedClip(scissorRect) {} | |
547 const GrFixedClip& fixedClip() const { return fFixedClip; } | |
548 | |
549 private: | |
550 bool quickContains(const SkRect& rect) const final { | |
551 return false; | |
552 } | |
553 void getConservativeBounds(int width, int height, SkIRect* devResult, | |
554 bool* isIntersectionOfRects) const final { | |
555 fFixedClip.getConservativeBounds(width, height, devResult, isIntersectio nOfRects); | |
556 } | |
557 bool apply(GrContext* context, GrDrawContext* drawContext, bool useHWAA, | |
558 bool hasUserStencilSettings, GrAppliedClip* out) const final { | |
559 if (!fFixedClip.apply(context, drawContext, useHWAA, hasUserStencilSetti ngs, out)) { | |
560 return false; | |
561 } | |
562 out->addStencilClip(); | |
563 return true; | |
564 } | |
565 | |
566 GrFixedClip fFixedClip; | |
csmartdalton
2016/08/23 19:51:29
This is much better. GrFixedClip REALLY needs to b
| |
567 | |
568 typedef GrClip INHERITED; | |
569 }; | |
570 | |
544 bool GrClipStackClip::CreateStencilClipMask(GrContext* context, | 571 bool GrClipStackClip::CreateStencilClipMask(GrContext* context, |
545 GrDrawContext* drawContext, | 572 GrDrawContext* drawContext, |
546 const GrReducedClip& reducedClip, | 573 const GrReducedClip& reducedClip, |
547 const SkIPoint& clipSpaceToStencilOf fset) { | 574 const SkIPoint& clipSpaceToStencilOf fset) { |
548 SkASSERT(drawContext); | 575 SkASSERT(drawContext); |
549 | 576 |
550 GrStencilAttachment* stencilAttachment = context->resourceProvider()->attach StencilAttachment( | 577 GrStencilAttachment* stencilAttachment = context->resourceProvider()->attach StencilAttachment( |
551 drawContext->accessRenderTar get()); | 578 drawContext->accessRenderTar get()); |
552 if (nullptr == stencilAttachment) { | 579 if (nullptr == stencilAttachment) { |
553 return false; | 580 return false; |
554 } | 581 } |
555 | 582 |
556 // TODO: these need to be swapped over to using a StencilAttachmentProxy | 583 // TODO: these need to be swapped over to using a StencilAttachmentProxy |
557 if (stencilAttachment->mustRenderClip(reducedClip.elementsGenID(), reducedCl ip.ibounds(), | 584 if (stencilAttachment->mustRenderClip(reducedClip.elementsGenID(), reducedCl ip.ibounds(), |
558 clipSpaceToStencilOffset)) { | 585 clipSpaceToStencilOffset)) { |
559 stencilAttachment->setLastClip(reducedClip.elementsGenID(), reducedClip. ibounds(), | 586 stencilAttachment->setLastClip(reducedClip.elementsGenID(), reducedClip. ibounds(), |
560 clipSpaceToStencilOffset); | 587 clipSpaceToStencilOffset); |
561 // Set the matrix so that rendered clip elements are transformed from cl ip to stencil space. | 588 // Set the matrix so that rendered clip elements are transformed from cl ip to stencil space. |
562 SkVector translate = { | 589 SkVector translate = { |
563 SkIntToScalar(clipSpaceToStencilOffset.fX), | 590 SkIntToScalar(clipSpaceToStencilOffset.fX), |
564 SkIntToScalar(clipSpaceToStencilOffset.fY) | 591 SkIntToScalar(clipSpaceToStencilOffset.fY) |
565 }; | 592 }; |
566 SkMatrix viewMatrix; | 593 SkMatrix viewMatrix; |
567 viewMatrix.setTranslate(translate); | 594 viewMatrix.setTranslate(translate); |
568 | 595 |
569 // We set the current clip to the bounds so that our recursive draws are scissored to them. | 596 // We set the current clip to the bounds so that our recursive draws are scissored to them. |
570 SkIRect stencilSpaceIBounds(reducedClip.ibounds()); | 597 SkIRect stencilSpaceIBounds(reducedClip.ibounds()); |
571 stencilSpaceIBounds.offset(clipSpaceToStencilOffset); | 598 stencilSpaceIBounds.offset(clipSpaceToStencilOffset); |
572 GrFixedClip clip(stencilSpaceIBounds); | 599 StencilClip stencilClip(stencilSpaceIBounds); |
573 | 600 |
574 bool insideClip = InitialState::kAllIn == reducedClip.initialState(); | 601 bool initialState = InitialState::kAllIn == reducedClip.initialState(); |
575 drawContext->drawContextPriv().clearStencilClip(stencilSpaceIBounds, ins ideClip); | 602 drawContext->drawContextPriv().clearStencilClip(stencilClip.fixedClip(), initialState); |
576 | 603 |
577 // walk through each clip element and perform its set op | 604 // walk through each clip element and perform its set op |
578 // with the existing clip. | 605 // with the existing clip. |
579 for (ElementList::Iter iter(reducedClip.elements()); iter.get(); iter.ne xt()) { | 606 for (ElementList::Iter iter(reducedClip.elements()); iter.get(); iter.ne xt()) { |
580 const Element* element = iter.get(); | 607 const Element* element = iter.get(); |
581 bool useHWAA = element->isAA() && drawContext->isStencilBufferMultis ampled(); | 608 bool useHWAA = element->isAA() && drawContext->isStencilBufferMultis ampled(); |
582 | 609 |
583 bool fillInverted = false; | 610 bool fillInverted = false; |
584 // enabled at bottom of loop | |
585 clip.disableStencilClip(); | |
586 | 611 |
587 // This will be used to determine whether the clip shape can be rend ered into the | 612 // This will be used to determine whether the clip shape can be rend ered into the |
588 // stencil with arbitrary stencil settings. | 613 // stencil with arbitrary stencil settings. |
589 GrPathRenderer::StencilSupport stencilSupport; | 614 GrPathRenderer::StencilSupport stencilSupport; |
590 | 615 |
591 SkRegion::Op op = element->getOp(); | 616 SkRegion::Op op = element->getOp(); |
592 | 617 |
593 GrPathRenderer* pr = nullptr; | 618 GrPathRenderer* pr = nullptr; |
594 SkPath clipPath; | 619 SkPath clipPath; |
595 if (Element::kRect_Type == element->getType()) { | 620 if (Element::kRect_Type == element->getType()) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
635 static constexpr GrUserStencilSettings kDrawToStencil( | 660 static constexpr GrUserStencilSettings kDrawToStencil( |
636 GrUserStencilSettings::StaticInit< | 661 GrUserStencilSettings::StaticInit< |
637 0x0000, | 662 0x0000, |
638 GrUserStencilTest::kAlways, | 663 GrUserStencilTest::kAlways, |
639 0xffff, | 664 0xffff, |
640 GrUserStencilOp::kIncMaybeClamp, | 665 GrUserStencilOp::kIncMaybeClamp, |
641 GrUserStencilOp::kIncMaybeClamp, | 666 GrUserStencilOp::kIncMaybeClamp, |
642 0xffff>() | 667 0xffff>() |
643 ); | 668 ); |
644 if (Element::kRect_Type == element->getType()) { | 669 if (Element::kRect_Type == element->getType()) { |
645 drawContext->drawContextPriv().stencilRect(clip, &kDrawToSte ncil, useHWAA, | 670 drawContext->drawContextPriv().stencilRect(stencilClip.fixed Clip(), |
671 &kDrawToStencil, useHWAA, | |
646 viewMatrix, eleme nt->getRect()); | 672 viewMatrix, eleme nt->getRect()); |
647 } else { | 673 } else { |
648 if (!clipPath.isEmpty()) { | 674 if (!clipPath.isEmpty()) { |
649 GrShape shape(clipPath, GrStyle::SimpleFill()); | 675 GrShape shape(clipPath, GrStyle::SimpleFill()); |
650 if (canRenderDirectToStencil) { | 676 if (canRenderDirectToStencil) { |
651 GrPaint paint; | 677 GrPaint paint; |
652 paint.setXPFactory(GrDisableColorXPFactory::Make()); | 678 paint.setXPFactory(GrDisableColorXPFactory::Make()); |
653 paint.setAntiAlias(element->isAA()); | 679 paint.setAntiAlias(element->isAA()); |
654 | 680 |
655 GrPathRenderer::DrawPathArgs args; | 681 GrPathRenderer::DrawPathArgs args; |
656 args.fResourceProvider = context->resourceProvider() ; | 682 args.fResourceProvider = context->resourceProvider() ; |
657 args.fPaint = &paint; | 683 args.fPaint = &paint; |
658 args.fUserStencilSettings = &kDrawToStencil; | 684 args.fUserStencilSettings = &kDrawToStencil; |
659 args.fDrawContext = drawContext; | 685 args.fDrawContext = drawContext; |
660 args.fClip = &clip; | 686 args.fClip = &stencilClip.fixedClip(); |
661 args.fViewMatrix = &viewMatrix; | 687 args.fViewMatrix = &viewMatrix; |
662 args.fShape = &shape; | 688 args.fShape = &shape; |
663 args.fAntiAlias = false; | 689 args.fAntiAlias = false; |
664 args.fGammaCorrect = false; | 690 args.fGammaCorrect = false; |
665 pr->drawPath(args); | 691 pr->drawPath(args); |
666 } else { | 692 } else { |
667 GrPathRenderer::StencilPathArgs args; | 693 GrPathRenderer::StencilPathArgs args; |
668 args.fResourceProvider = context->resourceProvider() ; | 694 args.fResourceProvider = context->resourceProvider() ; |
669 args.fDrawContext = drawContext; | 695 args.fDrawContext = drawContext; |
670 args.fClip = &clip; | 696 args.fClip = &stencilClip.fixedClip(); |
671 args.fViewMatrix = &viewMatrix; | 697 args.fViewMatrix = &viewMatrix; |
672 args.fIsAA = element->isAA(); | 698 args.fIsAA = element->isAA(); |
673 args.fShape = &shape; | 699 args.fShape = &shape; |
674 pr->stencilPath(args); | 700 pr->stencilPath(args); |
675 } | 701 } |
676 } | 702 } |
677 } | 703 } |
678 } | 704 } |
679 | 705 |
680 // Just enable stencil clip. The passes choose whether or not they w ill actually use it. | |
681 clip.enableStencilClip(); | |
682 | |
683 // now we modify the clip bit by rendering either the clip | 706 // now we modify the clip bit by rendering either the clip |
684 // element directly or a bounding rect of the entire clip. | 707 // element directly or a bounding rect of the entire clip. |
685 for (GrUserStencilSettings const* const* pass = stencilPasses; *pass ; ++pass) { | 708 for (GrUserStencilSettings const* const* pass = stencilPasses; *pass ; ++pass) { |
686 if (drawDirectToClip) { | 709 if (drawDirectToClip) { |
687 if (Element::kRect_Type == element->getType()) { | 710 if (Element::kRect_Type == element->getType()) { |
688 drawContext->drawContextPriv().stencilRect(clip, *pass, useHWAA, viewMatrix, | 711 drawContext->drawContextPriv().stencilRect(stencilClip, *pass, useHWAA, |
689 element->getR ect()); | 712 viewMatrix, e lement->getRect()); |
690 } else { | 713 } else { |
691 GrShape shape(clipPath, GrStyle::SimpleFill()); | 714 GrShape shape(clipPath, GrStyle::SimpleFill()); |
692 GrPaint paint; | 715 GrPaint paint; |
693 paint.setXPFactory(GrDisableColorXPFactory::Make()); | 716 paint.setXPFactory(GrDisableColorXPFactory::Make()); |
694 paint.setAntiAlias(element->isAA()); | 717 paint.setAntiAlias(element->isAA()); |
695 GrPathRenderer::DrawPathArgs args; | 718 GrPathRenderer::DrawPathArgs args; |
696 args.fResourceProvider = context->resourceProvider(); | 719 args.fResourceProvider = context->resourceProvider(); |
697 args.fPaint = &paint; | 720 args.fPaint = &paint; |
698 args.fUserStencilSettings = *pass; | 721 args.fUserStencilSettings = *pass; |
699 args.fDrawContext = drawContext; | 722 args.fDrawContext = drawContext; |
700 args.fClip = &clip; | 723 args.fClip = &stencilClip; |
701 args.fViewMatrix = &viewMatrix; | 724 args.fViewMatrix = &viewMatrix; |
702 args.fShape = &shape; | 725 args.fShape = &shape; |
703 args.fAntiAlias = false; | 726 args.fAntiAlias = false; |
704 args.fGammaCorrect = false; | 727 args.fGammaCorrect = false; |
705 pr->drawPath(args); | 728 pr->drawPath(args); |
706 } | 729 } |
707 } else { | 730 } else { |
708 // The view matrix is setup to do clip space -> stencil spac e translation, so | 731 // The view matrix is setup to do clip space -> stencil spac e translation, so |
709 // draw rect in clip space. | 732 // draw rect in clip space. |
710 drawContext->drawContextPriv().stencilRect(clip, *pass, fals e, viewMatrix, | 733 drawContext->drawContextPriv().stencilRect(stencilClip, *pas s, |
734 false, viewMatrix , | |
711 SkRect::Make(redu cedClip.ibounds())); | 735 SkRect::Make(redu cedClip.ibounds())); |
712 } | 736 } |
713 } | 737 } |
714 } | 738 } |
715 } | 739 } |
716 return true; | 740 return true; |
717 } | 741 } |
718 | 742 |
719 //////////////////////////////////////////////////////////////////////////////// | 743 //////////////////////////////////////////////////////////////////////////////// |
720 sk_sp<GrTexture> GrClipStackClip::CreateSoftwareClipMask(GrTextureProvider* texP rovider, | 744 sk_sp<GrTexture> GrClipStackClip::CreateSoftwareClipMask(GrTextureProvider* texP rovider, |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
783 sk_sp<GrTexture> result(texProvider->createApproxTexture(desc)); | 807 sk_sp<GrTexture> result(texProvider->createApproxTexture(desc)); |
784 if (!result) { | 808 if (!result) { |
785 return nullptr; | 809 return nullptr; |
786 } | 810 } |
787 result->resourcePriv().setUniqueKey(key); | 811 result->resourcePriv().setUniqueKey(key); |
788 | 812 |
789 helper.toTexture(result.get()); | 813 helper.toTexture(result.get()); |
790 | 814 |
791 return result; | 815 return result; |
792 } | 816 } |
OLD | NEW |