[Bf-blender-cvs] [49e64d4e26a] sculpt-dev: Fix dyntopo undo crash

Joseph Eagar noreply at git.blender.org
Sat Sep 25 10:36:37 CEST 2021


Commit: 49e64d4e26af860213bd1320ceb6ba27b2f8050e
Author: Joseph Eagar
Date:   Sat Sep 25 01:36:23 2021 -0700
Branches: sculpt-dev
https://developer.blender.org/rB49e64d4e26af860213bd1320ceb6ba27b2f8050e

Fix dyntopo undo crash

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

M	source/blender/blenkernel/BKE_brush_engine.h
M	source/blender/blenkernel/intern/brush_engine_presets.c
M	source/blender/bmesh/intern/bmesh_log.c
M	source/blender/bmesh/intern/bmesh_log.h
M	source/blender/editors/sculpt_paint/sculpt_undo.c

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

diff --git a/source/blender/blenkernel/BKE_brush_engine.h b/source/blender/blenkernel/BKE_brush_engine.h
index bfd29b559ae..2f6ebe1d740 100644
--- a/source/blender/blenkernel/BKE_brush_engine.h
+++ b/source/blender/blenkernel/BKE_brush_engine.h
@@ -143,7 +143,7 @@ typedef struct BrushTex {
   char idname[64], name[64];
 
   BrushChannelSet *channels;
-  MTex *__mtex;  // do not access directly. except for the actual evaluation code.
+  MTex __mtex;  // do not access directly. except for the actual evaluation code.
 } BrushTex;
 
 BrushTex *BKE_brush_tex_create();
diff --git a/source/blender/blenkernel/intern/brush_engine_presets.c b/source/blender/blenkernel/intern/brush_engine_presets.c
index bdc7cd638c0..2b398ff053b 100644
--- a/source/blender/blenkernel/intern/brush_engine_presets.c
+++ b/source/blender/blenkernel/intern/brush_engine_presets.c
@@ -947,8 +947,21 @@ void BKE_brush_channelset_ui_init(Brush *brush, int tool)
   SHOWWRK(radius_unit);
   SHOWWRK(use_frontface);
 
-  SHOWWRK(autosmooth);
-  SHOWWRK(topology_rake);
+  if (!ELEM(tool, SCULPT_TOOL_PAINT, SCULPT_TOOL_SMEAR)) {
+    SHOWWRK(autosmooth);
+    SHOWWRK(topology_rake);
+  }
+
+  if (ELEM(tool, SCULPT_TOOL_PAINT, SCULPT_TOOL_SMEAR)) {
+    SHOWWRK(vcol_boundary_factor);
+    SHOWWRK(vcol_boundary_exponent);
+    SHOWWRK(vcol_boundary_radius_scale);
+    SHOWWRK(vcol_boundary_spacing);
+  }
+  else if (tool == SCULPT_TOOL_VCOL_BOUNDARY) {
+    SHOWWRK(vcol_boundary_exponent);
+  }
+
   SHOWWRK(normal_radius_factor);
   SHOWWRK(hardness);
 
@@ -1092,6 +1105,14 @@ void BKE_brush_builtin_create(Brush *brush, int tool)
       GETCH(strength)->fvalue = 1.0f;
       GETCH(dyntopo_disabled)->ivalue = 1;
       break;
+    case SCULPT_TOOL_SMEAR:
+      BRUSHSET_SET_FLOAT(chset, spacing, 5.0f);
+      BRUSHSET_SET_FLOAT(chset, strength, 1.0f);
+      BRUSHSET_LOOKUP(chset, strength)->mappings[BRUSH_MAPPING_PRESSURE].flag &=
+          ~BRUSH_MAPPING_ENABLED;
+      BRUSHSET_SET_BOOL(chset, dyntopo_disabled, true);
+      break;
+
     case SCULPT_TOOL_SLIDE_RELAX:
       GETCH(spacing)->fvalue = 10;
       GETCH(strength)->fvalue = 1.0f;
diff --git a/source/blender/bmesh/intern/bmesh_log.c b/source/blender/bmesh/intern/bmesh_log.c
index deb735c8cf3..573383447d6 100644
--- a/source/blender/bmesh/intern/bmesh_log.c
+++ b/source/blender/bmesh/intern/bmesh_log.c
@@ -57,6 +57,34 @@
 
 #define CUSTOMDATA
 
+#ifdef DEBUG_LOG_REFCOUNTNG
+static struct {
+  char tag[4192];
+} namestack[256] = {0};
+int namestack_i = 1;
+
+void _namestack_push(const char *name)
+{
+  namestack_i++;
+
+  strcpy(namestack[namestack_i].tag, namestack[namestack_i - 1].tag);
+  strcat(namestack[namestack_i].tag, ".");
+  strcat(namestack[namestack_i].tag, name);
+}
+
+#  define namestack_push() _namestack_push(__func__)
+
+void namestack_pop()
+{
+  namestack_i--;
+}
+
+#  define namestack_head_name namestack[namestack_i].tag
+#else
+#  define namestack_push()
+#  define namestack_pop()
+#  define namestack_head_name ""
+#endif
 //#define DO_LOG_PRINT
 
 #ifdef DO_LOG_PRINT
@@ -187,6 +215,30 @@ struct BMLog {
   bool dead;
 };
 
+//#define PRINT_LOG_REF_COUNTING
+
+static void _bm_log_addref(BMLog *log, const char *func)
+{
+  log->refcount++;
+
+#ifdef PRINT_LOG_REF_COUNTING
+  printf("%d %s: bm_log_addref: %p\n", log->refcount, namestack_head_name, log);
+  fflush(stdout);
+#endif
+}
+
+static void _bm_log_decref(BMLog *log, const char *func)
+{
+  log->refcount--;
+#ifdef PRINT_LOG_REF_COUNTING
+  printf("%d %s: bm_log_decref: %p\n", log->refcount, namestack_head_name, log);
+  fflush(stdout);
+#endif
+}
+
+#define bm_log_addref(log) _bm_log_addref(log, __func__)
+#define bm_log_decref(log) _bm_log_decref(log, __func__)
+
 typedef struct BMLogVert {
 #ifdef DO_LOG_PRINT
   char msg[64];
@@ -246,7 +298,7 @@ static void full_copy_load(BMesh *bm, BMLog *log, BMLogEntry *entry);
 
 BMLogEntry *bm_log_entry_add_ex(
     BMesh *bm, BMLog *log, bool combine_with_last, BMLogEntryType type, BMLogEntry *last_entry);
-static void bm_log_entry_free(BMLogEntry *entry);
+static bool bm_log_entry_free(BMLogEntry *entry);
 static bool bm_log_free_direct(BMLog *log, bool safe_mode);
 
 static void *log_ghash_lookup(BMLog *log, GHash *gh, const void *key)
@@ -1172,13 +1224,15 @@ static void bm_log_entry_free_direct(BMLogEntry *entry)
 /* Free the data in a log entry
  * and handles bmlog ref counting
  * NOTE: does not free the log entry itself. */
-static void bm_log_entry_free(BMLogEntry *entry)
+static bool bm_log_entry_free(BMLogEntry *entry)
 {
   BMLog *log = entry->log;
   bool kill_log = false;
 
   if (log) {
-    log->refcount--;
+    namestack_push();
+    bm_log_decref(log);
+    namestack_pop();
 
     if (log->refcount < 0) {
       fprintf(stderr, "BMLog refcount error\n");
@@ -1193,6 +1247,8 @@ static void bm_log_entry_free(BMLogEntry *entry)
   if (kill_log) {
     bm_log_free_direct(log, true);
   }
+
+  return kill_log;
 }
 
 static int uint_compare(const void *a_v, const void *b_v)
@@ -1268,6 +1324,8 @@ BMLog *bm_log_from_existing_entries_create(BMesh *bm, BMLog *log, BMLogEntry *en
     log->entries.last = entry;
   }
 
+  namestack_push();
+
   for (entry = log->entries.first; entry; entry = entry->next) {
     BMLogEntry *entry2 = entry->combined_prev;
 
@@ -1275,13 +1333,15 @@ BMLog *bm_log_from_existing_entries_create(BMesh *bm, BMLog *log, BMLogEntry *en
       entry2->log = log;
       entry2 = entry2->combined_prev;
 
-      log->refcount++;
+      bm_log_addref(log);
     }
 
     entry->log = log;
-    log->refcount++;
+    bm_log_addref(log);
   }
 
+  namestack_pop();
+
   return log;
 }
 
@@ -1367,6 +1427,12 @@ static bool bm_log_free_direct(BMLog *log, bool safe_mode)
   return true;
 }
 
+// if true, make sure to call BM_log_free on the log
+bool BM_log_is_dead(BMLog *log)
+{
+  return log->dead;
+}
+
 bool BM_log_free(BMLog *log, bool safe_mode)
 {
   if (log->dead) {
@@ -1570,7 +1636,11 @@ BMLogEntry *bm_log_entry_add_ex(
 
   entry->log = log;
 
-  log->refcount++;
+  namestack_push();
+
+  bm_log_addref(log);
+
+  namestack_pop();
 
   if (combine_with_last) {
     if (!last_entry || last_entry == log->current_entry) {
@@ -1618,10 +1688,12 @@ BMLogEntry *BM_log_entry_add_ex(BMesh *bm, BMLog *log, bool combine_with_last)
  * This operation is only valid on the first and last entries in the
  * log. Deleting from the middle will assert.
  */
-void BM_log_entry_drop(BMLogEntry *entry)
+bool BM_log_entry_drop(BMLogEntry *entry)
 {
   BMLog *log = entry->log;
 
+  namestack_push();
+
   // go to head of entry subgroup
   while (entry->combined_next) {
     entry = entry->combined_next;
@@ -1647,9 +1719,11 @@ void BM_log_entry_drop(BMLogEntry *entry)
       entry2 = prev;
     }
 
+    namestack_pop();
     bm_log_entry_free(entry);
     MEM_freeN(entry);
-    return;
+
+    return false;
   }
 
   if (log && log->current_entry == entry) {
@@ -1670,8 +1744,12 @@ void BM_log_entry_drop(BMLogEntry *entry)
     entry2 = prev;
   }
 
-  bm_log_entry_free(entry);
+  bool ret = bm_log_entry_free(entry);
+
   MEM_freeN(entry);
+  namestack_pop();
+
+  return ret;
 }
 
 static void full_copy_load(BMesh *bm, BMLog *log, BMLogEntry *entry)
diff --git a/source/blender/bmesh/intern/bmesh_log.h b/source/blender/bmesh/intern/bmesh_log.h
index d81aa1dc5ae..aecb2bb5750 100644
--- a/source/blender/bmesh/intern/bmesh_log.h
+++ b/source/blender/bmesh/intern/bmesh_log.h
@@ -76,8 +76,11 @@ BMLogEntry *BM_log_entry_check_customdata(BMesh *bm, BMLog *log);
 /* Mark all used ids as unused for this node */
 void BM_log_cleanup_entry(BMLogEntry *entry);
 
-/* Remove an entry from the log */
-void BM_log_entry_drop(BMLogEntry *entry);
+/* Remove an entry from the log.
+   returns true if the log's refcount
+   reached zero and was freed*/
+bool BM_log_entry_drop(BMLogEntry *entry);
+bool BM_log_is_dead(BMLog *log);
 
 /* Undo one BMLogEntry.  node_layer_id is necassary to preserve node idxs with customdata, whose
  * layout might have changed */
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index 18c1bc9d8a8..1d9cb7e0872 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -1728,10 +1728,16 @@ static SculptUndoNode *sculpt_undo_face_sets_push(Object *ob, SculptUndoType typ
 
 void SCULPT_undo_ensure_bmlog(Object *ob)
 {
-  if (!ob->sculpt) {
+  SculptSession *ss = ob->sculpt;
+  Mesh *me = BKE_object_get_original_mesh(ob);
+
+  /*log exists or not in sculpt mode? good then*/
+  if (ss->bm_log || !ob->sculpt) {
     return;
   }
 
+  /*try to find log from entries in the undo stack*/
+
   UndoStack *ustack = ED_undo_stack_get();
 
   if (!ustack) {
@@ -1754,9 +1760,6 @@ void SCULPT_undo_ensure_bmlog(Object *ob)
 
   UndoSculpt *usculpt = sculpt_undosys_step_get_nodes(us);
 
-  SculptSession *ss = ob->sculpt;
-  Mesh *me = BKE_object_get_original_mesh(ob);
-
   if (!ss->bm && !(me->flag & ME_SCULPT_DYNAMIC_TOPOLOGY)) {
     return;
   }
@@ -1768,8 +1771,8 @@ void SCULPT_undo_ensure_bmlog(Object *ob)
 
   SculptUndoNode *unode = usculpt->nodes.first;
 
-  // this can happen in certain cases when going to/from other undo types
-  // I think.
+  /*when transition between undo step types the log might simply
+  have been freed, look for entries to rebuild it with*/
   if (!ss->bm_log) {
     if (unode && unode->bm_entry) {
       ss->bm_log = BM_log_from_existing_entries_create(ss->bm, unode->bm_entry);
@@ -2105,10 +2108,10 @@ SculptUndoNode *SCULPT_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType
 
 void sculpt_undo_push_begin_ex(Object *ob, const char *name, bool no_first_entry_check)
 {
-  SCULPT_undo_ensure_bmlog(ob);
-
   UndoStack *ustack = ED_undo_stack_get();
 
+  SCULPT_undo_ensure_bmlog(ob);
+
   if (ob != NULL) {
     if (!no_first_entry_check && ob->sculpt && ob->sculpt->bm) {
       check_first_undo_entry_dyntopo(ob);
@@ -2124,6 +2127,23 @@ void sculpt_undo_push_begin_ex(Object *ob, const char *name, bool no_first_entry
   bContext *C = NULL;
 
   BKE_undosys_step_push_init_with_type(ustack, C, name, BKE_UNDOSYS_TYPE_SCULPT);
+
+  SculptSession *ss = ob->sculpt;
+
+  /*whe

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list