diff options
author | Jeroen Bakker <jbakker> | 2021-11-10 15:50:00 +0300 |
---|---|---|
committer | Jeroen Bakker <jeroen@blender.org> | 2021-11-10 15:50:15 +0300 |
commit | bc0c06ecbe8cb23221e9cf05be6235e28d4597db (patch) | |
tree | 9f9ef2231d2f7e9a440dce9b7855547e08bc2461 | |
parent | 47b8baa5c4e5b713d33e3925df9d55b882ae2a27 (diff) |
Fix T91518: crash when recalculating looptris after clearing geometry.
When clearing geometry the runtime mutexes of a mesh were freed. This
resulted in crashes afterwards. The clear geometry is an RNA function so
would only effect when using from scripts.
This patch separates init/freeing of the mutexes from other code so they
can be used when needed.
Reviewed By: mont29
Maniphest Tasks: T91518
Differential Revision: https://developer.blender.org/D13142
-rw-r--r-- | source/blender/blenkernel/BKE_mesh_runtime.h | 3 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/mesh.c | 8 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/mesh_runtime.c | 64 |
3 files changed, 53 insertions, 22 deletions
diff --git a/source/blender/blenkernel/BKE_mesh_runtime.h b/source/blender/blenkernel/BKE_mesh_runtime.h index 3efbef94081..df111360bcd 100644 --- a/source/blender/blenkernel/BKE_mesh_runtime.h +++ b/source/blender/blenkernel/BKE_mesh_runtime.h @@ -41,7 +41,8 @@ struct Mesh; struct Object; struct Scene; -void BKE_mesh_runtime_reset(struct Mesh *mesh); +void BKE_mesh_runtime_init_data(struct Mesh *mesh); +void BKE_mesh_runtime_free_data(struct Mesh *mesh); void BKE_mesh_runtime_reset_on_copy(struct Mesh *mesh, const int flag); int BKE_mesh_runtime_looptri_len(const struct Mesh *mesh); void BKE_mesh_runtime_looptri_recalc(struct Mesh *mesh); diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 7277f7ad209..f0ba83b396b 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -88,7 +88,7 @@ static void mesh_init_data(ID *id) CustomData_reset(&mesh->pdata); CustomData_reset(&mesh->ldata); - BKE_mesh_runtime_reset(mesh); + BKE_mesh_runtime_init_data(mesh); mesh->face_sets_color_seed = BLI_hash_int(PIL_check_seconds_timer_i() & UINT_MAX); } @@ -168,7 +168,7 @@ static void mesh_free_data(ID *id) mesh->edit_mesh = NULL; } - BKE_mesh_runtime_clear_cache(mesh); + BKE_mesh_runtime_free_data(mesh); mesh_clear_geometry(mesh); MEM_SAFE_FREE(mesh->mat); } @@ -308,7 +308,9 @@ static void mesh_blend_read_data(BlendDataReader *reader, ID *id) mesh->texflag &= ~ME_AUTOSPACE_EVALUATED; mesh->edit_mesh = NULL; - BKE_mesh_runtime_reset(mesh); + + memset(&mesh->runtime, 0, sizeof(mesh->runtime)); + BKE_mesh_runtime_init_data(mesh); /* happens with old files */ if (mesh->mselect == NULL) { diff --git a/source/blender/blenkernel/intern/mesh_runtime.c b/source/blender/blenkernel/intern/mesh_runtime.c index 1c8646a4bdd..ce89c723a61 100644 --- a/source/blender/blenkernel/intern/mesh_runtime.c +++ b/source/blender/blenkernel/intern/mesh_runtime.c @@ -45,17 +45,54 @@ * \{ */ /** - * Default values defined at read time. + * \brief Initialize the runtime mutexes of the given mesh. + * + * Any existing mutexes will be overridden. */ -void BKE_mesh_runtime_reset(Mesh *mesh) +static void mesh_runtime_init_mutexes(Mesh *mesh) { - memset(&mesh->runtime, 0, sizeof(mesh->runtime)); mesh->runtime.eval_mutex = MEM_mallocN(sizeof(ThreadMutex), "mesh runtime eval_mutex"); BLI_mutex_init(mesh->runtime.eval_mutex); mesh->runtime.render_mutex = MEM_mallocN(sizeof(ThreadMutex), "mesh runtime render_mutex"); BLI_mutex_init(mesh->runtime.render_mutex); } +/** + * \brief free the mutexes of the given mesh runtime. + */ +static void mesh_runtime_free_mutexes(Mesh *mesh) +{ + if (mesh->runtime.eval_mutex != NULL) { + BLI_mutex_end(mesh->runtime.eval_mutex); + MEM_freeN(mesh->runtime.eval_mutex); + mesh->runtime.eval_mutex = NULL; + } + if (mesh->runtime.render_mutex != NULL) { + BLI_mutex_end(mesh->runtime.render_mutex); + MEM_freeN(mesh->runtime.render_mutex); + mesh->runtime.render_mutex = NULL; + } +} + +/** + * \brief Initialize the runtime of the given mesh. + * + * Function expects that the runtime is already cleared. + */ +void BKE_mesh_runtime_init_data(Mesh *mesh) +{ + mesh_runtime_init_mutexes(mesh); +} + +/** + * \brief Free all data (and mutexes) inside the runtime of the given mesh. + */ +void BKE_mesh_runtime_free_data(Mesh *mesh) +{ + BKE_mesh_runtime_clear_cache(mesh); + mesh_runtime_free_mutexes(mesh); +} + /* Clear all pointers which we don't want to be shared on copying the datablock. * However, keep all the flags which defines what the mesh is (for example, that * it's deformed only, or that its custom data layers are out of date.) */ @@ -71,25 +108,16 @@ void BKE_mesh_runtime_reset_on_copy(Mesh *mesh, const int UNUSED(flag)) runtime->bvh_cache = NULL; runtime->shrinkwrap_data = NULL; - mesh->runtime.eval_mutex = MEM_mallocN(sizeof(ThreadMutex), "mesh runtime eval_mutex"); - BLI_mutex_init(mesh->runtime.eval_mutex); - - mesh->runtime.render_mutex = MEM_mallocN(sizeof(ThreadMutex), "mesh runtime render_mutex"); - BLI_mutex_init(mesh->runtime.render_mutex); + mesh_runtime_init_mutexes(mesh); } +/** + * \brief This function clears runtime cache of the given mesh. + * + * Call this function to recalculate runtime data when used. + */ void BKE_mesh_runtime_clear_cache(Mesh *mesh) { - if (mesh->runtime.eval_mutex != NULL) { - BLI_mutex_end(mesh->runtime.eval_mutex); - MEM_freeN(mesh->runtime.eval_mutex); - mesh->runtime.eval_mutex = NULL; - } - if (mesh->runtime.render_mutex != NULL) { - BLI_mutex_end(mesh->runtime.render_mutex); - MEM_freeN(mesh->runtime.render_mutex); - mesh->runtime.render_mutex = NULL; - } if (mesh->runtime.mesh_eval != NULL) { mesh->runtime.mesh_eval->edit_mesh = NULL; BKE_id_free(NULL, mesh->runtime.mesh_eval); |