aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrTextStrike.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpu/GrTextStrike.cpp')
-rw-r--r--src/gpu/GrTextStrike.cpp80
1 files changed, 68 insertions, 12 deletions
diff --git a/src/gpu/GrTextStrike.cpp b/src/gpu/GrTextStrike.cpp
index 071c5d2724..9373351f22 100644
--- a/src/gpu/GrTextStrike.cpp
+++ b/src/gpu/GrTextStrike.cpp
@@ -16,6 +16,11 @@ SK_DEFINE_INST_COUNT(GrKey)
///////////////////////////////////////////////////////////////////////////////
+#define FONT_CACHE_STATS 0
+#if FONT_CACHE_STATS
+static int g_PurgeCount = 0;
+#endif
+
GrFontCache::GrFontCache(GrGpu* gpu) : fGpu(gpu) {
gpu->ref();
fAtlasMgr = NULL;
@@ -27,6 +32,9 @@ GrFontCache::~GrFontCache() {
fCache.deleteAll();
delete fAtlasMgr;
fGpu->unref();
+#if FONT_CACHE_STATS
+ GrPrintf("Num purges: %d\n", g_PurgeCount);
+#endif
}
GrTextStrike* GrFontCache::generateStrike(GrFontScaler* scaler,
@@ -62,19 +70,51 @@ void GrFontCache::freeAll() {
void GrFontCache::purgeExceptFor(GrTextStrike* preserveStrike) {
GrTextStrike* strike = fTail;
+ bool purge = true;
+ while (strike) {
+ if (strike == preserveStrike) {
+ strike = strike->fPrev;
+ continue;
+ }
+ GrTextStrike* strikeToPurge = strike;
+ strike = strikeToPurge->fPrev;
+ if (purge) {
+ // keep purging if we won't free up any atlases with this strike.
+ purge = (NULL == strikeToPurge->fAtlas);
+ int index = fCache.slowFindIndex(strikeToPurge);
+ GrAssert(index >= 0);
+ 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
+ ++g_PurgeCount;
+#endif
+}
+
+void GrFontCache::freeAtlasExceptFor(GrTextStrike* preserveStrike) {
+ GrTextStrike* strike = fTail;
while (strike) {
if (strike == preserveStrike) {
strike = strike->fPrev;
continue;
}
GrTextStrike* strikeToPurge = strike;
- // keep going if we won't free up any atlases with this strike.
- strike = (NULL == strikeToPurge->fAtlas) ? strikeToPurge->fPrev : NULL;
- int index = fCache.slowFindIndex(strikeToPurge);
- GrAssert(index >= 0);
- fCache.removeAt(index, strikeToPurge->fFontScalerKey->getHash());
- this->detachStrikeFromList(strikeToPurge);
- delete strikeToPurge;
+ strike = strikeToPurge->fPrev;
+ if (strikeToPurge->removeUnusedAtlases()) {
+ if (NULL == strikeToPurge->fAtlas) {
+ int index = fCache.slowFindIndex(strikeToPurge);
+ GrAssert(index >= 0);
+ fCache.removeAt(index, strikeToPurge->fFontScalerKey->getHash());
+ this->detachStrikeFromList(strikeToPurge);
+ delete strikeToPurge;
+ }
+ break;
+ }
}
}
@@ -140,12 +180,20 @@ GrTextStrike::GrTextStrike(GrFontCache* cache, const GrKey* key,
#endif
}
-static void FreeGlyph(GrGlyph*& glyph) { glyph->free(); }
+// these signatures are needed because they're used with
+// SkTDArray::visitAll() (see destructor & removeUnusedAtlases())
+static void free_glyph(GrGlyph*& glyph) { glyph->free(); }
+
+static void invalidate_glyph(GrGlyph*& glyph) {
+ if (glyph->fAtlas && !glyph->fAtlas->used()) {
+ glyph->fAtlas = NULL;
+ }
+}
GrTextStrike::~GrTextStrike() {
GrAtlas::FreeLList(fAtlas);
fFontScalerKey->unref();
- fCache.getArray().visitAll(FreeGlyph);
+ fCache.getArray().visitAll(free_glyph);
#if GR_DEBUG
gCounter -= 1;
@@ -166,6 +214,13 @@ GrGlyph* GrTextStrike::generateGlyph(GrGlyph::PackedID packed,
return glyph;
}
+bool GrTextStrike::removeUnusedAtlases() {
+ fCache.getArray().visitAll(invalidate_glyph);
+ return GrAtlas::RemoveUnusedAtlases(fAtlasMgr, &fAtlas);
+
+ return false;
+}
+
bool GrTextStrike::getGlyphAtlas(GrGlyph* glyph, GrFontScaler* scaler) {
#if 0 // testing hack to force us to flush our cache often
static int gCounter;
@@ -176,6 +231,7 @@ bool GrTextStrike::getGlyphAtlas(GrGlyph* glyph, GrFontScaler* scaler) {
GrAssert(scaler);
GrAssert(fCache.contains(glyph));
if (glyph->fAtlas) {
+ glyph->fAtlas->setUsed(true);
return true;
}
@@ -191,7 +247,7 @@ bool GrTextStrike::getGlyphAtlas(GrGlyph* glyph, GrFontScaler* scaler) {
return false;
}
- GrAtlas* atlas = fAtlasMgr->addToAtlas(fAtlas, glyph->width(),
+ GrAtlas* atlas = fAtlasMgr->addToAtlas(&fAtlas, glyph->width(),
glyph->height(), storage.get(),
fMaskFormat,
&glyph->fAtlasLocation);
@@ -199,7 +255,7 @@ bool GrTextStrike::getGlyphAtlas(GrGlyph* glyph, GrFontScaler* scaler) {
return false;
}
- // update fAtlas as well, since they may be chained in a linklist
- glyph->fAtlas = fAtlas = atlas;
+ glyph->fAtlas = atlas;
+ atlas->setUsed(true);
return true;
}