From 3d1b63b26027bb44591958cf1d6422d4c7deede3 Mon Sep 17 00:00:00 2001 From: "r.kuznetsov" Date: Thu, 2 Apr 2015 13:43:39 +0300 Subject: [PATCH] Fixed a bug with tiles removing --- base/internal/message.hpp | 9 ++++++ drape_frontend/backend_renderer.cpp | 11 +++++-- drape_frontend/engine_context.cpp | 5 ++++ drape_frontend/engine_context.hpp | 3 +- drape_frontend/frontend_renderer.cpp | 41 ++++++++------------------- drape_frontend/frontend_renderer.hpp | 5 +--- drape_frontend/message.hpp | 1 + drape_frontend/message_subclasses.hpp | 16 +++++++++++ drape_frontend/read_manager.cpp | 20 +++++++++++++ drape_frontend/read_manager.hpp | 6 ++++ drape_frontend/read_mwm_task.cpp | 9 ++++++ drape_frontend/read_mwm_task.hpp | 1 + drape_frontend/render_group.cpp | 7 +++++ drape_frontend/render_group.hpp | 3 ++ drape_frontend/tile_info.hpp | 2 -- drape_frontend/tile_tree.cpp | 15 ++++++---- drape_frontend/tile_tree.hpp | 4 +-- drape_frontend/tile_utils.cpp | 2 +- 18 files changed, 113 insertions(+), 47 deletions(-) diff --git a/base/internal/message.hpp b/base/internal/message.hpp index 969cba34aa..46786135ba 100644 --- a/base/internal/message.hpp +++ b/base/internal/message.hpp @@ -6,6 +6,7 @@ #include "std/set.hpp" #include "std/sstream.hpp" #include "std/string.hpp" +#include "std/unique_ptr.hpp" #include "std/utility.hpp" #include "std/vector.hpp" #include "std/initializer_list.hpp" @@ -25,6 +26,7 @@ template inline string DebugPrint(vector const & v); template inline string DebugPrint(set const & v); template inline string DebugPrint(map const & v); template inline string DebugPrint(initializer_list const & v); +template inline string DebugPrint(unique_ptr const & v); //@} @@ -116,6 +118,13 @@ template inline string DebugPrint(T const & t) return out.str(); } +template inline string DebugPrint(unique_ptr const & v) +{ + ostringstream out; + out << DebugPrint(*v); + return out.str(); +} + namespace my { namespace impl diff --git a/drape_frontend/backend_renderer.cpp b/drape_frontend/backend_renderer.cpp index c2107dd0a7..81932fa5c8 100644 --- a/drape_frontend/backend_renderer.cpp +++ b/drape_frontend/backend_renderer.cpp @@ -103,9 +103,14 @@ void BackendRenderer::AcceptMessage(dp::RefPointer message) { TileReadEndMessage * msg = df::CastMessage(message); m_batchersPool->ReleaseBatcher(msg->GetKey()); - - TileReadEndMessage * outputMsg = new TileReadEndMessage(msg->GetKey()); - m_commutator->PostMessage(ThreadsCommutator::RenderThread, dp::MovePointer(outputMsg), MessagePriority::Normal); + break; + } + case Message::FinishReading: + { + FinishReadingMessage * msg = df::CastMessage(message); + m_commutator->PostMessage(ThreadsCommutator::RenderThread, + dp::MovePointer(new FinishReadingMessage(move(msg->GetTiles()))), + MessagePriority::Normal); break; } case Message::MapShapeReaded: diff --git a/drape_frontend/engine_context.cpp b/drape_frontend/engine_context.cpp index 1af3246403..1ec961c469 100644 --- a/drape_frontend/engine_context.cpp +++ b/drape_frontend/engine_context.cpp @@ -67,6 +67,11 @@ void EngineContext::EndReadTile() PostMessage(dp::MovePointer(new TileReadEndMessage(m_tileKey))); } +void EngineContext::FinishReading(TTilesCollection const & finishedTiles) +{ + PostMessage(new FinishReadingMessage(finishedTiles)); +} + void EngineContext::PostMessage(dp::TransferPointer message) { m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread, message, diff --git a/drape_frontend/engine_context.hpp b/drape_frontend/engine_context.hpp index fb6283e123..df0c4c9e36 100644 --- a/drape_frontend/engine_context.hpp +++ b/drape_frontend/engine_context.hpp @@ -1,6 +1,6 @@ #pragma once -#include "drape_frontend/tile_key.hpp" +#include "drape_frontend/tile_utils.hpp" #include "drape_frontend/threads_commutator.hpp" #include "drape/pointers.hpp" @@ -23,6 +23,7 @@ public: /// It will be proccessed and delete later void InsertShape(dp::TransferPointer shape); void EndReadTile(); + void FinishReading(TTilesCollection const & finishedTiles); private: void PostMessage(dp::TransferPointer message); diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index e1f08f9f2b..060f0de70b 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -99,7 +99,7 @@ void FrontendRenderer::AfterDrawFrame() } #endif -unique_ptr & FrontendRenderer::FindUserMarkRenderGroup(TileKey const & tileKey, bool createIfNeed) +unique_ptr const & FrontendRenderer::FindUserMarkRenderGroup(TileKey const & tileKey, bool createIfNeed) { auto it = find_if(m_userMarkRenderGroups.begin(), m_userMarkRenderGroups.end(), [&tileKey](unique_ptr const & g) { @@ -137,29 +137,22 @@ void FrontendRenderer::AcceptMessage(dp::RefPointer message) bucket->GetBuffer()->Build(program); if (!IsUserMarkLayer(key)) { - int const zoomLevel = df::GetTileScaleBase(m_view); - bool const result = m_tileTree.ProcessTile(key, zoomLevel, state, bucket); - if (!result) + if (!m_tileTree.ProcessTile(key, df::GetTileScaleBase(m_view), state, bucket)) bucket.Destroy(); } else { - unique_ptr & group = FindUserMarkRenderGroup(key, true); + auto const & group = FindUserMarkRenderGroup(key, true); ASSERT(group.get() != nullptr, ()); group->SetRenderBucket(state, bucket.Move()); } break; } - case Message::TileReadEnded: + case Message::FinishReading: { - TileReadEndMessage * msg = df::CastMessage(message); - TileKey const & key = msg->GetKey(); - if (!IsUserMarkLayer(key)) - { - int const zoomLevel = df::GetTileScaleBase(m_view); - m_tileTree.FinishTile(key, zoomLevel); - } + FinishReadingMessage * msg = df::CastMessage(message); + m_tileTree.FinishTiles(msg->GetTiles(), df::GetTileScaleBase(m_view)); break; } @@ -224,7 +217,7 @@ void FrontendRenderer::AcceptMessage(dp::RefPointer message) case Message::ChangeUserMarkLayerVisibility: { ChangeUserMarkLayerVisibilityMessage * m = df::CastMessage(message); - unique_ptr & group = FindUserMarkRenderGroup(m->GetKey(), true); + auto const & group = FindUserMarkRenderGroup(m->GetKey(), true); ASSERT(group.get() != nullptr, ()); group->SetIsVisible(m->IsVisible()); break; @@ -290,10 +283,11 @@ void FrontendRenderer::OnAddDeferredTile(TileKey const & tileKey, TileStatus til void FrontendRenderer::OnRemoveTile(TileKey const & tileKey, TileStatus tileStatus) { - for(auto it = m_renderGroups.begin(); it != m_renderGroups.end(); ++it) + UNUSED_VALUE(tileStatus); + for(auto const & group : m_renderGroups) { - if ((*it)->GetTileKey() == tileKey) - (*it)->DeleteLater(); + if (group->GetTileKey() == tileKey) + group->DeleteLater(); } for(auto it = m_deferredRenderGroups.begin(); it != m_deferredRenderGroups.end();) @@ -348,9 +342,8 @@ void FrontendRenderer::RenderScene() GLFunctions::glClear(); dp::GLState::DepthLayer prevLayer = dp::GLState::GeometryLayer; - for (size_t i = 0; i < m_renderGroups.size(); ++i) + for (auto const & group : m_renderGroups) { - unique_ptr & group = m_renderGroups[i]; dp::GLState const & state = group->GetState(); dp::GLState::DepthLayer layer = state.GetDepthLayer(); if (prevLayer != layer && layer == dp::GLState::OverlayLayer) @@ -563,14 +556,4 @@ void FrontendRenderer::UpdateScene() } } -string DebugPrint(vector> const & groups) -{ - ostringstream out; - out << "\n{\n"; - for (auto it = groups.begin(); it != groups.end(); ++it) - out << DebugPrint((*it)->GetTileKey()) << "\n"; - out << "}\n"; - return out.str(); -} - } // namespace df diff --git a/drape_frontend/frontend_renderer.hpp b/drape_frontend/frontend_renderer.hpp index e4b17d860c..ac5b751253 100755 --- a/drape_frontend/frontend_renderer.hpp +++ b/drape_frontend/frontend_renderer.hpp @@ -71,7 +71,7 @@ private: void ResolveTileKeys(m2::RectD const & rect); void ResolveTileKeys(int tileScale); - unique_ptr & FindUserMarkRenderGroup(TileKey const & tileKey, bool createIfNeed); + unique_ptr const & FindUserMarkRenderGroup(TileKey const & tileKey, bool createIfNeed); private: class Routine : public threads::IRoutine @@ -130,9 +130,6 @@ private: mutex m_modelViewMutex; dp::OverlayTree m_overlayTree; - -private: - friend string DebugPrint(vector> const & groups); }; } // namespace df diff --git a/drape_frontend/message.hpp b/drape_frontend/message.hpp index 68c7beb1b4..fc2d5ed877 100644 --- a/drape_frontend/message.hpp +++ b/drape_frontend/message.hpp @@ -11,6 +11,7 @@ public: Unknown, TileReadStarted, TileReadEnded, + FinishReading, FlushTile, MapShapeReaded, UpdateReadManager, diff --git a/drape_frontend/message_subclasses.hpp b/drape_frontend/message_subclasses.hpp index b06635a74c..73bf28db0f 100644 --- a/drape_frontend/message_subclasses.hpp +++ b/drape_frontend/message_subclasses.hpp @@ -19,6 +19,7 @@ #include "std/shared_ptr.hpp" #include "std/set.hpp" #include "std/function.hpp" +#include "std/utility.hpp" namespace df { @@ -53,6 +54,21 @@ public: Type GetType() const override { return Message::TileReadEnded; } }; +class FinishReadingMessage : public Message +{ +public: + template FinishReadingMessage(T && tiles) + : m_tiles(forward(tiles)) + {} + + Type GetType() const override { return Message::FinishReading; } + + TTilesCollection & GetTiles() { return m_tiles; } + +private: + TTilesCollection m_tiles; +}; + class FlushRenderBucketMessage : public BaseTileMessage { public: diff --git a/drape_frontend/read_manager.cpp b/drape_frontend/read_manager.cpp index 6955f97885..f113d0adbc 100755 --- a/drape_frontend/read_manager.cpp +++ b/drape_frontend/read_manager.cpp @@ -34,6 +34,7 @@ ReadManager::ReadManager(dp::RefPointer commutator, MapDataPr : m_commutator(commutator) , m_model(model) , myPool(64, ReadMWMTaskFactory(m_memIndex, m_model)) + , m_counter(0) { m_pool.Reset(new threads::ThreadPool(ReadCount(), bind(&ReadManager::OnTaskFinished, this, _1))); } @@ -42,6 +43,21 @@ void ReadManager::OnTaskFinished(threads::IRoutine * task) { ASSERT(dynamic_cast(task) != NULL, ()); ReadMWMTask * t = static_cast(task); + + // add finished tile to collection + { + lock_guard lock(m_finishedTilesMutex); + m_finishedTiles.emplace(t->GetTileKey()); + + ASSERT(m_counter > 0, ()); + --m_counter; + if (m_counter == 0) + { + m_context.FinishReading(m_finishedTiles); + m_finishedTiles.clear(); + } + } + t->Reset(); myPool.Return(t); } @@ -53,6 +69,8 @@ void ReadManager::UpdateCoverage(ScreenBase const & screen, TTilesCollection con if (MustDropAllTiles(screen)) { + m_counter += tiles.size(); + for_each(m_tileInfos.begin(), m_tileInfos.end(), bind(&ReadManager::CancelTileInfo, this, _1)); m_tileInfos.clear(); for_each(tiles.begin(), tiles.end(), bind(&ReadManager::PushTaskBackForTileKey, this, _1)); @@ -77,6 +95,8 @@ void ReadManager::UpdateCoverage(ScreenBase const & screen, TTilesCollection con m_tileInfos.begin(), m_tileInfos.end(), back_inserter(inputRects), LessCoverageCell()); + m_counter += (inputRects.size() + (m_tileInfos.size() - outdatedTiles.size())); + for_each(outdatedTiles.begin(), outdatedTiles.end(), bind(&ReadManager::ClearTileInfo, this, _1)); for_each(m_tileInfos.begin(), m_tileInfos.end(), bind(&ReadManager::PushTaskFront, this, _1)); for_each(inputRects.begin(), inputRects.end(), bind(&ReadManager::PushTaskBackForTileKey, this, _1)); diff --git a/drape_frontend/read_manager.hpp b/drape_frontend/read_manager.hpp index 6b60ce9ae4..2d93026868 100755 --- a/drape_frontend/read_manager.hpp +++ b/drape_frontend/read_manager.hpp @@ -13,6 +13,8 @@ #include "base/thread_pool.hpp" +#include "std/atomic.hpp" +#include "std/mutex.hpp" #include "std/set.hpp" #include "std/shared_ptr.hpp" @@ -63,6 +65,10 @@ private: ObjectPool myPool; + atomic m_counter; + set m_finishedTiles; + mutex m_finishedTilesMutex; + void CancelTileInfo(shared_ptr const & tileToCancel); void ClearTileInfo(shared_ptr const & tileToClear); }; diff --git a/drape_frontend/read_mwm_task.cpp b/drape_frontend/read_mwm_task.cpp index 4212b66b35..0f84502888 100644 --- a/drape_frontend/read_mwm_task.cpp +++ b/drape_frontend/read_mwm_task.cpp @@ -48,4 +48,13 @@ void ReadMWMTask::Do() } } +TileKey ReadMWMTask::GetTileKey() const +{ + shared_ptr tileInfo = m_tileInfo.lock(); + if (tileInfo == NULL) + return TileKey(); + + return tileInfo->GetTileKey(); +} + } // namespace df diff --git a/drape_frontend/read_mwm_task.hpp b/drape_frontend/read_mwm_task.hpp index a6c389a8b8..9f35a73b90 100644 --- a/drape_frontend/read_mwm_task.hpp +++ b/drape_frontend/read_mwm_task.hpp @@ -25,6 +25,7 @@ public: void Init(weak_ptr const & tileInfo); void Reset(); + TileKey GetTileKey() const; private: weak_ptr m_tileInfo; diff --git a/drape_frontend/render_group.cpp b/drape_frontend/render_group.cpp index c21b9a160a..fc02c9d5bc 100755 --- a/drape_frontend/render_group.cpp +++ b/drape_frontend/render_group.cpp @@ -129,4 +129,11 @@ void UserMarkRenderGroup::Render(ScreenBase const & screen) m_renderBucket->Render(screen); } +string DebugPrint(RenderGroup const & group) +{ + ostringstream out; + out << DebugPrint(group.GetTileKey()); + return out.str(); +} + } // namespace df diff --git a/drape_frontend/render_group.hpp b/drape_frontend/render_group.hpp index 807997ffac..5b068cf4f3 100755 --- a/drape_frontend/render_group.hpp +++ b/drape_frontend/render_group.hpp @@ -57,6 +57,9 @@ private: vector > m_renderBuckets; mutable bool m_pendingOnDelete; + +private: + friend string DebugPrint(RenderGroup const & group); }; class RenderGroupComparator diff --git a/drape_frontend/tile_info.hpp b/drape_frontend/tile_info.hpp index 31e948f174..65be74d15a 100644 --- a/drape_frontend/tile_info.hpp +++ b/drape_frontend/tile_info.hpp @@ -10,8 +10,6 @@ #include "base/mutex.hpp" #include "std/atomic.hpp" -#include "std/mutex.hpp" -#include "std/noncopyable.hpp" #include "std/vector.hpp" class FeatureType; diff --git a/drape_frontend/tile_tree.cpp b/drape_frontend/tile_tree.cpp index 7d96b05f9f..2743b3f457 100755 --- a/drape_frontend/tile_tree.cpp +++ b/drape_frontend/tile_tree.cpp @@ -78,9 +78,13 @@ bool TileTree::ProcessTile(TileKey const & tileKey, int const zoomLevel, return result; } -void TileTree::FinishTile(TileKey const & tileKey, int const zoomLevel) +void TileTree::FinishTiles(TTilesCollection const & tiles, int const zoomLevel) { - if (FinishNode(m_root, tileKey, zoomLevel)) + bool changed = false; + for (TileKey const & tileKey : tiles) + changed |= FinishNode(m_root, tileKey, zoomLevel); + + if (changed) { CheckDeferredTiles(m_root); SimplifyTree(); @@ -277,12 +281,13 @@ bool TileTree::FinishNode(TNodePtr const & node, TileKey const & tileKey, int co if (childNode->m_tileKey == tileKey && childNode->m_tileStatus == TileStatus::Requested) { // here a tile has finished, but we hadn't got any data from BR. It means that - // this tile is empty, so we remove all his descendants and him - childNode->m_tileStatus = TileStatus::Unknown; + // this tile is empty, so we mark this tile as rendered + childNode->m_tileStatus = TileStatus::Rendered; + childNode->m_isRemoved = false; if (childNode->m_tileKey.m_zoomLevel >= zoomLevel) DeleteTilesBelow(childNode); - changed = true; + return true; } changed |= FinishNode(childNode, tileKey, zoomLevel); diff --git a/drape_frontend/tile_tree.hpp b/drape_frontend/tile_tree.hpp index 9f234b5007..3e86cf0d6e 100755 --- a/drape_frontend/tile_tree.hpp +++ b/drape_frontend/tile_tree.hpp @@ -46,8 +46,8 @@ public: /// this method processes received from BR tile bool ProcessTile(TileKey const & tileKey, int const zoomLevel, dp::GLState const & state, dp::MasterPointer & bucket); - /// this method processes a message about finishing tile on BR - void FinishTile(TileKey const & tileKey, int const zoomLevel); + /// this method processes a message about finishing reading tiles on BR + void FinishTiles(TTilesCollection const & tiles, int const zoomLevel); /// this method performs clipping by rectangle void ClipByRect(m2::RectD const & rect); diff --git a/drape_frontend/tile_utils.cpp b/drape_frontend/tile_utils.cpp index fa969b5cfb..a0baa0679e 100755 --- a/drape_frontend/tile_utils.cpp +++ b/drape_frontend/tile_utils.cpp @@ -1,4 +1,4 @@ -#include +#include "tile_utils.hpp" #include "../base/assert.hpp"