1 /* 2 * Copyright 2016 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef GrAppliedClip_DEFINED 9 #define GrAppliedClip_DEFINED 10 11 #include "GrFragmentProcessor.h" 12 #include "GrScissorState.h" 13 #include "GrWindowRectsState.h" 14 15 #include "SkClipStack.h" 16 17 18 /** 19 * Produced by GrHardClip. It provides a set of modifications to the hardware drawing state that 20 * implement the clip. 21 */ 22 class GrAppliedHardClip { 23 public: 24 GrAppliedHardClip() = default; 25 GrAppliedHardClip(GrAppliedHardClip&& that) = default; 26 GrAppliedHardClip(const GrAppliedHardClip&) = delete; 27 scissorState()28 const GrScissorState& scissorState() const { return fScissorState; } windowRectsState()29 const GrWindowRectsState& windowRectsState() const { return fWindowRectsState; } stencilStackID()30 uint32_t stencilStackID() const { return fStencilStackID; } hasStencilClip()31 bool hasStencilClip() const { return SkClipStack::kInvalidGenID != fStencilStackID; } 32 33 /** 34 * Intersects the applied clip with the provided rect. Returns false if the draw became empty. 35 * 'clippedDrawBounds' will be intersected with 'irect'. This returns false if the clip becomes 36 * empty or the draw no longer intersects the clip. In either case the draw can be skipped. 37 */ addScissor(const SkIRect & irect,SkRect * clippedDrawBounds)38 bool addScissor(const SkIRect& irect, SkRect* clippedDrawBounds) { 39 return fScissorState.intersect(irect) && clippedDrawBounds->intersect(SkRect::Make(irect)); 40 } 41 addWindowRectangles(const GrWindowRectsState & windowState)42 void addWindowRectangles(const GrWindowRectsState& windowState) { 43 SkASSERT(!fWindowRectsState.enabled()); 44 fWindowRectsState = windowState; 45 } 46 addWindowRectangles(const GrWindowRectangles & windows,GrWindowRectsState::Mode mode)47 void addWindowRectangles(const GrWindowRectangles& windows, GrWindowRectsState::Mode mode) { 48 SkASSERT(!fWindowRectsState.enabled()); 49 fWindowRectsState.set(windows, mode); 50 } 51 addStencilClip(uint32_t stencilStackID)52 void addStencilClip(uint32_t stencilStackID) { 53 SkASSERT(SkClipStack::kInvalidGenID == fStencilStackID); 54 fStencilStackID = stencilStackID; 55 } 56 doesClip()57 bool doesClip() const { 58 return fScissorState.enabled() || this->hasStencilClip() || fWindowRectsState.enabled(); 59 } 60 61 bool operator==(const GrAppliedHardClip& that) const { 62 return fScissorState == that.fScissorState && 63 fWindowRectsState == that.fWindowRectsState && 64 fStencilStackID == that.fStencilStackID; 65 } 66 bool operator!=(const GrAppliedHardClip& that) const { return !(*this == that); } 67 68 private: 69 GrScissorState fScissorState; 70 GrWindowRectsState fWindowRectsState; 71 uint32_t fStencilStackID = SkClipStack::kInvalidGenID; 72 }; 73 74 /** 75 * Produced by GrClip. It provides a set of modifications to GrPipeline that implement the clip. 76 */ 77 class GrAppliedClip { 78 public: 79 GrAppliedClip() = default; 80 GrAppliedClip(GrAppliedClip&& that) = default; 81 GrAppliedClip(const GrAppliedClip&) = delete; 82 scissorState()83 const GrScissorState& scissorState() const { return fHardClip.scissorState(); } windowRectsState()84 const GrWindowRectsState& windowRectsState() const { return fHardClip.windowRectsState(); } stencilStackID()85 uint32_t stencilStackID() const { return fHardClip.stencilStackID(); } hasStencilClip()86 bool hasStencilClip() const { return fHardClip.hasStencilClip(); } numClipCoverageFragmentProcessors()87 int numClipCoverageFragmentProcessors() const { return fClipCoverageFPs.count(); } clipCoverageFragmentProcessor(int i)88 const GrFragmentProcessor* clipCoverageFragmentProcessor(int i) const { 89 SkASSERT(fClipCoverageFPs[i]); 90 return fClipCoverageFPs[i].get(); 91 } detachClipCoverageFragmentProcessor(int i)92 std::unique_ptr<const GrFragmentProcessor> detachClipCoverageFragmentProcessor(int i) { 93 SkASSERT(fClipCoverageFPs[i]); 94 return std::move(fClipCoverageFPs[i]); 95 } 96 hardClip()97 GrAppliedHardClip& hardClip() { return fHardClip; } 98 addCoverageFP(std::unique_ptr<GrFragmentProcessor> fp)99 void addCoverageFP(std::unique_ptr<GrFragmentProcessor> fp) { 100 SkASSERT(fp); 101 fClipCoverageFPs.push_back(std::move(fp)); 102 } 103 doesClip()104 bool doesClip() const { 105 return fHardClip.doesClip() || !fClipCoverageFPs.empty(); 106 } 107 108 bool operator==(const GrAppliedClip& that) const { 109 if (fHardClip != that.fHardClip || 110 fClipCoverageFPs.count() != that.fClipCoverageFPs.count()) { 111 return false; 112 } 113 for (int i = 0; i < fClipCoverageFPs.count(); ++i) { 114 if (!fClipCoverageFPs[i] || !that.fClipCoverageFPs[i]) { 115 if (fClipCoverageFPs[i] == that.fClipCoverageFPs[i]) { 116 continue; // Both are null. 117 } 118 return false; 119 } 120 if (!fClipCoverageFPs[i]->isEqual(*that.fClipCoverageFPs[i])) { 121 return false; 122 } 123 } 124 return true; 125 } 126 bool operator!=(const GrAppliedClip& that) const { return !(*this == that); } 127 visitProxies(const std::function<void (GrSurfaceProxy *)> & func)128 void visitProxies(const std::function<void(GrSurfaceProxy*)>& func) const { 129 for (const std::unique_ptr<GrFragmentProcessor>& fp : fClipCoverageFPs) { 130 if (fp) { // This might be called after detach. 131 fp->visitProxies(func); 132 } 133 } 134 } 135 136 private: 137 GrAppliedHardClip fHardClip; 138 SkSTArray<4, std::unique_ptr<GrFragmentProcessor>> fClipCoverageFPs; 139 }; 140 141 #endif 142