diff --git a/app/decoder/oiio/oiiodecoder.cpp b/app/decoder/oiio/oiiodecoder.cpp index 9702ed148..f42e5562d 100644 --- a/app/decoder/oiio/oiiodecoder.cpp +++ b/app/decoder/oiio/oiiodecoder.cpp @@ -105,7 +105,6 @@ bool OIIODecoder::Open() return true; } -#include FramePtr OIIODecoder::RetrieveVideo(const rational &timecode) { if (!open_ && !Open()) { @@ -114,7 +113,7 @@ FramePtr OIIODecoder::RetrieveVideo(const rational &timecode) Q_UNUSED(timecode) - if (frame_ == nullptr) { + if (!frame_) { frame_ = Frame::Create(); frame_->set_width(width_); diff --git a/app/render/backend/opengl/openglbackend.cpp b/app/render/backend/opengl/openglbackend.cpp index 7754ba3e2..0ed6aef33 100644 --- a/app/render/backend/opengl/openglbackend.cpp +++ b/app/render/backend/opengl/openglbackend.cpp @@ -135,7 +135,7 @@ void OpenGLBackend::DecompileInternal() shader_cache_.Clear(); } -bool OpenGLBackend::TimeIsCached(const TimeRange &time) +bool OpenGLBackend::TimeIsQueued(const TimeRange &time) { return cache_queue_.contains(time); } @@ -164,9 +164,10 @@ void OpenGLBackend::ThreadCompletedFrame(NodeDependency path, QByteArray hash, N last_download_thread_++; } - // Set as push texture - if (!TimeIsCached(TimeRange(path.in(), path.in()))) { - emit CachedFrameReady(path.in(), value); + // Check if this frame has changed once again, in which case we may not want to draw it (it'll look jittery to the user) + if (!TimeIsQueued(TimeRange(path.in(), path.in()))) { + // FIXME: This texture is part of the texture cache and therefore volatile, we should probably copy it here instead + emit CachedFrameReady(path.in(), QVariant::fromValue(value.value()->texture())); } // Queue up a new frame for this worker diff --git a/app/render/backend/opengl/openglbackend.h b/app/render/backend/opengl/openglbackend.h index 7b72a1a24..6b2a75643 100644 --- a/app/render/backend/opengl/openglbackend.h +++ b/app/render/backend/opengl/openglbackend.h @@ -29,7 +29,7 @@ protected: virtual void DecompileInternal() override; private: - bool TimeIsCached(const TimeRange &time); + bool TimeIsQueued(const TimeRange &time); OpenGLTexturePtr master_texture_; diff --git a/app/render/backend/opengl/opengltexture.cpp b/app/render/backend/opengl/opengltexture.cpp index 186b78162..a967d2899 100644 --- a/app/render/backend/opengl/opengltexture.cpp +++ b/app/render/backend/opengl/opengltexture.cpp @@ -26,7 +26,7 @@ #include "render/pixelservice.h" OpenGLTexture::OpenGLTexture() : - context_(nullptr), + created_ctx_(nullptr), texture_(0), width_(0), height_(0), @@ -41,27 +41,27 @@ OpenGLTexture::~OpenGLTexture() bool OpenGLTexture::IsCreated() const { - return (texture_ != 0); + return (texture_); } void OpenGLTexture::Create(QOpenGLContext *ctx, int width, int height, const olive::PixelFormat &format, const void* data) { - if (ctx == nullptr) { + if (!ctx) { qWarning() << "RenderTexture::Create was passed an invalid context"; return; } Destroy(); - context_ = ctx; + created_ctx_ = ctx; width_ = width; height_ = height; format_ = format; - connect(context_, SIGNAL(aboutToBeDestroyed()), this, SLOT(Destroy())); + connect(created_ctx_, SIGNAL(aboutToBeDestroyed()), this, SLOT(Destroy())); // Create main texture - CreateInternal(&texture_, data); + CreateInternal(created_ctx_, &texture_, data); } void OpenGLTexture::Create(QOpenGLContext *ctx, FramePtr frame) @@ -71,34 +71,38 @@ void OpenGLTexture::Create(QOpenGLContext *ctx, FramePtr frame) void OpenGLTexture::Destroy() { - if (context_ != nullptr) { - disconnect(context_, SIGNAL(aboutToBeDestroyed()), this, SLOT(Destroy())); + if (created_ctx_) { + disconnect(created_ctx_, SIGNAL(aboutToBeDestroyed()), this, SLOT(Destroy())); - context_->functions()->glDeleteTextures(1, &texture_); + created_ctx_->functions()->glDeleteTextures(1, &texture_); texture_ = 0; - context_ = nullptr; + created_ctx_ = nullptr; } } void OpenGLTexture::Bind() { - if (context_ == nullptr) { + QOpenGLContext* context = QOpenGLContext::currentContext(); + + if (!context) { qWarning() << "RenderTexture::Bind() called with an invalid context"; return; } - context_->functions()->glBindTexture(GL_TEXTURE_2D, texture_); + context->functions()->glBindTexture(GL_TEXTURE_2D, texture_); } void OpenGLTexture::Release() { - if (context_ == nullptr) { + QOpenGLContext* context = QOpenGLContext::currentContext(); + + if (!context) { qWarning() << "RenderTexture::Release() called with an invalid context"; return; } - context_->functions()->glBindTexture(GL_TEXTURE_2D, 0); + context->functions()->glBindTexture(GL_TEXTURE_2D, 0); } const int &OpenGLTexture::width() const @@ -116,11 +120,6 @@ const olive::PixelFormat &OpenGLTexture::format() const return format_; } -QOpenGLContext *OpenGLTexture::context() const -{ - return context_; -} - const GLuint &OpenGLTexture::texture() const { return texture_; @@ -133,19 +132,26 @@ void OpenGLTexture::Upload(const void *data) return; } + QOpenGLContext* context = QOpenGLContext::currentContext(); + + if (!context) { + qWarning() << "RenderTexture::Release() called with an invalid context"; + return; + } + Bind(); PixelFormatInfo info = PixelService::GetPixelFormatInfo(format_); - context_->functions()->glTexSubImage2D(GL_TEXTURE_2D, - 0, - 0, - 0, - width_, - height_, - info.pixel_format, - info.gl_pixel_type, - data); + context->functions()->glTexSubImage2D(GL_TEXTURE_2D, + 0, + 0, + 0, + width_, + height_, + info.pixel_format, + info.gl_pixel_type, + data); Release(); } @@ -157,7 +163,8 @@ uchar *OpenGLTexture::Download() const return nullptr; } - QOpenGLFunctions* f = context_->functions(); + QOpenGLContext* context = QOpenGLContext::currentContext(); + QOpenGLFunctions* f = context->functions(); GLuint read_fbo; @@ -165,7 +172,7 @@ uchar *OpenGLTexture::Download() const f->glBindFramebuffer(GL_READ_FRAMEBUFFER, read_fbo); - context_->extraFunctions()->glFramebufferTexture2D( + context->extraFunctions()->glFramebufferTexture2D( GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_, 0 ); @@ -182,9 +189,9 @@ uchar *OpenGLTexture::Download() const return data; } -void OpenGLTexture::CreateInternal(GLuint* tex, const void *data) +void OpenGLTexture::CreateInternal(QOpenGLContext* create_ctx, GLuint* tex, const void *data) { - QOpenGLFunctions* f = context_->functions(); + QOpenGLFunctions* f = create_ctx->functions(); // Create texture f->glGenTextures(1, tex); diff --git a/app/render/backend/opengl/opengltexture.h b/app/render/backend/opengl/opengltexture.h index e84dbecf2..8a1631845 100644 --- a/app/render/backend/opengl/opengltexture.h +++ b/app/render/backend/opengl/opengltexture.h @@ -55,8 +55,6 @@ public: const olive::PixelFormat &format() const; - QOpenGLContext* context() const; - const GLuint& texture() const; void Upload(const void *data); @@ -67,9 +65,9 @@ public slots: void Destroy(); private: - void CreateInternal(GLuint *tex, const void *data = nullptr); + void CreateInternal(QOpenGLContext *create_ctx, GLuint *tex, const void *data = nullptr); - QOpenGLContext* context_; + QOpenGLContext* created_ctx_; GLuint texture_; diff --git a/app/render/backend/opengl/opengltexturecache.cpp b/app/render/backend/opengl/opengltexturecache.cpp index d3e1e8ab5..c5d20c044 100644 --- a/app/render/backend/opengl/opengltexturecache.cpp +++ b/app/render/backend/opengl/opengltexturecache.cpp @@ -7,7 +7,7 @@ OpenGLTextureCache::~OpenGLTextureCache() } } -OpenGLTextureCache::ReferencePtr OpenGLTextureCache::Get(const VideoRenderingParams ¶ms, const void *data) +OpenGLTextureCache::ReferencePtr OpenGLTextureCache::Get(QOpenGLContext* ctx, const VideoRenderingParams ¶ms, const void *data) { OpenGLTexturePtr texture = nullptr; @@ -28,8 +28,6 @@ OpenGLTextureCache::ReferencePtr OpenGLTextureCache::Get(const VideoRenderingPar lock_.unlock(); - QOpenGLContext* ctx = QOpenGLContext::currentContext(); - // If we didn't find a texture, we'll need to create one if (!texture) { texture = std::make_shared(); @@ -38,15 +36,19 @@ OpenGLTextureCache::ReferencePtr OpenGLTextureCache::Get(const VideoRenderingPar texture->Upload(data); } - return std::make_shared(this, texture); + ReferencePtr ref = std::make_shared(this, texture); + existing_references_.append(ref.get()); + return ref; } void OpenGLTextureCache::Relinquish(OpenGLTextureCache::Reference *ref) { + OpenGLTexturePtr tex = ref->texture(); + lock_.lock(); existing_references_.removeOne(ref); - available_textures_.append(ref->texture()); + available_textures_.append(tex); lock_.unlock(); } diff --git a/app/render/backend/opengl/opengltexturecache.h b/app/render/backend/opengl/opengltexturecache.h index 126d648e7..cb1b03969 100644 --- a/app/render/backend/opengl/opengltexturecache.h +++ b/app/render/backend/opengl/opengltexturecache.h @@ -35,7 +35,7 @@ public: DISABLE_COPY_MOVE(OpenGLTextureCache) - ReferencePtr Get(const VideoRenderingParams& params, const void *data = nullptr); + ReferencePtr Get(QOpenGLContext *ctx, const VideoRenderingParams& params, const void *data = nullptr); private: void Relinquish(Reference* ref); diff --git a/app/render/backend/opengl/openglworker.cpp b/app/render/backend/opengl/openglworker.cpp index b2cb0a7ca..6129418f5 100644 --- a/app/render/backend/opengl/openglworker.cpp +++ b/app/render/backend/opengl/openglworker.cpp @@ -98,7 +98,7 @@ void OpenGLWorker::FrameToValue(StreamPtr stream, FramePtr frame, NodeValueTable VideoRenderingParams footage_params(frame->width(), frame->height(), stream->timebase(), frame->format(), video_params().mode()); - OpenGLTextureCache::ReferencePtr footage_tex_ref = texture_cache_->Get(footage_params, frame->data()); + OpenGLTextureCache::ReferencePtr footage_tex_ref = texture_cache_->Get(ctx_, footage_params, frame->data()); if (video_params().mode() == olive::kOffline) { if (!color_processor->IsEnabled()) { @@ -106,15 +106,15 @@ void OpenGLWorker::FrameToValue(StreamPtr stream, FramePtr frame, NodeValueTable } // Create destination texture - OpenGLTextureCache::ReferencePtr associated_tex_ref = texture_cache_->Get(footage_params); - - // Set viewport for texture size - functions_->glViewport(0, 0, footage_tex_ref->texture()->width(), footage_tex_ref->texture()->height()); + OpenGLTextureCache::ReferencePtr associated_tex_ref = texture_cache_->Get(ctx_, footage_params); buffer_.Attach(associated_tex_ref->texture(), true); buffer_.Bind(); footage_tex_ref->texture()->Bind(); + // Set viewport for texture size + functions_->glViewport(0, 0, footage_tex_ref->texture()->width(), footage_tex_ref->texture()->height()); + // Blit old texture to new texture through OCIO shader color_processor->ProcessOpenGL(); @@ -123,6 +123,8 @@ void OpenGLWorker::FrameToValue(StreamPtr stream, FramePtr frame, NodeValueTable buffer_.Detach(); footage_tex_ref = associated_tex_ref; + + functions_->glFinish(); } table->Push(NodeParam::kTexture, QVariant::fromValue(footage_tex_ref)); @@ -151,7 +153,7 @@ void OpenGLWorker::RunNodeAccelerated(const Node *node, const NodeValueDatabase } // Create the output texture - OpenGLTextureCache::ReferencePtr output_ref = texture_cache_->Get(video_params()); + OpenGLTextureCache::ReferencePtr output_ref = texture_cache_->Get(ctx_, video_params()); buffer_.Attach(output_ref->texture(), true); buffer_.Bind(); @@ -284,7 +286,6 @@ void OpenGLWorker::RunNodeAccelerated(const Node *node, const NodeValueDatabase shader->release(); buffer_.Release(); - buffer_.Detach(); output_params->Push(NodeParam::kTexture, QVariant::fromValue(output_ref)); diff --git a/app/render/backend/renderbackend.cpp b/app/render/backend/renderbackend.cpp index 3316eed05..1e1ff1e77 100644 --- a/app/render/backend/renderbackend.cpp +++ b/app/render/backend/renderbackend.cpp @@ -256,8 +256,6 @@ void RenderBackend::CacheNext() if (!WorkerIsBusy(worker)) { TimeRange cache_frame = cache_queue_.takeFirst(); - qDebug() << "Rendering" << cache_frame.in().toDouble(); - NodeDependency dep = NodeDependency(node_connected_to_viewer, cache_frame.in(), cache_frame.out()); SetWorkerBusyState(worker, true);