First pass at font cache refactor: Create an atlas manager per texture

This changes the AtlasMgr from a singleton class to one that is
created per-texture. This is the first step in allowing us to create
Atlases of other types (e.g., combine small icons into one big texture).

R=bsalomon@google.com

Author: jvanverth@google.com

Review URL: https://chromiumcodereview.appspot.com/24608002

git-svn-id: http://skia.googlecode.com/svn/trunk/src@11468 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/GrAtlas.cpp b/gpu/GrAtlas.cpp
index 9cdde22..b3f2e34 100644
--- a/gpu/GrAtlas.cpp
+++ b/gpu/GrAtlas.cpp
@@ -55,7 +55,7 @@
     fAtlasMgr = mgr;    // just a pointer, not an owner
     fNext = NULL;
 
-    fTexture = mgr->getTexture(format); // we're not an owner, just a pointer
+    fTexture = mgr->getTexture(); // we're not an owner, just a pointer
     fPlot.set(plotX, plotY);
 
     fRects = GrRectanizer::Factory(GR_ATLAS_WIDTH - BORDER,
@@ -70,7 +70,7 @@
 }
 
 GrAtlas::~GrAtlas() {
-    fAtlasMgr->freePlot(fMaskFormat, fPlot.fX, fPlot.fY);
+    fAtlasMgr->freePlot(fPlot.fX, fPlot.fY);
 
     delete fRects;
 
@@ -161,22 +161,17 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-GrAtlasMgr::GrAtlasMgr(GrGpu* gpu) {
+GrAtlasMgr::GrAtlasMgr(GrGpu* gpu, GrMaskFormat format) {
     fGpu = gpu;
+    fMaskFormat = format;
     gpu->ref();
-    Gr_bzero(fTexture, sizeof(fTexture));
-    for (int i = 0; i < kCount_GrMaskFormats; ++i) {
-        fPlotMgr[i] = SkNEW_ARGS(GrPlotMgr, (GR_PLOT_WIDTH, GR_PLOT_HEIGHT));
-    }
+    fTexture = NULL;
+    fPlotMgr = SkNEW_ARGS(GrPlotMgr, (GR_PLOT_WIDTH, GR_PLOT_HEIGHT));
 }
 
 GrAtlasMgr::~GrAtlasMgr() {
-    for (size_t i = 0; i < GR_ARRAY_COUNT(fTexture); i++) {
-        SkSafeUnref(fTexture[i]);
-    }
-    for (int i = 0; i < kCount_GrMaskFormats; ++i) {
-        delete fPlotMgr[i];
-    }
+    SkSafeUnref(fTexture);
+    delete fPlotMgr;
 
     fGpu->unref();
 #if FONT_CACHE_STATS
@@ -200,10 +195,7 @@
 
 GrAtlas* GrAtlasMgr::addToAtlas(GrAtlas** atlas,
                                 int width, int height, const void* image,
-                                GrMaskFormat format,
                                 GrIPoint16* loc) {
-    SkASSERT(NULL == *atlas || (*atlas)->getMaskFormat() == format);
-
     // iterate through entire atlas list, see if we can find a hole
     GrAtlas* atlasIter = *atlas;
     while (atlasIter) {
@@ -217,27 +209,25 @@
     // atlas list is full. Either way we need to allocate a new atlas
 
     GrIPoint16 plot;
-    if (!fPlotMgr[format]->newPlot(&plot)) {
+    if (!fPlotMgr->newPlot(&plot)) {
         return NULL;
     }
 
-    SkASSERT(0 == kA8_GrMaskFormat);
-    SkASSERT(1 == kA565_GrMaskFormat);
-    if (NULL == fTexture[format]) {
+    if (NULL == fTexture) {
         // TODO: Update this to use the cache rather than directly creating a texture.
         GrTextureDesc desc;
         desc.fFlags = kDynamicUpdate_GrTextureFlagBit;
         desc.fWidth = GR_ATLAS_TEXTURE_WIDTH;
         desc.fHeight = GR_ATLAS_TEXTURE_HEIGHT;
-        desc.fConfig = maskformat2pixelconfig(format);
+        desc.fConfig = maskformat2pixelconfig(fMaskFormat);
 
-        fTexture[format] = fGpu->createTexture(desc, NULL, 0);
-        if (NULL == fTexture[format]) {
+        fTexture = fGpu->createTexture(desc, NULL, 0);
+        if (NULL == fTexture) {
             return NULL;
         }
     }
 
-    GrAtlas* newAtlas = SkNEW_ARGS(GrAtlas, (this, plot.fX, plot.fY, format));
+    GrAtlas* newAtlas = SkNEW_ARGS(GrAtlas, (this, plot.fX, plot.fY, fMaskFormat));
     if (!newAtlas->addSubImage(width, height, image, loc)) {
         delete newAtlas;
         return NULL;
@@ -250,7 +240,7 @@
     return newAtlas;
 }
 
-void GrAtlasMgr::freePlot(GrMaskFormat format, int x, int y) {
-    SkASSERT(fPlotMgr[format]->isBusy(x, y));
-    fPlotMgr[format]->freePlot(x, y);
+void GrAtlasMgr::freePlot(int x, int y) {
+    SkASSERT(fPlotMgr->isBusy(x, y));
+    fPlotMgr->freePlot(x, y);
 }
diff --git a/gpu/GrAtlas.h b/gpu/GrAtlas.h
index e4472e7..3f9da8c 100644
--- a/gpu/GrAtlas.h
+++ b/gpu/GrAtlas.h
@@ -64,25 +64,24 @@
 
 class GrAtlasMgr {
 public:
-    GrAtlasMgr(GrGpu*);
+    GrAtlasMgr(GrGpu*, GrMaskFormat);
     ~GrAtlasMgr();
 
-    GrAtlas* addToAtlas(GrAtlas**, int width, int height, const void*,
-                        GrMaskFormat, GrIPoint16*);
+    GrAtlas* addToAtlas(GrAtlas**, int width, int height, const void*, GrIPoint16*);
     void deleteAtlas(GrAtlas* atlas) { delete atlas; }
 
-    GrTexture* getTexture(GrMaskFormat format) const {
-        SkASSERT((unsigned)format < kCount_GrMaskFormats);
-        return fTexture[format];
+    GrTexture* getTexture() const {
+        return fTexture;
     }
 
     // to be called by ~GrAtlas()
-    void freePlot(GrMaskFormat format, int x, int y);
+    void freePlot(int x, int y);
 
 private:
-    GrGpu*      fGpu;
-    GrTexture*  fTexture[kCount_GrMaskFormats];
-    GrPlotMgr*  fPlotMgr[kCount_GrMaskFormats];
+    GrGpu*       fGpu;
+    GrMaskFormat fMaskFormat;
+    GrTexture*   fTexture;
+    GrPlotMgr*   fPlotMgr;
 };
 
 #endif
diff --git a/gpu/GrTextStrike.cpp b/gpu/GrTextStrike.cpp
index 47b6216..5798e5f 100644
--- a/gpu/GrTextStrike.cpp
+++ b/gpu/GrTextStrike.cpp
@@ -23,14 +23,18 @@
 
 GrFontCache::GrFontCache(GrGpu* gpu) : fGpu(gpu) {
     gpu->ref();
-    fAtlasMgr = NULL;
+    for (int i = 0; i < kMaskFormatCount; ++i) {
+        fAtlasMgr[i] = NULL;
+    }
 
     fHead = fTail = NULL;
 }
 
 GrFontCache::~GrFontCache() {
     fCache.deleteAll();
-    delete fAtlasMgr;
+    for (int i = 0; i < kMaskFormatCount; ++i) {
+        delete fAtlasMgr[i];
+    }
     fGpu->unref();
 #if FONT_CACHE_STATS
       GrPrintf("Num purges: %d\n", g_PurgeCount);
@@ -39,12 +43,13 @@
 
 GrTextStrike* GrFontCache::generateStrike(GrFontScaler* scaler,
                                           const Key& key) {
-    if (NULL == fAtlasMgr) {
-        fAtlasMgr = SkNEW_ARGS(GrAtlasMgr, (fGpu));
+    GrMaskFormat format = scaler->getMaskFormat();
+    if (NULL == fAtlasMgr[format]) {
+        fAtlasMgr[format] = SkNEW_ARGS(GrAtlasMgr, (fGpu, format));
     }
     GrTextStrike* strike = SkNEW_ARGS(GrTextStrike,
                                       (this, scaler->getKey(),
-                                       scaler->getMaskFormat(), fAtlasMgr));
+                                       scaler->getMaskFormat(), fAtlasMgr[format]));
     fCache.insert(key, strike);
 
     if (fHead) {
@@ -62,8 +67,10 @@
 
 void GrFontCache::freeAll() {
     fCache.deleteAll();
-    delete fAtlasMgr;
-    fAtlasMgr = NULL;
+    for (int i = 0; i < kMaskFormatCount; ++i) {
+        delete fAtlasMgr[i];
+        fAtlasMgr[i] = NULL;
+    }
     fHead = NULL;
     fTail = NULL;
 }
@@ -249,7 +256,6 @@
 
     GrAtlas* atlas = fAtlasMgr->addToAtlas(&fAtlas, glyph->width(),
                                            glyph->height(), storage.get(),
-                                           fMaskFormat,
                                            &glyph->fAtlasLocation);
     if (NULL == atlas) {
         return false;
diff --git a/gpu/GrTextStrike.h b/gpu/GrTextStrike.h
index a5abde6..7771e4a 100644
--- a/gpu/GrTextStrike.h
+++ b/gpu/GrTextStrike.h
@@ -111,7 +111,7 @@
     GrTextStrike* fTail;
 
     GrGpu*      fGpu;
-    GrAtlasMgr* fAtlasMgr;
+    GrAtlasMgr* fAtlasMgr[kMaskFormatCount];
 
 
     GrTextStrike* generateStrike(GrFontScaler*, const Key&);