1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software Foundation,
14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 *
16 * The Original Code is Copyright (C) 2017 Blender Foundation.
17 * All rights reserved.
18 */
19
20 /** \file
21 * \ingroup depsgraph
22 */
23
24 /* Enable special trickery to treat nested owned IDs (such as nodetree of
25 * material) to be handled in same way as "real" data-blocks, even tho some
26 * internal BKE routines doesn't treat them like that.
27 *
28 * TODO(sergey): Re-evaluate that after new ID handling is in place. */
29 #define NESTED_ID_NASTY_WORKAROUND
30
31 /* Silence warnings from copying deprecated fields. */
32 #define DNA_DEPRECATED_ALLOW
33
34 #include "intern/eval/deg_eval_copy_on_write.h"
35
36 #include <cstring>
37
38 #include "BLI_listbase.h"
39 #include "BLI_string.h"
40 #include "BLI_threads.h"
41 #include "BLI_utildefines.h"
42
43 #include "BKE_curve.h"
44 #include "BKE_global.h"
45 #include "BKE_gpencil.h"
46 #include "BKE_idprop.h"
47 #include "BKE_layer.h"
48 #include "BKE_lib_id.h"
49 #include "BKE_scene.h"
50
51 #include "DEG_depsgraph.h"
52 #include "DEG_depsgraph_query.h"
53
54 #include "MEM_guardedalloc.h"
55
56 #include "DNA_ID.h"
57 #include "DNA_anim_types.h"
58 #include "DNA_armature_types.h"
59 #include "DNA_mesh_types.h"
60 #include "DNA_modifier_types.h"
61 #include "DNA_object_types.h"
62 #include "DNA_particle_types.h"
63 #include "DNA_rigidbody_types.h"
64 #include "DNA_scene_types.h"
65 #include "DNA_sequence_types.h"
66 #include "DNA_simulation_types.h"
67 #include "DNA_sound_types.h"
68
69 #include "DRW_engine.h"
70
71 #ifdef NESTED_ID_NASTY_WORKAROUND
72 # include "DNA_curve_types.h"
73 # include "DNA_key_types.h"
74 # include "DNA_lattice_types.h"
75 # include "DNA_light_types.h"
76 # include "DNA_linestyle_types.h"
77 # include "DNA_material_types.h"
78 # include "DNA_meta_types.h"
79 # include "DNA_node_types.h"
80 # include "DNA_texture_types.h"
81 # include "DNA_world_types.h"
82 #endif
83
84 #include "BKE_action.h"
85 #include "BKE_anim_data.h"
86 #include "BKE_animsys.h"
87 #include "BKE_armature.h"
88 #include "BKE_editmesh.h"
89 #include "BKE_lib_query.h"
90 #include "BKE_modifier.h"
91 #include "BKE_object.h"
92 #include "BKE_pointcache.h"
93 #include "BKE_sequencer.h"
94 #include "BKE_sound.h"
95
96 #include "intern/builder/deg_builder.h"
97 #include "intern/builder/deg_builder_nodes.h"
98 #include "intern/depsgraph.h"
99 #include "intern/eval/deg_eval_runtime_backup.h"
100 #include "intern/node/deg_node.h"
101 #include "intern/node/deg_node_id.h"
102
103 namespace blender {
104 namespace deg {
105
106 #define DEBUG_PRINT \
107 if (G.debug & G_DEBUG_DEPSGRAPH_EVAL) \
108 printf
109
110 namespace {
111
112 #ifdef NESTED_ID_NASTY_WORKAROUND
113 union NestedIDHackTempStorage {
114 Curve curve;
115 FreestyleLineStyle linestyle;
116 Light lamp;
117 Lattice lattice;
118 Material material;
119 Mesh mesh;
120 Scene scene;
121 Tex tex;
122 World world;
123 Simulation simulation;
124 };
125
126 /* Set nested owned ID pointers to nullptr. */
nested_id_hack_discard_pointers(ID * id_cow)127 void nested_id_hack_discard_pointers(ID *id_cow)
128 {
129 switch (GS(id_cow->name)) {
130 # define SPECIAL_CASE(id_type, dna_type, field) \
131 case id_type: { \
132 ((dna_type *)id_cow)->field = nullptr; \
133 break; \
134 }
135
136 SPECIAL_CASE(ID_LS, FreestyleLineStyle, nodetree)
137 SPECIAL_CASE(ID_LA, Light, nodetree)
138 SPECIAL_CASE(ID_MA, Material, nodetree)
139 SPECIAL_CASE(ID_TE, Tex, nodetree)
140 SPECIAL_CASE(ID_WO, World, nodetree)
141 SPECIAL_CASE(ID_SIM, Simulation, nodetree)
142
143 SPECIAL_CASE(ID_CU, Curve, key)
144 SPECIAL_CASE(ID_LT, Lattice, key)
145 SPECIAL_CASE(ID_ME, Mesh, key)
146
147 case ID_SCE: {
148 Scene *scene_cow = (Scene *)id_cow;
149 /* Node trees always have their own ID node in the graph, and are
150 * being copied as part of their copy-on-write process. */
151 scene_cow->nodetree = nullptr;
152 /* Tool settings pointer is shared with the original scene. */
153 scene_cow->toolsettings = nullptr;
154 break;
155 }
156
157 case ID_OB: {
158 /* Clear the ParticleSettings pointer to prevent doubly-freeing it. */
159 Object *ob = (Object *)id_cow;
160 LISTBASE_FOREACH (ParticleSystem *, psys, &ob->particlesystem) {
161 psys->part = nullptr;
162 }
163 break;
164 }
165 # undef SPECIAL_CASE
166
167 default:
168 break;
169 }
170 }
171
172 /* Set ID pointer of nested owned IDs (nodetree, key) to nullptr.
173 *
174 * Return pointer to a new ID to be used. */
nested_id_hack_get_discarded_pointers(NestedIDHackTempStorage * storage,const ID * id)175 const ID *nested_id_hack_get_discarded_pointers(NestedIDHackTempStorage *storage, const ID *id)
176 {
177 switch (GS(id->name)) {
178 # define SPECIAL_CASE(id_type, dna_type, field, variable) \
179 case id_type: { \
180 storage->variable = *(dna_type *)id; \
181 storage->variable.field = nullptr; \
182 return &storage->variable.id; \
183 }
184
185 SPECIAL_CASE(ID_LS, FreestyleLineStyle, nodetree, linestyle)
186 SPECIAL_CASE(ID_LA, Light, nodetree, lamp)
187 SPECIAL_CASE(ID_MA, Material, nodetree, material)
188 SPECIAL_CASE(ID_TE, Tex, nodetree, tex)
189 SPECIAL_CASE(ID_WO, World, nodetree, world)
190 SPECIAL_CASE(ID_SIM, Simulation, nodetree, simulation)
191
192 SPECIAL_CASE(ID_CU, Curve, key, curve)
193 SPECIAL_CASE(ID_LT, Lattice, key, lattice)
194 SPECIAL_CASE(ID_ME, Mesh, key, mesh)
195
196 case ID_SCE: {
197 storage->scene = *(Scene *)id;
198 storage->scene.toolsettings = nullptr;
199 storage->scene.nodetree = nullptr;
200 return &storage->scene.id;
201 }
202
203 # undef SPECIAL_CASE
204
205 default:
206 break;
207 }
208 return id;
209 }
210
211 /* Set ID pointer of nested owned IDs (nodetree, key) to the original value. */
nested_id_hack_restore_pointers(const ID * old_id,ID * new_id)212 void nested_id_hack_restore_pointers(const ID *old_id, ID *new_id)
213 {
214 if (new_id == nullptr) {
215 return;
216 }
217 switch (GS(old_id->name)) {
218 # define SPECIAL_CASE(id_type, dna_type, field) \
219 case id_type: { \
220 ((dna_type *)(new_id))->field = ((dna_type *)(old_id))->field; \
221 break; \
222 }
223
224 SPECIAL_CASE(ID_LS, FreestyleLineStyle, nodetree)
225 SPECIAL_CASE(ID_LA, Light, nodetree)
226 SPECIAL_CASE(ID_MA, Material, nodetree)
227 SPECIAL_CASE(ID_SCE, Scene, nodetree)
228 SPECIAL_CASE(ID_TE, Tex, nodetree)
229 SPECIAL_CASE(ID_WO, World, nodetree)
230 SPECIAL_CASE(ID_SIM, Simulation, nodetree)
231
232 SPECIAL_CASE(ID_CU, Curve, key)
233 SPECIAL_CASE(ID_LT, Lattice, key)
234 SPECIAL_CASE(ID_ME, Mesh, key)
235
236 # undef SPECIAL_CASE
237 default:
238 break;
239 }
240 }
241
242 /* Remap pointer of nested owned IDs (nodetree. key) to the new ID values. */
ntree_hack_remap_pointers(const Depsgraph * depsgraph,ID * id_cow)243 void ntree_hack_remap_pointers(const Depsgraph *depsgraph, ID *id_cow)
244 {
245 switch (GS(id_cow->name)) {
246 # define SPECIAL_CASE(id_type, dna_type, field, field_type) \
247 case id_type: { \
248 dna_type *data = (dna_type *)id_cow; \
249 if (data->field != nullptr) { \
250 ID *ntree_id_cow = depsgraph->get_cow_id(&data->field->id); \
251 if (ntree_id_cow != nullptr) { \
252 DEG_COW_PRINT(" Remapping datablock for %s: id_orig=%p id_cow=%p\n", \
253 data->field->id.name, \
254 data->field, \
255 ntree_id_cow); \
256 data->field = (field_type *)ntree_id_cow; \
257 } \
258 } \
259 break; \
260 }
261
262 SPECIAL_CASE(ID_LS, FreestyleLineStyle, nodetree, bNodeTree)
263 SPECIAL_CASE(ID_LA, Light, nodetree, bNodeTree)
264 SPECIAL_CASE(ID_MA, Material, nodetree, bNodeTree)
265 SPECIAL_CASE(ID_SCE, Scene, nodetree, bNodeTree)
266 SPECIAL_CASE(ID_TE, Tex, nodetree, bNodeTree)
267 SPECIAL_CASE(ID_WO, World, nodetree, bNodeTree)
268 SPECIAL_CASE(ID_SIM, Simulation, nodetree, bNodeTree)
269
270 SPECIAL_CASE(ID_CU, Curve, key, Key)
271 SPECIAL_CASE(ID_LT, Lattice, key, Key)
272 SPECIAL_CASE(ID_ME, Mesh, key, Key)
273
274 # undef SPECIAL_CASE
275 default:
276 break;
277 }
278 }
279 #endif /* NODETREE_NASTY_WORKAROUND */
280
281 struct ValidateData {
282 bool is_valid;
283 };
284
285 /* Similar to generic BKE_id_copy() but does not require main and assumes pointer
286 * is already allocated. */
id_copy_inplace_no_main(const ID * id,ID * newid)287 bool id_copy_inplace_no_main(const ID *id, ID *newid)
288 {
289 const ID *id_for_copy = id;
290
291 if (G.debug & G_DEBUG_DEPSGRAPH_UUID) {
292 const ID_Type id_type = GS(id_for_copy->name);
293 if (id_type == ID_OB) {
294 const Object *object = reinterpret_cast<const Object *>(id_for_copy);
295 BKE_object_check_uuids_unique_and_report(object);
296 }
297 }
298
299 #ifdef NESTED_ID_NASTY_WORKAROUND
300 NestedIDHackTempStorage id_hack_storage;
301 id_for_copy = nested_id_hack_get_discarded_pointers(&id_hack_storage, id);
302 #endif
303
304 bool result = (BKE_id_copy_ex(nullptr,
305 (ID *)id_for_copy,
306 &newid,
307 LIB_ID_COPY_LOCALIZE | LIB_ID_CREATE_NO_ALLOCATE) != NULL);
308
309 #ifdef NESTED_ID_NASTY_WORKAROUND
310 if (result) {
311 nested_id_hack_restore_pointers(id, newid);
312 }
313 #endif
314
315 return result;
316 }
317
318 /* Similar to BKE_scene_copy() but does not require main and assumes pointer
319 * is already allocated. */
scene_copy_inplace_no_main(const Scene * scene,Scene * new_scene)320 bool scene_copy_inplace_no_main(const Scene *scene, Scene *new_scene)
321 {
322 const ID *id_for_copy = &scene->id;
323
324 if (G.debug & G_DEBUG_DEPSGRAPH_UUID) {
325 BKE_sequencer_check_uuids_unique_and_report(scene);
326 }
327
328 #ifdef NESTED_ID_NASTY_WORKAROUND
329 NestedIDHackTempStorage id_hack_storage;
330 id_for_copy = nested_id_hack_get_discarded_pointers(&id_hack_storage, &scene->id);
331 #endif
332
333 bool result = (BKE_id_copy_ex(nullptr,
334 id_for_copy,
335 (ID **)&new_scene,
336 LIB_ID_COPY_LOCALIZE | LIB_ID_CREATE_NO_ALLOCATE) != NULL);
337
338 #ifdef NESTED_ID_NASTY_WORKAROUND
339 if (result) {
340 nested_id_hack_restore_pointers(&scene->id, &new_scene->id);
341 }
342 #endif
343
344 return result;
345 }
346
347 /* For the given scene get view layer which corresponds to an original for the
348 * scene's evaluated one. This depends on how the scene is pulled into the
349 * dependency graph. */
get_original_view_layer(const Depsgraph * depsgraph,const IDNode * id_node)350 ViewLayer *get_original_view_layer(const Depsgraph *depsgraph, const IDNode *id_node)
351 {
352 if (id_node->linked_state == DEG_ID_LINKED_DIRECTLY) {
353 return depsgraph->view_layer;
354 }
355 if (id_node->linked_state == DEG_ID_LINKED_VIA_SET) {
356 Scene *scene_orig = reinterpret_cast<Scene *>(id_node->id_orig);
357 return BKE_view_layer_default_render(scene_orig);
358 }
359 /* Is possible to have scene linked indirectly (i.e. via the driver) which
360 * we need to support. Currently there are issues somewhere else, which
361 * makes testing hard. This is a reported problem, so will eventually be
362 * properly fixed.
363 *
364 * TODO(sergey): Support indirectly linked scene. */
365 return nullptr;
366 }
367
368 /* Remove all view layers but the one which corresponds to an input one. */
scene_remove_unused_view_layers(const Depsgraph * depsgraph,const IDNode * id_node,Scene * scene_cow)369 void scene_remove_unused_view_layers(const Depsgraph *depsgraph,
370 const IDNode *id_node,
371 Scene *scene_cow)
372 {
373 const ViewLayer *view_layer_input;
374 if (depsgraph->is_render_pipeline_depsgraph) {
375 /* If the dependency graph is used for post-processing (such as compositor) we do need to
376 * have access to its view layer names so can not remove any view layers.
377 * On a more positive side we can remove all the bases from all the view layers.
378 *
379 * NOTE: Need to clear pointers which might be pointing to original on freed (due to being
380 * unused) data.
381 *
382 * NOTE: Need to keep view layers for all scenes, even indirect ones. This is because of
383 * render layer node possibly pointing to another scene. */
384 LISTBASE_FOREACH (ViewLayer *, view_layer, &scene_cow->view_layers) {
385 view_layer->basact = nullptr;
386 }
387 return;
388 }
389 if (id_node->linked_state == DEG_ID_LINKED_INDIRECTLY) {
390 /* Indirectly linked scenes means it's not an input scene and not a set scene, and is pulled
391 * via some driver. Such scenes should not have view layers after copy. */
392 view_layer_input = nullptr;
393 }
394 else {
395 view_layer_input = get_original_view_layer(depsgraph, id_node);
396 }
397 ViewLayer *view_layer_eval = nullptr;
398 /* Find evaluated view layer. At the same time we free memory used by
399 * all other of the view layers. */
400 for (ViewLayer *view_layer_cow = reinterpret_cast<ViewLayer *>(scene_cow->view_layers.first),
401 *view_layer_next;
402 view_layer_cow != nullptr;
403 view_layer_cow = view_layer_next) {
404 view_layer_next = view_layer_cow->next;
405 if (view_layer_input != nullptr && STREQ(view_layer_input->name, view_layer_cow->name)) {
406 view_layer_eval = view_layer_cow;
407 }
408 else {
409 BKE_view_layer_free_ex(view_layer_cow, false);
410 }
411 }
412 /* Make evaluated view layer the only one in the evaluated scene (if it exists). */
413 if (view_layer_eval != nullptr) {
414 view_layer_eval->prev = view_layer_eval->next = nullptr;
415 }
416 scene_cow->view_layers.first = view_layer_eval;
417 scene_cow->view_layers.last = view_layer_eval;
418 }
419
scene_remove_all_bases(Scene * scene_cow)420 void scene_remove_all_bases(Scene *scene_cow)
421 {
422 LISTBASE_FOREACH (ViewLayer *, view_layer, &scene_cow->view_layers) {
423 BLI_freelistN(&view_layer->object_bases);
424 }
425 }
426
427 /* Makes it so given view layer only has bases corresponding to enabled
428 * objects. */
view_layer_remove_disabled_bases(const Depsgraph * depsgraph,ViewLayer * view_layer)429 void view_layer_remove_disabled_bases(const Depsgraph *depsgraph, ViewLayer *view_layer)
430 {
431 if (view_layer == nullptr) {
432 return;
433 }
434 ListBase enabled_bases = {nullptr, nullptr};
435 LISTBASE_FOREACH_MUTABLE (Base *, base, &view_layer->object_bases) {
436 /* TODO(sergey): Would be cool to optimize this somehow, or make it so
437 * builder tags bases.
438 *
439 * NOTE: The idea of using id's tag and check whether its copied ot not
440 * is not reliable, since object might be indirectly linked into the
441 * graph.
442 *
443 * NOTE: We are using original base since the object which evaluated base
444 * points to is not yet copied. This is dangerous access from evaluated
445 * domain to original one, but this is how the entire copy-on-write works:
446 * it does need to access original for an initial copy. */
447 const bool is_object_enabled = deg_check_base_in_depsgraph(depsgraph, base);
448 if (is_object_enabled) {
449 BLI_addtail(&enabled_bases, base);
450 }
451 else {
452 if (base == view_layer->basact) {
453 view_layer->basact = nullptr;
454 }
455 MEM_freeN(base);
456 }
457 }
458 view_layer->object_bases = enabled_bases;
459 }
460
view_layer_update_orig_base_pointers(const ViewLayer * view_layer_orig,ViewLayer * view_layer_eval)461 void view_layer_update_orig_base_pointers(const ViewLayer *view_layer_orig,
462 ViewLayer *view_layer_eval)
463 {
464 if (view_layer_orig == nullptr || view_layer_eval == nullptr) {
465 /* Happens when scene is only used for parameters or compositor/sequencer. */
466 return;
467 }
468 Base *base_orig = reinterpret_cast<Base *>(view_layer_orig->object_bases.first);
469 LISTBASE_FOREACH (Base *, base_eval, &view_layer_eval->object_bases) {
470 base_eval->base_orig = base_orig;
471 base_orig = base_orig->next;
472 }
473 }
474
scene_setup_view_layers_before_remap(const Depsgraph * depsgraph,const IDNode * id_node,Scene * scene_cow)475 void scene_setup_view_layers_before_remap(const Depsgraph *depsgraph,
476 const IDNode *id_node,
477 Scene *scene_cow)
478 {
479 scene_remove_unused_view_layers(depsgraph, id_node, scene_cow);
480 /* If dependency graph is used for post-processing we don't need any bases and can free of them.
481 * Do it before re-mapping to make that process faster. */
482 if (depsgraph->is_render_pipeline_depsgraph) {
483 scene_remove_all_bases(scene_cow);
484 }
485 }
486
scene_setup_view_layers_after_remap(const Depsgraph * depsgraph,const IDNode * id_node,Scene * scene_cow)487 void scene_setup_view_layers_after_remap(const Depsgraph *depsgraph,
488 const IDNode *id_node,
489 Scene *scene_cow)
490 {
491 const ViewLayer *view_layer_orig = get_original_view_layer(depsgraph, id_node);
492 ViewLayer *view_layer_eval = reinterpret_cast<ViewLayer *>(scene_cow->view_layers.first);
493 view_layer_update_orig_base_pointers(view_layer_orig, view_layer_eval);
494 view_layer_remove_disabled_bases(depsgraph, view_layer_eval);
495 /* TODO(sergey): Remove objects from collections as well.
496 * Not a HUGE deal for now, nobody is looking into those CURRENTLY.
497 * Still not an excuse to have those. */
498 }
499
500 /* Check whether given ID is expanded or still a shallow copy. */
check_datablock_expanded(const ID * id_cow)501 inline bool check_datablock_expanded(const ID *id_cow)
502 {
503 return (id_cow->name[0] != '\0');
504 }
505
506 /* Callback for BKE_library_foreach_ID_link which remaps original ID pointer
507 * with the one created by CoW system. */
508
509 struct RemapCallbackUserData {
510 /* Dependency graph for which remapping is happening. */
511 const Depsgraph *depsgraph;
512 /* Create placeholder for ID nodes for cases when we need to remap original
513 * ID to it[s CoW version but we don't have required ID node yet.
514 *
515 * This happens when expansion happens a ta construction time. */
516 DepsgraphNodeBuilder *node_builder;
517 bool create_placeholders;
518 };
519
foreach_libblock_remap_callback(LibraryIDLinkCallbackData * cb_data)520 int foreach_libblock_remap_callback(LibraryIDLinkCallbackData *cb_data)
521 {
522 ID **id_p = cb_data->id_pointer;
523 if (*id_p == nullptr) {
524 return IDWALK_RET_NOP;
525 }
526
527 ID *id_self = cb_data->id_self;
528 RemapCallbackUserData *user_data = (RemapCallbackUserData *)cb_data->user_data;
529 const Depsgraph *depsgraph = user_data->depsgraph;
530 ID *id_orig = *id_p;
531 if (deg_copy_on_write_is_needed(id_orig)) {
532 ID *id_cow;
533 if (user_data->create_placeholders) {
534 /* Special workaround to stop creating temp datablocks for
535 * objects which are coming from scene's collection and which
536 * are never linked to any of layers.
537 *
538 * TODO(sergey): Ideally we need to tell ID looper to ignore
539 * those or at least make it more reliable check where the
540 * pointer is coming from. */
541 const ID_Type id_type = GS(id_orig->name);
542 const ID_Type id_type_self = GS(id_self->name);
543 if (id_type == ID_OB && id_type_self == ID_SCE) {
544 IDNode *id_node = depsgraph->find_id_node(id_orig);
545 if (id_node == nullptr) {
546 id_cow = id_orig;
547 }
548 else {
549 id_cow = id_node->id_cow;
550 }
551 }
552 else {
553 id_cow = user_data->node_builder->ensure_cow_id(id_orig);
554 }
555 }
556 else {
557 id_cow = depsgraph->get_cow_id(id_orig);
558 }
559 BLI_assert(id_cow != nullptr);
560 DEG_COW_PRINT(
561 " Remapping datablock for %s: id_orig=%p id_cow=%p\n", id_orig->name, id_orig, id_cow);
562 *id_p = id_cow;
563 }
564 return IDWALK_RET_NOP;
565 }
566
update_armature_edit_mode_pointers(const Depsgraph *,const ID * id_orig,ID * id_cow)567 void update_armature_edit_mode_pointers(const Depsgraph * /*depsgraph*/,
568 const ID *id_orig,
569 ID *id_cow)
570 {
571 const bArmature *armature_orig = (const bArmature *)id_orig;
572 bArmature *armature_cow = (bArmature *)id_cow;
573 armature_cow->edbo = armature_orig->edbo;
574 armature_cow->act_edbone = armature_orig->act_edbone;
575 }
576
update_curve_edit_mode_pointers(const Depsgraph *,const ID * id_orig,ID * id_cow)577 void update_curve_edit_mode_pointers(const Depsgraph * /*depsgraph*/,
578 const ID *id_orig,
579 ID *id_cow)
580 {
581 const Curve *curve_orig = (const Curve *)id_orig;
582 Curve *curve_cow = (Curve *)id_cow;
583 curve_cow->editnurb = curve_orig->editnurb;
584 curve_cow->editfont = curve_orig->editfont;
585 }
586
update_mball_edit_mode_pointers(const Depsgraph *,const ID * id_orig,ID * id_cow)587 void update_mball_edit_mode_pointers(const Depsgraph * /*depsgraph*/,
588 const ID *id_orig,
589 ID *id_cow)
590 {
591 const MetaBall *mball_orig = (const MetaBall *)id_orig;
592 MetaBall *mball_cow = (MetaBall *)id_cow;
593 mball_cow->editelems = mball_orig->editelems;
594 }
595
update_lattice_edit_mode_pointers(const Depsgraph *,const ID * id_orig,ID * id_cow)596 void update_lattice_edit_mode_pointers(const Depsgraph * /*depsgraph*/,
597 const ID *id_orig,
598 ID *id_cow)
599 {
600 const Lattice *lt_orig = (const Lattice *)id_orig;
601 Lattice *lt_cow = (Lattice *)id_cow;
602 lt_cow->editlatt = lt_orig->editlatt;
603 }
604
update_mesh_edit_mode_pointers(const ID * id_orig,ID * id_cow)605 void update_mesh_edit_mode_pointers(const ID *id_orig, ID *id_cow)
606 {
607 /* For meshes we need to update edit_mesh to make it to point
608 * to the CoW version of object.
609 *
610 * This is kind of confusing, because actual bmesh is not owned by
611 * the CoW object, so need to be accurate about using link from
612 * edit_mesh to object. */
613 const Mesh *mesh_orig = (const Mesh *)id_orig;
614 Mesh *mesh_cow = (Mesh *)id_cow;
615 if (mesh_orig->edit_mesh == nullptr) {
616 return;
617 }
618 mesh_cow->edit_mesh = (BMEditMesh *)MEM_dupallocN(mesh_orig->edit_mesh);
619 mesh_cow->edit_mesh->mesh_eval_cage = nullptr;
620 mesh_cow->edit_mesh->mesh_eval_final = nullptr;
621 }
622
623 /* Edit data is stored and owned by original datablocks, copied ones
624 * are simply referencing to them. */
update_edit_mode_pointers(const Depsgraph * depsgraph,const ID * id_orig,ID * id_cow)625 void update_edit_mode_pointers(const Depsgraph *depsgraph, const ID *id_orig, ID *id_cow)
626 {
627 const ID_Type type = GS(id_orig->name);
628 switch (type) {
629 case ID_AR:
630 update_armature_edit_mode_pointers(depsgraph, id_orig, id_cow);
631 break;
632 case ID_ME:
633 update_mesh_edit_mode_pointers(id_orig, id_cow);
634 break;
635 case ID_CU:
636 update_curve_edit_mode_pointers(depsgraph, id_orig, id_cow);
637 break;
638 case ID_MB:
639 update_mball_edit_mode_pointers(depsgraph, id_orig, id_cow);
640 break;
641 case ID_LT:
642 update_lattice_edit_mode_pointers(depsgraph, id_orig, id_cow);
643 break;
644 default:
645 break;
646 }
647 }
648
649 template<typename T>
update_list_orig_pointers(const ListBase * listbase_orig,ListBase * listbase,T * T::* orig_field)650 void update_list_orig_pointers(const ListBase *listbase_orig,
651 ListBase *listbase,
652 T *T::*orig_field)
653 {
654 T *element_orig = reinterpret_cast<T *>(listbase_orig->first);
655 T *element_cow = reinterpret_cast<T *>(listbase->first);
656 while (element_orig != nullptr) {
657 element_cow->*orig_field = element_orig;
658 element_cow = element_cow->next;
659 element_orig = element_orig->next;
660 }
661 }
662
update_particle_system_orig_pointers(const Object * object_orig,Object * object_cow)663 void update_particle_system_orig_pointers(const Object *object_orig, Object *object_cow)
664 {
665 update_list_orig_pointers(
666 &object_orig->particlesystem, &object_cow->particlesystem, &ParticleSystem::orig_psys);
667 }
668
set_particle_system_modifiers_loaded(Object * object_cow)669 void set_particle_system_modifiers_loaded(Object *object_cow)
670 {
671 LISTBASE_FOREACH (ModifierData *, md, &object_cow->modifiers) {
672 if (md->type != eModifierType_ParticleSystem) {
673 continue;
674 }
675 ParticleSystemModifierData *psmd = reinterpret_cast<ParticleSystemModifierData *>(md);
676 psmd->flag |= eParticleSystemFlag_file_loaded;
677 }
678 }
679
reset_particle_system_edit_eval(const Depsgraph * depsgraph,Object * object_cow)680 void reset_particle_system_edit_eval(const Depsgraph *depsgraph, Object *object_cow)
681 {
682 /* Inactive (and render) dependency graphs are living in own little bubble, should not care about
683 * edit mode at all. */
684 if (!DEG_is_active(reinterpret_cast<const ::Depsgraph *>(depsgraph))) {
685 return;
686 }
687 LISTBASE_FOREACH (ParticleSystem *, psys, &object_cow->particlesystem) {
688 ParticleSystem *orig_psys = psys->orig_psys;
689 if (orig_psys->edit != nullptr) {
690 orig_psys->edit->psys_eval = nullptr;
691 orig_psys->edit->psmd_eval = nullptr;
692 }
693 }
694 }
695
update_particles_after_copy(const Depsgraph * depsgraph,const Object * object_orig,Object * object_cow)696 void update_particles_after_copy(const Depsgraph *depsgraph,
697 const Object *object_orig,
698 Object *object_cow)
699 {
700 update_particle_system_orig_pointers(object_orig, object_cow);
701 set_particle_system_modifiers_loaded(object_cow);
702 reset_particle_system_edit_eval(depsgraph, object_cow);
703 }
704
update_pose_orig_pointers(const bPose * pose_orig,bPose * pose_cow)705 void update_pose_orig_pointers(const bPose *pose_orig, bPose *pose_cow)
706 {
707 update_list_orig_pointers(&pose_orig->chanbase, &pose_cow->chanbase, &bPoseChannel::orig_pchan);
708 }
709
update_modifiers_orig_pointers(const Object * object_orig,Object * object_cow)710 void update_modifiers_orig_pointers(const Object *object_orig, Object *object_cow)
711 {
712 update_list_orig_pointers(
713 &object_orig->modifiers, &object_cow->modifiers, &ModifierData::orig_modifier_data);
714 }
715
update_nla_strips_orig_pointers(const ListBase * strips_orig,ListBase * strips_cow)716 void update_nla_strips_orig_pointers(const ListBase *strips_orig, ListBase *strips_cow)
717 {
718 NlaStrip *strip_orig = reinterpret_cast<NlaStrip *>(strips_orig->first);
719 NlaStrip *strip_cow = reinterpret_cast<NlaStrip *>(strips_cow->first);
720 while (strip_orig != nullptr) {
721 strip_cow->orig_strip = strip_orig;
722 update_nla_strips_orig_pointers(&strip_orig->strips, &strip_cow->strips);
723 strip_cow = strip_cow->next;
724 strip_orig = strip_orig->next;
725 }
726 }
727
update_nla_tracks_orig_pointers(const ListBase * tracks_orig,ListBase * tracks_cow)728 void update_nla_tracks_orig_pointers(const ListBase *tracks_orig, ListBase *tracks_cow)
729 {
730 NlaTrack *track_orig = reinterpret_cast<NlaTrack *>(tracks_orig->first);
731 NlaTrack *track_cow = reinterpret_cast<NlaTrack *>(tracks_cow->first);
732 while (track_orig != nullptr) {
733 update_nla_strips_orig_pointers(&track_orig->strips, &track_cow->strips);
734 track_cow = track_cow->next;
735 track_orig = track_orig->next;
736 }
737 }
738
update_animation_data_after_copy(const ID * id_orig,ID * id_cow)739 void update_animation_data_after_copy(const ID *id_orig, ID *id_cow)
740 {
741 const AnimData *anim_data_orig = BKE_animdata_from_id(const_cast<ID *>(id_orig));
742 if (anim_data_orig == nullptr) {
743 return;
744 }
745 AnimData *anim_data_cow = BKE_animdata_from_id(id_cow);
746 BLI_assert(anim_data_cow != nullptr);
747 update_nla_tracks_orig_pointers(&anim_data_orig->nla_tracks, &anim_data_cow->nla_tracks);
748 }
749
750 /* Some builders (like motion path one) will ignore proxies from being built. This code makes it so
751 * proxy and proxy_group pointers never point to an original objects, preventing evaluation code
752 * from assign evaluated pointer to an original proxy->proxy_from. */
update_proxy_pointers_after_copy(const Depsgraph * depsgraph,const Object * object_orig,Object * object_cow)753 void update_proxy_pointers_after_copy(const Depsgraph *depsgraph,
754 const Object *object_orig,
755 Object *object_cow)
756 {
757 if (object_cow->proxy != nullptr) {
758 if (!deg_check_id_in_depsgraph(depsgraph, &object_orig->proxy->id)) {
759 object_cow->proxy = nullptr;
760 }
761 }
762 if (object_cow->proxy_group != nullptr) {
763 if (!deg_check_id_in_depsgraph(depsgraph, &object_orig->proxy_group->id)) {
764 object_cow->proxy_group = nullptr;
765 }
766 }
767 }
768
769 /* Do some special treatment of data transfer from original ID to its
770 * CoW complementary part.
771 *
772 * Only use for the newly created CoW data-blocks. */
update_id_after_copy(const Depsgraph * depsgraph,const IDNode * id_node,const ID * id_orig,ID * id_cow)773 void update_id_after_copy(const Depsgraph *depsgraph,
774 const IDNode *id_node,
775 const ID *id_orig,
776 ID *id_cow)
777 {
778 const ID_Type type = GS(id_orig->name);
779 update_animation_data_after_copy(id_orig, id_cow);
780 switch (type) {
781 case ID_OB: {
782 /* Ensure we don't drag someone's else derived mesh to the
783 * new copy of the object. */
784 Object *object_cow = (Object *)id_cow;
785 const Object *object_orig = (const Object *)id_orig;
786 object_cow->mode = object_orig->mode;
787 object_cow->sculpt = object_orig->sculpt;
788 object_cow->runtime.data_orig = (ID *)object_cow->data;
789 if (object_cow->type == OB_ARMATURE) {
790 const bArmature *armature_orig = (bArmature *)object_orig->data;
791 bArmature *armature_cow = (bArmature *)object_cow->data;
792 BKE_pose_remap_bone_pointers(armature_cow, object_cow->pose);
793 if (armature_orig->edbo == nullptr) {
794 update_pose_orig_pointers(object_orig->pose, object_cow->pose);
795 }
796 BKE_pose_pchan_index_rebuild(object_cow->pose);
797 }
798 if (object_cow->type == OB_GPENCIL) {
799 BKE_gpencil_update_orig_pointers(object_orig, object_cow);
800 }
801 update_particles_after_copy(depsgraph, object_orig, object_cow);
802 update_modifiers_orig_pointers(object_orig, object_cow);
803 update_proxy_pointers_after_copy(depsgraph, object_orig, object_cow);
804 break;
805 }
806 case ID_SCE: {
807 Scene *scene_cow = (Scene *)id_cow;
808 const Scene *scene_orig = (const Scene *)id_orig;
809 scene_cow->toolsettings = scene_orig->toolsettings;
810 scene_cow->eevee.light_cache_data = scene_orig->eevee.light_cache_data;
811 scene_setup_view_layers_after_remap(depsgraph, id_node, reinterpret_cast<Scene *>(id_cow));
812 break;
813 }
814 default:
815 break;
816 }
817 update_edit_mode_pointers(depsgraph, id_orig, id_cow);
818 BKE_animsys_update_driver_array(id_cow);
819 }
820
821 /* This callback is used to validate that all nested ID data-blocks are
822 * properly expanded. */
foreach_libblock_validate_callback(LibraryIDLinkCallbackData * cb_data)823 int foreach_libblock_validate_callback(LibraryIDLinkCallbackData *cb_data)
824 {
825 ValidateData *data = (ValidateData *)cb_data->user_data;
826 ID **id_p = cb_data->id_pointer;
827
828 if (*id_p != nullptr) {
829 if (!check_datablock_expanded(*id_p)) {
830 data->is_valid = false;
831 /* TODO(sergey): Store which is not valid? */
832 }
833 }
834 return IDWALK_RET_NOP;
835 }
836
837 } // namespace
838
839 /* Actual implementation of logic which "expands" all the data which was not
840 * yet copied-on-write.
841 *
842 * NOTE: Expects that CoW datablock is empty. */
deg_expand_copy_on_write_datablock(const Depsgraph * depsgraph,const IDNode * id_node,DepsgraphNodeBuilder * node_builder,bool create_placeholders)843 ID *deg_expand_copy_on_write_datablock(const Depsgraph *depsgraph,
844 const IDNode *id_node,
845 DepsgraphNodeBuilder *node_builder,
846 bool create_placeholders)
847 {
848 const ID *id_orig = id_node->id_orig;
849 ID *id_cow = id_node->id_cow;
850 const int id_cow_recalc = id_cow->recalc;
851 /* No need to expand such datablocks, their copied ID is same as original
852 * one already. */
853 if (!deg_copy_on_write_is_needed(id_orig)) {
854 return id_cow;
855 }
856 DEG_COW_PRINT(
857 "Expanding datablock for %s: id_orig=%p id_cow=%p\n", id_orig->name, id_orig, id_cow);
858 /* Sanity checks. */
859 /* NOTE: Disabled for now, conflicts when re-using evaluated datablock when
860 * rebuilding dependencies. */
861 if (check_datablock_expanded(id_cow) && create_placeholders) {
862 deg_free_copy_on_write_datablock(id_cow);
863 }
864 // BLI_assert(check_datablock_expanded(id_cow) == false);
865 /* Copy data from original ID to a copied version. */
866 /* TODO(sergey): Avoid doing full ID copy somehow, make Mesh to reference
867 * original geometry arrays for until those are modified. */
868 /* TODO(sergey): We do some trickery with temp bmain and extra ID pointer
869 * just to be able to use existing API. Ideally we need to replace this with
870 * in-place copy from existing datablock to a prepared memory.
871 *
872 * NOTE: We don't use BKE_main_{new,free} because:
873 * - We don't want heap-allocations here.
874 * - We don't want bmain's content to be freed when main is freed. */
875 bool done = false;
876 /* First we handle special cases which are not covered by BKE_id_copy() yet.
877 * or cases where we want to do something smarter than simple datablock
878 * copy. */
879 const ID_Type id_type = GS(id_orig->name);
880 switch (id_type) {
881 case ID_SCE: {
882 done = scene_copy_inplace_no_main((Scene *)id_orig, (Scene *)id_cow);
883 if (done) {
884 /* NOTE: This is important to do before remap, because this
885 * function will make it so less IDs are to be remapped. */
886 scene_setup_view_layers_before_remap(depsgraph, id_node, (Scene *)id_cow);
887 }
888 break;
889 }
890 case ID_ME: {
891 /* TODO(sergey): Ideally we want to handle meshes in a special
892 * manner here to avoid initial copy of all the geometry arrays. */
893 break;
894 }
895 default:
896 break;
897 }
898 if (!done) {
899 done = id_copy_inplace_no_main(id_orig, id_cow);
900 }
901 if (!done) {
902 BLI_assert(!"No idea how to perform CoW on datablock");
903 }
904 /* Update pointers to nested ID datablocks. */
905 DEG_COW_PRINT(
906 " Remapping ID links for %s: id_orig=%p id_cow=%p\n", id_orig->name, id_orig, id_cow);
907
908 #ifdef NESTED_ID_NASTY_WORKAROUND
909 ntree_hack_remap_pointers(depsgraph, id_cow);
910 #endif
911 /* Do it now, so remapping will understand that possibly remapped self ID
912 * is not to be remapped again. */
913 deg_tag_copy_on_write_id(id_cow, id_orig);
914 /* Perform remapping of the nodes. */
915 RemapCallbackUserData user_data = {nullptr};
916 user_data.depsgraph = depsgraph;
917 user_data.node_builder = node_builder;
918 user_data.create_placeholders = create_placeholders;
919 BKE_library_foreach_ID_link(nullptr,
920 id_cow,
921 foreach_libblock_remap_callback,
922 (void *)&user_data,
923 IDWALK_IGNORE_EMBEDDED_ID);
924 /* Correct or tweak some pointers which are not taken care by foreach
925 * from above. */
926 update_id_after_copy(depsgraph, id_node, id_orig, id_cow);
927 id_cow->recalc = id_cow_recalc;
928 return id_cow;
929 }
930
931 /* NOTE: Depsgraph is supposed to have ID node already. */
deg_expand_copy_on_write_datablock(const Depsgraph * depsgraph,ID * id_orig,DepsgraphNodeBuilder * node_builder,bool create_placeholders)932 ID *deg_expand_copy_on_write_datablock(const Depsgraph *depsgraph,
933 ID *id_orig,
934 DepsgraphNodeBuilder *node_builder,
935 bool create_placeholders)
936 {
937 IDNode *id_node = depsgraph->find_id_node(id_orig);
938 BLI_assert(id_node != nullptr);
939 return deg_expand_copy_on_write_datablock(depsgraph, id_node, node_builder, create_placeholders);
940 }
941
deg_update_copy_on_write_datablock(const Depsgraph * depsgraph,const IDNode * id_node)942 ID *deg_update_copy_on_write_datablock(const Depsgraph *depsgraph, const IDNode *id_node)
943 {
944 const ID *id_orig = id_node->id_orig;
945 ID *id_cow = id_node->id_cow;
946 /* Similar to expansion, no need to do anything here. */
947 if (!deg_copy_on_write_is_needed(id_orig)) {
948 return id_cow;
949 }
950 RuntimeBackup backup(depsgraph);
951 backup.init_from_id(id_cow);
952 deg_free_copy_on_write_datablock(id_cow);
953 deg_expand_copy_on_write_datablock(depsgraph, id_node);
954 backup.restore_to_id(id_cow);
955 return id_cow;
956 }
957
958 /* NOTE: Depsgraph is supposed to have ID node already. */
deg_update_copy_on_write_datablock(const Depsgraph * depsgraph,ID * id_orig)959 ID *deg_update_copy_on_write_datablock(const Depsgraph *depsgraph, ID *id_orig)
960 {
961 IDNode *id_node = depsgraph->find_id_node(id_orig);
962 BLI_assert(id_node != nullptr);
963 return deg_update_copy_on_write_datablock(depsgraph, id_node);
964 }
965
966 namespace {
967
discard_armature_edit_mode_pointers(ID * id_cow)968 void discard_armature_edit_mode_pointers(ID *id_cow)
969 {
970 bArmature *armature_cow = (bArmature *)id_cow;
971 armature_cow->edbo = nullptr;
972 }
973
discard_curve_edit_mode_pointers(ID * id_cow)974 void discard_curve_edit_mode_pointers(ID *id_cow)
975 {
976 Curve *curve_cow = (Curve *)id_cow;
977 curve_cow->editnurb = nullptr;
978 curve_cow->editfont = nullptr;
979 }
980
discard_mball_edit_mode_pointers(ID * id_cow)981 void discard_mball_edit_mode_pointers(ID *id_cow)
982 {
983 MetaBall *mball_cow = (MetaBall *)id_cow;
984 mball_cow->editelems = nullptr;
985 }
986
discard_lattice_edit_mode_pointers(ID * id_cow)987 void discard_lattice_edit_mode_pointers(ID *id_cow)
988 {
989 Lattice *lt_cow = (Lattice *)id_cow;
990 lt_cow->editlatt = nullptr;
991 }
992
discard_mesh_edit_mode_pointers(ID * id_cow)993 void discard_mesh_edit_mode_pointers(ID *id_cow)
994 {
995 Mesh *mesh_cow = (Mesh *)id_cow;
996 if (mesh_cow->edit_mesh == nullptr) {
997 return;
998 }
999 BKE_editmesh_free_derivedmesh(mesh_cow->edit_mesh);
1000 MEM_freeN(mesh_cow->edit_mesh);
1001 mesh_cow->edit_mesh = nullptr;
1002 }
1003
discard_scene_pointers(ID * id_cow)1004 void discard_scene_pointers(ID *id_cow)
1005 {
1006 Scene *scene_cow = (Scene *)id_cow;
1007 scene_cow->toolsettings = nullptr;
1008 scene_cow->eevee.light_cache_data = nullptr;
1009 }
1010
1011 /* nullptr-ify all edit mode pointers which points to data from
1012 * original object. */
discard_edit_mode_pointers(ID * id_cow)1013 void discard_edit_mode_pointers(ID *id_cow)
1014 {
1015 const ID_Type type = GS(id_cow->name);
1016 switch (type) {
1017 case ID_AR:
1018 discard_armature_edit_mode_pointers(id_cow);
1019 break;
1020 case ID_ME:
1021 discard_mesh_edit_mode_pointers(id_cow);
1022 break;
1023 case ID_CU:
1024 discard_curve_edit_mode_pointers(id_cow);
1025 break;
1026 case ID_MB:
1027 discard_mball_edit_mode_pointers(id_cow);
1028 break;
1029 case ID_LT:
1030 discard_lattice_edit_mode_pointers(id_cow);
1031 break;
1032 case ID_SCE:
1033 /* Not really edit mode but still needs to run before
1034 * BKE_libblock_free_datablock() */
1035 discard_scene_pointers(id_cow);
1036 break;
1037 default:
1038 break;
1039 }
1040 }
1041
1042 } // namespace
1043
1044 /* Free content of the CoW data-block
1045 * Notes:
1046 * - Does not recurse into nested ID data-blocks.
1047 * - Does not free data-block itself. */
deg_free_copy_on_write_datablock(ID * id_cow)1048 void deg_free_copy_on_write_datablock(ID *id_cow)
1049 {
1050 if (!check_datablock_expanded(id_cow)) {
1051 /* Actual content was never copied on top of CoW block, we have
1052 * nothing to free. */
1053 return;
1054 }
1055 const ID_Type type = GS(id_cow->name);
1056 #ifdef NESTED_ID_NASTY_WORKAROUND
1057 nested_id_hack_discard_pointers(id_cow);
1058 #endif
1059 switch (type) {
1060 case ID_OB: {
1061 /* TODO(sergey): This workaround is only to prevent free derived
1062 * caches from modifying object->data. This is currently happening
1063 * due to mesh/curve datablock boundbox tagging dirty. */
1064 Object *ob_cow = (Object *)id_cow;
1065 ob_cow->data = nullptr;
1066 ob_cow->sculpt = nullptr;
1067 break;
1068 }
1069 default:
1070 break;
1071 }
1072 discard_edit_mode_pointers(id_cow);
1073 BKE_libblock_free_datablock(id_cow, 0);
1074 BKE_libblock_free_data(id_cow, false);
1075 /* Signal datablock as not being expanded. */
1076 id_cow->name[0] = '\0';
1077 }
1078
deg_evaluate_copy_on_write(struct::Depsgraph * graph,const IDNode * id_node)1079 void deg_evaluate_copy_on_write(struct ::Depsgraph *graph, const IDNode *id_node)
1080 {
1081 const Depsgraph *depsgraph = reinterpret_cast<const Depsgraph *>(graph);
1082 DEG_debug_print_eval(graph, __func__, id_node->id_orig->name, id_node->id_cow);
1083 if (id_node->id_orig == &depsgraph->scene->id) {
1084 /* NOTE: This is handled by eval_ctx setup routines, which
1085 * ensures scene and view layer pointers are valid. */
1086 return;
1087 }
1088 deg_update_copy_on_write_datablock(depsgraph, id_node);
1089 }
1090
deg_validate_copy_on_write_datablock(ID * id_cow)1091 bool deg_validate_copy_on_write_datablock(ID *id_cow)
1092 {
1093 if (id_cow == nullptr) {
1094 return false;
1095 }
1096 ValidateData data;
1097 data.is_valid = true;
1098 BKE_library_foreach_ID_link(
1099 nullptr, id_cow, foreach_libblock_validate_callback, &data, IDWALK_NOP);
1100 return data.is_valid;
1101 }
1102
deg_tag_copy_on_write_id(ID * id_cow,const ID * id_orig)1103 void deg_tag_copy_on_write_id(ID *id_cow, const ID *id_orig)
1104 {
1105 BLI_assert(id_cow != id_orig);
1106 BLI_assert((id_orig->tag & LIB_TAG_COPIED_ON_WRITE) == 0);
1107 id_cow->tag |= LIB_TAG_COPIED_ON_WRITE;
1108 /* This ID is no longer localized, is a self-sustaining copy now. */
1109 id_cow->tag &= ~LIB_TAG_LOCALIZED;
1110 id_cow->orig_id = (ID *)id_orig;
1111 }
1112
deg_copy_on_write_is_expanded(const ID * id_cow)1113 bool deg_copy_on_write_is_expanded(const ID *id_cow)
1114 {
1115 return check_datablock_expanded(id_cow);
1116 }
1117
deg_copy_on_write_is_needed(const ID * id_orig)1118 bool deg_copy_on_write_is_needed(const ID *id_orig)
1119 {
1120 const ID_Type id_type = GS(id_orig->name);
1121 return deg_copy_on_write_is_needed(id_type);
1122 }
1123
deg_copy_on_write_is_needed(const ID_Type id_type)1124 bool deg_copy_on_write_is_needed(const ID_Type id_type)
1125 {
1126 return ID_TYPE_IS_COW(id_type);
1127 }
1128
1129 } // namespace deg
1130 } // namespace blender
1131