Merge "Add support for linking to a skia bitmap rather than always copying the data from the bitmap."
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index 8185404..17c0778 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -32,6 +32,7 @@
  **/
 public class Allocation extends BaseObj {
     Type mType;
+    Bitmap mBitmap;
 
     Allocation(int id, RenderScript rs, Type t) {
         super(rs);
@@ -262,15 +263,58 @@
         return new Allocation(id, rs, t);
     }
 
+    static private Element elementFromBitmap(RenderScript rs, Bitmap b) {
+        final Bitmap.Config bc = b.getConfig();
+        if (bc == Bitmap.Config.ALPHA_8) {
+            return Element.A_8(rs);
+        }
+        if (bc == Bitmap.Config.ARGB_4444) {
+            return Element.RGBA_4444(rs);
+        }
+        if (bc == Bitmap.Config.ARGB_8888) {
+            return Element.RGBA_8888(rs);
+        }
+        if (bc == Bitmap.Config.RGB_565) {
+            return Element.RGB_565(rs);
+        }
+        throw new IllegalStateException("Bad bitmap type.");
+    }
+
+    static private Type typeFromBitmap(RenderScript rs, Bitmap b) {
+        Element e = elementFromBitmap(rs, b);
+        Type.Builder tb = new Type.Builder(rs, e);
+        tb.add(Dimension.X, b.getWidth());
+        tb.add(Dimension.Y, b.getHeight());
+        return tb.create();
+    }
+
     static public Allocation createFromBitmap(RenderScript rs, Bitmap b, Element dstFmt, boolean genMips)
         throws IllegalArgumentException {
 
         rs.validate();
+        Type t = typeFromBitmap(rs, b);
+
         int id = rs.nAllocationCreateFromBitmap(dstFmt.mID, genMips, b);
         if(id == 0) {
             throw new IllegalStateException("Load failed.");
         }
-        return new Allocation(id, rs, null);
+        return new Allocation(id, rs, t);
+    }
+
+    static public Allocation createBitmapRef(RenderScript rs, Bitmap b)
+        throws IllegalArgumentException {
+
+        rs.validate();
+        Type t = typeFromBitmap(rs, b);
+
+        int id = rs.nAllocationCreateBitmapRef(t.getID(), b);
+        if(id == 0) {
+            throw new IllegalStateException("Load failed.");
+        }
+
+        Allocation a = new Allocation(id, rs, t);
+        a.mBitmap = b;
+        return a;
     }
 
     static Allocation createFromBitmapBoxed(RenderScript rs, Bitmap b, Element dstFmt, boolean genMips)
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 70c97ea..a935243 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -98,6 +98,7 @@
 
     native int  nAllocationCreateTyped(int type);
     native int  nAllocationCreateFromBitmap(int dstFmt, boolean genMips, Bitmap bmp);
+    native int  nAllocationCreateBitmapRef(int type, Bitmap bmp);
     native int  nAllocationCreateFromBitmapBoxed(int dstFmt, boolean genMips, Bitmap bmp);
     native int  nAllocationCreateFromAssetStream(int dstFmt, boolean genMips, int assetStream);
 
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index cb5a00e..d8e0393 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -501,6 +501,26 @@
     return 0;
 }
 
+static void ReleaseBitmapCallback(void *bmp)
+{
+    SkBitmap const * nativeBitmap = (SkBitmap const *)bmp;
+    nativeBitmap->unlockPixels();
+}
+
+static int
+nAllocationCreateBitmapRef(JNIEnv *_env, jobject _this, jint type, jobject jbitmap)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    SkBitmap * nativeBitmap =
+            (SkBitmap *)_env->GetIntField(jbitmap, gNativeBitmapID);
+
+
+    nativeBitmap->lockPixels();
+    void* ptr = nativeBitmap->getPixels();
+    jint id = (jint)rsAllocationCreateBitmapRef(con, (RsType)type, ptr, nativeBitmap, ReleaseBitmapCallback);
+    return id;
+}
+
 static int
 nAllocationCreateFromAssetStream(JNIEnv *_env, jobject _this, jint dstFmt, jboolean genMips, jint native_asset)
 {
@@ -1367,6 +1387,7 @@
 
 {"nAllocationCreateTyped",         "(I)I",                                 (void*)nAllocationCreateTyped },
 {"nAllocationCreateFromBitmap",    "(IZLandroid/graphics/Bitmap;)I",       (void*)nAllocationCreateFromBitmap },
+{"nAllocationCreateBitmapRef",     "(ILandroid/graphics/Bitmap;)I",        (void*)nAllocationCreateBitmapRef },
 {"nAllocationCreateFromBitmapBoxed","(IZLandroid/graphics/Bitmap;)I",      (void*)nAllocationCreateFromBitmapBoxed },
 {"nAllocationCreateFromAssetStream","(IZI)I",                              (void*)nAllocationCreateFromAssetStream },
 {"nAllocationUploadToTexture",     "(IZI)V",                               (void*)nAllocationUploadToTexture },
diff --git a/libs/rs/RenderScript.h b/libs/rs/RenderScript.h
index 0c95e7d..cd8361c 100644
--- a/libs/rs/RenderScript.h
+++ b/libs/rs/RenderScript.h
@@ -46,6 +46,8 @@
 typedef void * RsProgramFragmentStore;
 typedef void * RsProgramRaster;
 
+typedef void (* RsBitmapCallback_t)(void *);
+
 enum RsDeviceParam {
     RS_DEVICE_PARAM_FORCE_SOFTWARE_GL,
     RS_DEVICE_PARAM_COUNT
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index 89d9d5e..4d97c0f 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -90,6 +90,14 @@
 	ret RsAllocation
 	}
 
+AllocationCreateBitmapRef {
+	param RsType type
+	param void * bmpPtr
+	param void * callbackData
+	param RsBitmapCallback_t callback
+	ret RsAllocation
+	}
+
 AllocationCreateFromBitmap {
 	param uint32_t width
 	param uint32_t height
diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
index f1798de..4e8278d 100644
--- a/libs/rs/rsAllocation.cpp
+++ b/libs/rs/rsAllocation.cpp
@@ -25,6 +25,27 @@
 
 Allocation::Allocation(Context *rsc, const Type *type) : ObjectBase(rsc)
 {
+    init(rsc, type);
+
+    mPtr = malloc(mType->getSizeBytes());
+    if (!mPtr) {
+        LOGE("Allocation::Allocation, alloc failure");
+    }
+}
+
+Allocation::Allocation(Context *rsc, const Type *type, void *bmp,
+                       void *callbackData, RsBitmapCallback_t callback)
+: ObjectBase(rsc)
+{
+    init(rsc, type);
+
+    mPtr = bmp;
+    mUserBitmapCallback = callback;
+    mUserBitmapCallbackData = callbackData;
+}
+
+void Allocation::init(Context *rsc, const Type *type)
+{
     mAllocFile = __FILE__;
     mAllocLine = __LINE__;
     mPtr = NULL;
@@ -43,17 +64,22 @@
     mBufferID = 0;
     mUploadDefered = false;
 
+    mUserBitmapCallback = NULL;
+    mUserBitmapCallbackData = NULL;
+
     mType.set(type);
     rsAssert(type);
-    mPtr = malloc(mType->getSizeBytes());
-    if (!mPtr) {
-        LOGE("Allocation::Allocation, alloc failure");
-    }
+
+    mPtr = NULL;
 }
 
 Allocation::~Allocation()
 {
-    free(mPtr);
+    if (mUserBitmapCallback != NULL) {
+        mUserBitmapCallback(mUserBitmapCallbackData);
+    } else {
+        free(mPtr);
+    }
     mPtr = NULL;
 
     if (mBufferID) {
@@ -486,6 +512,14 @@
     return 0;
 }
 
+RsAllocation rsi_AllocationCreateBitmapRef(Context *rsc, RsType vtype,
+                                           void *bmp, void *callbackData, RsBitmapCallback_t callback)
+{
+    const Type * type = static_cast<const Type *>(vtype);
+    Allocation * alloc = new Allocation(rsc, type, bmp, callbackData, callback);
+    alloc->incUserRef();
+    return alloc;
+}
 
 RsAllocation rsi_AllocationCreateFromBitmap(Context *rsc, uint32_t w, uint32_t h, RsElement _dst, RsElement _src,  bool genMips, const void *data)
 {
diff --git a/libs/rs/rsAllocation.h b/libs/rs/rsAllocation.h
index 778c904..516f8b7 100644
--- a/libs/rs/rsAllocation.h
+++ b/libs/rs/rsAllocation.h
@@ -29,11 +29,12 @@
 {
     // The graphics equilivent of malloc.  The allocation contains a structure of elements.
 
-
 public:
     // By policy this allocation will hold a pointer to the type
     // but will not destroy it on destruction.
     Allocation(Context *rsc, const Type *);
+    Allocation(Context *rsc, const Type *, void *bmp, void *callbackData, RsBitmapCallback_t callback);
+
     virtual ~Allocation();
 
     void setCpuWritable(bool);
@@ -82,6 +83,11 @@
 
     Vector<const Program *> mToDirtyList;
 
+    // Is we have a non-null user bitmap callback we do not own the bits and
+    // instead call this function to free the memort when its time.
+    RsBitmapCallback_t mUserBitmapCallback;
+    void *mUserBitmapCallbackData;
+
     // Usage restrictions
     bool mCpuWrite;
     bool mCpuRead;
@@ -109,6 +115,10 @@
     uint32_t mBufferID;
 
     bool mUploadDefered;
+
+private:
+    void init(Context *rsc, const Type *);
+
 };
 
 }