diff --git a/drape_frontend/backend_renderer.cpp b/drape_frontend/backend_renderer.cpp index 6b93dac786333..9b464d038e17f 100644 --- a/drape_frontend/backend_renderer.cpp +++ b/drape_frontend/backend_renderer.cpp @@ -138,10 +138,15 @@ BackendRenderer::Routine::Routine(BackendRenderer & renderer) : m_renderer(rende void BackendRenderer::Routine::Do() { m_renderer.m_contextFactory->getResourcesUploadContext()->makeCurrent(); + GLFunctions::Init(); + m_renderer.InitGLDependentResource(); while (!IsCancelled()) + { m_renderer.ProcessSingleMessage(); + m_renderer.CheckRenderingEnabled(); + } m_renderer.ReleaseResources(); } diff --git a/drape_frontend/backend_renderer.hpp b/drape_frontend/backend_renderer.hpp index eb4ce96e0132f..9fb483ac8b4d1 100644 --- a/drape_frontend/backend_renderer.hpp +++ b/drape_frontend/backend_renderer.hpp @@ -1,6 +1,6 @@ #pragma once -#include "drape_frontend/message_acceptor.hpp" +#include "drape_frontend/base_renderer.hpp" #include "drape_frontend/engine_context.hpp" #include "drape_frontend/viewport.hpp" #include "drape_frontend/map_data_provider.hpp" @@ -26,7 +26,7 @@ class ThreadsCommutator; class BatchersPool; class ReadManager; -class BackendRenderer : public MessageAcceptor +class BackendRenderer : public BaseRenderer { public: BackendRenderer(dp::RefPointer commutator, diff --git a/drape_frontend/base_renderer.cpp b/drape_frontend/base_renderer.cpp new file mode 100644 index 0000000000000..826e60ae6f45d --- /dev/null +++ b/drape_frontend/base_renderer.cpp @@ -0,0 +1,65 @@ +#include "base_renderer.hpp" +#include "../std/utility.hpp" + +namespace df +{ + +BaseRenderer::BaseRenderer() + : m_isEnabled(true) + , m_renderingEnablingCompletionHandler(nullptr) + , m_wasNotified(false) +{ +} + +void BaseRenderer::SetRenderingEnabled(bool const isEnabled, completion_handler_t completionHandler) +{ + if (isEnabled == m_isEnabled) + { + if (completionHandler != nullptr) completionHandler(); + return; + } + + m_renderingEnablingCompletionHandler = move(completionHandler); + if (isEnabled) + { + // wake up rendering thread + unique_lock lock(m_renderingEnablingMutex); + m_wasNotified = true; + m_renderingEnablingCondition.notify_one(); + } + else + { + // here we set up value only if rendering disabled + m_isEnabled = false; + + // if renderer thread is waiting for message let it go + CancelMessageWaiting(); + } +} + +void BaseRenderer::CheckRenderingEnabled() +{ + if (!m_isEnabled) + { + // nofity initiator-thread about rendering disabling + if (m_renderingEnablingCompletionHandler != nullptr) + m_renderingEnablingCompletionHandler(); + + // wait for signal + unique_lock lock(m_renderingEnablingMutex); + while(!m_wasNotified) + { + m_renderingEnablingCondition.wait(lock); + } + + // here rendering is enabled again + m_wasNotified = false; + m_isEnabled = true; + + // nofity initiator-thread about rendering enabling + if (m_renderingEnablingCompletionHandler != nullptr) + m_renderingEnablingCompletionHandler(); + } +} + +} // namespace df diff --git a/drape_frontend/base_renderer.hpp b/drape_frontend/base_renderer.hpp new file mode 100644 index 0000000000000..3c5735b31c333 --- /dev/null +++ b/drape_frontend/base_renderer.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include "message_acceptor.hpp" +#include "../std/condition_variable.hpp" +#include "../std/mutex.hpp" +#include "../std/atomic.hpp" +#include "../std/function.hpp" + +namespace df +{ + +class BaseRenderer : public MessageAcceptor +{ +public: + using completion_handler_t = function; + + BaseRenderer(); + + void SetRenderingEnabled(bool const isEnabled, completion_handler_t completionHandler); + +protected: + void CheckRenderingEnabled(); + +private: + mutex m_renderingEnablingMutex; + condition_variable m_renderingEnablingCondition; + atomic m_isEnabled; + completion_handler_t m_renderingEnablingCompletionHandler; + bool m_wasNotified; +}; + +} // namespace df diff --git a/drape_frontend/drape_engine.cpp b/drape_frontend/drape_engine.cpp index fae3ef30fc602..b3c9fb13ff77b 100644 --- a/drape_frontend/drape_engine.cpp +++ b/drape_frontend/drape_engine.cpp @@ -8,6 +8,8 @@ #include "drape/texture_manager.hpp" #include "std/bind.hpp" +#include "std/condition_variable.hpp" +#include "std/mutex.hpp" namespace df { @@ -94,8 +96,32 @@ void DrapeEngine::UpdateUserMarksLayer(TileKey const & tileKey, UserMarksProvide void DrapeEngine::SetRenderingEnabled(bool const isEnabled) { - m_threadCommutator->PostMessageBroadcast(dp::MovePointer(new RenderingEnabledMessage(isEnabled)), - MessagePriority::High); + SetRenderingEnabled(m_frontend.GetRefPointer(), isEnabled); + SetRenderingEnabled(m_backend.GetRefPointer(), isEnabled); + + LOG(LDEBUG, (isEnabled ? "Rendering enabled" : "Rendering disabled")); +} + +void DrapeEngine::SetRenderingEnabled(dp::RefPointer renderer, bool const isEnabled) +{ + // here we have to wait for finishing of message processing + mutex completionMutex; + condition_variable completionCondition; + bool notified = false; + auto completionHandler = [&]() + { + unique_lock lock(completionMutex); + notified = true; + completionCondition.notify_one(); + }; + + renderer->SetRenderingEnabled(isEnabled, completionHandler); + + unique_lock lock(completionMutex); + while (!notified) // loop to avoid spurious wakeups + { + completionCondition.wait(lock); + } } } // namespace df diff --git a/drape_frontend/drape_engine.hpp b/drape_frontend/drape_engine.hpp index e38eba25ac04a..da073391e1086 100644 --- a/drape_frontend/drape_engine.hpp +++ b/drape_frontend/drape_engine.hpp @@ -43,6 +43,8 @@ class DrapeEngine dp::MasterPointer m_textureManager; Viewport m_viewport; + + void SetRenderingEnabled(dp::RefPointer renderer, bool const isEnabled); }; } // namespace df diff --git a/drape_frontend/drape_frontend.pro b/drape_frontend/drape_frontend.pro index 184d22dc3e2f9..19d67350f6181 100644 --- a/drape_frontend/drape_frontend.pro +++ b/drape_frontend/drape_frontend.pro @@ -39,6 +39,7 @@ SOURCES += \ map_data_provider.cpp \ user_mark_shapes.cpp \ user_marks_provider.cpp \ + base_renderer.cpp HEADERS += \ engine_context.hpp \ @@ -76,3 +77,4 @@ HEADERS += \ map_data_provider.hpp \ user_mark_shapes.hpp \ user_marks_provider.hpp \ + base_renderer.hpp diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index d73e350d86c8f..2937ae539f82c 100644 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -41,7 +41,6 @@ FrontendRenderer::FrontendRenderer(dp::RefPointer commutator, , m_textureManager(textureManager) , m_gpuProgramManager(new dp::GpuProgramManager()) , m_viewport(viewport) - , m_isEnabled(true) { #ifdef DRAW_INFO m_tpf = 0,0; @@ -446,6 +445,8 @@ void FrontendRenderer::Routine::Do() context->present(); timer.Reset(); + + CheckRenderingEnabled(); } m_renderer.ReleaseResources(); diff --git a/drape_frontend/frontend_renderer.hpp b/drape_frontend/frontend_renderer.hpp index b8ee8b6c3732f..27b59eee55b90 100644 --- a/drape_frontend/frontend_renderer.hpp +++ b/drape_frontend/frontend_renderer.hpp @@ -3,12 +3,12 @@ #include "base/thread.hpp" #ifdef DRAW_INFO - #include "../base/timer.hpp" - #include "../std/vector.hpp" - #include "../std/numeric.hpp" + #include "base/timer.hpp" + #include "std/vector.hpp" + #include "std/numeric.hpp" #endif -#include "drape_frontend/message_acceptor.hpp" +#include "drape_frontend/base_renderer.hpp" #include "drape_frontend/threads_commutator.hpp" #include "drape_frontend/tile_info.hpp" #include "drape_frontend/backend_renderer.hpp" @@ -33,7 +33,10 @@ namespace dp { class RenderBucket; } namespace df { -class FrontendRenderer : public MessageAcceptor +struct RenderingEnablingContext; + + +class FrontendRenderer : public BaseRenderer { public: FrontendRenderer(dp::RefPointer commutator, @@ -112,8 +115,6 @@ class FrontendRenderer : public MessageAcceptor set m_tiles; dp::OverlayTree m_overlayTree; - - bool m_isEnabled; }; } // namespace df diff --git a/drape_frontend/message_acceptor.cpp b/drape_frontend/message_acceptor.cpp index b70b4d6b60dee..2f78106a8994a 100644 --- a/drape_frontend/message_acceptor.cpp +++ b/drape_frontend/message_acceptor.cpp @@ -27,4 +27,9 @@ void MessageAcceptor::CloseQueue() m_messageQueue.ClearQuery(); } +void MessageAcceptor::CancelMessageWaiting() +{ + m_messageQueue.CancelWait(); +} + } // namespace df diff --git a/drape_frontend/message_acceptor.hpp b/drape_frontend/message_acceptor.hpp index 44fca73a147e0..f5e2fbf8a564d 100644 --- a/drape_frontend/message_acceptor.hpp +++ b/drape_frontend/message_acceptor.hpp @@ -15,10 +15,15 @@ class MessageAcceptor virtual ~MessageAcceptor() {} protected: + virtual ~MessageAcceptor(){} + virtual void AcceptMessage(dp::RefPointer message) = 0; /// Must be called by subclass on message target thread void ProcessSingleMessage(unsigned maxTimeWait = -1); + + void CancelMessageWaiting(); + void CloseQueue(); private: diff --git a/drape_frontend/message_queue.hpp b/drape_frontend/message_queue.hpp index edf2485c3bc0f..b902469cbfe06 100644 --- a/drape_frontend/message_queue.hpp +++ b/drape_frontend/message_queue.hpp @@ -16,7 +16,7 @@ class MessageQueue public: ~MessageQueue(); - /// if queue is empty than return NULL + /// if queue is empty then return NULL dp::TransferPointer PopMessage(unsigned maxTimeWait); void PushMessage(dp::TransferPointer message, MessagePriority priority); void CancelWait(); diff --git a/drape_frontend/message_subclasses.hpp b/drape_frontend/message_subclasses.hpp index 71469e0c9b3c5..bc850d4c60767 100644 --- a/drape_frontend/message_subclasses.hpp +++ b/drape_frontend/message_subclasses.hpp @@ -10,13 +10,13 @@ #include "geometry/rect2d.hpp" #include "geometry/screenbase.hpp" - #include "drape/glstate.hpp" #include "drape/pointers.hpp" #include "drape/render_bucket.hpp" #include "std/shared_ptr.hpp" #include "std/set.hpp" +#include "std/function.hpp" namespace df { @@ -237,18 +237,4 @@ class GuiLayerRecachedMessage : public Message dp::TransferPointer m_renderer; }; -class RenderingEnabledMessage : public Message -{ -public: - RenderingEnabledMessage(bool const isEnabled) - : m_isEnabled(isEnabled) {} - - Type GetType() const override { return Message::RenderingEnabled; } - - bool isSuspended() const { return m_isEnabled; } - -private: - bool m_isEnabled; -}; - } // namespace df diff --git a/drape_frontend/threads_commutator.cpp b/drape_frontend/threads_commutator.cpp index d1f55e1f32b51..c365031eb8c0d 100644 --- a/drape_frontend/threads_commutator.cpp +++ b/drape_frontend/threads_commutator.cpp @@ -20,13 +20,5 @@ void ThreadsCommutator::PostMessage(ThreadName name, dp::TransferPointersecond->PostMessage(message, priority); } -void ThreadsCommutator::PostMessageBroadcast(dp::TransferPointer message, MessagePriority priority) -{ - for (auto it = m_acceptors.cbegin(); it != m_acceptors.cend(); ++it) - { - it->second->PostMessage(message, priority); - } -} - } // namespace df diff --git a/drape_frontend/threads_commutator.hpp b/drape_frontend/threads_commutator.hpp index f792603655b1a..be8ddaf9a9f79 100644 --- a/drape_frontend/threads_commutator.hpp +++ b/drape_frontend/threads_commutator.hpp @@ -21,7 +21,6 @@ class ThreadsCommutator void RegisterThread(ThreadName name, MessageAcceptor *acceptor); void PostMessage(ThreadName name, dp::TransferPointer message, MessagePriority priority); - void PostMessageBroadcast(dp::TransferPointer message, MessagePriority priority); private: typedef map acceptors_map_t; diff --git a/map/framework.cpp b/map/framework.cpp index f50fc878d66b2..fd9254351d8e6 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -897,11 +897,16 @@ void Framework::EnterBackground() #ifndef OMIM_OS_ANDROID ClearAllCaches(); #endif + if (!m_drapeEngine.IsNull()) + m_drapeEngine->SetRenderingEnabled(false); } void Framework::EnterForeground() { m_startForegroundTime = my::Timer::LocalTime(); + + if (!m_drapeEngine.IsNull()) + m_drapeEngine->SetRenderingEnabled(true); } void Framework::ShowAll()