diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1f70d9c..e110aea 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -67,6 +67,8 @@ set(APP_SOURCES
"${APP_DIR}/gl/pipeline/RenderPassDescriptor.h"
"${APP_DIR}/gl/renderer/OpenGLRenderer.cpp"
"${APP_DIR}/gl/renderer/OpenGLRenderer.h"
+ "${APP_DIR}/gl/renderer/RenderTargetPool.cpp"
+ "${APP_DIR}/gl/renderer/RenderTargetPool.h"
"${APP_DIR}/gl/pipeline/OpenGLVideoIOBridge.cpp"
"${APP_DIR}/gl/pipeline/OpenGLVideoIOBridge.h"
"${APP_DIR}/gl/shader/OpenGLShaderPrograms.cpp"
diff --git a/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj b/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj
index 6f8b9ec..5257d31 100644
--- a/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj
+++ b/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj
@@ -181,6 +181,7 @@
+
@@ -208,6 +209,7 @@
+
diff --git a/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj.filters b/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj.filters
index cae0ed3..c19a028 100644
--- a/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj.filters
+++ b/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj.filters
@@ -36,6 +36,9 @@
Source Files
+
+ Source Files
+
Source Files
@@ -98,6 +101,9 @@
Header Files
+
+ Header Files
+
Header Files
diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/renderer/OpenGLRenderer.cpp b/apps/LoopThroughWithOpenGLCompositing/gl/renderer/OpenGLRenderer.cpp
index 19fbd8e..1f1f8b0 100644
--- a/apps/LoopThroughWithOpenGLCompositing/gl/renderer/OpenGLRenderer.cpp
+++ b/apps/LoopThroughWithOpenGLCompositing/gl/renderer/OpenGLRenderer.cpp
@@ -12,15 +12,6 @@ namespace
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
}
-
- void ConfigureDisplayFrameTexture(unsigned width, unsigned height)
- {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
- }
}
bool OpenGLRenderer::InitializeResources(unsigned inputFrameWidth, unsigned inputFrameHeight, unsigned captureTextureWidth, unsigned outputFrameWidth, unsigned outputFrameHeight, unsigned outputPackTextureWidth, std::string& error)
@@ -35,80 +26,32 @@ bool OpenGLRenderer::InitializeResources(unsigned inputFrameWidth, unsigned inpu
ConfigureByteFrameTexture(captureTextureWidth, inputFrameHeight);
glBindTexture(GL_TEXTURE_2D, 0);
- glGenTextures(1, &mDecodedTexture);
- glBindTexture(GL_TEXTURE_2D, mDecodedTexture);
- ConfigureDisplayFrameTexture(inputFrameWidth, inputFrameHeight);
- glBindTexture(GL_TEXTURE_2D, 0);
-
- glGenTextures(1, &mLayerTempTexture);
- glBindTexture(GL_TEXTURE_2D, mLayerTempTexture);
- ConfigureDisplayFrameTexture(inputFrameWidth, inputFrameHeight);
- glBindTexture(GL_TEXTURE_2D, 0);
-
- glGenFramebuffers(1, &mDecodeFrameBuf);
- glGenFramebuffers(1, &mLayerTempFrameBuf);
- glGenFramebuffers(1, &mIdFrameBuf);
- glGenFramebuffers(1, &mOutputFrameBuf);
- glGenFramebuffers(1, &mOutputPackFrameBuf);
glGenRenderbuffers(1, &mIdColorBuf);
glGenRenderbuffers(1, &mIdDepthBuf);
glGenVertexArrays(1, &mFullscreenVAO);
glGenBuffers(1, &mGlobalParamsUBO);
- glBindFramebuffer(GL_FRAMEBUFFER, mDecodeFrameBuf);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mDecodedTexture, 0);
- if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
- {
- error = "Cannot initialize decode framebuffer.";
+ if (!mRenderTargets.Create(RenderTargetId::Decoded, inputFrameWidth, inputFrameHeight, GL_RGBA16F, GL_RGBA, GL_FLOAT, "decode", error))
return false;
- }
-
- glBindFramebuffer(GL_FRAMEBUFFER, mLayerTempFrameBuf);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mLayerTempTexture, 0);
- if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
- {
- error = "Cannot initialize layer framebuffer.";
+ if (!mRenderTargets.Create(RenderTargetId::LayerTemp, inputFrameWidth, inputFrameHeight, GL_RGBA16F, GL_RGBA, GL_FLOAT, "layer", error))
+ return false;
+ if (!mRenderTargets.Create(RenderTargetId::Composite, inputFrameWidth, inputFrameHeight, GL_RGBA16F, GL_RGBA, GL_FLOAT, "composite", error))
return false;
- }
-
- glBindFramebuffer(GL_FRAMEBUFFER, mIdFrameBuf);
- glGenTextures(1, &mFBOTexture);
- glBindTexture(GL_TEXTURE_2D, mFBOTexture);
- ConfigureDisplayFrameTexture(inputFrameWidth, inputFrameHeight);
+ glBindFramebuffer(GL_FRAMEBUFFER, CompositeFramebuffer());
glBindRenderbuffer(GL_RENDERBUFFER, mIdDepthBuf);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, inputFrameWidth, inputFrameHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER, mIdDepthBuf);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mFBOTexture, 0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
error = "Cannot initialize framebuffer.";
return false;
}
- glGenTextures(1, &mOutputTexture);
- glBindTexture(GL_TEXTURE_2D, mOutputTexture);
- ConfigureDisplayFrameTexture(outputFrameWidth, outputFrameHeight);
-
- glBindFramebuffer(GL_FRAMEBUFFER, mOutputFrameBuf);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mOutputTexture, 0);
- if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
- {
- error = "Cannot initialize output framebuffer.";
+ if (!mRenderTargets.Create(RenderTargetId::Output, outputFrameWidth, outputFrameHeight, GL_RGBA16F, GL_RGBA, GL_FLOAT, "output", error))
return false;
- }
-
- glGenTextures(1, &mOutputPackTexture);
- glBindTexture(GL_TEXTURE_2D, mOutputPackTexture);
- ConfigureByteFrameTexture(outputPackTextureWidth, outputFrameHeight);
-
- glBindFramebuffer(GL_FRAMEBUFFER, mOutputPackFrameBuf);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mOutputPackTexture, 0);
- if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
- {
- error = "Cannot initialize output pack framebuffer.";
+ if (!mRenderTargets.Create(RenderTargetId::OutputPack, outputPackTextureWidth, outputFrameHeight, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, "output pack", error))
return false;
- }
glBindTexture(GL_TEXTURE_2D, 0);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
@@ -169,7 +112,7 @@ void OpenGLRenderer::PresentToWindow(HDC hdc, unsigned outputFrameWidth, unsigne
}
}
- glBindFramebuffer(GL_READ_FRAMEBUFFER, mOutputFrameBuf);
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, OutputFramebuffer());
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glDisable(GL_SCISSOR_TEST);
glViewport(0, 0, mViewWidth, mViewHeight);
@@ -186,50 +129,21 @@ void OpenGLRenderer::DestroyResources()
glDeleteVertexArrays(1, &mFullscreenVAO);
if (mGlobalParamsUBO != 0)
glDeleteBuffers(1, &mGlobalParamsUBO);
- if (mDecodeFrameBuf != 0)
- glDeleteFramebuffers(1, &mDecodeFrameBuf);
- if (mLayerTempFrameBuf != 0)
- glDeleteFramebuffers(1, &mLayerTempFrameBuf);
- if (mIdFrameBuf != 0)
- glDeleteFramebuffers(1, &mIdFrameBuf);
- if (mOutputFrameBuf != 0)
- glDeleteFramebuffers(1, &mOutputFrameBuf);
- if (mOutputPackFrameBuf != 0)
- glDeleteFramebuffers(1, &mOutputPackFrameBuf);
if (mIdColorBuf != 0)
glDeleteRenderbuffers(1, &mIdColorBuf);
if (mIdDepthBuf != 0)
glDeleteRenderbuffers(1, &mIdDepthBuf);
if (mCaptureTexture != 0)
glDeleteTextures(1, &mCaptureTexture);
- if (mDecodedTexture != 0)
- glDeleteTextures(1, &mDecodedTexture);
- if (mLayerTempTexture != 0)
- glDeleteTextures(1, &mLayerTempTexture);
- if (mFBOTexture != 0)
- glDeleteTextures(1, &mFBOTexture);
- if (mOutputTexture != 0)
- glDeleteTextures(1, &mOutputTexture);
- if (mOutputPackTexture != 0)
- glDeleteTextures(1, &mOutputPackTexture);
if (mTextureUploadBuffer != 0)
glDeleteBuffers(1, &mTextureUploadBuffer);
+ mRenderTargets.Destroy();
mFullscreenVAO = 0;
mGlobalParamsUBO = 0;
- mDecodeFrameBuf = 0;
- mLayerTempFrameBuf = 0;
- mIdFrameBuf = 0;
- mOutputFrameBuf = 0;
- mOutputPackFrameBuf = 0;
mIdColorBuf = 0;
mIdDepthBuf = 0;
mCaptureTexture = 0;
- mDecodedTexture = 0;
- mLayerTempTexture = 0;
- mFBOTexture = 0;
- mOutputTexture = 0;
- mOutputPackTexture = 0;
mTextureUploadBuffer = 0;
mGlobalParamsUBOSize = 0;
diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/renderer/OpenGLRenderer.h b/apps/LoopThroughWithOpenGLCompositing/gl/renderer/OpenGLRenderer.h
index 357fa3c..dac49bc 100644
--- a/apps/LoopThroughWithOpenGLCompositing/gl/renderer/OpenGLRenderer.h
+++ b/apps/LoopThroughWithOpenGLCompositing/gl/renderer/OpenGLRenderer.h
@@ -1,6 +1,7 @@
#pragma once
#include "GLExtensions.h"
+#include "RenderTargetPool.h"
#include "ShaderTypes.h"
#include "TemporalHistoryBuffers.h"
@@ -45,17 +46,17 @@ public:
};
GLuint CaptureTexture() const { return mCaptureTexture; }
- GLuint DecodedTexture() const { return mDecodedTexture; }
- GLuint LayerTempTexture() const { return mLayerTempTexture; }
- GLuint CompositeTexture() const { return mFBOTexture; }
- GLuint OutputTexture() const { return mOutputTexture; }
- GLuint OutputPackTexture() const { return mOutputPackTexture; }
+ GLuint DecodedTexture() const { return mRenderTargets.Texture(RenderTargetId::Decoded); }
+ GLuint LayerTempTexture() const { return mRenderTargets.Texture(RenderTargetId::LayerTemp); }
+ GLuint CompositeTexture() const { return mRenderTargets.Texture(RenderTargetId::Composite); }
+ GLuint OutputTexture() const { return mRenderTargets.Texture(RenderTargetId::Output); }
+ GLuint OutputPackTexture() const { return mRenderTargets.Texture(RenderTargetId::OutputPack); }
GLuint TextureUploadBuffer() const { return mTextureUploadBuffer; }
- GLuint DecodeFramebuffer() const { return mDecodeFrameBuf; }
- GLuint LayerTempFramebuffer() const { return mLayerTempFrameBuf; }
- GLuint CompositeFramebuffer() const { return mIdFrameBuf; }
- GLuint OutputFramebuffer() const { return mOutputFrameBuf; }
- GLuint OutputPackFramebuffer() const { return mOutputPackFrameBuf; }
+ GLuint DecodeFramebuffer() const { return mRenderTargets.Framebuffer(RenderTargetId::Decoded); }
+ GLuint LayerTempFramebuffer() const { return mRenderTargets.Framebuffer(RenderTargetId::LayerTemp); }
+ GLuint CompositeFramebuffer() const { return mRenderTargets.Framebuffer(RenderTargetId::Composite); }
+ GLuint OutputFramebuffer() const { return mRenderTargets.Framebuffer(RenderTargetId::Output); }
+ GLuint OutputPackFramebuffer() const { return mRenderTargets.Framebuffer(RenderTargetId::OutputPack); }
GLuint FullscreenVertexArray() const { return mFullscreenVAO; }
GLuint GlobalParamsUBO() const { return mGlobalParamsUBO; }
GLuint DecodeProgram() const { return mDecodeProgram; }
@@ -80,17 +81,7 @@ public:
private:
GLuint mCaptureTexture = 0;
- GLuint mDecodedTexture = 0;
- GLuint mLayerTempTexture = 0;
- GLuint mFBOTexture = 0;
- GLuint mOutputTexture = 0;
- GLuint mOutputPackTexture = 0;
GLuint mTextureUploadBuffer = 0;
- GLuint mDecodeFrameBuf = 0;
- GLuint mLayerTempFrameBuf = 0;
- GLuint mIdFrameBuf = 0;
- GLuint mOutputFrameBuf = 0;
- GLuint mOutputPackFrameBuf = 0;
GLuint mIdColorBuf = 0;
GLuint mIdDepthBuf = 0;
GLuint mFullscreenVAO = 0;
@@ -105,5 +96,6 @@ private:
int mViewWidth = 0;
int mViewHeight = 0;
std::vector mLayerPrograms;
+ RenderTargetPool mRenderTargets;
TemporalHistoryBuffers mTemporalHistory;
};
diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/renderer/RenderTargetPool.cpp b/apps/LoopThroughWithOpenGLCompositing/gl/renderer/RenderTargetPool.cpp
new file mode 100644
index 0000000..012e39e
--- /dev/null
+++ b/apps/LoopThroughWithOpenGLCompositing/gl/renderer/RenderTargetPool.cpp
@@ -0,0 +1,132 @@
+#include "RenderTargetPool.h"
+
+#include
+
+namespace
+{
+ void ConfigureRenderTargetTexture(
+ unsigned width,
+ unsigned height,
+ GLenum internalFormat,
+ GLenum pixelFormat,
+ GLenum pixelType)
+ {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, pixelFormat, pixelType, NULL);
+ }
+}
+
+bool RenderTargetPool::Create(
+ RenderTargetId id,
+ unsigned width,
+ unsigned height,
+ GLenum internalFormat,
+ GLenum pixelFormat,
+ GLenum pixelType,
+ const char* errorPrefix,
+ std::string& error)
+{
+ RenderTarget& target = mTargets[TargetIndex(id)];
+ if (target.texture != 0 || target.framebuffer != 0)
+ {
+ error = std::string(errorPrefix) + " render target was already initialized.";
+ return false;
+ }
+
+ glGenTextures(1, &target.texture);
+ glBindTexture(GL_TEXTURE_2D, target.texture);
+ ConfigureRenderTargetTexture(width, height, internalFormat, pixelFormat, pixelType);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ glGenFramebuffers(1, &target.framebuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, target.framebuffer);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, target.texture, 0);
+ if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+ {
+ error = std::string("Cannot initialize ") + errorPrefix + " framebuffer.";
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ return false;
+ }
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ target.width = width;
+ target.height = height;
+ target.internalFormat = internalFormat;
+ target.pixelFormat = pixelFormat;
+ target.pixelType = pixelType;
+ return true;
+}
+
+bool RenderTargetPool::ReserveTemporaryTargets(
+ std::size_t count,
+ unsigned width,
+ unsigned height,
+ GLenum internalFormat,
+ GLenum pixelFormat,
+ GLenum pixelType,
+ std::string& error)
+{
+ if (!mTemporaryTargets.empty())
+ {
+ error = "Temporary render targets were already initialized.";
+ return false;
+ }
+
+ mTemporaryTargets.resize(count);
+ for (std::size_t index = 0; index < mTemporaryTargets.size(); ++index)
+ {
+ RenderTarget& target = mTemporaryTargets[index];
+ glGenTextures(1, &target.texture);
+ glBindTexture(GL_TEXTURE_2D, target.texture);
+ ConfigureRenderTargetTexture(width, height, internalFormat, pixelFormat, pixelType);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ glGenFramebuffers(1, &target.framebuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, target.framebuffer);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, target.texture, 0);
+ if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+ {
+ error = "Cannot initialize temporary render target.";
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ return false;
+ }
+
+ target.width = width;
+ target.height = height;
+ target.internalFormat = internalFormat;
+ target.pixelFormat = pixelFormat;
+ target.pixelType = pixelType;
+ }
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ return true;
+}
+
+void RenderTargetPool::Destroy()
+{
+ for (RenderTarget& target : mTargets)
+ {
+ if (target.framebuffer != 0)
+ glDeleteFramebuffers(1, &target.framebuffer);
+ if (target.texture != 0)
+ glDeleteTextures(1, &target.texture);
+ target = RenderTarget();
+ }
+
+ for (RenderTarget& target : mTemporaryTargets)
+ {
+ if (target.framebuffer != 0)
+ glDeleteFramebuffers(1, &target.framebuffer);
+ if (target.texture != 0)
+ glDeleteTextures(1, &target.texture);
+ }
+ mTemporaryTargets.clear();
+}
+
+const RenderTarget& RenderTargetPool::Target(RenderTargetId id) const
+{
+ return mTargets[TargetIndex(id)];
+}
diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/renderer/RenderTargetPool.h b/apps/LoopThroughWithOpenGLCompositing/gl/renderer/RenderTargetPool.h
index 1c0f1c1..6ca08d6 100644
--- a/apps/LoopThroughWithOpenGLCompositing/gl/renderer/RenderTargetPool.h
+++ b/apps/LoopThroughWithOpenGLCompositing/gl/renderer/RenderTargetPool.h
@@ -1,9 +1,10 @@
#pragma once
-#include
+#include "GLExtensions.h"
#include
#include
+#include
enum class RenderTargetId
{
@@ -38,14 +39,25 @@ public:
GLenum pixelType,
const char* errorPrefix,
std::string& error);
+ bool ReserveTemporaryTargets(
+ std::size_t count,
+ unsigned width,
+ unsigned height,
+ GLenum internalFormat,
+ GLenum pixelFormat,
+ GLenum pixelType,
+ std::string& error);
void Destroy();
GLuint Texture(RenderTargetId id) const { return Target(id).texture; }
GLuint Framebuffer(RenderTargetId id) const { return Target(id).framebuffer; }
const RenderTarget& Target(RenderTargetId id) const;
+ const RenderTarget& TemporaryTarget(std::size_t index) const { return mTemporaryTargets[index]; }
+ std::size_t TemporaryTargetCount() const { return mTemporaryTargets.size(); }
private:
static std::size_t TargetIndex(RenderTargetId id) { return static_cast(id); }
std::array(RenderTargetId::Count)> mTargets;
+ std::vector mTemporaryTargets;
};