Merge "De-allocate caches for large glyphs when trimming memory"
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 34245b0..8462307 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -85,9 +85,12 @@
     }
 }
 
-void Font::invalidateTextureCache() {
+void Font::invalidateTextureCache(CacheTextureLine *cacheLine) {
     for (uint32_t i = 0; i < mCachedGlyphs.size(); i++) {
-        mCachedGlyphs.valueAt(i)->mIsValid = false;
+        CachedGlyphInfo* cachedGlyph = mCachedGlyphs.valueAt(i);
+        if (cacheLine == NULL || cachedGlyph->mCachedTextureLine == cacheLine) {
+            cachedGlyph->mIsValid = false;
+        }
     }
 }
 
@@ -414,6 +417,40 @@
     }
 }
 
+void FontRenderer::deallocateTextureMemory(CacheTexture *cacheTexture) {
+    if (cacheTexture && cacheTexture->mTexture) {
+        glDeleteTextures(1, &cacheTexture->mTextureId);
+        delete cacheTexture->mTexture;
+        cacheTexture->mTexture = NULL;
+    }
+}
+
+void FontRenderer::flushLargeCaches() {
+    if ((!mCacheTexture128 || !mCacheTexture128->mTexture) &&
+            (!mCacheTexture256 || !mCacheTexture256->mTexture) &&
+            (!mCacheTexture512 || !mCacheTexture512->mTexture)) {
+        // Typical case; no large glyph caches allocated
+        return;
+    }
+
+    for (uint32_t i = 0; i < mCacheLines.size(); i++) {
+        CacheTextureLine* cacheLine = mCacheLines[i];
+        if ((cacheLine->mCacheTexture == mCacheTexture128 ||
+                cacheLine->mCacheTexture == mCacheTexture256 ||
+                cacheLine->mCacheTexture == mCacheTexture512) &&
+                cacheLine->mCacheTexture->mTexture != NULL) {
+            cacheLine->mCurrentCol = 0;
+            for (uint32_t i = 0; i < mActiveFonts.size(); i++) {
+                mActiveFonts[i]->invalidateTextureCache(cacheLine);
+            }
+        }
+    }
+
+    deallocateTextureMemory(mCacheTexture128);
+    deallocateTextureMemory(mCacheTexture256);
+    deallocateTextureMemory(mCacheTexture512);
+}
+
 void FontRenderer::allocateTextureMemory(CacheTexture *cacheTexture) {
     int width = cacheTexture->mWidth;
     int height = cacheTexture->mHeight;
diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h
index 9f32747..005cdde 100644
--- a/libs/hwui/FontRenderer.h
+++ b/libs/hwui/FontRenderer.h
@@ -180,7 +180,7 @@
     // Cache of glyphs
     DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs;
 
-    void invalidateTextureCache();
+    void invalidateTextureCache(CacheTextureLine *cacheLine = NULL);
 
     CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph);
     void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo *glyph);
@@ -219,6 +219,7 @@
 
     void init();
     void deinit();
+    void flushLargeCaches();
 
     void setGammaTable(const uint8_t* gammaTable) {
         mGammaTable = gammaTable;
@@ -286,6 +287,7 @@
     const uint8_t* mGammaTable;
 
     void allocateTextureMemory(CacheTexture* cacheTexture);
+    void deallocateTextureMemory(CacheTexture* cacheTexture);
     void initTextTexture();
     CacheTexture *createCacheTexture(int width, int height, bool allocate);
     void cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph,
diff --git a/libs/hwui/GammaFontRenderer.cpp b/libs/hwui/GammaFontRenderer.cpp
index eb863e9..1be957f 100644
--- a/libs/hwui/GammaFontRenderer.cpp
+++ b/libs/hwui/GammaFontRenderer.cpp
@@ -113,6 +113,13 @@
 
     delete mRenderers[min];
     mRenderers[min] = NULL;
+
+    // Also eliminate the caches for large glyphs, as they consume significant memory
+    for (int i = 0; i < kGammaCount; ++i) {
+        if (mRenderers[i]) {
+            mRenderers[i]->flushLargeCaches();
+        }
+    }
 }
 
 FontRenderer* GammaFontRenderer::getRenderer(Gamma gamma) {