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