From d76691a9efa4c80aaac1e0ce02ef806cb07d9b42 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Wed, 10 Jul 2019 23:06:09 -0400 Subject: [PATCH] began draft of internal node rendering structure --- app/decoder/ffmpeg/ffmpegdecoder.cpp | 2 + app/decoder/frame.h | 19 +- app/node/CMakeLists.txt | 9 +- app/node/generator/CMakeLists.txt | 22 ++ app/node/generator/solid/CMakeLists.txt | 22 ++ app/node/generator/solid/solid.cpp | 14 + app/node/generator/solid/solid.h | 17 ++ app/node/input.cpp | 42 +++ app/node/input.h | 10 + app/node/keyframe.cpp | 59 ++++ app/node/keyframe.h | 57 ++++ app/node/node.h | 3 + app/node/output.cpp | 16 + app/node/output.h | 5 + app/node/output/CMakeLists.txt | 22 ++ app/node/output/viewer/CMakeLists.txt | 22 ++ app/node/output/viewer/viewer.cpp | 6 + app/node/output/viewer/viewer.h | 15 + app/node/param.cpp | 5 + app/node/param.h | 9 +- app/render/CMakeLists.txt | 9 + app/render/gl/CMakeLists.txt | 4 +- app/render/gl/{glfunc.cpp => functions.cpp} | 2 +- app/render/gl/{glfunc.h => functions.h} | 0 app/render/imagecache.cpp | 313 ++++++++++++++++++++ app/render/imagecache.h | 111 +++++++ app/render/memorybuffer.cpp | 59 ++++ app/render/memorybuffer.h | 48 +++ app/render/pixelformat.cpp | 84 ++++++ app/render/pixelformat.h | 102 +++++++ app/render/renderer/CMakeLists.txt | 24 ++ app/render/renderer/renderer.cpp | 70 +++++ app/render/renderer/renderer.h | 43 +++ app/render/renderer/rendererthread.cpp | 106 +++++++ app/render/renderer/rendererthread.h | 68 +++++ app/render/texturebuffer.cpp | 150 ++++++++++ app/render/texturebuffer.h | 60 ++++ app/widget/viewer/viewerglwidget.cpp | 2 +- 38 files changed, 1617 insertions(+), 14 deletions(-) create mode 100644 app/node/generator/CMakeLists.txt create mode 100644 app/node/generator/solid/CMakeLists.txt create mode 100644 app/node/generator/solid/solid.cpp create mode 100644 app/node/generator/solid/solid.h create mode 100644 app/node/keyframe.cpp create mode 100644 app/node/keyframe.h create mode 100644 app/node/output/CMakeLists.txt create mode 100644 app/node/output/viewer/CMakeLists.txt create mode 100644 app/node/output/viewer/viewer.cpp create mode 100644 app/node/output/viewer/viewer.h rename app/render/gl/{glfunc.cpp => functions.cpp} (99%) rename app/render/gl/{glfunc.h => functions.h} (100%) create mode 100644 app/render/imagecache.cpp create mode 100644 app/render/imagecache.h create mode 100644 app/render/memorybuffer.cpp create mode 100644 app/render/memorybuffer.h create mode 100644 app/render/pixelformat.cpp create mode 100644 app/render/pixelformat.h create mode 100644 app/render/renderer/CMakeLists.txt create mode 100644 app/render/renderer/renderer.cpp create mode 100644 app/render/renderer/renderer.h create mode 100644 app/render/renderer/rendererthread.cpp create mode 100644 app/render/renderer/rendererthread.h create mode 100644 app/render/texturebuffer.cpp create mode 100644 app/render/texturebuffer.h 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) :