Optimization: pass Main to BKE_library_foreach_ID_link() and use its relations.
authorBastien Montagne <montagne29@wanadoo.fr>
Mon, 30 Jan 2017 20:41:44 +0000 (21:41 +0100)
committerBastien Montagne <montagne29@wanadoo.fr>
Mon, 30 Jan 2017 21:33:20 +0000 (22:33 +0100)
Use Main->relations in BKE_library_foreach_ID_link(), when possible
(i.e. IDWALK_READONLY is set), and if the data is available of course.

This is quite minor optimization, no sensible improvements are expected,
but does not hurt either to avoid potentially tens of looping over e.g.
objects constraints and modifiers, or heap of drivers...

source/blender/blenkernel/BKE_library.h
source/blender/blenkernel/BKE_library_query.h
source/blender/blenkernel/intern/brush.c
source/blender/blenkernel/intern/library.c
source/blender/blenkernel/intern/library_query.c
source/blender/blenkernel/intern/library_remap.c
source/blender/blenkernel/intern/object.c
source/blender/editors/object/object_relations.c
source/blender/python/intern/bpy_rna_id_collection.c
source/blender/windowmanager/intern/wm_operators.c

index 3403567..72ae2cf 100644 (file)
@@ -86,7 +86,7 @@ bool id_make_local(struct Main *bmain, struct ID *id, const bool test, const boo
 bool id_single_user(struct bContext *C, struct ID *id, struct PointerRNA *ptr, struct PropertyRNA *prop);
 bool id_copy(struct Main *bmain, struct ID *id, struct ID **newid, bool test);
 void id_sort_by_name(struct ListBase *lb, struct ID *id);
-void BKE_id_expand_local(struct ID *id);
+void BKE_id_expand_local(struct Main *bmain, struct ID *id);
 void BKE_id_copy_ensure_local(struct Main *bmain, struct ID *old_id, struct ID *new_id);
 
 bool new_id(struct ListBase *lb, struct ID *id, const char *name);
index c80eb7b..693d5e9 100644 (file)
@@ -80,7 +80,8 @@ enum {
 };
 
 /* Loop over all of the ID's this datablock links to. */
-void BKE_library_foreach_ID_link(struct ID *id, LibraryIDLinkCallback callback, void *user_data, int flag);
+void BKE_library_foreach_ID_link(
+        struct Main *bmain, struct ID *id, LibraryIDLinkCallback callback, void *user_data, int flag);
 void BKE_library_update_ID_link_user(struct ID *id_dst, struct ID *id_src, const int cd_flag);
 
 int BKE_library_ID_use_ID(struct ID *id_user, struct ID *id_used);
index 0d509ec..57b707a 100644 (file)
@@ -239,7 +239,7 @@ void BKE_brush_make_local(Main *bmain, Brush *brush, const bool lib_local)
        if (lib_local || is_local) {
                if (!is_lib) {
                        id_clear_lib_data(bmain, &brush->id);
-                       BKE_id_expand_local(&brush->id);
+                       BKE_id_expand_local(bmain, &brush->id);
 
                        /* enable fake user by default */
                        id_fake_user_set(&brush->id);
index bb426ac..3f75bb8 100644 (file)
@@ -293,9 +293,9 @@ static int id_expand_local_callback(
 /**
  * Expand ID usages of given id as 'extern' (and no more indirect) linked data. Used by ID copy/make_local functions.
  */
-void BKE_id_expand_local(ID *id)
+void BKE_id_expand_local(Main *bmain, ID *id)
 {
-       BKE_library_foreach_ID_link(id, id_expand_local_callback, NULL, 0);
+       BKE_library_foreach_ID_link(bmain, id, id_expand_local_callback, NULL, IDWALK_READONLY);
 }
 
 /**
@@ -304,7 +304,7 @@ void BKE_id_expand_local(ID *id)
 void BKE_id_copy_ensure_local(Main *bmain, ID *old_id, ID *new_id)
 {
        if (ID_IS_LINKED_DATABLOCK(old_id)) {
-               BKE_id_expand_local(new_id);
+               BKE_id_expand_local(bmain, new_id);
                BKE_id_lib_local_paths(bmain, old_id->lib, new_id);
        }
 }
@@ -331,7 +331,7 @@ void BKE_id_make_local_generic(Main *bmain, ID *id, const bool id_in_mainlist, c
        if (lib_local || is_local) {
                if (!is_lib) {
                        id_clear_lib_data_ex(bmain, id, id_in_mainlist);
-                       BKE_id_expand_local(id);
+                       BKE_id_expand_local(bmain, id);
                }
                else {
                        ID *id_new;
@@ -1329,7 +1329,7 @@ void BKE_main_relations_create(Main *bmain)
 
        for (a = set_listbasepointers(bmain, lbarray); a--; ) {
                for (id = lbarray[a]->first; id; id = id->next) {
-                       BKE_library_foreach_ID_link(id, main_relations_create_cb, bmain->relations, IDWALK_READONLY);
+                       BKE_library_foreach_ID_link(NULL, id, main_relations_create_cb, bmain->relations, IDWALK_READONLY);
                }
        }
 }
@@ -1777,7 +1777,7 @@ void BKE_library_make_local(
                         * some indirect usages. So instead of making a copy that se'll likely get rid of later, directly make
                         * that data block local. Saves a tremendous amount of time with complex scenes... */
                        id_clear_lib_data_ex(bmain, id, true);
-                       BKE_id_expand_local(id);
+                       BKE_id_expand_local(bmain, id);
                        id->tag &= ~LIB_TAG_DOIT;
                }
                else {
index 28f66b5..03c4b80 100644 (file)
@@ -282,7 +282,7 @@ static void library_foreach_ID_as_subdata_link(
                }
        }
        else {
-               BKE_library_foreach_ID_link(id, callback, user_data, flag);
+               BKE_library_foreach_ID_link(NULL, id, callback, user_data, flag);
        }
 
        FOREACH_FINALIZE_VOID;
@@ -293,7 +293,7 @@ static void library_foreach_ID_as_subdata_link(
  *
  * \note: May be extended to be recursive in the future.
  */
-void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *user_data, int flag)
+void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback callback, void *user_data, int flag)
 {
        LibraryForeachIDData data;
        int i;
@@ -321,10 +321,22 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
 #define CALLBACK_INVOKE(check_id_super, cb_flag) \
        FOREACH_CALLBACK_INVOKE(&data, check_id_super, cb_flag)
 
-       do {
+       for (; id != NULL; id = (flag & IDWALK_RECURSE) ? BLI_LINKSTACK_POP(data.ids_todo) : NULL) {
                data.self_id = id;
                data.cd_flag = ID_IS_LINKED_DATABLOCK(id) ? IDWALK_INDIRECT_USAGE : 0;
 
+               if (bmain != NULL && bmain->relations != NULL && (flag & IDWALK_READONLY)) {
+                       /* Note that this is minor optimization, even in worst cases (like id being an object with lots of
+                        * drivers and constraints and modifiers, or material etc. with huge node tree),
+                        * but we might as well use it (Main->relations is always assumed valid, it's responsability of code
+                        * creating it to free it, especially if/when it starts modifying Main database). */
+                       MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->id_user_to_used, id);
+                       for (; entry != NULL; entry = entry->next) {
+                               FOREACH_CALLBACK_INVOKE_ID_PP(&data, entry->id_pointer, entry->usage_flag);
+                       }
+                       continue;
+               }
+
                AnimData *adt = BKE_animdata_from_id(id);
                if (adt) {
                        library_foreach_animationData(&data, adt);
@@ -899,7 +911,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
                                break;
 
                }
-       } while ((id = (flag & IDWALK_RECURSE) ? BLI_LINKSTACK_POP(data.ids_todo) : NULL));
+       }
 
 FOREACH_FINALIZE:
        if (data.ids_handled) {
@@ -1088,7 +1100,7 @@ int BKE_library_ID_use_ID(ID *id_user, ID *id_used)
        iter.curr_id = id_user;
        iter.count_direct = iter.count_indirect = 0;
 
-       BKE_library_foreach_ID_link(iter.curr_id, foreach_libblock_id_users_callback, (void *)&iter, IDWALK_NOP);
+       BKE_library_foreach_ID_link(NULL, iter.curr_id, foreach_libblock_id_users_callback, (void *)&iter, IDWALK_READONLY);
 
        return iter.count_direct + iter.count_indirect;
 }
@@ -1117,7 +1129,7 @@ static bool library_ID_is_used(Main *bmain, void *idv, const bool check_linked)
                        }
                        iter.curr_id = id_curr;
                        BKE_library_foreach_ID_link(
-                                   id_curr, foreach_libblock_id_users_callback, &iter, IDWALK_NOP);
+                                   bmain, id_curr, foreach_libblock_id_users_callback, &iter, IDWALK_READONLY);
 
                        is_defined = ((check_linked ? iter.count_indirect : iter.count_direct) != 0);
                }
@@ -1168,7 +1180,7 @@ void BKE_library_ID_test_usages(Main *bmain, void *idv, bool *is_used_local, boo
                                continue;
                        }
                        iter.curr_id = id_curr;
-                       BKE_library_foreach_ID_link(id_curr, foreach_libblock_id_users_callback, &iter, IDWALK_NOP);
+                       BKE_library_foreach_ID_link(bmain, id_curr, foreach_libblock_id_users_callback, &iter, IDWALK_READONLY);
 
                        is_defined = (iter.count_direct != 0 && iter.count_indirect != 0);
                }
@@ -1245,7 +1257,8 @@ void BKE_library_unused_linked_data_set_tag(Main *bmain, const bool do_init_tag)
                                        /* Unused ID (so far), no need to check it further. */
                                        continue;
                                }
-                               BKE_library_foreach_ID_link(id, foreach_libblock_used_linked_data_tag_clear_cb, &do_loop, IDWALK_NOP);
+                               BKE_library_foreach_ID_link(
+                                           bmain, id, foreach_libblock_used_linked_data_tag_clear_cb, &do_loop, IDWALK_READONLY);
                        }
                }
        }
@@ -1272,7 +1285,8 @@ void BKE_library_indirectly_used_data_tag_clear(Main *bmain)
                                        /* Local or non-indirectly-used ID (so far), no need to check it further. */
                                        continue;
                                }
-                               BKE_library_foreach_ID_link(id, foreach_libblock_used_linked_data_tag_clear_cb, &do_loop, IDWALK_NOP);
+                               BKE_library_foreach_ID_link(
+                                           bmain, id, foreach_libblock_used_linked_data_tag_clear_cb, &do_loop, IDWALK_READONLY);
                        }
                }
        }
index 5fba7b7..ff66c37 100644 (file)
@@ -438,7 +438,7 @@ ATTR_NONNULL(1) static void libblock_remap_data(
 #endif
                r_id_remap_data->id = id;
                libblock_remap_data_preprocess(r_id_remap_data);
-               BKE_library_foreach_ID_link(id, foreach_libblock_remap_callback, (void *)r_id_remap_data, IDWALK_NOP);
+               BKE_library_foreach_ID_link(NULL, id, foreach_libblock_remap_callback, (void *)r_id_remap_data, IDWALK_NOP);
        }
        else {
                i = set_listbasepointers(bmain, lb_array);
@@ -460,7 +460,7 @@ ATTR_NONNULL(1) static void libblock_remap_data(
                                r_id_remap_data->id = id_curr;
                                libblock_remap_data_preprocess(r_id_remap_data);
                                BKE_library_foreach_ID_link(
-                                           id_curr, foreach_libblock_remap_callback, (void *)r_id_remap_data, IDWALK_NOP);
+                                           NULL, id_curr, foreach_libblock_remap_callback, (void *)r_id_remap_data, IDWALK_NOP);
                        }
                }
        }
@@ -719,7 +719,7 @@ void BKE_libblock_relink_to_newid(ID *id)
        if (ID_IS_LINKED_DATABLOCK(id))
                return;
 
-       BKE_library_foreach_ID_link(id, id_relink_to_newid_looper, NULL, 0);
+       BKE_library_foreach_ID_link(NULL, id, id_relink_to_newid_looper, NULL, 0);
 }
 
 void BKE_libblock_free_data(Main *UNUSED(bmain), ID *id)
index 41f725b..09b3a73 100644 (file)
@@ -1204,7 +1204,7 @@ void BKE_object_make_local_ex(Main *bmain, Object *ob, const bool lib_local, con
        if (lib_local || is_local) {
                if (!is_lib) {
                        id_clear_lib_data(bmain, &ob->id);
-                       BKE_id_expand_local(&ob->id);
+                       BKE_id_expand_local(bmain, &ob->id);
                        if (clear_proxy) {
                                if (ob->proxy_from != NULL) {
                                        ob->proxy_from->proxy = NULL;
index d30022c..01c307f 100644 (file)
@@ -2170,12 +2170,12 @@ static void tag_localizable_objects(bContext *C, const int mode)
         */
        for (Object *object = bmain->object.first; object; object = object->id.next) {
                if ((object->id.tag & LIB_TAG_DOIT) == 0) {
-                       BKE_library_foreach_ID_link(&object->id, tag_localizable_looper, NULL, IDWALK_READONLY);
+                       BKE_library_foreach_ID_link(NULL, &object->id, tag_localizable_looper, NULL, IDWALK_READONLY);
                }
                if (object->data) {
                        ID *data_id = (ID *) object->data;
                        if ((data_id->tag & LIB_TAG_DOIT) == 0) {
-                               BKE_library_foreach_ID_link(data_id, tag_localizable_looper, NULL, IDWALK_READONLY);
+                               BKE_library_foreach_ID_link(NULL, data_id, tag_localizable_looper, NULL, IDWALK_READONLY);
                        }
                }
        }
index 1037c83..a7bd5af 100644 (file)
@@ -263,7 +263,7 @@ static PyObject *bpy_user_map(PyObject *UNUSED(self), PyObject *args, PyObject *
                        }
 
                        data_cb.id_curr = id;
-                       BKE_library_foreach_ID_link(id, foreach_libblock_id_user_map_callback, &data_cb, IDWALK_NOP);
+                       BKE_library_foreach_ID_link(NULL, id, foreach_libblock_id_user_map_callback, &data_cb, IDWALK_NOP);
 
                        if (data_cb.py_id_curr) {
                                Py_DECREF(data_cb.py_id_curr);
index 36721d3..682f4dc 100644 (file)
@@ -3948,7 +3948,7 @@ static int previews_ensure_exec(bContext *C, wmOperator *UNUSED(op))
                preview_id_data.scene = scene;
                id = (ID *)scene;
 
-               BKE_library_foreach_ID_link(id, previews_id_ensure_callback, &preview_id_data, IDWALK_RECURSE);
+               BKE_library_foreach_ID_link(NULL, id, previews_id_ensure_callback, &preview_id_data, IDWALK_RECURSE);
        }
 
        /* Check a last time for ID not used (fake users only, in theory), and