Automatically cleanup textures that don't fit in the cache.

Change-Id: I4f29ed96ea11118b391fb957e1e4d1b8fcef1537
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index a72045b..db8c863 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -436,6 +436,8 @@
     }
 
     const Texture* texture = mTextureCache.get(bitmap);
+    const AutoTexture autoCleanup(texture);
+
     drawTextureRect(left, top, right, bottom, texture, paint);
 }
 
@@ -449,6 +451,8 @@
     }
 
     const Texture* texture = mTextureCache.get(bitmap);
+    const AutoTexture autoCleanup(texture);
+
     drawTextureRect(r.left, r.top, r.right, r.bottom, texture, paint);
 }
 
@@ -461,6 +465,7 @@
     }
 
     const Texture* texture = mTextureCache.get(bitmap);
+    const AutoTexture autoCleanup(texture);
 
     const float width = texture->width;
     const float height = texture->height;
@@ -484,6 +489,7 @@
     }
 
     const Texture* texture = mTextureCache.get(bitmap);
+    const AutoTexture autoCleanup(texture);
 
     int alpha;
     SkXfermode::Mode mode;
@@ -610,7 +616,8 @@
     GLuint textureUnit = 0;
     glActiveTexture(gTextureUnits[textureUnit]);
 
-    PathTexture* texture = mPathCache.get(path, paint);
+    const PathTexture* texture = mPathCache.get(path, paint);
+    const AutoTexture autoCleanup(texture);
 
     int alpha;
     SkXfermode::Mode mode;
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index 67a5f92..fa6ea25 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -88,7 +88,6 @@
         texture = addTexture(entry, path, paint);
     }
 
-    // TODO: Do something to destroy the texture object if it's too big for the cache
     return texture;
 }
 
@@ -129,6 +128,8 @@
     if (size < mMaxSize) {
         mSize += size;
         mCache.put(entry, texture);
+    } else {
+        texture->cleanup = true;
     }
 
     return texture;
diff --git a/libs/hwui/PathCache.h b/libs/hwui/PathCache.h
index 87a9141..206fb49 100644
--- a/libs/hwui/PathCache.h
+++ b/libs/hwui/PathCache.h
@@ -71,6 +71,9 @@
  * Alpha texture used to represent a path.
  */
 struct PathTexture: public Texture {
+    PathTexture(): Texture() {
+    }
+
     /**
      * Left coordinate of the path bounds.
      */
diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h
index d37013d..90f548b 100644
--- a/libs/hwui/Texture.h
+++ b/libs/hwui/Texture.h
@@ -26,6 +26,10 @@
  * Represents an OpenGL texture.
  */
 struct Texture {
+    Texture() {
+        cleanup = false;
+    }
+
     /**
      * Name of the texture.
      */
@@ -46,8 +50,26 @@
      * Height of the backing bitmap.
      */
     uint32_t height;
+    /**
+     * Indicates whether this texture should be cleaned up after use.
+     */
+    bool cleanup;
 }; // struct Texture
 
+class AutoTexture {
+public:
+    AutoTexture(const Texture* texture): mTexture(texture) { }
+    ~AutoTexture() {
+        if (mTexture && mTexture->cleanup) {
+            glDeleteTextures(1, &mTexture->id);
+            delete mTexture;
+        }
+    }
+
+private:
+    const Texture* mTexture;
+}; // class AutoTexture
+
 }; // namespace uirenderer
 }; // namespace android
 
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index 4975edb..59903b7 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -93,11 +93,13 @@
         if (size < mMaxSize) {
             mSize += size;
             mCache.put(bitmap, texture);
+        } else {
+            texture->cleanup = true;
         }
     } else if (bitmap->getGenerationID() != texture->generation) {
         generateTexture(bitmap, texture, true);
     }
-    // TODO: Do something to destroy the texture object if it's too big for the cache
+
     return texture;
 }