OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2010 Google Inc. | 2 * Copyright 2010 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 #ifndef GrClip_DEFINED | 8 #ifndef GrClip_DEFINED |
9 #define GrClip_DEFINED | 9 #define GrClip_DEFINED |
10 | 10 |
11 #include "GrFragmentProcessor.h" | 11 #include "GrFragmentProcessor.h" |
12 #include "GrTypesPriv.h" | 12 #include "GrTypesPriv.h" |
13 | 13 |
14 class GrDrawContext; | 14 class GrDrawContext; |
15 | 15 |
16 /** | 16 /** |
17 * Produced by GrClip. It provides a set of modifications to the drawing state t
hat are used to | 17 * Produced by GrClip. It provides a set of modifications to the drawing state t
hat are used to |
18 * create the final GrPipeline for a GrBatch. | 18 * create the final GrPipeline for a GrBatch. |
19 */ | 19 */ |
20 class GrAppliedClip : public SkNoncopyable { | 20 class GrAppliedClip : public SkNoncopyable { |
21 public: | 21 public: |
22 GrAppliedClip() : fHasStencilClip(false), fDeviceBounds(SkRect::MakeLargest(
)) {} | 22 GrAppliedClip(const SkRect& drawBounds) |
23 GrFragmentProcessor* getClipCoverageFragmentProcessor() const { | 23 : fHasStencilClip(false) |
24 return fClipCoverageFP.get(); | 24 , fClippedDrawBounds(drawBounds) { |
25 } | 25 } |
| 26 |
26 const GrScissorState& scissorState() const { return fScissorState; } | 27 const GrScissorState& scissorState() const { return fScissorState; } |
| 28 GrFragmentProcessor* clipCoverageFragmentProcessor() const { return fClipCov
erageFP.get(); } |
27 bool hasStencilClip() const { return fHasStencilClip; } | 29 bool hasStencilClip() const { return fHasStencilClip; } |
28 | 30 |
29 void makeStencil(bool hasStencil, const SkRect& deviceBounds) { | 31 /** |
30 fClipCoverageFP = nullptr; | 32 * Intersects the applied clip with the provided rect. Returns false if the
draw became empty. |
31 fScissorState.setDisabled(); | 33 */ |
32 fHasStencilClip = hasStencil; | 34 bool addScissor(const SkIRect& irect) { |
33 fDeviceBounds = deviceBounds; | 35 return fScissorState.intersect(irect) && fClippedDrawBounds.intersect(Sk
Rect::Make(irect)); |
| 36 } |
| 37 |
| 38 void addCoverageFP(sk_sp<GrFragmentProcessor> fp) { |
| 39 SkASSERT(!fClipCoverageFP); |
| 40 fClipCoverageFP = fp; |
| 41 } |
| 42 |
| 43 void addStencilClip() { |
| 44 SkASSERT(!fHasStencilClip); |
| 45 fHasStencilClip = true; |
34 } | 46 } |
35 | 47 |
36 /** | 48 /** |
37 * The device bounds of the clip defaults to the scissor rect, but a tighter
bounds (based | 49 * Returns the device bounds of the draw after clip has been applied. TODO:
Ideally this would |
38 * on the known effect of the stencil values) can be provided. | 50 * consider the combined effect of all clipping techniques in play (scissor,
stencil, fp, etc.). |
39 */ | 51 */ |
40 void makeScissoredStencil(const SkIRect& scissor, const SkRect* deviceBounds
= nullptr) { | 52 const SkRect& clippedDrawBounds() const { return fClippedDrawBounds; } |
41 fClipCoverageFP = nullptr; | |
42 fScissorState.set(scissor); | |
43 fHasStencilClip = true; | |
44 if (deviceBounds) { | |
45 fDeviceBounds = *deviceBounds; | |
46 SkASSERT(scissor.contains(*deviceBounds)); | |
47 } else { | |
48 fDeviceBounds = SkRect::Make(scissor); | |
49 } | |
50 } | |
51 | |
52 void makeFPBased(sk_sp<GrFragmentProcessor> fp, const SkRect& deviceBounds)
{ | |
53 fClipCoverageFP = fp; | |
54 fScissorState.setDisabled(); | |
55 fHasStencilClip = false; | |
56 fDeviceBounds = deviceBounds; | |
57 } | |
58 | |
59 void makeScissored(SkIRect& scissor) { | |
60 fClipCoverageFP.reset(); | |
61 fScissorState.set(scissor); | |
62 fHasStencilClip = false; | |
63 fDeviceBounds = SkRect::Make(scissor); | |
64 } | |
65 | |
66 /** | |
67 * The device bounds of the clip defaults to the scissor rect, but a tighter
bounds (based | |
68 * on the known effect of the fragment processor) can be provided. | |
69 */ | |
70 void makeScissoredFPBased(sk_sp<GrFragmentProcessor> fp, const SkIRect& scis
sor, | |
71 const SkRect* deviceBounds = nullptr) { | |
72 fClipCoverageFP = fp; | |
73 fScissorState.set(scissor); | |
74 fHasStencilClip = false; | |
75 if (deviceBounds) { | |
76 fDeviceBounds = *deviceBounds; | |
77 SkASSERT(scissor.contains(*deviceBounds)); | |
78 } else { | |
79 fDeviceBounds = SkRect::Make(scissor); | |
80 } | |
81 } | |
82 | |
83 /** | |
84 * Returns the device bounds of the applied clip. Ideally this considers the
combined effect of | |
85 * all clipping techniques in play (scissor, stencil, and/or coverage fp). | |
86 */ | |
87 const SkRect& deviceBounds() const { return fDeviceBounds; } | |
88 | 53 |
89 private: | 54 private: |
| 55 GrScissorState fScissorState; |
90 sk_sp<GrFragmentProcessor> fClipCoverageFP; | 56 sk_sp<GrFragmentProcessor> fClipCoverageFP; |
91 GrScissorState fScissorState; | |
92 bool fHasStencilClip; | 57 bool fHasStencilClip; |
93 SkRect fDeviceBounds; | 58 SkRect fClippedDrawBounds; |
94 typedef SkNoncopyable INHERITED; | 59 typedef SkNoncopyable INHERITED; |
95 }; | 60 }; |
96 | 61 |
97 /** | 62 /** |
98 * GrClip is an abstract base class for applying a clip. It constructs a clip ma
sk if necessary, and | 63 * GrClip is an abstract base class for applying a clip. It constructs a clip ma
sk if necessary, and |
99 * fills out a GrAppliedClip instructing the caller on how to set up the draw st
ate. | 64 * fills out a GrAppliedClip instructing the caller on how to set up the draw st
ate. |
100 */ | 65 */ |
101 class GrClip { | 66 class GrClip { |
102 public: | 67 public: |
103 virtual bool quickContains(const SkRect&) const = 0; | 68 virtual bool quickContains(const SkRect&) const = 0; |
104 virtual void getConservativeBounds(int width, int height, SkIRect* devResult
, | 69 virtual void getConservativeBounds(int width, int height, SkIRect* devResult
, |
105 bool* isIntersectionOfRects = nullptr) co
nst = 0; | 70 bool* isIntersectionOfRects = nullptr) co
nst = 0; |
106 virtual bool apply(GrContext*, | 71 virtual bool apply(GrContext*, GrDrawContext*, bool useHWAA, bool hasUserSte
ncilSettings, |
107 GrDrawContext*, | |
108 const SkRect* devBounds, | |
109 bool useHWAA, | |
110 bool hasUserStencilSettings, | |
111 GrAppliedClip* out) const = 0; | 72 GrAppliedClip* out) const = 0; |
112 | 73 |
113 virtual ~GrClip() {} | 74 virtual ~GrClip() {} |
114 | 75 |
115 /** | 76 /** |
116 * This is the maximum distance that a draw may extend beyond a clip's bound
ary and still count | 77 * This is the maximum distance that a draw may extend beyond a clip's bound
ary and still count |
117 * count as "on the other side". We leave some slack because floating point
rounding error is | 78 * count as "on the other side". We leave some slack because floating point
rounding error is |
118 * likely to blame. The rationale for 1e-3 is that in the coverage case (and
barring unexpected | 79 * likely to blame. The rationale for 1e-3 is that in the coverage case (and
barring unexpected |
119 * rounding), as long as coverage stays within 0.5 * 1/256 of its intended v
alue it shouldn't | 80 * rounding), as long as coverage stays within 0.5 * 1/256 of its intended v
alue it shouldn't |
120 * have any effect on the final pixel values. | 81 * have any effect on the final pixel values. |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 }; | 146 }; |
186 | 147 |
187 /** | 148 /** |
188 * Specialized implementation for no clip. | 149 * Specialized implementation for no clip. |
189 */ | 150 */ |
190 class GrNoClip final : public GrClip { | 151 class GrNoClip final : public GrClip { |
191 private: | 152 private: |
192 bool quickContains(const SkRect&) const final { return true; } | 153 bool quickContains(const SkRect&) const final { return true; } |
193 void getConservativeBounds(int width, int height, SkIRect* devResult, | 154 void getConservativeBounds(int width, int height, SkIRect* devResult, |
194 bool* isIntersectionOfRects) const final; | 155 bool* isIntersectionOfRects) const final; |
195 bool apply(GrContext*, | 156 bool apply(GrContext*, GrDrawContext*, bool, bool, GrAppliedClip*) const fin
al { return true; } |
196 GrDrawContext*, | |
197 const SkRect* /* devBounds */, | |
198 bool /* useHWAA */, | |
199 bool /* hasUserStencilSettings */, | |
200 GrAppliedClip* /* out */) const final { return true; } | |
201 }; | 157 }; |
202 | 158 |
203 /** | 159 /** |
204 * GrFixedClip is a clip that can be represented by fixed-function hardware. It
never modifies the | 160 * GrFixedClip is a clip that can be represented by fixed-function hardware. It
never modifies the |
205 * stencil buffer itself, but can be configured to use whatever clip is already
there. | 161 * stencil buffer itself, but can be configured to use whatever clip is already
there. |
206 */ | 162 */ |
207 class GrFixedClip final : public GrClip { | 163 class GrFixedClip final : public GrClip { |
208 public: | 164 public: |
209 GrFixedClip() : fDeviceBounds(SkRect::MakeLargest()), fHasStencilClip(false)
{} | 165 GrFixedClip() : fHasStencilClip(false) {} |
210 GrFixedClip(const SkIRect& scissorRect) | 166 GrFixedClip(const SkIRect& scissorRect) |
211 : fScissorState(scissorRect) | 167 : fScissorState(scissorRect) |
212 , fDeviceBounds(SkRect::Make(scissorRect)) | |
213 , fHasStencilClip(false) {} | 168 , fHasStencilClip(false) {} |
214 | 169 |
215 void reset() { | 170 void reset() { |
216 fScissorState.setDisabled(); | 171 fScissorState.setDisabled(); |
217 fDeviceBounds.setLargest(); | |
218 fHasStencilClip = false; | 172 fHasStencilClip = false; |
219 } | 173 } |
220 | 174 |
221 void reset(const SkIRect& scissorRect) { | 175 void reset(const SkIRect& scissorRect) { |
222 fScissorState.set(scissorRect); | 176 fScissorState.set(scissorRect); |
223 fDeviceBounds = SkRect::Make(scissorRect); | |
224 fHasStencilClip = false; | 177 fHasStencilClip = false; |
225 } | 178 } |
226 | 179 |
227 /** | 180 void enableStencilClip() { fHasStencilClip = true; } |
228 * Enables stenciling. The stencil bounds is the device space bounds where t
he stencil test | 181 void disableStencilClip() { fHasStencilClip = false; } |
229 * may pass. | |
230 */ | |
231 void enableStencilClip(const SkRect& stencilBounds) { | |
232 fHasStencilClip = true; | |
233 fDeviceBounds = stencilBounds; | |
234 if (fScissorState.enabled()) { | |
235 const SkIRect& s = fScissorState.rect(); | |
236 fDeviceBounds.fLeft = SkTMax(fDeviceBounds.fLeft, SkIntToScalar(
s.fLeft)); | |
237 fDeviceBounds.fTop = SkTMax(fDeviceBounds.fTop, SkIntToScalar(
s.fTop)); | |
238 fDeviceBounds.fRight = SkTMin(fDeviceBounds.fRight, SkIntToScalar(
s.fRight)); | |
239 fDeviceBounds.fBottom = SkTMin(fDeviceBounds.fBottom, SkIntToScalar(
s.fBottom)); | |
240 } | |
241 } | |
242 | |
243 void disableStencilClip() { | |
244 fHasStencilClip = false; | |
245 if (fScissorState.enabled()) { | |
246 fDeviceBounds = SkRect::Make(fScissorState.rect()); | |
247 } else { | |
248 fDeviceBounds.setLargest(); | |
249 } | |
250 } | |
251 | |
252 const GrScissorState& scissorState() const { return fScissorState; } | |
253 bool hasStencilClip() const { return fHasStencilClip; } | |
254 | 182 |
255 bool quickContains(const SkRect&) const final; | 183 bool quickContains(const SkRect&) const final; |
256 void getConservativeBounds(int width, int height, SkIRect* devResult, | 184 void getConservativeBounds(int width, int height, SkIRect* devResult, |
257 bool* isIntersectionOfRects) const final; | 185 bool* isIntersectionOfRects) const final; |
258 | 186 |
259 private: | 187 private: |
260 bool apply(GrContext*, | 188 bool apply(GrContext*, GrDrawContext*, bool useHWAA, bool hasUserStencilSett
ings, |
261 GrDrawContext*, | |
262 const SkRect* devBounds, | |
263 bool useHWAA, | |
264 bool hasUserStencilSettings, | |
265 GrAppliedClip* out) const final; | 189 GrAppliedClip* out) const final; |
266 | 190 |
267 GrScissorState fScissorState; | 191 GrScissorState fScissorState; |
268 SkRect fDeviceBounds; | |
269 bool fHasStencilClip; | 192 bool fHasStencilClip; |
270 }; | 193 }; |
271 | 194 |
272 #endif | 195 #endif |
OLD | NEW |