[Bf-blender-cvs] [b4e1e0946bf] master: Depsgraph: Preserve sound and audio pointers through copy-on-write

Sergey Sharybin noreply at git.blender.org
Fri May 3 15:52:53 CEST 2019


Commit: b4e1e0946bf124f95e1d9fa1a6ffa1cbc143c7d6
Author: Sergey Sharybin
Date:   Thu May 2 11:14:10 2019 +0200
Branches: master
https://developer.blender.org/rBb4e1e0946bf124f95e1d9fa1a6ffa1cbc143c7d6

Depsgraph: Preserve sound and audio pointers through copy-on-write

This allows to have scene and speaker copy-on-write executed without
interrupting the playing sound.

===================================================================

M	source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc

===================================================================

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 b73c525ca13..6d5714d5606 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
@@ -60,6 +60,7 @@ extern "C" {
 #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"
 
@@ -85,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"
@@ -859,6 +862,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.
@@ -899,7 +1101,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(). */
@@ -1077,6 +1280,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;
@@ -1092,6 +1297,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;
   }
@@ -1111,6 +1322,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;
   }



More information about the Bf-blender-cvs mailing list