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