diff --git a/base/mru_cache.hpp b/base/mru_cache.hpp index ae7dfadd97..2d94d4981a 100644 --- a/base/mru_cache.hpp +++ b/base/mru_cache.hpp @@ -64,9 +64,22 @@ namespace my return m_curWeight + weight <= m_maxWeight; } - /// how much elements we can fit in this cache, considering unlocked - /// elements, that could be popped out on request - int CanFit() const + /// how many elements in unlocked state do we have in cache + int UnlockedWeight() const + { + int unlockedWeight = 0; + + for (typename map_t::const_iterator it = m_map.begin(); it != m_map.end(); ++it) + { + if (it->second.m_lockCount == 0) + unlockedWeight += it->second.m_weight; + } + + return unlockedWeight; + } + + /// how many elements in locked state do we have in cache + int LockedWeight() const { int lockedWeight = 0; @@ -76,7 +89,14 @@ namespace my lockedWeight += it->second.m_weight; } - return m_maxWeight - lockedWeight; + return lockedWeight; + } + + /// how much elements we can fit in this cache, considering unlocked + /// elements, that could be popped out on request + int CanFit() const + { + return m_maxWeight - LockedWeight(); } int MaxWeight() const @@ -161,7 +181,7 @@ namespace my void UnlockElem(KeyT const & key) { ASSERT(HasElem(key), ()); - ASSERT(m_map[key].m_lockCount > 0, ()); + ASSERT(m_map[key].m_lockCount > 0, (m_map[key].m_lockCount)); m_map[key].m_lockCount -= 1; } diff --git a/map/coverage_generator.cpp b/map/coverage_generator.cpp index a4e4d92936..95fae1fb6b 100644 --- a/map/coverage_generator.cpp +++ b/map/coverage_generator.cpp @@ -3,6 +3,7 @@ #include "coverage_generator.hpp" #include "screen_coverage.hpp" #include "tile_renderer.hpp" +#include "tile_set.hpp" #include "../yg/rendercontext.hpp" @@ -87,22 +88,22 @@ void CoverageGenerator::InvalidateTilesImpl(m2::AnyRectD const & r, int startSca TileCache & tileCache = m_tileRenderer->GetTileCache(); - tileCache.lock(); + tileCache.Lock(); /// here we should copy elements as we've delete some of them later - set k = tileCache.keys(); + set k = tileCache.Keys(); for (set::const_iterator it = k.begin(); it != k.end(); ++it) { Tiler::RectInfo const & ri = *it; if ((ri.m_tileScale >= startScale) && r.IsIntersect(m2::AnyRectD(ri.m_rect))) { - ASSERT(tileCache.lockCount(ri) == 0, ()); - tileCache.remove(ri); + ASSERT(tileCache.LockCount(ri) == 0, ()); + tileCache.Remove(ri); } } - tileCache.unlock(); + tileCache.Unlock(); } void CoverageGenerator::InvalidateTiles(m2::AnyRectD const & r, int startScale) @@ -161,7 +162,8 @@ void CoverageGenerator::CoverScreen(ScreenBase const & screen, int sequenceID) m_windowHandle->invalidate(); } -void CoverageGenerator::AddMergeTileTask(Tiler::RectInfo const & rectInfo, int sequenceID) +void CoverageGenerator::AddMergeTileTask(Tiler::RectInfo const & rectInfo, + int sequenceID) { if (g_coverageGeneratorDestroyed) return; @@ -172,7 +174,10 @@ void CoverageGenerator::AddMergeTileTask(Tiler::RectInfo const & rectInfo, int s void CoverageGenerator::MergeTile(Tiler::RectInfo const & rectInfo, int sequenceID) { if (sequenceID < m_sequenceID) + { + m_tileRenderer->RemoveActiveTile(rectInfo); return; + } ASSERT(m_workCoverage == 0, ()); diff --git a/map/coverage_generator.hpp b/map/coverage_generator.hpp index 78e0f1ae15..c4d65929e7 100644 --- a/map/coverage_generator.hpp +++ b/map/coverage_generator.hpp @@ -70,7 +70,9 @@ public: void InvalidateTilesImpl(m2::AnyRectD const & rect, int startScale); void AddCoverScreenTask(ScreenBase const & screen, bool doForce); - void AddMergeTileTask(Tiler::RectInfo const & rectInfo, int sequenceID); + void AddMergeTileTask(Tiler::RectInfo const & rectInfo, + int sequenceID); + void AddCheckEmptyModelTask(int sequenceID); void CoverScreen(ScreenBase const & screen, int sequenceID); diff --git a/map/map.pro b/map/map.pro index 9c7b9d3fb3..3eea9d5ce1 100644 --- a/map/map.pro +++ b/map/map.pro @@ -47,7 +47,8 @@ HEADERS += \ queued_renderer.hpp \ basic_tiling_render_policy.hpp \ render_policy_mt.hpp \ - bookmark.hpp + bookmark.hpp \ + tile_set.hpp SOURCES += \ feature_vec_model.cpp \ @@ -85,7 +86,8 @@ SOURCES += \ events.cpp \ basic_tiling_render_policy.cpp \ render_policy_mt.cpp \ - address_finder.cpp + address_finder.cpp \ + tile_set.cpp !iphone*:!bada*:!android* { HEADERS += qgl_render_context.hpp @@ -96,3 +98,5 @@ SOURCES += \ + + diff --git a/map/screen_coverage.cpp b/map/screen_coverage.cpp index c725536513..61b8e4c336 100644 --- a/map/screen_coverage.cpp +++ b/map/screen_coverage.cpp @@ -57,17 +57,17 @@ ScreenCoverage * ScreenCoverage::Clone() TileCache * tileCache = &m_tileRenderer->GetTileCache(); - tileCache->lock(); + tileCache->Lock(); res->m_tiles = m_tiles; - for (TileSet::const_iterator it = res->m_tiles.begin(); it != res->m_tiles.end(); ++it) + for (TTileSet::const_iterator it = res->m_tiles.begin(); it != res->m_tiles.end(); ++it) { Tiler::RectInfo const & ri = (*it)->m_rectInfo; - tileCache->lockTile(ri); + tileCache->LockTile(ri); } - tileCache->unlock(); + tileCache->Unlock(); res->m_infoLayer.reset(); res->m_infoLayer.reset(m_infoLayer->clone()); @@ -88,45 +88,46 @@ yg::ResourceStyleCache * ScreenCoverage::GetResourceStyleCache() const void ScreenCoverage::Merge(Tiler::RectInfo const & ri) { - if (m_tileRects.find(ri) == m_tileRects.end()) - return; + ASSERT(m_tileRects.find(ri) != m_tileRects.end(), ()); - TileCache * tileCache = &m_tileRenderer->GetTileCache(); + TileCache & tileCache = m_tileRenderer->GetTileCache(); + TileSet & tileSet = m_tileRenderer->GetTileSet(); Tile const * tile = 0; bool hasTile = false; - tileCache->lock(); + tileCache.Lock(); + tileSet.Lock(); - hasTile = tileCache->hasTile(ri); - if (hasTile) - tile = &tileCache->getTile(ri); - - bool addTile = false; + hasTile = tileSet.HasTile(ri); if (hasTile) { - addTile = (m_tiles.find(tile) == m_tiles.end()); + ASSERT(tileCache.HasTile(ri), ()); - if (addTile) + tile = &tileCache.GetTile(ri); + ASSERT(m_tiles.find(tile) == m_tiles.end(), ()); + + /// while in the TileSet, the tile is assumed to be locked + + m_tiles.insert(tile); + m_tileRects.erase(ri); + m_newTileRects.erase(ri); + m_newLeafTileRects.erase(ri); + + if (m_tiler.isLeaf(ri)) { - tileCache->lockTile(ri); - m_tiles.insert(tile); - m_tileRects.erase(ri); - m_newTileRects.erase(ri); - m_newLeafTileRects.erase(ri); - - if (m_tiler.isLeaf(ri)) - { - m_isEmptyDrawingCoverage &= tile->m_isEmptyDrawing; - m_leafTilesToRender--; - } + m_isEmptyDrawingCoverage &= tile->m_isEmptyDrawing; + m_leafTilesToRender--; } + + tileSet.RemoveTile(ri); } - tileCache->unlock(); + tileSet.Unlock(); + tileCache.Unlock(); - if (addTile) + if (hasTile) { if (m_tiler.isLeaf(ri)) { @@ -169,13 +170,13 @@ void ScreenCoverage::SetScreen(ScreenBase const & screen) vector allRects; vector newRects; - TileSet tiles; + TTileSet tiles; m_tiler.tiles(allRects, GetPlatform().PreCachingDepth()); TileCache * tileCache = &m_tileRenderer->GetTileCache(); - tileCache->lock(); + tileCache->Lock(); m_isEmptyDrawingCoverage = true; m_isEmptyModelAtCoverageCenter = true; @@ -186,10 +187,10 @@ void ScreenCoverage::SetScreen(ScreenBase const & screen) m_tileRects.insert(allRects[i]); Tiler::RectInfo ri = allRects[i]; - if (tileCache->hasTile(ri)) + if (tileCache->HasTile(ri)) { - tileCache->touchTile(ri); - Tile const * tile = &tileCache->getTile(ri); + tileCache->TouchTile(ri); + Tile const * tile = &tileCache->GetTile(ri); ASSERT(tiles.find(tile) == tiles.end(), ()); if (m_tiler.isLeaf(allRects[i])) @@ -209,26 +210,26 @@ void ScreenCoverage::SetScreen(ScreenBase const & screen) /// tiles, that aren't in current coverage are unlocked to allow their deletion from TileCache /// tiles, that are new to the current coverage are added into m_tiles and locked in TileCache - TileSet erasedTiles; - TileSet addedTiles; + TTileSet erasedTiles; + TTileSet addedTiles; - set_difference(m_tiles.begin(), m_tiles.end(), tiles.begin(), tiles.end(), inserter(erasedTiles, erasedTiles.end()), TileSet::key_compare()); - set_difference(tiles.begin(), tiles.end(), m_tiles.begin(), m_tiles.end(), inserter(addedTiles, addedTiles.end()), TileSet::key_compare()); + set_difference(m_tiles.begin(), m_tiles.end(), tiles.begin(), tiles.end(), inserter(erasedTiles, erasedTiles.end()), TTileSet::key_compare()); + set_difference(tiles.begin(), tiles.end(), m_tiles.begin(), m_tiles.end(), inserter(addedTiles, addedTiles.end()), TTileSet::key_compare()); - for (TileSet::const_iterator it = erasedTiles.begin(); it != erasedTiles.end(); ++it) + for (TTileSet::const_iterator it = erasedTiles.begin(); it != erasedTiles.end(); ++it) { Tiler::RectInfo ri = (*it)->m_rectInfo; - tileCache->unlockTile((*it)->m_rectInfo); + tileCache->UnlockTile((*it)->m_rectInfo); /// here we should "unmerge" erasedTiles[i].m_infoLayer from m_infoLayer } - for (TileSet::const_iterator it = addedTiles.begin(); it != addedTiles.end(); ++it) + for (TTileSet::const_iterator it = addedTiles.begin(); it != addedTiles.end(); ++it) { Tiler::RectInfo ri = (*it)->m_rectInfo; - tileCache->lockTile((*it)->m_rectInfo); + tileCache->LockTile((*it)->m_rectInfo); } - tileCache->unlock(); + tileCache->Unlock(); m_tiles = tiles; @@ -236,9 +237,9 @@ void ScreenCoverage::SetScreen(ScreenBase const & screen) set drawnTiles; - for (TileSet::const_iterator it = m_tiles.begin(); it != m_tiles.end(); ++it) + for (TTileSet::const_iterator it = m_tiles.begin(); it != m_tiles.end(); ++it) { - Tiler::RectInfo ri = (*it)->m_rectInfo; + Tiler::RectInfo const & ri = (*it)->m_rectInfo; drawnTiles.insert(Tiler::RectInfo(ri.m_tileScale, ri.m_x, ri.m_y)); } @@ -283,10 +284,15 @@ void ScreenCoverage::SetScreen(ScreenBase const & screen) { Tiler::RectInfo const & ri = firstClassTiles[i]; + core::CommandsQueue::Chain chain; + + chain.addCommand(bind(&CoverageGenerator::AddMergeTileTask, + m_coverageGenerator, + ri, + GetSequenceID())); + m_tileRenderer->AddCommand(ri, GetSequenceID(), - bind(&CoverageGenerator::AddMergeTileTask, m_coverageGenerator, - ri, - GetSequenceID())); + chain); if (m_tiler.isLeaf(ri)) m_newLeafTileRects.insert(ri); @@ -295,23 +301,32 @@ void ScreenCoverage::SetScreen(ScreenBase const & screen) } for (size_t i = 0; i < secondClassTiles.size(); ++i) - m_tileRenderer->AddCommand(secondClassTiles[i], GetSequenceID()); + { + Tiler::RectInfo const & ri = secondClassTiles[i]; + + core::CommandsQueue::Chain chain; + + chain.addCommand(bind(&TileRenderer::RemoveActiveTile, + m_tileRenderer, + ri)); + + m_tileRenderer->AddCommand(ri, GetSequenceID(), chain); + } } ScreenCoverage::~ScreenCoverage() { TileCache * tileCache = &m_tileRenderer->GetTileCache(); - /// unlocking tiles from the primary level + tileCache->Lock(); - tileCache->lock(); - for (TileSet::const_iterator it = m_tiles.begin(); it != m_tiles.end(); ++it) + for (TTileSet::const_iterator it = m_tiles.begin(); it != m_tiles.end(); ++it) { Tiler::RectInfo const & ri = (*it)->m_rectInfo; - tileCache->unlockTile(ri); + tileCache->UnlockTile(ri); } - tileCache->unlock(); + tileCache->Unlock(); } void ScreenCoverage::Draw(yg::gl::Screen * s, ScreenBase const & screen) @@ -320,7 +335,7 @@ void ScreenCoverage::Draw(yg::gl::Screen * s, ScreenBase const & screen) // LOG(LINFO, ("drawing", m_tiles.size(), "tiles")); - for (TileSet::const_iterator it = m_tiles.begin(); it != m_tiles.end(); ++it) + for (TTileSet::const_iterator it = m_tiles.begin(); it != m_tiles.end(); ++it) { Tile const * tile = *it; @@ -401,7 +416,7 @@ void ScreenCoverage::RemoveTiles(m2::AnyRectD const & r, int startScale) { vector toRemove; - for (TileSet::const_iterator it = m_tiles.begin(); it != m_tiles.end(); ++it) + for (TTileSet::const_iterator it = m_tiles.begin(); it != m_tiles.end(); ++it) { Tiler::RectInfo const & ri = (*it)->m_rectInfo; @@ -414,7 +429,7 @@ void ScreenCoverage::RemoveTiles(m2::AnyRectD const & r, int startScale) for (vector::const_iterator it = toRemove.begin(); it != toRemove.end(); ++it) { Tiler::RectInfo const & ri = (*it)->m_rectInfo; - tileCache->unlockTile(ri); + tileCache->UnlockTile(ri); m_tiles.erase(*it); m_tileRects.erase(ri); } @@ -426,7 +441,7 @@ void ScreenCoverage::MergeInfoLayer() { m_infoLayer->clear(); - for (TileSet::const_iterator it = m_tiles.begin(); it != m_tiles.end(); ++it) + for (TTileSet::const_iterator it = m_tiles.begin(); it != m_tiles.end(); ++it) { Tiler::RectInfo const & ri = (*it)->m_rectInfo; if (m_tiler.isLeaf(ri)) diff --git a/map/screen_coverage.hpp b/map/screen_coverage.hpp index 718f3b34dc..9f8debf92d 100644 --- a/map/screen_coverage.hpp +++ b/map/screen_coverage.hpp @@ -36,16 +36,16 @@ private: /// Last covered screen ScreenBase m_screen; /// Container for a rects, that forms a set of tiles in the m_screen - typedef set TileRectSet; + typedef set TTileRectSet; /// All rects, including rects which corresponds to a tiles in m_tiles - TileRectSet m_tileRects; + TTileRectSet m_tileRects; /// Only rects, that should be drawn - TileRectSet m_newTileRects; + TTileRectSet m_newTileRects; /// Only leaf rects, that should be drawn - TileRectSet m_newLeafTileRects; + TTileRectSet m_newLeafTileRects; /// Typedef for a set of tiles, that are visible for the m_screen - typedef set TileSet; - TileSet m_tiles; + typedef set TTileSet; + TTileSet m_tiles; /// InfoLayer composed of infoLayers for visible tiles scoped_ptr m_infoLayer; /// Does this coverage holds only tiles that are empty diff --git a/map/tile_cache.cpp b/map/tile_cache.cpp index 7444e8118d..4ccb5fb8e0 100644 --- a/map/tile_cache.cpp +++ b/map/tile_cache.cpp @@ -16,22 +16,22 @@ TileCache::Entry::Entry(Tile const & tile, shared_ptr const TileCache::TileCache() {} -void TileCache::addTile(Tiler::RectInfo const & key, Entry const & entry) +void TileCache::AddTile(Tiler::RectInfo const & key, Entry const & entry) { m_cache.Add(key, entry, 1); } -void TileCache::lock() +void TileCache::Lock() { m_lock.Lock(); } -void TileCache::unlock() +void TileCache::Unlock() { m_lock.Unlock(); } -set const & TileCache::keys() const +set const & TileCache::Keys() const { return m_cache.Keys(); /* set keys = m_cache.Keys(); @@ -47,57 +47,67 @@ set const & TileCache::keys() const return rects;*/ } -bool TileCache::hasTile(Tiler::RectInfo const & key) +bool TileCache::HasTile(Tiler::RectInfo const & key) { return m_cache.HasElem(key); } -void TileCache::lockTile(Tiler::RectInfo const & key) +void TileCache::LockTile(Tiler::RectInfo const & key) { m_cache.LockElem(key); } -size_t TileCache::lockCount(Tiler::RectInfo const & key) +size_t TileCache::LockCount(Tiler::RectInfo const & key) { return m_cache.LockCount(key); } -void TileCache::unlockTile(Tiler::RectInfo const & key) +void TileCache::UnlockTile(Tiler::RectInfo const & key) { m_cache.UnlockElem(key); } -void TileCache::touchTile(Tiler::RectInfo const & key) +void TileCache::TouchTile(Tiler::RectInfo const & key) { m_cache.Touch(key); } -Tile const & TileCache::getTile(Tiler::RectInfo const & key) +Tile const & TileCache::GetTile(Tiler::RectInfo const & key) { return m_cache.Find(key).m_tile; } -void TileCache::remove(Tiler::RectInfo const & key) +void TileCache::Remove(Tiler::RectInfo const & key) { m_cache.Remove(key); } -int TileCache::canFit() const +int TileCache::CanFit() const { return m_cache.CanFit(); } -int TileCache::cacheSize() const +int TileCache::UnlockedWeight() const +{ + return m_cache.UnlockedWeight(); +} + +int TileCache::LockedWeight() const +{ + return m_cache.LockedWeight(); +} + +int TileCache::CacheSize() const { return m_cache.MaxWeight(); } -void TileCache::resize(int maxWeight) +void TileCache::Resize(int maxWeight) { m_cache.Resize(maxWeight); } -void TileCache::freeRoom(int weight) +void TileCache::FreeRoom(int weight) { m_cache.FreeRoom(weight); } diff --git a/map/tile_cache.hpp b/map/tile_cache.hpp index a8c5da0195..a4efa0e42d 100644 --- a/map/tile_cache.hpp +++ b/map/tile_cache.hpp @@ -41,33 +41,37 @@ public: TileCache(); /// lock for multithreaded access - void lock(); + void Lock(); /// unlock for multithreaded access - void unlock(); + void Unlock(); /// get keys of values in cache - set const & keys() const; + set const & Keys() const; /// add tile to cache - void addTile(Tiler::RectInfo const & key, Entry const & entry); + void AddTile(Tiler::RectInfo const & key, Entry const & entry); /// check, whether we have some tile in the cache - bool hasTile(Tiler::RectInfo const & key); + bool HasTile(Tiler::RectInfo const & key); /// lock tile - void lockTile(Tiler::RectInfo const & key); + void LockTile(Tiler::RectInfo const & key); /// unlock tile - void unlockTile(Tiler::RectInfo const & key); + void UnlockTile(Tiler::RectInfo const & key); /// lock count - size_t lockCount(Tiler::RectInfo const & key); + size_t LockCount(Tiler::RectInfo const & key); /// touch tile - void touchTile(Tiler::RectInfo const & key); + void TouchTile(Tiler::RectInfo const & key); /// get tile from the cache - Tile const & getTile(Tiler::RectInfo const & key); + Tile const & GetTile(Tiler::RectInfo const & key); /// remove the specified tile from the cache - void remove(Tiler::RectInfo const & key); + void Remove(Tiler::RectInfo const & key); /// how much elements can fit in the tileCache - int canFit() const; + int CanFit() const; + /// how many unlocked elements do we have in tileCache + int UnlockedWeight() const; + /// how many locked elements do we have in tileCache + int LockedWeight() const; /// the size of the cache - int cacheSize() const; + int CacheSize() const; /// resize the cache - void resize(int maxWeight); + void Resize(int maxWeight); /// free up to weight spaces evicting unlocked elements from cache - void freeRoom(int weight); + void FreeRoom(int weight); }; diff --git a/map/tile_renderer.cpp b/map/tile_renderer.cpp index bf2862a0c2..3df3ae7997 100644 --- a/map/tile_renderer.cpp +++ b/map/tile_renderer.cpp @@ -175,8 +175,6 @@ void TileRenderer::DrawTile(core::CommandsQueue::Environment const & env, if (m_resourceManager->renderTargetTextures()->IsCancelled()) return; - StartTile(rectInfo); - drawer->screen()->setRenderTarget(tileTarget); shared_ptr tileInfoLayer(new yg::InfoLayer()); @@ -226,10 +224,6 @@ void TileRenderer::DrawTile(core::CommandsQueue::Environment const & env, drawer->screen()->resetInfoLayer(); - // performing some computational task - // to give this thread some time to realize - // that it could be cancelled - /// filter out the overlay elements that are out of the bound rect for the tile if (!env.isCancelled()) tileInfoLayer->clip(renderRect); @@ -253,20 +247,20 @@ void TileRenderer::DrawTile(core::CommandsQueue::Environment const & env, } } - FinishTile(rectInfo); - if (env.isCancelled()) { if (!m_isExiting) m_resourceManager->renderTargetTextures()->Free(tileTarget); } else - AddTile(rectInfo, Tile(tileTarget, - tileInfoLayer, - frameScreen, - rectInfo, - 0, - paintEvent->isEmptyDrawing())); + { + AddActiveTile(Tile(tileTarget, + tileInfoLayer, + frameScreen, + rectInfo, + 0, + paintEvent->isEmptyDrawing())); + } } void TileRenderer::AddCommand(Tiler::RectInfo const & rectInfo, int sequenceID, core::CommandsQueue::Chain const & afterTileFns) @@ -300,6 +294,11 @@ TileCache & TileRenderer::GetTileCache() return m_tileCache; } +TileSet & TileRenderer::GetTileSet() +{ + return m_tileSet; +} + void TileRenderer::WaitForEmptyAndFinished() { m_queue.Join(); @@ -308,47 +307,56 @@ void TileRenderer::WaitForEmptyAndFinished() bool TileRenderer::HasTile(Tiler::RectInfo const & rectInfo) { TileCache & tileCache = GetTileCache(); - tileCache.lock(); - bool res = tileCache.hasTile(rectInfo); - tileCache.unlock(); + tileCache.Lock(); + bool res = tileCache.HasTile(rectInfo); + tileCache.Unlock(); return res; } -void TileRenderer::AddTile(Tiler::RectInfo const & rectInfo, Tile const & tile) -{ - m_tileCache.lock(); - if (m_tileCache.hasTile(rectInfo)) - { - m_resourceManager->renderTargetTextures()->Free(tile.m_renderTarget); - m_tileCache.touchTile(rectInfo); - } - else - { - if (m_tileCache.canFit() == 0) - { - LOG(LINFO, ("resizing tileCache to", m_tileCache.cacheSize() + 1, "elements")); - m_tileCache.resize(m_tileCache.cacheSize() + 1); - } - - m_tileCache.addTile(rectInfo, TileCache::Entry(tile, m_resourceManager)); - } - m_tileCache.unlock(); -} - -void TileRenderer::StartTile(Tiler::RectInfo const & rectInfo) -{ - threads::MutexGuard g(m_tilesInProgressMutex); - m_tilesInProgress.insert(rectInfo); -} - -void TileRenderer::FinishTile(Tiler::RectInfo const & rectInfo) -{ - threads::MutexGuard g(m_tilesInProgressMutex); - m_tilesInProgress.erase(rectInfo); -} - void TileRenderer::SetIsPaused(bool flag) { m_isPaused = flag; } +void TileRenderer::AddActiveTile(Tile const & tile) +{ + m_tileSet.Lock(); + m_tileCache.Lock(); + + Tiler::RectInfo const & key = tile.m_rectInfo; + + if (m_tileSet.HasTile(key) || m_tileCache.HasTile(key)) + m_resourceManager->renderTargetTextures()->Free(tile.m_renderTarget); + else + { + m_tileSet.AddTile(tile); + + if (m_tileCache.CanFit() == 0) + { + LOG(LINFO, ("resizing tileCache to", m_tileCache.CacheSize() + 1, "elements")); + m_tileCache.Resize(m_tileCache.CacheSize() + 1); + } + + m_tileCache.AddTile(key, TileCache::Entry(tile, m_resourceManager)); + m_tileCache.LockTile(key); + } + + m_tileCache.Unlock(); + m_tileSet.Unlock(); +} + +void TileRenderer::RemoveActiveTile(Tiler::RectInfo const & rectInfo) +{ + m_tileSet.Lock(); + m_tileCache.Lock(); + + if (m_tileSet.HasTile(rectInfo)) + { + ASSERT(m_tileCache.HasTile(rectInfo), ()); + m_tileCache.UnlockTile(rectInfo); + m_tileSet.RemoveTile(rectInfo); + } + + m_tileCache.Unlock(); + m_tileSet.Unlock(); +} diff --git a/map/tile_renderer.hpp b/map/tile_renderer.hpp index 1918b70f2a..4caf485cf2 100644 --- a/map/tile_renderer.hpp +++ b/map/tile_renderer.hpp @@ -3,6 +3,7 @@ #include "render_policy.hpp" #include "tiler.hpp" #include "tile_cache.hpp" +#include "tile_set.hpp" #include "drawer_yg.hpp" #include "../geometry/screenbase.hpp" @@ -51,6 +52,10 @@ protected: TileCache m_tileCache; + /// set of already rendered tiles, which are waiting + /// for the CoverageGenerator to process them + TileSet m_tileSet; + RenderPolicy::TRenderFn m_renderFn; string m_skinName; yg::Color m_bgColor; @@ -92,6 +97,8 @@ public: core::CommandsQueue::Chain const & afterTileFns = core::CommandsQueue::Chain()); /// get tile cache. TileCache & GetTileCache(); + /// get tile set + TileSet & GetTileSet(); /// wait on a condition variable for an empty queue. void WaitForEmptyAndFinished(); @@ -102,10 +109,14 @@ public: void ClearCommands(); bool HasTile(Tiler::RectInfo const & rectInfo); - void AddTile(Tiler::RectInfo const & rectInfo, Tile const & tile); - void StartTile(Tiler::RectInfo const & rectInfo); - void FinishTile(Tiler::RectInfo const & rectInfo); + /// add tile to the temporary set of rendered tiles, cache it and lock it in the cache. + /// temporary set is necessary to carry the state between corresponding Tile rendering + /// commands and MergeTile commands. + void AddActiveTile(Tile const & tile); + /// remove tile from the TileSet. + /// @param doUpdateCache shows, whether we should + void RemoveActiveTile(Tiler::RectInfo const & rectInfo); void SetIsPaused(bool flag); }; diff --git a/map/tile_set.cpp b/map/tile_set.cpp new file mode 100644 index 0000000000..9c8236b4e1 --- /dev/null +++ b/map/tile_set.cpp @@ -0,0 +1,36 @@ +#include "tile_set.hpp" + +void TileSet::Lock() +{ + m_mutex.Lock(); +} + +void TileSet::Unlock() +{ + m_mutex.Unlock(); +} + +bool TileSet::HasTile(Tiler::RectInfo const & rectInfo) +{ + return m_tiles.find(rectInfo) != m_tiles.end(); +} + +void TileSet::AddTile(Tile const & tile) +{ + m_tiles[tile.m_rectInfo] = tile; +} + +void TileSet::RemoveTile(const Tiler::RectInfo &rectInfo) +{ + m_tiles.erase(rectInfo); +} + +Tile const & TileSet::GetTile(Tiler::RectInfo const & rectInfo) +{ + return m_tiles[rectInfo]; +} + +size_t TileSet::Size() const +{ + return m_tiles.size(); +} diff --git a/map/tile_set.hpp b/map/tile_set.hpp new file mode 100644 index 0000000000..2af97da01d --- /dev/null +++ b/map/tile_set.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include "tile.hpp" +#include "../base/mutex.hpp" +#include "../std/map.hpp" + +class TileSet +{ +private: + + typedef map TTiles; + + TTiles m_tiles; + + threads::Mutex m_mutex; + +public: + + /// lock TileSet for multithreaded access. + void Lock(); + /// unlock TileSet for multithreaded access. + void Unlock(); + /// do we have the specified tile + bool HasTile(Tiler::RectInfo const & rectInfo); + /// add tile to the set + void AddTile(Tile const & tile); + /// get tile from the set + Tile const & GetTile(Tiler::RectInfo const & rectInfo); + /// remove tile from the set + void RemoveTile(Tiler::RectInfo const & rectInfo); + /// get the size of TileSet + size_t Size() const; +}; diff --git a/map/tiling_render_policy_st.cpp b/map/tiling_render_policy_st.cpp index 142c003e6d..89128d7e32 100644 --- a/map/tiling_render_policy_st.cpp +++ b/map/tiling_render_policy_st.cpp @@ -60,7 +60,7 @@ TilingRenderPolicyST::TilingRenderPolicyST(VideoTimer * videoTimer, rmp.m_renderTargetTexturesParams = yg::ResourceManager::TexturePoolParams(GetPlatform().TileSize(), GetPlatform().TileSize(), - GetPlatform().CpuCores(), + 1, rmp.m_texRtFormat, true, true,