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