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
diff --git a/src/gpu/GrAtlas.cpp b/src/gpu/GrAtlas.cpp
index f2daca1..5207061 100644
--- a/src/gpu/GrAtlas.cpp
+++ b/src/gpu/GrAtlas.cpp
@@ -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 @@
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 @@
case kA888_GrMaskFormat:
return kSkia8888_GrPixelConfig;
default:
- GrAssert(!"unknown maskformat");
+ SkASSERT(!"unknown maskformat");
}
return kUnknown_GrPixelConfig;
}
@@ -217,8 +217,8 @@
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 @@
}
void GrAtlasMgr::freePlot(GrMaskFormat format, int x, int y) {
- GrAssert(fPlotMgr->isBusy(x, y));
+ SkASSERT(fPlotMgr->isBusy(x, y));
fPlotMgr->freePlot(x, y);
}
diff --git a/src/gpu/GrAtlas.h b/src/gpu/GrAtlas.h
index b6f25c2..7831a8d 100644
--- a/src/gpu/GrAtlas.h
+++ b/src/gpu/GrAtlas.h
@@ -13,6 +13,7 @@
#include "GrPoint.h"
#include "GrTexture.h"
+#include "GrDrawTarget.h"
class GrGpu;
class GrRectanizer;
@@ -36,32 +37,25 @@
}
}
- 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;
};
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h
index 0c2b568..9501d96 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrDrawTarget.h
@@ -621,6 +621,23 @@
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 @@
// 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,
};
diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp
index 3ec9596..9e0d213 100644
--- a/src/gpu/GrInOrderDrawBuffer.cpp
+++ b/src/gpu/GrInOrderDrawBuffer.cpp
@@ -27,7 +27,8 @@
, fClipProxyState(kUnknown_ClipProxyState)
, fVertexPool(*vertexPool)
, fIndexPool(*indexPool)
- , fFlushing(false) {
+ , fFlushing(false)
+ , fDrawID(0) {
fDstGpu->ref();
fCaps.reset(SkRef(fDstGpu->caps()));
@@ -536,6 +537,7 @@
fDstGpu->setDrawState(prevDrawState);
prevDrawState->unref();
this->reset();
+ ++fDrawID;
}
bool GrInOrderDrawBuffer::onCopySurface(GrSurface* dst,
diff --git a/src/gpu/GrInOrderDrawBuffer.h b/src/gpu/GrInOrderDrawBuffer.h
index 6512dcc..ba5e790 100644
--- a/src/gpu/GrInOrderDrawBuffer.h
+++ b/src/gpu/GrInOrderDrawBuffer.h
@@ -66,6 +66,9 @@
*/
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 @@
virtual void initCopySurfaceDstDesc(const GrSurface* src, GrTextureDesc* desc) SK_OVERRIDE;
-
protected:
virtual void clipWillBeSet(const GrClipData* newClip) SK_OVERRIDE;
@@ -222,7 +224,10 @@
};
SkSTArray<kGeoPoolStatePreAllocCnt, GeometryPoolState> fGeoPoolStateStack;
+ virtual bool isIssued(uint32_t drawID) { return drawID != fDrawID; }
+
bool fFlushing;
+ uint32_t fDrawID;
typedef GrDrawTarget INHERITED;
};
diff --git a/src/gpu/GrTextContext.cpp b/src/gpu/GrTextContext.cpp
index 8f0f1cf..f4a3df6 100644
--- a/src/gpu/GrTextContext.cpp
+++ b/src/gpu/GrTextContext.cpp
@@ -148,14 +148,15 @@
}
}
+ 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 @@
// 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;
}
diff --git a/src/gpu/GrTextStrike.cpp b/src/gpu/GrTextStrike.cpp
index 9373351..1fe83c9 100644
--- a/src/gpu/GrTextStrike.cpp
+++ b/src/gpu/GrTextStrike.cpp
@@ -86,9 +86,6 @@
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 @@
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 @@
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 @@
GrAssert(scaler);
GrAssert(fCache.contains(glyph));
if (glyph->fAtlas) {
- glyph->fAtlas->setUsed(true);
+ glyph->fAtlas->setDrawToken(currentDrawToken);
return true;
}
@@ -256,6 +252,6 @@
}
glyph->fAtlas = atlas;
- atlas->setUsed(true);
+ atlas->setDrawToken(currentDrawToken);
return true;
}
diff --git a/src/gpu/GrTextStrike.h b/src/gpu/GrTextStrike.h
index e359e26..64c4b90 100644
--- a/src/gpu/GrTextStrike.h
+++ b/src/gpu/GrTextStrike.h
@@ -16,6 +16,7 @@
#include "GrTHashCache.h"
#include "GrPoint.h"
#include "GrGlyph.h"
+#include "GrDrawTarget.h"
class GrAtlasMgr;
class GrFontCache;
@@ -37,7 +38,7 @@
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(); }