From 1ff8be24ef8970f140865dfb118112ec08e7dfad Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 7 Nov 2018 16:06:36 +0100 Subject: Cleanup/Refactor: move Main stuff into BKE's new main.c file (and header). We already had a BKE_main.h header, no reason not to put there Main-specific functions, BKE_library has already more than enough to handle with IDs and library management! --- source/blender/blenkernel/BKE_library.h | 23 +- source/blender/blenkernel/BKE_main.h | 30 +- source/blender/blenkernel/CMakeLists.txt | 1 + source/blender/blenkernel/intern/blender.c | 1 + source/blender/blenkernel/intern/idcode.c | 2 +- source/blender/blenkernel/intern/library.c | 391 -------------------- source/blender/blenkernel/intern/library_idmap.c | 1 + source/blender/blenkernel/intern/main.c | 446 +++++++++++++++++++++++ source/blender/depsgraph/intern/depsgraph.h | 2 +- 9 files changed, 480 insertions(+), 417 deletions(-) create mode 100644 source/blender/blenkernel/intern/main.c (limited to 'source') diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h index 897d6206641..b821d19c0d6 100644 --- a/source/blender/blenkernel/BKE_library.h +++ b/source/blender/blenkernel/BKE_library.h @@ -165,28 +165,7 @@ bool new_id(struct ListBase *lb, struct ID *id, const char *name) ATTR_NONNULL(1 void id_clear_lib_data(struct Main *bmain, struct ID *id); void id_clear_lib_data_ex(struct Main *bmain, struct ID *id, const bool id_in_mainlist); -struct ListBase *which_libbase(struct Main *mainlib, short type); - -#define MAX_LIBARRAY 37 -int set_listbasepointers(struct Main *main, struct ListBase *lb[MAX_LIBARRAY]); - -/* Main API */ -struct Main *BKE_main_new(void); -void BKE_main_free(struct Main *mainvar); - -void BKE_main_lock(struct Main *bmain); -void BKE_main_unlock(struct Main *bmain); - -void BKE_main_relations_create(struct Main *bmain); -void BKE_main_relations_free(struct Main *bmain); - -struct BlendThumbnail *BKE_main_thumbnail_from_imbuf(struct Main *bmain, struct ImBuf *img); -struct ImBuf *BKE_main_thumbnail_to_imbuf(struct Main *bmain, struct BlendThumbnail *data); -void BKE_main_thumbnail_create(struct Main *bmain); - -const char *BKE_main_blendfile_path(const struct Main *bmain) ATTR_NONNULL(); -const char *BKE_main_blendfile_path_from_global(void); - +/* Affect whole Main database. */ void BKE_main_id_tag_idcode(struct Main *mainvar, const short type, const int tag, const bool value); void BKE_main_id_tag_listbase(struct ListBase *lb, const int tag, const bool value); void BKE_main_id_tag_all(struct Main *mainvar, const int tag, const bool value); diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h index 492962f3b00..e5a816b92ce 100644 --- a/source/blender/blenkernel/BKE_main.h +++ b/source/blender/blenkernel/BKE_main.h @@ -42,15 +42,20 @@ */ #include "DNA_listBase.h" +#include "BLI_compiler_attrs.h" +#include "BLI_sys_types.h" + #ifdef __cplusplus extern "C" { #endif +struct BlendThumbnail; +struct BLI_mempool; struct Depsgraph; +struct GHash; +struct ImBuf; struct Library; struct MainLock; -struct GHash; -struct BLI_mempool; /* Blender thumbnail, as written on file (width, height, and data as char RGBA). */ /* We pack pixel data after that struct. */ @@ -134,6 +139,27 @@ typedef struct Main { struct MainLock *lock; } Main; +struct Main *BKE_main_new(void); +void BKE_main_free(struct Main *mainvar); + +void BKE_main_lock(struct Main *bmain); +void BKE_main_unlock(struct Main *bmain); + +void BKE_main_relations_create(struct Main *bmain); +void BKE_main_relations_free(struct Main *bmain); + +struct BlendThumbnail *BKE_main_thumbnail_from_imbuf(struct Main *bmain, struct ImBuf *img); +struct ImBuf *BKE_main_thumbnail_to_imbuf(struct Main *bmain, struct BlendThumbnail *data); +void BKE_main_thumbnail_create(struct Main *bmain); + +const char *BKE_main_blendfile_path(const struct Main *bmain) ATTR_NONNULL(); +const char *BKE_main_blendfile_path_from_global(void); + +struct ListBase *which_libbase(struct Main *mainlib, short type); + +#define MAX_LIBARRAY 37 +int set_listbasepointers(struct Main *main, struct ListBase *lb[MAX_LIBARRAY]); + #define MAIN_VERSION_ATLEAST(main, ver, subver) \ ((main)->versionfile > (ver) || (main->versionfile == (ver) && (main)->subversionfile >= (subver))) diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index b18b6f6d63d..4161a5ecd79 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -136,6 +136,7 @@ set(SRC intern/library_query.c intern/library_remap.c intern/linestyle.c + intern/main.c intern/mask.c intern/mask_evaluate.c intern/mask_rasterize.c diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 66020679bf7..d0dea75860e 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -58,6 +58,7 @@ #include "BKE_image.h" #include "BKE_layer.h" #include "BKE_library.h" +#include "BKE_main.h" #include "BKE_node.h" #include "BKE_report.h" #include "BKE_scene.h" diff --git a/source/blender/blenkernel/intern/idcode.c b/source/blender/blenkernel/intern/idcode.c index 8328d71128a..23648a1a984 100644 --- a/source/blender/blenkernel/intern/idcode.c +++ b/source/blender/blenkernel/intern/idcode.c @@ -39,7 +39,7 @@ #include "BLT_translation.h" -#include "BKE_library.h" +#include "BKE_main.h" #include "BKE_idcode.h" typedef struct { diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 74c3341fa96..64227219683 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -898,85 +898,6 @@ void BKE_libblock_management_usercounts_clear(Main *bmain, void *idv) id->tag |= LIB_TAG_NO_USER_REFCOUNT; } -ListBase *which_libbase(Main *mainlib, short type) -{ - switch ((ID_Type)type) { - case ID_SCE: - return &(mainlib->scene); - case ID_LI: - return &(mainlib->library); - case ID_OB: - return &(mainlib->object); - case ID_ME: - return &(mainlib->mesh); - case ID_CU: - return &(mainlib->curve); - case ID_MB: - return &(mainlib->mball); - case ID_MA: - return &(mainlib->mat); - case ID_TE: - return &(mainlib->tex); - case ID_IM: - return &(mainlib->image); - case ID_LT: - return &(mainlib->latt); - case ID_LA: - return &(mainlib->lamp); - case ID_CA: - return &(mainlib->camera); - case ID_IP: - return &(mainlib->ipo); - case ID_KE: - return &(mainlib->key); - case ID_WO: - return &(mainlib->world); - case ID_SCR: - return &(mainlib->screen); - case ID_VF: - return &(mainlib->vfont); - case ID_TXT: - return &(mainlib->text); - case ID_SPK: - return &(mainlib->speaker); - case ID_LP: - return &(mainlib->lightprobe); - case ID_SO: - return &(mainlib->sound); - case ID_GR: - return &(mainlib->collection); - case ID_AR: - return &(mainlib->armature); - case ID_AC: - return &(mainlib->action); - case ID_NT: - return &(mainlib->nodetree); - case ID_BR: - return &(mainlib->brush); - case ID_PA: - return &(mainlib->particle); - case ID_WM: - return &(mainlib->wm); - case ID_GD: - return &(mainlib->gpencil); - case ID_MC: - return &(mainlib->movieclip); - case ID_MSK: - return &(mainlib->mask); - case ID_LS: - return &(mainlib->linestyle); - case ID_PAL: - return &(mainlib->palettes); - case ID_PC: - return &(mainlib->paintcurves); - case ID_CF: - return &(mainlib->cachefiles); - case ID_WS: - return &(mainlib->workspaces); - } - return NULL; -} - /** * Clear or set given tags for all ids in listbase (runtime tags). */ @@ -1065,70 +986,6 @@ void BKE_main_lib_objects_recalc_all(Main *bmain) DEG_id_type_tag(bmain, ID_OB); } -/** - * puts into array *lb pointers to all the ListBase structs in main, - * and returns the number of them as the function result. This is useful for - * generic traversal of all the blocks in a Main (by traversing all the - * lists in turn), without worrying about block types. - * - * \note MAX_LIBARRAY define should match this code */ -int set_listbasepointers(Main *main, ListBase **lb) -{ - /* BACKWARDS! also watch order of free-ing! (mesh<->mat), first items freed last. - * This is important because freeing data decreases usercounts of other datablocks, - * if this data is its self freed it can crash. */ - lb[INDEX_ID_LI] = &(main->library); /* Libraries may be accessed from pretty much any other ID... */ - lb[INDEX_ID_IP] = &(main->ipo); - lb[INDEX_ID_AC] = &(main->action); /* moved here to avoid problems when freeing with animato (aligorith) */ - lb[INDEX_ID_KE] = &(main->key); - lb[INDEX_ID_PAL] = &(main->palettes); /* referenced by gpencil, so needs to be before that to avoid crashes */ - lb[INDEX_ID_GD] = &(main->gpencil); /* referenced by nodes, objects, view, scene etc, before to free after. */ - lb[INDEX_ID_NT] = &(main->nodetree); - lb[INDEX_ID_IM] = &(main->image); - lb[INDEX_ID_TE] = &(main->tex); - lb[INDEX_ID_MA] = &(main->mat); - lb[INDEX_ID_VF] = &(main->vfont); - - /* Important!: When adding a new object type, - * the specific data should be inserted here - */ - - lb[INDEX_ID_AR] = &(main->armature); - - lb[INDEX_ID_CF] = &(main->cachefiles); - lb[INDEX_ID_ME] = &(main->mesh); - lb[INDEX_ID_CU] = &(main->curve); - lb[INDEX_ID_MB] = &(main->mball); - - lb[INDEX_ID_LT] = &(main->latt); - lb[INDEX_ID_LA] = &(main->lamp); - lb[INDEX_ID_CA] = &(main->camera); - - lb[INDEX_ID_TXT] = &(main->text); - lb[INDEX_ID_SO] = &(main->sound); - lb[INDEX_ID_GR] = &(main->collection); - lb[INDEX_ID_PAL] = &(main->palettes); - lb[INDEX_ID_PC] = &(main->paintcurves); - lb[INDEX_ID_BR] = &(main->brush); - lb[INDEX_ID_PA] = &(main->particle); - lb[INDEX_ID_SPK] = &(main->speaker); - lb[INDEX_ID_LP] = &(main->lightprobe); - - lb[INDEX_ID_WO] = &(main->world); - lb[INDEX_ID_MC] = &(main->movieclip); - lb[INDEX_ID_SCR] = &(main->screen); - lb[INDEX_ID_OB] = &(main->object); - lb[INDEX_ID_LS] = &(main->linestyle); /* referenced by scenes */ - lb[INDEX_ID_SCE] = &(main->scene); - lb[INDEX_ID_WS] = &(main->workspaces); /* before wm, so it's freed after it! */ - lb[INDEX_ID_WM] = &(main->wm); - lb[INDEX_ID_MSK] = &(main->mask); - - lb[INDEX_ID_NULL] = NULL; - - return (MAX_LIBARRAY - 1); -} - /* *********** ALLOC AND FREE ***************** * * BKE_libblock_free(ListBase *lb, ID *id ) @@ -1511,254 +1368,6 @@ void BKE_library_free(Library *lib) freePackedFile(lib->packedfile); } -Main *BKE_main_new(void) -{ - Main *bmain = MEM_callocN(sizeof(Main), "new main"); - bmain->lock = MEM_mallocN(sizeof(SpinLock), "main lock"); - BLI_spin_init((SpinLock *)bmain->lock); - return bmain; -} - -void BKE_main_free(Main *mainvar) -{ - /* also call when reading a file, erase all, etc */ - ListBase *lbarray[MAX_LIBARRAY]; - int a; - - MEM_SAFE_FREE(mainvar->blen_thumb); - - a = set_listbasepointers(mainvar, lbarray); - while (a--) { - ListBase *lb = lbarray[a]; - ID *id; - - while ( (id = lb->first) ) { -#if 1 - BKE_libblock_free_ex(mainvar, id, false, false); -#else - /* errors freeing ID's can be hard to track down, - * enable this so valgrind will give the line number in its error log */ - switch (a) { - case 0: BKE_libblock_free_ex(mainvar, id, false, false); break; - case 1: BKE_libblock_free_ex(mainvar, id, false, false); break; - case 2: BKE_libblock_free_ex(mainvar, id, false, false); break; - case 3: BKE_libblock_free_ex(mainvar, id, false, false); break; - case 4: BKE_libblock_free_ex(mainvar, id, false, false); break; - case 5: BKE_libblock_free_ex(mainvar, id, false, false); break; - case 6: BKE_libblock_free_ex(mainvar, id, false, false); break; - case 7: BKE_libblock_free_ex(mainvar, id, false, false); break; - case 8: BKE_libblock_free_ex(mainvar, id, false, false); break; - case 9: BKE_libblock_free_ex(mainvar, id, false, false); break; - case 10: BKE_libblock_free_ex(mainvar, id, false, false); break; - case 11: BKE_libblock_free_ex(mainvar, id, false, false); break; - case 12: BKE_libblock_free_ex(mainvar, id, false, false); break; - case 13: BKE_libblock_free_ex(mainvar, id, false, false); break; - case 14: BKE_libblock_free_ex(mainvar, id, false, false); break; - case 15: BKE_libblock_free_ex(mainvar, id, false, false); break; - case 16: BKE_libblock_free_ex(mainvar, id, false, false); break; - case 17: BKE_libblock_free_ex(mainvar, id, false, false); break; - case 18: BKE_libblock_free_ex(mainvar, id, false, false); break; - case 19: BKE_libblock_free_ex(mainvar, id, false, false); break; - case 20: BKE_libblock_free_ex(mainvar, id, false, false); break; - case 21: BKE_libblock_free_ex(mainvar, id, false, false); break; - case 22: BKE_libblock_free_ex(mainvar, id, false, false); break; - case 23: BKE_libblock_free_ex(mainvar, id, false, false); break; - case 24: BKE_libblock_free_ex(mainvar, id, false, false); break; - case 25: BKE_libblock_free_ex(mainvar, id, false, false); break; - case 26: BKE_libblock_free_ex(mainvar, id, false, false); break; - case 27: BKE_libblock_free_ex(mainvar, id, false, false); break; - case 28: BKE_libblock_free_ex(mainvar, id, false, false); break; - case 29: BKE_libblock_free_ex(mainvar, id, false, false); break; - case 30: BKE_libblock_free_ex(mainvar, id, false, false); break; - case 31: BKE_libblock_free_ex(mainvar, id, false, false); break; - case 32: BKE_libblock_free_ex(mainvar, id, false, false); break; - case 33: BKE_libblock_free_ex(mainvar, id, false, false); break; - case 34: BKE_libblock_free_ex(mainvar, id, false, false); break; - default: - BLI_assert(0); - break; - } -#endif - } - } - - if (mainvar->relations) { - BKE_main_relations_free(mainvar); - } - - BLI_spin_end((SpinLock *)mainvar->lock); - MEM_freeN(mainvar->lock); - MEM_freeN(mainvar); -} - -void BKE_main_lock(struct Main *bmain) -{ - BLI_spin_lock((SpinLock *) bmain->lock); -} - -void BKE_main_unlock(struct Main *bmain) -{ - BLI_spin_unlock((SpinLock *) bmain->lock); -} - - -static int main_relations_create_cb(void *user_data, ID *id_self, ID **id_pointer, int cb_flag) -{ - MainIDRelations *rel = user_data; - - if (*id_pointer) { - MainIDRelationsEntry *entry, **entry_p; - - entry = BLI_mempool_alloc(rel->entry_pool); - if (BLI_ghash_ensure_p(rel->id_user_to_used, id_self, (void ***)&entry_p)) { - entry->next = *entry_p; - } - else { - entry->next = NULL; - } - entry->id_pointer = id_pointer; - entry->usage_flag = cb_flag; - *entry_p = entry; - - entry = BLI_mempool_alloc(rel->entry_pool); - if (BLI_ghash_ensure_p(rel->id_used_to_user, *id_pointer, (void ***)&entry_p)) { - entry->next = *entry_p; - } - else { - entry->next = NULL; - } - entry->id_pointer = (ID **)id_self; - entry->usage_flag = cb_flag; - *entry_p = entry; - } - - return IDWALK_RET_NOP; -} - -/** Generate the mappings between used IDs and their users, and vice-versa. */ -void BKE_main_relations_create(Main *bmain) -{ - ListBase *lbarray[MAX_LIBARRAY]; - ID *id; - int a; - - if (bmain->relations != NULL) { - BKE_main_relations_free(bmain); - } - - bmain->relations = MEM_mallocN(sizeof(*bmain->relations), __func__); - bmain->relations->id_used_to_user = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); - bmain->relations->id_user_to_used = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); - bmain->relations->entry_pool = BLI_mempool_create(sizeof(MainIDRelationsEntry), 128, 128, BLI_MEMPOOL_NOP); - - for (a = set_listbasepointers(bmain, lbarray); a--; ) { - for (id = lbarray[a]->first; id; id = id->next) { - BKE_library_foreach_ID_link(NULL, id, main_relations_create_cb, bmain->relations, IDWALK_READONLY); - } - } -} - -void BKE_main_relations_free(Main *bmain) -{ - if (bmain->relations) { - if (bmain->relations->id_used_to_user) { - BLI_ghash_free(bmain->relations->id_used_to_user, NULL, NULL); - } - if (bmain->relations->id_user_to_used) { - BLI_ghash_free(bmain->relations->id_user_to_used, NULL, NULL); - } - BLI_mempool_destroy(bmain->relations->entry_pool); - MEM_freeN(bmain->relations); - bmain->relations = NULL; - } -} - -/** - * Generates a raw .blend file thumbnail data from given image. - * - * \param bmain If not NULL, also store generated data in this Main. - * \param img ImBuf image to generate thumbnail data from. - * \return The generated .blend file raw thumbnail data. - */ -BlendThumbnail *BKE_main_thumbnail_from_imbuf(Main *bmain, ImBuf *img) -{ - BlendThumbnail *data = NULL; - - if (bmain) { - MEM_SAFE_FREE(bmain->blen_thumb); - } - - if (img) { - const size_t sz = BLEN_THUMB_MEMSIZE(img->x, img->y); - data = MEM_mallocN(sz, __func__); - - IMB_rect_from_float(img); /* Just in case... */ - data->width = img->x; - data->height = img->y; - memcpy(data->rect, img->rect, sz - sizeof(*data)); - } - - if (bmain) { - bmain->blen_thumb = data; - } - return data; -} - -/** - * Generates an image from raw .blend file thumbnail \a data. - * - * \param bmain Use this bmain->blen_thumb data if given \a data is NULL. - * \param data Raw .blend file thumbnail data. - * \return An ImBuf from given data, or NULL if invalid. - */ -ImBuf *BKE_main_thumbnail_to_imbuf(Main *bmain, BlendThumbnail *data) -{ - ImBuf *img = NULL; - - if (!data && bmain) { - data = bmain->blen_thumb; - } - - if (data) { - /* Note: we cannot use IMB_allocFromBuffer(), since it tries to dupalloc passed buffer, which will fail - * here (we do not want to pass the first two ints!). */ - img = IMB_allocImBuf((unsigned int)data->width, (unsigned int)data->height, 32, IB_rect | IB_metadata); - memcpy(img->rect, data->rect, BLEN_THUMB_MEMSIZE(data->width, data->height) - sizeof(*data)); - } - - return img; -} - -/** - * Generates an empty (black) thumbnail for given Main. - */ -void BKE_main_thumbnail_create(struct Main *bmain) -{ - MEM_SAFE_FREE(bmain->blen_thumb); - - bmain->blen_thumb = MEM_callocN(BLEN_THUMB_MEMSIZE(BLEN_THUMB_SIZE, BLEN_THUMB_SIZE), __func__); - bmain->blen_thumb->width = BLEN_THUMB_SIZE; - bmain->blen_thumb->height = BLEN_THUMB_SIZE; -} - -/** - * Return filepath of given \a main. - */ -const char *BKE_main_blendfile_path(const Main *bmain) -{ - return bmain->name; -} - -/** - * Return filepath of global main (G_MAIN). - * - * \warning Usage is not recommended, you should always try to get a valid Main pointer from context... - */ -const char *BKE_main_blendfile_path_from_global(void) -{ - return BKE_main_blendfile_path(G_MAIN); -} - /* ***************** ID ************************ */ ID *BKE_libblock_find_name(struct Main *bmain, const short type, const char *name) { diff --git a/source/blender/blenkernel/intern/library_idmap.c b/source/blender/blenkernel/intern/library_idmap.c index daf097b9f0b..1cc13b39a97 100644 --- a/source/blender/blenkernel/intern/library_idmap.c +++ b/source/blender/blenkernel/intern/library_idmap.c @@ -32,6 +32,7 @@ #include "BKE_idcode.h" #include "BKE_library.h" #include "BKE_library_idmap.h" /* own include */ +#include "BKE_main.h" /** \file blender/blenkernel/intern/library_idmap.c * \ingroup bke diff --git a/source/blender/blenkernel/intern/main.c b/source/blender/blenkernel/intern/main.c new file mode 100644 index 00000000000..6291e35e968 --- /dev/null +++ b/source/blender/blenkernel/intern/main.c @@ -0,0 +1,446 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenkernel/intern/main.c + * \ingroup bke + * + * Contains management of Main database itself. + */ + +#include + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_ghash.h" +#include "BLI_mempool.h" +#include "BLI_threads.h" + +#include "DNA_ID.h" + +#include "BKE_global.h" +#include "BKE_library.h" +#include "BKE_library_query.h" +#include "BKE_main.h" + +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" + +Main *BKE_main_new(void) +{ + Main *bmain = MEM_callocN(sizeof(Main), "new main"); + bmain->lock = MEM_mallocN(sizeof(SpinLock), "main lock"); + BLI_spin_init((SpinLock *)bmain->lock); + return bmain; +} + +void BKE_main_free(Main *mainvar) +{ + /* also call when reading a file, erase all, etc */ + ListBase *lbarray[MAX_LIBARRAY]; + int a; + + MEM_SAFE_FREE(mainvar->blen_thumb); + + a = set_listbasepointers(mainvar, lbarray); + while (a--) { + ListBase *lb = lbarray[a]; + ID *id; + + while ( (id = lb->first) ) { +#if 1 + BKE_libblock_free_ex(mainvar, id, false, false); +#else + /* errors freeing ID's can be hard to track down, + * enable this so valgrind will give the line number in its error log */ + switch (a) { + case 0: BKE_libblock_free_ex(mainvar, id, false, false); break; + case 1: BKE_libblock_free_ex(mainvar, id, false, false); break; + case 2: BKE_libblock_free_ex(mainvar, id, false, false); break; + case 3: BKE_libblock_free_ex(mainvar, id, false, false); break; + case 4: BKE_libblock_free_ex(mainvar, id, false, false); break; + case 5: BKE_libblock_free_ex(mainvar, id, false, false); break; + case 6: BKE_libblock_free_ex(mainvar, id, false, false); break; + case 7: BKE_libblock_free_ex(mainvar, id, false, false); break; + case 8: BKE_libblock_free_ex(mainvar, id, false, false); break; + case 9: BKE_libblock_free_ex(mainvar, id, false, false); break; + case 10: BKE_libblock_free_ex(mainvar, id, false, false); break; + case 11: BKE_libblock_free_ex(mainvar, id, false, false); break; + case 12: BKE_libblock_free_ex(mainvar, id, false, false); break; + case 13: BKE_libblock_free_ex(mainvar, id, false, false); break; + case 14: BKE_libblock_free_ex(mainvar, id, false, false); break; + case 15: BKE_libblock_free_ex(mainvar, id, false, false); break; + case 16: BKE_libblock_free_ex(mainvar, id, false, false); break; + case 17: BKE_libblock_free_ex(mainvar, id, false, false); break; + case 18: BKE_libblock_free_ex(mainvar, id, false, false); break; + case 19: BKE_libblock_free_ex(mainvar, id, false, false); break; + case 20: BKE_libblock_free_ex(mainvar, id, false, false); break; + case 21: BKE_libblock_free_ex(mainvar, id, false, false); break; + case 22: BKE_libblock_free_ex(mainvar, id, false, false); break; + case 23: BKE_libblock_free_ex(mainvar, id, false, false); break; + case 24: BKE_libblock_free_ex(mainvar, id, false, false); break; + case 25: BKE_libblock_free_ex(mainvar, id, false, false); break; + case 26: BKE_libblock_free_ex(mainvar, id, false, false); break; + case 27: BKE_libblock_free_ex(mainvar, id, false, false); break; + case 28: BKE_libblock_free_ex(mainvar, id, false, false); break; + case 29: BKE_libblock_free_ex(mainvar, id, false, false); break; + case 30: BKE_libblock_free_ex(mainvar, id, false, false); break; + case 31: BKE_libblock_free_ex(mainvar, id, false, false); break; + case 32: BKE_libblock_free_ex(mainvar, id, false, false); break; + case 33: BKE_libblock_free_ex(mainvar, id, false, false); break; + case 34: BKE_libblock_free_ex(mainvar, id, false, false); break; + default: + BLI_assert(0); + break; + } +#endif + } + } + + if (mainvar->relations) { + BKE_main_relations_free(mainvar); + } + + BLI_spin_end((SpinLock *)mainvar->lock); + MEM_freeN(mainvar->lock); + MEM_freeN(mainvar); +} + +void BKE_main_lock(struct Main *bmain) +{ + BLI_spin_lock((SpinLock *) bmain->lock); +} + +void BKE_main_unlock(struct Main *bmain) +{ + BLI_spin_unlock((SpinLock *) bmain->lock); +} + + +static int main_relations_create_cb(void *user_data, ID *id_self, ID **id_pointer, int cb_flag) +{ + MainIDRelations *rel = user_data; + + if (*id_pointer) { + MainIDRelationsEntry *entry, **entry_p; + + entry = BLI_mempool_alloc(rel->entry_pool); + if (BLI_ghash_ensure_p(rel->id_user_to_used, id_self, (void ***)&entry_p)) { + entry->next = *entry_p; + } + else { + entry->next = NULL; + } + entry->id_pointer = id_pointer; + entry->usage_flag = cb_flag; + *entry_p = entry; + + entry = BLI_mempool_alloc(rel->entry_pool); + if (BLI_ghash_ensure_p(rel->id_used_to_user, *id_pointer, (void ***)&entry_p)) { + entry->next = *entry_p; + } + else { + entry->next = NULL; + } + entry->id_pointer = (ID **)id_self; + entry->usage_flag = cb_flag; + *entry_p = entry; + } + + return IDWALK_RET_NOP; +} + +/** Generate the mappings between used IDs and their users, and vice-versa. */ +void BKE_main_relations_create(Main *bmain) +{ + ListBase *lbarray[MAX_LIBARRAY]; + ID *id; + int a; + + if (bmain->relations != NULL) { + BKE_main_relations_free(bmain); + } + + bmain->relations = MEM_mallocN(sizeof(*bmain->relations), __func__); + bmain->relations->id_used_to_user = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); + bmain->relations->id_user_to_used = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); + bmain->relations->entry_pool = BLI_mempool_create(sizeof(MainIDRelationsEntry), 128, 128, BLI_MEMPOOL_NOP); + + for (a = set_listbasepointers(bmain, lbarray); a--; ) { + for (id = lbarray[a]->first; id; id = id->next) { + BKE_library_foreach_ID_link(NULL, id, main_relations_create_cb, bmain->relations, IDWALK_READONLY); + } + } +} + +void BKE_main_relations_free(Main *bmain) +{ + if (bmain->relations) { + if (bmain->relations->id_used_to_user) { + BLI_ghash_free(bmain->relations->id_used_to_user, NULL, NULL); + } + if (bmain->relations->id_user_to_used) { + BLI_ghash_free(bmain->relations->id_user_to_used, NULL, NULL); + } + BLI_mempool_destroy(bmain->relations->entry_pool); + MEM_freeN(bmain->relations); + bmain->relations = NULL; + } +} + +/** + * Generates a raw .blend file thumbnail data from given image. + * + * \param bmain If not NULL, also store generated data in this Main. + * \param img ImBuf image to generate thumbnail data from. + * \return The generated .blend file raw thumbnail data. + */ +BlendThumbnail *BKE_main_thumbnail_from_imbuf(Main *bmain, ImBuf *img) +{ + BlendThumbnail *data = NULL; + + if (bmain) { + MEM_SAFE_FREE(bmain->blen_thumb); + } + + if (img) { + const size_t sz = BLEN_THUMB_MEMSIZE(img->x, img->y); + data = MEM_mallocN(sz, __func__); + + IMB_rect_from_float(img); /* Just in case... */ + data->width = img->x; + data->height = img->y; + memcpy(data->rect, img->rect, sz - sizeof(*data)); + } + + if (bmain) { + bmain->blen_thumb = data; + } + return data; +} + +/** + * Generates an image from raw .blend file thumbnail \a data. + * + * \param bmain Use this bmain->blen_thumb data if given \a data is NULL. + * \param data Raw .blend file thumbnail data. + * \return An ImBuf from given data, or NULL if invalid. + */ +ImBuf *BKE_main_thumbnail_to_imbuf(Main *bmain, BlendThumbnail *data) +{ + ImBuf *img = NULL; + + if (!data && bmain) { + data = bmain->blen_thumb; + } + + if (data) { + /* Note: we cannot use IMB_allocFromBuffer(), since it tries to dupalloc passed buffer, which will fail + * here (we do not want to pass the first two ints!). */ + img = IMB_allocImBuf((unsigned int)data->width, (unsigned int)data->height, 32, IB_rect | IB_metadata); + memcpy(img->rect, data->rect, BLEN_THUMB_MEMSIZE(data->width, data->height) - sizeof(*data)); + } + + return img; +} + +/** + * Generates an empty (black) thumbnail for given Main. + */ +void BKE_main_thumbnail_create(struct Main *bmain) +{ + MEM_SAFE_FREE(bmain->blen_thumb); + + bmain->blen_thumb = MEM_callocN(BLEN_THUMB_MEMSIZE(BLEN_THUMB_SIZE, BLEN_THUMB_SIZE), __func__); + bmain->blen_thumb->width = BLEN_THUMB_SIZE; + bmain->blen_thumb->height = BLEN_THUMB_SIZE; +} + +/** + * Return filepath of given \a main. + */ +const char *BKE_main_blendfile_path(const Main *bmain) +{ + return bmain->name; +} + +/** + * Return filepath of global main (G_MAIN). + * + * \warning Usage is not recommended, you should always try to get a valid Main pointer from context... + */ +const char *BKE_main_blendfile_path_from_global(void) +{ + return BKE_main_blendfile_path(G_MAIN); +} + +/** + * \return A pointer to the \a ListBase of given \a bmain for requested \a type ID type. + */ +ListBase *which_libbase(Main *bmain, short type) +{ + switch ((ID_Type)type) { + case ID_SCE: + return &(bmain->scene); + case ID_LI: + return &(bmain->library); + case ID_OB: + return &(bmain->object); + case ID_ME: + return &(bmain->mesh); + case ID_CU: + return &(bmain->curve); + case ID_MB: + return &(bmain->mball); + case ID_MA: + return &(bmain->mat); + case ID_TE: + return &(bmain->tex); + case ID_IM: + return &(bmain->image); + case ID_LT: + return &(bmain->latt); + case ID_LA: + return &(bmain->lamp); + case ID_CA: + return &(bmain->camera); + case ID_IP: + return &(bmain->ipo); + case ID_KE: + return &(bmain->key); + case ID_WO: + return &(bmain->world); + case ID_SCR: + return &(bmain->screen); + case ID_VF: + return &(bmain->vfont); + case ID_TXT: + return &(bmain->text); + case ID_SPK: + return &(bmain->speaker); + case ID_LP: + return &(bmain->lightprobe); + case ID_SO: + return &(bmain->sound); + case ID_GR: + return &(bmain->collection); + case ID_AR: + return &(bmain->armature); + case ID_AC: + return &(bmain->action); + case ID_NT: + return &(bmain->nodetree); + case ID_BR: + return &(bmain->brush); + case ID_PA: + return &(bmain->particle); + case ID_WM: + return &(bmain->wm); + case ID_GD: + return &(bmain->gpencil); + case ID_MC: + return &(bmain->movieclip); + case ID_MSK: + return &(bmain->mask); + case ID_LS: + return &(bmain->linestyle); + case ID_PAL: + return &(bmain->palettes); + case ID_PC: + return &(bmain->paintcurves); + case ID_CF: + return &(bmain->cachefiles); + case ID_WS: + return &(bmain->workspaces); + } + return NULL; +} + +/** + * puts into array *lb pointers to all the ListBase structs in main, + * and returns the number of them as the function result. This is useful for + * generic traversal of all the blocks in a Main (by traversing all the + * lists in turn), without worrying about block types. + * + * \note MAX_LIBARRAY define should match this code */ +int set_listbasepointers(Main *bmain, ListBase **lb) +{ + /* BACKWARDS! also watch order of free-ing! (mesh<->mat), first items freed last. + * This is important because freeing data decreases usercounts of other datablocks, + * if this data is its self freed it can crash. */ + lb[INDEX_ID_LI] = &(bmain->library); /* Libraries may be accessed from pretty much any other ID... */ + lb[INDEX_ID_IP] = &(bmain->ipo); + lb[INDEX_ID_AC] = &(bmain->action); /* moved here to avoid problems when freeing with animato (aligorith) */ + lb[INDEX_ID_KE] = &(bmain->key); + lb[INDEX_ID_PAL] = &(bmain->palettes); /* referenced by gpencil, so needs to be before that to avoid crashes */ + lb[INDEX_ID_GD] = &(bmain->gpencil); /* referenced by nodes, objects, view, scene etc, before to free after. */ + lb[INDEX_ID_NT] = &(bmain->nodetree); + lb[INDEX_ID_IM] = &(bmain->image); + lb[INDEX_ID_TE] = &(bmain->tex); + lb[INDEX_ID_MA] = &(bmain->mat); + lb[INDEX_ID_VF] = &(bmain->vfont); + + /* Important!: When adding a new object type, + * the specific data should be inserted here + */ + + lb[INDEX_ID_AR] = &(bmain->armature); + + lb[INDEX_ID_CF] = &(bmain->cachefiles); + lb[INDEX_ID_ME] = &(bmain->mesh); + lb[INDEX_ID_CU] = &(bmain->curve); + lb[INDEX_ID_MB] = &(bmain->mball); + + lb[INDEX_ID_LT] = &(bmain->latt); + lb[INDEX_ID_LA] = &(bmain->lamp); + lb[INDEX_ID_CA] = &(bmain->camera); + + lb[INDEX_ID_TXT] = &(bmain->text); + lb[INDEX_ID_SO] = &(bmain->sound); + lb[INDEX_ID_GR] = &(bmain->collection); + lb[INDEX_ID_PAL] = &(bmain->palettes); + lb[INDEX_ID_PC] = &(bmain->paintcurves); + lb[INDEX_ID_BR] = &(bmain->brush); + lb[INDEX_ID_PA] = &(bmain->particle); + lb[INDEX_ID_SPK] = &(bmain->speaker); + lb[INDEX_ID_LP] = &(bmain->lightprobe); + + lb[INDEX_ID_WO] = &(bmain->world); + lb[INDEX_ID_MC] = &(bmain->movieclip); + lb[INDEX_ID_SCR] = &(bmain->screen); + lb[INDEX_ID_OB] = &(bmain->object); + lb[INDEX_ID_LS] = &(bmain->linestyle); /* referenced by scenes */ + lb[INDEX_ID_SCE] = &(bmain->scene); + lb[INDEX_ID_WS] = &(bmain->workspaces); /* before wm, so it's freed after it! */ + lb[INDEX_ID_WM] = &(bmain->wm); + lb[INDEX_ID_MSK] = &(bmain->mask); + + lb[INDEX_ID_NULL] = NULL; + + return (MAX_LIBARRAY - 1); +} + diff --git a/source/blender/depsgraph/intern/depsgraph.h b/source/blender/depsgraph/intern/depsgraph.h index 804fd1b36c2..3e7d34414ea 100644 --- a/source/blender/depsgraph/intern/depsgraph.h +++ b/source/blender/depsgraph/intern/depsgraph.h @@ -40,7 +40,7 @@ #include "DNA_ID.h" /* for ID_Type */ -#include "BKE_library.h" /* for MAX_LIBARRAY */ +#include "BKE_main.h" /* for MAX_LIBARRAY */ #include "BLI_threads.h" /* for SpinLock */ -- cgit v1.2.3