Undo: support implicit-sharing in memfile undo step #106903

Merged
Jacques Lucke merged 78 commits from JacquesLucke/blender:implicit-sharing-undo into main 2024-02-29 17:15:09 +01:00
4 changed files with 105 additions and 61 deletions
Showing only changes of commit 9760cf86bc - Show all commits

View File

@ -5150,48 +5150,52 @@ void CustomData_blend_write(BlendWriter *writer,
writer, CustomDataLayer, data->totlayer, data->layers, layers_to_write.data());
for (const CustomDataLayer &layer : layers_to_write) {
switch (layer.type) {
case CD_MDEFORMVERT:
BKE_defvert_blend_write(writer, count, static_cast<const MDeformVert *>(layer.data));
break;
case CD_MDISPS:
write_mdisps(
writer, count, static_cast<const MDisps *>(layer.data), layer.flag & CD_FLAG_EXTERNAL);
break;
case CD_PAINT_MASK:
BLO_write_raw(writer, sizeof(float) * count, static_cast<const float *>(layer.data));
break;
case CD_SCULPT_FACE_SETS:
BLO_write_raw(writer, sizeof(float) * count, static_cast<const float *>(layer.data));
break;
case CD_GRID_PAINT_MASK:
write_grid_paint_mask(writer, count, static_cast<const GridPaintMask *>(layer.data));
break;
case CD_FACEMAP:
BLO_write_raw(writer, sizeof(int) * count, static_cast<const int *>(layer.data));
break;
case CD_PROP_BOOL:
BLO_write_raw(writer, sizeof(bool) * count, static_cast<const bool *>(layer.data));
break;
case CD_CREASE:
BLO_write_raw(writer, sizeof(float) * count, static_cast<const float *>(layer.data));
break;
default: {
const char *structname;
int structnum;
CustomData_file_write_info(eCustomDataType(layer.type), &structname, &structnum);
if (structnum) {
int datasize = structnum * count;
BLO_write_struct_array_by_name(writer, structname, datasize, layer.data);
}
else if (!BLO_write_is_undo(writer)) { /* Do not warn on undo. */
printf("%s error: layer '%s':%d - can't be written to file\n",
__func__,
structname,
layer.type);
BLO_write_shared(writer, layer.data, layer.sharing_info, [&]() {
switch (layer.type) {
case CD_MDEFORMVERT:
BKE_defvert_blend_write(writer, count, static_cast<const MDeformVert *>(layer.data));
break;
JacquesLucke marked this conversation as resolved Outdated

I would rather not have such long callbacks as lambda, makes it very difficult to decipher the code imho.

Same for the reader below.

I would rather not have such long callbacks as lambda, makes it very difficult to decipher the code imho. Same for the reader below.
case CD_MDISPS:
write_mdisps(writer,
count,
static_cast<const MDisps *>(layer.data),
layer.flag & CD_FLAG_EXTERNAL);
break;
case CD_PAINT_MASK:
BLO_write_raw(writer, sizeof(float) * count, static_cast<const float *>(layer.data));
break;
case CD_SCULPT_FACE_SETS:
BLO_write_raw(writer, sizeof(float) * count, static_cast<const float *>(layer.data));
break;
case CD_GRID_PAINT_MASK:
write_grid_paint_mask(writer, count, static_cast<const GridPaintMask *>(layer.data));
break;
case CD_FACEMAP:
BLO_write_raw(writer, sizeof(int) * count, static_cast<const int *>(layer.data));
break;
case CD_PROP_BOOL:
BLO_write_raw(writer, sizeof(bool) * count, static_cast<const bool *>(layer.data));
break;
case CD_CREASE:
BLO_write_raw(writer, sizeof(float) * count, static_cast<const float *>(layer.data));
break;
default: {
const char *structname;
int structnum;
CustomData_file_write_info(eCustomDataType(layer.type), &structname, &structnum);
if (structnum) {
int datasize = structnum * count;
BLO_write_struct_array_by_name(writer, structname, datasize, layer.data);
}
else if (!BLO_write_is_undo(writer)) { /* Do not warn on undo. */
printf("%s error: layer '%s':%d - can't be written to file\n",
__func__,
structname,
layer.type);
}
}
}
}
});
}
if (data->external) {
@ -5267,31 +5271,34 @@ void CustomData_blend_read(BlendDataReader *reader, CustomData *data, const int
layer->sharing_info = nullptr;
if (CustomData_verify_versions(data, i)) {
BLO_read_data_address(reader, &layer->data);
if (layer->data != nullptr) {
layer->sharing_info = BLO_read_shared(reader, &layer->data, [&]() {
BLO_read_data_address(reader, &layer->data);
if (CustomData_layer_ensure_data_exists(layer, count)) {
/* Under normal operations, this shouldn't happen, but...
* For a CD_PROP_BOOL example, see #84935.
* For a CD_MLOOPUV example, see #90620. */
CLOG_WARN(
&LOG,
"Allocated custom data layer that was not saved correctly for layer->type = %d.",
layer->type);
}
if (layer->type == CD_MDISPS) {
blend_read_mdisps(
reader, count, static_cast<MDisps *>(layer->data), layer->flag & CD_FLAG_EXTERNAL);
}
else if (layer->type == CD_GRID_PAINT_MASK) {
blend_read_paint_mask(reader, count, static_cast<GridPaintMask *>(layer->data));
}
else if (layer->type == CD_MDEFORMVERT) {
BKE_defvert_blend_read(reader, count, static_cast<MDeformVert *>(layer->data));
}
});
if (layer->data != nullptr && layer->sharing_info == nullptr) {
/* Make layer data shareable. */
layer->sharing_info = make_implicit_sharing_info_for_layer(
eCustomDataType(layer->type), layer->data, count);
}
if (CustomData_layer_ensure_data_exists(layer, count)) {
/* Under normal operations, this shouldn't happen, but...
* For a CD_PROP_BOOL example, see #84935.
* For a CD_MLOOPUV example, see #90620. */
CLOG_WARN(&LOG,
"Allocated custom data layer that was not saved correctly for layer->type = %d.",
layer->type);
}
if (layer->type == CD_MDISPS) {
blend_read_mdisps(
reader, count, static_cast<MDisps *>(layer->data), layer->flag & CD_FLAG_EXTERNAL);
}
else if (layer->type == CD_GRID_PAINT_MASK) {
blend_read_paint_mask(reader, count, static_cast<GridPaintMask *>(layer->data));
}
else if (layer->type == CD_MDEFORMVERT) {
BKE_defvert_blend_read(reader, count, static_cast<MDeformVert *>(layer->data));
}
i++;
}
}

View File

@ -31,6 +31,12 @@
#include "DNA_windowmanager_types.h" /* for eReportType */
#include "BLI_implicit_sharing.h"
#ifdef __cplusplus
# include "BLI_function_ref.hh"
#endif
#ifdef __cplusplus
extern "C" {
#endif
@ -175,6 +181,13 @@ void BLO_write_string(BlendWriter *writer, const char *data_ptr);
/* Misc. */
#ifdef __cplusplus
void BLO_write_shared(BlendWriter *writer,
const void *data,
const ImplicitSharingInfoHandle *sharing_info,
blender::FunctionRef<void()> write_cb);
#endif
/**
* Sometimes different data is written depending on whether the file is saved to disk or used for
* undo. This function returns true when the current file-writing is done for undo.
@ -238,6 +251,12 @@ void BLO_read_pointer_array(BlendDataReader *reader, void **ptr_p);
/* Misc. */
#ifdef __cplusplus
const ImplicitSharingInfoHandle *BLO_read_shared(BlendDataReader *reader,
void **data_ptr,
blender::FunctionRef<void()> read_cb);
#endif
int BLO_read_fileversion_get(BlendDataReader *reader);
bool BLO_read_requires_endian_switch(BlendDataReader *reader);
bool BLO_read_data_is_undo(BlendDataReader *reader);

View File

@ -5150,6 +5150,15 @@ void BLO_read_pointer_array(BlendDataReader *reader, void **ptr_p)
*ptr_p = final_array;
}
const ImplicitSharingInfoHandle *BLO_read_shared(BlendDataReader *reader,
void **data_ptr,
blender::FunctionRef<void()> read_cb)
{
UNUSED_VARS(reader, data_ptr);
read_cb();
return nullptr;
}
bool BLO_read_data_is_undo(BlendDataReader *reader)
{
return (reader->fd->flags & FD_FLAGS_IS_MEMFILE);

View File

@ -1692,6 +1692,15 @@ void BLO_write_string(BlendWriter *writer, const char *data_ptr)
}
}
void BLO_write_shared(BlendWriter *writer,
const void *data,
const ImplicitSharingInfoHandle *sharing_info,
blender::FunctionRef<void()> write_cb)
{
UNUSED_VARS(writer, data, sharing_info);
write_cb();
}
bool BLO_write_is_undo(BlendWriter *writer)
{
return writer->wd->use_memfile;