diff --git a/drape_frontend/animation/interpolation_holder.cpp b/drape_frontend/animation/interpolation_holder.cpp index 95a8533ed0..f4c4dfae13 100644 --- a/drape_frontend/animation/interpolation_holder.cpp +++ b/drape_frontend/animation/interpolation_holder.cpp @@ -3,22 +3,22 @@ #include "base/assert.hpp" -#include "std/algorithm.hpp" -#include "std/bind.hpp" - namespace df { - InterpolationHolder & InterpolationHolder::Instance() { static InterpolationHolder holder; return holder; } -bool InterpolationHolder::Advance(double elapsedSeconds) +bool InterpolationHolder::IsActive() const { - bool hasAnimations = !m_interpolations.empty(); - TInterpolatorSet::iterator iter = m_interpolations.begin(); + return !m_interpolations.empty(); +} + +void InterpolationHolder::Advance(double elapsedSeconds) +{ + auto iter = m_interpolations.begin(); while (iter != m_interpolations.end()) { (*iter)->Advance(elapsedSeconds); @@ -27,8 +27,6 @@ bool InterpolationHolder::Advance(double elapsedSeconds) else ++iter; } - - return hasAnimations; } InterpolationHolder::~InterpolationHolder() @@ -45,5 +43,4 @@ void InterpolationHolder::DeregisterInterpolator(BaseInterpolator * interpolator { m_interpolations.erase(interpolator); } - -} +} // namespace df diff --git a/drape_frontend/animation/interpolation_holder.hpp b/drape_frontend/animation/interpolation_holder.hpp index 0b113e791d..cf2c197379 100644 --- a/drape_frontend/animation/interpolation_holder.hpp +++ b/drape_frontend/animation/interpolation_holder.hpp @@ -2,17 +2,18 @@ #include "base/macros.hpp" -#include "std/set.hpp" +#include namespace df { - class BaseInterpolator; + class InterpolationHolder { public: static InterpolationHolder & Instance(); - bool Advance(double elapsedSeconds); + bool IsActive() const; + void Advance(double elapsedSeconds); private: InterpolationHolder() = default; @@ -24,8 +25,7 @@ private: void RegisterInterpolator(BaseInterpolator * interpolator); void DeregisterInterpolator(BaseInterpolator * interpolator); - using TInterpolatorSet = set; + using TInterpolatorSet = std::set; TInterpolatorSet m_interpolations; }; - -} +} // namespace df diff --git a/drape_frontend/animation_system.cpp b/drape_frontend/animation_system.cpp index 70106f3b9e..b1c97231b5 100644 --- a/drape_frontend/animation_system.cpp +++ b/drape_frontend/animation_system.cpp @@ -156,6 +156,17 @@ bool AnimationSystem::HasAnimations() const return !m_animationChain.empty(); } +bool AnimationSystem::HasOnlyArrowAnimations() const +{ + if (AnimationExists(Animation::Object::MapPlane)) + return false; + + if (AnimationExists(Animation::Object::Selection)) + return false; + + return true; +} + AnimationSystem & AnimationSystem::Instance() { static AnimationSystem animSystem; @@ -346,10 +357,10 @@ void AnimationSystem::FinishObjectAnimations(Animation::Object object, bool rewi rewind, finishAll); } -bool AnimationSystem::Advance(double elapsedSeconds) +void AnimationSystem::Advance(double elapsedSeconds) { - if (m_animationChain.empty()) - return false; + if (!HasAnimations()) + return; TAnimationList finishedAnimations; TAnimationList & frontList = *(m_animationChain.front()); @@ -373,8 +384,6 @@ bool AnimationSystem::Advance(double elapsedSeconds) } if (frontList.empty()) StartNextAnimations(); - - return true; } #ifdef DEBUG_ANIMATIONS diff --git a/drape_frontend/animation_system.hpp b/drape_frontend/animation_system.hpp index 7247e60040..a7d42e857a 100644 --- a/drape_frontend/animation_system.hpp +++ b/drape_frontend/animation_system.hpp @@ -33,6 +33,7 @@ public: bool AnimationExists(Animation::Object object) const; bool HasAnimations() const; + bool HasOnlyArrowAnimations() const; void CombineAnimation(drape_ptr && animation); void PushAnimation(drape_ptr && animation); @@ -60,7 +61,7 @@ public: return nullptr; } - bool Advance(double elapsedSeconds); + void Advance(double elapsedSeconds); ScreenBase const & GetLastScreen() { return m_lastScreen; } void SaveAnimationResult(Animation const & animation); diff --git a/drape_frontend/drape_notifier.cpp b/drape_frontend/drape_notifier.cpp index 3af746dc32..2973ac2403 100644 --- a/drape_frontend/drape_notifier.cpp +++ b/drape_frontend/drape_notifier.cpp @@ -27,7 +27,7 @@ void DrapeNotifier::NotifyImpl(ThreadsCommutator::ThreadName threadName, [this, threadName, duration, repeating, notifyId, functor = std::move(functor)]() mutable { m_commutator->PostMessage(threadName, - make_unique_dp(std::move(functor), notifyId), + make_unique_dp(functor, notifyId), MessagePriority::Normal); if (repeating) NotifyImpl(threadName, duration, repeating, notifyId, std::move(functor)); diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index 43cd71ee38..66bd726fbb 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -1007,8 +1007,8 @@ void FrontendRenderer::OnResize(ScreenBase const & screen) m_myPositionController->OnUpdateScreen(screen); - uint32_t const sx = static_cast(viewportRect.SizeX()); - uint32_t const sy = static_cast(viewportRect.SizeY()); + auto const sx = static_cast(viewportRect.SizeX()); + auto const sy = static_cast(viewportRect.SizeY()); if (viewportChanged) { @@ -1197,104 +1197,104 @@ void FrontendRenderer::EndUpdateOverlayTree() } } -void FrontendRenderer::RenderScene(ScreenBase const & modelView) +void FrontendRenderer::RenderScene(ScreenBase const & modelView, bool activeFrame) { #if defined(DRAPE_MEASURER) && (defined(RENDER_STATISTIC) || defined(TRACK_GPU_MEM)) DrapeMeasurer::Instance().BeforeRenderFrame(); #endif - m_postprocessRenderer->BeginFrame(); - - GLFunctions::glEnable(gl_const::GLDepthTest); - m_viewport.Apply(); - RefreshBgColor(); - GLFunctions::glClear(gl_const::GLColorBit | gl_const::GLDepthBit | gl_const::GLStencilBit); - - Render2dLayer(modelView); - RenderUserMarksLayer(modelView, RenderState::UserLineLayer); - - if (m_buildingsFramebuffer->IsSupported()) + if (m_postprocessRenderer->BeginFrame(activeFrame)) { - RenderTrafficLayer(modelView); - if (!HasTransitRouteData()) + GLFunctions::glEnable(gl_const::GLDepthTest); + m_viewport.Apply(); + RefreshBgColor(); + GLFunctions::glClear(gl_const::GLColorBit | gl_const::GLDepthBit | gl_const::GLStencilBit); + + Render2dLayer(modelView); + RenderUserMarksLayer(modelView, RenderState::UserLineLayer); + + if (m_buildingsFramebuffer->IsSupported()) + { + RenderTrafficLayer(modelView); + if (!HasTransitRouteData()) + RenderRouteLayer(modelView); + Render3dLayer(modelView, true /* useFramebuffer */); + } + else + { + Render3dLayer(modelView, false /* useFramebuffer */); + RenderTrafficLayer(modelView); + if (!HasTransitRouteData()) + RenderRouteLayer(modelView); + } + + GLFunctions::glDisable(gl_const::GLDepthTest); + GLFunctions::glClear(gl_const::GLDepthBit); + + if (m_selectionShape != nullptr) + { + SelectionShape::ESelectedObject selectedObject = m_selectionShape->GetSelectedObject(); + if (selectedObject == SelectionShape::OBJECT_MY_POSITION) + { + ASSERT(m_myPositionController->IsModeHasPosition(), ()); + m_selectionShape->SetPosition(m_myPositionController->Position()); + m_selectionShape->Render(modelView, m_currentZoomLevel, make_ref(m_gpuProgramManager), + m_frameValues); + } + else if (selectedObject == SelectionShape::OBJECT_POI) + { + m_selectionShape->Render(modelView, m_currentZoomLevel, make_ref(m_gpuProgramManager), + m_frameValues); + } + } + + { + StencilWriterGuard guard(make_ref(m_postprocessRenderer)); + RenderOverlayLayer(modelView); + RenderUserMarksLayer(modelView, RenderState::LocalAdsMarkLayer); + } + + m_gpsTrackRenderer->RenderTrack(modelView, m_currentZoomLevel, make_ref(m_gpuProgramManager), + m_frameValues); + + if (m_selectionShape != nullptr && + m_selectionShape->GetSelectedObject() == SelectionShape::OBJECT_USER_MARK) + { + m_selectionShape->Render(modelView, m_currentZoomLevel, make_ref(m_gpuProgramManager), + m_frameValues); + } + + if (HasTransitRouteData()) RenderRouteLayer(modelView); - Render3dLayer(modelView, true /* useFramebuffer */); - } - else - { - Render3dLayer(modelView, false /* useFramebuffer */); - RenderTrafficLayer(modelView); + + { + StencilWriterGuard guard(make_ref(m_postprocessRenderer)); + RenderUserMarksLayer(modelView, RenderState::UserMarkLayer); + RenderUserMarksLayer(modelView, RenderState::TransitMarkLayer); + RenderUserMarksLayer(modelView, RenderState::RoutingMarkLayer); + RenderSearchMarksLayer(modelView); + } + if (!HasTransitRouteData()) - RenderRouteLayer(modelView); + RenderTransitSchemeLayer(modelView); + + m_drapeApiRenderer->Render(modelView, make_ref(m_gpuProgramManager), m_frameValues); + + for (auto const & arrow : m_overlayTree->GetDisplacementInfo()) + dp::DebugRectRenderer::Instance().DrawArrow(modelView, arrow); } + m_postprocessRenderer->EndFrame(make_ref(m_gpuProgramManager)); GLFunctions::glDisable(gl_const::GLDepthTest); - GLFunctions::glClear(gl_const::GLDepthBit); - - if (m_selectionShape != nullptr) - { - SelectionShape::ESelectedObject selectedObject = m_selectionShape->GetSelectedObject(); - if (selectedObject == SelectionShape::OBJECT_MY_POSITION) - { - ASSERT(m_myPositionController->IsModeHasPosition(), ()); - m_selectionShape->SetPosition(m_myPositionController->Position()); - m_selectionShape->Render(modelView, m_currentZoomLevel, make_ref(m_gpuProgramManager), - m_frameValues); - } - else if (selectedObject == SelectionShape::OBJECT_POI) - { - m_selectionShape->Render(modelView, m_currentZoomLevel, make_ref(m_gpuProgramManager), - m_frameValues); - } - } - - { - StencilWriterGuard guard(make_ref(m_postprocessRenderer)); - RenderOverlayLayer(modelView); - RenderUserMarksLayer(modelView, RenderState::LocalAdsMarkLayer); - } - - m_gpsTrackRenderer->RenderTrack(modelView, m_currentZoomLevel, make_ref(m_gpuProgramManager), - m_frameValues); - - if (m_selectionShape != nullptr && - m_selectionShape->GetSelectedObject() == SelectionShape::OBJECT_USER_MARK) - { - m_selectionShape->Render(modelView, m_currentZoomLevel, make_ref(m_gpuProgramManager), - m_frameValues); - } - - if (HasTransitRouteData()) - RenderRouteLayer(modelView); - - { - StencilWriterGuard guard(make_ref(m_postprocessRenderer)); - RenderUserMarksLayer(modelView, RenderState::UserMarkLayer); - RenderUserMarksLayer(modelView, RenderState::TransitMarkLayer); - RenderUserMarksLayer(modelView, RenderState::RoutingMarkLayer); - RenderSearchMarksLayer(modelView); - } - - if (!HasTransitRouteData()) - RenderTransitSchemeLayer(modelView); - m_myPositionController->Render(modelView, m_currentZoomLevel, make_ref(m_gpuProgramManager), m_frameValues); - m_drapeApiRenderer->Render(modelView, make_ref(m_gpuProgramManager), m_frameValues); - if (m_guiRenderer != nullptr) { - StencilWriterGuard guard(make_ref(m_postprocessRenderer)); m_guiRenderer->Render(make_ref(m_gpuProgramManager), m_myPositionController->IsInRouting(), modelView); } - for (auto const & arrow : m_overlayTree->GetDisplacementInfo()) - dp::DebugRectRenderer::Instance().DrawArrow(modelView, arrow); - - m_postprocessRenderer->EndFrame(make_ref(m_gpuProgramManager)); - #if defined(DRAPE_MEASURER) && (defined(RENDER_STATISTIC) || defined(TRACK_GPU_MEM)) DrapeMeasurer::Instance().AfterRenderFrame(); #endif @@ -1964,8 +1964,7 @@ void FrontendRenderer::OnContextCreate() // Resources recovering. m_screenQuadRenderer = make_unique_dp(); - m_postprocessRenderer->Init([context]() { context->setDefaultFramebuffer(); }); - m_postprocessRenderer->SetEnabled(m_apiVersion == dp::ApiVersion::OpenGLES3); + m_postprocessRenderer->Init(m_apiVersion, [context]() { context->setDefaultFramebuffer(); }); #ifndef OMIM_OS_IPHONE_SIMULATOR if (dp::SupportManager::Instance().IsAntialiasingEnabledByDefault()) m_postprocessRenderer->SetEffectEnabled(PostprocessRenderer::Antialiasing, true); @@ -1998,11 +1997,13 @@ void FrontendRenderer::Routine::Do() bool viewportChanged = true; bool invalidContext = false; uint32_t inactiveFramesCounter = 0; + uint32_t constexpr kMaxInactiveFrames = 2; dp::OGLContext * context = m_renderer.m_contextFactory->getDrawContext(); + auto & scaleFpsHelper = gui::DrapeGui::Instance().GetScaleFpsHelper(); #ifdef DEBUG - gui::DrapeGui::Instance().GetScaleFpsHelper().SetVisible(true); + scaleFpsHelper.SetVisible(true); #endif m_renderer.ScheduleOverlayCollecting(); @@ -2025,9 +2026,15 @@ void FrontendRenderer::Routine::Do() m_renderer.PrepareScene(modelView); isActiveFrame |= m_renderer.m_texMng->UpdateDynamicTextures(); + isActiveFrame |= m_renderer.m_userEventStream.IsWaitingForActionCompletion(); + isActiveFrame |= InterpolationHolder::Instance().IsActive(); + + bool isActiveFrameForScene = isActiveFrame || !AnimationSystem::Instance().HasOnlyArrowAnimations(); + isActiveFrame |= AnimationSystem::Instance().HasAnimations(); + m_renderer.m_routeRenderer->UpdatePreview(modelView); - m_renderer.RenderScene(modelView); + m_renderer.RenderScene(modelView, isActiveFrameForScene); auto const hasForceUpdate = m_renderer.m_forceUpdateScene || m_renderer.m_forceUpdateUserMarks; isActiveFrame |= hasForceUpdate; @@ -2035,9 +2042,8 @@ void FrontendRenderer::Routine::Do() if (modelViewChanged || hasForceUpdate) m_renderer.UpdateScene(modelView); - isActiveFrame |= InterpolationHolder::Instance().Advance(frameTime); - isActiveFrame |= AnimationSystem::Instance().Advance(frameTime); - isActiveFrame |= m_renderer.m_userEventStream.IsWaitingForActionCompletion(); + InterpolationHolder::Instance().Advance(frameTime); + AnimationSystem::Instance().Advance(frameTime); // On the first inactive frame we invalidate overlay tree. if (!isActiveFrame) @@ -2051,7 +2057,7 @@ void FrontendRenderer::Routine::Do() inactiveFramesCounter = 0; } - bool const canSuspend = inactiveFramesCounter > 2; + bool const canSuspend = inactiveFramesCounter > kMaxInactiveFrames; if (canSuspend) { // Process a message or wait for a message. @@ -2087,7 +2093,7 @@ void FrontendRenderer::Routine::Do() } frameTime = timer.ElapsedSeconds(); - gui::DrapeGui::Instance().GetScaleFpsHelper().SetFrameTime(frameTime, inactiveFramesCounter < 1); + scaleFpsHelper.SetFrameTime(frameTime, inactiveFramesCounter == 0); } else { @@ -2180,6 +2186,8 @@ ScreenBase const & FrontendRenderer::ProcessEvents(bool & modelViewChanged, bool { ScreenBase const & modelView = m_userEventStream.ProcessEvents(modelViewChanged, viewportChanged); gui::DrapeGui::Instance().SetInUserAction(m_userEventStream.IsInUserAction()); + if (m_lastReadedModelView != modelView) + modelViewChanged = true; return modelView; } diff --git a/drape_frontend/frontend_renderer.hpp b/drape_frontend/frontend_renderer.hpp index 80b6f977f6..1ce744b79e 100755 --- a/drape_frontend/frontend_renderer.hpp +++ b/drape_frontend/frontend_renderer.hpp @@ -142,7 +142,7 @@ protected: private: void OnResize(ScreenBase const & screen); - void RenderScene(ScreenBase const & modelView); + void RenderScene(ScreenBase const & modelView, bool activeFrame); void PrepareBucket(dp::GLState const & state, drape_ptr & bucket); void MergeBuckets(); void RenderSingleGroup(ScreenBase const & modelView, ref_ptr group); diff --git a/drape_frontend/postprocess_renderer.cpp b/drape_frontend/postprocess_renderer.cpp index 5385391722..e8b149f50e 100644 --- a/drape_frontend/postprocess_renderer.cpp +++ b/drape_frontend/postprocess_renderer.cpp @@ -145,6 +145,39 @@ private: uint32_t m_blendingWeightTextureId = 0; }; +class DefaultScreenQuadContext : public RendererContext +{ +public: + gpu::Program GetGpuProgram() const override { return gpu::Program::ScreenQuad; } + + void PreRender(ref_ptr mng) override + { + auto prg = mng->GetProgram(GetGpuProgram()); + + BindTexture(m_textureId, prg, "u_colorTex", 0 /* slotIndex */, + gl_const::GLLinear, gl_const::GLClampToEdge); + + mng->GetParamsSetter()->Apply(prg, m_params); + + GLFunctions::glDisable(gl_const::GLDepthTest); + GLFunctions::glDisable(gl_const::GLBlending); + } + + void PostRender() override + { + GLFunctions::glBindTexture(0); + } + + void SetParams(uint32_t textureId) + { + m_textureId = textureId; + } + +private: + uint32_t m_textureId = 0; + gpu::ScreenQuadProgramParams m_params; +}; + void InitFramebuffer(drape_ptr & framebuffer, uint32_t width, uint32_t height) { if (framebuffer == nullptr) @@ -169,13 +202,15 @@ bool IsSupported(drape_ptr const & framebuffer) } // namespace PostprocessRenderer::PostprocessRenderer() - : m_isEnabled(false) - , m_effects(0) + : m_effects(0) , m_width(0) , m_height(0) + , m_isMainFramebufferRendered(false) + , m_isSmaaFramebufferRendered(false) , m_edgesRendererContext(make_unique_dp()) , m_bwRendererContext(make_unique_dp()) , m_smaaFinalRendererContext(make_unique_dp()) + , m_defaultScreenQuadContext(make_unique_dp()) , m_frameStarted(false) {} @@ -184,9 +219,10 @@ PostprocessRenderer::~PostprocessRenderer() ClearGLDependentResources(); } -void PostprocessRenderer::Init(dp::FramebufferFallback && fallback) +void PostprocessRenderer::Init(dp::ApiVersion apiVersion, dp::FramebufferFallback && fallback) { - m_screenQuadRenderer.reset(new ScreenQuadRenderer()); + m_apiVersion = apiVersion; + m_screenQuadRenderer = make_unique_dp(); m_framebufferFallback = std::move(fallback); ASSERT(m_framebufferFallback != nullptr, ()); } @@ -198,8 +234,11 @@ void PostprocessRenderer::ClearGLDependentResources() m_staticTextures.reset(); m_mainFramebuffer.reset(); + m_isMainFramebufferRendered = false; m_edgesFramebuffer.reset(); m_blendingWeightFramebuffer.reset(); + m_smaaFramebuffer.reset(); + m_isSmaaFramebufferRendered = false; } void PostprocessRenderer::Resize(uint32_t width, uint32_t height) @@ -215,34 +254,17 @@ void PostprocessRenderer::SetStaticTextures(drape_ptr m_staticTextures = std::move(textures); } -void PostprocessRenderer::SetEnabled(bool enabled) -{ - m_isEnabled = enabled; - if (m_isEnabled && m_width != 0 && m_height != 0) - UpdateFramebuffers(m_width, m_height); -} - bool PostprocessRenderer::IsEnabled() const { - if (!m_isEnabled || m_effects == 0 || m_staticTextures == nullptr) - return false; - - if (!IsSupported(m_mainFramebuffer)) - return false; - - if (IsEffectEnabled(Effect::Antialiasing) && - (!IsSupported(m_edgesFramebuffer) || !IsSupported(m_blendingWeightFramebuffer))) - { - return false; - } - - // Insert checking new effects here. - - return true; + return IsSupported(m_mainFramebuffer); } void PostprocessRenderer::SetEffectEnabled(Effect effect, bool enabled) { + // Do not support AA for OpenGLES 2.0. + if (m_apiVersion == dp::ApiVersion::OpenGLES2 && effect == Effect::Antialiasing) + return; + auto const oldValue = m_effects; auto const effectMask = static_cast(effect); m_effects = (m_effects & ~effectMask) | (enabled ? effectMask : 0); @@ -256,42 +278,53 @@ bool PostprocessRenderer::IsEffectEnabled(Effect effect) const return (m_effects & static_cast(effect)) > 0; } -void PostprocessRenderer::BeginFrame() +bool PostprocessRenderer::CanRenderAntialiasing() const +{ + if (!IsEffectEnabled(Effect::Antialiasing)) + return false; + + if (!IsSupported(m_edgesFramebuffer) || !IsSupported(m_blendingWeightFramebuffer) || + !IsSupported(m_smaaFramebuffer)) + { + return false; + } + + if (m_staticTextures == nullptr) + return false; + + return m_staticTextures->m_smaaSearchTexture != nullptr && + m_staticTextures->m_smaaAreaTexture != nullptr && + m_staticTextures->m_smaaAreaTexture->GetID() != 0 && + m_staticTextures->m_smaaSearchTexture->GetID() != 0; +} + +bool PostprocessRenderer::BeginFrame(bool activeFrame) { if (!IsEnabled()) { m_framebufferFallback(); - return; + return true; } - // Check if Subpixel Morphological Antialiasing (SMAA) is unavailable. - ASSERT(m_staticTextures != nullptr, ()); - if (m_staticTextures->m_smaaSearchTexture == nullptr || - m_staticTextures->m_smaaAreaTexture == nullptr || - m_staticTextures->m_smaaAreaTexture->GetID() == 0 || - m_staticTextures->m_smaaSearchTexture->GetID() == 0) - { - SetEffectEnabled(Effect::Antialiasing, false); - } + m_frameStarted = activeFrame || !m_isMainFramebufferRendered; + if (m_frameStarted) + m_mainFramebuffer->Enable(); - m_mainFramebuffer->Enable(); - m_frameStarted = true; + if (m_frameStarted && CanRenderAntialiasing()) + GLFunctions::glDisable(gl_const::GLStencilTest); - GLFunctions::glDisable(gl_const::GLStencilTest); + m_isMainFramebufferRendered = true; + return m_frameStarted; } void PostprocessRenderer::EndFrame(ref_ptr gpuProgramManager) { - if (!IsEnabled() || !m_frameStarted) + if (!IsEnabled()) return; - bool wasPostEffect = false; - // Subpixel Morphological Antialiasing (SMAA). - if (IsEffectEnabled(Effect::Antialiasing)) + if (m_frameStarted && CanRenderAntialiasing()) { - wasPostEffect = true; - ASSERT(m_staticTextures->m_smaaAreaTexture != nullptr, ()); ASSERT_GREATER(m_staticTextures->m_smaaAreaTexture->GetID(), 0, ()); @@ -335,29 +368,35 @@ void PostprocessRenderer::EndFrame(ref_ptr gpuProgramManage // SMAA final pass. GLFunctions::glDisable(gl_const::GLStencilTest); { - m_framebufferFallback(); + m_smaaFramebuffer->Enable(); + ASSERT(dynamic_cast(m_smaaFinalRendererContext.get()) != nullptr, ()); auto context = static_cast(m_smaaFinalRendererContext.get()); context->SetParams(m_mainFramebuffer->GetTextureId(), m_blendingWeightFramebuffer->GetTextureId(), m_width, m_height); m_screenQuadRenderer->Render(gpuProgramManager, make_ref(m_smaaFinalRendererContext)); + m_isSmaaFramebufferRendered = true; } } - if (!wasPostEffect) - { - m_framebufferFallback(); - GLFunctions::glClear(gl_const::GLColorBit); - m_screenQuadRenderer->RenderTexture(gpuProgramManager, m_mainFramebuffer->GetTextureId(), - 1.0f /* opacity */); - } + ref_ptr finalFramebuffer; + if (m_isSmaaFramebufferRendered) + finalFramebuffer = make_ref(m_smaaFramebuffer); + else + finalFramebuffer = make_ref(m_mainFramebuffer); + + m_framebufferFallback(); + ASSERT(dynamic_cast(m_defaultScreenQuadContext.get()) != nullptr, ()); + auto context = static_cast(m_defaultScreenQuadContext.get()); + context->SetParams(finalFramebuffer->GetTextureId()); + m_screenQuadRenderer->Render(gpuProgramManager, make_ref(m_defaultScreenQuadContext)); m_frameStarted = false; } void PostprocessRenderer::EnableWritingToStencil() const { - if (!m_frameStarted) + if (!m_frameStarted || !CanRenderAntialiasing()) return; GLFunctions::glEnable(gl_const::GLStencilTest); GLFunctions::glStencilFuncSeparate(gl_const::GLFrontAndBack, gl_const::GLAlways, 1, 1); @@ -367,7 +406,7 @@ void PostprocessRenderer::EnableWritingToStencil() const void PostprocessRenderer::DisableWritingToStencil() const { - if (!m_frameStarted) + if (!m_frameStarted || !CanRenderAntialiasing()) return; GLFunctions::glDisable(gl_const::GLStencilTest); } @@ -377,11 +416,10 @@ void PostprocessRenderer::UpdateFramebuffers(uint32_t width, uint32_t height) ASSERT_NOT_EQUAL(width, 0, ()); ASSERT_NOT_EQUAL(height, 0, ()); - if (m_effects != 0) - InitFramebuffer(m_mainFramebuffer, width, height); - else - m_mainFramebuffer.reset(); + InitFramebuffer(m_mainFramebuffer, width, height); + m_isMainFramebufferRendered = false; + m_isSmaaFramebufferRendered = false; if (IsEffectEnabled(Effect::Antialiasing)) { InitFramebuffer(m_edgesFramebuffer, gl_const::GLRedGreen, @@ -390,11 +428,13 @@ void PostprocessRenderer::UpdateFramebuffers(uint32_t width, uint32_t height) InitFramebuffer(m_blendingWeightFramebuffer, gl_const::GLRGBA, m_mainFramebuffer->GetDepthStencilRef(), width, height); + InitFramebuffer(m_smaaFramebuffer, width, height); } else { m_edgesFramebuffer.reset(); m_blendingWeightFramebuffer.reset(); + m_smaaFramebuffer.reset(); } } diff --git a/drape_frontend/postprocess_renderer.hpp b/drape_frontend/postprocess_renderer.hpp index d6f54ea9e8..e4b9d8dd30 100644 --- a/drape_frontend/postprocess_renderer.hpp +++ b/drape_frontend/postprocess_renderer.hpp @@ -1,5 +1,6 @@ #pragma once +#include "drape/drape_global.hpp" #include "drape/framebuffer.hpp" #include "drape/pointers.hpp" @@ -37,19 +38,18 @@ public: PostprocessRenderer(); ~PostprocessRenderer(); - void Init(dp::FramebufferFallback && fallback); + void Init(dp::ApiVersion apiVersion, dp::FramebufferFallback && fallback); void ClearGLDependentResources(); void Resize(uint32_t width, uint32_t height); void SetStaticTextures(drape_ptr && textures); - void SetEnabled(bool enabled); bool IsEnabled() const; void SetEffectEnabled(Effect effect, bool enabled); bool IsEffectEnabled(Effect effect) const; void OnFramebufferFallback(); - void BeginFrame(); + bool BeginFrame(bool activeFrame); void EndFrame(ref_ptr gpuProgramManager); void EnableWritingToStencil() const; @@ -57,8 +57,9 @@ public: private: void UpdateFramebuffers(uint32_t width, uint32_t height); + bool CanRenderAntialiasing() const; - bool m_isEnabled; + dp::ApiVersion m_apiVersion; uint32_t m_effects; drape_ptr m_screenQuadRenderer; @@ -68,12 +69,16 @@ private: uint32_t m_height; drape_ptr m_mainFramebuffer; + bool m_isMainFramebufferRendered; drape_ptr m_edgesFramebuffer; drape_ptr m_blendingWeightFramebuffer; + drape_ptr m_smaaFramebuffer; + bool m_isSmaaFramebufferRendered; drape_ptr m_edgesRendererContext; drape_ptr m_bwRendererContext; drape_ptr m_smaaFinalRendererContext; + drape_ptr m_defaultScreenQuadContext; bool m_frameStarted; };