aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrTextStrike.cpp
diff options
context:
space:
mode:
authorGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-08-05 19:42:56 +0000
committerGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-08-05 19:42:56 +0000
commit67ed64e9aa70f5a95a2d309f9b73dc0009f3ed8c (patch)
tree8bad3381e82994c9ee43798c6d2c5c7986262f72 /src/gpu/GrTextStrike.cpp
parent9b6a185e36f3145aa53732e8fb30c870ff38a93c (diff)
GPU Font Cache improvements:
- If a strike has multiple atlases, check all for room for a new glyph - Mark remaining atlases unused after a purge, then check for an unused atlas before purging (reduces TextContext flushes and ghosting) - Hide Atlas management a little better inside AtlasMgr R=robertphillips@google.com, bsalomon@google.com Author: jvanverth@google.com Review URL: https://chromiumcodereview.appspot.com/21594005 git-svn-id: http://skia.googlecode.com/svn/trunk@10544 2bbb7eff-a529-9590-31e7-b0007b416f81
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;
}