Undo: support implicit-sharing in memfile undo step #106903
|
@ -8,6 +8,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "BLI_implicit_sharing.h"
|
||||
#include "BLI_sys_types.h"
|
||||
#include "BLI_utildefines.h"
|
||||
#ifdef __cplusplus
|
||||
|
@ -247,13 +248,14 @@ void *CustomData_add_layer(struct CustomData *data,
|
|||
|
||||
/**
|
||||
* Adds a layer of the given type to the #CustomData object. The new layer takes ownership of the
|
||||
* passed in `layer_data`. If a #bCopyOnWrite is passed in, it's user count is increased.
|
||||
* passed in `layer_data`. If a #ImplicitSharingInfoHandle is passed in, it's user count is
|
||||
* increased.
|
||||
*/
|
||||
const void *CustomData_add_layer_with_data(struct CustomData *data,
|
||||
eCustomDataType type,
|
||||
void *layer_data,
|
||||
int totelem,
|
||||
const struct bCopyOnWrite *cow);
|
||||
const ImplicitSharingInfoHandle *implicit_sharing_info);
|
||||
|
||||
/**
|
||||
* Same as above but accepts a name.
|
||||
|
@ -264,12 +266,13 @@ void *CustomData_add_layer_named(struct CustomData *data,
|
|||
int totelem,
|
||||
const char *name);
|
||||
|
||||
const void *CustomData_add_layer_named_with_data(struct CustomData *data,
|
||||
eCustomDataType type,
|
||||
void *layer_data,
|
||||
int totelem,
|
||||
const char *name,
|
||||
const struct bCopyOnWrite *cow);
|
||||
const void *CustomData_add_layer_named_with_data(
|
||||
struct CustomData *data,
|
||||
eCustomDataType type,
|
||||
void *layer_data,
|
||||
int totelem,
|
||||
const char *name,
|
||||
const ImplicitSharingInfoHandle *implicit_sharing_info);
|
||||
|
||||
void *CustomData_add_layer_anonymous(struct CustomData *data,
|
||||
eCustomDataType type,
|
||||
|
@ -282,7 +285,7 @@ const void *CustomData_add_layer_anonymous_with_data(
|
|||
const AnonymousAttributeIDHandle *anonymous_id,
|
||||
int totelem,
|
||||
void *layer_data,
|
||||
const struct bCopyOnWrite *cow);
|
||||
const ImplicitSharingInfoHandle *implicit_sharing_info);
|
||||
|
||||
/**
|
||||
* Frees the active or first data layer with the give type.
|
||||
|
|
|
@ -242,17 +242,17 @@ static const void *add_generic_custom_data_layer_with_existing_data(
|
|||
const AttributeIDRef &attribute_id,
|
||||
const int domain_size,
|
||||
void *layer_data,
|
||||
const bCopyOnWrite *cow)
|
||||
const ImplicitSharingInfo *implicit_sharing_info)
|
||||
{
|
||||
if (attribute_id.is_anonymous()) {
|
||||
const AnonymousAttributeID &anonymous_id = attribute_id.anonymous_id();
|
||||
return CustomData_add_layer_anonymous_with_data(
|
||||
&custom_data, data_type, &anonymous_id, domain_size, layer_data, cow);
|
||||
&custom_data, data_type, &anonymous_id, domain_size, layer_data, implicit_sharing_info);
|
||||
}
|
||||
char attribute_name_c[MAX_CUSTOMDATA_LAYER_NAME];
|
||||
attribute_id.name().copy(attribute_name_c);
|
||||
return CustomData_add_layer_named_with_data(
|
||||
&custom_data, data_type, layer_data, domain_size, attribute_name_c, cow);
|
||||
&custom_data, data_type, layer_data, domain_size, attribute_name_c, implicit_sharing_info);
|
||||
}
|
||||
|
||||
static bool add_custom_data_layer_from_attribute_init(const AttributeIDRef &attribute_id,
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
#include "data_transfer_intern.h"
|
||||
|
||||
using blender::float2;
|
||||
using blender::ImplicitSharingInfo;
|
||||
using blender::IndexRange;
|
||||
using blender::Set;
|
||||
using blender::Span;
|
||||
|
@ -2158,13 +2159,14 @@ void customData_mask_layers__print(const CustomData_MeshMasks *mask)
|
|||
|
||||
static void customData_update_offsets(CustomData *data);
|
||||
|
||||
static CustomDataLayer *customData_add_layer__internal(CustomData *data,
|
||||
eCustomDataType type,
|
||||
eCDAllocType alloctype,
|
||||
void *layer_data_to_assign,
|
||||
const bCopyOnWrite *cow_to_assign,
|
||||
int totelem,
|
||||
const char *name);
|
||||
static CustomDataLayer *customData_add_layer__internal(
|
||||
CustomData *data,
|
||||
eCustomDataType type,
|
||||
eCDAllocType alloctype,
|
||||
void *layer_data_to_assign,
|
||||
const ImplicitSharingInfo *implicit_sharing_info_to_assign,
|
||||
int totelem,
|
||||
const char *name);
|
||||
|
||||
void CustomData_update_typemap(CustomData *data)
|
||||
{
|
||||
|
@ -2266,23 +2268,28 @@ static bool customdata_merge_internal(const CustomData *source,
|
|||
}
|
||||
|
||||
void *layer_data_to_assign = nullptr;
|
||||
const bCopyOnWrite *cow_to_assign = nullptr;
|
||||
const ImplicitSharingInfo *implicit_sharing_info_to_assign = nullptr;
|
||||
if (alloctype == CD_ASSIGN) {
|
||||
if (src_layer.data != nullptr) {
|
||||
if (src_layer.cow == nullptr) {
|
||||
if (src_layer.implicit_sharing_info == nullptr) {
|
||||
/* Can't share the layer, duplicate it instead. */
|
||||
layer_data_to_assign = copy_layer_data(type, src_layer.data, totelem);
|
||||
}
|
||||
else {
|
||||
/* Share the layer. */
|
||||
layer_data_to_assign = src_layer.data;
|
||||
cow_to_assign = src_layer.cow;
|
||||
implicit_sharing_info_to_assign = src_layer.implicit_sharing_info;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CustomDataLayer *new_layer = customData_add_layer__internal(
|
||||
dest, type, alloctype, layer_data_to_assign, cow_to_assign, totelem, src_layer.name);
|
||||
CustomDataLayer *new_layer = customData_add_layer__internal(dest,
|
||||
type,
|
||||
alloctype,
|
||||
layer_data_to_assign,
|
||||
implicit_sharing_info_to_assign,
|
||||
totelem,
|
||||
src_layer.name);
|
||||
|
||||
new_layer->uid = src_layer.uid;
|
||||
new_layer->flag |= src_layer_flag & (CD_FLAG_EXTERNAL | CD_FLAG_IN_MEMORY);
|
||||
|
@ -2345,18 +2352,18 @@ CustomData CustomData_shallow_copy_remove_non_bmesh_attributes(const CustomData
|
|||
}
|
||||
|
||||
/**
|
||||
* A #bCopyOnWrite that knows how to free the entire referenced custom data layer (including
|
||||
* A #ImplicitSharingInfo that knows how to free the entire referenced custom data layer (including
|
||||
* potentially separately allocated chunks like for vertex groups).
|
||||
*/
|
||||
class CustomDataLayerCOW : public bCopyOnWrite {
|
||||
class CustomDataLayerImplicitSharing : public ImplicitSharingInfo {
|
||||
private:
|
||||
const void *data_;
|
||||
const int totelem_;
|
||||
const eCustomDataType type_;
|
||||
|
||||
public:
|
||||
CustomDataLayerCOW(const void *data, const int totelem, const eCustomDataType type)
|
||||
: bCopyOnWrite(1), data_(data), totelem_(totelem), type_(type)
|
||||
CustomDataLayerImplicitSharing(const void *data, const int totelem, const eCustomDataType type)
|
||||
: ImplicitSharingInfo(1), data_(data), totelem_(totelem), type_(type)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -2368,12 +2375,12 @@ class CustomDataLayerCOW : public bCopyOnWrite {
|
|||
}
|
||||
};
|
||||
|
||||
/** Create a #bCopyOnWrite that takes ownership of the data. */
|
||||
static bCopyOnWrite *make_cow_for_array(const eCustomDataType type,
|
||||
const void *data,
|
||||
const int totelem)
|
||||
/** Create a #ImplicitSharingInfo that takes ownership of the data. */
|
||||
static ImplicitSharingInfo *make_cow_for_array(const eCustomDataType type,
|
||||
const void *data,
|
||||
const int totelem)
|
||||
{
|
||||
return MEM_new<CustomDataLayerCOW>(__func__, data, totelem, type);
|
||||
return MEM_new<CustomDataLayerImplicitSharing>(__func__, data, totelem, type);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2384,16 +2391,16 @@ static void ensure_layer_data_is_mutable(CustomDataLayer &layer, const int totel
|
|||
if (layer.data == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (layer.cow == nullptr) {
|
||||
if (layer.implicit_sharing_info == nullptr) {
|
||||
/* Can not be shared without cow data. */
|
||||
return;
|
||||
}
|
||||
if (layer.cow->is_shared()) {
|
||||
if (layer.implicit_sharing_info->is_shared()) {
|
||||
const eCustomDataType type = eCustomDataType(layer.type);
|
||||
const void *old_data = layer.data;
|
||||
layer.data = copy_layer_data(type, old_data, totelem);
|
||||
layer.cow->remove_user_and_delete_if_last();
|
||||
layer.cow = make_cow_for_array(type, layer.data, totelem);
|
||||
layer.implicit_sharing_info->remove_user_and_delete_if_last();
|
||||
layer.implicit_sharing_info = make_cow_for_array(type, layer.data, totelem);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2415,14 +2422,15 @@ void CustomData_realloc(CustomData *data, const int old_size, const int new_size
|
|||
memcpy(new_layer_data, layer->data, std::min(old_size_in_bytes, new_size_in_bytes));
|
||||
}
|
||||
/* Remove ownership of old array */
|
||||
if (layer->cow) {
|
||||
layer->cow->remove_user_and_delete_if_last();
|
||||
layer->cow = nullptr;
|
||||
if (layer->implicit_sharing_info) {
|
||||
layer->implicit_sharing_info->remove_user_and_delete_if_last();
|
||||
layer->implicit_sharing_info = nullptr;
|
||||
}
|
||||
/* Take ownership of new array. */
|
||||
layer->data = new_layer_data;
|
||||
if (layer->data) {
|
||||
layer->cow = make_cow_for_array(eCustomDataType(layer->type), layer->data, new_size);
|
||||
layer->implicit_sharing_info = make_cow_for_array(
|
||||
eCustomDataType(layer->type), layer->data, new_size);
|
||||
}
|
||||
|
||||
if (new_size > old_size) {
|
||||
|
@ -2468,13 +2476,13 @@ static void customData_free_layer__internal(CustomDataLayer *layer, const int to
|
|||
layer->anonymous_id = nullptr;
|
||||
}
|
||||
const eCustomDataType type = eCustomDataType(layer->type);
|
||||
if (layer->cow == nullptr) {
|
||||
if (layer->implicit_sharing_info == nullptr) {
|
||||
if (layer->data) {
|
||||
free_layer_data(type, layer->data, totelem);
|
||||
}
|
||||
}
|
||||
else {
|
||||
layer->cow->remove_user_and_delete_if_last();
|
||||
layer->implicit_sharing_info->remove_user_and_delete_if_last();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2830,13 +2838,14 @@ static void customData_resize(CustomData *data, const int grow_amount)
|
|||
data->maxlayer += grow_amount;
|
||||
}
|
||||
|
||||
static CustomDataLayer *customData_add_layer__internal(CustomData *data,
|
||||
const eCustomDataType type,
|
||||
const eCDAllocType alloctype,
|
||||
void *layer_data_to_assign,
|
||||
const bCopyOnWrite *cow_to_assign,
|
||||
const int totelem,
|
||||
const char *name)
|
||||
static CustomDataLayer *customData_add_layer__internal(
|
||||
CustomData *data,
|
||||
const eCustomDataType type,
|
||||
const eCDAllocType alloctype,
|
||||
void *layer_data_to_assign,
|
||||
const ImplicitSharingInfo *implicit_sharing_info_to_assign,
|
||||
const int totelem,
|
||||
const char *name)
|
||||
{
|
||||
const LayerTypeInfo &type_info = *layerType_getInfo(type);
|
||||
int flag = 0;
|
||||
|
@ -2891,23 +2900,23 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data,
|
|||
break;
|
||||
}
|
||||
case CD_ASSIGN: {
|
||||
if (totelem == 0 && cow_to_assign == nullptr) {
|
||||
if (totelem == 0 && implicit_sharing_info_to_assign == nullptr) {
|
||||
MEM_SAFE_FREE(layer_data_to_assign);
|
||||
}
|
||||
else {
|
||||
new_layer.data = layer_data_to_assign;
|
||||
new_layer.cow = cow_to_assign;
|
||||
if (new_layer.cow) {
|
||||
new_layer.cow->add_user();
|
||||
new_layer.implicit_sharing_info = implicit_sharing_info_to_assign;
|
||||
if (new_layer.implicit_sharing_info) {
|
||||
new_layer.implicit_sharing_info->add_user();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (new_layer.data != nullptr && new_layer.cow == nullptr) {
|
||||
if (new_layer.data != nullptr && new_layer.implicit_sharing_info == nullptr) {
|
||||
/* Make layer data shareable. */
|
||||
new_layer.cow = make_cow_for_array(type, new_layer.data, totelem);
|
||||
new_layer.implicit_sharing_info = make_cow_for_array(type, new_layer.data, totelem);
|
||||
}
|
||||
|
||||
new_layer.type = type;
|
||||
|
@ -2968,7 +2977,7 @@ const void *CustomData_add_layer_with_data(CustomData *data,
|
|||
const eCustomDataType type,
|
||||
void *layer_data,
|
||||
const int totelem,
|
||||
const bCopyOnWrite *cow)
|
||||
const ImplicitSharingInfo *cow)
|
||||
{
|
||||
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
|
||||
|
||||
|
@ -3004,7 +3013,7 @@ const void *CustomData_add_layer_named_with_data(CustomData *data,
|
|||
void *layer_data,
|
||||
int totelem,
|
||||
const char *name,
|
||||
const bCopyOnWrite *cow)
|
||||
const ImplicitSharingInfo *cow)
|
||||
{
|
||||
CustomDataLayer *layer = customData_add_layer__internal(
|
||||
data, type, CD_ASSIGN, layer_data, cow, totelem, name);
|
||||
|
@ -3042,7 +3051,7 @@ const void *CustomData_add_layer_anonymous_with_data(
|
|||
const AnonymousAttributeIDHandle *anonymous_id,
|
||||
const int totelem,
|
||||
void *layer_data,
|
||||
const bCopyOnWrite *cow)
|
||||
const ImplicitSharingInfo *cow)
|
||||
{
|
||||
const char *name = anonymous_id->name().c_str();
|
||||
CustomDataLayer *layer = customData_add_layer__internal(
|
||||
|
|
|
@ -1300,22 +1300,26 @@ void BKE_mesh_legacy_face_set_to_generic(Mesh *mesh)
|
|||
return;
|
||||
}
|
||||
void *faceset_data = nullptr;
|
||||
const bCopyOnWrite *faceset_cow = nullptr;
|
||||
const ImplicitSharingInfo *faceset_implicit_sharing_info = nullptr;
|
||||
for (const int i : IndexRange(mesh->pdata.totlayer)) {
|
||||
CustomDataLayer &layer = mesh->pdata.layers[i];
|
||||
if (layer.type == CD_SCULPT_FACE_SETS) {
|
||||
faceset_data = layer.data;
|
||||
faceset_cow = layer.cow;
|
||||
faceset_implicit_sharing_info = layer.implicit_sharing_info;
|
||||
layer.data = nullptr;
|
||||
layer.cow = nullptr;
|
||||
layer.implicit_sharing_info = nullptr;
|
||||
CustomData_free_layer(&mesh->pdata, CD_SCULPT_FACE_SETS, mesh->totpoly, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (faceset_data != nullptr) {
|
||||
CustomData_add_layer_named_with_data(
|
||||
&mesh->pdata, CD_PROP_INT32, faceset_data, mesh->totpoly, ".sculpt_face_set", faceset_cow);
|
||||
faceset_cow->remove_user_and_delete_if_last();
|
||||
CustomData_add_layer_named_with_data(&mesh->pdata,
|
||||
CD_PROP_INT32,
|
||||
faceset_data,
|
||||
mesh->totpoly,
|
||||
".sculpt_face_set",
|
||||
faceset_implicit_sharing_info);
|
||||
faceset_implicit_sharing_info->remove_user_and_delete_if_last();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
/** \file
|
||||
* \ingroup bli
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
namespace blender {
|
||||
class ImplicitSharingInfo;
|
||||
}
|
||||
using ImplicitSharingInfoHandle = blender::ImplicitSharingInfo;
|
||||
|
||||
#else
|
||||
|
||||
typedef struct ImplicitSharingInfoHandle ImplicitSharingInfoHandle;
|
||||
|
||||
#endif
|
|
@ -200,8 +200,6 @@ set(SRC
|
|||
BLI_compute_context.hh
|
||||
BLI_console.h
|
||||
BLI_convexhull_2d.h
|
||||
BLI_copy_on_write.hh
|
||||
BLI_copy_on_write_user.hh
|
||||
BLI_cpp_type.hh
|
||||
BLI_cpp_type_make.hh
|
||||
BLI_cpp_types.hh
|
||||
|
@ -245,6 +243,7 @@ set(SRC
|
|||
BLI_hash_tables.hh
|
||||
BLI_heap.h
|
||||
BLI_heap_simple.h
|
||||
BLI_implicit_sharing.h
|
||||
BLI_implicit_sharing.hh
|
||||
BLI_implicit_sharing_ptr.hh
|
||||
BLI_index_mask.hh
|
||||
|
|
|
@ -102,6 +102,7 @@ extern struct Main *BLO_memfile_main_get(struct MemFile *memfile,
|
|||
*
|
||||
* \return success.
|
||||
*/
|
||||
extern bool BLO_memfile_write_file(struct MemFile *memfile, const char *filepath);
|
||||
|
||||
FileReader *BLO_memfile_new_filereader(MemFile *memfile, int undo_direction);
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "BLI_array_utils.h"
|
||||
#include "BLI_copy_on_write.hh"
|
||||
#include "BLI_implicit_sharing.hh"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_task.hh"
|
||||
|
||||
|
@ -272,16 +272,16 @@ static void um_arraystore_cd_compact(CustomData *cdata,
|
|||
}
|
||||
|
||||
if (layer->data) {
|
||||
if (layer->cow) {
|
||||
if (layer->implicit_sharing_info) {
|
||||
/* This assumes that the layer is not shared, which it is not here because it has just
|
||||
* been created in #BM_mesh_bm_to_me. The situation is a bit tricky here, because the
|
||||
* layer data may be freed partially below for e.g. vertex groups. */
|
||||
BLI_assert(layer->cow->is_mutable());
|
||||
MEM_delete(layer->cow);
|
||||
BLI_assert(layer->implicit_sharing_info->is_mutable());
|
||||
MEM_delete(layer->implicit_sharing_info);
|
||||
}
|
||||
MEM_freeN(layer->data);
|
||||
layer->data = nullptr;
|
||||
layer->cow = nullptr;
|
||||
layer->implicit_sharing_info = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
#include "DNA_defs.h"
|
||||
|
||||
#include "BLI_implicit_sharing.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -25,8 +27,6 @@ using AnonymousAttributeIDHandle = blender::bke::AnonymousAttributeID;
|
|||
typedef struct AnonymousAttributeIDHandle AnonymousAttributeIDHandle;
|
||||
#endif
|
||||
|
||||
struct bCopyOnWrite;
|
||||
|
||||
/** Descriptor and storage for a custom data layer. */
|
||||
typedef struct CustomDataLayer {
|
||||
/** Type of data in layer. */
|
||||
|
@ -59,7 +59,7 @@ typedef struct CustomDataLayer {
|
|||
* Run-time data that allows sharing `data` with other entities (mostly custom data layers on
|
||||
* other geometries).
|
||||
*/
|
||||
const struct bCopyOnWrite *cow;
|
||||
const ImplicitSharingInfoHandle *implicit_sharing_info;
|
||||
} CustomDataLayer;
|
||||
|
||||
#define MAX_CUSTOMDATA_LAYER_NAME 68
|
||||
|
|
Loading…
Reference in New Issue