OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 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 "GrReducedClip.h" | 8 #include "GrReducedClip.h" |
9 | 9 |
10 #include "GrAppliedClip.h" | 10 #include "GrAppliedClip.h" |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 return; | 67 return; |
68 } | 68 } |
69 | 69 |
70 SkRect tightBounds; | 70 SkRect tightBounds; |
71 SkAssertResult(tightBounds.intersect(stackBounds, queryBounds)); | 71 SkAssertResult(tightBounds.intersect(stackBounds, queryBounds)); |
72 fIBounds = GrClip::GetPixelIBounds(tightBounds); | 72 fIBounds = GrClip::GetPixelIBounds(tightBounds); |
73 SkASSERT(!fIBounds.isEmpty()); // Empty should have been blocked by IsOu
tsideClip above. | 73 SkASSERT(!fIBounds.isEmpty()); // Empty should have been blocked by IsOu
tsideClip above. |
74 fHasIBounds = true; | 74 fHasIBounds = true; |
75 | 75 |
76 // Implement the clip with an AA rect element. | 76 // Implement the clip with an AA rect element. |
77 fElements.addToHead(stackBounds, SkRegion::kReplace_Op, true/*doAA*/); | 77 fElements.addToHead(stackBounds, SkCanvas::kReplace_Op, true/*doAA*/); |
78 fElementsGenID = stack.getTopmostGenID(); | 78 fElementsGenID = stack.getTopmostGenID(); |
79 fRequiresAA = true; | 79 fRequiresAA = true; |
80 | 80 |
81 fInitialState = InitialState::kAllOut; | 81 fInitialState = InitialState::kAllOut; |
82 return; | 82 return; |
83 } | 83 } |
84 | 84 |
85 SkRect tighterQuery = queryBounds; | 85 SkRect tighterQuery = queryBounds; |
86 if (SkClipStack::kNormal_BoundsType == stackBoundsType) { | 86 if (SkClipStack::kNormal_BoundsType == stackBoundsType) { |
87 // Tighten the query by introducing a new clip at the stack's pixel boun
daries. (This new | 87 // Tighten the query by introducing a new clip at the stack's pixel boun
daries. (This new |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
139 } | 139 } |
140 if (SkClipStack::kWideOpenGenID == element->getGenID()) { | 140 if (SkClipStack::kWideOpenGenID == element->getGenID()) { |
141 initialTriState = InitialTriState::kAllIn; | 141 initialTriState = InitialTriState::kAllIn; |
142 break; | 142 break; |
143 } | 143 } |
144 | 144 |
145 bool skippable = false; | 145 bool skippable = false; |
146 bool isFlip = false; // does this op just flip the in/out state of every
point in the bounds | 146 bool isFlip = false; // does this op just flip the in/out state of every
point in the bounds |
147 | 147 |
148 switch (element->getOp()) { | 148 switch (element->getOp()) { |
149 case SkRegion::kDifference_Op: | 149 case SkCanvas::kDifference_Op: |
150 // check if the shape subtracted either contains the entire boun
ds (and makes | 150 // check if the shape subtracted either contains the entire boun
ds (and makes |
151 // the clip empty) or is outside the bounds and therefore can be
skipped. | 151 // the clip empty) or is outside the bounds and therefore can be
skipped. |
152 if (element->isInverseFilled()) { | 152 if (element->isInverseFilled()) { |
153 if (element->contains(relaxedQueryBounds)) { | 153 if (element->contains(relaxedQueryBounds)) { |
154 skippable = true; | 154 skippable = true; |
155 } else if (GrClip::IsOutsideClip(element->getBounds(), query
Bounds)) { | 155 } else if (GrClip::IsOutsideClip(element->getBounds(), query
Bounds)) { |
156 initialTriState = InitialTriState::kAllOut; | 156 initialTriState = InitialTriState::kAllOut; |
157 skippable = true; | 157 skippable = true; |
158 } | 158 } |
159 } else { | 159 } else { |
160 if (element->contains(relaxedQueryBounds)) { | 160 if (element->contains(relaxedQueryBounds)) { |
161 initialTriState = InitialTriState::kAllOut; | 161 initialTriState = InitialTriState::kAllOut; |
162 skippable = true; | 162 skippable = true; |
163 } else if (GrClip::IsOutsideClip(element->getBounds(), query
Bounds)) { | 163 } else if (GrClip::IsOutsideClip(element->getBounds(), query
Bounds)) { |
164 skippable = true; | 164 skippable = true; |
165 } else if (fWindowRects.count() < maxWindowRectangles && !em
biggens && | 165 } else if (fWindowRects.count() < maxWindowRectangles && !em
biggens && |
166 !element->isAA() && Element::kRect_Type == elemen
t->getType()) { | 166 !element->isAA() && Element::kRect_Type == elemen
t->getType()) { |
167 this->addWindowRectangle(element->getRect(), false); | 167 this->addWindowRectangle(element->getRect(), false); |
168 skippable = true; | 168 skippable = true; |
169 } | 169 } |
170 } | 170 } |
171 if (!skippable) { | 171 if (!skippable) { |
172 emsmallens = true; | 172 emsmallens = true; |
173 } | 173 } |
174 break; | 174 break; |
175 case SkRegion::kIntersect_Op: | 175 case SkCanvas::kIntersect_Op: |
176 // check if the shape intersected contains the entire bounds and
therefore can | 176 // check if the shape intersected contains the entire bounds and
therefore can |
177 // be skipped or it is outside the entire bounds and therefore m
akes the clip | 177 // be skipped or it is outside the entire bounds and therefore m
akes the clip |
178 // empty. | 178 // empty. |
179 if (element->isInverseFilled()) { | 179 if (element->isInverseFilled()) { |
180 if (element->contains(relaxedQueryBounds)) { | 180 if (element->contains(relaxedQueryBounds)) { |
181 initialTriState = InitialTriState::kAllOut; | 181 initialTriState = InitialTriState::kAllOut; |
182 skippable = true; | 182 skippable = true; |
183 } else if (GrClip::IsOutsideClip(element->getBounds(), query
Bounds)) { | 183 } else if (GrClip::IsOutsideClip(element->getBounds(), query
Bounds)) { |
184 skippable = true; | 184 skippable = true; |
185 } | 185 } |
(...skipping 12 matching lines...) Expand all Loading... |
198 if (!this->intersectIBounds(nonaaRect)) { | 198 if (!this->intersectIBounds(nonaaRect)) { |
199 return; | 199 return; |
200 } | 200 } |
201 skippable = true; | 201 skippable = true; |
202 } | 202 } |
203 } | 203 } |
204 if (!skippable) { | 204 if (!skippable) { |
205 emsmallens = true; | 205 emsmallens = true; |
206 } | 206 } |
207 break; | 207 break; |
208 case SkRegion::kUnion_Op: | 208 case SkCanvas::kUnion_Op: |
209 // If the union-ed shape contains the entire bounds then after t
his element | 209 // If the union-ed shape contains the entire bounds then after t
his element |
210 // the bounds is entirely inside the clip. If the union-ed shape
is outside the | 210 // the bounds is entirely inside the clip. If the union-ed shape
is outside the |
211 // bounds then this op can be skipped. | 211 // bounds then this op can be skipped. |
212 if (element->isInverseFilled()) { | 212 if (element->isInverseFilled()) { |
213 if (element->contains(relaxedQueryBounds)) { | 213 if (element->contains(relaxedQueryBounds)) { |
214 skippable = true; | 214 skippable = true; |
215 } else if (GrClip::IsOutsideClip(element->getBounds(), query
Bounds)) { | 215 } else if (GrClip::IsOutsideClip(element->getBounds(), query
Bounds)) { |
216 initialTriState = InitialTriState::kAllIn; | 216 initialTriState = InitialTriState::kAllIn; |
217 skippable = true; | 217 skippable = true; |
218 } | 218 } |
219 } else { | 219 } else { |
220 if (element->contains(relaxedQueryBounds)) { | 220 if (element->contains(relaxedQueryBounds)) { |
221 initialTriState = InitialTriState::kAllIn; | 221 initialTriState = InitialTriState::kAllIn; |
222 skippable = true; | 222 skippable = true; |
223 } else if (GrClip::IsOutsideClip(element->getBounds(), query
Bounds)) { | 223 } else if (GrClip::IsOutsideClip(element->getBounds(), query
Bounds)) { |
224 skippable = true; | 224 skippable = true; |
225 } | 225 } |
226 } | 226 } |
227 if (!skippable) { | 227 if (!skippable) { |
228 embiggens = true; | 228 embiggens = true; |
229 } | 229 } |
230 break; | 230 break; |
231 case SkRegion::kXOR_Op: | 231 case SkCanvas::kXOR_Op: |
232 // If the bounds is entirely inside the shape being xor-ed then
the effect is | 232 // If the bounds is entirely inside the shape being xor-ed then
the effect is |
233 // to flip the inside/outside state of every point in the bounds
. We may be | 233 // to flip the inside/outside state of every point in the bounds
. We may be |
234 // able to take advantage of this in the forward pass. If the xo
r-ed shape | 234 // able to take advantage of this in the forward pass. If the xo
r-ed shape |
235 // doesn't intersect the bounds then it can be skipped. | 235 // doesn't intersect the bounds then it can be skipped. |
236 if (element->isInverseFilled()) { | 236 if (element->isInverseFilled()) { |
237 if (element->contains(relaxedQueryBounds)) { | 237 if (element->contains(relaxedQueryBounds)) { |
238 skippable = true; | 238 skippable = true; |
239 } else if (GrClip::IsOutsideClip(element->getBounds(), query
Bounds)) { | 239 } else if (GrClip::IsOutsideClip(element->getBounds(), query
Bounds)) { |
240 isFlip = true; | 240 isFlip = true; |
241 } | 241 } |
242 } else { | 242 } else { |
243 if (element->contains(relaxedQueryBounds)) { | 243 if (element->contains(relaxedQueryBounds)) { |
244 isFlip = true; | 244 isFlip = true; |
245 } else if (GrClip::IsOutsideClip(element->getBounds(), query
Bounds)) { | 245 } else if (GrClip::IsOutsideClip(element->getBounds(), query
Bounds)) { |
246 skippable = true; | 246 skippable = true; |
247 } | 247 } |
248 } | 248 } |
249 if (!skippable) { | 249 if (!skippable) { |
250 emsmallens = embiggens = true; | 250 emsmallens = embiggens = true; |
251 } | 251 } |
252 break; | 252 break; |
253 case SkRegion::kReverseDifference_Op: | 253 case SkCanvas::kReverseDifference_Op: |
254 // When the bounds is entirely within the rev-diff shape then th
is behaves like xor | 254 // When the bounds is entirely within the rev-diff shape then th
is behaves like xor |
255 // and reverses every point inside the bounds. If the shape is c
ompletely outside | 255 // and reverses every point inside the bounds. If the shape is c
ompletely outside |
256 // the bounds then we know after this element is applied that th
e bounds will be | 256 // the bounds then we know after this element is applied that th
e bounds will be |
257 // all outside the current clip.B | 257 // all outside the current clip.B |
258 if (element->isInverseFilled()) { | 258 if (element->isInverseFilled()) { |
259 if (element->contains(relaxedQueryBounds)) { | 259 if (element->contains(relaxedQueryBounds)) { |
260 initialTriState = InitialTriState::kAllOut; | 260 initialTriState = InitialTriState::kAllOut; |
261 skippable = true; | 261 skippable = true; |
262 } else if (GrClip::IsOutsideClip(element->getBounds(), query
Bounds)) { | 262 } else if (GrClip::IsOutsideClip(element->getBounds(), query
Bounds)) { |
263 isFlip = true; | 263 isFlip = true; |
264 } | 264 } |
265 } else { | 265 } else { |
266 if (element->contains(relaxedQueryBounds)) { | 266 if (element->contains(relaxedQueryBounds)) { |
267 isFlip = true; | 267 isFlip = true; |
268 } else if (GrClip::IsOutsideClip(element->getBounds(), query
Bounds)) { | 268 } else if (GrClip::IsOutsideClip(element->getBounds(), query
Bounds)) { |
269 initialTriState = InitialTriState::kAllOut; | 269 initialTriState = InitialTriState::kAllOut; |
270 skippable = true; | 270 skippable = true; |
271 } | 271 } |
272 } | 272 } |
273 if (!skippable) { | 273 if (!skippable) { |
274 emsmallens = embiggens = true; | 274 emsmallens = embiggens = true; |
275 } | 275 } |
276 break; | 276 break; |
277 | 277 |
278 case SkRegion::kReplace_Op: | 278 case SkCanvas::kReplace_Op: |
279 // Replace will always terminate our walk. We will either begin
the forward walk | 279 // Replace will always terminate our walk. We will either begin
the forward walk |
280 // at the replace op or detect here than the shape is either com
pletely inside | 280 // at the replace op or detect here than the shape is either com
pletely inside |
281 // or completely outside the bounds. In this latter case it can
be skipped by | 281 // or completely outside the bounds. In this latter case it can
be skipped by |
282 // setting the correct value for initialTriState. | 282 // setting the correct value for initialTriState. |
283 if (element->isInverseFilled()) { | 283 if (element->isInverseFilled()) { |
284 if (element->contains(relaxedQueryBounds)) { | 284 if (element->contains(relaxedQueryBounds)) { |
285 initialTriState = InitialTriState::kAllOut; | 285 initialTriState = InitialTriState::kAllOut; |
286 skippable = true; | 286 skippable = true; |
287 } else if (GrClip::IsOutsideClip(element->getBounds(), query
Bounds)) { | 287 } else if (GrClip::IsOutsideClip(element->getBounds(), query
Bounds)) { |
288 initialTriState = InitialTriState::kAllIn; | 288 initialTriState = InitialTriState::kAllIn; |
(...skipping 29 matching lines...) Expand all Loading... |
318 break; | 318 break; |
319 } | 319 } |
320 if (!skippable) { | 320 if (!skippable) { |
321 if (0 == fElements.count()) { | 321 if (0 == fElements.count()) { |
322 // This will be the last element. Record the stricter genID. | 322 // This will be the last element. Record the stricter genID. |
323 fElementsGenID = element->getGenID(); | 323 fElementsGenID = element->getGenID(); |
324 } | 324 } |
325 | 325 |
326 // if it is a flip, change it to a bounds-filling rect | 326 // if it is a flip, change it to a bounds-filling rect |
327 if (isFlip) { | 327 if (isFlip) { |
328 SkASSERT(SkRegion::kXOR_Op == element->getOp() || | 328 SkASSERT(SkCanvas::kXOR_Op == element->getOp() || |
329 SkRegion::kReverseDifference_Op == element->getOp()); | 329 SkCanvas::kReverseDifference_Op == element->getOp()); |
330 fElements.addToHead(SkRect::Make(fIBounds), SkRegion::kReverseDi
fference_Op, false); | 330 fElements.addToHead(SkRect::Make(fIBounds), SkCanvas::kReverseDi
fference_Op, false); |
331 } else { | 331 } else { |
332 Element* newElement = fElements.addToHead(*element); | 332 Element* newElement = fElements.addToHead(*element); |
333 if (newElement->isAA()) { | 333 if (newElement->isAA()) { |
334 ++numAAElements; | 334 ++numAAElements; |
335 } | 335 } |
336 // Intersecting an inverse shape is the same as differencing the
non-inverse shape. | 336 // Intersecting an inverse shape is the same as differencing the
non-inverse shape. |
337 // Replacing with an inverse shape is the same as setting initia
lState=kAllIn and | 337 // Replacing with an inverse shape is the same as setting initia
lState=kAllIn and |
338 // differencing the non-inverse shape. | 338 // differencing the non-inverse shape. |
339 bool isReplace = SkRegion::kReplace_Op == newElement->getOp(); | 339 bool isReplace = SkCanvas::kReplace_Op == newElement->getOp(); |
340 if (newElement->isInverseFilled() && | 340 if (newElement->isInverseFilled() && |
341 (SkRegion::kIntersect_Op == newElement->getOp() || isReplace
)) { | 341 (SkCanvas::kIntersect_Op == newElement->getOp() || isReplace
)) { |
342 newElement->invertShapeFillType(); | 342 newElement->invertShapeFillType(); |
343 newElement->setOp(SkRegion::kDifference_Op); | 343 newElement->setOp(SkCanvas::kDifference_Op); |
344 if (isReplace) { | 344 if (isReplace) { |
345 SkASSERT(InitialTriState::kAllOut == initialTriState); | 345 SkASSERT(InitialTriState::kAllOut == initialTriState); |
346 initialTriState = InitialTriState::kAllIn; | 346 initialTriState = InitialTriState::kAllIn; |
347 } | 347 } |
348 } | 348 } |
349 } | 349 } |
350 } | 350 } |
351 } | 351 } |
352 | 352 |
353 if ((InitialTriState::kAllOut == initialTriState && !embiggens) || | 353 if ((InitialTriState::kAllOut == initialTriState && !embiggens) || |
354 (InitialTriState::kAllIn == initialTriState && !emsmallens)) { | 354 (InitialTriState::kAllIn == initialTriState && !emsmallens)) { |
355 fElements.reset(); | 355 fElements.reset(); |
356 numAAElements = 0; | 356 numAAElements = 0; |
357 } else { | 357 } else { |
358 Element* element = fElements.headIter().get(); | 358 Element* element = fElements.headIter().get(); |
359 while (element) { | 359 while (element) { |
360 bool skippable = false; | 360 bool skippable = false; |
361 switch (element->getOp()) { | 361 switch (element->getOp()) { |
362 case SkRegion::kDifference_Op: | 362 case SkCanvas::kDifference_Op: |
363 // subtracting from the empty set yields the empty set. | 363 // subtracting from the empty set yields the empty set. |
364 skippable = InitialTriState::kAllOut == initialTriState; | 364 skippable = InitialTriState::kAllOut == initialTriState; |
365 break; | 365 break; |
366 case SkRegion::kIntersect_Op: | 366 case SkCanvas::kIntersect_Op: |
367 // intersecting with the empty set yields the empty set | 367 // intersecting with the empty set yields the empty set |
368 if (InitialTriState::kAllOut == initialTriState) { | 368 if (InitialTriState::kAllOut == initialTriState) { |
369 skippable = true; | 369 skippable = true; |
370 } else { | 370 } else { |
371 // We can clear to zero and then simply draw the clip el
ement. | 371 // We can clear to zero and then simply draw the clip el
ement. |
372 initialTriState = InitialTriState::kAllOut; | 372 initialTriState = InitialTriState::kAllOut; |
373 element->setOp(SkRegion::kReplace_Op); | 373 element->setOp(SkCanvas::kReplace_Op); |
374 } | 374 } |
375 break; | 375 break; |
376 case SkRegion::kUnion_Op: | 376 case SkCanvas::kUnion_Op: |
377 if (InitialTriState::kAllIn == initialTriState) { | 377 if (InitialTriState::kAllIn == initialTriState) { |
378 // unioning the infinite plane with anything is a no-op. | 378 // unioning the infinite plane with anything is a no-op. |
379 skippable = true; | 379 skippable = true; |
380 } else { | 380 } else { |
381 // unioning the empty set with a shape is the shape. | 381 // unioning the empty set with a shape is the shape. |
382 element->setOp(SkRegion::kReplace_Op); | 382 element->setOp(SkCanvas::kReplace_Op); |
383 } | 383 } |
384 break; | 384 break; |
385 case SkRegion::kXOR_Op: | 385 case SkCanvas::kXOR_Op: |
386 if (InitialTriState::kAllOut == initialTriState) { | 386 if (InitialTriState::kAllOut == initialTriState) { |
387 // xor could be changed to diff in the kAllIn case, not
sure it's a win. | 387 // xor could be changed to diff in the kAllIn case, not
sure it's a win. |
388 element->setOp(SkRegion::kReplace_Op); | 388 element->setOp(SkCanvas::kReplace_Op); |
389 } | 389 } |
390 break; | 390 break; |
391 case SkRegion::kReverseDifference_Op: | 391 case SkCanvas::kReverseDifference_Op: |
392 if (InitialTriState::kAllIn == initialTriState) { | 392 if (InitialTriState::kAllIn == initialTriState) { |
393 // subtracting the whole plane will yield the empty set. | 393 // subtracting the whole plane will yield the empty set. |
394 skippable = true; | 394 skippable = true; |
395 initialTriState = InitialTriState::kAllOut; | 395 initialTriState = InitialTriState::kAllOut; |
396 } else { | 396 } else { |
397 // this picks up flips inserted in the backwards pass. | 397 // this picks up flips inserted in the backwards pass. |
398 skippable = element->isInverseFilled() ? | 398 skippable = element->isInverseFilled() ? |
399 GrClip::IsOutsideClip(element->getBounds(), queryBou
nds) : | 399 GrClip::IsOutsideClip(element->getBounds(), queryBou
nds) : |
400 element->contains(relaxedQueryBounds); | 400 element->contains(relaxedQueryBounds); |
401 if (skippable) { | 401 if (skippable) { |
402 initialTriState = InitialTriState::kAllIn; | 402 initialTriState = InitialTriState::kAllIn; |
403 } else { | 403 } else { |
404 element->setOp(SkRegion::kReplace_Op); | 404 element->setOp(SkCanvas::kReplace_Op); |
405 } | 405 } |
406 } | 406 } |
407 break; | 407 break; |
408 case SkRegion::kReplace_Op: | 408 case SkCanvas::kReplace_Op: |
409 skippable = false; // we would have skipped it in the backwa
rds walk if we | 409 skippable = false; // we would have skipped it in the backwa
rds walk if we |
410 // could've. | 410 // could've. |
411 break; | 411 break; |
412 default: | 412 default: |
413 SkDEBUGFAIL("Unexpected op."); | 413 SkDEBUGFAIL("Unexpected op."); |
414 break; | 414 break; |
415 } | 415 } |
416 if (!skippable) { | 416 if (!skippable) { |
417 break; | 417 break; |
418 } else { | 418 } else { |
419 if (element->isAA()) { | 419 if (element->isAA()) { |
420 --numAAElements; | 420 --numAAElements; |
421 } | 421 } |
422 fElements.popHead(); | 422 fElements.popHead(); |
423 element = fElements.headIter().get(); | 423 element = fElements.headIter().get(); |
424 } | 424 } |
425 } | 425 } |
426 } | 426 } |
427 fRequiresAA = numAAElements > 0; | 427 fRequiresAA = numAAElements > 0; |
428 | 428 |
429 SkASSERT(InitialTriState::kUnknown != initialTriState); | 429 SkASSERT(InitialTriState::kUnknown != initialTriState); |
430 fInitialState = static_cast<GrReducedClip::InitialState>(initialTriState); | 430 fInitialState = static_cast<GrReducedClip::InitialState>(initialTriState); |
431 } | 431 } |
432 | 432 |
433 static bool element_is_pure_subtract(SkRegion::Op op) { | 433 static bool element_is_pure_subtract(SkCanvas::ClipOp op) { |
434 SkASSERT(op >= 0); | 434 SkASSERT(op >= 0); |
435 return op <= SkRegion::kIntersect_Op; | 435 return op <= SkCanvas::kIntersect_Op; |
436 | 436 |
437 GR_STATIC_ASSERT(0 == SkRegion::kDifference_Op); | 437 GR_STATIC_ASSERT(0 == SkCanvas::kDifference_Op); |
438 GR_STATIC_ASSERT(1 == SkRegion::kIntersect_Op); | 438 GR_STATIC_ASSERT(1 == SkCanvas::kIntersect_Op); |
439 } | 439 } |
440 | 440 |
441 void GrReducedClip::addInteriorWindowRectangles(int maxWindowRectangles) { | 441 void GrReducedClip::addInteriorWindowRectangles(int maxWindowRectangles) { |
442 SkASSERT(fWindowRects.count() < maxWindowRectangles); | 442 SkASSERT(fWindowRects.count() < maxWindowRectangles); |
443 // Walk backwards through the element list and add window rectangles to the
interiors of | 443 // Walk backwards through the element list and add window rectangles to the
interiors of |
444 // "difference" elements. Quit if we encounter an element that may grow the
clip. | 444 // "difference" elements. Quit if we encounter an element that may grow the
clip. |
445 ElementList::Iter iter(fElements, ElementList::Iter::kTail_IterStart); | 445 ElementList::Iter iter(fElements, ElementList::Iter::kTail_IterStart); |
446 for (; iter.get() && element_is_pure_subtract(iter.get()->getOp()); iter.pre
v()) { | 446 for (; iter.get() && element_is_pure_subtract(iter.get()->getOp()); iter.pre
v()) { |
447 const Element* element = iter.get(); | 447 const Element* element = iter.get(); |
448 if (SkRegion::kDifference_Op != element->getOp()) { | 448 if (SkCanvas::kDifference_Op != element->getOp()) { |
449 continue; | 449 continue; |
450 } | 450 } |
451 | 451 |
452 if (Element::kRect_Type == element->getType()) { | 452 if (Element::kRect_Type == element->getType()) { |
453 SkASSERT(element->isAA()); | 453 SkASSERT(element->isAA()); |
454 this->addWindowRectangle(element->getRect(), true); | 454 this->addWindowRectangle(element->getRect(), true); |
455 if (fWindowRects.count() >= maxWindowRectangles) { | 455 if (fWindowRects.count() >= maxWindowRectangles) { |
456 return; | 456 return; |
457 } | 457 } |
458 continue; | 458 continue; |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
529 const SkMatrix& viewMatrix, | 529 const SkMatrix& viewMatrix, |
530 const SkClipStack::Element* element) { | 530 const SkClipStack::Element* element) { |
531 | 531 |
532 // TODO: Draw rrects directly here. | 532 // TODO: Draw rrects directly here. |
533 switch (element->getType()) { | 533 switch (element->getType()) { |
534 case Element::kEmpty_Type: | 534 case Element::kEmpty_Type: |
535 SkDEBUGFAIL("Should never get here with an empty element."); | 535 SkDEBUGFAIL("Should never get here with an empty element."); |
536 break; | 536 break; |
537 case Element::kRect_Type: | 537 case Element::kRect_Type: |
538 return dc->drawContextPriv().drawAndStencilRect(clip, ss, | 538 return dc->drawContextPriv().drawAndStencilRect(clip, ss, |
539 element->getOp(), | 539 (SkRegion::Op)elemen
t->getOp(), |
540 element->isInverseFi
lled(), | 540 element->isInverseFi
lled(), |
541 element->isAA(), | 541 element->isAA(), |
542 viewMatrix, element-
>getRect()); | 542 viewMatrix, element-
>getRect()); |
543 break; | 543 break; |
544 default: { | 544 default: { |
545 SkPath path; | 545 SkPath path; |
546 element->asPath(&path); | 546 element->asPath(&path); |
547 if (path.isInverseFillType()) { | 547 if (path.isInverseFillType()) { |
548 path.toggleInverseFillType(); | 548 path.toggleInverseFillType(); |
549 } | 549 } |
550 | 550 |
551 return dc->drawContextPriv().drawAndStencilPath(clip, ss, | 551 return dc->drawContextPriv().drawAndStencilPath(clip, ss, |
552 element->getOp(), | 552 (SkRegion::Op)elemen
t->getOp(), |
553 element->isInverseFi
lled(), | 553 element->isInverseFi
lled(), |
554 element->isAA(), vie
wMatrix, path); | 554 element->isAA(), vie
wMatrix, path); |
555 break; | 555 break; |
556 } | 556 } |
557 } | 557 } |
558 | 558 |
559 return false; | 559 return false; |
560 } | 560 } |
561 | 561 |
562 static void draw_element(GrDrawContext* dc, | 562 static void draw_element(GrDrawContext* dc, |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
601 GrColor initialCoverage = InitialState::kAllIn == this->initialState() ? -1
: 0; | 601 GrColor initialCoverage = InitialState::kAllIn == this->initialState() ? -1
: 0; |
602 dc->drawContextPriv().clear(clip, initialCoverage, true); | 602 dc->drawContextPriv().clear(clip, initialCoverage, true); |
603 | 603 |
604 // Set the matrix so that rendered clip elements are transformed to mask spa
ce from clip space. | 604 // Set the matrix so that rendered clip elements are transformed to mask spa
ce from clip space. |
605 SkMatrix translate; | 605 SkMatrix translate; |
606 translate.setTranslate(SkIntToScalar(-fIBounds.left()), SkIntToScalar(-fIBou
nds.top())); | 606 translate.setTranslate(SkIntToScalar(-fIBounds.left()), SkIntToScalar(-fIBou
nds.top())); |
607 | 607 |
608 // walk through each clip element and perform its set op | 608 // walk through each clip element and perform its set op |
609 for (ElementList::Iter iter(fElements); iter.get(); iter.next()) { | 609 for (ElementList::Iter iter(fElements); iter.get(); iter.next()) { |
610 const Element* element = iter.get(); | 610 const Element* element = iter.get(); |
611 SkRegion::Op op = element->getOp(); | 611 SkRegion::Op op = (SkRegion::Op)element->getOp(); |
612 bool invert = element->isInverseFilled(); | 612 bool invert = element->isInverseFilled(); |
613 if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDiffere
nce_Op == op) { | 613 if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDiffere
nce_Op == op) { |
614 // draw directly into the result with the stencil set to make the pi
xels affected | 614 // draw directly into the result with the stencil set to make the pi
xels affected |
615 // by the clip shape be non-zero. | 615 // by the clip shape be non-zero. |
616 static constexpr GrUserStencilSettings kStencilInElement( | 616 static constexpr GrUserStencilSettings kStencilInElement( |
617 GrUserStencilSettings::StaticInit< | 617 GrUserStencilSettings::StaticInit< |
618 0xffff, | 618 0xffff, |
619 GrUserStencilTest::kAlways, | 619 GrUserStencilTest::kAlways, |
620 0xffff, | 620 0xffff, |
621 GrUserStencilOp::kReplace, | 621 GrUserStencilOp::kReplace, |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
715 for (ElementList::Iter iter(fElements); iter.get(); iter.next()) { | 715 for (ElementList::Iter iter(fElements); iter.get(); iter.next()) { |
716 const Element* element = iter.get(); | 716 const Element* element = iter.get(); |
717 bool useHWAA = element->isAA() && drawContext->isStencilBufferMultisampl
ed(); | 717 bool useHWAA = element->isAA() && drawContext->isStencilBufferMultisampl
ed(); |
718 | 718 |
719 bool fillInverted = false; | 719 bool fillInverted = false; |
720 | 720 |
721 // This will be used to determine whether the clip shape can be rendered
into the | 721 // This will be used to determine whether the clip shape can be rendered
into the |
722 // stencil with arbitrary stencil settings. | 722 // stencil with arbitrary stencil settings. |
723 GrPathRenderer::StencilSupport stencilSupport; | 723 GrPathRenderer::StencilSupport stencilSupport; |
724 | 724 |
725 SkRegion::Op op = element->getOp(); | 725 SkRegion::Op op = (SkRegion::Op)element->getOp(); |
726 | 726 |
727 GrPathRenderer* pr = nullptr; | 727 GrPathRenderer* pr = nullptr; |
728 SkPath clipPath; | 728 SkPath clipPath; |
729 if (Element::kRect_Type == element->getType()) { | 729 if (Element::kRect_Type == element->getType()) { |
730 stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport; | 730 stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport; |
731 fillInverted = false; | 731 fillInverted = false; |
732 } else { | 732 } else { |
733 element->asPath(&clipPath); | 733 element->asPath(&clipPath); |
734 fillInverted = clipPath.isInverseFillType(); | 734 fillInverted = clipPath.isInverseFillType(); |
735 if (fillInverted) { | 735 if (fillInverted) { |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
840 // The view matrix is setup to do clip space -> stencil space tr
anslation, so | 840 // The view matrix is setup to do clip space -> stencil space tr
anslation, so |
841 // draw rect in clip space. | 841 // draw rect in clip space. |
842 drawContext->drawContextPriv().stencilRect(stencilClip, *pass, | 842 drawContext->drawContextPriv().stencilRect(stencilClip, *pass, |
843 false, viewMatrix, | 843 false, viewMatrix, |
844 SkRect::Make(fIBounds
)); | 844 SkRect::Make(fIBounds
)); |
845 } | 845 } |
846 } | 846 } |
847 } | 847 } |
848 return true; | 848 return true; |
849 } | 849 } |
OLD | NEW |