Index: src/gpu/GrTextStrike.cpp |
diff --git a/src/gpu/GrTextStrike.cpp b/src/gpu/GrTextStrike.cpp |
index 071c5d272486eadc77a36200e337e6bc15e19088..c1ee5b40c638f06e45492d63df3116584e098507 100644 |
--- a/src/gpu/GrTextStrike.cpp |
+++ b/src/gpu/GrTextStrike.cpp |
@@ -62,19 +62,48 @@ 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; |
- // 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 (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 |
+ strikeToPurge->markAtlasesUnused(); |
+ } |
+ } |
+} |
+ |
+void GrFontCache::freeAtlasExceptFor(GrTextStrike* preserveStrike) { |
+ GrTextStrike* strike = fTail; |
+ while (strike) { |
+ if (strike == preserveStrike) { |
+ strike = strike->fPrev; |
+ continue; |
+ } |
+ GrTextStrike* strikeToPurge = strike; |
+ strike = strikeToPurge->fPrev; |
+ if (strikeToPurge->removeUnusedAtlas()) { |
+ if (NULL == strikeToPurge->fAtlas) { |
+ int index = fCache.slowFindIndex(strikeToPurge); |
+ GrAssert(index >= 0); |
+ fCache.removeAt(index, strikeToPurge->fFontScalerKey->getHash()); |
+ this->detachStrikeFromList(strikeToPurge); |
+ delete strikeToPurge; |
+ } |
+ break; |
+ } |
} |
} |
@@ -142,6 +171,12 @@ GrTextStrike::GrTextStrike(GrFontCache* cache, const GrKey* key, |
static void FreeGlyph(GrGlyph*& glyph) { glyph->free(); } |
robertphillips
2013/08/02 15:23:50
invalidate_glyph?
GrGlyph*?
bsalomon
2013/08/02 15:30:35
ref to a ptr feels weird to me. We aren't assignin
jvanverth1
2013/08/02 21:49:27
The ref is needed because this function is used in
bsalomon
2013/08/05 13:09:54
Gotcha, maybe a comment // this is used with SkTDA
|
+static void InvalidateGlyph(GrGlyph*& glyph) { |
+ if (glyph->fAtlas && !glyph->fAtlas->fUsed) { |
+ glyph->fAtlas = NULL; |
+ } |
+} |
+ |
GrTextStrike::~GrTextStrike() { |
GrAtlas::FreeLList(fAtlas); |
fFontScalerKey->unref(); |
@@ -166,6 +201,34 @@ GrGlyph* GrTextStrike::generateGlyph(GrGlyph::PackedID packed, |
return glyph; |
} |
+bool GrTextStrike::removeUnusedAtlas() { |
robertphillips
2013/08/02 15:23:50
Why is prev a GrAtlas**?
jvanverth1
2013/08/02 21:49:27
Moved to GrAtlas.cpp, but that's done so I don't h
|
+ GrAtlas** prev = &fAtlas; |
+ GrAtlas* atlas = fAtlas; |
+ while (atlas) { |
+ if (!atlas->fUsed) { |
+ fCache.getArray().visitAll(InvalidateGlyph); |
+ *prev = atlas->fNext; |
+ fAtlasMgr->deleteAtlas(atlas); |
+ atlas = *prev; |
+ return true; |
+ } else { |
+ prev = &atlas->fNext; |
+ atlas = atlas->fNext; |
+ } |
+ } |
+ |
+ return false; |
+} |
+ |
+void GrTextStrike::markAtlasesUnused() { |
+ GrAtlas* atlas = fAtlas; |
robertphillips
2013/08/02 15:23:50
NULL !=?
jvanverth1
2013/08/02 21:49:27
Done.
|
+ while (atlas) { |
+ atlas->fUsed = false; |
+ atlas = atlas->fNext; |
+ } |
+} |
+ |
+ |
bool GrTextStrike::getGlyphAtlas(GrGlyph* glyph, GrFontScaler* scaler) { |
#if 0 // testing hack to force us to flush our cache often |
static int gCounter; |
@@ -176,6 +239,7 @@ bool GrTextStrike::getGlyphAtlas(GrGlyph* glyph, GrFontScaler* scaler) { |
GrAssert(scaler); |
GrAssert(fCache.contains(glyph)); |
if (glyph->fAtlas) { |
+ glyph->fAtlas->fUsed = true; |
return true; |
} |
@@ -191,7 +255,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 +263,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->fUsed = true; |
return true; |
} |