| 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 |