Optimizing ColorFilter in display lists

Change-Id: Ie4d5e5b0bc45e0ce47bba144049303c270762e54
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index a9cd5be..0dd9c5a 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -288,7 +288,7 @@
             }
             break;
             case SetupColorFilter: {
-                // TODO: Implement
+                renderer.setupColorFilter(getColorFilter());
             }
             break;
             case ResetShadow: {
@@ -512,7 +512,6 @@
 
 void DisplayListRenderer::resetShader() {
     addOp(DisplayList::ResetShader);
-    OpenGLRenderer::resetShader();
 }
 
 void DisplayListRenderer::setupShader(SkiaShader* shader) {
@@ -522,17 +521,15 @@
 
 void DisplayListRenderer::resetColorFilter() {
     addOp(DisplayList::ResetColorFilter);
-    OpenGLRenderer::resetColorFilter();
 }
 
 void DisplayListRenderer::setupColorFilter(SkiaColorFilter* filter) {
-    // TODO: Implement
-    OpenGLRenderer::setupColorFilter(filter);
+    addOp(DisplayList::SetupColorFilter);
+    addColorFilter(filter);
 }
 
 void DisplayListRenderer::resetShadow() {
     addOp(DisplayList::ResetShadow);
-    OpenGLRenderer::resetShadow();
 }
 
 void DisplayListRenderer::setupShadow(float radius, float dx, float dy, int color) {
@@ -540,7 +537,6 @@
     addFloat(radius);
     addPoint(dx, dy);
     addInt(color);
-    OpenGLRenderer::setupShadow(radius, dx, dy, color);
 }
 
 }; // namespace uirenderer
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index ce4cfc5..6636de6 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -135,6 +135,10 @@
         return (SkiaShader*) getInt();
     }
 
+    SkiaColorFilter* getColorFilter() {
+        return (SkiaColorFilter*) getInt();
+    }
+
     inline int getIndex() {
         return mReader.readInt();
     }
@@ -183,6 +187,7 @@
 
     Vector<SkBitmap*> mBitmapResources;
     Vector<SkiaShader*> mShaderResources;
+    Vector<SkiaColorFilter*> mFilterResources;
 
     Vector<SkPaint*> mPaints;
     Vector<SkMatrix*> mMatrices;
@@ -276,6 +281,10 @@
         return mMatrices;
     }
 
+    const Vector<SkiaColorFilter*>& getFilterResources() const {
+        return mFilterResources;
+    }
+
 private:
     inline void addOp(DisplayList::Op drawOp) {
         mWriter.writeInt(drawOp);
@@ -372,10 +381,18 @@
         caches.resourceCache.incrementRefcount(shader);
     }
 
+    inline void addColorFilter(SkiaColorFilter* colorFilter) {
+        addInt((int)colorFilter);
+        mFilterResources.add(colorFilter);
+        Caches& caches = Caches::getInstance();
+        caches.resourceCache.incrementRefcount(colorFilter);
+    }
+
     SkChunkAlloc mHeap;
 
     Vector<SkBitmap*> mBitmapResources;
     Vector<SkiaShader*> mShaderResources;
+    Vector<SkiaColorFilter*> mFilterResources;
 
     Vector<SkPaint*> mPaints;
     DefaultKeyedVector<SkPaint *, SkPaint *> mPaintMap;
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index b0fbe65..47c5d48 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -67,6 +67,11 @@
     incrementRefcount((void*)shaderResource, kShader);
 }
 
+void ResourceCache::incrementRefcount(SkiaColorFilter* filterResource) {
+    filterResource->getSkColorFilter()->safeRef();
+    incrementRefcount((void*)filterResource, kColorFilter);
+}
+
 void ResourceCache::decrementRefcount(void* resource) {
     ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
     if (ref == NULL) {
@@ -90,6 +95,11 @@
     decrementRefcount((void*)shaderResource);
 }
 
+void ResourceCache::decrementRefcount(SkiaColorFilter* filterResource) {
+    filterResource->getSkColorFilter()->safeUnref();
+    decrementRefcount((void*)filterResource);
+}
+
 void ResourceCache::recycle(SkBitmap* resource) {
     if (mCache->indexOfKey(resource) < 0) {
         // not tracking this resource; just recycle the pixel data
@@ -145,6 +155,20 @@
     }
 }
 
+void ResourceCache::destructor(SkiaColorFilter* resource) {
+    ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
+    if (ref == NULL) {
+        // If we're not tracking this resource, just delete it
+        delete resource;
+        return;
+    }
+    ref->destroyed = true;
+    if (ref->refCount == 0) {
+        deleteResourceReference(resource, ref);
+        return;
+    }
+}
+
 void ResourceCache::deleteResourceReference(void* resource, ResourceReference* ref) {
     if (ref->recycled && ref->resourceType == kBitmap) {
         ((SkBitmap*) resource)->setPixels(NULL, NULL);
@@ -161,12 +185,20 @@
             }
             break;
             case kShader:
+            {
                 SkiaShader* shader = (SkiaShader*)resource;
                 if (Caches::hasInstance()) {
                     Caches::getInstance().gradientCache.remove(shader->getSkShader());
                 }
                 delete shader;
-                break;
+            }
+            break;
+            case kColorFilter:
+            {
+                SkiaColorFilter* filter = (SkiaColorFilter*)resource;
+                delete filter;
+            }
+            break;
         }
     }
     mCache->removeItem(resource);
diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h
index b550367..d9b3718 100644
--- a/libs/hwui/ResourceCache.h
+++ b/libs/hwui/ResourceCache.h
@@ -18,6 +18,7 @@
 #define ANDROID_UI_RESOURCE_CACHE_H
 
 #include <SkBitmap.h>
+#include <SkiaColorFilter.h>
 #include <SkiaShader.h>
 #include <utils/KeyedVector.h>
 
@@ -30,6 +31,7 @@
 enum ResourceType {
     kBitmap,
     kShader,
+    kColorFilter,
 };
 
 class ResourceReference {
@@ -53,14 +55,17 @@
     ~ResourceCache();
     void incrementRefcount(SkBitmap* resource);
     void incrementRefcount(SkiaShader* resource);
+    void incrementRefcount(SkiaColorFilter* resource);
     void incrementRefcount(const void* resource, ResourceType resourceType);
     void decrementRefcount(void* resource);
     void decrementRefcount(SkBitmap* resource);
     void decrementRefcount(SkiaShader* resource);
+    void decrementRefcount(SkiaColorFilter* resource);
     void recycle(void* resource);
     void recycle(SkBitmap* resource);
     void destructor(SkBitmap* resource);
     void destructor(SkiaShader* resource);
+    void destructor(SkiaColorFilter* resource);
 private:
     void deleteResourceReference(void* resource, ResourceReference* ref);
     void incrementRefcount(void* resource, ResourceType resourceType);
diff --git a/libs/hwui/SkiaColorFilter.cpp b/libs/hwui/SkiaColorFilter.cpp
index fe57ae7..91b1c32 100644
--- a/libs/hwui/SkiaColorFilter.cpp
+++ b/libs/hwui/SkiaColorFilter.cpp
@@ -23,7 +23,8 @@
 // Base color filter
 ///////////////////////////////////////////////////////////////////////////////
 
-SkiaColorFilter::SkiaColorFilter(Type type, bool blend): mType(type), mBlend(blend) {
+SkiaColorFilter::SkiaColorFilter(SkColorFilter *skFilter, Type type, bool blend):
+        mType(type), mBlend(blend), mSkFilter(skFilter) {
 }
 
 SkiaColorFilter::~SkiaColorFilter() {
@@ -33,8 +34,8 @@
 // Color matrix filter
 ///////////////////////////////////////////////////////////////////////////////
 
-SkiaColorMatrixFilter::SkiaColorMatrixFilter(float* matrix, float* vector):
-        SkiaColorFilter(kColorMatrix, true), mMatrix(matrix), mVector(vector) {
+SkiaColorMatrixFilter::SkiaColorMatrixFilter(SkColorFilter *skFilter, float* matrix, float* vector):
+        SkiaColorFilter(skFilter, kColorMatrix, true), mMatrix(matrix), mVector(vector) {
 }
 
 SkiaColorMatrixFilter::~SkiaColorMatrixFilter() {
@@ -56,8 +57,8 @@
 // Lighting color filter
 ///////////////////////////////////////////////////////////////////////////////
 
-SkiaLightingFilter::SkiaLightingFilter(int multiply, int add):
-        SkiaColorFilter(kLighting, true) {
+SkiaLightingFilter::SkiaLightingFilter(SkColorFilter *skFilter, int multiply, int add):
+        SkiaColorFilter(skFilter, kLighting, true) {
     mMulR = ((multiply >> 16) & 0xFF) / 255.0f;
     mMulG = ((multiply >>  8) & 0xFF) / 255.0f;
     mMulB = ((multiply      ) & 0xFF) / 255.0f;
@@ -80,8 +81,8 @@
 // Blend color filter
 ///////////////////////////////////////////////////////////////////////////////
 
-SkiaBlendFilter::SkiaBlendFilter(int color, SkXfermode::Mode mode):
-        SkiaColorFilter(kBlend, true), mMode(mode) {
+SkiaBlendFilter::SkiaBlendFilter(SkColorFilter *skFilter, int color, SkXfermode::Mode mode):
+        SkiaColorFilter(skFilter, kBlend, true), mMode(mode) {
     const int alpha = (color >> 24) & 0xFF;
     mA = alpha / 255.0f;
     mR = mA * ((color >> 16) & 0xFF) / 255.0f;
diff --git a/libs/hwui/SkiaColorFilter.h b/libs/hwui/SkiaColorFilter.h
index 865b6f0..17f49f9 100644
--- a/libs/hwui/SkiaColorFilter.h
+++ b/libs/hwui/SkiaColorFilter.h
@@ -18,6 +18,7 @@
 #define ANDROID_UI_SKIA_COLOR_FILTER_H
 
 #include <GLES2/gl2.h>
+#include <SkColorFilter.h>
 
 #include "ProgramCache.h"
 #include "Extensions.h"
@@ -44,7 +45,7 @@
         kBlend,
     };
 
-    SkiaColorFilter(Type type, bool blend);
+    SkiaColorFilter(SkColorFilter *skFilter, Type type, bool blend);
     virtual ~SkiaColorFilter();
 
     virtual void describe(ProgramDescription& description, const Extensions& extensions) = 0;
@@ -58,9 +59,16 @@
         return mType;
     }
 
+    SkColorFilter *getSkColorFilter() {
+        return mSkFilter;
+    }
+
 protected:
     Type mType;
     bool mBlend;
+
+private:
+    SkColorFilter *mSkFilter;
 }; // struct SkiaColorFilter
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -71,7 +79,7 @@
  * A color filter that multiplies the source color with a matrix and adds a vector.
  */
 struct SkiaColorMatrixFilter: public SkiaColorFilter {
-    SkiaColorMatrixFilter(float* matrix, float* vector);
+    SkiaColorMatrixFilter(SkColorFilter *skFilter, float* matrix, float* vector);
     ~SkiaColorMatrixFilter();
 
     void describe(ProgramDescription& description, const Extensions& extensions);
@@ -87,7 +95,7 @@
  * another fixed value. Ignores the alpha channel of both arguments.
  */
 struct SkiaLightingFilter: public SkiaColorFilter {
-    SkiaLightingFilter(int multiply, int add);
+    SkiaLightingFilter(SkColorFilter *skFilter, int multiply, int add);
 
     void describe(ProgramDescription& description, const Extensions& extensions);
     void setupProgram(Program* program);
@@ -102,7 +110,7 @@
  * and PorterDuff blending mode.
  */
 struct SkiaBlendFilter: public SkiaColorFilter {
-    SkiaBlendFilter(int color, SkXfermode::Mode mode);
+    SkiaBlendFilter(SkColorFilter *skFilter, int color, SkXfermode::Mode mode);
 
     void describe(ProgramDescription& description, const Extensions& extensions);
     void setupProgram(Program* program);