diff --git a/drape/batcher.hpp b/drape/batcher.hpp index 82b6d835bc..9afcabe681 100644 --- a/drape/batcher.hpp +++ b/drape/batcher.hpp @@ -22,6 +22,11 @@ public: Batcher(uint32_t indexBufferSize = 9000, uint32_t vertexBufferSize = 10000); ~Batcher(); + uint32_t GetIndexBufferSize() const { return m_indexBufferSize; } + uint32_t GetVertexBufferSize() const { return m_vertexBufferSize; } + void SetIndexBufferSize(uint32_t indexBufferSize) { m_indexBufferSize = indexBufferSize; } + void SetVertexBufferSize(uint32_t vertexBufferSize) { m_vertexBufferSize = vertexBufferSize; } + void InsertTriangleList(GLState const & state, RefPointer params); void InsertTriangleList(GLState const & state, RefPointer params, TransferPointer handle); diff --git a/drape/batcher_helpers.cpp b/drape/batcher_helpers.cpp index 3b92aaec37..69a872fed2 100644 --- a/drape/batcher_helpers.cpp +++ b/drape/batcher_helpers.cpp @@ -166,6 +166,7 @@ void TriangleListBatch::BatchData(RefPointer streams) { while (streams->IsDataExists()) { + ChangeBuffer(true); uint16_t avVertex = GetAvailableVertexCount(); uint16_t avIndex = GetAvailableIndexCount(); uint16_t vertexCount = streams->GetVertexCount(); @@ -193,7 +194,6 @@ void TriangleListBatch::BatchData(RefPointer streams) FlushData(streams, vertexCount); streams->Advance(vertexCount); - ChangeBuffer(true); } } @@ -296,13 +296,13 @@ void TriangleStripBatch::BatchData(RefPointer streams) { while (streams->IsDataExists()) { + ChangeBuffer(true); uint16_t const batchVertexCount = BatchIndexes(streams->GetVertexCount()); FlushData(streams, batchVertexCount); uint16_t const advanceCount = IsFullUploaded() ? batchVertexCount : (batchVertexCount - 2); streams->Advance(advanceCount); - ChangeBuffer(true); } } @@ -417,11 +417,10 @@ void TriangleListOfStripBatch::BatchData(RefPointer streams) { while (streams->IsDataExists()) { + ChangeBuffer(true); uint16_t const batchVertexCount = BatchIndexes(streams->GetVertexCount()); FlushData(streams, batchVertexCount); streams->Advance(batchVertexCount); - - ChangeBuffer(true); } } diff --git a/drape/glstate.hpp b/drape/glstate.hpp index 32da30401e..d372e87c05 100644 --- a/drape/glstate.hpp +++ b/drape/glstate.hpp @@ -31,7 +31,8 @@ public: /// Do not change order GeometryLayer, DynamicGeometry, - OverlayLayer + OverlayLayer, + UserMarkLayer }; GLState(uint32_t gpuProgramIndex, DepthLayer depthLayer); diff --git a/drape_frontend/backend_renderer.cpp b/drape_frontend/backend_renderer.cpp index d3bf5bdc7b..6ccaf37ace 100644 --- a/drape_frontend/backend_renderer.cpp +++ b/drape_frontend/backend_renderer.cpp @@ -3,6 +3,7 @@ #include "drape_frontend/batchers_pool.hpp" #include "drape_frontend/visual_params.hpp" #include "drape_frontend/map_shape.hpp" +#include "drape_frontend/user_mark_shapes.hpp" #include "drape_frontend/threads_commutator.hpp" #include "drape_frontend/message_subclasses.hpp" @@ -73,8 +74,21 @@ void BackendRenderer::AcceptMessage(dp::RefPointer message) shape->Draw(batcher, m_textures.GetRefPointer()); shape.Destroy(); + break; + } + case Message::UpdateUserMarkLayer: + { + UpdateUserMarkLayerMessage * msg = df::CastMessage(message); + TileKey const & key = msg->GetKey(); + m_batchersPool->ReserveBatcher(key); + + UserMarksProvider const * marksProvider = msg->StartProcess(); + if (marksProvider->IsDirty()) + CacheUserMarks(marksProvider, m_batchersPool->GetTileBatcher(key), m_textures.GetRefPointer()); + msg->EndProcess(); + m_batchersPool->ReleaseBatcher(key); + break; } - break; default: ASSERT(false, ()); break; diff --git a/drape_frontend/drape_engine.cpp b/drape_frontend/drape_engine.cpp index 9a18f2c906..0917cd3b55 100644 --- a/drape_frontend/drape_engine.cpp +++ b/drape_frontend/drape_engine.cpp @@ -52,4 +52,22 @@ void DrapeEngine::UpdateCoverage(ScreenBase const & screen) dp::MovePointer(new UpdateModelViewMessage(screen))); } +void DrapeEngine::ClearUserMarksLayer(df::TileKey const & tileKey) +{ + m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread, + dp::MovePointer(new ClearUserMarkLayerMessage(tileKey))); +} + +void DrapeEngine::ChangeVisibilityUserMarksLayer(TileKey const & tileKey, bool isVisible) +{ + m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread, + dp::MovePointer(new ChangeUserMarkLayerVisibilityMessage(tileKey, isVisible))); +} + +void DrapeEngine::UpdateUserMarksLayer(TileKey const & tileKey, UserMarksProvider * provider) +{ + m_threadCommutator->PostMessage(ThreadsCommutator::ResourceUploadThread, + dp::MovePointer(new UpdateUserMarkLayerMessage(tileKey, provider))); +} + } // namespace df diff --git a/drape_frontend/drape_engine.hpp b/drape_frontend/drape_engine.hpp index 3bf7e0976c..ad2e260464 100644 --- a/drape_frontend/drape_engine.hpp +++ b/drape_frontend/drape_engine.hpp @@ -14,8 +14,10 @@ namespace dp { class OGLContextFactory; } namespace df { +class UserMarksProvider; class MapDataProvider; class Viewport; + class DrapeEngine { public: @@ -27,6 +29,10 @@ public: void Resize(int w, int h); void UpdateCoverage(ScreenBase const & screen); + void ClearUserMarksLayer(TileKey const & tileKey); + void ChangeVisibilityUserMarksLayer(TileKey const & tileKey, bool isVisible); + void UpdateUserMarksLayer(TileKey const & tileKey, UserMarksProvider * provider); + private: dp::MasterPointer m_frontend; dp::MasterPointer m_backend; diff --git a/drape_frontend/drape_frontend.pro b/drape_frontend/drape_frontend.pro index 8a016c2a84..a0183c5e5a 100644 --- a/drape_frontend/drape_frontend.pro +++ b/drape_frontend/drape_frontend.pro @@ -38,6 +38,8 @@ SOURCES += \ path_symbol_shape.cpp \ text_layout.cpp \ map_data_provider.cpp \ + user_mark_shapes.cpp \ + user_marks_provider.cpp \ HEADERS += \ engine_context.hpp \ @@ -74,3 +76,5 @@ HEADERS += \ text_layout.hpp \ intrusive_vector.hpp \ map_data_provider.hpp \ + user_mark_shapes.hpp \ + user_marks_provider.hpp \ diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index 8d0c1ccb27..55b8dcfa30 100644 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -1,6 +1,7 @@ #include "drape_frontend/frontend_renderer.hpp" #include "drape_frontend/message_subclasses.hpp" #include "drape_frontend/visual_params.hpp" +#include "drape_frontend/user_mark_shapes.hpp" #include "drape/utils/projection.hpp" @@ -81,6 +82,29 @@ void FrontendRenderer::AfterDrawFrame() } #endif +UserMarkRenderGroup * FrontendRenderer::FindUserMarkRenderGroup(TileKey const & tileKey, bool createIfNeed) +{ + auto it = find_if(m_userMarkRenderGroups.begin(), m_userMarkRenderGroups.end(), [&tileKey](UserMarkRenderGroup * g) + { + return g->GetTileKey() == tileKey; + }); + + if (it != m_userMarkRenderGroups.end()) + { + ASSERT((*it) != nullptr, ()); + return *it; + } + + if (createIfNeed) + { + UserMarkRenderGroup * group = new UserMarkRenderGroup(dp::GLState(0, dp::GLState::UserMarkLayer), tileKey); + m_userMarkRenderGroups.push_back(group); + return group; + } + + return nullptr; +} + void FrontendRenderer::AcceptMessage(dp::RefPointer message) { switch (message->GetType()) @@ -94,9 +118,18 @@ void FrontendRenderer::AcceptMessage(dp::RefPointer message) dp::RefPointer program = m_gpuProgramManager->GetProgram(state.GetProgramIndex()); program->Bind(); bucket->GetBuffer()->Build(program); - RenderGroup * group = new RenderGroup(state, key); - group->AddBucket(bucket.Move()); - m_renderGroups.push_back(group); + if (!IsUserMarkLayer(key)) + { + RenderGroup * group = new RenderGroup(state, key); + group->AddBucket(bucket.Move()); + m_renderGroups.push_back(group); + } + else + { + UserMarkRenderGroup * group = FindUserMarkRenderGroup(key, true); + ASSERT(group != nullptr, ()); + group->SetRenderBucket(state, bucket.Move()); + } break; } @@ -139,6 +172,33 @@ void FrontendRenderer::AcceptMessage(dp::RefPointer message) break; } + case Message::ClearUserMarkLayer: + { + TileKey const & tileKey = df::CastMessage(message)->GetKey(); + auto it = find_if(m_userMarkRenderGroups.begin(), m_userMarkRenderGroups.end(), [&tileKey](UserMarkRenderGroup * g) + { + return g->GetTileKey() == tileKey; + }); + + if (it != m_userMarkRenderGroups.end()) + { + UserMarkRenderGroup * group = *it; + ASSERT(group != nullptr, ()); + m_userMarkRenderGroups.erase(it); + delete group; + } + + break; + } + case Message::ChangeUserMarkLayerVisibility: + { + ChangeUserMarkLayerVisibilityMessage * m = df::CastMessage(message); + UserMarkRenderGroup * group = FindUserMarkRenderGroup(m->GetKey(), true); + ASSERT(group != nullptr, ()); + group->SetIsVisible(m->IsVisible()); + break; + } + default: ASSERT(false, ()); } @@ -150,8 +210,8 @@ void FrontendRenderer::RenderScene() BeforeDrawFrame(); #endif - RenderBucketComparator comparator(GetTileKeyStorage()); - sort(m_renderGroups.begin(), m_renderGroups.end(), bind(&RenderBucketComparator::operator (), &comparator, _1, _2)); + RenderGroupComparator comparator(GetTileKeyStorage()); + sort(m_renderGroups.begin(), m_renderGroups.end(), bind(&RenderGroupComparator::operator (), &comparator, _1, _2)); m_overlayTree.StartOverlayPlacing(m_view); size_t eraseCount = 0; @@ -213,6 +273,22 @@ void FrontendRenderer::RenderScene() group->Render(m_view); } + GLFunctions::glClearDepth(); + + for (UserMarkRenderGroup * group : m_userMarkRenderGroups) + { + ASSERT(group != nullptr, ()); + if (group->IsVisible()) + { + dp::GLState const & state = group->GetState(); + dp::RefPointer program = m_gpuProgramManager->GetProgram(state.GetProgramIndex()); + program->Bind(); + ApplyUniforms(m_generalUniforms, program); + ApplyState(state, program); + group->Render(m_view); + } + } + #ifdef DRAW_INFO AfterDrawFrame(); #endif @@ -348,7 +424,8 @@ void FrontendRenderer::ReleaseResources() void FrontendRenderer::DeleteRenderData() { - (void)GetRangeDeletor(m_renderGroups, DeleteFunctor())(); + DeleteRange(m_renderGroups, DeleteFunctor()); + DeleteRange(m_userMarkRenderGroups, DeleteFunctor()); } } // namespace df diff --git a/drape_frontend/frontend_renderer.hpp b/drape_frontend/frontend_renderer.hpp index 3ee45192a4..0979d1d34c 100644 --- a/drape_frontend/frontend_renderer.hpp +++ b/drape_frontend/frontend_renderer.hpp @@ -68,6 +68,7 @@ private: set & GetTileKeyStorage(); void InvalidateRenderGroups(set & keyStorage); + UserMarkRenderGroup * FindUserMarkRenderGroup(TileKey const & tileKey, bool createIfNeed); private: class Routine : public threads::IRoutine @@ -97,6 +98,7 @@ private: private: vector m_renderGroups; + vector m_userMarkRenderGroups; dp::UniformValuesStorage m_generalUniforms; diff --git a/drape_frontend/message.hpp b/drape_frontend/message.hpp index 73092796f1..13a8eb1d9e 100644 --- a/drape_frontend/message.hpp +++ b/drape_frontend/message.hpp @@ -20,7 +20,9 @@ public: InvalidateRect, InvalidateReadManagerRect, Resize, - Rotate + ClearUserMarkLayer, + ChangeUserMarkLayerVisibility, + UpdateUserMarkLayer }; Message(); diff --git a/drape_frontend/message_subclasses.hpp b/drape_frontend/message_subclasses.hpp index 2d90b90cec..15e58954b6 100644 --- a/drape_frontend/message_subclasses.hpp +++ b/drape_frontend/message_subclasses.hpp @@ -3,6 +3,7 @@ #include "drape_frontend/message.hpp" #include "drape_frontend/viewport.hpp" #include "drape_frontend/tile_key.hpp" +#include "drape_frontend/user_marks_provider.hpp" #include "geometry/rect2d.hpp" #include "geometry/screenbase.hpp" @@ -150,4 +151,66 @@ T * CastMessage(dp::RefPointer msg) return static_cast(msg.GetRaw()); } +class ClearUserMarkLayerMessage : public BaseTileMessage +{ +public: + ClearUserMarkLayerMessage(TileKey const & tileKey) + : BaseTileMessage(tileKey, Message::ClearUserMarkLayer) {} +}; + +class ChangeUserMarkLayerVisibilityMessage : public BaseTileMessage +{ +public: + ChangeUserMarkLayerVisibilityMessage(TileKey const & tileKey, bool isVisible) + : BaseTileMessage(tileKey, Message::ChangeUserMarkLayerVisibility) + , m_isVisible(isVisible) {} + +bool IsVisible() const { return m_isVisible; } + +private: + bool m_isVisible; +}; + +class UpdateUserMarkLayerMessage : public BaseTileMessage +{ +public: + UpdateUserMarkLayerMessage(TileKey const & tileKey, UserMarksProvider * provider) + : BaseTileMessage(tileKey, Message::UpdateUserMarkLayer) + , m_provider(provider) + { + m_provider->IncrementCounter(); + } + + ~UpdateUserMarkLayerMessage() + { + ASSERT(m_inProcess == false, ()); + m_provider->DecrementCounter(); + if (m_provider->IsPendingOnDelete() && m_provider->CanBeDeleted()) + delete m_provider; + } + + UserMarksProvider const * StartProcess() + { + m_provider->BeginRead(); +#ifdef DEBUG + m_inProcess = true; +#endif + return m_provider; + } + + void EndProcess() + { +#ifdef DEBUG + m_inProcess = false; +#endif + m_provider->EndRead(); + } + +private: + UserMarksProvider * m_provider; +#ifdef DEBUG + bool m_inProcess; +#endif +}; + } // namespace df diff --git a/drape_frontend/render_group.cpp b/drape_frontend/render_group.cpp index 9cd57441d8..c88df78dd7 100644 --- a/drape_frontend/render_group.cpp +++ b/drape_frontend/render_group.cpp @@ -9,8 +9,7 @@ namespace df { RenderGroup::RenderGroup(dp::GLState const & state, df::TileKey const & tileKey) - : m_state(state) - , m_tileKey(tileKey) + : TBase(state, tileKey) , m_pendingOnDelete(false) { } @@ -56,20 +55,20 @@ bool RenderGroup::IsLess(RenderGroup const & other) const return m_state < other.m_state; } -RenderBucketComparator::RenderBucketComparator(set const & activeTiles) +RenderGroupComparator::RenderGroupComparator(set const & activeTiles) : m_activeTiles(activeTiles) , m_needGroupMergeOperation(false) , m_needBucketsMergeOperation(false) { } -void RenderBucketComparator::ResetInternalState() +void RenderGroupComparator::ResetInternalState() { m_needBucketsMergeOperation = false; m_needGroupMergeOperation = false; } -bool RenderBucketComparator::operator()(RenderGroup const * l, RenderGroup const * r) +bool RenderGroupComparator::operator()(RenderGroup const * l, RenderGroup const * r) { dp::GLState const & lState = l->GetState(); dp::GLState const & rState = r->GetState(); @@ -98,4 +97,37 @@ bool RenderBucketComparator::operator()(RenderGroup const * l, RenderGroup const return false; } +UserMarkRenderGroup::UserMarkRenderGroup(dp::GLState const & state, TileKey const & tileKey) + : TBase(state, tileKey) + , m_isVisible(true) +{ +} + +UserMarkRenderGroup::~UserMarkRenderGroup() +{ + m_renderBucket.Destroy(); +} + +void UserMarkRenderGroup::SetIsVisible(bool isVisible) +{ + m_isVisible = isVisible; +} + +bool UserMarkRenderGroup::IsVisible() +{ + return m_isVisible && !m_renderBucket.IsNull(); +} + +void UserMarkRenderGroup::SetRenderBucket(dp::GLState const & state, dp::TransferPointer bucket) +{ + m_state = state; + m_renderBucket = dp::MasterPointer(bucket); +} + +void UserMarkRenderGroup::Render(ScreenBase const & screen) +{ + if (!m_renderBucket.IsNull()) + m_renderBucket->Render(screen); +} + } // namespace df diff --git a/drape_frontend/render_group.hpp b/drape_frontend/render_group.hpp index 571a627a49..1888dce930 100644 --- a/drape_frontend/render_group.hpp +++ b/drape_frontend/render_group.hpp @@ -15,8 +15,26 @@ namespace dp { class OverlayTree; } namespace df { -class RenderGroup +class BaseRenderGroup { +public: + BaseRenderGroup(dp::GLState const & state, TileKey const & tileKey) + : m_state(state) + , m_tileKey(tileKey) {} + + dp::GLState const & GetState() const { return m_state; } + TileKey const & GetTileKey() const { return m_tileKey; } + +protected: + dp::GLState m_state; + +private: + TileKey m_tileKey; +}; + +class RenderGroup : public BaseRenderGroup +{ + typedef BaseRenderGroup TBase; public: RenderGroup(dp::GLState const & state, TileKey const & tileKey); ~RenderGroup(); @@ -28,9 +46,6 @@ public: void PrepareForAdd(size_t countForAdd); void AddBucket(dp::TransferPointer bucket); - dp::GLState const & GetState() const { return m_state; } - TileKey const & GetTileKey() const { return m_tileKey; } - bool IsEmpty() const { return m_renderBuckets.empty(); } void DeleteLater() const { m_pendingOnDelete = true; } bool IsPendingOnDelete() const { return m_pendingOnDelete; } @@ -38,17 +53,15 @@ public: bool IsLess(RenderGroup const & other) const; private: - dp::GLState m_state; - TileKey m_tileKey; vector > m_renderBuckets; mutable bool m_pendingOnDelete; }; -class RenderBucketComparator +class RenderGroupComparator { public: - RenderBucketComparator(set const & activeTiles); + RenderGroupComparator(set const & activeTiles); void ResetInternalState(); @@ -60,4 +73,24 @@ private: bool m_needBucketsMergeOperation; }; +class UserMarkRenderGroup : public BaseRenderGroup +{ + typedef BaseRenderGroup TBase; + +public: + UserMarkRenderGroup(dp::GLState const & state, TileKey const & tileKey); + ~UserMarkRenderGroup(); + + void SetIsVisible(bool isVisible); + bool IsVisible(); + + void Clear(); + void SetRenderBucket(dp::GLState const & state, dp::TransferPointer bucket); + void Render(ScreenBase const & screen); + +private: + bool m_isVisible; + dp::MasterPointer m_renderBucket; +}; + } // namespace df diff --git a/drape_frontend/user_mark_shapes.cpp b/drape_frontend/user_mark_shapes.cpp new file mode 100644 index 0000000000..db6d63da0a --- /dev/null +++ b/drape_frontend/user_mark_shapes.cpp @@ -0,0 +1,121 @@ +#include "user_mark_shapes.hpp" + +#include "../drape/utils/vertex_decl.hpp" +#include "../drape/shader_def.hpp" +#include "../drape/attribute_provider.hpp" + +namespace df +{ + +namespace +{ + int const ZUserMarksLayer = -1; + int const YSearchMarksLayer = 1; + int const YApiMarksLayer = 2; + int const YBookmarksLayer = 3; +} + +TileKey GetSearchTileKey() +{ + return TileKey(0, YSearchMarksLayer, ZUserMarksLayer); +} + +TileKey GetApiTileKey() +{ + return TileKey(0, YApiMarksLayer, ZUserMarksLayer); +} + +TileKey GetBookmarkTileKey(size_t categoryIndex) +{ + return TileKey(categoryIndex, YBookmarksLayer, ZUserMarksLayer); +} + +bool IsUserMarkLayer(TileKey const & tileKey) +{ + return tileKey.m_zoomLevel == ZUserMarksLayer; +} + +namespace +{ + template + void AlignFormingNormals(TCreateVector const & fn, dp::Anchor anchor, + dp::Anchor first, dp::Anchor second, + glsl::vec2 & firstNormal, glsl::vec2 & secondNormal) + { + firstNormal = fn(); + secondNormal = -firstNormal; + if ((anchor & second) != 0) + { + firstNormal *= 2; + secondNormal = glsl::vec2(0.0, 0.0); + } + else if ((anchor & first) != 0) + { + firstNormal = glsl::vec2(0.0, 0.0); + secondNormal *= 2; + } + } + + void AlignHorizontal(float halfWidth, dp::Anchor anchor, + glsl::vec2 & left, glsl::vec2 & right) + { + AlignFormingNormals([&halfWidth]{ return glsl::vec2(-halfWidth, 0.0f); }, anchor, dp::Left, dp::Right, left, right); + } + + void AlignVertical(float halfHeight, dp::Anchor anchor, + glsl::vec2 & up, glsl::vec2 & down) + { + AlignFormingNormals([&halfHeight]{ return glsl::vec2(0.0f, -halfHeight); }, anchor, dp::Top, dp::Bottom, up, down); + } +} + +void CacheUserMarks(UserMarksProvider const * provider, + dp::RefPointer batcher, + dp::RefPointer textures) +{ + size_t markCount = provider->GetCount(); + if (markCount == 0) + return; + + uint32_t vertexCount = 4 * markCount; // 4 vertex per quad + uint32_t indexCount = 6 * markCount; // 6 index on one quad + + uint32_t savedIndSize = batcher->GetIndexBufferSize(); + uint32_t savedVerSize = batcher->GetVertexBufferSize(); + batcher->SetIndexBufferSize(indexCount); + batcher->SetVertexBufferSize(vertexCount); + + buffer_vector buffer; + buffer.reserve(vertexCount); + + dp::TextureManager::SymbolRegion region; + for (size_t i = 0; i < markCount; ++i) + { + textures->GetSymbolRegion(provider->GetSymbolName(i), region); + m2::RectF const & texRect = region.GetTexRect(); + m2::PointF pxSize = region.GetPixelSize(); + dp::Anchor anchor = provider->GetAnchor(i); + glsl::vec3 pos = glsl::vec3(glsl::ToVec2(provider->GetPivot(i)), provider->GetDepth(i)); + + glsl::vec2 left, right, up, down; + AlignHorizontal(pxSize.x * 0.5f, anchor, left, right); + AlignVertical(pxSize.y * 0.5f, anchor, up, down); + + buffer.push_back(gpu::SolidTexturingVertex(pos, left + down, glsl::ToVec2(texRect.LeftTop()))); + buffer.push_back(gpu::SolidTexturingVertex(pos, left + up, glsl::ToVec2(texRect.LeftBottom()))); + buffer.push_back(gpu::SolidTexturingVertex(pos, right + down, glsl::ToVec2(texRect.RightTop()))); + buffer.push_back(gpu::SolidTexturingVertex(pos, right + up, glsl::ToVec2(texRect.RightBottom()))); + } + + dp::GLState state(gpu::TEXTURING_PROGRAM, dp::GLState::UserMarkLayer); + state.SetBlending(true); + state.SetColorTexture(region.GetTexture()); + dp::AttributeProvider attribProvider(1, buffer.size()); + attribProvider.InitStream(0, gpu::SolidTexturingVertex::GetBindingInfo(), dp::MakeStackRefPointer(buffer.data())); + batcher->InsertListOfStrip(state, dp::MakeStackRefPointer(&attribProvider), 4); + + batcher->SetIndexBufferSize(savedIndSize); + batcher->SetVertexBufferSize(savedVerSize); +} + +} // namespace df diff --git a/drape_frontend/user_mark_shapes.hpp b/drape_frontend/user_mark_shapes.hpp new file mode 100644 index 0000000000..e12c755c63 --- /dev/null +++ b/drape_frontend/user_mark_shapes.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "tile_key.hpp" +#include "user_marks_provider.hpp" + +#include "../drape/batcher.hpp" +#include "../drape/texture_manager.hpp" + +#include "../geometry/point2d.hpp" + +#include "../std/function.hpp" + +namespace df +{ + TileKey GetSearchTileKey(); + TileKey GetApiTileKey(); + TileKey GetBookmarkTileKey(size_t categoryIndex); + bool IsUserMarkLayer(const TileKey & tileKey); + + void CacheUserMarks(UserMarksProvider const * provider, dp::RefPointer batcher, + dp::RefPointer textures); +} // namespace df diff --git a/drape_frontend/user_marks_provider.cpp b/drape_frontend/user_marks_provider.cpp new file mode 100644 index 0000000000..5cb7ab74ab --- /dev/null +++ b/drape_frontend/user_marks_provider.cpp @@ -0,0 +1,76 @@ +#include "user_marks_provider.hpp" + +df::UserMarksProvider::UserMarksProvider() + : m_pendingOnDelete(false) + , m_counter(0) +{ +} + +void df::UserMarksProvider::BeginRead() +{ + Lock(); +} + +bool df::UserMarksProvider::IsDirty() const +{ + return m_isDirty; +} + +void df::UserMarksProvider::EndRead() +{ + m_isDirty = false; + Unlock(); +} + +void df::UserMarksProvider::IncrementCounter() +{ + ASSERT(m_pendingOnDelete == false, ()); + ++m_counter; +} + +void df::UserMarksProvider::DecrementCounter() +{ + ASSERT(m_counter > 0, ()); + --m_counter; +} + +bool df::UserMarksProvider::IsPendingOnDelete() +{ + return m_pendingOnDelete; +} + +void df::UserMarksProvider::DeleteLater() +{ + ASSERT(m_pendingOnDelete == false, ()); + m_pendingOnDelete = true; +} + +bool df::UserMarksProvider::CanBeDeleted() +{ + return m_counter == 0; +} + +void df::UserMarksProvider::BeginWrite() +{ + Lock(); +} + +void df::UserMarksProvider::SetDirty() +{ + m_isDirty = true; +} + +void df::UserMarksProvider::EndWrite() +{ + Unlock(); +} + +void df::UserMarksProvider::Lock() +{ + m_mutex.Lock(); +} + +void df::UserMarksProvider::Unlock() +{ + m_mutex.Unlock(); +} diff --git a/drape_frontend/user_marks_provider.hpp b/drape_frontend/user_marks_provider.hpp new file mode 100644 index 0000000000..4a9e9b4398 --- /dev/null +++ b/drape_frontend/user_marks_provider.hpp @@ -0,0 +1,52 @@ +#pragma once + +#include "../drape/drape_global.hpp" + +#include "../geometry/point2d.hpp" + +#include "../base/mutex.hpp" + +#include "../std/atomic.hpp" + +namespace df +{ + +class UserMarksProvider +{ +public: + UserMarksProvider(); + virtual ~UserMarksProvider() {} + + void BeginRead(); + bool IsDirty() const; + virtual bool IsDrawable() const = 0; + virtual size_t GetCount() const = 0; + virtual m2::PointD const & GetPivot(size_t index) const = 0; + virtual string const & GetSymbolName(size_t index) const = 0; + virtual dp::Anchor GetAnchor(size_t index) const = 0; + virtual float GetDepth(size_t index) const = 0; + void EndRead(); + + void IncrementCounter(); + void DecrementCounter(); + bool CanBeDeleted(); + bool IsPendingOnDelete(); + void DeleteLater(); + +protected: + void BeginWrite(); + void SetDirty(); + void EndWrite(); + +private: + void Lock(); + void Unlock(); + +private: + threads::Mutex m_mutex; + bool m_isDirty = false; + atomic m_pendingOnDelete; + atomic m_counter; +}; + +} // namespace df