Merge "Cleanup bitmap uploads Implement standalone mipmap generation." into honeycomb
diff --git a/api/current.xml b/api/current.xml
index acab82a..d790c4f 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -166157,7 +166157,7 @@
 </parameter>
 <parameter name="h" type="int">
 </parameter>
-<parameter name="d" type="byte[]">
+<parameter name="data" type="byte[]">
 </parameter>
 </method>
 <method name="copy2DRangeFrom"
@@ -166178,7 +166178,7 @@
 </parameter>
 <parameter name="h" type="int">
 </parameter>
-<parameter name="d" type="short[]">
+<parameter name="data" type="short[]">
 </parameter>
 </method>
 <method name="copy2DRangeFrom"
@@ -166199,7 +166199,7 @@
 </parameter>
 <parameter name="h" type="int">
 </parameter>
-<parameter name="d" type="int[]">
+<parameter name="data" type="int[]">
 </parameter>
 </method>
 <method name="copy2DRangeFrom"
@@ -166220,7 +166220,7 @@
 </parameter>
 <parameter name="h" type="int">
 </parameter>
-<parameter name="d" type="float[]">
+<parameter name="data" type="float[]">
 </parameter>
 </method>
 <method name="copy2DRangeFrom"
@@ -166237,7 +166237,7 @@
 </parameter>
 <parameter name="yoff" type="int">
 </parameter>
-<parameter name="b" type="android.graphics.Bitmap">
+<parameter name="data" type="android.graphics.Bitmap">
 </parameter>
 </method>
 <method name="copyFrom"
@@ -166647,6 +166647,17 @@
 <parameter name="type" type="android.renderscript.Type">
 </parameter>
 </method>
+<method name="generateMipmaps"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getType"
  return="android.renderscript.Type"
  abstract="false"
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index abe66726..0c33a5f 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -46,15 +46,62 @@
     Bitmap mBitmap;
     int mUsage;
 
+    /**
+     * The usage of the allocation.  These signal to renderscript
+     * where to place the allocation in memory.
+     *
+     * SCRIPT The allocation will be bound to and accessed by
+     * scripts.
+     */
     public static final int USAGE_SCRIPT = 0x0001;
+
+    /**
+     * GRAPHICS_TEXTURE The allcation will be used as a texture
+     * source by one or more graphcics programs.
+     *
+     */
     public static final int USAGE_GRAPHICS_TEXTURE = 0x0002;
+
+    /**
+     * GRAPHICS_VERTEX The allocation will be used as a graphics
+     * mesh.
+     *
+     */
     public static final int USAGE_GRAPHICS_VERTEX = 0x0004;
+
+
+    /**
+     * GRAPHICS_CONSTANTS The allocation will be used as the source
+     * of shader constants by one or more programs.
+     *
+     */
     public static final int USAGE_GRAPHICS_CONSTANTS = 0x0008;
 
 
+    /**
+     * Controls mipmap behavior when using the bitmap creation and
+     * update functions.
+     */
     public enum MipmapControl {
+        /**
+         * No mipmaps will be generated and the type generated from the
+         * incoming bitmap will not contain additional LODs.
+         */
         MIPMAP_NONE(0),
+
+        /**
+         * A Full mipmap chain will be created in script memory.  The
+         * type of the allocation will contain a full mipmap chain.  On
+         * upload to graphics the full chain will be transfered.
+         */
         MIPMAP_FULL(1),
+
+        /**
+         * The type of the allocation will be the same as MIPMAP_NONE.
+         * It will not contain mipmaps.  On upload to graphics the
+         * graphics copy of the allocation data will contain a full
+         * mipmap chain generated from the top level in script memory.
+         */
         MIPMAP_ON_SYNC_TO_TEXTURE(2);
 
         int mID;
@@ -256,6 +303,20 @@
         }
     }
 
+    /**
+     * Generate a mipmap chain.  Requires the type of the allocation
+     * include mipmaps.
+     *
+     * This function will generate a complete set of mipmaps from
+     * the top level lod and place them into the script memoryspace.
+     *
+     * If the allocation is also using other memory spaces a
+     * followup sync will be required.
+     */
+    public void generateMipmaps() {
+        mRS.nAllocationGenerateMipmaps(getID());
+    }
+
     public void copy1DRangeFrom(int off, int count, int[] d) {
         int dataSize = mType.mElement.getSizeBytes() * count;
         data1DChecks(off, count, d.length * 4, dataSize);
@@ -278,29 +339,49 @@
     }
 
 
-    public void copy2DRangeFrom(int xoff, int yoff, int w, int h, byte[] d) {
+    /**
+     * Copy a rectanglular region from the array into the
+     * allocation.  The incoming array is assumed to be tightly
+     * packed.
+     *
+     * @param xoff X offset of the region to update
+     * @param yoff Y offset of the region to update
+     * @param w Width of the incoming region to update
+     * @param h Height of the incoming region to update
+     * @param data to be placed into the allocation
+     */
+    public void copy2DRangeFrom(int xoff, int yoff, int w, int h, byte[] data) {
         mRS.validate();
-        mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, d, d.length);
+        mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length);
     }
 
-    public void copy2DRangeFrom(int xoff, int yoff, int w, int h, short[] d) {
+    public void copy2DRangeFrom(int xoff, int yoff, int w, int h, short[] data) {
         mRS.validate();
-        mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, d, d.length * 2);
+        mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length * 2);
     }
 
-    public void copy2DRangeFrom(int xoff, int yoff, int w, int h, int[] d) {
+    public void copy2DRangeFrom(int xoff, int yoff, int w, int h, int[] data) {
         mRS.validate();
-        mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, d, d.length * 4);
+        mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length * 4);
     }
 
-    public void copy2DRangeFrom(int xoff, int yoff, int w, int h, float[] d) {
+    public void copy2DRangeFrom(int xoff, int yoff, int w, int h, float[] data) {
         mRS.validate();
-        mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, d, d.length * 4);
+        mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length * 4);
     }
 
-    public void copy2DRangeFrom(int xoff, int yoff, Bitmap b) {
+    /**
+     * Copy a bitmap into an allocation.  The height and width of
+     * the update will use the height and width of the incoming
+     * bitmap.
+     *
+     * @param xoff X offset of the region to update
+     * @param yoff Y offset of the region to update
+     * @param data the bitmap to be copied
+     */
+    public void copy2DRangeFrom(int xoff, int yoff, Bitmap data) {
         mRS.validate();
-        mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, b);
+        mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, data);
     }
 
 
@@ -329,6 +410,18 @@
         mRS.nAllocationRead(getID(), d);
     }
 
+    /**
+     * Resize a 1D allocation.  The contents of the allocation are
+     * preserved.  If new elements are allocated objects are created
+     * with null contents and the new region is otherwise undefined.
+     *
+     * If the new region is smaller the references of any objects
+     * outside the new region will be released.
+     *
+     * A new type will be created with the new dimension.
+     *
+     * @param dimX The new size of the allocation.
+     */
     public synchronized void resize(int dimX) {
         if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) {
             throw new RSInvalidStateException("Resize only support for 1D allocations at this time.");
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 4c9ad56..28b32d5 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -223,6 +223,10 @@
     synchronized void nAllocationSyncAll(int alloc, int src) {
         rsnAllocationSyncAll(mContext, alloc, src);
     }
+    native void rsnAllocationGenerateMipmaps(int con, int alloc);
+    synchronized void nAllocationGenerateMipmaps(int alloc) {
+        rsnAllocationGenerateMipmaps(mContext, alloc);
+    }
     native void  rsnAllocationCopyFromBitmap(int con, int alloc, Bitmap bmp);
     synchronized void nAllocationCopyFromBitmap(int alloc, Bitmap bmp) {
         rsnAllocationCopyFromBitmap(mContext, alloc, bmp);
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index 1817a1b..a7913d7e 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -411,6 +411,13 @@
     rsAllocationSyncAll(con, (RsAllocation)a, (RsAllocationUsageType)bits);
 }
 
+static void
+nAllocationGenerateMipmaps(JNIEnv *_env, jobject _this, RsContext con, jint alloc)
+{
+    LOG_API("nAllocationGenerateMipmaps, con(%p), a(%p)", con, (RsAllocation)alloc);
+    rsAllocationGenerateMipmaps(con, (RsAllocation)alloc);
+}
+
 static int
 nAllocationCreateFromBitmap(JNIEnv *_env, jobject _this, RsContext con, jint type, jint mip, jobject jbitmap, jint usage)
 {
@@ -445,10 +452,14 @@
     SkBitmap const * nativeBitmap =
             (SkBitmap const *)_env->GetIntField(jbitmap, gNativeBitmapID);
     const SkBitmap& bitmap(*nativeBitmap);
+    int w = bitmap.width();
+    int h = bitmap.height();
 
     bitmap.lockPixels();
     const void* ptr = bitmap.getPixels();
-    rsAllocationCopyFromBitmap(con, (RsAllocation)alloc, ptr, bitmap.getSize());
+    rsAllocation2DData(con, (RsAllocation)alloc, 0, 0,
+                       0, RS_ALLOCATION_CUBMAP_FACE_POSITVE_X,
+                       w, h, ptr, bitmap.getSize());
     bitmap.unlockPixels();
 }
 
@@ -1211,6 +1222,7 @@
 {"rsnAllocationGetType",             "(II)I",                                 (void*)nAllocationGetType},
 {"rsnAllocationResize1D",            "(III)V",                                (void*)nAllocationResize1D },
 {"rsnAllocationResize2D",            "(IIII)V",                               (void*)nAllocationResize2D },
+{"rsnAllocationGenerateMipmaps",     "(II)V",                                 (void*)nAllocationGenerateMipmaps },
 
 {"rsnScriptBindAllocation",          "(IIII)V",                               (void*)nScriptBindAllocation },
 {"rsnScriptSetTimeZone",             "(II[B)V",                               (void*)nScriptSetTimeZone },
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index 33ac2f0..7e23cec 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/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/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
index d6b90e6..cf394c0 100644
--- a/libs/rs/rsAllocation.cpp
+++ b/libs/rs/rsAllocation.cpp
@@ -342,26 +342,34 @@
     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 {
+        upload2DTexture(false, data);
     }
-    sendDirty();
-    mUploadDefered = true;
 }
 
 void Allocation::data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t lod, RsAllocationCubemapFace face,
@@ -685,28 +693,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) {
-            rsaAllocationGenerateScriptMips(rsc, texAlloc);
-        }
-    } else {
-        texAlloc->upload2DTexture(false, data);
-    }
-
+    rsaAllocationGenerateScriptMips(rsc, texAlloc);
 }
 
 void rsi_AllocationCopyToBitmap(Context *rsc, RsAllocation va, void *data, size_t dataLen) {