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