[Bf-blender-cvs] [b6db147c18d] undo-caches: Initial Refactor of code preserving caches during undo.
Bastien Montagne
noreply at git.blender.org
Thu Jul 2 17:44:44 CEST 2020
Commit: b6db147c18d89ed7f308fe93fddd66a1c4d96682
Author: Bastien Montagne
Date: Thu Jul 2 16:16:55 2020 +0200
Branches: undo-caches
https://developer.blender.org/rBb6db147c18d89ed7f308fe93fddd66a1c4d96682
Initial Refactor of code preserving caches during undo.
This is a proof od concept, it only implements new system for bSound
data-block as test subject.
===================================================================
M source/blender/blenkernel/BKE_idtype.h
M source/blender/blenkernel/intern/sound.c
M source/blender/blenloader/BLO_readfile.h
M source/blender/blenloader/intern/readblenentry.c
M source/blender/blenloader/intern/readfile.c
M source/blender/blenloader/intern/readfile.h
A source/blender/blenloader/intern/readfile.h.autosave
===================================================================
diff --git a/source/blender/blenkernel/BKE_idtype.h b/source/blender/blenkernel/BKE_idtype.h
index b6dfadd3b2a..89082c99c2d 100644
--- a/source/blender/blenkernel/BKE_idtype.h
+++ b/source/blender/blenkernel/BKE_idtype.h
@@ -33,6 +33,7 @@ extern "C" {
#endif
struct ID;
+struct BLOCacheStorageKey;
struct LibraryForeachIDData;
struct Main;
@@ -63,6 +64,14 @@ typedef void (*IDTypeMakeLocalFunction)(struct Main *bmain, struct ID *id, const
typedef void (*IDTypeForeachIDFunction)(struct ID *id, struct LibraryForeachIDData *data);
+typedef void (*IDTypeForeachCacheFunctionCallback)(struct ID *id,
+ const struct BLOCacheStorageKey *cache_key,
+ void **cache_p,
+ void *user_data);
+typedef void (*IDTypeForeachCacheFunction)(struct ID *id,
+ IDTypeForeachCacheFunctionCallback function_callback,
+ void *user_data);
+
typedef struct IDTypeInfo {
/* ********** General IDType data. ********** */
@@ -130,6 +139,11 @@ typedef struct IDTypeInfo {
* pointers) of given data-block.
*/
IDTypeForeachIDFunction foreach_id;
+
+ /**
+ * Iterator over all cache pointers of given ID.
+ */
+ IDTypeForeachCacheFunction foreach_cache;
} IDTypeInfo;
/* ********** Declaration of each IDTypeInfo. ********** */
diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c
index a293bc55073..84299818845 100644
--- a/source/blender/blenkernel/intern/sound.c
+++ b/source/blender/blenkernel/intern/sound.c
@@ -60,6 +60,8 @@
#include "BKE_sequencer.h"
#include "BKE_sound.h"
+#include "BLO_readfile.h"
+
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
@@ -112,6 +114,20 @@ static void sound_free_data(ID *id)
}
}
+static void sound_foreach_cache(ID *id,
+ IDTypeForeachCacheFunctionCallback function_callback,
+ void *user_data)
+{
+ bSound *sound = (bSound *)id;
+ BLOCacheStorageKey key = {
+ .id_session_uuid = id->session_uuid,
+ .offset_in_ID = offsetof(bSound, waveform),
+ .cache_v = sound->waveform,
+ };
+
+ function_callback(id, &key, &sound->waveform, user_data);
+}
+
IDTypeInfo IDType_ID_SO = {
.id_code = ID_SO,
.id_filter = FILTER_ID_SO,
@@ -128,6 +144,7 @@ IDTypeInfo IDType_ID_SO = {
.free_data = sound_free_data,
.make_local = NULL,
.foreach_id = NULL,
+ .foreach_cache = sound_foreach_cache,
};
#ifdef WITH_AUDASPACE
diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h
index e4908eb7257..dfce23559d9 100644
--- a/source/blender/blenloader/BLO_readfile.h
+++ b/source/blender/blenloader/BLO_readfile.h
@@ -193,6 +193,18 @@ struct BlendThumbnail *BLO_thumbnail_from_file(const char *filepath);
extern const struct bTheme U_theme_default;
extern const struct UserDef U_default;
+/* Management of chaches that we want to preserve across undo's. */
+
+typedef struct BLOCacheStorageKey {
+ /* The session uuid of the ID owning the cached data. */
+ unsigned int id_session_uuid;
+ /* Value uniquely indentifying the cache whithin its ID.
+ * Typically the offset of its member in the data-block struct, but can be anything. */
+ size_t offset_in_ID;
+ /* Actual address of the cached data to save and restore. */
+ void *cache_v;
+} BLOCacheStorageKey;
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c
index 1309b3e3c33..74e91b6bdc5 100644
--- a/source/blender/blenloader/intern/readblenentry.c
+++ b/source/blender/blenloader/intern/readblenentry.c
@@ -400,15 +400,19 @@ BlendFileData *BLO_read_from_memfile(Main *oldmain,
blo_make_movieclip_pointer_map(fd, oldmain);
/* make lookups of existing sound data in old main */
- blo_make_sound_pointer_map(fd, oldmain);
+ // blo_make_sound_pointer_map(fd, oldmain);
/* make lookups of existing volume data in old main */
blo_make_volume_pointer_map(fd, oldmain);
/* removed packed data from this trick - it's internal data that needs saves */
+ blo_cache_storage_init(fd, oldmain);
+
bfd = blo_read_file_internal(fd, filename);
+ blo_cache_storage_old_bmain_clear(fd, oldmain);
+
/* ensures relinked light caches are not freed */
blo_end_scene_pointer_map(fd, oldmain);
@@ -419,7 +423,7 @@ BlendFileData *BLO_read_from_memfile(Main *oldmain,
blo_end_movieclip_pointer_map(fd, oldmain);
/* ensures relinked sounds are not freed */
- blo_end_sound_pointer_map(fd, oldmain);
+ // blo_end_sound_pointer_map(fd, oldmain);
/* ensures relinked volumes are not freed */
blo_end_volume_pointer_map(fd, oldmain);
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index e4822c4cb7f..1273aec4592 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -105,6 +105,7 @@
#include "BLI_ghash.h"
#include "BLI_linklist.h"
#include "BLI_math.h"
+#include "BLI_memarena.h"
#include "BLI_mempool.h"
#include "BLI_threads.h"
@@ -1635,6 +1636,7 @@ void blo_filedata_free(FileData *fd)
if (fd->old_idmap != NULL) {
BKE_main_idmap_destroy(fd->old_idmap);
}
+ blo_cache_storage_end(fd);
if (fd->bheadmap) {
MEM_freeN(fd->bheadmap);
}
@@ -2316,6 +2318,157 @@ void blo_make_old_idmap_from_main(FileData *fd, Main *bmain)
fd->old_idmap = BKE_main_idmap_create(bmain, false, NULL, MAIN_IDMAP_TYPE_UUID);
}
+typedef struct BLOCacheStorage {
+ GHash *cache_map;
+ MemArena *memarena;
+} BLOCacheStorage;
+
+/** Register a cache data entry to be preserved when reading some undo memfile. */
+static void blo_cache_storage_entry_register(ID *id,
+ const BLOCacheStorageKey *key,
+ void **UNUSED(cache_p),
+ void *cache_storage_v)
+{
+ BLI_assert(key->id_session_uuid == id->session_uuid);
+
+ BLOCacheStorage *cache_storage = cache_storage_v;
+ BLI_assert(!BLI_ghash_haskey(cache_storage->cache_map, key));
+
+ BLOCacheStorageKey *storage_key = BLI_memarena_alloc(cache_storage->memarena,
+ sizeof(*storage_key));
+ *storage_key = *key;
+ BLI_ghash_insert(cache_storage->cache_map, storage_key, POINTER_FROM_UINT(0));
+}
+
+/** Restore a cache data entry from old ID into new one, when reading some undo memfile. */
+static void blo_cache_storage_entry_restore_in_new(ID *UNUSED(id),
+ const BLOCacheStorageKey *key,
+ void **cache_p,
+ void *cache_storage_v)
+{
+ BLOCacheStorage *cache_storage = cache_storage_v;
+
+ if (cache_storage == NULL) {
+ *cache_p = NULL;
+ return;
+ }
+
+ void **value = BLI_ghash_lookup_p(cache_storage->cache_map, key);
+ if (value == NULL) {
+ *cache_p = NULL;
+ return;
+ }
+ *value = POINTER_FROM_UINT(POINTER_AS_UINT(*value) + 1);
+ *cache_p = key->cache_v;
+}
+
+/** Clear as needed a cache data entry from old ID, when reading some undo memfile. */
+static void blo_cache_storage_entry_clear_in_old(ID *UNUSED(id),
+ const BLOCacheStorageKey *key,
+ void **cache_p,
+ void *cache_storage_v)
+{
+ BLOCacheStorage *cache_storage = cache_storage_v;
+
+ void **value = BLI_ghash_lookup_p(cache_storage->cache_map, key);
+ if (value == NULL) {
+ *cache_p = NULL;
+ return;
+ }
+ /* If that cache has been restored into some new ID, we want to remove it from old one, otherwise
+ * keep it there so that it gets properly freed together with its ID. */
+ *cache_p = POINTER_AS_UINT(*value) != 0 ? NULL : key->cache_v;
+}
+
+static uint blo_cache_storage_hash(const void *key_v)
+{
+ const BLOCacheStorageKey *key = key_v;
+ size_t hash = BLI_ghashutil_uinthash(key->id_session_uuid);
+ hash = BLI_ghashutil_combine_hash(hash, BLI_ghashutil_uinthash((uint)key->offset_in_ID));
+ return (uint)BLI_ghashutil_combine_hash(hash, BLI_ghashutil_ptrhash(key->cache_v));
+}
+
+static bool blo_cache_storage_cmp(const void *key_a_v, const void *key_b_v)
+{
+ const BLOCacheStorageKey *key_a = key_a_v;
+ const BLOCacheStorageKey *key_b = key_b_v;
+ return (key_a->id_session_uuid != key_b->id_session_uuid) ||
+ (key_a->offset_in_ID != key_b->offset_in_ID) || (key_a->cache_v != key_b->cache_v);
+}
+
+void blo_cache_storage_init(FileData *fd, Main *bmain)
+{
+ if (fd->memfile != NULL) {
+ BLI_assert(fd->cache_storage == NULL);
+ fd->cache_storage = MEM_mallocN(sizeof(*fd->cache_storage), __func__);
+ fd->cache_storage->memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+ fd->cache_storage->cache_map = BLI_ghash_new(
+ blo_cache_storage_hash, blo_cache_storage_cmp, __func__);
+
+ ListBase *lb;
+ FOREACH_MAIN_LISTBASE_BEGIN (bmain, lb) {
+ ID *id = lb->first;
+ if (id == NULL) {
+ continue;
+ }
+
+ const IDTypeInfo *type_info = BKE_idtype_get_info_from_id(id);
+ if (type_info->foreach_cache == NULL) {
+ continue;
+ }
+
+ FOREACH_MAIN_LISTBASE_ID_BEGIN (lb, id) {
+ if (ID_IS_LINKED(id)) {
+ continue;
+ }
+ type_info->foreach_cache(id, blo_cache_storage_entry_register, fd->cache_storage);
+ }
+ FOREACH_MAIN_LISTBASE_ID_END;
+ }
+ FOREACH_MAIN_LISTBASE_END;
+ }
+ else {
+ fd->cache_storage = NULL;
+ }
+}
+
+void blo_cache_storage_old_bmain_clear(FileData *fd, Main *bmain_old)
+{
+ if (fd->cache_storage != NULL) {
+ ListBase *lb;
+ FOREACH_MAIN_LISTBASE_BEGIN (bmain_old, lb) {
+ ID *id = lb->first;
+ if (id == NULL) {
+ continue
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list