blob: 63b8d1ec2cbdc4482856106287da3b50197b9ae6 [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#ifndef SkSGNode_DEFINED
9#define SkSGNode_DEFINED
10
Florin Malitac75e2402018-01-03 16:17:29 -050011#include "SkRect.h"
Florin Malita4aa44412017-12-19 12:21:02 -050012#include "SkRefCnt.h"
Florin Malitaca858b62018-09-02 13:44:13 -040013
14#include <vector>
Florin Malita4aa44412017-12-19 12:21:02 -050015
16class SkCanvas;
17class SkMatrix;
18
19namespace sksg {
20
21class InvalidationController;
22
23/**
24 * Base class for all scene graph nodes.
25 *
26 * Handles ingress edge management for the DAG (i.e. node -> "parent" node mapping),
27 * and invalidation.
28 *
29 * Note: egress edges are only implemented/supported in container subclasses
30 * (e.g. Group, Effect, Draw).
31 */
32class Node : public SkRefCnt {
33public:
Florin Malitac75e2402018-01-03 16:17:29 -050034 // Traverse the DAG and revalidate any dependant/invalidated nodes.
35 // Returns the bounding box for the DAG fragment.
36 const SkRect& revalidate(InvalidationController*, const SkMatrix&);
Florin Malita4aa44412017-12-19 12:21:02 -050037
38protected:
Florin Malitac14f1442018-01-05 11:32:31 -050039 enum InvalTraits {
40 // Nodes with this trait never generate direct damage -- instead,
41 // the damage bubbles up to ancestors.
42 kBubbleDamage_Trait = 1 << 0,
43 };
44
45 explicit Node(uint32_t invalTraits);
Florin Malita4aa44412017-12-19 12:21:02 -050046 ~Node() override;
47
Florin Malitac0034172018-01-08 16:42:59 -050048 const SkRect& bounds() const {
49 SkASSERT(!this->hasInval());
50 return fBounds;
51 }
52
Florin Malitac14f1442018-01-05 11:32:31 -050053 // Tag this node for invalidation and optional damage.
54 void invalidate(bool damage = true);
55 bool hasInval() const { return fFlags & kInvalidated_Flag; }
Florin Malita4aa44412017-12-19 12:21:02 -050056
Florin Malitac75e2402018-01-03 16:17:29 -050057 // Dispatched on revalidation. Subclasses are expected to recompute/cache their properties
58 // and return their bounding box in local coordinates.
Florin Malitac14f1442018-01-05 11:32:31 -050059 virtual SkRect onRevalidate(InvalidationController*, const SkMatrix& ctm) = 0;
Florin Malita4aa44412017-12-19 12:21:02 -050060
Florin Malita3ba3fa72018-01-22 10:19:28 -050061 // Register/unregister |this| to receive invalidation events from a descendant.
62 void observeInval(const sk_sp<Node>&);
63 void unobserveInval(const sk_sp<Node>&);
64
Florin Malita4aa44412017-12-19 12:21:02 -050065private:
Florin Malitac14f1442018-01-05 11:32:31 -050066 enum Flags {
67 kInvalidated_Flag = 1 << 0, // the node or its descendants require revalidation
68 kDamage_Flag = 1 << 1, // the node contributes damage during revalidation
Florin Malita3ba3fa72018-01-22 10:19:28 -050069 kObserverArray_Flag = 1 << 2, // the node has more than one inval observer
Florin Malitac14f1442018-01-05 11:32:31 -050070 kInTraversal_Flag = 1 << 3, // the node is part of a traversal (cycle detection)
71 };
72
Florin Malita4aa44412017-12-19 12:21:02 -050073 template <typename Func>
Florin Malita3ba3fa72018-01-22 10:19:28 -050074 void forEachInvalObserver(Func&&) const;
Florin Malita4aa44412017-12-19 12:21:02 -050075
Florin Malita4aa44412017-12-19 12:21:02 -050076 class ScopedFlag;
77
78 union {
Florin Malitaca858b62018-09-02 13:44:13 -040079 Node* fInvalObserver;
80 std::vector<Node*>* fInvalObserverArray;
Florin Malita4aa44412017-12-19 12:21:02 -050081 };
Florin Malitaca858b62018-09-02 13:44:13 -040082 SkRect fBounds;
83 const uint32_t fInvalTraits : 16;
84 uint32_t fFlags : 16;
Florin Malita4aa44412017-12-19 12:21:02 -050085
86 typedef SkRefCnt INHERITED;
87};
88
89// Helper for defining attribute getters/setters in subclasses.
Florin Malita16d0ad02018-01-19 15:07:29 -050090#define SG_ATTRIBUTE(attr_name, attr_type, attr_container) \
91 const attr_type& get##attr_name() const { return attr_container; } \
92 void set##attr_name(const attr_type& v) { \
93 if (attr_container == v) return; \
94 attr_container = v; \
95 this->invalidate(); \
Florin Malitacd05b192018-04-25 21:43:03 -040096 }
97
98#define SG_MAPPED_ATTRIBUTE(attr_name, attr_type, attr_container) \
99 attr_type get##attr_name() const { return attr_container.get##attr_name(); } \
100 void set##attr_name(const attr_type& v) { \
101 if (attr_container.get##attr_name() == v) return; \
102 attr_container.set##attr_name(v); \
103 this->invalidate(); \
104 }
Florin Malita4aa44412017-12-19 12:21:02 -0500105
106} // namespace sksg
107
108#endif // SkSGNode_DEFINED