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