Fixed a variety of memory corruption bugs

This commit is contained in:
Joseph Eagar 2020-10-29 04:28:03 -07:00
parent 3d47323162
commit 54ddb01299
6 changed files with 139 additions and 23 deletions

View File

@ -387,14 +387,16 @@ void BLI_table_gset_remove(TableGSet *ts, void *elem, GHashKeyFreeFP freefp)
return;
}
int idx2 = *idx;
BLI_ghash_remove(ts->ptr_to_idx, elem, freefp, NULL);
if (!ts->elems || ts->elems[*idx] != elem) {
if (!ts->elems || ts->elems[idx2] != elem) {
return;
}
ts->length--;
ts->elems[*idx] = NULL;
ts->elems[idx2] = NULL;
}
bool BLI_table_gset_haskey(TableGSet *ts, void *elem)

View File

@ -113,6 +113,10 @@ struct BMLog {
* entries have been applied (i.e. there is nothing left to redo.)
*/
BMLogEntry *current_entry;
int cd_origco_offset;
int cd_origno_offset;
int cd_origvcol_offset;
};
typedef struct {
@ -252,7 +256,10 @@ static void vert_mask_set(BMVert *v, const float new_mask, const int cd_vert_mas
}
/* Update a BMLogVert with data from a BMVert */
static void bm_log_vert_bmvert_copy(BMLog *log, BMLogVert *lv, BMVert *v, const int cd_vert_mask_offset)
static void bm_log_vert_bmvert_copy(BMLog *log,
BMLogVert *lv,
BMVert *v,
const int cd_vert_mask_offset)
{
copy_v3_v3(lv->co, v->co);
normal_float_to_short_v3(lv->no, v->no);
@ -345,6 +352,7 @@ static void bm_log_faces_unmake(BMesh *bm, BMLog *log, GHash *faces)
static void bm_log_verts_restore(BMesh *bm, BMLog *log, GHash *verts, BMLogEntry *entry)
{
const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK);
int cd_vcol_offset = CustomData_get_offset(&bm->vdata, CD_PROP_COLOR);
GHashIterator gh_iter;
GHASH_ITER (gh_iter, verts) {
@ -358,9 +366,25 @@ static void bm_log_verts_restore(BMesh *bm, BMLog *log, GHash *verts, BMLogEntry
#ifdef CUSTOMDATA
if (lv->customdata) {
CustomData_bmesh_copy_data(&bm->vdata, &entry->vdata, lv->customdata, &v->head.data);
CustomData_bmesh_copy_data(&entry->vdata, &bm->vdata, lv->customdata, &v->head.data);
}
#endif
if (log->cd_origco_offset >= 0) {
float *oco = BM_ELEM_CD_GET_VOID_P(v, log->cd_origco_offset);
copy_v3_v3(oco, v->co);
}
if (log->cd_origno_offset >= 0) {
float *ono = BM_ELEM_CD_GET_VOID_P(v, log->cd_origno_offset);
copy_v3_v3(ono, v->no);
}
if (log->cd_origvcol_offset >= 0) {
float *ocolor = BM_ELEM_CD_GET_VOID_P(v, log->cd_origvcol_offset);
float *color = BM_ELEM_CD_GET_VOID_P(v, cd_vcol_offset);
copy_v3_v3(ocolor, color);
}
}
}
@ -387,6 +411,8 @@ static void bm_log_vert_values_swap(BMesh *bm, BMLog *log, GHash *verts, BMLogEn
{
const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK);
int cd_vcol_offset = CustomData_get_offset(&bm->vdata, CD_PROP_COLOR);
GHashIterator gh_iter;
GHASH_ITER (gh_iter, verts) {
void *key = BLI_ghashIterator_getKey(&gh_iter);
@ -407,9 +433,26 @@ static void bm_log_vert_values_swap(BMesh *bm, BMLog *log, GHash *verts, BMLogEn
#ifdef CUSTOMDATA
if (lv->customdata) {
CustomData_bmesh_copy_data(&bm->vdata, &entry->vdata, lv->customdata, &v->head.data);
CustomData_bmesh_copy_data(&entry->vdata, &bm->vdata, lv->customdata, &v->head.data);
}
#endif
if (log->cd_origco_offset >= 0) {
float *oco = BM_ELEM_CD_GET_VOID_P(v, log->cd_origco_offset);
copy_v3_v3(oco, v->co);
}
if (log->cd_origno_offset >= 0) {
float *ono = BM_ELEM_CD_GET_VOID_P(v, log->cd_origno_offset);
copy_v3_v3(ono, v->no);
}
if (log->cd_origvcol_offset >= 0) {
float *ocolor = BM_ELEM_CD_GET_VOID_P(v, log->cd_origvcol_offset);
float *color = BM_ELEM_CD_GET_VOID_P(v, cd_vcol_offset);
copy_v3_v3(ocolor, color);
}
}
}
@ -539,8 +582,18 @@ static void bm_log_id_ghash_release(BMLog *log, GHash *id_ghash)
/***************************** Public API *****************************/
void BM_log_set_cd_offsets(BMLog *log,
int cd_origco_offset,
int cd_origno_offset,
int cd_origvol_offset)
{
log->cd_origco_offset = cd_origco_offset;
log->cd_origno_offset = cd_origno_offset;
log->cd_origvcol_offset = cd_origvol_offset;
}
/* Allocate, initialize, and assign a new BMLog */
BMLog *BM_log_create(BMesh *bm)
BMLog *BM_log_create(BMesh *bm, int cd_origco_offset, int cd_origno_offset, int cd_origvcol_offset)
{
BMLog *log = MEM_callocN(sizeof(*log), __func__);
const uint reserve_num = (uint)(bm->totvert + bm->totface);
@ -549,6 +602,8 @@ BMLog *BM_log_create(BMesh *bm)
log->id_to_elem = BLI_ghash_new_ex(logkey_hash, logkey_cmp, __func__, reserve_num);
log->elem_to_id = BLI_ghash_ptr_new_ex(__func__, reserve_num);
BM_log_set_cd_offsets(log, cd_origco_offset, cd_origno_offset, cd_origvcol_offset);
/* Assign IDs to all existing vertices and faces */
bm_log_assign_ids(bm, log);
@ -587,7 +642,7 @@ void BM_log_cleanup_entry(BMLogEntry *entry)
*/
BMLog *BM_log_from_existing_entries_create(BMesh *bm, BMLogEntry *entry)
{
BMLog *log = BM_log_create(bm);
BMLog *log = BM_log_create(bm, -1, -1, -1);
if (entry->prev) {
log->current_entry = entry;
@ -884,6 +939,9 @@ void BM_log_undo(BMesh *bm, BMLog *log)
{
BMLogEntry *entry = log->current_entry;
bm->elem_index_dirty |= BM_VERT|BM_EDGE|BM_FACE;
bm->elem_table_dirty |= BM_VERT|BM_EDGE|BM_FACE;
if (entry) {
log->current_entry = entry->prev;
@ -908,6 +966,9 @@ void BM_log_redo(BMesh *bm, BMLog *log)
{
BMLogEntry *entry = log->current_entry;
bm->elem_index_dirty |= BM_VERT | BM_EDGE | BM_FACE;
bm->elem_table_dirty |= BM_VERT | BM_EDGE | BM_FACE;
if (!entry) {
/* Currently at the beginning of the undo stack, move to first entry */
entry = log->entries.first;
@ -961,7 +1022,10 @@ void BM_log_redo(BMesh *bm, BMLog *log)
* state so that a subsequent redo operation will restore the newer
* vertex state.
*/
void BM_log_vert_before_modified(BMLog *log, BMVert *v, const int cd_vert_mask_offset, bool log_customdata)
void BM_log_vert_before_modified(BMLog *log,
BMVert *v,
const int cd_vert_mask_offset,
bool log_customdata)
{
BMLogEntry *entry = log->current_entry;
BMLogVert *lv;
@ -999,7 +1063,7 @@ void BM_log_vert_added(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
lv = bm_log_vert_alloc(log, v, cd_vert_mask_offset);
BLI_ghash_insert(log->current_entry->added_verts, key, lv);
//bm_log_vert_customdata(log->bm, log, v, lv);
// bm_log_vert_customdata(log->bm, log, v, lv);
}
/* Log a face before it is modified

View File

@ -29,7 +29,11 @@ typedef struct BMLog BMLog;
typedef struct BMLogEntry BMLogEntry;
/* Allocate and initialize a new BMLog */
BMLog *BM_log_create(BMesh *bm);
BMLog *BM_log_create(BMesh *bm, int cd_origco_offset, int cd_origno_offset, int cd_origvol_offset);
void BM_log_set_cd_offsets(BMLog *log,
int cd_origco_offset,
int cd_origno_offset,
int cd_origvcol_offset);
/* Allocate and initialize a new BMLog using existing BMLogEntries */
BMLog *BM_log_from_existing_entries_create(BMesh *bm, BMLogEntry *entry);
@ -49,7 +53,7 @@ BMLogEntry *BM_log_entry_add_ex(BMesh *bm, BMLog *log, bool combine_with_last);
BMLogEntry *BM_log_entry_check_customdata(BMesh *bm, BMLog *log);
/* Mark all used ids as unused for this node */
/* Mark all used ids as unused for this node */
void BM_log_cleanup_entry(BMLogEntry *entry);
/* Remove an entry from the log */
@ -62,7 +66,10 @@ void BM_log_undo(BMesh *bm, BMLog *log);
void BM_log_redo(BMesh *bm, BMLog *log);
/* Log a vertex before it is modified */
void BM_log_vert_before_modified(BMLog *log, struct BMVert *v, const int cd_vert_mask_offset, bool log_customdata);
void BM_log_vert_before_modified(BMLog *log,
struct BMVert *v,
const int cd_vert_mask_offset,
bool log_customdata);
/* Log a new vertex as added to the BMesh */
void BM_log_vert_added(BMLog *log, struct BMVert *v, const int cd_vert_mask_offset);

View File

@ -111,7 +111,7 @@
void SCULPT_vertex_random_access_ensure(SculptSession *ss)
{
if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
if (ss->bm) {
BM_mesh_elem_index_ensure(ss->bm, BM_VERT);
BM_mesh_elem_table_ensure(ss->bm, BM_VERT);
}

View File

@ -121,7 +121,7 @@ void SCULPT_dyntopo_save_origverts(SculptSession *ss)
float *no = BM_ELEM_CD_GET_VOID_P(v, ss->cd_origno_offset);
copy_v3_v3(co, v->co);
copy_v3_v3(co, v->no);
copy_v3_v3(no, v->no);
}
}
@ -189,6 +189,9 @@ void SCULPT_dyntopo_node_layers_add(SculptSession *ss)
cd_origvcol_index - CustomData_get_layer_index(&ss->bm->vdata, CD_PROP_COLOR));
ss->bm->vdata.layers[cd_origvcol_index].flag |= CD_FLAG_TEMPORARY;
}
else {
ss->cd_origvcol_offset = -1;
}
ss->cd_origco_offset = CustomData_get_n_offset(
&ss->bm->vdata,
@ -238,8 +241,8 @@ void SCULPT_dynamic_topology_sync_layers(Object *ob, Mesh *me)
CustomData *cd1[4] = {&me->vdata, &me->edata, &me->ldata, &me->pdata};
CustomData *cd2[4] = {&bm->vdata, &bm->edata, &bm->ldata, &bm->pdata};
int types[4] = {BM_VERT, BM_EDGE, BM_LOOP, BM_FACE};
int badmask = CD_MASK_MLOOP | CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MPOLY |
CD_MASK_ORIGINDEX | CD_MASK_ORIGSPACE | CD_MASK_MFACE;
int badmask = CD_MASK_MLOOP | CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MPOLY | CD_MASK_ORIGINDEX |
CD_MASK_ORIGSPACE | CD_MASK_MFACE;
for (int i = 0; i < 4; i++) {
CustomDataLayer **newlayers = NULL;
@ -350,6 +353,30 @@ void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene
SCULPT_dynamic_topology_triangulate(ss->bm);
BM_data_layer_add(ss->bm, &ss->bm->vdata, CD_PAINT_MASK);
SCULPT_dyntopo_node_layers_add(ss);
BMIter iter;
BMVert *v;
int cd_vcol_offset = CustomData_get_offset(&ss->bm->vdata, CD_PROP_COLOR);
BM_ITER_MESH (v, &iter, ss->bm, BM_VERTS_OF_MESH) {
if (ss->cd_origco_offset >= 0) {
float *co = BM_ELEM_CD_GET_VOID_P(v, ss->cd_origco_offset);
copy_v3_v3(co, v->co);
}
if (ss->cd_origno_offset >= 0) {
float *no = BM_ELEM_CD_GET_VOID_P(v, ss->cd_origno_offset);
copy_v3_v3(no, v->no);
}
if (ss->cd_origvcol_offset >= 0) {
float *ocolor = BM_ELEM_CD_GET_VOID_P(v, ss->cd_origvcol_offset);
float *color = BM_ELEM_CD_GET_VOID_P(v, cd_vcol_offset);
copy_v4_v4(ocolor, color);
}
}
/* Make sure the data for existing faces are initialized. */
if (me->totpoly != ss->bm->totface) {
BM_mesh_normals_update(ss->bm);
@ -359,7 +386,8 @@ void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene
me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY;
/* Enable logging for undo/redo. */
ss->bm_log = BM_log_create(ss->bm);
ss->bm_log = BM_log_create(
ss->bm, ss->cd_origco_offset, ss->cd_origno_offset, ss->cd_origvcol_offset);
/* Update dependency graph, so modifiers that depend on dyntopo being enabled
* are re-evaluated and the PBVH is re-created. */

View File

@ -463,6 +463,8 @@ static void sculpt_undo_bmesh_enable(Object *ob, SculptUndoNode *unode)
/* Restore the BMLog using saved entries. */
ss->bm_log = BM_log_from_existing_entries_create(ss->bm, unode->bm_entry);
BM_log_set_cd_offsets(
ss->bm_log, ss->cd_origco_offset, ss->cd_origno_offset, ss->cd_origvcol_offset);
}
static void sculpt_undo_bmesh_restore_begin(bContext *C,
@ -502,6 +504,8 @@ static void sculpt_undo_bmesh_restore_end(bContext *C,
SCULPT_dynamic_topology_disable(C, NULL);
unode->applied = true;
}
BM_mesh_elem_index_ensure(ss->bm, BM_VERT);
}
static void sculpt_undo_geometry_store_data(SculptUndoNodeGeometry *geometry, Object *object)
@ -593,17 +597,25 @@ static int sculpt_undo_bmesh_restore(bContext *C,
Object *ob,
SculptSession *ss)
{
if (ss->bm_log) {
BM_log_set_cd_offsets(
ss->bm_log, ss->cd_origco_offset, ss->cd_origno_offset, ss->cd_origvcol_offset);
}
switch (unode->type) {
case SCULPT_UNDO_DYNTOPO_BEGIN:
sculpt_undo_bmesh_restore_begin(C, unode, ob, ss);
SCULPT_vertex_random_access_ensure(ss);
return true;
case SCULPT_UNDO_DYNTOPO_END:
sculpt_undo_bmesh_restore_end(C, unode, ob, ss);
SCULPT_vertex_random_access_ensure(ss);
return true;
default:
if (ss->bm_log) {
sculpt_undo_bmesh_restore_generic(unode, ob, ss);
SCULPT_vertex_random_access_ensure(ss);
return true;
}
break;
@ -974,7 +986,6 @@ static SculptUndoNode *sculpt_undo_find_or_alloc_node_type(Object *object, Sculp
return sculpt_undo_alloc_node_type(object, type);
}
static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node, SculptUndoType type)
{
UndoSculpt *usculpt = sculpt_undo_get_nodes();
@ -1057,6 +1068,9 @@ static void sculpt_undo_store_coords(Object *ob, SculptUndoNode *unode)
SculptSession *ss = ob->sculpt;
PBVHVertexIter vd;
SculptOrigVertData orig_data;
SCULPT_orig_vert_data_unode_init(&orig_data, ob, unode);
BKE_pbvh_vertex_iter_begin(ss->pbvh, unode->node, vd, PBVH_ITER_ALL)
{
copy_v3_v3(unode->co[vd.i], vd.co);
@ -1068,9 +1082,11 @@ static void sculpt_undo_store_coords(Object *ob, SculptUndoNode *unode)
}
if (ss->deform_modifiers_active) {
SCULPT_orig_vert_data_update(&orig_data, &vd);
int index = BKE_pbvh_vertex_index_to_table(ss->pbvh, unode->index[vd.i]);
copy_v3_v3(unode->orig_co[vd.i], ss->orig_cos[index]);
copy_v3_v3(unode->orig_co[vd.i], orig_data.co);
}
}
BKE_pbvh_vertex_iter_end;
@ -1268,7 +1284,7 @@ static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob, PBVHNode *node, Sculpt
}
if (new_node) {
//sculpt_undo_print_nodes(NULL);
// sculpt_undo_print_nodes(NULL);
}
return unode;
@ -1453,7 +1469,7 @@ static void sculpt_undosys_step_decode_undo_impl(struct bContext *C,
sculpt_undo_restore_list(C, depsgraph, &us->data.nodes);
us->step.is_applied = false;
//sculpt_undo_print_nodes(us);
// sculpt_undo_print_nodes(us);
}
static void sculpt_undosys_step_decode_redo_impl(struct bContext *C,
@ -1464,7 +1480,7 @@ static void sculpt_undosys_step_decode_redo_impl(struct bContext *C,
sculpt_undo_restore_list(C, depsgraph, &us->data.nodes);
us->step.is_applied = true;
//sculpt_undo_print_nodes(us);
// sculpt_undo_print_nodes(us);
}
static void sculpt_undosys_step_decode_undo(struct bContext *C,
@ -1695,7 +1711,6 @@ void ED_sculpt_undo_push_multires_mesh_end(bContext *C, const char *str)
/** \} */
#ifdef _
# undef _
#endif