254 lines
7.4 KiB
C++
254 lines
7.4 KiB
C++
#include "OpenGLRenderer.h"
|
|
|
|
#include "GlRenderConstants.h"
|
|
|
|
namespace
|
|
{
|
|
void ConfigureByteFrameTexture(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_RGBA, GL_UNSIGNED_BYTE, NULL);
|
|
}
|
|
}
|
|
|
|
bool OpenGLRenderer::InitializeResources(unsigned inputFrameWidth, unsigned inputFrameHeight, unsigned captureTextureWidth, unsigned outputFrameWidth, unsigned outputFrameHeight, unsigned outputPackTextureWidth, std::string& error)
|
|
{
|
|
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
glGenBuffers(1, &mTextureUploadBuffer);
|
|
|
|
glGenTextures(1, &mCaptureTexture);
|
|
glBindTexture(GL_TEXTURE_2D, mCaptureTexture);
|
|
ConfigureByteFrameTexture(captureTextureWidth, inputFrameHeight);
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
|
|
glGenRenderbuffers(1, &mIdColorBuf);
|
|
glGenRenderbuffers(1, &mIdDepthBuf);
|
|
glGenVertexArrays(1, &mFullscreenVAO);
|
|
glGenBuffers(1, &mGlobalParamsUBO);
|
|
|
|
if (!mRenderTargets.Create(RenderTargetId::Decoded, inputFrameWidth, inputFrameHeight, GL_RGBA16F, GL_RGBA, GL_FLOAT, "decode", error))
|
|
return false;
|
|
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, CompositeFramebuffer());
|
|
glBindRenderbuffer(GL_RENDERBUFFER, mIdDepthBuf);
|
|
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, inputFrameWidth, inputFrameHeight);
|
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER, mIdDepthBuf);
|
|
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
|
{
|
|
error = "Cannot initialize framebuffer.";
|
|
return false;
|
|
}
|
|
|
|
if (!mRenderTargets.Create(RenderTargetId::Output, outputFrameWidth, outputFrameHeight, GL_RGBA16F, GL_RGBA, GL_FLOAT, "output", error))
|
|
return false;
|
|
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);
|
|
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::SetOutputPackShaderProgram(GLuint program, GLuint vertexShader, GLuint fragmentShader)
|
|
{
|
|
mOutputPackProgram = program;
|
|
mOutputPackVertexShader = vertexShader;
|
|
mOutputPackFragmentShader = fragmentShader;
|
|
}
|
|
|
|
bool OpenGLRenderer::ReserveTemporaryRenderTargets(std::size_t count, unsigned width, unsigned height, std::string& error)
|
|
{
|
|
return mRenderTargets.ReserveTemporaryTargets(count, width, height, GL_RGBA16F, GL_RGBA, GL_FLOAT, error);
|
|
}
|
|
|
|
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, OutputFramebuffer());
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
|
glDisable(GL_SCISSOR_TEST);
|
|
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 (mIdColorBuf != 0)
|
|
glDeleteRenderbuffers(1, &mIdColorBuf);
|
|
if (mIdDepthBuf != 0)
|
|
glDeleteRenderbuffers(1, &mIdDepthBuf);
|
|
if (mCaptureTexture != 0)
|
|
glDeleteTextures(1, &mCaptureTexture);
|
|
if (mTextureUploadBuffer != 0)
|
|
glDeleteBuffers(1, &mTextureUploadBuffer);
|
|
mRenderTargets.Destroy();
|
|
|
|
mFullscreenVAO = 0;
|
|
mGlobalParamsUBO = 0;
|
|
mIdColorBuf = 0;
|
|
mIdDepthBuf = 0;
|
|
mCaptureTexture = 0;
|
|
mTextureUploadBuffer = 0;
|
|
mGlobalParamsUBOSize = 0;
|
|
|
|
mTemporalHistory.DestroyResources();
|
|
DestroyLayerPrograms();
|
|
DestroyDecodeShaderProgram();
|
|
DestroyOutputPackShaderProgram();
|
|
}
|
|
|
|
void OpenGLRenderer::DestroySingleLayerProgram(LayerProgram& layerProgram)
|
|
{
|
|
for (LayerProgram::PassProgram& passProgram : layerProgram.passes)
|
|
{
|
|
for (LayerProgram::TextureBinding& binding : passProgram.textureBindings)
|
|
{
|
|
if (binding.texture != 0)
|
|
{
|
|
glDeleteTextures(1, &binding.texture);
|
|
binding.texture = 0;
|
|
}
|
|
}
|
|
passProgram.textureBindings.clear();
|
|
|
|
for (LayerProgram::TextBinding& binding : passProgram.textBindings)
|
|
{
|
|
if (binding.texture != 0)
|
|
{
|
|
glDeleteTextures(1, &binding.texture);
|
|
binding.texture = 0;
|
|
}
|
|
}
|
|
passProgram.textBindings.clear();
|
|
|
|
if (passProgram.program != 0)
|
|
{
|
|
glDeleteProgram(passProgram.program);
|
|
passProgram.program = 0;
|
|
}
|
|
|
|
if (passProgram.fragmentShader != 0)
|
|
{
|
|
glDeleteShader(passProgram.fragmentShader);
|
|
passProgram.fragmentShader = 0;
|
|
}
|
|
|
|
if (passProgram.vertexShader != 0)
|
|
{
|
|
glDeleteShader(passProgram.vertexShader);
|
|
passProgram.vertexShader = 0;
|
|
}
|
|
}
|
|
layerProgram.passes.clear();
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
void OpenGLRenderer::DestroyOutputPackShaderProgram()
|
|
{
|
|
if (mOutputPackProgram != 0)
|
|
{
|
|
glDeleteProgram(mOutputPackProgram);
|
|
mOutputPackProgram = 0;
|
|
}
|
|
|
|
if (mOutputPackFragmentShader != 0)
|
|
{
|
|
glDeleteShader(mOutputPackFragmentShader);
|
|
mOutputPackFragmentShader = 0;
|
|
}
|
|
|
|
if (mOutputPackVertexShader != 0)
|
|
{
|
|
glDeleteShader(mOutputPackVertexShader);
|
|
mOutputPackVertexShader = 0;
|
|
}
|
|
}
|