writefile: avoid adding SDNA to every undo step

Since SDNA was allocated for each undo step,
the new address meant it was considered different and included again.

Add an option not to duplicate the DNA string when calling DNA_sdna_from_data,
as well as avoiding a redundant copy, it writes the same address each time.
This commit is contained in:
2016-07-06 22:23:50 +10:00
parent 94e84f5be4
commit a0793765ef
6 changed files with 36 additions and 11 deletions

View File

@@ -918,7 +918,7 @@ static int read_file_dna(FileData *fd)
if (bhead->code == DNA1) {
const bool do_endian_swap = (fd->flags & FD_FLAGS_SWITCH_ENDIAN) != 0;
fd->filesdna = DNA_sdna_from_data(&bhead[1], bhead->len, do_endian_swap);
fd->filesdna = DNA_sdna_from_data(&bhead[1], bhead->len, do_endian_swap, true);
if (fd->filesdna) {
fd->compflags = DNA_struct_get_compareflags(fd->filesdna, fd->memsdna);
/* used to retrieve ID names from (bhead+1) */
@@ -1078,7 +1078,7 @@ static FileData *filedata_new(void)
* but it keeps us re-entrant, remove once we have
* a lib that provides a nice lock. - zr
*/
fd->memsdna = DNA_sdna_from_data(DNAstr, DNAlen, false);
fd->memsdna = DNA_sdna_from_data(DNAstr, DNAlen, false, false);
fd->datamap = oldnewmap_new();
fd->globmap = oldnewmap_new();

View File

@@ -325,7 +325,7 @@ static WriteData *writedata_new(WriteWrap *ww)
{
WriteData *wd = MEM_callocN(sizeof(*wd), "writedata");
wd->sdna = DNA_sdna_from_data(DNAstr, DNAlen, false);
wd->sdna = DNA_sdna_from_data(DNAstr, DNAlen, false, false);
wd->ww = ww;
@@ -4013,6 +4013,10 @@ static bool write_file_handle(
write_thumb(wd, thumb);
write_global(wd, write_flags, mainvar);
/* The windowmanager and screen often change,
* avoid thumbnail detecting changes because of this. */
mywrite(wd, MYWRITE_FLUSH, 0);
write_windowmanagers(wd, &mainvar->wm);
write_screens(wd, &mainvar->screen);
write_movieclips(wd, &mainvar->movieclip);
@@ -4046,11 +4050,17 @@ static bool write_file_handle(
write_linestyles(wd, &mainvar->linestyle);
write_libraries(wd, mainvar->next);
/* So changes above don't cause a 'DNA1' to be detected as changed on undo. */
mywrite(wd, MYWRITE_FLUSH, 0);
if (write_flags & G_FILE_USERPREFS) {
write_userdef(wd);
}
/* dna as last, because (to be implemented) test for which structs are written */
/* Write DNA last, because (to be implemented) test for which structs are written.
*
* Note that we *borrow* the pointer to 'DNAstr',
* so writing each time uses the same address and doesn't cause unnecessary undo overhead. */
writedata(wd, DNA1, wd->sdna->datalen, wd->sdna->data);
#ifdef USE_NODE_COMPAT_CUSTOMNODES

View File

@@ -74,7 +74,9 @@ enum eSDNA_StructCompare {
SDNA_CMP_NOT_EQUAL = 2,
};
struct SDNA *DNA_sdna_from_data(const void *data, const int datalen, bool do_endian_swap);
struct SDNA *DNA_sdna_from_data(
const void *data, const int datalen,
bool do_endian_swap, bool data_alloc);
void DNA_sdna_free(struct SDNA *sdna);
int DNA_struct_find_nr(struct SDNA *sdna, const char *str);

View File

@@ -35,8 +35,9 @@
#
#
typedef struct SDNA {
char *data; /* full copy of 'encoded' data */
const char *data; /* full copy of 'encoded' data */
int datalen; /* length of data */
bool data_alloc;
int nr_names; /* total number of struct members */
const char **names; /* struct member names */

View File

@@ -196,7 +196,10 @@ int DNA_elem_array_size(const char *str)
void DNA_sdna_free(SDNA *sdna)
{
MEM_freeN(sdna->data);
if (sdna->data_alloc) {
MEM_freeN((void *)sdna->data);
}
MEM_freeN((void *)sdna->names);
MEM_freeN(sdna->types);
MEM_freeN(sdna->structs);
@@ -549,15 +552,24 @@ static void init_structDNA(SDNA *sdna, bool do_endian_swap)
/**
* Constructs and returns a decoded SDNA structure from the given encoded SDNA data block.
*/
SDNA *DNA_sdna_from_data(const void *data, const int datalen, bool do_endian_swap)
SDNA *DNA_sdna_from_data(
const void *data, const int datalen,
bool do_endian_swap, bool data_alloc)
{
SDNA *sdna = MEM_mallocN(sizeof(*sdna), "sdna");
sdna->lastfind = 0;
sdna->datalen = datalen;
sdna->data = MEM_mallocN(datalen, "sdna_data");
memcpy(sdna->data, data, datalen);
if (data_alloc) {
char *data_copy = MEM_mallocN(datalen, "sdna_data");
memcpy(data_copy, data, datalen);
sdna->data = data_copy;
}
else {
sdna->data = data;
}
sdna->data_alloc = data_alloc;
init_structDNA(sdna, do_endian_swap);

View File

@@ -532,7 +532,7 @@ BlenderRNA *RNA_create(void)
brna = MEM_callocN(sizeof(BlenderRNA), "BlenderRNA");
DefRNA.sdna = DNA_sdna_from_data(DNAstr, DNAlen, false);
DefRNA.sdna = DNA_sdna_from_data(DNAstr, DNAlen, false, false);
BLI_listbase_clear(&DefRNA.structs);
DefRNA.error = 0;
DefRNA.preprocess = 1;