finished prototype of nodes providing a texture to a viewer
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
|
||||
add_subdirectory(generator)
|
||||
add_subdirectory(output)
|
||||
add_subdirectory(processor)
|
||||
|
||||
set(OLIVE_SOURCES
|
||||
${OLIVE_SOURCES}
|
||||
|
||||
@@ -1,14 +1,45 @@
|
||||
#include "solid.h"
|
||||
|
||||
SolidGenerator::SolidGenerator(QObject *parent) :
|
||||
Node(parent)
|
||||
Node(parent),
|
||||
texture_(nullptr)
|
||||
{
|
||||
texture_output_ = new NodeOutput(this);
|
||||
texture_output_->set_data_type(NodeOutput::kTexture);
|
||||
}
|
||||
|
||||
QString SolidGenerator::Name()
|
||||
{
|
||||
return tr("Solid");
|
||||
}
|
||||
|
||||
QString SolidGenerator::Category()
|
||||
{
|
||||
return tr("Generator");
|
||||
}
|
||||
|
||||
QString SolidGenerator::Description()
|
||||
{
|
||||
return tr("Generate a solid color.");
|
||||
}
|
||||
|
||||
NodeOutput *SolidGenerator::texture_output()
|
||||
{
|
||||
return texture_output_;
|
||||
}
|
||||
|
||||
void SolidGenerator::Process(const rational &time)
|
||||
{
|
||||
Q_UNUSED(time)
|
||||
|
||||
// FIXME: Test code
|
||||
if (texture_ == nullptr) {
|
||||
QImage img(1920, 1080, QImage::Format_RGBA8888_Premultiplied);
|
||||
img.fill(Qt::red);
|
||||
|
||||
texture_ = new QOpenGLTexture(img);
|
||||
}
|
||||
|
||||
texture_output_->set_value(texture_->textureId());
|
||||
// End test code
|
||||
}
|
||||
|
||||
@@ -1,17 +1,29 @@
|
||||
#ifndef SOLIDGENERATOR_H
|
||||
#define SOLIDGENERATOR_H
|
||||
|
||||
#include <QOpenGLTexture>
|
||||
|
||||
#include "node/node.h"
|
||||
|
||||
class SolidGenerator : public Node
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SolidGenerator(QObject* parent = nullptr);
|
||||
|
||||
virtual QString Name() override;
|
||||
virtual QString Category() override;
|
||||
virtual QString Description() override;
|
||||
|
||||
NodeOutput* texture_output();
|
||||
|
||||
public slots:
|
||||
virtual void Process(const rational &time) override;
|
||||
|
||||
private:
|
||||
NodeOutput* texture_output_;
|
||||
|
||||
QOpenGLTexture* texture_;
|
||||
};
|
||||
|
||||
#endif // SOLIDGENERATOR_H
|
||||
|
||||
@@ -24,3 +24,48 @@ Node::Node(QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
QString Node::Category()
|
||||
{
|
||||
// Return an empty category for any nodes that don't use one
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString Node::Description()
|
||||
{
|
||||
// Return an empty string by default
|
||||
return QString();
|
||||
}
|
||||
|
||||
void Node::InvalidateCache(const rational &start_range, const rational &end_range)
|
||||
{
|
||||
Q_UNUSED(start_range)
|
||||
Q_UNUSED(end_range)
|
||||
|
||||
/*
|
||||
ParamList params = Parameters();
|
||||
|
||||
for (int i=0;i<params.size();i++) {
|
||||
NodeParam* param = params.at(i);
|
||||
|
||||
if (param->type() == NodeParam::kOutput
|
||||
&& param->) {
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
Node::ParamList Node::Parameters()
|
||||
{
|
||||
const QObjectList& child_list = children();
|
||||
|
||||
ParamList params;
|
||||
params.reserve(child_list.size());
|
||||
|
||||
for (int i=0;i<child_list.size();i++) {
|
||||
params[i] = static_cast<NodeParam*>(child_list.at(i));
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
+14
-1
@@ -23,14 +23,27 @@
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "node/param.h"
|
||||
#include "node/input.h"
|
||||
#include "node/output.h"
|
||||
#include "rational.h"
|
||||
|
||||
class Node : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Node(QObject* parent = nullptr);
|
||||
|
||||
virtual QString Name() = 0;
|
||||
virtual QString Category();
|
||||
virtual QString Description();
|
||||
|
||||
virtual void InvalidateCache(const rational& start_range, const rational& end_range);
|
||||
|
||||
using ParamList = QList<NodeParam *>;
|
||||
|
||||
ParamList Parameters();
|
||||
|
||||
public slots:
|
||||
virtual void Process(const rational& time) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,57 @@
|
||||
#include "viewer.h"
|
||||
|
||||
#include "panel/panelfocusmanager.h"
|
||||
|
||||
ViewerOutput::ViewerOutput(QObject* parent) :
|
||||
Node(parent)
|
||||
Node(parent),
|
||||
attached_viewer_(nullptr)
|
||||
{
|
||||
texture_input_ = new NodeInput(this);
|
||||
texture_input_->add_data_input(NodeInput::kTexture);
|
||||
}
|
||||
|
||||
QString ViewerOutput::Name()
|
||||
{
|
||||
return tr("Viewer");
|
||||
}
|
||||
|
||||
QString ViewerOutput::Category()
|
||||
{
|
||||
return tr("Output");
|
||||
}
|
||||
|
||||
QString ViewerOutput::Description()
|
||||
{
|
||||
return tr("Interface between a Viewer panel and the node system.");
|
||||
}
|
||||
|
||||
NodeInput *ViewerOutput::texture_input()
|
||||
{
|
||||
return texture_input_;
|
||||
}
|
||||
|
||||
void ViewerOutput::Process(const rational &time)
|
||||
{
|
||||
if (attached_viewer_ != nullptr) {
|
||||
// Get the texture from whatever Node is currently connected (usually a Renderer of some kind)
|
||||
GLuint current_texture = texture_input_->get_value(time).value<GLuint>();
|
||||
|
||||
// Send the texture to the Viewer
|
||||
attached_viewer_->SetTexture(current_texture);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewerOutput::AttachViewer(ViewerPanel *viewer)
|
||||
{
|
||||
// Disconnect old viewer if there's one attached
|
||||
if (attached_viewer_ != nullptr) {
|
||||
disconnect(attached_viewer_, SIGNAL(TimeChanged(const rational&)), this, SLOT(Process(const rational&)));
|
||||
}
|
||||
|
||||
// FIXME: Currently this attaches to ViewerPanels, but should it attached to Viewers instead?
|
||||
attached_viewer_ = viewer;
|
||||
|
||||
if (attached_viewer_ != nullptr) {
|
||||
connect(attached_viewer_, SIGNAL(TimeChanged(const rational&)), this, SLOT(Process(const rational&)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,14 +2,29 @@
|
||||
#define VIEWER_H
|
||||
|
||||
#include "node/node.h"
|
||||
#include "panel/viewer/viewer.h"
|
||||
|
||||
class ViewerOutput : public Node
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ViewerOutput(QObject* parent = nullptr);
|
||||
|
||||
virtual QString Name() override;
|
||||
virtual QString Category() override;
|
||||
virtual QString Description() override;
|
||||
|
||||
NodeInput* texture_input();
|
||||
|
||||
void AttachViewer(ViewerPanel* viewer);
|
||||
|
||||
public slots:
|
||||
virtual void Process(const rational &time) override;
|
||||
|
||||
private:
|
||||
NodeInput* texture_input_;
|
||||
|
||||
ViewerPanel* attached_viewer_;
|
||||
};
|
||||
|
||||
#endif // VIEWER_H
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
add_subdirectory(renderer)
|
||||
|
||||
set(OLIVE_SOURCES
|
||||
${OLIVE_SOURCES}
|
||||
PARENT_SCOPE
|
||||
)
|
||||
@@ -0,0 +1,24 @@
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
set(OLIVE_SOURCES
|
||||
${OLIVE_SOURCES}
|
||||
node/processor/renderer/renderer.h
|
||||
node/processor/renderer/renderer.cpp
|
||||
node/processor/renderer/rendererthread.h
|
||||
node/processor/renderer/rendererthread.cpp
|
||||
PARENT_SCOPE
|
||||
)
|
||||
@@ -0,0 +1,80 @@
|
||||
/***
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "renderer.h"
|
||||
|
||||
RendererProcessor::RendererProcessor(QObject *parent) :
|
||||
Node(parent),
|
||||
started_(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QString RendererProcessor::Name()
|
||||
{
|
||||
return tr("Renderer");
|
||||
}
|
||||
|
||||
QString RendererProcessor::Category()
|
||||
{
|
||||
return tr("Processor");
|
||||
}
|
||||
|
||||
QString RendererProcessor::Description()
|
||||
{
|
||||
return tr("A multi-threaded OpenGL hardware-accelerated node compositor.");
|
||||
}
|
||||
|
||||
void RendererProcessor::Start()
|
||||
{
|
||||
if (started_) {
|
||||
return;
|
||||
}
|
||||
|
||||
threads_.resize(QThread::idealThreadCount());
|
||||
|
||||
for (int i=0;i<threads_.size();i++) {
|
||||
threads_[i] = new RendererThread();
|
||||
threads_[i]->run();
|
||||
}
|
||||
|
||||
started_ = true;
|
||||
}
|
||||
|
||||
void RendererProcessor::Stop()
|
||||
{
|
||||
if (!started_) {
|
||||
return;
|
||||
}
|
||||
|
||||
started_ = false;
|
||||
|
||||
for (int i=0;i<threads_.size();i++) {
|
||||
threads_[i]->Cancel();
|
||||
delete threads_[i];
|
||||
}
|
||||
|
||||
threads_.clear();
|
||||
}
|
||||
|
||||
RendererThread *RendererProcessor::CurrentThread()
|
||||
{
|
||||
return dynamic_cast<RendererThread*>(QThread::currentThread());
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/***
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef RENDERER_H
|
||||
#define RENDERER_H
|
||||
|
||||
#include "node/node.h"
|
||||
#include "rendererthread.h"
|
||||
|
||||
class RendererProcessor : public Node
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
* @brief Renderer Constructor
|
||||
*
|
||||
* Constructing a Renderer object will not start any threads/backend on its own. Use Start() to do this and Stop()
|
||||
* when the Renderer is about to be destroyed.
|
||||
*/
|
||||
RendererProcessor(QObject* parent = nullptr);
|
||||
|
||||
virtual QString Name() override;
|
||||
virtual QString Category() override;
|
||||
virtual QString Description() override;
|
||||
|
||||
/**
|
||||
* @brief Set parameters of the Renderer
|
||||
*
|
||||
* The Renderer owns the buffers that are used in the rendering process and this function sets the kind of buffers
|
||||
* to use. The Renderer must be stopped when calling this function.
|
||||
*
|
||||
* @param width
|
||||
*
|
||||
* Buffer width
|
||||
*
|
||||
* @param height
|
||||
*
|
||||
* Buffer height
|
||||
*
|
||||
* @param format
|
||||
*
|
||||
* Buffer pixel format
|
||||
*/
|
||||
void SetParameters(const int& width, const int& height, const olive::PixelFormat& format);
|
||||
|
||||
/**
|
||||
* @brief Allocate and start the multithreaded backend
|
||||
*/
|
||||
void Start();
|
||||
|
||||
/**
|
||||
* @brief Terminate and deallocate the multithreaded backend
|
||||
*/
|
||||
void Stop();
|
||||
|
||||
/**
|
||||
* @brief Return current instance of a RenderThread (or nullptr if there is none)
|
||||
*
|
||||
* This function attempts a dynamic_cast on QThread::currentThread() to RendererThread, which will return nullptr if
|
||||
* the cast fails (e.g. if this function is called from the main thread rather than a RendererThread).
|
||||
*/
|
||||
static RendererThread* CurrentThread();
|
||||
|
||||
private:
|
||||
QVector<RendererThread*> threads_;
|
||||
|
||||
bool started_;
|
||||
};
|
||||
|
||||
#endif // RENDERER_H
|
||||
@@ -0,0 +1,106 @@
|
||||
/***
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "rendererthread.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
RendererThread::RendererThread() :
|
||||
cancelled_(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool RendererThread::Queue(Node *n, const rational& time)
|
||||
{
|
||||
// If the thread is inactive, tryLock() will succeed
|
||||
if (mutex_.tryLock()) {
|
||||
|
||||
// The mutex is locked in the calling thread now, so we can change the active Node
|
||||
node_ = n;
|
||||
time_ = time;
|
||||
|
||||
// We can now wake up our main thread
|
||||
wait_cond_.wakeAll();
|
||||
mutex_.unlock();
|
||||
|
||||
// Wait for thread to start before returning
|
||||
caller_mutex_.lock();
|
||||
caller_mutex_.unlock();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void RendererThread::Cancel()
|
||||
{
|
||||
// Escape main loop
|
||||
cancelled_ = true;
|
||||
|
||||
// Wait until thread is finished before returning
|
||||
wait();
|
||||
}
|
||||
|
||||
void RendererThread::run()
|
||||
{
|
||||
// Create OpenGL context (automatically destroys any existing if there is one)
|
||||
if (!ctx_.create()) {
|
||||
qWarning() << tr("Failed to create OpenGL context in thread %1").arg(reinterpret_cast<quintptr>(this));
|
||||
return;
|
||||
}
|
||||
|
||||
// Create offscreen surface
|
||||
surface_.create();
|
||||
|
||||
// Make context current on that surface
|
||||
if (!ctx_.makeCurrent(&surface_)) {
|
||||
qWarning() << tr("Failed to makeCurrent() on offscreen surface in thread %1").arg(reinterpret_cast<quintptr>(this));
|
||||
surface_.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
// Lock mutex for main loop
|
||||
mutex_.lock();
|
||||
|
||||
// Main loop (use Cancel() to exit it)
|
||||
while (!cancelled_) {
|
||||
// Lock the caller mutex (used in Queue() for thread synchronization)
|
||||
caller_mutex_.lock();
|
||||
|
||||
// Main waiting condition
|
||||
wait_cond_.wait(&mutex_);
|
||||
|
||||
// Unlock the caller mutex
|
||||
caller_mutex_.unlock();
|
||||
|
||||
// Process the Node
|
||||
node_->Process(time_);
|
||||
}
|
||||
|
||||
// Release OpenGL context
|
||||
ctx_.doneCurrent();
|
||||
|
||||
// Destroy offscreen surface
|
||||
surface_.destroy();
|
||||
|
||||
// Unlock mutex before exiting
|
||||
mutex_.unlock();
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/***
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef RENDERTHREAD_H
|
||||
#define RENDERTHREAD_H
|
||||
|
||||
#include <QMutex>
|
||||
#include <QOffscreenSurface>
|
||||
#include <QOpenGLContext>
|
||||
#include <QThread>
|
||||
#include <QWaitCondition>
|
||||
|
||||
#include "node/node.h"
|
||||
#include "render/texturebuffer.h"
|
||||
|
||||
class RendererThread : public QThread
|
||||
{
|
||||
public:
|
||||
RendererThread();
|
||||
|
||||
QOpenGLContext* context();
|
||||
|
||||
TextureBuffer* buffer();
|
||||
|
||||
bool Queue(Node* n, const rational &time);
|
||||
|
||||
void Cancel();
|
||||
|
||||
virtual void run() override;
|
||||
|
||||
private:
|
||||
QOpenGLContext ctx_;
|
||||
|
||||
QOffscreenSurface surface_;
|
||||
|
||||
TextureBuffer buffer_;
|
||||
|
||||
QWaitCondition wait_cond_;
|
||||
|
||||
QMutex mutex_;
|
||||
|
||||
QMutex caller_mutex_;
|
||||
|
||||
Node* node_;
|
||||
|
||||
rational time_;
|
||||
|
||||
bool cancelled_;
|
||||
};
|
||||
|
||||
#endif // RENDERTHREAD_H
|
||||
Reference in New Issue
Block a user