Coverage Report

Created: 2021-08-22 09:07

/src/skia/modules/sksg/src/SkSGNode.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
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 "modules/sksg/include/SkSGInvalidationController.h"
9
#include "modules/sksg/include/SkSGNode.h"
10
#include "src/core/SkRectPriv.h"
11
12
#include <algorithm>
13
14
namespace sksg {
15
16
class Node::ScopedFlag {
17
public:
18
    ScopedFlag(Node* node, uint32_t flag)
19
        : fNode(node)
20
        , fFlag(flag)
21
3.65M
        , fWasSet(node->fFlags & flag) {
22
3.65M
        node->fFlags |= flag;
23
3.65M
    }
24
3.65M
    ~ScopedFlag() {
25
3.65M
        if (!fWasSet) {
26
3.65M
            fNode->fFlags &= ~fFlag;
27
3.65M
        }
28
3.65M
    }
29
30
3.65M
    bool wasSet() const { return fWasSet; }
31
32
private:
33
    Node*    fNode;
34
    uint32_t fFlag;
35
    bool     fWasSet;
36
};
37
38
#define TRAVERSAL_GUARD                                  \
39
3.65M
    ScopedFlag traversal_guard(this, kInTraversal_Flag); \
40
3.65M
    if (traversal_guard.wasSet())                        \
41
0
        return
42
43
Node::Node(uint32_t invalTraits)
44
    : fInvalObserver(nullptr)
45
    , fBounds(SkRectPriv::MakeLargeS32())
46
    , fInvalTraits(invalTraits)
47
    , fFlags(kInvalidated_Flag)
48
2.53M
    , fNodeFlags(0) {}
49
50
2.53M
Node::~Node() {
51
2.53M
    if (fFlags & kObserverArray_Flag) {
52
66.6k
        SkASSERT(fInvalObserverArray->empty());
53
66.6k
        delete fInvalObserverArray;
54
2.46M
    } else {
55
2.46M
        SkASSERT(!fInvalObserver);
56
2.46M
    }
57
2.53M
}
58
59
2.50M
void Node::observeInval(const sk_sp<Node>& node) {
60
2.50M
    SkASSERT(node);
61
2.50M
    if (!(node->fFlags & kObserverArray_Flag)) {
62
2.42M
        if (!node->fInvalObserver) {
63
2.35M
            node->fInvalObserver = this;
64
2.35M
            return;
65
2.35M
        }
66
67
66.6k
        auto observers = new std::vector<Node*>();
68
66.6k
        observers->reserve(2);
69
66.6k
        observers->push_back(node->fInvalObserver);
70
71
66.6k
        node->fInvalObserverArray = observers;
72
66.6k
        node->fFlags |= kObserverArray_Flag;
73
66.6k
    }
74
75
    // No duplicate observers.
76
147k
    SkASSERT(std::find(node->fInvalObserverArray->begin(),
77
147k
                       node->fInvalObserverArray->end(), this) == node->fInvalObserverArray->end());
78
79
147k
    node->fInvalObserverArray->push_back(this);
80
147k
}
81
82
2.50M
void Node::unobserveInval(const sk_sp<Node>& node) {
83
2.50M
    SkASSERT(node);
84
2.50M
    if (!(node->fFlags & kObserverArray_Flag)) {
85
2.29M
        SkASSERT(node->fInvalObserver == this);
86
2.29M
        node->fInvalObserver = nullptr;
87
2.29M
        return;
88
2.29M
    }
89
90
214k
    SkDEBUGCODE(const auto origSize = node->fInvalObserverArray->size());
91
214k
    node->fInvalObserverArray->erase(std::remove(node->fInvalObserverArray->begin(),
92
214k
                                                 node->fInvalObserverArray->end(), this),
93
214k
                                     node->fInvalObserverArray->end());
94
214k
    SkASSERT(node->fInvalObserverArray->size() == origSize - 1);
95
214k
}
96
97
template <typename Func>
98
1.36M
void Node::forEachInvalObserver(Func&& func) const {
99
1.36M
    if (fFlags & kObserverArray_Flag) {
100
4.46k
        for (const auto& parent : *fInvalObserverArray) {
101
4.46k
            func(parent);
102
4.46k
        }
103
2.71k
        return;
104
2.71k
    }
105
106
1.35M
    if (fInvalObserver) {
107
253k
        func(fInvalObserver);
108
253k
    }
109
1.35M
}
110
111
1.45M
void Node::invalidate(bool damageBubbling) {
112
1.45M
    TRAVERSAL_GUARD;
113
114
1.45M
    if (this->hasInval() && (!damageBubbling || (fFlags & kDamage_Flag))) {
115
        // All done.
116
93.5k
        return;
117
93.5k
    }
118
119
1.36M
    if (damageBubbling && !(fInvalTraits & kBubbleDamage_Trait)) {
120
        // Found a damage observer.
121
89.9k
        fFlags |= kDamage_Flag;
122
89.9k
        damageBubbling = false;
123
89.9k
    }
124
125
1.36M
    fFlags |= kInvalidated_Flag;
126
127
257k
    forEachInvalObserver([&](Node* observer) {
128
257k
        observer->invalidate(damageBubbling);
129
257k
    });
130
1.36M
}
131
132
2.20M
const SkRect& Node::revalidate(InvalidationController* ic, const SkMatrix& ctm) {
133
2.20M
    TRAVERSAL_GUARD fBounds;
134
135
2.20M
    if (!this->hasInval()) {
136
120k
        return fBounds;
137
120k
    }
138
139
2.08M
    const auto generate_damage =
140
2.08M
            ic && ((fFlags & kDamage_Flag) || (fInvalTraits & kOverrideDamage_Trait));
141
2.08M
    if (!generate_damage) {
142
        // Trivial transitive revalidation.
143
2.08M
        fBounds = this->onRevalidate(ic, ctm);
144
0
    } else {
145
        // Revalidate and emit damage for old-bounds, new-bounds.
146
0
        const auto prev_bounds = fBounds;
147
148
0
        auto* ic_override = (fInvalTraits & kOverrideDamage_Trait) ? nullptr : ic;
149
0
        fBounds = this->onRevalidate(ic_override, ctm);
150
151
0
        ic->inval(prev_bounds, ctm);
152
0
        if (fBounds != prev_bounds) {
153
0
            ic->inval(fBounds, ctm);
154
0
        }
155
0
    }
156
157
2.08M
    fFlags &= ~(kInvalidated_Flag | kDamage_Flag);
158
159
2.08M
    return fBounds;
160
2.08M
}
161
162
} // namespace sksg