Merge "Remove ObjBaseRef from the hal struct"
diff --git a/driver/rsdFrameBuffer.cpp b/driver/rsdFrameBuffer.cpp
index 8c1b12d..bb07d29 100644
--- a/driver/rsdFrameBuffer.cpp
+++ b/driver/rsdFrameBuffer.cpp
@@ -33,11 +33,11 @@
     RsdFrameBufferObj *fbo = (RsdFrameBufferObj*)fb->mHal.drv;
 
     DrvAllocation *depth = NULL;
-    if (fb->mHal.state.depthTarget.get() != NULL) {
+    if (fb->mHal.state.depthTarget != NULL) {
         depth = (DrvAllocation *)fb->mHal.state.depthTarget->mHal.drv;
 
         if (depth->uploadDeferred) {
-            rsdAllocationSyncAll(rsc, fb->mHal.state.depthTarget.get(),
+            rsdAllocationSyncAll(rsc, fb->mHal.state.depthTarget,
                                  RS_ALLOCATION_USAGE_SCRIPT);
         }
     }
@@ -49,11 +49,11 @@
     // Now attach color targets
     for (uint32_t i = 0; i < fb->mHal.state.colorTargetsCount; i ++) {
         DrvAllocation *color = NULL;
-        if (fb->mHal.state.colorTargets[i].get() != NULL) {
+        if (fb->mHal.state.colorTargets[i] != NULL) {
             color = (DrvAllocation *)fb->mHal.state.colorTargets[i]->mHal.drv;
 
             if (color->uploadDeferred) {
-                rsdAllocationSyncAll(rsc, fb->mHal.state.colorTargets[i].get(),
+                rsdAllocationSyncAll(rsc, fb->mHal.state.colorTargets[i],
                                      RS_ALLOCATION_USAGE_SCRIPT);
             }
         }
@@ -79,10 +79,10 @@
     setColorAttachment(rsc, fb);
 
     RsdFrameBufferObj *fbo = (RsdFrameBufferObj *)fb->mHal.drv;
-    if (fb->mHal.state.colorTargets[0].get()) {
+    if (fb->mHal.state.colorTargets[0]) {
         fbo->setDimensions(fb->mHal.state.colorTargets[0]->getType()->getDimX(),
                            fb->mHal.state.colorTargets[0]->getType()->getDimY());
-    } else if (fb->mHal.state.depthTarget.get()) {
+    } else if (fb->mHal.state.depthTarget) {
         fbo->setDimensions(fb->mHal.state.depthTarget->getType()->getDimX(),
                            fb->mHal.state.depthTarget->getType()->getDimY());
     }
diff --git a/driver/rsdMeshObj.cpp b/driver/rsdMeshObj.cpp
index 019167b..24a7183 100644
--- a/driver/rsdMeshObj.cpp
+++ b/driver/rsdMeshObj.cpp
@@ -138,7 +138,7 @@
     }
 
     for (uint32_t ct=0; ct < mRSMesh->mHal.state.vertexBuffersCount; ct++) {
-        const Allocation *alloc = mRSMesh->mHal.state.vertexBuffers[ct].get();
+        const Allocation *alloc = mRSMesh->mHal.state.vertexBuffers[ct];
         DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
         if (drv->uploadDeferred) {
             rsdAllocationSyncAll(rsc, alloc, RS_ALLOCATION_USAGE_SCRIPT);
@@ -148,7 +148,7 @@
     // update attributes with either buffer information or data ptr based on their current state
     for (uint32_t ct=0; ct < mAttribCount; ct++) {
         uint32_t allocIndex = mAttribAllocationIndex[ct];
-        Allocation *alloc = mRSMesh->mHal.state.vertexBuffers[allocIndex].get();
+        Allocation *alloc = mRSMesh->mHal.state.vertexBuffers[allocIndex];
         DrvAllocation *drvAlloc = (DrvAllocation *)alloc->mHal.drv;
 
         if (drvAlloc->bufferID) {
@@ -163,8 +163,7 @@
     RsdVertexArray va(mAttribs, mAttribCount);
     va.setup(rsc);
 
-    Mesh::Primitive_t *prim = mRSMesh->mHal.state.primitives[primIndex];
-    const Allocation *idxAlloc = prim->mIndexBuffer.get();
+    const Allocation *idxAlloc = mRSMesh->mHal.state.indexBuffers[primIndex];
     if (idxAlloc) {
         DrvAllocation *drvAlloc = (DrvAllocation *)idxAlloc->mHal.drv;
         if (drvAlloc->uploadDeferred) {
@@ -190,7 +189,7 @@
 void RsdMeshObj::updateGLPrimitives() {
     mGLPrimitives = new uint32_t[mRSMesh->mHal.state.primitivesCount];
     for (uint32_t i = 0; i < mRSMesh->mHal.state.primitivesCount; i ++) {
-        switch (mRSMesh->mHal.state.primitives[i]->mPrimitive) {
+        switch (mRSMesh->mHal.state.primitives[i]) {
             case RS_PRIMITIVE_POINT:          mGLPrimitives[i] = GL_POINTS; break;
             case RS_PRIMITIVE_LINE:           mGLPrimitives[i] = GL_LINES; break;
             case RS_PRIMITIVE_LINE_STRIP:     mGLPrimitives[i] = GL_LINE_STRIP; break;
diff --git a/driver/rsdProgram.cpp b/driver/rsdProgram.cpp
index 27a6663..7556e50 100644
--- a/driver/rsdProgram.cpp
+++ b/driver/rsdProgram.cpp
@@ -43,7 +43,7 @@
 
 static void SyncProgramConstants(const Context *rsc, const Program *p) {
     for (uint32_t ct=0; ct < p->mHal.state.texturesCount; ct++) {
-        const Allocation *a = p->mHal.state.textures[ct].get();
+        const Allocation *a = p->mHal.state.textures[ct];
         if (!a) {
             continue;
         }
diff --git a/driver/rsdShader.cpp b/driver/rsdShader.cpp
index 16ff063..bdb60c2 100644
--- a/driver/rsdShader.cpp
+++ b/driver/rsdShader.cpp
@@ -69,7 +69,7 @@
     uint32_t attribCount = 0;
     uint32_t uniformCount = 0;
     for (uint32_t ct=0; ct < mRSProgram->mHal.state.inputElementsCount; ct++) {
-        initAddUserElement(mRSProgram->mHal.state.inputElements[ct].get(), mAttribNames, NULL, &attribCount, RS_SHADER_ATTR);
+        initAddUserElement(mRSProgram->mHal.state.inputElements[ct], mAttribNames, NULL, &attribCount, RS_SHADER_ATTR);
     }
     for (uint32_t ct=0; ct < mRSProgram->mHal.state.constantsCount; ct++) {
         initAddUserElement(mRSProgram->mHal.state.constantTypes[ct]->getElement(), mUniformNames, mUniformArraySizes, &uniformCount, RS_SHADER_UNI);
@@ -89,7 +89,7 @@
 String8 RsdShader::getGLSLInputString() const {
     String8 s;
     for (uint32_t ct=0; ct < mRSProgram->mHal.state.inputElementsCount; ct++) {
-        const Element *e = mRSProgram->mHal.state.inputElements[ct].get();
+        const Element *e = mRSProgram->mHal.state.inputElements[ct];
         for (uint32_t field=0; field < e->getFieldCount(); field++) {
             const Element *f = e->getField(field);
 
@@ -113,7 +113,7 @@
 
 void RsdShader::appendAttributes() {
     for (uint32_t ct=0; ct < mRSProgram->mHal.state.inputElementsCount; ct++) {
-        const Element *e = mRSProgram->mHal.state.inputElements[ct].get();
+        const Element *e = mRSProgram->mHal.state.inputElements[ct];
         for (uint32_t field=0; field < e->getFieldCount(); field++) {
             const Element *f = e->getField(field);
             const char *fn = e->getFieldName(field);
@@ -414,7 +414,7 @@
         RSD_CALL_GL(glActiveTexture, GL_TEXTURE0 + ct);
         RSD_CALL_GL(glUniform1i, sc->fragUniformSlot(mTextureUniformIndexStart + ct), ct);
 
-        if (!mRSProgram->mHal.state.textures[ct].get()) {
+        if (!mRSProgram->mHal.state.textures[ct]) {
             // if nothing is bound, reset to default GL texture
             RSD_CALL_GL(glBindTexture, mTextureTargets[ct], 0);
             continue;
@@ -427,9 +427,9 @@
         }
         RSD_CALL_GL(glBindTexture, drvTex->glTarget, drvTex->textureID);
         rsdGLCheckError(rsc, "ProgramFragment::setup tex bind");
-        if (mRSProgram->mHal.state.samplers[ct].get()) {
-            setupSampler(rsc, mRSProgram->mHal.state.samplers[ct].get(),
-                         mRSProgram->mHal.state.textures[ct].get());
+        if (mRSProgram->mHal.state.samplers[ct]) {
+            setupSampler(rsc, mRSProgram->mHal.state.samplers[ct],
+                         mRSProgram->mHal.state.textures[ct]);
         } else {
             RSD_CALL_GL(glTexParameteri, drvTex->glTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
             RSD_CALL_GL(glTexParameteri, drvTex->glTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@@ -448,7 +448,7 @@
 void RsdShader::setupUserConstants(const Context *rsc, RsdShaderCache *sc, bool isFragment) {
     uint32_t uidx = 0;
     for (uint32_t ct=0; ct < mRSProgram->mHal.state.constantsCount; ct++) {
-        Allocation *alloc = mRSProgram->mHal.state.constants[ct].get();
+        Allocation *alloc = mRSProgram->mHal.state.constants[ct];
         if (!alloc) {
             LOGE("Attempting to set constants on shader id %u, but alloc at slot %u is not set",
                  (uint32_t)this, ct);
@@ -504,7 +504,7 @@
 void RsdShader::initAttribAndUniformArray() {
     mAttribCount = 0;
     for (uint32_t ct=0; ct < mRSProgram->mHal.state.inputElementsCount; ct++) {
-        const Element *elem = mRSProgram->mHal.state.inputElements[ct].get();
+        const Element *elem = mRSProgram->mHal.state.inputElements[ct];
         for (uint32_t field=0; field < elem->getFieldCount(); field++) {
             if (elem->getFieldName(field)[0] != '#') {
                 mAttribCount ++;
diff --git a/rsAllocation.cpp b/rsAllocation.cpp
index 4359d95..e732630 100644
--- a/rsAllocation.cpp
+++ b/rsAllocation.cpp
@@ -30,7 +30,7 @@
     mHal.state.usageFlags = usages;
     mHal.state.mipmapControl = mc;
 
-    mHal.state.type.set(type);
+    setType(type);
     updateCache();
 }
 
@@ -47,7 +47,7 @@
 }
 
 void Allocation::updateCache() {
-    const Type *type = mHal.state.type.get();
+    const Type *type = mHal.state.type;
     mHal.state.dimensionX = type->getDimX();
     mHal.state.dimensionY = type->getDimY();
     mHal.state.dimensionZ = type->getDimZ();
@@ -187,7 +187,7 @@
 
     String8 s(prefix);
     s.append(" type ");
-    if (mHal.state.type.get()) {
+    if (mHal.state.type) {
         mHal.state.type->dumpLOGV(s.string());
     }
 
@@ -314,7 +314,7 @@
         decRefs(getPtr(), oldDimX - dimX, dimX);
     }
     rsc->mHal.funcs.allocation.resize(rsc, this, t.get(), mHal.state.hasReferences);
-    mHal.state.type.set(t.get());
+    setType(t.get());
     updateCache();
 }
 
diff --git a/rsAllocation.h b/rsAllocation.h
index 67fc3b5..714798a 100644
--- a/rsAllocation.h
+++ b/rsAllocation.h
@@ -41,7 +41,7 @@
         void * drv;
 
         struct State {
-            ObjectBaseRef<const Type> type;
+            const Type * type;
 
             uint32_t usageFlags;
             RsAllocationMipmapControl mipmapControl;
@@ -71,7 +71,7 @@
     void updateCache();
 
     void * getPtr() const {return mHal.drvState.mallocPtr;}
-    const Type * getType() const {return mHal.state.type.get();}
+    const Type * getType() const {return mHal.state.type;}
 
     void syncAll(Context *rsc, RsAllocationUsageType src);
 
@@ -126,6 +126,11 @@
 
 protected:
     Vector<const Program *> mToDirtyList;
+    ObjectBaseRef<const Type> mType;
+    void setType(const Type *t) {
+        mType.set(t);
+        mHal.state.type = t;
+    }
 
 private:
     void freeChildrenUnlocked();
diff --git a/rsFBOCache.cpp b/rsFBOCache.cpp
index c5c64c2..f4a8bc6 100644
--- a/rsFBOCache.cpp
+++ b/rsFBOCache.cpp
@@ -26,11 +26,14 @@
 FBOCache::FBOCache() {
     mDirty = true;
     mHal.state.colorTargetsCount = 1;
-    mHal.state.colorTargets = new ObjectBaseRef<Allocation>[mHal.state.colorTargetsCount];
+    mHal.state.colorTargets = new Allocation*[mHal.state.colorTargetsCount];
+    mColorTargets = new ObjectBaseRef<Allocation>[mHal.state.colorTargetsCount];
+    resetAll(NULL);
 }
 
 FBOCache::~FBOCache() {
     delete[] mHal.state.colorTargets;
+    delete[] mColorTargets;
 }
 
 void FBOCache::init(Context *rsc) {
@@ -52,7 +55,8 @@
             return;
         }
     }
-    mHal.state.colorTargets[slot].set(a);
+    mColorTargets[slot].set(a);
+    mHal.state.colorTargets[slot] = a;
     mDirty = true;
 }
 
@@ -63,15 +67,18 @@
             return;
         }
     }
-    mHal.state.depthTarget.set(a);
+    mDepthTarget.set(a);
+    mHal.state.depthTarget = a;
     mDirty = true;
 }
 
 void FBOCache::resetAll(Context *) {
     for (uint32_t i = 0; i < mHal.state.colorTargetsCount; i ++) {
-        mHal.state.colorTargets[i].set(NULL);
+        mColorTargets[i].set(NULL);
+        mHal.state.colorTargets[i] = NULL;
     }
-    mHal.state.depthTarget.set(NULL);
+    mDepthTarget.set(NULL);
+    mHal.state.depthTarget = NULL;
     mDirty = true;
 }
 
diff --git a/rsFBOCache.h b/rsFBOCache.h
index 5d58ba4..abb84de 100644
--- a/rsFBOCache.h
+++ b/rsFBOCache.h
@@ -44,15 +44,17 @@
         mutable void *drv;
 
         struct State {
-            ObjectBaseRef<Allocation> *colorTargets;
+            Allocation **colorTargets;
             uint32_t colorTargetsCount;
-            ObjectBaseRef<Allocation> depthTarget;
+            Allocation *depthTarget;
         };
         State state;
     };
     Hal mHal;
 
 protected:
+    ObjectBaseRef<Allocation> *mColorTargets;
+    ObjectBaseRef<Allocation> mDepthTarget;
     bool mDirty;
     void checkError(Context *);
     void setColorAttachment(Context *rsc);
diff --git a/rsMesh.cpp b/rsMesh.cpp
index 359d09f..bf9284f 100644
--- a/rsMesh.cpp
+++ b/rsMesh.cpp
@@ -23,9 +23,14 @@
     mHal.drv = NULL;
     mHal.state.primitives = NULL;
     mHal.state.primitivesCount = 0;
+    mHal.state.indexBuffers = NULL;
+    mHal.state.indexBuffersCount = 0;
     mHal.state.vertexBuffers = NULL;
     mHal.state.vertexBuffersCount = 0;
     mInitialized = false;
+
+    mVertexBuffers = NULL;
+    mIndexBuffers = NULL;
 }
 
 Mesh::Mesh(Context *rsc,
@@ -33,12 +38,23 @@
            uint32_t primitivesCount) : ObjectBase(rsc) {
     mHal.drv = NULL;
     mHal.state.primitivesCount = primitivesCount;
-    mHal.state.primitives = new Primitive_t *[mHal.state.primitivesCount];
+    mHal.state.indexBuffersCount = primitivesCount;
+    mHal.state.primitives = new RsPrimitive[mHal.state.primitivesCount];
+    mHal.state.indexBuffers = new Allocation *[mHal.state.indexBuffersCount];
     for (uint32_t i = 0; i < mHal.state.primitivesCount; i ++) {
-        mHal.state.primitives[i] = new Primitive_t;
+        mHal.state.primitives[i] = RS_PRIMITIVE_POINT;
+    }
+    for (uint32_t i = 0; i < mHal.state.indexBuffersCount; i ++) {
+        mHal.state.indexBuffers[i] = NULL;
     }
     mHal.state.vertexBuffersCount = vertexBuffersCount;
-    mHal.state.vertexBuffers = new ObjectBaseRef<Allocation>[mHal.state.vertexBuffersCount];
+    mHal.state.vertexBuffers = new Allocation *[mHal.state.vertexBuffersCount];
+    for (uint32_t i = 0; i < mHal.state.vertexBuffersCount; i ++) {
+        mHal.state.vertexBuffers[i] = NULL;
+    }
+
+    mVertexBuffers = new ObjectBaseRef<Allocation>[mHal.state.vertexBuffersCount];
+    mIndexBuffers = new ObjectBaseRef<Allocation>[mHal.state.primitivesCount];
 }
 
 Mesh::~Mesh() {
@@ -46,17 +62,12 @@
     mRSC->mHal.funcs.mesh.destroy(mRSC, this);
 #endif
 
-    if (mHal.state.vertexBuffers) {
-        delete[] mHal.state.vertexBuffers;
-    }
+    delete[] mHal.state.vertexBuffers;
+    delete[] mHal.state.primitives;
+    delete[] mHal.state.indexBuffers;
 
-    if (mHal.state.primitives) {
-        for (uint32_t i = 0; i < mHal.state.primitivesCount; i ++) {
-            mHal.state.primitives[i]->mIndexBuffer.clear();
-            delete mHal.state.primitives[i];
-        }
-        delete[] mHal.state.primitives;
-    }
+    delete[] mVertexBuffers;
+    delete[] mIndexBuffers;
 }
 
 void Mesh::init() {
@@ -81,13 +92,11 @@
     stream->addU32(mHal.state.primitivesCount);
     // Store the primitives
     for (uint32_t pCount = 0; pCount < mHal.state.primitivesCount; pCount ++) {
-        Primitive_t * prim = mHal.state.primitives[pCount];
+        stream->addU8((uint8_t)mHal.state.primitives[pCount]);
 
-        stream->addU8((uint8_t)prim->mPrimitive);
-
-        if (prim->mIndexBuffer.get()) {
+        if (mHal.state.indexBuffers[pCount]) {
             stream->addU32(1);
-            prim->mIndexBuffer->serialize(stream);
+            mHal.state.indexBuffers[pCount]->serialize(stream);
         } else {
             stream->addU32(0);
         }
@@ -173,10 +182,8 @@
         return;
     }
 
-    Primitive_t *prim = mHal.state.primitives[primIndex];
-
-    if (prim->mIndexBuffer.get()) {
-        renderPrimitiveRange(rsc, primIndex, 0, prim->mIndexBuffer->getType()->getDimX());
+    if (mHal.state.indexBuffers[primIndex]) {
+        renderPrimitiveRange(rsc, primIndex, 0, mHal.state.indexBuffers[primIndex]->getType()->getDimX());
         return;
     }
 
@@ -194,14 +201,14 @@
 
 void Mesh::uploadAll(Context *rsc) {
     for (uint32_t ct = 0; ct < mHal.state.vertexBuffersCount; ct ++) {
-        if (mHal.state.vertexBuffers[ct].get()) {
-            rsc->mHal.funcs.allocation.markDirty(rsc, mHal.state.vertexBuffers[ct].get());
+        if (mHal.state.vertexBuffers[ct]) {
+            rsc->mHal.funcs.allocation.markDirty(rsc, mHal.state.vertexBuffers[ct]);
         }
     }
 
     for (uint32_t ct = 0; ct < mHal.state.primitivesCount; ct ++) {
-        if (mHal.state.primitives[ct]->mIndexBuffer.get()) {
-            rsc->mHal.funcs.allocation.markDirty(rsc, mHal.state.primitives[ct]->mIndexBuffer.get());
+        if (mHal.state.indexBuffers[ct]) {
+            rsc->mHal.funcs.allocation.markDirty(rsc, mHal.state.indexBuffers[ct]);
         }
     }
 }
@@ -290,7 +297,7 @@
     rsAssert(vtxDataCount == sm->mHal.state.vertexBuffersCount);
 
     for (uint32_t ct = 0; ct < vtxDataCount; ct ++) {
-        vtxData[ct] = sm->mHal.state.vertexBuffers[ct].get();
+        vtxData[ct] = sm->mHal.state.vertexBuffers[ct];
         sm->mHal.state.vertexBuffers[ct]->incUserRef();
     }
 }
@@ -300,10 +307,10 @@
     rsAssert(idxDataCount == sm->mHal.state.primitivesCount);
 
     for (uint32_t ct = 0; ct < idxDataCount; ct ++) {
-        va[ct] = sm->mHal.state.primitives[ct]->mIndexBuffer.get();
-        primType[ct] = sm->mHal.state.primitives[ct]->mPrimitive;
-        if (sm->mHal.state.primitives[ct]->mIndexBuffer.get()) {
-            sm->mHal.state.primitives[ct]->mIndexBuffer->incUserRef();
+        va[ct] = sm->mHal.state.indexBuffers[ct];
+        primType[ct] = sm->mHal.state.primitives[ct];
+        if (sm->mHal.state.indexBuffers[ct]) {
+            sm->mHal.state.indexBuffers[ct]->incUserRef();
         }
     }
 }
diff --git a/rsMesh.h b/rsMesh.h
index ed1e93d..0fc73fb 100644
--- a/rsMesh.h
+++ b/rsMesh.h
@@ -32,13 +32,6 @@
     Mesh(Context *, uint32_t vertexBuffersCount, uint32_t primitivesCount);
     ~Mesh();
 
-    // Either mIndexBuffer, mPrimitiveBuffer or both could have a NULL reference
-    // If both are null, mPrimitive only would be used to render the mesh
-    struct Primitive_t {
-        ObjectBaseRef<Allocation> mIndexBuffer;
-        RsPrimitive mPrimitive;
-    };
-
     virtual void serialize(OStream *stream) const;
     virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_MESH; }
     static Mesh *createFromStream(Context *rsc, IStream *stream);
@@ -51,10 +44,13 @@
             // Contains vertex data
             // Position, normal, texcoord, etc could either be strided in one allocation
             // of provided separetely in multiple ones
-            ObjectBaseRef<Allocation> *vertexBuffers;
+            Allocation **vertexBuffers;
             uint32_t vertexBuffersCount;
 
-            Primitive_t ** primitives;
+            // indexBuffers[i] could be NULL, in which case only primitives[i] is used
+            Allocation **indexBuffers;
+            uint32_t indexBuffersCount;
+            RsPrimitive *primitives;
             uint32_t primitivesCount;
         };
         State state;
@@ -62,12 +58,14 @@
     Hal mHal;
 
     void setVertexBuffer(Allocation *vb, uint32_t index) {
-        mHal.state.vertexBuffers[index].set(vb);
+        mVertexBuffers[index].set(vb);
+        mHal.state.vertexBuffers[index] = vb;
     }
 
     void setPrimitive(Allocation *idx, RsPrimitive prim, uint32_t index) {
-        mHal.state.primitives[index]->mIndexBuffer.set(idx);
-        mHal.state.primitives[index]->mPrimitive = prim;
+        mIndexBuffers[index].set(idx);
+        mHal.state.indexBuffers[index] = idx;
+        mHal.state.primitives[index] = prim;
     }
 
     void render(Context *) const;
@@ -80,6 +78,8 @@
     float mBBoxMax[3];
     void computeBBox();
 protected:
+    ObjectBaseRef<Allocation> *mVertexBuffers;
+    ObjectBaseRef<Allocation> *mIndexBuffers;
     bool mInitialized;
 };
 
diff --git a/rsProgram.cpp b/rsProgram.cpp
index 4178aa5..a9fd877 100644
--- a/rsProgram.cpp
+++ b/rsProgram.cpp
@@ -37,22 +37,33 @@
         }
     }
 
-    mHal.state.textures = new ObjectBaseRef<Allocation>[mHal.state.texturesCount];
-    mHal.state.samplers = new ObjectBaseRef<Sampler>[mHal.state.texturesCount];
+    mTextures = new ObjectBaseRef<Allocation>[mHal.state.texturesCount];
+    mSamplers = new ObjectBaseRef<Sampler>[mHal.state.texturesCount];
+    mInputElements = new ObjectBaseRef<Element>[mHal.state.inputElementsCount];
+    mConstantTypes = new ObjectBaseRef<Type>[mHal.state.constantsCount];
+    mConstants = new ObjectBaseRef<Allocation>[mHal.state.constantsCount];
+
+    mHal.state.textures = new Allocation*[mHal.state.texturesCount];
+    mHal.state.samplers = new Sampler*[mHal.state.texturesCount];
     mHal.state.textureTargets = new RsTextureTarget[mHal.state.texturesCount];
-    mHal.state.inputElements = new ObjectBaseRef<Element>[mHal.state.inputElementsCount];
-    mHal.state.constantTypes = new ObjectBaseRef<Type>[mHal.state.constantsCount];
-    mHal.state.constants = new ObjectBaseRef<Allocation>[mHal.state.constantsCount];
+    mHal.state.inputElements = new Element*[mHal.state.inputElementsCount];
+    mHal.state.constantTypes = new Type*[mHal.state.constantsCount];
+    mHal.state.constants = new Allocation*[mHal.state.constantsCount];
+
+    // Will initialize everything
+    freeChildren();
 
     uint32_t input = 0;
     uint32_t constant = 0;
     uint32_t texture = 0;
     for (uint32_t ct=0; ct < paramLength; ct+=2) {
         if (params[ct] == RS_PROGRAM_PARAM_INPUT) {
-            mHal.state.inputElements[input++].set(reinterpret_cast<Element *>(params[ct+1]));
+            mInputElements[input].set(reinterpret_cast<Element *>(params[ct+1]));
+            mHal.state.inputElements[input++] = reinterpret_cast<Element *>(params[ct+1]);
         }
         if (params[ct] == RS_PROGRAM_PARAM_CONSTANT) {
-            mHal.state.constantTypes[constant++].set(reinterpret_cast<Type *>(params[ct+1]));
+            mConstantTypes[constant].set(reinterpret_cast<Type *>(params[ct+1]));
+            mHal.state.constantTypes[constant++] = reinterpret_cast<Type *>(params[ct+1]);
         }
         if (params[ct] == RS_PROGRAM_PARAM_TEXTURE_TYPE) {
             mHal.state.textureTargets[texture++] = (RsTextureTarget)params[ct+1];
@@ -72,6 +83,12 @@
 Program::~Program() {
     freeChildren();
 
+    delete[] mTextures;
+    delete[] mSamplers;
+    delete[] mInputElements;
+    delete[] mConstantTypes;
+    delete[] mConstants;
+
     delete[] mHal.state.textures;
     delete[] mHal.state.samplers;
     delete[] mHal.state.textureTargets;
@@ -110,6 +127,12 @@
     mHal.state.constantsCount = 0;
     mHal.state.texturesCount = 0;
 
+    mTextures = NULL;
+    mSamplers = NULL;
+    mInputElements = NULL;
+    mConstantTypes = NULL;
+    mConstants = NULL;
+
     mIsInternal = false;
 }
 
@@ -121,20 +144,21 @@
             rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind allocation");
             return;
         }
-        if (alloc->getType() != mHal.state.constantTypes[slot].get()) {
+        if (alloc->getType() != mConstantTypes[slot].get()) {
             LOGE("Attempt to bind alloc at slot %u, on shader id %u, but types mismatch",
                  slot, (uint32_t)this);
             rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind allocation");
             return;
         }
     }
-    if (mHal.state.constants[slot].get() == alloc) {
+    if (mConstants[slot].get() == alloc) {
         return;
     }
-    if (mHal.state.constants[slot].get()) {
-        mHal.state.constants[slot].get()->removeProgramToDirty(this);
+    if (mConstants[slot].get()) {
+        mConstants[slot]->removeProgramToDirty(this);
     }
-    mHal.state.constants[slot].set(alloc);
+    mConstants[slot].set(alloc);
+    mHal.state.constants[slot] = alloc;
     if (alloc) {
         alloc->addProgramToDirty(this);
     }
@@ -154,7 +178,9 @@
         return;
     }
 
-    mHal.state.textures[slot].set(a);
+    mTextures[slot].set(a);
+    mHal.state.textures[slot] = a;
+
     mDirty = true;
 }
 
@@ -165,7 +191,8 @@
         return;
     }
 
-    mHal.state.samplers[slot].set(s);
+    mSamplers[slot].set(s);
+    mHal.state.samplers[slot] = s;
     mDirty = true;
 }
 
diff --git a/rsProgram.h b/rsProgram.h
index 3237a72..06fc3ec 100644
--- a/rsProgram.h
+++ b/rsProgram.h
@@ -30,6 +30,33 @@
 
 class Program : public ProgramBase {
 public:
+    struct Hal {
+        mutable void *drv;
+
+        struct State {
+            // The difference between Textures and Constants is how they are accessed
+            // Texture lookups go though a sampler which in effect converts normalized
+            // coordinates into type specific.  Multiple samples may also be taken
+            // and filtered.
+            //
+            // Constants are strictly accessed by the shader code
+            Allocation **textures;
+            RsTextureTarget *textureTargets;
+            uint32_t texturesCount;
+
+            Sampler **samplers;
+            uint32_t samplersCount;
+
+            Allocation **constants;
+            Type **constantTypes;
+            uint32_t constantsCount;
+
+            Element **inputElements;
+            uint32_t inputElementsCount;
+        };
+        State state;
+    };
+    Hal mHal;
 
     Program(Context *, const char * shaderText, uint32_t shaderLength,
                        const uint32_t * params, uint32_t paramLength);
@@ -43,35 +70,13 @@
     void bindTexture(Context *, uint32_t slot, Allocation *);
     void bindSampler(Context *, uint32_t slot, Sampler *);
 
-    struct Hal {
-        mutable void *drv;
-
-        struct State {
-            // The difference between Textures and Constants is how they are accessed
-            // Texture lookups go though a sampler which in effect converts normalized
-            // coordinates into type specific.  Multiple samples may also be taken
-            // and filtered.
-            //
-            // Constants are strictly accessed by the shader code
-            ObjectBaseRef<Allocation> *textures;
-            RsTextureTarget *textureTargets;
-            uint32_t texturesCount;
-
-            ObjectBaseRef<Sampler> *samplers;
-            uint32_t samplersCount;
-
-            ObjectBaseRef<Allocation> *constants;
-            ObjectBaseRef<Type> *constantTypes;
-            uint32_t constantsCount;
-
-            ObjectBaseRef<Element> *inputElements;
-            uint32_t inputElementsCount;
-        };
-        State state;
-    };
-    Hal mHal;
-
 protected:
+    ObjectBaseRef<Allocation> *mTextures;
+    ObjectBaseRef<Sampler> *mSamplers;
+    ObjectBaseRef<Allocation> *mConstants;
+    ObjectBaseRef<Type> *mConstantTypes;
+    ObjectBaseRef<Element> *mInputElements;
+
     bool mIsInternal;
     String8 mUserShader;
     void initMemberVars();
diff --git a/rsProgramFragment.cpp b/rsProgramFragment.cpp
index ff29520..81eedc4 100644
--- a/rsProgramFragment.cpp
+++ b/rsProgramFragment.cpp
@@ -42,7 +42,7 @@
         rsc->setError(RS_ERROR_BAD_SHADER, "Cannot  set fixed function emulation color on user program");
         return;
     }
-    if (mHal.state.constants[0].get() == NULL) {
+    if (mHal.state.constants[0] == NULL) {
         LOGE("Unable to set fixed function emulation color because allocation is missing");
         rsc->setError(RS_ERROR_BAD_SHADER, "Unable to set fixed function emulation color because allocation is missing");
         return;
@@ -62,7 +62,7 @@
     state->mLast.set(this);
 
     for (uint32_t ct=0; ct < mHal.state.texturesCount; ct++) {
-        if (!mHal.state.textures[ct].get()) {
+        if (!mHal.state.textures[ct]) {
             LOGE("No texture bound for shader id %u, texture unit %u", (uint)this, ct);
             rsc->setError(RS_ERROR_BAD_SHADER, "No texture bound");
             continue;
diff --git a/rsProgramVertex.cpp b/rsProgramVertex.cpp
index 51cb2a8..4a13622 100644
--- a/rsProgramVertex.cpp
+++ b/rsProgramVertex.cpp
@@ -38,7 +38,7 @@
     }
 
     if (!isUserProgram()) {
-        if (mHal.state.constants[0].get() == NULL) {
+        if (mHal.state.constants[0] == NULL) {
             rsc->setError(RS_ERROR_FATAL_UNKNOWN,
                           "Unable to set fixed function emulation matrices because allocation is missing");
             return;
@@ -65,7 +65,7 @@
                       "Attempting to set fixed function emulation matrix projection on user program");
         return;
     }
-    if (mHal.state.constants[0].get() == NULL) {
+    if (mHal.state.constants[0] == NULL) {
         rsc->setError(RS_ERROR_FATAL_UNKNOWN,
                       "Unable to set fixed function emulation matrix projection because allocation is missing");
         return;
@@ -81,7 +81,7 @@
                       "Attempting to set fixed function emulation matrix modelview on user program");
         return;
     }
-    if (mHal.state.constants[0].get() == NULL) {
+    if (mHal.state.constants[0] == NULL) {
         rsc->setError(RS_ERROR_FATAL_UNKNOWN,
                       "Unable to set fixed function emulation matrix modelview because allocation is missing");
         return;
@@ -97,7 +97,7 @@
                       "Attempting to set fixed function emulation matrix texture on user program");
         return;
     }
-    if (mHal.state.constants[0].get() == NULL) {
+    if (mHal.state.constants[0] == NULL) {
         rsc->setError(RS_ERROR_FATAL_UNKNOWN,
                       "Unable to set fixed function emulation matrix texture because allocation is missing");
         return;
@@ -113,7 +113,7 @@
                       "Attempting to get fixed function emulation matrix projection on user program");
         return;
     }
-    if (mHal.state.constants[0].get() == NULL) {
+    if (mHal.state.constants[0] == NULL) {
         rsc->setError(RS_ERROR_FATAL_UNKNOWN,
                       "Unable to get fixed function emulation matrix projection because allocation is missing");
         return;