Refcount 9-patches and properly handle GC events

This change adds refcounting of Res_png_9patch instances, the native
data structure used to represent 9-patches. The Dalvik NinePatch class
now holds a native pointer instead of a Dalvik byte[]. This pointer
is used whenever we need to draw the 9-patch (software or hardware.)

Since we are now tracking garbage collection of NinePatch objects
libhwui's PatchCache must keep a list of free blocks in the VBO
used to store the meshes.

This change also removes unnecessary instances tracking from
GLES20DisplayList. Bitmaps and 9-patches are refcounted at the
native level and do not need to be tracked by the Dalvik layer.

Change-Id: Ib8682d573a538aaf1945f8ec5a9bd5da5d16f74b
diff --git a/libs/hwui/PatchCache.h b/libs/hwui/PatchCache.h
index 1829b89..9f2c9a5 100644
--- a/libs/hwui/PatchCache.h
+++ b/libs/hwui/PatchCache.h
@@ -26,6 +26,7 @@
 #include "AssetAtlas.h"
 #include "Debug.h"
 #include "Patch.h"
+#include "utils/Pair.h"
 
 namespace android {
 namespace uirenderer {
@@ -74,10 +75,20 @@
         return mGenerationId;
     }
 
-private:
-    void clearCache();
-    void createVertexBuffer();
+    /**
+     * Removes the entries associated with the specified 9-patch. This is meant
+     * to be called from threads that are not the EGL context thread (GC thread
+     * on the VM side for instance.)
+     */
+    void removeDeferred(Res_png_9patch* patch);
 
+    /**
+     * Process deferred removals.
+     */
+    void clearGarbage();
+
+
+private:
     struct PatchDescription {
         PatchDescription(): mPatch(NULL), mBitmapWidth(0), mBitmapHeight(0),
                 mPixelWidth(0), mPixelHeight(0) {
@@ -91,6 +102,8 @@
 
         hash_t hash() const;
 
+        const Res_png_9patch* getPatch() const { return mPatch; }
+
         static int compare(const PatchDescription& lhs, const PatchDescription& rhs);
 
         bool operator==(const PatchDescription& other) const {
@@ -124,14 +137,50 @@
 
     }; // struct PatchDescription
 
+    /**
+     * A buffer block represents an empty range in the mesh buffer
+     * that can be used to store vertices.
+     *
+     * The patch cache maintains a linked-list of buffer blocks
+     * to track available regions of memory in the VBO.
+     */
+    struct BufferBlock {
+        BufferBlock(uint32_t offset, uint32_t size): offset(offset), size(size), next(NULL) {
+        }
+
+        uint32_t offset;
+        uint32_t size;
+
+        BufferBlock* next;
+    }; // struct BufferBlock
+
+    typedef Pair<const PatchDescription*, Patch*> patch_pair_t;
+
+    void clearCache();
+    void createVertexBuffer();
+
+    void setupMesh(Patch* newMesh, TextureVertex* vertices);
+
+    void remove(Vector<patch_pair_t>& patchesToRemove, Res_png_9patch* patch);
+
+#if DEBUG_PATCHES
+    void dumpFreeBlocks(const char* prefix);
+#endif
+
     uint32_t mMaxSize;
     uint32_t mSize;
 
     LruCache<PatchDescription, Patch*> mCache;
 
     GLuint mMeshBuffer;
+    // First available free block inside the mesh buffer
+    BufferBlock* mFreeBlocks;
 
     uint32_t mGenerationId;
+
+    // Garbage tracking, required to handle GC events on the VM side
+    Vector<Res_png_9patch*> mGarbage;
+    mutable Mutex mLock;
 }; // class PatchCache
 
 }; // namespace uirenderer