Merge branch 'master' into blender2.8
[blender.git] / source / blender / depsgraph / intern / nodes / deg_node_id.cc
index 478cc2863b07f81c80d3184e643b8dd72828421a..edc5c0114f9a636ead0bcbc2e8ba344f85288565 100644 (file)
@@ -41,8 +41,12 @@ extern "C" {
 #include "DNA_anim_types.h"
 
 #include "BKE_animsys.h"
+#include "BKE_library.h"
 }
 
+#include "DEG_depsgraph.h"
+
+#include "intern/eval/deg_eval_copy_on_write.h"
 #include "intern/nodes/deg_node_time.h"
 #include "intern/depsgraph_intern.h"
 
@@ -58,8 +62,8 @@ IDDepsNode::ComponentIDKey::ComponentIDKey(eDepsNode_Type type,
 
 bool IDDepsNode::ComponentIDKey::operator== (const ComponentIDKey &other) const
 {
-    return type == other.type &&
-           STREQ(name, other.name);
+       return type == other.type &&
+               STREQ(name, other.name);
 }
 
 static unsigned int id_deps_node_hash_key(const void *key_v)
@@ -95,33 +99,77 @@ static void id_deps_node_hash_value_free(void *value_v)
 /* Initialize 'id' node - from pointer data given. */
 void IDDepsNode::init(const ID *id, const char *UNUSED(subdata))
 {
-       /* Store ID-pointer. */
        BLI_assert(id != NULL);
-       this->id = (ID *)id;
-       this->layers = (1 << 20) - 1;
-       this->eval_flags = 0;
-
-       /* For object we initialize layers to layer from base. */
-       if (GS(id->name) == ID_OB) {
-               this->layers = 0;
-       }
+       /* Store ID-pointer. */
+       id_orig = (ID *)id;
+       eval_flags = 0;
+       linked_state = DEG_ID_LINKED_INDIRECTLY;
 
        components = BLI_ghash_new(id_deps_node_hash_key,
                                   id_deps_node_hash_key_cmp,
                                   "Depsgraph id components hash");
+}
 
-       /* NOTE: components themselves are created if/when needed.
-        * This prevents problems with components getting added
-        * twice if an ID-Ref needs to be created to house it...
+void IDDepsNode::init_copy_on_write(ID *id_cow_hint)
+{
+       /* Early output for non-copy-on-write case: we keep CoW pointer same as
+        * an original one.
+        */
+       if (!DEG_depsgraph_use_copy_on_write()) {
+               UNUSED_VARS(id_cow_hint);
+               id_cow = id_orig;
+               return;
+       }
+       /* Create pointer as early as possible, so we can use it for function
+        * bindings. Rest of data we'll be copying to the new datablock when
+        * it is actually needed.
         */
+       if (id_cow_hint != NULL) {
+               // BLI_assert(deg_copy_on_write_is_needed(id_orig));
+               if (deg_copy_on_write_is_needed(id_orig)) {
+                       id_cow = id_cow_hint;
+               }
+               else {
+                       id_cow = id_orig;
+               }
+       }
+       else if (deg_copy_on_write_is_needed(id_orig)) {
+               id_cow = (ID *)BKE_libblock_alloc_notest(GS(id_orig->name));
+               DEG_COW_PRINT("Create shallow copy for %s: id_orig=%p id_cow=%p\n",
+                             id_orig->name, id_orig, id_cow);
+               deg_tag_copy_on_write_id(id_cow, id_orig);
+       }
+       else {
+               id_cow = id_orig;
+       }
 }
 
 /* Free 'id' node. */
 IDDepsNode::~IDDepsNode()
 {
+       destroy();
+}
+
+void IDDepsNode::destroy()
+{
+       if (id_orig == NULL) {
+               return;
+       }
+
        BLI_ghash_free(components,
                       id_deps_node_hash_key_free,
                       id_deps_node_hash_value_free);
+
+       /* Free memory used by this CoW ID. */
+       if (id_cow != id_orig && id_cow != NULL) {
+               deg_free_copy_on_write_datablock(id_cow);
+               MEM_freeN(id_cow);
+               DEG_COW_PRINT("Destroy CoW for %s: id_orig=%p id_cow=%p\n",
+                             id_orig->name, id_orig, id_cow);
+       }
+
+       /* Tag that the node is freed. */
+       id_orig = NULL;
 }
 
 ComponentDepsNode *IDDepsNode::find_component(eDepsNode_Type type,
@@ -137,7 +185,7 @@ ComponentDepsNode *IDDepsNode::add_component(eDepsNode_Type type,
        ComponentDepsNode *comp_node = find_component(type, name);
        if (!comp_node) {
                DepsNodeFactory *factory = deg_type_get_factory(type);
-               comp_node = (ComponentDepsNode *)factory->create_node(this->id, "", name);
+               comp_node = (ComponentDepsNode *)factory->create_node(this->id_orig, "", name);
 
                /* Register. */
                ComponentIDKey *key = OBJECT_GUARDED_NEW(ComponentIDKey, type, name);
@@ -151,27 +199,17 @@ void IDDepsNode::tag_update(Depsgraph *graph)
 {
        GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp_node, components)
        {
-               /* TODO(sergey): What about drievrs? */
-               bool do_component_tag = comp_node->type != DEG_NODE_TYPE_ANIMATION;
-               if (comp_node->type == DEG_NODE_TYPE_ANIMATION) {
-                       AnimData *adt = BKE_animdata_from_id(id);
-                       /* Animation data might be null if relations are tagged for update. */
-                       if (adt != NULL && (adt->recalc & ADT_RECALC_ANIM)) {
-                               do_component_tag = true;
-                       }
-               }
-               if (do_component_tag) {
-                       comp_node->tag_update(graph);
-               }
+               comp_node->tag_update(graph);
        }
        GHASH_FOREACH_END();
 }
 
-void IDDepsNode::finalize_build()
+void IDDepsNode::finalize_build(Depsgraph *graph)
 {
+       /* Finalize build of all components. */
        GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp_node, components)
        {
-               comp_node->finalize_build();
+               comp_node->finalize_build(graph);
        }
        GHASH_FOREACH_END();
 }