began draft of internal node rendering structure
This commit is contained in:
@@ -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)
|
||||
|
||||
|
||||
+12
-7
@@ -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();
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,16 +14,21 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
add_subdirectory(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
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
# Olive - Non-Linear Video Editor
|
||||
# Copyright (C) 2019 Olive Team
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
add_subdirectory(solid)
|
||||
|
||||
set(OLIVE_SOURCES
|
||||
${OLIVE_SOURCES}
|
||||
PARENT_SCOPE
|
||||
)
|
||||
@@ -0,0 +1,22 @@
|
||||
# Olive - Non-Linear Video Editor
|
||||
# Copyright (C) 2019 Olive Team
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
set(OLIVE_SOURCES
|
||||
${OLIVE_SOURCES}
|
||||
node/generator/solid/solid.h
|
||||
node/generator/solid/solid.cpp
|
||||
PARENT_SCOPE
|
||||
)
|
||||
@@ -0,0 +1,14 @@
|
||||
#include "solid.h"
|
||||
|
||||
SolidGenerator::SolidGenerator(QObject *parent) :
|
||||
Node(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SolidGenerator::Process(const rational &time)
|
||||
{
|
||||
Q_UNUSED(time)
|
||||
|
||||
|
||||
}
|
||||
@@ -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
|
||||
@@ -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<QVariant> values;
|
||||
|
||||
for (int i=0;i<edges_.size();i++) {
|
||||
values.append(edges_.at(i)->output()->get_value(time));
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool NodeInput::keyframing()
|
||||
{
|
||||
return keyframing_;
|
||||
}
|
||||
|
||||
void NodeInput::set_keyframing(bool k)
|
||||
{
|
||||
keyframing_ = k;
|
||||
}
|
||||
|
||||
@@ -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<DataType> inputs_;
|
||||
|
||||
QList<NodeKeyframe> keyframes_;
|
||||
|
||||
bool keyframing_;
|
||||
|
||||
bool can_accept_multiple_inputs_;
|
||||
};
|
||||
|
||||
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#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;
|
||||
}
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef NODEKEYFRAME_H
|
||||
#define NODEKEYFRAME_H
|
||||
|
||||
#include <QVariant>
|
||||
|
||||
#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
|
||||
@@ -24,11 +24,14 @@
|
||||
#include <QObject>
|
||||
|
||||
#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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
# Olive - Non-Linear Video Editor
|
||||
# Copyright (C) 2019 Olive Team
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
add_subdirectory(viewer)
|
||||
|
||||
set(OLIVE_SOURCES
|
||||
${OLIVE_SOURCES}
|
||||
PARENT_SCOPE
|
||||
)
|
||||
@@ -0,0 +1,22 @@
|
||||
# Olive - Non-Linear Video Editor
|
||||
# Copyright (C) 2019 Olive Team
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
set(OLIVE_SOURCES
|
||||
${OLIVE_SOURCES}
|
||||
node/output/viewer/viewer.h
|
||||
node/output/viewer/viewer.cpp
|
||||
PARENT_SCOPE
|
||||
)
|
||||
@@ -0,0 +1,6 @@
|
||||
#include "viewer.h"
|
||||
|
||||
ViewerOutput::ViewerOutput(QObject* parent) :
|
||||
Node(parent)
|
||||
{
|
||||
}
|
||||
@@ -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
|
||||
@@ -40,6 +40,11 @@ void NodeParam::set_name(const QString &name)
|
||||
name_ = name;
|
||||
}
|
||||
|
||||
Node *NodeParam::parent()
|
||||
{
|
||||
return static_cast<Node*>(QObject::parent());
|
||||
}
|
||||
|
||||
bool NodeParam::AreDataTypesCompatible(const NodeParam::DataType &output_type, const NodeParam::DataType &input_type)
|
||||
{
|
||||
if (input_type == output_type) {
|
||||
|
||||
+8
-1
@@ -22,8 +22,10 @@
|
||||
#define NODEPARAM_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QVariant>
|
||||
|
||||
#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<DataType>& input_types);
|
||||
|
||||
@@ -66,10 +70,13 @@ public:
|
||||
|
||||
static QString GetDefaultDataTypeName(const DataType &type);
|
||||
|
||||
private:
|
||||
protected:
|
||||
QVector<NodeEdgePtr> edges_;
|
||||
|
||||
private:
|
||||
|
||||
QString name_;
|
||||
|
||||
};
|
||||
|
||||
#endif // NODEPARAM_H
|
||||
|
||||
@@ -15,8 +15,17 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
***/
|
||||
|
||||
#include "glfunc.h"
|
||||
#include "functions.h"
|
||||
|
||||
#include <QOpenGLFunctions>
|
||||
#include <QOpenGLVertexArrayObject>
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "imagecache.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
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<quintptr>(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<int>& relinquished = (type == kMemBuf) ? img_relinquished_ : tex_relinquished_;
|
||||
QList<Ref*>& refs = (type == kMemBuf) ? img_refs_ : tex_refs_;
|
||||
QList<time_t>& 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;i<relinquished.size();i++) {
|
||||
|
||||
const MemoryBuffer& b = img_buffers_.at(relinquished.at(i));
|
||||
|
||||
if (b.width() == width && b.height() == height) {
|
||||
// This buffer fits, we'll use it
|
||||
int buffer_index = relinquished.takeAt(i);
|
||||
|
||||
refs.replace(buffer_index, r);
|
||||
|
||||
return buffer_index;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// If no buffer was available, we may have to create a new one
|
||||
|
||||
// Check if we have enough memory (according to user-defined limits in the Config), if we don't, try to relinquish an
|
||||
// old buffer and return that.
|
||||
if (OutOfMemory()) {
|
||||
|
||||
//
|
||||
// TODO no support for a MemBuf's variable size
|
||||
//
|
||||
|
||||
int least_recent_access = 0;
|
||||
|
||||
// Loop through buffers for the oldest accessed buffer
|
||||
for (int i=1;i<access_times.size();i++) {
|
||||
if (access_times.at(i) < access_times.at(least_recent_access)
|
||||
&& refs.at(i) != nullptr) { // ensure this buffer has not been relinquished
|
||||
least_recent_access = i;
|
||||
}
|
||||
}
|
||||
|
||||
// Relinquish this buffer
|
||||
refs.at(least_recent_access)->Relinquish();
|
||||
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;i<img_refs_.size();i++) {
|
||||
img_refs_.at(i)->Relinquish();
|
||||
}
|
||||
|
||||
for (int i=0;i<tex_refs_.size();i++) {
|
||||
tex_refs_.at(i)->Relinquish();
|
||||
}
|
||||
|
||||
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<MemoryBuffer*>(BufferInternal());
|
||||
}
|
||||
|
||||
ImageCache::TexRef::TexRef(ImageCache *cache) :
|
||||
Ref(cache)
|
||||
{
|
||||
buffer_type_ = kTexBuf;
|
||||
}
|
||||
|
||||
TextureBuffer *ImageCache::TexRef::buffer()
|
||||
{
|
||||
return static_cast<TextureBuffer*>(BufferInternal());
|
||||
}
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef MEMORYCACHE_H
|
||||
#define MEMORYCACHE_H
|
||||
|
||||
#include <QList>
|
||||
#include <QMutex>
|
||||
|
||||
#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<MemoryBuffer> img_buffers_;
|
||||
QList<Ref*> img_refs_;
|
||||
QList<time_t> img_access_times_;
|
||||
QList<int> img_relinquished_;
|
||||
|
||||
QList<TextureBuffer> tex_buffers_;
|
||||
QList<Ref*> tex_refs_;
|
||||
QList<time_t> tex_access_times_;
|
||||
QList<int> tex_relinquished_;
|
||||
|
||||
QOpenGLContext* ctx_;
|
||||
|
||||
int width_;
|
||||
int height_;
|
||||
|
||||
QMutex buffer_array_mutex_;
|
||||
};
|
||||
|
||||
#endif // MEMORYCACHE_H
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#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();
|
||||
}
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef MEMORYBUFFER_H
|
||||
#define MEMORYBUFFER_H
|
||||
|
||||
#include <QVector>
|
||||
|
||||
#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<uint8_t> data_;
|
||||
int width_;
|
||||
int height_;
|
||||
olive::PixelFormat format_;
|
||||
};
|
||||
|
||||
#endif // MEMORYBUFFER_H
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "pixelformat.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef BITDEPTHS_H
|
||||
#define BITDEPTHS_H
|
||||
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
#include <QOpenGLExtraFunctions>
|
||||
|
||||
/**
|
||||
* @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
|
||||
@@ -0,0 +1,24 @@
|
||||
# Olive - Non-Linear Video Editor
|
||||
# Copyright (C) 2019 Olive Team
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
set(OLIVE_SOURCES
|
||||
${OLIVE_SOURCES}
|
||||
render/renderer/renderer.h
|
||||
render/renderer/renderer.cpp
|
||||
render/renderer/rendererthread.h
|
||||
render/renderer/rendererthread.cpp
|
||||
PARENT_SCOPE
|
||||
)
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "renderer.h"
|
||||
|
||||
Renderer::Renderer() :
|
||||
started_(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Renderer::Start()
|
||||
{
|
||||
if (started_) {
|
||||
return;
|
||||
}
|
||||
|
||||
threads_.resize(QThread::idealThreadCount());
|
||||
|
||||
for (int i=0;i<threads_.size();i++) {
|
||||
threads_[i] = new RendererThread();
|
||||
threads_[i]->run();
|
||||
}
|
||||
|
||||
started_ = true;
|
||||
}
|
||||
|
||||
void Renderer::Stop()
|
||||
{
|
||||
if (!started_) {
|
||||
return;
|
||||
}
|
||||
|
||||
started_ = false;
|
||||
|
||||
for (int i=0;i<threads_.size();i++) {
|
||||
threads_[i]->Cancel();
|
||||
delete threads_[i];
|
||||
}
|
||||
|
||||
threads_.clear();
|
||||
}
|
||||
|
||||
/*RendererThread *Renderer::CurrentThread()
|
||||
{
|
||||
for (int i=0;i<threads_.size();i++) {
|
||||
if (threads_.at(i) == QThread::currentThread()) {
|
||||
return threads_.at(i);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}*/
|
||||
@@ -0,0 +1,43 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2019 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef RENDERER_H
|
||||
#define RENDERER_H
|
||||
|
||||
#include "render/renderer/rendererthread.h"
|
||||
|
||||
class Renderer
|
||||
{
|
||||
public:
|
||||
Renderer();
|
||||
|
||||
void Start();
|
||||
|
||||
void Stop();
|
||||
|
||||
//RendererThread* CurrentThread();
|
||||
|
||||
private:
|
||||
QVector<RendererThread*> threads_;
|
||||
|
||||
bool started_;
|
||||
};
|
||||
|
||||
#endif // RENDERER_H
|
||||
@@ -0,0 +1,106 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2019 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "rendererthread.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
RendererThread::RendererThread() :
|
||||
cancelled_(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool RendererThread::Queue(Node *n, const rational& time)
|
||||
{
|
||||
// If the thread is inactive, tryLock() will succeed
|
||||
if (mutex_.tryLock()) {
|
||||
|
||||
// The mutex is locked in the calling thread now, so we can change the active Node
|
||||
node_ = n;
|
||||
time_ = time;
|
||||
|
||||
// We can now wake up our main thread
|
||||
wait_cond_.wakeAll();
|
||||
mutex_.unlock();
|
||||
|
||||
// Wait for thread to start before returning
|
||||
caller_mutex_.lock();
|
||||
caller_mutex_.unlock();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void RendererThread::Cancel()
|
||||
{
|
||||
// Escape main loop
|
||||
cancelled_ = true;
|
||||
|
||||
// Wait until thread is finished before returning
|
||||
wait();
|
||||
}
|
||||
|
||||
void RendererThread::run()
|
||||
{
|
||||
// Create OpenGL context (automatically destroys any existing if there is one)
|
||||
if (!ctx_.create()) {
|
||||
qWarning() << tr("Failed to create OpenGL context in thread %1").arg(reinterpret_cast<quintptr>(this));
|
||||
return;
|
||||
}
|
||||
|
||||
// Create offscreen surface
|
||||
surface_.create();
|
||||
|
||||
// Make context current on that surface
|
||||
if (!ctx_.makeCurrent(&surface_)) {
|
||||
qWarning() << tr("Failed to makeCurrent() on offscreen surface in thread %1").arg(reinterpret_cast<quintptr>(this));
|
||||
surface_.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
// Lock mutex for main loop
|
||||
mutex_.lock();
|
||||
|
||||
// Main loop (use Cancel() to exit it)
|
||||
while (!cancelled_) {
|
||||
// Lock the caller mutex (used in Queue() for thread synchronization)
|
||||
caller_mutex_.lock();
|
||||
|
||||
// Main waiting condition
|
||||
wait_cond_.wait(&mutex_);
|
||||
|
||||
// Unlock the caller mutex
|
||||
caller_mutex_.unlock();
|
||||
|
||||
// Process the Node
|
||||
node_->Process(time_);
|
||||
}
|
||||
|
||||
// Release OpenGL context
|
||||
ctx_.doneCurrent();
|
||||
|
||||
// Destroy offscreen surface
|
||||
surface_.destroy();
|
||||
|
||||
// Unlock mutex before exiting
|
||||
mutex_.unlock();
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2019 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef RENDERTHREAD_H
|
||||
#define RENDERTHREAD_H
|
||||
|
||||
#include <QMutex>
|
||||
#include <QOffscreenSurface>
|
||||
#include <QOpenGLContext>
|
||||
#include <QThread>
|
||||
#include <QWaitCondition>
|
||||
|
||||
#include "node/node.h"
|
||||
#include "render/texturebuffer.h"
|
||||
|
||||
class RendererThread : public QThread
|
||||
{
|
||||
public:
|
||||
RendererThread();
|
||||
|
||||
QOpenGLContext* context();
|
||||
|
||||
TextureBuffer* buffer();
|
||||
|
||||
bool Queue(Node* n, const rational &time);
|
||||
|
||||
void Cancel();
|
||||
|
||||
virtual void run() override;
|
||||
|
||||
private:
|
||||
QOpenGLContext ctx_;
|
||||
|
||||
QOffscreenSurface surface_;
|
||||
|
||||
TextureBuffer buffer_;
|
||||
|
||||
QWaitCondition wait_cond_;
|
||||
|
||||
QMutex mutex_;
|
||||
|
||||
QMutex caller_mutex_;
|
||||
|
||||
Node* node_;
|
||||
|
||||
rational time_;
|
||||
|
||||
bool cancelled_;
|
||||
};
|
||||
|
||||
#endif // RENDERTHREAD_H
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "texturebuffer.h"
|
||||
|
||||
#include <QOpenGLFunctions>
|
||||
#include <QOpenGLExtraFunctions>
|
||||
|
||||
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_;
|
||||
}
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef FRAMEBUFFEROBJECT_H
|
||||
#define FRAMEBUFFEROBJECT_H
|
||||
|
||||
#include <QOpenGLContext>
|
||||
|
||||
#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
|
||||
@@ -24,7 +24,7 @@
|
||||
#include <QOpenGLFunctions>
|
||||
#include <QOpenGLTexture>
|
||||
|
||||
#include "render/gl/glfunc.h"
|
||||
#include "render/gl/functions.h"
|
||||
#include "render/gl/shadergenerators.h"
|
||||
|
||||
ViewerGLWidget::ViewerGLWidget(QWidget *parent) :
|
||||
|
||||
Reference in New Issue
Block a user