diff --git a/app/render/backend/opengl/openglproxy.cpp b/app/render/backend/opengl/openglproxy.cpp index 2b12a54e2..951ef8e2f 100644 --- a/app/render/backend/opengl/openglproxy.cpp +++ b/app/render/backend/opengl/openglproxy.cpp @@ -195,6 +195,7 @@ void OpenGLProxy::Close() { shader_cache_.Clear(); buffer_.Destroy(); + copy_pipeline_ = nullptr; functions_ = nullptr; delete ctx_; ctx_ = nullptr; @@ -426,7 +427,7 @@ void OpenGLProxy::RunNodeAccelerated(const Node *node, const TimeRange &range, N output_params.Push(NodeParam::kTexture, QVariant::fromValue(output_tex)); } -void OpenGLProxy::TextureToBuffer(const QVariant &tex_in, void *buffer, int linesize) +void OpenGLProxy::TextureToBuffer(const QVariant &tex_in, int width, int height, const QMatrix4x4 &matrix, void *buffer, int linesize) { OpenGLTextureCache::ReferencePtr texture = tex_in.value(); @@ -435,7 +436,37 @@ void OpenGLProxy::TextureToBuffer(const QVariant &tex_in, void *buffer, int line } QOpenGLFunctions* f = QOpenGLContext::currentContext()->functions(); - buffer_.Attach(texture->texture()); + + OpenGLTextureCache::ReferencePtr download_tex; + + if (width != texture->texture()->width() || height != texture->texture()->height()) { + + // Resize the texture if necessary + OpenGLTextureCache::ReferencePtr resized = texture_cache_.Get(ctx_, + VideoRenderingParams(width, height, texture->texture()->format())); + + buffer_.Attach(resized->texture(), true); + buffer_.Bind(); + + texture->texture()->Bind(); + + // Blit to this new texture + OpenGLRenderFunctions::Blit(copy_pipeline_, false, matrix); + + texture->texture()->Release(); + + buffer_.Release(); + buffer_.Detach(); + + download_tex = resized; + + } else { + + download_tex = texture; + + } + + buffer_.Attach(download_tex->texture()); buffer_.Bind(); f->glPixelStorei(GL_PACK_ROW_LENGTH, linesize); @@ -478,6 +509,8 @@ void OpenGLProxy::FinishInit() SetParameters(video_params_); buffer_.Create(ctx_); + + copy_pipeline_ = OpenGLShader::CreateDefault(); } OLIVE_NAMESPACE_EXIT diff --git a/app/render/backend/opengl/openglproxy.h b/app/render/backend/opengl/openglproxy.h index 753615e6e..d9ba4e887 100644 --- a/app/render/backend/opengl/openglproxy.h +++ b/app/render/backend/opengl/openglproxy.h @@ -67,7 +67,7 @@ public: void RunNodeAccelerated(const Node *node, const TimeRange &range, NodeValueDatabase &input_params, NodeValueTable& output_params); - void TextureToBuffer(const QVariant& texture, void *buffer, int linesize); + void TextureToBuffer(const QVariant& texture, int width, int height, const QMatrix4x4& matrix, void *buffer, int linesize); void SetParameters(const VideoRenderingParams& params); @@ -83,6 +83,8 @@ private: VideoRenderingParams video_params_; + OpenGLShaderPtr copy_pipeline_; + OpenGLShaderCache shader_cache_; OpenGLTextureCache texture_cache_; diff --git a/app/render/backend/opengl/openglworker.cpp b/app/render/backend/opengl/openglworker.cpp index bee22d266..67f3fa835 100644 --- a/app/render/backend/opengl/openglworker.cpp +++ b/app/render/backend/opengl/openglworker.cpp @@ -50,9 +50,9 @@ void OpenGLWorker::RunNodeAccelerated(const Node *node, const TimeRange &range, emit RequestRunNodeAccelerated(node, range, input_params, output_params); } -void OpenGLWorker::TextureToBuffer(const QVariant &tex_in, void *buffer, int linesize) +void OpenGLWorker::TextureToBuffer(const QVariant &tex_in, int width, int height, const QMatrix4x4& matrix, void *buffer, int linesize) { - emit RequestTextureToBuffer(tex_in, buffer, linesize); + emit RequestTextureToBuffer(tex_in, width, height, matrix, buffer, linesize); } OLIVE_NAMESPACE_EXIT diff --git a/app/render/backend/opengl/openglworker.h b/app/render/backend/opengl/openglworker.h index 1f0330c7d..5b2215eb7 100644 --- a/app/render/backend/opengl/openglworker.h +++ b/app/render/backend/opengl/openglworker.h @@ -42,14 +42,14 @@ signals: void RequestRunNodeAccelerated(const Node *node, const TimeRange &range, NodeValueDatabase &input_params, NodeValueTable& output_params); - void RequestTextureToBuffer(const QVariant& texture, void *buffer, int linesize); + void RequestTextureToBuffer(const QVariant& texture, int width, int height, const QMatrix4x4& matrix, void *buffer, int linesize); protected: virtual void FrameToValue(DecoderPtr decoder, StreamPtr stream, const TimeRange &range, NodeValueTable* table) override; virtual void RunNodeAccelerated(const Node *node, const TimeRange &range, NodeValueDatabase &input_params, NodeValueTable& output_params) override; - virtual void TextureToBuffer(const QVariant& texture, void *buffer, int linesize) override; + virtual void TextureToBuffer(const QVariant& texture, int width, int height, const QMatrix4x4& matrix, void *buffer, int linesize) override; }; diff --git a/app/render/backend/videorenderbackend.cpp b/app/render/backend/videorenderbackend.cpp index c98649789..7e13d1af7 100644 --- a/app/render/backend/videorenderbackend.cpp +++ b/app/render/backend/videorenderbackend.cpp @@ -97,6 +97,13 @@ void VideoRenderBackend::SetOperatingMode(const VideoRenderWorker::OperatingMode } } +void VideoRenderBackend::SetFrameGenerationParams(int width, int height, const QMatrix4x4 &matrix) +{ + foreach (RenderWorker* worker, processors_) { + static_cast(worker)->SetFrameGenerationParams(width, height, matrix); + } +} + void VideoRenderBackend::SetOnlySignalLastFrameRequested(bool enabled) { only_signal_last_frame_requested_ = enabled; diff --git a/app/render/backend/videorenderbackend.h b/app/render/backend/videorenderbackend.h index a73d46df2..7391013c7 100644 --- a/app/render/backend/videorenderbackend.h +++ b/app/render/backend/videorenderbackend.h @@ -58,6 +58,8 @@ public: void SetOperatingMode(const VideoRenderWorker::OperatingMode& mode); + void SetFrameGenerationParams(int width, int height, const QMatrix4x4& matrix); + void SetOnlySignalLastFrameRequested(bool enabled); bool IsRendered(const rational& time) const; diff --git a/app/render/backend/videorenderworker.cpp b/app/render/backend/videorenderworker.cpp index 4a39b9797..968d826df 100644 --- a/app/render/backend/videorenderworker.cpp +++ b/app/render/backend/videorenderworker.cpp @@ -46,6 +46,16 @@ const VideoRenderingParams &VideoRenderWorker::video_params() return video_params_; } +void VideoRenderWorker::TextureToBuffer(const QVariant &texture, void *buffer, int linesize) +{ + TextureToBuffer(texture, + video_params_.effective_width(), + video_params_.effective_height(), + QMatrix4x4(), + buffer, + linesize); +} + NodeValueTable VideoRenderWorker::RenderInternal(const NodeDependency& path, const qint64 &job_time) { // Get hash of node graph @@ -238,6 +248,17 @@ void VideoRenderWorker::SetOperatingMode(const VideoRenderWorker::OperatingMode operating_mode_ = mode; } +void VideoRenderWorker::SetFrameGenerationParams(int width, int height, const QMatrix4x4 &matrix) +{ + frame_gen_params_ = VideoRenderingParams(width, + height, + video_params_.time_base(), + video_params_.format(), + video_params_.mode(), + video_params_.divider()); + frame_gen_mat_ = matrix; +} + bool VideoRenderWorker::InitInternal() { ResizeDownloadBuffer(); @@ -339,10 +360,18 @@ void VideoRenderWorker::Download(const rational& time, QVariant texture, QString } else { FramePtr frame = Frame::Create(); - frame->set_video_params(video_params()); + + if (frame_gen_params_.is_valid()) { + frame->set_video_params(frame_gen_params_); + } else { + frame->set_video_params(VideoRenderingParams(video_params_.effective_width(), + video_params_.effective_height(), + video_params_.format())); + } + frame->allocate(); - TextureToBuffer(texture, frame->data(), frame->linesize_pixels()); + TextureToBuffer(texture, frame->width(), frame->height(), frame_gen_mat_, frame->data(), frame->linesize_pixels()); emit GeneratedFrame(time, frame); diff --git a/app/render/backend/videorenderworker.h b/app/render/backend/videorenderworker.h index 96959bde1..6d43dbf6f 100644 --- a/app/render/backend/videorenderworker.h +++ b/app/render/backend/videorenderworker.h @@ -22,6 +22,7 @@ #define VIDEORENDERWORKER_H #include +#include #include "colorprocessorcache.h" #include "node/dependency.h" @@ -69,6 +70,8 @@ public: void SetOperatingMode(const OperatingMode& mode); + void SetFrameGenerationParams(int width, int height, const QMatrix4x4 &matrix); + signals: void CompletedDownload(NodeDependency path, qint64 job_time, QByteArray hash, bool texture_existed); @@ -89,7 +92,9 @@ protected: virtual void ParametersChangedEvent(){} - virtual void TextureToBuffer(const QVariant& texture, void *buffer, int linesize) = 0; + virtual void TextureToBuffer(const QVariant& texture, void *buffer, int linesize); + + virtual void TextureToBuffer(const QVariant& texture, int width, int height, const QMatrix4x4& matrix, void *buffer, int linesize) = 0; virtual NodeValueTable RenderInternal(const NodeDependency& CurrentPath, const qint64& job_time) override; @@ -106,6 +111,10 @@ private: void ResizeDownloadBuffer(); + VideoRenderingParams frame_gen_params_; + + QMatrix4x4 frame_gen_mat_; + VideoRenderingParams video_params_; VideoRenderFrameCache* frame_cache_;