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