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