forked from organicmaps/organicmaps
fixed bug with race conditions for free TileCache space, which results in dropped-out tiles.
This commit is contained in:
parent
457a8ed689
commit
3b9252b881
13 changed files with 309 additions and 161 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<Tiler::RectInfo> k = tileCache.keys();
|
||||
set<Tiler::RectInfo> k = tileCache.Keys();
|
||||
|
||||
for (set<Tiler::RectInfo>::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, ());
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 += \
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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<Tiler::RectInfo> allRects;
|
||||
vector<Tiler::RectInfo> 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<Tiler::RectInfo> 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<Tile const*> 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<Tile const *>::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))
|
||||
|
|
|
@ -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<Tiler::RectInfo> TileRectSet;
|
||||
typedef set<Tiler::RectInfo> 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<Tile const *, LessRectInfo> TileSet;
|
||||
TileSet m_tiles;
|
||||
typedef set<Tile const *, LessRectInfo> TTileSet;
|
||||
TTileSet m_tiles;
|
||||
/// InfoLayer composed of infoLayers for visible tiles
|
||||
scoped_ptr<yg::InfoLayer> m_infoLayer;
|
||||
/// Does this coverage holds only tiles that are empty
|
||||
|
|
|
@ -16,22 +16,22 @@ TileCache::Entry::Entry(Tile const & tile, shared_ptr<yg::ResourceManager> 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<Tiler::RectInfo> const & TileCache::keys() const
|
||||
set<Tiler::RectInfo> const & TileCache::Keys() const
|
||||
{
|
||||
return m_cache.Keys();
|
||||
/* set<uint64_t> keys = m_cache.Keys();
|
||||
|
@ -47,57 +47,67 @@ set<Tiler::RectInfo> 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);
|
||||
}
|
||||
|
|
|
@ -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<Tiler::RectInfo> const & keys() const;
|
||||
set<Tiler::RectInfo> 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);
|
||||
};
|
||||
|
|
|
@ -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<yg::InfoLayer> 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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
36
map/tile_set.cpp
Normal file
36
map/tile_set.cpp
Normal file
|
@ -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();
|
||||
}
|
33
map/tile_set.hpp
Normal file
33
map/tile_set.hpp
Normal file
|
@ -0,0 +1,33 @@
|
|||
#pragma once
|
||||
|
||||
#include "tile.hpp"
|
||||
#include "../base/mutex.hpp"
|
||||
#include "../std/map.hpp"
|
||||
|
||||
class TileSet
|
||||
{
|
||||
private:
|
||||
|
||||
typedef map<Tiler::RectInfo, Tile> 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;
|
||||
};
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Reference in a new issue