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