OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2012 Google Inc. | 3 * Copyright 2012 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 #include "GrReducedClip.h" | 9 #include "GrReducedClip.h" |
10 | 10 |
11 typedef SkClipStack::Element Element; | 11 typedef SkClipStack::Element Element; |
12 //////////////////////////////////////////////////////////////////////////////// | 12 //////////////////////////////////////////////////////////////////////////////// |
13 | 13 |
14 namespace GrReducedClip { | 14 namespace GrReducedClip { |
15 | 15 |
16 // helper function | 16 // helper function |
17 void reduced_stack_walker(const SkClipStack& stack, | 17 void reduced_stack_walker(const SkClipStack& stack, |
18 const SkRect& queryBounds, | 18 const SkRect& queryBounds, |
19 ElementList* result, | 19 ElementList* result, |
| 20 int32_t* resultGenID, |
20 InitialState* initialState, | 21 InitialState* initialState, |
21 bool* requiresAA); | 22 bool* requiresAA); |
22 | 23 |
23 /* | 24 /* |
24 There are plenty of optimizations that could be added here. Maybe flips could be
folded into | 25 There are plenty of optimizations that could be added here. Maybe flips could be
folded into |
25 earlier operations. Or would inserting flips and reversing earlier ops ever be a
win? Perhaps | 26 earlier operations. Or would inserting flips and reversing earlier ops ever be a
win? Perhaps |
26 for the case where the bounds are kInsideOut_BoundsType. We could restrict earli
er operations | 27 for the case where the bounds are kInsideOut_BoundsType. We could restrict earli
er operations |
27 based on later intersect operations, and perhaps remove intersect-rects. We coul
d optionally | 28 based on later intersect operations, and perhaps remove intersect-rects. We coul
d optionally |
28 take a rect in case the caller knows a bound on what is to be drawn through this
clip. | 29 take a rect in case the caller knows a bound on what is to be drawn through this
clip. |
29 */ | 30 */ |
30 void ReduceClipStack(const SkClipStack& stack, | 31 void ReduceClipStack(const SkClipStack& stack, |
31 const SkIRect& queryBounds, | 32 const SkIRect& queryBounds, |
32 ElementList* result, | 33 ElementList* result, |
| 34 int32_t* resultGenID, |
33 InitialState* initialState, | 35 InitialState* initialState, |
34 SkIRect* tighterBounds, | 36 SkIRect* tighterBounds, |
35 bool* requiresAA) { | 37 bool* requiresAA) { |
36 result->reset(); | 38 result->reset(); |
37 | 39 |
| 40 // The clip established by the element list might be cached based on the las
t |
| 41 // generation id. When we make early returns, we do not know what was the ge
neration |
| 42 // id that lead to the state. Make a conservative guess. |
| 43 *resultGenID = stack.getTopmostGenID(); |
| 44 |
38 if (stack.isWideOpen()) { | 45 if (stack.isWideOpen()) { |
39 *initialState = kAllIn_InitialState; | 46 *initialState = kAllIn_InitialState; |
40 return; | 47 return; |
41 } | 48 } |
42 | 49 |
43 | 50 |
44 // We initially look at whether the bounds alone is sufficient. We also use
the stack bounds to | 51 // We initially look at whether the bounds alone is sufficient. We also use
the stack bounds to |
45 // attempt to compute the tighterBounds. | 52 // attempt to compute the tighterBounds. |
46 | 53 |
47 SkClipStack::BoundsType stackBoundsType; | 54 SkClipStack::BoundsType stackBoundsType; |
(...skipping 15 matching lines...) Expand all Loading... |
63 } | 70 } |
64 if (NULL != requiresAA) { | 71 if (NULL != requiresAA) { |
65 *requiresAA = false; | 72 *requiresAA = false; |
66 } | 73 } |
67 } else if (isectRect.intersect(stackBounds, scalarQueryBounds)) { | 74 } else if (isectRect.intersect(stackBounds, scalarQueryBounds)) { |
68 if (NULL != tighterBounds) { | 75 if (NULL != tighterBounds) { |
69 isectRect.roundOut(tighterBounds); | 76 isectRect.roundOut(tighterBounds); |
70 SkRect scalarTighterBounds = SkRect::Make(*tighterBounds); | 77 SkRect scalarTighterBounds = SkRect::Make(*tighterBounds); |
71 if (scalarTighterBounds == isectRect) { | 78 if (scalarTighterBounds == isectRect) { |
72 // the round-out didn't add any area outside the clip rect. | 79 // the round-out didn't add any area outside the clip rect. |
73 *requiresAA = false; | 80 if (NULL != requiresAA) { |
| 81 *requiresAA = false; |
| 82 } |
74 *initialState = kAllIn_InitialState; | 83 *initialState = kAllIn_InitialState; |
75 return; | 84 return; |
76 } | 85 } |
77 *initialState = kAllOut_InitialState; | 86 *initialState = kAllOut_InitialState; |
78 // iior should only be true if aa/non-aa status matches among al
l elements. | 87 // iior should only be true if aa/non-aa status matches among al
l elements. |
79 SkClipStack::Iter iter(stack, SkClipStack::Iter::kTop_IterStart)
; | 88 SkClipStack::Iter iter(stack, SkClipStack::Iter::kTop_IterStart)
; |
80 bool doAA = iter.prev()->isAA(); | 89 bool doAA = iter.prev()->isAA(); |
81 SkNEW_INSERT_AT_LLIST_HEAD(result, Element, (isectRect, SkRegion
::kReplace_Op, doAA)); | 90 SkNEW_INSERT_AT_LLIST_HEAD(result, Element, (isectRect, SkRegion
::kReplace_Op, doAA)); |
82 if (NULL != requiresAA) { | 91 if (NULL != requiresAA) { |
83 *requiresAA = doAA; | 92 *requiresAA = doAA; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 if (NULL != tighterBounds) { | 125 if (NULL != tighterBounds) { |
117 *tighterBounds = queryBounds; | 126 *tighterBounds = queryBounds; |
118 } | 127 } |
119 } | 128 } |
120 } | 129 } |
121 | 130 |
122 SkRect scalarBounds = SkRect::Make(*bounds); | 131 SkRect scalarBounds = SkRect::Make(*bounds); |
123 | 132 |
124 // Now that we have determined the bounds to use and filtered out the trivia
l cases, call the | 133 // Now that we have determined the bounds to use and filtered out the trivia
l cases, call the |
125 // helper that actually walks the stack. | 134 // helper that actually walks the stack. |
126 reduced_stack_walker(stack, scalarBounds, result, initialState, requiresAA); | 135 reduced_stack_walker(stack, scalarBounds, result, resultGenID, initialState,
requiresAA); |
| 136 |
| 137 // The list that was computed in this function may be cached based on the ge
n id of the last |
| 138 // element. |
| 139 SkASSERT(SkClipStack::kInvalidGenID != *resultGenID); |
127 } | 140 } |
128 | 141 |
129 void reduced_stack_walker(const SkClipStack& stack, | 142 void reduced_stack_walker(const SkClipStack& stack, |
130 const SkRect& queryBounds, | 143 const SkRect& queryBounds, |
131 ElementList* result, | 144 ElementList* result, |
| 145 int32_t* resultGenID, |
132 InitialState* initialState, | 146 InitialState* initialState, |
133 bool* requiresAA) { | 147 bool* requiresAA) { |
134 | 148 |
135 // walk backwards until we get to: | 149 // walk backwards until we get to: |
136 // a) the beginning | 150 // a) the beginning |
137 // b) an operation that is known to make the bounds all inside/outside | 151 // b) an operation that is known to make the bounds all inside/outside |
138 // c) a replace operation | 152 // c) a replace operation |
139 | 153 |
140 static const InitialState kUnknown_InitialState = static_cast<InitialState>(
-1); | 154 static const InitialState kUnknown_InitialState = static_cast<InitialState>(
-1); |
141 *initialState = kUnknown_InitialState; | 155 *initialState = kUnknown_InitialState; |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
305 if (!skippable) { | 319 if (!skippable) { |
306 *initialState = kAllOut_InitialState; | 320 *initialState = kAllOut_InitialState; |
307 embiggens = emsmallens = true; | 321 embiggens = emsmallens = true; |
308 } | 322 } |
309 break; | 323 break; |
310 default: | 324 default: |
311 SkDEBUGFAIL("Unexpected op."); | 325 SkDEBUGFAIL("Unexpected op."); |
312 break; | 326 break; |
313 } | 327 } |
314 if (!skippable) { | 328 if (!skippable) { |
| 329 if (0 == result->count()) { |
| 330 // This will be the last element. Record the stricter genID. |
| 331 *resultGenID = element->getGenID(); |
| 332 } |
| 333 |
315 // if it is a flip, change it to a bounds-filling rect | 334 // if it is a flip, change it to a bounds-filling rect |
316 if (isFlip) { | 335 if (isFlip) { |
317 SkASSERT(SkRegion::kXOR_Op == element->getOp() || | 336 SkASSERT(SkRegion::kXOR_Op == element->getOp() || |
318 SkRegion::kReverseDifference_Op == element->getOp()); | 337 SkRegion::kReverseDifference_Op == element->getOp()); |
319 SkNEW_INSERT_AT_LLIST_HEAD(result, | 338 SkNEW_INSERT_AT_LLIST_HEAD(result, |
320 Element, | 339 Element, |
321 (queryBounds, SkRegion::kReverseDiffe
rence_Op, false)); | 340 (queryBounds, SkRegion::kReverseDiffe
rence_Op, false)); |
322 } else { | 341 } else { |
323 Element* newElement = result->addToHead(*element); | 342 Element* newElement = result->addToHead(*element); |
324 if (newElement->isAA()) { | 343 if (newElement->isAA()) { |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
410 --numAAElements; | 429 --numAAElements; |
411 } | 430 } |
412 result->popHead(); | 431 result->popHead(); |
413 element = result->headIter().get(); | 432 element = result->headIter().get(); |
414 } | 433 } |
415 } | 434 } |
416 } | 435 } |
417 if (NULL != requiresAA) { | 436 if (NULL != requiresAA) { |
418 *requiresAA = numAAElements > 0; | 437 *requiresAA = numAAElements > 0; |
419 } | 438 } |
| 439 |
| 440 if (0 == result->count()) { |
| 441 if (*initialState == kAllIn_InitialState) { |
| 442 *resultGenID = SkClipStack::kWideOpenGenID; |
| 443 } else { |
| 444 *resultGenID = SkClipStack::kEmptyGenID; |
| 445 } |
| 446 } |
420 } | 447 } |
421 } // namespace GrReducedClip | 448 } // namespace GrReducedClip |
OLD | NEW |