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