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

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 *op = SkRegion::kReplace_Op;
117 return kReplaceClippedAgainstGlobalBounds_MutateResult;
118 }
119 }
120 } else {
121 // Not inverse filled
122 switch (*op) {
123 case SkRegion::kIntersect_Op:
124 case SkRegion::kUnion_Op:
125 case SkRegion::kReplace_Op:
126 return kContinue_MutateResult;
127 case SkRegion::kDifference_Op:
128 // Difference can only shrink the current clip.
129 // Leaving clip unchanged conservatively fullfills the contract.
130 return kDoNothing_MutateResult;
131 case SkRegion::kReverseDifference_Op:
132 // To reverse, we swap in the bounds with a replace op.
133 // As with difference, leave it unchanged.
134 *op = SkRegion::kReplace_Op;
135 return kContinue_MutateResult;
136 case SkRegion::kXOR_Op:
137 // Be conservative, based on (A XOR B) always included in (A uni on B),
138 // which is always included in (bounds(A) union bounds(B))
139 *op = SkRegion::kUnion_Op;
140 return kContinue_MutateResult;
141 }
142 }
143 SkFAIL("should not get here");
144 return kDoNothing_MutateResult;
145 }
146
73 bool SkRasterClip::setPath(const SkPath& path, const SkRegion& clip, bool doAA) { 147 bool SkRasterClip::setPath(const SkPath& path, const SkRegion& clip, bool doAA) {
74 AUTO_RASTERCLIP_VALIDATE(*this); 148 AUTO_RASTERCLIP_VALIDATE(*this);
75 149
150 if (fForceConservativeRects) {
151 return this->setConservativeRect(path.getBounds(), clip.getBounds(), pat h.isInverseFillType());
152 }
153
76 if (this->isBW() && !doAA) { 154 if (this->isBW() && !doAA) {
77 (void)fBW.setPath(path, clip); 155 (void)fBW.setPath(path, clip);
78 } else { 156 } else {
79 // TODO: since we are going to over-write fAA completely (aren't we?) 157 // 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 158 // we should just clear our BW data (if any) and set fIsAA=true
81 if (this->isBW()) { 159 if (this->isBW()) {
82 this->convertToAA(); 160 this->convertToAA();
83 } 161 }
84 (void)fAA.setPath(path, &clip, doAA); 162 (void)fAA.setPath(path, &clip, doAA);
85 } 163 }
86 return this->updateCacheAndReturnNonEmpty(); 164 return this->updateCacheAndReturnNonEmpty();
87 } 165 }
88 166
89 bool SkRasterClip::op(const SkPath& path, const SkISize& size, SkRegion::Op op, bool doAA) { 167 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 168 // base is used to limit the size (and therefore memory allocation) of the
91 // region that results from scan converting devPath. 169 // region that results from scan converting devPath.
92 SkRegion base; 170 SkRegion base;
93 171
robertphillips 2014/09/10 14:44:23 Subroutine for this and the version in SkRasterCli
172 if (fForceConservativeRects) {
173 SkIRect ir;
174 switch (mutate_conservative_op(&op, path.isInverseFillType())) {
175 case kDoNothing_MutateResult:
176 return !this->isEmpty();
177 case kReplaceClippedAgainstGlobalBounds_MutateResult:
178 ir = SkIRect::MakeSize(size);
179 break;
180 case kContinue_MutateResult:
181 path.getBounds().roundOut(&ir);
182 break;
183 }
184 return this->op(ir, op);
185 }
186
94 if (SkRegion::kIntersect_Op == op) { 187 if (SkRegion::kIntersect_Op == op) {
95 // since we are intersect, we can do better (tighter) with currRgn's 188 // since we are intersect, we can do better (tighter) with currRgn's
96 // bounds, than just using the device. However, if currRgn is complex, 189 // 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. 190 // our region blitter may hork, so we do that case in two steps.
98 if (this->isRect()) { 191 if (this->isRect()) {
99 // FIXME: we should also be able to do this when this->isBW(), 192 // FIXME: we should also be able to do this when this->isBW(),
100 // but relaxing the test above triggers GM asserts in 193 // but relaxing the test above triggers GM asserts in
101 // SkRgnBuilder::blitH(). We need to investigate what's going on. 194 // SkRgnBuilder::blitH(). We need to investigate what's going on.
102 return this->setPath(path, this->bwRgn(), doAA); 195 return this->setPath(path, this->bwRgn(), doAA);
103 } else { 196 } else {
104 base.setRect(this->getBounds()); 197 base.setRect(this->getBounds());
105 SkRasterClip clip; 198 SkRasterClip clip(fForceConservativeRects);
106 clip.setPath(path, base, doAA); 199 clip.setPath(path, base, doAA);
107 return this->op(clip, op); 200 return this->op(clip, op);
108 } 201 }
109 } else { 202 } else {
110 base.setRect(0, 0, size.width(), size.height()); 203 base.setRect(0, 0, size.width(), size.height());
111 204
112 if (SkRegion::kReplace_Op == op) { 205 if (SkRegion::kReplace_Op == op) {
113 return this->setPath(path, base, doAA); 206 return this->setPath(path, base, doAA);
114 } else { 207 } else {
115 SkRasterClip clip; 208 SkRasterClip clip(fForceConservativeRects);
116 clip.setPath(path, base, doAA); 209 clip.setPath(path, base, doAA);
117 return this->op(clip, op); 210 return this->op(clip, op);
118 } 211 }
119 } 212 }
120 } 213 }
121 214
122 bool SkRasterClip::setPath(const SkPath& path, const SkIRect& clip, bool doAA) { 215 bool SkRasterClip::setPath(const SkPath& path, const SkIRect& clip, bool doAA) {
123 SkRegion tmp; 216 SkRegion tmp;
124 tmp.setRect(clip); 217 tmp.setRect(clip);
125 return this->setPath(path, tmp, doAA); 218 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). 268 * from its nearest int by < half of that value (1.8 in this case).
176 */ 269 */
177 static bool nearly_integral(SkScalar x) { 270 static bool nearly_integral(SkScalar x) {
178 static const SkScalar domain = SK_Scalar1 / 4; 271 static const SkScalar domain = SK_Scalar1 / 4;
179 static const SkScalar halfDomain = domain / 2; 272 static const SkScalar halfDomain = domain / 2;
180 273
181 x += halfDomain; 274 x += halfDomain;
182 return x - SkScalarFloorToScalar(x) < domain; 275 return x - SkScalarFloorToScalar(x) < domain;
183 } 276 }
184 277
185 bool SkRasterClip::op(const SkRect& r, SkRegion::Op op, bool doAA) { 278 bool SkRasterClip::op(const SkRect& r, const SkISize& size, SkRegion::Op op, boo l doAA) {
186 AUTO_RASTERCLIP_VALIDATE(*this); 279 AUTO_RASTERCLIP_VALIDATE(*this);
187 280
281 if (fForceConservativeRects) {
282 SkIRect ir;
283 switch (mutate_conservative_op(&op, false)) {
284 case kDoNothing_MutateResult:
285 return !this->isEmpty();
286 case kReplaceClippedAgainstGlobalBounds_MutateResult:
287 ir = SkIRect::MakeSize(size);
288 break;
289 case kContinue_MutateResult:
290 r.roundOut(&ir);
291 break;
292 }
293 return this->op(ir, op);
294 }
295
188 if (fIsBW && doAA) { 296 if (fIsBW && doAA) {
189 // check that the rect really needs aa, or is it close enought to 297 // 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? 298 // integer boundaries that we can just treat it as a BW rect?
191 if (nearly_integral(r.fLeft) && nearly_integral(r.fTop) && 299 if (nearly_integral(r.fLeft) && nearly_integral(r.fTop) &&
192 nearly_integral(r.fRight) && nearly_integral(r.fBottom)) { 300 nearly_integral(r.fRight) && nearly_integral(r.fBottom)) {
193 doAA = false; 301 doAA = false;
194 } 302 }
195 } 303 }
196 304
197 if (fIsBW && !doAA) { 305 if (fIsBW && !doAA) {
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 AUTO_RASTERCLIP_VALIDATE(*this); 352 AUTO_RASTERCLIP_VALIDATE(*this);
245 353
246 if (!fIsBW) { 354 if (!fIsBW) {
247 fBW.setRect(fAA.getBounds()); 355 fBW.setRect(fAA.getBounds());
248 } 356 }
249 return fBW; 357 return fBW;
250 } 358 }
251 359
252 void SkRasterClip::convertToAA() { 360 void SkRasterClip::convertToAA() {
253 AUTO_RASTERCLIP_VALIDATE(*this); 361 AUTO_RASTERCLIP_VALIDATE(*this);
254 362
363 SkASSERT(!fForceConservativeRects);
364
255 SkASSERT(fIsBW); 365 SkASSERT(fIsBW);
256 fAA.setRegion(fBW); 366 fAA.setRegion(fBW);
257 fIsBW = false; 367 fIsBW = false;
258 368
259 // since we are being explicitly asked to convert-to-aa, we pass false so we don't "optimize" 369 // since we are being explicitly asked to convert-to-aa, we pass false so we don't "optimize"
260 // ourselves back to BW. 370 // ourselves back to BW.
261 (void)this->updateCacheAndReturnNonEmpty(false); 371 (void)this->updateCacheAndReturnNonEmpty(false);
262 } 372 }
263 373
264 #ifdef SK_DEBUG 374 #ifdef SK_DEBUG
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 fBlitter = blitter; 416 fBlitter = blitter;
307 } else { 417 } else {
308 const SkAAClip& aaclip = clip.aaRgn(); 418 const SkAAClip& aaclip = clip.aaRgn();
309 fBWRgn.setRect(aaclip.getBounds()); 419 fBWRgn.setRect(aaclip.getBounds());
310 fAABlitter.init(blitter, &aaclip); 420 fAABlitter.init(blitter, &aaclip);
311 // now our return values 421 // now our return values
312 fClipRgn = &fBWRgn; 422 fClipRgn = &fBWRgn;
313 fBlitter = &fAABlitter; 423 fBlitter = &fAABlitter;
314 } 424 }
315 } 425 }
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