| Index: src/gpu/GrBatchFontCache.h
 | 
| diff --git a/src/gpu/GrBatchFontCache.h b/src/gpu/GrBatchFontCache.h
 | 
| index d9352323a5217f0a1c279fd5f6b5a7fe18d82122..6aa14e69daf271fd05f049c9acbb76fb820c78c4 100644
 | 
| --- a/src/gpu/GrBatchFontCache.h
 | 
| +++ b/src/gpu/GrBatchFontCache.h
 | 
| @@ -75,18 +75,17 @@ private:
 | 
|  /*
 | 
|   * GrBatchFontCache manages strikes which are indexed by a GrFontScaler.  These strikes can then be
 | 
|   * used to individual Glyph Masks.  The GrBatchFontCache also manages GrBatchAtlases, though this is
 | 
| - * more or less transparent to the client(aside from atlasGeneration, described below)
 | 
| + * more or less transparent to the client(aside from atlasGeneration, described below).
 | 
| + * Note - we used to initialize the backing atlas for the GrBatchFontCache at initialization time.
 | 
| + * However, this caused a regression, even when the GrBatchFontCache was unused.  We now initialize
 | 
| + * the backing atlases lazily.  Its not immediately clear why this improves the situation.
 | 
|   */
 | 
|  class GrBatchFontCache {
 | 
|  public:
 | 
| -    GrBatchFontCache();
 | 
| +    GrBatchFontCache(GrContext*);
 | 
|      ~GrBatchFontCache();
 | 
|  
 | 
| -    // Initializes the GrBatchFontCache on the owning GrContext
 | 
| -    void init(GrContext*);
 | 
| -
 | 
|      inline GrBatchTextStrike* getStrike(GrFontScaler* scaler) {
 | 
| -
 | 
|          GrBatchTextStrike* strike = fCache.find(*(scaler->getKey()));
 | 
|          if (NULL == strike) {
 | 
|              strike = this->generateStrike(scaler);
 | 
| @@ -94,49 +93,93 @@ public:
 | 
|          return strike;
 | 
|      }
 | 
|  
 | 
| -    bool hasGlyph(GrGlyph* glyph);
 | 
| +    void freeAll();
 | 
| +
 | 
| +    // if getTexture returns NULL, the client must not try to use other functions on the
 | 
| +    // GrBatchFontCache which use the atlas.  This function *must* be called first, before other
 | 
| +    // functions which use the atlas.
 | 
| +    GrTexture* getTexture(GrMaskFormat format) {
 | 
| +        if (this->initAtlas(format)) {
 | 
| +            return this->getAtlas(format)->getTexture();
 | 
| +        }
 | 
| +        return NULL;
 | 
| +    }
 | 
| +
 | 
| +    bool hasGlyph(GrGlyph* glyph) {
 | 
| +        SkASSERT(glyph);
 | 
| +        return this->getAtlas(glyph->fMaskFormat)->hasID(glyph->fID);
 | 
| +    }
 | 
|  
 | 
|      // To ensure the GrBatchAtlas does not evict the Glyph Mask from its texture backing store,
 | 
|      // the client must pass in the currentToken from the GrBatchTarget along with the GrGlyph.
 | 
|      // A BulkUseTokenUpdater is used to manage bulk last use token updating in the Atlas.
 | 
|      // For convenience, this function will also set the use token for the current glyph if required
 | 
|      // NOTE: the bulk uploader is only valid if the subrun has a valid atlasGeneration
 | 
| -    void addGlyphToBulkAndSetUseToken(GrBatchAtlas::BulkUseTokenUpdater*, GrGlyph*,
 | 
| -                                      GrBatchAtlas::BatchToken);
 | 
| +    void addGlyphToBulkAndSetUseToken(GrBatchAtlas::BulkUseTokenUpdater* updater,
 | 
| +                                      GrGlyph* glyph, GrBatchAtlas::BatchToken token) {
 | 
| +        SkASSERT(glyph);
 | 
| +        updater->add(glyph->fID);
 | 
| +        this->getAtlas(glyph->fMaskFormat)->setLastUseToken(glyph->fID, token);
 | 
| +    }
 | 
|  
 | 
| -    void setUseTokenBulk(const GrBatchAtlas::BulkUseTokenUpdater&, GrBatchAtlas::BatchToken,
 | 
| -                         GrMaskFormat);
 | 
| +    void setUseTokenBulk(const GrBatchAtlas::BulkUseTokenUpdater& updater,
 | 
| +                         GrBatchAtlas::BatchToken token,
 | 
| +                         GrMaskFormat format) {
 | 
| +        this->getAtlas(format)->setLastUseTokenBulk(updater, token);
 | 
| +    }
 | 
|  
 | 
|      // add to texture atlas that matches this format
 | 
| -    bool addToAtlas(GrBatchTextStrike*, GrBatchAtlas::AtlasID*, GrBatchTarget*,
 | 
| -                    GrMaskFormat, int width, int height, const void* image,
 | 
| -                    SkIPoint16* loc);
 | 
| +    bool addToAtlas(GrBatchTextStrike* strike, GrBatchAtlas::AtlasID* id,
 | 
| +                    GrBatchTarget* batchTarget,
 | 
| +                    GrMaskFormat format, int width, int height, const void* image,
 | 
| +                    SkIPoint16* loc) {
 | 
| +        fPreserveStrike = strike;
 | 
| +        return this->getAtlas(format)->addToAtlas(id, batchTarget, width, height, image, loc);
 | 
| +    }
 | 
|  
 | 
|      // Some clients may wish to verify the integrity of the texture backing store of the
 | 
|      // GrBatchAtlas.  The atlasGeneration returned below is a monitonically increasing number which
 | 
|      // changes everytime something is removed from the texture backing store.
 | 
| -    uint64_t atlasGeneration(GrMaskFormat) const;
 | 
| -
 | 
| -    void freeAll();
 | 
| +    uint64_t atlasGeneration(GrMaskFormat format) const {
 | 
| +        return this->getAtlas(format)->atlasGeneration();
 | 
| +    }
 | 
|  
 | 
| -    GrTexture* getTexture(GrMaskFormat);
 | 
|      GrPixelConfig getPixelConfig(GrMaskFormat) const;
 | 
|  
 | 
|      void dump() const;
 | 
|  
 | 
|  private:
 | 
|      // There is a 1:1 mapping between GrMaskFormats and atlas indices
 | 
| -    static int MaskFormatToAtlasIndex(GrMaskFormat);
 | 
| -    static GrMaskFormat AtlasIndexToMaskFormat(int atlasIndex);
 | 
| +    static int MaskFormatToAtlasIndex(GrMaskFormat format) {
 | 
| +        static const int sAtlasIndices[] = {
 | 
| +            kA8_GrMaskFormat,
 | 
| +            kA565_GrMaskFormat,
 | 
| +            kARGB_GrMaskFormat,
 | 
| +        };
 | 
| +        SK_COMPILE_ASSERT(SK_ARRAY_COUNT(sAtlasIndices) == kMaskFormatCount, array_size_mismatch);
 | 
| +
 | 
| +        SkASSERT(sAtlasIndices[format] < kMaskFormatCount);
 | 
| +        return sAtlasIndices[format];
 | 
| +    }
 | 
|  
 | 
| -    GrBatchTextStrike* generateStrike(GrFontScaler*);
 | 
| +    bool initAtlas(GrMaskFormat);
 | 
|  
 | 
| -    inline GrBatchAtlas* getAtlas(GrMaskFormat) const;
 | 
| +    GrBatchTextStrike* generateStrike(GrFontScaler* scaler) {
 | 
| +        GrBatchTextStrike* strike = SkNEW_ARGS(GrBatchTextStrike, (this, scaler->getKey()));
 | 
| +        fCache.add(strike);
 | 
| +        return strike;
 | 
| +    }
 | 
| +
 | 
| +    GrBatchAtlas* getAtlas(GrMaskFormat format) const {
 | 
| +        int atlasIndex = MaskFormatToAtlasIndex(format);
 | 
| +        SkASSERT(fAtlases[atlasIndex]);
 | 
| +        return fAtlases[atlasIndex];
 | 
| +    }
 | 
|  
 | 
|      static void HandleEviction(GrBatchAtlas::AtlasID, void*);
 | 
|  
 | 
| +    GrContext* fContext;
 | 
|      SkTDynamicHash<GrBatchTextStrike, GrFontDescKey> fCache;
 | 
| -
 | 
|      GrBatchAtlas* fAtlases[kMaskFormatCount];
 | 
|      GrBatchTextStrike* fPreserveStrike;
 | 
|  };
 | 
| 
 |