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
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_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;
103 FreestyleLineStyle linestyle;
104 Light lamp;
105 Lattice lattice;
106 Material material;
107 Mesh mesh;
108 Scene scene;
109 Tex tex;
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
171 SPECIAL_CASE(ID_LS, FreestyleLineStyle, nodetree, linestyle)
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)
178 SPECIAL_CASE(ID_LT, Lattice, key, lattice)
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 {
265 bool is_valid;
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{
337 if (id_node->linked_state == DEG_ID_LINKED_DIRECTLY) {
338 return depsgraph->view_layer;
339 }
340 if (id_node->linked_state == DEG_ID_LINKED_VIA_SET) {
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{
358 if (depsgraph->is_render_pipeline_depsgraph) {
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. */
465 if (depsgraph->is_render_pipeline_depsgraph) {
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
905 IDNode *id_node = depsgraph->find_id_node(id_orig);
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()
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
@ LIB_ID_CREATE_NO_ALLOCATE
@ LIB_ID_COPY_SET_COPIED_ON_WRITE
@ LIB_ID_COPY_LOCALIZE
@ IDWALK_IGNORE_MISSING_OWNER_ID
@ IDWALK_NOP
@ IDWALK_IGNORE_EMBEDDED_ID
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_RET_NOP
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
struct ID ID
@ ID_TAG_COPIED_ON_EVAL
Definition DNA_ID.h:964
@ ID_TAG_LOCALIZED
Definition DNA_ID.h:954
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
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)
Types and defines for representing Rigid Body entities.
struct Scene Scene
Read Guarded memory(de)allocation.
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between world
BPy_StructRNA * depsgraph
#define SPECIAL_CASE(id_type, dna_type, field)
#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 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 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
struct ToolSettings * toolsettings
ListBase view_layers
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