diff --git a/base/resource_pool.hpp b/base/resource_pool.hpp index 89e4e172f0..ae09b9a68f 100644 --- a/base/resource_pool.hpp +++ b/base/resource_pool.hpp @@ -116,6 +116,11 @@ public: m_traits.Free(m_pool, elem); } + size_t Size() const + { + return m_pool.Size(); + } + void EnterForeground() {} diff --git a/base/threaded_container.hpp b/base/threaded_container.hpp index dd611b7965..be0da06746 100644 --- a/base/threaded_container.hpp +++ b/base/threaded_container.hpp @@ -10,7 +10,7 @@ protected: my::Timer m_Timer; double m_WaitTime; - threads::Condition m_Cond; + mutable threads::Condition m_Cond; bool m_IsCancelled; public: diff --git a/base/threaded_list.hpp b/base/threaded_list.hpp index 35d83ab83a..5f7243c1ac 100644 --- a/base/threaded_list.hpp +++ b/base/threaded_list.hpp @@ -102,7 +102,7 @@ public: return res; } - size_t Size() + size_t Size() const { threads::ConditionGuard g(m_Cond); return m_list.size(); diff --git a/iphone/Maps/Classes/EAGLView.mm b/iphone/Maps/Classes/EAGLView.mm index 162554589f..b1f711bd1d 100644 --- a/iphone/Maps/Classes/EAGLView.mm +++ b/iphone/Maps/Classes/EAGLView.mm @@ -119,7 +119,7 @@ bool _inRepaint = false; "fonts_whitelist.txt", "fonts_blacklist.txt", 1.5 * 1024 * 1024, - GetPlatform().CpuCores() + 1, + GetPlatform().CpuCores() + 2, fmt, !yg::gl::g_isBufferObjectsSupported)); diff --git a/map/coverage_generator.cpp b/map/coverage_generator.cpp index e4ff2ec879..04905bf314 100644 --- a/map/coverage_generator.cpp +++ b/map/coverage_generator.cpp @@ -4,15 +4,17 @@ #include "screen_coverage.hpp" #include "tile_renderer.hpp" +#include "../yg/rendercontext.hpp" + #include "../base/logging.hpp" #include "../std/bind.hpp" CoverageGenerator::CoverageGenerator( - size_t tileSize, - size_t scaleEtalonSize, - TileRenderer * tileRenderer, - shared_ptr const & windowHandle) + size_t tileSize, + size_t scaleEtalonSize, + TileRenderer * tileRenderer, + shared_ptr const & windowHandle) : m_queue(1), m_tileRenderer(tileRenderer), m_workCoverage(0), @@ -22,8 +24,25 @@ CoverageGenerator::CoverageGenerator( { } -void CoverageGenerator::Initialize() +void CoverageGenerator::InitializeThreadGL() { + m_renderContext->makeCurrent(); +} + +void CoverageGenerator::FinalizeThreadGL() +{ + m_renderContext->endThreadDrawing(); +} + +void CoverageGenerator::Initialize(shared_ptr const & rc, + shared_ptr const & rm) +{ + m_resourceManager = rm; + m_renderContext = rc->createShared(); + + m_queue.AddInitCommand(bind(&CoverageGenerator::InitializeThreadGL, this)); + m_queue.AddFinCommand(bind(&CoverageGenerator::FinalizeThreadGL, this)); + m_queue.Start(); } @@ -66,6 +85,8 @@ void CoverageGenerator::CoverScreen(ScreenBase const & screen, int sequenceID) delete oldCoverage; m_workCoverage = 0; + + m_windowHandle->invalidate(); } void CoverageGenerator::AddMergeTileTask(Tiler::RectInfo const & rectInfo) @@ -106,3 +127,8 @@ threads::Mutex & CoverageGenerator::Mutex() { return m_mutex; } + +shared_ptr const & CoverageGenerator::resourceManager() const +{ + return m_resourceManager; +} diff --git a/map/coverage_generator.hpp b/map/coverage_generator.hpp index 2c1c2442d8..c72a74354f 100644 --- a/map/coverage_generator.hpp +++ b/map/coverage_generator.hpp @@ -29,6 +29,9 @@ private: TileRenderer * m_tileRenderer; + shared_ptr m_resourceManager; + shared_ptr m_renderContext; + ScreenCoverage * m_workCoverage; ScreenCoverage * m_currentCoverage; @@ -42,12 +45,15 @@ private: public: CoverageGenerator(size_t tileSize, - size_t scaleEtalonSize, - TileRenderer * tileRenderer, - shared_ptr const & windowHandle); + size_t scaleEtalonSize, + TileRenderer * tileRenderer, + shared_ptr const & windowHandle); ~CoverageGenerator(); + void InitializeThreadGL(); + void FinalizeThreadGL(); + void AddCoverScreenTask(ScreenBase const & screen); void AddMergeTileTask(Tiler::RectInfo const & rectInfo); @@ -56,11 +62,14 @@ public: void Cancel(); - void Initialize(); + void Initialize(shared_ptr const & rc, + shared_ptr const & rm); void WaitForEmptyAndFinished(); ScreenCoverage & CurrentCoverage(); threads::Mutex & Mutex(); + + shared_ptr const & resourceManager() const; }; diff --git a/map/screen_coverage.cpp b/map/screen_coverage.cpp index bac8ef88a6..99746cc168 100644 --- a/map/screen_coverage.cpp +++ b/map/screen_coverage.cpp @@ -87,9 +87,18 @@ void ScreenCoverage::Merge(Tiler::RectInfo const & ri) tileCache->readUnlock(); if (addTile) + { m_infoLayer.merge(*tile->m_infoLayer.get(), tile->m_tileScreen.PtoGMatrix() * m_screen.GtoPMatrix()); + if (!m_stylesCache) + m_stylesCache.reset(new yg::StylesCache(m_coverageGenerator->resourceManager(), + m_coverageGenerator->resourceManager()->cacheThreadGlyphCacheID(), + 2)); + + m_infoLayer.cache(m_stylesCache.get()); + m_stylesCache->upload(); + } } void ScreenCoverage::Remove(Tile const *) @@ -165,16 +174,22 @@ void ScreenCoverage::SetScreen(ScreenBase const & screen, bool /*mergePathNames* { Tiler::RectInfo ri = (*it)->m_rectInfo; tileCache->lockTile((*it)->m_rectInfo); - m_infoLayer.merge(*((*it)->m_infoLayer.get()), (*it)->m_tileScreen.PtoGMatrix() * screen.GtoPMatrix()); } + tileCache->readUnlock(); + + m_tiles = tiles; + + m_stylesCache.reset(new yg::StylesCache(m_coverageGenerator->resourceManager(), + m_coverageGenerator->resourceManager()->cacheThreadGlyphCacheID(), + 2)); + m_infoLayer.clear(); for (TileSet::const_iterator it = m_tiles.begin(); it != m_tiles.end(); ++it) m_infoLayer.merge(*((*it)->m_infoLayer.get()), (*it)->m_tileScreen.PtoGMatrix() * screen.GtoPMatrix()); - tileCache->readUnlock(); - - m_tiles = tiles; + m_infoLayer.cache(m_stylesCache.get()); + m_stylesCache->upload(); /// adding commands for tiles which aren't in cache for (size_t i = 0; i < newRects.size(); ++i) @@ -182,6 +197,7 @@ void ScreenCoverage::SetScreen(ScreenBase const & screen, bool /*mergePathNames* m_tileRenderer->AddCommand(newRects[i], m_tiler.sequenceID(), bind(&CoverageGenerator::AddMergeTileTask, m_coverageGenerator, newRects[i])); } + } ScreenCoverage::~ScreenCoverage() @@ -196,9 +212,6 @@ ScreenCoverage::~ScreenCoverage() } tileCache->writeUnlock(); - - m_tiles.clear(); - m_infoLayer.clear(); } void ScreenCoverage::Draw(yg::gl::Screen * s, ScreenBase const & screen) @@ -224,5 +237,8 @@ void ScreenCoverage::Draw(yg::gl::Screen * s, ScreenBase const & screen) s->blit(&infos[0], infos.size(), true); + if (m_stylesCache) + s->setAdditionalSkinPages(m_stylesCache->cachePages()); + m_infoLayer.draw(s, m_screen.PtoGMatrix() * screen.GtoPMatrix()); } diff --git a/map/screen_coverage.hpp b/map/screen_coverage.hpp index dea7baa31b..d78b120d6d 100644 --- a/map/screen_coverage.hpp +++ b/map/screen_coverage.hpp @@ -5,6 +5,7 @@ #include "../geometry/screenbase.hpp" #include "../yg/info_layer.hpp" +#include "../yg/styles_cache.hpp" #include "tile.hpp" #include "tiler.hpp" @@ -43,6 +44,7 @@ private: TileSet m_tiles; //< set of tiles, that are visible for the m_screen yg::InfoLayer m_infoLayer; //< composite infoLayers for visible tiles + shared_ptr m_stylesCache; CoverageGenerator * m_coverageGenerator; diff --git a/map/tiling_render_policy_mt.cpp b/map/tiling_render_policy_mt.cpp index 6541a8a01e..04e9dba8e7 100644 --- a/map/tiling_render_policy_mt.cpp +++ b/map/tiling_render_policy_mt.cpp @@ -6,6 +6,7 @@ #include "../geometry/screenbase.hpp" #include "../yg/base_texture.hpp" +#include "../yg/internal/opengl.hpp" #include "drawer_yg.hpp" #include "events.hpp" @@ -37,12 +38,21 @@ void TilingRenderPolicyMT::Initialize(shared_ptr const & resourceManager->initRenderTargets(GetPlatform().TileSize(), GetPlatform().TileSize(), GetPlatform().MaxTilesCount()); m_tileRenderer.Initialize(primaryContext, resourceManager, GetPlatform().VisualScale()); - m_coverageGenerator.Initialize(); + m_coverageGenerator.Initialize(primaryContext, resourceManager); +} + +void TilingRenderPolicyMT::BeginFrame() +{ +} + +void TilingRenderPolicyMT::EndFrame() +{ } void TilingRenderPolicyMT::DrawFrame(shared_ptr const & e, ScreenBase const & currentScreen) { DrawerYG * pDrawer = e->drawer(); + pDrawer->screen()->clear(bgColor()); m_coverageGenerator.AddCoverScreenTask(currentScreen); diff --git a/map/tiling_render_policy_mt.hpp b/map/tiling_render_policy_mt.hpp index d6a84908d0..76b5b2370c 100644 --- a/map/tiling_render_policy_mt.hpp +++ b/map/tiling_render_policy_mt.hpp @@ -43,5 +43,7 @@ public: void Initialize(shared_ptr const & renderContext, shared_ptr const & resourceManager); + void BeginFrame(); void DrawFrame(shared_ptr const & ev, ScreenBase const & currentScreen); + void EndFrame(); }; diff --git a/qt/widgets.cpp b/qt/widgets.cpp index 85578b7102..f458397c02 100644 --- a/qt/widgets.cpp +++ b/qt/widgets.cpp @@ -56,7 +56,7 @@ namespace qt "fonts_whitelist.txt", "fonts_blacklist.txt", 2 * 1024 * 1024, - GetPlatform().CpuCores() + 1, + GetPlatform().CpuCores() + 2, yg::Rt8Bpp, !yg::gl::g_isBufferObjectsSupported)); diff --git a/qt_tstfrm/tstwidgets.cpp b/qt_tstfrm/tstwidgets.cpp index 83408976cb..91ad6c0249 100644 --- a/qt_tstfrm/tstwidgets.cpp +++ b/qt_tstfrm/tstwidgets.cpp @@ -60,7 +60,7 @@ void GLDrawWidget::initializeGL() "fonts_whitelist.txt", "fonts_blacklist.txt", 2 * 1024 * 1024, - GetPlatform().CpuCores() + 1, + GetPlatform().CpuCores() + 2, yg::Rt8Bpp, !yg::gl::g_isBufferObjectsSupported)); diff --git a/yg/info_layer.cpp b/yg/info_layer.cpp index a05611b82d..c710187637 100644 --- a/yg/info_layer.cpp +++ b/yg/info_layer.cpp @@ -2,6 +2,7 @@ #include "info_layer.hpp" #include "text_element.hpp" +#include "styles_cache.hpp" #include "../std/bind.hpp" #include "../std/vector.hpp" @@ -219,5 +220,27 @@ namespace yg for (path_text_elements::const_iterator it = layer.m_pathTexts.begin(); it != layer.m_pathTexts.end(); ++it) for_each(it->second.begin(), it->second.end(), bind(&InfoLayer::addPathText, this, _1, m)); } + + void InfoLayer::cache(StylesCache * stylesCache) + { + list toErase; + + for (path_text_elements::const_iterator it = m_pathTexts.begin(); it != m_pathTexts.end(); ++it) + { + list const & l = it->second; + + for (list::const_iterator j = l.begin(); j != l.end(); ++j) + stylesCache->cachePathText(*j); + + if (l.empty()) + toErase.push_back(it->first); + } + + for (list::const_iterator it = toErase.begin(); it != toErase.end(); ++it) + m_pathTexts.erase(*it); + + m_tree.ForEach(bind(&StylesCache::cacheStraightText, stylesCache, _1)); + } + } diff --git a/yg/info_layer.hpp b/yg/info_layer.hpp index df472332ed..c32880e665 100644 --- a/yg/info_layer.hpp +++ b/yg/info_layer.hpp @@ -17,8 +17,11 @@ namespace yg namespace gl { class TextRenderer; + class SkinPage; } + class StylesCache; + struct StraightTextElementTraits { static m2::RectD const LimitRect(StraightTextElement const & elem); @@ -59,6 +62,8 @@ namespace yg void clear(); + void cache(StylesCache * cache); + void merge(InfoLayer const & infoLayer, math::Matrix const & m); }; } diff --git a/yg/resource_manager.cpp b/yg/resource_manager.cpp index cae025acad..9578fae6e4 100644 --- a/yg/resource_manager.cpp +++ b/yg/resource_manager.cpp @@ -250,7 +250,7 @@ namespace yg int ResourceManager::renderThreadGlyphCacheID(int threadNum) const { - return 1 + threadNum; + return 2 + threadNum; } int ResourceManager::guiThreadGlyphCacheID() const @@ -258,6 +258,11 @@ namespace yg return 0; } + int ResourceManager::cacheThreadGlyphCacheID() const + { + return 1; + } + ResourceManager::TStoragePool * ResourceManager::storages() { return m_storages.get(); diff --git a/yg/resource_manager.hpp b/yg/resource_manager.hpp index ef37855ce4..6d83ceb7d1 100644 --- a/yg/resource_manager.hpp +++ b/yg/resource_manager.hpp @@ -151,6 +151,7 @@ namespace yg int renderThreadGlyphCacheID(int threadNum) const; int guiThreadGlyphCacheID() const; + int cacheThreadGlyphCacheID() const; void addFonts(vector const & fontNames); diff --git a/yg/styles_cache.cpp b/yg/styles_cache.cpp new file mode 100644 index 0000000000..248aaf805f --- /dev/null +++ b/yg/styles_cache.cpp @@ -0,0 +1,46 @@ +#include "../base/SRC_FIRST.hpp" + +#include "styles_cache.hpp" +#include "text_element.hpp" +#include "glyph_cache.hpp" +#include "skin_page.hpp" +#include "resource_manager.hpp" + +namespace yg +{ + StylesCache::StylesCache(shared_ptr const & rm, + int glyphCacheID, + int maxPagesCount) + : m_rm(rm), + m_maxPagesCount(maxPagesCount) + { + m_glyphCache = m_rm->glyphCache(glyphCacheID); + } + + StylesCache::~StylesCache() + { + for (unsigned i = 0; i < m_cachePages.size(); ++i) + m_cachePages[i]->freeTexture(); + } + + void StylesCache::cachePathText(PathTextElement const & pte) + { + pte.cache(m_cachePages, m_rm, m_glyphCache); + } + + void StylesCache::cacheStraightText(StraightTextElement const & ste) + { + ste.cache(m_cachePages, m_rm, m_glyphCache); + } + + vector > const & StylesCache::cachePages() const + { + return m_cachePages; + } + + void StylesCache::upload() + { + for (unsigned i = 0; i < m_cachePages.size(); ++i) + m_cachePages[i]->uploadData(); + } +} diff --git a/yg/styles_cache.hpp b/yg/styles_cache.hpp new file mode 100644 index 0000000000..1c8dc3c131 --- /dev/null +++ b/yg/styles_cache.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include "../std/shared_ptr.hpp" +#include "../std/vector.hpp" + +namespace yg +{ + class StraightTextElement; + class PathTextElement; + class SkinPage; + class GlyphCache; + class ResourceManager; + + class StylesCache + { + private: + + vector > m_cachePages; + shared_ptr m_rm; + GlyphCache * m_glyphCache; + int m_maxPagesCount; + + public: + + StylesCache(shared_ptr const & rm, + int glyphCacheID, + int maxPagesCount); + + ~StylesCache(); + + void cacheStraightText(StraightTextElement const & ste); + + void cachePathText(PathTextElement const & pte); + + vector > const & cachePages() const; + + void upload(); + }; +} diff --git a/yg/text_element.cpp b/yg/text_element.cpp index 25d76fbc16..f8696cc9cc 100644 --- a/yg/text_element.cpp +++ b/yg/text_element.cpp @@ -1,6 +1,8 @@ #include "text_element.hpp" #include "screen.hpp" #include "skin.hpp" +#include "skin_page.hpp" +#include "resource_manager.hpp" #include "overlay_renderer.hpp" #include "resource_style.hpp" @@ -55,6 +57,43 @@ namespace yg } } + void TextElement::cacheTextImpl(GlyphLayout const & layout, + vector > & skinPages, + shared_ptr const & rm, + GlyphCache * glyphCache, + FontDesc const & desc) const + { + for (unsigned i = layout.firstVisible(); i < layout.lastVisible(); ++i) + { + GlyphLayoutElem const & elem = layout.entries()[i]; + + GlyphKey glyphKey(elem.m_sym, + m_fontDesc.m_size, + m_fontDesc.m_isMasked, + m_fontDesc.m_isMasked ? m_fontDesc.m_maskColor : m_fontDesc.m_color); + + bool found = false; + + for (unsigned j = 0; j < skinPages.size(); ++j) + if (skinPages[j]->findGlyph(glyphKey) != 0x00FFFFFF) + { + found = true; + break; + } + + if (!found) + { + if (!skinPages.empty() && skinPages.back()->hasRoom(glyphKey, glyphCache)) + skinPages.back()->mapGlyph(glyphKey, glyphCache); + else + { + skinPages.push_back(make_shared_ptr(new SkinPage(rm, SkinPage::EFontsUsage, 0))); + skinPages.back()->mapGlyph(glyphKey, glyphCache); + } + } + } + } + StraightTextElement::StraightTextElement(Params const & p) : TextElement(p), m_glyphLayout(p.m_glyphCache, @@ -112,6 +151,20 @@ namespace yg m_glyphLayout.setPivot(pivot()); } + void StraightTextElement::cache(vector > & skinPages, + shared_ptr const & rm, + GlyphCache * glyphCache) const + { + yg::FontDesc desc = m_fontDesc; + if (m_fontDesc.m_isMasked) + { + cacheTextImpl(m_glyphLayout, skinPages, rm, glyphCache, m_fontDesc); + desc.m_isMasked = false; + } + + cacheTextImpl(m_glyphLayout, skinPages, rm, glyphCache, desc); + } + PathTextElement::PathTextElement(Params const & p) : TextElement(p), m_glyphLayout(p.m_glyphCache, @@ -167,4 +220,19 @@ namespace yg TextElement::offset(offs); m_glyphLayout.setPivot(pivot()); } + + void PathTextElement::cache(vector > & skinPages, + shared_ptr const & rm, + GlyphCache * glyphCache) const + { + yg::FontDesc desc = m_fontDesc; + + if (m_fontDesc.m_isMasked) + { + cacheTextImpl(m_glyphLayout, skinPages, rm, glyphCache, m_fontDesc); + desc.m_isMasked = false; + } + + cacheTextImpl(m_glyphLayout, skinPages, rm, glyphCache, desc); + } } diff --git a/yg/text_element.hpp b/yg/text_element.hpp index 6969bbbe24..180782b3d7 100644 --- a/yg/text_element.hpp +++ b/yg/text_element.hpp @@ -16,6 +16,7 @@ namespace yg { class ResourceManager; class Skin; + class SkinPage; namespace gl { @@ -45,6 +46,12 @@ namespace yg TextElement(Params const & p); + void cacheTextImpl(GlyphLayout const & layout, + vector > & skinPages, + shared_ptr const & rm, + GlyphCache * glyphCache, + FontDesc const & desc) const; + void drawTextImpl(GlyphLayout const & layout, gl::OverlayRenderer * r, math::Matrix const & m, @@ -73,6 +80,9 @@ namespace yg m2::AARectD const boundRect() const; void draw(gl::OverlayRenderer * r, math::Matrix const & m) const; void offset(m2::PointD const & offs); + void cache(vector > & skinPages, + shared_ptr const & rm, + GlyphCache * glyphCache) const; }; class PathTextElement : public TextElement @@ -97,5 +107,9 @@ namespace yg m2::AARectD const boundRect() const; void draw(gl::OverlayRenderer * r, math::Matrix const & m) const; void offset(m2::PointD const & offs); + + void cache(vector > & skinPages, + shared_ptr const & rm, + GlyphCache * glyphCache) const; }; } diff --git a/yg/yg.pro b/yg/yg.pro index 82356eb626..7718b6e976 100644 --- a/yg/yg.pro +++ b/yg/yg.pro @@ -57,6 +57,7 @@ SOURCES += \ symbol_element.cpp \ overlay_renderer.cpp \ render_state_updater.cpp \ + styles_cache.cpp HEADERS += \ internal/opengl.hpp \ @@ -106,8 +107,11 @@ HEADERS += \ symbol_element.hpp \ overlay_renderer.hpp \ render_state_updater.hpp \ + styles_cache.hpp win32 { HEADERS += internal/opengl_win32.hpp SOURCES += internal/opengl_win32.cpp } + +