Implement type collapsing for Elements and Types.  Now if a user creates two or more identical objects we simply reuse the existing object rather than create a new one.
diff --git a/libs/rs/rsElement.cpp b/libs/rs/rsElement.cpp
index 207ad15..6288bc4 100644
--- a/libs/rs/rsElement.cpp
+++ b/libs/rs/rsElement.cpp
@@ -34,6 +34,12 @@
 
 Element::~Element()
 {
+    for (uint32_t ct = 0; ct < mRSC->mStateElement.mElements.size(); ct++) {
+        if (mRSC->mStateElement.mElements[ct] == this) {
+            mRSC->mStateElement.mElements.removeAt(ct);
+            break;
+        }
+    }
     clear();
 }
 
@@ -78,27 +84,62 @@
 }
 
 
-Element * Element::create(Context *rsc, RsDataType dt, RsDataKind dk,
+const Element * Element::create(Context *rsc, RsDataType dt, RsDataKind dk,
                             bool isNorm, uint32_t vecSize)
 {
+    // Look for an existing match.
+    for (uint32_t ct=0; ct < rsc->mStateElement.mElements.size(); ct++) {
+        const Element *ee = rsc->mStateElement.mElements[ct];
+        if (!ee->getFieldCount() &&
+            (ee->getComponent().getType() == dt) &&
+            (ee->getComponent().getKind() == dk) &&
+            (ee->getComponent().getIsNormalized() == isNorm) &&
+            (ee->getComponent().getVectorSize() == vecSize)) {
+            // Match
+            ee->incUserRef();
+            return ee;
+        }
+    }
+
     Element *e = new Element(rsc);
     e->mComponent.set(dt, dk, isNorm, vecSize);
     e->mBits = e->mComponent.getBits();
+    rsc->mStateElement.mElements.push(e);
     return e;
 }
 
-Element * Element::create(Context *rsc, size_t count, const Element **ein,
+const Element * Element::create(Context *rsc, size_t count, const Element **ein,
                             const char **nin, const size_t * lengths)
 {
+    // Look for an existing match.
+    for (uint32_t ct=0; ct < rsc->mStateElement.mElements.size(); ct++) {
+        const Element *ee = rsc->mStateElement.mElements[ct];
+        if (ee->getFieldCount() == count) {
+            bool match = true;
+            for (uint32_t i=0; i < count; i++) {
+                if ((ee->mFields[i].e.get() != ein[i]) ||
+                    (ee->mFields[i].name.length() != lengths[i]) ||
+                    (ee->mFields[i].name != nin[i])) {
+                    match = false;
+                    break;
+                }
+            }
+            if (match) {
+                ee->incUserRef();
+                return ee;
+            }
+        }
+    }
+
     Element *e = new Element(rsc);
     e->mFields = new ElementField_t [count];
     e->mFieldCount = count;
-
     for (size_t ct=0; ct < count; ct++) {
         e->mFields[ct].e.set(ein[ct]);
         e->mFields[ct].name.setTo(nin[ct], lengths[ct]);
     }
 
+    rsc->mStateElement.mElements.push(e);
     return e;
 }
 
@@ -168,6 +209,7 @@
 
 ElementState::~ElementState()
 {
+    rsAssert(!mElements.size());
 }
 
 
@@ -184,9 +226,9 @@
                             uint32_t vecSize)
 {
     //LOGE("rsi_ElementCreate %i %i %i %i", dt, dk, norm, vecSize);
-    Element *e = Element::create(rsc, dt, dk, norm, vecSize);
+    const Element *e = Element::create(rsc, dt, dk, norm, vecSize);
     e->incUserRef();
-    return e;
+    return (RsElement)e;
 }
 
 RsElement rsi_ElementCreate2(Context *rsc,
@@ -196,9 +238,9 @@
                              const size_t * nameLengths)
 {
     //LOGE("rsi_ElementCreate2 %i", count);
-    Element *e = Element::create(rsc, count, (const Element **)ein, names, nameLengths);
+    const Element *e = Element::create(rsc, count, (const Element **)ein, names, nameLengths);
     e->incUserRef();
-    return e;
+    return (RsElement)e;
 }
 
 
diff --git a/libs/rs/rsElement.h b/libs/rs/rsElement.h
index 777e8ee..02a1ca2 100644
--- a/libs/rs/rsElement.h
+++ b/libs/rs/rsElement.h
@@ -60,9 +60,9 @@
 
     void dumpLOGV(const char *prefix) const;
 
-    static Element * create(Context *rsc, RsDataType dt, RsDataKind dk,
+    static const Element * create(Context *rsc, RsDataType dt, RsDataKind dk,
                             bool isNorm, uint32_t vecSize);
-    static Element * create(Context *rsc, size_t count, const Element **,
+    static const Element * create(Context *rsc, size_t count, const Element **,
                             const char **, const size_t * lengths);
 
 protected:
@@ -89,6 +89,8 @@
     ElementState();
     ~ElementState();
 
+    // Cache of all existing elements.
+    Vector<const Element *> mElements;
 };
 
 
diff --git a/libs/rs/rsObjectBase.cpp b/libs/rs/rsObjectBase.cpp
index 89c5b00..677413e 100644
--- a/libs/rs/rsObjectBase.cpp
+++ b/libs/rs/rsObjectBase.cpp
@@ -191,6 +191,7 @@
     LOGV("Dumping all objects");
     const ObjectBase * o = rsc->mObjHead;
     while (o) {
+        LOGV(" Object %p", o);
         o->dumpLOGV("  ");
         o = o->mNext;
     }
diff --git a/libs/rs/rsObjectBase.h b/libs/rs/rsObjectBase.h
index f247022..bb03b87 100644
--- a/libs/rs/rsObjectBase.h
+++ b/libs/rs/rsObjectBase.h
@@ -56,6 +56,7 @@
 protected:
     const char *mAllocFile;
     uint32_t mAllocLine;
+    Context *mRSC;
 
 private:
     void add() const;
@@ -64,7 +65,6 @@
     bool checkDelete() const;
 
     char * mName;
-    Context *mRSC;
     mutable int32_t mSysRefCount;
     mutable int32_t mUserRefCount;
 
diff --git a/libs/rs/rsProgramVertex.cpp b/libs/rs/rsProgramVertex.cpp
index 28f13d4..a2b2df4 100644
--- a/libs/rs/rsProgramVertex.cpp
+++ b/libs/rs/rsProgramVertex.cpp
@@ -364,7 +364,7 @@
 
 void ProgramVertexState::init(Context *rsc, int32_t w, int32_t h)
 {
-    RsElement e = Element::create(rsc, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 1);
+    RsElement e = (RsElement) Element::create(rsc, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 1);
 
     rsi_TypeBegin(rsc, e);
     rsi_TypeAdd(rsc, RS_DIMENSION_X, 48);
diff --git a/libs/rs/rsType.cpp b/libs/rs/rsType.cpp
index 22a267a..9d24c6c 100644
--- a/libs/rs/rsType.cpp
+++ b/libs/rs/rsType.cpp
@@ -31,6 +31,12 @@
 
 Type::~Type()
 {
+    for (uint32_t ct = 0; ct < mRSC->mStateType.mTypes.size(); ct++) {
+        if (mRSC->mStateType.mTypes[ct] == this) {
+            mRSC->mStateType.mTypes.removeAt(ct);
+            break;
+        }
+    }
     if (mLODs) {
         delete [] mLODs;
     }
@@ -341,6 +347,18 @@
 {
     TypeState * stc = &rsc->mStateType;
 
+    for (uint32_t ct=0; ct < stc->mTypes.size(); ct++) {
+        Type *t = stc->mTypes[ct];
+        if (t->getElement() != stc->mElement.get()) continue;
+        if (t->getDimX() != stc->mX) continue;
+        if (t->getDimY() != stc->mY) continue;
+        if (t->getDimZ() != stc->mZ) continue;
+        if (t->getDimLOD() != stc->mLOD) continue;
+        if (t->getDimFaces() != stc->mFaces) continue;
+        t->incUserRef();
+        return t;
+    }
+
     Type * st = new Type(rsc);
     st->incUserRef();
     st->setDimX(stc->mX);
@@ -351,7 +369,7 @@
     st->setDimFaces(stc->mFaces);
     st->compute();
     stc->mElement.clear();
-
+    stc->mTypes.push(st);
     return st;
 }
 
diff --git a/libs/rs/rsType.h b/libs/rs/rsType.h
index 4fa4933..28e6274 100644
--- a/libs/rs/rsType.h
+++ b/libs/rs/rsType.h
@@ -137,6 +137,10 @@
     uint32_t mLOD;
     bool mFaces;
     ObjectBaseRef<const Element> mElement;
+
+
+    // Cache of all existing types.
+    Vector<Type *> mTypes;
 };