Async type creation.

Change-Id: I4d98446fabbf7e8a98c97f85b573a58c8a0c58c2
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 97ce7dc..8f1f273 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -178,17 +178,9 @@
         rsnElementGetSubElements(mContext, id, IDs, names);
     }
 
-    native void rsnTypeBegin(int con, int elementID);
-    synchronized void nTypeBegin(int elementID) {
-        rsnTypeBegin(mContext, elementID);
-    }
-    native void rsnTypeAdd(int con, int dim, int val);
-    synchronized void nTypeAdd(int dim, int val) {
-        rsnTypeAdd(mContext, dim, val);
-    }
-    native int  rsnTypeCreate(int con);
-    synchronized int nTypeCreate() {
-        return rsnTypeCreate(mContext);
+    native int rsnTypeCreate(int con, int eid, int[] dims, int[] vals);
+    synchronized int nTypeCreate(int eid, int[] dims, int[] vals) {
+        return rsnTypeCreate(mContext, eid, dims, vals);
     }
     native void rsnTypeGetNativeData(int con, int id, int[] typeData);
     synchronized void nTypeGetNativeData(int id, int[] typeData) {
diff --git a/graphics/java/android/renderscript/Type.java b/graphics/java/android/renderscript/Type.java
index 0b3db69..caa8b13 100644
--- a/graphics/java/android/renderscript/Type.java
+++ b/graphics/java/android/renderscript/Type.java
@@ -132,7 +132,8 @@
 
     public static class Builder {
         RenderScript mRS;
-        Entry[] mEntries;
+        Dimension[] mDimensions;
+        int[] mDimensionValues;
         int mEntryCount;
         Element mElement;
 
@@ -147,7 +148,8 @@
             }
 
             mRS = rs;
-            mEntries = new Entry[4];
+            mDimensions = new Dimension[4];
+            mDimensionValues = new int[4];
             mElement = e;
         }
 
@@ -155,46 +157,45 @@
             if(value < 1) {
                 throw new IllegalArgumentException("Values of less than 1 for Dimensions are not valid.");
             }
-            if(mEntries.length >= mEntryCount) {
-                Entry[] en = new Entry[mEntryCount + 8];
-                System.arraycopy(mEntries, 0, en, 0, mEntries.length);
-                mEntries = en;
+            if(mDimensions.length >= mEntryCount) {
+                Dimension[] dn = new Dimension[mEntryCount + 8];
+                System.arraycopy(mDimensions, 0, dn, 0, mEntryCount);
+                mDimensions = dn;
+
+                int[] in = new int[mEntryCount + 8];
+                System.arraycopy(mDimensionValues, 0, in, 0, mEntryCount);
+                mDimensionValues = in;
             }
-            mEntries[mEntryCount] = new Entry();
-            mEntries[mEntryCount].mDim = d;
-            mEntries[mEntryCount].mValue = value;
+            mDimensions[mEntryCount] = d;
+            mDimensionValues[mEntryCount] = value;
             mEntryCount++;
         }
 
-        static synchronized Type internalCreate(RenderScript rs, Builder b) {
-            rs.nTypeBegin(b.mElement.mID);
-            for (int ct=0; ct < b.mEntryCount; ct++) {
-                Entry en = b.mEntries[ct];
-                rs.nTypeAdd(en.mDim.mID, en.mValue);
-            }
-            int id = rs.nTypeCreate();
-            return new Type(id, rs);
-        }
-
         public Type create() {
-            Type t = internalCreate(mRS, this);
+            int dims[] = new int[mEntryCount];
+            for (int ct=0; ct < mEntryCount; ct++) {
+                dims[ct] = mDimensions[ct].mID;
+            }
+
+            int id = mRS.nTypeCreate(mElement.getID(), dims, mDimensionValues);
+            Type t = new Type(id, mRS);
             t.mElement = mElement;
 
             for(int ct=0; ct < mEntryCount; ct++) {
-                if(mEntries[ct].mDim == Dimension.X) {
-                    t.mDimX = mEntries[ct].mValue;
+                if(mDimensions[ct] == Dimension.X) {
+                    t.mDimX = mDimensionValues[ct];
                 }
-                if(mEntries[ct].mDim == Dimension.Y) {
-                    t.mDimY = mEntries[ct].mValue;
+                if(mDimensions[ct] == Dimension.Y) {
+                    t.mDimY = mDimensionValues[ct];
                 }
-                if(mEntries[ct].mDim == Dimension.Z) {
-                    t.mDimZ = mEntries[ct].mValue;
+                if(mDimensions[ct] == Dimension.Z) {
+                    t.mDimZ = mDimensionValues[ct];
                 }
-                if(mEntries[ct].mDim == Dimension.LOD) {
-                    t.mDimLOD = mEntries[ct].mValue != 0;
+                if(mDimensions[ct] == Dimension.LOD) {
+                    t.mDimLOD = mDimensionValues[ct] != 0;
                 }
-                if(mEntries[ct].mDim == Dimension.FACE) {
-                    t.mDimFaces = mEntries[ct].mValue != 0;
+                if(mDimensions[ct] == Dimension.FACE) {
+                    t.mDimFaces = mDimensionValues[ct] != 0;
                 }
             }
             t.calcElementCount();
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index ce2a40c..d9ff62d 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -112,7 +112,7 @@
 nObjDestroy(JNIEnv *_env, jobject _this, RsContext con, jint obj)
 {
     LOG_API("nObjDestroy, con(%p) obj(%p)", con, (void *)obj);
-    rsObjDestroy(con, (void *)obj);
+    rsObjDestroy(con, (uint32_t)obj);
 }
 
 
@@ -336,25 +336,21 @@
 
 // -----------------------------------
 
-static void
-nTypeBegin(JNIEnv *_env, jobject _this, RsContext con, jint eID)
+static int
+nTypeCreate(JNIEnv *_env, jobject _this, RsContext con, RsElement eid, jintArray _dims, jintArray _dimValues)
 {
-    LOG_API("nTypeBegin, con(%p) e(%p)", con, (RsElement)eID);
-    rsTypeBegin(con, (RsElement)eID);
-}
-
-static void
-nTypeAdd(JNIEnv *_env, jobject _this, RsContext con, jint dim, jint val)
-{
-    LOG_API("nTypeAdd, con(%p) dim(%i), val(%i)", con, dim, val);
-    rsTypeAdd(con, (RsDimension)dim, val);
-}
-
-static jint
-nTypeCreate(JNIEnv *_env, jobject _this, RsContext con)
-{
+    int count = _env->GetArrayLength(_dims);
     LOG_API("nTypeCreate, con(%p)", con);
-    return (jint)rsTypeCreate(con);
+
+    jint *dimPtr = _env->GetIntArrayElements(_dims, NULL);
+    jint *dimValPtr = _env->GetIntArrayElements(_dimValues, NULL);
+
+    jint id = (jint)rsaTypeCreate(con, (RsElement)eid, count,
+                                  (RsDimension *)dimPtr, (uint32_t *)dimValPtr);
+
+    _env->ReleaseIntArrayElements(_dims, dimPtr, JNI_ABORT);
+    _env->ReleaseIntArrayElements(_dimValues, dimValPtr, JNI_ABORT);
+    return (jint)id;
 }
 
 static void
@@ -1261,9 +1257,7 @@
 {"rsnElementGetNativeData",          "(II[I)V",                               (void*)nElementGetNativeData },
 {"rsnElementGetSubElements",         "(II[I[Ljava/lang/String;)V",            (void*)nElementGetSubElements },
 
-{"rsnTypeBegin",                     "(II)V",                                 (void*)nTypeBegin },
-{"rsnTypeAdd",                       "(III)V",                                (void*)nTypeAdd },
-{"rsnTypeCreate",                    "(I)I",                                  (void*)nTypeCreate },
+{"rsnTypeCreate",                    "(II[I[I)I",                             (void*)nTypeCreate },
 {"rsnTypeGetNativeData",             "(II[I)V",                               (void*)nTypeGetNativeData },
 
 {"rsnAllocationCreateTyped",         "(II)I",                                 (void*)nAllocationCreateTyped },
diff --git a/libs/rs/RenderScript.h b/libs/rs/RenderScript.h
index da8edbe..e63cc9b 100644
--- a/libs/rs/RenderScript.h
+++ b/libs/rs/RenderScript.h
@@ -27,6 +27,8 @@
 //////////////////////////////////////////////////////
 //
 
+typedef void * RsAsyncVoidPtr;
+
 typedef void * RsAdapter1D;
 typedef void * RsAdapter2D;
 typedef void * RsAllocation;
@@ -285,6 +287,11 @@
 } RsScriptCall;
 
 
+// Async commands for returning new IDS
+void * rsaTypeCreate(RsContext, RsElement, uint32_t dimCount,
+                     const RsDimension *dims, const uint32_t *vals);
+
+
 #ifndef NO_RS_FUNCS
 #include "rsgApiFuncDecl.h"
 #endif
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index 27bb006..eb2942e 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -64,7 +64,7 @@
 	}
 
 ObjDestroy {
-	param void *obj
+	param RsAsyncVoidPtr objPtr
 	}
 
 ElementCreate {
@@ -97,18 +97,6 @@
 	param uint32_t dataSize
 	}
 
-TypeBegin {
-	param RsElement type
-	}
-
-TypeAdd {
-	param RsDimension dim
-	param size_t value
-	}
-
-TypeCreate {
-	ret RsType
-	}
 
 TypeGetNativeData {
 	param RsType type
@@ -135,8 +123,8 @@
 
 AllocationCreateBitmapRef {
 	param RsType type
-	param void * bmpPtr
-	param void * callbackData
+	param RsAsyncVoidPtr bmpPtr
+	param RsAsyncVoidPtr callbackData
 	param RsBitmapCallback_t callback
 	ret RsAllocation
 	}
diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
index 172d07d..775fdf7 100644
--- a/libs/rs/rsAllocation.cpp
+++ b/libs/rs/rsAllocation.cpp
@@ -794,13 +794,9 @@
     const Element *dst = static_cast<const Element *>(_dst);
 
     //LOGE("%p rsi_AllocationCreateFromBitmap %i %i %i", rsc, w, h, genMips);
-    rsi_TypeBegin(rsc, _dst);
-    rsi_TypeAdd(rsc, RS_DIMENSION_X, w);
-    rsi_TypeAdd(rsc, RS_DIMENSION_Y, h);
-    if (genMips) {
-        rsi_TypeAdd(rsc, RS_DIMENSION_LOD, 1);
-    }
-    RsType type = rsi_TypeCreate(rsc);
+    RsDimension dims[] = {RS_DIMENSION_X, RS_DIMENSION_Y, RS_DIMENSION_LOD};
+    uint32_t dimValues[] = {w, h, genMips};
+    RsType type = rsaTypeCreate(rsc, _dst, 3, dims, dimValues);
 
     RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, type);
     Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc);
diff --git a/libs/rs/rsAllocation.h b/libs/rs/rsAllocation.h
index 24e245f..12cf832 100644
--- a/libs/rs/rsAllocation.h
+++ b/libs/rs/rsAllocation.h
@@ -30,8 +30,6 @@
     // The graphics equilivent of malloc.  The allocation contains a structure of elements.
 
 public:
-    // By policy this allocation will hold a pointer to the type
-    // but will not destroy it on destruction.
     Allocation(Context *rsc, const Type *);
     Allocation(Context *rsc, const Type *, void *bmp, void *callbackData, RsBitmapCallback_t callback);
 
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index be8fb0e..4dd074e 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -976,9 +976,9 @@
     (*name) = ob->getName();
 }
 
-void rsi_ObjDestroy(Context *rsc, void *obj)
+void rsi_ObjDestroy(Context *rsc, void *optr)
 {
-    ObjectBase *ob = static_cast<ObjectBase *>(obj);
+    ObjectBase *ob = static_cast<ObjectBase *>(optr);
     rsc->removeName(ob);
     ob->decUserRef();
 }
diff --git a/libs/rs/rsLocklessFifo.cpp b/libs/rs/rsLocklessFifo.cpp
index 019ea72..10b38af 100644
--- a/libs/rs/rsLocklessFifo.cpp
+++ b/libs/rs/rsLocklessFifo.cpp
@@ -15,6 +15,8 @@
  */
 
 #include "rsLocklessFifo.h"
+#include "utils/Timers.h"
+#include "utils/StopWatch.h"
 
 using namespace android;
 using namespace android::renderscript;
@@ -115,6 +117,10 @@
     if (mInShutdown) {
         return;
     }
+
+    //char buf[1024];
+    //sprintf(buf, "RenderScript LocklessCommandFifo::commitSync  %p %i  %i", this, command, sizeInBytes);
+    //StopWatch compileTimer(buf);
     commit(command, sizeInBytes);
     flush();
 }
diff --git a/libs/rs/rsObjectBase.cpp b/libs/rs/rsObjectBase.cpp
index 124d5e6..e4b07c4 100644
--- a/libs/rs/rsObjectBase.cpp
+++ b/libs/rs/rsObjectBase.cpp
@@ -25,16 +25,20 @@
 using namespace android;
 using namespace android::renderscript;
 
+pthread_mutex_t ObjectBase::gObjectInitMutex = PTHREAD_MUTEX_INITIALIZER;
+
 ObjectBase::ObjectBase(Context *rsc)
 {
     mUserRefCount = 0;
     mSysRefCount = 0;
-    mRSC = NULL;
+    mRSC = rsc;
     mNext = NULL;
     mPrev = NULL;
     mAllocFile = __FILE__;
     mAllocLine = __LINE__;
-    setContext(rsc);
+
+    rsAssert(rsc);
+    add();
 }
 
 ObjectBase::~ObjectBase()
@@ -56,24 +60,19 @@
     }
 }
 
-void ObjectBase::setContext(Context *rsc)
-{
-    if (mRSC) {
-        remove();
-    }
-    rsAssert(rsc);
-    mRSC = rsc;
-    if (rsc) {
-        add();
-    }
-}
-
 void ObjectBase::incUserRef() const
 {
-    mUserRefCount ++;
+    lockUserRef();
+    mUserRefCount++;
+    unlockUserRef();
     //LOGV("ObjectBase %p inc ref %i", this, mUserRefCount);
 }
 
+void ObjectBase::prelockedIncUserRef() const
+{
+    mUserRefCount++;
+}
+
 void ObjectBase::incSysRef() const
 {
     mSysRefCount ++;
@@ -83,10 +82,20 @@
 bool ObjectBase::checkDelete() const
 {
     if (!(mSysRefCount | mUserRefCount)) {
+        lockUserRef();
+
+        // Recheck the user ref count since it can be incremented from other threads.
+        if (mUserRefCount) {
+            unlockUserRef();
+            return false;
+        }
+
         if (mRSC && mRSC->props.mLogObjects) {
             dumpLOGV("checkDelete");
         }
         delete this;
+
+        unlockUserRef();
         return true;
     }
     return false;
@@ -94,17 +103,25 @@
 
 bool ObjectBase::decUserRef() const
 {
+    lockUserRef();
     rsAssert(mUserRefCount > 0);
-    mUserRefCount --;
     //dumpLOGV("decUserRef");
-    return checkDelete();
+    mUserRefCount--;
+    unlockUserRef();
+    bool ret = checkDelete();
+    return ret;
 }
 
 bool ObjectBase::zeroUserRef() const
 {
+    lockUserRef();
+    // This can only happen during cleanup and is therefore
+    // thread safe.
     mUserRefCount = 0;
     //dumpLOGV("zeroUserRef");
-    return checkDelete();
+    unlockUserRef();
+    bool ret = checkDelete();
+    return ret;
 }
 
 bool ObjectBase::decSysRef() const
@@ -125,8 +142,20 @@
     mName.setTo(name, len);
 }
 
+void ObjectBase::lockUserRef()
+{
+    pthread_mutex_lock(&gObjectInitMutex);
+}
+
+void ObjectBase::unlockUserRef()
+{
+    pthread_mutex_unlock(&gObjectInitMutex);
+}
+
 void ObjectBase::add() const
 {
+    pthread_mutex_lock(&gObjectInitMutex);
+
     rsAssert(!mNext);
     rsAssert(!mPrev);
     //LOGV("calling add  rsc %p", mRSC);
@@ -135,16 +164,22 @@
         mRSC->mObjHead->mPrev = this;
     }
     mRSC->mObjHead = this;
+
+    pthread_mutex_unlock(&gObjectInitMutex);
 }
 
 void ObjectBase::remove() const
 {
+    // Should be within gObjectInitMutex lock
+    // lock will be from checkDelete a few levels up in the stack.
+
     //LOGV("calling remove  rsc %p", mRSC);
     if (!mRSC) {
         rsAssert(!mPrev);
         rsAssert(!mNext);
         return;
     }
+
     if (mRSC->mObjHead == this) {
         mRSC->mObjHead = mNext;
     }
@@ -160,6 +195,8 @@
 
 void ObjectBase::zeroAllUserRef(Context *rsc)
 {
+    lockUserRef();
+
     if (rsc->props.mLogObjects) {
         LOGV("Forcing release of all outstanding user refs.");
     }
@@ -182,10 +219,14 @@
         LOGV("Objects remaining.");
         dumpAll(rsc);
     }
+
+    unlockUserRef();
 }
 
 void ObjectBase::dumpAll(Context *rsc)
 {
+    lockUserRef();
+
     LOGV("Dumping all objects");
     const ObjectBase * o = rsc->mObjHead;
     while (o) {
@@ -193,17 +234,23 @@
         o->dumpLOGV("  ");
         o = o->mNext;
     }
+
+    unlockUserRef();
 }
 
 bool ObjectBase::isValid(const Context *rsc, const ObjectBase *obj)
 {
+    lockUserRef();
+
     const ObjectBase * o = rsc->mObjHead;
     while (o) {
         if (o == obj) {
+            unlockUserRef();
             return true;
         }
         o = o->mNext;
     }
+    unlockUserRef();
     return false;
 }
 
diff --git a/libs/rs/rsObjectBase.h b/libs/rs/rsObjectBase.h
index 59fb4a6..8d1ace1 100644
--- a/libs/rs/rsObjectBase.h
+++ b/libs/rs/rsObjectBase.h
@@ -39,6 +39,7 @@
     void incUserRef() const;
     bool decUserRef() const;
     bool zeroUserRef() const;
+    void prelockedIncUserRef() const;
 
     const char * getName() const {
         return mName.string();
@@ -47,7 +48,6 @@
     void setName(const char *, uint32_t len);
 
     Context * getContext() const {return mRSC;}
-    void setContext(Context *);
 
     static void zeroAllUserRef(Context *rsc);
     static void dumpAll(Context *rsc);
@@ -58,12 +58,17 @@
 
     static bool isValid(const Context *rsc, const ObjectBase *obj);
 
+    static void lockUserRef();
+    static void unlockUserRef();
+
 protected:
     const char *mAllocFile;
     uint32_t mAllocLine;
     Context *mRSC;
 
 private:
+    static pthread_mutex_t gObjectInitMutex;
+
     void add() const;
     void remove() const;
 
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index e60255a..a2910d7 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -529,8 +529,6 @@
 
     ss->runCompiler(rsc, s.get());
     s->incUserRef();
-    s->setContext(rsc);
-
     ss->clear(rsc);
     return s.get();
 }
diff --git a/libs/rs/rsType.cpp b/libs/rs/rsType.cpp
index e0716eb..27b1b4f 100644
--- a/libs/rs/rsType.cpp
+++ b/libs/rs/rsType.cpp
@@ -381,88 +381,6 @@
 namespace android {
 namespace renderscript {
 
-void rsi_TypeBegin(Context *rsc, RsElement vse)
-{
-    TypeState * stc = &rsc->mStateType;
-
-    stc->mX = 0;
-    stc->mY = 0;
-    stc->mZ = 0;
-    stc->mLOD = false;
-    stc->mFaces = false;
-    stc->mElement.set(static_cast<const Element *>(vse));
-}
-
-void rsi_TypeAdd(Context *rsc, RsDimension dim, size_t value)
-{
-    TypeState * stc = &rsc->mStateType;
-
-    if (dim < 0) {
-        //error
-        return;
-    }
-
-
-    switch (dim) {
-    case RS_DIMENSION_X:
-        stc->mX = value;
-        return;
-    case RS_DIMENSION_Y:
-        stc->mY = value;
-        return;
-    case RS_DIMENSION_Z:
-        stc->mZ = value;
-        return;
-    case RS_DIMENSION_FACE:
-        stc->mFaces = (value != 0);
-        return;
-    case RS_DIMENSION_LOD:
-        stc->mLOD = (value != 0);
-        return;
-    default:
-        break;
-    }
-
-    if ((dim < 0) || (dim > RS_DIMENSION_MAX)) {
-        LOGE("rsTypeAdd: Bad dimension");
-        //error
-        return;
-    }
-
-    // todo: implement array support
-
-}
-
-RsType rsi_TypeCreate(Context *rsc)
-{
-    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);
-    st->setDimY(stc->mY);
-    st->setDimZ(stc->mZ);
-    st->setElement(stc->mElement.get());
-    st->setDimLOD(stc->mLOD);
-    st->setDimFaces(stc->mFaces);
-    st->compute();
-    stc->mElement.clear();
-    stc->mTypes.push(st);
-    return st;
-}
-
 void rsi_TypeGetNativeData(Context *rsc, RsType type, uint32_t *typeData, uint32_t typeDataSize)
 {
     rsAssert(typeDataSize == 6);
@@ -483,3 +401,61 @@
 }
 }
 
+void * rsaTypeCreate(RsContext con, RsElement _e, uint32_t dimCount,
+                     const RsDimension *dims, const uint32_t *vals)
+{
+    Context *rsc = static_cast<Context *>(con);
+    Element *e = static_cast<Element *>(_e);
+    TypeState * stc = &rsc->mStateType;
+
+    uint32_t dimX = 0;
+    uint32_t dimY = 0;
+    uint32_t dimZ = 0;
+    uint32_t dimLOD = 0;
+    uint32_t dimFaces = 0;
+
+    for (uint32_t ct=0; ct < dimCount; ct++) {
+        switch(dims[ct]) {
+        case RS_DIMENSION_X: dimX = vals[ct]; break;
+        case RS_DIMENSION_Y: dimY = vals[ct]; break;
+        case RS_DIMENSION_Z: dimZ = vals[ct]; break;
+        case RS_DIMENSION_LOD: dimLOD = vals[ct]; break;
+        case RS_DIMENSION_FACE: dimFaces = vals[ct]; break;
+
+        default:
+            LOGE("rsaTypeCreate: Bad dimension");
+            rsAssert(0);
+        }
+    }
+
+    ObjectBase::lockUserRef();
+    for (uint32_t ct=0; ct < stc->mTypes.size(); ct++) {
+        Type *t = stc->mTypes[ct];
+        if (t->getElement() != e) continue;
+        if (t->getDimX() != dimX) continue;
+        if (t->getDimY() != dimY) continue;
+        if (t->getDimZ() != dimZ) continue;
+        if (t->getDimLOD() != dimLOD) continue;
+        if (t->getDimFaces() != dimFaces) continue;
+        t->prelockedIncUserRef();
+        ObjectBase::unlockUserRef();
+        return t;
+    }
+    ObjectBase::unlockUserRef();
+
+    Type * st = new Type(rsc);
+    st->incUserRef();
+    st->setDimX(dimX);
+    st->setDimY(dimY);
+    st->setDimZ(dimZ);
+    st->setElement(e);
+    st->setDimLOD(dimLOD);
+    st->setDimFaces(dimFaces);
+    st->compute();
+
+    ObjectBase::lockUserRef();
+    stc->mTypes.push(st);
+    ObjectBase::unlockUserRef();
+    return st;
+}
+
diff --git a/libs/rs/rsType.h b/libs/rs/rsType.h
index 891edd4..a0c77ab 100644
--- a/libs/rs/rsType.h
+++ b/libs/rs/rsType.h
@@ -134,14 +134,6 @@
     TypeState();
     ~TypeState();
 
-    size_t mX;
-    size_t mY;
-    size_t mZ;
-    uint32_t mLOD;
-    bool mFaces;
-    ObjectBaseRef<const Element> mElement;
-
-
     // Cache of all existing types.
     Vector<Type *> mTypes;
 };