xref: /aosp_15_r20/external/skia/modules/sksg/include/SkSGNode.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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 #ifndef SkSGNode_DEFINED
9 #define SkSGNode_DEFINED
10 
11 #include "include/core/SkRect.h"
12 #include "include/core/SkRefCnt.h"
13 #include "include/private/base/SkAssert.h"
14 
15 #include <cstdint>
16 #include <vector>
17 
18 class SkMatrix;
19 
20 namespace sksg {
21 
22 class InvalidationController;
23 
24 /**
25  * Base class for all scene graph nodes.
26  *
27  * Handles ingress edge management for the DAG (i.e. node -> "parent" node mapping),
28  * and invalidation.
29  *
30  * Note: egress edges are only implemented/supported in container subclasses
31  * (e.g. Group, Effect, Draw).
32  */
33 class Node : public SkRefCnt {
34 public:
35     // Traverse the DAG and revalidate any dependant/invalidated nodes.
36     // Returns the bounding box for the DAG fragment.
37     const SkRect& revalidate(InvalidationController*, const SkMatrix&);
38 
39     // Tag this node for invalidation and optional damage.
40     void invalidate(bool damage = true);
41 
42 protected:
43     enum InvalTraits {
44         // Nodes with this trait never generate direct damage -- instead,
45         // the damage bubbles up to ancestors.
46         kBubbleDamage_Trait   = 1 << 0,
47 
48         // Nodes with this trait obscure the descendants' damage and always override it.
49         kOverrideDamage_Trait = 1 << 1,
50     };
51 
52     explicit Node(uint32_t invalTraits);
53     ~Node() override;
54 
bounds()55     const SkRect& bounds() const {
56         SkASSERT(!this->hasInval());
57         return fBounds;
58     }
59 
hasInval()60     bool hasInval() const { return fFlags & kInvalidated_Flag; }
61 
62     // Dispatched on revalidation.  Subclasses are expected to recompute/cache their properties
63     // and return their bounding box in local coordinates.
64     virtual SkRect onRevalidate(InvalidationController*, const SkMatrix& ctm) = 0;
65 
66     // Register/unregister |this| to receive invalidation events from a descendant.
67     void observeInval(const sk_sp<Node>&);
68     void unobserveInval(const sk_sp<Node>&);
69 
70 private:
71     enum Flags {
72         kInvalidated_Flag   = 1 << 0, // the node or its descendants require revalidation
73         kDamage_Flag        = 1 << 1, // the node contributes damage during revalidation
74         kObserverArray_Flag = 1 << 2, // the node has more than one inval observer
75         kInTraversal_Flag   = 1 << 3, // the node is part of a traversal (cycle detection)
76     };
77 
78     template <typename Func>
79     void forEachInvalObserver(Func&&) const;
80 
81     class ScopedFlag;
82 
83     union {
84         Node*               fInvalObserver;
85         std::vector<Node*>* fInvalObserverArray;
86     };
87     SkRect                  fBounds;
88     const uint32_t          fInvalTraits :  2;
89     uint32_t                fFlags       :  4; // Internal flags.
90     uint32_t                fNodeFlags   :  8; // Accessible from select subclasses.
91     // Free bits                         : 18;
92 
93     friend class NodePriv;
94     friend class RenderNode; // node flags access
95 
96     using INHERITED = SkRefCnt;
97 };
98 
99 // Helper for defining attribute getters/setters in subclasses.
100 #define SG_ATTRIBUTE(attr_name, attr_type, attr_container)             \
101     const attr_type& get##attr_name() const { return attr_container; } \
102     void set##attr_name(const attr_type& v) {                          \
103         if (attr_container == v) return;                               \
104         attr_container = v;                                            \
105         this->invalidate();                                            \
106     }                                                                  \
107     void set##attr_name(attr_type&& v) {                               \
108         if (attr_container == v) return;                               \
109         attr_container = std::move(v);                                 \
110         this->invalidate();                                            \
111     }
112 
113 #define SG_MAPPED_ATTRIBUTE(attr_name, attr_type, attr_container)                \
114     attr_type get##attr_name() const { return attr_container.get##attr_name(); } \
115     void set##attr_name(const attr_type& v) {                                    \
116         if (attr_container.get##attr_name() == v) return;                        \
117         attr_container.set##attr_name(v);                                        \
118         this->invalidate();                                                      \
119     }                                                                            \
120     void set##attr_name(attr_type&& v) {                                         \
121         if (attr_container.get##attr_name() == v) return;                        \
122         attr_container.set##attr_name(std::move(v));                             \
123         this->invalidate();                                                      \
124     }
125 
126 } // namespace sksg
127 
128 #endif // SkSGNode_DEFINED
129