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