[RenderScript] AutoPadding & Unpadding for Vec3 Elements during
copyTo & copyFrom.

Change-Id: I10b6fb235717e181ebb30b92e4dbe23e6183a29c
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index a145166..0bad827 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -54,10 +54,12 @@
 #define PER_ARRAY_TYPE(flag, fnc, readonly, ...) {                                      \
     jint len = 0;                                                                       \
     void *ptr = nullptr;                                                                \
+    void *srcPtr = nullptr;                                                             \
     size_t typeBytes = 0;                                                               \
     jint relFlag = 0;                                                                   \
     if (readonly) {                                                                     \
         /* The on-release mode should only be JNI_ABORT for read-only accesses. */      \
+        /* readonly = true, also indicates we are copying to the allocation   . */      \
         relFlag = JNI_ABORT;                                                            \
     }                                                                                   \
     switch(dataType) {                                                                  \
@@ -65,14 +67,50 @@
         len = _env->GetArrayLength((jfloatArray)data);                                  \
         ptr = _env->GetFloatArrayElements((jfloatArray)data, flag);                     \
         typeBytes = 4;                                                                  \
-        fnc(__VA_ARGS__);                                                               \
+        if (usePadding) {                                                               \
+            srcPtr = ptr;                                                               \
+            len = len / 3 * 4;                                                          \
+            if (count == 0) {                                                           \
+                count = len / 4;                                                        \
+            }                                                                           \
+            ptr = malloc (len * typeBytes);                                             \
+            if (readonly) {                                                             \
+                copyWithPadding(ptr, srcPtr, mSize, count);                             \
+                fnc(__VA_ARGS__);                                                       \
+            } else {                                                                    \
+                fnc(__VA_ARGS__);                                                       \
+                copyWithUnPadding(srcPtr, ptr, mSize, count);                           \
+            }                                                                           \
+            free(ptr);                                                                  \
+            ptr = srcPtr;                                                               \
+        } else {                                                                        \
+            fnc(__VA_ARGS__);                                                           \
+        }                                                                               \
         _env->ReleaseFloatArrayElements((jfloatArray)data, (jfloat *)ptr, relFlag);     \
         return;                                                                         \
     case RS_TYPE_FLOAT_64:                                                              \
         len = _env->GetArrayLength((jdoubleArray)data);                                 \
         ptr = _env->GetDoubleArrayElements((jdoubleArray)data, flag);                   \
         typeBytes = 8;                                                                  \
-        fnc(__VA_ARGS__);                                                               \
+        if (usePadding) {                                                               \
+            srcPtr = ptr;                                                               \
+            len = len / 3 * 4;                                                          \
+            if (count == 0) {                                                           \
+                count = len / 4;                                                        \
+            }                                                                           \
+            ptr = malloc (len * typeBytes);                                             \
+            if (readonly) {                                                             \
+                copyWithPadding(ptr, srcPtr, mSize, count);                             \
+                fnc(__VA_ARGS__);                                                       \
+            } else {                                                                    \
+                fnc(__VA_ARGS__);                                                       \
+                copyWithUnPadding(srcPtr, ptr, mSize, count);                           \
+            }                                                                           \
+            free(ptr);                                                                  \
+            ptr = srcPtr;                                                               \
+        } else {                                                                        \
+            fnc(__VA_ARGS__);                                                           \
+        }                                                                               \
         _env->ReleaseDoubleArrayElements((jdoubleArray)data, (jdouble *)ptr, relFlag);  \
         return;                                                                         \
     case RS_TYPE_SIGNED_8:                                                              \
@@ -80,7 +118,25 @@
         len = _env->GetArrayLength((jbyteArray)data);                                   \
         ptr = _env->GetByteArrayElements((jbyteArray)data, flag);                       \
         typeBytes = 1;                                                                  \
-        fnc(__VA_ARGS__);                                                               \
+        if (usePadding) {                                                               \
+            srcPtr = ptr;                                                               \
+            len = len / 3 * 4;                                                          \
+            if (count == 0) {                                                           \
+                count = len / 4;                                                        \
+            }                                                                           \
+            ptr = malloc (len * typeBytes);                                             \
+            if (readonly) {                                                             \
+                copyWithPadding(ptr, srcPtr, mSize, count);                             \
+                fnc(__VA_ARGS__);                                                       \
+            } else {                                                                    \
+                fnc(__VA_ARGS__);                                                       \
+                copyWithUnPadding(srcPtr, ptr, mSize, count);                           \
+            }                                                                           \
+            free(ptr);                                                                  \
+            ptr = srcPtr;                                                               \
+        } else {                                                                        \
+            fnc(__VA_ARGS__);                                                           \
+        }                                                                               \
         _env->ReleaseByteArrayElements((jbyteArray)data, (jbyte*)ptr, relFlag);         \
         return;                                                                         \
     case RS_TYPE_SIGNED_16:                                                             \
@@ -88,7 +144,25 @@
         len = _env->GetArrayLength((jshortArray)data);                                  \
         ptr = _env->GetShortArrayElements((jshortArray)data, flag);                     \
         typeBytes = 2;                                                                  \
-        fnc(__VA_ARGS__);                                                               \
+        if (usePadding) {                                                               \
+            srcPtr = ptr;                                                               \
+            len = len / 3 * 4;                                                          \
+            if (count == 0) {                                                           \
+                count = len / 4;                                                        \
+            }                                                                           \
+            ptr = malloc (len * typeBytes);                                             \
+            if (readonly) {                                                             \
+                copyWithPadding(ptr, srcPtr, mSize, count);                             \
+                fnc(__VA_ARGS__);                                                       \
+            } else {                                                                    \
+                fnc(__VA_ARGS__);                                                       \
+                copyWithUnPadding(srcPtr, ptr, mSize, count);                           \
+            }                                                                           \
+            free(ptr);                                                                  \
+            ptr = srcPtr;                                                               \
+        } else {                                                                        \
+            fnc(__VA_ARGS__);                                                           \
+        }                                                                               \
         _env->ReleaseShortArrayElements((jshortArray)data, (jshort *)ptr, relFlag);     \
         return;                                                                         \
     case RS_TYPE_SIGNED_32:                                                             \
@@ -96,7 +170,25 @@
         len = _env->GetArrayLength((jintArray)data);                                    \
         ptr = _env->GetIntArrayElements((jintArray)data, flag);                         \
         typeBytes = 4;                                                                  \
-        fnc(__VA_ARGS__);                                                               \
+        if (usePadding) {                                                               \
+            srcPtr = ptr;                                                               \
+            len = len / 3 * 4;                                                          \
+            if (count == 0) {                                                           \
+                count = len / 4;                                                        \
+            }                                                                           \
+            ptr = malloc (len * typeBytes);                                             \
+            if (readonly) {                                                             \
+                copyWithPadding(ptr, srcPtr, mSize, count);                             \
+                fnc(__VA_ARGS__);                                                       \
+            } else {                                                                    \
+                fnc(__VA_ARGS__);                                                       \
+                copyWithUnPadding(srcPtr, ptr, mSize, count);                           \
+            }                                                                           \
+            free(ptr);                                                                  \
+            ptr = srcPtr;                                                               \
+        } else {                                                                        \
+            fnc(__VA_ARGS__);                                                           \
+        }                                                                               \
         _env->ReleaseIntArrayElements((jintArray)data, (jint *)ptr, relFlag);           \
         return;                                                                         \
     case RS_TYPE_SIGNED_64:                                                             \
@@ -104,13 +196,31 @@
         len = _env->GetArrayLength((jlongArray)data);                                   \
         ptr = _env->GetLongArrayElements((jlongArray)data, flag);                       \
         typeBytes = 8;                                                                  \
-        fnc(__VA_ARGS__);                                                               \
+        if (usePadding) {                                                               \
+            srcPtr = ptr;                                                               \
+            len = len / 3 * 4;                                                          \
+            if (count == 0) {                                                           \
+                count = len / 4;                                                        \
+            }                                                                           \
+            ptr = malloc (len * typeBytes);                                             \
+            if (readonly) {                                                             \
+                copyWithPadding(ptr, srcPtr, mSize, count);                             \
+                fnc(__VA_ARGS__);                                                       \
+            } else {                                                                    \
+                fnc(__VA_ARGS__);                                                       \
+                copyWithUnPadding(srcPtr, ptr, mSize, count);                           \
+            }                                                                           \
+            free(ptr);                                                                  \
+            ptr = srcPtr;                                                               \
+        } else {                                                                        \
+            fnc(__VA_ARGS__);                                                           \
+        }                                                                               \
         _env->ReleaseLongArrayElements((jlongArray)data, (jlong *)ptr, relFlag);        \
         return;                                                                         \
     default:                                                                            \
         break;                                                                          \
     }                                                                                   \
-    UNUSED(len, ptr, typeBytes, relFlag);                                               \
+    UNUSED(len, ptr, srcPtr, typeBytes, relFlag);                                       \
 }
 
 
@@ -184,6 +294,32 @@
 
 // ---------------------------------------------------------------------------
 
+static void copyWithPadding(void* ptr, void* srcPtr, int mSize, int count) {
+    int sizeBytesPad = mSize * 4;
+    int sizeBytes = mSize * 3;
+    uint8_t *dst = static_cast<uint8_t *>(ptr);
+    uint8_t *src = static_cast<uint8_t *>(srcPtr);
+    for (int i = 0; i < count; i++) {
+        memcpy(dst, src, sizeBytes);
+        dst += sizeBytesPad;
+        src += sizeBytes;
+    }
+}
+
+static void copyWithUnPadding(void* ptr, void* srcPtr, int mSize, int count) {
+    int sizeBytesPad = mSize * 4;
+    int sizeBytes = mSize * 3;
+    uint8_t *dst = static_cast<uint8_t *>(ptr);
+    uint8_t *src = static_cast<uint8_t *>(srcPtr);
+    for (int i = 0; i < count; i++) {
+        memcpy(dst, src, sizeBytes);
+        dst += sizeBytes;
+        src += sizeBytesPad;
+    }
+}
+
+
+// ---------------------------------------------------------------------------
 static void
 nContextFinish(JNIEnv *_env, jobject _this, jlong con)
 {
@@ -1014,7 +1150,8 @@
 // Copies from the Java object data into the Allocation pointed to by _alloc.
 static void
 nAllocationData1D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint offset, jint lod,
-                  jint count, jobject data, jint sizeBytes, jint dataType)
+                  jint count, jobject data, jint sizeBytes, jint dataType, jint mSize,
+                  jboolean usePadding)
 {
     RsAllocation *alloc = (RsAllocation *)_alloc;
     if (kLogApi) {
@@ -1022,8 +1159,8 @@
               "dataType(%i)", (RsContext)con, (RsAllocation)alloc, offset, count, sizeBytes,
               dataType);
     }
-    PER_ARRAY_TYPE(nullptr, rsAllocation1DData, true, (RsContext)con, alloc, offset, lod, count,
-                   ptr, sizeBytes);
+    PER_ARRAY_TYPE(nullptr, rsAllocation1DData, true,
+                   (RsContext)con, alloc, offset, lod, count, ptr, sizeBytes);
 }
 
 static void
@@ -1048,7 +1185,8 @@
 // Copies from the Java object data into the Allocation pointed to by _alloc.
 static void
 nAllocationData2D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint xoff, jint yoff, jint lod, jint _face,
-                  jint w, jint h, jobject data, jint sizeBytes, jint dataType)
+                  jint w, jint h, jobject data, jint sizeBytes, jint dataType, jint mSize,
+                  jboolean usePadding)
 {
     RsAllocation *alloc = (RsAllocation *)_alloc;
     RsAllocationCubemapFace face = (RsAllocationCubemapFace)_face;
@@ -1056,7 +1194,9 @@
         ALOGD("nAllocation2DData, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i) "
               "type(%i)", (RsContext)con, alloc, xoff, yoff, w, h, sizeBytes, dataType);
     }
-    PER_ARRAY_TYPE(nullptr, rsAllocation2DData, true, (RsContext)con, alloc, xoff, yoff, lod, face, w, h, ptr, sizeBytes, 0);
+    int count = w * h;
+    PER_ARRAY_TYPE(nullptr, rsAllocation2DData, true,
+                   (RsContext)con, alloc, xoff, yoff, lod, face, w, h, ptr, sizeBytes, 0);
 }
 
 // Copies from the Allocation pointed to by srcAlloc into the Allocation
@@ -1090,7 +1230,8 @@
 // Copies from the Java object data into the Allocation pointed to by _alloc.
 static void
 nAllocationData3D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint xoff, jint yoff, jint zoff, jint lod,
-                    jint w, jint h, jint d, jobject data, int sizeBytes, int dataType)
+                  jint w, jint h, jint d, jobject data, jint sizeBytes, jint dataType,
+                  jint mSize, jboolean usePadding)
 {
     RsAllocation *alloc = (RsAllocation *)_alloc;
     if (kLogApi) {
@@ -1098,7 +1239,9 @@
               " h(%i), d(%i), sizeBytes(%i)", (RsContext)con, (RsAllocation)alloc, xoff, yoff, zoff,
               lod, w, h, d, sizeBytes);
     }
-    PER_ARRAY_TYPE(nullptr, rsAllocation3DData, true, (RsContext)con, alloc, xoff, yoff, zoff, lod, w, h, d, ptr, sizeBytes, 0);
+    int count = w * h * d;
+    PER_ARRAY_TYPE(nullptr, rsAllocation3DData, true,
+                   (RsContext)con, alloc, xoff, yoff, zoff, lod, w, h, d, ptr, sizeBytes, 0);
 }
 
 // Copies from the Allocation pointed to by srcAlloc into the Allocation
@@ -1130,26 +1273,31 @@
 
 // Copies from the Allocation pointed to by _alloc into the Java object data.
 static void
-nAllocationRead(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jobject data, int dataType)
+nAllocationRead(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jobject data, jint dataType,
+                jint mSize, jboolean usePadding)
 {
     RsAllocation *alloc = (RsAllocation *)_alloc;
     if (kLogApi) {
         ALOGD("nAllocationRead, con(%p), alloc(%p)", (RsContext)con, (RsAllocation)alloc);
     }
-    PER_ARRAY_TYPE(0, rsAllocationRead, false, (RsContext)con, alloc, ptr, len * typeBytes);
+    int count = 0;
+    PER_ARRAY_TYPE(0, rsAllocationRead, false,
+                   (RsContext)con, alloc, ptr, len * typeBytes);
 }
 
 // Copies from the Allocation pointed to by _alloc into the Java object data.
 static void
 nAllocationRead1D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint offset, jint lod,
-                  jint count, jobject data, int sizeBytes, int dataType)
+                  jint count, jobject data, jint sizeBytes, jint dataType,
+                  jint mSize, jboolean usePadding)
 {
     RsAllocation *alloc = (RsAllocation *)_alloc;
     if (kLogApi) {
         ALOGD("nAllocation1DRead, con(%p), adapter(%p), offset(%i), count(%i), sizeBytes(%i), "
               "dataType(%i)", (RsContext)con, alloc, offset, count, sizeBytes, dataType);
     }
-    PER_ARRAY_TYPE(0, rsAllocation1DRead, false, (RsContext)con, alloc, offset, lod, count, ptr, sizeBytes);
+    PER_ARRAY_TYPE(0, rsAllocation1DRead, false,
+                   (RsContext)con, alloc, offset, lod, count, ptr, sizeBytes);
 }
 
 // Copies from the Element in the Allocation pointed to by _alloc into the Java array data.
@@ -1170,7 +1318,8 @@
 // Copies from the Allocation pointed to by _alloc into the Java object data.
 static void
 nAllocationRead2D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint xoff, jint yoff, jint lod, jint _face,
-                  jint w, jint h, jobject data, int sizeBytes, int dataType)
+                  jint w, jint h, jobject data, jint sizeBytes, jint dataType,
+                  jint mSize, jboolean usePadding)
 {
     RsAllocation *alloc = (RsAllocation *)_alloc;
     RsAllocationCubemapFace face = (RsAllocationCubemapFace)_face;
@@ -1178,13 +1327,16 @@
         ALOGD("nAllocation2DRead, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i) "
               "type(%i)", (RsContext)con, alloc, xoff, yoff, w, h, sizeBytes, dataType);
     }
-    PER_ARRAY_TYPE(0, rsAllocation2DRead, false, (RsContext)con, alloc, xoff, yoff, lod, face, w, h,
-                   ptr, sizeBytes, 0);
+    int count = w * h;
+    PER_ARRAY_TYPE(0, rsAllocation2DRead, false,
+                   (RsContext)con, alloc, xoff, yoff, lod, face, w, h, ptr, sizeBytes, 0);
 }
+
 // Copies from the Allocation pointed to by _alloc into the Java object data.
 static void
 nAllocationRead3D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint xoff, jint yoff, jint zoff, jint lod,
-                  jint w, jint h, jint d, jobject data, int sizeBytes, int dataType)
+                  jint w, jint h, jint d, jobject data, int sizeBytes, int dataType,
+                  jint mSize, jboolean usePadding)
 {
     RsAllocation *alloc = (RsAllocation *)_alloc;
     if (kLogApi) {
@@ -1192,8 +1344,9 @@
               " h(%i), d(%i), sizeBytes(%i)", (RsContext)con, (RsAllocation)alloc, xoff, yoff, zoff,
               lod, w, h, d, sizeBytes);
     }
-    PER_ARRAY_TYPE(0, rsAllocation3DRead, false, (RsContext)con, alloc, xoff, yoff, zoff, lod, w, h, d,
-                   ptr, sizeBytes, 0);
+    int count = w * h * d;
+    PER_ARRAY_TYPE(nullptr, rsAllocation3DRead, false,
+                   (RsContext)con, alloc, xoff, yoff, zoff, lod, w, h, d, ptr, sizeBytes, 0);
 }
 
 static jlong
@@ -2214,17 +2367,17 @@
 {"rsnAllocationSetSurface",          "(JJLandroid/view/Surface;)V",           (void*)nAllocationSetSurface },
 {"rsnAllocationIoSend",              "(JJ)V",                                 (void*)nAllocationIoSend },
 {"rsnAllocationIoReceive",           "(JJ)V",                                 (void*)nAllocationIoReceive },
-{"rsnAllocationData1D",              "(JJIIILjava/lang/Object;II)V",          (void*)nAllocationData1D },
+{"rsnAllocationData1D",              "(JJIIILjava/lang/Object;IIIZ)V",        (void*)nAllocationData1D },
 {"rsnAllocationElementData",         "(JJIIIII[BI)V",                         (void*)nAllocationElementData },
-{"rsnAllocationData2D",              "(JJIIIIIILjava/lang/Object;II)V",       (void*)nAllocationData2D },
+{"rsnAllocationData2D",              "(JJIIIIIILjava/lang/Object;IIIZ)V",     (void*)nAllocationData2D },
 {"rsnAllocationData2D",              "(JJIIIIIIJIIII)V",                      (void*)nAllocationData2D_alloc },
-{"rsnAllocationData3D",              "(JJIIIIIIILjava/lang/Object;II)V",      (void*)nAllocationData3D },
+{"rsnAllocationData3D",              "(JJIIIIIIILjava/lang/Object;IIIZ)V",    (void*)nAllocationData3D },
 {"rsnAllocationData3D",              "(JJIIIIIIIJIIII)V",                     (void*)nAllocationData3D_alloc },
-{"rsnAllocationRead",                "(JJLjava/lang/Object;I)V",              (void*)nAllocationRead },
-{"rsnAllocationRead1D",              "(JJIIILjava/lang/Object;II)V",          (void*)nAllocationRead1D },
+{"rsnAllocationRead",                "(JJLjava/lang/Object;IIZ)V",            (void*)nAllocationRead },
+{"rsnAllocationRead1D",              "(JJIIILjava/lang/Object;IIIZ)V",        (void*)nAllocationRead1D },
 {"rsnAllocationElementRead",         "(JJIIIIILjava/lang/Object;II)V",        (void*)nAllocationElementRead },
-{"rsnAllocationRead2D",              "(JJIIIIIILjava/lang/Object;II)V",       (void*)nAllocationRead2D },
-{"rsnAllocationRead3D",              "(JJIIIIIIILjava/lang/Object;II)V",      (void*)nAllocationRead3D },
+{"rsnAllocationRead2D",              "(JJIIIIIILjava/lang/Object;IIIZ)V",     (void*)nAllocationRead2D },
+{"rsnAllocationRead3D",              "(JJIIIIIIILjava/lang/Object;IIIZ)V",    (void*)nAllocationRead3D },
 {"rsnAllocationGetType",             "(JJ)J",                                 (void*)nAllocationGetType},
 {"rsnAllocationResize1D",            "(JJI)V",                                (void*)nAllocationResize1D },
 {"rsnAllocationGenerateMipmaps",     "(JJ)V",                                 (void*)nAllocationGenerateMipmaps },