introduced FenceManager for TileRenderer and StyleCache to wait correctly on the command completion.

This commit is contained in:
rachytski 2011-12-30 16:09:55 +04:00 committed by Alex Zolotarev
parent cd07b0c61e
commit de75766c92
46 changed files with 493 additions and 201 deletions

View file

@ -16,7 +16,8 @@ CoverageGenerator::CoverageGenerator(
TileRenderer * tileRenderer,
shared_ptr<WindowHandle> const & windowHandle,
shared_ptr<yg::gl::RenderContext> const & primaryRC,
shared_ptr<yg::ResourceManager> const & rm)
shared_ptr<yg::ResourceManager> const & rm,
yg::gl::PacketsQueue * glQueue)
: m_queue(1),
m_tileRenderer(tileRenderer),
m_workCoverage(0),
@ -28,10 +29,12 @@ CoverageGenerator::CoverageGenerator(
m_renderContext = primaryRC->createShared();
m_currentStylesCache.reset(new yg::StylesCache(rm,
rm->cacheThreadGlyphCacheID()));
rm->cacheThreadGlyphCacheID(),
glQueue));
m_workStylesCache.reset(new yg::StylesCache(rm,
rm->cacheThreadGlyphCacheID()));
rm->cacheThreadGlyphCacheID(),
glQueue));
m_queue.AddInitCommand(bind(&CoverageGenerator::InitializeThreadGL, this));
m_queue.AddFinCommand(bind(&CoverageGenerator::FinalizeThreadGL, this));

View file

@ -52,7 +52,8 @@ public:
TileRenderer * tileRenderer,
shared_ptr<WindowHandle> const & windowHandle,
shared_ptr<yg::gl::RenderContext> const & primaryRC,
shared_ptr<yg::ResourceManager> const & rm);
shared_ptr<yg::ResourceManager> const & rm,
yg::gl::PacketsQueue * glQueue);
~CoverageGenerator();

View file

@ -183,7 +183,7 @@ PartialRenderPolicy::~PartialRenderPolicy()
LOG(LINFO, ("PartialRenderPolicy destroyed"));
}
void PartialRenderPolicy::ProcessRenderQueue(list<yg::gl::Renderer::Packet> & renderQueue, int maxPackets)
void PartialRenderPolicy::ProcessRenderQueue(list<yg::gl::Packet> & renderQueue, int maxPackets)
{
m_frameGLQueue.clear();
if (maxPackets == -1)
@ -199,19 +199,19 @@ void PartialRenderPolicy::ProcessRenderQueue(list<yg::gl::Renderer::Packet> & re
{
/// searching for "frame boundary" markers (empty packets)
list<yg::gl::Renderer::Packet>::iterator first = renderQueue.begin();
list<yg::gl::Renderer::Packet>::iterator last = renderQueue.begin();
list<yg::gl::Packet>::iterator first = renderQueue.begin();
list<yg::gl::Packet>::iterator last = renderQueue.begin();
int packetsLeft = maxPackets;
while ((packetsLeft != 0) && (last != renderQueue.end()))
{
yg::gl::Renderer::Packet p = *last;
if ((p.m_command == 0) && (p.m_state == 0))
yg::gl::Packet p = *last;
if (p.m_groupBoundary)
{
LOG(LINFO, ("found frame boundary"));
/// found frame boundary, copying
copy(first, last++, back_inserter(m_frameGLQueue));
copy(first, ++last, back_inserter(m_frameGLQueue));
/// erasing from the main queue
renderQueue.erase(first, last);
first = renderQueue.begin();
@ -250,7 +250,7 @@ void PartialRenderPolicy::DrawFrame(shared_ptr<PaintEvent> const & e,
cmdProcessed = m_frameGLQueue.size();
for (list<yg::gl::Renderer::Packet>::iterator it = m_frameGLQueue.begin(); it != m_frameGLQueue.end(); ++it)
for (list<yg::gl::Packet>::iterator it = m_frameGLQueue.begin(); it != m_frameGLQueue.end(); ++it)
{
if (it->m_state)
{
@ -259,9 +259,12 @@ void PartialRenderPolicy::DrawFrame(shared_ptr<PaintEvent> const & e,
// OGLCHECK(glFinish());
m_curState = it->m_state;
}
it->m_command->setIsDebugging(m_IsDebugging);
it->m_command->perform();
// OGLCHECK(glFinish());
if (it->m_command)
{
it->m_command->setIsDebugging(m_IsDebugging);
it->m_command->perform();
// OGLCHECK(glFinish());
}
}
/// should clear to release resources, refered from the stored commands.

View file

@ -12,20 +12,20 @@ class PartialRenderPolicy : public RenderPolicy
{
private:
ThreadedList<yg::gl::Renderer::Packet> m_glQueue;
list<yg::gl::Renderer::Packet> m_frameGLQueue;
yg::gl::PacketsQueue m_glQueue;
list<yg::gl::Packet> m_frameGLQueue;
threads::Condition m_glCondition;
shared_ptr<yg::gl::Screen::BaseState> m_curState;
shared_ptr<yg::gl::BaseState> m_curState;
shared_ptr<yg::gl::Renderer::BaseState> m_state;
shared_ptr<yg::gl::BaseState> m_state;
scoped_ptr<RenderQueue> m_renderQueue;
bool m_DoAddCommand;
bool m_DoSynchronize;
void ProcessRenderQueue(list<yg::gl::Renderer::Packet> & renderQueue, int maxPackets);
void ProcessRenderQueue(list<yg::gl::Packet> & renderQueue, int maxPackets);
bool m_IsDebugging;

View file

@ -125,7 +125,7 @@ void RenderQueue::WaitForEmptyAndFinished()
m_routine->waitForEmptyAndFinished();
}
void RenderQueue::SetGLQueue(ThreadedList<yg::gl::Renderer::Packet> * glQueue,
void RenderQueue::SetGLQueue(yg::gl::PacketsQueue * glQueue,
threads::Condition * glCondition)
{
m_routine->setGLQueue(glQueue, glCondition);

View file

@ -80,6 +80,6 @@ public:
void WaitForEmptyAndFinished();
void SetGLQueue(ThreadedList<yg::gl::Renderer::Packet> * glQueue,
void SetGLQueue(yg::gl::PacketsQueue * glQueue,
threads::Condition * glCondition);
};

View file

@ -537,11 +537,8 @@ void RenderQueueRoutine::invalidate()
{
shared_ptr<Invalidate> command(new Invalidate());
command->m_windowHandles = m_windowHandles;
m_glQueue->PushBack(yg::gl::Renderer::Packet(command));
m_glQueue->PushBack(yg::gl::Packet(command, true));
}
if (m_glQueue)
m_glQueue->PushBack(yg::gl::Renderer::Packet());
}
void RenderQueueRoutine::addCommand(render_fn_t const & fn, ScreenBase const & frameScreen)
@ -600,7 +597,7 @@ void RenderQueueRoutine::waitForEmptyAndFinished()
guard.Wait();
}
void RenderQueueRoutine::setGLQueue(ThreadedList<yg::gl::Renderer::Packet> * glQueue,
void RenderQueueRoutine::setGLQueue(yg::gl::PacketsQueue * glQueue,
threads::Condition * glCondition)
{
m_glQueue = glQueue;

View file

@ -8,7 +8,6 @@
#include "../std/list.hpp"
#include "../std/function.hpp"
#include "../yg/color.hpp"
#include "../yg/renderer.hpp"
class DrawerYG;
@ -32,6 +31,7 @@ namespace yg
class BaseTexture;
class RenderState;
class Screen;
class PacketsQueue;
}
}
@ -53,7 +53,7 @@ private:
render_fn_t renderFn);
};
struct Invalidate : public yg::gl::Renderer::Command
struct Invalidate : public yg::gl::Command
{
list<shared_ptr<WindowHandle> > m_windowHandles;
void perform();
@ -91,7 +91,7 @@ private:
bool m_isBenchmarking;
unsigned m_scaleEtalonSize;
yg::Color m_bgColor;
ThreadedList<yg::gl::Renderer::Packet> * m_glQueue;
yg::gl::PacketsQueue * m_glQueue;
TEmptyModelFn m_emptyModelFn;
@ -144,6 +144,6 @@ public:
/// wait for all commands are processed.
void waitForEmptyAndFinished();
void setGLQueue(ThreadedList<yg::gl::Renderer::Packet> * glQueue,
void setGLQueue(yg::gl::PacketsQueue * glQueue,
threads::Condition * glCondition);
};

View file

@ -313,7 +313,7 @@ bool Ruler::find(yg::StylesCache * stylesCache) const
return true;
}
void Ruler::fillUnpacked(yg::StylesCache * stylesCache, vector<m2::PointU> & v) const
void Ruler::getNonPackedRects(yg::StylesCache * stylesCache, vector<m2::PointU> & v) const
{
}

View file

@ -75,7 +75,7 @@ public:
void map(yg::StylesCache * stylesCache) const;
bool find(yg::StylesCache * stylesCache) const;
void fillUnpacked(yg::StylesCache * stylesCache, vector<m2::PointU> & v) const;
void getNonPackedRects(yg::StylesCache * stylesCache, vector<m2::PointU> & v) const;
int visualRank() const;
yg::OverlayElement * clone(math::Matrix<double, 3, 3> const & m) const;

View file

@ -105,7 +105,7 @@ void ScreenCoverage::Merge(Tiler::RectInfo const & ri)
else
{
m_infoLayer.cache(m_stylesCache);
// m_stylesCache->upload();
m_stylesCache->upload();
}
}
}
@ -198,7 +198,7 @@ void ScreenCoverage::SetScreen(ScreenBase const & screen)
else
{
m_infoLayer.cache(m_stylesCache);
// m_stylesCache->upload();
m_stylesCache->upload();
}
/// clearing all old commands
@ -251,10 +251,10 @@ void ScreenCoverage::Draw(yg::gl::Screen * s, ScreenBase const & screen)
s->blit(&infos[0], infos.size(), true);
/* if (m_stylesCache)
if (m_stylesCache)
s->setAdditionalSkinPage(m_stylesCache->cachePage());
m_infoLayer.draw(s, m_screen.PtoGMatrix() * screen.GtoPMatrix());*/
m_infoLayer.draw(s, m_screen.PtoGMatrix() * screen.GtoPMatrix());
}
void ScreenCoverage::EndFrame(yg::gl::Screen *s)

View file

@ -6,6 +6,7 @@
#include "../yg/render_state.hpp"
#include "../yg/rendercontext.hpp"
#include "../yg/base_texture.hpp"
#include "../yg/packets_queue.hpp"
#include "../std/bind.hpp"
@ -21,7 +22,7 @@ TileRenderer::TileRenderer(
shared_ptr<yg::gl::RenderContext> const & primaryRC,
shared_ptr<yg::ResourceManager> const & rm,
double visualScale,
yg::gl::Renderer::PacketsQueue * packetsQueue
yg::gl::PacketsQueue * packetsQueue
) : m_queue(executorsCount),
m_tileCache(maxTilesCount - executorsCount - 1),
m_renderFn(renderFn),
@ -171,6 +172,10 @@ void TileRenderer::DrawTile(core::CommandsQueue::Environment const & env,
drawer->screen()->resetInfoLayer();
yg::gl::PacketsQueue * glQueue = threadData.m_drawerParams.m_renderQueue;
if (glQueue)
glQueue->joinFence(glQueue->insertFence());
double duration = timer.ElapsedSeconds();
if (env.isCancelled())

View file

@ -21,6 +21,7 @@ namespace yg
{
class RenderState;
class RenderContext;
class PacketsQueue;
}
}
@ -74,7 +75,7 @@ public:
shared_ptr<yg::gl::RenderContext> const & primaryRC,
shared_ptr<yg::ResourceManager> const & rm,
double visualScale,
yg::gl::Renderer::PacketsQueue * packetsQueue);
yg::gl::PacketsQueue * packetsQueue);
/// destructor.
virtual ~TileRenderer();
/// add command to the commands queue.

View file

@ -178,8 +178,8 @@ void TilingRenderPolicyMT::SetRenderFn(TRenderFn renderFn)
m_tileRenderer.get(),
m_windowHandle,
m_primaryRC,
m_resourceManager
));
m_resourceManager,
0));
}
void TilingRenderPolicyMT::BeginFrame(shared_ptr<PaintEvent> const & e, ScreenBase const & s)

View file

@ -118,8 +118,8 @@ TilingRenderPolicyST::TilingRenderPolicyST(VideoTimer * videoTimer,
4,
"renderTargetTexture");
rmp.m_styleCacheTexturesParams = yg::ResourceManager::TexturePoolParams(rmp.m_fontTexturesParams.m_texWidth,
rmp.m_fontTexturesParams.m_texHeight,
rmp.m_styleCacheTexturesParams = yg::ResourceManager::TexturePoolParams(rmp.m_fontTexturesParams.m_texWidth * 2,
rmp.m_fontTexturesParams.m_texHeight * 2,
2,
rmp.m_texFormat,
true,
@ -198,13 +198,14 @@ void TilingRenderPolicyST::SetRenderFn(TRenderFn renderFn)
m_tileRenderer.get(),
m_windowHandle,
m_primaryRC,
m_resourceManager
m_resourceManager,
&m_glQueue
));
}
void TilingRenderPolicyST::BeginFrame(shared_ptr<PaintEvent> const & e, ScreenBase const & s)
{
m_IsDebugging = false;
m_IsDebugging = true;
if (m_IsDebugging)
LOG(LINFO, ("-------BeginFrame-------"));
}
@ -226,10 +227,10 @@ bool TilingRenderPolicyST::NeedRedraw() const
void TilingRenderPolicyST::DrawFrame(shared_ptr<PaintEvent> const & e, ScreenBase const & currentScreen)
{
m_resourceManager->mergeFreeResources();
RenderQueuedCommands(e->drawer()->screen().get());
m_resourceManager->mergeFreeResources();
DrawerYG * pDrawer = e->drawer();
pDrawer->screen()->clear(m_bgColor);
@ -282,7 +283,7 @@ void TilingRenderPolicyST::RenderQueuedCommands(yg::gl::Screen * screen)
cmdProcessed = m_frameGLQueue.size();
for (list<yg::gl::Renderer::Packet>::iterator it = m_frameGLQueue.begin(); it != m_frameGLQueue.end(); ++it)
for (list<yg::gl::Packet>::iterator it = m_frameGLQueue.begin(); it != m_frameGLQueue.end(); ++it)
{
if (it->m_state)
{
@ -291,9 +292,13 @@ void TilingRenderPolicyST::RenderQueuedCommands(yg::gl::Screen * screen)
// OGLCHECK(glFinish());
m_curState = it->m_state;
}
it->m_command->setIsDebugging(m_IsDebugging);
it->m_command->perform();
if (it->m_command)
{
it->m_command->setIsDebugging(m_IsDebugging);
it->m_command->perform();
// OGLCHECK(glFinish());
}
}
/// should clear to release resources, refered from the stored commands.
@ -318,7 +323,7 @@ void TilingRenderPolicyST::RenderQueuedCommands(yg::gl::Screen * screen)
// OGLCHECK(glFinish());
}
void TilingRenderPolicyST::ProcessRenderQueue(list<yg::gl::Renderer::Packet> & renderQueue, int maxPackets)
void TilingRenderPolicyST::ProcessRenderQueue(list<yg::gl::Packet> & renderQueue, int maxPackets)
{
m_frameGLQueue.clear();
if (maxPackets == -1)
@ -332,22 +337,22 @@ void TilingRenderPolicyST::ProcessRenderQueue(list<yg::gl::Renderer::Packet> & r
m_glCondition.Signal();
else
{
/// searching for "frame boundary" markers (empty packets)
/// searching for "group boundary" markers
list<yg::gl::Renderer::Packet>::iterator first = renderQueue.begin();
list<yg::gl::Renderer::Packet>::iterator last = renderQueue.begin();
list<yg::gl::Packet>::iterator first = renderQueue.begin();
list<yg::gl::Packet>::iterator last = renderQueue.begin();
int packetsLeft = maxPackets;
while ((packetsLeft != 0) && (last != renderQueue.end()))
{
yg::gl::Renderer::Packet p = *last;
if ((p.m_command == 0) && (p.m_state == 0))
yg::gl::Packet p = *last;
if (p.m_groupBoundary)
{
if (m_IsDebugging)
LOG(LINFO, ("found frame boundary"));
/// found frame boundary, copying
copy(first, last++, back_inserter(m_frameGLQueue));
copy(first, ++last, back_inserter(m_frameGLQueue));
/// erasing from the main queue
renderQueue.erase(first, last);
first = renderQueue.begin();

View file

@ -37,16 +37,16 @@ private:
/// --- COPY/PASTE HERE ---
ThreadedList<yg::gl::Renderer::Packet> m_glQueue;
list<yg::gl::Renderer::Packet> m_frameGLQueue;
yg::gl::PacketsQueue m_glQueue;
list<yg::gl::Packet> m_frameGLQueue;
threads::Condition m_glCondition;
shared_ptr<yg::gl::Screen::BaseState> m_curState;
shared_ptr<yg::gl::BaseState> m_curState;
shared_ptr<yg::gl::Renderer::BaseState> m_state;
shared_ptr<yg::gl::BaseState> m_state;
void ProcessRenderQueue(list<yg::gl::Renderer::Packet> & renderQueue, int maxPackets);
void ProcessRenderQueue(list<yg::gl::Packet> & renderQueue, int maxPackets);
bool m_IsDebugging;

View file

@ -76,7 +76,7 @@ int Platform::MaxTilesCount() const
int Platform::TileSize() const
{
return 256;
return 512;
}
int Platform::ScaleEtalonSize() const
@ -86,7 +86,7 @@ int Platform::ScaleEtalonSize() const
int Platform::VideoMemoryLimit() const
{
return 20 * 1024 * 1024;
return 100 * 1024 * 1024;
}
bool Platform::IsFeatureSupported(string const & feature) const

View file

@ -85,7 +85,7 @@ namespace yg
return skinPage->findCircleInfo(m_ci) != 0x00FFFFFF;
}
void CircleElement::fillUnpacked(StylesCache * stylesCache, vector<m2::PointU> & v) const
void CircleElement::getNonPackedRects(StylesCache * stylesCache, vector<m2::PointU> & v) const
{
shared_ptr<SkinPage> const & skinPage = stylesCache->cachePage();

View file

@ -32,7 +32,7 @@ namespace yg
void draw(gl::OverlayRenderer * s, math::Matrix<double, 3, 3> const & m) const;
void map(StylesCache * stylesCache) const;
void fillUnpacked(StylesCache * stylesCache, vector<m2::PointU> & v) const;
void getNonPackedRects(StylesCache * stylesCache, vector<m2::PointU> & v) const;
bool find(StylesCache * stylesCache) const;
int visualRank() const;

View file

@ -92,7 +92,7 @@ namespace yg
return m_clipRect;
}
shared_ptr<Clipper::BaseState> const Clipper::createState() const
shared_ptr<BaseState> const Clipper::createState() const
{
return shared_ptr<BaseState>(new State());
}

View file

@ -54,10 +54,10 @@ namespace yg
m_elements[i]->map(stylesCache);
}
void CompositeOverlayElement::fillUnpacked(StylesCache * stylesCache, vector<m2::PointU> & v) const
void CompositeOverlayElement::getNonPackedRects(StylesCache * stylesCache, vector<m2::PointU> & v) const
{
for (unsigned i = 0; i < m_elements.size(); ++i)
m_elements[i]->fillUnpacked(stylesCache, v);
m_elements[i]->getNonPackedRects(stylesCache, v);
}
bool CompositeOverlayElement::find(StylesCache * stylesCache) const

View file

@ -28,7 +28,7 @@ namespace yg
void map(StylesCache * stylesCache) const;
bool find(StylesCache * stylesCache) const;
void fillUnpacked(StylesCache * stylesCache, vector<m2::PointU> & v) const;
void getNonPackedRects(StylesCache * stylesCache, vector<m2::PointU> & v) const;
int visualRank() const;

89
yg/fence_manager.cpp Normal file
View file

@ -0,0 +1,89 @@
#include "fence_manager.hpp"
#include "../base/assert.hpp"
#include "../base/logging.hpp"
namespace yg
{
FenceManager::FenceManager(int conditionPoolSize)
: m_currentFence(0)
{
m_conditionPool.resize(conditionPoolSize);
for (unsigned i = 0; i < m_conditionPool.size(); ++i)
m_conditionPool[i] = new threads::Condition();
}
FenceManager::~FenceManager()
{
for (map<int, threads::Condition*>::const_iterator it = m_activeFences.begin();
it != m_activeFences.end();
++it)
{
it->second->Signal(true);
delete it->second;
}
for (unsigned i = 0; i < m_conditionPool.size(); ++i)
{
delete m_conditionPool[i];
}
}
int FenceManager::insertFence()
{
threads::MutexGuard g(m_mutex);
if (m_conditionPool.empty())
return -1;
threads::Condition * cond = m_conditionPool.back();
m_conditionPool.pop_back();
int id = m_currentFence++;
m_activeFences[id] = cond;
return id;
}
void FenceManager::signalFence(int id)
{
threads::MutexGuard g(m_mutex);
map<int, threads::Condition*>::iterator it = m_activeFences.find(id);
CHECK(it != m_activeFences.end(), ("using singalFence twice for the same id is error"));
threads::Condition * cond = it->second;
/// signalling to all waiting fences
cond->Signal(true);
/// erasing fence from active fences
m_activeFences.erase(it);
/// returning condition to the pool
m_conditionPool.push_back(cond);
}
void FenceManager::joinFence(int id)
{
threads::Condition * cond = 0;
{
threads::MutexGuard g(m_mutex);
map<int, threads::Condition*>::iterator it = m_activeFences.find(id);
if (it == m_activeFences.end())
{
LOG(LINFO, ("fence has been reached in the past or haven't been installed yet"));
return;
}
cond = it->second;
}
threads::ConditionGuard g(*cond);
g.Wait();
}
}

29
yg/fence_manager.hpp Normal file
View file

@ -0,0 +1,29 @@
#pragma once
#include "../base/condition.hpp"
#include "../base/mutex.hpp"
#include "../std/map.hpp"
#include "../std/vector.hpp"
namespace yg
{
class FenceManager
{
private:
threads::Mutex m_mutex;
vector<threads::Condition *> m_conditionPool;
map<int, threads::Condition *> m_activeFences;
int m_currentFence;
public:
FenceManager(int conditionPoolSize);
~FenceManager();
int insertFence();
void joinFence(int id);
void signalFence(int id);
};
}

View file

@ -23,14 +23,14 @@ namespace yg
typedef Blitter base_t;
struct UploadData : base_t::Command
struct UploadData : Command
{
vector<shared_ptr<ResourceStyle> > m_styles;
shared_ptr<BaseTexture> m_texture;
void perform();
};
struct DrawGeometry : base_t::Command
struct DrawGeometry : Command
{
shared_ptr<BaseTexture> m_texture;
shared_ptr<VertexBuffer> m_vertices;

View file

@ -223,7 +223,7 @@ namespace yg
sizes.reserve(100);
for (unsigned i = 0; i < v.size(); ++i)
v[i]->fillUnpacked(stylesCache, sizes);
v[i]->getNonPackedRects(stylesCache, sizes);
if (stylesCache->hasRoom(&sizes[0], sizes.size()))
{
@ -240,7 +240,7 @@ namespace yg
for (pos = 0; pos < v.size(); ++pos)
{
sizes.clear();
v[pos]->fillUnpacked(stylesCache, sizes);
v[pos]->getNonPackedRects(stylesCache, sizes);
if (stylesCache->hasRoom(&sizes[0], sizes.size()))
v[pos]->map(stylesCache);
else

View file

@ -57,7 +57,7 @@ namespace yg
/// caching-related functions.
/// @{
virtual void fillUnpacked(StylesCache * stylesCache, vector<m2::PointU> & sizes) const = 0;
virtual void getNonPackedRects(StylesCache * stylesCache, vector<m2::PointU> & sizes) const = 0;
virtual bool find(StylesCache * stylesCache) const = 0;
virtual void map(StylesCache * stylesCache) const = 0;
/// @}

91
yg/packets_queue.cpp Normal file
View file

@ -0,0 +1,91 @@
#include "packets_queue.hpp"
namespace yg
{
namespace gl
{
BaseState::BaseState()
: m_isDebugging(false)
{}
BaseState::~BaseState()
{}
bool Command::isDebugging() const
{
return m_isDebugging;
}
void Command::setIsDebugging(bool flag)
{
m_isDebugging = flag;
}
Command::Command()
: m_isDebugging(false)
{}
Command::~Command()
{}
Packet::Packet()
: m_groupBoundary(true)
{}
Packet::Packet(bool groupBoundary)
: m_groupBoundary(groupBoundary)
{}
Packet::Packet(shared_ptr<Command> const & command,
bool groupBoundary)
: m_command(command),
m_groupBoundary(groupBoundary)
{}
Packet::Packet(shared_ptr<BaseState> const & state,
shared_ptr<Command> const & command,
bool groupBoundary)
: m_state(state),
m_command(command),
m_groupBoundary(groupBoundary)
{
if (m_state && m_command)
m_state->m_isDebugging = m_command->isDebugging();
}
PacketsQueue::PacketsQueue() : m_fenceManager(10)
{}
void PacketsQueue::markFrameBoundary()
{
PushBack(Packet(true));
}
struct SignalFence : public Command
{
int m_id;
FenceManager * m_fenceManager;
SignalFence(int id, FenceManager * fenceManager)
: m_id(id), m_fenceManager(fenceManager)
{}
void perform()
{
m_fenceManager->signalFence(m_id);
}
};
int PacketsQueue::insertFence()
{
int id = m_fenceManager.insertFence();
PushBack(Packet(make_shared_ptr(new SignalFence(id, &m_fenceManager)), true));
return id;
}
void PacketsQueue::joinFence(int id)
{
m_fenceManager.joinFence(id);
}
}
}

73
yg/packets_queue.hpp Normal file
View file

@ -0,0 +1,73 @@
#pragma once
#include "fence_manager.hpp"
#include "../base/threaded_list.hpp"
#include "../base/mutex.hpp"
#include "../base/condition.hpp"
#include "../std/shared_ptr.hpp"
namespace yg
{
namespace gl
{
struct BaseState
{
bool m_isDebugging;
BaseState();
virtual ~BaseState();
virtual void apply(BaseState const * prev) = 0;
};
struct Command
{
private:
bool m_isDebugging;
public:
bool isDebugging() const;
void setIsDebugging(bool flag);
Command();
virtual ~Command();
virtual void perform() = 0;
friend class Renderer;
};
struct Packet
{
shared_ptr<BaseState> m_state;
shared_ptr<Command> m_command;
bool m_groupBoundary;
explicit Packet();
/// empty packet act as a frame delimiter
explicit Packet(bool groupBoundary);
/// non-opengl command, without any state
explicit Packet(shared_ptr<Command> const & command,
bool groupBoundary);
/// opengl command with state
explicit Packet(shared_ptr<BaseState> const & state,
shared_ptr<Command> const & command,
bool groupBoundary);
};
class PacketsQueue : public ThreadedList<Packet>
{
private:
FenceManager m_fenceManager;
public:
PacketsQueue();
void markFrameBoundary();
int insertFence();
void joinFence(int id);
};
}
}

View file

@ -93,16 +93,16 @@ namespace yg
return TextElement::find(m_glyphLayout, stylesCache, desc);
}
void PathTextElement::fillUnpacked(StylesCache * stylesCache, vector<m2::PointU> & v) const
void PathTextElement::getNonPackedRects(StylesCache * stylesCache, vector<m2::PointU> & v) const
{
yg::FontDesc desc = m_fontDesc;
if (desc.m_isMasked)
{
TextElement::fillUnpacked(m_glyphLayout, desc, stylesCache, v);
TextElement::getNonPackedRects(m_glyphLayout, desc, stylesCache, v);
desc.m_isMasked = false;
}
return TextElement::fillUnpacked(m_glyphLayout, desc, stylesCache, v);
return TextElement::getNonPackedRects(m_glyphLayout, desc, stylesCache, v);
}
void PathTextElement::map(StylesCache * stylesCache) const

View file

@ -27,7 +27,7 @@ namespace yg
void draw(gl::OverlayRenderer * r, math::Matrix<double, 3, 3> const & m) const;
void fillUnpacked(StylesCache * stylesCache, vector<m2::PointU> & v) const;
void getNonPackedRects(StylesCache * stylesCache, vector<m2::PointU> & v) const;
bool find(StylesCache * stylesCache) const;
void map(StylesCache * stylesCache) const;

View file

@ -26,7 +26,7 @@ namespace yg
double m_updateInterval;
my::Timer m_updateTimer;
struct UpdateActualTarget : base_t::Command
struct UpdateActualTarget : Command
{
bool m_doSynchronize;
shared_ptr<RenderState> m_renderState;
@ -35,7 +35,7 @@ namespace yg
void perform();
};
struct UpdateBackBuffer : base_t::Command
struct UpdateBackBuffer : Command
{
shared_ptr<RenderState> m_renderState;
shared_ptr<ResourceManager> m_resourceManager;
@ -47,7 +47,7 @@ namespace yg
void perform();
};
struct Invalidate : base_t::Command
struct Invalidate : Command
{
shared_ptr<RenderState> m_renderState;
void perform();

View file

@ -13,29 +13,6 @@ namespace yg
{
const yg::Color Renderer::s_bgColor(192, 192, 192, 255);
Renderer::BaseState::BaseState()
: m_isDebugging(false)
{}
Renderer::BaseState::~BaseState()
{}
bool Renderer::Command::isDebugging() const
{
return m_isDebugging;
}
void Renderer::Command::setIsDebugging(bool flag)
{
m_isDebugging = flag;
}
Renderer::Command::Command()
: m_isDebugging(false)
{}
Renderer::Command::~Command()
{}
void Renderer::State::apply(BaseState const * prevBase)
{
@ -187,20 +164,6 @@ namespace yg
CHECK(false, ());
}
Renderer::Packet::Packet()
{}
Renderer::Packet::Packet(shared_ptr<Command> const & command)
: m_command(command)
{}
Renderer::Packet::Packet(shared_ptr<BaseState> const & state,
shared_ptr<Command> const & command)
: m_state(state), m_command(command)
{
if (m_state && m_command)
m_state->m_isDebugging = m_command->isDebugging();
}
Renderer::Params::Params()
: m_isDebugging(false),
@ -327,7 +290,7 @@ namespace yg
processCommand(command);
}
shared_ptr<Renderer::BaseState> const Renderer::createState() const
shared_ptr<BaseState> const Renderer::createState() const
{
return shared_ptr<BaseState>(new State());
}
@ -391,13 +354,13 @@ namespace yg
{
shared_ptr<BaseState> state = createState();
getState(state.get());
m_renderQueue->PushBack(Packet(state, command));
m_renderQueue->PushBack(Packet(state, command, false));
}
else
command->perform();
}
ThreadedList<Renderer::Packet> * Renderer::renderQueue()
PacketsQueue * Renderer::renderQueue()
{
return m_renderQueue;
}
@ -405,7 +368,7 @@ namespace yg
void Renderer::markFrameBoundary()
{
if (m_renderQueue)
m_renderQueue->PushBack(Packet());
m_renderQueue->PushBack(Packet(true));
}
}
}

View file

@ -1,6 +1,7 @@
#pragma once
#include "color.hpp"
#include "packets_queue.hpp"
#include "../base/threaded_list.hpp"
#include "../std/function.hpp"
@ -21,14 +22,6 @@ namespace yg
{
public:
struct BaseState
{
bool m_isDebugging;
BaseState();
virtual ~BaseState();
virtual void apply(BaseState const * prev) = 0;
};
struct State : BaseState
{
shared_ptr<FrameBuffer> m_frameBuffer;
@ -39,35 +32,6 @@ namespace yg
void apply(BaseState const * prev);
};
struct Command
{
private:
bool m_isDebugging;
public:
bool isDebugging() const;
void setIsDebugging(bool flag);
Command();
virtual ~Command();
virtual void perform() = 0;
friend class Renderer;
};
struct Packet
{
shared_ptr<BaseState> m_state;
shared_ptr<Command> m_command;
Packet();
Packet(shared_ptr<Command> const & command);
Packet(shared_ptr<BaseState> const & state,
shared_ptr<Command> const & command);
};
typedef ThreadedList<Packet> PacketsQueue;
struct ClearCommand : Command
{
yg::Color m_color;
@ -106,7 +70,7 @@ namespace yg
shared_ptr<RenderBuffer> m_depthBuffer;
shared_ptr<ResourceManager> m_resourceManager;
ThreadedList<Packet> * m_renderQueue;
PacketsQueue * m_renderQueue;
bool m_isDebugging;
@ -157,7 +121,7 @@ namespace yg
virtual void getState(BaseState * state);
void processCommand(shared_ptr<Command> const & command);
ThreadedList<Packet> * renderQueue();
PacketsQueue * renderQueue();
/// insert empty packet into glQueue to mark the frame boundary
void markFrameBoundary();

View file

@ -361,7 +361,13 @@ namespace yg
if (videoMemoryLimit < fixedMemoryUsage())
{
LOG(LINFO, ("videoMemoryLimit", videoMemoryLimit,"is less than an amount of fixed resources", fixedMemoryUsage()));
LOG(LINFO, ("videoMemoryLimit", videoMemoryLimit, "is less than an amount of fixed resources", fixedMemoryUsage()));
videoMemoryLimit = memoryUsage();
}
if (videoMemoryLimit < memoryUsage())
{
LOG(LINFO, ("videoMemoryLimit", videoMemoryLimit, "is less than amount of currently allocated resources", memoryUsage()));
videoMemoryLimit = memoryUsage();
}

View file

@ -329,30 +329,53 @@ namespace yg
it->second->m_pipelineID = pipelineID;
}
void SkinPage::uploadData()
SkinPage::UploadData::UploadData(SkinPage::TUploadQueue const & uploadQueue,
shared_ptr<yg::gl::BaseTexture> const & texture)
: m_uploadQueue(uploadQueue), m_texture(texture)
{}
SkinPage::UploadData::UploadData()
{}
void SkinPage::UploadData::perform()
{
if (isDebugging())
LOG(LINFO, ("performing UploadData command", m_texture->width(), m_texture->height()));
static_cast<gl::ManagedTexture*>(m_texture.get())->lock();
TDynamicTexture * dynTexture = static_cast<TDynamicTexture*>(m_texture.get());
for (size_t i = 0; i < m_uploadQueue.size(); ++i)
{
shared_ptr<ResourceStyle> const & style = m_uploadQueue[i];
TDynamicTexture::view_t v = dynTexture->view(style->m_texRect.SizeX(),
style->m_texRect.SizeY());
style->render(&v(0, 0));
dynTexture->upload(&v(0, 0), style->m_texRect);
}
static_cast<gl::ManagedTexture*>(m_texture.get())->unlock();
}
void SkinPage::uploadData(yg::gl::PacketsQueue * glQueue)
{
if (hasData())
{
checkTexture();
static_cast<gl::ManagedTexture*>(m_texture.get())->lock();
TDynamicTexture * dynTexture = static_cast<TDynamicTexture*>(m_texture.get());
shared_ptr<UploadData> cmd(new UploadData(m_uploadQueue, m_texture));
for (size_t i = 0; i < m_uploadQueue.size(); ++i)
{
shared_ptr<ResourceStyle> const & style = m_uploadQueue[i];
TDynamicTexture::view_t v = dynTexture->view(style->m_texRect.SizeX(),
style->m_texRect.SizeY());
style->render(&v(0, 0));
dynTexture->upload(&v(0, 0), style->m_texRect);
}
if (glQueue)
glQueue->PushBack(yg::gl::Packet(cmd, false));
else
cmd->perform();
m_uploadQueue.clear();
static_cast<gl::ManagedTexture*>(m_texture.get())->unlock();
}
}

View file

@ -9,6 +9,7 @@
#include "circle_info.hpp"
#include "color.hpp"
#include "glyph_cache.hpp"
#include "packets_queue.hpp"
namespace yg
{
@ -96,6 +97,18 @@ namespace yg
public:
struct UploadData : public yg::gl::Command
{
SkinPage::TUploadQueue m_uploadQueue;
shared_ptr<yg::gl::BaseTexture> m_texture;
UploadData();
UploadData(SkinPage::TUploadQueue const & uploadQueue,
shared_ptr<yg::gl::BaseTexture> const & texture);
void perform();
};
void clearColorHandles();
void clearPenInfoHandles();
void clearFontHandles();
@ -109,7 +122,7 @@ namespace yg
TUploadQueue const & uploadQueue() const;
void clearUploadQueue();
void uploadData();
void uploadData(yg::gl::PacketsQueue * glQueue);
void checkTexture() const;
void setPipelineID(uint8_t pipelineID);

View file

@ -321,20 +321,20 @@ namespace yg
return true;
}
void StraightTextElement::fillUnpacked(StylesCache * stylesCache, vector<m2::PointU> & v) const
void StraightTextElement::getNonPackedRects(StylesCache * stylesCache, vector<m2::PointU> & 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);
TextElement::getNonPackedRects(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);
TextElement::getNonPackedRects(m_glyphLayouts[i], desc, stylesCache, v);
}
int StraightTextElement::visualRank() const

View file

@ -33,7 +33,7 @@ namespace yg
void draw(gl::OverlayRenderer * r, math::Matrix<double, 3, 3> const & m) const;
void fillUnpacked(StylesCache * stylesCache, vector<m2::PointU> & v) const;
void getNonPackedRects(StylesCache * stylesCache, vector<m2::PointU> & v) const;
bool find(StylesCache * stylesCache) const;
void map(StylesCache * stylesCache) const;

View file

@ -6,15 +6,19 @@
#include "skin_page.hpp"
#include "resource_manager.hpp"
#include "base_texture.hpp"
#include "packets_queue.hpp"
#include "internal/opengl.hpp"
#include "renderer.hpp"
#include "../base/thread.hpp"
namespace yg
{
StylesCache::StylesCache(shared_ptr<ResourceManager> const & rm,
int glyphCacheID)
: m_rm(rm)
int glyphCacheID,
yg::gl::PacketsQueue * glQueue)
: m_rm(rm),
m_glQueue(glQueue)
{
m_glyphCache = m_rm->glyphCache(glyphCacheID);
m_cachePage.reset(new SkinPage());
@ -48,8 +52,15 @@ namespace yg
void StylesCache::upload()
{
m_cachePage->uploadData();
OGLCHECK(glFinish());
m_cachePage->uploadData(m_glQueue);
m_glQueue->PushBack(yg::gl::Packet(make_shared_ptr(new yg::gl::Renderer::FinishCommand()), false));
/// waiting for upload to complete
if (m_glQueue)
m_glQueue->joinFence(m_glQueue->insertFence());
else
OGLCHECK(glFinish());
}
bool StylesCache::hasRoom(m2::PointU const * sizes, size_t cnt) const

View file

@ -5,6 +5,11 @@
namespace yg
{
namespace gl
{
class PacketsQueue;
}
class StraightTextElement;
class PathTextElement;
class SkinPage;
@ -20,13 +25,15 @@ namespace yg
shared_ptr<ResourceManager> m_rm;
GlyphCache * m_glyphCache;
yg::gl::PacketsQueue * m_glQueue;
shared_ptr<SkinPage> m_cachePage;
public:
StylesCache(shared_ptr<ResourceManager> const & rm,
int glyphCacheID);
int glyphCacheID,
yg::gl::PacketsQueue * glQueue);
~StylesCache();

View file

@ -95,7 +95,7 @@ namespace yg
return true;
}
void SymbolElement::fillUnpacked(StylesCache * stylesCache, vector<m2::PointU> & v) const
void SymbolElement::getNonPackedRects(StylesCache * stylesCache, vector<m2::PointU> & v) const
{
}

View file

@ -36,7 +36,7 @@ namespace yg
void draw(gl::OverlayRenderer * s, math::Matrix<double, 3, 3> const & m) const;
void map(StylesCache * stylesCache) const;
void fillUnpacked(StylesCache * stylesCache, vector<m2::PointU> & v) const;
void getNonPackedRects(StylesCache * stylesCache, vector<m2::PointU> & v) const;
bool find(StylesCache * stylesCache) const;
uint32_t styleID() const;

View file

@ -184,10 +184,10 @@ namespace yg
return true;
}
void TextElement::fillUnpacked(GlyphLayout const & layout,
FontDesc const & desc,
StylesCache * stylesCache,
vector<m2::PointU> & v) const
void TextElement::getNonPackedRects(GlyphLayout const & layout,
FontDesc const & desc,
StylesCache * stylesCache,
vector<m2::PointU> & v) const
{
if (!desc.IsValid())
return;

View file

@ -49,7 +49,7 @@ namespace yg
using OverlayElement::map;
using OverlayElement::find;
using OverlayElement::fillUnpacked;
using OverlayElement::getNonPackedRects;
void map(GlyphLayout const & layout,
StylesCache * stylesCache,
@ -59,10 +59,10 @@ namespace yg
StylesCache * stylesCache,
FontDesc const & desc) const;
void fillUnpacked(GlyphLayout const & layout,
FontDesc const & desc,
StylesCache * stylesCache,
vector<m2::PointU> & v) const;
void getNonPackedRects(GlyphLayout const & layout,
FontDesc const & desc,
StylesCache * stylesCache,
vector<m2::PointU> & v) const;
public:

View file

@ -61,7 +61,9 @@ SOURCES += \
line_style.cpp \
circle_style.cpp \
glyph_style.cpp \
circle_element.cpp
circle_element.cpp \
packets_queue.cpp \
fence_manager.cpp
HEADERS += \
internal/opengl.hpp \
@ -116,7 +118,9 @@ HEADERS += \
path_text_element.hpp \
straight_text_element.hpp \
agg_traits.hpp \
circle_element.hpp
circle_element.hpp \
packets_queue.hpp \
fence_manager.hpp
win32* {
SOURCES += internal/opengl_win32.cpp
@ -125,3 +129,7 @@ win32* {
} else {
SOURCES += internal/opengl_ext.cpp
}