Optimize FBO cache.

This change introduces a new generational cache called GenerationMultiCache
that can store several values with the same key. This can be used to use
multiple layers of the same size at the same time, without recreating them
over and over again.

Change-Id: I425466a20908b862c5f464a0f9e582ec18cbd7ac
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 394aeca..cbdbc3c 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -6,6 +6,7 @@
 	Matrix.cpp \
 	OpenGLRenderer.cpp \
 	Program.cpp \
+	SortedList.cpp \
 	TextureCache.cpp
 
 LOCAL_C_INCLUDES += \
diff --git a/libs/hwui/GenerationCache.h b/libs/hwui/GenerationCache.h
index d92a0bb..5f64a35 100644
--- a/libs/hwui/GenerationCache.h
+++ b/libs/hwui/GenerationCache.h
@@ -20,9 +20,68 @@
 #include <utils/KeyedVector.h>
 #include <utils/RefBase.h>
 
+#include "SortedList.h"
+
 namespace android {
 namespace uirenderer {
 
+template<typename K, typename V>
+class GenerationCacheStorage {
+public:
+    virtual ~GenerationCacheStorage();
+
+    virtual size_t size() const = 0;
+    virtual void clear() = 0;
+    virtual ssize_t add(const K& key, const V& item) = 0;
+    virtual ssize_t indexOfKey(const K& key) const = 0;
+    virtual const V& valueAt(size_t index) const = 0;
+    virtual ssize_t removeItemsAt(size_t index, size_t count) = 0;
+}; // GenerationCacheStorage
+
+template<typename K, typename V>
+GenerationCacheStorage<K, V>::~GenerationCacheStorage() {
+}
+
+template<typename K, typename V>
+class KeyedVectorStorage: public GenerationCacheStorage<K, V> {
+public:
+    KeyedVectorStorage() { }
+    ~KeyedVectorStorage() { }
+
+    inline size_t size() const { return mStorage.size(); }
+    inline void clear() { mStorage.clear(); }
+    inline ssize_t add(const K& key, const V& value) { return mStorage.add(key, value); }
+    inline ssize_t indexOfKey(const K& key) const { return mStorage.indexOfKey(key); }
+    inline const V& valueAt(size_t index) const { return mStorage.valueAt(index); }
+    inline ssize_t removeItemsAt(size_t index, size_t count) {
+        return mStorage.removeItemsAt(index, count);
+    }
+private:
+    KeyedVector<K, V> mStorage;
+}; // class KeyedVectorStorage
+
+template<typename K, typename V>
+class SortedListStorage: public GenerationCacheStorage<K, V> {
+public:
+    SortedListStorage() { }
+    ~SortedListStorage() { }
+
+    inline size_t size() const { return mStorage.size(); }
+    inline void clear() { mStorage.clear(); }
+    inline ssize_t add(const K& key, const V& value) {
+        return mStorage.add(key_value_pair_t<K, V>(key, value));
+    }
+    inline ssize_t indexOfKey(const K& key) const {
+        return mStorage.indexOf(key_value_pair_t<K, V>(key));
+    }
+    inline const V& valueAt(size_t index) const { return mStorage.itemAt(index).value; }
+    inline ssize_t removeItemsAt(size_t index, size_t count) {
+        return mStorage.removeItemsAt(index, count);
+    }
+private:
+    SortedList<key_value_pair_t<K, V> > mStorage;
+}; // class SortedListStorage
+
 template<typename EntryKey, typename EntryValue>
 class OnEntryRemoved {
 public:
@@ -30,11 +89,27 @@
     virtual void operator()(EntryKey& key, EntryValue& value) = 0;
 }; // class OnEntryRemoved
 
+template<typename EntryKey, typename EntryValue>
+struct Entry: public LightRefBase<Entry<EntryKey, EntryValue> > {
+    Entry() { }
+    Entry(const Entry<EntryKey, EntryValue>& e):
+            key(e.key), value(e.value), index(e.index), parent(e.parent), child(e.child) { }
+    Entry(sp<Entry<EntryKey, EntryValue> > e):
+            key(e->key), value(e->value), index(e->index), parent(e->parent), child(e->child) { }
+
+    EntryKey key;
+    EntryValue value;
+    ssize_t index;
+
+    sp<Entry<EntryKey, EntryValue> > parent;
+    sp<Entry<EntryKey, EntryValue> > child;
+}; // struct Entry
+
 template<typename K, typename V>
 class GenerationCache {
 public:
-    GenerationCache(uint32_t maxCapacity): mMaxCapacity(maxCapacity), mListener(NULL) { };
-    ~GenerationCache() { clear(); };
+    GenerationCache(uint32_t maxCapacity);
+    virtual ~GenerationCache();
 
     enum Capacity {
         kUnlimitedCapacity,
@@ -52,39 +127,64 @@
 
     uint32_t size() const;
 
+protected:
+    virtual GenerationCacheStorage<K, sp<Entry<K, V> > >* createStorage() = 0;
+    GenerationCacheStorage<K, sp<Entry<K, V> > >* mCache;
+
 private:
-    template<typename EntryKey, typename EntryValue>
-    struct Entry: public LightRefBase<Entry<EntryKey, EntryValue> > {
-        Entry() { }
-        Entry(const Entry<EntryKey, EntryValue>& e):
-                key(e.key), value(e.value), parent(e.parent), child(e.child) { }
-        Entry(sp<Entry<EntryKey, EntryValue> > e):
-                key(e->key), value(e->value), parent(e->parent), child(e->child) { }
-
-        EntryKey key;
-        EntryValue value;
-
-        sp<Entry<EntryKey, EntryValue> > parent;
-        sp<Entry<EntryKey, EntryValue> > child;
-    }; // struct Entry
-
     void addToCache(sp<Entry<K, V> > entry, K key, V value);
     void attachToCache(sp<Entry<K, V> > entry);
     void detachFromCache(sp<Entry<K, V> > entry);
 
+    V removeAt(ssize_t index);
+
     uint32_t mMaxCapacity;
 
     OnEntryRemoved<K, V>* mListener;
 
-    KeyedVector<K, sp<Entry<K, V> > > mCache;
-
     sp<Entry<K, V> > mOldest;
-    sp<Entry<K, V> > mYougest;
+    sp<Entry<K, V> > mYoungest;
 }; // class GenerationCache
 
 template<typename K, typename V>
+class GenerationSingleCache: public GenerationCache<K, V> {
+public:
+    GenerationSingleCache(uint32_t maxCapacity): GenerationCache<K, V>(maxCapacity) {
+        GenerationCache<K, V>::mCache = createStorage();
+    };
+    ~GenerationSingleCache() { }
+protected:
+    GenerationCacheStorage<K, sp<Entry<K, V> > >* createStorage() {
+        return new KeyedVectorStorage<K, sp<Entry<K, V> > >;
+    }
+}; // GenerationSingleCache
+
+template<typename K, typename V>
+class GenerationMultiCache: public GenerationCache<K, V> {
+public:
+    GenerationMultiCache(uint32_t maxCapacity): GenerationCache<K, V>(maxCapacity) {
+        GenerationCache<K, V>::mCache = createStorage();
+    };
+    ~GenerationMultiCache() { }
+protected:
+    GenerationCacheStorage<K, sp<Entry<K, V> > >* createStorage() {
+        return new SortedListStorage<K, sp<Entry<K, V> > >;
+    }
+}; // GenerationMultiCache
+
+template<typename K, typename V>
+GenerationCache<K, V>::GenerationCache(uint32_t maxCapacity): mMaxCapacity(maxCapacity), mListener(NULL) {
+};
+
+template<typename K, typename V>
+GenerationCache<K, V>::~GenerationCache() {
+    clear();
+    delete mCache;
+};
+
+template<typename K, typename V>
 uint32_t GenerationCache<K, V>::size() const {
-    return mCache.size();
+    return mCache->size();
 }
 
 template<typename K, typename V>
@@ -95,26 +195,26 @@
 template<typename K, typename V>
 void GenerationCache<K, V>::clear() {
     if (mListener) {
-        while (mCache.size() > 0) {
+        while (mCache->size() > 0) {
             removeOldest();
         }
     } else {
-        mCache.clear();
+        mCache->clear();
     }
-    mYougest.clear();
+    mYoungest.clear();
     mOldest.clear();
 }
 
 template<typename K, typename V>
 bool GenerationCache<K, V>::contains(K key) const {
-    return mCache.indexOfKey(key) >= 0;
+    return mCache->indexOfKey(key) >= 0;
 }
 
 template<typename K, typename V>
 V GenerationCache<K, V>::get(K key) {
-    ssize_t index = mCache.indexOfKey(key);
+    ssize_t index = mCache->indexOfKey(key);
     if (index >= 0) {
-        sp<Entry<K, V> > entry = mCache.valueAt(index);
+        sp<Entry<K, V> > entry = mCache->valueAt(index);
         if (entry.get()) {
             detachFromCache(entry);
             attachToCache(entry);
@@ -127,13 +227,13 @@
 
 template<typename K, typename V>
 void GenerationCache<K, V>::put(K key, V value) {
-    if (mMaxCapacity != kUnlimitedCapacity && mCache.size() >= mMaxCapacity) {
+    if (mMaxCapacity != kUnlimitedCapacity && mCache->size() >= mMaxCapacity) {
         removeOldest();
     }
 
-    ssize_t index = mCache.indexOfKey(key);
+    ssize_t index = mCache->indexOfKey(key);
     if (index >= 0) {
-        sp<Entry<K, V> > entry = mCache.valueAt(index);
+        sp<Entry<K, V> > entry = mCache->valueAt(index);
         detachFromCache(entry);
         addToCache(entry, key, value);
     } else {
@@ -146,31 +246,36 @@
 void GenerationCache<K, V>::addToCache(sp<Entry<K, V> > entry, K key, V value) {
     entry->key = key;
     entry->value = value;
-    mCache.add(key, entry);
+    entry->index = mCache->add(key, entry);
     attachToCache(entry);
 }
 
 template<typename K, typename V>
 V GenerationCache<K, V>::remove(K key) {
-    ssize_t index = mCache.indexOfKey(key);
+    ssize_t index = mCache->indexOfKey(key);
     if (index >= 0) {
-        sp<Entry<K, V> > entry = mCache.valueAt(index);
-        if (mListener) {
-            (*mListener)(entry->key, entry->value);
-        }
-        mCache.removeItemsAt(index, 1);
-        detachFromCache(entry);
-
-        return entry->value;
+        return removeAt(index);
     }
 
     return NULL;
 }
 
 template<typename K, typename V>
+V GenerationCache<K, V>::removeAt(ssize_t index) {
+    sp<Entry<K, V> > entry = mCache->valueAt(index);
+    if (mListener) {
+        (*mListener)(entry->key, entry->value);
+    }
+    mCache->removeItemsAt(index, 1);
+    detachFromCache(entry);
+
+    return entry->value;
+}
+
+template<typename K, typename V>
 V GenerationCache<K, V>::removeOldest() {
     if (mOldest.get()) {
-        return remove(mOldest->key);
+        return removeAt(mOldest->index);
     }
 
     return NULL;
@@ -178,12 +283,12 @@
 
 template<typename K, typename V>
 void GenerationCache<K, V>::attachToCache(sp<Entry<K, V> > entry) {
-    if (!mYougest.get()) {
-        mYougest = mOldest = entry;
+    if (!mYoungest.get()) {
+        mYoungest = mOldest = entry;
     } else {
-        entry->parent = mYougest;
-        mYougest->child = entry;
-        mYougest = entry;
+        entry->parent = mYoungest;
+        mYoungest->child = entry;
+        mYoungest = entry;
     }
 }
 
@@ -201,8 +306,8 @@
         mOldest = entry->child;
     }
 
-    if (mYougest == entry) {
-        mYougest = entry->parent;
+    if (mYoungest == entry) {
+        mYoungest = entry->parent;
     }
 
     entry->parent.clear();
diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp
index 0d3214d..7d85e7b 100644
--- a/libs/hwui/LayerCache.cpp
+++ b/libs/hwui/LayerCache.cpp
@@ -28,13 +28,12 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 LayerCache::LayerCache(uint32_t maxByteSize):
-        mCache(GenerationCache<LayerSize, Layer*>::kUnlimitedCapacity),
+        mCache(GenerationMultiCache<LayerSize, Layer*>::kUnlimitedCapacity),
         mSize(0), mMaxSize(maxByteSize) {
 }
 
 LayerCache::~LayerCache() {
-    mCache.setOnEntryRemovedListener(this);
-    mCache.clear();
+    clear();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/LayerCache.h b/libs/hwui/LayerCache.h
index 3696848..2d339fa 100644
--- a/libs/hwui/LayerCache.h
+++ b/libs/hwui/LayerCache.h
@@ -66,7 +66,7 @@
 private:
     void deleteLayer(Layer* layer);
 
-    GenerationCache<LayerSize, Layer*> mCache;
+    GenerationMultiCache<LayerSize, Layer*> mCache;
 
     uint32_t mSize;
     uint32_t mMaxSize;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 9f2cc24..0ade173 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -52,7 +52,7 @@
 #define FV(x, y, u, v) { { x, y }, { u, v } }
 
 // Debug
-#ifdef DEBUG_LAYERS
+#if DEBUG_LAYERS
     #define LAYER_LOGD(...) LOGD(__VA_ARGS__)
 #else
     #define LAYER_LOGD(...)
diff --git a/libs/hwui/SortedList.cpp b/libs/hwui/SortedList.cpp
new file mode 100644
index 0000000..05adff5
--- /dev/null
+++ b/libs/hwui/SortedList.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SortedList.h"
+
+namespace android {
+namespace uirenderer {
+
+SortedListImpl::SortedListImpl(size_t itemSize, uint32_t flags) :
+    VectorImpl(itemSize, flags) {
+}
+
+SortedListImpl::SortedListImpl(const VectorImpl& rhs) :
+    VectorImpl(rhs) {
+}
+
+SortedListImpl::~SortedListImpl() {
+}
+
+SortedListImpl& SortedListImpl::operator =(const SortedListImpl& rhs) {
+    return static_cast<SortedListImpl&> (VectorImpl::operator =(
+            static_cast<const VectorImpl&> (rhs)));
+}
+
+ssize_t SortedListImpl::indexOf(const void* item) const {
+    return _indexOrderOf(item);
+}
+
+size_t SortedListImpl::orderOf(const void* item) const {
+    size_t o;
+    _indexOrderOf(item, &o);
+    return o;
+}
+
+ssize_t SortedListImpl::_indexOrderOf(const void* item, size_t* order) const {
+    // binary search
+    ssize_t err = NAME_NOT_FOUND;
+    ssize_t l = 0;
+    ssize_t h = size() - 1;
+    ssize_t mid;
+    const void* a = arrayImpl();
+    const size_t s = itemSize();
+    while (l <= h) {
+        mid = l + (h - l) / 2;
+        const void* const curr = reinterpret_cast<const char *> (a) + (mid * s);
+        const int c = do_compare(curr, item);
+        if (c == 0) {
+            err = l = mid;
+            break;
+        } else if (c < 0) {
+            l = mid + 1;
+        } else {
+            h = mid - 1;
+        }
+    }
+    if (order)
+        *order = l;
+    return err;
+}
+
+ssize_t SortedListImpl::add(const void* item) {
+    size_t order;
+    ssize_t index = _indexOrderOf(item, &order);
+    index = VectorImpl::insertAt(item, order, 1);
+    return index;
+}
+
+ssize_t SortedListImpl::merge(const VectorImpl& vector) {
+    // naive merge...
+    if (!vector.isEmpty()) {
+        const void* buffer = vector.arrayImpl();
+        const size_t is = itemSize();
+        size_t s = vector.size();
+        for (size_t i = 0; i < s; i++) {
+            ssize_t err = add(reinterpret_cast<const char*> (buffer) + i * is);
+            if (err < 0) {
+                return err;
+            }
+        }
+    }
+    return NO_ERROR;
+}
+
+ssize_t SortedListImpl::merge(const SortedListImpl& vector) {
+    // we've merging a sorted vector... nice!
+    ssize_t err = NO_ERROR;
+    if (!vector.isEmpty()) {
+        // first take care of the case where the vectors are sorted together
+        if (do_compare(vector.itemLocation(vector.size() - 1), arrayImpl()) <= 0) {
+            err = VectorImpl::insertVectorAt(static_cast<const VectorImpl&> (vector), 0);
+        } else if (do_compare(vector.arrayImpl(), itemLocation(size() - 1)) >= 0) {
+            err = VectorImpl::appendVector(static_cast<const VectorImpl&> (vector));
+        } else {
+            // this could be made a little better
+            err = merge(static_cast<const VectorImpl&> (vector));
+        }
+    }
+    return err;
+}
+
+ssize_t SortedListImpl::remove(const void* item) {
+    ssize_t i = indexOf(item);
+    if (i >= 0) {
+        VectorImpl::removeItemsAt(i, 1);
+    }
+    return i;
+}
+
+}
+; // namespace uirenderer
+}
+; // namespace android
+
diff --git a/libs/hwui/SortedList.h b/libs/hwui/SortedList.h
new file mode 100644
index 0000000..13cb64d
--- /dev/null
+++ b/libs/hwui/SortedList.h
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_UI_SORTED_LIST_H
+#define ANDROID_UI_SORTED_LIST_H
+
+#include <utils/Vector.h>
+#include <utils/VectorImpl.h>
+
+namespace android {
+namespace uirenderer {
+
+class SortedListImpl: public VectorImpl {
+public:
+    SortedListImpl(size_t itemSize, uint32_t flags);
+    SortedListImpl(const VectorImpl& rhs);
+    virtual ~SortedListImpl();
+
+    SortedListImpl& operator =(const SortedListImpl& rhs);
+
+    ssize_t indexOf(const void* item) const;
+    size_t orderOf(const void* item) const;
+    ssize_t add(const void* item);
+    ssize_t merge(const VectorImpl& vector);
+    ssize_t merge(const SortedListImpl& vector);
+    ssize_t remove(const void* item);
+
+protected:
+    virtual int do_compare(const void* lhs, const void* rhs) const = 0;
+
+private:
+    ssize_t _indexOrderOf(const void* item, size_t* order = 0) const;
+
+    // these are made private, because they can't be used on a SortedList
+    // (they don't have an implementation either)
+    ssize_t add();
+    void pop();
+    void push();
+    void push(const void* item);
+    ssize_t insertVectorAt(const VectorImpl& vector, size_t index);
+    ssize_t appendVector(const VectorImpl& vector);
+    ssize_t insertArrayAt(const void* array, size_t index, size_t length);
+    ssize_t appendArray(const void* array, size_t length);
+    ssize_t insertAt(size_t where, size_t numItems = 1);
+    ssize_t insertAt(const void* item, size_t where, size_t numItems = 1);
+    ssize_t replaceAt(size_t index);
+    ssize_t replaceAt(const void* item, size_t index);
+}; // class SortedListImpl
+
+template<class TYPE>
+class SortedList: private SortedListImpl {
+public:
+    typedef TYPE value_type;
+
+    SortedList();
+    SortedList(const SortedList<TYPE>& rhs);
+    virtual ~SortedList();
+
+    const SortedList<TYPE>& operator =(const SortedList<TYPE>& rhs) const;
+    SortedList<TYPE>& operator =(const SortedList<TYPE>& rhs);
+
+    inline void clear() {
+        VectorImpl::clear();
+    }
+
+    inline size_t size() const {
+        return VectorImpl::size();
+    }
+
+    inline bool isEmpty() const {
+        return VectorImpl::isEmpty();
+    }
+
+    inline size_t capacity() const {
+        return VectorImpl::capacity();
+    }
+
+    inline ssize_t setCapacity(size_t size) {
+        return VectorImpl::setCapacity(size);
+    }
+
+    inline const TYPE* array() const;
+
+    TYPE* editArray();
+
+    ssize_t indexOf(const TYPE& item) const;
+
+    size_t orderOf(const TYPE& item) const;
+
+    inline const TYPE& operator [](size_t index) const;
+    inline const TYPE& itemAt(size_t index) const;
+    const TYPE& top() const;
+    const TYPE& mirrorItemAt(ssize_t index) const;
+
+    ssize_t add(const TYPE& item);
+
+    TYPE& editItemAt(size_t index) {
+        return *(static_cast<TYPE *> (VectorImpl::editItemLocation(index)));
+    }
+
+    ssize_t merge(const Vector<TYPE>& vector);
+    ssize_t merge(const SortedList<TYPE>& vector);
+
+    ssize_t remove(const TYPE&);
+
+    inline ssize_t removeItemsAt(size_t index, size_t count = 1);
+    inline ssize_t removeAt(size_t index) {
+        return removeItemsAt(index);
+    }
+
+protected:
+    virtual void do_construct(void* storage, size_t num) const;
+    virtual void do_destroy(void* storage, size_t num) const;
+    virtual void do_copy(void* dest, const void* from, size_t num) const;
+    virtual void do_splat(void* dest, const void* item, size_t num) const;
+    virtual void do_move_forward(void* dest, const void* from, size_t num) const;
+    virtual void
+    do_move_backward(void* dest, const void* from, size_t num) const;
+    virtual int do_compare(const void* lhs, const void* rhs) const;
+};
+
+template<class TYPE> inline SortedList<TYPE>::SortedList() :
+    SortedListImpl(sizeof(TYPE), ((traits<TYPE>::has_trivial_ctor ? HAS_TRIVIAL_CTOR : 0)
+            | (traits<TYPE>::has_trivial_dtor ? HAS_TRIVIAL_DTOR : 0)
+            | (traits<TYPE>::has_trivial_copy ? HAS_TRIVIAL_COPY : 0))) {
+}
+
+template<class TYPE> inline SortedList<TYPE>::SortedList(const SortedList<TYPE>& rhs) :
+    SortedListImpl(rhs) {
+}
+
+template<class TYPE> inline SortedList<TYPE>::~SortedList() {
+    finish_vector();
+}
+
+template<class TYPE> inline SortedList<TYPE>& SortedList<TYPE>::operator =(
+        const SortedList<TYPE>& rhs) {
+    SortedListImpl::operator =(rhs);
+    return *this;
+}
+
+template<class TYPE> inline const SortedList<TYPE>& SortedList<TYPE>::operator =(const SortedList<
+        TYPE>& rhs) const {
+    SortedListImpl::operator =(rhs);
+    return *this;
+}
+
+template<class TYPE> inline const TYPE* SortedList<TYPE>::array() const {
+    return static_cast<const TYPE *> (arrayImpl());
+}
+
+template<class TYPE> inline TYPE* SortedList<TYPE>::editArray() {
+    return static_cast<TYPE *> (editArrayImpl());
+}
+
+template<class TYPE> inline const TYPE& SortedList<TYPE>::operator[](size_t index) const {
+    assert( index<size() );
+    return *(array() + index);
+}
+
+template<class TYPE> inline const TYPE& SortedList<TYPE>::itemAt(size_t index) const {
+    return operator[](index);
+}
+
+template<class TYPE> inline const TYPE& SortedList<TYPE>::mirrorItemAt(ssize_t index) const {
+    assert( (index>0 ? index : -index)<size() );
+    return *(array() + ((index < 0) ? (size() - index) : index));
+}
+
+template<class TYPE> inline const TYPE& SortedList<TYPE>::top() const {
+    return *(array() + size() - 1);
+}
+
+template<class TYPE> inline ssize_t SortedList<TYPE>::add(const TYPE& item) {
+    return SortedListImpl::add(&item);
+}
+
+template<class TYPE> inline ssize_t SortedList<TYPE>::indexOf(const TYPE& item) const {
+    return SortedListImpl::indexOf(&item);
+}
+
+template<class TYPE> inline size_t SortedList<TYPE>::orderOf(const TYPE& item) const {
+    return SortedListImpl::orderOf(&item);
+}
+
+template<class TYPE> inline ssize_t SortedList<TYPE>::merge(const Vector<TYPE>& vector) {
+    return SortedListImpl::merge(reinterpret_cast<const VectorImpl&> (vector));
+}
+
+template<class TYPE> inline ssize_t SortedList<TYPE>::merge(const SortedList<TYPE>& vector) {
+    return SortedListImpl::merge(reinterpret_cast<const SortedListImpl&> (vector));
+}
+
+template<class TYPE> inline ssize_t SortedList<TYPE>::remove(const TYPE& item) {
+    return SortedListImpl::remove(&item);
+}
+
+template<class TYPE> inline ssize_t SortedList<TYPE>::removeItemsAt(size_t index, size_t count) {
+    return VectorImpl::removeItemsAt(index, count);
+}
+
+template<class TYPE>
+void SortedList<TYPE>::do_construct(void* storage, size_t num) const {
+    construct_type(reinterpret_cast<TYPE*> (storage), num);
+}
+
+template<class TYPE>
+void SortedList<TYPE>::do_destroy(void* storage, size_t num) const {
+    destroy_type(reinterpret_cast<TYPE*> (storage), num);
+}
+
+template<class TYPE>
+void SortedList<TYPE>::do_copy(void* dest, const void* from, size_t num) const {
+    copy_type(reinterpret_cast<TYPE*> (dest), reinterpret_cast<const TYPE*> (from), num);
+}
+
+template<class TYPE>
+void SortedList<TYPE>::do_splat(void* dest, const void* item, size_t num) const {
+    splat_type(reinterpret_cast<TYPE*> (dest), reinterpret_cast<const TYPE*> (item), num);
+}
+
+template<class TYPE>
+void SortedList<TYPE>::do_move_forward(void* dest, const void* from, size_t num) const {
+    move_forward_type(reinterpret_cast<TYPE*> (dest), reinterpret_cast<const TYPE*> (from), num);
+}
+
+template<class TYPE>
+void SortedList<TYPE>::do_move_backward(void* dest, const void* from, size_t num) const {
+    move_backward_type(reinterpret_cast<TYPE*> (dest), reinterpret_cast<const TYPE*> (from), num);
+}
+
+template<class TYPE>
+int SortedList<TYPE>::do_compare(const void* lhs, const void* rhs) const {
+    return compare_type(*reinterpret_cast<const TYPE*> (lhs), *reinterpret_cast<const TYPE*> (rhs));
+}
+
+}
+; // namespace uirenderer
+}
+; // namespace android
+
+#endif // ANDROID_UI_SORTED_LIST_H
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index 612f04e..460284e 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -28,7 +28,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 TextureCache::TextureCache(uint32_t maxByteSize):
-        mCache(GenerationCache<SkBitmap*, Texture*>::kUnlimitedCapacity),
+        mCache(GenerationSingleCache<SkBitmap*, Texture*>::kUnlimitedCapacity),
         mSize(0), mMaxSize(maxByteSize) {
     mCache.setOnEntryRemovedListener(this);
 }
diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h
index bed1191..a620876 100644
--- a/libs/hwui/TextureCache.h
+++ b/libs/hwui/TextureCache.h
@@ -78,7 +78,7 @@
      */
     void generateTexture(SkBitmap* bitmap, Texture* texture, bool regenerate = false);
 
-    GenerationCache<SkBitmap*, Texture*> mCache;
+    GenerationSingleCache<SkBitmap*, Texture*> mCache;
 
     uint32_t mSize;
     uint32_t mMaxSize;