Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(115)

Side by Side Diff: src/gpu/GrReducedClip.cpp

Issue 2289363005: Improve usage of window rectangles (Closed) Base URL: https://skia.googlesource.com/skia.git@upload_drawsinreducedclip
Patch Set: comments Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "GrReducedClip.h" 8 #include "GrReducedClip.h"
9 9
10 #include "GrAppliedClip.h" 10 #include "GrAppliedClip.h"
(...skipping 10 matching lines...) Expand all
21 21
22 typedef SkClipStack::Element Element; 22 typedef SkClipStack::Element Element;
23 23
24 /** 24 /**
25 * There are plenty of optimizations that could be added here. Maybe flips could be folded into 25 * There are plenty of optimizations that could be added here. Maybe flips could be folded into
26 * earlier operations. Or would inserting flips and reversing earlier ops ever b e a win? Perhaps 26 * earlier operations. Or would inserting flips and reversing earlier ops ever b e a win? Perhaps
27 * for the case where the bounds are kInsideOut_BoundsType. We could restrict ea rlier operations 27 * for the case where the bounds are kInsideOut_BoundsType. We could restrict ea rlier operations
28 * based on later intersect operations, and perhaps remove intersect-rects. We c ould optionally 28 * based on later intersect operations, and perhaps remove intersect-rects. We c ould optionally
29 * take a rect in case the caller knows a bound on what is to be drawn through t his clip. 29 * take a rect in case the caller knows a bound on what is to be drawn through t his clip.
30 */ 30 */
31 GrReducedClip::GrReducedClip(const SkClipStack& stack, const SkRect& queryBounds ) { 31 GrReducedClip::GrReducedClip(const SkClipStack& stack, const SkRect& queryBounds ,
32 int maxWindowRectangles) {
32 SkASSERT(!queryBounds.isEmpty()); 33 SkASSERT(!queryBounds.isEmpty());
33 fHasIBounds = false; 34 fHasIBounds = false;
34 35
35 if (stack.isWideOpen()) { 36 if (stack.isWideOpen()) {
36 fInitialState = InitialState::kAllIn; 37 fInitialState = InitialState::kAllIn;
37 return; 38 return;
38 } 39 }
39 40
40 SkClipStack::BoundsType stackBoundsType; 41 SkClipStack::BoundsType stackBoundsType;
41 SkRect stackBounds; 42 SkRect stackBounds;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 // clip will be enforced by the scissor through fIBounds.) 88 // clip will be enforced by the scissor through fIBounds.)
88 SkAssertResult(tighterQuery.intersect(GrClip::GetPixelBounds(stackBounds ))); 89 SkAssertResult(tighterQuery.intersect(GrClip::GetPixelBounds(stackBounds )));
89 } 90 }
90 91
91 fIBounds = GrClip::GetPixelIBounds(tighterQuery); 92 fIBounds = GrClip::GetPixelIBounds(tighterQuery);
92 SkASSERT(!fIBounds.isEmpty()); // Empty should have been blocked by IsOutsid eClip above. 93 SkASSERT(!fIBounds.isEmpty()); // Empty should have been blocked by IsOutsid eClip above.
93 fHasIBounds = true; 94 fHasIBounds = true;
94 95
95 // Now that we have determined the bounds to use and filtered out the trivia l cases, call the 96 // Now that we have determined the bounds to use and filtered out the trivia l cases, call the
96 // helper that actually walks the stack. 97 // helper that actually walks the stack.
97 this->walkStack(stack, tighterQuery); 98 this->walkStack(stack, tighterQuery, maxWindowRectangles);
99
100 if (fWindowRects.count() < maxWindowRectangles) {
101 this->addInteriorWindowRectangles(maxWindowRectangles);
102 }
98 } 103 }
99 104
100 void GrReducedClip::walkStack(const SkClipStack& stack, const SkRect& queryBound s) { 105 void GrReducedClip::walkStack(const SkClipStack& stack, const SkRect& queryBound s,
106 int maxWindowRectangles) {
101 // walk backwards until we get to: 107 // walk backwards until we get to:
102 // a) the beginning 108 // a) the beginning
103 // b) an operation that is known to make the bounds all inside/outside 109 // b) an operation that is known to make the bounds all inside/outside
104 // c) a replace operation 110 // c) a replace operation
105 111
106 enum class InitialTriState { 112 enum class InitialTriState {
107 kUnknown = -1, 113 kUnknown = -1,
108 kAllIn = (int)GrReducedClip::InitialState::kAllIn, 114 kAllIn = (int)GrReducedClip::InitialState::kAllIn,
109 kAllOut = (int)GrReducedClip::InitialState::kAllOut 115 kAllOut = (int)GrReducedClip::InitialState::kAllOut
110 } initialTriState = InitialTriState::kUnknown; 116 } initialTriState = InitialTriState::kUnknown;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 } else if (GrClip::IsOutsideClip(element->getBounds(), query Bounds)) { 155 } else if (GrClip::IsOutsideClip(element->getBounds(), query Bounds)) {
150 initialTriState = InitialTriState::kAllOut; 156 initialTriState = InitialTriState::kAllOut;
151 skippable = true; 157 skippable = true;
152 } 158 }
153 } else { 159 } else {
154 if (element->contains(relaxedQueryBounds)) { 160 if (element->contains(relaxedQueryBounds)) {
155 initialTriState = InitialTriState::kAllOut; 161 initialTriState = InitialTriState::kAllOut;
156 skippable = true; 162 skippable = true;
157 } else if (GrClip::IsOutsideClip(element->getBounds(), query Bounds)) { 163 } else if (GrClip::IsOutsideClip(element->getBounds(), query Bounds)) {
158 skippable = true; 164 skippable = true;
165 } else if (fWindowRects.count() < maxWindowRectangles && !em biggens &&
166 !element->isAA() && Element::kRect_Type == elemen t->getType()) {
167 this->addWindowRectangle(element->getRect(), false);
168 skippable = true;
159 } 169 }
160 } 170 }
161 if (!skippable) { 171 if (!skippable) {
162 emsmallens = true; 172 emsmallens = true;
163 } 173 }
164 break; 174 break;
165 case SkRegion::kIntersect_Op: 175 case SkRegion::kIntersect_Op:
166 // check if the shape intersected contains the entire bounds and therefore can 176 // check if the shape intersected contains the entire bounds and therefore can
167 // be skipped or it is outside the entire bounds and therefore m akes the clip 177 // be skipped or it is outside the entire bounds and therefore m akes the clip
168 // empty. 178 // empty.
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after
413 element = fElements.headIter().get(); 423 element = fElements.headIter().get();
414 } 424 }
415 } 425 }
416 } 426 }
417 fRequiresAA = numAAElements > 0; 427 fRequiresAA = numAAElements > 0;
418 428
419 SkASSERT(InitialTriState::kUnknown != initialTriState); 429 SkASSERT(InitialTriState::kUnknown != initialTriState);
420 fInitialState = static_cast<GrReducedClip::InitialState>(initialTriState); 430 fInitialState = static_cast<GrReducedClip::InitialState>(initialTriState);
421 } 431 }
422 432
433 static bool element_is_pure_subtract(SkRegion::Op op) {
434 SkASSERT(op >= 0);
435 return op <= SkRegion::kIntersect_Op;
436
437 GR_STATIC_ASSERT(0 == SkRegion::kDifference_Op);
438 GR_STATIC_ASSERT(1 == SkRegion::kIntersect_Op);
439 }
440
441 void GrReducedClip::addInteriorWindowRectangles(int maxWindowRectangles) {
442 SkASSERT(fWindowRects.count() < maxWindowRectangles);
443 // Walk backwards through the element list and add window rectangles to the interiors of
444 // "difference" elements. Quit if we encounter an element that may grow the clip.
445 ElementList::Iter iter(fElements, ElementList::Iter::kTail_IterStart);
446 for (; iter.get() && element_is_pure_subtract(iter.get()->getOp()); iter.pre v()) {
447 const Element* element = iter.get();
448 if (SkRegion::kDifference_Op != element->getOp()) {
449 continue;
450 }
451
452 if (Element::kRect_Type == element->getType()) {
453 SkASSERT(element->isAA());
454 this->addWindowRectangle(element->getRect(), true);
455 if (fWindowRects.count() >= maxWindowRectangles) {
456 return;
457 }
458 continue;
459 }
460
461 if (Element::kRRect_Type == element->getType()) {
462 // For round rects we add two overlapping windows in the shape of a plus.
463 const SkRRect& clipRRect = element->getRRect();
464 SkVector insetTL = clipRRect.radii(SkRRect::kUpperLeft_Corner);
465 SkVector insetBR = clipRRect.radii(SkRRect::kLowerRight_Corner);
466 if (SkRRect::kComplex_Type == clipRRect.getType()) {
467 const SkVector& insetTR = clipRRect.radii(SkRRect::kUpperRight_C orner);
468 const SkVector& insetBL = clipRRect.radii(SkRRect::kLowerLeft_Co rner);
469 insetTL.fX = SkTMax(insetTL.x(), insetBL.x());
470 insetTL.fY = SkTMax(insetTL.y(), insetTR.y());
471 insetBR.fX = SkTMax(insetBR.x(), insetTR.x());
472 insetBR.fY = SkTMax(insetBR.y(), insetBL.y());
473 }
474 const SkRect& bounds = clipRRect.getBounds();
475 if (insetTL.x() + insetBR.x() >= bounds.width() ||
476 insetTL.y() + insetBR.y() >= bounds.height()) {
477 continue; // The interior "plus" is empty.
478 }
479
480 SkRect horzRect = SkRect::MakeLTRB(bounds.left(), bounds.top() + ins etTL.y(),
481 bounds.right(), bounds.bottom() - insetBR.y());
482 this->addWindowRectangle(horzRect, element->isAA());
483 if (fWindowRects.count() >= maxWindowRectangles) {
484 return;
485 }
486
487 SkRect vertRect = SkRect::MakeLTRB(bounds.left() + insetTL.x(), boun ds.top(),
488 bounds.right() - insetBR.x(), bou nds.bottom());
489 this->addWindowRectangle(vertRect, element->isAA());
490 if (fWindowRects.count() >= maxWindowRectangles) {
491 return;
492 }
493 continue;
494 }
495 }
496 }
497
498 inline void GrReducedClip::addWindowRectangle(const SkRect& elementInteriorRect, bool elementIsAA) {
499 SkIRect* window = &fWindowRects.addWindow();
500 if (!elementIsAA) {
501 elementInteriorRect.round(window);
502 } else {
503 elementInteriorRect.roundIn(window);
504 }
505 }
506
423 inline bool GrReducedClip::intersectIBounds(const SkIRect& irect) { 507 inline bool GrReducedClip::intersectIBounds(const SkIRect& irect) {
424 SkASSERT(fHasIBounds); 508 SkASSERT(fHasIBounds);
425 if (!fIBounds.intersect(irect)) { 509 if (!fIBounds.intersect(irect)) {
426 fHasIBounds = false; 510 fHasIBounds = false;
511 fWindowRects.reset();
427 fElements.reset(); 512 fElements.reset();
428 fRequiresAA = false; 513 fRequiresAA = false;
429 fInitialState = InitialState::kAllOut; 514 fInitialState = InitialState::kAllOut;
430 return false; 515 return false;
431 } 516 }
432 return true; 517 return true;
433 } 518 }
434 519
435 //////////////////////////////////////////////////////////////////////////////// 520 ////////////////////////////////////////////////////////////////////////////////
436 // Create a 8-bit clip mask in alpha 521 // Create a 8-bit clip mask in alpha
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
496 break; 581 break;
497 } 582 }
498 } 583 }
499 } 584 }
500 585
501 bool GrReducedClip::drawAlphaClipMask(GrDrawContext* dc) const { 586 bool GrReducedClip::drawAlphaClipMask(GrDrawContext* dc) const {
502 // The texture may be larger than necessary, this rect represents the part o f the texture 587 // The texture may be larger than necessary, this rect represents the part o f the texture
503 // we populate with a rasterization of the clip. 588 // we populate with a rasterization of the clip.
504 GrFixedClip clip(SkIRect::MakeWH(fIBounds.width(), fIBounds.height())); 589 GrFixedClip clip(SkIRect::MakeWH(fIBounds.width(), fIBounds.height()));
505 590
591 if (!fWindowRects.empty()) {
592 clip.windowRectsState().setExclusive(fWindowRects, {fIBounds.left(), fIB ounds.top()});
593 }
594
506 // The scratch texture that we are drawing into can be substantially larger than the mask. Only 595 // The scratch texture that we are drawing into can be substantially larger than the mask. Only
507 // clear the part that we care about. 596 // clear the part that we care about.
508 GrColor initialCoverage = InitialState::kAllIn == this->initialState() ? -1 : 0; 597 GrColor initialCoverage = InitialState::kAllIn == this->initialState() ? -1 : 0;
509 dc->drawContextPriv().clear(clip, initialCoverage, true); 598 dc->drawContextPriv().clear(clip, initialCoverage, true);
510 599
511 // Set the matrix so that rendered clip elements are transformed to mask spa ce from clip space. 600 // Set the matrix so that rendered clip elements are transformed to mask spa ce from clip space.
512 SkMatrix translate; 601 SkMatrix translate;
513 translate.setTranslate(SkIntToScalar(-fIBounds.left()), SkIntToScalar(-fIBou nds.top())); 602 translate.setTranslate(SkIntToScalar(-fIBounds.left()), SkIntToScalar(-fIBou nds.top()));
514 603
515 // walk through each clip element and perform its set op 604 // walk through each clip element and perform its set op
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
562 return true; 651 return true;
563 } 652 }
564 653
565 //////////////////////////////////////////////////////////////////////////////// 654 ////////////////////////////////////////////////////////////////////////////////
566 // Create a 1-bit clip mask in the stencil buffer. 655 // Create a 1-bit clip mask in the stencil buffer.
567 656
568 class StencilClip final : public GrClip { 657 class StencilClip final : public GrClip {
569 public: 658 public:
570 StencilClip(const SkIRect& scissorRect) : fFixedClip(scissorRect) {} 659 StencilClip(const SkIRect& scissorRect) : fFixedClip(scissorRect) {}
571 const GrFixedClip& fixedClip() const { return fFixedClip; } 660 const GrFixedClip& fixedClip() const { return fFixedClip; }
661 GrWindowRectsState& windowRectsState() { return fFixedClip.windowRectsState( ); }
572 662
573 private: 663 private:
574 bool quickContains(const SkRect&) const final { 664 bool quickContains(const SkRect&) const override {
575 return false; 665 return false;
576 } 666 }
577 void getConservativeBounds(int width, int height, SkIRect* devResult, bool* iior) const final { 667 void getConservativeBounds(int width, int height, SkIRect* bounds, bool* iio r) const override {
578 fFixedClip.getConservativeBounds(width, height, devResult, iior); 668 fFixedClip.getConservativeBounds(width, height, bounds, iior);
579 } 669 }
580 bool isRRect(const SkRect& rtBounds, SkRRect* rr, bool* aa) const final { 670 bool isRRect(const SkRect& rtBounds, SkRRect* rr, bool* aa) const override {
581 return false; 671 return false;
582 } 672 }
583 bool apply(GrContext* context, GrDrawContext* drawContext, bool useHWAA, 673 bool apply(GrContext* context, GrDrawContext* drawContext, bool useHWAA,
584 bool hasUserStencilSettings, GrAppliedClip* out) const final { 674 bool hasUserStencilSettings, GrAppliedClip* out) const override {
585 if (!fFixedClip.apply(context, drawContext, useHWAA, hasUserStencilSetti ngs, out)) { 675 if (!fFixedClip.apply(context, drawContext, useHWAA, hasUserStencilSetti ngs, out)) {
586 return false; 676 return false;
587 } 677 }
588 out->addStencilClip(); 678 out->addStencilClip();
589 return true; 679 return true;
590 } 680 }
591 681
592 GrFixedClip fFixedClip; 682 GrFixedClip fFixedClip;
593 683
594 typedef GrClip INHERITED; 684 typedef GrClip INHERITED;
595 }; 685 };
596 686
597 bool GrReducedClip::drawStencilClipMask(GrContext* context, 687 bool GrReducedClip::drawStencilClipMask(GrContext* context,
598 GrDrawContext* drawContext, 688 GrDrawContext* drawContext,
599 const SkIPoint& clipOrigin) const { 689 const SkIPoint& clipOrigin) const {
600 // We set the current clip to the bounds so that our recursive draws are sci ssored to them. 690 // We set the current clip to the bounds so that our recursive draws are sci ssored to them.
601 StencilClip stencilClip(fIBounds.makeOffset(-clipOrigin.x(), -clipOrigin.y() )); 691 StencilClip stencilClip(fIBounds.makeOffset(-clipOrigin.x(), -clipOrigin.y() ));
602 692
693 if (!fWindowRects.empty()) {
694 stencilClip.windowRectsState().setExclusive(fWindowRects, clipOrigin);
695 }
696
603 bool initialState = InitialState::kAllIn == this->initialState(); 697 bool initialState = InitialState::kAllIn == this->initialState();
604 drawContext->drawContextPriv().clearStencilClip(stencilClip.fixedClip(), ini tialState); 698 drawContext->drawContextPriv().clearStencilClip(stencilClip.fixedClip(), ini tialState);
605 699
606 // Set the matrix so that rendered clip elements are transformed from clip t o stencil space. 700 // Set the matrix so that rendered clip elements are transformed from clip t o stencil space.
607 SkMatrix viewMatrix; 701 SkMatrix viewMatrix;
608 viewMatrix.setTranslate(SkIntToScalar(-clipOrigin.x()), SkIntToScalar(-clipO rigin.y())); 702 viewMatrix.setTranslate(SkIntToScalar(-clipOrigin.x()), SkIntToScalar(-clipO rigin.y()));
609 703
610 // walk through each clip element and perform its set op 704 // walk through each clip element and perform its set op
611 // with the existing clip. 705 // with the existing clip.
612 for (ElementList::Iter iter(fElements); iter.get(); iter.next()) { 706 for (ElementList::Iter iter(fElements); iter.get(); iter.next()) {
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
737 // The view matrix is setup to do clip space -> stencil space tr anslation, so 831 // The view matrix is setup to do clip space -> stencil space tr anslation, so
738 // draw rect in clip space. 832 // draw rect in clip space.
739 drawContext->drawContextPriv().stencilRect(stencilClip, *pass, 833 drawContext->drawContextPriv().stencilRect(stencilClip, *pass,
740 false, viewMatrix, 834 false, viewMatrix,
741 SkRect::Make(fIBounds )); 835 SkRect::Make(fIBounds ));
742 } 836 }
743 } 837 }
744 } 838 }
745 return true; 839 return true;
746 } 840 }
OLDNEW
« src/gpu/GrFixedClip.h ('K') | « src/gpu/GrReducedClip.h ('k') | src/gpu/GrRenderTarget.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698