From 8776bb9c4ae19212dc30ed1350d7b26f73056b7e Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Thu, 12 Nov 2020 15:36:29 +1100 Subject: [PATCH] finished upgrade to ocio v2 --- app/codec/oiio/oiiodecoder.cpp | 3 +- app/codec/oiio/oiiodecoder.h | 2 +- app/config/config.cpp | 6 +- app/core.cpp | 1 - app/node/node.h | 5 +- app/render/CMakeLists.txt | 39 +-- app/render/backend/renderer.cpp | 113 -------- app/render/{backend => job}/CMakeLists.txt | 10 +- app/render/job/acceleratedjob.h | 101 +++++++ app/render/job/generatejob.h | 54 ++++ app/render/job/samplejob.h | 65 +++++ app/render/job/shaderjob.h | 112 ++++++++ .../{backend => }/opengl/CMakeLists.txt | 4 +- .../{backend => }/opengl/openglrenderer.cpp | 160 +++++++---- .../{backend => }/opengl/openglrenderer.h | 21 +- app/render/renderer.cpp | 229 ++++++++++++++++ app/render/{backend => }/renderer.h | 119 ++------- .../{backend => }/rendererthreadwrapper.cpp | 48 ++-- .../{backend => }/rendererthreadwrapper.h | 11 +- app/render/rendermanager.cpp | 4 +- app/render/rendermanager.h | 2 +- app/render/renderprocessor.cpp | 20 +- app/render/renderprocessor.h | 2 +- app/render/shadercode.h | 62 +++++ app/render/shaderinfo.h | 249 ------------------ app/render/shadervalue.h | 2 + app/render/stillimagecache.h | 4 +- app/render/texture.cpp | 39 +++ app/render/texture.h | 134 ++++++++++ app/render/videoparams.cpp | 19 +- app/render/videoparams.h | 22 ++ app/widget/manageddisplay/manageddisplay.cpp | 2 +- app/widget/manageddisplay/manageddisplay.h | 2 +- app/widget/scope/histogram/histogram.cpp | 2 +- app/widget/scope/histogram/histogram.h | 4 +- app/widget/scope/scopebase/scopebase.cpp | 2 +- app/widget/scope/scopebase/scopebase.h | 6 +- app/widget/scope/waveform/waveform.cpp | 2 +- app/widget/scope/waveform/waveform.h | 2 +- app/widget/viewer/viewerdisplay.h | 2 +- 40 files changed, 1095 insertions(+), 591 deletions(-) delete mode 100644 app/render/backend/renderer.cpp rename app/render/{backend => job}/CMakeLists.txt (81%) create mode 100644 app/render/job/acceleratedjob.h create mode 100644 app/render/job/generatejob.h create mode 100644 app/render/job/samplejob.h create mode 100644 app/render/job/shaderjob.h rename app/render/{backend => }/opengl/CMakeLists.txt (90%) rename app/render/{backend => }/opengl/openglrenderer.cpp (80%) rename app/render/{backend => }/opengl/openglrenderer.h (64%) create mode 100644 app/render/renderer.cpp rename app/render/{backend => }/renderer.h (54%) rename app/render/{backend => }/rendererthreadwrapper.cpp (63%) rename app/render/{backend => }/rendererthreadwrapper.h (69%) create mode 100644 app/render/shadercode.h delete mode 100644 app/render/shaderinfo.h create mode 100644 app/render/texture.cpp create mode 100644 app/render/texture.h diff --git a/app/codec/oiio/oiiodecoder.cpp b/app/codec/oiio/oiiodecoder.cpp index 632220189..1728c04d2 100644 --- a/app/codec/oiio/oiiodecoder.cpp +++ b/app/codec/oiio/oiiodecoder.cpp @@ -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) { diff --git a/app/codec/oiio/oiiodecoder.h b/app/codec/oiio/oiiodecoder.h index 328b54a30..820057d3e 100644 --- a/app/codec/oiio/oiiodecoder.h +++ b/app/codec/oiio/oiiodecoder.h @@ -65,7 +65,7 @@ private: PixelFormat::Format pix_fmt_; - bool is_rgba_; + //bool is_rgba_; OIIO::ImageBuf* buffer_; diff --git a/app/config/config.cpp b/app/config/config.cpp index a40718a8d..40f53240f 100644 --- a/app/config/config.cpp +++ b/app/config/config.cpp @@ -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); } } diff --git a/app/core.cpp b/app/core.cpp index 608b79da7..b60591b88 100644 --- a/app/core.cpp +++ b/app/core.cpp @@ -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" diff --git a/app/node/node.h b/app/node/node.h index bcc168c15..6da128f51 100644 --- a/app/node/node.h +++ b/app/node/node.h @@ -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 diff --git a/app/render/CMakeLists.txt b/app/render/CMakeLists.txt index 6e8f1e43d..abb4bda59 100644 --- a/app/render/CMakeLists.txt +++ b/app/render/CMakeLists.txt @@ -14,45 +14,52 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -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 ) diff --git a/app/render/backend/renderer.cpp b/app/render/backend/renderer.cpp deleted file mode 100644 index b2bf0ee04..000000000 --- a/app/render/backend/renderer.cpp +++ /dev/null @@ -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 . - -***/ - -#include "renderer.h" - -#include - -#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(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 diff --git a/app/render/backend/CMakeLists.txt b/app/render/job/CMakeLists.txt similarity index 81% rename from app/render/backend/CMakeLists.txt rename to app/render/job/CMakeLists.txt index de34bd6b3..d71defccf 100644 --- a/app/render/backend/CMakeLists.txt +++ b/app/render/job/CMakeLists.txt @@ -14,13 +14,11 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -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 ) diff --git a/app/render/job/acceleratedjob.h b/app/render/job/acceleratedjob.h new file mode 100644 index 000000000..71fb1a838 --- /dev/null +++ b/app/render/job/acceleratedjob.h @@ -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 . + +***/ + +#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(input); + QVector values(array->GetSize()); + + for (int j=0;jGetSize();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 diff --git a/app/render/job/generatejob.h b/app/render/job/generatejob.h new file mode 100644 index 000000000..e2ab45c72 --- /dev/null +++ b/app/render/job/generatejob.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 . + +***/ + +#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 diff --git a/app/render/job/samplejob.h b/app/render/job/samplejob.h new file mode 100644 index 000000000..f46e6a3eb --- /dev/null +++ b/app/render/job/samplejob.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 . + +***/ + +#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(); + } + + SampleJob(NodeInput* from, NodeValueDatabase& db) + { + samples_ = db[from].Take(NodeParam::kSamples).value(); + } + + 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 diff --git a/app/render/job/shaderjob.h b/app/render/job/shaderjob.h new file mode 100644 index 000000000..c6fc66cd9 --- /dev/null +++ b/app/render/job/shaderjob.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 . + +***/ + +#ifndef SHADERJOB_H +#define SHADERJOB_H + +#include + +#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 interpolation_; + + QMatrix4x4 matrix_; + +}; + +OLIVE_NAMESPACE_EXIT + +Q_DECLARE_METATYPE(OLIVE_NAMESPACE::ShaderJob) + +#endif // SHADERJOB_H diff --git a/app/render/backend/opengl/CMakeLists.txt b/app/render/opengl/CMakeLists.txt similarity index 90% rename from app/render/backend/opengl/CMakeLists.txt rename to app/render/opengl/CMakeLists.txt index e2df52f90..72662cb31 100644 --- a/app/render/backend/opengl/CMakeLists.txt +++ b/app/render/opengl/CMakeLists.txt @@ -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 ) diff --git a/app/render/backend/opengl/openglrenderer.cpp b/app/render/opengl/openglrenderer.cpp similarity index 80% rename from app/render/backend/opengl/openglrenderer.cpp rename to app/render/opengl/openglrenderer.cpp index a435bfd75..25a1c9fb0 100644 --- a/app/render/backend/opengl/openglrenderer.cpp +++ b/app/render/opengl/openglrenderer.cpp @@ -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(); @@ -203,7 +226,7 @@ void OpenGLRenderer::DestroyNativeShader(QVariant shader) delete Node::ValueToPtr(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(); 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 textures_to_bind; + QVector textures_to_bind; bool input_textures_have_alpha = false; QOpenGLShaderProgram* shader = Node::ValueToPtr(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() : 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; iid().value() : 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()); - 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 diff --git a/app/render/backend/opengl/openglrenderer.h b/app/render/opengl/openglrenderer.h similarity index 64% rename from app/render/backend/opengl/openglrenderer.h rename to app/render/opengl/openglrenderer.h index 12b6e2a40..ce1f5d795 100644 --- a/app/render/backend/opengl/openglrenderer.h +++ b/app/render/opengl/openglrenderer.h @@ -28,7 +28,7 @@ #include #include -#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_; diff --git a/app/render/renderer.cpp b/app/render/renderer.cpp new file mode 100644 index 000000000..ffebfa072 --- /dev/null +++ b/app/render/renderer.cpp @@ -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 . + +***/ + +#include "renderer.h" + +#include + +#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(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; igetNum3DTextures(); 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; igetNumTextures(); 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 diff --git a/app/render/backend/renderer.h b/app/render/renderer.h similarity index 54% rename from app/render/backend/renderer.h rename to app/render/renderer.h index 356299fcb..2da550fa1 100644 --- a/app/render/backend/renderer.h +++ b/app/render/renderer.h @@ -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; - - 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 lut3d_textures; + QVector lut1d_textures; + }; + bool GetColorContext(ColorProcessorPtr color_processor, ColorContext* ctx); + + void BlitColorManagedInternal(ColorProcessorPtr color_processor, TexturePtr source, + Texture* destination, VideoParams params, bool flipped); + QHash color_cache_; }; OLIVE_NAMESPACE_EXIT -Q_DECLARE_METATYPE(OLIVE_NAMESPACE::Renderer::TexturePtr); - #endif // RENDERCONTEXT_H diff --git a/app/render/backend/rendererthreadwrapper.cpp b/app/render/rendererthreadwrapper.cpp similarity index 63% rename from app/render/backend/rendererthreadwrapper.cpp rename to app/render/rendererthreadwrapper.cpp index 8b024054e..2024fd377 100644 --- a/app/render/backend/rendererthreadwrapper.cpp +++ b/app/render/rendererthreadwrapper.cpp @@ -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)); } diff --git a/app/render/backend/rendererthreadwrapper.h b/app/render/rendererthreadwrapper.h similarity index 69% rename from app/render/backend/rendererthreadwrapper.h rename to app/render/rendererthreadwrapper.h index 95445bc25..a3b9e5cda 100644 --- a/app/render/backend/rendererthreadwrapper.h +++ b/app/render/rendererthreadwrapper.h @@ -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: diff --git a/app/render/rendermanager.cpp b/app/render/rendermanager.cpp index 2aa648fd5..de9b4b408 100644 --- a/app/render/rendermanager.cpp +++ b/app/render/rendermanager.cpp @@ -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" diff --git a/app/render/rendermanager.h b/app/render/rendermanager.h index f170e2aa2..0f73ca53d 100644 --- a/app/render/rendermanager.h +++ b/app/render/rendermanager.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" diff --git a/app/render/renderprocessor.cpp b/app/render/renderprocessor.cpp index 34b612ec6..6587c6d0c 100644 --- a/app/render/renderprocessor.cpp +++ b/app/render/renderprocessor.cpp @@ -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(); + TexturePtr texture = table.Get(NodeParam::kTexture).value(); 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(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"; diff --git a/app/render/renderprocessor.h b/app/render/renderprocessor.h index e2be6eb61..ed5bf38ae 100644 --- a/app/render/renderprocessor.h +++ b/app/render/renderprocessor.h @@ -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" diff --git a/app/render/shadercode.h b/app/render/shadercode.h new file mode 100644 index 000000000..59d5a59de --- /dev/null +++ b/app/render/shadercode.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 . + +***/ + +#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 diff --git a/app/render/shaderinfo.h b/app/render/shaderinfo.h deleted file mode 100644 index 3dc69f681..000000000 --- a/app/render/shaderinfo.h +++ /dev/null @@ -1,249 +0,0 @@ -#ifndef SHADERINFO_H -#define SHADERINFO_H - -#include - -#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; - -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(input); - QVector values(array->GetSize()); - - for (int j=0;jGetSize();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(); - } - - SampleJob(NodeInput* from, NodeValueDatabase& db) - { - samples_ = db[from].Take(NodeParam::kSamples).value(); - } - - 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 diff --git a/app/render/shadervalue.h b/app/render/shadervalue.h index 5d4e8dbfb..dd8412b30 100644 --- a/app/render/shadervalue.h +++ b/app/render/shadervalue.h @@ -48,6 +48,8 @@ struct ShaderValue }; +using NodeValueMap = QHash; + OLIVE_NAMESPACE_EXIT #endif // SHADERVALUE_H diff --git a/app/render/stillimagecache.h b/app/render/stillimagecache.h index 9a0b17cb7..efd7ac515 100644 --- a/app/render/stillimagecache.h +++ b/app/render/stillimagecache.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; diff --git a/app/render/texture.cpp b/app/render/texture.cpp new file mode 100644 index 000000000..66bd9dc77 --- /dev/null +++ b/app/render/texture.cpp @@ -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 . + +***/ + +#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 diff --git a/app/render/texture.h b/app/render/texture.h new file mode 100644 index 000000000..abf4e7e2e --- /dev/null +++ b/app/render/texture.h @@ -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 . + +***/ + +#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; + +OLIVE_NAMESPACE_EXIT + +Q_DECLARE_METATYPE(OLIVE_NAMESPACE::TexturePtr); + +#endif // RENDERTEXTURE_H diff --git a/app/render/videoparams.cpp b/app/render/videoparams.cpp index 00167c63a..c9609701e 100644 --- a/app/render/videoparams.cpp +++ b/app/render/videoparams.cpp @@ -62,6 +62,7 @@ const QVector 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 diff --git a/app/render/videoparams.h b/app/render/videoparams.h index dab019254..3d7102e9f 100644 --- a/app/render/videoparams.h +++ b/app/render/videoparams.h @@ -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 diff --git a/app/widget/manageddisplay/manageddisplay.cpp b/app/widget/manageddisplay/manageddisplay.cpp index cd0636b6d..ce1528f7b 100644 --- a/app/widget/manageddisplay/manageddisplay.cpp +++ b/app/widget/manageddisplay/manageddisplay.cpp @@ -23,7 +23,7 @@ #include #include -#include "render/backend/opengl/openglrenderer.h" +#include "render/opengl/openglrenderer.h" #include "render/rendermanager.h" OLIVE_NAMESPACE_ENTER diff --git a/app/widget/manageddisplay/manageddisplay.h b/app/widget/manageddisplay/manageddisplay.h index 55da88103..86f82113a 100644 --- a/app/widget/manageddisplay/manageddisplay.h +++ b/app/widget/manageddisplay/manageddisplay.h @@ -23,8 +23,8 @@ #include -#include "render/backend/renderer.h" #include "render/colormanager.h" +#include "render/renderer.h" #include "widget/menu/menu.h" OLIVE_NAMESPACE_ENTER diff --git a/app/widget/scope/histogram/histogram.cpp b/app/widget/scope/histogram/histogram.cpp index aed0d6988..87def5cc3 100644 --- a/app/widget/scope/histogram/histogram.cpp +++ b/app/widget/scope/histogram/histogram.cpp @@ -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 diff --git a/app/widget/scope/histogram/histogram.h b/app/widget/scope/histogram/histogram.h index d0ab83958..30895f93d 100644 --- a/app/widget/scope/histogram/histogram.h +++ b/app/widget/scope/histogram/histogram.h @@ -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_; }; diff --git a/app/widget/scope/scopebase/scopebase.cpp b/app/widget/scope/scopebase/scopebase.cpp index 89644e589..76a717112 100644 --- a/app/widget/scope/scopebase/scopebase.cpp +++ b/app/widget/scope/scopebase/scopebase.cpp @@ -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; diff --git a/app/widget/scope/scopebase/scopebase.h b/app/widget/scope/scopebase/scopebase.h index 8cde613f8..2bcd415c5 100644 --- a/app/widget/scope/scopebase/scopebase.h +++ b/app/widget/scope/scopebase/scopebase.h @@ -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_; diff --git a/app/widget/scope/waveform/waveform.cpp b/app/widget/scope/waveform/waveform.cpp index 3f9f85afc..9abd47458 100644 --- a/app/widget/scope/waveform/waveform.cpp +++ b/app/widget/scope/waveform/waveform.cpp @@ -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; diff --git a/app/widget/scope/waveform/waveform.h b/app/widget/scope/waveform/waveform.h index 2640f9cf3..687d5b038 100644 --- a/app/widget/scope/waveform/waveform.h +++ b/app/widget/scope/waveform/waveform.h @@ -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; }; diff --git a/app/widget/viewer/viewerdisplay.h b/app/widget/viewer/viewerdisplay.h index d61d16c20..a8d8b3ade 100644 --- a/app/widget/viewer/viewerdisplay.h +++ b/app/widget/viewer/viewerdisplay.h @@ -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).