Commit: 336b263b568fad2547014fe50d5810f03daa1677 Author: Joseph Eagar Date: Sun Sep 19 15:35:10 2021 -0700 Branches: sculpt-dev https://developer.blender.org/rB336b263b568fad2547014fe50d5810f03daa1677
Sculpt: brush engine stuff BrushChannels are now stored in linked lists instead of simple arrays. This helps to avoid memory corruption. I had originally wanted to be able to pass BrushChannels by value, but that doesn't really work since they heap allocd data (the input mapping curves). =================================================================== M release/scripts/startup/bl_ui/properties_paint_common.py M source/blender/blenkernel/BKE_brush_engine.h M source/blender/blenkernel/intern/brush.c M source/blender/blenkernel/intern/brush_engine.c M source/blender/blenkernel/intern/brush_engine_presets.c M source/blender/blenkernel/intern/colortools.c M source/blender/blenloader/intern/versioning_300.c M source/blender/makesdna/DNA_sculpt_brush_types.h M source/blender/makesrna/intern/rna_brush_engine.c =================================================================== diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py index b3d9230974e..ee748af74b3 100644 --- a/release/scripts/startup/bl_ui/properties_paint_common.py +++ b/release/scripts/startup/bl_ui/properties_paint_common.py @@ -137,7 +137,7 @@ class UnifiedPaintPanel: if ch.inherit: sd = context.tool_settings.sculpt #ensure channel exists in tool settings channel set - sd.channels.ensure(ch, queue=True) + sd.channels.ensure(ch) finalch = sd.channels.channels[prop_name] diff --git a/source/blender/blenkernel/BKE_brush_engine.h b/source/blender/blenkernel/BKE_brush_engine.h index 25c6227cf32..8fd2ded7075 100644 --- a/source/blender/blenkernel/BKE_brush_engine.h +++ b/source/blender/blenkernel/BKE_brush_engine.h @@ -73,18 +73,26 @@ typedef struct BrushMappingData { #define MAX_BRUSH_ENUM_DEF 32 typedef struct BrushEnumDef { - EnumPropertyItem items[MAX_BRUSH_ENUM_DEF]; + int value; + const char identifier[64]; + int icon; + const char name[64]; + const char description[512]; } BrushEnumDef; typedef struct BrushChannelType { - char name[32], idname[32], tooltip[512]; + char name[64], idname[64], tooltip[512]; float min, max, soft_min, soft_max; BrushMappingPreset mappings; int type, flag; int ivalue; float fvalue; - BrushEnumDef enumdef; // if an enum type + + BrushEnumDef enumdef[MAX_BRUSH_ENUM_DEF]; // for enum/bitmask types + EnumPropertyItem *rna_enumdef; + + bool user_defined; } BrushChannelType; typedef struct BrushCommand { @@ -98,6 +106,7 @@ typedef struct BrushCommandList { int totcommand; } BrushCommandList; +void BKE_brush_channel_free_data(BrushChannel *ch); void BKE_brush_channel_free(BrushChannel *ch); void BKE_brush_channel_copy_data(BrushChannel *dst, BrushChannel *src); void BKE_brush_channel_init(BrushChannel *ch, BrushChannelType *def); @@ -106,14 +115,22 @@ BrushChannelSet *BKE_brush_channelset_create(); BrushChannelSet *BKE_brush_channelset_copy(BrushChannelSet *src); void BKE_brush_channelset_free(BrushChannelSet *chset); -// makes a copy of ch void BKE_brush_channelset_add(BrushChannelSet *chset, BrushChannel *ch); -void BKE_brush_channelset_queue(BrushChannelSet *chset, BrushChannel *ch); + +// makes a copy of ch +void BKE_brush_channelset_add_duplicate(BrushChannelSet *chset, BrushChannel *ch); + +// does not add to namemap ghash +void BKE_brush_channel_ensure_unque_name(BrushChannelSet *chset, BrushChannel *ch); + +// does not free ch or its data +void BKE_brush_channelset_remove(BrushChannelSet *chset, BrushChannel *ch); + +// does not free ch or its data +bool BKE_brush_channelset_remove_named(BrushChannelSet *chset, const char *idname); // checks is a channel with existing->idname exists; if not a copy of existing is made and inserted -void BKE_brush_channelset_ensure_existing(BrushChannelSet *chset, - BrushChannel *existing, - bool queue); +void BKE_brush_channelset_ensure_existing(BrushChannelSet *chset, BrushChannel *existing); BrushChannel *BKE_brush_channelset_lookup(BrushChannelSet *chset, const char *idname); @@ -193,6 +210,7 @@ void BKE_brush_channelset_compat_load(BrushChannelSet *chset, // merge in channels the ui requested void BKE_brush_apply_queued_channels(BrushChannelSet *chset, bool do_override); +void BKE_brush_channeltype_rna_check(BrushChannelType *def); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index e2e33db0fd8..0151cc4e16d 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -315,6 +315,7 @@ static void brush_blend_read_data(BlendDataReader *reader, ID *id) if (brush->channels) { BLO_read_data_address(reader, &brush->channels); + BKE_brush_channelset_read(reader, brush->channels); BKE_brush_builtin_patch(brush, brush->sculpt_tool); } @@ -1798,12 +1799,12 @@ void BKE_brush_sculpt_reset(Brush *br) // BKE_brush_debug_print_state(br); BKE_brush_builtin_create(br, br->sculpt_tool); + BrushChannel *ch; - for (int i = 0; i < br->channels->totchannel; i++) { - BrushChannel *ch = br->channels->channels + i; + for (ch = (BrushChannel *)br->channels->channels.first; ch; ch = ch->next) { BrushChannelType *def = ch->def; - BKE_brush_channel_free(ch); + BKE_brush_channel_free_data(ch); BKE_brush_channel_init(ch, def); } diff --git a/source/blender/blenkernel/intern/brush_engine.c b/source/blender/blenkernel/intern/brush_engine.c index ee345bccd3a..4a67ffd2e37 100644 --- a/source/blender/blenkernel/intern/brush_engine.c +++ b/source/blender/blenkernel/intern/brush_engine.c @@ -10,8 +10,12 @@ #include "BLI_math.h" #include "BLI_memarena.h" #include "BLI_mempool.h" +#include "BLI_rand.h" #include "BLI_rect.h" #include "BLI_smallhash.h" +#include "BLI_string.h" +#include "BLI_string_utils.h" +#include "BLI_utildefines.h" #include "DNA_brush_enums.h" #include "DNA_brush_types.h" @@ -38,7 +42,7 @@ static struct { } namestack[256] = {0}; int namestack_i = 1; -ATTR_NO_OPT void namestack_push(const char *name) +void namestack_push(const char *name) { namestack_i++; @@ -50,6 +54,7 @@ void namestack_pop() { namestack_i--; } + #define namestack_head_name strdup(namestack[namestack_i].tag) void BKE_curvemapping_copy_data_tag_ex(CurveMapping *target, @@ -59,7 +64,7 @@ void BKE_curvemapping_copy_data_tag_ex(CurveMapping *target, #define BKE_curvemapping_copy_data(dst, src) \ BKE_curvemapping_copy_data_tag_ex(dst, src, namestack_head_name) -static bool check_corrupted_curve(BrushMapping *dst) +ATTR_NO_OPT static bool check_corrupted_curve(BrushMapping *dst) { const float clip_size_x = BLI_rctf_size_x(&dst->curve.curr); @@ -100,13 +105,44 @@ generated from the node group inputs. extern BrushChannelType brush_builtin_channels[]; extern const int brush_builtin_channel_len; -void BKE_brush_channel_free(BrushChannel *ch) +ATTR_NO_OPT void BKE_brush_channeltype_rna_check(BrushChannelType *def) +{ + if (def->rna_enumdef) { + return; + } + + if (!def->user_defined) { + // builtin channel types are never freed, don't use guardedalloc + def->rna_enumdef = malloc(sizeof(EnumPropertyItem) * ARRAY_SIZE(def->enumdef)); + } + + else { + def->rna_enumdef = MEM_calloc_arrayN( + ARRAY_SIZE(def->enumdef), sizeof(EnumPropertyItem), "def->rna_enumdef"); + } + + for (int i = 0; i < ARRAY_SIZE(def->enumdef); i++) { + def->rna_enumdef[i].value = def->enumdef[i].value; + def->rna_enumdef[i].identifier = def->enumdef[i].identifier; + def->rna_enumdef[i].icon = def->enumdef[i].icon; + def->rna_enumdef[i].name = def->enumdef[i].name; + def->rna_enumdef[i].description = def->enumdef[i].description; + } +} + +ATTR_NO_OPT void BKE_brush_channel_free_data(BrushChannel *ch) { for (int i = 0; i < BRUSH_MAPPING_MAX; i++) { BKE_curvemapping_free_data(&ch->mappings[i].curve); } } +ATTR_NO_OPT void BKE_brush_channel_free(BrushChannel *ch) +{ + BKE_brush_channel_free_data(ch); + MEM_freeN(ch); +} + ATTR_NO_OPT void BKE_brush_channel_copy_data(BrushChannel *dst, BrushChannel *src) { // we have to free old curvemappings here, @@ -116,8 +152,14 @@ ATTR_NO_OPT void BKE_brush_channel_copy_data(BrushChannel *dst, BrushChannel *sr BKE_curvemapping_free_data(&dst->mappings[i].curve); } + // preserve linked list pointers + void *next = dst->next, *prev = dst->prev; + *dst = *src; + dst->next = next; + dst->prev = prev; + // clear curves in dst, see comment above for (int i = 0; i < BRUSH_MAPPING_MAX; i++) { memset(&dst->mappings[i].curve, 0, sizeof(CurveMapping)); @@ -135,7 +177,12 @@ ATTR_NO_OPT void BKE_brush_channel_copy_data(BrushChannel *dst, BrushChannel *sr ATTR_NO_OPT void BKE_brush_channel_init(BrushChannel *ch, BrushChannelType *def) { + // preserve linked list pointers + BrushChannel *next = ch->next, *prev = ch->prev; + memset(ch, 0, sizeof(*ch)); + ch->next = next; + ch->prev = prev; strcpy(ch->name, def->name); strcpy(ch->idname, def->idname); @@ -197,108 +244,137 @@ ATTR_NO_OPT void BKE_brush_channel_init(BrushChannel *ch, BrushChannelType *def) BrushChannelSet *BKE_brush_channelset_create() { - return (BrushChannelSet *)MEM_callocN(sizeof(BrushChannelSet), "BrushChannelSet"); -} + BrushChannelSet *chset = (BrushChannelSet *)MEM_callocN(sizeof(BrushChannelSet), + "BrushChannelSet"); -void BKE_brush_apply_queued_channels(BrushChannelSet *chset, bool do_override) -{ - if (!chset->tot_queued_channel) { - return; - } + chset->namemap = BLI_ghash_str_new("BrushChannelSet"); - for (int i = 0; i < chset->tot_queued_channel; i++) { - BrushChannel *ch = chset->queued_channels; + return chset; +} - BrushChannel *exist = BKE_brush_channelset_lookup(chset, ch->idname); +ATTR_NO_OPT void BKE_brush_channelset_free(BrushChannelSet *chset) +{ + BrushChannel *ch, *next; - if (exist) { - if (!do_override) { - continue; - } + BLI_ghash_free(chset->namemap, NULL, NULL); - BKE_brush_channel_free(exist); - *exist = *ch; + for (ch = chset->channels.first; ch; ch = next) { + next = ch->next; - continue; - } - else { - BKE_brush_channelset_add(chset, ch); - BKE_brush_channel_free(ch); - } + BKE_brush_channel_free(ch); } - MEM_SAFE_FREE(chset->queued_channels); - chset->queued_channels = NULL; - chset->tot_queued_channel = NULL; + MEM_freeN(chset); } -void BKE_brush_channelset_free(BrushChannelSet *chset) +static int _rng_seed = 0; + +ATTR_NO_OPT void BKE_brush_channel_ensure_unque_name(BrushChannelSet *chset, BrushChannel *ch) { - for (int step = 0; step < 2; step++) { - BrushChannel *channels = step ? chset->queued_channels : chset->channels; - int totchannel = step ? chset->tot_queued_channel : chset->totchannel; + BrushChannel *ch2; + int i = 1; + char idname[512]; - if (ch @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org List details, subscription details or unsubscribe: https://lists.blender.org/mailman/listinfo/bf-blender-cvs