Merge "On-device linking." into honeycomb
diff --git a/rs.spec b/rs.spec
index 33ac2f0..7e23cec 100644
--- a/rs.spec
+++ b/rs.spec
@@ -77,12 +77,6 @@
 	ret RsElement
 	}
 
-AllocationCopyFromBitmap {
-	param RsAllocation alloc
-	param const void * data
-	param size_t dataLen
-	}
-
 AllocationCopyToBitmap {
 	param RsAllocation alloc
 	param void * data
@@ -135,6 +129,10 @@
 	param uint32_t bytes
 	}
 
+AllocationGenerateMipmaps {
+	param RsAllocation va
+}
+
 AllocationRead {
 	param RsAllocation va
 	param void * data
diff --git a/rsAllocation.cpp b/rsAllocation.cpp
index 673ade2..2ed7774 100644
--- a/rsAllocation.cpp
+++ b/rsAllocation.cpp
@@ -28,6 +28,8 @@
 
 #include "utils/StopWatch.h"
 
+static void rsaAllocationGenerateScriptMips(RsContext con, RsAllocation va);
+
 using namespace android;
 using namespace android::renderscript;
 
@@ -200,6 +202,17 @@
     rsc->checkError("Allocation::uploadToTexture");
 }
 
+void Allocation::update2DTexture(const void *ptr, uint32_t xoff, uint32_t yoff,
+                                 uint32_t lod, RsAllocationCubemapFace face,
+                                 uint32_t w, uint32_t h) {
+    GLenum type = mType->getElement()->getComponent().getGLType();
+    GLenum format = mType->getElement()->getComponent().getGLFormat();
+    GLenum target = (GLenum)getGLTarget();
+    glBindTexture(target, mTextureID);
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+    glTexSubImage2D(GL_TEXTURE_2D, lod, xoff, yoff, w, h, format, type, ptr);
+}
+
 void Allocation::upload2DTexture(bool isFirstUpload, const void *ptr) {
     GLenum type = mType->getElement()->getComponent().getGLType();
     GLenum format = mType->getElement()->getComponent().getGLFormat();
@@ -340,30 +353,39 @@
     uint32_t lineSize = eSize * w;
     uint32_t destW = mType->getDimX();
 
-    const uint8_t *src = static_cast<const uint8_t *>(data);
-    uint8_t *dst = static_cast<uint8_t *>(mPtr);
-    dst += eSize * (xoff + yoff * destW);
+    //LOGE("data2d %p,  %i %i %i %i %i %i %p %i", this, xoff, yoff, lod, face, w, h, data, sizeBytes);
 
-    if ((lineSize * eSize * h) != sizeBytes) {
+    if ((lineSize * h) != sizeBytes) {
+        LOGE("Allocation size mismatch, expected %i, got %i", (lineSize * h), sizeBytes);
         rsAssert(!"Allocation::subData called with mismatched size");
         return;
     }
 
-    for (uint32_t line=yoff; line < (yoff+h); line++) {
-        if (mType->getElement()->getHasReferences()) {
-            incRefs(src, w);
-            decRefs(dst, w);
+    if (mPtr) {
+        const uint8_t *src = static_cast<const uint8_t *>(data);
+        uint8_t *dst = static_cast<uint8_t *>(mPtr);
+        dst += mType->getLODOffset(lod, xoff, yoff);
+
+        //LOGE("            %p  %p  %i  ", dst, src, eSize);
+        for (uint32_t line=yoff; line < (yoff+h); line++) {
+            if (mType->getElement()->getHasReferences()) {
+                incRefs(src, w);
+                decRefs(dst, w);
+            }
+            memcpy(dst, src, lineSize);
+            src += lineSize;
+            dst += destW * eSize;
         }
-        memcpy(dst, src, lineSize);
-        src += lineSize;
-        dst += destW * eSize;
+        sendDirty();
+        mUploadDefered = true;
+    } else {
+        update2DTexture(data, xoff, yoff, lod, face, w, h);
     }
-    sendDirty();
-    mUploadDefered = true;
 }
 
-void Allocation::data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t lod, RsAllocationCubemapFace face,
-             uint32_t w, uint32_t h, uint32_t d, const void *data, uint32_t sizeBytes) {
+void Allocation::data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t zoff,
+                      uint32_t lod, RsAllocationCubemapFace face,
+                      uint32_t w, uint32_t h, uint32_t d, const void *data, uint32_t sizeBytes) {
 }
 
 void Allocation::elementData(Context *rsc, uint32_t x, const void *data,
@@ -683,34 +705,9 @@
     a->syncAll(rsc, src);
 }
 
-void rsi_AllocationCopyFromBitmap(Context *rsc, RsAllocation va, const void *data, size_t dataLen) {
+void rsi_AllocationGenerateMipmaps(Context *rsc, RsAllocation va) {
     Allocation *texAlloc = static_cast<Allocation *>(va);
-    const Type * t = texAlloc->getType();
-
-    uint32_t w = t->getDimX();
-    uint32_t h = t->getDimY();
-    bool genMips = t->getDimLOD();
-    size_t s = w * h * t->getElementSizeBytes();
-    if (s != dataLen) {
-        rsc->setError(RS_ERROR_BAD_VALUE, "Bitmap size didn't match allocation size");
-        return;
-    }
-
-    if (texAlloc->getIsScript()) {
-        memcpy(texAlloc->getPtr(), data, s);
-        if (genMips) {
-            Adapter2D adapt(rsc, texAlloc);
-            Adapter2D adapt2(rsc, texAlloc);
-            for (uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) {
-                adapt.setLOD(lod);
-                adapt2.setLOD(lod + 1);
-                mip(adapt2, adapt);
-            }
-        }
-    } else {
-        texAlloc->upload2DTexture(false, data);
-    }
-
+    rsaAllocationGenerateScriptMips(rsc, texAlloc);
 }
 
 void rsi_AllocationCopyToBitmap(Context *rsc, RsAllocation va, void *data, size_t dataLen) {
@@ -770,6 +767,23 @@
 }
 }
 
+static void rsaAllocationGenerateScriptMips(RsContext con, RsAllocation va) {
+    Context *rsc = static_cast<Context *>(con);
+    Allocation *texAlloc = static_cast<Allocation *>(va);
+    uint32_t numFaces = texAlloc->getType()->getDimFaces() ? 6 : 1;
+    for (uint32_t face = 0; face < numFaces; face ++) {
+        Adapter2D adapt(rsc, texAlloc);
+        Adapter2D adapt2(rsc, texAlloc);
+        adapt.setFace(face);
+        adapt2.setFace(face);
+        for (uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) {
+            adapt.setLOD(lod);
+            adapt2.setLOD(lod + 1);
+            mip(adapt2, adapt);
+        }
+    }
+}
+
 const void * rsaAllocationGetType(RsContext con, RsAllocation va) {
     Allocation *a = static_cast<Allocation *>(va);
     a->getType()->incUserRef();
@@ -802,13 +816,7 @@
 
     memcpy(texAlloc->getPtr(), data, t->getDimX() * t->getDimY() * t->getElementSizeBytes());
     if (mips == RS_ALLOCATION_MIPMAP_FULL) {
-        Adapter2D adapt(rsc, texAlloc);
-        Adapter2D adapt2(rsc, texAlloc);
-        for (uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) {
-            adapt.setLOD(lod);
-            adapt2.setLOD(lod + 1);
-            mip(adapt2, adapt);
-        }
+        rsaAllocationGenerateScriptMips(rsc, texAlloc);
     }
 
     texAlloc->deferedUploadToTexture(rsc);
@@ -846,18 +854,10 @@
 
         // Move the data pointer to the next cube face
         sourcePtr += copySize;
+    }
 
-        if (mips == RS_ALLOCATION_MIPMAP_FULL) {
-            Adapter2D adapt(rsc, texAlloc);
-            Adapter2D adapt2(rsc, texAlloc);
-            adapt.setFace(face);
-            adapt2.setFace(face);
-            for (uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) {
-                adapt.setLOD(lod);
-                adapt2.setLOD(lod + 1);
-                mip(adapt2, adapt);
-            }
-        }
+    if (mips == RS_ALLOCATION_MIPMAP_FULL) {
+        rsaAllocationGenerateScriptMips(rsc, texAlloc);
     }
 
     texAlloc->deferedUploadToTexture(rsc);
diff --git a/rsAllocation.h b/rsAllocation.h
index a8d086e..a160765 100644
--- a/rsAllocation.h
+++ b/rsAllocation.h
@@ -106,6 +106,8 @@
     }
 
     void upload2DTexture(bool isFirstUpload, const void *ptr);
+    void update2DTexture(const void *ptr, uint32_t xoff, uint32_t yoff,
+                         uint32_t lod, RsAllocationCubemapFace face, uint32_t w, uint32_t h);
 
 protected:
     ObjectBaseRef<const Type> mType;
diff --git a/rsContext.cpp b/rsContext.cpp
index c5ee7ee..bb38825 100644
--- a/rsContext.cpp
+++ b/rsContext.cpp
@@ -743,7 +743,9 @@
     rsAssert(mIsGraphicsContext);
 
     EGLBoolean ret;
-    if (mEGL.mSurface != NULL) {
+    // WAR: Some drivers fail to handle 0 size surfaces correcntly.
+    // Use the pbuffer to avoid this pitfall.
+    if ((mEGL.mSurface != NULL) || (w == 0) || (h == 0)) {
         ret = eglMakeCurrent(mEGL.mDisplay, mEGL.mSurfaceDefault, mEGL.mSurfaceDefault, mEGL.mContext);
         checkEglError("eglMakeCurrent", ret);