Implement RS tracked defered texture and buffer object uploads.
diff --git a/rsAllocation.cpp b/rsAllocation.cpp
index 3aee6b8..7f76390 100644
--- a/rsAllocation.cpp
+++ b/rsAllocation.cpp
@@ -38,9 +38,9 @@
 
     mIsTexture = false;
     mTextureID = 0;
-
     mIsVertexBuffer = false;
     mBufferID = 0;
+    mUploadDefered = false;
 
     mType.set(type);
     rsAssert(type);
@@ -88,10 +88,23 @@
     return false;
 }
 
-void Allocation::uploadToTexture(Context *rsc, uint32_t lodOffset)
+void Allocation::deferedUploadToTexture(const Context *rsc, uint32_t lodOffset)
+{
+    rsAssert(lodOffset < mType->getLODCount());
+    mIsTexture = true;
+    mTextureLOD = lodOffset;
+    mUploadDefered = true;
+}
+
+void Allocation::uploadToTexture(const Context *rsc)
 {
     //rsAssert(!mTextureId);
-    rsAssert(lodOffset < mType->getLODCount());
+
+    mIsTexture = true;
+    if (!rsc->checkDriver()) {
+        mUploadDefered = true;
+        return;
+    }
 
     GLenum type = mType->getElement()->getGLType();
     GLenum format = mType->getElement()->getGLFormat();
@@ -109,15 +122,16 @@
             // Force a crash to 1: restart the app, 2: make sure we get a bugreport.
             LOGE("Upload to texture failed to gen mTextureID");
             rsc->dumpDebug();
-            ((char *)0)[0] = 0;
+            mUploadDefered = true;
+            return;
         }
     }
     glBindTexture(GL_TEXTURE_2D, mTextureID);
     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
 
     Adapter2D adapt(getContext(), this);
-    for(uint32_t lod = 0; (lod + lodOffset) < mType->getLODCount(); lod++) {
-        adapt.setLOD(lod+lodOffset);
+    for(uint32_t lod = 0; (lod + mTextureLOD) < mType->getLODCount(); lod++) {
+        adapt.setLOD(lod+mTextureLOD);
 
         uint16_t * ptr = static_cast<uint16_t *>(adapt.getElement(0,0));
         glTexImage2D(GL_TEXTURE_2D, lod, format,
@@ -126,19 +140,50 @@
     }
 }
 
-void Allocation::uploadToBufferObject()
+void Allocation::deferedUploadToBufferObject(const Context *rsc)
+{
+    mIsVertexBuffer = true;
+    mUploadDefered = true;
+}
+
+void Allocation::uploadToBufferObject(const Context *rsc)
 {
     rsAssert(!mType->getDimY());
     rsAssert(!mType->getDimZ());
 
+    mIsVertexBuffer = true;
+    if (!rsc->checkDriver()) {
+        mUploadDefered = true;
+        return;
+    }
+
     if (!mBufferID) {
         glGenBuffers(1, &mBufferID);
     }
+    if (!mBufferID) {
+        LOGE("Upload to buffer object failed");
+        mUploadDefered = true;
+        return;
+    }
+
     glBindBuffer(GL_ARRAY_BUFFER, mBufferID);
     glBufferData(GL_ARRAY_BUFFER, mType->getSizeBytes(), getPtr(), GL_DYNAMIC_DRAW);
     glBindBuffer(GL_ARRAY_BUFFER, 0);
 }
 
+void Allocation::uploadCheck(const Context *rsc)
+{
+    if (mUploadDefered) {
+        mUploadDefered = false;
+        if (mIsVertexBuffer) {
+            uploadToBufferObject(rsc);
+        }
+        if (mIsTexture) {
+            uploadToTexture(rsc);
+        }
+    }
+}
+
 
 void Allocation::data(const void *data, uint32_t sizeBytes)
 {
@@ -149,6 +194,7 @@
     }
     memcpy(mPtr, data, size);
     sendDirty();
+    mUploadDefered = true;
 }
 
 void Allocation::read(void *data)
@@ -170,6 +216,7 @@
     }
     memcpy(ptr, data, size);
     sendDirty();
+    mUploadDefered = true;
 }
 
 void Allocation::subData(uint32_t xoff, uint32_t yoff,
@@ -195,6 +242,7 @@
         dst += destW * eSize;
     }
     sendDirty();
+    mUploadDefered = true;
 }
 
 void Allocation::subData(uint32_t xoff, uint32_t yoff, uint32_t zoff,
@@ -271,13 +319,13 @@
 void rsi_AllocationUploadToTexture(Context *rsc, RsAllocation va, uint32_t baseMipLevel)
 {
     Allocation *alloc = static_cast<Allocation *>(va);
-    alloc->uploadToTexture(rsc, baseMipLevel);
+    alloc->deferedUploadToTexture(rsc, baseMipLevel);
 }
 
 void rsi_AllocationUploadToBufferObject(Context *rsc, RsAllocation va)
 {
     Allocation *alloc = static_cast<Allocation *>(va);
-    alloc->uploadToBufferObject();
+    alloc->deferedUploadToBufferObject(rsc);
 }
 
 static void mip565(const Adapter2D &out, const Adapter2D &in)
diff --git a/rsAllocation.h b/rsAllocation.h
index 490abcf..f0b2122 100644
--- a/rsAllocation.h
+++ b/rsAllocation.h
@@ -46,10 +46,12 @@
     void * getPtr() const {return mPtr;}
     const Type * getType() const {return mType.get();}
 
-    void uploadToTexture(Context *rsc, uint32_t lodOffset = 0);
+    void deferedUploadToTexture(const Context *rsc, uint32_t lodOffset);
+    void uploadToTexture(const Context *rsc);
     uint32_t getTextureID() const {return mTextureID;}
 
-    void uploadToBufferObject();
+    void deferedUploadToBufferObject(const Context *rsc);
+    void uploadToBufferObject(const Context *rsc);
     uint32_t getBufferObjectID() const {return mBufferID;}
 
 
@@ -70,6 +72,8 @@
 
     virtual void dumpLOGV(const char *prefix) const;
 
+    virtual void uploadCheck(const Context *rsc);
+
 protected:
     void sendDirty() const;
 
@@ -94,6 +98,7 @@
     // Is this a legal structure to be used as a texture source.
     // Initially this will require 1D or 2D and color data
     bool mIsTexture;
+    uint32_t mTextureLOD;
     uint32_t mTextureID;
 
     // Is this a legal structure to be used as a vertex source.
@@ -101,6 +106,8 @@
     // is allowed.
     bool mIsVertexBuffer;
     uint32_t mBufferID;
+
+    bool mUploadDefered;
 };
 
 }
diff --git a/rsContext.h b/rsContext.h
index 708551c..426f921 100644
--- a/rsContext.h
+++ b/rsContext.h
@@ -94,6 +94,7 @@
     const ProgramVertex * getVertex() {return mVertex.get();}
 
     void setupCheck();
+    bool checkDriver() const {return mEGL.mSurface != 0;}
 
     void pause();
     void resume();
diff --git a/rsProgramFragment.cpp b/rsProgramFragment.cpp
index b239ce8..1225ff3 100644
--- a/rsProgramFragment.cpp
+++ b/rsProgramFragment.cpp
@@ -67,6 +67,7 @@
             }
             glTexEnvi(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, mPointSpriteEnable);
         }
+        mTextures[ct]->uploadCheck(rsc);
         glBindTexture(GL_TEXTURE_2D, mTextures[ct]->getTextureID());
 
         switch(mEnvModes[ct]) {
@@ -126,6 +127,7 @@
             continue;
         }
 
+        mTextures[ct]->uploadCheck(rsc);
         glBindTexture(GL_TEXTURE_2D, mTextures[ct]->getTextureID());
         if (mSamplers[ct].get()) {
             mSamplers[ct]->setupGL();
diff --git a/rsSimpleMesh.cpp b/rsSimpleMesh.cpp
index edfe967..f7d14a5 100644
--- a/rsSimpleMesh.cpp
+++ b/rsSimpleMesh.cpp
@@ -57,6 +57,7 @@
 
     VertexArray va;
     for (uint32_t ct=0; ct < mVertexTypeCount; ct++) {
+        mVertexBuffers[ct]->uploadCheck(rsc);
         va.setActiveBuffer(mVertexBuffers[ct]->getBufferObjectID());
         mVertexTypes[ct]->enableGLVertexBuffer(&va);
     }
@@ -67,6 +68,7 @@
     }
 
     if (mIndexType.get()) {
+        mIndexBuffer->uploadCheck(rsc);
         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer->getBufferObjectID());
         glDrawElements(mGLPrimitive, len, GL_UNSIGNED_SHORT, (uint16_t *)(start * 2));
     } else {
@@ -78,14 +80,14 @@
 {
     for (uint32_t ct=0; ct < mVertexTypeCount; ct++) {
         if (mVertexBuffers[ct].get()) {
-            mVertexBuffers[ct]->uploadToBufferObject();
+            mVertexBuffers[ct]->deferedUploadToBufferObject(rsc);
         }
     }
     if (mIndexBuffer.get()) {
-        mIndexBuffer->uploadToBufferObject();
+        mIndexBuffer->deferedUploadToBufferObject(rsc);
     }
     if (mPrimitiveBuffer.get()) {
-        mPrimitiveBuffer->uploadToBufferObject();
+        mPrimitiveBuffer->deferedUploadToBufferObject(rsc);
     }
 }