GrAtlas cleanup: Split out GrPlot and GrAtlas

This breaks up GrAtlas into the head of the list (GrAtlas) and the list elements (GrPlot). It also moves all of the GrPlot management code into GrAtlasMgr. It adds a simple pool allocator for GrPlots and removes use of GrPlotMgr.

R=bsalomon@google.com, robertphillips@google.com

Author: jvanverth@google.com

Review URL: https://codereview.chromium.org/24981004

git-svn-id: http://skia.googlecode.com/svn/trunk/src@11508 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/GrAtlas.cpp b/gpu/GrAtlas.cpp
index b3340a0..e33ec65 100644
--- a/gpu/GrAtlas.cpp
+++ b/gpu/GrAtlas.cpp
@@ -6,13 +6,10 @@
  * found in the LICENSE file.
  */
 
-
-
 #include "GrAtlas.h"
 #include "GrContext.h"
 #include "GrGpu.h"
 #include "GrRectanizer.h"
-#include "GrPlotMgr.h"
 
 #if 0
 #define GR_PLOT_WIDTH   8
@@ -50,70 +47,34 @@
 static int g_UploadCount = 0;
 #endif
 
-GrAtlas::GrAtlas(GrAtlasMgr* mgr, int plotX, int plotY, int bpp) :
-                 fDrawToken(NULL, 0) {
-    fAtlasMgr = mgr;    // just a pointer, not an owner
-    fNext = NULL;
-
-    fTexture = mgr->getTexture(); // we're not an owner, just a pointer
-    fPlot.set(plotX, plotY);
-
+GrPlot::GrPlot() : fDrawToken(NULL, 0)
+                 , fNext(NULL)
+                 , fTexture(NULL)
+                 , fAtlasMgr(NULL)
+                 , fBytesPerPixel(1)
+{
     fRects = GrRectanizer::Factory(GR_ATLAS_WIDTH - BORDER,
                                    GR_ATLAS_HEIGHT - BORDER);
-
-    fBytesPerPixel = bpp;
-
-#ifdef SK_DEBUG
-//    GrPrintf(" GrAtlas %p [%d %d] %d\n", this, plotX, plotY, gCounter);
-    gCounter += 1;
-#endif
+    fOffset.set(0, 0);
 }
 
-GrAtlas::~GrAtlas() {
-    fAtlasMgr->freePlot(fPlot.fX, fPlot.fY);
-
+GrPlot::~GrPlot() {
     delete fRects;
-
-#ifdef SK_DEBUG
-    --gCounter;
-//    GrPrintf("~GrAtlas %p [%d %d] %d\n", this, fPlot.fX, fPlot.fY, gCounter);
-#endif
 }
 
-bool GrAtlas::RemoveUnusedAtlases(GrAtlasMgr* atlasMgr, GrAtlas** startAtlas) {
-    // GrAtlas** is used so that a pointer to the head element can be passed in and
-    // modified when the first element is deleted
-    GrAtlas** atlasRef = startAtlas;
-    GrAtlas* atlas = *startAtlas;
-    bool removed = false;
-    while (NULL != atlas) {
-        if (atlas->drawToken().isIssued()) {
-            *atlasRef = atlas->fNext;
-            atlasMgr->deleteAtlas(atlas);
-            atlas = *atlasRef;
-            removed = true;
-        } else {
-            atlasRef = &atlas->fNext;
-            atlas = atlas->fNext;
-        }
-    }
-
-    return removed;
+static void adjust_for_offset(GrIPoint16* loc, const GrIPoint16& offset) {
+    loc->fX += offset.fX * GR_ATLAS_WIDTH;
+    loc->fY += offset.fY * GR_ATLAS_HEIGHT;
 }
 
-static void adjustForPlot(GrIPoint16* loc, const GrIPoint16& plot) {
-    loc->fX += plot.fX * GR_ATLAS_WIDTH;
-    loc->fY += plot.fY * GR_ATLAS_HEIGHT;
-}
-
-static uint8_t* zerofill(uint8_t* ptr, int count) {
+static uint8_t* zero_fill(uint8_t* ptr, int count) {
     while (--count >= 0) {
         *ptr++ = 0;
     }
     return ptr;
 }
 
-bool GrAtlas::addSubImage(int width, int height, const void* image,
+bool GrPlot::addSubImage(int width, int height, const void* image,
                           GrIPoint16* loc) {
     if (!fRects->addRect(width + BORDER, height + BORDER, loc)) {
         return false;
@@ -128,16 +89,16 @@
         sk_bzero(dst, dstRB);                // zero top row
         dst += dstRB;
         for (int y = 0; y < height; y++) {
-            dst = zerofill(dst, fBytesPerPixel);   // zero left edge
+            dst = zero_fill(dst, fBytesPerPixel);   // zero left edge
             memcpy(dst, image, width * fBytesPerPixel);
             dst += width * fBytesPerPixel;
-            dst = zerofill(dst, fBytesPerPixel);   // zero right edge
+            dst = zero_fill(dst, fBytesPerPixel);   // zero right edge
             image = (const void*)((const char*)image + width * fBytesPerPixel);
         }
         sk_bzero(dst, dstRB);                // zero bottom row
         image = storage.get();
     }
-    adjustForPlot(loc, fPlot);
+    adjust_for_offset(loc, fOffset);
     GrContext* context = fTexture->getContext();
     // We pass the flag that does not force a flush. We assume our caller is
     // smart and hasn't referenced the part of the texture we're about to update
@@ -165,12 +126,30 @@
     fPixelConfig = config;
     gpu->ref();
     fTexture = NULL;
-    fPlotMgr = SkNEW_ARGS(GrPlotMgr, (GR_PLOT_WIDTH, GR_PLOT_HEIGHT));
+    
+    // set up allocated plots
+    int bpp = GrBytesPerPixel(fPixelConfig);
+    fPlots = SkNEW_ARRAY(GrPlot, (GR_PLOT_WIDTH*GR_PLOT_HEIGHT));
+    fFreePlots = NULL;
+    GrPlot* currPlot = fPlots;
+    for (int y = GR_PLOT_HEIGHT-1; y >= 0; --y) {
+        for (int x = GR_PLOT_WIDTH-1; x >= 0; --x) {
+            currPlot->fAtlasMgr = this;
+            currPlot->fOffset.set(x, y);
+            currPlot->fBytesPerPixel = bpp;
+            
+            // add to free list
+            currPlot->fNext = fFreePlots;
+            fFreePlots = currPlot;
+            
+            ++currPlot;
+        }
+    }
 }
 
 GrAtlasMgr::~GrAtlasMgr() {
     SkSafeUnref(fTexture);
-    delete fPlotMgr;
+    SkDELETE_ARRAY(fPlots);
 
     fGpu->unref();
 #if FONT_CACHE_STATS
@@ -178,23 +157,22 @@
 #endif
 }
 
-GrAtlas* GrAtlasMgr::addToAtlas(GrAtlas** atlas,
-                                int width, int height, const void* image,
-                                GrIPoint16* loc) {
-    // iterate through entire atlas list, see if we can find a hole
-    GrAtlas* atlasIter = *atlas;
-    while (atlasIter) {
-        if (atlasIter->addSubImage(width, height, image, loc)) {
-            return atlasIter;
+GrPlot* GrAtlasMgr::addToAtlas(GrAtlas* atlas,
+                               int width, int height, const void* image,
+                               GrIPoint16* loc) {
+    // iterate through entire plot list, see if we can find a hole
+    GrPlot* plotIter = atlas->fPlots;
+    while (plotIter) {
+        if (plotIter->addSubImage(width, height, image, loc)) {
+            return plotIter;
         }
-        atlasIter = atlasIter->fNext;
+        plotIter = plotIter->fNext;
     }
 
-    // If the above fails, then either we have no starting atlas, or the current
-    // atlas list is full. Either way we need to allocate a new atlas
-
-    GrIPoint16 plot;
-    if (!fPlotMgr->newPlot(&plot)) {
+    // If the above fails, then either we have no starting plot, or the current
+    // plot list is full. Either way we need to allocate a new plot
+    GrPlot* newPlot = this->allocPlot();
+    if (NULL == newPlot) {
         return NULL;
     }
 
@@ -211,22 +189,74 @@
             return NULL;
         }
     }
-
-    int bpp = GrBytesPerPixel(fPixelConfig);
-    GrAtlas* newAtlas = SkNEW_ARGS(GrAtlas, (this, plot.fX, plot.fY, bpp));
-    if (!newAtlas->addSubImage(width, height, image, loc)) {
-        delete newAtlas;
+    // be sure to set texture for fast lookup 
+    newPlot->fTexture = fTexture;
+    
+    if (!newPlot->addSubImage(width, height, image, loc)) {
+        this->freePlot(newPlot);
         return NULL;
     }
 
-    // new atlas, put at head
-    newAtlas->fNext = *atlas;
-    *atlas = newAtlas;
+    // new plot, put at head
+    newPlot->fNext = atlas->fPlots;
+    atlas->fPlots = newPlot;
 
-    return newAtlas;
+    return newPlot;
 }
 
-void GrAtlasMgr::freePlot(int x, int y) {
-    SkASSERT(fPlotMgr->isBusy(x, y));
-    fPlotMgr->freePlot(x, y);
+bool GrAtlasMgr::removeUnusedPlots(GrAtlas* atlas) {
+    // GrPlot** is used so that the head element can be easily
+    // modified when the first element is deleted
+    GrPlot** plotRef = &atlas->fPlots;
+    GrPlot* plot = atlas->fPlots;
+    bool removed = false;
+    while (NULL != plot) {
+        if (plot->drawToken().isIssued()) {
+            *plotRef = plot->fNext;
+            this->freePlot(plot);
+            plot = *plotRef;
+            removed = true;
+        } else {
+            plotRef = &plot->fNext;
+            plot = plot->fNext;
+        }
+    }
+    
+    return removed;
+}
+
+void GrAtlasMgr::deletePlotList(GrPlot* plot) {
+    while (NULL != plot) {
+        GrPlot* next = plot->fNext;
+        this->freePlot(plot);
+        plot = next;
+    }
+}
+
+GrPlot* GrAtlasMgr::allocPlot() {
+    if (NULL == fFreePlots) {
+        return NULL;
+    } else {
+        GrPlot* alloc = fFreePlots;
+        fFreePlots = alloc->fNext;
+#ifdef SK_DEBUG
+//        GrPrintf(" GrPlot %p [%d %d] %d\n", this, alloc->fOffset.fX, alloc->fOffset.fY, gCounter);
+        gCounter += 1;
+#endif
+        return alloc;
+    }
+    
+}
+
+void GrAtlasMgr::freePlot(GrPlot* plot) {
+    SkASSERT(this == plot->fAtlasMgr);
+    
+    plot->fRects->reset();
+    plot->fNext = fFreePlots;
+    fFreePlots = plot;
+    
+#ifdef SK_DEBUG
+    --gCounter;
+//    GrPrintf("~GrPlot %p [%d %d] %d\n", this, plot->fOffset.fX, plot->fOffset.fY, gCounter);
+#endif
 }
diff --git a/gpu/GrAtlas.h b/gpu/GrAtlas.h
index b2acaee..d06bba1 100644
--- a/gpu/GrAtlas.h
+++ b/gpu/GrAtlas.h
@@ -6,11 +6,10 @@
  * found in the LICENSE file.
  */
 
-
-
 #ifndef GrAtlas_DEFINED
 #define GrAtlas_DEFINED
 
+
 #include "GrPoint.h"
 #include "GrTexture.h"
 #include "GrDrawTarget.h"
@@ -18,69 +17,93 @@
 class GrGpu;
 class GrRectanizer;
 class GrAtlasMgr;
+class GrAtlas;
 
-class GrAtlas {
+// The backing GrTexture for a set of GrAtlases is broken into a spatial grid of GrPlots. When
+// a GrAtlas needs space on the texture, it requests a GrPlot. Each GrAtlas can claim one
+// or more GrPlots. The GrPlots keep track of subimage placement via their GrRectanizer. Once a
+// GrPlot is "full" (i.e. there is no room for the new subimage according to the GrRectanizer), the
+// GrAtlas can request a new GrPlot via GrAtlasMgr::addToAtlas().
+//
+// If all GrPlots are allocated, the replacement strategy is up to the client. The drawToken is
+// available to ensure that all draw calls are finished for that particular GrPlot.
+// GrAtlasMgr::removeUnusedPlots() will free up any finished plots for a given GrAtlas.
+
+class GrPlot {
 public:
-    int getPlotX() const { return fPlot.fX; }
-    int getPlotY() const { return fPlot.fY; }
+    int getOffsetX() const { return fOffset.fX; }
+    int getOffsetY() const { return fOffset.fY; }
 
     GrTexture* texture() const { return fTexture; }
 
     bool addSubImage(int width, int height, const void*, GrIPoint16*);
 
-    static void FreeLList(GrAtlas* atlas) {
-        while (NULL != atlas) {
-            GrAtlas* next = atlas->fNext;
-            delete atlas;
-            atlas = next;
-        }
-    }
-
-    static bool RemoveUnusedAtlases(GrAtlasMgr* atlasMgr, GrAtlas** startAtlas);
-
     GrDrawTarget::DrawToken drawToken() const { return fDrawToken; }
     void setDrawToken(GrDrawTarget::DrawToken draw) { fDrawToken = draw; }
 
 private:
-    GrAtlas(GrAtlasMgr*, int plotX, int plotY, int bpp);
-    ~GrAtlas(); // does not try to delete the fNext field
+    GrPlot();
+    ~GrPlot(); // does not try to delete the fNext field
 
     // for recycling
     GrDrawTarget::DrawToken fDrawToken;
 
-    GrAtlas*                fNext;
+    GrPlot*                 fNext;
 
     GrTexture*              fTexture;
     GrRectanizer*           fRects;
     GrAtlasMgr*             fAtlasMgr;
-    GrIPoint16              fPlot;
+    GrIPoint16              fOffset;
     int                     fBytesPerPixel;
 
     friend class GrAtlasMgr;
 };
 
-class GrPlotMgr;
-
 class GrAtlasMgr {
 public:
     GrAtlasMgr(GrGpu*, GrPixelConfig);
     ~GrAtlasMgr();
 
-    GrAtlas* addToAtlas(GrAtlas**, int width, int height, const void*, GrIPoint16*);
-    void deleteAtlas(GrAtlas* atlas) { delete atlas; }
-
+    // add subimage of width, height dimensions to atlas
+    // returns the containing GrPlot and location relative to the backing texture
+    GrPlot* addToAtlas(GrAtlas*, int width, int height, const void*, GrIPoint16*);
+    
+    // free up any plots that are not waiting on a draw call
+    bool removeUnusedPlots(GrAtlas* atlas);
+    
+    // to be called by ~GrAtlas()
+    void deletePlotList(GrPlot* plot);
+    
     GrTexture* getTexture() const {
         return fTexture;
     }
 
-    // to be called by ~GrAtlas()
-    void freePlot(int x, int y);
-
 private:
+    GrPlot* allocPlot();
+    void freePlot(GrPlot* plot);
+    
     GrGpu*        fGpu;
     GrPixelConfig fPixelConfig;
     GrTexture*    fTexture;
-    GrPlotMgr*    fPlotMgr;
+    
+    // allocated array of GrPlots
+    GrPlot*       fPlots;
+    // linked list of free GrPlots
+    GrPlot*       fFreePlots;
+};
+
+class GrAtlas {
+public:
+    GrAtlas(GrAtlasMgr* mgr) : fPlots(NULL), fAtlasMgr(mgr) { }
+    ~GrAtlas() { fAtlasMgr->deletePlotList(fPlots); }
+    
+    bool isEmpty() { return NULL == fPlots; }
+    
+private:
+    GrPlot*     fPlots;
+    GrAtlasMgr* fAtlasMgr;
+    
+    friend class GrAtlasMgr;
 };
 
 #endif
diff --git a/gpu/GrRectanizer.cpp b/gpu/GrRectanizer.cpp
index 7b49530..418bf19 100644
--- a/gpu/GrRectanizer.cpp
+++ b/gpu/GrRectanizer.cpp
@@ -24,6 +24,12 @@
     virtual ~GrRectanizerPow2() {
     }
 
+    virtual void reset() {
+        fNextStripY = 0;
+        fAreaSoFar = 0;
+        sk_bzero(fRows, sizeof(fRows));        
+    }
+
     virtual bool addRect(int w, int h, GrIPoint16* loc);
 
     virtual float percentFull() const {
diff --git a/gpu/GrRectanizer.h b/gpu/GrRectanizer.h
index dc479f1..c1ac2c1 100644
--- a/gpu/GrRectanizer.h
+++ b/gpu/GrRectanizer.h
@@ -26,6 +26,8 @@
 
     virtual ~GrRectanizer() {}
 
+    virtual void reset() = 0;
+
     int width() const { return fWidth; }
     int height() const { return fHeight; }
 
diff --git a/gpu/GrTextContext.cpp b/gpu/GrTextContext.cpp
index e4303c1..b050305 100644
--- a/gpu/GrTextContext.cpp
+++ b/gpu/GrTextContext.cpp
@@ -139,7 +139,7 @@
     GrFixed height = glyph->fBounds.height();
 
     // check if we clipped out
-    if (true || NULL == glyph->fAtlas) {
+    if (true || NULL == glyph->fPlot) {
         int x = vx >> 16;
         int y = vy >> 16;
         if (fClipRect.quickReject(x, y, x + width, y + height)) {
@@ -149,13 +149,13 @@
     }
 
     GrDrawTarget::DrawToken drawToken = fDrawTarget->getCurrentDrawToken();
-    if (NULL == glyph->fAtlas) {
+    if (NULL == glyph->fPlot) {
         if (fStrike->getGlyphAtlas(glyph, scaler, drawToken)) {
             goto HAS_ATLAS;
         }
 
-        // try to clear out an unused atlas before we flush
-        fContext->getFontCache()->freeAtlasExceptFor(fStrike);
+        // try to clear out an unused plot before we flush
+        fContext->getFontCache()->freePlotExceptFor(fStrike);
         if (fStrike->getGlyphAtlas(glyph, scaler, drawToken)) {
             goto HAS_ATLAS;
         }
@@ -193,13 +193,13 @@
     }
 
 HAS_ATLAS:
-    SkASSERT(glyph->fAtlas);
+    SkASSERT(glyph->fPlot);
 
     // now promote them to fixed (TODO: Rethink using fixed pt).
     width = SkIntToFixed(width);
     height = SkIntToFixed(height);
 
-    GrTexture* texture = glyph->fAtlas->texture();
+    GrTexture* texture = glyph->fPlot->texture();
     SkASSERT(texture);
 
     if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) {
diff --git a/gpu/GrTextStrike.cpp b/gpu/GrTextStrike.cpp
index d1f1861..e399c91 100644
--- a/gpu/GrTextStrike.cpp
+++ b/gpu/GrTextStrike.cpp
@@ -103,7 +103,7 @@
         strike = strikeToPurge->fPrev;
         if (purge) {
             // keep purging if we won't free up any atlases with this strike.
-            purge = (NULL == strikeToPurge->fAtlas);
+            purge = strikeToPurge->fAtlas.isEmpty();
             int index = fCache.slowFindIndex(strikeToPurge);
             SkASSERT(index >= 0);
             fCache.removeAt(index, strikeToPurge->fFontScalerKey->getHash());
@@ -116,7 +116,7 @@
 #endif
 }
 
-void GrFontCache::freeAtlasExceptFor(GrTextStrike* preserveStrike) {
+void GrFontCache::freePlotExceptFor(GrTextStrike* preserveStrike) {
     SkASSERT(NULL != preserveStrike);
     GrTextStrike* strike = fTail;
     GrMaskFormat maskFormat = preserveStrike->fMaskFormat;
@@ -127,8 +127,8 @@
         }
         GrTextStrike* strikeToPurge = strike;
         strike = strikeToPurge->fPrev;
-        if (strikeToPurge->removeUnusedAtlases()) {
-            if (NULL == strikeToPurge->fAtlas) {
+        if (strikeToPurge->removeUnusedPlots()) {
+            if (strikeToPurge->fAtlas.isEmpty()) {
                 int index = fCache.slowFindIndex(strikeToPurge);
                 SkASSERT(index >= 0);
                 fCache.removeAt(index, strikeToPurge->fFontScalerKey->getHash());
@@ -186,13 +186,12 @@
 
 GrTextStrike::GrTextStrike(GrFontCache* cache, const GrKey* key,
                            GrMaskFormat format,
-                           GrAtlasMgr* atlasMgr) : fPool(64) {
+                           GrAtlasMgr* atlasMgr) : fPool(64), fAtlas(atlasMgr) {
     fFontScalerKey = key;
     fFontScalerKey->ref();
 
     fFontCache = cache;     // no need to ref, it won't go away before we do
     fAtlasMgr = atlasMgr;   // no need to ref, it won't go away before we do
-    fAtlas = NULL;
 
     fMaskFormat = format;
 
@@ -207,13 +206,12 @@
 static void free_glyph(GrGlyph*& glyph) { glyph->free(); }
 
 static void invalidate_glyph(GrGlyph*& glyph) {
-    if (glyph->fAtlas && glyph->fAtlas->drawToken().isIssued()) {
-        glyph->fAtlas = NULL;
+    if (glyph->fPlot && glyph->fPlot->drawToken().isIssued()) {
+        glyph->fPlot = NULL;
     }
 }
 
 GrTextStrike::~GrTextStrike() {
-    GrAtlas::FreeLList(fAtlas);
     fFontScalerKey->unref();
     fCache.getArray().visitAll(free_glyph);
 
@@ -236,9 +234,9 @@
     return glyph;
 }
 
-bool GrTextStrike::removeUnusedAtlases() {
+bool GrTextStrike::removeUnusedPlots() {
     fCache.getArray().visitAll(invalidate_glyph);
-    return GrAtlas::RemoveUnusedAtlases(fAtlasMgr, &fAtlas);
+    return fAtlasMgr->removeUnusedPlots(&fAtlas);
 }
 
 bool GrTextStrike::getGlyphAtlas(GrGlyph* glyph, GrFontScaler* scaler,
@@ -251,8 +249,8 @@
     SkASSERT(glyph);
     SkASSERT(scaler);
     SkASSERT(fCache.contains(glyph));
-    if (glyph->fAtlas) {
-        glyph->fAtlas->setDrawToken(currentDrawToken);
+    if (glyph->fPlot) {
+        glyph->fPlot->setDrawToken(currentDrawToken);
         return true;
     }
 
@@ -268,14 +266,14 @@
         return false;
     }
 
-    GrAtlas* atlas = fAtlasMgr->addToAtlas(&fAtlas, glyph->width(),
-                                           glyph->height(), storage.get(),
-                                           &glyph->fAtlasLocation);
-    if (NULL == atlas) {
+    GrPlot* plot = fAtlasMgr->addToAtlas(&fAtlas, glyph->width(),
+                                         glyph->height(), storage.get(),
+                                         &glyph->fAtlasLocation);
+    if (NULL == plot) {
         return false;
     }
 
-    glyph->fAtlas = atlas;
-    atlas->setDrawToken(currentDrawToken);
+    glyph->fPlot = plot;
+    plot->setDrawToken(currentDrawToken);
     return true;
 }
diff --git a/gpu/GrTextStrike.h b/gpu/GrTextStrike.h
index 66bbb0d..2f52d98 100644
--- a/gpu/GrTextStrike.h
+++ b/gpu/GrTextStrike.h
@@ -17,8 +17,8 @@
 #include "GrPoint.h"
 #include "GrGlyph.h"
 #include "GrDrawTarget.h"
+#include "GrAtlas.h"
 
-class GrAtlasMgr;
 class GrFontCache;
 class GrGpu;
 class GrFontPurgeListener;
@@ -45,10 +45,9 @@
     const GrGlyph* glyphAt(int index) const {
         return fCache.getArray()[index];
     }
-    GrAtlas* getAtlas() const { return fAtlas; }
 
-    // returns true if an atlas was removed
-    bool removeUnusedAtlases();
+    // returns true if a plot was removed
+    bool removeUnusedPlots();
 
 public:
     // for LRU
@@ -63,13 +62,11 @@
 
     GrFontCache*    fFontCache;
     GrAtlasMgr*     fAtlasMgr;
-    GrAtlas*        fAtlas;     // linklist
+    GrAtlas         fAtlas;     
 
     GrMaskFormat    fMaskFormat;
 
     GrGlyph* generateGlyph(GrGlyph::PackedID packed, GrFontScaler* scaler);
-    // returns true if after the purge, the strike is empty
-    bool purgeAtlasAtY(GrAtlas* atlas, int yCoord);
 
     friend class GrFontCache;
 };
@@ -85,8 +82,8 @@
 
     void purgeExceptFor(GrTextStrike*);
 
-    // remove an unused atlas and its strike (if necessary)
-    void freeAtlasExceptFor(GrTextStrike*);
+    // remove an unused plot and its strike (if necessary)
+    void freePlotExceptFor(GrTextStrike*);
 
     // testing
     int countStrikes() const { return fCache.getArray().count(); }
@@ -113,7 +110,6 @@
     GrGpu*      fGpu;
     GrAtlasMgr* fAtlasMgr[kMaskFormatCount];
 
-
     GrTextStrike* generateStrike(GrFontScaler*, const Key&);
     inline void detachStrikeFromList(GrTextStrike*);
 };