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

Side by Side Diff: src/core/SkRasterClip.cpp

Issue 541593005: allow canvas to force conservative clips (for speed) (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 6 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
« no previous file with comments | « src/core/SkRasterClip.h ('k') | src/core/SkRecorder.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 #include "SkRasterClip.h" 8 #include "SkRasterClip.h"
9 9 #include "SkPath.h"
10
11 SkRasterClip::SkRasterClip() {
12 fIsBW = true;
13 fIsEmpty = true;
14 fIsRect = false;
15 SkDEBUGCODE(this->validate();)
16 }
17 10
18 SkRasterClip::SkRasterClip(const SkRasterClip& src) { 11 SkRasterClip::SkRasterClip(const SkRasterClip& src) {
19 AUTO_RASTERCLIP_VALIDATE(src); 12 AUTO_RASTERCLIP_VALIDATE(src);
20 13
14 fForceConservativeRects = src.fForceConservativeRects;
21 fIsBW = src.fIsBW; 15 fIsBW = src.fIsBW;
22 if (fIsBW) { 16 if (fIsBW) {
23 fBW = src.fBW; 17 fBW = src.fBW;
24 } else { 18 } else {
25 fAA = src.fAA; 19 fAA = src.fAA;
26 } 20 }
27 21
28 fIsEmpty = src.isEmpty(); 22 fIsEmpty = src.isEmpty();
29 fIsRect = src.isRect(); 23 fIsRect = src.isRect();
30 SkDEBUGCODE(this->validate();) 24 SkDEBUGCODE(this->validate();)
31 } 25 }
32 26
33 SkRasterClip::SkRasterClip(const SkIRect& bounds) : fBW(bounds) { 27 SkRasterClip::SkRasterClip(const SkIRect& bounds, bool forceConservativeRects) : fBW(bounds) {
28 fForceConservativeRects = forceConservativeRects;
34 fIsBW = true; 29 fIsBW = true;
35 fIsEmpty = this->computeIsEmpty(); // bounds might be empty, so compute 30 fIsEmpty = this->computeIsEmpty(); // bounds might be empty, so compute
36 fIsRect = !fIsEmpty; 31 fIsRect = !fIsEmpty;
37 SkDEBUGCODE(this->validate();) 32 SkDEBUGCODE(this->validate();)
38 } 33 }
39 34
35 SkRasterClip::SkRasterClip(bool forceConservativeRects) {
36 fForceConservativeRects = forceConservativeRects;
37 fIsBW = true;
38 fIsEmpty = true;
39 fIsRect = false;
40 SkDEBUGCODE(this->validate();)
41 }
42
40 SkRasterClip::~SkRasterClip() { 43 SkRasterClip::~SkRasterClip() {
41 SkDEBUGCODE(this->validate();) 44 SkDEBUGCODE(this->validate();)
42 } 45 }
43 46
44 bool SkRasterClip::isComplex() const { 47 bool SkRasterClip::isComplex() const {
45 return fIsBW ? fBW.isComplex() : !fAA.isEmpty(); 48 return fIsBW ? fBW.isComplex() : !fAA.isEmpty();
46 } 49 }
47 50
48 const SkIRect& SkRasterClip::getBounds() const { 51 const SkIRect& SkRasterClip::getBounds() const {
49 return fIsBW ? fBW.getBounds() : fAA.getBounds(); 52 return fIsBW ? fBW.getBounds() : fAA.getBounds();
(...skipping 13 matching lines...) Expand all
63 bool SkRasterClip::setRect(const SkIRect& rect) { 66 bool SkRasterClip::setRect(const SkIRect& rect) {
64 AUTO_RASTERCLIP_VALIDATE(*this); 67 AUTO_RASTERCLIP_VALIDATE(*this);
65 68
66 fIsBW = true; 69 fIsBW = true;
67 fAA.setEmpty(); 70 fAA.setEmpty();
68 fIsRect = fBW.setRect(rect); 71 fIsRect = fBW.setRect(rect);
69 fIsEmpty = !fIsRect; 72 fIsEmpty = !fIsRect;
70 return fIsRect; 73 return fIsRect;
71 } 74 }
72 75
76 //////////////////////////////////////////////////////////////////////////////// /////
77
78 bool SkRasterClip::setConservativeRect(const SkRect& r, const SkIRect& clipR, bo ol isInverse) {
79 SkIRect ir;
80 r.roundOut(&ir);
81
82 SkRegion::Op op;
83 if (isInverse) {
84 op = SkRegion::kDifference_Op;
85 } else {
86 op = SkRegion::kIntersect_Op;
87 }
88 fBW.setRect(clipR);
89 fBW.op(ir, op);
90 return this->updateCacheAndReturnNonEmpty();
91 }
92
93 //////////////////////////////////////////////////////////////////////////////// /////
94
95 enum MutateResult {
96 kDoNothing_MutateResult,
97 kReplaceClippedAgainstGlobalBounds_MutateResult,
98 kContinue_MutateResult,
99 };
100
101 static MutateResult mutate_conservative_op(SkRegion::Op* op, bool inverseFilled) {
102 if (inverseFilled) {
103 switch (*op) {
104 case SkRegion::kIntersect_Op:
105 case SkRegion::kDifference_Op:
106 // These ops can only shrink the current clip. So leaving
107 // the clip unchanged conservatively respects the contract.
108 return kDoNothing_MutateResult;
109 case SkRegion::kUnion_Op:
110 case SkRegion::kReplace_Op:
111 case SkRegion::kReverseDifference_Op:
112 case SkRegion::kXOR_Op: {
113 // These ops can grow the current clip up to the extents of
114 // the input clip, which is inverse filled, so we just set
115 // the current clip to the device bounds.
116 // this->getDevice()->getGlobalBounds(&deviceIBounds);
mtklein 2014/09/09 17:25:38 stray?
reed1 2014/09/09 17:41:38 Done.
117 *op = SkRegion::kReplace_Op;
118 return kReplaceClippedAgainstGlobalBounds_MutateResult;
119 }
120 }
121 } else {
122 // Not inverse filled
123 switch (*op) {
124 case SkRegion::kIntersect_Op:
125 case SkRegion::kUnion_Op:
126 case SkRegion::kReplace_Op:
127 return kContinue_MutateResult;
128 case SkRegion::kDifference_Op:
129 // Difference can only shrink the current clip.
130 // Leaving clip unchanged conservatively fullfills the contract.
131 return kDoNothing_MutateResult;
132 case SkRegion::kReverseDifference_Op:
133 // To reverse, we swap in the bounds with a replace op.
134 // As with difference, leave it unchanged.
135 *op = SkRegion::kReplace_Op;
136 return kContinue_MutateResult;
137 case SkRegion::kXOR_Op:
138 // Be conservative, based on (A XOR B) always included in (A uni on B),
139 // which is always included in (bounds(A) union bounds(B))
140 *op = SkRegion::kUnion_Op;
141 return kContinue_MutateResult;
142 }
143 }
144 // should not get here
mtklein 2014/09/09 17:25:38 SkFAIL("should not get here")?
reed1 2014/09/09 17:41:38 Done.
145 return kDoNothing_MutateResult;
146 }
147
73 bool SkRasterClip::setPath(const SkPath& path, const SkRegion& clip, bool doAA) { 148 bool SkRasterClip::setPath(const SkPath& path, const SkRegion& clip, bool doAA) {
74 AUTO_RASTERCLIP_VALIDATE(*this); 149 AUTO_RASTERCLIP_VALIDATE(*this);
75 150
151 if (fForceConservativeRects) {
152 return this->setConservativeRect(path.getBounds(), clip.getBounds(), pat h.isInverseFillType());
153 }
154
76 if (this->isBW() && !doAA) { 155 if (this->isBW() && !doAA) {
77 (void)fBW.setPath(path, clip); 156 (void)fBW.setPath(path, clip);
78 } else { 157 } else {
79 // TODO: since we are going to over-write fAA completely (aren't we?) 158 // TODO: since we are going to over-write fAA completely (aren't we?)
80 // we should just clear our BW data (if any) and set fIsAA=true 159 // we should just clear our BW data (if any) and set fIsAA=true
81 if (this->isBW()) { 160 if (this->isBW()) {
82 this->convertToAA(); 161 this->convertToAA();
83 } 162 }
84 (void)fAA.setPath(path, &clip, doAA); 163 (void)fAA.setPath(path, &clip, doAA);
85 } 164 }
86 return this->updateCacheAndReturnNonEmpty(); 165 return this->updateCacheAndReturnNonEmpty();
87 } 166 }
88 167
89 bool SkRasterClip::op(const SkPath& path, const SkISize& size, SkRegion::Op op, bool doAA) { 168 bool SkRasterClip::op(const SkPath& path, const SkISize& size, SkRegion::Op op, bool doAA) {
90 // base is used to limit the size (and therefore memory allocation) of the 169 // base is used to limit the size (and therefore memory allocation) of the
91 // region that results from scan converting devPath. 170 // region that results from scan converting devPath.
92 SkRegion base; 171 SkRegion base;
93 172
173 if (fForceConservativeRects) {
174 SkIRect ir;
175 switch (mutate_conservative_op(&op, path.isInverseFillType())) {
176 case kDoNothing_MutateResult:
177 return !this->isEmpty();
178 case kReplaceClippedAgainstGlobalBounds_MutateResult:
179 ir = SkIRect::MakeSize(size);
180 break;
181 case kContinue_MutateResult:
182 path.getBounds().roundOut(&ir);
183 break;
184 }
185 return this->op(ir, op);
186 }
187
94 if (SkRegion::kIntersect_Op == op) { 188 if (SkRegion::kIntersect_Op == op) {
95 // since we are intersect, we can do better (tighter) with currRgn's 189 // since we are intersect, we can do better (tighter) with currRgn's
96 // bounds, than just using the device. However, if currRgn is complex, 190 // bounds, than just using the device. However, if currRgn is complex,
97 // our region blitter may hork, so we do that case in two steps. 191 // our region blitter may hork, so we do that case in two steps.
98 if (this->isRect()) { 192 if (this->isRect()) {
99 // FIXME: we should also be able to do this when this->isBW(), 193 // FIXME: we should also be able to do this when this->isBW(),
100 // but relaxing the test above triggers GM asserts in 194 // but relaxing the test above triggers GM asserts in
101 // SkRgnBuilder::blitH(). We need to investigate what's going on. 195 // SkRgnBuilder::blitH(). We need to investigate what's going on.
102 return this->setPath(path, this->bwRgn(), doAA); 196 return this->setPath(path, this->bwRgn(), doAA);
103 } else { 197 } else {
104 base.setRect(this->getBounds()); 198 base.setRect(this->getBounds());
105 SkRasterClip clip; 199 SkRasterClip clip(fForceConservativeRects);
106 clip.setPath(path, base, doAA); 200 clip.setPath(path, base, doAA);
107 return this->op(clip, op); 201 return this->op(clip, op);
108 } 202 }
109 } else { 203 } else {
110 base.setRect(0, 0, size.width(), size.height()); 204 base.setRect(0, 0, size.width(), size.height());
111 205
112 if (SkRegion::kReplace_Op == op) { 206 if (SkRegion::kReplace_Op == op) {
113 return this->setPath(path, base, doAA); 207 return this->setPath(path, base, doAA);
114 } else { 208 } else {
115 SkRasterClip clip; 209 SkRasterClip clip(fForceConservativeRects);
116 clip.setPath(path, base, doAA); 210 clip.setPath(path, base, doAA);
117 return this->op(clip, op); 211 return this->op(clip, op);
118 } 212 }
119 } 213 }
120 } 214 }
121 215
122 bool SkRasterClip::setPath(const SkPath& path, const SkIRect& clip, bool doAA) { 216 bool SkRasterClip::setPath(const SkPath& path, const SkIRect& clip, bool doAA) {
123 SkRegion tmp; 217 SkRegion tmp;
124 tmp.setRect(clip); 218 tmp.setRect(clip);
125 return this->setPath(path, tmp, doAA); 219 return this->setPath(path, tmp, doAA);
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 * from its nearest int by < half of that value (1.8 in this case). 269 * from its nearest int by < half of that value (1.8 in this case).
176 */ 270 */
177 static bool nearly_integral(SkScalar x) { 271 static bool nearly_integral(SkScalar x) {
178 static const SkScalar domain = SK_Scalar1 / 4; 272 static const SkScalar domain = SK_Scalar1 / 4;
179 static const SkScalar halfDomain = domain / 2; 273 static const SkScalar halfDomain = domain / 2;
180 274
181 x += halfDomain; 275 x += halfDomain;
182 return x - SkScalarFloorToScalar(x) < domain; 276 return x - SkScalarFloorToScalar(x) < domain;
183 } 277 }
184 278
185 bool SkRasterClip::op(const SkRect& r, SkRegion::Op op, bool doAA) { 279 bool SkRasterClip::op(const SkRect& r, const SkISize& size, SkRegion::Op op, boo l doAA) {
186 AUTO_RASTERCLIP_VALIDATE(*this); 280 AUTO_RASTERCLIP_VALIDATE(*this);
187 281
282 if (fForceConservativeRects) {
283 SkIRect ir;
284 switch (mutate_conservative_op(&op, false)) {
285 case kDoNothing_MutateResult:
286 return !this->isEmpty();
287 case kReplaceClippedAgainstGlobalBounds_MutateResult:
288 ir = SkIRect::MakeSize(size);
289 break;
290 case kContinue_MutateResult:
291 r.roundOut(&ir);
292 break;
293 }
294 return this->op(ir, op);
295 }
296
188 if (fIsBW && doAA) { 297 if (fIsBW && doAA) {
189 // check that the rect really needs aa, or is it close enought to 298 // check that the rect really needs aa, or is it close enought to
190 // integer boundaries that we can just treat it as a BW rect? 299 // integer boundaries that we can just treat it as a BW rect?
191 if (nearly_integral(r.fLeft) && nearly_integral(r.fTop) && 300 if (nearly_integral(r.fLeft) && nearly_integral(r.fTop) &&
192 nearly_integral(r.fRight) && nearly_integral(r.fBottom)) { 301 nearly_integral(r.fRight) && nearly_integral(r.fBottom)) {
193 doAA = false; 302 doAA = false;
194 } 303 }
195 } 304 }
196 305
197 if (fIsBW && !doAA) { 306 if (fIsBW && !doAA) {
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 AUTO_RASTERCLIP_VALIDATE(*this); 353 AUTO_RASTERCLIP_VALIDATE(*this);
245 354
246 if (!fIsBW) { 355 if (!fIsBW) {
247 fBW.setRect(fAA.getBounds()); 356 fBW.setRect(fAA.getBounds());
248 } 357 }
249 return fBW; 358 return fBW;
250 } 359 }
251 360
252 void SkRasterClip::convertToAA() { 361 void SkRasterClip::convertToAA() {
253 AUTO_RASTERCLIP_VALIDATE(*this); 362 AUTO_RASTERCLIP_VALIDATE(*this);
254 363
364 SkASSERT(!fForceConservativeRects);
365
255 SkASSERT(fIsBW); 366 SkASSERT(fIsBW);
256 fAA.setRegion(fBW); 367 fAA.setRegion(fBW);
257 fIsBW = false; 368 fIsBW = false;
258 369
259 // since we are being explicitly asked to convert-to-aa, we pass false so we don't "optimize" 370 // since we are being explicitly asked to convert-to-aa, we pass false so we don't "optimize"
260 // ourselves back to BW. 371 // ourselves back to BW.
261 (void)this->updateCacheAndReturnNonEmpty(false); 372 (void)this->updateCacheAndReturnNonEmpty(false);
262 } 373 }
263 374
264 #ifdef SK_DEBUG 375 #ifdef SK_DEBUG
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 fBlitter = blitter; 417 fBlitter = blitter;
307 } else { 418 } else {
308 const SkAAClip& aaclip = clip.aaRgn(); 419 const SkAAClip& aaclip = clip.aaRgn();
309 fBWRgn.setRect(aaclip.getBounds()); 420 fBWRgn.setRect(aaclip.getBounds());
310 fAABlitter.init(blitter, &aaclip); 421 fAABlitter.init(blitter, &aaclip);
311 // now our return values 422 // now our return values
312 fClipRgn = &fBWRgn; 423 fClipRgn = &fBWRgn;
313 fBlitter = &fAABlitter; 424 fBlitter = &fAABlitter;
314 } 425 }
315 } 426 }
OLDNEW
« no previous file with comments | « src/core/SkRasterClip.h ('k') | src/core/SkRecorder.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698