From d76218924e84a8b669bdc9d8389b3d71ae1779d4 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Tue, 27 Aug 2019 23:45:13 +1000 Subject: [PATCH] created double buffered textures --- app/render/renderframebuffer.cpp | 48 +++++++++------ app/render/renderframebuffer.h | 4 ++ app/render/rendertexture.cpp | 101 +++++++++++++++++++++---------- app/render/rendertexture.h | 14 ++++- 4 files changed, 114 insertions(+), 53 deletions(-) diff --git a/app/render/renderframebuffer.cpp b/app/render/renderframebuffer.cpp index 7819bb5a0..0fede0011 100644 --- a/app/render/renderframebuffer.cpp +++ b/app/render/renderframebuffer.cpp @@ -86,27 +86,14 @@ void RenderFramebuffer::Release() void RenderFramebuffer::Attach(RenderTexturePtr texture) { - Detach(); - texture_ = texture; + AttachInternal(texture_->texture()); +} - QOpenGLFunctions* f = context_->functions(); - - // bind framebuffer for attaching - f->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, buffer_); - - // bind texture - f->glBindTexture(GL_TEXTURE_2D, texture_->texture()); - - context_->extraFunctions()->glFramebufferTexture2D( - GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_->texture(), 0 - ); - - // release texture - f->glBindTexture(GL_TEXTURE_2D, 0); - - // release framebuffer - f->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); +void RenderFramebuffer::AttachBackBuffer(RenderTexturePtr texture) +{ + texture_ = texture; + AttachInternal(texture_->back_texture()); } void RenderFramebuffer::Detach() @@ -130,3 +117,26 @@ const GLuint &RenderFramebuffer::buffer() const { return buffer_; } + +void RenderFramebuffer::AttachInternal(GLuint tex) +{ + Detach(); + + QOpenGLFunctions* f = context_->functions(); + + // bind framebuffer for attaching + f->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, buffer_); + + // bind texture + f->glBindTexture(GL_TEXTURE_2D, tex); + + context_->extraFunctions()->glFramebufferTexture2D( + GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0 + ); + + // release texture + f->glBindTexture(GL_TEXTURE_2D, 0); + + // release framebuffer + f->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); +} diff --git a/app/render/renderframebuffer.h b/app/render/renderframebuffer.h index 1416fd21e..10f3fac98 100644 --- a/app/render/renderframebuffer.h +++ b/app/render/renderframebuffer.h @@ -47,11 +47,15 @@ public: void Attach(RenderTexturePtr texture); + void AttachBackBuffer(RenderTexturePtr texture); + void Detach(); const GLuint& buffer() const; private: + void AttachInternal(GLuint tex); + QOpenGLContext* context_; GLuint buffer_; diff --git a/app/render/rendertexture.cpp b/app/render/rendertexture.cpp index df437a215..e09c76600 100644 --- a/app/render/rendertexture.cpp +++ b/app/render/rendertexture.cpp @@ -42,6 +42,11 @@ bool RenderTexture::IsCreated() const } void RenderTexture::Create(QOpenGLContext *ctx, int width, int height, const olive::PixelFormat &format, void* data) +{ + Create(ctx, width, height, format, kSingleBuffer, data); +} + +void RenderTexture::Create(QOpenGLContext *ctx, int width, int height, const olive::PixelFormat &format, const RenderTexture::Type &type, void *data) { if (ctx == nullptr) { qWarning() << tr("RenderTexture::Create was passed an invalid context"); @@ -51,48 +56,27 @@ void RenderTexture::Create(QOpenGLContext *ctx, int width, int height, const oli Destroy(); context_ = ctx; + width_ = width; + height_ = height; + format_ = format; - QOpenGLFunctions* f = context_->functions(); + // Create main texture + CreateInternal(data); - // Create texture - f->glGenTextures(1, &texture_); - - // Verify texture - if (texture_ == 0) { - qWarning() << tr("OpenGL texture creation failed"); - return; + if (type == kDoubleBuffer) { + // Create back texture + CreateInternal(nullptr); } - - // Bind texture - f->glBindTexture(GL_TEXTURE_2D, texture_); - - // Allocate storage for texture - const PixelFormatInfo& bit_depth = PixelService::GetPixelFormatInfo(format); - - f->glTexImage2D( - GL_TEXTURE_2D, - 0, - bit_depth.internal_format, - width, - height, - 0, - bit_depth.pixel_format, - bit_depth.pixel_type, - data - ); - - // Set texture filtering to bilinear - f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - // Release texture - f->glBindTexture(GL_TEXTURE_2D, 0); } void RenderTexture::Destroy() { if (context_ != nullptr) { context_->functions()->glDeleteTextures(1, &texture_); + texture_ = 0; + + context_->functions()->glDeleteTextures(1, &back_texture_); + back_texture_ = 0; context_ = nullptr; } @@ -143,6 +127,18 @@ const GLuint &RenderTexture::texture() const return texture_; } +const GLuint &RenderTexture::back_texture() const +{ + return back_texture_; +} + +void RenderTexture::SwapFrontAndBack() +{ + GLuint temp = texture_; + texture_ = back_texture_; + back_texture_ = temp; +} + void RenderTexture::Upload(void *data) { if (!IsCreated()) { @@ -178,3 +174,42 @@ void *RenderTexture::Download() const return nullptr; } + +void RenderTexture::CreateInternal(void *data) +{ + QOpenGLFunctions* f = context_->functions(); + + // Create texture + f->glGenTextures(1, &texture_); + + // Verify texture + if (texture_ == 0) { + qWarning() << tr("OpenGL texture creation failed"); + return; + } + + // Bind texture + f->glBindTexture(GL_TEXTURE_2D, texture_); + + // Allocate storage for texture + const PixelFormatInfo& bit_depth = PixelService::GetPixelFormatInfo(format_); + + f->glTexImage2D( + GL_TEXTURE_2D, + 0, + bit_depth.internal_format, + width_, + height_, + 0, + bit_depth.pixel_format, + bit_depth.pixel_type, + data + ); + + // Set texture filtering to bilinear + f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // Release texture + f->glBindTexture(GL_TEXTURE_2D, 0); +} diff --git a/app/render/rendertexture.h b/app/render/rendertexture.h index c2e9fa7dc..52590a243 100644 --- a/app/render/rendertexture.h +++ b/app/render/rendertexture.h @@ -1,4 +1,4 @@ -/*** +/*** Olive - Non-Linear Video Editor Copyright (C) 2019 Olive Team @@ -29,6 +29,11 @@ class RenderTexture : public QObject { public: + enum Type { + kSingleBuffer, + kDoubleBuffer + }; + RenderTexture(); ~RenderTexture(); RenderTexture(const RenderTexture& other) = delete; @@ -37,6 +42,7 @@ public: RenderTexture& operator=(RenderTexture&& other) = delete; void Create(QOpenGLContext* ctx, int width, int height, const olive::PixelFormat &format, void *data = nullptr); + void Create(QOpenGLContext* ctx, int width, int height, const olive::PixelFormat &format, const Type& type, void *data = nullptr); bool IsCreated() const; @@ -55,16 +61,22 @@ public: QOpenGLContext* context() const; const GLuint& texture() const; + const GLuint& back_texture() const; + void SwapFrontAndBack(); void Upload(void* data); void* Download() const; private: + void CreateInternal(void *data = nullptr); + QOpenGLContext* context_; GLuint texture_; + GLuint back_texture_; + int width_; int height_;