diff options
author | Campbell Barton <ideasman42@gmail.com> | 2020-09-09 13:38:33 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2020-09-09 13:38:33 +0300 |
commit | 4ccd5bf5c6581c3dd93e684cacfb87c103339572 (patch) | |
tree | 6b4d60274990c95c10cc449d22f1395e56a6a64f /source/blender | |
parent | dbec51109bbd3a6143bc45c6faa3908142f9da46 (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.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/BKE_customdata.h | 11 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/customdata.c | 27 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/mesh.c | 44 | ||||
-rw-r--r-- | source/blender/blenloader/intern/writefile.c | 34 |
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 *) |