#include "OpenGLRenderPass.h" #include "GlRenderConstants.h" OpenGLRenderPass::OpenGLRenderPass(OpenGLRenderer& renderer) : mRenderer(renderer) { } void OpenGLRenderPass::Render( bool hasInputSource, const std::vector& layerStates, unsigned inputFrameWidth, unsigned inputFrameHeight, unsigned captureTextureWidth, VideoIOPixelFormat inputPixelFormat, unsigned historyCap, const TextBindingUpdater& updateTextBinding, const GlobalParamsUpdater& updateGlobalParams) { glDisable(GL_SCISSOR_TEST); glDisable(GL_BLEND); glDisable(GL_DEPTH_TEST); if (hasInputSource) { RenderDecodePass(inputFrameWidth, inputFrameHeight, captureTextureWidth, inputPixelFormat); } else { glBindFramebuffer(GL_FRAMEBUFFER, mRenderer.DecodeFramebuffer()); glViewport(0, 0, inputFrameWidth, inputFrameHeight); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); } std::vector& layerPrograms = mRenderer.LayerPrograms(); if (layerStates.empty() || layerPrograms.empty()) { glBindFramebuffer(GL_READ_FRAMEBUFFER, mRenderer.DecodeFramebuffer()); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mRenderer.CompositeFramebuffer()); glBlitFramebuffer(0, 0, inputFrameWidth, inputFrameHeight, 0, 0, inputFrameWidth, inputFrameHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR); glBindFramebuffer(GL_FRAMEBUFFER, mRenderer.CompositeFramebuffer()); } else { GLuint sourceTexture = mRenderer.DecodedTexture(); GLuint sourceFrameBuffer = mRenderer.DecodeFramebuffer(); for (std::size_t index = 0; index < layerStates.size() && index < layerPrograms.size(); ++index) { const std::size_t remaining = layerStates.size() - index; const bool writeToMain = (remaining % 2) == 1; RenderShaderProgram( sourceTexture, writeToMain ? mRenderer.CompositeFramebuffer() : mRenderer.LayerTempFramebuffer(), layerPrograms[index], layerStates[index], inputFrameWidth, inputFrameHeight, historyCap, updateTextBinding, updateGlobalParams); if (layerStates[index].temporalHistorySource == TemporalHistorySource::PreLayerInput) mRenderer.TemporalHistory().PushPreLayerFramebuffer(layerStates[index].layerId, sourceFrameBuffer, inputFrameWidth, inputFrameHeight); sourceTexture = writeToMain ? mRenderer.CompositeTexture() : mRenderer.LayerTempTexture(); sourceFrameBuffer = writeToMain ? mRenderer.CompositeFramebuffer() : mRenderer.LayerTempFramebuffer(); } } mRenderer.TemporalHistory().PushSourceFramebuffer(mRenderer.DecodeFramebuffer(), inputFrameWidth, inputFrameHeight); } void OpenGLRenderPass::RenderDecodePass(unsigned inputFrameWidth, unsigned inputFrameHeight, unsigned captureTextureWidth, VideoIOPixelFormat inputPixelFormat) { glBindFramebuffer(GL_FRAMEBUFFER, mRenderer.DecodeFramebuffer()); glViewport(0, 0, inputFrameWidth, inputFrameHeight); glClear(GL_COLOR_BUFFER_BIT); glActiveTexture(GL_TEXTURE0 + kPackedVideoTextureUnit); glBindTexture(GL_TEXTURE_2D, mRenderer.CaptureTexture()); glBindVertexArray(mRenderer.FullscreenVertexArray()); glUseProgram(mRenderer.DecodeProgram()); const GLint packedResolutionLocation = glGetUniformLocation(mRenderer.DecodeProgram(), "uPackedVideoResolution"); const GLint decodedResolutionLocation = glGetUniformLocation(mRenderer.DecodeProgram(), "uDecodedVideoResolution"); const GLint inputPixelFormatLocation = glGetUniformLocation(mRenderer.DecodeProgram(), "uInputPixelFormat"); if (packedResolutionLocation >= 0) glUniform2f(packedResolutionLocation, static_cast(captureTextureWidth), static_cast(inputFrameHeight)); if (decodedResolutionLocation >= 0) glUniform2f(decodedResolutionLocation, static_cast(inputFrameWidth), static_cast(inputFrameHeight)); if (inputPixelFormatLocation >= 0) glUniform1i(inputPixelFormatLocation, inputPixelFormat == VideoIOPixelFormat::V210 ? 1 : 0); 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.TemporalHistory().BindSamplers(state, sourceTexture, historyCap); BindLayerTextureAssets(layerProgram); glBindVertexArray(mRenderer.FullscreenVertexArray()); glUseProgram(layerProgram.program); updateGlobalParams(state, mRenderer.TemporalHistory().SourceAvailableCount(), mRenderer.TemporalHistory().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); }