diff --git a/app/decoder/ffmpeg/ffmpegdecoder.cpp b/app/decoder/ffmpeg/ffmpegdecoder.cpp
index a597ec07f..52552461f 100644
--- a/app/decoder/ffmpeg/ffmpegdecoder.cpp
+++ b/app/decoder/ffmpeg/ffmpegdecoder.cpp
@@ -122,6 +122,8 @@ bool FFmpegDecoder::Open()
FramePtr FFmpegDecoder::Retrieve(const rational &timecode, const rational &length)
{
+ // FIXME: Fill this out
+
Q_UNUSED(timecode)
Q_UNUSED(length)
diff --git a/app/decoder/frame.h b/app/decoder/frame.h
index 7e8c412dd..e07cd0621 100644
--- a/app/decoder/frame.h
+++ b/app/decoder/frame.h
@@ -37,25 +37,30 @@ extern "C" {
class Frame
{
public:
- // Normal constructor
+ enum Type {
+ kNative,
+ kAVFrame
+ };
+
+ /// Normal constructor
Frame();
- // AVFrame constructor
+ /// AVFrame constructor
Frame(AVFrame* f);
- // Copy constructor
+ /// Copy constructor
Frame(const Frame& f);
- // Move constructor
+ /// Move constructor
Frame(Frame&& f);
- // Copy assignment operator
+ /// Copy assignment operator
Frame& operator=(const Frame& f);
- // Move assignment operator
+ /// Move assignment operator
Frame& operator=(Frame&& f);
- // Destructor
+ /// Destructor
~Frame();
/**
diff --git a/app/node/CMakeLists.txt b/app/node/CMakeLists.txt
index 1571fe79d..2d433e223 100644
--- a/app/node/CMakeLists.txt
+++ b/app/node/CMakeLists.txt
@@ -14,16 +14,21 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
+add_subdirectory(generator)
+add_subdirectory(output)
+
set(OLIVE_SOURCES
${OLIVE_SOURCES}
node/edge.h
node/edge.cpp
- node/node.h
- node/node.cpp
node/graph.h
node/graph.cpp
node/input.h
node/input.cpp
+ node/keyframe.h
+ node/keyframe.cpp
+ node/node.h
+ node/node.cpp
node/output.h
node/output.cpp
node/param.h
diff --git a/app/node/generator/CMakeLists.txt b/app/node/generator/CMakeLists.txt
new file mode 100644
index 000000000..2c5c9b40b
--- /dev/null
+++ b/app/node/generator/CMakeLists.txt
@@ -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 .
+
+add_subdirectory(solid)
+
+set(OLIVE_SOURCES
+ ${OLIVE_SOURCES}
+ PARENT_SCOPE
+)
diff --git a/app/node/generator/solid/CMakeLists.txt b/app/node/generator/solid/CMakeLists.txt
new file mode 100644
index 000000000..df388a97d
--- /dev/null
+++ b/app/node/generator/solid/CMakeLists.txt
@@ -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 .
+
+set(OLIVE_SOURCES
+ ${OLIVE_SOURCES}
+ node/generator/solid/solid.h
+ node/generator/solid/solid.cpp
+ PARENT_SCOPE
+)
diff --git a/app/node/generator/solid/solid.cpp b/app/node/generator/solid/solid.cpp
new file mode 100644
index 000000000..3fac44ea9
--- /dev/null
+++ b/app/node/generator/solid/solid.cpp
@@ -0,0 +1,14 @@
+#include "solid.h"
+
+SolidGenerator::SolidGenerator(QObject *parent) :
+ Node(parent)
+{
+
+}
+
+void SolidGenerator::Process(const rational &time)
+{
+ Q_UNUSED(time)
+
+
+}
diff --git a/app/node/generator/solid/solid.h b/app/node/generator/solid/solid.h
new file mode 100644
index 000000000..742999d85
--- /dev/null
+++ b/app/node/generator/solid/solid.h
@@ -0,0 +1,17 @@
+#ifndef SOLIDGENERATOR_H
+#define SOLIDGENERATOR_H
+
+#include "node/node.h"
+
+class SolidGenerator : public Node
+{
+public:
+ SolidGenerator(QObject* parent = nullptr);
+
+ virtual void Process(const rational &time) override;
+
+private:
+ NodeOutput* texture_output_;
+};
+
+#endif // SOLIDGENERATOR_H
diff --git a/app/node/input.cpp b/app/node/input.cpp
index 44b275d0f..ce015eb7b 100644
--- a/app/node/input.cpp
+++ b/app/node/input.cpp
@@ -20,10 +20,14 @@
#include "input.h"
+#include "output.h"
+
NodeInput::NodeInput(Node* parent) :
NodeParam(parent),
can_accept_multiple_inputs_(false)
{
+ // Have at least one keyframe/value active at any time
+ keyframes_.append(NodeKeyframe());
}
NodeParam::Type NodeInput::type()
@@ -50,3 +54,41 @@ void NodeInput::set_can_accept_multiple_inputs(bool b)
{
can_accept_multiple_inputs_ = b;
}
+
+QVariant NodeInput::get_value(const rational &time)
+{
+ /// Determine if this input has any connections to it
+ switch (edges_.size()) {
+
+ /// No connections - use the internal value
+ case 0:
+ // FIXME: Re-implement keyframing
+ return keyframes_.first().value();
+
+ /// One connection - use the output of the connected Node
+ case 1:
+ return edges_.first()->output()->get_value(time);
+
+ /// Multiple connections - rare, return a list of the outputs of the connected Nodes
+ default:
+ {
+ QList values;
+
+ for (int i=0;ioutput()->get_value(time));
+ }
+
+ return values;
+ }
+ }
+}
+
+bool NodeInput::keyframing()
+{
+ return keyframing_;
+}
+
+void NodeInput::set_keyframing(bool k)
+{
+ keyframing_ = k;
+}
diff --git a/app/node/input.h b/app/node/input.h
index be3c6c67a..29d35cdd8 100644
--- a/app/node/input.h
+++ b/app/node/input.h
@@ -21,6 +21,7 @@
#ifndef NODEINPUT_H
#define NODEINPUT_H
+#include "keyframe.h"
#include "param.h"
class NodeInput : public NodeParam
@@ -37,9 +38,18 @@ public:
bool can_accept_multiple_inputs();
void set_can_accept_multiple_inputs(bool b);
+ QVariant get_value(const rational &time);
+
+ bool keyframing();
+ void set_keyframing(bool k);
+
private:
QList inputs_;
+ QList keyframes_;
+
+ bool keyframing_;
+
bool can_accept_multiple_inputs_;
};
diff --git a/app/node/keyframe.cpp b/app/node/keyframe.cpp
new file mode 100644
index 000000000..2ce4ef695
--- /dev/null
+++ b/app/node/keyframe.cpp
@@ -0,0 +1,59 @@
+/***
+
+ 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 "keyframe.h"
+
+NodeKeyframe::NodeKeyframe() :
+ time_(0),
+ value_(0),
+ type_(kLinear)
+{
+
+}
+
+const rational &NodeKeyframe::time()
+{
+ return time_;
+}
+
+void NodeKeyframe::set_time(const rational &time)
+{
+ time_ = time;
+}
+
+const QVariant &NodeKeyframe::value()
+{
+ return value_;
+}
+
+void NodeKeyframe::set_value(const QVariant &value)
+{
+ value_ = value;
+}
+
+const NodeKeyframe::Type &NodeKeyframe::type()
+{
+ return type_;
+}
+
+void NodeKeyframe::set_type(const NodeKeyframe::Type &type)
+{
+ type_ = type;
+}
diff --git a/app/node/keyframe.h b/app/node/keyframe.h
new file mode 100644
index 000000000..127fd7fa5
--- /dev/null
+++ b/app/node/keyframe.h
@@ -0,0 +1,57 @@
+/***
+
+ 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 NODEKEYFRAME_H
+#define NODEKEYFRAME_H
+
+#include
+
+#include "rational.h"
+
+class NodeKeyframe
+{
+public:
+
+ enum Type {
+ kLinear,
+ kHold,
+ kBezier
+ };
+
+ NodeKeyframe();
+
+ const rational& time();
+ void set_time(const rational& time);
+
+ const QVariant& value();
+ void set_value(const QVariant &value);
+
+ const Type& type();
+ void set_type(const Type& type);
+
+private:
+ rational time_;
+
+ QVariant value_;
+
+ Type type_;
+};
+
+#endif // NODEKEYFRAME_H
diff --git a/app/node/node.h b/app/node/node.h
index 2c8ca143b..7b6253ac0 100644
--- a/app/node/node.h
+++ b/app/node/node.h
@@ -24,11 +24,14 @@
#include
#include "node/param.h"
+#include "rational.h"
class Node : public QObject
{
public:
Node(QObject* parent = nullptr);
+
+ virtual void Process(const rational& time) = 0;
};
#endif // NODE_H
diff --git a/app/node/output.cpp b/app/node/output.cpp
index 309890f92..3b508845b 100644
--- a/app/node/output.cpp
+++ b/app/node/output.cpp
@@ -20,6 +20,8 @@
#include "output.h"
+#include "node/node.h"
+
NodeOutput::NodeOutput(Node *parent) :
NodeParam(parent)
{
@@ -40,3 +42,17 @@ void NodeOutput::set_data_type(const NodeParam::DataType &type)
{
data_type_ = type;
}
+
+const QVariant &NodeOutput::get_value(const rational& time)
+{
+ // Node::Process() should put the correct value in this output
+ parent()->Process(time);
+
+ // The value should be have been set by this point
+ return value_;
+}
+
+void NodeOutput::set_value(const QVariant &value)
+{
+ value_ = value;
+}
diff --git a/app/node/output.h b/app/node/output.h
index 248990d47..e84f72146 100644
--- a/app/node/output.h
+++ b/app/node/output.h
@@ -33,8 +33,13 @@ public:
const DataType& data_type();
void set_data_type(const DataType& type);
+ virtual const QVariant& get_value(const rational &time);
+ virtual void set_value(const QVariant& value);
+
private:
DataType data_type_;
+
+ QVariant value_;
};
#endif // NODEOUTPUT_H
diff --git a/app/node/output/CMakeLists.txt b/app/node/output/CMakeLists.txt
new file mode 100644
index 000000000..1af491378
--- /dev/null
+++ b/app/node/output/CMakeLists.txt
@@ -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 .
+
+add_subdirectory(viewer)
+
+set(OLIVE_SOURCES
+ ${OLIVE_SOURCES}
+ PARENT_SCOPE
+)
diff --git a/app/node/output/viewer/CMakeLists.txt b/app/node/output/viewer/CMakeLists.txt
new file mode 100644
index 000000000..86c82a689
--- /dev/null
+++ b/app/node/output/viewer/CMakeLists.txt
@@ -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 .
+
+set(OLIVE_SOURCES
+ ${OLIVE_SOURCES}
+ node/output/viewer/viewer.h
+ node/output/viewer/viewer.cpp
+ PARENT_SCOPE
+)
diff --git a/app/node/output/viewer/viewer.cpp b/app/node/output/viewer/viewer.cpp
new file mode 100644
index 000000000..f03f83730
--- /dev/null
+++ b/app/node/output/viewer/viewer.cpp
@@ -0,0 +1,6 @@
+#include "viewer.h"
+
+ViewerOutput::ViewerOutput(QObject* parent) :
+ Node(parent)
+{
+}
diff --git a/app/node/output/viewer/viewer.h b/app/node/output/viewer/viewer.h
new file mode 100644
index 000000000..d480e5e52
--- /dev/null
+++ b/app/node/output/viewer/viewer.h
@@ -0,0 +1,15 @@
+#ifndef VIEWER_H
+#define VIEWER_H
+
+#include "node/node.h"
+
+class ViewerOutput : public Node
+{
+public:
+ ViewerOutput(QObject* parent = nullptr);
+
+private:
+ NodeInput* texture_input_;
+};
+
+#endif // VIEWER_H
diff --git a/app/node/param.cpp b/app/node/param.cpp
index 03688b23a..773a73ad8 100644
--- a/app/node/param.cpp
+++ b/app/node/param.cpp
@@ -40,6 +40,11 @@ void NodeParam::set_name(const QString &name)
name_ = name;
}
+Node *NodeParam::parent()
+{
+ return static_cast(QObject::parent());
+}
+
bool NodeParam::AreDataTypesCompatible(const NodeParam::DataType &output_type, const NodeParam::DataType &input_type)
{
if (input_type == output_type) {
diff --git a/app/node/param.h b/app/node/param.h
index 0a81d6400..c142c1bef 100644
--- a/app/node/param.h
+++ b/app/node/param.h
@@ -22,8 +22,10 @@
#define NODEPARAM_H
#include
+#include
#include "node/edge.h"
+#include "rational.h"
class Node;
@@ -58,6 +60,8 @@ public:
const QString& name();
void set_name(const QString& name);
+ Node* parent();
+
static bool AreDataTypesCompatible(const DataType& output_type, const DataType& input_type);
static bool AreDataTypesCompatible(const DataType& output_type, const QList& input_types);
@@ -66,10 +70,13 @@ public:
static QString GetDefaultDataTypeName(const DataType &type);
-private:
+protected:
QVector edges_;
+private:
+
QString name_;
+
};
#endif // NODEPARAM_H
diff --git a/app/render/CMakeLists.txt b/app/render/CMakeLists.txt
index d782b3964..d5c5b2286 100644
--- a/app/render/CMakeLists.txt
+++ b/app/render/CMakeLists.txt
@@ -15,8 +15,17 @@
# along with this program. If not, see .
add_subdirectory(gl)
+add_subdirectory(renderer)
set(OLIVE_SOURCES
${OLIVE_SOURCES}
+ #render/imagecache.h
+ #render/imagecache.cpp
+ #render/memorybuffer.h
+ #render/memorybuffer.cpp
+ render/pixelformat.h
+ render/pixelformat.cpp
+ render/texturebuffer.h
+ render/texturebuffer.cpp
PARENT_SCOPE
)
diff --git a/app/render/gl/CMakeLists.txt b/app/render/gl/CMakeLists.txt
index 743401cdf..c5079ebdf 100644
--- a/app/render/gl/CMakeLists.txt
+++ b/app/render/gl/CMakeLists.txt
@@ -16,8 +16,8 @@
set(OLIVE_SOURCES
${OLIVE_SOURCES}
- render/gl/glfunc.h
- render/gl/glfunc.cpp
+ render/gl/functions.h
+ render/gl/functions.cpp
render/gl/shadergenerators.h
render/gl/shadergenerators.cpp
render/gl/shaderptr.h
diff --git a/app/render/gl/glfunc.cpp b/app/render/gl/functions.cpp
similarity index 99%
rename from app/render/gl/glfunc.cpp
rename to app/render/gl/functions.cpp
index 857bebe06..265a62ba5 100644
--- a/app/render/gl/glfunc.cpp
+++ b/app/render/gl/functions.cpp
@@ -18,7 +18,7 @@
***/
-#include "glfunc.h"
+#include "functions.h"
#include
#include
diff --git a/app/render/gl/glfunc.h b/app/render/gl/functions.h
similarity index 100%
rename from app/render/gl/glfunc.h
rename to app/render/gl/functions.h
diff --git a/app/render/imagecache.cpp b/app/render/imagecache.cpp
new file mode 100644
index 000000000..615255f14
--- /dev/null
+++ b/app/render/imagecache.cpp
@@ -0,0 +1,313 @@
+/***
+
+ 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 "imagecache.h"
+
+#include
+
+ImageCache::ImageCache() :
+ ctx_(nullptr),
+ width_(0),
+ height_(0)
+{
+}
+
+ImageCache::~ImageCache()
+{
+ buffer_array_mutex_.lock();
+
+ Clear();
+
+ buffer_array_mutex_.unlock();
+}
+
+void ImageCache::SetParameters(QOpenGLContext *ctx, int width, int height)
+{
+ buffer_array_mutex_.lock();
+
+ ctx_ = ctx;
+
+ if (ctx_ != nullptr) {
+ Q_ASSERT(width > 0 && height > 0);
+
+ width_ = width;
+ height_ = height;
+ }
+
+ Clear();
+
+ buffer_array_mutex_.unlock();
+}
+
+int ImageCache::RequestBuffer(Ref* r, const BufferType& type, const olive::PixelFormat& format, int width, int height)
+{
+ if (type == kTexBuf && (ctx_ == nullptr || width_ == 0 || height_ == 0)) {
+ qWarning() << tr("Texture cache request made without valid parameters (%1: %2, %3").arg(QString::number(reinterpret_cast(ctx_)),
+ QString::number(width_),
+ QString::number(height_));
+ return -1;
+ }
+
+ buffer_array_mutex_.lock();
+
+ int buffer = RequestBufferInternal(r, type, format, width, height);
+
+ buffer_array_mutex_.unlock();
+
+ return buffer;
+}
+
+int ImageCache::RequestBufferInternal(Ref *r, const BufferType& type, const olive::PixelFormat& format, int width, int height)
+{
+ Q_ASSERT(type != kInvalidBuf);
+
+ QList& relinquished = (type == kMemBuf) ? img_relinquished_ : tex_relinquished_;
+ QList[& refs = (type == kMemBuf) ? img_refs_ : tex_refs_;
+ QList& access_times = (type == kMemBuf) ? img_access_times_ : tex_access_times_;
+
+ // Try to return a relinquished buffer
+ if (!relinquished.isEmpty()) {
+
+ if (type == kTexBuf) {
+
+ int buf_index = relinquished.takeFirst();
+
+ refs.replace(buf_index, r);
+
+ return buf_index;
+
+ } else if (type == kMemBuf) {
+
+ // Check for a relinquished buffer with the desired size
+
+ //
+ // TODO consider a database for sorting through these buffers
+ //
+ for (int i=0;iRelinquish();
+ refs.replace(least_recent_access, r);
+ return least_recent_access;
+ }
+
+ // Otherwise, just generate a new buffer
+ int index = -1;
+ switch (type) {
+ case kMemBuf:
+ index = img_buffers_.size();
+ img_buffers_.append(MemoryBuffer());
+ img_buffers_.last().Create(width_, height_, format);
+ break;
+ case kTexBuf:
+ index = tex_buffers_.size();
+ tex_buffers_.append(TextureBuffer());
+ tex_buffers_.last().Create(ctx_, format, width_, height_);
+ break;
+ default:
+ Q_ASSERT(false);
+ }
+
+ refs.append(r);
+ access_times.append(time(nullptr));
+
+ return index;
+}
+
+void ImageCache::RelinquishBuffer(int index, const BufferType &type)
+{
+ buffer_array_mutex_.lock();
+
+ switch (type) {
+ case kMemBuf:
+ img_refs_.replace(index, nullptr);
+ img_relinquished_.append(index);
+ break;
+ case kTexBuf:
+ tex_refs_.replace(index, nullptr);
+ tex_relinquished_.append(index);
+ break;
+ default:
+ qFatal("Invalid buffer type on ImageCache::RelinquishBuffer");
+ }
+
+ buffer_array_mutex_.unlock();
+}
+
+void *ImageCache::Buffer(int index, const BufferType &type)
+{
+ switch (type) {
+ case kMemBuf:
+ img_access_times_.replace(index, time(nullptr));
+ return &img_buffers_[index];
+ case kTexBuf:
+ tex_access_times_.replace(index, time(nullptr));
+ return &tex_buffers_[index];
+ default:
+ qFatal("Invalid buffer type on ImageCache::Buffer");
+ }
+}
+
+bool ImageCache::OutOfMemory()
+{
+ // TODO actually check if we have any memory or not
+ return false;
+}
+
+void ImageCache::Clear()
+{
+ for (int i=0;iRelinquish();
+ }
+
+ for (int i=0;iRelinquish();
+ }
+
+ img_refs_.clear();
+ tex_refs_.clear();
+
+ img_buffers_.clear();
+ tex_buffers_.clear();
+
+ img_relinquished_.clear();
+ tex_relinquished_.clear();
+}
+
+ImageCache::Ref::Ref(ImageCache *cache) :
+ buffer_type_(kInvalidBuf),
+ width_(cache->width_),
+ height_(cache->height_),
+ cache_(cache),
+ buffer_(-1)
+{
+}
+
+ImageCache::Ref::~Ref()
+{
+ Relinquish();
+}
+
+void *ImageCache::Ref::BufferInternal()
+{
+ // If we don't have a buffer yet, request one
+ if (buffer_ == -1) {
+ Request();
+ }
+
+ // If we didn't receive one, return null
+ if (buffer_ == -1) {
+ return nullptr;
+ }
+
+ // Otherwise, return the buffer we received
+ return cache_->Buffer(buffer_, buffer_type_);
+}
+
+void ImageCache::Ref::Relinquish()
+{
+ if (buffer_ == -1) {
+ return;
+ }
+
+ cache_->RelinquishBuffer(buffer_, buffer_type_);
+ buffer_ = -1;
+}
+
+void ImageCache::Ref::Request()
+{
+ // Check if we already have a buffer, in which case we don't need to request a new one
+ if (buffer_ != -1) {
+ return;
+ }
+
+ // Check if we have a valid buffer type to request
+ if (buffer_type_ == kInvalidBuf) {
+ qWarning() << tr("Tried to request an invalid buffer type");
+ return;
+ }
+
+ buffer_ = cache_->RequestBuffer(this, buffer_type_, width_, height_);
+}
+
+ImageCache::ImgRef::ImgRef(ImageCache *cache) :
+ Ref(cache)
+{
+ buffer_type_ = kMemBuf;
+}
+
+void ImageCache::ImgRef::SetSize(int w, int h)
+{
+ width_ = w;
+ height_ = h;
+
+ Relinquish();
+}
+
+MemoryBuffer *ImageCache::ImgRef::buffer()
+{
+ return static_cast(BufferInternal());
+}
+
+ImageCache::TexRef::TexRef(ImageCache *cache) :
+ Ref(cache)
+{
+ buffer_type_ = kTexBuf;
+}
+
+TextureBuffer *ImageCache::TexRef::buffer()
+{
+ return static_cast(BufferInternal());
+}
diff --git a/app/render/imagecache.h b/app/render/imagecache.h
new file mode 100644
index 000000000..0a859199b
--- /dev/null
+++ b/app/render/imagecache.h
@@ -0,0 +1,111 @@
+/***
+
+ 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 MEMORYCACHE_H
+#define MEMORYCACHE_H
+
+#include
+#include
+
+#include "texturebuffer.h"
+#include "memorybuffer.h"
+
+class ImageCache : public QObject
+{
+public:
+
+ enum BufferType {
+ kInvalidBuf, // No buffer
+ kMemBuf, // RAM (CPU) buffer
+ kTexBuf // VRAM (GPU) buffer
+ };
+
+ class Ref {
+ public:
+ Ref(ImageCache* cache);
+ ~Ref();
+
+ void Relinquish();
+ protected:
+ void* BufferInternal();
+
+ BufferType buffer_type_;
+
+ int width_;
+ int height_;
+ private:
+ void Request();
+
+ ImageCache* cache_;
+ int buffer_;
+ };
+
+ class ImgRef : public Ref {
+ public:
+ ImgRef(ImageCache* cache);
+
+ void SetSize(int w, int h);
+
+ MemoryBuffer* buffer();
+
+ };
+
+ class TexRef : public Ref {
+ public:
+ TexRef(ImageCache* cache);
+ TextureBuffer* buffer();
+ };
+
+ ImageCache();
+ ~ImageCache();
+
+ void SetParameters(QOpenGLContext* ctx, int width, int height);
+
+private:
+ int RequestBuffer(Ref *r, const BufferType& type, const olive::PixelFormat &format, int width, int height);
+ int RequestBufferInternal(Ref *r, const BufferType& type, const olive::PixelFormat &format, int width, int height);
+
+ void RelinquishBuffer(int index, const BufferType& type);
+
+ void *Buffer(int index, const BufferType &type);
+
+ bool OutOfMemory();
+
+ void Clear();
+
+ QList img_buffers_;
+ QList][ img_refs_;
+ QList img_access_times_;
+ QList img_relinquished_;
+
+ QList tex_buffers_;
+ QList][ tex_refs_;
+ QList tex_access_times_;
+ QList tex_relinquished_;
+
+ QOpenGLContext* ctx_;
+
+ int width_;
+ int height_;
+
+ QMutex buffer_array_mutex_;
+};
+
+#endif // MEMORYCACHE_H
diff --git a/app/render/memorybuffer.cpp b/app/render/memorybuffer.cpp
new file mode 100644
index 000000000..33af7fc41
--- /dev/null
+++ b/app/render/memorybuffer.cpp
@@ -0,0 +1,59 @@
+/***
+
+ 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 "memorybuffer.h"
+
+MemoryBuffer::MemoryBuffer()
+{
+}
+
+void MemoryBuffer::Create(int width, int height, const olive::PixelFormat &format)
+{
+ width_ = width;
+ height_ = height;
+ format_ = format;
+
+ data_.resize(PixelService::GetBufferSize(format, width, height));
+}
+
+const int &MemoryBuffer::width() const
+{
+ return width_;
+}
+
+const int &MemoryBuffer::height() const
+{
+ return height_;
+}
+
+const olive::PixelFormat &MemoryBuffer::format() const
+{
+ return format_;
+}
+
+uint8_t *MemoryBuffer::data()
+{
+ return data_.data();
+}
+
+const uint8_t *MemoryBuffer::const_data() const
+{
+ return data_.constData();
+}
diff --git a/app/render/memorybuffer.h b/app/render/memorybuffer.h
new file mode 100644
index 000000000..d9c08a40b
--- /dev/null
+++ b/app/render/memorybuffer.h
@@ -0,0 +1,48 @@
+/***
+
+ 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 MEMORYBUFFER_H
+#define MEMORYBUFFER_H
+
+#include
+
+#include "pixelformat.h"
+
+class MemoryBuffer
+{
+public:
+ MemoryBuffer();
+
+ void Create(int width, int height, const olive::PixelFormat &format);
+
+ const int& width() const;
+ const int& height() const;
+ const olive::PixelFormat& format() const;
+ uint8_t* data();
+ const uint8_t* const_data() const;
+
+private:
+ QVector data_;
+ int width_;
+ int height_;
+ olive::PixelFormat format_;
+};
+
+#endif // MEMORYBUFFER_H
diff --git a/app/render/pixelformat.cpp b/app/render/pixelformat.cpp
new file mode 100644
index 000000000..8299ba374
--- /dev/null
+++ b/app/render/pixelformat.cpp
@@ -0,0 +1,84 @@
+/***
+
+ 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 "pixelformat.h"
+
+#include
+
+const int kRGBAChannels = 4;
+
+PixelService::PixelService()
+{
+}
+
+PixelFormatInfo PixelService::GetPixelFormatInfo(const olive::PixelFormat &format)
+{
+ PixelFormatInfo info;
+
+ switch (format) {
+ case olive::PIX_FMT_RGBA8:
+ info.name = tr("8-bit");
+ info.internal_format = GL_RGBA8;
+ info.pixel_type = GL_UNSIGNED_BYTE;
+ break;
+ case olive::PIX_FMT_RGBA16:
+ info.name = tr("16-bit Integer");
+ info.internal_format = GL_RGBA16;
+ info.pixel_type = GL_UNSIGNED_SHORT;
+ break;
+ case olive::PIX_FMT_RGBA16F:
+ info.name = tr("Half-Float (16-bit)");
+ info.internal_format = GL_RGBA16F;
+ info.pixel_type = GL_HALF_FLOAT;
+ break;
+ case olive::PIX_FMT_RGBA32F:
+ info.name = tr("Full-Float (32-bit)");
+ info.internal_format = GL_RGBA32F;
+ info.pixel_type = GL_FLOAT;
+ break;
+ default:
+ qFatal("Invalid pixel format requested");
+ }
+
+ info.pixel_format = GL_RGBA;
+ info.bytes_per_pixel = BytesPerPixel(format);
+
+ return info;
+}
+
+int PixelService::GetBufferSize(const olive::PixelFormat &format, const int &width, const int &height)
+{
+ return BytesPerPixel(format) * width * height;
+}
+
+int PixelService::BytesPerPixel(const olive::PixelFormat &format)
+{
+ switch (format) {
+ case olive::PIX_FMT_RGBA8:
+ return 1 * kRGBAChannels;
+ case olive::PIX_FMT_RGBA16:
+ case olive::PIX_FMT_RGBA16F:
+ return 2 * kRGBAChannels;
+ case olive::PIX_FMT_RGBA32F:
+ return 4 * kRGBAChannels;
+ default:
+ qFatal("Invalid pixel format requested");
+ }
+}
diff --git a/app/render/pixelformat.h b/app/render/pixelformat.h
new file mode 100644
index 000000000..c1607fa94
--- /dev/null
+++ b/app/render/pixelformat.h
@@ -0,0 +1,102 @@
+/***
+
+ 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 BITDEPTHS_H
+#define BITDEPTHS_H
+
+#include
+#include
+#include
+
+/**
+ * @brief A struct of information pertaining to each enum PixelFormat.
+ *
+ * Primarily this is a means of retrieving OpenGL texture information for different pixel formats/bit depths. Both
+ * RAM and VRAM buffers will need a PixelFormat. To keep consistency between the OpenGL code and CPU code when using
+ * a given PixelFormat, the PixelFormatInfo struct contains all necessary variables that you'll need to plug into
+ * OpenGL.
+ *
+ * Use the static function PixelService::GetPixelFormatInfo to generate a PixelFormatInfo object.
+ */
+struct PixelFormatInfo {
+ QString name;
+ GLint internal_format;
+ GLenum pixel_format;
+ GLenum pixel_type;
+ int bytes_per_pixel;
+};
+
+namespace olive {
+
+/**
+ * @brief Olive's internal supported pixel formats.
+ */
+enum PixelFormat {
+ PIX_FMT_RGBA8,
+ PIX_FMT_RGBA16,
+ PIX_FMT_RGBA16F,
+ PIX_FMT_RGBA32F,
+ PIX_FMT_COUNT
+};
+
+}
+
+class PixelService : public QObject {
+public:
+
+ PixelService();
+
+ /**
+ * @brief Return a PixelFormatInfo containing information for a certain format
+ *
+ * \see PixelFormatInfo
+ */
+ static PixelFormatInfo GetPixelFormatInfo(const olive::PixelFormat& format);
+
+ /**
+ * @brief Returns the minimum buffer size (in bytes) necessary for a given format, width, and height.
+ *
+ * @param format
+ *
+ * The format of the data the buffer should contain. Must be a member of the olive::PixelFormat enum.
+ *
+ * @param width
+ *
+ * The width (in pixels) of the buffer.
+ *
+ * @param height
+ *
+ * The height (in pixels) of the buffer.
+ */
+ static int GetBufferSize(const olive::PixelFormat &format, const int& width, const int& height);
+
+ /**
+ * @brief Returns the number of bytes per pixel for a certain format
+ *
+ * Different formats use different sizes of data for pixels. Use this function to determine how many bytes a pixel
+ * requires for a certain format. The number of bytes will always be a multiple of 4 since all formats use RGBA and
+ * are at least 1 bpc.
+ */
+ static int BytesPerPixel(const olive::PixelFormat& format);
+
+private:
+};
+
+#endif // BITDEPTHS_H
diff --git a/app/render/renderer/CMakeLists.txt b/app/render/renderer/CMakeLists.txt
new file mode 100644
index 000000000..14071a2fb
--- /dev/null
+++ b/app/render/renderer/CMakeLists.txt
@@ -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 .
+
+set(OLIVE_SOURCES
+ ${OLIVE_SOURCES}
+ render/renderer/renderer.h
+ render/renderer/renderer.cpp
+ render/renderer/rendererthread.h
+ render/renderer/rendererthread.cpp
+ PARENT_SCOPE
+)
diff --git a/app/render/renderer/renderer.cpp b/app/render/renderer/renderer.cpp
new file mode 100644
index 000000000..315fb4c7c
--- /dev/null
+++ b/app/render/renderer/renderer.cpp
@@ -0,0 +1,70 @@
+/***
+
+ 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 "renderer.h"
+
+Renderer::Renderer() :
+ started_(false)
+{
+
+}
+
+void Renderer::Start()
+{
+ if (started_) {
+ return;
+ }
+
+ threads_.resize(QThread::idealThreadCount());
+
+ for (int i=0;irun();
+ }
+
+ started_ = true;
+}
+
+void Renderer::Stop()
+{
+ if (!started_) {
+ return;
+ }
+
+ started_ = false;
+
+ for (int i=0;iCancel();
+ delete threads_[i];
+ }
+
+ threads_.clear();
+}
+
+/*RendererThread *Renderer::CurrentThread()
+{
+ for (int i=0;i.
+
+***/
+
+#ifndef RENDERER_H
+#define RENDERER_H
+
+#include "render/renderer/rendererthread.h"
+
+class Renderer
+{
+public:
+ Renderer();
+
+ void Start();
+
+ void Stop();
+
+ //RendererThread* CurrentThread();
+
+private:
+ QVector threads_;
+
+ bool started_;
+};
+
+#endif // RENDERER_H
diff --git a/app/render/renderer/rendererthread.cpp b/app/render/renderer/rendererthread.cpp
new file mode 100644
index 000000000..b029aaab1
--- /dev/null
+++ b/app/render/renderer/rendererthread.cpp
@@ -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 .
+
+***/
+
+#include "rendererthread.h"
+
+#include
+
+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(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(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();
+}
diff --git a/app/render/renderer/rendererthread.h b/app/render/renderer/rendererthread.h
new file mode 100644
index 000000000..8dde541ba
--- /dev/null
+++ b/app/render/renderer/rendererthread.h
@@ -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 .
+
+***/
+
+#ifndef RENDERTHREAD_H
+#define RENDERTHREAD_H
+
+#include
+#include
+#include
+#include
+#include
+
+#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
diff --git a/app/render/texturebuffer.cpp b/app/render/texturebuffer.cpp
new file mode 100644
index 000000000..44bf75b1b
--- /dev/null
+++ b/app/render/texturebuffer.cpp
@@ -0,0 +1,150 @@
+/***
+
+ 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 "texturebuffer.h"
+
+#include
+#include
+
+TextureBuffer::TextureBuffer() :
+ ctx_(nullptr),
+ buffer_(0),
+ texture_(0)
+{}
+
+TextureBuffer::~TextureBuffer()
+{
+ Destroy();
+}
+
+bool TextureBuffer::IsCreated()
+{
+ return (ctx_ != nullptr);
+}
+
+void TextureBuffer::Create(QOpenGLContext *ctx, const olive::PixelFormat &format, int width, int height)
+{
+ // free any previous textures
+ Destroy();
+
+ // set context to new context provided
+ ctx_ = ctx;
+
+ QOpenGLFunctions* f = ctx->functions();
+
+ // create framebuffer object
+ f->glGenFramebuffers(1, &buffer_);
+
+ // create texture
+ f->glGenTextures(1, &texture_);
+
+ // bind framebuffer for attaching
+ f->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, buffer_);
+
+ // bind texture
+ f->glBindTexture(GL_TEXTURE_2D, texture_);
+
+ // allocate storage for texture
+ const PixelFormatInfo& bit_depth = PixelService::GetPixelFormatInfo(format);
+
+ ctx->functions()->glTexImage2D(
+ GL_TEXTURE_2D,
+ 0,
+ bit_depth.internal_format,
+ width,
+ height,
+ 0,
+ bit_depth.pixel_format,
+ bit_depth.pixel_type,
+ nullptr
+ );
+
+ // set texture filtering to bilinear
+ f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ // attach texture to framebuffer
+ ctx->extraFunctions()->glFramebufferTexture2D(
+ GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_, 0
+ );
+
+ // clear new texture
+ ctx->functions()->glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ ctx->functions()->glClear(GL_COLOR_BUFFER_BIT);
+
+ // release texture
+ f->glBindTexture(GL_TEXTURE_2D, 0);
+
+ // release framebuffer
+ f->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+}
+
+void TextureBuffer::Destroy()
+{
+ if (ctx_ != nullptr) {
+ ctx_->functions()->glDeleteFramebuffers(1, &buffer_);
+
+ ctx_->functions()->glDeleteTextures(1, &texture_);
+
+ ctx_ = nullptr;
+ }
+}
+
+void TextureBuffer::BindBuffer() const
+{
+ if (ctx_ == nullptr) {
+ return;
+ }
+ ctx_->functions()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, buffer_);
+}
+
+void TextureBuffer::ReleaseBuffer() const
+{
+ if (ctx_ == nullptr) {
+ return;
+ }
+ ctx_->functions()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+}
+
+void TextureBuffer::BindTexture() const
+{
+ if (ctx_ == nullptr) {
+ return;
+ }
+ ctx_->functions()->glBindTexture(GL_TEXTURE_2D, texture_);
+}
+
+void TextureBuffer::ReleaseTexture() const
+{
+ if (ctx_ == nullptr) {
+ return;
+ }
+ ctx_->functions()->glBindTexture(GL_TEXTURE_2D, 0);
+}
+
+const GLuint &TextureBuffer::buffer() const
+{
+ return buffer_;
+}
+
+const GLuint &TextureBuffer::texture() const
+{
+ return texture_;
+}
diff --git a/app/render/texturebuffer.h b/app/render/texturebuffer.h
new file mode 100644
index 000000000..550ffe122
--- /dev/null
+++ b/app/render/texturebuffer.h
@@ -0,0 +1,60 @@
+/***
+
+ 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 FRAMEBUFFEROBJECT_H
+#define FRAMEBUFFEROBJECT_H
+
+#include
+
+#include "pixelformat.h"
+
+/**
+ * @brief A class for managing an OpenGL framebuffer and attached texture
+ *
+ * The GPU pipeline will frequently need framebuffers for drawing onto textures. The TextureBuffer is a convenience
+ * class to handle the creation, management, and destruction of a framebuffer with a texture attachment.
+ *
+ * After creating a new TextureBuffer, call Create() when a valid OpenGL context is available.
+ */
+class TextureBuffer
+{
+public:
+ TextureBuffer();
+ ~TextureBuffer();
+
+ bool IsCreated();
+ void Create(QOpenGLContext* ctx, const olive::PixelFormat& format, int width, int height);
+ void Destroy();
+
+ const GLuint& buffer() const;
+ const GLuint& texture() const;
+
+ void BindBuffer() const;
+ void ReleaseBuffer() const;
+
+ void BindTexture() const;
+ void ReleaseTexture() const;
+private:
+ QOpenGLContext* ctx_;
+ GLuint buffer_;
+ GLuint texture_;
+};
+
+#endif // FRAMEBUFFEROBJECT_H
diff --git a/app/widget/viewer/viewerglwidget.cpp b/app/widget/viewer/viewerglwidget.cpp
index ad68ef1af..17b57b82c 100644
--- a/app/widget/viewer/viewerglwidget.cpp
+++ b/app/widget/viewer/viewerglwidget.cpp
@@ -24,7 +24,7 @@
#include
#include
-#include "render/gl/glfunc.h"
+#include "render/gl/functions.h"
#include "render/gl/shadergenerators.h"
ViewerGLWidget::ViewerGLWidget(QWidget *parent) :
]