finished upgrade to ocio v2

This commit is contained in:
itsmattkc
2020-11-12 15:36:29 +11:00
parent ddbca1ba51
commit 8776bb9c4a
40 changed files with 1095 additions and 591 deletions
+2 -1
View File
@@ -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) {
+1 -1
View File
@@ -65,7 +65,7 @@ private:
PixelFormat::Format pix_fmt_;
bool is_rgba_;
//bool is_rgba_;
OIIO::ImageBuf* buffer_;
+3 -3
View File
@@ -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);
}
}
-1
View File
@@ -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
View File
@@ -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
View File
@@ -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
)
-113
View File
@@ -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 &param, 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
)
+101
View File
@@ -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
+54
View File
@@ -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
+65
View File
@@ -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
+112
View File
@@ -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
)
@@ -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, &current_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, &current_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, &current_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_;
+229
View File
@@ -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 &params, 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 &params, 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
@@ -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:
+2 -2
View File
@@ -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"
+1 -1
View File
@@ -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"
+10 -10
View File
@@ -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";
+1 -1
View File
@@ -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"
+62
View File
@@ -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
-249
View File
@@ -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
+2
View File
@@ -48,6 +48,8 @@ struct ShaderValue
};
using NodeValueMap = QHash<QString, ShaderValue>;
OLIVE_NAMESPACE_EXIT
#endif // SHADERVALUE_H
+2 -2
View File
@@ -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;
+39
View File
@@ -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
+134
View File
@@ -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
+18 -1
View File
@@ -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 &divider) :
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 &divider) :
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
+22
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+2 -2
View File
@@ -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_;
};
+1 -1
View File
@@ -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;
+3 -3
View File
@@ -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_;
+1 -1
View File
@@ -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;
+1 -1
View File
@@ -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;
};
+1 -1
View File
@@ -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).