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 StencilFixedClip final : public GrFixedClip { |
| 545 public: |
| 546 StencilFixedClip(const SkIRect& scissorRect) : INHERITED(scissorRect), fUseC
lipBit(false) {} |
| 547 void useClipBit(bool use) { fUseClipBit = use; } |
| 548 |
| 549 private: |
| 550 bool quickContains(const SkRect& rect) const override { |
| 551 return fUseClipBit ? false : INHERITED::quickContains(rect); |
| 552 } |
| 553 bool apply(GrContext* context, GrDrawContext* drawContext, bool useHWAA, |
| 554 bool hasUserStencilSettings, GrAppliedClip* out) const override { |
| 555 if (!INHERITED::apply(context, drawContext, useHWAA, hasUserStencilSetti
ngs, out)) { |
| 556 return false; |
| 557 } |
| 558 if (fUseClipBit) { |
| 559 out->addStencilClip(); |
| 560 } |
| 561 return true; |
| 562 } |
| 563 |
| 564 bool fUseClipBit; |
| 565 |
| 566 typedef GrFixedClip INHERITED; |
| 567 }; |
| 568 |
544 bool GrClipStackClip::CreateStencilClipMask(GrContext* context, | 569 bool GrClipStackClip::CreateStencilClipMask(GrContext* context, |
545 GrDrawContext* drawContext, | 570 GrDrawContext* drawContext, |
546 const GrReducedClip& reducedClip, | 571 const GrReducedClip& reducedClip, |
547 const SkIPoint& clipSpaceToStencilOf
fset) { | 572 const SkIPoint& clipSpaceToStencilOf
fset) { |
548 SkASSERT(drawContext); | 573 SkASSERT(drawContext); |
549 | 574 |
550 GrStencilAttachment* stencilAttachment = context->resourceProvider()->attach
StencilAttachment( | 575 GrStencilAttachment* stencilAttachment = context->resourceProvider()->attach
StencilAttachment( |
551 drawContext->accessRenderTar
get()); | 576 drawContext->accessRenderTar
get()); |
552 if (nullptr == stencilAttachment) { | 577 if (nullptr == stencilAttachment) { |
553 return false; | 578 return false; |
554 } | 579 } |
555 | 580 |
556 // TODO: these need to be swapped over to using a StencilAttachmentProxy | 581 // TODO: these need to be swapped over to using a StencilAttachmentProxy |
557 if (stencilAttachment->mustRenderClip(reducedClip.elementsGenID(), reducedCl
ip.ibounds(), | 582 if (stencilAttachment->mustRenderClip(reducedClip.elementsGenID(), reducedCl
ip.ibounds(), |
558 clipSpaceToStencilOffset)) { | 583 clipSpaceToStencilOffset)) { |
559 stencilAttachment->setLastClip(reducedClip.elementsGenID(), reducedClip.
ibounds(), | 584 stencilAttachment->setLastClip(reducedClip.elementsGenID(), reducedClip.
ibounds(), |
560 clipSpaceToStencilOffset); | 585 clipSpaceToStencilOffset); |
561 // Set the matrix so that rendered clip elements are transformed from cl
ip to stencil space. | 586 // Set the matrix so that rendered clip elements are transformed from cl
ip to stencil space. |
562 SkVector translate = { | 587 SkVector translate = { |
563 SkIntToScalar(clipSpaceToStencilOffset.fX), | 588 SkIntToScalar(clipSpaceToStencilOffset.fX), |
564 SkIntToScalar(clipSpaceToStencilOffset.fY) | 589 SkIntToScalar(clipSpaceToStencilOffset.fY) |
565 }; | 590 }; |
566 SkMatrix viewMatrix; | 591 SkMatrix viewMatrix; |
567 viewMatrix.setTranslate(translate); | 592 viewMatrix.setTranslate(translate); |
568 | 593 |
569 // We set the current clip to the bounds so that our recursive draws are
scissored to them. | 594 // We set the current clip to the bounds so that our recursive draws are
scissored to them. |
570 SkIRect stencilSpaceIBounds(reducedClip.ibounds()); | 595 SkIRect stencilSpaceIBounds(reducedClip.ibounds()); |
571 stencilSpaceIBounds.offset(clipSpaceToStencilOffset); | 596 stencilSpaceIBounds.offset(clipSpaceToStencilOffset); |
572 GrFixedClip clip(stencilSpaceIBounds); | 597 StencilFixedClip clip(stencilSpaceIBounds); |
573 | 598 |
574 bool insideClip = InitialState::kAllIn == reducedClip.initialState(); | 599 bool initialState = InitialState::kAllIn == reducedClip.initialState(); |
575 drawContext->drawContextPriv().clearStencilClip(stencilSpaceIBounds, ins
ideClip); | 600 drawContext->drawContextPriv().clearStencilClip(clip, initialState); |
576 | 601 |
577 // walk through each clip element and perform its set op | 602 // walk through each clip element and perform its set op |
578 // with the existing clip. | 603 // with the existing clip. |
579 for (ElementList::Iter iter(reducedClip.elements()); iter.get(); iter.ne
xt()) { | 604 for (ElementList::Iter iter(reducedClip.elements()); iter.get(); iter.ne
xt()) { |
580 const Element* element = iter.get(); | 605 const Element* element = iter.get(); |
581 bool useHWAA = element->isAA() && drawContext->isStencilBufferMultis
ampled(); | 606 bool useHWAA = element->isAA() && drawContext->isStencilBufferMultis
ampled(); |
582 | 607 |
583 bool fillInverted = false; | 608 bool fillInverted = false; |
584 // enabled at bottom of loop | 609 // enabled at bottom of loop |
585 clip.disableStencilClip(); | 610 clip.useClipBit(false); |
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 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
670 args.fClip = &clip; | 695 args.fClip = &clip; |
671 args.fViewMatrix = &viewMatrix; | 696 args.fViewMatrix = &viewMatrix; |
672 args.fIsAA = element->isAA(); | 697 args.fIsAA = element->isAA(); |
673 args.fShape = &shape; | 698 args.fShape = &shape; |
674 pr->stencilPath(args); | 699 pr->stencilPath(args); |
675 } | 700 } |
676 } | 701 } |
677 } | 702 } |
678 } | 703 } |
679 | 704 |
680 // Just enable stencil clip. The passes choose whether or not they w
ill actually use it. | 705 // This doesn't mean the current pass will be clipped by the stencil
buffer. That is |
681 clip.enableStencilClip(); | 706 // decided by GrUserStencilSettings. This just tells it there is dat
a in the clip bit. |
| 707 clip.useClipBit(true); |
682 | 708 |
683 // now we modify the clip bit by rendering either the clip | 709 // now we modify the clip bit by rendering either the clip |
684 // element directly or a bounding rect of the entire clip. | 710 // element directly or a bounding rect of the entire clip. |
685 for (GrUserStencilSettings const* const* pass = stencilPasses; *pass
; ++pass) { | 711 for (GrUserStencilSettings const* const* pass = stencilPasses; *pass
; ++pass) { |
686 if (drawDirectToClip) { | 712 if (drawDirectToClip) { |
687 if (Element::kRect_Type == element->getType()) { | 713 if (Element::kRect_Type == element->getType()) { |
688 drawContext->drawContextPriv().stencilRect(clip, *pass,
useHWAA, viewMatrix, | 714 drawContext->drawContextPriv().stencilRect(clip, *pass,
useHWAA, viewMatrix, |
689 element->getR
ect()); | 715 element->getR
ect()); |
690 } else { | 716 } else { |
691 GrShape shape(clipPath, GrStyle::SimpleFill()); | 717 GrShape shape(clipPath, GrStyle::SimpleFill()); |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
783 sk_sp<GrTexture> result(texProvider->createApproxTexture(desc)); | 809 sk_sp<GrTexture> result(texProvider->createApproxTexture(desc)); |
784 if (!result) { | 810 if (!result) { |
785 return nullptr; | 811 return nullptr; |
786 } | 812 } |
787 result->resourcePriv().setUniqueKey(key); | 813 result->resourcePriv().setUniqueKey(key); |
788 | 814 |
789 helper.toTexture(result.get()); | 815 helper.toTexture(result.get()); |
790 | 816 |
791 return result; | 817 return result; |
792 } | 818 } |
OLD | NEW |