diff --git a/app/node/block/block.cpp b/app/node/block/block.cpp index 5e5ed1156..4c31954f5 100644 --- a/app/node/block/block.cpp +++ b/app/node/block/block.cpp @@ -102,6 +102,9 @@ void Block::EdgeAddedSlot(NodeEdgePtr edge) // The blocks surrounding this one have changed, we need to Refresh() RefreshFollowing(); + + // Entire track will have shifted, so the whole cache needs to be re-validated + InvalidateCache(0, RATIONAL_MAX); } } @@ -127,8 +130,6 @@ void Block::Refresh() // Update out point by adding this clip's length to the just calculated in point out_point_ = in_point_ + length(); - InvalidateCache(nullptr, in_point_, out_point_); - emit Refreshed(); } @@ -176,7 +177,7 @@ void Block::set_media_in(const rational &media_in) media_in_ = media_in; // Signal that this clips contents have changed - InvalidateCache(nullptr, in(), out()); + InvalidateCache(in(), out()); } } diff --git a/app/node/block/clip/clip.cpp b/app/node/block/clip/clip.cpp index 6ffd423d2..8000c140b 100644 --- a/app/node/block/clip/clip.cpp +++ b/app/node/block/clip/clip.cpp @@ -86,7 +86,7 @@ QVariant ClipBlock::Value(NodeOutput* param, const rational& time) return Block::Value(param, time); } -void ClipBlock::InvalidateCache(NodeInput *from, const rational &start_range, const rational &end_range) +void ClipBlock::InvalidateCache(const rational &start_range, const rational &end_range, NodeInput *from) { // If signal is from texture input, transform all times from media time to sequence time if (from == texture_input_) { @@ -97,10 +97,10 @@ void ClipBlock::InvalidateCache(NodeInput *from, const rational &start_range, co start = qMax(start, in()); end = qMin(end, out()); - Node::InvalidateCache(from, start, end); + Node::InvalidateCache(start, end, from); } else { // Otherwise, pass signal along normally - Node::InvalidateCache(from, start_range, end_range); + Node::InvalidateCache(start_range, end_range, from); } } diff --git a/app/node/block/clip/clip.h b/app/node/block/clip/clip.h index ae5005216..c701b3878 100644 --- a/app/node/block/clip/clip.h +++ b/app/node/block/clip/clip.h @@ -42,7 +42,7 @@ public: NodeInput* texture_input(); - virtual void InvalidateCache(NodeInput *from, const rational &start_range, const rational &end_range) override; + virtual void InvalidateCache(const rational &start_range, const rational &end_range, NodeInput *from = nullptr) override; virtual QList RunDependencies(NodeOutput *output, const rational &time) override; diff --git a/app/node/node.cpp b/app/node/node.cpp index ae987e1ae..641567f81 100644 --- a/app/node/node.cpp +++ b/app/node/node.cpp @@ -65,7 +65,7 @@ void Node::RemoveParameter(NodeParam *param) delete param; } -void Node::InvalidateCache(NodeInput* from, const rational &start_range, const rational &end_range) +void Node::InvalidateCache(const rational &start_range, const rational &end_range, NodeInput *from) { Q_UNUSED(from) @@ -91,7 +91,7 @@ void Node::InvalidateCache(NodeInput* from, const rational &start_range, const r edge->output()->ClearCachedValue(); // Send clear cache signal to the Node - connected_node->InvalidateCache(connected_input, start_range, end_range); + connected_node->InvalidateCache(start_range, end_range, connected_input); } } } @@ -326,5 +326,5 @@ bool Node::HasParamWithID(const QString &id) void Node::InputChanged(rational start, rational end) { - InvalidateCache(static_cast(sender()), start, end); + InvalidateCache(start, end, static_cast(sender())); } diff --git a/app/node/node.h b/app/node/node.h index a908e1340..b6475c31e 100644 --- a/app/node/node.h +++ b/app/node/node.h @@ -173,7 +173,7 @@ public: * the DAG. Even if the time needs to be transformed somehow (e.g. converting media time to sequence time), you can * call this function with transformed time and relay the signal that way. */ - virtual void InvalidateCache(NodeInput* from, const rational& start_range, const rational& end_range); + virtual void InvalidateCache(const rational& start_range, const rational& end_range, NodeInput* from = nullptr); protected: /** diff --git a/app/node/output/track/track.cpp b/app/node/output/track/track.cpp index 277a1c95e..cb69dc23a 100644 --- a/app/node/output/track/track.cpp +++ b/app/node/output/track/track.cpp @@ -26,7 +26,8 @@ #include "node/graph.h" TrackOutput::TrackOutput() : - current_block_(this) + current_block_(this), + block_invalidate_cache_stack_(0) { track_input_ = new NodeInput("track_in"); track_input_->add_data_input(NodeParam::kTrack); @@ -148,7 +149,13 @@ NodeOutput* TrackOutput::track_output() return track_output_; } -#include "render/rendertexture.h" +void TrackOutput::InvalidateCache(const rational &start_range, const rational &end_range, NodeInput *from) +{ + // We intercept IC signals from Blocks since we may be performing several options and they may over-signal + if (!block_invalidate_cache_stack_) { + Node::InvalidateCache(qMax(start_range, rational(0)), qMin(end_range, in()), from); + } +} QVariant TrackOutput::Value(NodeOutput *output, const rational &time) { @@ -247,11 +254,18 @@ void TrackOutput::AppendBlock(Block *block) { AddBlockToGraph(block); + BlockInvalidateCache(); + if (block_cache_.isEmpty()) { ConnectBlockInternal(block); } else { InsertBlockBetweenBlocks(block, block_cache_.last(), this); } + + UnblockInvalidateCache(); + + // Invalidate area that block was added to + InvalidateCache(block->in(), in()); } void TrackOutput::ConnectBlockInternal(Block *block) @@ -289,6 +303,16 @@ void TrackOutput::ValidateCurrentBlock(const rational &time) } } +void TrackOutput::BlockInvalidateCache() +{ + block_invalidate_cache_stack_++; +} + +void TrackOutput::UnblockInvalidateCache() +{ + block_invalidate_cache_stack_--; +} + void TrackOutput::PlaceBlock(Block *block, rational start) { if (block_cache_.contains(block) && block->in() == start) { @@ -299,20 +323,14 @@ void TrackOutput::PlaceBlock(Block *block, rational start) // Check if the placement location is past the end of the timeline if (start >= in()) { - GapBlock* gap = nullptr; - if (start > in()) { // If so, insert a gap here - gap = new GapBlock(); + GapBlock* gap = new GapBlock(); gap->set_length(start - in()); + AppendBlock(gap); } - InsertBlockBefore(block, this); - - if (gap != nullptr) { - // Insert gap if we made one before - InsertBlockBefore(gap, block); - } + AppendBlock(block); return; } @@ -365,6 +383,8 @@ Block* TrackOutput::SplitBlock(Block *block, rational time) return nullptr; } + BlockInvalidateCache(); + rational original_length = block->length(); block->set_length(time - block->in()); @@ -373,6 +393,8 @@ Block* TrackOutput::SplitBlock(Block *block, rational time) copy->set_length(original_length - block->length()); InsertBlockAfter(copy, block); + UnblockInvalidateCache(); + return copy; } @@ -477,9 +499,13 @@ void TrackOutput::RippleRemoveArea(rational in, rational out, Block *insert) void TrackOutput::ReplaceBlock(Block *old, Block *replace) { + Q_ASSERT(old->length() == replace->length()); + Block* previous = old->previous(); Block* next = old->next(); + BlockInvalidateCache(); + AddBlockToGraph(replace); // Disconnect old block from its surroundings @@ -492,4 +518,8 @@ void TrackOutput::ReplaceBlock(Block *old, Block *replace) Block::DisconnectBlocks(old, next); Block::ConnectBlocks(replace, next); } + + UnblockInvalidateCache(); + + InvalidateCache(replace->in(), replace->out()); } diff --git a/app/node/output/track/track.h b/app/node/output/track/track.h index c88705494..d189a3207 100644 --- a/app/node/output/track/track.h +++ b/app/node/output/track/track.h @@ -61,6 +61,8 @@ public: NodeOutput* track_output(); + virtual void InvalidateCache(const rational& start_range, const rational& end_range, NodeInput* from = nullptr) override; + /** * @brief Adds Block `block` at the very beginning of the Sequence before all other clips */ @@ -145,7 +147,7 @@ public: /** * @brief Replaces Block `old` with Block `replace` * - * Makes no modification to the lengths of either Blocks + * Both blocks must have equal lengths. */ void ReplaceBlock(Block* old, Block* replace); @@ -186,6 +188,9 @@ private: */ void ValidateCurrentBlock(const rational& time); + void BlockInvalidateCache(); + void UnblockInvalidateCache(); + Block* attached_block(); QVector block_cache_; @@ -196,6 +201,8 @@ private: NodeOutput* track_output_; + int block_invalidate_cache_stack_; + private slots: }; diff --git a/app/node/output/viewer/viewer.cpp b/app/node/output/viewer/viewer.cpp index 9eefb59a2..50ad35abd 100644 --- a/app/node/output/viewer/viewer.cpp +++ b/app/node/output/viewer/viewer.cpp @@ -78,12 +78,12 @@ void ViewerOutput::AttachViewer(ViewerPanel *viewer) } } -void ViewerOutput::InvalidateCache(NodeInput* from, const rational &start_range, const rational &end_range) +void ViewerOutput::InvalidateCache(const rational &start_range, const rational &end_range, NodeInput *from) { // Update any attached viewer UpdateViewer(); - Node::InvalidateCache(from, start_range, end_range); + Node::InvalidateCache(start_range, end_range, from); } void ViewerOutput::UpdateViewer() diff --git a/app/node/output/viewer/viewer.h b/app/node/output/viewer/viewer.h index b1b628515..3a0f8a73c 100644 --- a/app/node/output/viewer/viewer.h +++ b/app/node/output/viewer/viewer.h @@ -47,7 +47,7 @@ public: void AttachViewer(ViewerPanel* viewer); - virtual void InvalidateCache(NodeInput* from, const rational &start_range, const rational &end_range) override; + virtual void InvalidateCache(const rational &start_range, const rational &end_range, NodeInput *from = nullptr) override; protected: virtual QVariant Value(NodeOutput* output, const rational& time) override; diff --git a/app/node/processor/renderer/renderer.cpp b/app/node/processor/renderer/renderer.cpp index 0d04e35a6..577947207 100644 --- a/app/node/processor/renderer/renderer.cpp +++ b/app/node/processor/renderer/renderer.cpp @@ -124,7 +124,7 @@ void RendererProcessor::Release() Stop(); } -void RendererProcessor::InvalidateCache(NodeInput* from, const rational &start_range, const rational &end_range) +void RendererProcessor::InvalidateCache(const rational &start_range, const rational &end_range, NodeInput *from) { Q_UNUSED(from) @@ -362,9 +362,9 @@ void RendererProcessor::DownloadThreadFinished(const rational& time) texture_output_->ClearCachedValue(); foreach (NodeEdgePtr edge, edges) { - edge->input()->parent()->InvalidateCache(edge->input(), + edge->input()->parent()->InvalidateCache(time, time, - time); + edge->input()); } } } diff --git a/app/node/processor/renderer/renderer.h b/app/node/processor/renderer/renderer.h index 4a60717d6..c60fa54fa 100644 --- a/app/node/processor/renderer/renderer.h +++ b/app/node/processor/renderer/renderer.h @@ -53,7 +53,7 @@ public: virtual void Release() override; - virtual void InvalidateCache(NodeInput *from, const rational &start_range, const rational &end_range) override; + virtual void InvalidateCache(const rational &start_range, const rational &end_range, NodeInput *from = nullptr) override; void SetTimebase(const rational& timebase);