#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::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(outputFrameWidth) / static_cast(outputFrameHeight); const double viewAspect = static_cast(mViewWidth) / static_cast(mViewHeight); if (viewAspect > frameAspect) { destHeight = mViewHeight; destWidth = static_cast(destHeight * frameAspect + 0.5); destX = (mViewWidth - destWidth) / 2; } else { destWidth = mViewWidth; destHeight = static_cast(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; } }