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