diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index a6d19f7a77..46e655eb30 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -119,7 +119,10 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) program->Bind(); bucket->GetBuffer()->Build(program); if (!IsUserMarkLayer(key)) + { + CheckTileGenerations(key); m_tileTree->ProcessTile(key, GetCurrentZoomLevel(), state, move(bucket)); + } else { m_userMarkRenderGroups.emplace_back(make_unique_dp(state, key, move(bucket))); @@ -510,26 +513,42 @@ void FrontendRenderer::OnActivateTile(TileKey const & tileKey) void FrontendRenderer::OnRemoveTile(TileKey const & tileKey) { + auto removePredicate = [&tileKey](drape_ptr const & group) + { + return group->GetTileKey() == tileKey; + }; + RemoveRenderGroups(removePredicate); +} + +void FrontendRenderer::RemoveRenderGroups(TRenderGroupRemovePredicate const & predicate) +{ + ASSERT(predicate != nullptr, ()); m_overlayTree->ForceUpdate(); + for(auto const & group : m_renderGroups) { - if (group->GetTileKey() == tileKey) + if (predicate(group)) { group->DeleteLater(); group->Disappear(); } } - auto removePredicate = [&tileKey](drape_ptr const & group) - { - return group->GetTileKey() == tileKey; - }; m_deferredRenderGroups.erase(remove_if(m_deferredRenderGroups.begin(), m_deferredRenderGroups.end(), - removePredicate), + predicate), m_deferredRenderGroups.end()); } +void FrontendRenderer::CheckTileGenerations(TileKey const & tileKey) +{ + auto removePredicate = [&tileKey](drape_ptr const & group) + { + return group->GetTileKey() == tileKey && group->GetTileKey().m_generation < tileKey.m_generation; + }; + RemoveRenderGroups(removePredicate); +} + void FrontendRenderer::OnCompassTapped() { m_myPositionController->StopCompassFollow(); @@ -1054,23 +1073,11 @@ void FrontendRenderer::UpdateScene(ScreenBase const & modelView) TTilesCollection tiles; ResolveTileKeys(modelView, tiles); - m_overlayTree->ForceUpdate(); auto removePredicate = [this](drape_ptr const & group) { return group->IsOverlay() && group->GetTileKey().m_zoomLevel > GetCurrentZoomLevel(); }; - for (auto const & group : m_renderGroups) - { - if (removePredicate(group)) - { - group->DeleteLater(); - group->Disappear(); - } - } - m_deferredRenderGroups.erase(remove_if(m_deferredRenderGroups.begin(), - m_deferredRenderGroups.end(), - removePredicate), - m_deferredRenderGroups.end()); + RemoveRenderGroups(removePredicate); m_requestedTiles->Set(modelView, move(tiles)); m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread, diff --git a/drape_frontend/frontend_renderer.hpp b/drape_frontend/frontend_renderer.hpp index 9ffedffbca..2c40ac8865 100755 --- a/drape_frontend/frontend_renderer.hpp +++ b/drape_frontend/frontend_renderer.hpp @@ -194,6 +194,11 @@ private: void OnActivateTile(TileKey const & tileKey); void OnRemoveTile(TileKey const & tileKey); + using TRenderGroupRemovePredicate = function const &)>; + void RemoveRenderGroups(TRenderGroupRemovePredicate const & predicate); + + void CheckTileGenerations(TileKey const & tileKey); + void OnCompassTapped(); FeatureID GetVisiblePOI(m2::PointD const & pixelPoint) const; diff --git a/drape_frontend/read_manager.cpp b/drape_frontend/read_manager.cpp index ab77fa3dce..5559c80049 100755 --- a/drape_frontend/read_manager.cpp +++ b/drape_frontend/read_manager.cpp @@ -38,6 +38,7 @@ ReadManager::ReadManager(ref_ptr commutator, MapDataProvider , m_forceUpdate(true) , myPool(64, ReadMWMTaskFactory(m_memIndex, m_model)) , m_counter(0) + , m_generationCounter(0) { } @@ -78,6 +79,7 @@ void ReadManager::UpdateCoverage(ScreenBase const & screen, TTilesCollection con if (MustDropAllTiles(screen)) { IncreaseCounter(static_cast(tiles.size())); + m_generationCounter++; for_each(m_tileInfos.begin(), m_tileInfos.end(), bind(&ReadManager::CancelTileInfo, this, _1)); m_tileInfos.clear(); @@ -176,7 +178,8 @@ bool ReadManager::MustDropAllTiles(ScreenBase const & screen) const void ReadManager::PushTaskBackForTileKey(TileKey const & tileKey, ref_ptr texMng) { - shared_ptr tileInfo(new TileInfo(make_unique_dp(tileKey, m_commutator, texMng))); + shared_ptr tileInfo(new TileInfo(make_unique_dp(TileKey(tileKey, m_generationCounter), + m_commutator, texMng))); m_tileInfos.insert(tileInfo); ReadMWMTask * task = myPool.Get(); task->Init(tileInfo); diff --git a/drape_frontend/read_manager.hpp b/drape_frontend/read_manager.hpp index 0e33c9656a..bb61ac02cc 100755 --- a/drape_frontend/read_manager.hpp +++ b/drape_frontend/read_manager.hpp @@ -72,6 +72,7 @@ private: int m_counter; set m_finishedTiles; mutex m_finishedTilesMutex; + uint64_t m_generationCounter; void CancelTileInfo(shared_ptr const & tileToCancel); void ClearTileInfo(shared_ptr const & tileToClear); diff --git a/drape_frontend/tile_key.cpp b/drape_frontend/tile_key.cpp index 6af420cc37..16a22c5958 100755 --- a/drape_frontend/tile_key.cpp +++ b/drape_frontend/tile_key.cpp @@ -6,19 +6,24 @@ namespace df { TileKey::TileKey() - : m_x(-1), m_y(-1), m_zoomLevel(-1) -{ -} + : m_x(-1), m_y(-1), m_zoomLevel(-1), m_generation(0) +{} TileKey::TileKey(int x, int y, int zoomLevel) - : m_x(x), m_y(y), m_zoomLevel(zoomLevel) -{ -} + : m_x(x), m_y(y), m_zoomLevel(zoomLevel), m_generation(0) +{} + +TileKey::TileKey(TileKey const & key, uint64_t generation) + : m_x(key.m_x), m_y(key.m_y), + m_zoomLevel(key.m_zoomLevel), + m_generation(generation) +{} bool TileKey::operator <(TileKey const & other) const { if (m_zoomLevel != other.m_zoomLevel) return m_zoomLevel < other.m_zoomLevel; + if (m_y != other.m_y) return m_y < other.m_y; @@ -47,7 +52,8 @@ m2::RectD TileKey::GetGlobalRect() const string DebugPrint(TileKey const & key) { ostringstream out; - out << "[x = " << key.m_x << ", y = " << key.m_y << ", zoomLevel = " << key.m_zoomLevel << "]"; + out << "[x = " << key.m_x << ", y = " << key.m_y << ", zoomLevel = " + << key.m_zoomLevel << ", gen = " << key.m_generation << "]"; return out.str(); } diff --git a/drape_frontend/tile_key.hpp b/drape_frontend/tile_key.hpp index 24a9e73d47..f51fa3a77e 100755 --- a/drape_frontend/tile_key.hpp +++ b/drape_frontend/tile_key.hpp @@ -21,6 +21,7 @@ struct TileKey { TileKey(); TileKey(int x, int y, int zoomLevel); + TileKey(TileKey const & key, uint64_t generation); bool operator < (TileKey const & other) const; bool operator == (TileKey const & other) const; @@ -30,6 +31,7 @@ struct TileKey int m_x; int m_y; int m_zoomLevel; + uint64_t m_generation; }; string DebugPrint(TileKey const & key); diff --git a/drape_frontend/tile_tree.cpp b/drape_frontend/tile_tree.cpp index 7ff45bd4f3..59f607d548 100755 --- a/drape_frontend/tile_tree.cpp +++ b/drape_frontend/tile_tree.cpp @@ -239,8 +239,7 @@ bool TileTree::ProcessNode(TNodePtr const & node, TileKey const & tileKey, int c { // skip unknown tiles and tiles from different zoom level // A tile can get Unknown status if it becomes invalid before BR finished its processing - if (childNode->m_tileStatus == TileStatus::Unknown || - childNode->m_tileKey.m_zoomLevel != zoomLevel) + if (childNode->m_tileStatus == TileStatus::Unknown || tileKey.m_zoomLevel != zoomLevel) return false; // remove all tiles below current @@ -251,14 +250,14 @@ bool TileTree::ProcessNode(TNodePtr const & node, TileKey const & tileKey, int c { childNode->m_tileStatus = TileStatus::Deferred; if (m_deferRenderGroupHandler != nullptr) - m_deferRenderGroupHandler(childNode->m_tileKey, state, move(bucket)); + m_deferRenderGroupHandler(tileKey, state, move(bucket)); childNode->m_isRemoved = false; } else { childNode->m_tileStatus = TileStatus::Rendered; if (m_addRenderGroupHandler != nullptr) - m_addRenderGroupHandler(childNode->m_tileKey, state, move(bucket)); + m_addRenderGroupHandler(tileKey, state, move(bucket)); childNode->m_isRemoved = false; }