finished upgrade to ocio v2
This commit is contained in:
@@ -215,8 +215,9 @@ bool OIIODecoder::OpenImageHandler(const QString &fn)
|
||||
// Check if we can work with this pixel format
|
||||
const OIIO::ImageSpec& spec = image_->spec();
|
||||
|
||||
is_rgba_ = (spec.nchannels == kRGBAChannels);
|
||||
//is_rgba_ = (spec.nchannels == kRGBAChannels);
|
||||
|
||||
// We use RGBA frames because that tends to be the native format of GPUs
|
||||
pix_fmt_ = OIIOCommon::GetFormatFromOIIOBasetype(spec);
|
||||
|
||||
if (pix_fmt_ == PixelFormat::PIX_FMT_INVALID) {
|
||||
|
||||
@@ -65,7 +65,7 @@ private:
|
||||
|
||||
PixelFormat::Format pix_fmt_;
|
||||
|
||||
bool is_rgba_;
|
||||
//bool is_rgba_;
|
||||
|
||||
OIIO::ImageBuf* buffer_;
|
||||
|
||||
|
||||
@@ -231,10 +231,10 @@ void Config::Save()
|
||||
|
||||
QString value = NodeInput::ValueToString(iterator.value().type, iterator.value().data, false);
|
||||
|
||||
writer.writeTextElement(iterator.key(), value);
|
||||
|
||||
if (iterator.value().type == NodeParam::kNone) {
|
||||
qWarning() << "Config key" << iterator.key() << "had null type";
|
||||
qWarning() << "Config key" << iterator.key() << "had null type and was discarded";
|
||||
} else {
|
||||
writer.writeTextElement(iterator.key(), value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,6 @@
|
||||
#include "render/diskmanager.h"
|
||||
#include "render/pixelformat.h"
|
||||
#include "render/rendermanager.h"
|
||||
#include "render/shaderinfo.h"
|
||||
#ifdef USE_OTIO
|
||||
#include "task/project/loadotio/loadotio.h"
|
||||
#include "task/project/saveotio/saveotio.h"
|
||||
|
||||
+4
-1
@@ -36,7 +36,10 @@
|
||||
#include "node/output.h"
|
||||
#include "node/value.h"
|
||||
#include "render/audioparams.h"
|
||||
#include "render/shaderinfo.h"
|
||||
#include "render/job/generatejob.h"
|
||||
#include "render/job/samplejob.h"
|
||||
#include "render/job/shaderjob.h"
|
||||
#include "render/shadercode.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
|
||||
+23
-16
@@ -14,45 +14,52 @@
|
||||
# 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(backend)
|
||||
add_subdirectory(job)
|
||||
add_subdirectory(ocioconf)
|
||||
add_subdirectory(opengl)
|
||||
|
||||
set(OLIVE_SOURCES
|
||||
${OLIVE_SOURCES}
|
||||
render/audioparams.h
|
||||
render/audioparams.cpp
|
||||
render/audioplaybackcache.h
|
||||
render/audioparams.h
|
||||
render/audioplaybackcache.cpp
|
||||
render/color.h
|
||||
render/audioplaybackcache.h
|
||||
render/color.cpp
|
||||
render/colormanager.h
|
||||
render/color.h
|
||||
render/colormanager.cpp
|
||||
render/colormanager.h
|
||||
render/colorprocessor.cpp
|
||||
render/colorprocessor.h
|
||||
render/colorprocessorcache.h
|
||||
render/colorprocessor.cpp
|
||||
render/diskmanager.h
|
||||
render/diskmanager.cpp
|
||||
render/framehashcache.h
|
||||
render/diskmanager.h
|
||||
render/framehashcache.cpp
|
||||
render/managedcolor.h
|
||||
render/framehashcache.h
|
||||
render/managedcolor.cpp
|
||||
render/pixelformat.h
|
||||
render/managedcolor.h
|
||||
render/pixelformat.cpp
|
||||
render/playbackcache.h
|
||||
render/pixelformat.h
|
||||
render/playbackcache.cpp
|
||||
render/previewautocacher.h
|
||||
render/playbackcache.h
|
||||
render/previewautocacher.cpp
|
||||
render/previewautocacher.h
|
||||
render/renderer.cpp
|
||||
render/renderer.h
|
||||
render/rendercache.h
|
||||
render/rendermanager.h
|
||||
render/rendererthreadwrapper.cpp
|
||||
render/rendererthreadwrapper.h
|
||||
render/rendermanager.cpp
|
||||
render/rendermanager.h
|
||||
render/rendermodes.h
|
||||
render/renderprocessor.h
|
||||
render/renderprocessor.cpp
|
||||
render/shaderinfo.h
|
||||
render/renderprocessor.h
|
||||
render/shadercode.h
|
||||
render/shadervalue.h
|
||||
render/stillimagecache.h
|
||||
render/videoparams.h
|
||||
render/texture.cpp
|
||||
render/texture.h
|
||||
render/videoparams.cpp
|
||||
render/videoparams.h
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2019 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "renderer.h"
|
||||
|
||||
#include <QFloat16>
|
||||
|
||||
#include "common/ocioutils.h"
|
||||
#include "render/colormanager.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
Renderer::Renderer(QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Renderer::TexturePtr Renderer::CreateTexture(const VideoParams ¶m, void *data, int linesize)
|
||||
{
|
||||
QVariant v = CreateNativeTexture(param, data, linesize);
|
||||
|
||||
if (v.isNull()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::make_shared<Texture>(this, v, param);
|
||||
}
|
||||
|
||||
// copied from source code to OCIODisplay
|
||||
/*const int OCIO_LUT3D_EDGE_SIZE = 64;
|
||||
|
||||
const int OCIO_LUT3D_PIXEL_COUNT = OCIO_LUT3D_EDGE_SIZE*OCIO_LUT3D_EDGE_SIZE*OCIO_LUT3D_EDGE_SIZE;
|
||||
const int OCIO_LUT3D_ENTRY_COUNT = 3 * OCIO_LUT3D_PIXEL_COUNT;
|
||||
const int OCIO_LUT3D_ENTRY_COUNT_WITH_ALPHA = 4 * OCIO_LUT3D_PIXEL_COUNT;
|
||||
const int OCIO_LUT2D_EDGE_SIZE = 512;*/
|
||||
|
||||
void Renderer::BlitColorManaged(ColorProcessorPtr color_processor, TexturePtr source, Texture *destination, bool flipped)
|
||||
{
|
||||
qDebug() << "BlitColorManaged is a partial stub";
|
||||
|
||||
QVariant shader = CreateNativeShader(ShaderCode(FileFunctions::ReadFileAsString(":/shaders/default.frag"), FileFunctions::ReadFileAsString(":/shaders/default.vert")));
|
||||
|
||||
ShaderJob job;
|
||||
job.InsertValue(QStringLiteral("ove_maintex"), ShaderValue(QVariant::fromValue(source), NodeParam::kTexture));
|
||||
|
||||
if (flipped) {
|
||||
QMatrix4x4 mat;
|
||||
mat.scale(1, -1, 1);
|
||||
job.SetMatrix(mat);
|
||||
}
|
||||
|
||||
BlitToTexture(shader, job, destination);
|
||||
|
||||
DestroyNativeShader(shader);
|
||||
}
|
||||
|
||||
void Renderer::BlitColorManaged(ColorProcessorPtr color_processor, TexturePtr source, VideoParams params, bool flipped)
|
||||
{
|
||||
qDebug() << "BlitColorManaged is a partial stub";
|
||||
|
||||
/*ColorContext color_ctx;
|
||||
|
||||
if (color_cache_.contains(color_processor->id())) {
|
||||
color_ctx = color_cache_.value(color_processor->id());
|
||||
} else {
|
||||
// Create shader description
|
||||
const char* ocio_func_name = "OCIODisplay";
|
||||
OCIO::GpuShaderDescRcPtr shader_desc = OCIO::GpuShaderDesc::CreateShaderDesc();
|
||||
shader_desc->setLanguage(OCIO::GPU_LANGUAGE_GLSL_1_2);
|
||||
shader_desc->setFunctionName(ocio_func_name);
|
||||
shader_desc->setResourcePrefix("ocio_");
|
||||
|
||||
// Generate shader
|
||||
color_processor->GetProcessor()->getDefaultGPUProcessor()->extractGpuShaderInfo(shader_desc);
|
||||
|
||||
qDebug() << "Shader:" << shader_desc->getShaderText();
|
||||
}*/
|
||||
|
||||
QVariant shader = CreateNativeShader(ShaderCode(FileFunctions::ReadFileAsString(":/shaders/default.frag"), FileFunctions::ReadFileAsString(":/shaders/default.vert")));
|
||||
|
||||
ShaderJob job;
|
||||
job.InsertValue(QStringLiteral("ove_maintex"), ShaderValue(QVariant::fromValue(source), NodeParam::kTexture));
|
||||
|
||||
if (flipped) {
|
||||
QMatrix4x4 mat;
|
||||
mat.scale(1, -1, 1);
|
||||
job.SetMatrix(mat);
|
||||
}
|
||||
|
||||
Blit(shader, job, params);
|
||||
|
||||
DestroyNativeShader(shader);
|
||||
}
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
@@ -14,13 +14,11 @@
|
||||
# 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(opengl)
|
||||
|
||||
set(OLIVE_SOURCES
|
||||
${OLIVE_SOURCES}
|
||||
render/backend/renderer.cpp
|
||||
render/backend/renderer.h
|
||||
render/backend/rendererthreadwrapper.cpp
|
||||
render/backend/rendererthreadwrapper.h
|
||||
render/job/acceleratedjob.h
|
||||
render/job/generatejob.h
|
||||
render/job/samplejob.h
|
||||
render/job/shaderjob.h
|
||||
PARENT_SCOPE
|
||||
)
|
||||
@@ -0,0 +1,101 @@
|
||||
/***
|
||||
|
||||
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 ACCELERATEDJOB_H
|
||||
#define ACCELERATEDJOB_H
|
||||
|
||||
#include "node/input.h"
|
||||
#include "node/inputarray.h"
|
||||
#include "render/shadervalue.h"
|
||||
#include "node/value.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
class AcceleratedJob {
|
||||
public:
|
||||
AcceleratedJob() = default;
|
||||
|
||||
ShaderValue GetValue(NodeInput* input) const
|
||||
{
|
||||
return value_map_.value(input->id());
|
||||
}
|
||||
|
||||
ShaderValue GetValue(const QString& input) const
|
||||
{
|
||||
return value_map_.value(input);
|
||||
}
|
||||
|
||||
void InsertValue(NodeInput* input, NodeValueDatabase& value)
|
||||
{
|
||||
ShaderValue shader_val;
|
||||
|
||||
shader_val.type = input->data_type();
|
||||
shader_val.array = input->IsArray();
|
||||
|
||||
if (input->IsArray()) {
|
||||
NodeInputArray* array = static_cast<NodeInputArray*>(input);
|
||||
QVector<QVariant> values(array->GetSize());
|
||||
|
||||
for (int j=0;j<array->GetSize();j++) {
|
||||
NodeInput* subparam = array->At(j);
|
||||
|
||||
values[j] = value[subparam].Take(subparam->data_type());
|
||||
}
|
||||
|
||||
shader_val.data = QVariant::fromValue(values);
|
||||
} else {
|
||||
NodeValue node_val = value[input].TakeWithMeta(input->data_type());
|
||||
shader_val.data = node_val.data();
|
||||
shader_val.tag = node_val.tag();
|
||||
}
|
||||
|
||||
InsertValue(input->id(), shader_val);
|
||||
}
|
||||
|
||||
void InsertValue(const QString& input, const ShaderValue& value)
|
||||
{
|
||||
value_map_.insert(input, value);
|
||||
}
|
||||
|
||||
void InsertValue(NodeInput* input, const ShaderValue& value)
|
||||
{
|
||||
value_map_.insert(input->id(), value);
|
||||
}
|
||||
|
||||
void InsertValue(NodeInput* input, const NodeValue& value)
|
||||
{
|
||||
ShaderValue s(value.data(), value.type());
|
||||
s.tag = value.tag();
|
||||
value_map_.insert(input->id(), s);
|
||||
}
|
||||
|
||||
const NodeValueMap &GetValues() const
|
||||
{
|
||||
return value_map_;
|
||||
}
|
||||
|
||||
private:
|
||||
NodeValueMap value_map_;
|
||||
|
||||
};
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
#endif // ACCELERATEDJOB_H
|
||||
@@ -0,0 +1,54 @@
|
||||
/***
|
||||
|
||||
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 GENERATEJOB_H
|
||||
#define GENERATEJOB_H
|
||||
|
||||
#include "acceleratedjob.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
class GenerateJob : public AcceleratedJob {
|
||||
public:
|
||||
GenerateJob()
|
||||
{
|
||||
alpha_channel_required_ = false;
|
||||
}
|
||||
|
||||
bool GetAlphaChannelRequired() const
|
||||
{
|
||||
return alpha_channel_required_;
|
||||
}
|
||||
|
||||
void SetAlphaChannelRequired(bool e)
|
||||
{
|
||||
alpha_channel_required_ = e;
|
||||
}
|
||||
|
||||
private:
|
||||
bool alpha_channel_required_;
|
||||
|
||||
};
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
Q_DECLARE_METATYPE(OLIVE_NAMESPACE::GenerateJob)
|
||||
|
||||
#endif // GENERATEJOB_H
|
||||
@@ -0,0 +1,65 @@
|
||||
/***
|
||||
|
||||
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 SAMPLEJOB_H
|
||||
#define SAMPLEJOB_H
|
||||
|
||||
#include "acceleratedjob.h"
|
||||
#include "codec/samplebuffer.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
class SampleJob : public AcceleratedJob {
|
||||
public:
|
||||
SampleJob()
|
||||
{
|
||||
samples_ = nullptr;
|
||||
}
|
||||
|
||||
SampleJob(const NodeValue& value)
|
||||
{
|
||||
samples_ = value.data().value<SampleBufferPtr>();
|
||||
}
|
||||
|
||||
SampleJob(NodeInput* from, NodeValueDatabase& db)
|
||||
{
|
||||
samples_ = db[from].Take(NodeParam::kSamples).value<SampleBufferPtr>();
|
||||
}
|
||||
|
||||
SampleBufferPtr samples() const
|
||||
{
|
||||
return samples_;
|
||||
}
|
||||
|
||||
bool HasSamples() const
|
||||
{
|
||||
return samples_ && samples_->is_allocated();
|
||||
}
|
||||
|
||||
private:
|
||||
SampleBufferPtr samples_;
|
||||
|
||||
};
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
Q_DECLARE_METATYPE(OLIVE_NAMESPACE::SampleJob)
|
||||
|
||||
#endif // SAMPLEJOB_H
|
||||
@@ -0,0 +1,112 @@
|
||||
/***
|
||||
|
||||
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 SHADERJOB_H
|
||||
#define SHADERJOB_H
|
||||
|
||||
#include <QMatrix4x4>
|
||||
|
||||
#include "generatejob.h"
|
||||
#include "render/texture.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
class ShaderJob : public GenerateJob {
|
||||
public:
|
||||
ShaderJob()
|
||||
{
|
||||
iterations_ = 1;
|
||||
iterative_input_ = nullptr;
|
||||
}
|
||||
|
||||
const QMatrix4x4& GetMatrix() const
|
||||
{
|
||||
return matrix_;
|
||||
}
|
||||
|
||||
void SetMatrix(const QMatrix4x4& matrix)
|
||||
{
|
||||
matrix_ = matrix;
|
||||
}
|
||||
|
||||
const QString& GetShaderID() const
|
||||
{
|
||||
return shader_id_;
|
||||
}
|
||||
|
||||
void SetShaderID(const QString& id)
|
||||
{
|
||||
shader_id_ = id;
|
||||
}
|
||||
|
||||
void SetIterations(int iterations, NodeInput* iterative_input)
|
||||
{
|
||||
SetIterations(iterations, iterative_input->id());
|
||||
}
|
||||
|
||||
void SetIterations(int iterations, const QString& iterative_input)
|
||||
{
|
||||
iterations_ = iterations;
|
||||
iterative_input_ = iterative_input;
|
||||
}
|
||||
|
||||
int GetIterationCount() const
|
||||
{
|
||||
return iterations_;
|
||||
}
|
||||
|
||||
const QString& GetIterativeInput() const
|
||||
{
|
||||
return iterative_input_;
|
||||
}
|
||||
|
||||
Texture::Interpolation GetInterpolation(const QString& id)
|
||||
{
|
||||
return interpolation_.value(id, Texture::kDefaultInterpolation);
|
||||
}
|
||||
|
||||
void SetInterpolation(NodeInput* input, Texture::Interpolation interp)
|
||||
{
|
||||
interpolation_.insert(input->id(), interp);
|
||||
}
|
||||
|
||||
void SetInterpolation(const QString& id, Texture::Interpolation interp)
|
||||
{
|
||||
interpolation_.insert(id, interp);
|
||||
}
|
||||
|
||||
private:
|
||||
QString shader_id_;
|
||||
|
||||
int iterations_;
|
||||
|
||||
QString iterative_input_;
|
||||
|
||||
QHash<QString, Texture::Interpolation> interpolation_;
|
||||
|
||||
QMatrix4x4 matrix_;
|
||||
|
||||
};
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
Q_DECLARE_METATYPE(OLIVE_NAMESPACE::ShaderJob)
|
||||
|
||||
#endif // SHADERJOB_H
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
set(OLIVE_SOURCES
|
||||
${OLIVE_SOURCES}
|
||||
render/backend/opengl/openglrenderer.cpp
|
||||
render/backend/opengl/openglrenderer.h
|
||||
render/opengl/openglrenderer.cpp
|
||||
render/opengl/openglrenderer.h
|
||||
PARENT_SCOPE
|
||||
)
|
||||
+110
-50
@@ -103,7 +103,7 @@ void OpenGLRenderer::PostInit()
|
||||
functions_->glGenFramebuffers(1, &framebuffer_);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::Destroy()
|
||||
void OpenGLRenderer::DestroyInternal()
|
||||
{
|
||||
if (context_) {
|
||||
// Delete framebuffer
|
||||
@@ -128,7 +128,53 @@ void OpenGLRenderer::ClearDestination(double r, double g, double b, double a)
|
||||
functions_->glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::AttachTextureAsDestination(Renderer::Texture* texture)
|
||||
QVariant OpenGLRenderer::CreateNativeTexture2D(int width, int height, PixelFormat::Format format, Texture::ChannelFormat channel_format, const void *data, int linesize)
|
||||
{
|
||||
GLuint texture;
|
||||
functions_->glGenTextures(1, &texture);
|
||||
|
||||
functions_->glPixelStorei(GL_UNPACK_ROW_LENGTH, linesize);
|
||||
|
||||
GLint current_tex;
|
||||
functions_->glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤t_tex);
|
||||
|
||||
functions_->glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
functions_->glTexImage2D(GL_TEXTURE_2D, 0, GetInternalFormat(format, channel_format),
|
||||
width, height, 0, GetPixelFormat(channel_format),
|
||||
GetPixelType(format), data);
|
||||
|
||||
functions_->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
|
||||
functions_->glBindTexture(GL_TEXTURE_2D, current_tex);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
QVariant OpenGLRenderer::CreateNativeTexture3D(int width, int height, int depth, PixelFormat::Format format, Texture::ChannelFormat channel_format, const void *data, int linesize)
|
||||
{
|
||||
GLuint texture;
|
||||
functions_->glGenTextures(1, &texture);
|
||||
|
||||
functions_->glPixelStorei(GL_UNPACK_ROW_LENGTH, linesize);
|
||||
|
||||
GLint current_tex;
|
||||
functions_->glGetIntegerv(GL_TEXTURE_BINDING_3D, ¤t_tex);
|
||||
|
||||
functions_->glBindTexture(GL_TEXTURE_3D, texture);
|
||||
|
||||
context_->extraFunctions()->glTexImage3D(GL_TEXTURE_3D, 0, GetInternalFormat(format, channel_format),
|
||||
width, height, depth, 0, GetPixelFormat(channel_format),
|
||||
GetPixelType(format), data);
|
||||
|
||||
functions_->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
|
||||
functions_->glBindTexture(GL_TEXTURE_3D, current_tex);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
void OpenGLRenderer::AttachTextureAsDestination(Texture* texture)
|
||||
{
|
||||
functions_->glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_);
|
||||
functions_->glFramebufferTexture2D(GL_FRAMEBUFFER,
|
||||
@@ -143,29 +189,6 @@ void OpenGLRenderer::DetachTextureAsDestination()
|
||||
functions_->glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
QVariant OpenGLRenderer::CreateNativeTexture(VideoParams p, void *data, int linesize)
|
||||
{
|
||||
GLuint texture;
|
||||
functions_->glGenTextures(1, &texture);
|
||||
|
||||
functions_->glPixelStorei(GL_UNPACK_ROW_LENGTH, linesize);
|
||||
|
||||
GLint current_tex;
|
||||
functions_->glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤t_tex);
|
||||
|
||||
functions_->glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
functions_->glTexImage2D(GL_TEXTURE_2D, 0, GetInternalFormat(p.format()),
|
||||
p.effective_width(), p.effective_height(), 0, GL_RGBA,
|
||||
GetPixelType(p.format()), data);
|
||||
|
||||
functions_->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
|
||||
functions_->glBindTexture(GL_TEXTURE_2D, current_tex);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
void OpenGLRenderer::DestroyNativeTexture(QVariant texture)
|
||||
{
|
||||
GLuint t = texture.value<GLuint>();
|
||||
@@ -203,7 +226,7 @@ void OpenGLRenderer::DestroyNativeShader(QVariant shader)
|
||||
delete Node::ValueToPtr<QOpenGLShaderProgram>(shader);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::UploadToTexture(Texture *texture, void *data, int linesize)
|
||||
void OpenGLRenderer::UploadToTexture(Texture *texture, const void *data, int linesize)
|
||||
{
|
||||
GLuint t = texture->id().value<GLuint>();
|
||||
const VideoParams& p = texture->params();
|
||||
@@ -252,11 +275,17 @@ void OpenGLRenderer::DownloadFromTexture(Texture* texture, void *data, int lines
|
||||
functions_->glBindTexture(GL_TEXTURE_2D, current_tex);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::Blit(QVariant s, ShaderJob job, Renderer::Texture *destination, VideoParams destination_params)
|
||||
struct TextureToBind {
|
||||
TexturePtr texture;
|
||||
Texture::Interpolation interpolation;
|
||||
};
|
||||
|
||||
void OpenGLRenderer::Blit(QVariant s, ShaderJob job, Texture *destination, VideoParams destination_params)
|
||||
{
|
||||
// If this node is iterative, we'll pick up which input here
|
||||
QString iterative_name;
|
||||
GLuint iterative_input = 0;
|
||||
QList<GLuint> textures_to_bind;
|
||||
QVector<TextureToBind> textures_to_bind;
|
||||
bool input_textures_have_alpha = false;
|
||||
|
||||
QOpenGLShaderProgram* shader = Node::ValueToPtr<QOpenGLShaderProgram>(s);
|
||||
@@ -325,10 +354,11 @@ void OpenGLRenderer::Blit(QVariant s, ShaderJob job, Renderer::Texture *destinat
|
||||
// If this texture binding is the iterative input, set it here
|
||||
if (it.key() == job.GetIterativeInput()) {
|
||||
iterative_input = textures_to_bind.size();
|
||||
iterative_name = it.key();
|
||||
}
|
||||
|
||||
GLuint tex_id = texture ? texture->id().value<GLuint>() : 0;
|
||||
textures_to_bind.append(tex_id);
|
||||
textures_to_bind.append({texture, job.GetInterpolation(it.key())});
|
||||
|
||||
if (texture && texture->has_meaningful_alpha()) {
|
||||
input_textures_have_alpha = true;
|
||||
@@ -383,9 +413,17 @@ void OpenGLRenderer::Blit(QVariant s, ShaderJob job, Renderer::Texture *destinat
|
||||
|
||||
// Bind all textures
|
||||
for (int i=0; i<textures_to_bind.size(); i++) {
|
||||
const TextureToBind& t = textures_to_bind.at(i);
|
||||
TexturePtr texture = t.texture;
|
||||
|
||||
GLuint tex_id = texture ? texture->id().value<GLuint>() : 0;
|
||||
|
||||
functions_->glActiveTexture(GL_TEXTURE0 + i);
|
||||
functions_->glBindTexture(GL_TEXTURE_2D, textures_to_bind.at(i));
|
||||
PrepareInputTexture(job.GetBilinearFiltering());
|
||||
|
||||
GLenum target = (texture->type() == Texture::k3D) ? GL_TEXTURE_3D : GL_TEXTURE_2D;
|
||||
functions_->glBindTexture(target, tex_id);
|
||||
|
||||
PrepareInputTexture(target, t.interpolation);
|
||||
}
|
||||
|
||||
// Set ove_resolution to the destination to the "logical" resolution of the destination
|
||||
@@ -479,7 +517,9 @@ void OpenGLRenderer::Blit(QVariant s, ShaderJob job, Renderer::Texture *destinat
|
||||
// last drew
|
||||
functions_->glActiveTexture(GL_TEXTURE0 + iterative_input);
|
||||
functions_->glBindTexture(GL_TEXTURE_2D, input_tex->id().value<GLuint>());
|
||||
PrepareInputTexture(job.GetBilinearFiltering());
|
||||
|
||||
// At this time, we only support iterating 2D textures
|
||||
PrepareInputTexture(GL_TEXTURE_2D, job.GetInterpolation(iterative_name));
|
||||
}
|
||||
|
||||
// Swap so that the next iteration, the texture we draw now will be the input texture next
|
||||
@@ -499,8 +539,9 @@ void OpenGLRenderer::Blit(QVariant s, ShaderJob job, Renderer::Texture *destinat
|
||||
|
||||
// Release any textures we bound before
|
||||
for (int i=textures_to_bind.size()-1; i>=0; i--) {
|
||||
GLenum target = (textures_to_bind.at(i).texture->type() == Texture::k3D) ? GL_TEXTURE_3D : GL_TEXTURE_2D;
|
||||
functions_->glActiveTexture(GL_TEXTURE0 + i);
|
||||
functions_->glBindTexture(GL_TEXTURE_2D, 0);
|
||||
functions_->glBindTexture(target, 0);
|
||||
}
|
||||
|
||||
// Release shader
|
||||
@@ -513,17 +554,17 @@ void OpenGLRenderer::Blit(QVariant s, ShaderJob job, Renderer::Texture *destinat
|
||||
vao_.destroy();
|
||||
}
|
||||
|
||||
GLint OpenGLRenderer::GetInternalFormat(PixelFormat::Format format)
|
||||
GLint OpenGLRenderer::GetInternalFormat(PixelFormat::Format format, bool with_alpha)
|
||||
{
|
||||
switch (format) {
|
||||
case PixelFormat::PIX_FMT_RGBA8:
|
||||
return GL_RGBA8;
|
||||
return with_alpha ? GL_RGBA8 : GL_RGB8;
|
||||
case PixelFormat::PIX_FMT_RGBA16U:
|
||||
return GL_RGBA16;
|
||||
return with_alpha ? GL_RGBA16 : GL_RGB16;
|
||||
case PixelFormat::PIX_FMT_RGBA16F:
|
||||
return GL_RGBA16F;
|
||||
return with_alpha ? GL_RGBA16F : GL_RGB16F;
|
||||
case PixelFormat::PIX_FMT_RGBA32F:
|
||||
return GL_RGBA32F;
|
||||
return with_alpha ? GL_RGBA32F : GL_RGB32F;
|
||||
|
||||
case PixelFormat::PIX_FMT_INVALID:
|
||||
case PixelFormat::PIX_FMT_COUNT:
|
||||
@@ -553,21 +594,40 @@ GLenum OpenGLRenderer::GetPixelType(PixelFormat::Format format)
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
void OpenGLRenderer::PrepareInputTexture(bool bilinear)
|
||||
GLenum OpenGLRenderer::GetPixelFormat(Texture::ChannelFormat format)
|
||||
{
|
||||
if (bilinear) {
|
||||
// Use mipmapped bilinear
|
||||
functions_->glGenerateMipmap(GL_TEXTURE_2D);
|
||||
functions_->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
functions_->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
} else {
|
||||
// Use nearest
|
||||
functions_->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
functions_->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
switch (format) {
|
||||
case Texture::kRGBA:
|
||||
return GL_RGBA;
|
||||
case Texture::kRGB:
|
||||
return GL_RGB;
|
||||
case Texture::kRedOnly:
|
||||
return GL_RED;
|
||||
}
|
||||
|
||||
functions_->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
functions_->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
return GL_INVALID_ENUM;
|
||||
}
|
||||
|
||||
void OpenGLRenderer::PrepareInputTexture(GLenum target, Texture::Interpolation interp)
|
||||
{
|
||||
switch (interp) {
|
||||
case Texture::kNearest:
|
||||
functions_->glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
functions_->glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
break;
|
||||
case Texture::kLinear:
|
||||
functions_->glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
functions_->glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
break;
|
||||
case Texture::kMipmappedLinear:
|
||||
functions_->glGenerateMipmap(target);
|
||||
functions_->glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
functions_->glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
break;
|
||||
}
|
||||
|
||||
functions_->glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
functions_->glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
@@ -28,7 +28,7 @@
|
||||
#include <QOpenGLVertexArrayObject>
|
||||
#include <QThread>
|
||||
|
||||
#include "render/backend/renderer.h"
|
||||
#include "render/renderer.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
@@ -47,11 +47,12 @@ public:
|
||||
public slots:
|
||||
virtual void PostInit() override;
|
||||
|
||||
virtual void Destroy() override;
|
||||
virtual void DestroyInternal() override;
|
||||
|
||||
virtual void ClearDestination(double r = 0.0, double g = 0.0, double b = 0.0, double a = 0.0) override;
|
||||
|
||||
virtual QVariant CreateNativeTexture(OLIVE_NAMESPACE::VideoParams param, void* data = nullptr, int linesize = 0) override;
|
||||
virtual QVariant CreateNativeTexture2D(int width, int height, OLIVE_NAMESPACE::PixelFormat::Format format, OLIVE_NAMESPACE::Texture::ChannelFormat channel_format, const void* data = nullptr, int linesize = 0) override;
|
||||
virtual QVariant CreateNativeTexture3D(int width, int height, int depth, OLIVE_NAMESPACE::PixelFormat::Format format, OLIVE_NAMESPACE::Texture::ChannelFormat channel_format, const void* data = nullptr, int linesize = 0) override;
|
||||
|
||||
virtual void DestroyNativeTexture(QVariant texture) override;
|
||||
|
||||
@@ -59,26 +60,28 @@ public slots:
|
||||
|
||||
virtual void DestroyNativeShader(QVariant shader) override;
|
||||
|
||||
virtual void UploadToTexture(OLIVE_NAMESPACE::Renderer::Texture* texture, void* data, int linesize) override;
|
||||
virtual void UploadToTexture(OLIVE_NAMESPACE::Texture* texture, const void* data, int linesize) override;
|
||||
|
||||
virtual void DownloadFromTexture(OLIVE_NAMESPACE::Renderer::Texture* texture, void* data, int linesize) override;
|
||||
virtual void DownloadFromTexture(OLIVE_NAMESPACE::Texture* texture, void* data, int linesize) override;
|
||||
|
||||
protected slots:
|
||||
virtual void Blit(QVariant shader,
|
||||
OLIVE_NAMESPACE::ShaderJob job,
|
||||
OLIVE_NAMESPACE::Renderer::Texture* destination,
|
||||
OLIVE_NAMESPACE::Texture* destination,
|
||||
OLIVE_NAMESPACE::VideoParams destination_params) override;
|
||||
|
||||
private:
|
||||
static GLint GetInternalFormat(PixelFormat::Format format);
|
||||
static GLint GetInternalFormat(PixelFormat::Format format, bool with_alpha);
|
||||
|
||||
static GLenum GetPixelType(PixelFormat::Format format);
|
||||
|
||||
void AttachTextureAsDestination(OLIVE_NAMESPACE::Renderer::Texture* texture);
|
||||
static GLenum GetPixelFormat(Texture::ChannelFormat format);
|
||||
|
||||
void AttachTextureAsDestination(OLIVE_NAMESPACE::Texture* texture);
|
||||
|
||||
void DetachTextureAsDestination();
|
||||
|
||||
void PrepareInputTexture(bool bilinear);
|
||||
void PrepareInputTexture(GLenum target, Texture::Interpolation interp);
|
||||
|
||||
QOpenGLContext* context_;
|
||||
|
||||
@@ -0,0 +1,229 @@
|
||||
/***
|
||||
|
||||
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"
|
||||
|
||||
#include <QFloat16>
|
||||
|
||||
#include "common/ocioutils.h"
|
||||
#include "render/colormanager.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
Renderer::Renderer(QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
TexturePtr Renderer::CreateTexture(const VideoParams ¶ms, Texture::Type type, Texture::ChannelFormat channel_format, const void *data, int linesize)
|
||||
{
|
||||
QVariant v;
|
||||
|
||||
if (type == Texture::k3D) {
|
||||
v = CreateNativeTexture3D(params.effective_width(), params.effective_height(),
|
||||
params.effective_depth(), params.format(), channel_format, data, linesize);
|
||||
} else {
|
||||
v = CreateNativeTexture2D(params.effective_width(), params.effective_height(), params.format(),
|
||||
channel_format, data, linesize);
|
||||
}
|
||||
|
||||
if (v.isNull()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::make_shared<Texture>(this, v, params, type);
|
||||
}
|
||||
|
||||
TexturePtr Renderer::CreateTexture(const VideoParams ¶ms, const void *data, int linesize)
|
||||
{
|
||||
return CreateTexture(params, Texture::k2D, Texture::kRGBA, data, linesize);
|
||||
}
|
||||
|
||||
void Renderer::BlitColorManaged(ColorProcessorPtr color_processor, TexturePtr source, Texture *destination, bool flipped)
|
||||
{
|
||||
BlitColorManagedInternal(color_processor, source, destination, destination->params(), flipped);
|
||||
}
|
||||
|
||||
void Renderer::BlitColorManaged(ColorProcessorPtr color_processor, TexturePtr source, VideoParams params, bool flipped)
|
||||
{
|
||||
BlitColorManagedInternal(color_processor, source, nullptr, params, flipped);
|
||||
}
|
||||
|
||||
void Renderer::Destroy()
|
||||
{
|
||||
color_cache_.clear();
|
||||
|
||||
DestroyInternal();
|
||||
}
|
||||
|
||||
bool Renderer::GetColorContext(ColorProcessorPtr color_processor, Renderer::ColorContext *ctx)
|
||||
{
|
||||
ColorContext& color_ctx = *ctx;
|
||||
|
||||
if (color_cache_.contains(color_processor->id())) {
|
||||
color_ctx = color_cache_.value(color_processor->id());
|
||||
return true;
|
||||
} else {
|
||||
// Create shader description
|
||||
const char* ocio_func_name = "OCIODisplay";
|
||||
auto shader_desc = OCIO::GpuShaderDesc::CreateShaderDesc();
|
||||
shader_desc->setLanguage(OCIO::GPU_LANGUAGE_GLSL_1_3);
|
||||
shader_desc->setFunctionName(ocio_func_name);
|
||||
shader_desc->setResourcePrefix("ocio_");
|
||||
|
||||
// Generate shader
|
||||
color_processor->GetProcessor()->getDefaultGPUProcessor()->extractGpuShaderInfo(shader_desc);
|
||||
|
||||
QString shader_frag;
|
||||
shader_frag.append(QStringLiteral("#version 150\n"
|
||||
"\n"
|
||||
"#ifdef GL_ES\n"
|
||||
"precision highp int;\n"
|
||||
"precision highp float;\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"// Main texture input\n"
|
||||
"uniform sampler2D ove_maintex;\n"
|
||||
"\n"
|
||||
"// Macros so OCIO's shaders work on this GLSL version\n"
|
||||
"#define texture2D texture\n"
|
||||
"#define texture3D texture\n"
|
||||
"\n"
|
||||
"// Main texture coordinate\n"
|
||||
"in vec2 ove_texcoord;\n"
|
||||
"\n"
|
||||
"// Texture output\n"
|
||||
"out vec4 fragColor;\n"));
|
||||
shader_frag.append(shader_desc->getShaderText());
|
||||
shader_frag.append(QStringLiteral("\n"
|
||||
"void main() {\n"
|
||||
" fragColor = %1(texture(ove_maintex, ove_texcoord));\n"
|
||||
"}\n").arg(ocio_func_name));
|
||||
|
||||
// Try to compile shader
|
||||
color_ctx.compiled_shader = CreateNativeShader(ShaderCode(shader_frag,
|
||||
FileFunctions::ReadFileAsString(QStringLiteral(":/shaders/default.vert"))));
|
||||
|
||||
if (color_ctx.compiled_shader.isNull()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
color_ctx.lut3d_textures.resize(shader_desc->getNum3DTextures());
|
||||
for (unsigned int i=0; i<shader_desc->getNum3DTextures(); i++) {
|
||||
const char* tex_name = nullptr;
|
||||
const char* sampler_name = nullptr;
|
||||
unsigned int edge_len = 0;
|
||||
OCIO::Interpolation interpolation = OCIO::INTERP_LINEAR;
|
||||
|
||||
shader_desc->get3DTexture(i, tex_name, sampler_name, edge_len, interpolation);
|
||||
|
||||
if (!tex_name || !*tex_name
|
||||
|| !sampler_name || !*sampler_name
|
||||
|| !edge_len) {
|
||||
qCritical() << "3D LUT texture data is corrupted";
|
||||
return false;
|
||||
}
|
||||
|
||||
const float* values = nullptr;
|
||||
shader_desc->get3DTextureValues(i, values);
|
||||
if (!values) {
|
||||
qCritical() << "3D LUT texture values are missing";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Allocate 3D LUT
|
||||
color_ctx.lut3d_textures[i].texture = CreateTexture(VideoParams(edge_len, edge_len, edge_len, PixelFormat::PIX_FMT_RGBA32F),
|
||||
Texture::k3D, Texture::kRGB, values);
|
||||
color_ctx.lut3d_textures[i].name = sampler_name;
|
||||
color_ctx.lut3d_textures[i].interpolation = (interpolation == OCIO::INTERP_NEAREST) ? Texture::kNearest : Texture::kLinear;
|
||||
}
|
||||
|
||||
color_ctx.lut1d_textures.resize(shader_desc->getNumTextures());
|
||||
for (unsigned int i=0; i<shader_desc->getNumTextures(); i++) {
|
||||
const char* tex_name = nullptr;
|
||||
const char* sampler_name = nullptr;
|
||||
unsigned int width = 0, height = 0;
|
||||
OCIO::GpuShaderDesc::TextureType channel = OCIO::GpuShaderDesc::TEXTURE_RGB_CHANNEL;
|
||||
OCIO::Interpolation interpolation = OCIO::INTERP_LINEAR;
|
||||
|
||||
shader_desc->getTexture(i, tex_name, sampler_name, width, height, channel, interpolation);
|
||||
|
||||
if (!tex_name || !*tex_name
|
||||
|| !sampler_name || !*sampler_name
|
||||
|| !width) {
|
||||
qCritical() << "1D LUT texture data is corrupted";
|
||||
return false;
|
||||
}
|
||||
|
||||
const float* values = nullptr;
|
||||
shader_desc->getTextureValues(i, values);
|
||||
if (!values) {
|
||||
qCritical() << "1D LUT texture values are missing";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Allocate 1D LUT
|
||||
color_ctx.lut1d_textures[i].texture = CreateTexture(VideoParams(width, height, PixelFormat::PIX_FMT_RGBA32F),
|
||||
Texture::k2D,
|
||||
(channel == OCIO::GpuShaderDesc::TEXTURE_RED_CHANNEL) ? Texture::kRedOnly : Texture::kRGB,
|
||||
values);
|
||||
color_ctx.lut1d_textures[i].name = sampler_name;
|
||||
color_ctx.lut1d_textures[i].interpolation = (interpolation == OCIO::INTERP_NEAREST) ? Texture::kNearest : Texture::kLinear;
|
||||
}
|
||||
|
||||
color_cache_.insert(color_processor->id(), color_ctx);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::BlitColorManagedInternal(ColorProcessorPtr color_processor, TexturePtr source, Texture *destination, VideoParams params, bool flipped)
|
||||
{
|
||||
ColorContext color_ctx;
|
||||
if (!GetColorContext(color_processor, &color_ctx)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ShaderJob job;
|
||||
job.InsertValue(QStringLiteral("ove_maintex"), ShaderValue(QVariant::fromValue(source), NodeParam::kTexture));
|
||||
foreach (const ColorContext::LUT& l, color_ctx.lut3d_textures) {
|
||||
job.InsertValue(l.name, ShaderValue(QVariant::fromValue(l.texture), NodeParam::kTexture));
|
||||
job.SetInterpolation(l.name, l.interpolation);
|
||||
}
|
||||
foreach (const ColorContext::LUT& l, color_ctx.lut1d_textures) {
|
||||
job.InsertValue(l.name, ShaderValue(QVariant::fromValue(l.texture), NodeParam::kTexture));
|
||||
job.SetInterpolation(l.name, l.interpolation);
|
||||
}
|
||||
|
||||
if (flipped) {
|
||||
QMatrix4x4 mat;
|
||||
mat.scale(1, -1, 1);
|
||||
job.SetMatrix(mat);
|
||||
}
|
||||
|
||||
if (destination) {
|
||||
BlitToTexture(color_ctx.compiled_shader, job, destination);
|
||||
} else {
|
||||
Blit(color_ctx.compiled_shader, job, params);
|
||||
}
|
||||
}
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
@@ -29,9 +29,12 @@
|
||||
#include "node/node.h"
|
||||
#include "render/colorprocessor.h"
|
||||
#include "render/videoparams.h"
|
||||
#include "texture.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
class ShaderJob;
|
||||
|
||||
class Renderer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -40,90 +43,12 @@ public:
|
||||
|
||||
virtual bool Init() = 0;
|
||||
|
||||
class Texture
|
||||
{
|
||||
public:
|
||||
Texture(Renderer* renderer, const QVariant& native, const VideoParams& param) :
|
||||
renderer_(renderer),
|
||||
params_(param),
|
||||
id_(native),
|
||||
meaningful_alpha_(true)
|
||||
{
|
||||
}
|
||||
|
||||
~Texture()
|
||||
{
|
||||
renderer_->DestroyNativeTexture(id_);
|
||||
}
|
||||
|
||||
QVariant id() const
|
||||
{
|
||||
return id_;
|
||||
}
|
||||
|
||||
const VideoParams& params() const
|
||||
{
|
||||
return params_;
|
||||
}
|
||||
|
||||
void Upload(void* data, int linesize)
|
||||
{
|
||||
renderer_->UploadToTexture(this, data, linesize);
|
||||
}
|
||||
|
||||
int width() const
|
||||
{
|
||||
return params_.width();
|
||||
}
|
||||
|
||||
int height() const
|
||||
{
|
||||
return params_.height();
|
||||
}
|
||||
|
||||
PixelFormat::Format format() const
|
||||
{
|
||||
return params_.format();
|
||||
}
|
||||
|
||||
int divider() const
|
||||
{
|
||||
return params_.divider();
|
||||
}
|
||||
|
||||
const rational& pixel_aspect_ratio() const
|
||||
{
|
||||
return params_.pixel_aspect_ratio();
|
||||
}
|
||||
|
||||
bool has_meaningful_alpha() const
|
||||
{
|
||||
return meaningful_alpha_;
|
||||
}
|
||||
|
||||
void set_has_meaningful_alpha(bool e)
|
||||
{
|
||||
meaningful_alpha_ = e;
|
||||
}
|
||||
|
||||
private:
|
||||
Renderer* renderer_;
|
||||
|
||||
VideoParams params_;
|
||||
|
||||
QVariant id_;
|
||||
|
||||
bool meaningful_alpha_;
|
||||
|
||||
};
|
||||
|
||||
using TexturePtr = std::shared_ptr<Texture>;
|
||||
|
||||
TexturePtr CreateTexture(const VideoParams& param, void* data = nullptr, int linesize = 0);
|
||||
TexturePtr CreateTexture(const VideoParams& params, Texture::Type type, Texture::ChannelFormat channel_format, const void* data = nullptr, int linesize = 0);
|
||||
TexturePtr CreateTexture(const VideoParams& params, const void *data = nullptr, int linesize = 0);
|
||||
|
||||
void BlitToTexture(QVariant shader,
|
||||
OLIVE_NAMESPACE::ShaderJob job,
|
||||
OLIVE_NAMESPACE::Renderer::Texture* destination)
|
||||
OLIVE_NAMESPACE::Texture* destination)
|
||||
{
|
||||
Blit(shader, job, destination, destination->params());
|
||||
}
|
||||
@@ -138,14 +63,17 @@ public:
|
||||
void BlitColorManaged(ColorProcessorPtr color_processor, TexturePtr source, Texture* destination, bool flipped = false);
|
||||
void BlitColorManaged(ColorProcessorPtr color_processor, TexturePtr source, VideoParams params, bool flipped = false);
|
||||
|
||||
void Destroy();
|
||||
|
||||
public slots:
|
||||
virtual void PostInit() = 0;
|
||||
|
||||
virtual void Destroy() = 0;
|
||||
virtual void DestroyInternal() = 0;
|
||||
|
||||
virtual void ClearDestination(double r = 0.0, double g = 0.0, double b = 0.0, double a = 0.0) = 0;
|
||||
|
||||
virtual QVariant CreateNativeTexture(OLIVE_NAMESPACE::VideoParams param, void* data = nullptr, int linesize = 0) = 0;
|
||||
virtual QVariant CreateNativeTexture2D(int width, int height, OLIVE_NAMESPACE::PixelFormat::Format format, OLIVE_NAMESPACE::Texture::ChannelFormat channel_format, const void* data = nullptr, int linesize = 0) = 0;
|
||||
virtual QVariant CreateNativeTexture3D(int width, int height, int depth, OLIVE_NAMESPACE::PixelFormat::Format format, OLIVE_NAMESPACE::Texture::ChannelFormat channel_format, const void* data = nullptr, int linesize = 0) = 0;
|
||||
|
||||
virtual void DestroyNativeTexture(QVariant texture) = 0;
|
||||
|
||||
@@ -153,28 +81,39 @@ public slots:
|
||||
|
||||
virtual void DestroyNativeShader(QVariant shader) = 0;
|
||||
|
||||
virtual void UploadToTexture(OLIVE_NAMESPACE::Renderer::Texture* texture, void* data, int linesize) = 0;
|
||||
virtual void UploadToTexture(OLIVE_NAMESPACE::Texture* texture, const void* data, int linesize) = 0;
|
||||
|
||||
virtual void DownloadFromTexture(OLIVE_NAMESPACE::Renderer::Texture* texture, void* data, int linesize) = 0;
|
||||
virtual void DownloadFromTexture(OLIVE_NAMESPACE::Texture* texture, void* data, int linesize) = 0;
|
||||
|
||||
protected slots:
|
||||
virtual void Blit(QVariant shader,
|
||||
OLIVE_NAMESPACE::ShaderJob job,
|
||||
OLIVE_NAMESPACE::Renderer::Texture* destination,
|
||||
OLIVE_NAMESPACE::Texture* destination,
|
||||
OLIVE_NAMESPACE::VideoParams destination_params) = 0;
|
||||
|
||||
private:
|
||||
struct ColorContext {
|
||||
QVariant shader;
|
||||
TexturePtr lut;
|
||||
struct LUT {
|
||||
TexturePtr texture;
|
||||
Texture::Interpolation interpolation;
|
||||
QString name;
|
||||
};
|
||||
|
||||
QVariant compiled_shader;
|
||||
QVector<LUT> lut3d_textures;
|
||||
QVector<LUT> lut1d_textures;
|
||||
|
||||
};
|
||||
|
||||
bool GetColorContext(ColorProcessorPtr color_processor, ColorContext* ctx);
|
||||
|
||||
void BlitColorManagedInternal(ColorProcessorPtr color_processor, TexturePtr source,
|
||||
Texture* destination, VideoParams params, bool flipped);
|
||||
|
||||
QHash<QString, ColorContext> color_cache_;
|
||||
|
||||
};
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
Q_DECLARE_METATYPE(OLIVE_NAMESPACE::Renderer::TexturePtr);
|
||||
|
||||
#endif // RENDERCONTEXT_H
|
||||
+33
-15
@@ -54,10 +54,10 @@ void RendererThreadWrapper::PostInit()
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
void RendererThreadWrapper::Destroy()
|
||||
void RendererThreadWrapper::DestroyInternal()
|
||||
{
|
||||
if (thread_) {
|
||||
QMetaObject::invokeMethod(inner_, "Destroy", Qt::BlockingQueuedConnection);
|
||||
QMetaObject::invokeMethod(inner_, "DestroyInternal", Qt::BlockingQueuedConnection);
|
||||
inner_ = nullptr;
|
||||
|
||||
thread_->quit();
|
||||
@@ -76,14 +76,34 @@ void RendererThreadWrapper::ClearDestination(double r, double g, double b, doubl
|
||||
Q_ARG(double, a));
|
||||
}
|
||||
|
||||
QVariant RendererThreadWrapper::CreateNativeTexture(VideoParams param, void *data, int linesize)
|
||||
QVariant RendererThreadWrapper::CreateNativeTexture2D(int width, int height, PixelFormat::Format format, OLIVE_NAMESPACE::Texture::ChannelFormat channel_format, const void *data, int linesize)
|
||||
{
|
||||
QVariant v;
|
||||
|
||||
QMetaObject::invokeMethod(inner_, "CreateNativeTexture", Qt::BlockingQueuedConnection,
|
||||
QMetaObject::invokeMethod(inner_, "CreateNativeTexture2D", Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(QVariant, v),
|
||||
OLIVE_NS_ARG(VideoParams, param),
|
||||
Q_ARG(void*, data),
|
||||
Q_ARG(int, width),
|
||||
Q_ARG(int, height),
|
||||
OLIVE_NS_ARG(PixelFormat::Format, format),
|
||||
OLIVE_NS_ARG(Texture::ChannelFormat, channel_format),
|
||||
Q_ARG(const void*, data),
|
||||
Q_ARG(int, linesize));
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
QVariant RendererThreadWrapper::CreateNativeTexture3D(int width, int height, int depth, PixelFormat::Format format, Texture::ChannelFormat channel_format, const void *data, int linesize)
|
||||
{
|
||||
QVariant v;
|
||||
|
||||
QMetaObject::invokeMethod(inner_, "CreateNativeTexture3D", Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(QVariant, v),
|
||||
Q_ARG(int, width),
|
||||
Q_ARG(int, height),
|
||||
Q_ARG(int, depth),
|
||||
OLIVE_NS_ARG(PixelFormat::Format, format),
|
||||
OLIVE_NS_ARG(Texture::ChannelFormat, channel_format),
|
||||
Q_ARG(const void*, data),
|
||||
Q_ARG(int, linesize));
|
||||
|
||||
return v;
|
||||
@@ -112,30 +132,28 @@ void RendererThreadWrapper::DestroyNativeShader(QVariant shader)
|
||||
Q_ARG(QVariant, shader));
|
||||
}
|
||||
|
||||
void RendererThreadWrapper::UploadToTexture(Renderer::Texture *texture, void *data, int linesize)
|
||||
void RendererThreadWrapper::UploadToTexture(Texture *texture, const void *data, int linesize)
|
||||
{
|
||||
QMetaObject::invokeMethod(inner_, "UploadToTexture", Qt::BlockingQueuedConnection,
|
||||
OLIVE_NS_ARG(Renderer::Texture*, texture),
|
||||
Q_ARG(void*, data),
|
||||
OLIVE_NS_ARG(Texture*, texture),
|
||||
Q_ARG(const void*, data),
|
||||
Q_ARG(int, linesize));
|
||||
}
|
||||
|
||||
void RendererThreadWrapper::DownloadFromTexture(Renderer::Texture *texture, void *data, int linesize)
|
||||
void RendererThreadWrapper::DownloadFromTexture(Texture *texture, void *data, int linesize)
|
||||
{
|
||||
QMetaObject::invokeMethod(inner_, "DownloadFromTexture", Qt::BlockingQueuedConnection,
|
||||
OLIVE_NS_ARG(Renderer::Texture*, texture),
|
||||
OLIVE_NS_ARG(Texture*, texture),
|
||||
Q_ARG(void*, data),
|
||||
Q_ARG(int, linesize));
|
||||
}
|
||||
|
||||
void RendererThreadWrapper::Blit(QVariant shader, ShaderJob job, Renderer::Texture *destination, VideoParams destination_params)
|
||||
void RendererThreadWrapper::Blit(QVariant shader, ShaderJob job, Texture *destination, VideoParams destination_params)
|
||||
{
|
||||
Renderer::TexturePtr tex;
|
||||
|
||||
QMetaObject::invokeMethod(inner_, "Blit", Qt::BlockingQueuedConnection,
|
||||
Q_ARG(QVariant, shader),
|
||||
OLIVE_NS_ARG(ShaderJob, job),
|
||||
OLIVE_NS_ARG(Renderer::Texture*, destination),
|
||||
OLIVE_NS_ARG(Texture*, destination),
|
||||
OLIVE_NS_ARG(VideoParams, destination_params));
|
||||
}
|
||||
|
||||
@@ -43,11 +43,12 @@ public:
|
||||
public slots:
|
||||
virtual void PostInit() override;
|
||||
|
||||
virtual void Destroy() override;
|
||||
virtual void DestroyInternal() override;
|
||||
|
||||
virtual void ClearDestination(double r = 0.0, double g = 0.0, double b = 0.0, double a = 0.0) override;
|
||||
|
||||
virtual QVariant CreateNativeTexture(OLIVE_NAMESPACE::VideoParams param, void* data = nullptr, int linesize = 0) override;
|
||||
virtual QVariant CreateNativeTexture2D(int width, int height, OLIVE_NAMESPACE::PixelFormat::Format format, OLIVE_NAMESPACE::Texture::ChannelFormat channel_format, const void* data = nullptr, int linesize = 0) override;
|
||||
virtual QVariant CreateNativeTexture3D(int width, int height, int depth, OLIVE_NAMESPACE::PixelFormat::Format format, OLIVE_NAMESPACE::Texture::ChannelFormat channel_format, const void* data = nullptr, int linesize = 0) override;
|
||||
|
||||
virtual void DestroyNativeTexture(QVariant texture) override;
|
||||
|
||||
@@ -55,14 +56,14 @@ public slots:
|
||||
|
||||
virtual void DestroyNativeShader(QVariant shader) override;
|
||||
|
||||
virtual void UploadToTexture(OLIVE_NAMESPACE::Renderer::Texture* texture, void* data, int linesize) override;
|
||||
virtual void UploadToTexture(OLIVE_NAMESPACE::Texture* texture, const void* data, int linesize) override;
|
||||
|
||||
virtual void DownloadFromTexture(OLIVE_NAMESPACE::Renderer::Texture* texture, void* data, int linesize) override;
|
||||
virtual void DownloadFromTexture(OLIVE_NAMESPACE::Texture* texture, void* data, int linesize) override;
|
||||
|
||||
protected slots:
|
||||
virtual void Blit(QVariant shader,
|
||||
OLIVE_NAMESPACE::ShaderJob job,
|
||||
OLIVE_NAMESPACE::Renderer::Texture* destination,
|
||||
OLIVE_NAMESPACE::Texture* destination,
|
||||
OLIVE_NAMESPACE::VideoParams destination_params) override;
|
||||
|
||||
private:
|
||||
@@ -27,8 +27,8 @@
|
||||
|
||||
#include "config/config.h"
|
||||
#include "core.h"
|
||||
#include "render/backend/opengl/openglrenderer.h"
|
||||
#include "render/backend/rendererthreadwrapper.h"
|
||||
#include "render/opengl/openglrenderer.h"
|
||||
#include "render/rendererthreadwrapper.h"
|
||||
#include "renderprocessor.h"
|
||||
#include "task/conform/conform.h"
|
||||
#include "task/taskmanager.h"
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#include "node/graph.h"
|
||||
#include "node/output/viewer/viewer.h"
|
||||
#include "node/traverser.h"
|
||||
#include "render/backend/renderer.h"
|
||||
#include "render/renderer.h"
|
||||
#include "rendercache.h"
|
||||
#include "stillimagecache.h"
|
||||
#include "threading/threadpool.h"
|
||||
|
||||
@@ -54,7 +54,7 @@ void RenderProcessor::Run()
|
||||
NodeValueTable table = ProcessInput(viewer->texture_input(),
|
||||
TimeRange(time, time + viewer->video_params().time_base()));
|
||||
|
||||
Renderer::TexturePtr texture = table.Get(NodeParam::kTexture).value<Renderer::TexturePtr>();
|
||||
TexturePtr texture = table.Get(NodeParam::kTexture).value<TexturePtr>();
|
||||
|
||||
VideoParams frame_params = viewer->video_params();
|
||||
|
||||
@@ -222,7 +222,7 @@ NodeValueTable RenderProcessor::GenerateBlockTable(const TrackOutput *track, con
|
||||
|
||||
QVariant RenderProcessor::ProcessVideoFootage(StreamPtr stream, const rational &input_time)
|
||||
{
|
||||
Renderer::TexturePtr value = nullptr;
|
||||
TexturePtr value = nullptr;
|
||||
|
||||
// Check the still frame cache. On large frames such as high resolution still images, uploading
|
||||
// and color managing them for every frame is a waste of time, so we implement a small cache here
|
||||
@@ -285,9 +285,9 @@ QVariant RenderProcessor::ProcessVideoFootage(StreamPtr stream, const rational &
|
||||
|
||||
if (frame) {
|
||||
// Return a texture from the derived class
|
||||
Renderer::TexturePtr unmanaged_texture = render_ctx_->CreateTexture(frame->video_params(),
|
||||
frame->data(),
|
||||
frame->linesize_pixels());
|
||||
TexturePtr unmanaged_texture = render_ctx_->CreateTexture(frame->video_params(),
|
||||
frame->data(),
|
||||
frame->linesize_pixels());
|
||||
|
||||
// We convert to our rendering pixel format, since that will always be float-based which
|
||||
// is necessary for correct color conversion
|
||||
@@ -361,7 +361,7 @@ QVariant RenderProcessor::ProcessShader(const Node *node, const TimeRange &range
|
||||
|
||||
const VideoParams& video_params = Node::ValueToPtr<ViewerOutput>(ticket_->property("viewer"))->video_params();
|
||||
|
||||
Renderer::TexturePtr destination = render_ctx_->CreateTexture(video_params);
|
||||
TexturePtr destination = render_ctx_->CreateTexture(video_params);
|
||||
|
||||
// Run shader
|
||||
render_ctx_->BlitToTexture(shader, job, destination.get());
|
||||
@@ -423,9 +423,9 @@ QVariant RenderProcessor::ProcessFrameGeneration(const Node *node, const Generat
|
||||
|
||||
node->GenerateFrame(frame, job);
|
||||
|
||||
Renderer::TexturePtr texture = render_ctx_->CreateTexture(frame->video_params(),
|
||||
frame->data(),
|
||||
frame->linesize_pixels());
|
||||
TexturePtr texture = render_ctx_->CreateTexture(frame->video_params(),
|
||||
frame->data(),
|
||||
frame->linesize_pixels());
|
||||
|
||||
texture->set_has_meaningful_alpha(job.GetAlphaChannelRequired());
|
||||
|
||||
@@ -456,7 +456,7 @@ QVariant RenderProcessor::GetCachedFrame(const Node *node, const rational &time)
|
||||
|
||||
qDebug() << "Using cached frame!";
|
||||
|
||||
Renderer::TexturePtr texture = render_ctx_->CreateTexture(f->video_params(), f->data(), f->linesize_pixels());
|
||||
TexturePtr texture = render_ctx_->CreateTexture(f->video_params(), f->data(), f->linesize_pixels());
|
||||
return QVariant::fromValue(texture);
|
||||
} else {
|
||||
qDebug() << "Not using cached frame because frame is null";
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#define RENDERPROCESSOR_H
|
||||
|
||||
#include "node/traverser.h"
|
||||
#include "render/backend/renderer.h"
|
||||
#include "render/renderer.h"
|
||||
#include "rendercache.h"
|
||||
#include "stillimagecache.h"
|
||||
#include "threading/threadticket.h"
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/***
|
||||
|
||||
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 SHADERCODE_H
|
||||
#define SHADERCODE_H
|
||||
|
||||
#include "common/filefunctions.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
class ShaderCode {
|
||||
public:
|
||||
ShaderCode(const QString& frag_code, const QString& vert_code) :
|
||||
frag_code_(frag_code),
|
||||
vert_code_(vert_code)
|
||||
{
|
||||
if (frag_code_.isEmpty()) {
|
||||
frag_code_ = FileFunctions::ReadFileAsString(QStringLiteral(":/shaders/default.frag"));
|
||||
}
|
||||
|
||||
if (vert_code_.isEmpty()) {
|
||||
vert_code_ = FileFunctions::ReadFileAsString(QStringLiteral(":/shaders/default.vert"));
|
||||
}
|
||||
}
|
||||
|
||||
const QString& frag_code() const
|
||||
{
|
||||
return frag_code_;
|
||||
}
|
||||
|
||||
const QString& vert_code() const
|
||||
{
|
||||
return vert_code_;
|
||||
}
|
||||
|
||||
private:
|
||||
QString frag_code_;
|
||||
|
||||
QString vert_code_;
|
||||
|
||||
};
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
#endif // SHADERCODE_H
|
||||
@@ -1,249 +0,0 @@
|
||||
#ifndef SHADERINFO_H
|
||||
#define SHADERINFO_H
|
||||
|
||||
#include <QMatrix4x4>
|
||||
|
||||
#include "codec/samplebuffer.h"
|
||||
#include "common/filefunctions.h"
|
||||
#include "node/input.h"
|
||||
#include "node/inputarray.h"
|
||||
#include "node/value.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
using NodeValueMap = QHash<QString, ShaderValue>;
|
||||
|
||||
class AcceleratedJob {
|
||||
public:
|
||||
AcceleratedJob() = default;
|
||||
|
||||
ShaderValue GetValue(NodeInput* input) const
|
||||
{
|
||||
return value_map_.value(input->id());
|
||||
}
|
||||
|
||||
ShaderValue GetValue(const QString& input) const
|
||||
{
|
||||
return value_map_.value(input);
|
||||
}
|
||||
|
||||
void InsertValue(NodeInput* input, NodeValueDatabase& value)
|
||||
{
|
||||
ShaderValue shader_val;
|
||||
|
||||
shader_val.type = input->data_type();
|
||||
shader_val.array = input->IsArray();
|
||||
|
||||
if (input->IsArray()) {
|
||||
NodeInputArray* array = static_cast<NodeInputArray*>(input);
|
||||
QVector<QVariant> values(array->GetSize());
|
||||
|
||||
for (int j=0;j<array->GetSize();j++) {
|
||||
NodeInput* subparam = array->At(j);
|
||||
|
||||
values[j] = value[subparam].Take(subparam->data_type());
|
||||
}
|
||||
|
||||
shader_val.data = QVariant::fromValue(values);
|
||||
} else {
|
||||
NodeValue node_val = value[input].TakeWithMeta(input->data_type());
|
||||
shader_val.data = node_val.data();
|
||||
shader_val.tag = node_val.tag();
|
||||
}
|
||||
|
||||
InsertValue(input->id(), shader_val);
|
||||
}
|
||||
|
||||
void InsertValue(const QString& input, const ShaderValue& value)
|
||||
{
|
||||
value_map_.insert(input, value);
|
||||
}
|
||||
|
||||
void InsertValue(NodeInput* input, const ShaderValue& value)
|
||||
{
|
||||
value_map_.insert(input->id(), value);
|
||||
}
|
||||
|
||||
void InsertValue(NodeInput* input, const NodeValue& value)
|
||||
{
|
||||
ShaderValue s(value.data(), value.type());
|
||||
s.tag = value.tag();
|
||||
value_map_.insert(input->id(), s);
|
||||
}
|
||||
|
||||
const NodeValueMap &GetValues() const
|
||||
{
|
||||
return value_map_;
|
||||
}
|
||||
|
||||
private:
|
||||
NodeValueMap value_map_;
|
||||
|
||||
};
|
||||
|
||||
class SampleJob : public AcceleratedJob {
|
||||
public:
|
||||
SampleJob()
|
||||
{
|
||||
samples_ = nullptr;
|
||||
}
|
||||
|
||||
SampleJob(const NodeValue& value)
|
||||
{
|
||||
samples_ = value.data().value<SampleBufferPtr>();
|
||||
}
|
||||
|
||||
SampleJob(NodeInput* from, NodeValueDatabase& db)
|
||||
{
|
||||
samples_ = db[from].Take(NodeParam::kSamples).value<SampleBufferPtr>();
|
||||
}
|
||||
|
||||
SampleBufferPtr samples() const
|
||||
{
|
||||
return samples_;
|
||||
}
|
||||
|
||||
bool HasSamples() const
|
||||
{
|
||||
return samples_ && samples_->is_allocated();
|
||||
}
|
||||
|
||||
private:
|
||||
SampleBufferPtr samples_;
|
||||
|
||||
};
|
||||
|
||||
class GenerateJob : public AcceleratedJob {
|
||||
public:
|
||||
GenerateJob()
|
||||
{
|
||||
alpha_channel_required_ = false;
|
||||
}
|
||||
|
||||
bool GetAlphaChannelRequired() const
|
||||
{
|
||||
return alpha_channel_required_;
|
||||
}
|
||||
|
||||
void SetAlphaChannelRequired(bool e)
|
||||
{
|
||||
alpha_channel_required_ = e;
|
||||
}
|
||||
|
||||
private:
|
||||
bool alpha_channel_required_;
|
||||
|
||||
};
|
||||
|
||||
class ShaderJob : public GenerateJob {
|
||||
public:
|
||||
ShaderJob()
|
||||
{
|
||||
iterations_ = 1;
|
||||
iterative_input_ = nullptr;
|
||||
bilinear_ = true;
|
||||
}
|
||||
|
||||
const QMatrix4x4& GetMatrix() const
|
||||
{
|
||||
return matrix_;
|
||||
}
|
||||
|
||||
void SetMatrix(const QMatrix4x4& matrix)
|
||||
{
|
||||
matrix_ = matrix;
|
||||
}
|
||||
|
||||
const QString& GetShaderID() const
|
||||
{
|
||||
return shader_id_;
|
||||
}
|
||||
|
||||
void SetShaderID(const QString& id)
|
||||
{
|
||||
shader_id_ = id;
|
||||
}
|
||||
|
||||
void SetIterations(int iterations, NodeInput* iterative_input)
|
||||
{
|
||||
SetIterations(iterations, iterative_input->id());
|
||||
}
|
||||
|
||||
void SetIterations(int iterations, const QString& iterative_input)
|
||||
{
|
||||
iterations_ = iterations;
|
||||
iterative_input_ = iterative_input;
|
||||
}
|
||||
|
||||
int GetIterationCount() const
|
||||
{
|
||||
return iterations_;
|
||||
}
|
||||
|
||||
const QString& GetIterativeInput() const
|
||||
{
|
||||
return iterative_input_;
|
||||
}
|
||||
|
||||
bool GetBilinearFiltering() const
|
||||
{
|
||||
return bilinear_;
|
||||
}
|
||||
|
||||
void SetBilinearFiltering(bool e)
|
||||
{
|
||||
bilinear_ = e;
|
||||
}
|
||||
|
||||
private:
|
||||
QString shader_id_;
|
||||
|
||||
int iterations_;
|
||||
|
||||
QString iterative_input_;
|
||||
|
||||
bool bilinear_;
|
||||
|
||||
QMatrix4x4 matrix_;
|
||||
|
||||
};
|
||||
|
||||
class ShaderCode {
|
||||
public:
|
||||
ShaderCode(const QString& frag_code, const QString& vert_code) :
|
||||
frag_code_(frag_code),
|
||||
vert_code_(vert_code)
|
||||
{
|
||||
if (frag_code_.isEmpty()) {
|
||||
frag_code_ = FileFunctions::ReadFileAsString(QStringLiteral(":/shaders/default.frag"));
|
||||
}
|
||||
|
||||
if (vert_code_.isEmpty()) {
|
||||
vert_code_ = FileFunctions::ReadFileAsString(QStringLiteral(":/shaders/default.vert"));
|
||||
}
|
||||
}
|
||||
|
||||
const QString& frag_code() const
|
||||
{
|
||||
return frag_code_;
|
||||
}
|
||||
|
||||
const QString& vert_code() const
|
||||
{
|
||||
return vert_code_;
|
||||
}
|
||||
|
||||
private:
|
||||
QString frag_code_;
|
||||
|
||||
QString vert_code_;
|
||||
|
||||
};
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
Q_DECLARE_METATYPE(OLIVE_NAMESPACE::ShaderJob)
|
||||
Q_DECLARE_METATYPE(OLIVE_NAMESPACE::SampleJob)
|
||||
Q_DECLARE_METATYPE(OLIVE_NAMESPACE::GenerateJob)
|
||||
|
||||
#endif // SHADERINFO_H
|
||||
@@ -48,6 +48,8 @@ struct ShaderValue
|
||||
|
||||
};
|
||||
|
||||
using NodeValueMap = QHash<QString, ShaderValue>;
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
#endif // SHADERVALUE_H
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#include "common/rational.h"
|
||||
#include "project/item/footage/stream.h"
|
||||
#include "render/backend/renderer.h"
|
||||
#include "render/texture.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
@@ -13,7 +13,7 @@ class StillImageCache
|
||||
{
|
||||
public:
|
||||
struct Entry {
|
||||
Renderer::TexturePtr texture;
|
||||
TexturePtr texture;
|
||||
StreamPtr stream;
|
||||
QString colorspace;
|
||||
bool alpha_is_associated;
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/***
|
||||
|
||||
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 "texture.h"
|
||||
|
||||
#include "renderer.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
const Texture::Interpolation Texture::kDefaultInterpolation = Texture::kMipmappedLinear;
|
||||
|
||||
Texture::~Texture()
|
||||
{
|
||||
renderer_->DestroyNativeTexture(id_);
|
||||
}
|
||||
|
||||
void Texture::Upload(void *data, int linesize)
|
||||
{
|
||||
renderer_->UploadToTexture(this, data, linesize);
|
||||
}
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
@@ -0,0 +1,134 @@
|
||||
/***
|
||||
|
||||
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 RENDERTEXTURE_H
|
||||
#define RENDERTEXTURE_H
|
||||
|
||||
#include "render/videoparams.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
class Renderer;
|
||||
|
||||
class Texture
|
||||
{
|
||||
public:
|
||||
enum Type {
|
||||
k2D,
|
||||
k3D
|
||||
};
|
||||
|
||||
enum Interpolation {
|
||||
kNearest,
|
||||
kLinear,
|
||||
kMipmappedLinear
|
||||
};
|
||||
|
||||
enum ChannelFormat {
|
||||
kRGBA,
|
||||
kRGB,
|
||||
kRedOnly
|
||||
};
|
||||
|
||||
static const Interpolation kDefaultInterpolation;
|
||||
|
||||
Texture(Renderer* renderer, const QVariant& native, const VideoParams& param, Type type) :
|
||||
renderer_(renderer),
|
||||
params_(param),
|
||||
id_(native),
|
||||
meaningful_alpha_(true),
|
||||
type_(type)
|
||||
{
|
||||
}
|
||||
|
||||
~Texture();
|
||||
|
||||
QVariant id() const
|
||||
{
|
||||
return id_;
|
||||
}
|
||||
|
||||
const VideoParams& params() const
|
||||
{
|
||||
return params_;
|
||||
}
|
||||
|
||||
void Upload(void* data, int linesize);
|
||||
|
||||
int width() const
|
||||
{
|
||||
return params_.width();
|
||||
}
|
||||
|
||||
int height() const
|
||||
{
|
||||
return params_.height();
|
||||
}
|
||||
|
||||
PixelFormat::Format format() const
|
||||
{
|
||||
return params_.format();
|
||||
}
|
||||
|
||||
int divider() const
|
||||
{
|
||||
return params_.divider();
|
||||
}
|
||||
|
||||
const rational& pixel_aspect_ratio() const
|
||||
{
|
||||
return params_.pixel_aspect_ratio();
|
||||
}
|
||||
|
||||
bool has_meaningful_alpha() const
|
||||
{
|
||||
return meaningful_alpha_;
|
||||
}
|
||||
|
||||
void set_has_meaningful_alpha(bool e)
|
||||
{
|
||||
meaningful_alpha_ = e;
|
||||
}
|
||||
|
||||
Type type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
private:
|
||||
Renderer* renderer_;
|
||||
|
||||
VideoParams params_;
|
||||
|
||||
QVariant id_;
|
||||
|
||||
bool meaningful_alpha_;
|
||||
|
||||
Type type_;
|
||||
|
||||
};
|
||||
|
||||
using TexturePtr = std::shared_ptr<Texture>;
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
Q_DECLARE_METATYPE(OLIVE_NAMESPACE::TexturePtr);
|
||||
|
||||
#endif // RENDERTEXTURE_H
|
||||
@@ -62,6 +62,7 @@ const QVector<rational> VideoParams::kStandardPixelAspects = {
|
||||
VideoParams::VideoParams() :
|
||||
width_(0),
|
||||
height_(0),
|
||||
depth_(0),
|
||||
format_(PixelFormat::PIX_FMT_INVALID),
|
||||
interlacing_(Interlacing::kInterlaceNone)
|
||||
{
|
||||
@@ -70,6 +71,20 @@ VideoParams::VideoParams() :
|
||||
VideoParams::VideoParams(const int &width, const int &height, const PixelFormat::Format &format, const rational& pixel_aspect_ratio, const Interlacing &interlacing, const int& divider) :
|
||||
width_(width),
|
||||
height_(height),
|
||||
depth_(0),
|
||||
format_(format),
|
||||
pixel_aspect_ratio_(pixel_aspect_ratio),
|
||||
interlacing_(interlacing),
|
||||
divider_(divider)
|
||||
{
|
||||
calculate_effective_size();
|
||||
validate_pixel_aspect_ratio();
|
||||
}
|
||||
|
||||
VideoParams::VideoParams(const int &width, const int &height, const int &depth, const PixelFormat::Format &format, const rational &pixel_aspect_ratio, const VideoParams::Interlacing &interlacing, const int ÷r) :
|
||||
width_(width),
|
||||
height_(height),
|
||||
depth_(depth),
|
||||
format_(format),
|
||||
pixel_aspect_ratio_(pixel_aspect_ratio),
|
||||
interlacing_(interlacing),
|
||||
@@ -82,6 +97,7 @@ VideoParams::VideoParams(const int &width, const int &height, const PixelFormat:
|
||||
VideoParams::VideoParams(const int &width, const int &height, const rational &time_base, const PixelFormat::Format &format, const rational& pixel_aspect_ratio, const Interlacing &interlacing, const int ÷r) :
|
||||
width_(width),
|
||||
height_(height),
|
||||
depth_(0),
|
||||
time_base_(time_base),
|
||||
format_(format),
|
||||
pixel_aspect_ratio_(pixel_aspect_ratio),
|
||||
@@ -147,6 +163,7 @@ void VideoParams::calculate_effective_size()
|
||||
{
|
||||
effective_width_ = GetScaledDimension(width(), divider_);
|
||||
effective_height_ = GetScaledDimension(height(), divider_);
|
||||
effective_depth_ = GetScaledDimension(depth(), divider_);
|
||||
}
|
||||
|
||||
void VideoParams::validate_pixel_aspect_ratio()
|
||||
@@ -196,7 +213,7 @@ QString VideoParams::FormatPixelAspectRatioString(const QString &format, const r
|
||||
|
||||
int VideoParams::GetScaledDimension(int dim, int divider)
|
||||
{
|
||||
return qCeil(dim / divider * 0.5) * 2;
|
||||
return dim / divider;
|
||||
}
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
@@ -39,6 +39,10 @@ public:
|
||||
VideoParams(const int& width, const int& height, const PixelFormat::Format& format,
|
||||
const rational& pixel_aspect_ratio = 1,
|
||||
const Interlacing& interlacing = kInterlaceNone, const int& divider = 1);
|
||||
VideoParams(const int& width, const int& height, const int& depth,
|
||||
const PixelFormat::Format& format,
|
||||
const rational& pixel_aspect_ratio = 1,
|
||||
const Interlacing& interlacing = kInterlaceNone, const int& divider = 1);
|
||||
VideoParams(const int& width, const int& height, const rational& time_base,
|
||||
const PixelFormat::Format& format, const rational& pixel_aspect_ratio = 1,
|
||||
const Interlacing& interlacing = kInterlaceNone, const int& divider = 1);
|
||||
@@ -65,6 +69,17 @@ public:
|
||||
calculate_effective_size();
|
||||
}
|
||||
|
||||
int depth() const
|
||||
{
|
||||
return depth_;
|
||||
}
|
||||
|
||||
void set_depth(int depth)
|
||||
{
|
||||
depth_ = depth;
|
||||
calculate_effective_size();
|
||||
}
|
||||
|
||||
const rational& time_base() const
|
||||
{
|
||||
return time_base_;
|
||||
@@ -96,6 +111,11 @@ public:
|
||||
return effective_height_;
|
||||
}
|
||||
|
||||
int effective_depth() const
|
||||
{
|
||||
return effective_depth_;
|
||||
}
|
||||
|
||||
PixelFormat::Format format() const
|
||||
{
|
||||
return format_;
|
||||
@@ -162,6 +182,7 @@ private:
|
||||
|
||||
int width_;
|
||||
int height_;
|
||||
int depth_;
|
||||
rational time_base_;
|
||||
|
||||
PixelFormat::Format format_;
|
||||
@@ -173,6 +194,7 @@ private:
|
||||
int divider_;
|
||||
int effective_width_;
|
||||
int effective_height_;
|
||||
int effective_depth_;
|
||||
};
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include <QHBoxLayout>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "render/backend/opengl/openglrenderer.h"
|
||||
#include "render/opengl/openglrenderer.h"
|
||||
#include "render/rendermanager.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
|
||||
#include <QOpenGLWidget>
|
||||
|
||||
#include "render/backend/renderer.h"
|
||||
#include "render/colormanager.h"
|
||||
#include "render/renderer.h"
|
||||
#include "widget/menu/menu.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
@@ -62,7 +62,7 @@ ShaderCode HistogramScope::GenerateShaderCode()
|
||||
FileFunctions::ReadFileAsString(":/shaders/default.vert"));
|
||||
}
|
||||
|
||||
void HistogramScope::DrawScope(Renderer::TexturePtr managed_tex, QVariant pipeline)
|
||||
void HistogramScope::DrawScope(TexturePtr managed_tex, QVariant pipeline)
|
||||
{
|
||||
float histogram_scale = 0.80f;
|
||||
// This value is eyeballed for usefulness. Until we have a geometry
|
||||
|
||||
@@ -42,11 +42,11 @@ protected:
|
||||
virtual ShaderCode GenerateShaderCode() override;
|
||||
QVariant CreateSecondaryShader();
|
||||
|
||||
virtual void DrawScope(Renderer::TexturePtr managed_tex, QVariant pipeline) override;
|
||||
virtual void DrawScope(TexturePtr managed_tex, QVariant pipeline) override;
|
||||
|
||||
private:
|
||||
QVariant pipeline_secondary_;
|
||||
Renderer::TexturePtr texture_row_sums_;
|
||||
TexturePtr texture_row_sums_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ void ScopeBase::showEvent(QShowEvent* e)
|
||||
UploadTextureFromBuffer();
|
||||
}
|
||||
|
||||
void ScopeBase::DrawScope(Renderer::TexturePtr managed_tex, QVariant pipeline)
|
||||
void ScopeBase::DrawScope(TexturePtr managed_tex, QVariant pipeline)
|
||||
{
|
||||
ShaderJob job;
|
||||
|
||||
|
||||
@@ -54,16 +54,16 @@ protected:
|
||||
*
|
||||
* Override this if your sub-class scope needs extra drawing.
|
||||
*/
|
||||
virtual void DrawScope(Renderer::TexturePtr managed_tex, QVariant pipeline);
|
||||
virtual void DrawScope(TexturePtr managed_tex, QVariant pipeline);
|
||||
|
||||
private:
|
||||
void UploadTextureFromBuffer();
|
||||
|
||||
QVariant pipeline_;
|
||||
|
||||
Renderer::TexturePtr texture_;
|
||||
TexturePtr texture_;
|
||||
|
||||
Renderer::TexturePtr managed_tex_;
|
||||
TexturePtr managed_tex_;
|
||||
|
||||
Frame* buffer_;
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ ShaderCode WaveformScope::GenerateShaderCode()
|
||||
FileFunctions::ReadFileAsString(":/shaders/rgbwaveform.vert"));
|
||||
}
|
||||
|
||||
void WaveformScope::DrawScope(Renderer::TexturePtr managed_tex, QVariant pipeline)
|
||||
void WaveformScope::DrawScope(TexturePtr managed_tex, QVariant pipeline)
|
||||
{
|
||||
float waveform_scale = 0.80f;
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
protected:
|
||||
virtual ShaderCode GenerateShaderCode() override;
|
||||
|
||||
virtual void DrawScope(Renderer::TexturePtr managed_tex, QVariant pipeline) override;
|
||||
virtual void DrawScope(TexturePtr managed_tex, QVariant pipeline) override;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -211,7 +211,7 @@ private:
|
||||
/**
|
||||
* @brief Internal reference to the OpenGL texture to draw. Set in SetTexture() and used in paintGL().
|
||||
*/
|
||||
Renderer::TexturePtr texture_;
|
||||
TexturePtr texture_;
|
||||
|
||||
/**
|
||||
* @brief Translation only matrix (defaults to identity).
|
||||
|
||||
Reference in New Issue
Block a user