#include "OpenGLRenderPass.h" #include "GlRenderConstants.h" #include "VideoFrameTransfer.h" OpenGLRenderPass::OpenGLRenderPass(OpenGLRenderer& renderer) : mRenderer(renderer) { } void OpenGLRenderPass::Render( bool hasInputSource, const std::vector& layerStates, unsigned inputFrameWidth, unsigned inputFrameHeight, unsigned historyCap, const TextBindingUpdater& updateTextBinding, const GlobalParamsUpdater& updateGlobalParams) { if (hasInputSource && mRenderer.mFastTransferExtensionAvailable) { // Signal that we're about to draw using mCaptureTexture onto mFBOTexture. VideoFrameTransfer::beginTextureInUse(VideoFrameTransfer::CPUtoGPU); } glDisable(GL_BLEND); glDisable(GL_DEPTH_TEST); if (hasInputSource) { RenderDecodePass(inputFrameWidth, inputFrameHeight); } else { glBindFramebuffer(GL_FRAMEBUFFER, mRenderer.mDecodeFrameBuf); glViewport(0, 0, inputFrameWidth, inputFrameHeight); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); } if (layerStates.empty() || mRenderer.mLayerPrograms.empty()) { glBindFramebuffer(GL_READ_FRAMEBUFFER, mRenderer.mDecodeFrameBuf); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mRenderer.mIdFrameBuf); glBlitFramebuffer(0, 0, inputFrameWidth, inputFrameHeight, 0, 0, inputFrameWidth, inputFrameHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR); glBindFramebuffer(GL_FRAMEBUFFER, mRenderer.mIdFrameBuf); } else { GLuint sourceTexture = mRenderer.mDecodedTexture; GLuint sourceFrameBuffer = mRenderer.mDecodeFrameBuf; for (std::size_t index = 0; index < layerStates.size() && index < mRenderer.mLayerPrograms.size(); ++index) { const std::size_t remaining = layerStates.size() - index; const bool writeToMain = (remaining % 2) == 1; RenderShaderProgram( sourceTexture, writeToMain ? mRenderer.mIdFrameBuf : mRenderer.mLayerTempFrameBuf, mRenderer.mLayerPrograms[index], layerStates[index], inputFrameWidth, inputFrameHeight, historyCap, updateTextBinding, updateGlobalParams); if (layerStates[index].temporalHistorySource == TemporalHistorySource::PreLayerInput) mRenderer.mTemporalHistory.PushPreLayerFramebuffer(layerStates[index].layerId, sourceFrameBuffer, inputFrameWidth, inputFrameHeight); sourceTexture = writeToMain ? mRenderer.mFBOTexture : mRenderer.mLayerTempTexture; sourceFrameBuffer = writeToMain ? mRenderer.mIdFrameBuf : mRenderer.mLayerTempFrameBuf; } } mRenderer.mTemporalHistory.PushSourceFramebuffer(mRenderer.mDecodeFrameBuf, inputFrameWidth, inputFrameHeight); if (hasInputSource && mRenderer.mFastTransferExtensionAvailable) VideoFrameTransfer::endTextureInUse(VideoFrameTransfer::CPUtoGPU); } void OpenGLRenderPass::RenderDecodePass(unsigned inputFrameWidth, unsigned inputFrameHeight) { glBindFramebuffer(GL_FRAMEBUFFER, mRenderer.mDecodeFrameBuf); glViewport(0, 0, inputFrameWidth, inputFrameHeight); glClear(GL_COLOR_BUFFER_BIT); glActiveTexture(GL_TEXTURE0 + kPackedVideoTextureUnit); glBindTexture(GL_TEXTURE_2D, mRenderer.mCaptureTexture); glBindVertexArray(mRenderer.mFullscreenVAO); glUseProgram(mRenderer.mDecodeProgram); const GLint packedResolutionLocation = glGetUniformLocation(mRenderer.mDecodeProgram, "uPackedVideoResolution"); const GLint decodedResolutionLocation = glGetUniformLocation(mRenderer.mDecodeProgram, "uDecodedVideoResolution"); if (packedResolutionLocation >= 0) glUniform2f(packedResolutionLocation, static_cast(inputFrameWidth / 2), static_cast(inputFrameHeight)); if (decodedResolutionLocation >= 0) glUniform2f(decodedResolutionLocation, static_cast(inputFrameWidth), static_cast(inputFrameHeight)); glDrawArrays(GL_TRIANGLES, 0, 3); glUseProgram(0); glBindVertexArray(0); glBindTexture(GL_TEXTURE_2D, 0); glActiveTexture(GL_TEXTURE0); } void OpenGLRenderPass::RenderShaderProgram( GLuint sourceTexture, GLuint destinationFrameBuffer, LayerProgram& layerProgram, const RuntimeRenderState& state, unsigned inputFrameWidth, unsigned inputFrameHeight, unsigned historyCap, const TextBindingUpdater& updateTextBinding, const GlobalParamsUpdater& updateGlobalParams) { for (LayerProgram::TextBinding& textBinding : layerProgram.textBindings) { std::string textError; if (!updateTextBinding(state, textBinding, textError)) OutputDebugStringA((textError + "\n").c_str()); } glBindFramebuffer(GL_FRAMEBUFFER, destinationFrameBuffer); glViewport(0, 0, inputFrameWidth, inputFrameHeight); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glActiveTexture(GL_TEXTURE0 + kDecodedVideoTextureUnit); glBindTexture(GL_TEXTURE_2D, sourceTexture); mRenderer.mTemporalHistory.BindSamplers(state, sourceTexture, historyCap); BindLayerTextureAssets(layerProgram); glBindVertexArray(mRenderer.mFullscreenVAO); glUseProgram(layerProgram.program); updateGlobalParams(state, mRenderer.mTemporalHistory.SourceAvailableCount(), mRenderer.mTemporalHistory.AvailableCountForLayer(state.layerId)); glDrawArrays(GL_TRIANGLES, 0, 3); glUseProgram(0); glBindVertexArray(0); UnbindLayerTextureAssets(layerProgram, historyCap); } void OpenGLRenderPass::BindLayerTextureAssets(const LayerProgram& layerProgram) { const GLuint shaderTextureBase = layerProgram.shaderTextureBase != 0 ? layerProgram.shaderTextureBase : kSourceHistoryTextureUnitBase; for (std::size_t index = 0; index < layerProgram.textureBindings.size(); ++index) { glActiveTexture(GL_TEXTURE0 + shaderTextureBase + static_cast(index)); glBindTexture(GL_TEXTURE_2D, layerProgram.textureBindings[index].texture); } const GLuint textTextureBase = shaderTextureBase + static_cast(layerProgram.textureBindings.size()); for (std::size_t index = 0; index < layerProgram.textBindings.size(); ++index) { glActiveTexture(GL_TEXTURE0 + textTextureBase + static_cast(index)); glBindTexture(GL_TEXTURE_2D, layerProgram.textBindings[index].texture); } glActiveTexture(GL_TEXTURE0); } void OpenGLRenderPass::UnbindLayerTextureAssets(const LayerProgram& layerProgram, unsigned historyCap) { for (unsigned index = 0; index < historyCap; ++index) { glActiveTexture(GL_TEXTURE0 + kSourceHistoryTextureUnitBase + index); glBindTexture(GL_TEXTURE_2D, 0); glActiveTexture(GL_TEXTURE0 + kSourceHistoryTextureUnitBase + historyCap + index); glBindTexture(GL_TEXTURE_2D, 0); } const GLuint shaderTextureBase = layerProgram.shaderTextureBase != 0 ? layerProgram.shaderTextureBase : kSourceHistoryTextureUnitBase; for (std::size_t index = 0; index < layerProgram.textureBindings.size() + layerProgram.textBindings.size(); ++index) { glActiveTexture(GL_TEXTURE0 + shaderTextureBase + static_cast(index)); glBindTexture(GL_TEXTURE_2D, 0); } glActiveTexture(GL_TEXTURE0 + kDecodedVideoTextureUnit); glBindTexture(GL_TEXTURE_2D, 0); glActiveTexture(GL_TEXTURE0); }