Chromium Code Reviews| 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 |