Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2020-09-09 13:38:33 +0300
committerCampbell Barton <ideasman42@gmail.com>2020-09-09 13:38:33 +0300
commit4ccd5bf5c6581c3dd93e684cacfb87c103339572 (patch)
tree6b4d60274990c95c10cc449d22f1395e56a6a64f
parentdbec51109bbd3a6143bc45c6faa3908142f9da46 (diff)
Fix T80626: Crash adding custom-data layers after reloading the file
Regression in a48d78ce07f4f which caused the meshes CustomData to be written before it's layer values were updated for writing.
-rw-r--r--source/blender/blenkernel/BKE_customdata.h11
-rw-r--r--source/blender/blenkernel/intern/customdata.c27
-rw-r--r--source/blender/blenkernel/intern/mesh.c44
-rw-r--r--source/blender/blenloader/intern/writefile.c34
4 files changed, 88 insertions, 28 deletions
diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h
index 25360d4b3fa..d21fe5afa7e 100644
--- a/source/blender/blenkernel/BKE_customdata.h
+++ b/source/blender/blenkernel/BKE_customdata.h
@@ -414,11 +414,6 @@ void CustomData_from_bmesh_block(const struct CustomData *source,
void *src_block,
int dest_index);
-void CustomData_file_write_prepare(struct CustomData *data,
- struct CustomDataLayer **r_write_layers,
- struct CustomDataLayer *write_layers_buff,
- size_t write_layers_size);
-
/* query info over types */
void CustomData_file_write_info(int type, const char **r_struct_name, int *r_struct_num);
int CustomData_sizeof(int type);
@@ -574,8 +569,14 @@ void CustomData_data_transfer(const struct MeshPairRemap *me_remap,
const CustomDataTransferLayerMap *laymap);
/* .blend file I/O */
+void CustomData_blend_write_prepare(struct CustomData *data,
+ struct CustomDataLayer **r_write_layers,
+ struct CustomDataLayer *write_layers_buff,
+ size_t write_layers_size);
+
void CustomData_blend_write(struct BlendWriter *writer,
struct CustomData *data,
+ CustomDataLayer *layers,
int count,
CustomDataMask cddata_mask,
struct ID *id);
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index 5a5fb7a36df..e2adaabca33 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -4342,10 +4342,10 @@ void CustomData_file_write_info(int type, const char **r_struct_name, int *r_str
* This means written typemap does not match written layers (as returned by \a r_write_layers).
* Trivial to fix is ever needed.
*/
-void CustomData_file_write_prepare(CustomData *data,
- CustomDataLayer **r_write_layers,
- CustomDataLayer *write_layers_buff,
- size_t write_layers_size)
+void CustomData_blend_write_prepare(CustomData *data,
+ CustomDataLayer **r_write_layers,
+ CustomDataLayer *write_layers_buff,
+ size_t write_layers_size)
{
CustomDataLayer *write_layers = write_layers_buff;
const size_t chunk_size = (write_layers_size > 0) ? write_layers_size : CD_TEMP_CHUNK_SIZE;
@@ -5193,13 +5193,16 @@ static void write_grid_paint_mask(BlendWriter *writer, int count, GridPaintMask
}
}
-void CustomData_blend_write(
- BlendWriter *writer, CustomData *data, int count, CustomDataMask cddata_mask, ID *id)
+/**
+ * \param layers: The layers argument assigned by #CustomData_blend_write_prepare.
+ */
+void CustomData_blend_write(BlendWriter *writer,
+ CustomData *data,
+ CustomDataLayer *layers,
+ int count,
+ CustomDataMask cddata_mask,
+ ID *id)
{
- CustomDataLayer *layers = NULL;
- CustomDataLayer layers_buff[CD_TEMP_CHUNK_SIZE];
- CustomData_file_write_prepare(data, &layers, layers_buff, ARRAY_SIZE(layers_buff));
-
/* write external customdata (not for undo) */
if (data->external && !BLO_write_is_undo(writer)) {
CustomData_external_write(data, id, cddata_mask, count, 0);
@@ -5252,10 +5255,6 @@ void CustomData_blend_write(
if (data->external) {
BLO_write_struct(writer, CustomDataExternal, data->external);
}
-
- if (!ELEM(layers, NULL, layers_buff)) {
- MEM_freeN(layers);
- }
}
static void blend_read_mdisps(BlendDataReader *reader, int count, MDisps *mdisps, int external)
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index a7568bcd6ea..0e6ef50f491 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -180,6 +180,18 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address
memset(&mesh->fdata, 0, sizeof(mesh->fdata));
memset(&mesh->runtime, 0, sizeof(mesh->runtime));
+ CustomDataLayer *vlayers = NULL, vlayers_buff[CD_TEMP_CHUNK_SIZE];
+ CustomDataLayer *elayers = NULL, elayers_buff[CD_TEMP_CHUNK_SIZE];
+ CustomDataLayer *flayers = NULL, flayers_buff[CD_TEMP_CHUNK_SIZE];
+ CustomDataLayer *llayers = NULL, llayers_buff[CD_TEMP_CHUNK_SIZE];
+ CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE];
+
+ CustomData_blend_write_prepare(&mesh->vdata, &vlayers, vlayers_buff, ARRAY_SIZE(vlayers_buff));
+ CustomData_blend_write_prepare(&mesh->edata, &elayers, elayers_buff, ARRAY_SIZE(elayers_buff));
+ flayers = flayers_buff;
+ CustomData_blend_write_prepare(&mesh->ldata, &llayers, llayers_buff, ARRAY_SIZE(llayers_buff));
+ CustomData_blend_write_prepare(&mesh->pdata, &players, players_buff, ARRAY_SIZE(players_buff));
+
BLO_write_id_struct(writer, Mesh, id_address, &mesh->id);
BKE_id_blend_write(writer, &mesh->id);
@@ -191,12 +203,34 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address
BLO_write_pointer_array(writer, mesh->totcol, mesh->mat);
BLO_write_raw(writer, sizeof(MSelect) * mesh->totselect, mesh->mselect);
- CustomData_blend_write(writer, &mesh->vdata, mesh->totvert, CD_MASK_MESH.vmask, &mesh->id);
- CustomData_blend_write(writer, &mesh->edata, mesh->totedge, CD_MASK_MESH.emask, &mesh->id);
+ CustomData_blend_write(
+ writer, &mesh->vdata, vlayers, mesh->totvert, CD_MASK_MESH.vmask, &mesh->id);
+ CustomData_blend_write(
+ writer, &mesh->edata, elayers, mesh->totedge, CD_MASK_MESH.emask, &mesh->id);
/* fdata is really a dummy - written so slots align */
- CustomData_blend_write(writer, &mesh->fdata, mesh->totface, CD_MASK_MESH.fmask, &mesh->id);
- CustomData_blend_write(writer, &mesh->ldata, mesh->totloop, CD_MASK_MESH.lmask, &mesh->id);
- CustomData_blend_write(writer, &mesh->pdata, mesh->totpoly, CD_MASK_MESH.pmask, &mesh->id);
+ CustomData_blend_write(
+ writer, &mesh->fdata, flayers, mesh->totface, CD_MASK_MESH.fmask, &mesh->id);
+ CustomData_blend_write(
+ writer, &mesh->ldata, llayers, mesh->totloop, CD_MASK_MESH.lmask, &mesh->id);
+ CustomData_blend_write(
+ writer, &mesh->pdata, players, mesh->totpoly, CD_MASK_MESH.pmask, &mesh->id);
+
+ /* Free temporary data */
+
+/* Free custom-data layers, when not assigned a buffer value. */
+#define CD_LAYERS_FREE(id) \
+ if (id && id != id##_buff) { \
+ MEM_freeN(id); \
+ } \
+ ((void)0)
+
+ CD_LAYERS_FREE(vlayers);
+ CD_LAYERS_FREE(elayers);
+ /* CD_LAYER_FREE(flayers); */ /* Never allocated. */
+ CD_LAYERS_FREE(llayers);
+ CD_LAYERS_FREE(players);
+
+#undef CD_LAYERS_FREE
}
}
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index a9c92719a33..7b089ec0f8f 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -3263,17 +3263,31 @@ static void write_workspace(BlendWriter *writer, WorkSpace *workspace, const voi
static void write_hair(BlendWriter *writer, Hair *hair, const void *id_address)
{
if (hair->id.us > 0 || BLO_write_is_undo(writer)) {
+ CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE];
+ CustomDataLayer *clayers = NULL, clayers_buff[CD_TEMP_CHUNK_SIZE];
+ CustomData_blend_write_prepare(&hair->pdata, &players, players_buff, ARRAY_SIZE(players_buff));
+ CustomData_blend_write_prepare(&hair->cdata, &clayers, clayers_buff, ARRAY_SIZE(clayers_buff));
+
/* Write LibData */
BLO_write_id_struct(writer, Hair, id_address, &hair->id);
BKE_id_blend_write(writer, &hair->id);
/* Direct data */
- CustomData_blend_write(writer, &hair->pdata, hair->totpoint, CD_MASK_ALL, &hair->id);
- CustomData_blend_write(writer, &hair->cdata, hair->totcurve, CD_MASK_ALL, &hair->id);
+ CustomData_blend_write(writer, &hair->pdata, players, hair->totpoint, CD_MASK_ALL, &hair->id);
+ CustomData_blend_write(writer, &hair->cdata, clayers, hair->totcurve, CD_MASK_ALL, &hair->id);
+
BLO_write_pointer_array(writer, hair->totcol, hair->mat);
if (hair->adt) {
BKE_animdata_blend_write(writer, hair->adt);
}
+
+ /* Remove temporary data. */
+ if (players && players != players_buff) {
+ MEM_freeN(players);
+ }
+ if (clayers && clayers != clayers_buff) {
+ MEM_freeN(clayers);
+ }
}
}
@@ -3281,7 +3295,7 @@ static void write_pointcloud(BlendWriter *writer, PointCloud *pointcloud, const
{
if (pointcloud->id.us > 0 || BLO_write_is_undo(writer)) {
CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE];
- CustomData_file_write_prepare(
+ CustomData_blend_write_prepare(
&pointcloud->pdata, &players, players_buff, ARRAY_SIZE(players_buff));
/* Write LibData */
@@ -3290,7 +3304,8 @@ static void write_pointcloud(BlendWriter *writer, PointCloud *pointcloud, const
/* Direct data */
CustomData_blend_write(
- writer, &pointcloud->pdata, pointcloud->totpoint, CD_MASK_ALL, &pointcloud->id);
+ writer, &pointcloud->pdata, players, pointcloud->totpoint, CD_MASK_ALL, &pointcloud->id);
+
BLO_write_pointer_array(writer, pointcloud->totcol, pointcloud->mat);
if (pointcloud->adt) {
BKE_animdata_blend_write(writer, pointcloud->adt);
@@ -3349,13 +3364,24 @@ static void write_simulation(BlendWriter *writer, Simulation *simulation, const
/* TODO: Decentralize this part. */
if (STREQ(state->type, SIM_TYPE_NAME_PARTICLE_SIMULATION)) {
ParticleSimulationState *particle_state = (ParticleSimulationState *)state;
+
+ CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE];
+ CustomData_blend_write_prepare(
+ &particle_state->attributes, &players, players_buff, ARRAY_SIZE(players_buff));
+
BLO_write_struct(writer, ParticleSimulationState, particle_state);
CustomData_blend_write(writer,
&particle_state->attributes,
+ players,
particle_state->tot_particles,
CD_MASK_ALL,
&simulation->id);
+
+ /* Remove temporary data. */
+ if (players && players != players_buff) {
+ MEM_freeN(players);
+ }
}
else if (STREQ(state->type, SIM_TYPE_NAME_PARTICLE_MESH_EMITTER)) {
ParticleMeshEmitterSimulationState *emitter_state = (ParticleMeshEmitterSimulationState *)