diff --git a/app/core.cpp b/app/core.cpp index d66495ed5..9a12dd5c5 100644 --- a/app/core.cpp +++ b/app/core.cpp @@ -327,6 +327,7 @@ void Core::AddOpenProject(ProjectPtr p) void Core::DeclareTypesForQt() { qRegisterMetaType("Task::Status"); + qRegisterMetaType(); } void Core::StartGUI(bool full_screen) diff --git a/app/node/CMakeLists.txt b/app/node/CMakeLists.txt index 7ab867338..8d3af812e 100644 --- a/app/node/CMakeLists.txt +++ b/app/node/CMakeLists.txt @@ -23,6 +23,8 @@ add_subdirectory(processor) set(OLIVE_SOURCES ${OLIVE_SOURCES} + node/dependency.h + node/dependency.cpp node/edge.h node/edge.cpp node/graph.h diff --git a/app/node/processor/renderer/rendererprobe.h b/app/node/dependency.cpp similarity index 66% rename from app/node/processor/renderer/rendererprobe.h rename to app/node/dependency.cpp index 83d09cb5f..a98117a57 100644 --- a/app/node/processor/renderer/rendererprobe.h +++ b/app/node/dependency.cpp @@ -18,22 +18,25 @@ ***/ -#ifndef RENDERERPROBE_H -#define RENDERERPROBE_H +#include "dependency.h" -#include "node/node.h" -#include "renderpath.h" - -class RendererProbe +NodeDependency::NodeDependency() : + node_(nullptr) { -public: - RendererProbe(); +} - static RenderPath ProbeNode(Node* node, int thread_count, const rational &time); +NodeDependency::NodeDependency(NodeOutput *node, const rational &time) : + node_(node), + time_(time) +{ +} -private: - static void TraverseNode(RenderPath& path, Node* node, const rational& time, int thread, int index); +NodeOutput *NodeDependency::node() const +{ + return node_; +} -}; - -#endif // RENDERERPROBE_H +const rational& NodeDependency::time() const +{ + return time_; +} diff --git a/app/node/dependency.h b/app/node/dependency.h new file mode 100644 index 000000000..7fa719173 --- /dev/null +++ b/app/node/dependency.h @@ -0,0 +1,44 @@ +/*** + + Olive - Non-Linear Video Editor + Copyright (C) 2019 Olive Team + + 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 3 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, see . + +***/ + +#ifndef NODEDEPENDENCY_H +#define NODEDEPENDENCY_H + +#include + +#include "common/rational.h" +#include "node/output.h" + +class NodeDependency { +public: + NodeDependency(); + NodeDependency(NodeOutput* node, const rational& time); + + NodeOutput* node() const; + const rational& time() const; + +private: + NodeOutput* node_; + rational time_; +}; + +Q_DECLARE_METATYPE(NodeDependency) + +#endif // NODEDEPENDENCY_H diff --git a/app/node/input.cpp b/app/node/input.cpp index 5ac9a1ced..e42df1aa4 100644 --- a/app/node/input.cpp +++ b/app/node/input.cpp @@ -24,7 +24,6 @@ NodeInput::NodeInput(const QString& id) : NodeParam(id), - time_(-1), keyframing_(false) { // Have at least one keyframe/value active at any time @@ -51,23 +50,51 @@ bool NodeInput::can_accept_type(const NodeParam::DataType &data_type) return AreDataTypesCompatible(data_type, inputs_); } +NodeOutput *NodeInput::get_connected_output() +{ + if (!edges_.isEmpty()) { + return edges_.first()->output(); + } + + return nullptr; +} + +Node *NodeInput::get_connected_node() +{ + NodeOutput* output = get_connected_output(); + + if (output != nullptr) { + return output->parent(); + } + + return nullptr; +} + QVariant NodeInput::get_value(const rational& time) { + QVariant v; + + lock_.lock(); + if (time_ != time) { // Retrieve the value if (!edges_.isEmpty()) { - // One connection - use the output of the connected Node + // A connection - use the output of the connected Node value_ = edges_.first()->output()->get_value(time); + } else { + // No connections - use the internal value + // FIXME: Re-implement keyframing + value_ = keyframes_.first().value(); } - // No connections - use the internal value - // FIXME: Re-implement keyframing - value_ = keyframes_.first().value(); - time_ = time; } - return value_; + v = value_; + + lock_.unlock(); + + return v; } void NodeInput::set_value(const QVariant &value) diff --git a/app/node/input.h b/app/node/input.h index c33cc0894..03936532b 100644 --- a/app/node/input.h +++ b/app/node/input.h @@ -54,6 +54,24 @@ public: */ bool can_accept_type(const DataType& data_type); + /** + * @brief If this input is connected to an output, retrieve the output parameter + * + * @return + * + * The output parameter if connected or nullptr if not + */ + NodeOutput* get_connected_output(); + + /** + * @brief If this input is connected to an output, retrieve the Node whose output is connected + * + * @return + * + * The connected Node if connected or nullptr if not + */ + Node* get_connected_node(); + /** * @brief Get the value at a given time * @@ -109,16 +127,6 @@ private: */ QList keyframes_; - /** - * @brief Currently cached value - */ - QVariant value_; - - /** - * @brief Last timecode that a value was requested with - */ - rational time_; - /** * @brief Internal keyframing enabled setting */ diff --git a/app/node/node.cpp b/app/node/node.cpp index ea0686014..9ad9323c1 100644 --- a/app/node/node.cpp +++ b/app/node/node.cpp @@ -232,11 +232,18 @@ QList Node::RunDependencies(NodeOutput *output, const rational & { Q_UNUSED(output) - QList immediate_deps = GetImmediateDependencies(); + QList params = parameters(); QList run_deps; - foreach (Node* dep, immediate_deps) { - run_deps.append(NodeDependency(dep, time)); + foreach (NodeParam* p, params) { + if (p->type() == NodeParam::kInput) { + NodeOutput* potential_dep = static_cast(p)->get_connected_output(); + + if (potential_dep != nullptr) { + run_deps.append(NodeDependency(potential_dep, time)); + } + } + } return run_deps; @@ -280,19 +287,3 @@ bool Node::HasParamWithID(const QString &id) return false; } - -NodeDependency::NodeDependency(Node *node, const rational &time) : - node_(node), - time_(time) -{ -} - -Node *NodeDependency::node() -{ - return node_; -} - -rational NodeDependency::time() -{ - return time_; -} diff --git a/app/node/node.h b/app/node/node.h index 17c457fb8..cca6967ed 100644 --- a/app/node/node.h +++ b/app/node/node.h @@ -25,21 +25,10 @@ #include #include "common/rational.h" +#include "node/dependency.h" #include "node/input.h" #include "node/output.h" -class NodeDependency { -public: - NodeDependency(Node* node, const rational& time); - - Node* node(); - rational time(); - -private: - Node* node_; - rational time_; -}; - /** * @brief A single processing unit that can be connected with others to create intricate processing systems * diff --git a/app/node/output.cpp b/app/node/output.cpp index 5afd6cfb3..17ffef804 100644 --- a/app/node/output.cpp +++ b/app/node/output.cpp @@ -23,8 +23,7 @@ #include "node/node.h" NodeOutput::NodeOutput(const QString &id) : - NodeParam(id), - time_(-1) + NodeParam(id) { } @@ -48,8 +47,12 @@ void NodeOutput::set_data_type(const NodeParam::DataType &type) } } -const QVariant &NodeOutput::get_value(const rational& time) +QVariant NodeOutput::get_value(const rational& time) { + QVariant v; + + lock_.lock(); + if (time_ != time) { // Update the value value_ = parent()->Run(this, time); @@ -57,6 +60,10 @@ const QVariant &NodeOutput::get_value(const rational& time) time_ = time; } - // The value should be have been set by this point - return value_; + v = value_; + + lock_.unlock(); + + return v; } + diff --git a/app/node/output.h b/app/node/output.h index a86559bcd..45d9ee5ea 100644 --- a/app/node/output.h +++ b/app/node/output.h @@ -61,14 +61,11 @@ public: * In many cases for efficiency, the Node can also ignore this request if it knows the output data will not change * (i.e. if the time has not changed from the last Process()). */ - virtual const QVariant& get_value(const rational &time); + virtual QVariant get_value(const rational &time); private: DataType data_type_; - QVariant value_; - - rational time_; }; #endif // NODEOUTPUT_H diff --git a/app/node/output/track/track.cpp b/app/node/output/track/track.cpp index 320244239..a58e80351 100644 --- a/app/node/output/track/track.cpp +++ b/app/node/output/track/track.cpp @@ -107,7 +107,7 @@ QList TrackOutput::RunDependencies(NodeOutput* output, const rat ValidateCurrentBlock(time); if (current_block_ != this) { - deps.append(NodeDependency(current_block_, time)); + deps.append(NodeDependency(current_block_->texture_output(), time)); } } diff --git a/app/node/output/viewer/viewer.cpp b/app/node/output/viewer/viewer.cpp index 8199260d6..a37f2012d 100644 --- a/app/node/output/viewer/viewer.cpp +++ b/app/node/output/viewer/viewer.cpp @@ -20,8 +20,6 @@ #include "viewer.h" -#include "render/rendertexture.h" - ViewerOutput::ViewerOutput() : attached_viewer_(nullptr) { @@ -83,11 +81,17 @@ void ViewerOutput::AttachViewer(ViewerPanel *viewer) void ViewerOutput::InvalidateCache(const rational &start_range, const rational &end_range) { // Update any attached viewer - ViewerTimeChanged(current_time_); + UpdateViewer(); Node::InvalidateCache(start_range, end_range); } +void ViewerOutput::UpdateViewer() +{ + texture_input_->ClearCachedValue(); + ViewerTimeChanged(current_time_); +} + QVariant ViewerOutput::Value(NodeOutput *output, const rational &time) { Q_UNUSED(output) diff --git a/app/node/output/viewer/viewer.h b/app/node/output/viewer/viewer.h index ae4b8ddaf..2eecb758a 100644 --- a/app/node/output/viewer/viewer.h +++ b/app/node/output/viewer/viewer.h @@ -23,6 +23,7 @@ #include "node/node.h" #include "panel/viewer/viewer.h" +#include "render/rendertexture.h" /** * @brief A bridge between a node system and a ViewerPanel diff --git a/app/node/param.cpp b/app/node/param.cpp index 810f0a6b3..68d775ae9 100644 --- a/app/node/param.cpp +++ b/app/node/param.cpp @@ -27,6 +27,7 @@ #include "node/output.h" NodeParam::NodeParam(const QString &id) : + time_(-1), id_(id) { Q_ASSERT(!id_.isEmpty()); @@ -151,6 +152,8 @@ NodeEdgePtr NodeParam::ConnectEdge(NodeOutput *output, NodeInput *input) output->edges_.append(edge); input->edges_.append(edge); + input->ClearCachedValue(); + // Emit a signal than an edge was added (only one signal needs emitting) emit input->EdgeAdded(edge); @@ -165,6 +168,8 @@ void NodeParam::DisconnectEdge(NodeEdgePtr edge) output->edges_.removeAll(edge); input->edges_.removeAll(edge); + input->ClearCachedValue(); + emit input->EdgeRemoved(edge); } @@ -214,3 +219,10 @@ QString NodeParam::GetDefaultDataTypeName(const DataType& type) return QString(); } + +void NodeParam::ClearCachedValue() +{ + // Since get_value() will (read: should) never receive a negative number, this will effectively invalidate any value + // currently cached + time_ = -1; +} diff --git a/app/node/param.h b/app/node/param.h index 573c33f70..65b2044db 100644 --- a/app/node/param.h +++ b/app/node/param.h @@ -21,6 +21,7 @@ #ifndef NODEPARAM_H #define NODEPARAM_H +#include #include #include #include @@ -202,6 +203,11 @@ public: */ static QString GetDefaultDataTypeName(const DataType &type); + /** + * @brief Clear the cached value + */ + void ClearCachedValue(); + signals: /** * @brief Signal emitted when an edge is added to this parameter @@ -225,6 +231,21 @@ protected: */ QVector edges_; + /** + * @brief Used for thread safety + */ + QMutex lock_; + + /** + * @brief Currently cached value + */ + QVariant value_; + + /** + * @brief Last timecode that a value was requested with + */ + rational time_; + private: /** * @brief Internal name string diff --git a/app/node/processor/renderer/CMakeLists.txt b/app/node/processor/renderer/CMakeLists.txt index 64d6f7a16..6f78b5cc4 100644 --- a/app/node/processor/renderer/CMakeLists.txt +++ b/app/node/processor/renderer/CMakeLists.txt @@ -16,12 +16,8 @@ set(OLIVE_SOURCES ${OLIVE_SOURCES} - node/processor/renderer/renderpath.h - node/processor/renderer/renderpath.cpp node/processor/renderer/renderer.h node/processor/renderer/renderer.cpp - node/processor/renderer/rendererprobe.h - node/processor/renderer/rendererprobe.cpp node/processor/renderer/rendererthread.h node/processor/renderer/rendererthread.cpp PARENT_SCOPE diff --git a/app/node/processor/renderer/renderer.cpp b/app/node/processor/renderer/renderer.cpp index 545b934cf..346a22036 100644 --- a/app/node/processor/renderer/renderer.cpp +++ b/app/node/processor/renderer/renderer.cpp @@ -27,9 +27,6 @@ #include #include -#include "renderpath.h" -#include "rendererprobe.h" - RendererProcessor::RendererProcessor() : started_(false), width_(0), @@ -208,6 +205,7 @@ void RendererProcessor::Start() // Ensure this connection is "Queued" so that it always runs in this object's threaded rather than any of the // other threads connect(threads_[i].get(), SIGNAL(FinishedPath()), this, SLOT(ThreadCallback()), Qt::QueuedConnection); + connect(threads_[i].get(), SIGNAL(RequestSibling(NodeDependency)), this, SLOT(ThreadRequestSibling(NodeDependency)), Qt::QueuedConnection); } started_ = true; @@ -259,44 +257,11 @@ void RendererProcessor::CacheNext() qDebug() << "Caching" << time_to_cache.toDouble(); - Node* node_to_cache = texture_input_->edges().first()->output()->parent(); - - // Set graph time - //node_to_cache->set_time(time_to_cache); - // Run this probe in another thread - RenderPath path = RendererProbe::ProbeNode(node_to_cache, threads_.size(), time_to_cache); - - cache_return_count_ = 0; - - for (int i=0;iQueue(path.GetThreadPath(i), time_to_cache); - } + master_thread_ = threads_.at(0).get(); + master_thread_->Queue(NodeDependency(texture_input_->get_connected_output(), time_to_cache), true); caching_ = true; - - /* - - - bool caching = false; - - // Look for a thread that's available - for (int i=0;iQueue(node_to_cache, time_to_cache)) { - // This thread is free and we've just taken control of it - caching = true; - break; - } - } - - if (caching) { - cache_queue_.removeFirst(); - - qDebug() << "[RendererProcessor] Ready to cache" << time_to_cache.numerator() << "/" << time_to_cache.denominator(); - } - */ } // FIXME: Test code only @@ -305,21 +270,26 @@ void RendererProcessor::CacheNext() void RendererProcessor::ThreadCallback() { - cache_return_count_++; - - if (cache_return_count_ == threads_.size()) { + if (sender() == master_thread_) { // Threads are all done now, time to proceed caching_ = false; - // FIXME: Test code only - // Signal update to viewer - static_cast(texture_output()->edges().first()->input()->parent())->InvalidateCache(0, 0); - // End test code + // FIXME: Save the texture results here CacheNext(); } } +void RendererProcessor::ThreadRequestSibling(NodeDependency dep) +{ + // Try to queue another thread to run this dep in advance + for (int i=0;iQueue(dep, false)) { + return; + } + } +} + RendererThread* RendererProcessor::CurrentThread() { return dynamic_cast(QThread::currentThread()); diff --git a/app/node/processor/renderer/renderer.h b/app/node/processor/renderer/renderer.h index 650e4b896..1a864b3cd 100644 --- a/app/node/processor/renderer/renderer.h +++ b/app/node/processor/renderer/renderer.h @@ -149,11 +149,13 @@ private: qint64 cache_time_; QString cache_id_; bool caching_; - int cache_return_count_; + RendererThread* master_thread_; private slots: void ThreadCallback(); + void ThreadRequestSibling(NodeDependency dep); + }; #endif // RENDERER_H diff --git a/app/node/processor/renderer/rendererprobe.cpp b/app/node/processor/renderer/rendererprobe.cpp deleted file mode 100644 index f7e2651f2..000000000 --- a/app/node/processor/renderer/rendererprobe.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/*** - - Olive - Non-Linear Video Editor - Copyright (C) 2019 Olive Team - - 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 3 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, see . - -***/ - -#include "rendererprobe.h" - -#include - -RendererProbe::RendererProbe() -{ - -} - -RenderPath RendererProbe::ProbeNode(Node *node, int thread_count, const rational& time) -{ - Q_ASSERT(thread_count > 0); - - RenderPath render_path(thread_count); - - TraverseNode(render_path, node, time, 0, 0); - - render_path.Finalize(); - - return render_path; -} - -void RendererProbe::TraverseNode(RenderPath& path, Node *node, const rational& time, int thread, int index) -{ - Q_UNUSED(path) - Q_UNUSED(node) - Q_UNUSED(time) - Q_UNUSED(thread) - Q_UNUSED(index) - /*bool can_take_node = true; - - if (path.ContainsNode(node) >= 0) { - if (path.NodeIndex(node) < index) { - // If the other thread's index is smaller, it means we can do it earlier here so we should "steal" it - qDebug() << "Stealing" << node << "to" << thread; - path.RemoveEntry(node); - } else { - // Otherwise, we'll be delaying it and there's no point to that - can_take_node = false; - } - } - - // Add this node to the thread path - if (can_take_node) { - qDebug() << node << "will run on thread" << thread << "at index" << index; - path.AddEntry(node, thread, index); - } - - QList deps = node->RunDependencies(nullptr, time); - - // Print debugging information - foreach (Node* dep, deps) { - qDebug() << " Dependency found:" << dep; - } - - int next_index = index + 1; - - foreach (Node* dep, deps) { - int ideal_thread = path.FindAvailableThreadAtIndex(index); - - // FIXME: This will throw this thread's index off by one, test whether this is okay - int run_thread = (ideal_thread == -1) ? thread : ideal_thread; - - TraverseNode(path, dep, time, run_thread, next_index); - }*/ -} diff --git a/app/node/processor/renderer/rendererthread.cpp b/app/node/processor/renderer/rendererthread.cpp index ef1686174..9ba2e939c 100644 --- a/app/node/processor/renderer/rendererthread.cpp +++ b/app/node/processor/renderer/rendererthread.cpp @@ -33,14 +33,17 @@ RendererThread::RendererThread(QOpenGLContext *share_ctx, const int &width, cons { } -void RendererThread::Queue(const RenderThreadPath &path, const rational& time) +bool RendererThread::Queue(const NodeDependency& dep, bool wait) { - // Wait for thread to be available - mutex_.lock(); + if (wait) { + // Wait for thread to be available + mutex_.lock(); + } else if (!mutex_.tryLock()) { + return false; + } // We can now change params without the other thread using them - path_ = path; - time_ = time; + path_ = dep; // Prepare to wait for thread to respond caller_mutex_.lock(); @@ -52,6 +55,8 @@ void RendererThread::Queue(const RenderThreadPath &path, const rational& time) // Wait for thread to start before returning wait_cond_.wait(&caller_mutex_); caller_mutex_.unlock(); + + return true; } void RendererThread::Cancel() @@ -97,9 +102,20 @@ void RendererThread::run() caller_mutex_.unlock(); // Process the Node - /*for (int i=path_.size()-1;i>=0;i--) { - path_.at(i)->Run(); - }*/ + NodeOutput* output_to_process = path_.node(); + Node* node_to_process = output_to_process->parent(); + + QList deps = node_to_process->RunDependencies(output_to_process, path_.time()); + + // Ask for other threads to run these deps while we're here + if (!deps.isEmpty()) { + for (int i=1;iget_value(path_.time()); emit FinishedPath(); } @@ -115,8 +131,6 @@ void RendererThread::run() void RendererThread::StartThread(QThread::Priority priority) { - path_.clear(); - caller_mutex_.lock(); // Start the thread diff --git a/app/node/processor/renderer/rendererthread.h b/app/node/processor/renderer/rendererthread.h index 0f9abe3a1..6b3840cb8 100644 --- a/app/node/processor/renderer/rendererthread.h +++ b/app/node/processor/renderer/rendererthread.h @@ -28,7 +28,6 @@ #include "node/node.h" #include "render/renderinstance.h" -#include "renderpath.h" class RendererThread : public QThread { @@ -40,7 +39,7 @@ public: const olive::PixelFormat& format, const olive::RenderMode& mode); - void Queue(const RenderThreadPath& path, const rational &time); + bool Queue(const NodeDependency &dep, bool wait); void Cancel(); @@ -51,6 +50,8 @@ public: void StartThread(Priority priority = InheritPriority); signals: + void RequestSibling(NodeDependency dep); + void FinishedPath(); private: @@ -62,7 +63,7 @@ private: QMutex caller_mutex_; - RenderThreadPath path_; + NodeDependency path_; rational time_; diff --git a/app/node/processor/renderer/renderpath.cpp b/app/node/processor/renderer/renderpath.cpp deleted file mode 100644 index 4f0e4739b..000000000 --- a/app/node/processor/renderer/renderpath.cpp +++ /dev/null @@ -1,88 +0,0 @@ -#include "renderpath.h" - -RenderPath::RenderPath(int max_threads) : - finalized_(false) -{ - Q_ASSERT(max_threads > 0); - - render_path_.resize(max_threads); -} - -void RenderPath::AddEntry(Node *node, int thread, int index) -{ - if (finalized_) { - return; - } - - RenderThreadPath& thread_path = render_path_[thread]; - - // Make sure there are enough indices for this entry - while (thread_path.size() < index) { - thread_path.append(nullptr); - } - - thread_path.append(node); - thread_map_.insert(node, thread); -} - -void RenderPath::RemoveEntry(Node *node) -{ - if (finalized_) { - return; - } - - Q_ASSERT(thread_map_.contains(node)); - - int node_thread = thread_map_[node]; - - render_path_[node_thread].replace(NodeIndexInThread(node, node_thread), nullptr); - thread_map_.remove(node); -} - -int RenderPath::ContainsNode(Node *node) -{ - if (thread_map_.contains(node)) { - return thread_map_[node]; - } - return -1; -} - -int RenderPath::NodeIndex(Node *node) -{ - if (thread_map_.contains(node)) { - return NodeIndexInThread(node, thread_map_[node]); - } - return -1; -} - -int RenderPath::NodeIndexInThread(Node *node, int thread) -{ - return render_path_[thread].indexOf(node); -} - -void RenderPath::Finalize() -{ - for (int i=0;i& thread_path_ = render_path_[i]; - - if (index >= thread_path_.size() || thread_path_.at(index) == nullptr) { - return i; - } - } - - return -1; -} - -RenderThreadPath &RenderPath::GetThreadPath(int thread) -{ - return render_path_[thread]; -} diff --git a/app/node/processor/renderer/renderpath.h b/app/node/processor/renderer/renderpath.h deleted file mode 100644 index 03b924b14..000000000 --- a/app/node/processor/renderer/renderpath.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef RENDERPATH_H -#define RENDERPATH_H - -#include - -#include "node/node.h" - -using RenderThreadPath = QVector; - -class RenderPath -{ -public: - RenderPath(int max_threads); - - /** - * @brief Add a Node to this thread at this index - * - * The Node is guaranteed to be added to at least this index. The index may be higher if this thread has other Nodes - * taking up this index, but it will never be lower. - */ - void AddEntry(Node* node, int thread, int index); - - /** - * @brief Removes a Node, replacing its entry with nullptr - * - * This function asserts whether the Node was added initially to help aid bug detection. - * - * @param node - */ - void RemoveEntry(Node* node); - - /** - * @brief Determine whether the RenderPath already contains this Node - * - * @return - * - * The thread index if one contains this Node, or -1 if none of them do - */ - int ContainsNode(Node* node); - - /** - * @brief Determine what index a Node has in whatever thread it's in - * - * @return - * - * The Node's index in its thread, or -1 if no threads have this Node. - */ - int NodeIndex(Node* node); - - /** - * @brief Determine what index a Node has in a particular thread - * - * @return - * - * The Node's index in this thread, or -1 if this thread does not have this Node. - */ - int NodeIndexInThread(Node* node, int thread); - - /** - * @brief Finalize the render path ready for executing - * - * Probing uses indices to determine what Nodes occur where. Depending on the state of the graph, many of these - * indices will be empty across all the threads which, while helpful for probing, is unnecessary for executing. - * Running this function assumes no further probing will occur. - * - * Finalizing places this RenderPath into more-or-less a read-only state. - */ - void Finalize(); - - int FindAvailableThreadAtIndex(int index); - - RenderThreadPath& GetThreadPath(int thread); - -private: - QVector render_path_; - - QMap thread_map_; - - bool finalized_; -}; - -#endif // RENDERPATH_H diff --git a/app/render/renderinstance.cpp b/app/render/renderinstance.cpp index 9a49d3720..87aa9dfc3 100644 --- a/app/render/renderinstance.cpp +++ b/app/render/renderinstance.cpp @@ -90,3 +90,28 @@ RenderFramebuffer *RenderInstance::buffer() { return &buffer_; } + +QOpenGLContext *RenderInstance::context() +{ + return &ctx_; +} + +const int &RenderInstance::width() const +{ + return width_; +} + +const int &RenderInstance::height() const +{ + return height_; +} + +const olive::PixelFormat &RenderInstance::format() const +{ + return format_; +} + +const olive::RenderMode &RenderInstance::mode() const +{ + return mode_; +} diff --git a/app/render/renderinstance.h b/app/render/renderinstance.h index 01b518eb0..e61372752 100644 --- a/app/render/renderinstance.h +++ b/app/render/renderinstance.h @@ -53,6 +53,16 @@ public: RenderFramebuffer* buffer(); + QOpenGLContext* context(); + + const int& width() const; + + const int& height() const; + + const olive::PixelFormat& format() const; + + const olive::RenderMode& mode() const; + private: QOpenGLContext ctx_; diff --git a/app/widget/nodeparamview/nodeparamviewwidgetbridge.cpp b/app/widget/nodeparamview/nodeparamviewwidgetbridge.cpp index 590fd6e1f..ba2edbcef 100644 --- a/app/widget/nodeparamview/nodeparamviewwidgetbridge.cpp +++ b/app/widget/nodeparamview/nodeparamviewwidgetbridge.cpp @@ -91,7 +91,7 @@ void NodeParamViewWidgetBridge::CreateWidgets() footage_combobox->SetRoot(pp->project()->root()); // Use multiple values - footage_combobox->SetFootage(Node::ValueToPtr(base_input->get_value())); + footage_combobox->SetFootage(Node::ValueToPtr(base_input->get_value(0))); connect(footage_combobox, SIGNAL(FootageChanged(Footage*)), this, SLOT(WidgetCallback())); // End test code