[Bf-blender-cvs] [6766efce4c7] undo-experiments-idnames: undoexp: add a way to prevent re-using data from old bmain for memfile undo.

Bastien Montagne noreply at git.blender.org
Thu Jan 9 11:25:55 CET 2020


Commit: 6766efce4c7e201eac5ae29385d41314129df48d
Author: Bastien Montagne
Date:   Wed Jan 8 15:35:53 2020 +0100
Branches: undo-experiments-idnames
https://developer.blender.org/rB6766efce4c7e201eac5ae29385d41314129df48d

undoexp: add a way to prevent re-using data from old bmain for memfile undo.

There are cases where we need a full 'clean' re-read of stored memfile
data. This include some (rather uncommon, but possible) ID rename
situations, and also likely some switching between memfileundo and
edit-data undo systems.

===================================================================

M	source/blender/blenkernel/BKE_blender_undo.h
M	source/blender/blenkernel/BKE_main.h
M	source/blender/blenkernel/BKE_undo_system.h
M	source/blender/blenkernel/intern/blender_undo.c
M	source/blender/blenkernel/intern/undo_system.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/editors/undo/memfile_undo.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_blender_undo.h b/source/blender/blenkernel/BKE_blender_undo.h
index 7392d3947a2..f869790decf 100644
--- a/source/blender/blenkernel/BKE_blender_undo.h
+++ b/source/blender/blenkernel/BKE_blender_undo.h
@@ -32,7 +32,9 @@ struct bContext;
 
 struct MemFileUndoData *BKE_memfile_undo_encode(struct Main *bmain,
                                                 struct MemFileUndoData *mfu_prev);
-bool BKE_memfile_undo_decode(struct MemFileUndoData *mfu, struct bContext *C);
+bool BKE_memfile_undo_decode(struct MemFileUndoData *mfu,
+                             const bool use_old_bmain_data,
+                             struct bContext *C);
 void BKE_memfile_undo_free(struct MemFileUndoData *mfu);
 
 #ifdef __cplusplus
diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h
index c48a9cad443..c756a5e12df 100644
--- a/source/blender/blenkernel/BKE_main.h
+++ b/source/blender/blenkernel/BKE_main.h
@@ -85,6 +85,11 @@ typedef struct Main {
    * use "needs_flush_to_id" in edit data to flag data which needs updating.
    */
   char is_memfile_undo_flush_needed;
+  /**
+   * Indicates that next memfile undo step should not allow to re-use old bmain when re-read, but
+   * instead do a complete full re-read/update from stored memfile.
+   */
+  char use_memfile_full_barrier;
 
   BlendThumbnail *blen_thumb;
 
diff --git a/source/blender/blenkernel/BKE_undo_system.h b/source/blender/blenkernel/BKE_undo_system.h
index bc10d422a61..74ce4d3f020 100644
--- a/source/blender/blenkernel/BKE_undo_system.h
+++ b/source/blender/blenkernel/BKE_undo_system.h
@@ -79,6 +79,9 @@ typedef struct UndoStep {
   bool skip;
   /** Some situations require the global state to be stored, edge cases when exiting modes. */
   bool use_memfile_step;
+  /** When this is true, undo/memfile read code is allowed to re-use old data-blocks for unchanged
+   * IDs, and existing depsgraphes. This has to be forbidden in some cases (like renamed IDs). */
+  bool use_old_bmain_data;
   /** For use by undo systems that accumulate changes (text editor, painting). */
   bool is_applied;
   /* Over alloc 'type->struct_size'. */
diff --git a/source/blender/blenkernel/intern/blender_undo.c b/source/blender/blenkernel/intern/blender_undo.c
index cd950e05415..3a91eb3c1a3 100644
--- a/source/blender/blenkernel/intern/blender_undo.c
+++ b/source/blender/blenkernel/intern/blender_undo.c
@@ -61,7 +61,7 @@
 
 #define UNDO_DISK 0
 
-bool BKE_memfile_undo_decode(MemFileUndoData *mfu, bContext *C)
+bool BKE_memfile_undo_decode(MemFileUndoData *mfu, const bool use_old_bmain_data, bContext *C)
 {
   Main *bmain = CTX_data_main(C);
   char mainstr[sizeof(bmain->name)];
@@ -76,8 +76,11 @@ bool BKE_memfile_undo_decode(MemFileUndoData *mfu, bContext *C)
     success = BKE_blendfile_read(C, mfu->filename, &(const struct BlendFileReadParams){0}, NULL);
   }
   else {
-    success = BKE_blendfile_read_from_memfile(
-        C, &mfu->memfile, &(const struct BlendFileReadParams){0}, NULL);
+    struct BlendFileReadParams params = {0};
+    if (!use_old_bmain_data) {
+      params.skip_flags |= BLO_READ_SKIP_UNDO_OLD_MAIN;
+    }
+    success = BKE_blendfile_read_from_memfile(C, &mfu->memfile, &params, NULL);
   }
 
   /* Restore, bmain has been re-allocated. */
diff --git a/source/blender/blenkernel/intern/undo_system.c b/source/blender/blenkernel/intern/undo_system.c
index 5d049e9fa3e..3af7c978553 100644
--- a/source/blender/blenkernel/intern/undo_system.c
+++ b/source/blender/blenkernel/intern/undo_system.c
@@ -170,6 +170,12 @@ static bool undosys_step_encode(bContext *C, Main *bmain, UndoStack *ustack, Und
        * not all members are filled in. */
       us->type->step_foreach_ID_ref(us, undosys_id_ref_store, bmain);
     }
+
+    /* Store the fact that we should not re-use old data with that undo step, and reset the Main
+     * flag. */
+    us->use_old_bmain_data = !bmain->use_memfile_full_barrier;
+    bmain->use_memfile_full_barrier = false;
+
 #ifdef WITH_GLOBAL_UNDO_CORRECT_ORDER
     if (us->type == BKE_UNDOSYS_TYPE_MEMFILE) {
       ustack->step_active_memfile = us;
@@ -233,27 +239,32 @@ static void undosys_step_decode(
 
   /* Extract depsgraphs from current bmain (which may be freed during undo step reading),
    * and store them for re-use. */
-  GHash *depsgraphs = BKE_scene_undo_depsgraphs_extract(bmain);
+  GHash *depsgraphs = NULL;
+  if (us->use_old_bmain_data) {
+    depsgraphs = BKE_scene_undo_depsgraphs_extract(bmain);
+  }
 
   UNDO_NESTED_CHECK_BEGIN;
   us->type->step_decode(C, bmain, us, dir, is_final);
   UNDO_NESTED_CHECK_END;
 
-  /* Restore previous depsgraphs into current bmain. */
-  bmain = G_MAIN;
-  BKE_scene_undo_depsgraphs_restore(bmain, depsgraphs);
-
-  /* We need to inform depsgraph about re-used old IDs that would be using newly read data-blocks,
-   * at least COW evaluated copies need to be updated... */
-  ID *id = NULL;
-  FOREACH_MAIN_ID_BEGIN (bmain, id) {
-    if (id->tag & LIB_TAG_UNDO_OLD_ID_REUSED) {
-      BKE_library_foreach_ID_link(bmain, id, undosys_step_id_reused_cb, bmain, IDWALK_READONLY);
+  if (us->use_old_bmain_data) {
+    /* Restore previous depsgraphs into current bmain. */
+    bmain = G_MAIN;
+    BKE_scene_undo_depsgraphs_restore(bmain, depsgraphs);
+
+    /* We need to inform depsgraph about re-used old IDs that would be using newly read
+     * data-blocks, at least COW evaluated copies need to be updated... */
+    ID *id = NULL;
+    FOREACH_MAIN_ID_BEGIN (bmain, id) {
+      if (id->tag & LIB_TAG_UNDO_OLD_ID_REUSED) {
+        BKE_library_foreach_ID_link(bmain, id, undosys_step_id_reused_cb, bmain, IDWALK_READONLY);
+      }
     }
-  }
-  FOREACH_MAIN_ID_END;
+    FOREACH_MAIN_ID_END;
 
-  BKE_main_id_tag_all(bmain, LIB_TAG_UNDO_OLD_ID_REUSED, false);
+    BKE_main_id_tag_all(bmain, LIB_TAG_UNDO_OLD_ID_REUSED, false);
+  }
 
 #ifdef WITH_GLOBAL_UNDO_CORRECT_ORDER
   if (us->type == BKE_UNDOSYS_TYPE_MEMFILE) {
diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h
index adf3bf00d48..978a38808ad 100644
--- a/source/blender/blenloader/BLO_readfile.h
+++ b/source/blender/blenloader/BLO_readfile.h
@@ -74,7 +74,7 @@ typedef struct WorkspaceConfigFileData {
 } WorkspaceConfigFileData;
 
 struct BlendFileReadParams {
-  uint skip_flags : 2; /* eBLOReadSkip */
+  uint skip_flags : 3; /* eBLOReadSkip */
   uint is_startup : 1;
 };
 
@@ -83,6 +83,8 @@ typedef enum eBLOReadSkip {
   BLO_READ_SKIP_NONE = 0,
   BLO_READ_SKIP_USERDEF = (1 << 0),
   BLO_READ_SKIP_DATA = (1 << 1),
+  /** Do not attempt to re-use IDs from old bmain for unchanged ones in case of undo. */
+  BLO_READ_SKIP_UNDO_OLD_MAIN = (1 << 2),
 } eBLOReadSkip;
 #define BLO_READ_SKIP_ALL (BLO_READ_SKIP_USERDEF | BLO_READ_SKIP_DATA)
 
diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c
index 0c010a59477..f11d2de57c3 100644
--- a/source/blender/blenloader/intern/readblenentry.c
+++ b/source/blender/blenloader/intern/readblenentry.c
@@ -384,13 +384,15 @@ BlendFileData *BLO_read_from_memfile(Main *oldmain,
     /* add the library pointers in oldmap lookup */
     blo_add_library_pointer_map(&old_mainlist, fd);
 
-    /* Build idmap of old main (we only care about local data here, so we can do that after
-     * split_main() call. */
-    blo_make_idmap_from_main(fd, old_mainlist.first);
-
-    /* Create sibling mapping of libmap (i.e. old ID pointer values to new valid IDs), but for the
-     * addresses from old main. */
-    blo_make_undo_reused_libmap(fd);
+    if ((skip_flags & BLO_READ_SKIP_UNDO_OLD_MAIN) == 0) {
+      /* Build idmap of old main (we only care about local data here, so we can do that after
+       * split_main() call. */
+      blo_make_idmap_from_main(fd, old_mainlist.first);
+
+      /* Create sibling mapping of libmap (i.e. old ID pointer values to new valid IDs), but for
+       * the addresses from old main. */
+      blo_make_undo_reused_libmap(fd);
+    }
 
     /* makes lookup of existing images in old main */
     blo_make_image_pointer_map(fd, oldmain);
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 2984e690e1f..1a098d1428e 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -9469,7 +9469,8 @@ static BHead *read_libblock(FileData *fd,
                    id->name,
                    fd->are_memchunks_identical);
 
-      if (fd->are_memchunks_identical && !ELEM(idcode, ID_WM, ID_SCR, ID_WS)) {
+      if (fd->memfile != NULL && (fd->skip_flags & BLO_READ_SKIP_UNDO_OLD_MAIN) == 0 &&
+          fd->are_memchunks_identical && !ELEM(idcode, ID_WM, ID_SCR, ID_WS)) {
         BLI_assert(fd->memfile != NULL);
         BLI_assert(fd->old_idmap != NULL);
         /* This code should only ever be reached for local data-blocks. */
@@ -9522,7 +9523,9 @@ static BHead *read_libblock(FileData *fd,
 
       /* Some re-used old IDs might also use newly read ones, so we have to check for old memory
        * addresses for those as well. */
-      if (fd->old_idmap != NULL && id->lib == NULL) {
+      if (fd->memfile != NULL && (fd->skip_flags & BLO_READ_SKIP_UNDO_OLD_MAIN) == 0 &&
+          id->lib == NULL) {
+        BLI_assert(fd->old_idmap != NULL);
         ID *id_old = BKE_main_idmap_lookup(fd->old_idmap, idcode, id->name + 2, NULL);
         if (id_old != NULL) {
           oldnewmap_insert(fd->libmap_undo_reused, id_old, id, id_bhead->code);
@@ -10245,7 +10248,7 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
 
     blo_join_main(&mainlist);
 
-    if (fd->memfile != NULL) {
+    if (fd->memfile != NULL && (fd->skip_flags & BLO_READ_SKIP_UNDO_OLD_MAIN) == 0) {
       /* In case of undo, we have to handle possible 'pointer collisions' between newly read
        * data-blocks and those re-used from the old bmain. */
       BLI_assert(fd->libmap_undo_reused != NULL);
diff --git a/source/blender/editors/undo/memfile_undo.c b/source/blender/editors/undo/memfile_undo.c
index a5f30409aa6..30d8a7d5a61 100644
--- a/source/blender/editors/undo/memfile_undo.c
+++ b/sou

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list