blob: fc4d2785807e1e8e8f42462c50f20b1bb0a9eeba [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
8#include "SkSGNode.h"
9
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
41Node::Node()
42 : fInvalReceiver(nullptr)
Florin Malitac75e2402018-01-03 16:17:29 -050043 , fBounds(SkRect::MakeLargestS32())
44 , fFlags(kInvalSelf_Flag | kInvalDescendant_Flag) {}
Florin Malita4aa44412017-12-19 12:21:02 -050045
46Node::~Node() {
47 if (fFlags & kReceiverArray_Flag) {
48 SkASSERT(fInvalReceiverArray->isEmpty());
49 delete fInvalReceiverArray;
50 } else {
51 SkASSERT(!fInvalReceiver);
52 }
53}
54
55void Node::addInvalReceiver(Node* receiver) {
56 if (!(fFlags & kReceiverArray_Flag)) {
57 if (!fInvalReceiver) {
58 fInvalReceiver = receiver;
59 return;
60 }
61
62 auto receivers = new SkTDArray<Node*>();
63 receivers->setReserve(2);
64 receivers->push(fInvalReceiver);
65
66 fInvalReceiverArray = receivers;
67 fFlags |= kReceiverArray_Flag;
68 }
69
70 // No duplicate receivers.
71 SkASSERT(fInvalReceiverArray->find(receiver) < 0);
72
73 fInvalReceiverArray->push(receiver);
74}
75
76void Node::removeInvalReceiver(Node* receiver) {
77 if (!(fFlags & kReceiverArray_Flag)) {
78 SkASSERT(fInvalReceiver == receiver);
79 fInvalReceiver = nullptr;
80 return;
81 }
82
83 const auto idx = fInvalReceiverArray->find(receiver);
84 SkASSERT(idx >= 0);
85 fInvalReceiverArray->remove(idx);
86}
87
88template <typename Func>
89void Node::forEachInvalReceiver(Func&& func) const {
90 if (fFlags & kReceiverArray_Flag) {
91 for (const auto& parent : *fInvalReceiverArray) {
92 func(parent);
93 }
94 return;
95 }
96
97 if (fInvalReceiver) {
98 func(fInvalReceiver);
99 }
100}
101
Florin Malitac75e2402018-01-03 16:17:29 -0500102void Node::invalidateSelf() {
103 if (this->hasSelfInval()) {
Florin Malita4aa44412017-12-19 12:21:02 -0500104 return;
105 }
106
Florin Malitac75e2402018-01-03 16:17:29 -0500107 fFlags |= kInvalSelf_Flag;
108 this->invalidateAncestors();
109}
110
111void Node::invalidateAncestors() {
112 TRAVERSAL_GUARD;
113
Florin Malita4aa44412017-12-19 12:21:02 -0500114 forEachInvalReceiver([&](Node* receiver) {
Florin Malitac75e2402018-01-03 16:17:29 -0500115 if (receiver->hasDescendantInval()) {
116 return;
117 }
118 receiver->fFlags |= kInvalDescendant_Flag;
119 receiver->invalidateAncestors();
Florin Malita4aa44412017-12-19 12:21:02 -0500120 });
121}
122
Florin Malitac75e2402018-01-03 16:17:29 -0500123const SkRect& Node::revalidate(InvalidationController* ic, const SkMatrix& ctm) {
124 TRAVERSAL_GUARD fBounds;
Florin Malita4aa44412017-12-19 12:21:02 -0500125
Florin Malitac75e2402018-01-03 16:17:29 -0500126 if (!this->hasInval()) {
127 return fBounds;
Florin Malita4aa44412017-12-19 12:21:02 -0500128 }
Florin Malitac75e2402018-01-03 16:17:29 -0500129
Florin Malita0ebf4192018-01-04 19:21:58 -0500130 const auto result = this->onRevalidate(ic, ctm);
Florin Malita18eafd92018-01-04 21:11:55 -0500131 const auto selfDamage = result.fDamage == Damage::kForceSelf ||
132 (this->hasSelfInval() && result.fDamage != Damage::kBlockSelf);
Florin Malitac75e2402018-01-03 16:17:29 -0500133
Florin Malita0ebf4192018-01-04 19:21:58 -0500134 if (selfDamage) {
135 // old bounds
136 ic->inval(fBounds, ctm);
137 if (result.fBounds != fBounds) {
138 // new bounds
139 ic->inval(result.fBounds, ctm);
Florin Malitac75e2402018-01-03 16:17:29 -0500140 }
141 }
142
Florin Malita0ebf4192018-01-04 19:21:58 -0500143 fBounds = result.fBounds;
Florin Malitac75e2402018-01-03 16:17:29 -0500144 fFlags &= ~(kInvalSelf_Flag | kInvalDescendant_Flag);
145
146 return fBounds;
Florin Malita4aa44412017-12-19 12:21:02 -0500147}
148
149} // namespace sksg