Chromium Code Reviews| 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; |
| } |