Blender V5.0
deg_eval_copy_on_write.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2017 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9/* Enable special trickery to treat nested owned IDs (such as nodetree of
10 * material) to be handled in same way as "real" data-blocks, even tho some
11 * internal BKE routines doesn't treat them like that.
12 *
13 * TODO(sergey): Re-evaluate that after new ID handling is in place. */
14#define NESTED_ID_NASTY_WORKAROUND
15
16/* Silence warnings from copying deprecated fields. */
17#define DNA_DEPRECATED_ALLOW
18
20
21#include <cstring>
22
23#include "BLI_listbase.h"
24#include "BLI_utildefines.h"
25
26#include "BKE_curve.hh"
27#include "BKE_global.hh"
28#include "BKE_layer.hh"
29#include "BKE_lib_id.hh"
30#include "BKE_scene.hh"
31
32#include "DEG_depsgraph.hh"
34
35#include "MEM_guardedalloc.h"
36
37#include "DNA_ID.h"
38#include "DNA_anim_types.h"
39#include "DNA_armature_types.h"
40#include "DNA_mesh_types.h"
41#include "DNA_modifier_types.h"
42#include "DNA_object_types.h"
43#include "DNA_particle_types.h"
44#include "DNA_scene_types.h"
45
46#include "DRW_engine.hh"
47
48#ifdef NESTED_ID_NASTY_WORKAROUND
49# include "DNA_curve_types.h"
50# include "DNA_key_types.h"
51# include "DNA_lattice_types.h"
52# include "DNA_light_types.h"
53# include "DNA_linestyle_types.h"
54# include "DNA_material_types.h"
55# include "DNA_meta_types.h"
56# include "DNA_node_types.h"
57# include "DNA_texture_types.h"
58# include "DNA_world_types.h"
59#endif
60
61#include "BKE_anim_data.hh"
62#include "BKE_animsys.h"
63#include "BKE_armature.hh"
64#include "BKE_editmesh.hh"
65#include "BKE_lib_query.hh"
66#include "BKE_mesh_types.hh"
67#include "BKE_modifier.hh"
68#include "BKE_object.hh"
69#include "BKE_pointcache.h"
70#include "BKE_sound.h"
71
72#include "SEQ_relations.hh"
73
76#include "intern/depsgraph.hh"
80
81namespace blender::deg {
82
83#define DEBUG_PRINT \
84 if (G.debug & G_DEBUG_DEPSGRAPH_EVAL) \
85 printf
86
87namespace {
88
89#ifdef NESTED_ID_NASTY_WORKAROUND
90union NestedIDHackTempStorage {
91 Curve curve;
92 FreestyleLineStyle linestyle;
93 Light lamp;
94 Lattice lattice;
95 Material material;
96 Mesh mesh;
97 Scene scene;
98 Tex tex;
99 World world;
100};
101
102/* Set nested owned ID pointers to nullptr. */
103void nested_id_hack_discard_pointers(ID *id_cow)
104{
105 switch (GS(id_cow->name)) {
106# define SPECIAL_CASE(id_type, dna_type, field) \
107 case id_type: { \
108 ((dna_type *)id_cow)->field = nullptr; \
109 break; \
110 }
111
113 SPECIAL_CASE(ID_LA, Light, nodetree)
114 SPECIAL_CASE(ID_MA, Material, nodetree)
115 SPECIAL_CASE(ID_TE, Tex, nodetree)
116 SPECIAL_CASE(ID_WO, World, nodetree)
117
120 SPECIAL_CASE(ID_ME, Mesh, key)
121
122 case ID_SCE: {
123 Scene *scene_cow = (Scene *)id_cow;
124 /* Tool settings pointer is shared with the original scene. */
125 scene_cow->toolsettings = nullptr;
126 break;
127 }
128
129 case ID_OB: {
130 /* Clear the ParticleSettings pointer to prevent doubly-freeing it. */
131 Object *ob = (Object *)id_cow;
133 psys->part = nullptr;
134 }
135 break;
136 }
137# undef SPECIAL_CASE
138
139 default:
140 break;
141 }
142}
143
144/* Set ID pointer of nested owned IDs (nodetree, key) to nullptr.
145 *
146 * Return pointer to a new ID to be used. */
147const ID *nested_id_hack_get_discarded_pointers(NestedIDHackTempStorage *storage, const ID *id)
148{
149 switch (GS(id->name)) {
150# define SPECIAL_CASE(id_type, dna_type, field, variable) \
151 case id_type: { \
152 storage->variable = dna::shallow_copy(*(dna_type *)id); \
153 storage->variable.field = nullptr; \
154 return &storage->variable.id; \
155 }
156
157 SPECIAL_CASE(ID_LS, FreestyleLineStyle, nodetree, linestyle)
158 SPECIAL_CASE(ID_LA, Light, nodetree, lamp)
159 SPECIAL_CASE(ID_MA, Material, nodetree, material)
160 SPECIAL_CASE(ID_TE, Tex, nodetree, tex)
161 SPECIAL_CASE(ID_WO, World, nodetree, world)
162
163 SPECIAL_CASE(ID_CU_LEGACY, Curve, key, curve)
164 SPECIAL_CASE(ID_LT, Lattice, key, lattice)
165 SPECIAL_CASE(ID_ME, Mesh, key, mesh)
166
167 case ID_SCE: {
168 storage->scene = *(Scene *)id;
169 storage->scene.toolsettings = nullptr;
170 return &storage->scene.id;
171 }
172
173# undef SPECIAL_CASE
174
175 default:
176 break;
177 }
178 return id;
179}
180
181/* Set ID pointer of nested owned IDs (nodetree, key) to the original value. */
182void nested_id_hack_restore_pointers(const ID *old_id, ID *new_id)
183{
184 if (new_id == nullptr) {
185 return;
186 }
187 switch (GS(old_id->name)) {
188# define SPECIAL_CASE(id_type, dna_type, field) \
189 case id_type: { \
190 ((dna_type *)(new_id))->field = ((dna_type *)(old_id))->field; \
191 break; \
192 }
193
195 SPECIAL_CASE(ID_LA, Light, nodetree)
196 SPECIAL_CASE(ID_MA, Material, nodetree)
197 SPECIAL_CASE(ID_TE, Tex, nodetree)
198 SPECIAL_CASE(ID_WO, World, nodetree)
199
202 SPECIAL_CASE(ID_ME, Mesh, key)
203
204# undef SPECIAL_CASE
205 default:
206 break;
207 }
208}
209
210/* Remap pointer of nested owned IDs (nodetree. key) to the new ID values. */
211void ntree_hack_remap_pointers(const Depsgraph *depsgraph, ID *id_cow)
212{
213 switch (GS(id_cow->name)) {
214# define SPECIAL_CASE(id_type, dna_type, field, field_type) \
215 case id_type: { \
216 dna_type *data = (dna_type *)id_cow; \
217 if (data->field != nullptr) { \
218 ID *ntree_id_cow = depsgraph->get_cow_id(&data->field->id); \
219 if (ntree_id_cow != nullptr) { \
220 DEG_COW_PRINT(" Remapping datablock for %s: id_orig=%p id_cow=%p\n", \
221 data->field->id.name, \
222 data->field, \
223 ntree_id_cow); \
224 data->field = (field_type *)ntree_id_cow; \
225 } \
226 } \
227 break; \
228 }
229
231 SPECIAL_CASE(ID_LA, Light, nodetree, bNodeTree)
233 SPECIAL_CASE(ID_TE, Tex, nodetree, bNodeTree)
234 SPECIAL_CASE(ID_WO, World, nodetree, bNodeTree)
235
238 SPECIAL_CASE(ID_ME, Mesh, key, Key)
239
240# undef SPECIAL_CASE
241 default:
242 break;
243 }
244}
245#endif /* NODETREE_NASTY_WORKAROUND */
246
247struct ValidateData {
248 bool is_valid;
249};
250
251/* Similar to generic BKE_id_copy() but does not require main and assumes pointer
252 * is already allocated. */
253bool id_copy_inplace_no_main(const ID *id, ID *newid)
254{
255 const ID *id_for_copy = id;
256
257 if (G.debug & G_DEBUG_DEPSGRAPH_UID) {
258 const ID_Type id_type = GS(id_for_copy->name);
259 if (id_type == ID_OB) {
260 const Object *object = reinterpret_cast<const Object *>(id_for_copy);
262 }
263 }
264
265#ifdef NESTED_ID_NASTY_WORKAROUND
266 NestedIDHackTempStorage id_hack_storage;
267 id_for_copy = nested_id_hack_get_discarded_pointers(&id_hack_storage, id);
268#endif
269
270 bool result = (BKE_id_copy_ex(nullptr,
271 (ID *)id_for_copy,
272 &newid,
275
276#ifdef NESTED_ID_NASTY_WORKAROUND
277 if (result) {
278 nested_id_hack_restore_pointers(id, newid);
279 }
280#endif
281
282 return result;
283}
284
285/* Similar to BKE_scene_copy() but does not require main and assumes pointer
286 * is already allocated. */
287bool scene_copy_inplace_no_main(const Scene *scene, Scene *new_scene)
288{
289
290 if (G.debug & G_DEBUG_DEPSGRAPH_UID) {
292 }
293
294#ifdef NESTED_ID_NASTY_WORKAROUND
295 NestedIDHackTempStorage id_hack_storage;
296 const ID *id_for_copy = nested_id_hack_get_discarded_pointers(&id_hack_storage, &scene->id);
297#else
298 const ID *id_for_copy = &scene->id;
299#endif
300 bool result = (BKE_id_copy_ex(nullptr,
301 id_for_copy,
302 (ID **)&new_scene,
305
306#ifdef NESTED_ID_NASTY_WORKAROUND
307 if (result) {
308 nested_id_hack_restore_pointers(&scene->id, &new_scene->id);
309 }
310#endif
311
312 return result;
313}
314
315/* For the given scene get view layer which corresponds to an original for the
316 * scene's evaluated one. This depends on how the scene is pulled into the
317 * dependency graph. */
318ViewLayer *get_original_view_layer(const Depsgraph *depsgraph, const IDNode *id_node)
319{
320 if (id_node->linked_state == DEG_ID_LINKED_DIRECTLY) {
321 return depsgraph->view_layer;
322 }
323 if (id_node->linked_state == DEG_ID_LINKED_VIA_SET) {
324 Scene *scene_orig = reinterpret_cast<Scene *>(id_node->id_orig);
325 return BKE_view_layer_default_render(scene_orig);
326 }
327 /* Is possible to have scene linked indirectly (i.e. via the driver) which
328 * we need to support. Currently there are issues somewhere else, which
329 * makes testing hard. This is a reported problem, so will eventually be
330 * properly fixed.
331 *
332 * TODO(sergey): Support indirectly linked scene. */
333 return nullptr;
334}
335
336/* Remove all bases from all view layers except the input one. */
337void scene_minimize_unused_view_layers(const Depsgraph *depsgraph,
338 const IDNode *id_node,
339 Scene *scene_cow)
340{
341 if (depsgraph->is_render_pipeline_depsgraph) {
342 /* If the dependency graph is used for post-processing (such as compositor) we do need to
343 * have access to its view layer names so can not remove any view layers.
344 * On a more positive side we can remove all the bases from all the view layers.
345 *
346 * NOTE: Need to clear pointers which might be pointing to original on freed (due to being
347 * unused) data.
348 *
349 * NOTE: Need to keep view layers for all scenes, even indirect ones. This is because of
350 * render layer node possibly pointing to another scene. */
351 LISTBASE_FOREACH (ViewLayer *, view_layer, &scene_cow->view_layers) {
353 }
354 return;
355 }
356
357 const ViewLayer *view_layer_input = get_original_view_layer(depsgraph, id_node);
358 ViewLayer *view_layer_eval = nullptr;
359 /* Find evaluated view layer. At the same time we free memory used by
360 * all other of the view layers. */
361 for (ViewLayer *view_layer_cow = reinterpret_cast<ViewLayer *>(scene_cow->view_layers.first),
362 *view_layer_next;
363 view_layer_cow != nullptr;
364 view_layer_cow = view_layer_next)
365 {
366 view_layer_next = view_layer_cow->next;
367 if (view_layer_input != nullptr && STREQ(view_layer_input->name, view_layer_cow->name)) {
368 view_layer_eval = view_layer_cow;
369 }
370 else {
372 }
373 }
374
375 /* Make evaluated view layer the first one in the evaluated scene (if it exists). This is for
376 * legacy sake, as this used to remove all other view layers, automatically making the evaluated
377 * one the first. Some other code may still assume it is. */
378 if (view_layer_eval != nullptr) {
379 BLI_listbase_swaplinks(&scene_cow->view_layers, scene_cow->view_layers.first, view_layer_eval);
380 }
381}
382
383void scene_remove_all_bases(Scene *scene_cow)
384{
385 LISTBASE_FOREACH (ViewLayer *, view_layer, &scene_cow->view_layers) {
386 BLI_freelistN(&view_layer->object_bases);
387 }
388}
389
390/* Makes it so given view layer only has bases corresponding to enabled
391 * objects. */
392void view_layer_remove_disabled_bases(const Depsgraph *depsgraph,
393 const Scene *scene,
394 ViewLayer *view_layer)
395{
396 if (view_layer == nullptr) {
397 return;
398 }
399 ListBase enabled_bases = {nullptr, nullptr};
400 BKE_view_layer_synced_ensure(scene, view_layer);
402 /* TODO(sergey): Would be cool to optimize this somehow, or make it so
403 * builder tags bases.
404 *
405 * NOTE: The idea of using id's tag and check whether its copied ot not
406 * is not reliable, since object might be indirectly linked into the
407 * graph.
408 *
409 * NOTE: We are using original base since the object which evaluated base
410 * points to is not yet copied. This is dangerous access from evaluated
411 * domain to original one, but this is how the entire copy-on-evaluation works:
412 * it does need to access original for an initial copy. */
413 const bool is_object_enabled = deg_check_base_in_depsgraph(depsgraph, base);
414 if (is_object_enabled) {
415 BLI_addtail(&enabled_bases, base);
416 }
417 else {
418 if (base == view_layer->basact) {
419 view_layer->basact = nullptr;
420 }
421 MEM_freeN(base);
422 }
423 }
424 view_layer->object_bases = enabled_bases;
425}
426
427void view_layer_update_orig_base_pointers(const ViewLayer *view_layer_orig,
428 ViewLayer *view_layer_eval)
429{
430 if (view_layer_orig == nullptr || view_layer_eval == nullptr) {
431 /* Happens when scene is only used for parameters or compositor/sequencer. */
432 return;
433 }
434 Base *base_orig = reinterpret_cast<Base *>(view_layer_orig->object_bases.first);
435 LISTBASE_FOREACH (Base *, base_eval, &view_layer_eval->object_bases) {
436 base_eval->base_orig = base_orig;
437 base_orig = base_orig->next;
438 }
439}
440
441void scene_setup_view_layers_before_remap(const Depsgraph *depsgraph,
442 const IDNode *id_node,
443 Scene *scene_cow)
444{
445 scene_minimize_unused_view_layers(depsgraph, id_node, scene_cow);
446 /* If dependency graph is used for post-processing we don't need any bases and can free of them.
447 * Do it before re-mapping to make that process faster. */
448 if (depsgraph->is_render_pipeline_depsgraph) {
449 scene_remove_all_bases(scene_cow);
450 }
451}
452
453void scene_setup_view_layers_after_remap(const Depsgraph *depsgraph,
454 const IDNode *id_node,
455 Scene *scene_cow)
456{
457 const ViewLayer *view_layer_orig = get_original_view_layer(depsgraph, id_node);
458 ViewLayer *view_layer_eval = reinterpret_cast<ViewLayer *>(scene_cow->view_layers.first);
459 view_layer_update_orig_base_pointers(view_layer_orig, view_layer_eval);
460 view_layer_remove_disabled_bases(depsgraph, scene_cow, view_layer_eval);
461 /* TODO(sergey): Remove objects from collections as well.
462 * Not a HUGE deal for now, nobody is looking into those CURRENTLY.
463 * Still not an excuse to have those. */
464}
465
466/* Check whether given ID is expanded or still a shallow copy. */
467inline bool check_datablock_expanded(const ID *id_cow)
468{
469 return (id_cow->name[0] != '\0');
470}
471
472/* Callback for BKE_library_foreach_ID_link which remaps original ID pointer
473 * with the one created by copy-on-evaluation system. */
474
475struct RemapCallbackUserData {
476 /* Dependency graph for which remapping is happening. */
477 const Depsgraph *depsgraph;
478};
479
481{
482 ID **id_p = cb_data->id_pointer;
483 if (*id_p == nullptr) {
484 return IDWALK_RET_NOP;
485 }
486
487 RemapCallbackUserData *user_data = (RemapCallbackUserData *)cb_data->user_data;
488 const Depsgraph *depsgraph = user_data->depsgraph;
489 ID *id_orig = *id_p;
490 if (deg_eval_copy_is_needed(id_orig)) {
491 ID *id_cow = depsgraph->get_cow_id(id_orig);
492 BLI_assert(id_cow != nullptr);
494 " Remapping data-block for %s: id_orig=%p id_cow=%p\n", id_orig->name, id_orig, id_cow);
495 *id_p = id_cow;
496 }
497 return IDWALK_RET_NOP;
498}
499
500void update_armature_edit_mode_pointers(const Depsgraph * /*depsgraph*/,
501 const ID *id_orig,
502 ID *id_cow)
503{
504 const bArmature *armature_orig = (const bArmature *)id_orig;
505 bArmature *armature_cow = (bArmature *)id_cow;
506 armature_cow->edbo = armature_orig->edbo;
507 armature_cow->act_edbone = armature_orig->act_edbone;
508}
509
510void update_curve_edit_mode_pointers(const Depsgraph * /*depsgraph*/,
511 const ID *id_orig,
512 ID *id_cow)
513{
514 const Curve *curve_orig = (const Curve *)id_orig;
515 Curve *curve_cow = (Curve *)id_cow;
516 curve_cow->editnurb = curve_orig->editnurb;
517 curve_cow->editfont = curve_orig->editfont;
518}
519
520void update_mball_edit_mode_pointers(const Depsgraph * /*depsgraph*/,
521 const ID *id_orig,
522 ID *id_cow)
523{
524 const MetaBall *mball_orig = (const MetaBall *)id_orig;
525 MetaBall *mball_cow = (MetaBall *)id_cow;
526 mball_cow->editelems = mball_orig->editelems;
527}
528
529void update_lattice_edit_mode_pointers(const Depsgraph * /*depsgraph*/,
530 const ID *id_orig,
531 ID *id_cow)
532{
533 const Lattice *lt_orig = (const Lattice *)id_orig;
534 Lattice *lt_cow = (Lattice *)id_cow;
535 lt_cow->editlatt = lt_orig->editlatt;
536}
537
538void update_mesh_edit_mode_pointers(const ID *id_orig, ID *id_cow)
539{
540 const Mesh *mesh_orig = (const Mesh *)id_orig;
541 Mesh *mesh_cow = (Mesh *)id_cow;
542 if (mesh_orig->runtime->edit_mesh == nullptr) {
543 return;
544 }
545 mesh_cow->runtime->edit_mesh = mesh_orig->runtime->edit_mesh;
546}
547
548/* Edit data is stored and owned by original datablocks, copied ones
549 * are simply referencing to them. */
550void update_edit_mode_pointers(const Depsgraph *depsgraph, const ID *id_orig, ID *id_cow)
551{
552 const ID_Type type = GS(id_orig->name);
553 switch (type) {
554 case ID_AR:
555 update_armature_edit_mode_pointers(depsgraph, id_orig, id_cow);
556 break;
557 case ID_ME:
558 update_mesh_edit_mode_pointers(id_orig, id_cow);
559 break;
560 case ID_CU_LEGACY:
561 update_curve_edit_mode_pointers(depsgraph, id_orig, id_cow);
562 break;
563 case ID_MB:
564 update_mball_edit_mode_pointers(depsgraph, id_orig, id_cow);
565 break;
566 case ID_LT:
567 update_lattice_edit_mode_pointers(depsgraph, id_orig, id_cow);
568 break;
569 default:
570 break;
571 }
572}
573
574template<typename T>
575void update_list_orig_pointers(const ListBase *listbase_orig,
576 ListBase *listbase,
577 T *T::*orig_field)
578{
579 T *element_orig = reinterpret_cast<T *>(listbase_orig->first);
580 T *element_cow = reinterpret_cast<T *>(listbase->first);
581
582 /* Both lists should have the same number of elements, so the check on
583 * `element_cow` is just to prevent a crash if this is not the case. */
584 while (element_orig != nullptr && element_cow != nullptr) {
585 element_cow->*orig_field = element_orig;
586 element_cow = element_cow->next;
587 element_orig = element_orig->next;
588 }
589
590 BLI_assert_msg(element_orig == nullptr && element_cow == nullptr,
591 "list of pointers of different sizes, unable to reliably set orig pointer");
592}
593
594void update_particle_system_orig_pointers(const Object *object_orig, Object *object_cow)
595{
596 update_list_orig_pointers(
597 &object_orig->particlesystem, &object_cow->particlesystem, &ParticleSystem::orig_psys);
598}
599
600void set_particle_system_modifiers_loaded(Object *object_cow)
601{
602 LISTBASE_FOREACH (ModifierData *, md, &object_cow->modifiers) {
603 if (md->type != eModifierType_ParticleSystem) {
604 continue;
605 }
606 ParticleSystemModifierData *psmd = reinterpret_cast<ParticleSystemModifierData *>(md);
608 }
609}
610
611void reset_particle_system_edit_eval(const Depsgraph *depsgraph, Object *object_cow)
612{
613 /* Inactive (and render) dependency graphs are living in their own little bubble, should not care
614 * about edit mode at all. */
615 if (!DEG_is_active(reinterpret_cast<const ::Depsgraph *>(depsgraph))) {
616 return;
617 }
618 LISTBASE_FOREACH (ParticleSystem *, psys, &object_cow->particlesystem) {
619 ParticleSystem *orig_psys = psys->orig_psys;
620 if (orig_psys->edit != nullptr) {
621 orig_psys->edit->psys_eval = nullptr;
622 orig_psys->edit->psmd_eval = nullptr;
623 }
624 }
625}
626
627void update_particles_after_copy(const Depsgraph *depsgraph,
628 const Object *object_orig,
629 Object *object_cow)
630{
631 update_particle_system_orig_pointers(object_orig, object_cow);
632 set_particle_system_modifiers_loaded(object_cow);
633 reset_particle_system_edit_eval(depsgraph, object_cow);
634}
635
636void update_pose_orig_pointers(const bPose *pose_orig, bPose *pose_cow)
637{
638 update_list_orig_pointers(&pose_orig->chanbase, &pose_cow->chanbase, &bPoseChannel::orig_pchan);
639}
640
641void update_nla_strips_orig_pointers(const ListBase *strips_orig, ListBase *strips_cow)
642{
643 NlaStrip *strip_orig = reinterpret_cast<NlaStrip *>(strips_orig->first);
644 NlaStrip *strip_cow = reinterpret_cast<NlaStrip *>(strips_cow->first);
645 while (strip_orig != nullptr) {
646 strip_cow->orig_strip = strip_orig;
647 update_nla_strips_orig_pointers(&strip_orig->strips, &strip_cow->strips);
648 strip_cow = strip_cow->next;
649 strip_orig = strip_orig->next;
650 }
651}
652
653void update_nla_tracks_orig_pointers(const ListBase *tracks_orig, ListBase *tracks_cow)
654{
655 NlaTrack *track_orig = reinterpret_cast<NlaTrack *>(tracks_orig->first);
656 NlaTrack *track_cow = reinterpret_cast<NlaTrack *>(tracks_cow->first);
657 while (track_orig != nullptr) {
658 update_nla_strips_orig_pointers(&track_orig->strips, &track_cow->strips);
659 track_cow = track_cow->next;
660 track_orig = track_orig->next;
661 }
662}
663
664void update_animation_data_after_copy(const ID *id_orig, ID *id_cow)
665{
666 const AnimData *anim_data_orig = BKE_animdata_from_id(const_cast<ID *>(id_orig));
667 if (anim_data_orig == nullptr) {
668 return;
669 }
670 AnimData *anim_data_cow = BKE_animdata_from_id(id_cow);
671 BLI_assert(anim_data_cow != nullptr);
672 update_nla_tracks_orig_pointers(&anim_data_orig->nla_tracks, &anim_data_cow->nla_tracks);
673}
674
675/* Do some special treatment of data transfer from original ID to its
676 * evaluated complementary part.
677 *
678 * Only use for the newly created evaluated data-blocks. */
679void update_id_after_copy(const Depsgraph *depsgraph,
680 const IDNode *id_node,
681 const ID *id_orig,
682 ID *id_cow)
683{
684 const ID_Type type = GS(id_orig->name);
685 update_animation_data_after_copy(id_orig, id_cow);
686 switch (type) {
687 case ID_OB: {
688 /* Ensure we don't drag someone's else derived mesh to the
689 * new copy of the object. */
690 Object *object_cow = (Object *)id_cow;
691 const Object *object_orig = (const Object *)id_orig;
692 object_cow->mode = object_orig->mode;
693 object_cow->sculpt = object_orig->sculpt;
694 object_cow->runtime->data_orig = (ID *)object_cow->data;
695 if (object_cow->type == OB_ARMATURE) {
696 const bArmature *armature_orig = (bArmature *)object_orig->data;
697 bArmature *armature_cow = (bArmature *)object_cow->data;
698 BKE_pose_remap_bone_pointers(armature_cow, object_cow->pose);
699 if (armature_orig->edbo == nullptr) {
700 update_pose_orig_pointers(object_orig->pose, object_cow->pose);
701 }
703 }
704 update_particles_after_copy(depsgraph, object_orig, object_cow);
705 break;
706 }
707 case ID_SCE: {
708 Scene *scene_cow = (Scene *)id_cow;
709 const Scene *scene_orig = (const Scene *)id_orig;
710 scene_cow->toolsettings = scene_orig->toolsettings;
711 scene_setup_view_layers_after_remap(depsgraph, id_node, reinterpret_cast<Scene *>(id_cow));
712 break;
713 }
714 default:
715 break;
716 }
717 update_edit_mode_pointers(depsgraph, id_orig, id_cow);
719}
720
721/* This callback is used to validate that all nested ID data-blocks are
722 * properly expanded. */
723int foreach_libblock_validate_callback(LibraryIDLinkCallbackData *cb_data)
724{
725 ValidateData *data = (ValidateData *)cb_data->user_data;
726 ID **id_p = cb_data->id_pointer;
727
728 if (*id_p != nullptr) {
729 if (!check_datablock_expanded(*id_p)) {
730 data->is_valid = false;
731 /* TODO(sergey): Store which is not valid? */
732 }
733 }
734 return IDWALK_RET_NOP;
735}
736
737/* Actual implementation of logic which "expands" all the data which was not
738 * yet copied-on-eval.
739 *
740 * NOTE: Expects that evaluated datablock is empty. */
741ID *deg_expand_eval_copy_datablock(const Depsgraph *depsgraph, const IDNode *id_node)
742{
743 const ID *id_orig = id_node->id_orig;
744 ID *id_cow = id_node->id_cow;
745 const int id_cow_recalc = id_cow->recalc;
746
747 /* No need to expand such datablocks, their copied ID is same as original
748 * one already. */
749 if (!deg_eval_copy_is_needed(id_orig)) {
750 return id_cow;
751 }
752
754 "Expanding datablock for %s: id_orig=%p id_cow=%p\n", id_orig->name, id_orig, id_cow);
755
756 /* Sanity checks.
757 *
758 * At this point, `id_cow` is essentially considered as a (partially dirty) allocated buffer (it
759 * has been freed, but not fully cleared, as a result of calling #deg_free_eval_copy_datablock on
760 * it). It is not expected to have any valid sub-data, not even a valid `ID::runtime` pointer.
761 */
762 BLI_assert(check_datablock_expanded(id_cow) == false);
763 BLI_assert(id_cow->py_instance == nullptr);
764 BLI_assert(id_cow->runtime == nullptr);
765
766 /* Copy data from original ID to a copied version. */
767 /* TODO(sergey): Avoid doing full ID copy somehow, make Mesh to reference
768 * original geometry arrays for until those are modified. */
769 /* TODO(sergey): We do some trickery with temp bmain and extra ID pointer
770 * just to be able to use existing API. Ideally we need to replace this with
771 * in-place copy from existing datablock to a prepared memory.
772 *
773 * NOTE: We don't use BKE_main_{new,free} because:
774 * - We don't want heap-allocations here.
775 * - We don't want bmain's content to be freed when main is freed. */
776 bool done = false;
777 /* First we handle special cases which are not covered by BKE_id_copy() yet.
778 * or cases where we want to do something smarter than simple datablock
779 * copy. */
780 const ID_Type id_type = GS(id_orig->name);
781 switch (id_type) {
782 case ID_SCE: {
783 done = scene_copy_inplace_no_main((Scene *)id_orig, (Scene *)id_cow);
784 if (done) {
785 /* NOTE: This is important to do before remap, because this
786 * function will make it so less IDs are to be remapped. */
787 scene_setup_view_layers_before_remap(depsgraph, id_node, (Scene *)id_cow);
788 }
789 break;
790 }
791 case ID_ME: {
792 /* TODO(sergey): Ideally we want to handle meshes in a special
793 * manner here to avoid initial copy of all the geometry arrays. */
794 break;
795 }
796 default:
797 break;
798 }
799 if (!done) {
800 done = id_copy_inplace_no_main(id_orig, id_cow);
801 }
802 if (!done) {
803 BLI_assert_msg(0, "No idea how to perform evaluated copy on datablock");
804 }
805 /* Update pointers to nested ID datablocks. */
807 " Remapping ID links for %s: id_orig=%p id_cow=%p\n", id_orig->name, id_orig, id_cow);
808
809#ifdef NESTED_ID_NASTY_WORKAROUND
810 ntree_hack_remap_pointers(depsgraph, id_cow);
811#endif
812 /* Do it now, so remapping will understand that possibly remapped self ID
813 * is not to be remapped again. */
814 deg_tag_eval_copy_id(const_cast<Depsgraph &>(*depsgraph), id_cow, id_orig);
815 /* Perform remapping of the nodes. */
816 RemapCallbackUserData user_data = {nullptr};
817 user_data.depsgraph = depsgraph;
818 /* About IDWALK flags:
819 * - #IDWALK_IGNORE_EMBEDDED_ID: In depsgraph embedded IDs are handled (mostly) as regular IDs,
820 * and processed on their own, not as part of their owner ID (the owner ID's pointer to its
821 * embedded data is set to null before actual copying, in #id_copy_inplace_no_main).
822 * - #IDWALK_IGNORE_MISSING_OWNER_ID is necessary for the same reason: when directly processing
823 * an embedded ID here, its owner is unknown, and its internal owner ID pointer is not yet
824 * remapped, so it is currently 'invalid'. */
826 id_cow,
828 (void *)&user_data,
830 /* Correct or tweak some pointers which are not taken care by foreach
831 * from above. */
832 update_id_after_copy(depsgraph, id_node, id_orig, id_cow);
833 id_cow->recalc = id_cow_recalc;
834 return id_cow;
835}
836
837} // namespace
838
840{
841 const ID *id_orig = id_node->id_orig;
842 ID *id_cow = id_node->id_cow;
843 /* Similar to expansion, no need to do anything here. */
844 if (!deg_eval_copy_is_needed(id_orig)) {
845 return id_cow;
846 }
847
848 /* When updating object data in edit-mode, don't request copy-on-eval update since this will
849 * duplicate all object data which is unnecessary when the edit-mode data is used for calculating
850 * modifiers.
851 *
852 * TODO: Investigate modes besides edit-mode. */
853 if (check_datablock_expanded(id_cow) && !id_node->is_cow_explicitly_tagged) {
854 const ID_Type id_type = GS(id_orig->name);
855 /* Pass nullptr as the object is only needed for Curves which do not have edit mode pointers.
856 */
857 if (OB_DATA_SUPPORT_EDITMODE(id_type) && BKE_object_data_is_in_editmode(nullptr, id_orig)) {
858 /* Make sure pointers in the edit mode data are updated in the copy.
859 * This allows depsgraph to pick up changes made in another context after it has been
860 * evaluated. Consider the following scenario:
861 *
862 * - ObjectA in SceneA is using Mesh.
863 * - ObjectB in SceneB is using Mesh (same exact datablock).
864 * - Depsgraph of SceneA is evaluated.
865 * - Depsgraph of SceneB is evaluated.
866 * - User enters edit mode of ObjectA in SceneA. */
867 update_edit_mode_pointers(depsgraph, id_orig, id_cow);
868 return id_cow;
869 }
870 }
871
872 RuntimeBackup backup(depsgraph);
873 backup.init_from_id(id_cow);
875 deg_expand_eval_copy_datablock(depsgraph, id_node);
876 backup.restore_to_id(id_cow);
877 return id_cow;
878}
879
881{
882 /* NOTE: Depsgraph is supposed to have ID node already. */
883
884 IDNode *id_node = depsgraph->find_id_node(id_orig);
885 BLI_assert(id_node != nullptr);
887}
888
889namespace {
890
891void discard_armature_edit_mode_pointers(ID *id_cow)
892{
893 bArmature *armature_cow = (bArmature *)id_cow;
894 armature_cow->edbo = nullptr;
895}
896
897void discard_curve_edit_mode_pointers(ID *id_cow)
898{
899 Curve *curve_cow = (Curve *)id_cow;
900 curve_cow->editnurb = nullptr;
901 curve_cow->editfont = nullptr;
902}
903
904void discard_mball_edit_mode_pointers(ID *id_cow)
905{
906 MetaBall *mball_cow = (MetaBall *)id_cow;
907 mball_cow->editelems = nullptr;
908}
909
910void discard_lattice_edit_mode_pointers(ID *id_cow)
911{
912 Lattice *lt_cow = (Lattice *)id_cow;
913 lt_cow->editlatt = nullptr;
914}
915
916void discard_mesh_edit_mode_pointers(ID *id_cow)
917{
918 Mesh *mesh_cow = (Mesh *)id_cow;
919 mesh_cow->runtime->edit_mesh = nullptr;
920}
921
922void discard_scene_pointers(ID *id_cow)
923{
924 Scene *scene_cow = (Scene *)id_cow;
925 scene_cow->toolsettings = nullptr;
926}
927
928/* nullptr-ify all edit mode pointers which points to data from
929 * original object. */
930void discard_edit_mode_pointers(ID *id_cow)
931{
932 const ID_Type type = GS(id_cow->name);
933 switch (type) {
934 case ID_AR:
935 discard_armature_edit_mode_pointers(id_cow);
936 break;
937 case ID_ME:
938 discard_mesh_edit_mode_pointers(id_cow);
939 break;
940 case ID_CU_LEGACY:
941 discard_curve_edit_mode_pointers(id_cow);
942 break;
943 case ID_MB:
944 discard_mball_edit_mode_pointers(id_cow);
945 break;
946 case ID_LT:
947 discard_lattice_edit_mode_pointers(id_cow);
948 break;
949 case ID_SCE:
950 /* Not really edit mode but still needs to run before
951 * BKE_libblock_free_datablock() */
952 discard_scene_pointers(id_cow);
953 break;
954 default:
955 break;
956 }
957}
958
959} // namespace
960
962{
963 /* Free content of the evaluated data-block.
964 * Notes:
965 * - Does not recurse into nested ID data-blocks.
966 * - Does not free data-block itself.
967 */
968
969 if (!check_datablock_expanded(id_cow)) {
970 /* Actual content was never copied on top of evaluated data-block, we have
971 * nothing to free. */
972 return;
973 }
974 const ID_Type type = GS(id_cow->name);
975#ifdef NESTED_ID_NASTY_WORKAROUND
976 nested_id_hack_discard_pointers(id_cow);
977#endif
978 switch (type) {
979 case ID_OB: {
980 /* TODO(sergey): This workaround is only to prevent free derived
981 * caches from modifying object->data. This is currently happening
982 * due to mesh/curve data-block bound-box tagging dirty. */
983 Object *ob_cow = (Object *)id_cow;
984 ob_cow->data = nullptr;
985 ob_cow->sculpt = nullptr;
986 break;
987 }
988 default:
989 break;
990 }
991 discard_edit_mode_pointers(id_cow);
994 BKE_libblock_free_data(id_cow, false);
995 /* Signal datablock as not being expanded. */
996 id_cow->name[0] = '\0';
997}
998
999void deg_create_eval_copy(::Depsgraph *graph, const IDNode *id_node)
1000{
1001 const Depsgraph *depsgraph = reinterpret_cast<const Depsgraph *>(graph);
1002 DEG_debug_print_eval(graph, __func__, id_node->id_orig->name, id_node->id_cow);
1003 if (id_node->id_orig == &depsgraph->scene->id) {
1004 /* NOTE: This is handled by eval_ctx setup routines, which
1005 * ensures scene and view layer pointers are valid. */
1006 return;
1007 }
1009}
1010
1012{
1013 if (id_cow == nullptr) {
1014 return false;
1015 }
1016 ValidateData data;
1017 data.is_valid = true;
1019 nullptr, id_cow, foreach_libblock_validate_callback, &data, IDWALK_NOP);
1020 return data.is_valid;
1021}
1022
1023void deg_tag_eval_copy_id(deg::Depsgraph &depsgraph, ID *id_cow, const ID *id_orig)
1024{
1025 BLI_assert(id_cow != id_orig);
1026 BLI_assert((id_orig->tag & ID_TAG_COPIED_ON_EVAL) == 0);
1027 id_cow->tag |= ID_TAG_COPIED_ON_EVAL;
1028 /* This ID is no longer localized, is a self-sustaining copy now. */
1029 id_cow->tag &= ~ID_TAG_LOCALIZED;
1030 id_cow->orig_id = (ID *)id_orig;
1031 id_cow->runtime->depsgraph = &reinterpret_cast<::Depsgraph &>(depsgraph);
1032}
1033
1035{
1036 return check_datablock_expanded(id_cow);
1037}
1038
1039bool deg_eval_copy_is_needed(const ID *id_orig)
1040{
1041 const ID_Type id_type = GS(id_orig->name);
1042 return deg_eval_copy_is_needed(id_type);
1043}
1044
1046{
1047 return ID_TYPE_USE_COPY_ON_EVAL(id_type);
1048}
1049
1050} // namespace blender::deg
AnimData * BKE_animdata_from_id(const ID *id)
Definition anim_data.cc:83
void BKE_animsys_update_driver_array(struct ID *id)
Definition anim_sys.cc:4172
void BKE_pose_pchan_index_rebuild(bPose *pose)
void BKE_pose_remap_bone_pointers(bArmature *armature, bPose *pose)
@ G_DEBUG_DEPSGRAPH_UID
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
void BKE_view_layer_free_object_content(ViewLayer *view_layer)
ViewLayer * BKE_view_layer_default_render(const Scene *scene)
ListBase * BKE_view_layer_object_bases_get(ViewLayer *view_layer)
void BKE_libblock_free_data_py(ID *id)
void BKE_libblock_free_datablock(ID *id, int flag) ATTR_NONNULL()
void BKE_libblock_free_data(ID *id, bool do_id_user) ATTR_NONNULL()
ID * BKE_id_copy_ex(Main *bmain, const ID *id, ID **new_id_p, int flag)
Definition lib_id.cc:777
@ LIB_ID_CREATE_NO_ALLOCATE
@ LIB_ID_COPY_SET_COPIED_ON_WRITE
@ LIB_ID_COPY_LOCALIZE
@ IDWALK_RET_NOP
void BKE_library_foreach_ID_link(Main *bmain, ID *id, blender::FunctionRef< LibraryIDLinkCallback > callback, void *user_data, LibraryForeachIDFlag flag)
Definition lib_query.cc:431
@ IDWALK_IGNORE_MISSING_OWNER_ID
@ IDWALK_NOP
@ IDWALK_IGNORE_EMBEDDED_ID
General operations, lookup, etc. for blender objects.
void BKE_object_check_uids_unique_and_report(const Object *object)
bool BKE_object_data_is_in_editmode(const Object *ob, const ID *id)
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
#define LISTBASE_FOREACH(type, var, list)
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:497
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
void BLI_listbase_swaplinks(ListBase *listbase, void *vlinka, void *vlinkb) ATTR_NONNULL(1
#define STREQ(a, b)
bool DEG_is_active(const Depsgraph *depsgraph)
Definition depsgraph.cc:323
void DEG_debug_print_eval(Depsgraph *depsgraph, const char *function_name, const char *object_name, const void *object_address)
ID and Library types, which are fundamental for SDNA.
@ ID_TAG_COPIED_ON_EVAL
Definition DNA_ID.h:997
@ ID_TAG_LOCALIZED
Definition DNA_ID.h:987
#define ID_TYPE_USE_COPY_ON_EVAL(_id_type)
Definition DNA_ID.h:740
struct ID ID
ID_Type
@ ID_AR
@ ID_TE
@ ID_LA
@ ID_SCE
@ ID_LS
@ ID_WO
@ ID_MA
@ ID_CU_LEGACY
@ ID_ME
@ ID_MB
@ ID_LT
@ ID_OB
struct Lattice Lattice
struct Mesh Mesh
struct MetaBall MetaBall
@ eParticleSystemFlag_file_loaded
@ eModifierType_ParticleSystem
Object is a sort of wrapper for general info.
@ OB_ARMATURE
#define OB_DATA_SUPPORT_EDITMODE(_type)
struct Scene Scene
Read Guarded memory(de)allocation.
BMesh const char void * data
BPy_StructRNA * depsgraph
#define SPECIAL_CASE(id_type, dna_type, field)
#define DEG_COW_PRINT(format,...)
#define GS(x)
static int foreach_libblock_remap_callback(LibraryIDLinkCallbackData *cb_data)
Definition lib_remap.cc:173
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
#define T
#define G(x, y, z)
void deg_tag_eval_copy_id(deg::Depsgraph &depsgraph, ID *id_cow, const ID *id_orig)
void deg_create_eval_copy(::Depsgraph *graph, const IDNode *id_node)
bool deg_check_base_in_depsgraph(const Depsgraph *graph, Base *base)
bool deg_eval_copy_is_expanded(const ID *id_cow)
void deg_free_eval_copy_datablock(ID *id_cow)
bool deg_eval_copy_is_needed(const ID *id_orig)
ID * deg_update_eval_copy_datablock(const Depsgraph *depsgraph, const IDNode *id_node)
bool deg_validate_eval_copy_datablock(ID *id_cow)
void relations_check_uids_unique_and_report(const Scene *scene)
ListBase nla_tracks
struct Base * next
struct Base * base_orig
struct EditFont * editfont
EditNurb * editnurb
Definition DNA_ID.h:414
unsigned int recalc
Definition DNA_ID.h:445
void * py_instance
Definition DNA_ID.h:518
int tag
Definition DNA_ID.h:442
ID_RuntimeHandle * runtime
Definition DNA_ID.h:538
char name[258]
Definition DNA_ID.h:432
struct ID * orig_id
Definition DNA_ID.h:501
struct EditLatt * editlatt
void * first
MeshRuntimeHandle * runtime
ListBase * editelems
struct NlaStrip * next
ListBase strips
struct NlaStrip * orig_strip
ListBase strips
struct NlaTrack * next
ListBase particlesystem
struct bPose * pose
ObjectRuntimeHandle * runtime
ListBase modifiers
struct SculptSession * sculpt
struct ParticleSystemModifierData * psmd_eval
struct ParticleSystem * psys_eval
struct PTCacheEdit * edit
struct ParticleSystem * orig_psys
struct ToolSettings * toolsettings
ListBase view_layers
struct Base * basact
ListBase object_bases
char name[64]
struct EditBone * act_edbone
ListBase * edbo
struct bPoseChannel * orig_pchan
ListBase chanbase