1 /* 2 * Copyright 2017 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkRectPriv.h" 9 #include "SkSGNode.h" 10 #include "SkSGInvalidationController.h" 11 12 namespace sksg { 13 14 class Node::ScopedFlag { 15 public: 16 ScopedFlag(Node* node, uint32_t flag) 17 : fNode(node) 18 , fFlag(flag) 19 , fWasSet(node->fFlags & flag) { 20 node->fFlags |= flag; 21 } 22 ~ScopedFlag() { 23 if (!fWasSet) { 24 fNode->fFlags &= ~fFlag;; 25 } 26 } 27 28 bool wasSet() const { return fWasSet; } 29 30 private: 31 Node* fNode; 32 uint32_t fFlag; 33 bool fWasSet; 34 }; 35 36 #define TRAVERSAL_GUARD \ 37 ScopedFlag traversal_guard(this, kInTraversal_Flag); \ 38 if (traversal_guard.wasSet()) \ 39 return 40 41 Node::Node(uint32_t invalTraits) 42 : fInvalObserver(nullptr) 43 , fBounds(SkRectPriv::MakeLargeS32()) 44 , fInvalTraits(invalTraits) 45 , fFlags(kInvalidated_Flag) {} 46 47 Node::~Node() { 48 if (fFlags & kObserverArray_Flag) { 49 SkASSERT(fInvalObserverArray->isEmpty()); 50 delete fInvalObserverArray; 51 } else { 52 SkASSERT(!fInvalObserver); 53 } 54 } 55 56 void Node::observeInval(const sk_sp<Node>& node) { 57 SkASSERT(node); 58 if (!(node->fFlags & kObserverArray_Flag)) { 59 if (!node->fInvalObserver) { 60 node->fInvalObserver = this; 61 return; 62 } 63 64 auto observers = new SkTDArray<Node*>(); 65 observers->setReserve(2); 66 observers->push(node->fInvalObserver); 67 68 node->fInvalObserverArray = observers; 69 node->fFlags |= kObserverArray_Flag; 70 } 71 72 // No duplicate observers. 73 SkASSERT(node->fInvalObserverArray->find(this) < 0); 74 75 node->fInvalObserverArray->push(this); 76 } 77 78 void Node::unobserveInval(const sk_sp<Node>& node) { 79 SkASSERT(node); 80 if (!(node->fFlags & kObserverArray_Flag)) { 81 SkASSERT(node->fInvalObserver == this); 82 node->fInvalObserver = nullptr; 83 return; 84 } 85 86 const auto idx = node->fInvalObserverArray->find(this); 87 SkASSERT(idx >= 0); 88 node->fInvalObserverArray->remove(idx); 89 } 90 91 template <typename Func> 92 void Node::forEachInvalObserver(Func&& func) const { 93 if (fFlags & kObserverArray_Flag) { 94 for (const auto& parent : *fInvalObserverArray) { 95 func(parent); 96 } 97 return; 98 } 99 100 if (fInvalObserver) { 101 func(fInvalObserver); 102 } 103 } 104 105 void Node::invalidate(bool damageBubbling) { 106 TRAVERSAL_GUARD; 107 108 if (this->hasInval() && (!damageBubbling || (fFlags & kDamage_Flag))) { 109 // All done. 110 return; 111 } 112 113 if (damageBubbling && !(fInvalTraits & kBubbleDamage_Trait)) { 114 // Found a damage observer. 115 fFlags |= kDamage_Flag; 116 damageBubbling = false; 117 } 118 119 fFlags |= kInvalidated_Flag; 120 121 forEachInvalObserver([&](Node* observer) { 122 observer->invalidate(damageBubbling); 123 }); 124 } 125 126 const SkRect& Node::revalidate(InvalidationController* ic, const SkMatrix& ctm) { 127 TRAVERSAL_GUARD fBounds; 128 129 if (!this->hasInval()) { 130 return fBounds; 131 } 132 133 SkRect prevBounds; 134 if (fFlags & kDamage_Flag) { 135 prevBounds = fBounds; 136 } 137 138 fBounds = this->onRevalidate(ic, ctm); 139 140 if (fFlags & kDamage_Flag) { 141 ic->inval(prevBounds, ctm); 142 if (fBounds != prevBounds) { 143 ic->inval(fBounds, ctm); 144 } 145 } 146 147 fFlags &= ~(kInvalidated_Flag | kDamage_Flag); 148 149 return fBounds; 150 } 151 152 } // namespace sksg 153