Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Sharybin <sergey.vfx@gmail.com>2019-06-04 17:52:48 +0300
committerSergey Sharybin <sergey.vfx@gmail.com>2019-06-05 15:23:54 +0300
commitbbaa1bffe9dbc35d2791b83d0014ccb4ffb6087a (patch)
treed0ded24e2fb254943831cacca7c28b7752e57eae /source/blender/depsgraph
parent863b7b3668fe67a082439181eaf49c3e94a87536 (diff)
Sound: Port to a copy-on-write concept
This change makes it so sound handles are created for evaluated scene, sequencer and speakers. This allows to have properly evaluated animation on them. For the viewport playback sound uses regular dependency graph. For the final render sound uses dependency graph created for render pipeline, which now also contains sequencer and sound datablocks. All the direct sound update calls are replaced with corresponding dependency graph recalc tag.
Diffstat (limited to 'source/blender/depsgraph')
-rw-r--r--source/blender/depsgraph/DEG_depsgraph_query.h10
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc37
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.h2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc6
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc5
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc35
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.h7
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc6
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc11
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_rna.cc2
-rw-r--r--source/blender/depsgraph/intern/depsgraph_build.cc2
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query.cc13
-rw-r--r--source/blender/depsgraph/intern/depsgraph_tag.cc22
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc244
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_operation.cc3
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_operation.h6
16 files changed, 398 insertions, 13 deletions
diff --git a/source/blender/depsgraph/DEG_depsgraph_query.h b/source/blender/depsgraph/DEG_depsgraph_query.h
index 48a62a69f30..cc6c5e7282a 100644
--- a/source/blender/depsgraph/DEG_depsgraph_query.h
+++ b/source/blender/depsgraph/DEG_depsgraph_query.h
@@ -85,6 +85,16 @@ void DEG_get_customdata_mask_for_object(const struct Depsgraph *graph,
* one. Assert will happen if it's not. */
struct Scene *DEG_get_evaluated_scene(const struct Depsgraph *graph);
+/* Similar to DEG_get_evaluated_scene(), but allows to access non-fully evaluated pointer without
+ * causing asserts or crashes. Works the following way:
+ * - If the scene was never evaluated NULL returned.
+ * - Otherwise the last known state of the scene is returned.
+ *
+ * Use in exceptional case if it's absolutely must to.
+ *
+ * Allows to pass depsgraph == NULL, wil lreturn NULL in that case. */
+struct Scene *DEG_get_evaluated_scene_if_exists(const struct Depsgraph *graph);
+
/* Get view layer at its evaluated state.
* This is a shortcut for accessing active view layer from evaluated scene. */
struct ViewLayer *DEG_get_evaluated_view_layer(const struct Depsgraph *graph);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index 93e5dd14ae0..9bdc815518d 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -58,6 +58,7 @@ extern "C" {
#include "DNA_lightprobe_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
+#include "DNA_sequence_types.h"
#include "DNA_sound_types.h"
#include "DNA_speaker_types.h"
#include "DNA_texture_types.h"
@@ -89,6 +90,8 @@ extern "C" {
#include "BKE_particle.h"
#include "BKE_pointcache.h"
#include "BKE_rigidbody.h"
+#include "BKE_scene.h"
+#include "BKE_sequencer.h"
#include "BKE_shader_fx.h"
#include "BKE_sound.h"
#include "BKE_tracking.h"
@@ -1564,12 +1567,42 @@ void DepsgraphNodeBuilder::build_sound(bSound *sound)
if (built_map_.checkIsBuiltAndTag(sound)) {
return;
}
- /* Placeholder so we can add relations and tag ID node for update. */
- add_operation_node(&sound->id, NodeType::AUDIO, OperationCode::SOUND_EVAL);
+ add_id_node(&sound->id);
+ bSound *sound_cow = get_cow_datablock(sound);
+ add_operation_node(&sound->id,
+ NodeType::AUDIO,
+ OperationCode::SOUND_EVAL,
+ function_bind(BKE_sound_evaluate, _1, bmain_, sound_cow));
build_animdata(&sound->id);
build_parameters(&sound->id);
}
+void DepsgraphNodeBuilder::build_scene_sequencer(Scene *scene)
+{
+ if (scene->ed == NULL) {
+ return;
+ }
+ Scene *scene_cow = get_cow_datablock(scene_);
+ add_operation_node(&scene->id,
+ NodeType::SEQUENCER,
+ OperationCode::SEQUENCES_EVAL,
+ function_bind(BKE_scene_eval_sequencer_sequences, _1, scene_cow));
+ /* Make sure data for sequences is in the graph. */
+ Sequence *seq;
+ SEQ_BEGIN (scene->ed, seq) {
+ if (seq->sound != NULL) {
+ build_sound(seq->sound);
+ }
+ /* TODO(sergey): Movie clip, scene, camera, mask. */
+ }
+ SEQ_END;
+}
+
+void DepsgraphNodeBuilder::build_scene_audio(Scene *scene)
+{
+ add_operation_node(&scene->id, NodeType::AUDIO, OperationCode::SOUND_EVAL);
+}
+
/* **** ID traversal callbacks functions **** */
void DepsgraphNodeBuilder::modifier_walk(void *user_data,
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
index c3a04a9ad88..896854870de 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
@@ -212,6 +212,8 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder {
void build_lightprobe(LightProbe *probe);
void build_speaker(Speaker *speaker);
void build_sound(bSound *sound);
+ void build_scene_sequencer(Scene *scene);
+ void build_scene_audio(Scene *scene);
/* Per-ID information about what was already in the dependency graph.
* Allows to re-use certain values, to speed up following evaluation. */
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc
index 64f841d56fc..ef73de517e8 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc
@@ -31,13 +31,19 @@ void DepsgraphNodeBuilder::build_scene_render(Scene *scene)
{
scene_ = scene;
const bool build_compositor = (scene->r.scemode & R_DOCOMP);
+ const bool build_sequencer = (scene->r.scemode & R_DOSEQ);
IDNode *id_node = add_id_node(&scene->id);
id_node->linked_state = DEG_ID_LINKED_DIRECTLY;
add_time_source();
+ build_animdata(&scene->id);
build_scene_parameters(scene);
+ build_scene_audio(scene);
if (build_compositor) {
build_scene_compositor(scene);
}
+ if (build_sequencer) {
+ build_scene_sequencer(scene);
+ }
}
void DepsgraphNodeBuilder::build_scene_parameters(Scene *scene)
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc
index 4e3fdfc6c19..2f6b8c0ba6b 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc
@@ -146,6 +146,11 @@ void DepsgraphNodeBuilder::build_view_layer(Scene *scene,
build_collection(NULL, fls->group);
}
}
+ /* Sequencer. */
+ if (linked_state == DEG_ID_LINKED_DIRECTLY) {
+ build_scene_audio(scene);
+ build_scene_sequencer(scene);
+ }
/* Collections. */
add_operation_node(
&scene->id,
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index 54d5223497e..a1f8c59f936 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -58,6 +58,7 @@ extern "C" {
#include "DNA_object_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
+#include "DNA_sequence_types.h"
#include "DNA_sound_types.h"
#include "DNA_speaker_types.h"
#include "DNA_texture_types.h"
@@ -84,6 +85,7 @@ extern "C" {
#include "BKE_particle.h"
#include "BKE_pointcache.h"
#include "BKE_rigidbody.h"
+#include "BKE_sequencer.h"
#include "BKE_shader_fx.h"
#include "BKE_shrinkwrap.h"
#include "BKE_sound.h"
@@ -2324,6 +2326,35 @@ void DepsgraphRelationBuilder::build_sound(bSound *sound)
build_parameters(&sound->id);
}
+void DepsgraphRelationBuilder::build_scene_sequencer(Scene *scene)
+{
+ if (scene->ed == NULL) {
+ return;
+ }
+ /* Make sure dependencies from sequences data goes to the sequencer evaluation. */
+ ComponentKey sequencer_key(&scene->id, NodeType::SEQUENCER);
+ Sequence *seq;
+ bool has_audio_strips = false;
+ SEQ_BEGIN (scene->ed, seq) {
+ if (seq->sound != NULL) {
+ build_sound(seq->sound);
+ ComponentKey sound_key(&seq->sound->id, NodeType::AUDIO);
+ add_relation(sound_key, sequencer_key, "Sound -> Sequencer");
+ has_audio_strips = true;
+ }
+ /* TODO(sergey): Movie clip, scene, camera, mask. */
+ }
+ SEQ_END;
+ if (has_audio_strips) {
+ ComponentKey scene_audio_key(&scene->id, NodeType::AUDIO);
+ add_relation(sequencer_key, scene_audio_key, "Sequencer -> Audio");
+ }
+}
+
+void DepsgraphRelationBuilder::build_scene_audio(Scene * /*scene*/)
+{
+}
+
void DepsgraphRelationBuilder::build_copy_on_write_relations()
{
for (IDNode *id_node : graph_->id_nodes) {
@@ -2387,6 +2418,10 @@ void DepsgraphRelationBuilder::build_copy_on_write_relations(IDNode *id_node)
(id_type == ID_CF && comp_node->type == NodeType::CACHE)) {
rel_flag &= ~RELATION_FLAG_NO_FLUSH;
}
+ /* TODO(sergey): Needs better solution for this. */
+ if (id_type == ID_SO) {
+ rel_flag &= ~RELATION_FLAG_NO_FLUSH;
+ }
/* Notes on exceptions:
* - Parameters component is where drivers are living. Changing any
* of the (custom) properties in the original datablock (even the
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
index 7d302092119..55295c8b075 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
@@ -41,6 +41,7 @@
#include "intern/builder/deg_builder_rna.h"
#include "intern/depsgraph.h"
#include "intern/node/deg_node.h"
+#include "intern/node/deg_node_id.h"
#include "intern/node/deg_node_component.h"
#include "intern/node/deg_node_operation.h"
@@ -200,7 +201,9 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder {
void build_scene_compositor(Scene *scene);
void build_layer_collections(ListBase *lb);
- void build_view_layer(Scene *scene, ViewLayer *view_layer);
+ void build_view_layer(Scene *scene,
+ ViewLayer *view_layer,
+ eDepsNode_LinkedState_Type linked_state);
void build_collection(LayerCollection *from_layer_collection,
Object *object,
Collection *collection);
@@ -270,6 +273,8 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder {
void build_lightprobe(LightProbe *probe);
void build_speaker(Speaker *speaker);
void build_sound(bSound *sound);
+ void build_scene_sequencer(Scene *scene);
+ void build_scene_audio(Scene *scene);
void build_nested_datablock(ID *owner, ID *id);
void build_nested_nodetree(ID *owner, bNodeTree *ntree);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc
index 26bb1bd3d2a..46e8b8e7acc 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc
@@ -31,10 +31,16 @@ void DepsgraphRelationBuilder::build_scene_render(Scene *scene)
{
scene_ = scene;
const bool build_compositor = (scene->r.scemode & R_DOCOMP);
+ const bool build_sequencer = (scene->r.scemode & R_DOSEQ);
build_scene_parameters(scene);
+ build_animdata(&scene->id);
+ build_scene_audio(scene);
if (build_compositor) {
build_scene_compositor(scene);
}
+ if (build_sequencer) {
+ build_scene_sequencer(scene);
+ }
}
void DepsgraphRelationBuilder::build_scene_parameters(Scene *scene)
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc
index b832473bde9..4c55e4a137a 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc
@@ -75,7 +75,9 @@ void DepsgraphRelationBuilder::build_layer_collections(ListBase *lb)
}
}
-void DepsgraphRelationBuilder::build_view_layer(Scene *scene, ViewLayer *view_layer)
+void DepsgraphRelationBuilder::build_view_layer(Scene *scene,
+ ViewLayer *view_layer,
+ eDepsNode_LinkedState_Type linked_state)
{
/* Setup currently building context. */
scene_ = scene;
@@ -132,10 +134,15 @@ void DepsgraphRelationBuilder::build_view_layer(Scene *scene, ViewLayer *view_la
&scene->id, NodeType::LAYER_COLLECTIONS, OperationCode::VIEW_LAYER_EVAL);
OperationKey scene_eval_key(&scene->id, NodeType::PARAMETERS, OperationCode::SCENE_EVAL);
add_relation(scene_view_layer_key, scene_eval_key, "View Layer -> Scene Eval");
+ /* Sequencer. */
+ if (linked_state == DEG_ID_LINKED_DIRECTLY) {
+ build_scene_audio(scene);
+ build_scene_sequencer(scene);
+ }
/* Build all set scenes. */
if (scene->set != NULL) {
ViewLayer *set_view_layer = BKE_view_layer_default_render(scene->set);
- build_view_layer(scene->set, set_view_layer);
+ build_view_layer(scene->set, set_view_layer, DEG_ID_LINKED_VIA_SET);
}
}
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc
index 403c9cfc778..b7efdc0fa3f 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc
@@ -329,10 +329,8 @@ RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr,
return node_identifier;
}
else if (RNA_struct_is_a(ptr->type, &RNA_Sequence)) {
- const Sequence *seq = static_cast<Sequence *>(ptr->data);
/* Sequencer strip */
node_identifier.type = NodeType::SEQUENCER;
- node_identifier.component_name = seq->name;
return node_identifier;
}
else if (RNA_struct_is_a(ptr->type, &RNA_NodeSocket)) {
diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc
index cf1ebccc6c6..bfb0a2aade4 100644
--- a/source/blender/depsgraph/intern/depsgraph_build.cc
+++ b/source/blender/depsgraph/intern/depsgraph_build.cc
@@ -272,7 +272,7 @@ void DEG_graph_build_from_view_layer(Depsgraph *graph,
/* Hook up relationships between operations - to determine evaluation order. */
DEG::DepsgraphRelationBuilder relation_builder(bmain, deg_graph, &builder_cache);
relation_builder.begin_build();
- relation_builder.build_view_layer(scene, view_layer);
+ relation_builder.build_view_layer(scene, view_layer, DEG::DEG_ID_LINKED_DIRECTLY);
relation_builder.build_copy_on_write_relations();
/* Finalize building. */
graph_build_finalize_common(deg_graph, bmain);
diff --git a/source/blender/depsgraph/intern/depsgraph_query.cc b/source/blender/depsgraph/intern/depsgraph_query.cc
index 0345f294860..865da20e6fd 100644
--- a/source/blender/depsgraph/intern/depsgraph_query.cc
+++ b/source/blender/depsgraph/intern/depsgraph_query.cc
@@ -160,6 +160,19 @@ Scene *DEG_get_evaluated_scene(const Depsgraph *graph)
return scene_cow;
}
+Scene *DEG_get_evaluated_scene_if_exists(const Depsgraph *graph)
+{
+ if (graph == NULL) {
+ return NULL;
+ }
+ const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
+ Scene *scene_cow = deg_graph->scene_cow;
+ if (scene_cow == NULL || !DEG::deg_copy_on_write_is_expanded(&scene_cow->id)) {
+ return NULL;
+ }
+ return scene_cow;
+}
+
ViewLayer *DEG_get_evaluated_view_layer(const Depsgraph *graph)
{
const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc
index c2cc15460d1..9f48dd2b47e 100644
--- a/source/blender/depsgraph/intern/depsgraph_tag.cc
+++ b/source/blender/depsgraph/intern/depsgraph_tag.cc
@@ -215,6 +215,16 @@ void depsgraph_tag_to_component_opcode(const ID *id,
/* There is no such node in depsgraph, this tag is to be handled
* separately. */
break;
+ case ID_RECALC_SEQUENCER_STRIPS:
+ *component_type = NodeType::SEQUENCER;
+ break;
+ case ID_RECALC_AUDIO_SEEK:
+ case ID_RECALC_AUDIO_FPS:
+ case ID_RECALC_AUDIO_VOLUME:
+ case ID_RECALC_AUDIO_MUTE:
+ case ID_RECALC_AUDIO_LISTENER:
+ *component_type = NodeType::AUDIO;
+ break;
case ID_RECALC_ALL:
case ID_RECALC_PSYS_ALL:
BLI_assert(!"Should not happen");
@@ -633,6 +643,18 @@ const char *DEG_update_tag_as_string(IDRecalcFlag flag)
return "POINT_CACHE";
case ID_RECALC_EDITORS:
return "EDITORS";
+ case ID_RECALC_SEQUENCER_STRIPS:
+ return "SEQUENCER_STRIPS";
+ case ID_RECALC_AUDIO_SEEK:
+ return "AUDIO_SEEK";
+ case ID_RECALC_AUDIO_FPS:
+ return "AUDIO_FPS";
+ case ID_RECALC_AUDIO_VOLUME:
+ return "AUDIO_VOLUME";
+ case ID_RECALC_AUDIO_MUTE:
+ return "AUDIO_MUTE";
+ case ID_RECALC_AUDIO_LISTENER:
+ return "AUDIO_LISTENER";
case ID_RECALC_ALL:
return "ALL";
}
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
index 4bc05bc9185..ef2862ab387 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
@@ -59,6 +59,8 @@ extern "C" {
#include "DNA_mesh_types.h"
#include "DNA_modifier_types.h"
#include "DNA_scene_types.h"
+#include "DNA_sequence_types.h"
+#include "DNA_sound_types.h"
#include "DNA_object_types.h"
#include "DNA_particle_types.h"
@@ -84,6 +86,8 @@ extern "C" {
#include "BKE_library_query.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
+#include "BKE_sequencer.h"
+#include "BKE_sound.h"
}
#include "intern/depsgraph.h"
@@ -467,6 +471,25 @@ void scene_setup_view_layers_after_remap(const Depsgraph *depsgraph,
* Still not an excuse to have those. */
}
+void update_sequence_orig_pointers(const ListBase *sequences_orig, ListBase *sequences_cow)
+{
+ Sequence *sequence_orig = reinterpret_cast<Sequence *>(sequences_orig->first);
+ Sequence *sequence_cow = reinterpret_cast<Sequence *>(sequences_cow->first);
+ while (sequence_orig != NULL) {
+ update_sequence_orig_pointers(&sequence_orig->seqbase, &sequence_cow->seqbase);
+ sequence_cow->orig_sequence = sequence_orig;
+ sequence_cow = sequence_cow->next;
+ sequence_orig = sequence_orig->next;
+ }
+}
+
+void update_scene_orig_pointers(const Scene *scene_orig, Scene *scene_cow)
+{
+ if (scene_orig->ed != NULL) {
+ update_sequence_orig_pointers(&scene_orig->ed->seqbase, &scene_cow->ed->seqbase);
+ }
+}
+
/* Check whether given ID is expanded or still a shallow copy. */
BLI_INLINE bool check_datablock_expanded(const ID *id_cow)
{
@@ -751,6 +774,7 @@ void update_id_after_copy(const Depsgraph *depsgraph,
scene_cow->toolsettings = scene_orig->toolsettings;
scene_cow->eevee.light_cache = scene_orig->eevee.light_cache;
scene_setup_view_layers_after_remap(depsgraph, id_node, reinterpret_cast<Scene *>(id_cow));
+ update_scene_orig_pointers(scene_orig, scene_cow);
break;
}
default:
@@ -881,6 +905,205 @@ ID *deg_expand_copy_on_write_datablock(const Depsgraph *depsgraph,
namespace {
+/* Backup of sequencer strips runtime data. */
+
+/* Backup of a single strip. */
+class SequenceBackup {
+ public:
+ SequenceBackup()
+ {
+ reset();
+ }
+
+ inline void reset()
+ {
+ scene_sound = NULL;
+ }
+
+ void init_from_sequence(Sequence *sequence)
+ {
+ scene_sound = sequence->scene_sound;
+
+ sequence->scene_sound = NULL;
+ }
+
+ void restore_to_sequence(Sequence *sequence)
+ {
+ sequence->scene_sound = scene_sound;
+ reset();
+ }
+
+ inline bool isEmpty() const
+ {
+ return (scene_sound == NULL);
+ }
+
+ void *scene_sound;
+};
+
+class SequencerBackup {
+ public:
+ SequencerBackup();
+
+ void init_from_scene(Scene *scene);
+ void restore_to_scene(Scene *scene);
+
+ typedef map<Sequence *, SequenceBackup> SequencesBackupMap;
+ SequencesBackupMap sequences_backup;
+};
+
+SequencerBackup::SequencerBackup()
+{
+}
+
+void SequencerBackup::init_from_scene(Scene *scene)
+{
+ Sequence *sequence;
+ SEQ_BEGIN (scene->ed, sequence) {
+ SequenceBackup sequence_backup;
+ sequence_backup.init_from_sequence(sequence);
+ if (!sequence_backup.isEmpty()) {
+ sequences_backup.insert(make_pair(sequence->orig_sequence, sequence_backup));
+ }
+ }
+ SEQ_END;
+}
+
+void SequencerBackup::restore_to_scene(Scene *scene)
+{
+ Sequence *sequence;
+ SEQ_BEGIN (scene->ed, sequence) {
+ SequencesBackupMap::iterator it = sequences_backup.find(sequence->orig_sequence);
+ if (it == sequences_backup.end()) {
+ continue;
+ }
+ SequenceBackup &sequence_backup = it->second;
+ sequence_backup.restore_to_sequence(sequence);
+ }
+ SEQ_END;
+ /* Cleanup audio while the scene is still known. */
+ for (SequencesBackupMap::value_type &it : sequences_backup) {
+ SequenceBackup &sequence_backup = it.second;
+ if (sequence_backup.scene_sound != NULL) {
+ BKE_sound_remove_scene_sound(scene, sequence_backup.scene_sound);
+ }
+ }
+}
+
+/* Backup of scene runtime data. */
+
+class SceneBackup {
+ public:
+ SceneBackup();
+
+ void reset();
+
+ void init_from_scene(Scene *scene);
+ void restore_to_scene(Scene *scene);
+
+ /* Sound/audio related pointers of the scene itself.
+ *
+ * NOTE: Scene can not disappear after relations update, because otherwise the entire dependency
+ * graph will be gone. This means we don't need to compare original scene pointer, or worry about
+ * freeing those if they cant' be restorted: we just copy them over to a new scene. */
+ void *sound_scene;
+ void *playback_handle;
+ void *sound_scrub_handle;
+ void *speaker_handles;
+
+ SequencerBackup sequencer_backup;
+};
+
+SceneBackup::SceneBackup()
+{
+ reset();
+}
+
+void SceneBackup::reset()
+{
+ sound_scene = NULL;
+ playback_handle = NULL;
+ sound_scrub_handle = NULL;
+ speaker_handles = NULL;
+}
+
+void SceneBackup::init_from_scene(Scene *scene)
+{
+ sound_scene = scene->sound_scene;
+ playback_handle = scene->playback_handle;
+ sound_scrub_handle = scene->sound_scrub_handle;
+ speaker_handles = scene->speaker_handles;
+
+ /* Clear pointers stored in the scene, so they are not freed when copied-on-written datablock
+ * is freed for re-allocation. */
+ scene->sound_scene = NULL;
+ scene->playback_handle = NULL;
+ scene->sound_scrub_handle = NULL;
+ scene->speaker_handles = NULL;
+
+ sequencer_backup.init_from_scene(scene);
+}
+
+void SceneBackup::restore_to_scene(Scene *scene)
+{
+ scene->sound_scene = sound_scene;
+ scene->playback_handle = playback_handle;
+ scene->sound_scrub_handle = sound_scrub_handle;
+ scene->speaker_handles = speaker_handles;
+
+ sequencer_backup.restore_to_scene(scene);
+
+ reset();
+}
+
+/* Backup of sound datablocks runtime data. */
+
+class SoundBackup {
+ public:
+ SoundBackup();
+
+ void reset();
+
+ void init_from_sound(bSound *sound);
+ void restore_to_sound(bSound *sound);
+
+ void *cache;
+ void *waveform;
+ void *playback_handle;
+};
+
+SoundBackup::SoundBackup()
+{
+ reset();
+}
+
+void SoundBackup::reset()
+{
+ cache = NULL;
+ waveform = NULL;
+ playback_handle = NULL;
+}
+
+void SoundBackup::init_from_sound(bSound *sound)
+{
+ cache = sound->cache;
+ waveform = sound->waveform;
+ playback_handle = sound->playback_handle;
+
+ sound->cache = NULL;
+ sound->waveform = NULL;
+ sound->playback_handle = NULL;
+}
+
+void SoundBackup::restore_to_sound(bSound *sound)
+{
+ sound->cache = cache;
+ sound->waveform = waveform;
+ sound->playback_handle = playback_handle;
+
+ reset();
+}
+
/* Identifier used to match modifiers to backup/restore their runtime data.
* Identification is happening using original modifier data pointer and the
* modifier type.
@@ -921,7 +1144,8 @@ typedef map<ModifierDataBackupID, void *> ModifierRuntimeDataBackup;
/* Storage for backed up pose channel runtime data. */
typedef map<bPoseChannel *, bPoseChannel_Runtime> PoseChannelRuntimeDataBackup;
-struct ObjectRuntimeBackup {
+class ObjectRuntimeBackup {
+ public:
ObjectRuntimeBackup() : base_flag(0), base_local_view_bits(0)
{
/* TODO(sergey): Use something like BKE_object_runtime_reset(). */
@@ -1099,6 +1323,8 @@ class RuntimeBackup {
/* Restore fields to the given ID. */
void restore_to_id(ID *id);
+ SceneBackup scene_backup;
+ SoundBackup sound_backup;
ObjectRuntimeBackup object_backup;
DrawDataList drawdata_backup;
DrawDataList *drawdata_ptr;
@@ -1114,6 +1340,12 @@ void RuntimeBackup::init_from_id(ID *id)
case ID_OB:
object_backup.init_from_object(reinterpret_cast<Object *>(id));
break;
+ case ID_SCE:
+ scene_backup.init_from_scene(reinterpret_cast<Scene *>(id));
+ break;
+ case ID_SO:
+ sound_backup.init_from_sound(reinterpret_cast<bSound *>(id));
+ break;
default:
break;
}
@@ -1133,6 +1365,12 @@ void RuntimeBackup::restore_to_id(ID *id)
case ID_OB:
object_backup.restore_to_object(reinterpret_cast<Object *>(id));
break;
+ case ID_SCE:
+ scene_backup.restore_to_scene(reinterpret_cast<Scene *>(id));
+ break;
+ case ID_SO:
+ sound_backup.restore_to_sound(reinterpret_cast<bSound *>(id));
+ break;
default:
break;
}
@@ -1321,9 +1559,7 @@ bool deg_copy_on_write_is_expanded(const ID *id_cow)
bool deg_copy_on_write_is_needed(const ID *id_orig)
{
const ID_Type id_type = GS(id_orig->name);
- /* TODO(sergey): Make Sound copyable. It is here only because the code for dependency graph is
- * being work in progress. */
- return !ELEM(id_type, ID_IM, ID_SO);
+ return !ELEM(id_type, ID_IM);
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.cc b/source/blender/depsgraph/intern/node/deg_node_operation.cc
index 62a61675bcc..09a761d282f 100644
--- a/source/blender/depsgraph/intern/node/deg_node_operation.cc
+++ b/source/blender/depsgraph/intern/node/deg_node_operation.cc
@@ -185,6 +185,9 @@ const char *operationCodeAsString(OperationCode opcode)
/* Generic datablock. */
case OperationCode::GENERIC_DATABLOCK_UPDATE:
return "GENERIC_DATABLOCK_UPDATE";
+ /* Sequencer. */
+ case OperationCode::SEQUENCES_EVAL:
+ return "SEQUENCES_EVAL";
/* instancing/duplication. */
case OperationCode::DUPLI:
return "DUPLI";
diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.h b/source/blender/depsgraph/intern/node/deg_node_operation.h
index ab6242a6196..8fc565cfa77 100644
--- a/source/blender/depsgraph/intern/node/deg_node_operation.h
+++ b/source/blender/depsgraph/intern/node/deg_node_operation.h
@@ -185,12 +185,16 @@ enum class OperationCode {
/* Images. -------------------------------------------------------------- */
IMAGE_ANIMATION,
- /* Synchronization clips. ----------------------------------------------- */
+ /* Synchronization. ----------------------------------------------------- */
SYNCHRONIZE_TO_ORIGINAL,
/* Generic datablock ---------------------------------------------------- */
GENERIC_DATABLOCK_UPDATE,
+ /* Sequencer. ----------------------------------------------------------- */
+
+ SEQUENCES_EVAL,
+
/* Duplication/instancing system. --------------------------------------- */
DUPLI,
};