Reduce the amount of data cached by the gradients cache.

Change-Id: I8546f5a5ecf38031c9a40bdcc434d4c7f22da63d
diff --git a/libs/hwui/GradientCache.h b/libs/hwui/GradientCache.h
index 30da462..086921c 100644
--- a/libs/hwui/GradientCache.h
+++ b/libs/hwui/GradientCache.h
@@ -22,17 +22,74 @@
 #include <utils/Vector.h>
 
 #include "Texture.h"
+#include "utils/Compare.h"
 #include "utils/GenerationCache.h"
 
 namespace android {
 namespace uirenderer {
 
+struct GradientCacheEntry {
+    GradientCacheEntry() {
+        count = 0;
+        colors = NULL;
+        positions = NULL;
+        tileMode = SkShader::kClamp_TileMode;
+    }
+
+    GradientCacheEntry(uint32_t* colors, float* positions, int count,
+            SkShader::TileMode tileMode) {
+        this->count = count;
+        this->colors = new uint32_t[count];
+        this->positions = new float[count];
+        this->tileMode = tileMode;
+
+        memcpy(this->colors, colors, count * sizeof(uint32_t));
+        memcpy(this->positions, positions, count * sizeof(float));
+    }
+
+    GradientCacheEntry(const GradientCacheEntry& entry) {
+        this->count = entry.count;
+        this->colors = new uint32_t[count];
+        this->positions = new float[count];
+        this->tileMode = entry.tileMode;
+
+        memcpy(this->colors, entry.colors, count * sizeof(uint32_t));
+        memcpy(this->positions, entry.positions, count * sizeof(float));
+    }
+
+    ~GradientCacheEntry() {
+        delete[] colors;
+        delete[] positions;
+    }
+
+    bool operator<(const GradientCacheEntry& r) const {
+        const GradientCacheEntry& rhs = (const GradientCacheEntry&) r;
+        LTE_INT(count) {
+            LTE_INT(tileMode) {
+                int result = memcmp(colors, rhs.colors, count * sizeof(uint32_t));
+                if (result< 0) return true;
+                else if (result == 0) {
+                    result = memcmp(positions, rhs.positions, count * sizeof(float));
+                    if (result < 0) return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    uint32_t* colors;
+    float* positions;
+    int count;
+    SkShader::TileMode tileMode;
+
+}; // GradientCacheEntry
+
 /**
  * A simple LRU gradient cache. The cache has a maximum size expressed in bytes.
  * Any texture added to the cache causing the cache to grow beyond the maximum
  * allowed size will also cause the oldest texture to be kicked out.
  */
-class GradientCache: public OnEntryRemoved<SkShader*, Texture*> {
+class GradientCache: public OnEntryRemoved<GradientCacheEntry, Texture*> {
 public:
     GradientCache();
     GradientCache(uint32_t maxByteSize);
@@ -42,32 +99,13 @@
      * Used as a callback when an entry is removed from the cache.
      * Do not invoke directly.
      */
-    void operator()(SkShader*& shader, Texture*& texture);
+    void operator()(GradientCacheEntry& shader, Texture*& texture);
 
     /**
-     * Adds a new linear gradient to the cache. The generated texture is
-     * returned.
-     */
-    Texture* addLinearGradient(SkShader* shader, uint32_t* colors, float* positions,
-            int count, SkShader::TileMode tileMode = SkShader::kClamp_TileMode);
-    /**
      * Returns the texture associated with the specified shader.
      */
-    Texture* get(SkShader* shader);
-    /**
-     * Removes the texture associated with the specified shader.
-     * Upon remove the texture is freed.
-     */
-    void remove(SkShader* shader);
-    /**
-     * Removes the texture associated with the specified shader. This is meant
-     * to be called from threads that are not the EGL context thread.
-     */
-    void removeDeferred(SkShader* shader);
-    /**
-     * Process deferred removals.
-     */
-    void clearGarbage();
+    Texture* get(uint32_t* colors, float* positions,
+            int count, SkShader::TileMode tileMode = SkShader::kClamp_TileMode);
     /**
      * Clears the cache. This causes all textures to be deleted.
      */
@@ -87,9 +125,17 @@
     uint32_t getSize();
 
 private:
+    /**
+     * Adds a new linear gradient to the cache. The generated texture is
+     * returned.
+     */
+    Texture* addLinearGradient(GradientCacheEntry& gradient,
+            uint32_t* colors, float* positions, int count,
+            SkShader::TileMode tileMode = SkShader::kClamp_TileMode);
+
     void generateTexture(SkBitmap* bitmap, Texture* texture);
 
-    GenerationCache<SkShader*, Texture*> mCache;
+    GenerationCache<GradientCacheEntry, Texture*> mCache;
 
     uint32_t mSize;
     uint32_t mMaxSize;