blob: 768fdfa7b698afdd46aed579036e97b36bf08943 [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
Florin Malitac14f1442018-01-05 11:32:31 -050041Node::Node(uint32_t invalTraits)
Florin Malita4aa44412017-12-19 12:21:02 -050042 : fInvalReceiver(nullptr)
Florin Malitac75e2402018-01-03 16:17:29 -050043 , fBounds(SkRect::MakeLargestS32())
Florin Malitac14f1442018-01-05 11:32:31 -050044 , fInvalTraits(invalTraits)
45 , fFlags(kInvalidated_Flag) {}
Florin Malita4aa44412017-12-19 12:21:02 -050046
47Node::~Node() {
48 if (fFlags & kReceiverArray_Flag) {
49 SkASSERT(fInvalReceiverArray->isEmpty());
50 delete fInvalReceiverArray;
51 } else {
52 SkASSERT(!fInvalReceiver);
53 }
54}
55
56void Node::addInvalReceiver(Node* receiver) {
57 if (!(fFlags & kReceiverArray_Flag)) {
58 if (!fInvalReceiver) {
59 fInvalReceiver = receiver;
60 return;
61 }
62
63 auto receivers = new SkTDArray<Node*>();
64 receivers->setReserve(2);
65 receivers->push(fInvalReceiver);
66
67 fInvalReceiverArray = receivers;
68 fFlags |= kReceiverArray_Flag;
69 }
70
71 // No duplicate receivers.
72 SkASSERT(fInvalReceiverArray->find(receiver) < 0);
73
74 fInvalReceiverArray->push(receiver);
75}
76
77void Node::removeInvalReceiver(Node* receiver) {
78 if (!(fFlags & kReceiverArray_Flag)) {
79 SkASSERT(fInvalReceiver == receiver);
80 fInvalReceiver = nullptr;
81 return;
82 }
83
84 const auto idx = fInvalReceiverArray->find(receiver);
85 SkASSERT(idx >= 0);
86 fInvalReceiverArray->remove(idx);
87}
88
89template <typename Func>
90void Node::forEachInvalReceiver(Func&& func) const {
91 if (fFlags & kReceiverArray_Flag) {
92 for (const auto& parent : *fInvalReceiverArray) {
93 func(parent);
94 }
95 return;
96 }
97
98 if (fInvalReceiver) {
99 func(fInvalReceiver);
100 }
101}
102
Florin Malitac14f1442018-01-05 11:32:31 -0500103void Node::invalidate(bool damageBubbling) {
104 TRAVERSAL_GUARD;
105
106 if (this->hasInval() && (!damageBubbling || (fFlags & kDamage_Flag))) {
107 // All done.
Florin Malita4aa44412017-12-19 12:21:02 -0500108 return;
109 }
110
Florin Malitac14f1442018-01-05 11:32:31 -0500111 if (damageBubbling && !(fInvalTraits & kBubbleDamage_Trait)) {
112 // Found a damage receiver.
113 fFlags |= kDamage_Flag;
114 damageBubbling = false;
115 }
Florin Malitac75e2402018-01-03 16:17:29 -0500116
Florin Malitac14f1442018-01-05 11:32:31 -0500117 fFlags |= kInvalidated_Flag;
Florin Malitac75e2402018-01-03 16:17:29 -0500118
Florin Malita4aa44412017-12-19 12:21:02 -0500119 forEachInvalReceiver([&](Node* receiver) {
Florin Malitac14f1442018-01-05 11:32:31 -0500120 receiver->invalidate(damageBubbling);
Florin Malita4aa44412017-12-19 12:21:02 -0500121 });
122}
123
Florin Malitac75e2402018-01-03 16:17:29 -0500124const SkRect& Node::revalidate(InvalidationController* ic, const SkMatrix& ctm) {
125 TRAVERSAL_GUARD fBounds;
Florin Malita4aa44412017-12-19 12:21:02 -0500126
Florin Malitac75e2402018-01-03 16:17:29 -0500127 if (!this->hasInval()) {
128 return fBounds;
Florin Malita4aa44412017-12-19 12:21:02 -0500129 }
Florin Malitac75e2402018-01-03 16:17:29 -0500130
Florin Malitac14f1442018-01-05 11:32:31 -0500131 SkRect prevBounds;
132 if (fFlags & kDamage_Flag) {
133 prevBounds = fBounds;
134 }
Florin Malitac75e2402018-01-03 16:17:29 -0500135
Florin Malitac14f1442018-01-05 11:32:31 -0500136 fBounds = this->onRevalidate(ic, ctm);
137
138 if (fFlags & kDamage_Flag) {
139 ic->inval(prevBounds, ctm);
140 if (fBounds != prevBounds) {
141 ic->inval(fBounds, ctm);
Florin Malitac75e2402018-01-03 16:17:29 -0500142 }
143 }
144
Florin Malitac14f1442018-01-05 11:32:31 -0500145 fFlags &= ~(kInvalidated_Flag | kDamage_Flag);
Florin Malitac75e2402018-01-03 16:17:29 -0500146
147 return fBounds;
Florin Malita4aa44412017-12-19 12:21:02 -0500148}
149
150} // namespace sksg