fast InfoLayer rendering on GUI thread through StylesCache.

This commit is contained in:
rachytski 2011-09-13 17:54:43 +03:00 committed by Alex Zolotarev
parent bea0f2b792
commit ba950b9fb6
21 changed files with 298 additions and 23 deletions

View file

@ -116,6 +116,11 @@ public:
m_traits.Free(m_pool, elem);
}
size_t Size() const
{
return m_pool.Size();
}
void EnterForeground()
{}

View file

@ -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:

View file

@ -102,7 +102,7 @@ public:
return res;
}
size_t Size()
size_t Size() const
{
threads::ConditionGuard g(m_Cond);
return m_list.size();

View file

@ -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));

View file

@ -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<WindowHandle> const & windowHandle)
size_t tileSize,
size_t scaleEtalonSize,
TileRenderer * tileRenderer,
shared_ptr<WindowHandle> 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<yg::gl::RenderContext> const & rc,
shared_ptr<yg::ResourceManager> 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<yg::ResourceManager> const & CoverageGenerator::resourceManager() const
{
return m_resourceManager;
}

View file

@ -29,6 +29,9 @@ private:
TileRenderer * m_tileRenderer;
shared_ptr<yg::ResourceManager> m_resourceManager;
shared_ptr<yg::gl::RenderContext> 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<WindowHandle> const & windowHandle);
size_t scaleEtalonSize,
TileRenderer * tileRenderer,
shared_ptr<WindowHandle> 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<yg::gl::RenderContext> const & rc,
shared_ptr<yg::ResourceManager> const & rm);
void WaitForEmptyAndFinished();
ScreenCoverage & CurrentCoverage();
threads::Mutex & Mutex();
shared_ptr<yg::ResourceManager> const & resourceManager() const;
};

View file

@ -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());
}

View file

@ -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<yg::StylesCache> m_stylesCache;
CoverageGenerator * m_coverageGenerator;

View file

@ -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<yg::gl::RenderContext> 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<PaintEvent> const & e, ScreenBase const & currentScreen)
{
DrawerYG * pDrawer = e->drawer();
pDrawer->screen()->clear(bgColor());
m_coverageGenerator.AddCoverScreenTask(currentScreen);

View file

@ -43,5 +43,7 @@ public:
void Initialize(shared_ptr<yg::gl::RenderContext> const & renderContext,
shared_ptr<yg::ResourceManager> const & resourceManager);
void BeginFrame();
void DrawFrame(shared_ptr<PaintEvent> const & ev, ScreenBase const & currentScreen);
void EndFrame();
};

View file

@ -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));

View file

@ -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));

View file

@ -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<strings::UniString> toErase;
for (path_text_elements::const_iterator it = m_pathTexts.begin(); it != m_pathTexts.end(); ++it)
{
list<PathTextElement> const & l = it->second;
for (list<PathTextElement>::const_iterator j = l.begin(); j != l.end(); ++j)
stylesCache->cachePathText(*j);
if (l.empty())
toErase.push_back(it->first);
}
for (list<strings::UniString>::const_iterator it = toErase.begin(); it != toErase.end(); ++it)
m_pathTexts.erase(*it);
m_tree.ForEach(bind(&StylesCache::cacheStraightText, stylesCache, _1));
}
}

View file

@ -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<double, 3, 3> const & m);
};
}

View file

@ -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();

View file

@ -151,6 +151,7 @@ namespace yg
int renderThreadGlyphCacheID(int threadNum) const;
int guiThreadGlyphCacheID() const;
int cacheThreadGlyphCacheID() const;
void addFonts(vector<string> const & fontNames);

46
yg/styles_cache.cpp Normal file
View file

@ -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<ResourceManager> 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<shared_ptr<SkinPage> > const & StylesCache::cachePages() const
{
return m_cachePages;
}
void StylesCache::upload()
{
for (unsigned i = 0; i < m_cachePages.size(); ++i)
m_cachePages[i]->uploadData();
}
}

39
yg/styles_cache.hpp Normal file
View file

@ -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<shared_ptr<SkinPage> > m_cachePages;
shared_ptr<ResourceManager> m_rm;
GlyphCache * m_glyphCache;
int m_maxPagesCount;
public:
StylesCache(shared_ptr<ResourceManager> const & rm,
int glyphCacheID,
int maxPagesCount);
~StylesCache();
void cacheStraightText(StraightTextElement const & ste);
void cachePathText(PathTextElement const & pte);
vector<shared_ptr<SkinPage> > const & cachePages() const;
void upload();
};
}

View file

@ -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<shared_ptr<SkinPage> > & skinPages,
shared_ptr<ResourceManager> 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<shared_ptr<SkinPage> > & skinPages,
shared_ptr<ResourceManager> 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<shared_ptr<SkinPage> > & skinPages,
shared_ptr<ResourceManager> 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);
}
}

View file

@ -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<shared_ptr<SkinPage> > & skinPages,
shared_ptr<ResourceManager> const & rm,
GlyphCache * glyphCache,
FontDesc const & desc) const;
void drawTextImpl(GlyphLayout const & layout,
gl::OverlayRenderer * r,
math::Matrix<double, 3, 3> const & m,
@ -73,6 +80,9 @@ namespace yg
m2::AARectD const boundRect() const;
void draw(gl::OverlayRenderer * r, math::Matrix<double, 3, 3> const & m) const;
void offset(m2::PointD const & offs);
void cache(vector<shared_ptr<SkinPage> > & skinPages,
shared_ptr<ResourceManager> 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<double, 3, 3> const & m) const;
void offset(m2::PointD const & offs);
void cache(vector<shared_ptr<SkinPage> > & skinPages,
shared_ptr<ResourceManager> const & rm,
GlyphCache * glyphCache) const;
};
}

View file

@ -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
}