diff options
20 files changed, 1176 insertions, 541 deletions
diff --git a/source/blender/depsgraph/CMakeLists.txt b/source/blender/depsgraph/CMakeLists.txt index 21ab148496c..4abeec19645 100644 --- a/source/blender/depsgraph/CMakeLists.txt +++ b/source/blender/depsgraph/CMakeLists.txt @@ -58,6 +58,15 @@ set(SRC intern/eval/deg_eval.cc intern/eval/deg_eval_copy_on_write.cc intern/eval/deg_eval_flush.cc + intern/eval/deg_eval_runtime_backup.cc + intern/eval/deg_eval_runtime_backup_modifier.cc + intern/eval/deg_eval_runtime_backup_movieclip.cc + intern/eval/deg_eval_runtime_backup_object.cc + intern/eval/deg_eval_runtime_backup_pose.cc + intern/eval/deg_eval_runtime_backup_scene.cc + intern/eval/deg_eval_runtime_backup_sequence.cc + intern/eval/deg_eval_runtime_backup_sequencer.cc + intern/eval/deg_eval_runtime_backup_sound.cc intern/eval/deg_eval_stats.cc intern/node/deg_node.cc intern/node/deg_node_component.cc @@ -98,6 +107,15 @@ set(SRC intern/eval/deg_eval.h intern/eval/deg_eval_copy_on_write.h intern/eval/deg_eval_flush.h + intern/eval/deg_eval_runtime_backup.h + intern/eval/deg_eval_runtime_backup_modifier.h + intern/eval/deg_eval_runtime_backup_movieclip.h + intern/eval/deg_eval_runtime_backup_object.h + intern/eval/deg_eval_runtime_backup_pose.h + intern/eval/deg_eval_runtime_backup_scene.h + intern/eval/deg_eval_runtime_backup_sequence.h + intern/eval/deg_eval_runtime_backup_sequencer.h + intern/eval/deg_eval_runtime_backup_sound.h intern/eval/deg_eval_stats.h intern/node/deg_node.h intern/node/deg_node_component.h 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 8a33453b923..3a2cf35f4d5 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 @@ -21,7 +21,7 @@ * \ingroup depsgraph */ -/* Enable special; trickery to treat nested owned IDs (such as nodetree of +/* Enable special trickery to treat nested owned IDs (such as nodetree of * material) to be handled in same way as "real" data-blocks, even tho some * internal BKE routines doesn't treat them like that. * @@ -95,6 +95,7 @@ extern "C" { #include "intern/depsgraph.h" #include "intern/builder/deg_builder.h" #include "intern/builder/deg_builder_nodes.h" +#include "intern/eval/deg_eval_runtime_backup.h" #include "intern/node/deg_node.h" #include "intern/node/deg_node_id.h" @@ -945,545 +946,6 @@ ID *deg_expand_copy_on_write_datablock(const Depsgraph *depsgraph, return deg_expand_copy_on_write_datablock(depsgraph, id_node, node_builder, create_placeholders); } -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 restored: we just copy them over to a new scene. */ - void *sound_scene; - void *playback_handle; - void *sound_scrub_handle; - void *speaker_handles; - float rigidbody_last_time; - - SequencerBackup sequencer_backup; -}; - -SceneBackup::SceneBackup() -{ - reset(); -} - -void SceneBackup::reset() -{ - sound_scene = NULL; - playback_handle = NULL; - sound_scrub_handle = NULL; - speaker_handles = NULL; - rigidbody_last_time = -1; -} - -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; - - if (scene->rigidbody_world != NULL) { - rigidbody_last_time = scene->rigidbody_world->ltime; - } - - /* 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; - - if (scene->rigidbody_world != NULL) { - scene->rigidbody_world->ltime = rigidbody_last_time; - } - - 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. - * It is not enough to only pointer, since it's possible to have a situation - * when modifier is removed and a new one added, and due to memory allocation - * policy they might have same pointer. - * By adding type into matching we are at least ensuring that modifier will not - * try to interpret runtime data created by another modifier type. */ -class ModifierDataBackupID { - public: - ModifierDataBackupID() : ModifierDataBackupID(NULL, eModifierType_None) - { - } - - ModifierDataBackupID(ModifierData *modifier_data, ModifierType type) - : modifier_data(modifier_data), type(type) - { - } - - bool operator<(const ModifierDataBackupID &other) const - { - if (modifier_data < other.modifier_data) { - return true; - } - if (modifier_data == other.modifier_data) { - return static_cast<int>(type) < static_cast<int>(other.type); - } - return false; - } - - ModifierData *modifier_data; - ModifierType type; -}; - -/* Storage for backed up runtime modifier data. */ -typedef map<ModifierDataBackupID, void *> ModifierRuntimeDataBackup; - -/* Storage for backed up pose channel runtime data. */ -typedef map<bPoseChannel *, bPoseChannel_Runtime> PoseChannelRuntimeDataBackup; - -class ObjectRuntimeBackup { - public: - ObjectRuntimeBackup() : base_flag(0), base_local_view_bits(0) - { - /* TODO(sergey): Use something like BKE_object_runtime_reset(). */ - memset(&runtime, 0, sizeof(runtime)); - } - - /* Make a backup of object's evaluation runtime data, additionally - * make object to be safe for free without invalidating backed up - * pointers. */ - void init_from_object(Object *object); - void backup_modifier_runtime_data(Object *object); - void backup_pose_channel_runtime_data(Object *object); - - /* Restore all fields to the given object. */ - void restore_to_object(Object *object); - /* NOTE: Will free all runtime data which has not been restored. */ - void restore_modifier_runtime_data(Object *object); - void restore_pose_channel_runtime_data(Object *object); - - Object_Runtime runtime; - short base_flag; - unsigned short base_local_view_bits; - ModifierRuntimeDataBackup modifier_runtime_data; - PoseChannelRuntimeDataBackup pose_channel_runtime_data; -}; - -void ObjectRuntimeBackup::init_from_object(Object *object) -{ - /* Store evaluated mesh and curve_cache, and make sure we don't free it. */ - Mesh *mesh_eval = object->runtime.mesh_eval; - runtime = object->runtime; - BKE_object_runtime_reset(object); - /* Keep bbox (for now at least). */ - object->runtime.bb = runtime.bb; - /* Object update will override actual object->data to an evaluated version. - * Need to make sure we don't have data set to evaluated one before free - * anything. */ - if (mesh_eval != NULL && object->data == mesh_eval) { - object->data = runtime.mesh_orig; - } - /* Make a backup of base flags. */ - base_flag = object->base_flag; - base_local_view_bits = object->base_local_view_bits; - /* Backup tuntime data of all modifiers. */ - backup_modifier_runtime_data(object); - /* Backup runtime data of all pose channels. */ - backup_pose_channel_runtime_data(object); -} - -inline ModifierDataBackupID create_modifier_data_id(const ModifierData *modifier_data) -{ - return ModifierDataBackupID(modifier_data->orig_modifier_data, - static_cast<ModifierType>(modifier_data->type)); -} - -void ObjectRuntimeBackup::backup_modifier_runtime_data(Object *object) -{ - LISTBASE_FOREACH (ModifierData *, modifier_data, &object->modifiers) { - if (modifier_data->runtime == NULL) { - continue; - } - BLI_assert(modifier_data->orig_modifier_data != NULL); - ModifierDataBackupID modifier_data_id = create_modifier_data_id(modifier_data); - modifier_runtime_data.insert(make_pair(modifier_data_id, modifier_data->runtime)); - modifier_data->runtime = NULL; - } -} - -void ObjectRuntimeBackup::backup_pose_channel_runtime_data(Object *object) -{ - if (object->pose != NULL) { - LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { - /* This is NULL in Edit mode. */ - if (pchan->orig_pchan != NULL) { - pose_channel_runtime_data[pchan->orig_pchan] = pchan->runtime; - BKE_pose_channel_runtime_reset(&pchan->runtime); - } - } - } -} - -void ObjectRuntimeBackup::restore_to_object(Object *object) -{ - Mesh *mesh_orig = object->runtime.mesh_orig; - BoundBox *bb = object->runtime.bb; - object->runtime = runtime; - object->runtime.mesh_orig = mesh_orig; - object->runtime.bb = bb; - if (object->type == OB_MESH && object->runtime.mesh_eval != NULL) { - if (object->id.recalc & ID_RECALC_GEOMETRY) { - /* If geometry is tagged for update it means, that part of - * evaluated mesh are not valid anymore. In this case we can not - * have any "persistent" pointers to point to an invalid data. - * - * We restore object's data datablock to an original copy of - * that datablock. */ - object->data = mesh_orig; - - /* After that, immediately free the invalidated caches. */ - BKE_object_free_derived_caches(object); - } - else { - Mesh *mesh_eval = object->runtime.mesh_eval; - /* Do same thing as object update: override actual object data - * pointer with evaluated datablock. */ - object->data = mesh_eval; - /* Evaluated mesh simply copied edit_mesh pointer from - * original mesh during update, need to make sure no dead - * pointers are left behind. */ - mesh_eval->edit_mesh = mesh_orig->edit_mesh; - } - } - object->base_flag = base_flag; - object->base_local_view_bits = base_local_view_bits; - /* Restore modifier's runtime data. - * NOTE: Data of unused modifiers will be freed there. */ - restore_modifier_runtime_data(object); - restore_pose_channel_runtime_data(object); -} - -void ObjectRuntimeBackup::restore_modifier_runtime_data(Object *object) -{ - LISTBASE_FOREACH (ModifierData *, modifier_data, &object->modifiers) { - BLI_assert(modifier_data->orig_modifier_data != NULL); - ModifierDataBackupID modifier_data_id = create_modifier_data_id(modifier_data); - ModifierRuntimeDataBackup::iterator runtime_data_iterator = modifier_runtime_data.find( - modifier_data_id); - if (runtime_data_iterator != modifier_runtime_data.end()) { - modifier_data->runtime = runtime_data_iterator->second; - runtime_data_iterator->second = NULL; - } - } - for (ModifierRuntimeDataBackup::value_type value : modifier_runtime_data) { - const ModifierDataBackupID modifier_data_id = value.first; - void *runtime = value.second; - if (value.second == NULL) { - continue; - } - const ModifierTypeInfo *modifier_type_info = modifierType_getInfo(modifier_data_id.type); - BLI_assert(modifier_type_info != NULL); - modifier_type_info->freeRuntimeData(runtime); - } -} - -void ObjectRuntimeBackup::restore_pose_channel_runtime_data(Object *object) -{ - if (object->pose != NULL) { - LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { - /* This is NULL in Edit mode. */ - if (pchan->orig_pchan != NULL) { - PoseChannelRuntimeDataBackup::iterator runtime_data_iterator = - pose_channel_runtime_data.find(pchan->orig_pchan); - if (runtime_data_iterator != pose_channel_runtime_data.end()) { - pchan->runtime = runtime_data_iterator->second; - pose_channel_runtime_data.erase(runtime_data_iterator); - } - } - } - } - for (PoseChannelRuntimeDataBackup::value_type &value : pose_channel_runtime_data) { - BKE_pose_channel_runtime_free(&value.second); - } -} - -/* Backup of movie clip runtime data. */ - -class MovieClipBackup { - public: - MovieClipBackup(); - - void reset(); - - void init_from_movieclip(MovieClip *movieclip); - void restore_to_movieclip(MovieClip *movieclip); - - struct anim *anim; - struct MovieClipCache *cache; -}; - -MovieClipBackup::MovieClipBackup() -{ - reset(); -} - -void MovieClipBackup::reset() -{ - anim = NULL; - cache = NULL; -} - -void MovieClipBackup::init_from_movieclip(MovieClip *movieclip) -{ - anim = movieclip->anim; - cache = movieclip->cache; - /* Clear pointers stored in the movie clip, so they are not freed when copied-on-written - * datablock is freed for re-allocation. */ - movieclip->anim = NULL; - movieclip->cache = NULL; -} - -void MovieClipBackup::restore_to_movieclip(MovieClip *movieclip) -{ - movieclip->anim = anim; - movieclip->cache = cache; - - reset(); -} - -class RuntimeBackup { - public: - RuntimeBackup() : drawdata_ptr(NULL) - { - drawdata_backup.first = drawdata_backup.last = NULL; - } - - /* NOTE: Will reset all runbtime fields which has been backed up to NULL. */ - void init_from_id(ID *id); - - /* 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; - MovieClipBackup movieclip_backup; -}; - -void RuntimeBackup::init_from_id(ID *id) -{ - if (!check_datablock_expanded(id)) { - return; - } - const ID_Type id_type = GS(id->name); - switch (id_type) { - 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; - case ID_MC: - movieclip_backup.init_from_movieclip(reinterpret_cast<MovieClip *>(id)); - break; - default: - break; - } - /* Note that we never free GPU draw data from here since that's not - * safe for threading and draw data is likely to be re-used. */ - drawdata_ptr = DRW_drawdatalist_from_id(id); - if (drawdata_ptr != NULL) { - drawdata_backup = *drawdata_ptr; - drawdata_ptr->first = drawdata_ptr->last = NULL; - } -} - -void RuntimeBackup::restore_to_id(ID *id) -{ - const ID_Type id_type = GS(id->name); - switch (id_type) { - 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; - case ID_MC: - movieclip_backup.restore_to_movieclip(reinterpret_cast<MovieClip *>(id)); - break; - default: - break; - } - if (drawdata_ptr != NULL) { - *drawdata_ptr = drawdata_backup; - } -} - -} // namespace - ID *deg_update_copy_on_write_datablock(const Depsgraph *depsgraph, const IDNode *id_node) { const ID *id_orig = id_node->id_orig; @@ -1492,7 +954,7 @@ ID *deg_update_copy_on_write_datablock(const Depsgraph *depsgraph, const IDNode if (!deg_copy_on_write_is_needed(id_orig)) { return id_cow; } - RuntimeBackup backup; + RuntimeBackup backup(depsgraph); backup.init_from_id(id_cow); deg_free_copy_on_write_datablock(id_cow); deg_expand_copy_on_write_datablock(depsgraph, id_node); diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.cc new file mode 100644 index 00000000000..88390ab412f --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.cc @@ -0,0 +1,101 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2017 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#include "intern/eval/deg_eval_runtime_backup.h" + +#include "intern/eval/deg_eval_copy_on_write.h" + +#include "BLI_utildefines.h" + +#include "DRW_engine.h" + +namespace DEG { + +RuntimeBackup::RuntimeBackup(const Depsgraph *depsgraph) + : scene_backup(depsgraph), + sound_backup(depsgraph), + object_backup(depsgraph), + drawdata_ptr(NULL), + movieclip_backup(depsgraph) +{ + drawdata_backup.first = drawdata_backup.last = NULL; +} + +void RuntimeBackup::init_from_id(ID *id) +{ + if (!deg_copy_on_write_is_expanded(id)) { + return; + } + + const ID_Type id_type = GS(id->name); + switch (id_type) { + 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; + case ID_MC: + movieclip_backup.init_from_movieclip(reinterpret_cast<MovieClip *>(id)); + break; + default: + break; + } + + /* Note that we never free GPU draw data from here since that's not + * safe for threading and draw data is likely to be re-used. */ + drawdata_ptr = DRW_drawdatalist_from_id(id); + if (drawdata_ptr != NULL) { + drawdata_backup = *drawdata_ptr; + drawdata_ptr->first = drawdata_ptr->last = NULL; + } +} + +void RuntimeBackup::restore_to_id(ID *id) +{ + const ID_Type id_type = GS(id->name); + switch (id_type) { + 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; + case ID_MC: + movieclip_backup.restore_to_movieclip(reinterpret_cast<MovieClip *>(id)); + break; + default: + break; + } + if (drawdata_ptr != NULL) { + *drawdata_ptr = drawdata_backup; + } +} + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.h new file mode 100644 index 00000000000..31ae3164e37 --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.h @@ -0,0 +1,55 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +#include "DNA_ID.h" + +#include "intern/eval/deg_eval_runtime_backup_movieclip.h" +#include "intern/eval/deg_eval_runtime_backup_object.h" +#include "intern/eval/deg_eval_runtime_backup_scene.h" +#include "intern/eval/deg_eval_runtime_backup_sound.h" + +namespace DEG { + +struct Depsgraph; + +class RuntimeBackup { + public: + explicit RuntimeBackup(const Depsgraph *depsgraph); + + /* NOTE: Will reset all runtime fields which has been backed up to NULL. */ + void init_from_id(ID *id); + + /* 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; + MovieClipBackup movieclip_backup; +}; + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.cc new file mode 100644 index 00000000000..c5744533083 --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.cc @@ -0,0 +1,49 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#include "intern/eval/deg_eval_runtime_backup_modifier.h" + +namespace DEG { + +ModifierDataBackupID::ModifierDataBackupID(const Depsgraph * /*depsgraph*/) + : ModifierDataBackupID(NULL, eModifierType_None) +{ +} + +ModifierDataBackupID::ModifierDataBackupID(ModifierData *modifier_data, ModifierType type) + : modifier_data(modifier_data), type(type) +{ +} + +bool ModifierDataBackupID::operator<(const ModifierDataBackupID &other) const +{ + if (modifier_data < other.modifier_data) { + return true; + } + if (modifier_data == other.modifier_data) { + return static_cast<int>(type) < static_cast<int>(other.type); + } + return false; +} + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.h new file mode 100644 index 00000000000..4b3d46126f3 --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.h @@ -0,0 +1,58 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +#include "BKE_modifier.h" + +#include "intern/depsgraph_type.h" + +struct ModifierData; + +namespace DEG { + +struct Depsgraph; + +/* Identifier used to match modifiers to backup/restore their runtime data. + * Identification is happening using original modifier data pointer and the + * modifier type. + * It is not enough to only pointer, since it's possible to have a situation + * when modifier is removed and a new one added, and due to memory allocation + * policy they might have same pointer. + * By adding type into matching we are at least ensuring that modifier will not + * try to interpret runtime data created by another modifier type. */ +class ModifierDataBackupID { + public: + ModifierDataBackupID(const Depsgraph *depsgraph); + ModifierDataBackupID(ModifierData *modifier_data, ModifierType type); + + bool operator<(const ModifierDataBackupID &other) const; + + ModifierData *modifier_data; + ModifierType type; +}; + +/* Storage for backed up runtime modifier data. */ +typedef map<ModifierDataBackupID, void *> ModifierRuntimeDataBackup; + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_movieclip.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_movieclip.cc new file mode 100644 index 00000000000..54838475bbf --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_movieclip.cc @@ -0,0 +1,61 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#include "intern/eval/deg_eval_runtime_backup_movieclip.h" + +#include "DNA_movieclip_types.h" + +#include "BLI_utildefines.h" + +namespace DEG { + +MovieClipBackup::MovieClipBackup(const Depsgraph * /*depsgraph*/) +{ + reset(); +} + +void MovieClipBackup::reset() +{ + anim = NULL; + cache = NULL; +} + +void MovieClipBackup::init_from_movieclip(MovieClip *movieclip) +{ + anim = movieclip->anim; + cache = movieclip->cache; + /* Clear pointers stored in the movie clip, so they are not freed when copied-on-written + * datablock is freed for re-allocation. */ + movieclip->anim = NULL; + movieclip->cache = NULL; +} + +void MovieClipBackup::restore_to_movieclip(MovieClip *movieclip) +{ + movieclip->anim = anim; + movieclip->cache = cache; + + reset(); +} + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_movieclip.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_movieclip.h new file mode 100644 index 00000000000..a9d528a254c --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_movieclip.h @@ -0,0 +1,48 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +struct anim; +struct MovieClip; +struct MovieClipCache; + +namespace DEG { + +struct Depsgraph; + +/* Backup of movie clip runtime data. */ +class MovieClipBackup { + public: + MovieClipBackup(const Depsgraph *depsgraph); + + void reset(); + + void init_from_movieclip(MovieClip *movieclip); + void restore_to_movieclip(MovieClip *movieclip); + + struct anim *anim; + struct MovieClipCache *cache; +}; + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc new file mode 100644 index 00000000000..a6a042f3e7b --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc @@ -0,0 +1,182 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#include "intern/eval/deg_eval_runtime_backup_object.h" + +#include <cstring> + +#include "DNA_mesh_types.h" + +#include "BLI_listbase.h" + +#include "BKE_action.h" +#include "BKE_object.h" + +namespace DEG { + +ObjectRuntimeBackup::ObjectRuntimeBackup(const Depsgraph * /*depsgraph*/) + : base_flag(0), base_local_view_bits(0) +{ + /* TODO(sergey): Use something like BKE_object_runtime_reset(). */ + memset(&runtime, 0, sizeof(runtime)); +} + +void ObjectRuntimeBackup::init_from_object(Object *object) +{ + /* Store evaluated mesh and curve_cache, and make sure we don't free it. */ + Mesh *mesh_eval = object->runtime.mesh_eval; + runtime = object->runtime; + BKE_object_runtime_reset(object); + /* Keep bbox (for now at least). */ + object->runtime.bb = runtime.bb; + /* Object update will override actual object->data to an evaluated version. + * Need to make sure we don't have data set to evaluated one before free + * anything. */ + if (mesh_eval != NULL && object->data == mesh_eval) { + object->data = runtime.mesh_orig; + } + /* Make a backup of base flags. */ + base_flag = object->base_flag; + base_local_view_bits = object->base_local_view_bits; + /* Backup tuntime data of all modifiers. */ + backup_modifier_runtime_data(object); + /* Backup runtime data of all pose channels. */ + backup_pose_channel_runtime_data(object); +} + +inline ModifierDataBackupID create_modifier_data_id(const ModifierData *modifier_data) +{ + return ModifierDataBackupID(modifier_data->orig_modifier_data, + static_cast<ModifierType>(modifier_data->type)); +} + +void ObjectRuntimeBackup::backup_modifier_runtime_data(Object *object) +{ + LISTBASE_FOREACH (ModifierData *, modifier_data, &object->modifiers) { + if (modifier_data->runtime == NULL) { + continue; + } + BLI_assert(modifier_data->orig_modifier_data != NULL); + ModifierDataBackupID modifier_data_id = create_modifier_data_id(modifier_data); + modifier_runtime_data.insert(make_pair(modifier_data_id, modifier_data->runtime)); + modifier_data->runtime = NULL; + } +} + +void ObjectRuntimeBackup::backup_pose_channel_runtime_data(Object *object) +{ + if (object->pose != NULL) { + LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { + /* This is NULL in Edit mode. */ + if (pchan->orig_pchan != NULL) { + pose_channel_runtime_data[pchan->orig_pchan] = pchan->runtime; + BKE_pose_channel_runtime_reset(&pchan->runtime); + } + } + } +} + +void ObjectRuntimeBackup::restore_to_object(Object *object) +{ + Mesh *mesh_orig = object->runtime.mesh_orig; + BoundBox *bb = object->runtime.bb; + object->runtime = runtime; + object->runtime.mesh_orig = mesh_orig; + object->runtime.bb = bb; + if (object->type == OB_MESH && object->runtime.mesh_eval != NULL) { + if (object->id.recalc & ID_RECALC_GEOMETRY) { + /* If geometry is tagged for update it means, that part of + * evaluated mesh are not valid anymore. In this case we can not + * have any "persistent" pointers to point to an invalid data. + * + * We restore object's data datablock to an original copy of + * that datablock. */ + object->data = mesh_orig; + + /* After that, immediately free the invalidated caches. */ + BKE_object_free_derived_caches(object); + } + else { + Mesh *mesh_eval = object->runtime.mesh_eval; + /* Do same thing as object update: override actual object data + * pointer with evaluated datablock. */ + object->data = mesh_eval; + /* Evaluated mesh simply copied edit_mesh pointer from + * original mesh during update, need to make sure no dead + * pointers are left behind. */ + mesh_eval->edit_mesh = mesh_orig->edit_mesh; + } + } + object->base_flag = base_flag; + object->base_local_view_bits = base_local_view_bits; + /* Restore modifier's runtime data. + * NOTE: Data of unused modifiers will be freed there. */ + restore_modifier_runtime_data(object); + restore_pose_channel_runtime_data(object); +} + +void ObjectRuntimeBackup::restore_modifier_runtime_data(Object *object) +{ + LISTBASE_FOREACH (ModifierData *, modifier_data, &object->modifiers) { + BLI_assert(modifier_data->orig_modifier_data != NULL); + ModifierDataBackupID modifier_data_id = create_modifier_data_id(modifier_data); + ModifierRuntimeDataBackup::iterator runtime_data_iterator = modifier_runtime_data.find( + modifier_data_id); + if (runtime_data_iterator != modifier_runtime_data.end()) { + modifier_data->runtime = runtime_data_iterator->second; + runtime_data_iterator->second = NULL; + } + } + for (ModifierRuntimeDataBackup::value_type value : modifier_runtime_data) { + const ModifierDataBackupID modifier_data_id = value.first; + void *runtime = value.second; + if (value.second == NULL) { + continue; + } + const ModifierTypeInfo *modifier_type_info = modifierType_getInfo(modifier_data_id.type); + BLI_assert(modifier_type_info != NULL); + modifier_type_info->freeRuntimeData(runtime); + } +} + +void ObjectRuntimeBackup::restore_pose_channel_runtime_data(Object *object) +{ + if (object->pose != NULL) { + LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { + /* This is NULL in Edit mode. */ + if (pchan->orig_pchan != NULL) { + PoseChannelRuntimeDataBackup::iterator runtime_data_iterator = + pose_channel_runtime_data.find(pchan->orig_pchan); + if (runtime_data_iterator != pose_channel_runtime_data.end()) { + pchan->runtime = runtime_data_iterator->second; + pose_channel_runtime_data.erase(runtime_data_iterator); + } + } + } + } + for (PoseChannelRuntimeDataBackup::value_type &value : pose_channel_runtime_data) { + BKE_pose_channel_runtime_free(&value.second); + } +} + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.h new file mode 100644 index 00000000000..e5c3d6a967a --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.h @@ -0,0 +1,59 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +#include "DNA_object_types.h" + +#include "intern/eval/deg_eval_runtime_backup_modifier.h" +#include "intern/eval/deg_eval_runtime_backup_pose.h" + +struct Object; + +namespace DEG { + +class ObjectRuntimeBackup { + public: + ObjectRuntimeBackup(const Depsgraph *depsgraph); + + /* Make a backup of object's evaluation runtime data, additionally + * make object to be safe for free without invalidating backed up + * pointers. */ + void init_from_object(Object *object); + void backup_modifier_runtime_data(Object *object); + void backup_pose_channel_runtime_data(Object *object); + + /* Restore all fields to the given object. */ + void restore_to_object(Object *object); + /* NOTE: Will free all runtime data which has not been restored. */ + void restore_modifier_runtime_data(Object *object); + void restore_pose_channel_runtime_data(Object *object); + + Object_Runtime runtime; + short base_flag; + unsigned short base_local_view_bits; + ModifierRuntimeDataBackup modifier_runtime_data; + PoseChannelRuntimeDataBackup pose_channel_runtime_data; +}; + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_pose.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_pose.cc new file mode 100644 index 00000000000..821cc21f359 --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_pose.cc @@ -0,0 +1,28 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#include "intern/eval/deg_eval_runtime_backup_pose.h" + +namespace DEG { + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_pose.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_pose.h new file mode 100644 index 00000000000..53a2c4c0784 --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_pose.h @@ -0,0 +1,37 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +#include "intern/depsgraph_type.h" + +#include "DNA_action_types.h" + +struct bPoseChannel; + +namespace DEG { + +/* Storage for backed up pose channel runtime data. */ +typedef map<bPoseChannel *, bPoseChannel_Runtime> PoseChannelRuntimeDataBackup; + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_scene.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_scene.cc new file mode 100644 index 00000000000..a288fb6ab92 --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_scene.cc @@ -0,0 +1,82 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#include "intern/eval/deg_eval_runtime_backup_scene.h" + +#include "DNA_scene_types.h" +#include "DNA_rigidbody_types.h" + +namespace DEG { + +SceneBackup::SceneBackup(const Depsgraph *depsgraph) : sequencer_backup(depsgraph) +{ + reset(); +} + +void SceneBackup::reset() +{ + sound_scene = NULL; + playback_handle = NULL; + sound_scrub_handle = NULL; + speaker_handles = NULL; + rigidbody_last_time = -1; +} + +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; + + if (scene->rigidbody_world != NULL) { + rigidbody_last_time = scene->rigidbody_world->ltime; + } + + /* 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; + + if (scene->rigidbody_world != NULL) { + scene->rigidbody_world->ltime = rigidbody_last_time; + } + + sequencer_backup.restore_to_scene(scene); + + reset(); +} + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_scene.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_scene.h new file mode 100644 index 00000000000..751bc4208d2 --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_scene.h @@ -0,0 +1,58 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +#include "intern/eval/deg_eval_runtime_backup_sequencer.h" + +struct Scene; + +namespace DEG { + +struct Depsgraph; + +/* Backup of scene runtime data. */ +class SceneBackup { + public: + SceneBackup(const Depsgraph *depsgraph); + + 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 restored: we just copy them over to a new scene. */ + void *sound_scene; + void *playback_handle; + void *sound_scrub_handle; + void *speaker_handles; + float rigidbody_last_time; + + SequencerBackup sequencer_backup; +}; + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequence.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequence.cc new file mode 100644 index 00000000000..0150281a4ef --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequence.cc @@ -0,0 +1,58 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#include "intern/eval/deg_eval_runtime_backup_sequence.h" + +#include "DNA_sequence_types.h" + +namespace DEG { + +SequenceBackup::SequenceBackup(const Depsgraph * /*depsgraph*/) +{ + reset(); +} + +void SequenceBackup::reset() +{ + scene_sound = NULL; +} + +void SequenceBackup::init_from_sequence(Sequence *sequence) +{ + scene_sound = sequence->scene_sound; + + sequence->scene_sound = NULL; +} + +void SequenceBackup::restore_to_sequence(Sequence *sequence) +{ + sequence->scene_sound = scene_sound; + reset(); +} + +bool SequenceBackup::isEmpty() const +{ + return (scene_sound == NULL); +} + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequence.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequence.h new file mode 100644 index 00000000000..8a762a2785e --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequence.h @@ -0,0 +1,47 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +struct Sequence; + +namespace DEG { + +struct Depsgraph; + +/* Backup of a single strip. */ +class SequenceBackup { + public: + SequenceBackup(const Depsgraph *depsgraph); + + void reset(); + + void init_from_sequence(Sequence *sequence); + void restore_to_sequence(Sequence *sequence); + + bool isEmpty() const; + + void *scene_sound; +}; + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.cc new file mode 100644 index 00000000000..08c2697aab3 --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.cc @@ -0,0 +1,72 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#include "intern/eval/deg_eval_runtime_backup_sequencer.h" + +#include "DNA_scene_types.h" +#include "DNA_sequence_types.h" + +#include "BKE_sequencer.h" +#include "BKE_sound.h" + +namespace DEG { + +SequencerBackup::SequencerBackup(const Depsgraph *depsgraph) : depsgraph(depsgraph) +{ +} + +void SequencerBackup::init_from_scene(Scene *scene) +{ + Sequence *sequence; + SEQ_BEGIN (scene->ed, sequence) { + SequenceBackup sequence_backup(depsgraph); + 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); + } + } +} + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.h new file mode 100644 index 00000000000..57b533a1b84 --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.h @@ -0,0 +1,49 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +#include "intern/eval/deg_eval_runtime_backup_sequence.h" +#include "intern/depsgraph_type.h" + +struct Scene; + +namespace DEG { + +struct Depsgraph; + +/* Backup of sequencer strips runtime data. */ +class SequencerBackup { + public: + SequencerBackup(const Depsgraph *depsgraph); + + void init_from_scene(Scene *scene); + void restore_to_scene(Scene *scene); + + const Depsgraph *depsgraph; + + typedef map<Sequence *, SequenceBackup> SequencesBackupMap; + SequencesBackupMap sequences_backup; +}; + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sound.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sound.cc new file mode 100644 index 00000000000..0c54032e32c --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sound.cc @@ -0,0 +1,64 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#include "intern/eval/deg_eval_runtime_backup_sound.h" + +#include "BLI_utildefines.h" + +#include "DNA_sound_types.h" + +namespace DEG { + +SoundBackup::SoundBackup(const Depsgraph * /*depsgraph*/) +{ + 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(); +} + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sound.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sound.h new file mode 100644 index 00000000000..87783146701 --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sound.h @@ -0,0 +1,47 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +struct bSound; + +namespace DEG { + +struct Depsgraph; + +/* Backup of sound datablocks runtime data. */ +class SoundBackup { + public: + SoundBackup(const Depsgraph *depsgraph); + + void reset(); + + void init_from_sound(bSound *sound); + void restore_to_sound(bSound *sound); + + void *cache; + void *waveform; + void *playback_handle; +}; + +} // namespace DEG |