blob: 0cb578ed5fa993cc8d9297b57dded14265e6a6fa [file] [log] [blame]
Florin Malita4aa44412017-12-19 12:21:02 -05001/*
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
Mike Reed274218e2018-01-08 15:05:02 -05008#include "SkRectPriv.h"
Florin Malita4aa44412017-12-19 12:21:02 -05009#include "SkSGNode.h"
Florin Malitac75e2402018-01-03 16:17:29 -050010#include "SkSGInvalidationController.h"
11
Florin Malita4aa44412017-12-19 12:21:02 -050012namespace sksg {
13
14class Node::ScopedFlag {
15public:
16 ScopedFlag(Node* node, uint32_t flag)
17 : fNode(node)
Florin Malitac75e2402018-01-03 16:17:29 -050018 , fFlag(flag)
19 , fWasSet(node->fFlags & flag) {
20 node->fFlags |= flag;
Florin Malita4aa44412017-12-19 12:21:02 -050021 }
22 ~ScopedFlag() {
Florin Malitac75e2402018-01-03 16:17:29 -050023 if (!fWasSet) {
24 fNode->fFlags &= ~fFlag;;
25 }
Florin Malita4aa44412017-12-19 12:21:02 -050026 }
27
Florin Malitac75e2402018-01-03 16:17:29 -050028 bool wasSet() const { return fWasSet; }
29
Florin Malita4aa44412017-12-19 12:21:02 -050030private:
31 Node* fNode;
32 uint32_t fFlag;
Florin Malitac75e2402018-01-03 16:17:29 -050033 bool fWasSet;
Florin Malita4aa44412017-12-19 12:21:02 -050034};
35
Florin Malitac75e2402018-01-03 16:17:29 -050036#define TRAVERSAL_GUARD \
37 ScopedFlag traversal_guard(this, kInTraversal_Flag); \
38 if (traversal_guard.wasSet()) \
39 return
Florin Malita4aa44412017-12-19 12:21:02 -050040
Florin Malitac14f1442018-01-05 11:32:31 -050041Node::Node(uint32_t invalTraits)
Florin Malita3ba3fa72018-01-22 10:19:28 -050042 : fInvalObserver(nullptr)
Mike Reed8008df12018-01-17 12:20:04 -050043 , fBounds(SkRectPriv::MakeLargeS32())
Florin Malitac14f1442018-01-05 11:32:31 -050044 , fInvalTraits(invalTraits)
45 , fFlags(kInvalidated_Flag) {}
Florin Malita4aa44412017-12-19 12:21:02 -050046
47Node::~Node() {
Florin Malita3ba3fa72018-01-22 10:19:28 -050048 if (fFlags & kObserverArray_Flag) {
49 SkASSERT(fInvalObserverArray->isEmpty());
50 delete fInvalObserverArray;
Florin Malita4aa44412017-12-19 12:21:02 -050051 } else {
Florin Malita3ba3fa72018-01-22 10:19:28 -050052 SkASSERT(!fInvalObserver);
Florin Malita4aa44412017-12-19 12:21:02 -050053 }
54}
55
Florin Malita3ba3fa72018-01-22 10:19:28 -050056void Node::observeInval(const sk_sp<Node>& node) {
57 SkASSERT(node);
58 if (!(node->fFlags & kObserverArray_Flag)) {
59 if (!node->fInvalObserver) {
60 node->fInvalObserver = this;
Florin Malita4aa44412017-12-19 12:21:02 -050061 return;
62 }
63
Florin Malita3ba3fa72018-01-22 10:19:28 -050064 auto observers = new SkTDArray<Node*>();
65 observers->setReserve(2);
Mike Reed5edcd312018-08-08 11:23:41 -040066 observers->push_back(node->fInvalObserver);
Florin Malita4aa44412017-12-19 12:21:02 -050067
Florin Malita3ba3fa72018-01-22 10:19:28 -050068 node->fInvalObserverArray = observers;
69 node->fFlags |= kObserverArray_Flag;
Florin Malita4aa44412017-12-19 12:21:02 -050070 }
71
Florin Malita3ba3fa72018-01-22 10:19:28 -050072 // No duplicate observers.
73 SkASSERT(node->fInvalObserverArray->find(this) < 0);
Florin Malita4aa44412017-12-19 12:21:02 -050074
Mike Reed5edcd312018-08-08 11:23:41 -040075 node->fInvalObserverArray->push_back(this);
Florin Malita4aa44412017-12-19 12:21:02 -050076}
77
Florin Malita3ba3fa72018-01-22 10:19:28 -050078void 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;
Florin Malita4aa44412017-12-19 12:21:02 -050083 return;
84 }
85
Florin Malita3ba3fa72018-01-22 10:19:28 -050086 const auto idx = node->fInvalObserverArray->find(this);
Florin Malita4aa44412017-12-19 12:21:02 -050087 SkASSERT(idx >= 0);
Florin Malita3ba3fa72018-01-22 10:19:28 -050088 node->fInvalObserverArray->remove(idx);
Florin Malita4aa44412017-12-19 12:21:02 -050089}
90
91template <typename Func>
Florin Malita3ba3fa72018-01-22 10:19:28 -050092void Node::forEachInvalObserver(Func&& func) const {
93 if (fFlags & kObserverArray_Flag) {
94 for (const auto& parent : *fInvalObserverArray) {
Florin Malita4aa44412017-12-19 12:21:02 -050095 func(parent);
96 }
97 return;
98 }
99
Florin Malita3ba3fa72018-01-22 10:19:28 -0500100 if (fInvalObserver) {
101 func(fInvalObserver);
Florin Malita4aa44412017-12-19 12:21:02 -0500102 }
103}
104
Florin Malitac14f1442018-01-05 11:32:31 -0500105void Node::invalidate(bool damageBubbling) {
106 TRAVERSAL_GUARD;
107
108 if (this->hasInval() && (!damageBubbling || (fFlags & kDamage_Flag))) {
109 // All done.
Florin Malita4aa44412017-12-19 12:21:02 -0500110 return;
111 }
112
Florin Malitac14f1442018-01-05 11:32:31 -0500113 if (damageBubbling && !(fInvalTraits & kBubbleDamage_Trait)) {
Florin Malita3ba3fa72018-01-22 10:19:28 -0500114 // Found a damage observer.
Florin Malitac14f1442018-01-05 11:32:31 -0500115 fFlags |= kDamage_Flag;
116 damageBubbling = false;
117 }
Florin Malitac75e2402018-01-03 16:17:29 -0500118
Florin Malitac14f1442018-01-05 11:32:31 -0500119 fFlags |= kInvalidated_Flag;
Florin Malitac75e2402018-01-03 16:17:29 -0500120
Florin Malita3ba3fa72018-01-22 10:19:28 -0500121 forEachInvalObserver([&](Node* observer) {
122 observer->invalidate(damageBubbling);
Florin Malita4aa44412017-12-19 12:21:02 -0500123 });
124}
125
Florin Malitac75e2402018-01-03 16:17:29 -0500126const SkRect& Node::revalidate(InvalidationController* ic, const SkMatrix& ctm) {
127 TRAVERSAL_GUARD fBounds;
Florin Malita4aa44412017-12-19 12:21:02 -0500128
Florin Malitac75e2402018-01-03 16:17:29 -0500129 if (!this->hasInval()) {
130 return fBounds;
Florin Malita4aa44412017-12-19 12:21:02 -0500131 }
Florin Malitac75e2402018-01-03 16:17:29 -0500132
Florin Malitac14f1442018-01-05 11:32:31 -0500133 SkRect prevBounds;
134 if (fFlags & kDamage_Flag) {
135 prevBounds = fBounds;
136 }
Florin Malitac75e2402018-01-03 16:17:29 -0500137
Florin Malitac14f1442018-01-05 11:32:31 -0500138 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);
Florin Malitac75e2402018-01-03 16:17:29 -0500144 }
145 }
146
Florin Malitac14f1442018-01-05 11:32:31 -0500147 fFlags &= ~(kInvalidated_Flag | kDamage_Flag);
Florin Malitac75e2402018-01-03 16:17:29 -0500148
149 return fBounds;
Florin Malita4aa44412017-12-19 12:21:02 -0500150}
151
152} // namespace sksg