using double buffering for dynamicPage in Skin. fixes issue on iPhone5.

This commit is contained in:
rachytski 2012-11-06 19:54:00 +03:00 committed by Alex Zolotarev
parent be63171c2a
commit 56e06376d1
7 changed files with 132 additions and 39 deletions

View file

@ -60,7 +60,7 @@ namespace yg
float texX = style->m_texRect.minX() + 1.0f;
float texY = style->m_texRect.minY() + 1.0f;
shared_ptr<BaseTexture> texture = skin()->getPage(style->m_pipelineID)->texture();
shared_ptr<BaseTexture> texture = skin()->page(style->m_pipelineID)->texture();
if (!texture)
{
@ -105,7 +105,7 @@ namespace yg
float texX = style->m_texRect.minX() + 1.0f;
float texY = style->m_texRect.minY() + 1.0f;
shared_ptr<BaseTexture> texture = skin()->getPage(style->m_pipelineID)->texture();
shared_ptr<BaseTexture> texture = skin()->page(style->m_pipelineID)->texture();
if (!texture)
{

View file

@ -45,7 +45,7 @@ namespace yg
{
discardPipeline(i);
freePipeline(i);
if (m_skin->getPage(i)->type() != SkinPage::EStatic)
if (m_skin->page(i)->type() != SkinPage::EStatic)
freeTexture(i);
}
}
@ -154,11 +154,11 @@ namespace yg
{
/// settings proper skin page type according to useGuiResources flag
if (m_useGuiResources)
for (size_t i = 0; i < m_skin->getPagesCount(); ++i)
if (m_skin->getPage(i)->type() != SkinPage::EStatic)
m_skin->getPage(i)->setType(SkinPage::ELightWeight);
for (size_t i = 0; i < m_skin->pagesCount(); ++i)
if (m_skin->page(i)->type() != SkinPage::EStatic)
m_skin->page(i)->setType(SkinPage::ELightWeight);
m_pipelines.resize(m_skin->getPagesCount());
m_pipelines.resize(m_skin->pagesCount());
m_skin->addClearPageFn(bind(&GeometryBatcher::flush, this, _1), 100);
m_skin->addClearPageFn(bind(&GeometryBatcher::freeTexture, this, _1), 99);
@ -170,7 +170,7 @@ namespace yg
m_pipelines[i].m_currentIndex = 0;
m_pipelines[i].m_hasStorage = false;
m_pipelines[i].m_type = skin->getPage(i)->type();
m_pipelines[i].m_type = skin->page(i)->type();
m_pipelines[i].m_maxVertices = 0;
m_pipelines[i].m_maxIndices = 0;
@ -275,10 +275,27 @@ namespace yg
{
for (size_t i = m_pipelines.size(); i > 0; --i)
{
if ((pipelineID == -1) || ((i - 1) == (size_t)pipelineID))
size_t id = i - 1;
if ((pipelineID == -1) || (id == (size_t)pipelineID))
{
flushPipeline(m_skin->getPage(i - 1), i - 1);
reset(i - 1);
if (flushPipeline(m_skin->page(id), id))
{
int nextPage = m_skin->nextPage(id);
if (nextPage != id)
{
// reserving texture in advance, before we'll
// potentially return current texture into the pool.
m_skin->page(nextPage)->checkTexture();
}
m_skin->changePage(id);
}
/// resetting geometry storage associated
/// with the specified pipeline.
reset(id);
}
}
}
@ -286,13 +303,13 @@ namespace yg
void GeometryBatcher::freeTexture(int pipelineID)
{
if (!m_skin->getPage(pipelineID)->hasTexture())
if (!m_skin->page(pipelineID)->hasTexture())
return;
shared_ptr<BaseTexture> texture = m_skin->getPage(pipelineID)->texture();
shared_ptr<BaseTexture> texture = m_skin->page(pipelineID)->texture();
TTexturePool * texturePool = 0;
switch (m_skin->getPage(pipelineID)->type())
switch (m_skin->page(pipelineID)->type())
{
case SkinPage::EPrimary:
texturePool = resourceManager()->primaryTextures();
@ -310,7 +327,7 @@ namespace yg
base_t::freeTexture(texture, texturePool);
m_skin->getPage(pipelineID)->resetTexture();
m_skin->page(pipelineID)->resetTexture();
}
void GeometryBatcher::unlockPipeline(int pipelineID)
@ -327,7 +344,7 @@ namespace yg
base_t::discardStorage(pipeline.m_storage);
}
void GeometryBatcher::flushPipeline(shared_ptr<SkinPage> const & skinPage,
bool GeometryBatcher::flushPipeline(shared_ptr<SkinPage> const & skinPage,
int pipelineID)
{
GeometryPipeline & pipeline = m_pipelines[pipelineID];
@ -365,7 +382,11 @@ namespace yg
pipeline.m_indices = 0;
pipeline.m_currentIndex = 0;
pipeline.m_currentVertex = 0;
return true;
}
return false;
}
void GeometryBatcher::drawTexturedPolygon(
@ -388,7 +409,7 @@ namespace yg
float texMinY = ty0;
float texMaxY = ty1;
shared_ptr<BaseTexture> const & texture = m_skin->getPage(pipelineID)->texture();
shared_ptr<BaseTexture> const & texture = m_skin->page(pipelineID)->texture();
if (!texture)
{
@ -459,7 +480,7 @@ namespace yg
float texMinY = ty0;
float texMaxY = ty1;
shared_ptr<BaseTexture> const & texture = m_skin->getPage(pipelineID)->texture();
shared_ptr<BaseTexture> const & texture = m_skin->page(pipelineID)->texture();
if (!texture)
{

View file

@ -109,7 +109,7 @@ namespace yg
void beginFrame();
void endFrame();
void flushPipeline(shared_ptr<SkinPage> const & skinPage, int pipelineID);
bool flushPipeline(shared_ptr<SkinPage> const & skinPage, int pipelineID);
void unlockPipeline(int pipelineID);
void discardPipeline(int pipelineID);

View file

@ -95,7 +95,7 @@ namespace yg
/// Length of the actual pattern data being tiling(without antialiasing zones).
rawTileLen = 0;
shared_ptr<BaseTexture> texture = skin()->getPage(lineStyle->m_pipelineID)->texture();
shared_ptr<BaseTexture> texture = skin()->page(lineStyle->m_pipelineID)->texture();
if (!texture)
{
@ -186,7 +186,7 @@ namespace yg
startVec = norm;
}
shared_ptr<BaseTexture> texture = skin()->getPage(lineStyle->m_pipelineID)->texture();
shared_ptr<BaseTexture> texture = skin()->page(lineStyle->m_pipelineID)->texture();
if (!texture)
{
@ -276,7 +276,7 @@ namespace yg
nextPt + fDir - fNorm
};
shared_ptr<BaseTexture> texture = skin()->getPage(lineStyle->m_pipelineID)->texture();
shared_ptr<BaseTexture> texture = skin()->page(lineStyle->m_pipelineID)->texture();
if (!texture)
{

View file

@ -110,7 +110,7 @@ namespace yg
for (int i = 0; i < 4; ++i)
rectPtsF[i] = m2::PointF(rectPts[i].x, rectPts[i].y);
shared_ptr<BaseTexture> texture = skin()->getPage(style->m_pipelineID)->texture();
shared_ptr<BaseTexture> texture = skin()->page(style->m_pipelineID)->texture();
if (!texture)
{
@ -151,7 +151,7 @@ namespace yg
m2::PointF(r.maxX(), r.maxY())
};
shared_ptr<BaseTexture> texture = skin()->getPage(style->m_pipelineID)->texture();
shared_ptr<BaseTexture> texture = skin()->page(style->m_pipelineID)->texture();
if (!texture)
{
@ -186,7 +186,7 @@ namespace yg
return;
}
shared_ptr<BaseTexture> texture = skin()->getPage(style->m_pipelineID)->texture();
shared_ptr<BaseTexture> texture = skin()->page(style->m_pipelineID)->texture();
if (!texture)
{

View file

@ -25,8 +25,9 @@ namespace yg
m_textPage = m_pages.size();
addTextPages(1);
m_dynamicPage = m_pages.size();
addDynamicPages(1);
m_startDynamicPage = m_dynamicPage = m_pages.size();
m_dynamicPagesCount = 2;
addDynamicPages(m_dynamicPagesCount);
}
void Skin::addTextPages(int count)
@ -150,7 +151,8 @@ namespace yg
bool Skin::mapPenInfo(PenInfo const * penInfos, uint32_t * styleIDS, size_t count)
{
bool alreadyFlushed = false;
int startDynamicPage = m_dynamicPage;
int cycles = 0;
int i = 0;
@ -165,10 +167,17 @@ namespace yg
{
/// no room - flush the page
flushDynamicPage();
if (alreadyFlushed)
return false; //<cycling
alreadyFlushed = true;
if (startDynamicPage == m_dynamicPage)
cycles += 1;
/// there could be maximum 2 cycles to
/// pack the sequence as a whole.
/// second cycle is necessary as the first one
/// could possibly run on partially packed skin pages.
if (cycles == 2)
return false;
/// re-start packing
i = 0;
}
@ -200,13 +209,13 @@ namespace yg
return packID(m_textPage, m_pages[m_textPage]->mapGlyph(gk, glyphCache));
}
shared_ptr<SkinPage> const & Skin::getPage(int i) const
shared_ptr<SkinPage> const & Skin::page(int i) const
{
ASSERT(i < m_pages.size(), ());
return m_pages[i];
}
size_t Skin::getPagesCount() const
size_t Skin::pagesCount() const
{
return m_pages.size();
}
@ -228,7 +237,7 @@ namespace yg
void Skin::clearPageHandles(uint8_t pipelineID)
{
getPage(pipelineID)->clearHandles();
page(pipelineID)->clearHandles();
}
/// This function is set to perform as a callback on texture or handles overflow
@ -246,9 +255,33 @@ namespace yg
flushTextPage();
}
bool Skin::isDynamicPage(int i) const
{
return (i >= m_startDynamicPage) && (i < m_startDynamicPage + m_dynamicPagesCount);
}
void Skin::flushDynamicPage()
{
callClearPageFns(m_dynamicPage);
changeDynamicPage();
}
int Skin::nextDynamicPage() const
{
if (m_dynamicPage == m_startDynamicPage + m_dynamicPagesCount - 1)
return m_startDynamicPage;
else
return m_dynamicPage + 1;
}
void Skin::changeDynamicPage()
{
m_dynamicPage = nextDynamicPage();
}
bool Skin::isTextPage(int i) const
{
return i == m_textPage;
}
void Skin::flushTextPage()
@ -257,6 +290,23 @@ namespace yg
callClearPageFns(m_textPage);
}
int Skin::nextPage(int i) const
{
ASSERT(i < m_pages.size(), ());
if (isDynamicPage(i))
return nextDynamicPage();
/// for static and text pages return same index as passed in.
return i;
}
void Skin::changePage(int i)
{
if (isDynamicPage(i))
changeDynamicPage();
}
uint32_t Skin::invalidHandle() const
{
return 0xFFFFFFFF;

View file

@ -44,11 +44,13 @@ namespace yg
TSkinPages m_pages;
uint8_t m_startDynamicPage;
uint8_t m_dynamicPage;
uint8_t m_dynamicPagesCount;
uint8_t m_textPage;
uint8_t m_startStaticPage;
uint8_t m_currentStaticPage;
uint8_t m_staticPagesCount;
shared_ptr<ResourceManager> m_resourceManager;
@ -82,12 +84,19 @@ namespace yg
void callOverflowFns(uint8_t pipelineID);
void clearPageHandles(uint8_t pipelineID);
void onDynamicOverflow(uint8_t pipelineID);
void onTextOverflow(uint8_t pipelineID);
bool isDynamicPage(int i) const;
void flushDynamicPage();
int nextDynamicPage() const;
void changeDynamicPage();
void onDynamicOverflow(uint8_t pipelineID);
bool isTextPage(int i) const;
void flushTextPage();
void onTextOverflow(uint8_t pipelineID);
public:
/// clean and destroy
@ -117,10 +126,13 @@ namespace yg
/// if not - pack and return id
uint32_t mapCircleInfo(CircleInfo const & circleInfo);
/// adding function which will be called, when some SkinPage
/// is getting cleared.
void addClearPageFn(clearPageFn fn, int priority);
shared_ptr<SkinPage> const & getPage(int i) const;
size_t getPagesCount() const;
shared_ptr<SkinPage> const & page(int i) const;
size_t pagesCount() const;
uint32_t invalidHandle() const;
uint32_t invalidPageHandle() const;
@ -128,6 +140,16 @@ namespace yg
uint8_t textPage() const;
uint8_t dynamicPage() const;
/// change page for its "backbuffer" counterpart.
/// this function is called after any rendering command
/// issued to avoid the "GPU is waiting on texture used in
/// rendering call" issue.
/// @warning does nothing for static pages
/// (pages loaded at skin creation time)
/// and text pages.
void changePage(int i);
int nextPage(int i) const;
void clearHandles();
void memoryWarning();