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