Merge "Implement allocation resizing."
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index 985d700..2c076b3 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -182,6 +182,24 @@
         mRS.nAllocationRead(mID, d);
     }
 
+    public void resize(int dimX) {
+        if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.getFaces() || mType.getLOD()) {
+            throw new IllegalStateException("Resize only support for 1D allocations at this time.");
+        }
+        mRS.nAllocationResize1D(mID, dimX);
+    }
+
+    /*
+    public void resize(int dimX, int dimY) {
+        if ((mType.getZ() > 0) || mType.getFaces() || mType.getLOD()) {
+            throw new IllegalStateException("Resize only support for 2D allocations at this time.");
+        }
+        if (mType.getY() == 0) {
+            throw new IllegalStateException("Resize only support for 2D allocations at this time.");
+        }
+        mRS.nAllocationResize2D(mID, dimX, dimY);
+    }
+    */
 
     public class Adapter1D extends BaseObj {
         Adapter1D(int id, RenderScript rs) {
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 3c0b4e5..0088373 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -254,6 +254,15 @@
         return rsnAllocationGetType(mContext, id);
     }
 
+    native void rsnAllocationResize1D(int con, int id, int dimX);
+    synchronized void nAllocationResize1D(int id, int dimX) {
+        rsnAllocationResize1D(mContext, id, dimX);
+    }
+    native void rsnAllocationResize2D(int con, int id, int dimX, int dimY);
+    synchronized void nAllocationResize2D(int id, int dimX, int dimY) {
+        rsnAllocationResize2D(mContext, id, dimX, dimY);
+    }
+
     native int  rsnFileA3DCreateFromAssetStream(int con, int assetStream);
     synchronized int nFileA3DCreateFromAssetStream(int assetStream) {
         return rsnFileA3DCreateFromAssetStream(mContext, assetStream);
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index 67a2b63..8f1e93c 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -587,6 +587,20 @@
     return (jint) rsAllocationGetType(con, (RsAllocation)a);
 }
 
+static void
+nAllocationResize1D(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint dimX)
+{
+    LOG_API("nAllocationResize1D, con(%p), alloc(%p), sizeX(%i)", con, (RsAllocation)alloc, dimX);
+    rsAllocationResize1D(con, (RsAllocation)alloc, dimX);
+}
+
+static void
+nAllocationResize2D(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint dimX, jint dimY)
+{
+    LOG_API("nAllocationResize1D, con(%p), alloc(%p), sizeX(%i), sizeY(%i)", con, (RsAllocation)alloc, dimX, dimY);
+    rsAllocationResize2D(con, (RsAllocation)alloc, dimX, dimY);
+}
+
 // -----------------------------------
 
 static int
@@ -1252,6 +1266,8 @@
 {"rsnAllocationRead",                "(II[I)V",                               (void*)nAllocationRead_i },
 {"rsnAllocationRead",                "(II[F)V",                               (void*)nAllocationRead_f },
 {"rsnAllocationGetType",             "(II)I",                                 (void*)nAllocationGetType},
+{"rsnAllocationResize1D",            "(III)V",                                (void*)nAllocationResize1D },
+{"rsnAllocationResize2D",            "(IIII)V",                               (void*)nAllocationResize2D },
 
 {"rsnAdapter1DBindAllocation",       "(III)V",                                (void*)nAdapter1DBindAllocation },
 {"rsnAdapter1DSetConstraint",        "(IIII)V",                               (void*)nAdapter1DSetConstraint },
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index a4752f4..0da637e 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -280,6 +280,17 @@
 	ret const void*
 	}
 
+AllocationResize1D {
+	param RsAllocation va
+	param uint32_t dimX
+	}
+
+AllocationResize2D {
+	param RsAllocation va
+	param uint32_t dimX
+	param uint32_t dimY
+	}
+
 SamplerBegin {
 	}
 
diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
index 0356e4d..2e9e0b3 100644
--- a/libs/rs/rsAllocation.cpp
+++ b/libs/rs/rsAllocation.cpp
@@ -488,12 +488,13 @@
     }
 }
 
-void Allocation::incRefs(const void *ptr, size_t ct) const
+void Allocation::incRefs(const void *ptr, size_t ct, size_t startOff) const
 {
     const uint8_t *p = static_cast<const uint8_t *>(ptr);
     const Element *e = mType->getElement();
     uint32_t stride = e->getSizeBytes();
 
+    p += stride * startOff;
     while (ct > 0) {
         e->incRefs(p);
         ct --;
@@ -501,12 +502,13 @@
     }
 }
 
-void Allocation::decRefs(const void *ptr, size_t ct) const
+void Allocation::decRefs(const void *ptr, size_t ct, size_t startOff) const
 {
     const uint8_t *p = static_cast<const uint8_t *>(ptr);
     const Element *e = mType->getElement();
     uint32_t stride = e->getSizeBytes();
 
+    p += stride * startOff;
     while (ct > 0) {
         e->decRefs(p);
         ct --;
@@ -514,6 +516,37 @@
     }
 }
 
+void Allocation::copyRange1D(Context *rsc, const Allocation *src, int32_t srcOff, int32_t destOff, int32_t len)
+{
+}
+
+void Allocation::resize1D(Context *rsc, uint32_t dimX)
+{
+    Type *t = mType->cloneAndResize1D(rsc, dimX);
+
+    uint32_t oldDimX = mType->getDimX();
+    if (dimX == oldDimX) {
+        return;
+    }
+
+    if (dimX < oldDimX) {
+        decRefs(mPtr, oldDimX - dimX, dimX);
+    }
+    mPtr = realloc(mPtr, t->getSizeBytes());
+
+    if (dimX > oldDimX) {
+        const Element *e = mType->getElement();
+        uint32_t stride = e->getSizeBytes();
+        memset(((uint8_t *)mPtr) + stride * oldDimX, 0, stride * (dimX - oldDimX));
+    }
+    mType.set(t);
+}
+
+void Allocation::resize2D(Context *rsc, uint32_t dimX, uint32_t dimY)
+{
+    LOGE("not implemented");
+}
+
 /////////////////
 //
 
@@ -822,6 +855,18 @@
     a->read(data);
 }
 
+void rsi_AllocationResize1D(Context *rsc, RsAllocation va, uint32_t dimX)
+{
+    Allocation *a = static_cast<Allocation *>(va);
+    a->resize1D(rsc, dimX);
+}
+
+void rsi_AllocationResize2D(Context *rsc, RsAllocation va, uint32_t dimX, uint32_t dimY)
+{
+    Allocation *a = static_cast<Allocation *>(va);
+    a->resize2D(rsc, dimX, dimY);
+}
+
 const void* rsi_AllocationGetType(Context *rsc, RsAllocation va)
 {
     Allocation *a = static_cast<Allocation *>(va);
diff --git a/libs/rs/rsAllocation.h b/libs/rs/rsAllocation.h
index ce5372f..24e245f 100644
--- a/libs/rs/rsAllocation.h
+++ b/libs/rs/rsAllocation.h
@@ -55,6 +55,10 @@
     void uploadToBufferObject(const Context *rsc);
     uint32_t getBufferObjectID() const {return mBufferID;}
 
+    void copyRange1D(Context *rsc, const Allocation *src, int32_t srcOff, int32_t destOff, int32_t len);
+
+    void resize1D(Context *rsc, uint32_t dimX);
+    void resize2D(Context *rsc, uint32_t dimX, uint32_t dimY);
 
     void data(Context *rsc, const void *data, uint32_t sizeBytes);
     void subData(Context *rsc, uint32_t xoff, uint32_t count, const void *data, uint32_t sizeBytes);
@@ -86,8 +90,8 @@
     bool getIsTexture() const {return mIsTexture;}
     bool getIsBufferObject() const {return mIsVertexBuffer;}
 
-    void incRefs(const void *ptr, size_t ct) const;
-    void decRefs(const void *ptr, size_t ct) const;
+    void incRefs(const void *ptr, size_t ct, size_t startOff = 0) const;
+    void decRefs(const void *ptr, size_t ct, size_t startOff = 0) const;
 
     void sendDirty() const;
     bool getHasGraphicsMipmaps() const {return mTextureGenMipmap;}
diff --git a/libs/rs/rsType.cpp b/libs/rs/rsType.cpp
index fc037a3..8cdb48a 100644
--- a/libs/rs/rsType.cpp
+++ b/libs/rs/rsType.cpp
@@ -274,6 +274,59 @@
     return false;
 }
 
+Type * Type::cloneAndResize1D(Context *rsc, uint32_t dimX) const
+{
+    TypeState * stc = &rsc->mStateType;
+    for (uint32_t ct=0; ct < stc->mTypes.size(); ct++) {
+        Type *t = stc->mTypes[ct];
+        if (t->getElement() != mElement.get()) continue;
+        if (t->getDimX() != dimX) continue;
+        if (t->getDimY() != mDimY) continue;
+        if (t->getDimZ() != mDimZ) continue;
+        if (t->getDimLOD() != mDimLOD) continue;
+        if (t->getDimFaces() != mFaces) continue;
+        t->incUserRef();
+        return t;
+    }
+
+    Type *nt = new Type(rsc);
+    nt->mElement.set(mElement);
+    nt->mDimX = dimX;
+    nt->mDimY = mDimY;
+    nt->mDimZ = mDimZ;
+    nt->mDimLOD = mDimLOD;
+    nt->mFaces = mFaces;
+    nt->compute();
+    return nt;
+}
+
+Type * Type::cloneAndResize2D(Context *rsc, uint32_t dimX, uint32_t dimY) const
+{
+    TypeState * stc = &rsc->mStateType;
+    for (uint32_t ct=0; ct < stc->mTypes.size(); ct++) {
+        Type *t = stc->mTypes[ct];
+        if (t->getElement() != mElement.get()) continue;
+        if (t->getDimX() != dimX) continue;
+        if (t->getDimY() != dimY) continue;
+        if (t->getDimZ() != mDimZ) continue;
+        if (t->getDimLOD() != mDimLOD) continue;
+        if (t->getDimFaces() != mFaces) continue;
+        t->incUserRef();
+        return t;
+    }
+
+    Type *nt = new Type(rsc);
+    nt->mElement.set(mElement);
+    nt->mDimX = dimX;
+    nt->mDimY = dimY;
+    nt->mDimZ = mDimZ;
+    nt->mDimLOD = mDimLOD;
+    nt->mFaces = mFaces;
+    nt->compute();
+    return nt;
+}
+
+
 //////////////////////////////////////////////////
 //
 namespace android {
diff --git a/libs/rs/rsType.h b/libs/rs/rsType.h
index 33faa87..b5548c0 100644
--- a/libs/rs/rsType.h
+++ b/libs/rs/rsType.h
@@ -79,6 +79,9 @@
 
     bool isEqual(const Type *other) const;
 
+    Type * cloneAndResize1D(Context *rsc, uint32_t dimX) const;
+    Type * cloneAndResize2D(Context *rsc, uint32_t dimX, uint32_t dimY) const;
+
 protected:
     struct LOD {
         size_t mX;