#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 { const std::vector passes = BuildLayerPassDescriptors(layerStates, layerPrograms); for (const RenderPassDescriptor& pass : passes) { RenderLayerPass( pass, inputFrameWidth, inputFrameHeight, historyCap, updateTextBinding, updateGlobalParams); } } 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); } std::vector OpenGLRenderPass::BuildLayerPassDescriptors( const std::vector& layerStates, std::vector& layerPrograms) const { std::vector passes; const std::size_t passCount = layerStates.size() < layerPrograms.size() ? layerStates.size() : layerPrograms.size(); passes.reserve(passCount); GLuint sourceTexture = mRenderer.DecodedTexture(); GLuint sourceFramebuffer = mRenderer.DecodeFramebuffer(); for (std::size_t index = 0; index < passCount; ++index) { const RuntimeRenderState& state = layerStates[index]; LayerProgram& layerProgram = layerPrograms[index]; const std::size_t remaining = layerStates.size() - index; const bool writeToMain = (remaining % 2) == 1; RenderPassDescriptor pass; pass.kind = RenderPassKind::LayerEffect; pass.outputTarget = writeToMain ? RenderPassOutputTarget::Composite : RenderPassOutputTarget::LayerTemp; pass.passIndex = index; pass.passId = state.layerId; pass.layerId = state.layerId; pass.shaderId = state.shaderId; pass.sourceTexture = sourceTexture; pass.sourceFramebuffer = sourceFramebuffer; pass.destinationFramebuffer = writeToMain ? mRenderer.CompositeFramebuffer() : mRenderer.LayerTempFramebuffer(); pass.layerProgram = &layerProgram; pass.layerState = &state; pass.capturePreLayerHistory = state.temporalHistorySource == TemporalHistorySource::PreLayerInput; passes.push_back(pass); sourceTexture = writeToMain ? mRenderer.CompositeTexture() : mRenderer.LayerTempTexture(); sourceFramebuffer = writeToMain ? mRenderer.CompositeFramebuffer() : mRenderer.LayerTempFramebuffer(); } return passes; } void OpenGLRenderPass::RenderLayerPass( const RenderPassDescriptor& pass, unsigned inputFrameWidth, unsigned inputFrameHeight, unsigned historyCap, const TextBindingUpdater& updateTextBinding, const GlobalParamsUpdater& updateGlobalParams) { if (pass.layerProgram == nullptr || pass.layerState == nullptr) return; RenderShaderProgram( pass.sourceTexture, pass.destinationFramebuffer, *pass.layerProgram, *pass.layerState, inputFrameWidth, inputFrameHeight, historyCap, updateTextBinding, updateGlobalParams); if (pass.capturePreLayerHistory) mRenderer.TemporalHistory().PushPreLayerFramebuffer(pass.layerId, pass.sourceFramebuffer, inputFrameWidth, inputFrameHeight); } 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); const std::vector sourceHistoryTextures = mRenderer.TemporalHistory().ResolveSourceHistoryTextures(sourceTexture, state.isTemporal ? historyCap : 0); const std::vector temporalHistoryTextures = mRenderer.TemporalHistory().ResolveTemporalHistoryTextures(state, sourceTexture, state.isTemporal ? historyCap : 0); const ShaderTextureBindings::RuntimeTextureBindingPlan texturePlan = mTextureBindings.BuildLayerRuntimeBindingPlan(layerProgram, sourceTexture, sourceHistoryTextures, temporalHistoryTextures); mTextureBindings.BindRuntimeTexturePlan(texturePlan); 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); mTextureBindings.UnbindRuntimeTexturePlan(texturePlan); }