diff options
author | Florin Malita <fmalita@chromium.org> | 2018-05-25 12:43:51 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-05-25 17:11:52 +0000 |
commit | 3b526b05d652ad6c310d9c636187b20b51c7648c (patch) | |
tree | 6c6fa99f2e80db81e9c3f593fe5883aabdaa442b /modules/sksg/src/SkSGNode.cpp | |
parent | 59da548b0c4d4239e0ec1855d3f7f77a2bff4b93 (diff) |
"Modularize" SkSG
* relocate all SkSG-related files under modules/sksg/
* fix various tidbits to make non-sksg builds possible
* drop obsolete SampleSGInval.cpp
Change-Id: I54e6c5bb1a09f45030fa8d607b3eb3f7cba78957
Reviewed-on: https://skia-review.googlesource.com/130025
Commit-Queue: Florin Malita <fmalita@chromium.org>
Reviewed-by: Mike Klein <mtklein@google.com>
Diffstat (limited to 'modules/sksg/src/SkSGNode.cpp')
-rw-r--r-- | modules/sksg/src/SkSGNode.cpp | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/modules/sksg/src/SkSGNode.cpp b/modules/sksg/src/SkSGNode.cpp new file mode 100644 index 0000000000..35b2640dbb --- /dev/null +++ b/modules/sksg/src/SkSGNode.cpp @@ -0,0 +1,152 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkRectPriv.h" +#include "SkSGNode.h" +#include "SkSGInvalidationController.h" + +namespace sksg { + +class Node::ScopedFlag { +public: + ScopedFlag(Node* node, uint32_t flag) + : fNode(node) + , fFlag(flag) + , fWasSet(node->fFlags & flag) { + node->fFlags |= flag; + } + ~ScopedFlag() { + if (!fWasSet) { + fNode->fFlags &= ~fFlag;; + } + } + + bool wasSet() const { return fWasSet; } + +private: + Node* fNode; + uint32_t fFlag; + bool fWasSet; +}; + +#define TRAVERSAL_GUARD \ + ScopedFlag traversal_guard(this, kInTraversal_Flag); \ + if (traversal_guard.wasSet()) \ + return + +Node::Node(uint32_t invalTraits) + : fInvalObserver(nullptr) + , fBounds(SkRectPriv::MakeLargeS32()) + , fInvalTraits(invalTraits) + , fFlags(kInvalidated_Flag) {} + +Node::~Node() { + if (fFlags & kObserverArray_Flag) { + SkASSERT(fInvalObserverArray->isEmpty()); + delete fInvalObserverArray; + } else { + SkASSERT(!fInvalObserver); + } +} + +void Node::observeInval(const sk_sp<Node>& node) { + SkASSERT(node); + if (!(node->fFlags & kObserverArray_Flag)) { + if (!node->fInvalObserver) { + node->fInvalObserver = this; + return; + } + + auto observers = new SkTDArray<Node*>(); + observers->setReserve(2); + observers->push(node->fInvalObserver); + + node->fInvalObserverArray = observers; + node->fFlags |= kObserverArray_Flag; + } + + // No duplicate observers. + SkASSERT(node->fInvalObserverArray->find(this) < 0); + + node->fInvalObserverArray->push(this); +} + +void Node::unobserveInval(const sk_sp<Node>& node) { + SkASSERT(node); + if (!(node->fFlags & kObserverArray_Flag)) { + SkASSERT(node->fInvalObserver == this); + node->fInvalObserver = nullptr; + return; + } + + const auto idx = node->fInvalObserverArray->find(this); + SkASSERT(idx >= 0); + node->fInvalObserverArray->remove(idx); +} + +template <typename Func> +void Node::forEachInvalObserver(Func&& func) const { + if (fFlags & kObserverArray_Flag) { + for (const auto& parent : *fInvalObserverArray) { + func(parent); + } + return; + } + + if (fInvalObserver) { + func(fInvalObserver); + } +} + +void Node::invalidate(bool damageBubbling) { + TRAVERSAL_GUARD; + + if (this->hasInval() && (!damageBubbling || (fFlags & kDamage_Flag))) { + // All done. + return; + } + + if (damageBubbling && !(fInvalTraits & kBubbleDamage_Trait)) { + // Found a damage observer. + fFlags |= kDamage_Flag; + damageBubbling = false; + } + + fFlags |= kInvalidated_Flag; + + forEachInvalObserver([&](Node* observer) { + observer->invalidate(damageBubbling); + }); +} + +const SkRect& Node::revalidate(InvalidationController* ic, const SkMatrix& ctm) { + TRAVERSAL_GUARD fBounds; + + if (!this->hasInval()) { + return fBounds; + } + + SkRect prevBounds; + if (fFlags & kDamage_Flag) { + prevBounds = fBounds; + } + + fBounds = this->onRevalidate(ic, ctm); + + if (fFlags & kDamage_Flag) { + ic->inval(prevBounds, ctm); + if (fBounds != prevBounds) { + ic->inval(fBounds, ctm); + } + } + + fFlags &= ~(kInvalidated_Flag | kDamage_Flag); + + return fBounds; +} + +} // namespace sksg |