diff --git a/map/render_queue_routine.cpp b/map/render_queue_routine.cpp index 00e8a66d2a..5237e8bb5d 100644 --- a/map/render_queue_routine.cpp +++ b/map/render_queue_routine.cpp @@ -235,6 +235,7 @@ void RenderQueueRoutine::Do() params.m_doPeriodicalUpdate = m_doPeriodicalUpdate; params.m_updateInterval = m_updateInterval; params.m_textTreeAutoClean = false; + params.m_useTextTree = true; m_threadDrawer = make_shared_ptr(new DrawerYG(m_skinName, params)); @@ -334,6 +335,8 @@ void RenderQueueRoutine::Do() else m_threadDrawer->screen()->clearTextTree(); + m_threadDrawer->screen()->setNeedTextRedraw(s.isPanning()); + ScreenBase const & frameScreen = m_currentRenderCommand->m_frameScreen; m2::RectD glbRect; frameScreen.PtoG(m2::RectD(0, 0, s.m_surfaceWidth, s.m_surfaceHeight), glbRect); diff --git a/platform/qtplatform.cpp b/platform/qtplatform.cpp index cc19571675..37d98e0b31 100644 --- a/platform/qtplatform.cpp +++ b/platform/qtplatform.cpp @@ -382,7 +382,7 @@ public: bool IsBenchmarking() const { - return true; + return false; } string const DeviceID() const diff --git a/yg/geometry_batcher.hpp b/yg/geometry_batcher.hpp index 3edfca75b2..19d09c923e 100644 --- a/yg/geometry_batcher.hpp +++ b/yg/geometry_batcher.hpp @@ -79,7 +79,6 @@ namespace yg size_t indicesLeft(int pageID); void reset(int pageID); - void flush(int pageID); void switchTextures(int pageID); @@ -93,6 +92,9 @@ namespace yg public: + /// INTERNAL API! USE WITH CAUTION + void flush(int pageID); + struct Params : base_t::Params { bool m_isAntiAliased; diff --git a/yg/render_state_updater.hpp b/yg/render_state_updater.hpp index f2a9c6d3c0..fb668134c3 100644 --- a/yg/render_state_updater.hpp +++ b/yg/render_state_updater.hpp @@ -20,8 +20,6 @@ namespace yg shared_ptr m_renderState; - void updateActualTarget(); - int m_indicesCount; bool m_doPeriodicalUpdate; double m_updateInterval; @@ -48,6 +46,7 @@ namespace yg void beginFrame(); void endFrame(); + virtual void updateActualTarget(); }; } } diff --git a/yg/skin.cpp b/yg/skin.cpp index 077b12cecc..951bbcefdd 100644 --- a/yg/skin.cpp +++ b/yg/skin.cpp @@ -297,6 +297,16 @@ namespace yg return 0x00FFFFFF; } + uint8_t Skin::currentTextPage() const + { + return m_currentTextPage; + } + + uint8_t Skin::currentDynamicPage() const + { + return m_currentDynamicPage; + } + void Skin::memoryWarning() { } diff --git a/yg/skin.hpp b/yg/skin.hpp index 09c76c567a..4b87e75571 100644 --- a/yg/skin.hpp +++ b/yg/skin.hpp @@ -141,6 +141,9 @@ namespace yg uint32_t invalidHandle() const; uint32_t invalidPageHandle() const; + uint8_t currentTextPage() const; + uint8_t currentDynamicPage() const; + void memoryWarning(); void enterBackground(); void enterForeground(); diff --git a/yg/text_renderer.cpp b/yg/text_renderer.cpp index a5bf5bef71..22e850ffdf 100644 --- a/yg/text_renderer.cpp +++ b/yg/text_renderer.cpp @@ -15,6 +15,7 @@ #include "../3party/fribidi/lib/fribidi-deprecated.h" +#include "../base/logging.hpp" #include "../base/start_mem_debug.hpp" @@ -23,13 +24,21 @@ namespace yg namespace gl { TextRenderer::Params::Params() - : m_textTreeAutoClean(true) + : m_textTreeAutoClean(true), m_useTextTree(false) {} TextRenderer::TextRenderer(Params const & params) - : base_t(params), m_textTreeAutoClean(params.m_textTreeAutoClean) + : base_t(params), + m_needTextRedraw(false), + m_textTreeAutoClean(params.m_textTreeAutoClean), + m_useTextTree(params.m_useTextTree) {} + TextRenderer::TextObj::TextObj(m2::PointD const & pt, string const & txt, uint8_t sz, yg::Color const & c, bool isMasked, yg::Color const & maskColor, double d, bool isFixedFont, bool log2vis) + : m_pt(pt), m_size(sz), m_utf8Text(txt), m_isMasked(isMasked), m_depth(d), m_needRedraw(true), m_frozen(false), m_isFixedFont(isFixedFont), m_log2vis(log2vis), m_color(c), m_maskColor(maskColor) + { + } + void TextRenderer::TextObj::Draw(TextRenderer * pTextRenderer) const { /// this value is assigned inside offsetTextRect function to the texts which completely @@ -37,10 +46,7 @@ namespace yg if (m_needRedraw) { pTextRenderer->drawTextImpl(m_pt, 0.0, m_size, m_color, m_utf8Text, true, m_maskColor, yg::maxDepth, m_isFixedFont, m_log2vis); - /// boosting its depth to "out of range" value, - /// to mark it as a rendered text and prevent it from - /// popping out of tree, when more important text arrives - m_depth = yg::maxDepth; + m_frozen = true; } } @@ -61,6 +67,10 @@ namespace yg bool TextRenderer::TextObj::better_text(TextObj const & r1, TextObj const & r2) { + /// any text is worse than a frozen one, + /// because frozen texts shouldn't be popped out by newly arrived texts. + if (r2.m_frozen) + return false; if ((r1.m_isMasked) && (!r2.m_isMasked)) return true; return r1.m_depth > r2.m_depth; @@ -77,41 +87,64 @@ namespace yg bool isFixedFont, bool log2vis) { - if (isFixedFont) - drawTextImpl(pt, angle, fontSize, color, utf8Text, true, maskColor, depth, isFixedFont, log2vis); + if (!m_useTextTree || isFixedFont) + drawTextImpl(pt, angle, fontSize, color, utf8Text, true, maskColor, depth, isFixedFont, log2vis); else { + checkTextRedraw(); TextObj obj(pt, utf8Text, fontSize, color, isMasked, maskColor, depth, isFixedFont, log2vis); m2::RectD r = obj.GetLimitRect(this); m_tree.ReplaceIf(obj, r, &TextObj::better_text); } } + void TextRenderer::checkTextRedraw() + { + ASSERT(m_useTextTree, ()); + if (m_needTextRedraw) + { + m_tree.ForEach(bind(&TextObj::Draw, _1, this)); + /// flushing only texts + base_t::flush(skin()->currentTextPage()); + m_needTextRedraw = false; + } + } + void TextRenderer::setClipRect(m2::RectI const & rect) { -// m_tree.ForEach(bind(&TextObj::Draw, _1, this)); -// m_tree.ForEach(bind(&TextObj::BoostPriority, _1)); -// if (m_textTreeAutoClean) -// m_tree.Clear(); - base_t::setClipRect(rect); + if (m_useTextTree) + { + bool needTextRedraw = m_needTextRedraw; + checkTextRedraw(); + base_t::setClipRect(rect); + setNeedTextRedraw(needTextRedraw); + } + else + base_t::setClipRect(rect); } void TextRenderer::endFrame() { - m_tree.ForEach(bind(&TextObj::Draw, _1, this)); - if (m_textTreeAutoClean) - m_tree.Clear(); + if (m_useTextTree) + { + m_tree.ForEach(bind(&TextObj::Draw, _1, this)); + if (m_textTreeAutoClean) + m_tree.Clear(); + m_needTextRedraw = false; + } base_t::endFrame(); } void TextRenderer::clearTextTree() { + ASSERT(m_useTextTree, ()); m_tree.Clear(); } void TextRenderer::offsetTextTree(m2::PointD const & offs, m2::RectD const & rect) { + ASSERT(m_useTextTree, ()); vector texts; m_tree.ForEach(bind(&vector::push_back, ref(texts), _1)); m_tree.Clear(); @@ -134,6 +167,19 @@ namespace yg } } + void TextRenderer::setNeedTextRedraw(bool flag) + { + ASSERT(m_useTextTree, ()); + m_needTextRedraw = flag; + } + + void TextRenderer::updateActualTarget() + { + if (m_useTextTree) + setNeedTextRedraw(true); + base_t::updateActualTarget(); + } + template void TextRenderer::ForEachGlyph(uint8_t fontSize, yg::Color const & color, wstring const & text, bool isMasked, bool isFixedFont, ToDo toDo) { @@ -174,6 +220,9 @@ namespace yg m2::RectD const TextRenderer::textRect(string const & utf8Text, uint8_t fontSize, bool fixedFont, bool log2vis) { + if (m_useTextTree) + checkTextRedraw(); + m2::RectD rect; m2::PointD pt(0, 0); @@ -281,6 +330,9 @@ namespace yg m2::PointD const * path, size_t s, uint8_t fontSize, yg::Color const & color, string const & utf8Text, double fullLength, double pathOffset, TextPos pos, bool isMasked, yg::Color const & maskColor, double depth, bool isFixedFont) { + if (m_useTextTree) + checkTextRedraw(); + if (isMasked) if (!drawPathTextImpl(path, s, fontSize, maskColor, utf8Text, fullLength, pathOffset, pos, true, depth, isFixedFont)) return false; @@ -366,5 +418,11 @@ namespace yg p->m_pageID); } + void TextRenderer::drawPath(m2::PointD const * points, size_t pointsCount, uint32_t styleID, double depth) + { + if (m_useTextTree) + checkTextRedraw(); + base_t::drawPath(points, pointsCount, styleID, depth); + } } } diff --git a/yg/text_renderer.hpp b/yg/text_renderer.hpp index 00a20268ba..7702113fb7 100644 --- a/yg/text_renderer.hpp +++ b/yg/text_renderer.hpp @@ -27,8 +27,9 @@ namespace yg uint8_t m_size; string m_utf8Text; bool m_isMasked; - mutable double m_depth; + double m_depth; mutable bool m_needRedraw; + mutable bool m_frozen; bool m_isFixedFont; bool m_log2vis; yg::Color m_color; @@ -36,11 +37,7 @@ namespace yg public: - TextObj(m2::PointD const & pt, string const & txt, uint8_t sz, yg::Color const & c, bool isMasked, yg::Color const & maskColor, double d, bool isFixedFont, bool log2vis) - : m_pt(pt), m_size(sz), m_utf8Text(txt), m_isMasked(isMasked), m_depth(d), m_needRedraw(true), m_isFixedFont(isFixedFont), m_log2vis(log2vis), m_color(c), m_maskColor(maskColor) - { - } - + TextObj(m2::PointD const & pt, string const & txt, uint8_t sz, yg::Color const & c, bool isMasked, yg::Color const & maskColor, double d, bool isFixedFont, bool log2vis); void Draw(TextRenderer * pTextRenderer) const; m2::RectD const GetLimitRect(TextRenderer * pTextRenderer) const; void SetNeedRedraw(bool needRedraw) const; @@ -51,6 +48,9 @@ namespace yg m4::Tree m_tree; + void checkTextRedraw(); + bool m_needTextRedraw; + static wstring Log2Vis(wstring const & str); template @@ -89,6 +89,7 @@ namespace yg bool log2vis); bool m_textTreeAutoClean; + bool m_useTextTree; public: @@ -97,6 +98,7 @@ namespace yg struct Params : base_t::Params { bool m_textTreeAutoClean; + bool m_useTextTree; Params(); }; @@ -144,6 +146,13 @@ namespace yg /// boosting their priority to the top for them not to be filtered away, /// when the new texts arrive void offsetTextTree(m2::PointD const & offs, m2::RectD const & r); + + /// flush texts upon any function call. + void setNeedTextRedraw(bool flag); + + void drawPath(m2::PointD const * points, size_t pointsCount, uint32_t styleID, double depth); + + void updateActualTarget(); }; } }