Refcounting in allocations.

Change-Id: Ida2dfb404b2cd832e622d981d73a938d5bc5b821
diff --git a/rsAllocation.cpp b/rsAllocation.cpp
index 6560101..d62fa55 100644
--- a/rsAllocation.cpp
+++ b/rsAllocation.cpp
@@ -234,6 +234,12 @@
         LOGE("Allocation::data called with mismatched size expected %i, got %i", size, sizeBytes);
         return;
     }
+
+    if (mType->getElement()->getHasReferences()) {
+        incRefs(data, sizeBytes / mType->getElement()->getSizeBytes());
+        decRefs(mPtr, sizeBytes / mType->getElement()->getSizeBytes());
+    }
+
     memcpy(mPtr, data, size);
     sendDirty();
     mUploadDefered = true;
@@ -256,6 +262,12 @@
         mType->dumpLOGV("type info");
         return;
     }
+
+    if (mType->getElement()->getHasReferences()) {
+        incRefs(data, count);
+        decRefs(ptr, count);
+    }
+
     memcpy(ptr, data, size);
     sendDirty();
     mUploadDefered = true;
@@ -279,6 +291,10 @@
 
     for (uint32_t line=yoff; line < (yoff+h); line++) {
         uint8_t * ptr = static_cast<uint8_t *>(mPtr);
+        if (mType->getElement()->getHasReferences()) {
+            incRefs(src, w);
+            decRefs(dst, w);
+        }
         memcpy(dst, src, lineSize);
         src += lineSize;
         dst += destW * eSize;
@@ -387,6 +403,32 @@
     }
 }
 
+void Allocation::incRefs(const void *ptr, size_t ct) const
+{
+    const uint8_t *p = static_cast<const uint8_t *>(ptr);
+    const Element *e = mType->getElement();
+    uint32_t stride = e->getSizeBytes();
+
+    while (ct > 0) {
+        e->incRefs(p);
+        ct --;
+        p += stride;
+    }
+}
+
+void Allocation::decRefs(const void *ptr, size_t ct) const
+{
+    const uint8_t *p = static_cast<const uint8_t *>(ptr);
+    const Element *e = mType->getElement();
+    uint32_t stride = e->getSizeBytes();
+
+    while (ct > 0) {
+        e->decRefs(p);
+        ct --;
+        p += stride;
+    }
+}
+
 /////////////////
 //