From 7af3a0cd6e8b82937d0fd3e6e2bd2cd7eccddaf6 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sun, 3 Mar 2019 12:17:55 -0800 Subject: [PATCH] minor render thread refactor --- olive.pro | 6 +- rendering/cacher.cpp | 9 +- rendering/framebufferobject.cpp | 81 ++++++++++++++++ rendering/framebufferobject.h | 24 +++++ rendering/renderthread.cpp | 165 ++++++++++---------------------- rendering/renderthread.h | 22 ++--- 6 files changed, 173 insertions(+), 134 deletions(-) create mode 100644 rendering/framebufferobject.cpp create mode 100644 rendering/framebufferobject.h diff --git a/olive.pro b/olive.pro index 0a38ee49a..ddaedc3c5 100644 --- a/olive.pro +++ b/olive.pro @@ -159,7 +159,8 @@ SOURCES += \ rendering/cacher.cpp \ rendering/clipqueue.cpp \ rendering/audio.cpp \ - dialogs/clippropertiesdialog.cpp + dialogs/clippropertiesdialog.cpp \ + rendering/framebufferobject.cpp HEADERS += \ mainwindow.h \ @@ -270,7 +271,8 @@ HEADERS += \ rendering/clipqueue.h \ rendering/cacher.h \ rendering/audio.h \ - dialogs/clippropertiesdialog.h + dialogs/clippropertiesdialog.h \ + rendering/framebufferobject.h FORMS += diff --git a/rendering/cacher.cpp b/rendering/cacher.cpp index 6c5785bb8..eb33619b8 100644 --- a/rendering/cacher.cpp +++ b/rendering/cacher.cpp @@ -749,10 +749,11 @@ void Cacher::WakeMainThread() main_thread_lock_.unlock(); } -Cacher::Cacher(Clip* c) : clip(c) { - frame_ = nullptr; - pkt = nullptr; -} +Cacher::Cacher(Clip* c) : + clip(c), + frame_(nullptr), + pkt(nullptr) +{} void Cacher::OpenWorker() { qint64 time_start = QDateTime::currentMSecsSinceEpoch(); diff --git a/rendering/framebufferobject.cpp b/rendering/framebufferobject.cpp new file mode 100644 index 000000000..10a2cbb96 --- /dev/null +++ b/rendering/framebufferobject.cpp @@ -0,0 +1,81 @@ +#include "framebufferobject.h" + +#include + +FramebufferObject::FramebufferObject() : + buffer_(0), + texture_(0), + ctx_(nullptr) +{} + +FramebufferObject::~FramebufferObject() +{ + Destroy(); +} + +bool FramebufferObject::IsCreated() +{ + return ctx_ != nullptr; +} + +void FramebufferObject::Create(QOpenGLContext *ctx, int width, int height) +{ + // free any previous textures + Destroy(); + + // set context to new context provided + ctx_ = ctx; + + // create framebuffer object + ctx->functions()->glGenFramebuffers(1, &buffer_); + + // create texture + ctx->functions()->glGenTextures(1, &texture_); + + // bind framebuffer for attaching + ctx->functions()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, buffer_); + + // bind texture + ctx->functions()->glBindTexture(GL_TEXTURE_2D, texture_); + + // allocate storage for texture + ctx->functions()->glTexImage2D( + GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr + ); + + // set texture filtering to bilinear + ctx->functions()->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + ctx->functions()->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // attach texture to framebuffer + ctx->functions()->glFramebufferTexture2D( + GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_, 0 + ); + + // release texture + ctx->functions()->glBindTexture(GL_TEXTURE_2D, 0); + + // release framebuffer + ctx->functions()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); +} + +void FramebufferObject::Destroy() +{ + if (ctx_ != nullptr) { + ctx_->functions()->glDeleteFramebuffers(1, &buffer_); + + ctx_->functions()->glDeleteTextures(1, &texture_); + } + + ctx_ = nullptr; +} + +const GLuint &FramebufferObject::buffer() +{ + return buffer_; +} + +const GLuint &FramebufferObject::texture() +{ + return texture_; +} diff --git a/rendering/framebufferobject.h b/rendering/framebufferobject.h new file mode 100644 index 000000000..fc5644392 --- /dev/null +++ b/rendering/framebufferobject.h @@ -0,0 +1,24 @@ +#ifndef FRAMEBUFFEROBJECT_H +#define FRAMEBUFFEROBJECT_H + +#include + +class FramebufferObject +{ +public: + FramebufferObject(); + ~FramebufferObject(); + + bool IsCreated(); + void Create(QOpenGLContext* ctx, int width, int height); + void Destroy(); + + const GLuint& buffer(); + const GLuint& texture(); +private: + QOpenGLContext* ctx_; + GLuint buffer_; + GLuint texture_; +}; + +#endif // FRAMEBUFFEROBJECT_H diff --git a/rendering/renderthread.cpp b/rendering/renderthread.cpp index 700cc290e..0c3ff96f3 100644 --- a/rendering/renderthread.cpp +++ b/rendering/renderthread.cpp @@ -33,25 +33,20 @@ namespace OCIO = OCIO_NAMESPACE; #include "rendering/renderfunctions.h" #include "project/sequence.h" -RenderThread::RenderThread() +RenderThread::RenderThread() : + gizmos(nullptr), + share_ctx(nullptr), + ctx(nullptr), + blend_mode_program(nullptr), + premultiply_program(nullptr), + seq(nullptr), + tex_width(-1), + tex_height(-1), + queued(false), + texture_failed(false), + running(true), + front_buffer_switcher(false) { - front_buffer1 = 0; - front_buffer2 = 0; - front_texture1 = 0; - front_texture2 = 0; - gizmos = nullptr; - share_ctx = nullptr; - ctx = nullptr; - blend_mode_program = nullptr; - premultiply_program = nullptr; - seq = nullptr; - tex_width = -1; - tex_height = -1; - queued = false; - texture_failed = false; - running = true; - front_buffer_switcher = false; - surface.create(); } @@ -75,44 +70,32 @@ void RenderThread::run() { if (ctx != nullptr) { ctx->makeCurrent(&surface); - // gen fbo - if (front_buffer1 == 0) { - // delete any existing framebuffers - delete_fbo(); + // if the sequence size has changed, we'll need to reinitialize the textures + if (seq->width != tex_width || seq->height != tex_height) { + delete_buffers(); - // create framebuffers - ctx->functions()->glGenFramebuffers(1, &front_buffer1); - ctx->functions()->glGenFramebuffers(1, &front_buffer2); - ctx->functions()->glGenFramebuffers(1, &back_buffer_1); - ctx->functions()->glGenFramebuffers(1, &back_buffer_2); - } - - // gen texture - if (front_texture1 == 0 || tex_width != seq->width || tex_height != seq->height) { - // cache texture size + // cache sequence values for future checks tex_width = seq->width; tex_height = seq->height; + } - // delete any existing textures - delete_texture(); - - // create texture - glGenTextures(1, &front_texture1); - glGenTextures(1, &front_texture2); - glGenTextures(1, &back_texture_1); - glGenTextures(1, &back_texture_2); - - GLuint textures[4] = { front_texture1, front_texture2, back_texture_1, back_texture_2 }; - GLuint fbos[4] = { front_buffer1, front_buffer2, back_buffer_1, back_buffer_2 }; - - for (int i=0;i<4;i++) { - allocate_texture(textures[i], fbos[i]); - } + // create any buffers that don't yet exist + if (!front_buffer_1.IsCreated()) { + front_buffer_1.Create(ctx, seq->width, seq->height); + } + if (!front_buffer_2.IsCreated()) { + front_buffer_2.Create(ctx, seq->width, seq->height); + } + if (!back_buffer_1.IsCreated()) { + back_buffer_1.Create(ctx, seq->width, seq->height); + } + if (!back_buffer_2.IsCreated()) { + back_buffer_2.Create(ctx, seq->width, seq->height); } if (blend_mode_program == nullptr) { // create shader program to make blending modes work - delete_shader_program(); + delete_shaders(); blend_mode_program = new QOpenGLShaderProgram(); blend_mode_program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/internalshaders/common.vert"); @@ -149,36 +132,7 @@ QMutex *RenderThread::get_texture_mutex() const GLuint &RenderThread::get_texture() { // return the opposite texture to the texture being drawn to by the renderer - return front_buffer_switcher ? front_texture2 : front_texture1; -} - -void RenderThread::allocate_texture(GLuint tex, GLuint fbo) -{ - // bind framebuffer for attaching - ctx->functions()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); - - // bind texture - glBindTexture(GL_TEXTURE_2D, tex); - - // allocate storage for texture - glTexImage2D( - GL_TEXTURE_2D, 0, GL_RGBA, seq->width, seq->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr - ); - - // set texture filtering to bilinear - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - // attach texture to framebuffer - ctx->functions()->glFramebufferTexture2D( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0 - ); - - // release texture - glBindTexture(GL_TEXTURE_2D, 0); - - // release framebuffer - ctx->functions()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + return front_buffer_switcher ? front_buffer_2.texture() : front_buffer_1.texture(); } void RenderThread::set_up_ocio() @@ -197,12 +151,12 @@ void RenderThread::paint() { params.playback_speed = 1; params.blend_mode_program = blend_mode_program; params.premultiply_program = premultiply_program; - params.backend_buffer1 = back_buffer_1; - params.backend_buffer2 = back_buffer_2; - params.backend_attachment1 = back_texture_1; - params.backend_attachment2 = back_texture_2; - params.main_buffer = front_buffer_switcher ? front_buffer1 : front_buffer2; - params.main_attachment = front_buffer_switcher ? front_texture1 : front_texture2; + params.backend_buffer1 = back_buffer_1.buffer(); + params.backend_buffer2 = back_buffer_2.buffer(); + params.backend_attachment1 = back_buffer_1.texture(); + params.backend_attachment2 = back_buffer_2.texture(); + params.main_buffer = front_buffer_switcher ? front_buffer_1.buffer() : front_buffer_2.buffer(); + params.main_attachment = front_buffer_switcher ? front_buffer_1.texture() : front_buffer_2.texture(); // get currently selected gizmos gizmos = seq->GetSelectedGizmo(); @@ -313,44 +267,27 @@ void RenderThread::cancel() { wait(); } -void RenderThread::delete_texture() { - if (front_texture1 > 0) { - GLuint tex[4] = {front_texture1, front_texture2, back_texture_1, back_texture_2}; - glDeleteTextures(3, tex); - } - front_texture1 = 0; - front_texture2 = 0; - back_texture_1 = 0; - back_texture_2 = 0; +void RenderThread::delete_buffers() { + front_buffer_1.Destroy(); + front_buffer_2.Destroy(); + back_buffer_1.Destroy(); + back_buffer_2.Destroy(); } -void RenderThread::delete_fbo() { - if (front_buffer1 > 0) { - GLuint fbos[4] = {front_buffer1, front_buffer2, back_buffer_1, back_buffer_2}; - ctx->functions()->glDeleteFramebuffers(3, fbos); - } - front_buffer1 = 0; - front_buffer2 = 0; - back_buffer_1 = 0; - back_buffer_2 = 0; -} - -void RenderThread::delete_shader_program() { - if (blend_mode_program != nullptr) { - delete blend_mode_program; - delete premultiply_program; - } +void RenderThread::delete_shaders() { + delete blend_mode_program; blend_mode_program = nullptr; + + delete premultiply_program; premultiply_program = nullptr; } void RenderThread::delete_ctx() { if (ctx != nullptr) { - delete_shader_program(); - delete_texture(); - delete_fbo(); - ctx->doneCurrent(); - delete ctx; + delete_shaders(); + delete_buffers(); } + + delete ctx; ctx = nullptr; } diff --git a/rendering/renderthread.h b/rendering/renderthread.h index b7c4717ff..e18be91d3 100644 --- a/rendering/renderthread.h +++ b/rendering/renderthread.h @@ -31,6 +31,7 @@ #include "project/sequence.h" #include "project/effect.h" +#include "rendering/framebufferobject.h" // copied from source code to OCIODisplay const int LUT3D_EDGE_SIZE = 32; @@ -66,22 +67,17 @@ public slots: signals: void ready(); private: - void allocate_texture(GLuint tex, GLuint fbo); + // cleanup functions + void delete_buffers(); + void delete_shaders(); void set_up_ocio(); void destroy_ocio(); - // cleanup functions - void delete_texture(); - void delete_fbo(); - void delete_shader_program(); - - GLuint front_buffer1; - GLuint front_texture1; + FramebufferObject front_buffer_1; QMutex front_mutex1; - GLuint front_buffer2; - GLuint front_texture2; + FramebufferObject front_buffer_2; QMutex front_mutex2; bool front_buffer_switcher; @@ -98,10 +94,8 @@ private: QOpenGLShaderProgram* blend_mode_program; QOpenGLShaderProgram* premultiply_program; - GLuint back_buffer_1; - GLuint back_buffer_2; - GLuint back_texture_1; - GLuint back_texture_2; + FramebufferObject back_buffer_1; + FramebufferObject back_buffer_2; float ocio_lut_data[NUM_3D_ENTRIES]; GLuint ocio_lut_texture;