forked from organicmaps/organicmaps-tmp
Optimizations of tiles tree and small bugfixes
This commit is contained in:
parent
0f239e8852
commit
c14d67c567
4 changed files with 150 additions and 139 deletions
|
@ -50,12 +50,17 @@ FrontendRenderer::FrontendRenderer(dp::RefPointer<ThreadsCommutator> commutator,
|
|||
RefreshProjection();
|
||||
RefreshModelView();
|
||||
|
||||
m_tileTree.SetHandlers(bind(&FrontendRenderer::OnAddRenderGroup, this, _1, _2, _3),
|
||||
bind(&FrontendRenderer::OnDeferRenderGroup, this, _1, _2, _3),
|
||||
bind(&FrontendRenderer::OnAddDeferredTile, this, _1, _2),
|
||||
bind(&FrontendRenderer::OnRemoveTile, this, _1, _2));
|
||||
StartThread();
|
||||
}
|
||||
|
||||
FrontendRenderer::~FrontendRenderer()
|
||||
{
|
||||
StopThread();
|
||||
m_tileTree.ResetHandlers();
|
||||
}
|
||||
|
||||
#ifdef DRAW_INFO
|
||||
|
@ -131,7 +136,11 @@ void FrontendRenderer::AcceptMessage(dp::RefPointer<Message> message)
|
|||
program->Bind();
|
||||
bucket->GetBuffer()->Build(program);
|
||||
if (!IsUserMarkLayer(key))
|
||||
CreateTileRenderGroup(state, bucket, key);
|
||||
{
|
||||
bool const result = m_tileTree.ProcessTile(key, state, bucket);
|
||||
if (!result)
|
||||
bucket.Destroy();
|
||||
}
|
||||
else
|
||||
{
|
||||
unique_ptr<UserMarkRenderGroup> & group = FindUserMarkRenderGroup(key, true);
|
||||
|
@ -146,7 +155,7 @@ void FrontendRenderer::AcceptMessage(dp::RefPointer<Message> message)
|
|||
TileReadEndMessage * msg = df::CastMessage<TileReadEndMessage>(message);
|
||||
TileKey const & key = msg->GetKey();
|
||||
if (!IsUserMarkLayer(key))
|
||||
FinishTileRenderGroup(key);
|
||||
m_tileTree.FinishTile(key);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -238,51 +247,6 @@ void FrontendRenderer::AcceptMessage(dp::RefPointer<Message> message)
|
|||
}
|
||||
}
|
||||
|
||||
void FrontendRenderer::CreateTileRenderGroup(dp::GLState const & state,
|
||||
dp::MasterPointer<dp::RenderBucket> & renderBucket,
|
||||
TileKey const & newTile)
|
||||
{
|
||||
// adding tiles to render
|
||||
auto onAddTile = [&state, &renderBucket, this](TileKey const & tileKey, TileStatus tileStatus)
|
||||
{
|
||||
if (tileStatus == TileStatus::Rendered)
|
||||
AddToRenderGroup(m_renderGroups, state, renderBucket, tileKey);
|
||||
else if (tileStatus == TileStatus::Deferred)
|
||||
OnAddDeferredTile(tileKey, tileStatus);
|
||||
else
|
||||
ASSERT(false, ());
|
||||
};
|
||||
|
||||
// deferring tiles
|
||||
auto onDeferTile = [&state, &renderBucket, this](TileKey const & tileKey, TileStatus tileStatus)
|
||||
{
|
||||
AddToRenderGroup(m_deferredRenderGroups, state, renderBucket, tileKey);
|
||||
};
|
||||
|
||||
// removing tiles
|
||||
auto onRemoveTile = [this](TileKey const & tileKey, TileStatus tileStatus)
|
||||
{
|
||||
OnRemoveTile(tileKey, tileStatus);
|
||||
};
|
||||
|
||||
bool const result = m_tileTree.ProcessTile(newTile, onAddTile, onRemoveTile, onDeferTile);
|
||||
if (!result)
|
||||
renderBucket.Destroy();
|
||||
}
|
||||
|
||||
void FrontendRenderer::FinishTileRenderGroup(TileKey const & newTile)
|
||||
{
|
||||
auto onRemoveTile = [this](TileKey const & tileKey, TileStatus tileStatus)
|
||||
{
|
||||
OnRemoveTile(tileKey, tileStatus);
|
||||
};
|
||||
auto onAddDeferredTile = [this](TileKey const & tileKey, TileStatus tileStatus)
|
||||
{
|
||||
OnAddDeferredTile(tileKey, tileStatus);
|
||||
};
|
||||
m_tileTree.FinishTile(newTile, onAddDeferredTile, onRemoveTile);
|
||||
}
|
||||
|
||||
void FrontendRenderer::AddToRenderGroup(vector<unique_ptr<RenderGroup>> & groups,
|
||||
dp::GLState const & state,
|
||||
dp::MasterPointer<dp::RenderBucket> & renderBucket,
|
||||
|
@ -293,6 +257,18 @@ void FrontendRenderer::AddToRenderGroup(vector<unique_ptr<RenderGroup>> & groups
|
|||
groups.emplace_back(move(group));
|
||||
}
|
||||
|
||||
void FrontendRenderer::OnAddRenderGroup(TileKey const & tileKey, dp::GLState const & state,
|
||||
dp::MasterPointer<dp::RenderBucket> & renderBucket)
|
||||
{
|
||||
AddToRenderGroup(m_renderGroups, state, renderBucket, tileKey);
|
||||
}
|
||||
|
||||
void FrontendRenderer::OnDeferRenderGroup(TileKey const & tileKey, dp::GLState const & state,
|
||||
dp::MasterPointer<dp::RenderBucket> & renderBucket)
|
||||
{
|
||||
AddToRenderGroup(m_deferredRenderGroups, state, renderBucket, tileKey);
|
||||
}
|
||||
|
||||
void FrontendRenderer::OnAddDeferredTile(TileKey const & tileKey, TileStatus tileStatus)
|
||||
{
|
||||
ASSERT(tileStatus == TileStatus::Deferred, ());
|
||||
|
@ -463,18 +439,10 @@ void FrontendRenderer::ResolveTileKeys(int tileScale)
|
|||
int const maxTileY = static_cast<int>(ceil(clipRect.maxY() / rectSize));
|
||||
|
||||
// clip all tiles which are out of viewport
|
||||
auto onRemoveTile = [this](TileKey const & tileKey, TileStatus tileStatus)
|
||||
{
|
||||
OnRemoveTile(tileKey, tileStatus);
|
||||
};
|
||||
auto onAddDeferredTile = [this](TileKey const & tileKey, TileStatus tileStatus)
|
||||
{
|
||||
OnAddDeferredTile(tileKey, tileStatus);
|
||||
};
|
||||
m_tileTree.ClipByRect(clipRect, onAddDeferredTile, onRemoveTile);
|
||||
m_tileTree.ClipByRect(clipRect);
|
||||
|
||||
// request new tiles
|
||||
m_tileTree.BeginRequesting(tileScale, onRemoveTile);
|
||||
m_tileTree.BeginRequesting(tileScale);
|
||||
for (int tileY = minTileY; tileY < maxTileY; ++tileY)
|
||||
{
|
||||
for (int tileX = minTileX; tileX < maxTileX; ++tileX)
|
||||
|
@ -484,7 +452,7 @@ void FrontendRenderer::ResolveTileKeys(int tileScale)
|
|||
m_tileTree.RequestTile(key);
|
||||
}
|
||||
}
|
||||
m_tileTree.EndRequesting(onRemoveTile);
|
||||
m_tileTree.EndRequesting();
|
||||
}
|
||||
|
||||
void FrontendRenderer::StartThread()
|
||||
|
|
|
@ -96,14 +96,14 @@ private:
|
|||
// it applies new model-view matrix to the scene (this matrix will be used on next frame)
|
||||
void UpdateScene();
|
||||
|
||||
void CreateTileRenderGroup(dp::GLState const & state,
|
||||
dp::MasterPointer<dp::RenderBucket> & renderBucket,
|
||||
TileKey const & newTile);
|
||||
void FinishTileRenderGroup(TileKey const & newTile);
|
||||
void AddToRenderGroup(vector<unique_ptr<RenderGroup>> & groups,
|
||||
dp::GLState const & state,
|
||||
dp::MasterPointer<dp::RenderBucket> & renderBucket,
|
||||
TileKey const & newTile);
|
||||
void OnAddRenderGroup(TileKey const & tileKey, dp::GLState const & state,
|
||||
dp::MasterPointer<dp::RenderBucket> & renderBucket);
|
||||
void OnDeferRenderGroup(TileKey const & tileKey, dp::GLState const & state,
|
||||
dp::MasterPointer<dp::RenderBucket> & renderBucket);
|
||||
|
||||
void OnAddDeferredTile(TileKey const & tileKey, TileStatus tileStatus);
|
||||
void OnRemoveTile(TileKey const & tileKey, TileStatus tileStatus);
|
||||
|
|
130
drape_frontend/tile_tree.cpp
Normal file → Executable file
130
drape_frontend/tile_tree.cpp
Normal file → Executable file
|
@ -14,6 +14,26 @@ TileTree::TileTree()
|
|||
TileTree::~TileTree()
|
||||
{
|
||||
m_root.reset();
|
||||
ResetHandlers();
|
||||
}
|
||||
|
||||
void TileTree::SetHandlers(TRenderGroupHandler const & addRenderGroup,
|
||||
TRenderGroupHandler const & deferRenderGroup,
|
||||
TTileHandler const & addDeferredTile,
|
||||
TTileHandler const & removeTile)
|
||||
{
|
||||
m_addRenderGroup = addRenderGroup;
|
||||
m_deferRenderGroup = deferRenderGroup;
|
||||
m_addDeferredTile = addDeferredTile;
|
||||
m_removeTile = removeTile;
|
||||
}
|
||||
|
||||
void TileTree::ResetHandlers()
|
||||
{
|
||||
m_addRenderGroup = nullptr;
|
||||
m_deferRenderGroup = nullptr;
|
||||
m_addDeferredTile = nullptr;
|
||||
m_removeTile = nullptr;
|
||||
}
|
||||
|
||||
void TileTree::Clear()
|
||||
|
@ -21,9 +41,9 @@ void TileTree::Clear()
|
|||
m_root.reset(new Node());
|
||||
}
|
||||
|
||||
void TileTree::BeginRequesting(int const zoomLevel, TTileHandler const & removeTile)
|
||||
void TileTree::BeginRequesting(int const zoomLevel)
|
||||
{
|
||||
AbortTiles(m_root, zoomLevel, removeTile);
|
||||
AbortTiles(m_root, zoomLevel);
|
||||
}
|
||||
|
||||
void TileTree::RequestTile(TileKey const & tileKey)
|
||||
|
@ -31,9 +51,9 @@ void TileTree::RequestTile(TileKey const & tileKey)
|
|||
InsertToNode(m_root, tileKey);
|
||||
}
|
||||
|
||||
void TileTree::EndRequesting(TTileHandler const & removeTile)
|
||||
void TileTree::EndRequesting()
|
||||
{
|
||||
SimplifyTree(removeTile);
|
||||
SimplifyTree();
|
||||
}
|
||||
|
||||
void TileTree::GetTilesCollection(TTilesCollection & tiles, int const zoomLevel)
|
||||
|
@ -41,31 +61,29 @@ void TileTree::GetTilesCollection(TTilesCollection & tiles, int const zoomLevel)
|
|||
FillTilesCollection(m_root, tiles, zoomLevel);
|
||||
}
|
||||
|
||||
void TileTree::ClipByRect(m2::RectD const & rect, TTileHandler const & addDeferredTile,
|
||||
TTileHandler const & removeTile)
|
||||
void TileTree::ClipByRect(m2::RectD const & rect)
|
||||
{
|
||||
ClipNode(m_root, rect, removeTile);
|
||||
CheckDeferredTiles(m_root, addDeferredTile, removeTile);
|
||||
SimplifyTree(removeTile);
|
||||
ClipNode(m_root, rect);
|
||||
CheckDeferredTiles(m_root);
|
||||
SimplifyTree();
|
||||
}
|
||||
|
||||
bool TileTree::ProcessTile(TileKey const & tileKey, TTileHandler const & addTile,
|
||||
TTileHandler const & removeTile, TTileHandler const & deferTile)
|
||||
bool TileTree::ProcessTile(TileKey const & tileKey, dp::GLState const & state,
|
||||
dp::MasterPointer<dp::RenderBucket> & bucket)
|
||||
{
|
||||
bool const result = ProcessNode(m_root, tileKey, addTile, removeTile, deferTile);
|
||||
bool const result = ProcessNode(m_root, tileKey, state, bucket);
|
||||
if (result)
|
||||
SimplifyTree(removeTile);
|
||||
SimplifyTree();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void TileTree::FinishTile(TileKey const & tileKey, TTileHandler const & addDeferredTile,
|
||||
TTileHandler const & removeTile)
|
||||
void TileTree::FinishTile(TileKey const & tileKey)
|
||||
{
|
||||
if (FinishNode(m_root, tileKey))
|
||||
{
|
||||
CheckDeferredTiles(m_root, addDeferredTile, removeTile);
|
||||
SimplifyTree(removeTile);
|
||||
CheckDeferredTiles(m_root);
|
||||
SimplifyTree();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,7 +171,7 @@ void TileTree::InsertToNode(TNodePtr const & node, TileKey const & tileKey)
|
|||
}
|
||||
}
|
||||
|
||||
void TileTree::AbortTiles(TNodePtr const & node, int const zoomLevel, TTileHandler const & removeTile)
|
||||
void TileTree::AbortTiles(TNodePtr const & node, int const zoomLevel)
|
||||
{
|
||||
for (auto it = node->m_children.begin(); it != node->m_children.end(); ++it)
|
||||
{
|
||||
|
@ -162,10 +180,10 @@ void TileTree::AbortTiles(TNodePtr const & node, int const zoomLevel, TTileHandl
|
|||
if ((*it)->m_tileStatus == TileStatus::Requested)
|
||||
(*it)->m_tileStatus = TileStatus::Unknown;
|
||||
else if ((*it)->m_tileStatus == TileStatus::Deferred)
|
||||
RemoveTile(*it, removeTile);
|
||||
RemoveTile(*it);
|
||||
}
|
||||
|
||||
AbortTiles(*it, zoomLevel, removeTile);
|
||||
AbortTiles(*it, zoomLevel);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -180,37 +198,36 @@ void TileTree::FillTilesCollection(TNodePtr const & node, TTilesCollection & til
|
|||
}
|
||||
}
|
||||
|
||||
void TileTree::ClipNode(TNodePtr const & node, m2::RectD const & rect, TTileHandler const & removeTile)
|
||||
void TileTree::ClipNode(TNodePtr const & node, m2::RectD const & rect)
|
||||
{
|
||||
for (auto it = node->m_children.begin(); it != node->m_children.end();)
|
||||
{
|
||||
m2::RectD const tileRect = (*it)->m_tileKey.GetGlobalRect();
|
||||
if(rect.IsIntersect(tileRect))
|
||||
{
|
||||
ClipNode(*it, rect, removeTile);
|
||||
ClipNode(*it, rect);
|
||||
++it;
|
||||
}
|
||||
else
|
||||
{
|
||||
RemoveTile(*it, removeTile);
|
||||
ClipNode(*it, rect, removeTile);
|
||||
RemoveTile(*it);
|
||||
ClipNode(*it, rect);
|
||||
it = node->m_children.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TileTree::RemoveTile(TNodePtr const & node, TTileHandler const & removeTile)
|
||||
void TileTree::RemoveTile(TNodePtr const & node)
|
||||
{
|
||||
if (removeTile != nullptr && !node->m_isRemoved)
|
||||
removeTile(node->m_tileKey, node->m_tileStatus);
|
||||
if (m_removeTile != nullptr && !node->m_isRemoved)
|
||||
m_removeTile(node->m_tileKey, node->m_tileStatus);
|
||||
|
||||
node->m_isRemoved = true;
|
||||
node->m_tileStatus = TileStatus::Unknown;
|
||||
}
|
||||
|
||||
bool TileTree::ProcessNode(TNodePtr const & node, TileKey const & tileKey,
|
||||
TTileHandler const & addTile, TTileHandler const & removeTile,
|
||||
TTileHandler const & deferTile)
|
||||
dp::GLState const & state, dp::MasterPointer<dp::RenderBucket> & bucket)
|
||||
{
|
||||
for (auto it = node->m_children.begin(); it != node->m_children.end(); ++it)
|
||||
{
|
||||
|
@ -219,28 +236,28 @@ bool TileTree::ProcessNode(TNodePtr const & node, TileKey const & tileKey,
|
|||
if ((*it)->m_tileStatus == TileStatus::Unknown)
|
||||
return false;
|
||||
|
||||
DeleteTilesBelow(*it, removeTile);
|
||||
DeleteTilesBelow(*it);
|
||||
|
||||
if (node->m_tileStatus == TileStatus::Rendered)
|
||||
{
|
||||
(*it)->m_tileStatus = TileStatus::Deferred;
|
||||
if (deferTile != nullptr)
|
||||
deferTile((*it)->m_tileKey, (*it)->m_tileStatus);
|
||||
if (m_deferRenderGroup != nullptr)
|
||||
m_deferRenderGroup((*it)->m_tileKey, state, bucket);
|
||||
(*it)->m_isRemoved = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
(*it)->m_tileStatus = TileStatus::Rendered;
|
||||
if (addTile != nullptr)
|
||||
addTile((*it)->m_tileKey, (*it)->m_tileStatus);
|
||||
if (m_addRenderGroup != nullptr)
|
||||
m_addRenderGroup((*it)->m_tileKey, state, bucket);
|
||||
(*it)->m_isRemoved = false;
|
||||
}
|
||||
|
||||
DeleteTilesAbove(node, addTile, removeTile);
|
||||
DeleteTilesAbove(node);
|
||||
return true;
|
||||
}
|
||||
else if (IsTileBelow((*it)->m_tileKey, tileKey))
|
||||
return ProcessNode(*it, tileKey, addTile, removeTile, deferTile);
|
||||
return ProcessNode(*it, tileKey, state, bucket);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -252,7 +269,10 @@ bool TileTree::FinishNode(TNodePtr const & node, TileKey const & tileKey)
|
|||
{
|
||||
if ((*it)->m_tileKey == tileKey && (*it)->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
|
||||
(*it)->m_tileStatus = TileStatus::Unknown;
|
||||
DeleteTilesBelow(*it);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
|
@ -261,17 +281,17 @@ bool TileTree::FinishNode(TNodePtr const & node, TileKey const & tileKey)
|
|||
return changed;
|
||||
}
|
||||
|
||||
void TileTree::DeleteTilesBelow(TNodePtr const & node, TTileHandler const & removeTile)
|
||||
void TileTree::DeleteTilesBelow(TNodePtr const & node)
|
||||
{
|
||||
for (auto it = node->m_children.begin(); it != node->m_children.end(); ++it)
|
||||
{
|
||||
RemoveTile(*it, removeTile);
|
||||
DeleteTilesBelow(*it, removeTile);
|
||||
RemoveTile(*it);
|
||||
DeleteTilesBelow(*it);
|
||||
}
|
||||
node->m_children.clear();
|
||||
}
|
||||
|
||||
void TileTree::DeleteTilesAbove(TNodePtr const & node, TTileHandler const & addTile, TTileHandler const & removeTile)
|
||||
void TileTree::DeleteTilesAbove(TNodePtr const & node)
|
||||
{
|
||||
if (node->m_tileStatus == TileStatus::Requested || node->m_children.empty())
|
||||
return;
|
||||
|
@ -286,8 +306,8 @@ void TileTree::DeleteTilesAbove(TNodePtr const & node, TTileHandler const & addT
|
|||
{
|
||||
if ((*it)->m_tileStatus == TileStatus::Deferred)
|
||||
{
|
||||
if (addTile != nullptr)
|
||||
addTile((*it)->m_tileKey, (*it)->m_tileStatus);
|
||||
if (m_addDeferredTile != nullptr)
|
||||
m_addDeferredTile((*it)->m_tileKey, (*it)->m_tileStatus);
|
||||
|
||||
(*it)->m_tileStatus = TileStatus::Rendered;
|
||||
(*it)->m_isRemoved = false;
|
||||
|
@ -296,16 +316,16 @@ void TileTree::DeleteTilesAbove(TNodePtr const & node, TTileHandler const & addT
|
|||
|
||||
// remove current tile
|
||||
if (node != m_root)
|
||||
RemoveTile(node, removeTile);
|
||||
RemoveTile(node);
|
||||
}
|
||||
|
||||
void TileTree::SimplifyTree(TTileHandler const & removeTile)
|
||||
void TileTree::SimplifyTree()
|
||||
{
|
||||
ClearEmptyLevels(m_root, removeTile);
|
||||
ClearObsoleteTiles(m_root, removeTile);
|
||||
ClearEmptyLevels(m_root);
|
||||
ClearObsoleteTiles(m_root);
|
||||
}
|
||||
|
||||
void TileTree::ClearEmptyLevels(TNodePtr const & node, TTileHandler const & removeTile)
|
||||
void TileTree::ClearEmptyLevels(TNodePtr const & node)
|
||||
{
|
||||
if (HaveChildrenSameStatus(node, TileStatus::Unknown))
|
||||
{
|
||||
|
@ -317,26 +337,26 @@ void TileTree::ClearEmptyLevels(TNodePtr const & node, TTileHandler const & remo
|
|||
list<TNodePtr> newChildren;
|
||||
for (auto it = node->m_children.begin(); it != node->m_children.end(); ++it)
|
||||
{
|
||||
RemoveTile(*it, removeTile);
|
||||
RemoveTile(*it);
|
||||
newChildren.splice(newChildren.begin(), (*it)->m_children);
|
||||
}
|
||||
node->m_children.swap(newChildren);
|
||||
}
|
||||
|
||||
for (auto it = node->m_children.begin(); it != node->m_children.end(); ++it)
|
||||
ClearEmptyLevels(*it, removeTile);
|
||||
ClearEmptyLevels(*it);
|
||||
}
|
||||
|
||||
bool TileTree::ClearObsoleteTiles(TNodePtr const & node, TTileHandler const & removeTile)
|
||||
bool TileTree::ClearObsoleteTiles(TNodePtr const & node)
|
||||
{
|
||||
bool canClear = true;
|
||||
for (auto it = node->m_children.begin(); it != node->m_children.end(); ++it)
|
||||
canClear &= ClearObsoleteTiles(*it, removeTile);
|
||||
canClear &= ClearObsoleteTiles(*it);
|
||||
|
||||
if (canClear)
|
||||
{
|
||||
for (auto it = node->m_children.begin(); it != node->m_children.end(); ++it)
|
||||
RemoveTile(*it, removeTile);
|
||||
RemoveTile(*it);
|
||||
|
||||
node->m_children.clear();
|
||||
}
|
||||
|
@ -375,12 +395,12 @@ bool TileTree::HaveGrandchildrenSameZoomLevel(TNodePtr const & node) const
|
|||
return true;
|
||||
}
|
||||
|
||||
void TileTree::CheckDeferredTiles(TNodePtr const & node, TTileHandler const & addTile, TTileHandler const & removeTile)
|
||||
void TileTree::CheckDeferredTiles(TNodePtr const & node)
|
||||
{
|
||||
for (auto it = node->m_children.begin(); it != node->m_children.end(); ++it)
|
||||
{
|
||||
DeleteTilesAbove(*it, addTile, removeTile);
|
||||
CheckDeferredTiles(*it, addTile, removeTile);
|
||||
DeleteTilesAbove(*it);
|
||||
CheckDeferredTiles(*it);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
67
drape_frontend/tile_tree.hpp
Normal file → Executable file
67
drape_frontend/tile_tree.hpp
Normal file → Executable file
|
@ -1,7 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
#include "tile_utils.hpp"
|
||||
#include "render_group.hpp"
|
||||
|
||||
#include "../drape/glstate.hpp"
|
||||
#include "../drape/pointers.hpp"
|
||||
#include "../geometry/rect2d.hpp"
|
||||
|
||||
#include "../std/function.hpp"
|
||||
|
@ -12,6 +15,7 @@
|
|||
namespace df
|
||||
{
|
||||
|
||||
/// this class implements K-d tree of visible tiles
|
||||
class TileTree
|
||||
{
|
||||
public:
|
||||
|
@ -19,21 +23,40 @@ public:
|
|||
~TileTree();
|
||||
|
||||
using TTileHandler = function<void(TileKey const &, TileStatus)>;
|
||||
using TRenderGroupHandler = function<void(TileKey const &, dp::GLState const &,
|
||||
dp::MasterPointer<dp::RenderBucket> &)>;
|
||||
|
||||
void BeginRequesting(int const zoomLevel, TTileHandler const & removeTile);
|
||||
/// addRenderGroup is called when render group can be created by a tile and rendered at once
|
||||
/// deferRenderGroup is called when render group can be created by a tile but has to be deferred
|
||||
/// addDeferredTile is called when previously deferred tile can be rendered
|
||||
/// removeTile is called when a tile must be removed from rendering
|
||||
void SetHandlers(TRenderGroupHandler const & addRenderGroup,
|
||||
TRenderGroupHandler const & deferRenderGroup,
|
||||
TTileHandler const & addDeferredTile,
|
||||
TTileHandler const & removeTile);
|
||||
void ResetHandlers();
|
||||
|
||||
/// this method must be called before requesting bunch of tiles
|
||||
void BeginRequesting(int const zoomLevel);
|
||||
/// request a new tile
|
||||
void RequestTile(TileKey const & tileKey);
|
||||
void EndRequesting(TTileHandler const & removeTile);
|
||||
/// this method must be called after requesting bunch of tiles
|
||||
void EndRequesting();
|
||||
|
||||
bool ProcessTile(TileKey const & tileKey, TTileHandler const & addTile,
|
||||
TTileHandler const & removeTile, TTileHandler const & deferTile);
|
||||
/// this method processes received from BR tile
|
||||
bool ProcessTile(TileKey const & tileKey, dp::GLState const & state,
|
||||
dp::MasterPointer<dp::RenderBucket> & bucket);
|
||||
/// this method processes a message about finishing tile on BR
|
||||
void FinishTile(TileKey const & tileKey);
|
||||
|
||||
void FinishTile(TileKey const & tileKey, TTileHandler const & addDeferredTile,
|
||||
TTileHandler const & removeTile);
|
||||
/// this method performs clipping by rectangle
|
||||
void ClipByRect(m2::RectD const & rect);
|
||||
|
||||
void ClipByRect(m2::RectD const & rect, TTileHandler const & addDeferredTile,
|
||||
TTileHandler const & removeTile);
|
||||
/// clear all entire structure of tree. DO NOT call removeTile handlers,
|
||||
/// so all external storages of tiles must be cleared manually
|
||||
void Clear();
|
||||
|
||||
/// it returns actual tile collection to send to BR
|
||||
void GetTilesCollection(TTilesCollection & tiles, int const zoomLevel);
|
||||
|
||||
private:
|
||||
|
@ -41,29 +64,25 @@ private:
|
|||
using TNodePtr = unique_ptr<Node>;
|
||||
|
||||
void InsertToNode(TNodePtr const & node, TileKey const & tileKey);
|
||||
void AbortTiles(TNodePtr const & node, int const zoomLevel, TTileHandler const & removeTile);
|
||||
void AbortTiles(TNodePtr const & node, int const zoomLevel);
|
||||
|
||||
void FillTilesCollection(TNodePtr const & node, TTilesCollection & tiles, int const zoomLevel);
|
||||
|
||||
void ClipNode(TNodePtr const & node, m2::RectD const & rect,
|
||||
TTileHandler const & removeTile);
|
||||
void CheckDeferredTiles(TNodePtr const & node, TTileHandler const & addTile,
|
||||
TTileHandler const & removeTile);
|
||||
void ClipNode(TNodePtr const & node, m2::RectD const & rect);
|
||||
void CheckDeferredTiles(TNodePtr const & node);
|
||||
|
||||
void RemoveTile(TNodePtr const & node, TTileHandler const & removeTile);
|
||||
void RemoveTile(TNodePtr const & node);
|
||||
|
||||
bool ProcessNode(TNodePtr const & node, TileKey const & tileKey,
|
||||
TTileHandler const & addTile, TTileHandler const & removeTile,
|
||||
TTileHandler const & deferTile);
|
||||
dp::GLState const & state, dp::MasterPointer<dp::RenderBucket> & bucket);
|
||||
bool FinishNode(TNodePtr const & node, TileKey const & tileKey);
|
||||
|
||||
void DeleteTilesBelow(TNodePtr const & node, TTileHandler const & removeTile);
|
||||
void DeleteTilesAbove(TNodePtr const & node, TTileHandler const & addTile,
|
||||
TTileHandler const & removeTile);
|
||||
void DeleteTilesBelow(TNodePtr const & node);
|
||||
void DeleteTilesAbove(TNodePtr const & node);
|
||||
|
||||
void SimplifyTree(TTileHandler const & removeTile);
|
||||
void ClearEmptyLevels(TNodePtr const & node, TTileHandler const & removeTile);
|
||||
bool ClearObsoleteTiles(TNodePtr const & node, TTileHandler const & removeTile);
|
||||
void SimplifyTree();
|
||||
void ClearEmptyLevels(TNodePtr const & node);
|
||||
bool ClearObsoleteTiles(TNodePtr const & node);
|
||||
|
||||
bool HaveChildrenSameStatus(TNodePtr const & node, TileStatus tileStatus) const;
|
||||
bool HaveGrandchildrenSameZoomLevel(TNodePtr const & node) const;
|
||||
|
@ -83,6 +102,10 @@ private:
|
|||
};
|
||||
|
||||
TNodePtr m_root;
|
||||
TRenderGroupHandler m_addRenderGroup;
|
||||
TRenderGroupHandler m_deferRenderGroup;
|
||||
TTileHandler m_addDeferredTile;
|
||||
TTileHandler m_removeTile;
|
||||
|
||||
private:
|
||||
friend void DebugPrintNode(TileTree::TNodePtr const & node, ostringstream & out, string const & offset);
|
||||
|
|
Loading…
Add table
Reference in a new issue