274 lines
8.0 KiB
C++
274 lines
8.0 KiB
C++
#include "OpenGLRenderer.h"
|
|
|
|
#include "GlRenderConstants.h"
|
|
|
|
namespace
|
|
{
|
|
void ConfigureFrameTexture(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_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
|
|
}
|
|
}
|
|
|
|
bool OpenGLRenderer::InitializeResources(unsigned inputFrameWidth, unsigned inputFrameHeight, unsigned outputFrameWidth, unsigned outputFrameHeight, std::string& error)
|
|
{
|
|
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
if (!mFastTransferExtensionAvailable)
|
|
glGenBuffers(1, &mUnpinnedTextureBuffer);
|
|
|
|
glGenTextures(1, &mCaptureTexture);
|
|
glBindTexture(GL_TEXTURE_2D, mCaptureTexture);
|
|
ConfigureFrameTexture(inputFrameWidth / 2, inputFrameHeight);
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
|
|
glGenTextures(1, &mDecodedTexture);
|
|
glBindTexture(GL_TEXTURE_2D, mDecodedTexture);
|
|
ConfigureFrameTexture(inputFrameWidth, inputFrameHeight);
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
|
|
glGenTextures(1, &mLayerTempTexture);
|
|
glBindTexture(GL_TEXTURE_2D, mLayerTempTexture);
|
|
ConfigureFrameTexture(inputFrameWidth, inputFrameHeight);
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
|
|
glGenFramebuffers(1, &mDecodeFrameBuf);
|
|
glGenFramebuffers(1, &mLayerTempFrameBuf);
|
|
glGenFramebuffers(1, &mIdFrameBuf);
|
|
glGenFramebuffers(1, &mOutputFrameBuf);
|
|
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.";
|
|
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.";
|
|
return false;
|
|
}
|
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, mIdFrameBuf);
|
|
glGenTextures(1, &mFBOTexture);
|
|
glBindTexture(GL_TEXTURE_2D, mFBOTexture);
|
|
ConfigureFrameTexture(inputFrameWidth, inputFrameHeight);
|
|
|
|
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);
|
|
ConfigureFrameTexture(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.";
|
|
return false;
|
|
}
|
|
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
glBindVertexArray(mFullscreenVAO);
|
|
glBindVertexArray(0);
|
|
glBindBuffer(GL_UNIFORM_BUFFER, mGlobalParamsUBO);
|
|
glBufferData(GL_UNIFORM_BUFFER, 1024, NULL, GL_DYNAMIC_DRAW);
|
|
glBindBufferBase(GL_UNIFORM_BUFFER, kGlobalParamsBindingPoint, mGlobalParamsUBO);
|
|
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
|
|
|
return true;
|
|
}
|
|
|
|
void OpenGLRenderer::SetDecodeShaderProgram(GLuint program, GLuint vertexShader, GLuint fragmentShader)
|
|
{
|
|
mDecodeProgram = program;
|
|
mDecodeVertexShader = vertexShader;
|
|
mDecodeFragmentShader = fragmentShader;
|
|
}
|
|
|
|
void OpenGLRenderer::ResizeView(int width, int height)
|
|
{
|
|
mViewWidth = width;
|
|
mViewHeight = height;
|
|
}
|
|
|
|
void OpenGLRenderer::PresentToWindow(HDC hdc, unsigned outputFrameWidth, unsigned outputFrameHeight)
|
|
{
|
|
int destWidth = mViewWidth;
|
|
int destHeight = mViewHeight;
|
|
int destX = 0;
|
|
int destY = 0;
|
|
|
|
if (outputFrameWidth > 0 && outputFrameHeight > 0 && mViewWidth > 0 && mViewHeight > 0)
|
|
{
|
|
const double frameAspect = static_cast<double>(outputFrameWidth) / static_cast<double>(outputFrameHeight);
|
|
const double viewAspect = static_cast<double>(mViewWidth) / static_cast<double>(mViewHeight);
|
|
|
|
if (viewAspect > frameAspect)
|
|
{
|
|
destHeight = mViewHeight;
|
|
destWidth = static_cast<int>(destHeight * frameAspect + 0.5);
|
|
destX = (mViewWidth - destWidth) / 2;
|
|
}
|
|
else
|
|
{
|
|
destWidth = mViewWidth;
|
|
destHeight = static_cast<int>(destWidth / frameAspect + 0.5);
|
|
destY = (mViewHeight - destHeight) / 2;
|
|
}
|
|
}
|
|
|
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, mOutputFrameBuf);
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
|
glViewport(0, 0, mViewWidth, mViewHeight);
|
|
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
glBlitFramebuffer(0, 0, outputFrameWidth, outputFrameHeight, destX, destY, destX + destWidth, destY + destHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
|
|
|
SwapBuffers(hdc);
|
|
}
|
|
|
|
void OpenGLRenderer::DestroyResources()
|
|
{
|
|
if (mFullscreenVAO != 0)
|
|
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 (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 (mUnpinnedTextureBuffer != 0)
|
|
glDeleteBuffers(1, &mUnpinnedTextureBuffer);
|
|
|
|
mFullscreenVAO = 0;
|
|
mGlobalParamsUBO = 0;
|
|
mDecodeFrameBuf = 0;
|
|
mLayerTempFrameBuf = 0;
|
|
mIdFrameBuf = 0;
|
|
mOutputFrameBuf = 0;
|
|
mIdColorBuf = 0;
|
|
mIdDepthBuf = 0;
|
|
mCaptureTexture = 0;
|
|
mDecodedTexture = 0;
|
|
mLayerTempTexture = 0;
|
|
mFBOTexture = 0;
|
|
mOutputTexture = 0;
|
|
mUnpinnedTextureBuffer = 0;
|
|
mGlobalParamsUBOSize = 0;
|
|
|
|
mTemporalHistory.DestroyResources();
|
|
DestroyLayerPrograms();
|
|
DestroyDecodeShaderProgram();
|
|
}
|
|
|
|
void OpenGLRenderer::DestroySingleLayerProgram(LayerProgram& layerProgram)
|
|
{
|
|
for (LayerProgram::TextureBinding& binding : layerProgram.textureBindings)
|
|
{
|
|
if (binding.texture != 0)
|
|
{
|
|
glDeleteTextures(1, &binding.texture);
|
|
binding.texture = 0;
|
|
}
|
|
}
|
|
layerProgram.textureBindings.clear();
|
|
|
|
for (LayerProgram::TextBinding& binding : layerProgram.textBindings)
|
|
{
|
|
if (binding.texture != 0)
|
|
{
|
|
glDeleteTextures(1, &binding.texture);
|
|
binding.texture = 0;
|
|
}
|
|
}
|
|
layerProgram.textBindings.clear();
|
|
|
|
if (layerProgram.program != 0)
|
|
{
|
|
glDeleteProgram(layerProgram.program);
|
|
layerProgram.program = 0;
|
|
}
|
|
|
|
if (layerProgram.fragmentShader != 0)
|
|
{
|
|
glDeleteShader(layerProgram.fragmentShader);
|
|
layerProgram.fragmentShader = 0;
|
|
}
|
|
|
|
if (layerProgram.vertexShader != 0)
|
|
{
|
|
glDeleteShader(layerProgram.vertexShader);
|
|
layerProgram.vertexShader = 0;
|
|
}
|
|
}
|
|
|
|
void OpenGLRenderer::DestroyLayerPrograms()
|
|
{
|
|
for (LayerProgram& layerProgram : mLayerPrograms)
|
|
DestroySingleLayerProgram(layerProgram);
|
|
mLayerPrograms.clear();
|
|
}
|
|
|
|
void OpenGLRenderer::DestroyDecodeShaderProgram()
|
|
{
|
|
if (mDecodeProgram != 0)
|
|
{
|
|
glDeleteProgram(mDecodeProgram);
|
|
mDecodeProgram = 0;
|
|
}
|
|
|
|
if (mDecodeFragmentShader != 0)
|
|
{
|
|
glDeleteShader(mDecodeFragmentShader);
|
|
mDecodeFragmentShader = 0;
|
|
}
|
|
|
|
if (mDecodeVertexShader != 0)
|
|
{
|
|
glDeleteShader(mDecodeVertexShader);
|
|
mDecodeVertexShader = 0;
|
|
}
|
|
}
|