1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software Foundation,
14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 *
16 * The Original Code is Copyright (C) 2013 Blender Foundation.
17 * All rights reserved.
18 */
19
20 /** \file
21 * \ingroup depsgraph
22 */
23
24 #include "intern/node/deg_node_id.h"
25
26 #include <cstring> /* required for STREQ later on. */
27 #include <stdio.h>
28
29 #include "BLI_string.h"
30 #include "BLI_utildefines.h"
31
32 #include "DNA_ID.h"
33 #include "DNA_anim_types.h"
34
35 #include "BKE_lib_id.h"
36
37 #include "DEG_depsgraph.h"
38
39 #include "intern/eval/deg_eval_copy_on_write.h"
40 #include "intern/node/deg_node_component.h"
41 #include "intern/node/deg_node_factory.h"
42 #include "intern/node/deg_node_time.h"
43
44 namespace blender {
45 namespace deg {
46
linkedStateAsString(eDepsNode_LinkedState_Type linked_state)47 const char *linkedStateAsString(eDepsNode_LinkedState_Type linked_state)
48 {
49 switch (linked_state) {
50 case DEG_ID_LINKED_INDIRECTLY:
51 return "INDIRECTLY";
52 case DEG_ID_LINKED_VIA_SET:
53 return "VIA_SET";
54 case DEG_ID_LINKED_DIRECTLY:
55 return "DIRECTLY";
56 }
57 BLI_assert(!"Unhandled linked state, should never happen.");
58 return "UNKNOWN";
59 }
60
ComponentIDKey(NodeType type,const char * name)61 IDNode::ComponentIDKey::ComponentIDKey(NodeType type, const char *name) : type(type), name(name)
62 {
63 }
64
operator ==(const ComponentIDKey & other) const65 bool IDNode::ComponentIDKey::operator==(const ComponentIDKey &other) const
66 {
67 return type == other.type && STREQ(name, other.name);
68 }
69
hash() const70 uint64_t IDNode::ComponentIDKey::hash() const
71 {
72 const int type_as_int = static_cast<int>(type);
73 return BLI_ghashutil_combine_hash(BLI_ghashutil_uinthash(type_as_int),
74 BLI_ghashutil_strhash_p(name));
75 }
76
77 /* Initialize 'id' node - from pointer data given. */
init(const ID * id,const char * UNUSED (subdata))78 void IDNode::init(const ID *id, const char *UNUSED(subdata))
79 {
80 BLI_assert(id != nullptr);
81 /* Store ID-pointer. */
82 id_type = GS(id->name);
83 id_orig = (ID *)id;
84 eval_flags = 0;
85 previous_eval_flags = 0;
86 customdata_masks = DEGCustomDataMeshMasks();
87 previous_customdata_masks = DEGCustomDataMeshMasks();
88 linked_state = DEG_ID_LINKED_INDIRECTLY;
89 is_directly_visible = true;
90 is_collection_fully_expanded = false;
91 has_base = false;
92 is_user_modified = false;
93
94 visible_components_mask = 0;
95 previously_visible_components_mask = 0;
96 }
97
init_copy_on_write(ID * id_cow_hint)98 void IDNode::init_copy_on_write(ID *id_cow_hint)
99 {
100 /* Create pointer as early as possible, so we can use it for function
101 * bindings. Rest of data we'll be copying to the new datablock when
102 * it is actually needed. */
103 if (id_cow_hint != nullptr) {
104 // BLI_assert(deg_copy_on_write_is_needed(id_orig));
105 if (deg_copy_on_write_is_needed(id_orig)) {
106 id_cow = id_cow_hint;
107 }
108 else {
109 id_cow = id_orig;
110 }
111 }
112 else if (deg_copy_on_write_is_needed(id_orig)) {
113 id_cow = (ID *)BKE_libblock_alloc_notest(GS(id_orig->name));
114 DEG_COW_PRINT(
115 "Create shallow copy for %s: id_orig=%p id_cow=%p\n", id_orig->name, id_orig, id_cow);
116 deg_tag_copy_on_write_id(id_cow, id_orig);
117 }
118 else {
119 id_cow = id_orig;
120 }
121 }
122
123 /* Free 'id' node. */
~IDNode()124 IDNode::~IDNode()
125 {
126 destroy();
127 }
128
destroy()129 void IDNode::destroy()
130 {
131 if (id_orig == nullptr) {
132 return;
133 }
134
135 for (ComponentNode *comp_node : components.values()) {
136 delete comp_node;
137 }
138
139 /* Free memory used by this CoW ID. */
140 if (id_cow != id_orig && id_cow != nullptr) {
141 deg_free_copy_on_write_datablock(id_cow);
142 MEM_freeN(id_cow);
143 id_cow = nullptr;
144 DEG_COW_PRINT("Destroy CoW for %s: id_orig=%p id_cow=%p\n", id_orig->name, id_orig, id_cow);
145 }
146
147 /* Tag that the node is freed. */
148 id_orig = nullptr;
149 }
150
identifier() const151 string IDNode::identifier() const
152 {
153 char orig_ptr[24], cow_ptr[24];
154 BLI_snprintf(orig_ptr, sizeof(orig_ptr), "%p", id_orig);
155 BLI_snprintf(cow_ptr, sizeof(cow_ptr), "%p", id_cow);
156 return string(nodeTypeAsString(type)) + " : " + name + " (orig: " + orig_ptr +
157 ", eval: " + cow_ptr + ", is_directly_visible " +
158 (is_directly_visible ? "true" : "false") + ")";
159 }
160
find_component(NodeType type,const char * name) const161 ComponentNode *IDNode::find_component(NodeType type, const char *name) const
162 {
163 ComponentIDKey key(type, name);
164 return components.lookup_default(key, nullptr);
165 }
166
add_component(NodeType type,const char * name)167 ComponentNode *IDNode::add_component(NodeType type, const char *name)
168 {
169 ComponentNode *comp_node = find_component(type, name);
170 if (!comp_node) {
171 DepsNodeFactory *factory = type_get_factory(type);
172 comp_node = (ComponentNode *)factory->create_node(this->id_orig, "", name);
173
174 /* Register. */
175 ComponentIDKey key(type, name);
176 components.add_new(key, comp_node);
177 comp_node->owner = this;
178 }
179 return comp_node;
180 }
181
tag_update(Depsgraph * graph,eUpdateSource source)182 void IDNode::tag_update(Depsgraph *graph, eUpdateSource source)
183 {
184 for (ComponentNode *comp_node : components.values()) {
185 /* Relations update does explicit animation update when needed. Here we ignore animation
186 * component to avoid loss of possible unkeyed changes. */
187 if (comp_node->type == NodeType::ANIMATION && source == DEG_UPDATE_SOURCE_RELATIONS) {
188 continue;
189 }
190 comp_node->tag_update(graph, source);
191 }
192 }
193
finalize_build(Depsgraph * graph)194 void IDNode::finalize_build(Depsgraph *graph)
195 {
196 /* Finalize build of all components. */
197 for (ComponentNode *comp_node : components.values()) {
198 comp_node->finalize_build(graph);
199 }
200 visible_components_mask = get_visible_components_mask();
201 }
202
get_visible_components_mask() const203 IDComponentsMask IDNode::get_visible_components_mask() const
204 {
205 IDComponentsMask result = 0;
206 for (ComponentNode *comp_node : components.values()) {
207 if (comp_node->affects_directly_visible) {
208 const int component_type_as_int = static_cast<int>(comp_node->type);
209 BLI_assert(component_type_as_int < 64);
210 result |= (1ULL << component_type_as_int);
211 }
212 }
213 return result;
214 }
215
216 } // namespace deg
217 } // namespace blender
218