Change Atlas recycling to track current flush count and recycle if Atlas not used in current flush.

BUG=
R=bsalomon@google.com, robertphillips@google.com

Author: jvanverth@google.com

Review URL: https://chromiumcodereview.appspot.com/23120004

git-svn-id: http://skia.googlecode.com/svn/trunk@10777 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
commit-bot@chromium.org 2013-08-16 15:53:46 +00:00
parent 2276c01920
commit a8916ffd90
9 changed files with 60 additions and 39 deletions

View File

@ -840,6 +840,7 @@ public:
GrPathRendererChain::DrawType drawType = GrPathRendererChain::kColor_DrawType,
GrPathRendererChain::StencilSupport* stencilSupport = NULL);
#if GR_CACHE_STATS
void printCacheStats() const;
#endif

View File

@ -50,10 +50,10 @@
static int g_UploadCount = 0;
#endif
GrAtlas::GrAtlas(GrAtlasMgr* mgr, int plotX, int plotY, GrMaskFormat format) {
GrAtlas::GrAtlas(GrAtlasMgr* mgr, int plotX, int plotY, GrMaskFormat format) :
fDrawToken(NULL, 0) {
fAtlasMgr = mgr; // just a pointer, not an owner
fNext = NULL;
fUsed = false;
fTexture = mgr->getTexture(format); // we're not an owner, just a pointer
fPlot.set(plotX, plotY);
@ -87,7 +87,7 @@ bool GrAtlas::RemoveUnusedAtlases(GrAtlasMgr* atlasMgr, GrAtlas** startAtlas) {
GrAtlas* atlas = *startAtlas;
bool removed = false;
while (NULL != atlas) {
if (!atlas->used()) {
if (atlas->drawToken().isIssued()) {
*atlasRef = atlas->fNext;
atlasMgr->deleteAtlas(atlas);
atlas = *atlasRef;
@ -189,7 +189,7 @@ static GrPixelConfig maskformat2pixelconfig(GrMaskFormat format) {
case kA888_GrMaskFormat:
return kSkia8888_GrPixelConfig;
default:
GrAssert(!"unknown maskformat");
SkASSERT(!"unknown maskformat");
}
return kUnknown_GrPixelConfig;
}
@ -217,8 +217,8 @@ GrAtlas* GrAtlasMgr::addToAtlas(GrAtlas** atlas,
return NULL;
}
GrAssert(0 == kA8_GrMaskFormat);
GrAssert(1 == kA565_GrMaskFormat);
SkASSERT(0 == kA8_GrMaskFormat);
SkASSERT(1 == kA565_GrMaskFormat);
if (NULL == fTexture[format]) {
// TODO: Update this to use the cache rather than directly creating a texture.
GrTextureDesc desc;
@ -247,6 +247,6 @@ GrAtlas* GrAtlasMgr::addToAtlas(GrAtlas** atlas,
}
void GrAtlasMgr::freePlot(GrMaskFormat format, int x, int y) {
GrAssert(fPlotMgr->isBusy(x, y));
SkASSERT(fPlotMgr->isBusy(x, y));
fPlotMgr->freePlot(x, y);
}

View File

@ -13,6 +13,7 @@
#include "GrPoint.h"
#include "GrTexture.h"
#include "GrDrawTarget.h"
class GrGpu;
class GrRectanizer;
@ -36,32 +37,25 @@ public:
}
}
static void MarkAllUnused(GrAtlas* atlas) {
while (NULL != atlas) {
atlas->fUsed = false;
atlas = atlas->fNext;
}
}
static bool RemoveUnusedAtlases(GrAtlasMgr* atlasMgr, GrAtlas** startAtlas);
bool used() const { return fUsed; }
void setUsed(bool used) { fUsed = used; }
GrDrawTarget::DrawToken drawToken() const { return fDrawToken; }
void setDrawToken(GrDrawTarget::DrawToken draw) { fDrawToken = draw; }
private:
GrAtlas(GrAtlasMgr*, int plotX, int plotY, GrMaskFormat format);
~GrAtlas(); // does not try to delete the fNext field
GrAtlas* fNext;
// for recycling
bool fUsed;
GrDrawTarget::DrawToken fDrawToken;
GrTexture* fTexture;
GrRectanizer* fRects;
GrAtlasMgr* fAtlasMgr;
GrIPoint16 fPlot;
GrMaskFormat fMaskFormat;
GrAtlas* fNext;
GrTexture* fTexture;
GrRectanizer* fRects;
GrAtlasMgr* fAtlasMgr;
GrIPoint16 fPlot;
GrMaskFormat fMaskFormat;
friend class GrAtlasMgr;
};

View File

@ -621,6 +621,23 @@ public:
GrDrawTarget* fTarget;
};
///////////////////////////////////////////////////////////////////////////
// Draw execution tracking (for font atlases and other resources)
class DrawToken {
public:
DrawToken(GrDrawTarget* drawTarget, uint32_t drawID) :
fDrawTarget(drawTarget), fDrawID(drawID) {}
bool isIssued() { return NULL != fDrawTarget && fDrawTarget->isIssued(fDrawID); }
private:
GrDrawTarget* fDrawTarget;
uint32_t fDrawID; // this may wrap, but we're doing direct comparison
// so that should be okay
};
virtual DrawToken getCurrentDrawToken() { return DrawToken(this, 0); }
protected:
enum GeometrySrcType {
@ -839,6 +856,9 @@ private:
// but couldn't be made. Otherwise, returns true.
bool setupDstReadIfNecessary(DrawInfo* info);
// Check to see if this set of draw commands has been sent out
virtual bool isIssued(uint32_t drawID) { return true; }
enum {
kPreallocGeoSrcStateStackCnt = 4,
};

View File

@ -27,7 +27,8 @@ GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrGpu* gpu,
, fClipProxyState(kUnknown_ClipProxyState)
, fVertexPool(*vertexPool)
, fIndexPool(*indexPool)
, fFlushing(false) {
, fFlushing(false)
, fDrawID(0) {
fDstGpu->ref();
fCaps.reset(SkRef(fDstGpu->caps()));
@ -536,6 +537,7 @@ void GrInOrderDrawBuffer::flush() {
fDstGpu->setDrawState(prevDrawState);
prevDrawState->unref();
this->reset();
++fDrawID;
}
bool GrInOrderDrawBuffer::onCopySurface(GrSurface* dst,

View File

@ -66,6 +66,9 @@ public:
*/
void flush();
// tracking for draws
virtual DrawToken getCurrentDrawToken() { return DrawToken(this, fDrawID); }
// overrides from GrDrawTarget
virtual bool geometryHints(int* vertexCount,
int* indexCount) const SK_OVERRIDE;
@ -75,7 +78,6 @@ public:
virtual void initCopySurfaceDstDesc(const GrSurface* src, GrTextureDesc* desc) SK_OVERRIDE;
protected:
virtual void clipWillBeSet(const GrClipData* newClip) SK_OVERRIDE;
@ -222,7 +224,10 @@ private:
};
SkSTArray<kGeoPoolStatePreAllocCnt, GeometryPoolState> fGeoPoolStateStack;
virtual bool isIssued(uint32_t drawID) { return drawID != fDrawID; }
bool fFlushing;
uint32_t fDrawID;
typedef GrDrawTarget INHERITED;
};

View File

@ -148,14 +148,15 @@ void GrTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
}
}
GrDrawTarget::DrawToken drawToken = fDrawTarget->getCurrentDrawToken();
if (NULL == glyph->fAtlas) {
if (fStrike->getGlyphAtlas(glyph, scaler)) {
if (fStrike->getGlyphAtlas(glyph, scaler, drawToken)) {
goto HAS_ATLAS;
}
// try to clear out an unused atlas before we flush
fContext->getFontCache()->freeAtlasExceptFor(fStrike);
if (fStrike->getGlyphAtlas(glyph, scaler)) {
if (fStrike->getGlyphAtlas(glyph, scaler, drawToken)) {
goto HAS_ATLAS;
}
@ -165,7 +166,8 @@ void GrTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
// try to purge
fContext->getFontCache()->purgeExceptFor(fStrike);
if (fStrike->getGlyphAtlas(glyph, scaler)) {
// need to use new flush count here
if (fStrike->getGlyphAtlas(glyph, scaler, drawToken)) {
goto HAS_ATLAS;
}

View File

@ -86,9 +86,6 @@ void GrFontCache::purgeExceptFor(GrTextStrike* preserveStrike) {
fCache.removeAt(index, strikeToPurge->fFontScalerKey->getHash());
this->detachStrikeFromList(strikeToPurge);
delete strikeToPurge;
} else {
// for the remaining strikes, we just mark them unused
GrAtlas::MarkAllUnused(strikeToPurge->fAtlas);
}
}
#if FONT_CACHE_STATS
@ -185,7 +182,7 @@ GrTextStrike::GrTextStrike(GrFontCache* cache, const GrKey* key,
static void free_glyph(GrGlyph*& glyph) { glyph->free(); }
static void invalidate_glyph(GrGlyph*& glyph) {
if (glyph->fAtlas && !glyph->fAtlas->used()) {
if (glyph->fAtlas && glyph->fAtlas->drawToken().isIssued()) {
glyph->fAtlas = NULL;
}
}
@ -217,11 +214,10 @@ GrGlyph* GrTextStrike::generateGlyph(GrGlyph::PackedID packed,
bool GrTextStrike::removeUnusedAtlases() {
fCache.getArray().visitAll(invalidate_glyph);
return GrAtlas::RemoveUnusedAtlases(fAtlasMgr, &fAtlas);
return false;
}
bool GrTextStrike::getGlyphAtlas(GrGlyph* glyph, GrFontScaler* scaler) {
bool GrTextStrike::getGlyphAtlas(GrGlyph* glyph, GrFontScaler* scaler,
GrDrawTarget::DrawToken currentDrawToken) {
#if 0 // testing hack to force us to flush our cache often
static int gCounter;
if ((++gCounter % 10) == 0) return false;
@ -231,7 +227,7 @@ bool GrTextStrike::getGlyphAtlas(GrGlyph* glyph, GrFontScaler* scaler) {
GrAssert(scaler);
GrAssert(fCache.contains(glyph));
if (glyph->fAtlas) {
glyph->fAtlas->setUsed(true);
glyph->fAtlas->setDrawToken(currentDrawToken);
return true;
}
@ -256,6 +252,6 @@ bool GrTextStrike::getGlyphAtlas(GrGlyph* glyph, GrFontScaler* scaler) {
}
glyph->fAtlas = atlas;
atlas->setUsed(true);
atlas->setDrawToken(currentDrawToken);
return true;
}

View File

@ -16,6 +16,7 @@
#include "GrTHashCache.h"
#include "GrPoint.h"
#include "GrGlyph.h"
#include "GrDrawTarget.h"
class GrAtlasMgr;
class GrFontCache;
@ -37,7 +38,7 @@ public:
GrMaskFormat getMaskFormat() const { return fMaskFormat; }
inline GrGlyph* getGlyph(GrGlyph::PackedID, GrFontScaler*);
bool getGlyphAtlas(GrGlyph*, GrFontScaler*);
bool getGlyphAtlas(GrGlyph*, GrFontScaler*, GrDrawTarget::DrawToken currentDrawToken);
// testing
int countGlyphs() const { return fCache.getArray().count(); }