From c48b44e6ff65feecb940455dc15cae7b65084151 Mon Sep 17 00:00:00 2001 From: rachytski Date: Mon, 26 Sep 2011 18:35:38 +0300 Subject: [PATCH] StylesCache creation on the CoverageGenerator thread. improvement of the GUI thread text rendering speed. --- base/commands_queue.cpp | 10 +- base/commands_queue.hpp | 7 +- base/resource_pool.hpp | 2 +- iphone/Maps/Classes/EAGLView.h | 3 +- iphone/Maps/Classes/EAGLView.mm | 12 ++- iphone/Maps/Classes/MapViewController.h | 4 +- iphone/Maps/Classes/MapViewController.mm | 27 ++--- iphone/Maps/Maps.xcodeproj/project.pbxproj | 109 +++++++++++++++++++++ map/benchmark_render_policy_mt.cpp | 4 +- map/coverage_generator.cpp | 12 +++ map/coverage_generator.hpp | 3 + map/framework.cpp | 10 +- map/framework.hpp | 6 +- map/render_policy.cpp | 4 +- map/render_policy.hpp | 6 +- map/render_policy_mt.cpp | 6 +- map/render_policy_mt.hpp | 10 +- map/ruler.cpp | 11 ++- map/ruler.hpp | 5 +- map/screen_coverage.cpp | 43 +++++--- map/screen_coverage.hpp | 4 +- map/tiling_render_policy_mt.cpp | 17 ++-- map/tiling_render_policy_mt.hpp | 6 +- qt/draw_widget.cpp | 6 +- yg/composite_overlay_element.cpp | 19 +++- yg/composite_overlay_element.hpp | 7 +- yg/geometry_batcher.cpp | 34 +++++-- yg/geometry_batcher.hpp | 4 +- yg/info_layer.cpp | 54 +++++++++- yg/overlay_element.hpp | 8 +- yg/path_text_element.cpp | 40 ++++++-- yg/path_text_element.hpp | 6 +- yg/resource_manager.cpp | 21 ++++ yg/resource_manager.hpp | 7 ++ yg/skin.cpp | 17 ++-- yg/skin.hpp | 5 +- yg/skin_page.cpp | 35 ++++++- yg/skin_page.hpp | 9 ++ yg/straight_text_element.cpp | 46 ++++++++- yg/straight_text_element.hpp | 6 +- yg/styles_cache.cpp | 33 +++++-- yg/styles_cache.hpp | 17 ++-- yg/symbol_element.cpp | 11 ++- yg/symbol_element.hpp | 5 +- yg/text_element.cpp | 86 +++++++++++----- yg/text_element.hpp | 19 +++- 46 files changed, 647 insertions(+), 169 deletions(-) diff --git a/base/commands_queue.cpp b/base/commands_queue.cpp index 0543dd405c..8ea78bd00d 100644 --- a/base/commands_queue.cpp +++ b/base/commands_queue.cpp @@ -150,18 +150,10 @@ namespace core m_cancelCommands.push_back(cmd); } - void CommandsQueue::Clear() - { - threads::ConditionGuard g(m_cond); - m_commands.Clear(); - m_activeCommands = 0; - if (m_activeCommands == 0) - m_cond.Signal(); - } - void CommandsQueue::FinishCommand() { threads::ConditionGuard g(m_cond); + --m_activeCommands; if (m_activeCommands == 0) m_cond.Signal(); diff --git a/base/commands_queue.hpp b/base/commands_queue.hpp index 56d65345c6..6d6758bae5 100644 --- a/base/commands_queue.hpp +++ b/base/commands_queue.hpp @@ -129,13 +129,18 @@ namespace core CommandsQueue(size_t executorsCount); ~CommandsQueue(); + /// Number of executors in this queue int ExecutorsCount() const; + + /// Adding different types of commands + /// @{ void AddCommand(Command const & cmd); void AddInitCommand(Command const & cmd); void AddFinCommand(Command const & cmd); void AddCancelCommand(Command const & cmd); + /// @} + void Start(); - void Clear(); void Cancel(); void Join(); diff --git a/base/resource_pool.hpp b/base/resource_pool.hpp index ae09b9a68f..b6665ca533 100644 --- a/base/resource_pool.hpp +++ b/base/resource_pool.hpp @@ -47,7 +47,7 @@ struct FixedSizePoolTraits : BasePoolTraits { m_isAllocated = true; - LOG(LINFO, ("allocating ", base_t::m_factory.ElemSize() * m_count, "bytes for ", base_t::m_factory.ResName())); + LOG(LINFO, ("allocating ", m_count, " elements, ", base_t::m_factory.ElemSize() * m_count, "bytes total for ", base_t::m_factory.ResName())); for (size_t i = 0; i < m_count; ++i) elems.PushBack(base_t::m_factory.Create()); diff --git a/iphone/Maps/Classes/EAGLView.h b/iphone/Maps/Classes/EAGLView.h index 873874a650..6687375a03 100644 --- a/iphone/Maps/Classes/EAGLView.h +++ b/iphone/Maps/Classes/EAGLView.h @@ -32,13 +32,13 @@ namespace yg // The pixel dimensions of the backbuffer shared_ptr renderContext; - shared_ptr renderBuffer; shared_ptr frameBuffer; @public shared_ptr windowHandle; shared_ptr drawer; + shared_ptr renderBuffer; MapViewController * controller; } @@ -51,6 +51,7 @@ namespace yg @property (nonatomic, assign) shared_ptr windowHandle; @property (nonatomic, assign) shared_ptr drawer; @property (nonatomic, assign) shared_ptr renderContext; +@property (nonatomic, assign) shared_ptr renderBuffer; @property (nonatomic, assign) shared_ptr resourceManager; @end diff --git a/iphone/Maps/Classes/EAGLView.mm b/iphone/Maps/Classes/EAGLView.mm index 6136a3a379..ec0b1eb8d2 100644 --- a/iphone/Maps/Classes/EAGLView.mm +++ b/iphone/Maps/Classes/EAGLView.mm @@ -22,6 +22,7 @@ bool _inRepaint = false; @synthesize windowHandle; @synthesize drawer; @synthesize renderContext; +@synthesize renderBuffer; @synthesize resourceManager; @synthesize displayLink; @@ -108,7 +109,7 @@ bool _inRepaint = false; size_t fontTexWidth = 512; size_t fontTexHeight = 256; - size_t fontTexCount = 10; + size_t fontTexCount = 15; resourceManager = shared_ptr(new yg::ResourceManager( bigVBSize, bigIBSize, 6 * GetPlatform().CpuCores(), @@ -119,7 +120,7 @@ bool _inRepaint = false; "unicode_blocks.txt", "fonts_whitelist.txt", "fonts_blacklist.txt", - 1.5 * 1024 * 1024, + 2 * 1024 * 1024, GetPlatform().CpuCores() + 2, fmt, !yg::gl::g_isBufferObjectsSupported)); @@ -138,7 +139,7 @@ bool _inRepaint = false; p.m_skinName = pl.SkinName(); p.m_visualScale = pl.VisualScale(); p.m_isSynchronized = false; - p.m_useTinyStorage = true; //< use tiny buffers to minimize CPU->GPU data transfer overhead. + p.m_useTinyStorage = false; //< use tiny buffers to minimize CPU->GPU data transfer overhead. drawer = shared_ptr(new DrawerYG(p)); @@ -174,14 +175,15 @@ bool _inRepaint = false; - (void)drawView { - if (windowHandle->needRedraw()) + [controller drawFrame]; + /*if (windowHandle->needRedraw()) { windowHandle->setNeedRedraw(false); [controller beginPaint]; [controller doPaint]; renderBuffer->present(); [controller endPaint]; - } + }*/ } - (void)drawViewThunk:(id)obj diff --git a/iphone/Maps/Classes/MapViewController.h b/iphone/Maps/Classes/MapViewController.h index 1bdbf18530..1dfcaa21b4 100644 --- a/iphone/Maps/Classes/MapViewController.h +++ b/iphone/Maps/Classes/MapViewController.h @@ -33,9 +33,7 @@ - (void) ZoomToRect: (m2::RectD const &) rect; - (void) onResize: (GLint)width withHeight: (GLint)height; -- (void) beginPaint; -- (void) doPaint; -- (void) endPaint; +- (void) drawFrame; // called when app is terminated by system - (void) OnTerminate; diff --git a/iphone/Maps/Classes/MapViewController.mm b/iphone/Maps/Classes/MapViewController.mm index 3162c5015c..163924a660 100644 --- a/iphone/Maps/Classes/MapViewController.mm +++ b/iphone/Maps/Classes/MapViewController.mm @@ -277,21 +277,22 @@ NSInteger compareAddress(id l, id r, void * context) m_framework->Scale(0.5); } -- (void)beginPaint -{ - m_framework->BeginPaint(); -} - -- (void)endPaint -{ - m_framework->EndPaint(); -} - -- (void)doPaint +- (void)drawFrame { + EAGLView * v = (EAGLView*)self.view; + boost::shared_ptr wh = [v windowHandle]; + boost::shared_ptr rb = [v renderBuffer]; shared_ptr drawer = [(EAGLView*)self.view drawer]; - shared_ptr paintEvent(new PaintEvent(drawer.get())); - m_framework->DoPaint(paintEvent); + shared_ptr pe(new PaintEvent(drawer.get())); + + if (wh->needRedraw()) + { + wh->setNeedRedraw(false); + m_framework->BeginPaint(pe); + m_framework->DoPaint(pe); + rb->present(); + m_framework->EndPaint(pe); + } } - (BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) interfaceOrientation diff --git a/iphone/Maps/Maps.xcodeproj/project.pbxproj b/iphone/Maps/Maps.xcodeproj/project.pbxproj index a18619cf55..e806c5a61f 100644 --- a/iphone/Maps/Maps.xcodeproj/project.pbxproj +++ b/iphone/Maps/Maps.xcodeproj/project.pbxproj @@ -2669,6 +2669,111 @@ }; name = "Simulator Debug"; }; + EE423F1B142E8BB100E0A701 /* Device Release Clang */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COMPRESS_PNG_FILES = NO; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1.0.1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_DYNAMIC_NO_PIC = YES; + GCC_ENABLE_PASCAL_STRINGS = NO; + GCC_FAST_MATH = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_OPTIMIZATION_LEVEL = 3; + GCC_PREPROCESSOR_DEFINITIONS = ( + RELEASE, + _RELEASE, + TARGET_OS_IPHONE, + ); + GCC_THUMB_SUPPORT = NO; + "GCC_THUMB_SUPPORT[arch=armv7]" = YES; + GCC_UNROLL_LOOPS = YES; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ( + ../../3party/protobuf, + ../../3party/protobuf/src, + ../../3party/boost, + ); + INFOPLIST_FILE = "MapsWithMe-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 4.0; + LIBRARY_SEARCH_PATHS = "\"$(SRCROOT)/../../../omim-iphone-release-clang/out/release\""; + ONLY_ACTIVE_ARCH = NO; + OTHER_CFLAGS = "-Wall"; + OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)"; + PRODUCT_NAME = MapsWithMe; + PROVISIONING_PROFILE = ""; + SDKROOT = iphoneos; + STRIP_INSTALLED_PRODUCT = NO; + TARGETED_DEVICE_FAMILY = "1,2"; + VALID_ARCHS = "armv6 armv7"; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = "Device Release Clang"; + }; + EE423F1C142E8BB100E0A701 /* Device Release Clang */ = { + isa = XCBuildConfiguration; + buildSettings = { + LIBRARY_SEARCH_PATHS = "$(inherited)"; + }; + name = "Device Release Clang"; + }; + EE423F1D142E8BBD00E0A701 /* Device Debug Clang */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COMPRESS_PNG_FILES = NO; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1.0.1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_PASCAL_STRINGS = NO; + GCC_FAST_MATH = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + DEBUG, + _DEBUG, + TARGET_OS_IPHONE, + ); + GCC_THUMB_SUPPORT = NO; + "GCC_THUMB_SUPPORT[arch=armv7]" = YES; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ( + ../../3party/protobuf, + ../../3party/protobuf/src, + ../../3party/boost, + ); + INFOPLIST_FILE = "MapsWithMe-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 4.0; + LIBRARY_SEARCH_PATHS = "\"$(SRCROOT)/../../../omim-iphone-debug-clang/out/debug\""; + ONLY_ACTIVE_ARCH = NO; + OTHER_CFLAGS = "-Wall"; + OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)"; + PRODUCT_NAME = MapsWithMe; + PROVISIONING_PROFILE = ""; + SDKROOT = iphoneos; + STRIP_INSTALLED_PRODUCT = NO; + TARGETED_DEVICE_FAMILY = "1,2"; + VALID_ARCHS = "armv6 armv7"; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = "Device Debug Clang"; + }; + EE423F1E142E8BBD00E0A701 /* Device Debug Clang */ = { + isa = XCBuildConfiguration; + buildSettings = { + LIBRARY_SEARCH_PATHS = "$(inherited)"; + }; + name = "Device Debug Clang"; + }; FA0686DE13578E1D004CFF81 /* Production Release */ = { isa = XCBuildConfiguration; buildSettings = { @@ -2885,8 +2990,10 @@ buildConfigurations = ( 1D6058940D05DD3E006BFB54 /* Simulator Debug */, FA1DE85A11E2235D00C6D69A /* Device Debug */, + EE423F1E142E8BBD00E0A701 /* Device Debug Clang */, FA1DE83211E2205400C6D69A /* Simulator Release */, FA1DE85C11E2236200C6D69A /* Device Release */, + EE423F1C142E8BB100E0A701 /* Device Release Clang */, FA0686DF13578E1D004CFF81 /* Production Release */, ); defaultConfigurationIsVisible = 0; @@ -2897,8 +3004,10 @@ buildConfigurations = ( C01FCF4F08A954540054247B /* Simulator Debug */, FA1DE85911E2235D00C6D69A /* Device Debug */, + EE423F1D142E8BBD00E0A701 /* Device Debug Clang */, FA1DE83111E2205400C6D69A /* Simulator Release */, FA1DE85B11E2236200C6D69A /* Device Release */, + EE423F1B142E8BB100E0A701 /* Device Release Clang */, FA0686DE13578E1D004CFF81 /* Production Release */, ); defaultConfigurationIsVisible = 0; diff --git a/map/benchmark_render_policy_mt.cpp b/map/benchmark_render_policy_mt.cpp index 955a188603..ddb1efc9da 100644 --- a/map/benchmark_render_policy_mt.cpp +++ b/map/benchmark_render_policy_mt.cpp @@ -19,9 +19,9 @@ void BenchmarkRenderPolicyMT::DrawFrame(shared_ptr const & e, ScreenBase const & s) { RenderPolicyMT::DrawFrame(e, s); - RenderPolicyMT::EndFrame(); + RenderPolicyMT::EndFrame(e, s); GetRenderQueue().WaitForEmptyAndFinished(); - RenderPolicyMT::BeginFrame(); + RenderPolicyMT::BeginFrame(e, s); RenderPolicyMT::DrawFrame(e, s); } diff --git a/map/coverage_generator.cpp b/map/coverage_generator.cpp index 04905bf314..1712605b6c 100644 --- a/map/coverage_generator.cpp +++ b/map/coverage_generator.cpp @@ -40,6 +40,12 @@ void CoverageGenerator::Initialize(shared_ptr const & rc, m_resourceManager = rm; m_renderContext = rc->createShared(); + m_currentStylesCache.reset(new yg::StylesCache(rm, + rm->cacheThreadGlyphCacheID())); + + m_workStylesCache.reset(new yg::StylesCache(rm, + rm->cacheThreadGlyphCacheID())); + m_queue.AddInitCommand(bind(&CoverageGenerator::InitializeThreadGL, this)); m_queue.AddFinCommand(bind(&CoverageGenerator::FinalizeThreadGL, this)); @@ -74,13 +80,16 @@ void CoverageGenerator::CoverScreen(ScreenBase const & screen, int sequenceID) return; m_workCoverage = m_currentCoverage->Clone(); + m_workCoverage->SetStylesCache(m_workStylesCache.get()); m_workCoverage->SetScreen(screen); ScreenCoverage * oldCoverage = m_currentCoverage; { threads::MutexGuard g(m_mutex); + m_currentCoverage->SetStylesCache(0); m_currentCoverage = m_workCoverage; + swap(m_currentStylesCache, m_workStylesCache); } delete oldCoverage; @@ -97,6 +106,7 @@ void CoverageGenerator::AddMergeTileTask(Tiler::RectInfo const & rectInfo) void CoverageGenerator::MergeTile(Tiler::RectInfo const & rectInfo) { m_workCoverage = m_currentCoverage->Clone(); + m_workCoverage->SetStylesCache(m_workStylesCache.get()); m_workCoverage->Merge(rectInfo); @@ -104,7 +114,9 @@ void CoverageGenerator::MergeTile(Tiler::RectInfo const & rectInfo) { threads::MutexGuard g(m_mutex); + m_currentCoverage->SetStylesCache(0); m_currentCoverage = m_workCoverage; + swap(m_currentStylesCache, m_workStylesCache); } delete oldCoverage; diff --git a/map/coverage_generator.hpp b/map/coverage_generator.hpp index c72a74354f..5cb487ea2f 100644 --- a/map/coverage_generator.hpp +++ b/map/coverage_generator.hpp @@ -35,6 +35,9 @@ private: ScreenCoverage * m_workCoverage; ScreenCoverage * m_currentCoverage; + shared_ptr m_workStylesCache; + shared_ptr m_currentStylesCache; + ScreenBase m_currentScreen; int m_sequenceID; diff --git a/map/framework.cpp b/map/framework.cpp index b029156857..0f615f7302 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -342,20 +342,20 @@ void Framework::DrawModel(shared_ptr const & e, } template -void Framework::BeginPaint() +void Framework::BeginPaint(shared_ptr const & e) { - m_renderPolicy->BeginFrame(); + m_renderPolicy->BeginFrame(e, m_navigator.Screen()); } template -void Framework::EndPaint() +void Framework::EndPaint(shared_ptr const & e) { - m_renderPolicy->EndFrame(); + m_renderPolicy->EndFrame(e, m_navigator.Screen()); } /// Function for calling from platform dependent-paint function. template -void Framework::DoPaint(shared_ptr e) +void Framework::DoPaint(shared_ptr const & e) { DrawerYG * pDrawer = e->drawer(); diff --git a/map/framework.hpp b/map/framework.hpp index 3e0faf1aed..3db098a0c0 100644 --- a/map/framework.hpp +++ b/map/framework.hpp @@ -211,11 +211,11 @@ public: bool NeedRedraw() const; void SetNeedRedraw(bool flag); - virtual void BeginPaint(); + virtual void BeginPaint(shared_ptr const & e); /// Function for calling from platform dependent-paint function. - virtual void DoPaint(shared_ptr e); + virtual void DoPaint(shared_ptr const & e); - virtual void EndPaint(); + virtual void EndPaint(shared_ptr const & e); void CenterViewport(m2::PointD const & pt); diff --git a/map/render_policy.cpp b/map/render_policy.cpp index beb25fc573..b83e4ad097 100644 --- a/map/render_policy.cpp +++ b/map/render_policy.cpp @@ -70,8 +70,8 @@ void RenderPolicy::StopScale(m2::PointD const &, m2::PointD const &, double) m_windowHandle->invalidate(); } -void RenderPolicy::BeginFrame() +void RenderPolicy::BeginFrame(shared_ptr const & e, ScreenBase const & s) {} -void RenderPolicy::EndFrame() +void RenderPolicy::EndFrame(shared_ptr const & e, ScreenBase const & s) {} diff --git a/map/render_policy.hpp b/map/render_policy.hpp index 59d20ce3a9..d791819dde 100644 --- a/map/render_policy.hpp +++ b/map/render_policy.hpp @@ -48,11 +48,11 @@ public: RenderPolicy(shared_ptr const & windowHandle, TRenderFn const & renderFn); virtual ~RenderPolicy() {} /// starting frame - virtual void BeginFrame(); + virtual void BeginFrame(shared_ptr const & e, ScreenBase const & s); /// drawing single frame - virtual void DrawFrame(shared_ptr const & paintEvent, ScreenBase const & currentScreen) = 0; + virtual void DrawFrame(shared_ptr const & e, ScreenBase const & s) = 0; /// ending frame - virtual void EndFrame(); + virtual void EndFrame(shared_ptr const & e, ScreenBase const & s); /// processing resize request virtual m2::RectI const OnSize(int w, int h); /// initialize render policy diff --git a/map/render_policy_mt.cpp b/map/render_policy_mt.cpp index 0dd15c270b..4f181924a9 100644 --- a/map/render_policy_mt.cpp +++ b/map/render_policy_mt.cpp @@ -43,11 +43,13 @@ m2::RectI const RenderPolicyMT::OnSize(int w, int h) return m2::RectI(pt.x, pt.y, pt.x + w, pt.y + h); } -void RenderPolicyMT::BeginFrame() +void RenderPolicyMT::BeginFrame(shared_ptr const & e, + ScreenBase const & s) { } -void RenderPolicyMT::EndFrame() +void RenderPolicyMT::EndFrame(shared_ptr const & e, + ScreenBase const & s) { m_renderQueue.renderState().m_mutex->Unlock(); } diff --git a/map/render_policy_mt.hpp b/map/render_policy_mt.hpp index e34ee2bb4f..13dba5f564 100644 --- a/map/render_policy_mt.hpp +++ b/map/render_policy_mt.hpp @@ -20,12 +20,14 @@ public: void Initialize(shared_ptr const & rc, shared_ptr const & rm); - void BeginFrame(); + void BeginFrame(shared_ptr const & e, + ScreenBase const & s); - void DrawFrame(shared_ptr const & paintEvent, - ScreenBase const & screenBase); + void DrawFrame(shared_ptr const & e, + ScreenBase const & s); - void EndFrame(); + void EndFrame(shared_ptr const & e, + ScreenBase const & s); m2::RectI const OnSize(int w, int h); diff --git a/map/ruler.cpp b/map/ruler.cpp index 56a1b00dc4..764358f16d 100644 --- a/map/ruler.cpp +++ b/map/ruler.cpp @@ -211,7 +211,16 @@ void Ruler::draw(yg::gl::OverlayRenderer * s, math::Matrix const & } -void Ruler::cache(yg::StylesCache * stylesCache) const +void Ruler::map(yg::StylesCache * stylesCache) const +{ +} + +bool Ruler::find(yg::StylesCache * stylesCache) const +{ + return true; +} + +void Ruler::fillUnpacked(yg::StylesCache * stylesCache, vector & v) const { } diff --git a/map/ruler.hpp b/map/ruler.hpp index 9bb36a83e7..a237b74ca5 100644 --- a/map/ruler.hpp +++ b/map/ruler.hpp @@ -66,7 +66,10 @@ public: void draw(yg::gl::OverlayRenderer * r, math::Matrix const & m) const; - void cache(yg::StylesCache * stylesCache) const; + void map(yg::StylesCache * stylesCache) const; + bool find(yg::StylesCache * stylesCache) const; + void fillUnpacked(yg::StylesCache * stylesCache, vector & v) const; + int visualRank() const; yg::OverlayElement * clone(math::Matrix const & m) const; }; diff --git a/map/screen_coverage.cpp b/map/screen_coverage.cpp index 5eb9d8f355..4386128510 100644 --- a/map/screen_coverage.cpp +++ b/map/screen_coverage.cpp @@ -13,7 +13,7 @@ #include "coverage_generator.hpp" ScreenCoverage::ScreenCoverage() - : m_tiler(0, 0) + : m_tiler(0, 0), m_stylesCache(0) {} ScreenCoverage::ScreenCoverage(TileRenderer * tileRenderer, @@ -22,7 +22,8 @@ ScreenCoverage::ScreenCoverage(TileRenderer * tileRenderer, size_t scaleEtalonSize) : m_tileRenderer(tileRenderer), m_tiler(tileSize, scaleEtalonSize), - m_coverageGenerator(coverageGenerator) + m_coverageGenerator(coverageGenerator), + m_stylesCache(0) { m_infoLayer.setCouldOverlap(false); } @@ -52,10 +53,16 @@ ScreenCoverage * ScreenCoverage::Clone() tileCache->writeUnlock(); res->m_infoLayer = m_infoLayer; + res->m_stylesCache = 0; return res; } +void ScreenCoverage::SetStylesCache(yg::StylesCache * stylesCache) +{ + m_stylesCache = stylesCache; +} + void ScreenCoverage::Merge(Tiler::RectInfo const & ri) { if (m_tileRects.find(ri) == m_tileRects.end()) @@ -94,12 +101,12 @@ void ScreenCoverage::Merge(Tiler::RectInfo const & ri) 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(); + LOG(LWARN, ("no styles cache")); + else + { + m_infoLayer.cache(m_stylesCache); + m_stylesCache->upload(); + } } } @@ -182,16 +189,17 @@ void ScreenCoverage::SetScreen(ScreenBase const & screen, bool /*mergePathNames* 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()); - m_infoLayer.cache(m_stylesCache.get()); - m_stylesCache->upload(); + if (!m_stylesCache) + LOG(LWARN, ("no styles cache")); + else + { + m_infoLayer.cache(m_stylesCache); + m_stylesCache->upload(); + } /// adding commands for tiles which aren't in cache for (size_t i = 0; i < newRects.size(); ++i) @@ -240,7 +248,12 @@ 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()); + s->setAdditionalSkinPage(m_stylesCache->cachePage()); m_infoLayer.draw(s, m_screen.PtoGMatrix() * screen.GtoPMatrix()); } + +void ScreenCoverage::EndFrame(yg::gl::Screen *s) +{ + s->clearAdditionalSkinPage(); +} diff --git a/map/screen_coverage.hpp b/map/screen_coverage.hpp index bca86581ae..d9aeb0fe2f 100644 --- a/map/screen_coverage.hpp +++ b/map/screen_coverage.hpp @@ -44,9 +44,9 @@ 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; + yg::StylesCache * m_stylesCache; ScreenCoverage(ScreenCoverage const & src); ScreenCoverage const & operator=(ScreenCoverage const & src); @@ -61,6 +61,7 @@ public: size_t scaleEtalonSize); ScreenCoverage * Clone(); + void SetStylesCache(yg::StylesCache * stylesCache); /// add rendered tile to coverage. Tile is locked, so make sure to unlock it in case it's not needed. void Merge(Tiler::RectInfo const & ri); @@ -70,4 +71,5 @@ public: void SetScreen(ScreenBase const & screen, bool mergePathNames = true); /// draw screen coverage void Draw(yg::gl::Screen * s, ScreenBase const & currentScreen); + void EndFrame(yg::gl::Screen * s); }; diff --git a/map/tiling_render_policy_mt.cpp b/map/tiling_render_policy_mt.cpp index 04e9dba8e7..584e8ca84e 100644 --- a/map/tiling_render_policy_mt.cpp +++ b/map/tiling_render_policy_mt.cpp @@ -36,17 +36,21 @@ void TilingRenderPolicyMT::Initialize(shared_ptr const & RenderPolicy::Initialize(primaryContext, resourceManager); resourceManager->initRenderTargets(GetPlatform().TileSize(), GetPlatform().TileSize(), GetPlatform().MaxTilesCount()); + resourceManager->initStyleCacheTextures(resourceManager->fontTextureWidth(), resourceManager->fontTextureHeight() * 2, 2); m_tileRenderer.Initialize(primaryContext, resourceManager, GetPlatform().VisualScale()); m_coverageGenerator.Initialize(primaryContext, resourceManager); } -void TilingRenderPolicyMT::BeginFrame() +void TilingRenderPolicyMT::BeginFrame(shared_ptr const & e, ScreenBase const & s) { } -void TilingRenderPolicyMT::EndFrame() +void TilingRenderPolicyMT::EndFrame(shared_ptr const & e, ScreenBase const & s) { + ScreenCoverage * curCvg = &m_coverageGenerator.CurrentCoverage(); + curCvg->EndFrame(e->drawer()->screen().get()); + m_coverageGenerator.Mutex().Unlock(); } void TilingRenderPolicyMT::DrawFrame(shared_ptr const & e, ScreenBase const & currentScreen) @@ -57,10 +61,11 @@ void TilingRenderPolicyMT::DrawFrame(shared_ptr const & e, ScreenBas m_coverageGenerator.AddCoverScreenTask(currentScreen); - { - threads::MutexGuard g(m_coverageGenerator.Mutex()); - m_coverageGenerator.CurrentCoverage().Draw(pDrawer->screen().get(), currentScreen); - } + m_coverageGenerator.Mutex().Lock(); + + ScreenCoverage * curCvg = &m_coverageGenerator.CurrentCoverage(); + + curCvg->Draw(pDrawer->screen().get(), currentScreen); } TileRenderer & TilingRenderPolicyMT::GetTileRenderer() diff --git a/map/tiling_render_policy_mt.hpp b/map/tiling_render_policy_mt.hpp index 76b5b2370c..fb7077839c 100644 --- a/map/tiling_render_policy_mt.hpp +++ b/map/tiling_render_policy_mt.hpp @@ -43,7 +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(); + void BeginFrame(shared_ptr const & ev, ScreenBase const & s); + void DrawFrame(shared_ptr const & ev, ScreenBase const & s); + void EndFrame(shared_ptr const & ev, ScreenBase const & s); }; diff --git a/qt/draw_widget.cpp b/qt/draw_widget.cpp index aa6a2aeaca..670a2a2624 100644 --- a/qt/draw_widget.cpp +++ b/qt/draw_widget.cpp @@ -188,14 +188,16 @@ namespace qt { makeCurrent(); m_framework->SetNeedRedraw(false); - m_framework->BeginPaint(); + shared_ptr paintEvent(new PaintEvent(GetDrawer().get())); + + m_framework->BeginPaint(paintEvent); m_framework->DoPaint(paintEvent); /// swapping buffers before ending the frame, see issue #333 swapBuffers(); - m_framework->EndPaint(); + m_framework->EndPaint(paintEvent); doneCurrent(); } } diff --git a/yg/composite_overlay_element.cpp b/yg/composite_overlay_element.cpp index 18e1c0332d..31e01d785a 100644 --- a/yg/composite_overlay_element.cpp +++ b/yg/composite_overlay_element.cpp @@ -48,10 +48,25 @@ namespace yg m_elements[i]->draw(r, m); } - void CompositeOverlayElement::cache(StylesCache * stylesCache) const + void CompositeOverlayElement::map(StylesCache * stylesCache) const { for (unsigned i = 0; i < m_elements.size(); ++i) - m_elements[i]->cache(stylesCache); + m_elements[i]->map(stylesCache); + } + + void CompositeOverlayElement::fillUnpacked(StylesCache * stylesCache, vector & v) const + { + for (unsigned i = 0; i < m_elements.size(); ++i) + m_elements[i]->fillUnpacked(stylesCache, v); + } + + bool CompositeOverlayElement::find(StylesCache * stylesCache) const + { + for (unsigned i = 0; i < m_elements.size(); ++i) + if (!m_elements[i]->find(stylesCache)) + return false; + + return true; } int CompositeOverlayElement::visualRank() const diff --git a/yg/composite_overlay_element.hpp b/yg/composite_overlay_element.hpp index d85f90de04..ebaafe16db 100644 --- a/yg/composite_overlay_element.hpp +++ b/yg/composite_overlay_element.hpp @@ -25,9 +25,14 @@ namespace yg vector const & boundRects() const; void draw(gl::OverlayRenderer * r, math::Matrix const & m) const; - void cache(StylesCache * stylesCache) const; + + void map(StylesCache * stylesCache) const; + bool find(StylesCache * stylesCache) const; + void fillUnpacked(StylesCache * stylesCache, vector & v) const; + int visualRank() const; + void offset(m2::PointD const & offs); }; } diff --git a/yg/geometry_batcher.cpp b/yg/geometry_batcher.cpp index 4808886e03..ad5f1a7be7 100644 --- a/yg/geometry_batcher.cpp +++ b/yg/geometry_batcher.cpp @@ -97,21 +97,21 @@ namespace yg } } - void GeometryBatcher::setAdditionalSkinPages(vector > const & v) + void GeometryBatcher::setAdditionalSkinPage(shared_ptr const & p) { if (m_skin != 0) { - m_skin->setAdditionalPages(v); + m_skin->setAdditionalPage(p); int pagesCount = m_skin->getPagesCount(); - m_pipelines.resize(pagesCount + v.size()); + m_pipelines.resize(pagesCount + 1); - /// additional pages are fixed + /// additional page are fixed /*m_skin->addOverflowFn(bind(&GeometryBatcher::flush, this, _1), 100); m_skin->addClearPageFn(bind(&GeometryBatcher::flush, this, _1), 100); m_skin->addClearPageFn(bind(&GeometryBatcher::switchTextures, this, _1), 99);*/ - for (size_t i = 0; i < v.size(); ++i) + for (size_t i = 0; i < 1; ++i) { m_pipelines[i + pagesCount].m_useTinyStorage = m_useTinyStorage; m_pipelines[i + pagesCount].m_currentVertex = 0; @@ -128,11 +128,29 @@ namespace yg } } - void GeometryBatcher::clearAdditionalSkinPages() + void GeometryBatcher::clearAdditionalSkinPage() { if (m_skin != 0) { - m_skin->clearAdditionalPages(); + size_t pagesCount = m_skin->getPagesCount(); + size_t additionalPagesCount = m_skin->getAdditionalPagesCount(); + + m_skin->clearAdditionalPage(); + + for (unsigned i = pagesCount; i < pagesCount + additionalPagesCount; ++i) + { + if (m_pipelines[i].m_hasStorage) + { + if (m_useTinyStorage) + resourceManager()->tinyStorages()->Free(m_pipelines[i].m_storage); + else + if (m_skin->getPage(i)->usage() != SkinPage::EStaticUsage) + resourceManager()->storages()->Free(m_pipelines[i].m_storage); + else + resourceManager()->smallStorages()->Free(m_pipelines[i].m_storage); + } + } + m_pipelines.resize(m_skin->getPagesCount()); } } @@ -212,8 +230,6 @@ namespace yg } } - clearAdditionalSkinPages(); - base_t::endFrame(); } diff --git a/yg/geometry_batcher.hpp b/yg/geometry_batcher.hpp index 3330a1a4c9..40fd59e6f7 100644 --- a/yg/geometry_batcher.hpp +++ b/yg/geometry_batcher.hpp @@ -183,8 +183,8 @@ namespace yg void enterBackground(); void enterForeground(); - void setAdditionalSkinPages(vector > const & v); - void clearAdditionalSkinPages(); + void setAdditionalSkinPage(shared_ptr const & v); + void clearAdditionalSkinPage(); }; } } diff --git a/yg/info_layer.cpp b/yg/info_layer.cpp index c5859c0891..1f03365244 100644 --- a/yg/info_layer.cpp +++ b/yg/info_layer.cpp @@ -143,9 +143,61 @@ namespace yg layer.m_tree.ForEach(bind(&InfoLayer::processOverlayElement, this, _1, m)); } + bool greater_priority(shared_ptr const & l, + shared_ptr const & r) + { + return l->visualRank() > r->visualRank(); + } + void InfoLayer::cache(StylesCache * stylesCache) { - m_tree.ForEach(bind(&OverlayElement::cache, _1, stylesCache)); + /// collecting elements into vector sorted by visualPriority + + vector > v; + m_tree.ForEach(bind(&vector >::push_back, &v, _1)); + + sort(v.begin(), v.end(), &greater_priority); + + for (unsigned i = 0; i < v.size(); ++i) + v[i]->setIsNeedRedraw(true); + + /// caching on StylesCache::m_maxPagesCount at most + + vector sizes; + sizes.reserve(100); + + for (unsigned i = 0; i < v.size(); ++i) + v[i]->fillUnpacked(stylesCache, sizes); + + if (stylesCache->hasRoom(&sizes[0], sizes.size())) + { + for (unsigned i = 0; i < v.size(); ++i) + v[i]->map(stylesCache); + } + else + { + /// no room to cache, so clear all pages and re-cache from the beginning + stylesCache->clear(); + + int pos = 0; + + for (pos = 0; pos < v.size(); ++pos) + { + sizes.clear(); + v[pos]->fillUnpacked(stylesCache, sizes); + if (stylesCache->hasRoom(&sizes[0], sizes.size())) + v[pos]->map(stylesCache); + else + break; + } + + if (v.size() - pos > 1) + LOG(LINFO, ("making ", v.size() - pos, "elements invisible")); + + /// making all uncached elements invisible + for (; pos < v.size(); ++pos) + v[pos]->setIsNeedRedraw(false); + } } } diff --git a/yg/overlay_element.hpp b/yg/overlay_element.hpp index 05999a2989..f6c7cef7f1 100644 --- a/yg/overlay_element.hpp +++ b/yg/overlay_element.hpp @@ -51,9 +51,15 @@ namespace yg /// PLEASE, REMEMBER THE REFERENCE!!! virtual vector const & boundRects() const = 0; virtual void draw(gl::OverlayRenderer * r, math::Matrix const & m) const = 0; - virtual void cache(StylesCache * stylesCache) const = 0; virtual int visualRank() const = 0; + /// caching-related functions. + /// @{ + virtual void fillUnpacked(StylesCache * stylesCache, vector & sizes) const = 0; + virtual bool find(StylesCache * stylesCache) const = 0; + virtual void map(StylesCache * stylesCache) const = 0; + /// @} + m2::PointD const & pivot() const; void setPivot(m2::PointD const & pv); diff --git a/yg/path_text_element.cpp b/yg/path_text_element.cpp index 54d0bed995..2d8985e165 100644 --- a/yg/path_text_element.cpp +++ b/yg/path_text_element.cpp @@ -64,12 +64,13 @@ namespace yg return; yg::FontDesc desc = m_fontDesc; - if (m_fontDesc.m_isMasked) + + if (desc.m_isMasked) { if ((m_glyphLayout.firstVisible() != 0) || (m_glyphLayout.lastVisible() != visText().size())) return; - drawTextImpl(m_glyphLayout, screen, m, m_fontDesc, yg::maxDepth); + drawTextImpl(m_glyphLayout, screen, m, desc, yg::maxDepth - 1); desc.m_isMasked = false; } @@ -82,17 +83,42 @@ namespace yg m_glyphLayout.setPivot(pivot()); } - void PathTextElement::cache(StylesCache * stylesCache) const + bool PathTextElement::find(StylesCache * stylesCache) const { yg::FontDesc desc = m_fontDesc; - - if (m_fontDesc.m_isMasked) + if (desc.m_isMasked) { - cacheTextImpl(m_glyphLayout, stylesCache, m_fontDesc); + if (!TextElement::find(m_glyphLayout, stylesCache, desc)) + return false; desc.m_isMasked = false; } - cacheTextImpl(m_glyphLayout, stylesCache, desc); + return TextElement::find(m_glyphLayout, stylesCache, desc); + } + + void PathTextElement::fillUnpacked(StylesCache * stylesCache, vector & v) const + { + yg::FontDesc desc = m_fontDesc; + if (desc.m_isMasked) + { + TextElement::fillUnpacked(m_glyphLayout, desc, stylesCache, v); + desc.m_isMasked = false; + } + + return TextElement::fillUnpacked(m_glyphLayout, desc, stylesCache, v); + } + + void PathTextElement::map(StylesCache * stylesCache) const + { + yg::FontDesc desc = m_fontDesc; + + if (desc.m_isMasked) + { + TextElement::map(m_glyphLayout, stylesCache, desc); + desc.m_isMasked = false; + } + + TextElement::map(m_glyphLayout, stylesCache, desc); } int PathTextElement::visualRank() const diff --git a/yg/path_text_element.hpp b/yg/path_text_element.hpp index 1795e0ec94..cafc76df24 100644 --- a/yg/path_text_element.hpp +++ b/yg/path_text_element.hpp @@ -28,7 +28,11 @@ namespace yg vector const & boundRects() const; void draw(gl::OverlayRenderer * r, math::Matrix const & m) const; - void cache(StylesCache * stylesCache) const; + + void fillUnpacked(StylesCache * stylesCache, vector & v) const; + bool find(StylesCache * stylesCache) const; + void map(StylesCache * stylesCache) const; + int visualRank() const; void offset(m2::PointD const & offs); diff --git a/yg/resource_manager.cpp b/yg/resource_manager.cpp index 9578fae6e4..89500d6d4e 100644 --- a/yg/resource_manager.cpp +++ b/yg/resource_manager.cpp @@ -57,6 +57,8 @@ namespace yg m_format(fmt), m_useVA(useVA) { + LOG(LINFO, ("allocating ", glyphCacheCount, " glyphCaches, ", glyphCacheSize, " bytes total.")); + for (size_t i = 0; i < glyphCacheCount; ++i) m_glyphCaches.push_back(GlyphCache(GlyphCache::Params(blocksFile, whiteListFile, blackListFile, glyphCacheSize / glyphCacheCount))); @@ -95,6 +97,14 @@ namespace yg m_renderTargets.reset(new TTexturePool(TTexturePoolTraits(TTextureFactory(renderTargetWidth, renderTargetHeight, "renderTargets"), renderTargetsCount))); } + void ResourceManager::initStyleCacheTextures(size_t styleCacheTextureWidth, size_t styleCacheTextureHeight, size_t styleCacheTexturesCount) + { + m_styleCacheTextureWidth = styleCacheTextureWidth; + m_styleCacheTextureHeight = styleCacheTextureHeight; + + m_styleCacheTextures.reset(new TTexturePool(TTexturePoolTraits(TTextureFactory(styleCacheTextureWidth, styleCacheTextureHeight, "styleCacheTextures"), styleCacheTexturesCount))); + } + shared_ptr const & ResourceManager::getTexture(string const & fileName) { TStaticTextures::const_iterator it = m_staticTextures.find(fileName); @@ -204,6 +214,9 @@ namespace yg if (m_renderTargets.get()) m_renderTargets->EnterBackground(); + + if (m_styleCacheTextures.get()) + m_styleCacheTextures->EnterBackground(); } void ResourceManager::enterForeground() @@ -233,6 +246,9 @@ namespace yg if (m_renderTargets.get()) m_renderTargets->EnterForeground(); + + if (m_styleCacheTextures.get()) + m_styleCacheTextures->EnterForeground(); } shared_ptr ResourceManager::createRenderTarget(unsigned w, unsigned h) @@ -302,4 +318,9 @@ namespace yg { return m_renderTargets.get(); } + + ResourceManager::TTexturePool * ResourceManager::styleCacheTextures() + { + return m_styleCacheTextures.get(); + } } diff --git a/yg/resource_manager.hpp b/yg/resource_manager.hpp index 6d83ceb7d1..51b5cea441 100644 --- a/yg/resource_manager.hpp +++ b/yg/resource_manager.hpp @@ -75,6 +75,11 @@ namespace yg auto_ptr m_fontTextures; + size_t m_styleCacheTextureWidth; + size_t m_styleCacheTextureHeight; + + auto_ptr m_styleCacheTextures; + size_t m_renderTargetWidth; size_t m_renderTargetHeight; @@ -123,6 +128,7 @@ namespace yg void initMultiBlitStorage(size_t multiBlitVBSize, size_t multiBlitIBSize, size_t multiBlitStoragesCount); void initRenderTargets(size_t renderTargetWidth, size_t renderTargetHeight, size_t renderTargetCount); void initTinyStorage(size_t tinyVBSize, size_t tinyIBSize, size_t tinyStoragesCount); + void initStyleCacheTextures(size_t styleCacheTextureWidth, size_t styleCacheTextureHeight, size_t styleCacheTexturesCount); shared_ptr const & getTexture(string const & fileName); @@ -135,6 +141,7 @@ namespace yg TTexturePool * dynamicTextures(); TTexturePool * fontTextures(); TTexturePool * renderTargets(); + TTexturePool * styleCacheTextures(); size_t dynamicTextureWidth() const; size_t dynamicTextureHeight() const; diff --git a/yg/skin.cpp b/yg/skin.cpp index ff1cdb7d52..74069baca1 100644 --- a/yg/skin.cpp +++ b/yg/skin.cpp @@ -255,6 +255,11 @@ namespace yg return m_pages.size(); } + size_t Skin::getAdditionalPagesCount() const + { + return m_additionalPages.size(); + } + void Skin::addClearPageFn(clearPageFn fn, int priority) { m_clearPageFns.push(std::pair(priority, fn)); @@ -368,17 +373,15 @@ namespace yg { } - void Skin::setAdditionalPages(vector > const & pages) + void Skin::setAdditionalPage(shared_ptr const & page) { - m_additionalPages = pages; - for (unsigned i = 0; i < pages.size(); ++i) - m_additionalPages[i]->setPipelineID(i + m_pages.size()); + m_additionalPages.clear(); + m_additionalPages.push_back(page); + m_additionalPages[0]->setPipelineID(0 + m_pages.size()); } - void Skin::clearAdditionalPages() + void Skin::clearAdditionalPage() { - for (unsigned i = 0; i < m_additionalPages.size(); ++i) - m_additionalPages[i]->freeTexture(); m_additionalPages.clear(); } } diff --git a/yg/skin.hpp b/yg/skin.hpp index 182d1abbe9..c14104bc05 100644 --- a/yg/skin.hpp +++ b/yg/skin.hpp @@ -141,6 +141,7 @@ namespace yg shared_ptr const & getPage(int i) const; size_t getPagesCount() const; + size_t getAdditionalPagesCount() const; uint32_t invalidHandle() const; uint32_t invalidPageHandle() const; @@ -148,8 +149,8 @@ namespace yg uint8_t currentTextPage() const; uint8_t currentDynamicPage() const; - void setAdditionalPages(vector > const & pages); - void clearAdditionalPages(); + void setAdditionalPage(shared_ptr const & pages); + void clearAdditionalPage(); void memoryWarning(); void enterBackground(); diff --git a/yg/skin_page.cpp b/yg/skin_page.cpp index 18ae9d71da..d008fbbb6f 100644 --- a/yg/skin_page.cpp +++ b/yg/skin_page.cpp @@ -91,6 +91,11 @@ namespace yg return it->second.first.get(); } + SkinPage::SkinPage() + : m_usage(EStaticUsage), + m_pipelineID(0) + {} + SkinPage::SkinPage(shared_ptr const & resourceManager, char const * name, @@ -102,7 +107,6 @@ namespace yg m_packer = m2::Packer(m_texture->width(), m_texture->height(), 0x00FFFFFF - 1); } - SkinPage::SkinPage(shared_ptr const & resourceManager, EUsage usage, uint8_t pipelineID) @@ -126,6 +130,20 @@ namespace yg m_packer.reset(); } + void SkinPage::clearUploadCommands() + { + m_penUploadCommands.clear(); + m_colorUploadCommands.clear(); + m_glyphUploadCommands.clear(); + m_circleUploadCommands.clear(); + } + + void SkinPage::clear() + { + clearHandles(); + clearUploadCommands(); + } + void SkinPage::clearColorHandles() { for (TColorMap::const_iterator it = m_colorMap.begin(); it != m_colorMap.end(); ++it) @@ -240,6 +258,11 @@ namespace yg return m_packer.hasRoom(gi->m_metrics.m_width + 4, gi->m_metrics.m_height + 4); } + bool SkinPage::hasRoom(m2::PointU const * sizes, size_t cnt) const + { + return m_packer.hasRoom(sizes, cnt); + } + uint32_t SkinPage::findCircleInfo(CircleInfo const & circleInfo) const { TCircleInfoMap::const_iterator it = m_circleInfoMap.find(circleInfo); @@ -738,7 +761,7 @@ namespace yg void SkinPage::uploadData() { - if ((m_usage != EStaticUsage) && (hasData())) + if (hasData()) { checkTexture(); static_cast(m_texture.get())->lock(); @@ -771,6 +794,14 @@ namespace yg return m_texture; } + void SkinPage::setTexture(shared_ptr const & texture) + { + m_texture = texture; + m_packer = m2::Packer(texture->width(), + texture->height(), + 0x00FFFFFF - 1); + } + void SkinPage::freeTexture() { if (m_texture) diff --git a/yg/skin_page.hpp b/yg/skin_page.hpp index 3cc5d20493..fba0478d42 100644 --- a/yg/skin_page.hpp +++ b/yg/skin_page.hpp @@ -116,6 +116,8 @@ namespace yg void uploadGlyphs(); void uploadCircleInfo(); + void clearUploadCommands(); + typedef vector TFonts; TFonts m_fonts; @@ -139,12 +141,17 @@ namespace yg void clearHandles(); + void clear(); + bool hasData(); void uploadData(); void checkTexture() const; void setPipelineID(uint8_t pipelineID); + /// creation of detached page + SkinPage(); + /// creation of a static page SkinPage(shared_ptr const & resourceManager, char const * name, @@ -174,6 +181,7 @@ namespace yg uint32_t findGlyph(GlyphKey const & g) const; uint32_t mapGlyph(GlyphKey const & g, GlyphCache * glyphCache); bool hasRoom(GlyphKey const & g, GlyphCache * glyphCache) const; + bool hasRoom(m2::PointU const * sizes, size_t cnt) const; uint32_t findSymbol(char const * symbolName) const; @@ -185,5 +193,6 @@ namespace yg void addOverflowFn(overflowFn fn, int priority); shared_ptr const & texture() const; + void setTexture(shared_ptr const & t); }; } diff --git a/yg/straight_text_element.cpp b/yg/straight_text_element.cpp index 1325b00454..2bbf537f3b 100644 --- a/yg/straight_text_element.cpp +++ b/yg/straight_text_element.cpp @@ -201,7 +201,7 @@ namespace yg if (m_fontDesc.m_isMasked) { for (unsigned i = 0; i < m_glyphLayouts.size(); ++i) - drawTextImpl(m_glyphLayouts[i], screen, m, m_fontDesc, yg::maxDepth); + drawTextImpl(m_glyphLayouts[i], screen, m, m_fontDesc, yg::maxDepth - 1); desc.m_isMasked = false; } @@ -218,18 +218,54 @@ namespace yg m_glyphLayouts[i].setPivot(m_glyphLayouts[i].pivot() + offs); } - void StraightTextElement::cache(StylesCache * stylesCache) const + void StraightTextElement::map(StylesCache * stylesCache) const { yg::FontDesc desc = m_fontDesc; - if (m_fontDesc.m_isMasked) + if (desc.m_isMasked) { for (unsigned i = 0; i < m_glyphLayouts.size(); ++i) - cacheTextImpl(m_glyphLayouts[i], stylesCache, m_fontDesc); + TextElement::map(m_glyphLayouts[i], stylesCache, desc); desc.m_isMasked = false; } for (unsigned i = 0; i < m_glyphLayouts.size(); ++i) - cacheTextImpl(m_glyphLayouts[i], stylesCache, desc); + TextElement::map(m_glyphLayouts[i], stylesCache, desc); + } + + bool StraightTextElement::find(StylesCache * stylesCache) const + { + yg::FontDesc desc = m_fontDesc; + + if (desc.m_isMasked) + { + for (unsigned i = 0; i < m_glyphLayouts.size(); ++i) + if (!TextElement::find(m_glyphLayouts[i], stylesCache, desc)) + return false; + + desc.m_isMasked = false; + } + + for (unsigned i = 0; i < m_glyphLayouts.size(); ++i) + if (!TextElement::find(m_glyphLayouts[i], stylesCache, desc)) + return false; + + return true; + } + + void StraightTextElement::fillUnpacked(StylesCache * stylesCache, vector & v) const + { + yg::FontDesc desc = m_fontDesc; + + if (desc.m_isMasked) + { + for (unsigned i = 0; i < m_glyphLayouts.size(); ++i) + TextElement::fillUnpacked(m_glyphLayouts[i], desc, stylesCache, v); + + desc.m_isMasked = false; + } + + for (unsigned i = 0; i < m_glyphLayouts.size(); ++i) + TextElement::fillUnpacked(m_glyphLayouts[i], desc, stylesCache, v); } int StraightTextElement::visualRank() const diff --git a/yg/straight_text_element.hpp b/yg/straight_text_element.hpp index 352b457820..6d05a70d0f 100644 --- a/yg/straight_text_element.hpp +++ b/yg/straight_text_element.hpp @@ -31,7 +31,11 @@ namespace yg vector const & boundRects() const; void draw(gl::OverlayRenderer * r, math::Matrix const & m) const; - void cache(StylesCache * stylesCache) const; + + void fillUnpacked(StylesCache * stylesCache, vector & v) const; + bool find(StylesCache * stylesCache) const; + void map(StylesCache * stylesCache) const; + int visualRank() const; void offset(m2::PointD const & offs); diff --git a/yg/styles_cache.cpp b/yg/styles_cache.cpp index da8ffb6f15..c02064c122 100644 --- a/yg/styles_cache.cpp +++ b/yg/styles_cache.cpp @@ -5,27 +5,30 @@ #include "glyph_cache.hpp" #include "skin_page.hpp" #include "resource_manager.hpp" +#include "base_texture.hpp" +#include "internal/opengl.hpp" + +#include "../base/thread.hpp" namespace yg { StylesCache::StylesCache(shared_ptr const & rm, - int glyphCacheID, - int maxPagesCount) - : m_rm(rm), - m_maxPagesCount(maxPagesCount) + int glyphCacheID) + : m_rm(rm) { m_glyphCache = m_rm->glyphCache(glyphCacheID); + m_cachePage.reset(new SkinPage()); + m_cachePage->setTexture(m_rm->styleCacheTextures()->Reserve()); } StylesCache::~StylesCache() { - for (unsigned i = 0; i < m_cachePages.size(); ++i) - m_cachePages[i]->freeTexture(); + m_rm->styleCacheTextures()->Free(m_cachePage->texture()); } - vector > & StylesCache::cachePages() + shared_ptr const & StylesCache::cachePage() { - return m_cachePages; + return m_cachePage; } shared_ptr const & StylesCache::resourceManager() @@ -38,9 +41,19 @@ namespace yg return m_glyphCache; } + void StylesCache::clear() + { + m_cachePage->clear(); + } + void StylesCache::upload() { - for (unsigned i = 0; i < m_cachePages.size(); ++i) - m_cachePages[i]->uploadData(); + m_cachePage->uploadData(); + OGLCHECK(glFinish()); + } + + bool StylesCache::hasRoom(m2::PointU const * sizes, size_t cnt) const + { + return m_cachePage->hasRoom(sizes, cnt); } } diff --git a/yg/styles_cache.hpp b/yg/styles_cache.hpp index 00ca6b2114..09db4ffd60 100644 --- a/yg/styles_cache.hpp +++ b/yg/styles_cache.hpp @@ -1,7 +1,7 @@ #pragma once #include "../std/shared_ptr.hpp" -#include "../std/vector.hpp" +#include "../geometry/point2d.hpp" namespace yg { @@ -11,29 +11,34 @@ namespace yg class GlyphCache; class ResourceManager; + /// - cache of potentially all yg::ResourceStyle's + /// - cache is build on the separate thread (CoverageGenerator thread) + /// - it is used to remove texture uploading code from the GUI-thread class StylesCache { private: - vector > m_cachePages; shared_ptr m_rm; GlyphCache * m_glyphCache; - int m_maxPagesCount; + + shared_ptr m_cachePage; public: StylesCache(shared_ptr const & rm, - int glyphCacheID, - int maxPagesCount); + int glyphCacheID); ~StylesCache(); - vector > & cachePages(); + shared_ptr const & cachePage(); shared_ptr const & resourceManager(); GlyphCache * glyphCache(); void upload(); + void clear(); + + bool hasRoom(m2::PointU const * sizes, size_t cnt) const; }; } diff --git a/yg/symbol_element.cpp b/yg/symbol_element.cpp index 0bbb71d1e7..efc7ff9c75 100644 --- a/yg/symbol_element.cpp +++ b/yg/symbol_element.cpp @@ -88,7 +88,16 @@ namespace yg return m_styleID; } - void SymbolElement::cache(StylesCache * stylesCache) const + void SymbolElement::map(StylesCache * stylesCache) const + { + } + + bool SymbolElement::find(StylesCache * stylesCache) const + { + return true; + } + + void SymbolElement::fillUnpacked(StylesCache * stylesCache, vector & v) const { } diff --git a/yg/symbol_element.hpp b/yg/symbol_element.hpp index db6b1fb289..152c1e48da 100644 --- a/yg/symbol_element.hpp +++ b/yg/symbol_element.hpp @@ -38,7 +38,10 @@ namespace yg vector const & boundRects() const; void draw(gl::OverlayRenderer * s, math::Matrix const & m) const; - void cache(StylesCache * stylesCache) const; + + void map(StylesCache * stylesCache) const; + void fillUnpacked(StylesCache * stylesCache, vector & v) const; + bool find(StylesCache * stylesCache) const; uint32_t styleID() const; diff --git a/yg/text_element.cpp b/yg/text_element.cpp index bf4531744b..3a04a63282 100644 --- a/yg/text_element.cpp +++ b/yg/text_element.cpp @@ -52,7 +52,10 @@ namespace yg { Skin * skin = screen->skin().get(); GlyphLayoutElem const & elem = layout.entries()[i]; - GlyphKey glyphKey(elem.m_sym, fontDesc.m_size, fontDesc.m_isMasked, fontDesc.m_isMasked ? fontDesc.m_maskColor : fontDesc.m_color); + GlyphKey glyphKey(elem.m_sym, + fontDesc.m_size, + fontDesc.m_isMasked, + fontDesc.m_isMasked ? fontDesc.m_maskColor : fontDesc.m_color); uint32_t const glyphID = skin->mapGlyph(glyphKey, screen->glyphCache()); CharStyle const * charStyle = static_cast(skin->fromID(glyphID)); @@ -60,42 +63,79 @@ namespace yg } } - void TextElement::cacheTextImpl(GlyphLayout const & layout, - StylesCache * stylesCache, - FontDesc const & desc) const + void TextElement::map(GlyphLayout const & layout, + StylesCache * stylesCache, + FontDesc const & desc) const { - vector > & skinPages = stylesCache->cachePages(); + shared_ptr const & skinPage = stylesCache->cachePage(); GlyphCache * glyphCache = stylesCache->glyphCache(); - shared_ptr const & rm = stylesCache->resourceManager(); 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); + desc.m_size, + desc.m_isMasked, + desc.m_isMasked ? desc.m_maskColor : desc.m_color); - bool found = false; + bool packed = skinPage->findGlyph(glyphKey) != 0x00FFFFFF; - for (unsigned j = 0; j < skinPages.size(); ++j) - if (skinPages[j]->findGlyph(glyphKey) != 0x00FFFFFF) - { - found = true; - break; - } - - if (!found) + if (!packed) { - if (!skinPages.empty() && skinPages.back()->hasRoom(glyphKey, glyphCache)) - skinPages.back()->mapGlyph(glyphKey, glyphCache); - else + if (skinPage->hasRoom(glyphKey, glyphCache)) { - skinPages.push_back(make_shared_ptr(new SkinPage(rm, SkinPage::EFontsUsage, 0))); - skinPages.back()->mapGlyph(glyphKey, glyphCache); + skinPage->mapGlyph(glyphKey, glyphCache); + packed = true; } } + + CHECK(packed, ("couldn't pack")); + } + } + + bool TextElement::find(GlyphLayout const & layout, StylesCache * stylesCache, FontDesc const & desc) const + { + shared_ptr const & skinPage = stylesCache->cachePage(); + + for (unsigned i = layout.firstVisible(); i < layout.lastVisible(); ++i) + { + GlyphLayoutElem const & elem = layout.entries()[i]; + + GlyphKey glyphKey(elem.m_sym, + desc.m_size, + desc.m_isMasked, + desc.m_isMasked ? desc.m_maskColor : desc.m_color); + + if (skinPage->findGlyph(glyphKey) == 0x00FFFFFF) + return false; + } + + return true; + } + + void TextElement::fillUnpacked(GlyphLayout const & layout, + FontDesc const & desc, + StylesCache * stylesCache, + vector & v) const + { + shared_ptr const & skinPage = stylesCache->cachePage(); + GlyphCache * glyphCache = stylesCache->glyphCache(); + + for (unsigned i = layout.firstVisible(); i < layout.lastVisible(); ++i) + { + GlyphLayoutElem const & elem = layout.entries()[i]; + + GlyphKey glyphKey(elem.m_sym, + desc.m_size, + desc.m_isMasked, + desc.m_isMasked ? desc.m_maskColor : desc.m_color); + + if (skinPage->findGlyph(glyphKey) == 0x00FFFFFF) + { + shared_ptr gi = glyphCache->getGlyphInfo(glyphKey); + v.push_back(m2::PointU(gi->m_metrics.m_width + 4, gi->m_metrics.m_height + 4)); + } } } } diff --git a/yg/text_element.hpp b/yg/text_element.hpp index fb395d00cd..984205087f 100644 --- a/yg/text_element.hpp +++ b/yg/text_element.hpp @@ -38,6 +38,21 @@ namespace yg bool isBidi() const; + protected: + + void map(GlyphLayout const & layout, + StylesCache * stylesCache, + FontDesc const & desc) const; + + bool find(GlyphLayout const & layout, + StylesCache * stylesCache, + FontDesc const & desc) const; + + void fillUnpacked(GlyphLayout const & layout, + FontDesc const & desc, + StylesCache * stylesCache, + vector & v) const; + public: struct Params : OverlayElement::Params @@ -50,10 +65,6 @@ namespace yg TextElement(Params const & p); - void cacheTextImpl(GlyphLayout const & layout, - StylesCache * stylesCache, - FontDesc const & desc) const; - void drawTextImpl(GlyphLayout const & layout, gl::OverlayRenderer * r, math::Matrix const & m,