fixed bug with race conditions for free TileCache space, which results in dropped-out tiles.

This commit is contained in:
rachytski 2012-04-16 23:47:02 +04:00 committed by Alex Zolotarev
parent 457a8ed689
commit 3b9252b881
13 changed files with 309 additions and 161 deletions

View file

@ -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;
}

View file

@ -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, ());

View file

@ -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);

View file

@ -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 += \

View file

@ -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))

View file

@ -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

View file

@ -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);
}

View file

@ -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);
};

View file

@ -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();
}

View file

@ -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
View 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
View 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;
};

View file

@ -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,