| 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 |