Home | History | Annotate | Download | only in jni
      1 /*
      2  * Copyright (C) 2011-2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define LOG_TAG "libRS_jni"
     18 
     19 #include <stdlib.h>
     20 #include <stdio.h>
     21 #include <fcntl.h>
     22 #include <unistd.h>
     23 #include <math.h>
     24 #include <android/bitmap.h>
     25 #include <android/log.h>
     26 
     27 #include <rsEnv.h>
     28 #include "rsDispatch.h"
     29 #include <dlfcn.h>
     30 
     31 //#define LOG_API ALOG
     32 #define LOG_API(...)
     33 #define LOG_ERR(...) __android_log_print(ANDROID_LOG_ERROR, "RenderScript JNI", __VA_ARGS__);
     34 #define RS_JNI_VERSION 2301
     35 
     36 #define NELEM(m) (sizeof(m) / sizeof((m)[0]))
     37 
     38 template <typename... T>
     39 void UNUSED(T... t) {}
     40 #define PER_ARRAY_TYPE(flag, fnc, readonly, ...) {                                      \
     41     jint len = 0;                                                                       \
     42     void *ptr = nullptr;                                                                \
     43     void *srcPtr = nullptr;                                                             \
     44     size_t typeBytes = 0;                                                               \
     45     jint relFlag = 0;                                                                   \
     46     if (readonly) {                                                                     \
     47         /* The on-release mode should only be JNI_ABORT for read-only accesses. */      \
     48         /* readonly = true, also indicates we are copying to the allocation   . */      \
     49         relFlag = JNI_ABORT;                                                            \
     50     }                                                                                   \
     51     switch(dataType) {                                                                  \
     52     case RS_TYPE_FLOAT_32:                                                              \
     53         len = _env->GetArrayLength((jfloatArray)data);                                  \
     54         ptr = _env->GetFloatArrayElements((jfloatArray)data, flag);                     \
     55         typeBytes = 4;                                                                  \
     56         if (usePadding) {                                                               \
     57             srcPtr = ptr;                                                               \
     58             len = len / 3 * 4;                                                          \
     59             if (count == 0) {                                                           \
     60                 count = len / 4;                                                        \
     61             }                                                                           \
     62             ptr = malloc (len * typeBytes);                                             \
     63             if (readonly) {                                                             \
     64                 copyWithPadding(ptr, srcPtr, mSize, count);                             \
     65                 fnc(__VA_ARGS__);                                                       \
     66             } else {                                                                    \
     67                 fnc(__VA_ARGS__);                                                       \
     68                 copyWithUnPadding(srcPtr, ptr, mSize, count);                           \
     69             }                                                                           \
     70             free(ptr);                                                                  \
     71             ptr = srcPtr;                                                               \
     72         } else {                                                                        \
     73             fnc(__VA_ARGS__);                                                           \
     74         }                                                                               \
     75         _env->ReleaseFloatArrayElements((jfloatArray)data, (jfloat *)ptr, relFlag);     \
     76         return;                                                                         \
     77     case RS_TYPE_FLOAT_64:                                                              \
     78         len = _env->GetArrayLength((jdoubleArray)data);                                 \
     79         ptr = _env->GetDoubleArrayElements((jdoubleArray)data, flag);                   \
     80         typeBytes = 8;                                                                  \
     81         if (usePadding) {                                                               \
     82             srcPtr = ptr;                                                               \
     83             len = len / 3 * 4;                                                          \
     84             if (count == 0) {                                                           \
     85                 count = len / 4;                                                        \
     86             }                                                                           \
     87             ptr = malloc (len * typeBytes);                                             \
     88             if (readonly) {                                                             \
     89                 copyWithPadding(ptr, srcPtr, mSize, count);                             \
     90                 fnc(__VA_ARGS__);                                                       \
     91             } else {                                                                    \
     92                 fnc(__VA_ARGS__);                                                       \
     93                 copyWithUnPadding(srcPtr, ptr, mSize, count);                           \
     94             }                                                                           \
     95             free(ptr);                                                                  \
     96             ptr = srcPtr;                                                               \
     97         } else {                                                                        \
     98             fnc(__VA_ARGS__);                                                           \
     99         }                                                                               \
    100         _env->ReleaseDoubleArrayElements((jdoubleArray)data, (jdouble *)ptr, relFlag);  \
    101         return;                                                                         \
    102     case RS_TYPE_SIGNED_8:                                                              \
    103     case RS_TYPE_UNSIGNED_8:                                                            \
    104         len = _env->GetArrayLength((jbyteArray)data);                                   \
    105         ptr = _env->GetByteArrayElements((jbyteArray)data, flag);                       \
    106         typeBytes = 1;                                                                  \
    107         if (usePadding) {                                                               \
    108             srcPtr = ptr;                                                               \
    109             len = len / 3 * 4;                                                          \
    110             if (count == 0) {                                                           \
    111                 count = len / 4;                                                        \
    112             }                                                                           \
    113             ptr = malloc (len * typeBytes);                                             \
    114             if (readonly) {                                                             \
    115                 copyWithPadding(ptr, srcPtr, mSize, count);                             \
    116                 fnc(__VA_ARGS__);                                                       \
    117             } else {                                                                    \
    118                 fnc(__VA_ARGS__);                                                       \
    119                 copyWithUnPadding(srcPtr, ptr, mSize, count);                           \
    120             }                                                                           \
    121             free(ptr);                                                                  \
    122             ptr = srcPtr;                                                               \
    123         } else {                                                                        \
    124             fnc(__VA_ARGS__);                                                           \
    125         }                                                                               \
    126         _env->ReleaseByteArrayElements((jbyteArray)data, (jbyte*)ptr, relFlag);         \
    127         return;                                                                         \
    128     case RS_TYPE_SIGNED_16:                                                             \
    129     case RS_TYPE_UNSIGNED_16:                                                           \
    130         len = _env->GetArrayLength((jshortArray)data);                                  \
    131         ptr = _env->GetShortArrayElements((jshortArray)data, flag);                     \
    132         typeBytes = 2;                                                                  \
    133         if (usePadding) {                                                               \
    134             srcPtr = ptr;                                                               \
    135             len = len / 3 * 4;                                                          \
    136             if (count == 0) {                                                           \
    137                 count = len / 4;                                                        \
    138             }                                                                           \
    139             ptr = malloc (len * typeBytes);                                             \
    140             if (readonly) {                                                             \
    141                 copyWithPadding(ptr, srcPtr, mSize, count);                             \
    142                 fnc(__VA_ARGS__);                                                       \
    143             } else {                                                                    \
    144                 fnc(__VA_ARGS__);                                                       \
    145                 copyWithUnPadding(srcPtr, ptr, mSize, count);                           \
    146             }                                                                           \
    147             free(ptr);                                                                  \
    148             ptr = srcPtr;                                                               \
    149         } else {                                                                        \
    150             fnc(__VA_ARGS__);                                                           \
    151         }                                                                               \
    152         _env->ReleaseShortArrayElements((jshortArray)data, (jshort *)ptr, relFlag);     \
    153         return;                                                                         \
    154     case RS_TYPE_SIGNED_32:                                                             \
    155     case RS_TYPE_UNSIGNED_32:                                                           \
    156         len = _env->GetArrayLength((jintArray)data);                                    \
    157         ptr = _env->GetIntArrayElements((jintArray)data, flag);                         \
    158         typeBytes = 4;                                                                  \
    159         if (usePadding) {                                                               \
    160             srcPtr = ptr;                                                               \
    161             len = len / 3 * 4;                                                          \
    162             if (count == 0) {                                                           \
    163                 count = len / 4;                                                        \
    164             }                                                                           \
    165             ptr = malloc (len * typeBytes);                                             \
    166             if (readonly) {                                                             \
    167                 copyWithPadding(ptr, srcPtr, mSize, count);                             \
    168                 fnc(__VA_ARGS__);                                                       \
    169             } else {                                                                    \
    170                 fnc(__VA_ARGS__);                                                       \
    171                 copyWithUnPadding(srcPtr, ptr, mSize, count);                           \
    172             }                                                                           \
    173             free(ptr);                                                                  \
    174             ptr = srcPtr;                                                               \
    175         } else {                                                                        \
    176             fnc(__VA_ARGS__);                                                           \
    177         }                                                                               \
    178         _env->ReleaseIntArrayElements((jintArray)data, (jint *)ptr, relFlag);           \
    179         return;                                                                         \
    180     case RS_TYPE_SIGNED_64:                                                             \
    181     case RS_TYPE_UNSIGNED_64:                                                           \
    182         len = _env->GetArrayLength((jlongArray)data);                                   \
    183         ptr = _env->GetLongArrayElements((jlongArray)data, flag);                       \
    184         typeBytes = 8;                                                                  \
    185         if (usePadding) {                                                               \
    186             srcPtr = ptr;                                                               \
    187             len = len / 3 * 4;                                                          \
    188             if (count == 0) {                                                           \
    189                 count = len / 4;                                                        \
    190             }                                                                           \
    191             ptr = malloc (len * typeBytes);                                             \
    192             if (readonly) {                                                             \
    193                 copyWithPadding(ptr, srcPtr, mSize, count);                             \
    194                 fnc(__VA_ARGS__);                                                       \
    195             } else {                                                                    \
    196                 fnc(__VA_ARGS__);                                                       \
    197                 copyWithUnPadding(srcPtr, ptr, mSize, count);                           \
    198             }                                                                           \
    199             free(ptr);                                                                  \
    200             ptr = srcPtr;                                                               \
    201         } else {                                                                        \
    202             fnc(__VA_ARGS__);                                                           \
    203         }                                                                               \
    204         _env->ReleaseLongArrayElements((jlongArray)data, (jlong *)ptr, relFlag);        \
    205         return;                                                                         \
    206     default:                                                                            \
    207         break;                                                                          \
    208     }                                                                                   \
    209     UNUSED(len, ptr, srcPtr, typeBytes, relFlag);                                       \
    210 }
    211 
    212 
    213 class AutoJavaStringToUTF8 {
    214 public:
    215     AutoJavaStringToUTF8(JNIEnv* env, jstring str) : fEnv(env), fJStr(str) {
    216         fCStr = env->GetStringUTFChars(str, NULL);
    217         fLength = env->GetStringUTFLength(str);
    218     }
    219     ~AutoJavaStringToUTF8() {
    220         fEnv->ReleaseStringUTFChars(fJStr, fCStr);
    221     }
    222     const char* c_str() const { return fCStr; }
    223     jsize length() const { return fLength; }
    224 
    225 private:
    226     JNIEnv*     fEnv;
    227     jstring     fJStr;
    228     const char* fCStr;
    229     jsize       fLength;
    230 };
    231 
    232 class AutoJavaStringArrayToUTF8 {
    233 public:
    234     AutoJavaStringArrayToUTF8(JNIEnv* env, jobjectArray strings, jsize stringsLength)
    235     : mEnv(env), mStrings(strings), mStringsLength(stringsLength) {
    236         mCStrings = NULL;
    237         mSizeArray = NULL;
    238         if (stringsLength > 0) {
    239             mCStrings = (const char **)calloc(stringsLength, sizeof(char *));
    240             mSizeArray = (size_t*)calloc(stringsLength, sizeof(size_t));
    241             for (jsize ct = 0; ct < stringsLength; ct ++) {
    242                 jstring s = (jstring)mEnv->GetObjectArrayElement(mStrings, ct);
    243                 mCStrings[ct] = mEnv->GetStringUTFChars(s, NULL);
    244                 mSizeArray[ct] = mEnv->GetStringUTFLength(s);
    245             }
    246         }
    247     }
    248     ~AutoJavaStringArrayToUTF8() {
    249         for (jsize ct=0; ct < mStringsLength; ct++) {
    250             jstring s = (jstring)mEnv->GetObjectArrayElement(mStrings, ct);
    251             mEnv->ReleaseStringUTFChars(s, mCStrings[ct]);
    252         }
    253         free(mCStrings);
    254         free(mSizeArray);
    255     }
    256     const char **c_str() const { return mCStrings; }
    257     size_t *c_str_len() const { return mSizeArray; }
    258     jsize length() const { return mStringsLength; }
    259 
    260 private:
    261     JNIEnv      *mEnv;
    262     jobjectArray mStrings;
    263     const char **mCStrings;
    264     size_t      *mSizeArray;
    265     jsize        mStringsLength;
    266 };
    267 
    268 
    269 // ---------------------------------------------------------------------------
    270 static dispatchTable dispatchTab;
    271 // Incremental Support lib
    272 static dispatchTable dispatchTabInc;
    273 
    274 static jboolean nLoadSO(JNIEnv *_env, jobject _this, jboolean useNative, jint targetApi, jstring libPath) {
    275     void* handle = NULL;
    276     if (useNative) {
    277         handle = dlopen("libRS.so", RTLD_LAZY | RTLD_LOCAL);
    278     } else {
    279         // For API 9+, dlopen the full path of libRSSupport.
    280         if (libPath != NULL) {
    281             const char * libPathJni = _env->GetStringUTFChars(libPath, JNI_FALSE);
    282             handle = dlopen(libPathJni, RTLD_LAZY | RTLD_LOCAL);
    283             _env->ReleaseStringUTFChars(libPath, libPathJni);
    284         } else {
    285             handle = dlopen("libRSSupport.so", RTLD_LAZY | RTLD_LOCAL);
    286         }
    287     }
    288     if (handle == NULL) {
    289         LOG_ERR("couldn't dlopen %s; librsjni version: %d", dlerror(), RS_JNI_VERSION);
    290         return false;
    291     }
    292 
    293     if (loadSymbols(handle, dispatchTab, targetApi) == false) {
    294         LOG_ERR("Dispatch table init failed! librsjni version: %d", RS_JNI_VERSION);
    295         dlclose(handle);
    296         return false;
    297     }
    298     LOG_API("Successfully loaded runtime");
    299     return true;
    300 }
    301 
    302 static ioSuppDT ioDispatch;
    303 static jboolean nLoadIOSO(JNIEnv *_env, jobject _this) {
    304     void* handleIO = NULL;
    305     handleIO = dlopen("libRSSupportIO.so", RTLD_LAZY | RTLD_LOCAL);
    306     if (handleIO == NULL) {
    307         LOG_ERR("Couldn't load libRSSupportIO.so, librsjni version: %d", RS_JNI_VERSION);
    308         return false;
    309     }
    310     if (loadIOSuppSyms(handleIO, ioDispatch) == false) {
    311         LOG_ERR("libRSSupportIO init failed! librsjni version: %d", RS_JNI_VERSION);
    312         return false;
    313     }
    314     return true;
    315 }
    316 
    317 // ---------------------------------------------------------------------------
    318 
    319 static void copyWithPadding(void* ptr, void* srcPtr, int mSize, int count) {
    320     int sizeBytesPad = mSize * 4;
    321     int sizeBytes = mSize * 3;
    322     uint8_t *dst = static_cast<uint8_t *>(ptr);
    323     uint8_t *src = static_cast<uint8_t *>(srcPtr);
    324     for (int i = 0; i < count; i++) {
    325         memcpy(dst, src, sizeBytes);
    326         dst += sizeBytesPad;
    327         src += sizeBytes;
    328     }
    329 }
    330 
    331 static void copyWithUnPadding(void* ptr, void* srcPtr, int mSize, int count) {
    332     int sizeBytesPad = mSize * 4;
    333     int sizeBytes = mSize * 3;
    334     uint8_t *dst = static_cast<uint8_t *>(ptr);
    335     uint8_t *src = static_cast<uint8_t *>(srcPtr);
    336     for (int i = 0; i < count; i++) {
    337         memcpy(dst, src, sizeBytes);
    338         dst += sizeBytes;
    339         src += sizeBytesPad;
    340     }
    341 }
    342 
    343 
    344 // ---------------------------------------------------------------------------
    345 
    346 static void
    347 nContextFinish(JNIEnv *_env, jobject _this, jlong con)
    348 {
    349     LOG_API("nContextFinish, con(%p)", (RsContext)con);
    350     dispatchTab.ContextFinish((RsContext)con);
    351 }
    352 
    353 static jlong
    354 nClosureCreate(JNIEnv *_env, jobject _this, jlong con, jlong kernelID,
    355                jlong returnValue, jlongArray fieldIDArray,
    356                jlongArray valueArray, jintArray sizeArray,
    357                jlongArray depClosureArray, jlongArray depFieldIDArray) {
    358   jlong ret = 0;
    359 
    360   jlong* jFieldIDs = _env->GetLongArrayElements(fieldIDArray, nullptr);
    361   jsize fieldIDs_length = _env->GetArrayLength(fieldIDArray);
    362   jlong* jValues = _env->GetLongArrayElements(valueArray, nullptr);
    363   jsize values_length = _env->GetArrayLength(valueArray);
    364   jint* jSizes = _env->GetIntArrayElements(sizeArray, nullptr);
    365   jsize sizes_length = _env->GetArrayLength(sizeArray);
    366   jlong* jDepClosures =
    367       _env->GetLongArrayElements(depClosureArray, nullptr);
    368   jsize depClosures_length = _env->GetArrayLength(depClosureArray);
    369   jlong* jDepFieldIDs =
    370       _env->GetLongArrayElements(depFieldIDArray, nullptr);
    371   jsize depFieldIDs_length = _env->GetArrayLength(depFieldIDArray);
    372 
    373   size_t numValues, numDependencies;
    374   RsScriptFieldID* fieldIDs;
    375   RsClosure* depClosures;
    376   RsScriptFieldID* depFieldIDs;
    377 
    378   if (fieldIDs_length != values_length || values_length != sizes_length) {
    379       LOG_ERR("Unmatched field IDs, values, and sizes in closure creation.");
    380       goto exit;
    381   }
    382 
    383   numValues = (size_t)fieldIDs_length;
    384 
    385   if (depClosures_length != depFieldIDs_length) {
    386       LOG_ERR("Unmatched closures and field IDs for dependencies in closure creation.");
    387       goto exit;
    388   }
    389 
    390   numDependencies = (size_t)depClosures_length;
    391 
    392   if (numDependencies > numValues) {
    393       LOG_ERR("Unexpected number of dependencies in closure creation");
    394       goto exit;
    395   }
    396 
    397   if (numValues > RS_CLOSURE_MAX_NUMBER_ARGS_AND_BINDINGS) {
    398       LOG_ERR("Too many arguments or globals in closure creation");
    399       goto exit;
    400   }
    401 
    402   fieldIDs = (RsScriptFieldID*)alloca(sizeof(RsScriptFieldID) * numValues);
    403   if (fieldIDs == nullptr) {
    404       goto exit;
    405   }
    406 
    407   for (size_t i = 0; i < numValues; i++) {
    408     fieldIDs[i] = (RsScriptFieldID)jFieldIDs[i];
    409   }
    410 
    411   depClosures = (RsClosure*)alloca(sizeof(RsClosure) * numDependencies);
    412   if (depClosures == nullptr) {
    413       goto exit;
    414   }
    415 
    416   for (size_t i = 0; i < numDependencies; i++) {
    417     depClosures[i] = (RsClosure)jDepClosures[i];
    418   }
    419 
    420   depFieldIDs = (RsScriptFieldID*)alloca(sizeof(RsScriptFieldID) * numDependencies);
    421   if (depFieldIDs == nullptr) {
    422       goto exit;
    423   }
    424 
    425   for (size_t i = 0; i < numDependencies; i++) {
    426     depFieldIDs[i] = (RsClosure)jDepFieldIDs[i];
    427   }
    428 
    429   ret = (jlong)(uintptr_t)dispatchTab.ClosureCreate(
    430       (RsContext)con, (RsScriptKernelID)kernelID, (RsAllocation)returnValue,
    431       fieldIDs, numValues, jValues, numValues,
    432       (int*)jSizes, numValues,
    433       depClosures, numDependencies,
    434       depFieldIDs, numDependencies);
    435 
    436 exit:
    437 
    438   _env->ReleaseLongArrayElements(depFieldIDArray, jDepFieldIDs, JNI_ABORT);
    439   _env->ReleaseLongArrayElements(depClosureArray, jDepClosures, JNI_ABORT);
    440   _env->ReleaseIntArrayElements (sizeArray,       jSizes,       JNI_ABORT);
    441   _env->ReleaseLongArrayElements(valueArray,      jValues,      JNI_ABORT);
    442   _env->ReleaseLongArrayElements(fieldIDArray,    jFieldIDs,    JNI_ABORT);
    443 
    444   return ret;
    445 }
    446 
    447 static jlong
    448 nInvokeClosureCreate(JNIEnv *_env, jobject _this, jlong con, jlong invokeID,
    449                      jbyteArray paramArray, jlongArray fieldIDArray, jlongArray valueArray,
    450                      jintArray sizeArray) {
    451   jlong ret = 0;
    452 
    453   jbyte* jParams = _env->GetByteArrayElements(paramArray, nullptr);
    454   jsize jParamLength = _env->GetArrayLength(paramArray);
    455   jlong* jFieldIDs = _env->GetLongArrayElements(fieldIDArray, nullptr);
    456   jsize fieldIDs_length = _env->GetArrayLength(fieldIDArray);
    457   jlong* jValues = _env->GetLongArrayElements(valueArray, nullptr);
    458   jsize values_length = _env->GetArrayLength(valueArray);
    459   jint* jSizes = _env->GetIntArrayElements(sizeArray, nullptr);
    460   jsize sizes_length = _env->GetArrayLength(sizeArray);
    461 
    462   size_t numValues;
    463   RsScriptFieldID* fieldIDs;
    464 
    465   if (fieldIDs_length != values_length || values_length != sizes_length) {
    466       LOG_ERR("Unmatched field IDs, values, and sizes in closure creation.");
    467       goto exit;
    468   }
    469 
    470   numValues = (size_t) fieldIDs_length;
    471 
    472   if (numValues > RS_CLOSURE_MAX_NUMBER_ARGS_AND_BINDINGS) {
    473       LOG_ERR("Too many arguments or globals in closure creation");
    474       goto exit;
    475   }
    476 
    477   fieldIDs = (RsScriptFieldID*)alloca(sizeof(RsScriptFieldID) * numValues);
    478   if (fieldIDs == nullptr) {
    479       goto exit;
    480   }
    481 
    482   for (size_t i = 0; i < numValues; i++) {
    483     fieldIDs[i] = (RsScriptFieldID)jFieldIDs[i];
    484   }
    485 
    486   ret = (jlong)(uintptr_t)dispatchTab.InvokeClosureCreate(
    487       (RsContext)con, (RsScriptInvokeID)invokeID, jParams, jParamLength,
    488       fieldIDs, numValues, jValues, numValues,
    489       (int*)jSizes, numValues);
    490 
    491 exit:
    492 
    493   _env->ReleaseIntArrayElements (sizeArray,       jSizes,       JNI_ABORT);
    494   _env->ReleaseLongArrayElements(valueArray,      jValues,      JNI_ABORT);
    495   _env->ReleaseLongArrayElements(fieldIDArray,    jFieldIDs,    JNI_ABORT);
    496   _env->ReleaseByteArrayElements(paramArray,      jParams,      JNI_ABORT);
    497 
    498   return ret;
    499 }
    500 
    501 static void
    502 nClosureSetArg(JNIEnv *_env, jobject _this, jlong con, jlong closureID,
    503                jint index, jlong value, jint size) {
    504   // Size is signed with -1 indicating the values is an Allocation
    505   dispatchTab.ClosureSetArg((RsContext)con, (RsClosure)closureID, (uint32_t)index,
    506                   (uintptr_t)value, size);
    507 }
    508 
    509 static void
    510 nClosureSetGlobal(JNIEnv *_env, jobject _this, jlong con, jlong closureID,
    511                   jlong fieldID, jlong value, jint size) {
    512   // Size is signed with -1 indicating the values is an Allocation
    513   dispatchTab.ClosureSetGlobal((RsContext)con, (RsClosure)closureID,
    514                      (RsScriptFieldID)fieldID, (int64_t)value, size);
    515 }
    516 
    517 static long
    518 nScriptGroup2Create(JNIEnv *_env, jobject _this, jlong con, jstring name,
    519                     jstring cacheDir, jlongArray closureArray) {
    520   jlong ret = 0;
    521 
    522   AutoJavaStringToUTF8 nameUTF(_env, name);
    523   AutoJavaStringToUTF8 cacheDirUTF(_env, cacheDir);
    524 
    525   jlong* jClosures = _env->GetLongArrayElements(closureArray, nullptr);
    526   jsize numClosures = _env->GetArrayLength(closureArray);
    527 
    528   RsClosure* closures;
    529 
    530   if (numClosures > (jsize) RS_SCRIPT_GROUP_MAX_NUMBER_CLOSURES) {
    531     LOG_ERR("Too many closures in script group");
    532     goto exit;
    533   }
    534 
    535   closures = (RsClosure*)alloca(sizeof(RsClosure) * numClosures);
    536   if (closures == nullptr) {
    537       goto exit;
    538   }
    539 
    540   for (int i = 0; i < numClosures; i++) {
    541     closures[i] = (RsClosure)jClosures[i];
    542   }
    543 
    544   ret = (jlong)(uintptr_t)dispatchTab.ScriptGroup2Create(
    545       (RsContext)con, nameUTF.c_str(), nameUTF.length(),
    546       cacheDirUTF.c_str(), cacheDirUTF.length(),
    547       closures, numClosures);
    548 
    549 exit:
    550 
    551   _env->ReleaseLongArrayElements(closureArray, jClosures, JNI_ABORT);
    552 
    553   return ret;
    554 }
    555 
    556 static void
    557 nScriptGroup2Execute(JNIEnv *_env, jobject _this, jlong con, jlong groupID) {
    558   dispatchTab.ScriptGroupExecute((RsContext)con, (RsScriptGroup2)groupID);
    559 }
    560 
    561 static void
    562 nObjDestroy(JNIEnv *_env, jobject _this, jlong con, jlong obj)
    563 {
    564     LOG_API("nObjDestroy, con(%p) obj(%p)", (RsContext)con, (void *)obj);
    565     dispatchTab.ObjDestroy((RsContext)con, (void *)obj);
    566 }
    567 
    568 
    569 static void
    570 nScriptIntrinsicBLAS_Single(JNIEnv *_env, jobject _this, jlong con, jlong incCon, jlong id, jint func, jint TransA,
    571                             jint TransB, jint Side, jint Uplo, jint Diag, jint M, jint N, jint K,
    572                             jfloat alpha, jlong A, jlong B, jfloat beta, jlong C, jint incX, jint incY,
    573                             jint KL, jint KU, jboolean mUseInc) {
    574     RsBlasCall call;
    575     memset(&call, 0, sizeof(call));
    576     call.func = (RsBlasFunction)func;
    577     call.transA = (RsBlasTranspose)TransA;
    578     call.transB = (RsBlasTranspose)TransB;
    579     call.side = (RsBlasSide)Side;
    580     call.uplo = (RsBlasUplo)Uplo;
    581     call.diag = (RsBlasDiag)Diag;
    582     call.M = M;
    583     call.N = N;
    584     call.K = K;
    585     call.alpha.f = alpha;
    586     call.beta.f = beta;
    587     call.incX = incX;
    588     call.incY = incY;
    589     call.KL = KL;
    590     call.KU = KU;
    591 
    592     RsAllocation in_allocs[3];
    593     in_allocs[0] = (RsAllocation)A;
    594     in_allocs[1] = (RsAllocation)B;
    595     in_allocs[2] = (RsAllocation)C;
    596 
    597     if (mUseInc) {
    598         dispatchTab.ContextFinish((RsContext)con);
    599         dispatchTabInc.ScriptForEachMulti((RsContext)incCon, (RsScript)id, 0,
    600                                           in_allocs, NELEM(in_allocs), nullptr,
    601                                           &call, sizeof(call), nullptr, 0);
    602     } else {
    603         dispatchTab.ScriptForEachMulti((RsContext)con, (RsScript)id, 0,
    604                                        in_allocs, NELEM(in_allocs), nullptr,
    605                                        &call, sizeof(call), nullptr, 0);
    606     }
    607 }
    608 
    609 static void
    610 nScriptIntrinsicBLAS_Double(JNIEnv *_env, jobject _this, jlong con, jlong incCon, jlong id, jint func, jint TransA,
    611                             jint TransB, jint Side, jint Uplo, jint Diag, jint M, jint N, jint K,
    612                             jdouble alpha, jlong A, jlong B, jdouble beta, jlong C, jint incX, jint incY,
    613                             jint KL, jint KU, jboolean mUseInc) {
    614     RsBlasCall call;
    615     memset(&call, 0, sizeof(call));
    616     call.func = (RsBlasFunction)func;
    617     call.transA = (RsBlasTranspose)TransA;
    618     call.transB = (RsBlasTranspose)TransB;
    619     call.side = (RsBlasSide)Side;
    620     call.uplo = (RsBlasUplo)Uplo;
    621     call.diag = (RsBlasDiag)Diag;
    622     call.M = M;
    623     call.N = N;
    624     call.K = K;
    625     call.alpha.d = alpha;
    626     call.beta.d = beta;
    627     call.incX = incX;
    628     call.incY = incY;
    629     call.KL = KL;
    630     call.KU = KU;
    631 
    632     RsAllocation in_allocs[3];
    633     in_allocs[0] = (RsAllocation)A;
    634     in_allocs[1] = (RsAllocation)B;
    635     in_allocs[2] = (RsAllocation)C;
    636 
    637     if (mUseInc) {
    638         dispatchTab.ContextFinish((RsContext)con);
    639         dispatchTabInc.ScriptForEachMulti((RsContext)incCon, (RsScript)id, 0,
    640                                           in_allocs, NELEM(in_allocs), nullptr,
    641                                           &call, sizeof(call), nullptr, 0);
    642     } else {
    643         dispatchTab.ScriptForEachMulti((RsContext)con, (RsScript)id, 0,
    644                                         in_allocs, NELEM(in_allocs), nullptr,
    645                                         &call, sizeof(call), nullptr, 0);
    646     }
    647 }
    648 
    649 static void
    650 nScriptIntrinsicBLAS_Complex(JNIEnv *_env, jobject _this, jlong con, jlong incCon, jlong id, jint func, jint TransA,
    651                              jint TransB, jint Side, jint Uplo, jint Diag, jint M, jint N, jint K,
    652                              jfloat alphaX, jfloat alphaY, jlong A, jlong B, jfloat betaX,
    653                              jfloat betaY, jlong C, jint incX, jint incY, jint KL, jint KU, jboolean mUseInc) {
    654     RsBlasCall call;
    655     memset(&call, 0, sizeof(call));
    656     call.func = (RsBlasFunction)func;
    657     call.transA = (RsBlasTranspose)TransA;
    658     call.transB = (RsBlasTranspose)TransB;
    659     call.side = (RsBlasSide)Side;
    660     call.uplo = (RsBlasUplo)Uplo;
    661     call.diag = (RsBlasDiag)Diag;
    662     call.M = M;
    663     call.N = N;
    664     call.K = K;
    665     call.alpha.c.r = alphaX;
    666     call.alpha.c.i = alphaY;
    667     call.beta.c.r = betaX;
    668     call.beta.c.i = betaY;
    669     call.incX = incX;
    670     call.incY = incY;
    671     call.KL = KL;
    672     call.KU = KU;
    673 
    674     RsAllocation in_allocs[3];
    675     in_allocs[0] = (RsAllocation)A;
    676     in_allocs[1] = (RsAllocation)B;
    677     in_allocs[2] = (RsAllocation)C;
    678 
    679 
    680     if (mUseInc) {
    681         dispatchTab.ContextFinish((RsContext)con);
    682         dispatchTabInc.ScriptForEachMulti((RsContext)incCon, (RsScript)id, 0,
    683                                           in_allocs, NELEM(in_allocs), nullptr,
    684                                           &call, sizeof(call), nullptr, 0);
    685     } else {
    686         dispatchTab.ScriptForEachMulti((RsContext)con, (RsScript)id, 0,
    687                                        in_allocs, NELEM(in_allocs), nullptr,
    688                                        &call, sizeof(call), nullptr, 0);
    689     }
    690 }
    691 
    692 static void
    693 nScriptIntrinsicBLAS_Z(JNIEnv *_env, jobject _this, jlong con, jlong incCon, jlong id, jint func, jint TransA,
    694                        jint TransB, jint Side, jint Uplo, jint Diag, jint M, jint N, jint K,
    695                        jdouble alphaX, jdouble alphaY, jlong A, jlong B, jdouble betaX,
    696                        jdouble betaY, jlong C, jint incX, jint incY, jint KL, jint KU, jboolean mUseInc) {
    697     RsBlasCall call;
    698     memset(&call, 0, sizeof(call));
    699     call.func = (RsBlasFunction)func;
    700     call.transA = (RsBlasTranspose)TransA;
    701     call.transB = (RsBlasTranspose)TransB;
    702     call.side = (RsBlasSide)Side;
    703     call.uplo = (RsBlasUplo)Uplo;
    704     call.diag = (RsBlasDiag)Diag;
    705     call.M = M;
    706     call.N = N;
    707     call.K = K;
    708     call.alpha.z.r = alphaX;
    709     call.alpha.z.i = alphaY;
    710     call.beta.z.r = betaX;
    711     call.beta.z.i = betaY;
    712     call.incX = incX;
    713     call.incY = incY;
    714     call.KL = KL;
    715     call.KU = KU;
    716 
    717     RsAllocation in_allocs[3];
    718     in_allocs[0] = (RsAllocation)A;
    719     in_allocs[1] = (RsAllocation)B;
    720     in_allocs[2] = (RsAllocation)C;
    721 
    722 
    723     if (mUseInc) {
    724         dispatchTab.ContextFinish((RsContext)con);
    725         dispatchTabInc.ScriptForEachMulti((RsContext)incCon, (RsScript)id, 0,
    726                                           in_allocs, NELEM(in_allocs), nullptr,
    727                                           &call, sizeof(call), nullptr, 0);
    728     } else {
    729         dispatchTab.ScriptForEachMulti((RsContext)con, (RsScript)id, 0,
    730                                         in_allocs, NELEM(in_allocs), nullptr,
    731                                         &call, sizeof(call), nullptr, 0);
    732     }
    733 }
    734 
    735 
    736 static void
    737 nScriptIntrinsicBLAS_BNNM(JNIEnv *_env, jobject _this, jlong con, jlong incCon, jlong id, jint M, jint N, jint K,
    738                           jlong A, jint a_offset, jlong B, jint b_offset, jlong C, jint c_offset,
    739                           jint c_mult_int, jboolean mUseInc) {
    740     RsBlasCall call;
    741     memset(&call, 0, sizeof(call));
    742     call.func = RsBlas_bnnm;
    743     call.M = M;
    744     call.N = N;
    745     call.K = K;
    746     call.a_offset = a_offset & 0xFF;
    747     call.b_offset = b_offset & 0xFF;
    748     call.c_offset = c_offset;
    749     call.c_mult_int = c_mult_int;
    750 
    751     RsAllocation in_allocs[3];
    752     in_allocs[0] = (RsAllocation)A;
    753     in_allocs[1] = (RsAllocation)B;
    754     in_allocs[2] = (RsAllocation)C;
    755 
    756     if (mUseInc) {
    757         dispatchTab.ContextFinish((RsContext)con);
    758         dispatchTabInc.ScriptForEachMulti((RsContext)incCon, (RsScript)id, 0,
    759                                           in_allocs, NELEM(in_allocs), nullptr,
    760                                           &call, sizeof(call), nullptr, 0);
    761     } else {
    762         dispatchTab.ScriptForEachMulti((RsContext)con, (RsScript)id, 0,
    763                                         in_allocs, NELEM(in_allocs), nullptr,
    764                                         &call, sizeof(call), nullptr, 0);
    765     }
    766 }
    767 // ---------------------------------------------------------------------------
    768 static jlong
    769 nDeviceCreate(JNIEnv *_env, jobject _this)
    770 {
    771     LOG_API("nDeviceCreate");
    772     return (jlong)(uintptr_t)dispatchTab.DeviceCreate();
    773 }
    774 
    775 static void
    776 nDeviceDestroy(JNIEnv *_env, jobject _this, jlong dev)
    777 {
    778     LOG_API("nDeviceDestroy");
    779     return dispatchTab.DeviceDestroy((RsDevice)dev);
    780 }
    781 
    782 static void
    783 nDeviceSetConfig(JNIEnv *_env, jobject _this, jlong dev, jint p, jint value)
    784 {
    785     LOG_API("nDeviceSetConfig  dev(%p), param(%i), value(%i)", (void *)dev, p, value);
    786     return dispatchTab.DeviceSetConfig((RsDevice)dev, (RsDeviceParam)p, value);
    787 }
    788 
    789 static jlong
    790 nContextCreate(JNIEnv *_env, jobject _this, jlong dev, jint ver, jint sdkVer,
    791                jint ct, jstring nativeLibDirJava)
    792 {
    793     LOG_API("nContextCreate");
    794     // Access the NativeLibDir in the Java Context.
    795     const char * nativeLibDir = _env->GetStringUTFChars(nativeLibDirJava, JNI_FALSE);
    796     size_t length = (size_t)_env->GetStringUTFLength(nativeLibDirJava);
    797 
    798     jlong id = (jlong)(uintptr_t)dispatchTab.ContextCreate((RsDevice)dev, ver,
    799                                                            sdkVer,
    800                                                            (RsContextType)ct, 0);
    801     if (dispatchTab.SetNativeLibDir) {
    802         dispatchTab.SetNativeLibDir((RsContext)id, nativeLibDir, length);
    803     }
    804 
    805     _env->ReleaseStringUTFChars(nativeLibDirJava, nativeLibDir);
    806     return id;
    807 }
    808 
    809 
    810 static void
    811 nContextSetPriority(JNIEnv *_env, jobject _this, jlong con, jint p)
    812 {
    813     LOG_API("ContextSetPriority, con(%p), priority(%i)", (RsContext)con, p);
    814     dispatchTab.ContextSetPriority((RsContext)con, p);
    815 }
    816 
    817 
    818 
    819 static void
    820 nContextDestroy(JNIEnv *_env, jobject _this, jlong con)
    821 {
    822     LOG_API("nContextDestroy, con(%p)", (RsContext)con);
    823     dispatchTab.ContextDestroy((RsContext)con);
    824 }
    825 
    826 static void
    827 nContextDump(JNIEnv *_env, jobject _this, jlong con, jint bits)
    828 {
    829     LOG_API("nContextDump, con(%p)  bits(%i)", (RsContext)con, bits);
    830     dispatchTab.ContextDump((RsContext)con, bits);
    831 }
    832 
    833 
    834 static jstring
    835 nContextGetErrorMessage(JNIEnv *_env, jobject _this, jlong con)
    836 {
    837     LOG_API("nContextGetErrorMessage, con(%p)", (RsContext)con);
    838     char buf[1024];
    839 
    840     size_t receiveLen;
    841     uint32_t subID;
    842     int id = dispatchTab.ContextGetMessage((RsContext)con,
    843                                            buf, sizeof(buf),
    844                                            &receiveLen, sizeof(receiveLen),
    845                                            &subID, sizeof(subID));
    846     if (!id && receiveLen) {
    847         //        __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG,
    848         //            "message receive buffer too small.  %zu", receiveLen);
    849     }
    850     return _env->NewStringUTF(buf);
    851 }
    852 
    853 static jint
    854 nContextGetUserMessage(JNIEnv *_env, jobject _this, jlong con, jintArray data)
    855 {
    856     jint len = _env->GetArrayLength(data);
    857     LOG_API("nContextGetMessage, con(%p), len(%i)", (RsContext)con, len);
    858     jint *ptr = _env->GetIntArrayElements(data, NULL);
    859     size_t receiveLen;
    860     uint32_t subID;
    861     int id = dispatchTab.ContextGetMessage((RsContext)con,
    862                                            ptr, len * 4,
    863                                            &receiveLen, sizeof(receiveLen),
    864                                            &subID, sizeof(subID));
    865     if (!id && receiveLen) {
    866         //        __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG,
    867         //            "message receive buffer too small.  %zu", receiveLen);
    868     }
    869     _env->ReleaseIntArrayElements(data, ptr, 0);
    870     return (jint)id;
    871 }
    872 
    873 static jint
    874 nContextPeekMessage(JNIEnv *_env, jobject _this, jlong con, jintArray auxData)
    875 {
    876     LOG_API("nContextPeekMessage, con(%p)", (RsContext)con);
    877     jint *auxDataPtr = _env->GetIntArrayElements(auxData, NULL);
    878     size_t receiveLen;
    879     uint32_t subID;
    880     int id = dispatchTab.ContextPeekMessage((RsContext)con, &receiveLen, sizeof(receiveLen),
    881                                   &subID, sizeof(subID));
    882     auxDataPtr[0] = (jint)subID;
    883     auxDataPtr[1] = (jint)receiveLen;
    884     _env->ReleaseIntArrayElements(auxData, auxDataPtr, 0);
    885     return (jint)id;
    886 }
    887 
    888 static void nContextInitToClient(JNIEnv *_env, jobject _this, jlong con)
    889 {
    890     LOG_API("nContextInitToClient, con(%p)", (RsContext)con);
    891     dispatchTab.ContextInitToClient((RsContext)con);
    892 }
    893 
    894 static void nContextDeinitToClient(JNIEnv *_env, jobject _this, jlong con)
    895 {
    896     LOG_API("nContextDeinitToClient, con(%p)", (RsContext)con);
    897     dispatchTab.ContextDeinitToClient((RsContext)con);
    898 }
    899 
    900 static void
    901 nContextSendMessage(JNIEnv *_env, jobject _this, jlong con, jint id, jintArray data)
    902 {
    903     jint *ptr = NULL;
    904     jint len = 0;
    905     if (data) {
    906         len = _env->GetArrayLength(data);
    907         ptr = _env->GetIntArrayElements(data, NULL);
    908     }
    909     LOG_API("nContextSendMessage, con(%p), id(%i), len(%i)", (RsContext)con, id, len);
    910     dispatchTab.ContextSendMessage((RsContext)con, id, (const uint8_t *)ptr, len * sizeof(int));
    911     if (data) {
    912         _env->ReleaseIntArrayElements(data, ptr, JNI_ABORT);
    913     }
    914 }
    915 
    916 
    917 
    918 static jlong
    919 nElementCreate(JNIEnv *_env, jobject _this, jlong con, jlong type, jint kind,
    920                jboolean norm, jint size)
    921 {
    922     LOG_API("nElementCreate, con(%p), type(%i), kind(%i), norm(%i), size(%i)", (RsContext)con,
    923             type, kind, norm, size);
    924     return (jlong)(uintptr_t)dispatchTab.ElementCreate((RsContext)con,
    925                                                        (RsDataType)type,
    926                                                        (RsDataKind)kind,
    927                                                        norm, size);
    928 }
    929 
    930 static jlong
    931 nElementCreate2(JNIEnv *_env, jobject _this, jlong con,
    932                 jlongArray _ids, jobjectArray _names, jintArray _arraySizes)
    933 {
    934     int fieldCount = _env->GetArrayLength(_ids);
    935     LOG_API("nElementCreate2, con(%p)", (RsContext)con);
    936 
    937     jlong *jIds = _env->GetLongArrayElements(_ids, NULL);
    938     jint *jArraySizes = _env->GetIntArrayElements(_arraySizes, NULL);
    939 
    940     RsElement *ids = (RsElement*)malloc(fieldCount * sizeof(RsElement));
    941     uint32_t *arraySizes = (uint32_t *)malloc(fieldCount * sizeof(uint32_t));
    942 
    943     for(int i = 0; i < fieldCount; i ++) {
    944         ids[i] = (RsElement)jIds[i];
    945         arraySizes[i] = (uint32_t)jArraySizes[i];
    946     }
    947 
    948     AutoJavaStringArrayToUTF8 names(_env, _names, fieldCount);
    949 
    950     const char **nameArray = names.c_str();
    951     size_t *sizeArray = names.c_str_len();
    952 
    953     jlong id = (jlong)(uintptr_t)dispatchTab.ElementCreate2((RsContext)con, (RsElement *)ids,
    954                                                             fieldCount, nameArray,
    955                                                             fieldCount * sizeof(size_t),  sizeArray,
    956                                                             (const uint32_t *)arraySizes, fieldCount);
    957 
    958     free(ids);
    959     free(arraySizes);
    960     _env->ReleaseLongArrayElements(_ids, jIds, JNI_ABORT);
    961     _env->ReleaseIntArrayElements(_arraySizes, jArraySizes, JNI_ABORT);
    962     return id;
    963 }
    964 
    965 
    966 
    967 
    968 static void
    969 nElementGetSubElements(JNIEnv *_env, jobject _this, jlong con, jlong id,
    970                        jlongArray _IDs,
    971                        jobjectArray _names,
    972                        jintArray _arraySizes)
    973 {
    974     uint32_t dataSize = _env->GetArrayLength(_IDs);
    975     LOG_API("nElementGetSubElements, con(%p)", (RsContext)con);
    976 
    977     uintptr_t *ids = (uintptr_t *)malloc(dataSize * sizeof(uintptr_t));
    978     const char **names = (const char **)malloc((uint32_t)dataSize * sizeof(const char *));
    979     uint32_t *arraySizes = (uint32_t *)malloc((uint32_t)dataSize * sizeof(uint32_t));
    980 
    981     dispatchTab.ElementGetSubElements((RsContext)con, (RsElement)id, ids, names, arraySizes,
    982                                       (uint32_t)dataSize);
    983 
    984     for(uint32_t i = 0; i < dataSize; i++) {
    985         const jlong id = (jlong)(uintptr_t)ids[i];
    986         const jint arraySize = (jint)arraySizes[i];
    987         _env->SetObjectArrayElement(_names, i, _env->NewStringUTF(names[i]));
    988         _env->SetLongArrayRegion(_IDs, i, 1, &id);
    989         _env->SetIntArrayRegion(_arraySizes, i, 1, &arraySize);
    990     }
    991 
    992     free(ids);
    993     free(names);
    994     free(arraySizes);
    995 }
    996 
    997 // -----------------------------------
    998 
    999 static jlong
   1000 nTypeCreate(JNIEnv *_env, jobject _this, jlong con, jlong eid,
   1001             jint dimx, jint dimy, jint dimz, jboolean mips, jboolean faces, jint yuv)
   1002 {
   1003     LOG_API("nTypeCreate, con(%p) eid(%p), x(%i), y(%i), z(%i), mips(%i), faces(%i), yuv(%i)",
   1004             (RsContext)con, eid, dimx, dimy, dimz, mips, faces, yuv);
   1005 
   1006     return (jlong)(uintptr_t)dispatchTab.TypeCreate((RsContext)con, (RsElement)eid, dimx, dimy,
   1007                                                     dimz, mips, faces, yuv);
   1008 }
   1009 
   1010 // -----------------------------------
   1011 
   1012 static jlong
   1013 nAllocationCreateTyped(JNIEnv *_env, jobject _this, jlong con, jlong type, jint mips, jint usage,
   1014                        jlong pointer)
   1015 {
   1016     LOG_API("nAllocationCreateTyped, con(%p), type(%p), mip(%i), usage(%i), ptr(%p)",
   1017             (RsContext)con, (RsElement)type, mips, usage, (void *)pointer);
   1018     return (jlong)(uintptr_t) dispatchTab.AllocationCreateTyped((RsContext)con, (RsType)type,
   1019                                                                 (RsAllocationMipmapControl)mips,
   1020                                                                 (uint32_t)usage, (uintptr_t)pointer);
   1021 }
   1022 
   1023 static void
   1024 nAllocationSyncAll(JNIEnv *_env, jobject _this, jlong con, jlong a, jint bits)
   1025 {
   1026     LOG_API("nAllocationSyncAll, con(%p), a(%p), bits(0x%08x)", (RsContext)con, (RsAllocation)a, bits);
   1027     dispatchTab.AllocationSyncAll((RsContext)con, (RsAllocation)a, (RsAllocationUsageType)bits);
   1028 }
   1029 
   1030 static void
   1031 nAllocationSetSurface(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jobject sur)
   1032 {
   1033     ioDispatch.sAllocationSetSurface(_env, _this, (RsContext)con, (RsAllocation)alloc, sur, dispatchTab);
   1034 }
   1035 
   1036 static void
   1037 nAllocationIoSend(JNIEnv *_env, jobject _this, jlong con, jlong alloc)
   1038 {
   1039     dispatchTab.AllocationIoSend((RsContext)con, (RsAllocation)alloc);
   1040 }
   1041 
   1042 static void
   1043 nAllocationGenerateMipmaps(JNIEnv *_env, jobject _this, jlong con, jlong alloc)
   1044 {
   1045     LOG_API("nAllocationGenerateMipmaps, con(%p), a(%p)", (RsContext)con, (RsAllocation)alloc);
   1046     dispatchTab.AllocationGenerateMipmaps((RsContext)con, (RsAllocation)alloc);
   1047 }
   1048 
   1049 static size_t GetBitmapSize(JNIEnv *env, jobject jbitmap) {
   1050     AndroidBitmapInfo info;
   1051     memset(&info, 0, sizeof(info));
   1052     AndroidBitmap_getInfo(env, jbitmap, &info);
   1053     size_t s = info.width * info.height;
   1054     switch (info.format) {
   1055         case ANDROID_BITMAP_FORMAT_RGBA_8888: s *= 4; break;
   1056         case ANDROID_BITMAP_FORMAT_RGB_565: s *= 2; break;
   1057         case ANDROID_BITMAP_FORMAT_RGBA_4444: s *= 2; break;
   1058     }
   1059     return s;
   1060 }
   1061 
   1062 static jlong
   1063 nAllocationCreateFromBitmap(JNIEnv *_env, jobject _this, jlong con, jlong type, jint mip,
   1064                             jobject jbitmap, jint usage)
   1065 {
   1066     jlong id = 0;
   1067     void *pixels = NULL;
   1068     AndroidBitmap_lockPixels(_env, jbitmap, &pixels);
   1069 
   1070     if (pixels != NULL) {
   1071         id = (jlong)(uintptr_t)dispatchTab.AllocationCreateFromBitmap((RsContext)con,
   1072                                                                       (RsType)type,
   1073                                                                       (RsAllocationMipmapControl)mip,
   1074                                                                       pixels,
   1075                                                                       GetBitmapSize(_env, jbitmap),
   1076                                                                       usage);
   1077         AndroidBitmap_unlockPixels(_env, jbitmap);
   1078     }
   1079     return id;
   1080 }
   1081 
   1082 static jlong
   1083 nAllocationCreateBitmapBackedAllocation(JNIEnv *_env, jobject _this, jlong con, jlong type,
   1084                                         jint mip, jobject jbitmap, jint usage)
   1085 {
   1086     jlong id = 0;
   1087     void *pixels = NULL;
   1088     AndroidBitmap_lockPixels(_env, jbitmap, &pixels);
   1089 
   1090     if (pixels != NULL) {
   1091         id = (jlong)(uintptr_t)dispatchTab.AllocationCreateTyped((RsContext)con,
   1092                                                                  (RsType)type,
   1093                                                                  (RsAllocationMipmapControl)mip,
   1094                                                                  (uint32_t)usage,
   1095                                                                  (uintptr_t)pixels);
   1096         AndroidBitmap_unlockPixels(_env, jbitmap);
   1097     }
   1098     return id;
   1099 }
   1100 
   1101 static jlong
   1102 nAllocationCubeCreateFromBitmap(JNIEnv *_env, jobject _this, jlong con, jlong type,
   1103                                 jint mip, jobject jbitmap, jint usage)
   1104 {
   1105     void *pixels = NULL;
   1106     AndroidBitmap_lockPixels(_env, jbitmap, &pixels);
   1107 
   1108     jlong id = 0;
   1109     if (pixels != NULL) {
   1110         id = (jlong)(uintptr_t)dispatchTab.AllocationCubeCreateFromBitmap((RsContext)con,
   1111                                                                           (RsType)type,
   1112                                                                           (RsAllocationMipmapControl)mip,
   1113                                                                           pixels,
   1114                                                                           GetBitmapSize(_env, jbitmap),
   1115                                                                           usage);
   1116         AndroidBitmap_unlockPixels(_env, jbitmap);
   1117     }
   1118     return id;
   1119 }
   1120 
   1121 static void
   1122 nAllocationCopyFromBitmap(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jobject jbitmap)
   1123 {
   1124     AndroidBitmapInfo info;
   1125     memset(&info, 0, sizeof(info));
   1126     AndroidBitmap_getInfo(_env, jbitmap, &info);
   1127 
   1128     void *pixels = NULL;
   1129     AndroidBitmap_lockPixels(_env, jbitmap, &pixels);
   1130 
   1131     if (pixels != NULL) {
   1132         dispatchTab.Allocation2DData((RsContext)con, (RsAllocation)alloc, 0, 0, 0,
   1133                                      RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X, info.width,
   1134                                      info.height, pixels, GetBitmapSize(_env, jbitmap), 0);
   1135         AndroidBitmap_unlockPixels(_env, jbitmap);
   1136     }
   1137 }
   1138 
   1139 static void
   1140 nAllocationCopyToBitmap(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jobject jbitmap)
   1141 {
   1142     AndroidBitmapInfo info;
   1143     memset(&info, 0, sizeof(info));
   1144     AndroidBitmap_getInfo(_env, jbitmap, &info);
   1145 
   1146     void *pixels = NULL;
   1147     AndroidBitmap_lockPixels(_env, jbitmap, &pixels);
   1148 
   1149     if (pixels != NULL) {
   1150         dispatchTab.AllocationCopyToBitmap((RsContext)con, (RsAllocation)alloc, pixels,
   1151                                            GetBitmapSize(_env, jbitmap));
   1152         AndroidBitmap_unlockPixels(_env, jbitmap);
   1153     }
   1154     //bitmap.notifyPixelsChanged();
   1155 }
   1156 
   1157 // Copies from the Java object data into the Allocation pointed to by _alloc.
   1158 static void
   1159 nAllocationData1D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint offset, jint lod,
   1160                   jint count, jobject data, jint sizeBytes, jint dataType, jint mSize,
   1161                   jboolean usePadding)
   1162 {
   1163     RsAllocation *alloc = (RsAllocation *)_alloc;
   1164     LOG_API("nAllocation1DData, con(%p), adapter(%p), offset(%i), count(%i), sizeBytes(%i), "
   1165             "dataType(%i)", (RsContext)con, (RsAllocation)alloc, offset, count, sizeBytes,
   1166             dataType);
   1167     PER_ARRAY_TYPE(nullptr, dispatchTab.Allocation1DData, true,
   1168                    (RsContext)con, alloc, offset, lod, count, ptr, sizeBytes);
   1169 }
   1170 
   1171 
   1172 static void
   1173 nAllocationElementData1D(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jint xoff,
   1174                          jint lod, jint compIdx, jbyteArray data, jint sizeBytes)
   1175 {
   1176     jint len = _env->GetArrayLength(data);
   1177     LOG_API("nAllocationElementData1D, con(%p), alloc(%p), xoff(%i), comp(%i), len(%i), "
   1178             "sizeBytes(%i)", (RsContext)con, (RsAllocation)alloc, xoff, compIdx, len,
   1179             sizeBytes);
   1180     jbyte *ptr = _env->GetByteArrayElements(data, nullptr);
   1181     dispatchTab.Allocation1DElementData((RsContext)con, (RsAllocation)alloc, xoff,
   1182                                         lod, ptr, sizeBytes, compIdx);
   1183     _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
   1184 }
   1185 
   1186 /*
   1187 static void
   1188 nAllocationElementData(JNIEnv *_env, jobject _this, jlong con, jlong alloc,
   1189                        jint xoff, jint yoff, jint zoff,
   1190                        jint lod, jint compIdx, jbyteArray data, jint sizeBytes)
   1191 {
   1192     jint len = _env->GetArrayLength(data);
   1193     LOG_API("nAllocationElementData, con(%p), alloc(%p), xoff(%i), yoff(%i), zoff(%i), comp(%i), len(%i), "
   1194             "sizeBytes(%i)", (RsContext)con, (RsAllocation)alloc, xoff, yoff, zoff, compIdx, len,
   1195             sizeBytes);
   1196     jbyte *ptr = _env->GetByteArrayElements(data, nullptr);
   1197     dispatchTab.AllocationElementData((RsContext)con, (RsAllocation)alloc,
   1198                                       xoff, yoff, zoff,
   1199                                       lod, ptr, sizeBytes, compIdx);
   1200     _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
   1201 }
   1202 */
   1203 
   1204 // Copies from the Java object data into the Allocation pointed to by _alloc.
   1205 static void
   1206 nAllocationData2D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint xoff, jint yoff, jint lod, jint _face,
   1207                   jint w, jint h, jobject data, jint sizeBytes, jint dataType, jint mSize,
   1208                   jboolean usePadding)
   1209 {
   1210     RsAllocation *alloc = (RsAllocation *)_alloc;
   1211     RsAllocationCubemapFace face = (RsAllocationCubemapFace)_face;
   1212     LOG_API("nAllocation2DData, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i) "
   1213             "type(%i)", (RsContext)con, alloc, xoff, yoff, w, h, sizeBytes, dataType);
   1214     int count = w * h;
   1215     PER_ARRAY_TYPE(nullptr, dispatchTab.Allocation2DData, true,
   1216                    (RsContext)con, alloc, xoff, yoff, lod, face, w, h, ptr, sizeBytes, 0);
   1217 }
   1218 
   1219 static void
   1220 nAllocationData2D_alloc(JNIEnv *_env, jobject _this, jlong con,
   1221                         jlong dstAlloc, jint dstXoff, jint dstYoff,
   1222                         jint dstMip, jint dstFace,
   1223                         jint width, jint height,
   1224                         jlong srcAlloc, jint srcXoff, jint srcYoff,
   1225                         jint srcMip, jint srcFace)
   1226 {
   1227     LOG_API("nAllocation2DData_s, con(%p), dstAlloc(%p), dstXoff(%i), dstYoff(%i),"
   1228             " dstMip(%i), dstFace(%i), width(%i), height(%i),"
   1229             " srcAlloc(%p), srcXoff(%i), srcYoff(%i), srcMip(%i), srcFace(%i)",
   1230             (RsContext)con, (RsAllocation)dstAlloc, dstXoff, dstYoff, dstMip, dstFace,
   1231             width, height, (RsAllocation)srcAlloc, srcXoff, srcYoff, srcMip, srcFace);
   1232 
   1233     dispatchTab.AllocationCopy2DRange((RsContext)con,
   1234                                       (RsAllocation)dstAlloc,
   1235                                       dstXoff, dstYoff,
   1236                                       dstMip, dstFace,
   1237                                       width, height,
   1238                                       (RsAllocation)srcAlloc,
   1239                                       srcXoff, srcYoff,
   1240                                       srcMip, srcFace);
   1241 }
   1242 
   1243 // Copies from the Java object data into the Allocation pointed to by _alloc.
   1244 static void
   1245 nAllocationData3D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint xoff, jint yoff, jint zoff, jint lod,
   1246                   jint w, jint h, jint d, jobject data, jint sizeBytes, jint dataType,
   1247                   jint mSize, jboolean usePadding)
   1248 {
   1249     RsAllocation *alloc = (RsAllocation *)_alloc;
   1250     LOG_API("nAllocation3DData, con(%p), alloc(%p), xoff(%i), yoff(%i), zoff(%i), lod(%i), w(%i),"
   1251             " h(%i), d(%i), sizeBytes(%i)", (RsContext)con, (RsAllocation)alloc, xoff, yoff, zoff,
   1252             lod, w, h, d, sizeBytes);
   1253     int count = w * h * d;
   1254     PER_ARRAY_TYPE(nullptr, dispatchTab.Allocation3DData, true,
   1255                    (RsContext)con, alloc, xoff, yoff, zoff, lod, w, h, d, ptr, sizeBytes, 0);
   1256 }
   1257 
   1258 static void
   1259 nAllocationData3D_alloc(JNIEnv *_env, jobject _this, jlong con,
   1260                         jlong dstAlloc, jint dstXoff, jint dstYoff, jint dstZoff,
   1261                         jint dstMip,
   1262                         jint width, jint height, jint depth,
   1263                         jlong srcAlloc, jint srcXoff, jint srcYoff, jint srcZoff,
   1264                         jint srcMip)
   1265 {
   1266     LOG_API("nAllocationData3D_alloc, con(%p), dstAlloc(%p), dstXoff(%i), dstYoff(%i),"
   1267             " dstMip(%i), width(%i), height(%i),"
   1268             " srcAlloc(%p), srcXoff(%i), srcYoff(%i), srcMip(%i)",
   1269             (RsContext)con, (RsAllocation)dstAlloc, dstXoff, dstYoff, dstMip, dstFace,
   1270             width, height, (RsAllocation)srcAlloc, srcXoff, srcYoff, srcMip, srcFace);
   1271 
   1272     dispatchTab.AllocationCopy3DRange((RsContext)con,
   1273                                       (RsAllocation)dstAlloc,
   1274                                       dstXoff, dstYoff, dstZoff, dstMip,
   1275                                       width, height, depth,
   1276                                       (RsAllocation)srcAlloc,
   1277                                       srcXoff, srcYoff, srcZoff, srcMip);
   1278 }
   1279 
   1280 // Copies from the Allocation pointed to by _alloc into the Java object data.
   1281 static void
   1282 nAllocationRead(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jobject data, jint dataType,
   1283                 jint mSize, jboolean usePadding)
   1284 {
   1285     RsAllocation *alloc = (RsAllocation *)_alloc;
   1286     LOG_API("nAllocationRead, con(%p), alloc(%p)", (RsContext)con, (RsAllocation)alloc);
   1287     int count = 0;
   1288     PER_ARRAY_TYPE(0, dispatchTab.AllocationRead, false,
   1289                    (RsContext)con, alloc, ptr, len * typeBytes);
   1290 }
   1291 
   1292 // Copies from the Allocation pointed to by _alloc into the Java object data.
   1293 static void
   1294 nAllocationRead1D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint offset, jint lod,
   1295                   jint count, jobject data, jint sizeBytes, jint dataType,
   1296                   jint mSize, jboolean usePadding)
   1297 {
   1298     RsAllocation *alloc = (RsAllocation *)_alloc;
   1299     LOG_API("nAllocation1DRead, con(%p), adapter(%p), offset(%i), count(%i), sizeBytes(%i), "
   1300               "dataType(%i)", (RsContext)con, alloc, offset, count, sizeBytes, dataType);
   1301     PER_ARRAY_TYPE(0, dispatchTab.Allocation1DRead, false,
   1302                    (RsContext)con, alloc, offset, lod, count, ptr, sizeBytes);
   1303 }
   1304 
   1305 // Copies from the Element in the Allocation pointed to by _alloc into the Java array data.
   1306 /*
   1307 static void
   1308 nAllocationElementRead(JNIEnv *_env, jobject _this, jlong con, jlong _alloc,
   1309                        jint xoff, jint yoff, jint zoff,
   1310                        jint lod, jint compIdx, jobject data, jint sizeBytes)
   1311 {
   1312     jint len = _env->GetArrayLength(data);
   1313     LOG_API("nAllocationElementRead, con(%p), alloc(%p), xoff(%i), yoff(%i), zoff(%i), comp(%i), len(%i), "
   1314             "sizeBytes(%i)", (RsContext)con, (RsAllocation)alloc, xoff, yoff, zoff, compIdx, len,
   1315             sizeBytes);
   1316     jbyte *ptr = _env->GetByteArrayElements(data, nullptr);
   1317     dispatchTab.AllocationElementRead((RsContext)con, (RsAllocation)alloc,
   1318                                       xoff, yoff, zoff,
   1319                                       lod, ptr, sizeBytes, compIdx);
   1320     _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
   1321 }
   1322 */
   1323 
   1324 // Copies from the Allocation pointed to by _alloc into the Java object data.
   1325 static void
   1326 nAllocationRead2D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint xoff, jint yoff, jint lod, jint _face,
   1327                   jint w, jint h, jobject data, jint sizeBytes, jint dataType,
   1328                   jint mSize, jboolean usePadding)
   1329 {
   1330     RsAllocation *alloc = (RsAllocation *)_alloc;
   1331     RsAllocationCubemapFace face = (RsAllocationCubemapFace)_face;
   1332     LOG_API("nAllocation2DRead, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i) "
   1333               "type(%i)", (RsContext)con, alloc, xoff, yoff, w, h, sizeBytes, dataType);
   1334     int count = w * h;
   1335     PER_ARRAY_TYPE(0, dispatchTab.Allocation2DRead, false,
   1336                    (RsContext)con, alloc, xoff, yoff, lod, face, w, h, ptr, sizeBytes, 0);
   1337 }
   1338 
   1339 // Copies from the Allocation pointed to by _alloc into the Java object data.
   1340 /*
   1341 static void
   1342 nAllocationRead3D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint xoff, jint yoff, jint zoff, jint lod,
   1343                   jint w, jint h, jint d, jobject data, int sizeBytes, int dataType,
   1344                   jint mSize, jboolean usePadding)
   1345 {
   1346     RsAllocation *alloc = (RsAllocation *)_alloc;
   1347     LOG_API("nAllocation3DRead, con(%p), alloc(%p), xoff(%i), yoff(%i), zoff(%i), lod(%i), w(%i),"
   1348             " h(%i), d(%i), sizeBytes(%i)", (RsContext)con, (RsAllocation)alloc, xoff, yoff, zoff,
   1349             lod, w, h, d, sizeBytes);
   1350     int count = w * h * d;
   1351     PER_ARRAY_TYPE(nullptr, dispatchTab.Allocation3DRead, false,
   1352                    (RsContext)con, alloc, xoff, yoff, zoff, lod, w, h, d, ptr, sizeBytes, 0);
   1353 }
   1354 */
   1355 
   1356 static jlong
   1357 nAllocationGetType(JNIEnv *_env, jobject _this, jlong con, jlong a)
   1358 {
   1359     LOG_API("nAllocationGetType, con(%p), a(%p)", (RsContext)con, (RsAllocation)a);
   1360     return (jlong)(uintptr_t) dispatchTab.AllocationGetType((RsContext)con, (RsAllocation)a);
   1361 }
   1362 
   1363 static void
   1364 nAllocationResize1D(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jint dimX)
   1365 {
   1366     LOG_API("nAllocationResize1D, con(%p), alloc(%p), sizeX(%i)", (RsContext)con,
   1367             (RsAllocation)alloc, dimX);
   1368     dispatchTab.AllocationResize1D((RsContext)con, (RsAllocation)alloc, dimX);
   1369 }
   1370 
   1371 // -----------------------------------
   1372 
   1373 static void
   1374 nScriptBindAllocation(JNIEnv *_env, jobject _this, jlong con, jlong script, jlong alloc, jint slot, jboolean mUseInc)
   1375 {
   1376     LOG_API("nScriptBindAllocation, con(%p), script(%p), alloc(%p), slot(%i)",
   1377             (RsContext)con, (RsScript)script, (RsAllocation)alloc, slot);
   1378     if (mUseInc) {
   1379         dispatchTabInc.ScriptBindAllocation((RsContext)con, (RsScript)script, (RsAllocation)alloc, slot);
   1380     } else {
   1381         dispatchTab.ScriptBindAllocation((RsContext)con, (RsScript)script, (RsAllocation)alloc, slot);
   1382     }
   1383 }
   1384 
   1385 static void
   1386 nScriptSetVarI(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jint val, jboolean mUseInc)
   1387 {
   1388     LOG_API("nScriptSetVarI, con(%p), s(%p), slot(%i), val(%i)", (RsContext)con,
   1389             (void *)script, slot, val);
   1390     if (mUseInc) {
   1391         dispatchTabInc.ScriptSetVarI((RsContext)con, (RsScript)script, slot, val);
   1392     } else {
   1393         dispatchTab.ScriptSetVarI((RsContext)con, (RsScript)script, slot, val);
   1394     }
   1395 }
   1396 
   1397 static void
   1398 nScriptSetVarObj(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jlong val, jboolean mUseInc)
   1399 {
   1400     LOG_API("nScriptSetVarObj, con(%p), s(%p), slot(%i), val(%i)", (RsContext)con,
   1401             (void *)script, slot, val);
   1402     if (mUseInc) {
   1403         dispatchTabInc.ScriptSetVarObj((RsContext)con, (RsScript)script, slot, (RsObjectBase)val);
   1404     } else {
   1405         dispatchTab.ScriptSetVarObj((RsContext)con, (RsScript)script, slot, (RsObjectBase)val);
   1406     }
   1407 }
   1408 
   1409 static void
   1410 nScriptSetVarJ(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jlong val, jboolean mUseInc)
   1411 {
   1412     LOG_API("nScriptSetVarJ, con(%p), s(%p), slot(%i), val(%lli)", (RsContext)con,
   1413             (void *)script, slot, val);
   1414     if (mUseInc) {
   1415         dispatchTabInc.ScriptSetVarJ((RsContext)con, (RsScript)script, slot, val);
   1416     } else {
   1417         dispatchTab.ScriptSetVarJ((RsContext)con, (RsScript)script, slot, val);
   1418     }
   1419 }
   1420 
   1421 static void
   1422 nScriptSetVarF(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, float val, jboolean mUseInc)
   1423 {
   1424     LOG_API("nScriptSetVarF, con(%p), s(%p), slot(%i), val(%f)", (RsContext)con,
   1425             (void *)script, slot, val);
   1426     if (mUseInc) {
   1427         dispatchTabInc.ScriptSetVarF((RsContext)con, (RsScript)script, slot, val);
   1428     } else {
   1429         dispatchTab.ScriptSetVarF((RsContext)con, (RsScript)script, slot, val);
   1430     }
   1431 }
   1432 
   1433 static void
   1434 nScriptSetVarD(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, double val, jboolean mUseInc)
   1435 {
   1436     LOG_API("nScriptSetVarD, con(%p), s(%p), slot(%i), val(%lf)", (RsContext)con,
   1437             (void *)script, slot, val);
   1438     if (mUseInc) {
   1439         dispatchTabInc.ScriptSetVarD((RsContext)con, (RsScript)script, slot, val);
   1440     } else {
   1441         dispatchTab.ScriptSetVarD((RsContext)con, (RsScript)script, slot, val);
   1442     }
   1443 }
   1444 
   1445 static void
   1446 nScriptSetVarV(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jbyteArray data, jboolean mUseInc)
   1447 {
   1448     LOG_API("nScriptSetVarV, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
   1449     jint len = _env->GetArrayLength(data);
   1450     jbyte *ptr = _env->GetByteArrayElements(data, NULL);
   1451     if (mUseInc) {
   1452         dispatchTabInc.ScriptSetVarV((RsContext)con, (RsScript)script, slot, ptr, len);
   1453     } else {
   1454         dispatchTab.ScriptSetVarV((RsContext)con, (RsScript)script, slot, ptr, len);
   1455     }
   1456     _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
   1457 }
   1458 
   1459 static void
   1460 nScriptSetVarVE(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jbyteArray data,
   1461                 jlong elem, jintArray dims, jboolean mUseInc)
   1462 {
   1463     LOG_API("nScriptSetVarVE, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
   1464     jint len = _env->GetArrayLength(data);
   1465     jbyte *ptr = _env->GetByteArrayElements(data, NULL);
   1466     jint dimsLen = _env->GetArrayLength(dims) * sizeof(int);
   1467     jint *dimsPtr = _env->GetIntArrayElements(dims, NULL);
   1468     if (mUseInc) {
   1469         dispatchTabInc.ScriptSetVarVE((RsContext)con, (RsScript)script, slot, ptr, len, (RsElement)elem,
   1470                                       (const uint32_t *)dimsPtr, dimsLen);
   1471     } else {
   1472         dispatchTab.ScriptSetVarVE((RsContext)con, (RsScript)script, slot, ptr, len, (RsElement)elem,
   1473                                    (const uint32_t *)dimsPtr, dimsLen);
   1474     }
   1475     _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
   1476     _env->ReleaseIntArrayElements(dims, dimsPtr, JNI_ABORT);
   1477 }
   1478 
   1479 
   1480 static void
   1481 nScriptSetTimeZone(JNIEnv *_env, jobject _this, jlong con, jlong script, jbyteArray timeZone, jboolean mUseInc)
   1482 {
   1483     LOG_API("nScriptCSetTimeZone, con(%p), s(%p), timeZone(%s)", (RsContext)con,
   1484             (void *)script, (const char *)timeZone);
   1485 
   1486     jint length = _env->GetArrayLength(timeZone);
   1487     jbyte* timeZone_ptr;
   1488     timeZone_ptr = (jbyte *) _env->GetPrimitiveArrayCritical(timeZone, (jboolean *)0);
   1489     if (mUseInc) {
   1490         dispatchTabInc.ScriptSetTimeZone((RsContext)con, (RsScript)script, (const char *)timeZone_ptr, length);
   1491     } else {
   1492         dispatchTab.ScriptSetTimeZone((RsContext)con, (RsScript)script, (const char *)timeZone_ptr, length);
   1493     }
   1494 
   1495     if (timeZone_ptr) {
   1496         _env->ReleasePrimitiveArrayCritical(timeZone, timeZone_ptr, 0);
   1497     }
   1498 }
   1499 
   1500 static void
   1501 nScriptInvoke(JNIEnv *_env, jobject _this, jlong con, jlong obj, jint slot, jboolean mUseInc)
   1502 {
   1503     LOG_API("nScriptInvoke, con(%p), script(%p)", (RsContext)con, (void *)obj);
   1504     if (mUseInc) {
   1505         dispatchTabInc.ScriptInvoke((RsContext)con, (RsScript)obj, slot);
   1506     } else {
   1507         dispatchTab.ScriptInvoke((RsContext)con, (RsScript)obj, slot);
   1508     }
   1509 }
   1510 
   1511 static void
   1512 nScriptInvokeV(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jbyteArray data, jboolean mUseInc)
   1513 {
   1514     LOG_API("nScriptInvokeV, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
   1515     jint len = _env->GetArrayLength(data);
   1516     jbyte *ptr = _env->GetByteArrayElements(data, NULL);
   1517     if (mUseInc) {
   1518         dispatchTabInc.ScriptInvokeV((RsContext)con, (RsScript)script, slot, ptr, len);
   1519     } else {
   1520         dispatchTab.ScriptInvokeV((RsContext)con, (RsScript)script, slot, ptr, len);
   1521     }
   1522     _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
   1523 }
   1524 
   1525 static void
   1526 nScriptForEach(JNIEnv *_env, jobject _this, jlong con, jlong incCon,
   1527                jlong script, jint slot, jlong ain, jlong aout, jboolean mUseInc)
   1528 {
   1529     LOG_API("nScriptForEach, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
   1530     if (mUseInc) {
   1531         dispatchTab.ContextFinish((RsContext)con);
   1532         dispatchTabInc.ScriptForEach((RsContext)incCon, (RsScript)script, slot,
   1533                                      (RsAllocation)ain, (RsAllocation)aout,
   1534                                      NULL, 0, NULL, 0);
   1535     } else {
   1536         dispatchTab.ScriptForEach((RsContext)con, (RsScript)script, slot,
   1537                                   (RsAllocation)ain, (RsAllocation)aout,
   1538                                   NULL, 0, NULL, 0);
   1539     }
   1540 }
   1541 
   1542 static void
   1543 nScriptForEachV(JNIEnv *_env, jobject _this, jlong con, jlong incCon,
   1544                 jlong script, jint slot, jlong ain, jlong aout, jbyteArray params, jboolean mUseInc)
   1545 {
   1546     LOG_API("nScriptForEach, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
   1547     jint len = _env->GetArrayLength(params);
   1548     jbyte *ptr = _env->GetByteArrayElements(params, NULL);
   1549     if (mUseInc) {
   1550         dispatchTab.ContextFinish((RsContext)con);
   1551         dispatchTabInc.ScriptForEach((RsContext)incCon, (RsScript)script, slot,
   1552                                      (RsAllocation)ain, (RsAllocation)aout,
   1553                                      ptr, len, NULL, 0);
   1554     } else {
   1555         dispatchTab.ScriptForEach((RsContext)con, (RsScript)script, slot,
   1556                                   (RsAllocation)ain, (RsAllocation)aout,
   1557                                   ptr, len, NULL, 0);
   1558     }
   1559     _env->ReleaseByteArrayElements(params, ptr, JNI_ABORT);
   1560 }
   1561 
   1562 static void
   1563 nScriptForEachClipped(JNIEnv *_env, jobject _this, jlong con, jlong incCon,
   1564                       jlong script, jint slot, jlong ain, jlong aout,
   1565                       jint xstart, jint xend,
   1566                       jint ystart, jint yend, jint zstart, jint zend, jboolean mUseInc)
   1567 {
   1568     LOG_API("nScriptForEachClipped, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
   1569     RsScriptCall sc;
   1570     sc.xStart = xstart;
   1571     sc.xEnd = xend;
   1572     sc.yStart = ystart;
   1573     sc.yEnd = yend;
   1574     sc.zStart = zstart;
   1575     sc.zEnd = zend;
   1576     sc.strategy = RS_FOR_EACH_STRATEGY_DONT_CARE;
   1577     sc.arrayStart = 0;
   1578     sc.arrayEnd = 0;
   1579     sc.array2Start = 0;
   1580     sc.array2End = 0;
   1581     sc.array3Start = 0;
   1582     sc.array3End = 0;
   1583     sc.array4Start = 0;
   1584     sc.array4End = 0;
   1585     if (mUseInc) {
   1586         dispatchTab.ContextFinish((RsContext)con);
   1587         dispatchTabInc.ScriptForEach((RsContext)incCon, (RsScript)script, slot,
   1588                                      (RsAllocation)ain, (RsAllocation)aout,
   1589                                      NULL, 0, &sc, sizeof(sc));
   1590     } else {
   1591         dispatchTab.ScriptForEach((RsContext)con, (RsScript)script, slot,
   1592                                   (RsAllocation)ain, (RsAllocation)aout,
   1593                                   NULL, 0, &sc, sizeof(sc));
   1594     }
   1595 }
   1596 
   1597 static void
   1598 nScriptForEachClippedV(JNIEnv *_env, jobject _this, jlong con, jlong incCon,
   1599                        jlong script, jint slot, jlong ain, jlong aout,
   1600                        jbyteArray params, jint xstart, jint xend,
   1601                        jint ystart, jint yend, jint zstart, jint zend, jboolean mUseInc)
   1602 {
   1603     LOG_API("nScriptForEachClipped, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
   1604     jint len = _env->GetArrayLength(params);
   1605     jbyte *ptr = _env->GetByteArrayElements(params, NULL);
   1606     RsScriptCall sc;
   1607     sc.xStart = xstart;
   1608     sc.xEnd = xend;
   1609     sc.yStart = ystart;
   1610     sc.yEnd = yend;
   1611     sc.zStart = zstart;
   1612     sc.zEnd = zend;
   1613     sc.strategy = RS_FOR_EACH_STRATEGY_DONT_CARE;
   1614     sc.arrayStart = 0;
   1615     sc.arrayEnd = 0;
   1616     sc.array2Start = 0;
   1617     sc.array2End = 0;
   1618     sc.array3Start = 0;
   1619     sc.array3End = 0;
   1620     sc.array4Start = 0;
   1621     sc.array4End = 0;
   1622     if (mUseInc) {
   1623         dispatchTab.ContextFinish((RsContext)con);
   1624         dispatchTabInc.ScriptForEach((RsContext)incCon, (RsScript)script, slot,
   1625                                      (RsAllocation)ain, (RsAllocation)aout,
   1626                                      ptr, len, &sc, sizeof(sc));
   1627     } else {
   1628         dispatchTab.ScriptForEach((RsContext)con, (RsScript)script, slot,
   1629                                   (RsAllocation)ain, (RsAllocation)aout,
   1630                                   ptr, len, &sc, sizeof(sc));
   1631     }
   1632     _env->ReleaseByteArrayElements(params, ptr, JNI_ABORT);
   1633 }
   1634 
   1635 static void
   1636 nScriptForEachMulti(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot,
   1637                     jlongArray ains, jlong aout, jbyteArray params,
   1638                     jintArray limits)
   1639 {
   1640     LOG_API("nScriptForEach, con(%p), s(%p), slot(%i) ains(%p) aout(%" PRId64 ")", (RsContext)con, (void *)script, slot, ains, aout);
   1641 
   1642     jint   in_len = 0;
   1643     jlong *in_ptr = nullptr;
   1644 
   1645     RsAllocation *in_allocs = nullptr;
   1646 
   1647     if (ains != nullptr) {
   1648         in_len = _env->GetArrayLength(ains);
   1649         if (in_len > (jint)RS_KERNEL_MAX_ARGUMENTS) {
   1650             LOG_ERR("Too many arguments in kernel launch.");
   1651             // TODO (b/20758983): Report back to Java and throw an exception
   1652             return;
   1653         }
   1654 
   1655         // TODO (b/20760800): Check in_ptr is not null
   1656         in_ptr = _env->GetLongArrayElements(ains, nullptr);
   1657         if (sizeof(RsAllocation) == sizeof(jlong)) {
   1658             in_allocs = (RsAllocation*)in_ptr;
   1659 
   1660         } else {
   1661             // Convert from 64-bit jlong types to the native pointer type.
   1662 
   1663             in_allocs = (RsAllocation*)alloca(in_len * sizeof(RsAllocation));
   1664             if (in_allocs == nullptr) {
   1665                 LOG_ERR("Failed launching kernel for lack of memory.");
   1666                 _env->ReleaseLongArrayElements(ains, in_ptr, JNI_ABORT);
   1667                 return;
   1668             }
   1669 
   1670             for (int index = in_len; --index >= 0;) {
   1671                 in_allocs[index] = (RsAllocation)in_ptr[index];
   1672             }
   1673         }
   1674     }
   1675 
   1676     jint   param_len = 0;
   1677     jbyte *param_ptr = nullptr;
   1678 
   1679     if (params != nullptr) {
   1680         param_len = _env->GetArrayLength(params);
   1681         param_ptr = _env->GetByteArrayElements(params, nullptr);
   1682     }
   1683 
   1684     RsScriptCall sc, *sca = nullptr;
   1685     uint32_t sc_size = 0;
   1686 
   1687     jint  limit_len = 0;
   1688     jint *limit_ptr = nullptr;
   1689 
   1690     if (limits != nullptr) {
   1691         limit_len = _env->GetArrayLength(limits);
   1692         limit_ptr = _env->GetIntArrayElements(limits, nullptr);
   1693 
   1694         if (limit_len != 6) {
   1695             LOG_ERR("LaunchOptions cannot be recognized.");
   1696             goto exit;
   1697         }
   1698 
   1699         sc.xStart     = limit_ptr[0];
   1700         sc.xEnd       = limit_ptr[1];
   1701         sc.yStart     = limit_ptr[2];
   1702         sc.yEnd       = limit_ptr[3];
   1703         sc.zStart     = limit_ptr[4];
   1704         sc.zEnd       = limit_ptr[5];
   1705         sc.strategy   = RS_FOR_EACH_STRATEGY_DONT_CARE;
   1706         sc.arrayStart = 0;
   1707         sc.arrayEnd = 0;
   1708         sc.array2Start = 0;
   1709         sc.array2End = 0;
   1710         sc.array3Start = 0;
   1711         sc.array3End = 0;
   1712         sc.array4Start = 0;
   1713         sc.array4End = 0;
   1714 
   1715         sca = &sc;
   1716     }
   1717 
   1718     dispatchTabInc.ScriptForEachMulti((RsContext)con, (RsScript)script, slot,
   1719                                       in_allocs, in_len, (RsAllocation)aout,
   1720                                       param_ptr, param_len, sca, sc_size);
   1721 
   1722 exit:
   1723 
   1724     if (ains != nullptr) {
   1725         _env->ReleaseLongArrayElements(ains, in_ptr, JNI_ABORT);
   1726     }
   1727 
   1728     if (params != nullptr) {
   1729         _env->ReleaseByteArrayElements(params, param_ptr, JNI_ABORT);
   1730     }
   1731 
   1732     if (limits != nullptr) {
   1733         _env->ReleaseIntArrayElements(limits, limit_ptr, JNI_ABORT);
   1734     }
   1735 }
   1736 
   1737 static void
   1738 nScriptReduce(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot,
   1739               jlongArray ains, jlong aout, jintArray limits)
   1740 {
   1741     LOG_API("nScriptReduce, con(%p), s(%p), slot(%i) ains(%p) aout(%" PRId64 ")", (RsContext)con, (void *)script, slot, ains, aout);
   1742 
   1743     if (ains == nullptr) {
   1744         LOG_ERR("At least one input required.");
   1745         // TODO (b/20758983): Report back to Java and throw an exception
   1746         return;
   1747     }
   1748     jint in_len = _env->GetArrayLength(ains);
   1749     if (in_len > (jint)RS_KERNEL_MAX_ARGUMENTS) {
   1750         LOG_ERR("Too many arguments in kernel launch.");
   1751         // TODO (b/20758983): Report back to Java and throw an exception
   1752         return;
   1753     }
   1754 
   1755     jlong *in_ptr = _env->GetLongArrayElements(ains, nullptr);
   1756     if (in_ptr == nullptr) {
   1757         LOG_ERR("Failed to get Java array elements");
   1758         // TODO (b/20758983): Report back to Java and throw an exception
   1759         return;
   1760     }
   1761 
   1762     RsAllocation *in_allocs = nullptr;
   1763     if (sizeof(RsAllocation) == sizeof(jlong)) {
   1764         in_allocs = (RsAllocation*)in_ptr;
   1765     } else {
   1766         // Convert from 64-bit jlong types to the native pointer type.
   1767 
   1768         in_allocs = (RsAllocation*)alloca(in_len * sizeof(RsAllocation));
   1769         if (in_allocs == nullptr) {
   1770             LOG_ERR("Failed launching kernel for lack of memory.");
   1771             // TODO (b/20758983): Report back to Java and throw an exception
   1772             _env->ReleaseLongArrayElements(ains, in_ptr, JNI_ABORT);
   1773             return;
   1774         }
   1775 
   1776         for (int index = in_len; --index >= 0;) {
   1777             in_allocs[index] = (RsAllocation)in_ptr[index];
   1778         }
   1779     }
   1780 
   1781     RsScriptCall sc, *sca = nullptr;
   1782     uint32_t sc_size = 0;
   1783 
   1784     jint  limit_len = 0;
   1785     jint *limit_ptr = nullptr;
   1786 
   1787     if (limits != nullptr) {
   1788         limit_len = _env->GetArrayLength(limits);
   1789         limit_ptr = _env->GetIntArrayElements(limits, nullptr);
   1790         if (limit_ptr == nullptr) {
   1791             LOG_ERR("Failed to get Java array elements");
   1792             // TODO (b/20758983): Report back to Java and throw an exception
   1793             _env->ReleaseLongArrayElements(ains, in_ptr, JNI_ABORT);
   1794             return;
   1795         }
   1796 
   1797         if (limit_len != 6) {
   1798             LOG_ERR("LaunchOptions cannot be recognized");
   1799             // TODO (b/20758983): Report back to Java and throw an exception
   1800             _env->ReleaseLongArrayElements(ains, in_ptr, JNI_ABORT);
   1801             return;
   1802         }
   1803 
   1804         sc.xStart     = limit_ptr[0];
   1805         sc.xEnd       = limit_ptr[1];
   1806         sc.yStart     = limit_ptr[2];
   1807         sc.yEnd       = limit_ptr[3];
   1808         sc.zStart     = limit_ptr[4];
   1809         sc.zEnd       = limit_ptr[5];
   1810         sc.strategy   = RS_FOR_EACH_STRATEGY_DONT_CARE;
   1811         sc.arrayStart = 0;
   1812         sc.arrayEnd = 0;
   1813         sc.array2Start = 0;
   1814         sc.array2End = 0;
   1815         sc.array3Start = 0;
   1816         sc.array3End = 0;
   1817         sc.array4Start = 0;
   1818         sc.array4End = 0;
   1819 
   1820         sca = &sc;
   1821         sc_size = sizeof(sc);
   1822     }
   1823 
   1824     dispatchTab.ScriptReduce((RsContext)con, (RsScript)script, slot,
   1825                              in_allocs, in_len, (RsAllocation)aout,
   1826                              sca, sc_size);
   1827 
   1828     _env->ReleaseLongArrayElements(ains, in_ptr, JNI_ABORT);
   1829 
   1830     if (limits != nullptr) {
   1831         _env->ReleaseIntArrayElements(limits, limit_ptr, JNI_ABORT);
   1832     }
   1833 }
   1834 
   1835 // -----------------------------------
   1836 
   1837 static jlong
   1838 nScriptCCreate(JNIEnv *_env, jobject _this, jlong con,
   1839                jstring resName, jstring cacheDir,
   1840                jbyteArray scriptRef, jint length)
   1841 {
   1842     LOG_API("nScriptCCreate, con(%p)", (RsContext)con);
   1843 
   1844     AutoJavaStringToUTF8 resNameUTF(_env, resName);
   1845     AutoJavaStringToUTF8 cacheDirUTF(_env, cacheDir);
   1846     jlong ret = 0;
   1847     jbyte* script_ptr = NULL;
   1848     jint _exception = 0;
   1849     jint remaining;
   1850     if (!scriptRef) {
   1851         _exception = 1;
   1852         //jniThrowException(_env, "java/lang/IllegalArgumentException", "script == null");
   1853         goto exit;
   1854     }
   1855     if (length < 0) {
   1856         _exception = 1;
   1857         //jniThrowException(_env, "java/lang/IllegalArgumentException", "length < 0");
   1858         goto exit;
   1859     }
   1860     remaining = _env->GetArrayLength(scriptRef);
   1861     if (remaining < length) {
   1862         _exception = 1;
   1863         //jniThrowException(_env, "java/lang/IllegalArgumentException",
   1864         //        "length > script.length - offset");
   1865         goto exit;
   1866     }
   1867     script_ptr = (jbyte *)
   1868         _env->GetPrimitiveArrayCritical(scriptRef, (jboolean *)0);
   1869 
   1870     //rsScriptCSetText(con, (const char *)script_ptr, length);
   1871 
   1872     ret = (jlong)(uintptr_t)dispatchTab.ScriptCCreate((RsContext)con,
   1873                                                       resNameUTF.c_str(), resNameUTF.length(),
   1874                                                       cacheDirUTF.c_str(), cacheDirUTF.length(),
   1875                                                       (const char *)script_ptr, length);
   1876 
   1877 exit:
   1878     if (script_ptr) {
   1879         _env->ReleasePrimitiveArrayCritical(scriptRef, script_ptr,
   1880                 _exception ? JNI_ABORT: 0);
   1881     }
   1882 
   1883     return (jlong)(uintptr_t)ret;
   1884 }
   1885 
   1886 static jlong
   1887 nScriptIntrinsicCreate(JNIEnv *_env, jobject _this, jlong con, jint id, jlong eid, jboolean mUseInc)
   1888 {
   1889     LOG_API("nScriptIntrinsicCreate, con(%p) id(%i) element(%p)", (RsContext)con, id, (void *)eid);
   1890     if (mUseInc) {
   1891         return (jlong)(uintptr_t)dispatchTabInc.ScriptIntrinsicCreate((RsContext)con, id, (RsElement)eid);
   1892     } else {
   1893         return (jlong)(uintptr_t)dispatchTab.ScriptIntrinsicCreate((RsContext)con, id, (RsElement)eid);
   1894     }
   1895 }
   1896 
   1897 static jlong
   1898 nScriptKernelIDCreate(JNIEnv *_env, jobject _this, jlong con, jlong sid, jint slot, jint sig, jboolean mUseInc)
   1899 {
   1900     LOG_API("nScriptKernelIDCreate, con(%p) script(%p), slot(%i), sig(%i)", (RsContext)con,
   1901             (void *)sid, slot, sig);
   1902     if (mUseInc) {
   1903         return (jlong)(uintptr_t)dispatchTabInc.ScriptKernelIDCreate((RsContext)con, (RsScript)sid,
   1904                                                                      slot, sig);
   1905     } else {
   1906         return (jlong)(uintptr_t)dispatchTab.ScriptKernelIDCreate((RsContext)con, (RsScript)sid,
   1907                                                                   slot, sig);
   1908     }
   1909 }
   1910 
   1911 static jlong
   1912 nScriptInvokeIDCreate(JNIEnv *_env, jobject _this, jlong con, jlong sid, jint slot)
   1913 {
   1914     LOG_API("nScriptInvokeIDCreate, con(%p) script(%p), slot(%i), sig(%i)", con,
   1915             (void *)sid, slot);
   1916     return (jlong)dispatchTab.ScriptInvokeIDCreate((RsContext)con, (RsScript)sid, slot);
   1917 }
   1918 
   1919 static jlong
   1920 nScriptFieldIDCreate(JNIEnv *_env, jobject _this, jlong con, jlong sid, jint slot, jboolean mUseInc)
   1921 {
   1922     LOG_API("nScriptFieldIDCreate, con(%p) script(%p), slot(%i)", (RsContext)con, (void *)sid, slot);
   1923     if (mUseInc) {
   1924         return (jlong)(uintptr_t)dispatchTabInc.ScriptFieldIDCreate((RsContext)con, (RsScript)sid, slot);
   1925     } else {
   1926         return (jlong)(uintptr_t)dispatchTab.ScriptFieldIDCreate((RsContext)con, (RsScript)sid, slot);
   1927     }
   1928 }
   1929 
   1930 static jlong
   1931 nScriptGroupCreate(JNIEnv *_env, jobject _this, jlong con, jlongArray _kernels, jlongArray _src,
   1932     jlongArray _dstk, jlongArray _dstf, jlongArray _types)
   1933 {
   1934     LOG_API("nScriptGroupCreate, con(%p)", (RsContext)con);
   1935 
   1936     jlong id = 0;
   1937 
   1938     RsScriptKernelID* kernelsPtr;
   1939     jint kernelsLen = _env->GetArrayLength(_kernels);
   1940     jlong *jKernelsPtr = _env->GetLongArrayElements(_kernels, nullptr);
   1941 
   1942     RsScriptKernelID* srcPtr;
   1943     jint srcLen = _env->GetArrayLength(_src);
   1944     jlong *jSrcPtr = _env->GetLongArrayElements(_src, nullptr);
   1945 
   1946     RsScriptKernelID* dstkPtr;
   1947     jint dstkLen = _env->GetArrayLength(_dstk);
   1948     jlong *jDstkPtr = _env->GetLongArrayElements(_dstk, nullptr);
   1949 
   1950     RsScriptKernelID* dstfPtr;
   1951     jint dstfLen = _env->GetArrayLength(_dstf);
   1952     jlong *jDstfPtr = _env->GetLongArrayElements(_dstf, nullptr);
   1953 
   1954     RsType* typesPtr;
   1955     jint typesLen = _env->GetArrayLength(_types);
   1956     jlong *jTypesPtr = _env->GetLongArrayElements(_types, nullptr);
   1957 
   1958     if (jKernelsPtr == nullptr) {
   1959         LOG_ERR("Failed to get Java array elements: kernels");
   1960         goto cleanup;
   1961     }
   1962     if (jSrcPtr == nullptr) {
   1963         LOG_ERR("Failed to get Java array elements: src");
   1964         goto cleanup;
   1965     }
   1966     if (jDstkPtr == nullptr) {
   1967         LOG_ERR("Failed to get Java array elements: dstk");
   1968         goto cleanup;
   1969     }
   1970     if (jDstfPtr == nullptr) {
   1971         LOG_ERR("Failed to get Java array elements: dstf");
   1972         goto cleanup;
   1973     }
   1974     if (jTypesPtr == nullptr) {
   1975         LOG_ERR("Failed to get Java array elements: types");
   1976         goto cleanup;
   1977     }
   1978 
   1979     kernelsPtr = (RsScriptKernelID*) malloc(sizeof(RsScriptKernelID) * kernelsLen);
   1980     for(int i = 0; i < kernelsLen; ++i) {
   1981         kernelsPtr[i] = (RsScriptKernelID)jKernelsPtr[i];
   1982     }
   1983 
   1984     srcPtr = (RsScriptKernelID*) malloc(sizeof(RsScriptKernelID) * srcLen);
   1985     for(int i = 0; i < srcLen; ++i) {
   1986         srcPtr[i] = (RsScriptKernelID)jSrcPtr[i];
   1987     }
   1988 
   1989     dstkPtr = (RsScriptKernelID*) malloc(sizeof(RsScriptKernelID) * dstkLen);
   1990     for(int i = 0; i < dstkLen; ++i) {
   1991         dstkPtr[i] = (RsScriptKernelID)jDstkPtr[i];
   1992     }
   1993 
   1994     dstfPtr = (RsScriptKernelID*) malloc(sizeof(RsScriptKernelID) * dstfLen);
   1995     for(int i = 0; i < dstfLen; ++i) {
   1996         dstfPtr[i] = (RsScriptKernelID)jDstfPtr[i];
   1997     }
   1998 
   1999     typesPtr = (RsType*) malloc(sizeof(RsType) * typesLen);
   2000     for(int i = 0; i < typesLen; ++i) {
   2001         typesPtr[i] = (RsType)jTypesPtr[i];
   2002     }
   2003 
   2004     id = (jlong)(uintptr_t) dispatchTab.ScriptGroupCreate((RsContext)con,
   2005                                (RsScriptKernelID *)kernelsPtr, kernelsLen * sizeof(RsScriptKernelID),
   2006                                (RsScriptKernelID *)srcPtr, srcLen * sizeof(RsScriptKernelID),
   2007                                (RsScriptKernelID *)dstkPtr, dstkLen * sizeof(RsScriptKernelID),
   2008                                (RsScriptFieldID *)dstfPtr, dstfLen * sizeof(RsScriptKernelID),
   2009                                (RsType *)typesPtr, typesLen * sizeof(RsType));
   2010 
   2011     free(kernelsPtr);
   2012     free(srcPtr);
   2013     free(dstkPtr);
   2014     free(dstfPtr);
   2015     free(typesPtr);
   2016 
   2017 cleanup:
   2018     if (jKernelsPtr != nullptr) {
   2019         _env->ReleaseLongArrayElements(_kernels, jKernelsPtr, 0);
   2020     }
   2021     if (jSrcPtr != nullptr) {
   2022         _env->ReleaseLongArrayElements(_src, jSrcPtr, 0);
   2023     }
   2024     if (jDstkPtr != nullptr) {
   2025         _env->ReleaseLongArrayElements(_dstk, jDstkPtr, 0);
   2026     }
   2027     if (jDstfPtr != nullptr) {
   2028         _env->ReleaseLongArrayElements(_dstf, jDstfPtr, 0);
   2029     }
   2030     if (jTypesPtr != nullptr) {
   2031         _env->ReleaseLongArrayElements(_types, jTypesPtr, 0);
   2032     }
   2033 
   2034     return id;
   2035 }
   2036 
   2037 static void
   2038 nScriptGroupSetInput(JNIEnv *_env, jobject _this, jlong con, jlong gid, jlong kid, jlong alloc)
   2039 {
   2040     LOG_API("nScriptGroupSetInput, con(%p) group(%p), kernelId(%p), alloc(%p)", (RsContext)con,
   2041             (void *)gid, (void *)kid, (void *)alloc);
   2042     dispatchTab.ScriptGroupSetInput((RsContext)con, (RsScriptGroup)gid, (RsScriptKernelID)kid,
   2043                                     (RsAllocation)alloc);
   2044 }
   2045 
   2046 static void
   2047 nScriptGroupSetOutput(JNIEnv *_env, jobject _this, jlong con, jlong gid, jlong kid, jlong alloc)
   2048 {
   2049     LOG_API("nScriptGroupSetOutput, con(%p) group(%p), kernelId(%p), alloc(%p)", (RsContext)con,
   2050             (void *)gid, (void *)kid, (void *)alloc);
   2051     dispatchTab.ScriptGroupSetOutput((RsContext)con, (RsScriptGroup)gid, (RsScriptKernelID)kid,
   2052                                      (RsAllocation)alloc);
   2053 }
   2054 
   2055 static void
   2056 nScriptGroupExecute(JNIEnv *_env, jobject _this, jlong con, jlong gid)
   2057 {
   2058     LOG_API("nScriptGroupSetOutput, con(%p) group(%p)", (RsContext)con, (void *)gid);
   2059     dispatchTab.ScriptGroupExecute((RsContext)con, (RsScriptGroup)gid);
   2060 }
   2061 
   2062 // ---------------------------------------------------------------------------
   2063 
   2064 static jlong
   2065 nSamplerCreate(JNIEnv *_env, jobject _this, jlong con, jint magFilter, jint minFilter,
   2066                jint wrapS, jint wrapT, jint wrapR, jfloat aniso)
   2067 {
   2068     LOG_API("nSamplerCreate, con(%p)", (RsContext)con);
   2069     return (jlong)(uintptr_t)dispatchTab.SamplerCreate((RsContext)con,
   2070                                                        (RsSamplerValue)magFilter,
   2071                                                        (RsSamplerValue)minFilter,
   2072                                                        (RsSamplerValue)wrapS,
   2073                                                        (RsSamplerValue)wrapT,
   2074                                                        (RsSamplerValue)wrapR,
   2075                                                        aniso);
   2076 }
   2077 
   2078 static jint
   2079 nSystemGetPointerSize(JNIEnv *_env, jobject _this) {
   2080     return (jint)sizeof(void*);
   2081 }
   2082 
   2083 // ---------------------------------------------------------------------------
   2084 // For Incremental Intrinsic Support
   2085 static jboolean nIncLoadSO(JNIEnv *_env, jobject _this, jint deviceApi, jstring libPath) {
   2086     void* handle = NULL;
   2087     // For API 9+, dlopen the full path of libRSSupport.
   2088     if (libPath != NULL) {
   2089         const char * libPathJni = _env->GetStringUTFChars(libPath, JNI_FALSE);
   2090         handle = dlopen(libPathJni, RTLD_LAZY | RTLD_LOCAL);
   2091         _env->ReleaseStringUTFChars(libPath, libPathJni);
   2092     } else {
   2093         handle = dlopen("libRSSupport.so", RTLD_LAZY | RTLD_LOCAL);
   2094     }
   2095 
   2096     if (handle == NULL) {
   2097         LOG_ERR("couldn't dlopen %s;  librsjni version: %d", dlerror(), RS_JNI_VERSION);
   2098         return false;
   2099     }
   2100 
   2101     if (loadSymbols(handle, dispatchTabInc, deviceApi) == false) {
   2102         LOG_ERR("Dispatch Table init failed! librsjni version: %d", RS_JNI_VERSION);
   2103         dlclose(handle);
   2104         return false;
   2105     }
   2106     dispatchTabInc.AllocationCreateStrided = (AllocationCreateStridedFnPtr)dlsym(handle, "rsAllocationCreateStrided");
   2107     if (dispatchTabInc.AllocationCreateStrided == NULL) {
   2108         LOG_ERR("Couldn't initialize dispatchTabInc.AllocationCreateStrided");
   2109         dlclose(handle);
   2110         return false;
   2111     }
   2112     LOG_API("Successfully loaded compat runtime");
   2113     return true;
   2114 }
   2115 
   2116 // -----------------------------------
   2117 // To create/destroy a dummy context
   2118 static void
   2119 nIncObjDestroy(JNIEnv *_env, jobject _this, jlong con, jlong obj)
   2120 {
   2121     LOG_API("nObjDestroy, con(%p) obj(%p)", (RsContext)con, (void *)obj);
   2122     dispatchTabInc.ObjDestroy((RsContext)con, (void *)obj);
   2123 }
   2124 
   2125 
   2126 static jlong
   2127 nIncDeviceCreate(JNIEnv *_env, jobject _this)
   2128 {
   2129     LOG_API("nDeviceCreate");
   2130     return (jlong)(uintptr_t)dispatchTabInc.DeviceCreate();
   2131 }
   2132 
   2133 static void
   2134 nIncDeviceDestroy(JNIEnv *_env, jobject _this, jlong dev)
   2135 {
   2136     LOG_API("nDeviceDestroy");
   2137     return dispatchTabInc.DeviceDestroy((RsDevice)dev);
   2138 }
   2139 
   2140 static jlong
   2141 nIncContextCreate(JNIEnv *_env, jobject _this, jlong dev, jint ver, jint sdkVer, jint ct)
   2142 {
   2143     LOG_API("nContextCreate");
   2144     //The compat context for incremental support will be synchronous.
   2145     return (jlong)(uintptr_t)dispatchTabInc.ContextCreate((RsDevice)dev, ver, sdkVer,
   2146                                                           (RsContextType)ct,
   2147                                                           RS_CONTEXT_SYNCHRONOUS);
   2148 }
   2149 
   2150 static void
   2151 nIncContextFinish(JNIEnv *_env, jobject _this, jlong con)
   2152 {
   2153     LOG_API("nContextFinish, con(%p)", (RsContext)con);
   2154     dispatchTabInc.ContextFinish((RsContext)con);
   2155 }
   2156 
   2157 static void
   2158 nIncContextDestroy(JNIEnv *_env, jobject _this, jlong con)
   2159 {
   2160     LOG_API("nContextDestroy, con(%p)", (RsContext)con);
   2161     dispatchTabInc.ContextDestroy((RsContext)con);
   2162 }
   2163 
   2164 // -----------------------------------
   2165 // Create dummy Element
   2166 static jlong
   2167 nIncElementCreate(JNIEnv *_env, jobject _this, jlong con, jlong type, jint kind, jboolean norm, jint size)
   2168 {
   2169     LOG_API("nElementCreate, con(%p), type(%i), kind(%i), norm(%i), size(%i)", (RsContext)con,
   2170             type, kind, norm, size);
   2171     return (jlong)(uintptr_t)dispatchTabInc.ElementCreate((RsContext)con, (RsDataType)type,
   2172                                                           (RsDataKind)kind, norm, size);
   2173 }
   2174 // -----------------------------------
   2175 // Create dummy Type
   2176 static jlong
   2177 nIncTypeCreate(JNIEnv *_env, jobject _this, jlong con, jlong eid,
   2178             jint dimx, jint dimy, jint dimz, jboolean mips, jboolean faces, jint yuv)
   2179 {
   2180     LOG_API("nTypeCreate, con(%p) eid(%p), x(%i), y(%i), z(%i), mips(%i), faces(%i), yuv(%i)",
   2181             incCon, eid, dimx, dimy, dimz, mips, faces, yuv);
   2182 
   2183     return (jlong)(uintptr_t)dispatchTabInc.TypeCreate((RsContext)con, (RsElement)eid, dimx, dimy,
   2184                                                        dimz, mips, faces, yuv);
   2185 }
   2186 
   2187 // -----------------------------------
   2188 // Create Allocation from pointer
   2189 static jlong
   2190 nIncAllocationCreateTyped(JNIEnv *_env, jobject _this, jlong con, jlong incCon, jlong alloc, jlong type, jint xBytesSize)
   2191 {
   2192     LOG_API("nAllocationCreateTyped, con(%p), type(%p), mip(%i), usage(%i), ptr(%p)",
   2193             incCon, (RsElement)type, mips, usage, (void *)pointer);
   2194     size_t strideIn;
   2195     void* pIn = NULL;
   2196     RsAllocation ainI = NULL;
   2197     if (alloc != 0) {
   2198         pIn = dispatchTab.AllocationGetPointer((RsContext)con, (RsAllocation)alloc, 0,
   2199                                                RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X, 0, 0,
   2200                                                &strideIn, sizeof(size_t));
   2201         /*
   2202          * By definition stride is a roundup of xBytesSize with requiredAlignment, so requiredAlignment must
   2203          * be strictly larger than the difference of (stride - xBytesSize).
   2204          *
   2205          * We can prove that as long as requiredAlignment satisfies the following two conditions, the
   2206          * memory layout will be identical :
   2207          * 1. Smaller or equal than stride;
   2208          * 2. Larger than minRequiredAlignment.
   2209          *
   2210          * In this case we can simply choose the first power of 2 that satisfies both conditions.
   2211          */
   2212         size_t requiredAlignment = 16;
   2213         size_t minRequiredAlignment = strideIn - xBytesSize;
   2214         while (requiredAlignment <= minRequiredAlignment) {
   2215             requiredAlignment <<= 1;
   2216         }
   2217         ainI = dispatchTabInc.AllocationCreateStrided((RsContext)incCon, (RsType)type,
   2218                                                       RS_ALLOCATION_MIPMAP_NONE,
   2219                                                       RS_ALLOCATION_USAGE_INCREMENTAL_SUPPORT | RS_ALLOCATION_USAGE_SHARED,
   2220                                                       (uintptr_t)pIn, requiredAlignment);
   2221     }
   2222     return (jlong)(uintptr_t) ainI;
   2223 }
   2224 
   2225 static jobject
   2226 nAllocationGetByteBuffer(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jint xBytesSize, jint dimY, jint dimZ)
   2227 {
   2228     LOG_API("nAllocationGetByteBuffer, con(%p), alloc(%p)", (RsContext)con, (RsAllocation)alloc);
   2229     size_t strideIn = xBytesSize;
   2230     void* ptr = NULL;
   2231     if (alloc != 0 && dispatchTab.AllocationGetPointer != nullptr) {
   2232         ptr = dispatchTab.AllocationGetPointer((RsContext)con, (RsAllocation)alloc, 0,
   2233                                                RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X, dimZ, 0,
   2234                                                &strideIn, sizeof(size_t));
   2235     }
   2236     if (ptr != NULL) {
   2237         size_t bufferSize = strideIn;
   2238         if (dimY > 0) {
   2239             bufferSize *= dimY;
   2240         }
   2241         if (dimZ > 0) {
   2242             bufferSize *= dimZ;
   2243         }
   2244         jobject byteBuffer = _env->NewDirectByteBuffer(ptr, (jlong) bufferSize);
   2245         return byteBuffer;
   2246     } else {
   2247         return NULL;
   2248     }
   2249 }
   2250 
   2251 static jlong
   2252 nAllocationGetStride(JNIEnv *_env, jobject _this, jlong con, jlong alloc)
   2253 {
   2254     LOG_API("nAllocationGetStride, con(%p), alloc(%p)", (RsContext)con, (RsAllocation)alloc);
   2255     size_t strideIn;
   2256     void* ptr = NULL;
   2257     if (alloc != 0 && dispatchTab.AllocationGetPointer != nullptr) {
   2258         ptr = dispatchTab.AllocationGetPointer((RsContext)con, (RsAllocation)alloc, 0,
   2259                                                RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X, 0, 0,
   2260                                                &strideIn, sizeof(size_t));
   2261     }
   2262     return (jlong)strideIn;
   2263 }
   2264 
   2265 // ---------------------------------------------------------------------------
   2266 
   2267 
   2268 static const char *classPathName = "android/support/v8/renderscript/RenderScript";
   2269 
   2270 static JNINativeMethod methods[] = {
   2271 {"nLoadSO",                        "(ZILjava/lang/String;)Z",                 (bool*)nLoadSO },
   2272 {"nLoadIOSO",                      "()Z",                                     (bool*)nLoadIOSO },
   2273 {"nDeviceCreate",                  "()J",                                     (void*)nDeviceCreate },
   2274 {"nDeviceDestroy",                 "(J)V",                                    (void*)nDeviceDestroy },
   2275 {"nDeviceSetConfig",               "(JII)V",                                  (void*)nDeviceSetConfig },
   2276 {"nContextGetUserMessage",         "(J[I)I",                                  (void*)nContextGetUserMessage },
   2277 {"nContextGetErrorMessage",        "(J)Ljava/lang/String;",                   (void*)nContextGetErrorMessage },
   2278 {"nContextPeekMessage",            "(J[I)I",                                  (void*)nContextPeekMessage },
   2279 {"nContextInitToClient",           "(J)V",                                    (void*)nContextInitToClient },
   2280 {"nContextDeinitToClient",         "(J)V",                                    (void*)nContextDeinitToClient },
   2281 
   2282 
   2283 // All methods below are thread protected in java.
   2284 {"rsnContextCreate",                 "(JIIILjava/lang/String;)J",             (void*)nContextCreate },
   2285 {"rsnContextFinish",                 "(J)V",                                  (void*)nContextFinish },
   2286 {"rsnContextSetPriority",            "(JI)V",                                 (void*)nContextSetPriority },
   2287 {"rsnContextDestroy",                "(J)V",                                  (void*)nContextDestroy },
   2288 {"rsnContextDump",                   "(JI)V",                                 (void*)nContextDump },
   2289 {"rsnContextSendMessage",            "(JI[I)V",                               (void*)nContextSendMessage },
   2290 {"rsnClosureCreate",                 "(JJJ[J[J[I[J[J)J",                      (void*)nClosureCreate },
   2291 {"rsnInvokeClosureCreate",           "(JJ[B[J[J[I)J",                         (void*)nInvokeClosureCreate },
   2292 {"rsnClosureSetArg",                 "(JJIJI)V",                              (void*)nClosureSetArg },
   2293 {"rsnClosureSetGlobal",              "(JJJJI)V",                              (void*)nClosureSetGlobal },
   2294 {"rsnObjDestroy",                    "(JJ)V",                                 (void*)nObjDestroy },
   2295 
   2296 {"rsnElementCreate",                 "(JJIZI)J",                              (void*)nElementCreate },
   2297 {"rsnElementCreate2",                "(J[J[Ljava/lang/String;[I)J",           (void*)nElementCreate2 },
   2298 {"rsnElementGetSubElements",         "(JJ[J[Ljava/lang/String;[I)V",          (void*)nElementGetSubElements },
   2299 
   2300 {"rsnTypeCreate",                    "(JJIIIZZI)J",                           (void*)nTypeCreate },
   2301 
   2302 {"rsnAllocationCreateTyped",         "(JJIIJ)J",                              (void*)nAllocationCreateTyped },
   2303 {"rsnAllocationCreateFromBitmap",    "(JJILandroid/graphics/Bitmap;I)J",      (void*)nAllocationCreateFromBitmap },
   2304 {"rsnAllocationCreateBitmapBackedAllocation",    "(JJILandroid/graphics/Bitmap;I)J",      (void*)nAllocationCreateBitmapBackedAllocation },
   2305 {"rsnAllocationCubeCreateFromBitmap","(JJILandroid/graphics/Bitmap;I)J",      (void*)nAllocationCubeCreateFromBitmap },
   2306 
   2307 {"rsnAllocationCopyFromBitmap",      "(JJLandroid/graphics/Bitmap;)V",        (void*)nAllocationCopyFromBitmap },
   2308 {"rsnAllocationCopyToBitmap",        "(JJLandroid/graphics/Bitmap;)V",        (void*)nAllocationCopyToBitmap },
   2309 
   2310 {"rsnAllocationSyncAll",             "(JJI)V",                                (void*)nAllocationSyncAll },
   2311 {"rsnAllocationSetSurface",          "(JJLandroid/view/Surface;)V",           (void*)nAllocationSetSurface },
   2312 {"rsnAllocationIoSend",              "(JJ)V",                                 (void*)nAllocationIoSend },
   2313 {"rsnAllocationData1D",              "(JJIIILjava/lang/Object;IIIZ)V",        (void*)nAllocationData1D },
   2314 {"rsnAllocationElementData1D",       "(JJIII[BI)V",                           (void*)nAllocationElementData1D },
   2315 //{"rsnAllocationElementData",         "(JJIIIII[BI)V",                         (void*)nAllocationElementData },
   2316 {"rsnAllocationData2D",              "(JJIIIIIILjava/lang/Object;IIIZ)V",     (void*)nAllocationData2D },
   2317 {"rsnAllocationData2D",              "(JJIIIIIIJIIII)V",                      (void*)nAllocationData2D_alloc },
   2318 {"rsnAllocationData3D",              "(JJIIIIIIILjava/lang/Object;IIIZ)V",    (void*)nAllocationData3D },
   2319 {"rsnAllocationData3D",              "(JJIIIIIIIJIIII)V",                     (void*)nAllocationData3D_alloc },
   2320 {"rsnAllocationRead",                "(JJLjava/lang/Object;IIZ)V",            (void*)nAllocationRead },
   2321 {"rsnAllocationRead1D",              "(JJIIILjava/lang/Object;IIIZ)V",        (void*)nAllocationRead1D },
   2322 //{"rsnAllocationElementRead",         "(JJIIIII[BI)V",                         (void*)nAllocationElementRead },
   2323 {"rsnAllocationRead2D",              "(JJIIIIIILjava/lang/Object;IIIZ)V",     (void*)nAllocationRead2D },
   2324 //{"rsnAllocationRead3D",              "(JJIIIIIIILjava/lang/Object;IIIZ)V",  (void*)nAllocationRead3D },
   2325 {"rsnAllocationGetType",             "(JJ)J",                                 (void*)nAllocationGetType},
   2326 {"rsnAllocationResize1D",            "(JJI)V",                                (void*)nAllocationResize1D },
   2327 {"rsnAllocationGenerateMipmaps",     "(JJ)V",                                 (void*)nAllocationGenerateMipmaps },
   2328 
   2329 {"rsnScriptBindAllocation",          "(JJJIZ)V",                              (void*)nScriptBindAllocation },
   2330 {"rsnScriptSetTimeZone",             "(JJ[BZ)V",                              (void*)nScriptSetTimeZone },
   2331 {"rsnScriptInvoke",                  "(JJIZ)V",                               (void*)nScriptInvoke },
   2332 {"rsnScriptInvokeV",                 "(JJI[BZ)V",                             (void*)nScriptInvokeV },
   2333 {"rsnScriptForEach",                 "(JJJIJJZ)V",                            (void*)nScriptForEach },
   2334 {"rsnScriptForEach",                 "(JJJIJJ[BZ)V",                          (void*)nScriptForEachV },
   2335 {"rsnScriptForEach",                 "(JJI[JJ[B[I)V",                         (void*)nScriptForEachMulti },
   2336 {"rsnScriptForEachClipped",          "(JJJIJJIIIIIIZ)V",                      (void*)nScriptForEachClipped },
   2337 {"rsnScriptForEachClipped",          "(JJJIJJ[BIIIIIIZ)V",                    (void*)nScriptForEachClippedV },
   2338 {"rsnScriptReduce",                  "(JJI[JJ[I)V",                           (void*)nScriptReduce },
   2339 {"rsnScriptSetVarI",                 "(JJIIZ)V",                              (void*)nScriptSetVarI },
   2340 {"rsnScriptSetVarJ",                 "(JJIJZ)V",                              (void*)nScriptSetVarJ },
   2341 {"rsnScriptSetVarF",                 "(JJIFZ)V",                              (void*)nScriptSetVarF },
   2342 {"rsnScriptSetVarD",                 "(JJIDZ)V",                              (void*)nScriptSetVarD },
   2343 {"rsnScriptSetVarV",                 "(JJI[BZ)V",                             (void*)nScriptSetVarV },
   2344 {"rsnScriptSetVarVE",                "(JJI[BJ[IZ)V",                          (void*)nScriptSetVarVE },
   2345 {"rsnScriptSetVarObj",               "(JJIJZ)V",                              (void*)nScriptSetVarObj },
   2346 
   2347 {"rsnScriptCCreate",                 "(JLjava/lang/String;Ljava/lang/String;[BI)J",  (void*)nScriptCCreate },
   2348 {"rsnScriptIntrinsicCreate",         "(JIJZ)J",                               (void*)nScriptIntrinsicCreate },
   2349 {"rsnScriptKernelIDCreate",          "(JJIIZ)J",                              (void*)nScriptKernelIDCreate },
   2350 {"rsnScriptInvokeIDCreate",          "(JJI)J",                                (void*)nScriptInvokeIDCreate },
   2351 {"rsnScriptFieldIDCreate",           "(JJIZ)J",                               (void*)nScriptFieldIDCreate },
   2352 {"rsnScriptGroupCreate",             "(J[J[J[J[J[J)J",                        (void*)nScriptGroupCreate },
   2353 {"rsnScriptGroup2Create",            "(JLjava/lang/String;Ljava/lang/String;[J)J", (void*)nScriptGroup2Create },
   2354 {"rsnScriptGroupSetInput",           "(JJJJ)V",                               (void*)nScriptGroupSetInput },
   2355 {"rsnScriptGroupSetOutput",          "(JJJJ)V",                               (void*)nScriptGroupSetOutput },
   2356 {"rsnScriptGroupExecute",            "(JJ)V",                                 (void*)nScriptGroupExecute },
   2357 {"rsnScriptGroup2Execute",           "(JJ)V",                                 (void*)nScriptGroup2Execute },
   2358 
   2359 {"rsnScriptIntrinsicBLAS_Single",    "(JJJIIIIIIIIIFJJFJIIIIZ)V",             (void*)nScriptIntrinsicBLAS_Single },
   2360 {"rsnScriptIntrinsicBLAS_Double",    "(JJJIIIIIIIIIDJJDJIIIIZ)V",             (void*)nScriptIntrinsicBLAS_Double },
   2361 {"rsnScriptIntrinsicBLAS_Complex",   "(JJJIIIIIIIIIFFJJFFJIIIIZ)V",           (void*)nScriptIntrinsicBLAS_Complex },
   2362 {"rsnScriptIntrinsicBLAS_Z",         "(JJJIIIIIIIIIDDJJDDJIIIIZ)V",           (void*)nScriptIntrinsicBLAS_Z },
   2363 
   2364 {"rsnScriptIntrinsicBLAS_BNNM",      "(JJJIIIJIJIJIIZ)V",                     (void*)nScriptIntrinsicBLAS_BNNM },
   2365 
   2366 {"rsnSamplerCreate",                 "(JIIIIIF)J",                            (void*)nSamplerCreate },
   2367 
   2368 {"rsnSystemGetPointerSize",          "()I",                                   (void*)nSystemGetPointerSize },
   2369 
   2370 // Entry points for Inc libRSSupport
   2371 {"nIncLoadSO",                       "(ILjava/lang/String;)Z",                (bool*)nIncLoadSO },
   2372 {"nIncDeviceCreate",                 "()J",                                   (void*)nIncDeviceCreate },
   2373 {"nIncDeviceDestroy",                "(J)V",                                  (void*)nIncDeviceDestroy },
   2374 {"rsnIncContextCreate",              "(JIII)J",                               (void*)nIncContextCreate },
   2375 {"rsnIncContextFinish",              "(J)V",                                  (void*)nIncContextFinish },
   2376 {"rsnIncContextDestroy",             "(J)V",                                  (void*)nIncContextDestroy },
   2377 {"rsnIncObjDestroy",                 "(JJ)V",                                 (void*)nIncObjDestroy },
   2378 {"rsnIncElementCreate",              "(JJIZI)J",                              (void*)nIncElementCreate },
   2379 {"rsnIncTypeCreate",                 "(JJIIIZZI)J",                           (void*)nIncTypeCreate },
   2380 {"rsnIncAllocationCreateTyped",      "(JJJJI)J",                              (void*)nIncAllocationCreateTyped },
   2381 {"rsnAllocationGetByteBuffer",       "(JJIII)Ljava/nio/ByteBuffer;",          (void*)nAllocationGetByteBuffer },
   2382 {"rsnAllocationGetStride",           "(JJ)J",                                 (void*)nAllocationGetStride },
   2383 };
   2384 
   2385 // ---------------------------------------------------------------------------
   2386 
   2387 jint JNI_OnLoad(JavaVM* vm, void* reserved)
   2388 {
   2389     JNIEnv* env = NULL;
   2390     jclass clazz = NULL;
   2391     jint result = -1;
   2392 
   2393     if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
   2394         //        __android_log_print(ANDROID_LOG_ERROR, LOG_TAG,
   2395         //            "ERROR: GetEnv failed\n");
   2396         goto bail;
   2397     }
   2398     if (env == NULL) {
   2399         //        __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "ERROR: env == NULL");
   2400         goto bail;
   2401     }
   2402 
   2403     clazz = env->FindClass(classPathName);
   2404     if (clazz == NULL) {
   2405         goto bail;
   2406     }
   2407 
   2408     if (env->RegisterNatives(clazz, methods, NELEM(methods)) < 0) {
   2409         //        __android_log_print(ANDROID_LOG_ERROR, LOG_TAG,
   2410         //            "ERROR: MediaPlayer native registration failed\n");
   2411         goto bail;
   2412     }
   2413 
   2414     /* success -- return valid version number */
   2415     result = JNI_VERSION_1_4;
   2416 
   2417 bail:
   2418     return result;
   2419 }
   2420