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