diff --git a/map/basic_tiling_render_policy.cpp b/map/basic_tiling_render_policy.cpp index ae2d17feae..9db519f524 100644 --- a/map/basic_tiling_render_policy.cpp +++ b/map/basic_tiling_render_policy.cpp @@ -89,12 +89,16 @@ void BasicTilingRenderPolicy::DrawFrame(shared_ptr const & e, Screen bool doForceUpdate = DoForceUpdate(); bool doIntersectInvalidRect = GetInvalidRect().IsIntersect(s.GlobalRect()); + bool doForceUpdateFromGenerator = m_CoverageGenerator->DoForceUpdate(); + if (doForceUpdate) m_CoverageGenerator->InvalidateTiles(GetInvalidRect(), scales::GetUpperWorldScale() + 1); if (!m_IsNavigating && (!IsAnimating())) m_CoverageGenerator->AddCoverScreenTask(s, - m_DoRecreateCoverage || (doForceUpdate && doIntersectInvalidRect)); + doForceUpdateFromGenerator + || m_DoRecreateCoverage + || (doForceUpdate && doIntersectInvalidRect)); SetForceUpdate(false); m_DoRecreateCoverage = false; @@ -144,6 +148,8 @@ void BasicTilingRenderPolicy::PauseBackgroundRendering() { m_TileRenderer->SetIsPaused(true); m_TileRenderer->CancelCommands(); + m_CoverageGenerator->SetIsPaused(true); + m_CoverageGenerator->CancelCommands(); if (m_QueuedRenderer) m_QueuedRenderer->SetPartialExecution(GetPlatform().CpuCores(), true); } @@ -151,6 +157,7 @@ void BasicTilingRenderPolicy::PauseBackgroundRendering() void BasicTilingRenderPolicy::ResumeBackgroundRendering() { m_TileRenderer->SetIsPaused(false); + m_CoverageGenerator->SetIsPaused(false); m_DoRecreateCoverage = true; if (m_QueuedRenderer) m_QueuedRenderer->SetPartialExecution(GetPlatform().CpuCores(), false); diff --git a/map/coverage_generator.cpp b/map/coverage_generator.cpp index f721683dc9..bb8422a952 100644 --- a/map/coverage_generator.cpp +++ b/map/coverage_generator.cpp @@ -30,7 +30,9 @@ CoverageGenerator::CoverageGenerator( m_glQueue(glQueue), m_skinName(skinName), m_fenceManager(2), - m_currentFenceID(-1) + m_currentFenceID(-1), + m_doForceUpdate(false), + m_isPaused(false) { g_coverageGeneratorDestroyed = false; @@ -151,7 +153,7 @@ void CoverageGenerator::AddCoverScreenTask(ScreenBase const & screen, bool doFor ++m_sequenceID; - m_queue.AddCommand(bind(&CoverageGenerator::CoverScreen, this, screen, m_sequenceID)); + m_queue.AddCommand(bind(&CoverageGenerator::CoverScreen, this, _1, screen, m_sequenceID)); } int CoverageGenerator::InsertBenchmarkFence() @@ -172,7 +174,9 @@ void CoverageGenerator::SignalBenchmarkFence() m_fenceManager.signalFence(m_currentFenceID); } -void CoverageGenerator::CoverScreen(ScreenBase const & screen, int sequenceID) +void CoverageGenerator::CoverScreen(core::CommandsQueue::Environment const & env, + ScreenBase const & screen, + int sequenceID) { if (sequenceID < m_sequenceID) return; @@ -188,13 +192,16 @@ void CoverageGenerator::CoverScreen(ScreenBase const & screen, int sequenceID) AddCheckEmptyModelTask(sequenceID); } - m_workCoverage->Cache(); + bool shouldSwap = !m_isPaused && m_workCoverage->Cache(env); + if (shouldSwap) { threads::MutexGuard g(m_mutex); swap(m_currentCoverage, m_workCoverage); } + m_doForceUpdate = !shouldSwap; + m_workCoverage->Clear(); m_windowHandle->invalidate(); @@ -206,10 +213,12 @@ void CoverageGenerator::AddMergeTileTask(Tiler::RectInfo const & rectInfo, if (g_coverageGeneratorDestroyed) return; - m_queue.AddCommand(bind(&CoverageGenerator::MergeTile, this, rectInfo, sequenceID)); + m_queue.AddCommand(bind(&CoverageGenerator::MergeTile, this, _1, rectInfo, sequenceID)); } -void CoverageGenerator::MergeTile(Tiler::RectInfo const & rectInfo, int sequenceID) +void CoverageGenerator::MergeTile(core::CommandsQueue::Environment const & env, + Tiler::RectInfo const & rectInfo, + int sequenceID) { if (sequenceID < m_sequenceID) { @@ -227,13 +236,16 @@ void CoverageGenerator::MergeTile(Tiler::RectInfo const & rectInfo, int sequence AddCheckEmptyModelTask(sequenceID); } - m_workCoverage->Cache(); + bool shouldSwap = !m_isPaused && m_workCoverage->Cache(env); + if (shouldSwap) { threads::MutexGuard g(m_mutex); swap(m_currentCoverage, m_workCoverage); } + m_doForceUpdate = !shouldSwap; + m_workCoverage->Clear(); m_windowHandle->invalidate(); @@ -302,3 +314,18 @@ string CoverageGenerator::GetCountryName(m2::PointD const & pt) const { return m_countryNameFn(pt); } + +void CoverageGenerator::CancelCommands() +{ + m_queue.CancelCommands(); +} + +void CoverageGenerator::SetIsPaused(bool flag) +{ + m_isPaused = flag; +} + +bool CoverageGenerator::DoForceUpdate() const +{ + return m_doForceUpdate; +} diff --git a/map/coverage_generator.hpp b/map/coverage_generator.hpp index 4b938f93f7..3f8263ffb9 100644 --- a/map/coverage_generator.hpp +++ b/map/coverage_generator.hpp @@ -66,6 +66,9 @@ private: FenceManager m_fenceManager; int m_currentFenceID; + bool m_doForceUpdate; + bool m_isPaused; + ScreenCoverage * CreateCoverage(); public: @@ -93,9 +96,16 @@ public: void AddCheckEmptyModelTask(int sequenceID); void AddFinishSequenceTask(int sequenceID); - void CoverScreen(ScreenBase const & screen, int sequenceID); - void MergeTile(Tiler::RectInfo const & rectInfo, int sequenceID); + void CoverScreen(core::CommandsQueue::Environment const & env, + ScreenBase const & screen, + int sequenceID); + + void MergeTile(core::CommandsQueue::Environment const & env, + Tiler::RectInfo const & rectInfo, + int sequenceID); + void CheckEmptyModel(int sequenceID); + void FinishSequence(int sequenceID); void Cancel(); @@ -110,9 +120,14 @@ public: void JoinBenchmarkFence(int fenceID); void SignalBenchmarkFence(); + bool DoForceUpdate() const; + void SetSequenceID(int sequenceID); threads::Mutex & Mutex(); shared_ptr const & resourceManager() const; + + void SetIsPaused(bool flag); + void CancelCommands(); }; diff --git a/map/screen_coverage.cpp b/map/screen_coverage.cpp index aae2112923..b383484664 100644 --- a/map/screen_coverage.cpp +++ b/map/screen_coverage.cpp @@ -10,6 +10,7 @@ #include "../yg/screen.hpp" #include "../yg/display_list.hpp" +#include "../yg/skin.hpp" #include "../yg/base_texture.hpp" #include "screen_coverage.hpp" @@ -154,13 +155,15 @@ void ScreenCoverage::Merge(Tiler::RectInfo const & ri) } } -void ScreenCoverage::Cache() +bool ScreenCoverage::Cache(core::CommandsQueue::Environment const & env) { /// caching tiles blitting commands. m_displayList.reset(); m_displayList.reset(m_cacheScreen->createDisplayList()); + m_cacheScreen->setEnvironment(&env); + m_cacheScreen->beginFrame(); m_cacheScreen->setDisplayList(m_displayList.get()); @@ -195,6 +198,12 @@ void ScreenCoverage::Cache() /// while recording of displayList(for example UnlockStorage) m_cacheScreen->completeCommands(); + + bool isCancelled = m_cacheScreen->isCancelled(); + + m_cacheScreen->setEnvironment(0); + + return !isCancelled; } void ScreenCoverage::SetScreen(ScreenBase const & screen) diff --git a/map/screen_coverage.hpp b/map/screen_coverage.hpp index a633956864..6076feafb5 100644 --- a/map/screen_coverage.hpp +++ b/map/screen_coverage.hpp @@ -113,7 +113,9 @@ public: /// Getter for Overlay shared_ptr const & GetOverlay() const; /// Cache coverage in display list - void Cache(); + /// @return true - if the coverage was cached successfully, + /// false - otherwise(p.e. the caching was cancelled) + bool Cache(core::CommandsQueue::Environment const & env); /// add rendered tile to coverage. Tile is locked, so make sure to unlock it in case it's not needed. void Merge(Tiler::RectInfo const & ri); /// recalculate screen coverage, using as much info from prev coverage as possible diff --git a/yg/geometry_batcher.cpp b/yg/geometry_batcher.cpp index 56e8b01998..e110ed8db3 100644 --- a/yg/geometry_batcher.cpp +++ b/yg/geometry_batcher.cpp @@ -274,6 +274,14 @@ namespace yg } } + /// is the rendering was cancelled, there possibly could + /// be "ghost" render styles which are present in internal + /// skin structures, but aren't rendered onto skin texture. + /// so we are clearing the whole skin, to ensure that they + /// are gone(slightly heavy, but very simple solution). + if (isCancelled()) + m_skin->clearHandles(); + base_t::endFrame(); } diff --git a/yg/geometry_renderer.cpp b/yg/geometry_renderer.cpp index 359c0117ac..ef1f661461 100644 --- a/yg/geometry_renderer.cpp +++ b/yg/geometry_renderer.cpp @@ -89,6 +89,9 @@ namespace yg shared_ptr const & texture, bool shouldAddCheckPoint) { + if (isCancelled()) + return; + vector > v; v.reserve(end - start); copy(&uploadQueue[0] + start, &uploadQueue[0] + end, back_inserter(v)); @@ -185,6 +188,9 @@ namespace yg size_t indicesOffs, unsigned primType) { + if (isCancelled()) + return; + shared_ptr command(new DrawGeometry()); command->m_texture = texture; diff --git a/yg/overlay.cpp b/yg/overlay.cpp index a80f56937a..e3eb6607a3 100644 --- a/yg/overlay.cpp +++ b/yg/overlay.cpp @@ -1,6 +1,7 @@ #include "../base/SRC_FIRST.hpp" #include "overlay.hpp" +#include "overlay_renderer.hpp" #include "text_element.hpp" #include "../base/logging.hpp" @@ -28,9 +29,17 @@ namespace yg return elem->roughBoundRect(); } + void DrawIfNotCancelled(gl::OverlayRenderer * r, + shared_ptr const & e, + math::Matrix const & m) + { + if (!r->isCancelled()) + e->draw(r, m); + } + void Overlay::draw(gl::OverlayRenderer * r, math::Matrix const & m) { - m_tree.ForEach(bind(&OverlayElement::draw, _1, r, cref(m))); + m_tree.ForEach(bind(&DrawIfNotCancelled, r, _1, cref(m))); } Overlay::Overlay() diff --git a/yg/renderer.cpp b/yg/renderer.cpp index d051f0b272..5392702c46 100644 --- a/yg/renderer.cpp +++ b/yg/renderer.cpp @@ -27,7 +27,8 @@ namespace yg m_isSynchronized(params.m_isSynchronized), m_isRendering(false), m_width(0), - m_height(0) + m_height(0), + m_env(0) { m_frameBuffer = params.m_frameBuffer; m_resourceManager = params.m_resourceManager; @@ -287,5 +288,18 @@ namespace yg if (m_renderQueue) m_renderQueue->completeCommands(); } + + void Renderer::setEnvironment(core::CommandsQueue::Environment const * env) + { + m_env = env; + } + + bool Renderer::isCancelled() const + { + if (m_env) + return m_env->isCancelled(); + else + return false; + } } } diff --git a/yg/renderer.hpp b/yg/renderer.hpp index 3b83a438e0..1cf7571a62 100644 --- a/yg/renderer.hpp +++ b/yg/renderer.hpp @@ -5,6 +5,7 @@ #include "resource_manager.hpp" #include "../base/threaded_list.hpp" +#include "../base/commands_queue.hpp" #include "../std/function.hpp" #include "../std/shared_ptr.hpp" #include "../geometry/rect2d.hpp" @@ -102,6 +103,8 @@ namespace yg unsigned int m_width; unsigned int m_height; + core::CommandsQueue::Environment const * m_env; + public: static const yg::Color s_bgColor; @@ -151,6 +154,9 @@ namespace yg void addFramePoint(); void completeCommands(); + + void setEnvironment(core::CommandsQueue::Environment const * env); + bool isCancelled() const; }; } } diff --git a/yg/skin.cpp b/yg/skin.cpp index 03be663434..106914a2b5 100644 --- a/yg/skin.cpp +++ b/yg/skin.cpp @@ -354,6 +354,12 @@ namespace yg m_additionalPages[0]->setPipelineID(0 + m_pages.size()); } + void Skin::clearHandles() + { + for (unsigned i = 0; i < m_pages.size(); ++i) + m_pages[i]->clear(); + } + void Skin::clearAdditionalPage() { m_additionalPages.clear(); diff --git a/yg/skin.hpp b/yg/skin.hpp index 193e28760b..c0297cfed2 100644 --- a/yg/skin.hpp +++ b/yg/skin.hpp @@ -57,8 +57,6 @@ namespace yg bool m_fillAlpha; - void clearHandles(); - Skin(shared_ptr const & resourceManager, TSkinPages const & pages); @@ -141,6 +139,8 @@ namespace yg void setAdditionalPage(shared_ptr const & pages); void clearAdditionalPage(); + void clearHandles(); + void memoryWarning(); void enterBackground(); void enterForeground();