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 "src/gpu/GrFragmentProcessor.h"
12 #include "src/gpu/GrScissorState.h"
13 #include "src/gpu/GrWindowRectsState.h"
14 
15 #include "src/core/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:
Disabled()24     static const GrAppliedHardClip& Disabled() {
25         // The size doesn't really matter here since it's returned as const& so an actual scissor
26         // will never be set on it, and applied clips are not used to query or bounds test like
27         // the GrClip is.
28         static const GrAppliedHardClip kDisabled({1 << 29, 1 << 29});
29         return kDisabled;
30     }
31 
GrAppliedHardClip(const SkISize & rtDims)32     GrAppliedHardClip(const SkISize& rtDims) : fScissorState(rtDims) {}
GrAppliedHardClip(const SkISize & logicalRTDims,const SkISize & backingStoreDims)33     GrAppliedHardClip(const SkISize& logicalRTDims, const SkISize& backingStoreDims)
34             : fScissorState(backingStoreDims) {
35         fScissorState.set(SkIRect::MakeSize(logicalRTDims));
36     }
37 
38     GrAppliedHardClip(GrAppliedHardClip&& that) = default;
39     explicit GrAppliedHardClip(const GrAppliedHardClip&) = default;
40 
scissorState()41     const GrScissorState& scissorState() const { return fScissorState; }
windowRectsState()42     const GrWindowRectsState& windowRectsState() const { return fWindowRectsState; }
stencilStackID()43     uint32_t stencilStackID() const { return fStencilStackID; }
hasStencilClip()44     bool hasStencilClip() const { return SkClipStack::kInvalidGenID != fStencilStackID; }
45 
46     /**
47      * Intersects the applied clip with the provided rect. Returns false if the draw became empty.
48      * 'clippedDrawBounds' will be intersected with 'irect'. This returns false if the clip becomes
49      * empty or the draw no longer intersects the clip. In either case the draw can be skipped.
50      */
addScissor(const SkIRect & irect,SkRect * clippedDrawBounds)51     bool addScissor(const SkIRect& irect, SkRect* clippedDrawBounds) {
52         return fScissorState.intersect(irect) && clippedDrawBounds->intersect(SkRect::Make(irect));
53     }
54 
setScissor(const SkIRect & irect)55     void setScissor(const SkIRect& irect) {
56         fScissorState.set(irect);
57     }
58 
addWindowRectangles(const GrWindowRectsState & windowState)59     void addWindowRectangles(const GrWindowRectsState& windowState) {
60         SkASSERT(!fWindowRectsState.enabled());
61         fWindowRectsState = windowState;
62     }
63 
addWindowRectangles(const GrWindowRectangles & windows,GrWindowRectsState::Mode mode)64     void addWindowRectangles(const GrWindowRectangles& windows, GrWindowRectsState::Mode mode) {
65         SkASSERT(!fWindowRectsState.enabled());
66         fWindowRectsState.set(windows, mode);
67     }
68 
addStencilClip(uint32_t stencilStackID)69     void addStencilClip(uint32_t stencilStackID) {
70         SkASSERT(SkClipStack::kInvalidGenID == fStencilStackID);
71         fStencilStackID = stencilStackID;
72     }
73 
doesClip()74     bool doesClip() const {
75         return fScissorState.enabled() || this->hasStencilClip() || fWindowRectsState.enabled();
76     }
77 
78     bool operator==(const GrAppliedHardClip& that) const {
79         return fScissorState == that.fScissorState &&
80                fWindowRectsState == that.fWindowRectsState &&
81                fStencilStackID == that.fStencilStackID;
82     }
83     bool operator!=(const GrAppliedHardClip& that) const { return !(*this == that); }
84 
85 private:
86     GrScissorState             fScissorState;
87     GrWindowRectsState         fWindowRectsState;
88     uint32_t                   fStencilStackID = SkClipStack::kInvalidGenID;
89 };
90 
91 /**
92  * Produced by GrClip. It provides a set of modifications to GrPipeline that implement the clip.
93  */
94 class GrAppliedClip {
95 public:
Disabled()96     static GrAppliedClip Disabled() {
97         return GrAppliedClip({1 << 29, 1 << 29});
98     }
99 
GrAppliedClip(const SkISize & rtDims)100     GrAppliedClip(const SkISize& rtDims) : fHardClip(rtDims) {}
GrAppliedClip(const SkISize & logicalRTDims,const SkISize & backingStoreDims)101     GrAppliedClip(const SkISize& logicalRTDims, const SkISize& backingStoreDims)
102             : fHardClip(logicalRTDims, backingStoreDims) {}
103 
104     GrAppliedClip(GrAppliedClip&& that) = default;
105     GrAppliedClip(const GrAppliedClip&) = delete;
106 
scissorState()107     const GrScissorState& scissorState() const { return fHardClip.scissorState(); }
windowRectsState()108     const GrWindowRectsState& windowRectsState() const { return fHardClip.windowRectsState(); }
stencilStackID()109     uint32_t stencilStackID() const { return fHardClip.stencilStackID(); }
hasStencilClip()110     bool hasStencilClip() const { return fHardClip.hasStencilClip(); }
hasCoverageFragmentProcessor()111     int hasCoverageFragmentProcessor() const { return fCoverageFP != nullptr; }
coverageFragmentProcessor()112     const GrFragmentProcessor* coverageFragmentProcessor() const {
113         SkASSERT(fCoverageFP != nullptr);
114         return fCoverageFP.get();
115     }
detachCoverageFragmentProcessor()116     std::unique_ptr<GrFragmentProcessor> detachCoverageFragmentProcessor() {
117         SkASSERT(fCoverageFP != nullptr);
118         return std::move(fCoverageFP);
119     }
120 
hardClip()121     const GrAppliedHardClip& hardClip() const { return fHardClip; }
hardClip()122     GrAppliedHardClip& hardClip() { return fHardClip; }
123 
addCoverageFP(std::unique_ptr<GrFragmentProcessor> fp)124     void addCoverageFP(std::unique_ptr<GrFragmentProcessor> fp) {
125         if (fCoverageFP == nullptr) {
126             fCoverageFP = std::move(fp);
127         } else {
128             // Compose this coverage FP with the previously-added coverage.
129             fCoverageFP = GrFragmentProcessor::Compose(std::move(fCoverageFP), std::move(fp));
130         }
131     }
132 
doesClip()133     bool doesClip() const {
134         return fHardClip.doesClip() || fCoverageFP != nullptr;
135     }
136 
137     bool operator==(const GrAppliedClip& that) const {
138         if (fHardClip != that.fHardClip ||
139             this->hasCoverageFragmentProcessor() != that.hasCoverageFragmentProcessor()) {
140             return false;
141         }
142         if (fCoverageFP != nullptr && !fCoverageFP->isEqual(*that.fCoverageFP)) {
143             return false;
144         }
145         return true;
146     }
147     bool operator!=(const GrAppliedClip& that) const { return !(*this == that); }
148 
visitProxies(const GrOp::VisitProxyFunc & func)149     void visitProxies(const GrOp::VisitProxyFunc& func) const {
150         if (fCoverageFP != nullptr) {
151             fCoverageFP->visitProxies(func);
152         }
153     }
154 
155 private:
156     GrAppliedHardClip fHardClip;
157     std::unique_ptr<GrFragmentProcessor> fCoverageFP;
158 };
159 
160 #endif
161