From 9b177a7c73d93bf7bf585978228aafd5c55a3384 Mon Sep 17 00:00:00 2001 From: rachytski Date: Tue, 14 Jun 2011 00:46:06 +0300 Subject: [PATCH] restored "frozen" text rendering logic. --- iphone/Maps/Classes/EAGLView.mm | 6 +- map/drawer_yg.cpp | 6 +- map/render_queue_routine.cpp | 6 +- qt/widgets.cpp | 9 ++- qt_tstfrm/tstwidgets.cpp | 8 ++- yg/geometry_batcher.cpp | 22 +++--- yg/geometry_batcher.hpp | 3 +- yg/info_layer.cpp | 30 ++++++-- yg/resource_manager.cpp | 118 +++++++++++++++++++++++-------- yg/resource_manager.hpp | 34 +++++++-- yg/skin.cpp | 4 +- yg/skin_page.cpp | 63 +++++++++++++---- yg/skin_page.hpp | 13 +++- yg/text_element.cpp | 33 ++++++++- yg/text_element.hpp | 9 +++ yg/text_renderer.cpp | 2 +- yg/yg_tests/skin_loader_test.cpp | 2 +- yg/yg_tests/skin_test.cpp | 2 +- 18 files changed, 282 insertions(+), 88 deletions(-) diff --git a/iphone/Maps/Classes/EAGLView.mm b/iphone/Maps/Classes/EAGLView.mm index 765ad7cc33..b39e4e64fc 100644 --- a/iphone/Maps/Classes/EAGLView.mm +++ b/iphone/Maps/Classes/EAGLView.mm @@ -98,11 +98,13 @@ bigVBSize, bigIBSize, 4, smallVBSize, smallIBSize, 10, blitVBSize, blitIBSize, 10, - 512, 256, 10, + 512, 256, 6, + 512, 256, 4, GetPlatform().ReadPathForFile("unicode_blocks.txt").c_str(), GetPlatform().ReadPathForFile("fonts_whitelist.txt").c_str(), GetPlatform().ReadPathForFile("fonts_blacklist.txt").c_str(), - 2000000, + 2 * 1024 * 1024, + 500 * 1024, fmt, !yg::gl::g_isBufferObjectsSupported, !GetPlatform().IsMultiSampled())); diff --git a/map/drawer_yg.cpp b/map/drawer_yg.cpp index 056226c103..553935f6d8 100644 --- a/map/drawer_yg.cpp +++ b/map/drawer_yg.cpp @@ -260,7 +260,7 @@ void DrawerYG::drawText(m2::PointD const & pt, di::DrawInfo const * pInfo, rule_ true); } -bool DrawerYG::drawPathText(di::PathInfo const & info, string const & name, uint8_t fontSize, int /*depth*/) +bool DrawerYG::drawPathText(di::PathInfo const & info, string const & name, uint8_t fontSize, int depth) { // bool const isMasked = (double(fontSize) / m_visualScale >= min_text_height); @@ -273,12 +273,12 @@ bool DrawerYG::drawPathText(di::PathInfo const & info, string const & name, uint info.GetFullLength(), info.GetOffset(), yg::EPosCenter, - yg::maxDepth); + depth); } void DrawerYG::drawPathNumber(di::PathInfo const & path, di::DrawInfo const * pInfo) { - int const textHeight = 12; + int const textHeight = 12 * m_visualScale; m2::PointD pt; double const length = path.GetFullLength(); if (length >= (pInfo->m_road.size() + 2)*textHeight) diff --git a/map/render_queue_routine.cpp b/map/render_queue_routine.cpp index 5f1888145b..752d9a7a17 100644 --- a/map/render_queue_routine.cpp +++ b/map/render_queue_routine.cpp @@ -239,11 +239,11 @@ void RenderQueueRoutine::Do() params.m_renderState = m_renderState; params.m_doPeriodicalUpdate = m_doPeriodicalUpdate; params.m_updateInterval = m_updateInterval; - params.m_glyphCacheID = 0; + params.m_glyphCacheID = m_resourceManager->renderThreadGlyphCacheID(); /* params.m_isDebugging = true; params.m_drawPathes = false; params.m_drawAreas = false; - params.m_drawTexts = false;*/ + params.m_drawTexts = false; */ m_threadDrawer = make_shared_ptr(new DrawerYG(m_skinName, params)); @@ -389,8 +389,6 @@ void RenderQueueRoutine::Do() m_renderState->m_currentScreen); } -// m_threadDrawer->screen()->setNeedTextRedraw(isPanning); - ScreenBase const & frameScreen = m_currentRenderCommand->m_frameScreen; m2::RectD glbRect; frameScreen.PtoG(m2::RectD(textureRect.Center() - m2::PointD(m_scaleEtalonSize / 2, m_scaleEtalonSize / 2), diff --git a/qt/widgets.cpp b/qt/widgets.cpp index eb403f9391..8eb2d5a1b8 100644 --- a/qt/widgets.cpp +++ b/qt/widgets.cpp @@ -47,11 +47,14 @@ namespace qt 10 * sizeof(unsigned short), 50, 512, 256, - 15, + 10, + 512, 256, + 5, GetPlatform().ReadPathForFile("unicode_blocks.txt").c_str(), GetPlatform().ReadPathForFile("fonts_whitelist.txt").c_str(), GetPlatform().ReadPathForFile("fonts_blacklist.txt").c_str(), - 2000000, + 2 * 1024 * 1024, + 500 * 1024, yg::Rt8Bpp, !yg::gl::g_isBufferObjectsSupported, !GetPlatform().IsMultiSampled())); @@ -65,7 +68,7 @@ namespace qt p.m_frameBuffer = make_shared_ptr(new yg::gl::FrameBuffer(true)); p.m_dynamicPagesCount = 2; p.m_textPagesCount = 2; - p.m_glyphCacheID = 1; + p.m_glyphCacheID = m_resourceManager->guiThreadGlyphCacheID(); m_p = shared_ptr(new DrawerYG(GetPlatform().SkinName(), p)); } diff --git a/qt_tstfrm/tstwidgets.cpp b/qt_tstfrm/tstwidgets.cpp index 2582ed494a..e8967bcabc 100644 --- a/qt_tstfrm/tstwidgets.cpp +++ b/qt_tstfrm/tstwidgets.cpp @@ -54,11 +54,13 @@ void GLDrawWidget::initializeGL() 10 * sizeof(yg::gl::AuxVertex), 10 * sizeof(unsigned short), 30, - 512, 256, 15, + 512, 256, 10, + 512, 256, 5, GetPlatform().ReadPathForFile("unicode_blocks.txt").c_str(), GetPlatform().ReadPathForFile("fonts_whitelist.txt").c_str(), GetPlatform().ReadPathForFile("fonts_blacklist.txt").c_str(), - 2000000, + 2 * 1024 * 1024, + 500 * 1024, yg::Rt8Bpp, !yg::gl::g_isBufferObjectsSupported, !GetPlatform().IsMultiSampled())); @@ -71,7 +73,7 @@ void GLDrawWidget::initializeGL() params.m_resourceManager = m_resourceManager; params.m_isMultiSampled = false; params.m_frameBuffer = m_frameBuffer; - params.m_glyphCacheID = 1; + params.m_glyphCacheID = m_resourceManager->guiThreadGlyphCacheID(); m_p = make_shared_ptr(new yg::gl::Screen(params)); diff --git a/yg/geometry_batcher.cpp b/yg/geometry_batcher.cpp index 1f456c043a..2083e7ed49 100644 --- a/yg/geometry_batcher.cpp +++ b/yg/geometry_batcher.cpp @@ -72,11 +72,11 @@ namespace yg } } - void GeometryBatcher::GeometryPipeline::checkStorage(shared_ptr const & resourceManager, bool isDynamic) const + void GeometryBatcher::GeometryPipeline::checkStorage(shared_ptr const & resourceManager, SkinPage::EUsage usage) const { if (!m_hasStorage) { - m_storage = isDynamic ? resourceManager->reserveStorage() : resourceManager->reserveSmallStorage(); + m_storage = usage != SkinPage::EStaticUsage ? resourceManager->reserveStorage() : resourceManager->reserveSmallStorage(); m_maxVertices = m_storage.m_vertices->size() / sizeof(Vertex); m_maxIndices = m_storage.m_indices->size() / sizeof(unsigned short); @@ -165,7 +165,7 @@ namespace yg bool GeometryBatcher::hasRoom(size_t verticesCount, size_t indicesCount, int pageID) const { - m_pipelines[pageID].checkStorage(resourceManager(), skin()->pages()[pageID]->isDynamic()); + m_pipelines[pageID].checkStorage(resourceManager(), skin()->pages()[pageID]->usage()); return ((m_pipelines[pageID].m_currentVertex + verticesCount <= m_pipelines[pageID].m_maxVertices) && (m_pipelines[pageID].m_currentIndex + indicesCount <= m_pipelines[pageID].m_maxIndices)); @@ -173,14 +173,14 @@ namespace yg size_t GeometryBatcher::verticesLeft(int pageID) { - m_pipelines[pageID].checkStorage(resourceManager(), skin()->pages()[pageID]->isDynamic()); + m_pipelines[pageID].checkStorage(resourceManager(), skin()->pages()[pageID]->usage()); return m_pipelines[pageID].m_maxVertices - m_pipelines[pageID].m_currentVertex; } size_t GeometryBatcher::indicesLeft(int pageID) { - m_pipelines[pageID].checkStorage(resourceManager(), skin()->pages()[pageID]->isDynamic()); + m_pipelines[pageID].checkStorage(resourceManager(), skin()->pages()[pageID]->usage()); return m_pipelines[pageID].m_maxIndices - m_pipelines[pageID].m_currentIndex; } @@ -219,7 +219,7 @@ namespace yg renderedData = true; - if (skinPage->isDynamic()) + if (skinPage->usage() != SkinPage::EStaticUsage) resourceManager()->freeStorage(pipeline.m_storage); else resourceManager()->freeSmallStorage(pipeline.m_storage); @@ -256,7 +256,7 @@ namespace yg if (!hasRoom(4, 6, pageID)) flush(pageID); - m_pipelines[pageID].checkStorage(resourceManager(), skin()->pages()[pageID]->isDynamic()); + m_pipelines[pageID].checkStorage(resourceManager(), skin()->pages()[pageID]->usage()); float texMinX = tx0; float texMaxX = tx1; @@ -307,7 +307,7 @@ namespace yg if (!hasRoom(size, (size - 2) * 3, pageID)) flush(pageID); - m_pipelines[pageID].checkStorage(resourceManager(), skin()->pages()[pageID]->isDynamic()); + m_pipelines[pageID].checkStorage(resourceManager(), skin()->pages()[pageID]->usage()); ASSERT(size > 2, ()); @@ -357,7 +357,7 @@ namespace yg if (!hasRoom(size, (size - 2) * 3, pageID)) flush(pageID); - m_pipelines[pageID].checkStorage(resourceManager(), skin()->pages()[pageID]->isDynamic()); + m_pipelines[pageID].checkStorage(resourceManager(), skin()->pages()[pageID]->usage()); ASSERT(size > 2, ()); @@ -403,7 +403,7 @@ namespace yg if (!hasRoom(size, size, pageID)) flush(pageID); - m_pipelines[pageID].checkStorage(resourceManager(), skin()->pages()[pageID]->isDynamic()); + m_pipelines[pageID].checkStorage(resourceManager(), skin()->pages()[pageID]->usage()); ASSERT(size > 2, ()); @@ -440,7 +440,7 @@ namespace yg if (!hasRoom(size, size, pageID)) flush(pageID); - m_pipelines[pageID].checkStorage(resourceManager(), skin()->pages()[pageID]->isDynamic()); + m_pipelines[pageID].checkStorage(resourceManager(), skin()->pages()[pageID]->usage()); ASSERT(size > 2, ()); diff --git a/yg/geometry_batcher.hpp b/yg/geometry_batcher.hpp index 431faac6b3..6738013a22 100644 --- a/yg/geometry_batcher.hpp +++ b/yg/geometry_batcher.hpp @@ -7,6 +7,7 @@ #include "framebuffer.hpp" #include "render_state_updater.hpp" #include "storage.hpp" +#include "skin_page.hpp" #include "../std/vector.hpp" #include "../std/string.hpp" @@ -64,7 +65,7 @@ namespace yg size_t verticesLeft(); size_t indicesLeft(); - void checkStorage(shared_ptr const & resourceManager, bool isDynamic) const; + void checkStorage(shared_ptr const & resourceManager, SkinPage::EUsage usage) const; }; vector m_pipelines; diff --git a/yg/info_layer.cpp b/yg/info_layer.cpp index bac538a3fa..643d4f1448 100644 --- a/yg/info_layer.cpp +++ b/yg/info_layer.cpp @@ -14,6 +14,9 @@ namespace yg bool InfoLayer::better_text(StraightTextElement const & r1, StraightTextElement const & r2) { + /// any text is worse than a frozen one + if (r2.isFrozen()) + return false; if (r1.fontDesc() != r2.fontDesc()) return r1.fontDesc() > r2.fontDesc(); if (r1.depth() != r2.depth()) @@ -23,8 +26,6 @@ namespace yg void InfoLayer::draw(gl::TextRenderer *r, math::Matrix const & m) { - m_tree.ForEach(bind(&StraightTextElement::draw, _1, r, m)); - list toErase; for (path_text_elements::const_iterator it = m_pathTexts.begin(); it != m_pathTexts.end(); ++it) @@ -40,6 +41,8 @@ namespace yg for (list::const_iterator it = toErase.begin(); it != toErase.end(); ++it) m_pathTexts.erase(*it); + + m_tree.ForEach(bind(&StraightTextElement::draw, _1, r, m)); } void InfoLayer::offsetTextTree(m2::PointD const & offs, m2::RectD const & rect) @@ -50,8 +53,27 @@ namespace yg for (vector::iterator it = texts.begin(); it != texts.end(); ++it) { it->offset(offs); - if (it->boundRect().GetGlobalRect().IsIntersect(rect)) - m_tree.Add(*it, it->boundRect().GetGlobalRect()); + + m2::RectD limitRect = it->boundRect().GetGlobalRect(); + + bool doAppend = false; + it->setIsNeedRedraw(true); + it->setIsFrozen(false); + + if (rect.IsRectInside(limitRect)) + { + it->setIsFrozen(true); + doAppend = true; + } + else + if (rect.IsIntersect(limitRect)) + { + it->setIsFrozen(true); + doAppend = true; + } + + if (doAppend) + m_tree.Add(*it, limitRect); } } diff --git a/yg/resource_manager.cpp b/yg/resource_manager.cpp index 1d25333f80..218cf26823 100644 --- a/yg/resource_manager.cpp +++ b/yg/resource_manager.cpp @@ -22,12 +22,16 @@ namespace yg ResourceManager::ResourceManager(size_t vbSize, size_t ibSize, size_t storagesCount, size_t smallVBSize, size_t smallIBSize, size_t smallStoragesCount, size_t blitVBSize, size_t blitIBSize, size_t blitStoragesCount, - size_t texWidth, size_t texHeight, size_t texCount, - char const * blocksFile, char const * whiteListFile, char const * blackListFile, size_t maxGlyphCacheSize, + size_t dynamicTexWidth, size_t dynamicTexHeight, size_t dynamicTexCount, + size_t fontTexWidth, size_t fontTexHeight, size_t fontTexCount, + char const * blocksFile, char const * whiteListFile, char const * blackListFile, + size_t primaryGlyphCacheSize, + size_t secondaryGlyphCacheSize, RtFormat fmt, bool useVA, bool fillSkinAlpha) - : m_textureWidth(texWidth), m_textureHeight(texHeight), + : m_dynamicTextureWidth(dynamicTexWidth), m_dynamicTextureHeight(dynamicTexHeight), + m_fontTextureWidth(fontTexWidth), m_fontTextureHeight(fontTexHeight), m_vbSize(vbSize), m_ibSize(ibSize), m_smallVBSize(smallVBSize), m_smallIBSize(smallIBSize), m_blitVBSize(blitVBSize), m_blitIBSize(blitIBSize), @@ -36,9 +40,9 @@ namespace yg m_fillSkinAlpha(fillSkinAlpha) { /// primary cache is for rendering, so it's big - m_glyphCaches.push_back(GlyphCache(GlyphCache::Params(blocksFile, whiteListFile, blackListFile, maxGlyphCacheSize))); + m_glyphCaches.push_back(GlyphCache(GlyphCache::Params(blocksFile, whiteListFile, blackListFile, primaryGlyphCacheSize))); /// secondary caches is for glyph metrics only, so they are small - m_glyphCaches.push_back(GlyphCache(GlyphCache::Params(blocksFile, whiteListFile, blackListFile, 500 * 1024))); + m_glyphCaches.push_back(GlyphCache(GlyphCache::Params(blocksFile, whiteListFile, blackListFile, secondaryGlyphCacheSize))); if (useVA) { @@ -60,15 +64,25 @@ namespace yg LOG(LINFO, ("allocating ", (blitVBSize + blitIBSize) * blitStoragesCount, " bytes for blit storage")); - for (size_t i = 0; i < texCount; ++i) + for (size_t i = 0; i < dynamicTexCount; ++i) { - m_dynamicTextures.push_back(shared_ptr(new TDynamicTexture(texWidth, texHeight))); + m_dynamicTextures.push_back(shared_ptr(new TDynamicTexture(dynamicTexWidth, dynamicTexHeight))); #ifdef DEBUG static_cast(m_dynamicTextures.back().get())->randomize(); #endif } - LOG(LINFO, ("allocating ", texWidth * texHeight * sizeof(TDynamicTexture::pixel_t), " bytes for textures")); + LOG(LINFO, ("allocating ", dynamicTexWidth * dynamicTexHeight * sizeof(TDynamicTexture::pixel_t), " bytes for textures")); + + for (size_t i = 0; i < fontTexCount; ++i) + { + m_fontTextures.push_back(shared_ptr(new TDynamicTexture(fontTexWidth, fontTexHeight))); +#ifdef DEBUG + static_cast(m_fontTextures.back().get())->randomize(); +#endif + } + + LOG(LINFO, ("allocating ", fontTexWidth * fontTexHeight * sizeof(TDynamicTexture::pixel_t), " bytes for font textures")); } shared_ptr const & ResourceManager::getTexture(string const & fileName) @@ -160,11 +174,11 @@ namespace yg return freeStorageImpl(storage, doSignal, m_storages); } - shared_ptr const ResourceManager::reserveTexture(bool doWait) + shared_ptr const ResourceManager::reserveTextureImpl(bool doWait, list > & l) { threads::MutexGuard guard(m_mutex); - if (m_dynamicTextures.empty()) + if (l.empty()) { if (doWait) { @@ -172,28 +186,18 @@ namespace yg } } - shared_ptr res = m_dynamicTextures.front(); - m_dynamicTextures.pop_front(); + shared_ptr res = l.front(); + l.pop_front(); return res; } - size_t ResourceManager::textureWidth() const - { - return m_textureWidth; - } - - size_t ResourceManager::textureHeight() const - { - return m_textureHeight; - } - - void ResourceManager::freeTexture(shared_ptr const & texture, bool doSignal) + void ResourceManager::freeTextureImpl(shared_ptr const & texture, bool doSignal, list > & l) { threads::MutexGuard guard(m_mutex); - bool needToSignal = m_dynamicTextures.empty(); + bool needToSignal = l.empty(); - m_dynamicTextures.push_back(texture); + l.push_back(texture); if ((needToSignal) && (doSignal)) { @@ -201,9 +205,52 @@ namespace yg } } + + shared_ptr const ResourceManager::reserveDynamicTexture(bool doWait) + { + return reserveTextureImpl(doWait, m_dynamicTextures); + } + + void ResourceManager::freeDynamicTexture(shared_ptr const & texture, bool doSignal) + { + freeTextureImpl(texture, doSignal, m_dynamicTextures); + } + + + size_t ResourceManager::dynamicTextureWidth() const + { + return m_dynamicTextureWidth; + } + + size_t ResourceManager::dynamicTextureHeight() const + { + return m_dynamicTextureHeight; + } + + shared_ptr const ResourceManager::reserveFontTexture(bool doWait) + { + return reserveTextureImpl(doWait, m_fontTextures); + } + + void ResourceManager::freeFontTexture(shared_ptr const & texture, bool doSignal) + { + freeTextureImpl(texture, doSignal, m_fontTextures); + } + + size_t ResourceManager::fontTextureWidth() const + { + return m_fontTextureWidth; + } + + size_t ResourceManager::fontTextureHeight() const + { + return m_fontTextureHeight; + } + + GlyphCache * ResourceManager::glyphCache(int glyphCacheID) { - return &m_glyphCaches[glyphCacheID]; + return glyphCacheID == -1 ? 0 : &m_glyphCaches[glyphCacheID]; } void ResourceManager::addFonts(vector const & fontNames) @@ -230,7 +277,10 @@ namespace yg for (list >::iterator it = m_dynamicTextures.begin(); it != m_dynamicTextures.end(); ++it) it->reset(); - LOG(LINFO, ("freed ", m_storages.size(), " storages, ", m_smallStorages.size(), " small storages, ", m_blitStorages.size(), " blit storages and ", m_dynamicTextures.size(), " textures")); + for (list >::iterator it = m_fontTextures.begin(); it != m_fontTextures.end(); ++it) + it->reset(); + + LOG(LINFO, ("freed ", m_storages.size(), " storages, ", m_smallStorages.size(), " small storages, ", m_blitStorages.size(), " blit storages, ", m_dynamicTextures.size(), " dynamic textures and ", m_fontTextures.size(), " font textures")); } void ResourceManager::enterForeground() @@ -245,7 +295,9 @@ namespace yg *it = gl::Storage(m_blitVBSize, m_blitIBSize, m_useVA); for (list >::iterator it = m_dynamicTextures.begin(); it != m_dynamicTextures.end(); ++it) - *it = shared_ptr(new TDynamicTexture(m_textureWidth, m_textureHeight)); + *it = shared_ptr(new TDynamicTexture(m_dynamicTextureWidth, m_dynamicTextureHeight)); + for (list >::iterator it = m_fontTextures.begin(); it != m_fontTextures.end(); ++it) + *it = shared_ptr(new TDynamicTexture(m_fontTextureWidth, m_fontTextureHeight)); } shared_ptr ResourceManager::createRenderTarget(unsigned w, unsigned h) @@ -265,4 +317,14 @@ namespace yg { return m_fillSkinAlpha; } + + int ResourceManager::renderThreadGlyphCacheID() const + { + return 0; + } + + int ResourceManager::guiThreadGlyphCacheID() const + { + return 1; + } } diff --git a/yg/resource_manager.hpp b/yg/resource_manager.hpp index cf68d74d7d..a1df0f6e61 100644 --- a/yg/resource_manager.hpp +++ b/yg/resource_manager.hpp @@ -38,11 +38,16 @@ namespace yg threads::Mutex m_mutex; - size_t m_textureWidth; - size_t m_textureHeight; + size_t m_dynamicTextureWidth; + size_t m_dynamicTextureHeight; list > m_dynamicTextures; + size_t m_fontTextureWidth; + size_t m_fontTextureHeight; + + list > m_fontTextures; + size_t m_vbSize; size_t m_ibSize; @@ -59,6 +64,9 @@ namespace yg gl::Storage const reserveStorageImpl(bool doWait, list & l); void freeStorageImpl(gl::Storage const & storage, bool doSignal, list & l); + shared_ptr const reserveTextureImpl(bool doWait, list > & l); + void freeTextureImpl(shared_ptr const & texture, bool doSignal, list > & l); + vector m_glyphCaches; RtFormat m_format; @@ -72,7 +80,10 @@ namespace yg size_t smallVBSize, size_t smallIBSize, size_t smallStoragesCount, size_t blitVBSize, size_t blitIBSize, size_t blitStoragesCount, size_t texWidth, size_t texHeight, size_t texCount, - char const * blocksFile, char const * whileListFile, char const * blackListFile, size_t maxGlyphCacheSize, + size_t fontTexWidth, size_t fontTexHeight, size_t fontTexCount, + char const * blocksFile, char const * whileListFile, char const * blackListFile, + size_t primaryGlyphCacheSize, + size_t secondaryGlyphCacheSize, RtFormat fmt, bool useVA, bool fillSkinAlpha); @@ -88,16 +99,25 @@ namespace yg gl::Storage const reserveBlitStorage(bool doWait = false); void freeBlitStorage(gl::Storage const & storage, bool doSignal = false); - shared_ptr const reserveTexture(bool doWait = false); - void freeTexture(shared_ptr const & texture, bool doSignal = false); + shared_ptr const reserveDynamicTexture(bool doWait = false); + void freeDynamicTexture(shared_ptr const & texture, bool doSignal = false); - size_t textureWidth() const; - size_t textureHeight() const; + size_t dynamicTextureWidth() const; + size_t dynamicTextureHeight() const; + + shared_ptr const reserveFontTexture(bool doWait = false); + void freeFontTexture(shared_ptr const & texture, bool doSignal = false); + + size_t fontTextureWidth() const; + size_t fontTextureHeight() const; shared_ptr const getGlyphInfo(GlyphKey const & key); GlyphMetrics const getGlyphMetrics(GlyphKey const & key); GlyphCache * glyphCache(int glyphCacheID = 0); + int renderThreadGlyphCacheID() const; + int guiThreadGlyphCacheID() const; + void addFonts(vector const & fontNames); void memoryWarning(); diff --git a/yg/skin.cpp b/yg/skin.cpp index 03e16f540a..10882fca53 100644 --- a/yg/skin.cpp +++ b/yg/skin.cpp @@ -45,7 +45,7 @@ namespace yg for (int i = 0; i < count; ++i) { uint8_t pageID = (uint8_t)m_pages.size(); - m_pages.push_back(make_shared_ptr(new SkinPage(m_resourceManager, pageID, m_resourceManager->fillSkinAlpha()))); + m_pages.push_back(make_shared_ptr(new SkinPage(m_resourceManager, SkinPage::EFontsUsage, pageID, m_resourceManager->fillSkinAlpha()))); m_pages.back()->addOverflowFn(bind(&Skin::onTextOverflow, this, pageID), 0); } } @@ -59,7 +59,7 @@ namespace yg for (int i = 0; i < count; ++i) { uint8_t pageID = (uint8_t)m_pages.size(); - m_pages.push_back(make_shared_ptr(new SkinPage(m_resourceManager, pageID, m_resourceManager->fillSkinAlpha()))); + m_pages.push_back(make_shared_ptr(new SkinPage(m_resourceManager, SkinPage::EDynamicUsage, pageID, m_resourceManager->fillSkinAlpha()))); m_pages.back()->addOverflowFn(bind(&Skin::onDynamicOverflow, this, pageID), 0); } } diff --git a/yg/skin_page.cpp b/yg/skin_page.cpp index 802329f314..fb4491781a 100644 --- a/yg/skin_page.cpp +++ b/yg/skin_page.cpp @@ -96,7 +96,7 @@ namespace yg uint8_t pageID, bool fillAlpha) : m_texture(resourceManager->getTexture(name)), - m_isDynamic(false), + m_usage(EStaticUsage), m_pageID(pageID), m_fillAlpha(fillAlpha) { @@ -105,16 +105,15 @@ namespace yg SkinPage::SkinPage(shared_ptr const & resourceManager, + EUsage usage, uint8_t pageID, bool fillAlpha) : m_resourceManager(resourceManager), - m_isDynamic(true), + m_usage(usage), m_pageID(pageID), m_fillAlpha(fillAlpha) { - m_packer = m2::Packer(m_resourceManager->textureWidth(), - m_resourceManager->textureHeight(), - 0x00FFFFFF - 1); + createPacker(); /// clear handles will be called only upon handles overflow, /// as the texture overflow is processed separately m_packer.addOverflowFn(bind(&SkinPage::clearHandles, this), 0); @@ -319,9 +318,9 @@ namespace yg return m_packer.hasRoom(p.x, p.y); } - bool SkinPage::isDynamic() const + SkinPage::EUsage SkinPage::usage() const { - return m_isDynamic; + return m_usage; } void SkinPage::uploadPenInfo() @@ -705,13 +704,13 @@ namespace yg void SkinPage::checkTexture() const { - if ((m_isDynamic) && (m_texture == 0)) + if ((m_usage != EStaticUsage) && (m_texture == 0)) reserveTexture(); } void SkinPage::uploadData() { - if ((m_isDynamic) && (hasData())) + if ((m_usage != EStaticUsage) && (hasData())) { checkTexture(); static_cast(m_texture.get())->lock(); @@ -747,12 +746,52 @@ namespace yg void SkinPage::freeTexture() { if (m_texture) - m_resourceManager->freeTexture(m_texture); - m_texture.reset(); + { + switch (m_usage) + { + case EDynamicUsage: + m_resourceManager->freeDynamicTexture(m_texture); + break; + case EFontsUsage: + m_resourceManager->freeFontTexture(m_texture); + break; + default: + LOG(LINFO, ("freeTexture call for with invalid usage param")); + } + + m_texture.reset(); + } } void SkinPage::reserveTexture() const { - m_texture = m_resourceManager->reserveTexture(); + switch (m_usage) + { + case EDynamicUsage: + m_texture = m_resourceManager->reserveDynamicTexture(); + break; + case EFontsUsage: + m_texture = m_resourceManager->reserveFontTexture(); + break; + default: + LOG(LINFO, ("freeTexture call for with invalid usage param")); + } + } + + void SkinPage::createPacker() + { + switch (m_usage) + { + case EDynamicUsage: + m_packer = m2::Packer(m_resourceManager->dynamicTextureWidth(), + m_resourceManager->dynamicTextureHeight(), + 0x00FFFFFF - 1); + break; + case EFontsUsage: + m_packer = m2::Packer(m_resourceManager->fontTextureWidth(), + m_resourceManager->fontTextureHeight(), + 0x00FFFFFF - 1); + break; + } } } diff --git a/yg/skin_page.hpp b/yg/skin_page.hpp index 543d967901..9d17e9dbc6 100644 --- a/yg/skin_page.hpp +++ b/yg/skin_page.hpp @@ -70,6 +70,13 @@ namespace yg { public: + enum EUsage + { + EStaticUsage, + EDynamicUsage, + EFontsUsage + }; + typedef m2::Packer::overflowFn overflowFn; private: @@ -112,7 +119,7 @@ namespace yg typedef vector TFonts; TFonts m_fonts; - bool m_isDynamic; + EUsage m_usage; uint32_t m_pageID; bool m_fillAlpha; @@ -147,11 +154,13 @@ namespace yg /// creation of a dynamic page SkinPage(shared_ptr const & resourceManager, + EUsage usage, uint8_t pageID, bool fillAlpha); void reserveTexture() const; void freeTexture(); + void createPacker(); uint32_t findColor(Color const & c) const; uint32_t mapColor(Color const & c); @@ -173,7 +182,7 @@ namespace yg ResourceStyle * fromID(uint32_t idx) const; - bool isDynamic() const; + EUsage usage() const; void addOverflowFn(overflowFn fn, int priority); diff --git a/yg/text_element.cpp b/yg/text_element.cpp index 646d2794ee..4f4538ffc5 100644 --- a/yg/text_element.cpp +++ b/yg/text_element.cpp @@ -11,7 +11,11 @@ namespace yg { OverlayElement::OverlayElement(Params const & p) - : m_pivot(p.m_pivot), m_position(p.m_position), m_depth(p.m_depth) + : m_pivot(p.m_pivot), + m_position(p.m_position), + m_depth(p.m_depth), + m_isNeedRedraw(true), + m_isFrozen(false) {} void OverlayElement::offset(m2::PointD const & offs) @@ -49,6 +53,26 @@ namespace yg m_depth = depth; } + bool OverlayElement::isFrozen() const + { + return m_isFrozen; + } + + void OverlayElement::setIsFrozen(bool flag) + { + m_isFrozen = flag; + } + + bool OverlayElement::isNeedRedraw() const + { + return m_isNeedRedraw; + } + + void OverlayElement::setIsNeedRedraw(bool flag) + { + m_isNeedRedraw = flag; + } + strings::UniString TextElement::log2vis(strings::UniString const & str) { size_t const count = str.size(); @@ -123,6 +147,9 @@ namespace yg void StraightTextElement::draw(gl::TextRenderer * screen, math::Matrix const & m) const { + if (!isNeedRedraw()) + return; + yg::FontDesc desc = m_fontDesc; if (m_fontDesc.m_isMasked) { @@ -167,11 +194,11 @@ namespace yg yg::FontDesc desc = m_fontDesc; if (m_fontDesc.m_isMasked) { - drawTextImpl(m_glyphLayout, screen, m, m_fontDesc, depth()); + drawTextImpl(m_glyphLayout, screen, m, m_fontDesc, yg::maxDepth); desc.m_isMasked = false; } - drawTextImpl(m_glyphLayout, screen, m, desc, depth()); + drawTextImpl(m_glyphLayout, screen, m, desc, yg::maxDepth); } /* void PathTextElement::draw(gl::Screen * screen) const diff --git a/yg/text_element.hpp b/yg/text_element.hpp index 8052f7e653..19d1796212 100644 --- a/yg/text_element.hpp +++ b/yg/text_element.hpp @@ -33,6 +33,9 @@ namespace yg yg::EPosition m_position; double m_depth; + bool m_isNeedRedraw; + bool m_isFrozen; + public: struct Params @@ -56,6 +59,12 @@ namespace yg double depth() const; void setDepth(double depth); + + bool isFrozen() const; + void setIsFrozen(bool flag); + + bool isNeedRedraw() const; + void setIsNeedRedraw(bool flag); }; class TextElement : public OverlayElement diff --git a/yg/text_renderer.cpp b/yg/text_renderer.cpp index cbe7e29c88..0db53e2896 100644 --- a/yg/text_renderer.cpp +++ b/yg/text_renderer.cpp @@ -18,7 +18,7 @@ namespace yg TextRenderer::Params::Params() : m_drawTexts(true), - m_glyphCacheID(0) + m_glyphCacheID(-1) {} TextRenderer::TextRenderer(Params const & params) diff --git a/yg/yg_tests/skin_loader_test.cpp b/yg/yg_tests/skin_loader_test.cpp index 4beac9007c..4120359936 100644 --- a/yg/yg_tests/skin_loader_test.cpp +++ b/yg/yg_tests/skin_loader_test.cpp @@ -8,6 +8,6 @@ UNIT_TEST(SkinLoaderTest_Main) { GL_TEST_START; - shared_ptr rm(new yg::ResourceManager(1000, 1000, 2, 1000, 1000, 2, 1000, 1000, 2, 128, 128, 15, "", "", "", 2000000, yg::Rt8Bpp, false, false)); + shared_ptr rm(new yg::ResourceManager(1000, 1000, 2, 1000, 1000, 2, 1000, 1000, 2, 128, 128, 15, 256, 256, 5, "", "", "", 2 * 1024 * 1024, 500 * 1024, yg::Rt8Bpp, false, false)); /*yg::Skin * skin = */loadSkin(rm, "basic.skn", 2, 2); }; diff --git a/yg/yg_tests/skin_test.cpp b/yg/yg_tests/skin_test.cpp index eb053a7141..2e015e7402 100644 --- a/yg/yg_tests/skin_test.cpp +++ b/yg/yg_tests/skin_test.cpp @@ -10,7 +10,7 @@ UNIT_TEST(SkinTest_Main) { GL_TEST_START; - shared_ptr rm(new yg::ResourceManager(100, 100, 1, 100, 100, 1, 100, 100, 1, 128, 128, 15, "", "", "", 2000000, yg::Rt8Bpp, false, false)); + shared_ptr rm(new yg::ResourceManager(100, 100, 1, 100, 100, 1, 100, 100, 1, 128, 128, 15, 256, 256, 5, "", "", "", 2 * 1024 * 1024, 500 * 1024, yg::Rt8Bpp, false, false)); yg::Skin * skin = loadSkin(rm, "test.skn", 2, 2); double p0 [] = {1, 1};