android_renderscript_RenderScript.cpp revision a29ca11099195f67cd856b1fdc94c22c8b29060f
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              jlong ain, jlong aout, jintArray limits)
1740{
1741    LOG_API("nScriptReduce, con(%p), s(%p), slot(%i) ain(%" PRId64 ") aout(%" PRId64 ")", (RsContext)con, (void *)script, slot, ain, aout);
1742
1743    RsScriptCall sc, *sca = nullptr;
1744    uint32_t sc_size = 0;
1745
1746    jint  limit_len = 0;
1747    jint *limit_ptr = nullptr;
1748
1749    bool limitLengthValid = true;
1750
1751    // If the caller passed limits, reflect them in the RsScriptCall.
1752    if (limits != nullptr) {
1753        limit_len = _env->GetArrayLength(limits);
1754        limit_ptr = _env->GetIntArrayElements(limits, nullptr);
1755
1756        // We expect to be passed an array [x1, x2] which specifies
1757        // the sub-range for a 1-dimensional reduction.
1758        if (limit_len == 2) {
1759            sc.xStart     = limit_ptr[0];
1760            sc.xEnd       = limit_ptr[1];
1761            sc.yStart     = 0;
1762            sc.yEnd       = 0;
1763            sc.zStart     = 0;
1764            sc.zEnd       = 0;
1765            sc.strategy   = RS_FOR_EACH_STRATEGY_DONT_CARE;
1766            sc.arrayStart = 0;
1767            sc.arrayEnd = 0;
1768            sc.array2Start = 0;
1769            sc.array2End = 0;
1770            sc.array3Start = 0;
1771            sc.array3End = 0;
1772            sc.array4Start = 0;
1773            sc.array4End = 0;
1774
1775            sca = &sc;
1776            sc_size = sizeof(sc);
1777        } else {
1778            LOG_ERR("LaunchOptions cannot be recognized.");
1779            limitLengthValid = false;
1780        }
1781    }
1782
1783    if (limitLengthValid) {
1784        dispatchTab.ScriptReduce((RsContext)con, (RsScript)script, slot,
1785                                 (RsAllocation)ain, (RsAllocation)aout,
1786                                 sca, sc_size);
1787    }
1788
1789    if (limits != nullptr) {
1790        _env->ReleaseIntArrayElements(limits, limit_ptr, JNI_ABORT);
1791    }
1792}
1793
1794static void
1795nScriptReduceNew(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot,
1796                 jlongArray ains, jlong aout, jintArray limits)
1797{
1798    LOG_API("nScriptReduceNew, con(%p), s(%p), slot(%i) ains(%p) aout(%" PRId64 ")", (RsContext)con, (void *)script, slot, ains, aout);
1799
1800    if (ains == nullptr) {
1801        LOG_ERR("At least one input required.");
1802        // TODO (b/20758983): Report back to Java and throw an exception
1803        return;
1804    }
1805    jint in_len = _env->GetArrayLength(ains);
1806    if (in_len > (jint)RS_KERNEL_MAX_ARGUMENTS) {
1807        LOG_ERR("Too many arguments in kernel launch.");
1808        // TODO (b/20758983): Report back to Java and throw an exception
1809        return;
1810    }
1811
1812    jlong *in_ptr = _env->GetLongArrayElements(ains, nullptr);
1813    if (in_ptr == nullptr) {
1814        LOG_ERR("Failed to get Java array elements");
1815        // TODO (b/20758983): Report back to Java and throw an exception
1816        return;
1817    }
1818
1819    RsAllocation *in_allocs = nullptr;
1820    if (sizeof(RsAllocation) == sizeof(jlong)) {
1821        in_allocs = (RsAllocation*)in_ptr;
1822    } else {
1823        // Convert from 64-bit jlong types to the native pointer type.
1824
1825        in_allocs = (RsAllocation*)alloca(in_len * sizeof(RsAllocation));
1826        if (in_allocs == nullptr) {
1827            LOG_ERR("Failed launching kernel for lack of memory.");
1828            // TODO (b/20758983): Report back to Java and throw an exception
1829            _env->ReleaseLongArrayElements(ains, in_ptr, JNI_ABORT);
1830            return;
1831        }
1832
1833        for (int index = in_len; --index >= 0;) {
1834            in_allocs[index] = (RsAllocation)in_ptr[index];
1835        }
1836    }
1837
1838    RsScriptCall sc, *sca = nullptr;
1839    uint32_t sc_size = 0;
1840
1841    jint  limit_len = 0;
1842    jint *limit_ptr = nullptr;
1843
1844    if (limits != nullptr) {
1845        limit_len = _env->GetArrayLength(limits);
1846        limit_ptr = _env->GetIntArrayElements(limits, nullptr);
1847        if (limit_ptr == nullptr) {
1848            LOG_ERR("Failed to get Java array elements");
1849            // TODO (b/20758983): Report back to Java and throw an exception
1850            _env->ReleaseLongArrayElements(ains, in_ptr, JNI_ABORT);
1851            return;
1852        }
1853
1854        if (limit_len != 6) {
1855            LOG_ERR("LaunchOptions cannot be recognized");
1856            // TODO (b/20758983): Report back to Java and throw an exception
1857            _env->ReleaseLongArrayElements(ains, in_ptr, JNI_ABORT);
1858            return;
1859        }
1860
1861        sc.xStart     = limit_ptr[0];
1862        sc.xEnd       = limit_ptr[1];
1863        sc.yStart     = limit_ptr[2];
1864        sc.yEnd       = limit_ptr[3];
1865        sc.zStart     = limit_ptr[4];
1866        sc.zEnd       = limit_ptr[5];
1867        sc.strategy   = RS_FOR_EACH_STRATEGY_DONT_CARE;
1868        sc.arrayStart = 0;
1869        sc.arrayEnd = 0;
1870        sc.array2Start = 0;
1871        sc.array2End = 0;
1872        sc.array3Start = 0;
1873        sc.array3End = 0;
1874        sc.array4Start = 0;
1875        sc.array4End = 0;
1876
1877        sca = &sc;
1878        sc_size = sizeof(sc);
1879    }
1880
1881    dispatchTab.ScriptReduceNew((RsContext)con, (RsScript)script, slot,
1882                                in_allocs, in_len, (RsAllocation)aout,
1883                                sca, sc_size);
1884
1885    _env->ReleaseLongArrayElements(ains, in_ptr, JNI_ABORT);
1886
1887    if (limits != nullptr) {
1888        _env->ReleaseIntArrayElements(limits, limit_ptr, JNI_ABORT);
1889    }
1890}
1891
1892// -----------------------------------
1893
1894static jlong
1895nScriptCCreate(JNIEnv *_env, jobject _this, jlong con,
1896               jstring resName, jstring cacheDir,
1897               jbyteArray scriptRef, jint length)
1898{
1899    LOG_API("nScriptCCreate, con(%p)", (RsContext)con);
1900
1901    AutoJavaStringToUTF8 resNameUTF(_env, resName);
1902    AutoJavaStringToUTF8 cacheDirUTF(_env, cacheDir);
1903    jlong ret = 0;
1904    jbyte* script_ptr = NULL;
1905    jint _exception = 0;
1906    jint remaining;
1907    if (!scriptRef) {
1908        _exception = 1;
1909        //jniThrowException(_env, "java/lang/IllegalArgumentException", "script == null");
1910        goto exit;
1911    }
1912    if (length < 0) {
1913        _exception = 1;
1914        //jniThrowException(_env, "java/lang/IllegalArgumentException", "length < 0");
1915        goto exit;
1916    }
1917    remaining = _env->GetArrayLength(scriptRef);
1918    if (remaining < length) {
1919        _exception = 1;
1920        //jniThrowException(_env, "java/lang/IllegalArgumentException",
1921        //        "length > script.length - offset");
1922        goto exit;
1923    }
1924    script_ptr = (jbyte *)
1925        _env->GetPrimitiveArrayCritical(scriptRef, (jboolean *)0);
1926
1927    //rsScriptCSetText(con, (const char *)script_ptr, length);
1928
1929    ret = (jlong)(uintptr_t)dispatchTab.ScriptCCreate((RsContext)con,
1930                                                      resNameUTF.c_str(), resNameUTF.length(),
1931                                                      cacheDirUTF.c_str(), cacheDirUTF.length(),
1932                                                      (const char *)script_ptr, length);
1933
1934exit:
1935    if (script_ptr) {
1936        _env->ReleasePrimitiveArrayCritical(scriptRef, script_ptr,
1937                _exception ? JNI_ABORT: 0);
1938    }
1939
1940    return (jlong)(uintptr_t)ret;
1941}
1942
1943static jlong
1944nScriptIntrinsicCreate(JNIEnv *_env, jobject _this, jlong con, jint id, jlong eid, jboolean mUseInc)
1945{
1946    LOG_API("nScriptIntrinsicCreate, con(%p) id(%i) element(%p)", (RsContext)con, id, (void *)eid);
1947    if (mUseInc) {
1948        return (jlong)(uintptr_t)dispatchTabInc.ScriptIntrinsicCreate((RsContext)con, id, (RsElement)eid);
1949    } else {
1950        return (jlong)(uintptr_t)dispatchTab.ScriptIntrinsicCreate((RsContext)con, id, (RsElement)eid);
1951    }
1952}
1953
1954static jlong
1955nScriptKernelIDCreate(JNIEnv *_env, jobject _this, jlong con, jlong sid, jint slot, jint sig, jboolean mUseInc)
1956{
1957    LOG_API("nScriptKernelIDCreate, con(%p) script(%p), slot(%i), sig(%i)", (RsContext)con,
1958            (void *)sid, slot, sig);
1959    if (mUseInc) {
1960        return (jlong)(uintptr_t)dispatchTabInc.ScriptKernelIDCreate((RsContext)con, (RsScript)sid,
1961                                                                     slot, sig);
1962    } else {
1963        return (jlong)(uintptr_t)dispatchTab.ScriptKernelIDCreate((RsContext)con, (RsScript)sid,
1964                                                                  slot, sig);
1965    }
1966}
1967
1968static jlong
1969nScriptInvokeIDCreate(JNIEnv *_env, jobject _this, jlong con, jlong sid, jint slot)
1970{
1971    LOG_API("nScriptInvokeIDCreate, con(%p) script(%p), slot(%i), sig(%i)", con,
1972            (void *)sid, slot);
1973    return (jlong)dispatchTab.ScriptInvokeIDCreate((RsContext)con, (RsScript)sid, slot);
1974}
1975
1976static jlong
1977nScriptFieldIDCreate(JNIEnv *_env, jobject _this, jlong con, jlong sid, jint slot, jboolean mUseInc)
1978{
1979    LOG_API("nScriptFieldIDCreate, con(%p) script(%p), slot(%i)", (RsContext)con, (void *)sid, slot);
1980    if (mUseInc) {
1981        return (jlong)(uintptr_t)dispatchTabInc.ScriptFieldIDCreate((RsContext)con, (RsScript)sid, slot);
1982    } else {
1983        return (jlong)(uintptr_t)dispatchTab.ScriptFieldIDCreate((RsContext)con, (RsScript)sid, slot);
1984    }
1985}
1986
1987static jlong
1988nScriptGroupCreate(JNIEnv *_env, jobject _this, jlong con, jlongArray _kernels, jlongArray _src,
1989    jlongArray _dstk, jlongArray _dstf, jlongArray _types)
1990{
1991    LOG_API("nScriptGroupCreate, con(%p)", (RsContext)con);
1992
1993    jlong id = 0;
1994
1995    RsScriptKernelID* kernelsPtr;
1996    jint kernelsLen = _env->GetArrayLength(_kernels);
1997    jlong *jKernelsPtr = _env->GetLongArrayElements(_kernels, nullptr);
1998
1999    RsScriptKernelID* srcPtr;
2000    jint srcLen = _env->GetArrayLength(_src);
2001    jlong *jSrcPtr = _env->GetLongArrayElements(_src, nullptr);
2002
2003    RsScriptKernelID* dstkPtr;
2004    jint dstkLen = _env->GetArrayLength(_dstk);
2005    jlong *jDstkPtr = _env->GetLongArrayElements(_dstk, nullptr);
2006
2007    RsScriptKernelID* dstfPtr;
2008    jint dstfLen = _env->GetArrayLength(_dstf);
2009    jlong *jDstfPtr = _env->GetLongArrayElements(_dstf, nullptr);
2010
2011    RsType* typesPtr;
2012    jint typesLen = _env->GetArrayLength(_types);
2013    jlong *jTypesPtr = _env->GetLongArrayElements(_types, nullptr);
2014
2015    if (jKernelsPtr == nullptr) {
2016        LOG_ERR("Failed to get Java array elements: kernels");
2017        goto cleanup;
2018    }
2019    if (jSrcPtr == nullptr) {
2020        LOG_ERR("Failed to get Java array elements: src");
2021        goto cleanup;
2022    }
2023    if (jDstkPtr == nullptr) {
2024        LOG_ERR("Failed to get Java array elements: dstk");
2025        goto cleanup;
2026    }
2027    if (jDstfPtr == nullptr) {
2028        LOG_ERR("Failed to get Java array elements: dstf");
2029        goto cleanup;
2030    }
2031    if (jTypesPtr == nullptr) {
2032        LOG_ERR("Failed to get Java array elements: types");
2033        goto cleanup;
2034    }
2035
2036    kernelsPtr = (RsScriptKernelID*) malloc(sizeof(RsScriptKernelID) * kernelsLen);
2037    for(int i = 0; i < kernelsLen; ++i) {
2038        kernelsPtr[i] = (RsScriptKernelID)jKernelsPtr[i];
2039    }
2040
2041    srcPtr = (RsScriptKernelID*) malloc(sizeof(RsScriptKernelID) * srcLen);
2042    for(int i = 0; i < srcLen; ++i) {
2043        srcPtr[i] = (RsScriptKernelID)jSrcPtr[i];
2044    }
2045
2046    dstkPtr = (RsScriptKernelID*) malloc(sizeof(RsScriptKernelID) * dstkLen);
2047    for(int i = 0; i < dstkLen; ++i) {
2048        dstkPtr[i] = (RsScriptKernelID)jDstkPtr[i];
2049    }
2050
2051    dstfPtr = (RsScriptKernelID*) malloc(sizeof(RsScriptKernelID) * dstfLen);
2052    for(int i = 0; i < dstfLen; ++i) {
2053        dstfPtr[i] = (RsScriptKernelID)jDstfPtr[i];
2054    }
2055
2056    typesPtr = (RsType*) malloc(sizeof(RsType) * typesLen);
2057    for(int i = 0; i < typesLen; ++i) {
2058        typesPtr[i] = (RsType)jTypesPtr[i];
2059    }
2060
2061    id = (jlong)(uintptr_t) dispatchTab.ScriptGroupCreate((RsContext)con,
2062                               (RsScriptKernelID *)kernelsPtr, kernelsLen * sizeof(RsScriptKernelID),
2063                               (RsScriptKernelID *)srcPtr, srcLen * sizeof(RsScriptKernelID),
2064                               (RsScriptKernelID *)dstkPtr, dstkLen * sizeof(RsScriptKernelID),
2065                               (RsScriptFieldID *)dstfPtr, dstfLen * sizeof(RsScriptKernelID),
2066                               (RsType *)typesPtr, typesLen * sizeof(RsType));
2067
2068    free(kernelsPtr);
2069    free(srcPtr);
2070    free(dstkPtr);
2071    free(dstfPtr);
2072    free(typesPtr);
2073
2074cleanup:
2075    if (jKernelsPtr != nullptr) {
2076        _env->ReleaseLongArrayElements(_kernels, jKernelsPtr, 0);
2077    }
2078    if (jSrcPtr != nullptr) {
2079        _env->ReleaseLongArrayElements(_src, jSrcPtr, 0);
2080    }
2081    if (jDstkPtr != nullptr) {
2082        _env->ReleaseLongArrayElements(_dstk, jDstkPtr, 0);
2083    }
2084    if (jDstfPtr != nullptr) {
2085        _env->ReleaseLongArrayElements(_dstf, jDstfPtr, 0);
2086    }
2087    if (jTypesPtr != nullptr) {
2088        _env->ReleaseLongArrayElements(_types, jTypesPtr, 0);
2089    }
2090
2091    return id;
2092}
2093
2094static void
2095nScriptGroupSetInput(JNIEnv *_env, jobject _this, jlong con, jlong gid, jlong kid, jlong alloc)
2096{
2097    LOG_API("nScriptGroupSetInput, con(%p) group(%p), kernelId(%p), alloc(%p)", (RsContext)con,
2098            (void *)gid, (void *)kid, (void *)alloc);
2099    dispatchTab.ScriptGroupSetInput((RsContext)con, (RsScriptGroup)gid, (RsScriptKernelID)kid,
2100                                    (RsAllocation)alloc);
2101}
2102
2103static void
2104nScriptGroupSetOutput(JNIEnv *_env, jobject _this, jlong con, jlong gid, jlong kid, jlong alloc)
2105{
2106    LOG_API("nScriptGroupSetOutput, con(%p) group(%p), kernelId(%p), alloc(%p)", (RsContext)con,
2107            (void *)gid, (void *)kid, (void *)alloc);
2108    dispatchTab.ScriptGroupSetOutput((RsContext)con, (RsScriptGroup)gid, (RsScriptKernelID)kid,
2109                                     (RsAllocation)alloc);
2110}
2111
2112static void
2113nScriptGroupExecute(JNIEnv *_env, jobject _this, jlong con, jlong gid)
2114{
2115    LOG_API("nScriptGroupSetOutput, con(%p) group(%p)", (RsContext)con, (void *)gid);
2116    dispatchTab.ScriptGroupExecute((RsContext)con, (RsScriptGroup)gid);
2117}
2118
2119// ---------------------------------------------------------------------------
2120
2121static jlong
2122nSamplerCreate(JNIEnv *_env, jobject _this, jlong con, jint magFilter, jint minFilter,
2123               jint wrapS, jint wrapT, jint wrapR, jfloat aniso)
2124{
2125    LOG_API("nSamplerCreate, con(%p)", (RsContext)con);
2126    return (jlong)(uintptr_t)dispatchTab.SamplerCreate((RsContext)con,
2127                                                       (RsSamplerValue)magFilter,
2128                                                       (RsSamplerValue)minFilter,
2129                                                       (RsSamplerValue)wrapS,
2130                                                       (RsSamplerValue)wrapT,
2131                                                       (RsSamplerValue)wrapR,
2132                                                       aniso);
2133}
2134
2135static jint
2136nSystemGetPointerSize(JNIEnv *_env, jobject _this) {
2137    return (jint)sizeof(void*);
2138}
2139
2140// ---------------------------------------------------------------------------
2141// For Incremental Intrinsic Support
2142static jboolean nIncLoadSO(JNIEnv *_env, jobject _this, jint deviceApi, jstring libPath) {
2143    void* handle = NULL;
2144    // For API 9+, dlopen the full path of libRSSupport.
2145    if (libPath != NULL) {
2146        const char * libPathJni = _env->GetStringUTFChars(libPath, JNI_FALSE);
2147        handle = dlopen(libPathJni, RTLD_LAZY | RTLD_LOCAL);
2148        _env->ReleaseStringUTFChars(libPath, libPathJni);
2149    } else {
2150        handle = dlopen("libRSSupport.so", RTLD_LAZY | RTLD_LOCAL);
2151    }
2152
2153    if (handle == NULL) {
2154        LOG_ERR("couldn't dlopen %s;  librsjni version: %d", dlerror(), RS_JNI_VERSION);
2155        return false;
2156    }
2157
2158    if (loadSymbols(handle, dispatchTabInc, deviceApi) == false) {
2159        LOG_ERR("Dispatch Table init failed! librsjni version: %d", RS_JNI_VERSION);
2160        dlclose(handle);
2161        return false;
2162    }
2163    dispatchTabInc.AllocationCreateStrided = (AllocationCreateStridedFnPtr)dlsym(handle, "rsAllocationCreateStrided");
2164    if (dispatchTabInc.AllocationCreateStrided == NULL) {
2165        LOG_ERR("Couldn't initialize dispatchTabInc.AllocationCreateStrided");
2166        dlclose(handle);
2167        return false;
2168    }
2169    LOG_API("Successfully loaded compat runtime");
2170    return true;
2171}
2172
2173// -----------------------------------
2174// To create/destroy a dummy context
2175static void
2176nIncObjDestroy(JNIEnv *_env, jobject _this, jlong con, jlong obj)
2177{
2178    LOG_API("nObjDestroy, con(%p) obj(%p)", (RsContext)con, (void *)obj);
2179    dispatchTabInc.ObjDestroy((RsContext)con, (void *)obj);
2180}
2181
2182
2183static jlong
2184nIncDeviceCreate(JNIEnv *_env, jobject _this)
2185{
2186    LOG_API("nDeviceCreate");
2187    return (jlong)(uintptr_t)dispatchTabInc.DeviceCreate();
2188}
2189
2190static void
2191nIncDeviceDestroy(JNIEnv *_env, jobject _this, jlong dev)
2192{
2193    LOG_API("nDeviceDestroy");
2194    return dispatchTabInc.DeviceDestroy((RsDevice)dev);
2195}
2196
2197static jlong
2198nIncContextCreate(JNIEnv *_env, jobject _this, jlong dev, jint ver, jint sdkVer, jint ct)
2199{
2200    LOG_API("nContextCreate");
2201    //The compat context for incremental support will be synchronous.
2202    return (jlong)(uintptr_t)dispatchTabInc.ContextCreate((RsDevice)dev, ver, sdkVer,
2203                                                          (RsContextType)ct,
2204                                                          RS_CONTEXT_SYNCHRONOUS);
2205}
2206
2207static void
2208nIncContextFinish(JNIEnv *_env, jobject _this, jlong con)
2209{
2210    LOG_API("nContextFinish, con(%p)", (RsContext)con);
2211    dispatchTabInc.ContextFinish((RsContext)con);
2212}
2213
2214static void
2215nIncContextDestroy(JNIEnv *_env, jobject _this, jlong con)
2216{
2217    LOG_API("nContextDestroy, con(%p)", (RsContext)con);
2218    dispatchTabInc.ContextDestroy((RsContext)con);
2219}
2220
2221// -----------------------------------
2222// Create dummy Element
2223static jlong
2224nIncElementCreate(JNIEnv *_env, jobject _this, jlong con, jlong type, jint kind, jboolean norm, jint size)
2225{
2226    LOG_API("nElementCreate, con(%p), type(%i), kind(%i), norm(%i), size(%i)", (RsContext)con,
2227            type, kind, norm, size);
2228    return (jlong)(uintptr_t)dispatchTabInc.ElementCreate((RsContext)con, (RsDataType)type,
2229                                                          (RsDataKind)kind, norm, size);
2230}
2231// -----------------------------------
2232// Create dummy Type
2233static jlong
2234nIncTypeCreate(JNIEnv *_env, jobject _this, jlong con, jlong eid,
2235            jint dimx, jint dimy, jint dimz, jboolean mips, jboolean faces, jint yuv)
2236{
2237    LOG_API("nTypeCreate, con(%p) eid(%p), x(%i), y(%i), z(%i), mips(%i), faces(%i), yuv(%i)",
2238            incCon, eid, dimx, dimy, dimz, mips, faces, yuv);
2239
2240    return (jlong)(uintptr_t)dispatchTabInc.TypeCreate((RsContext)con, (RsElement)eid, dimx, dimy,
2241                                                       dimz, mips, faces, yuv);
2242}
2243
2244// -----------------------------------
2245// Create Allocation from pointer
2246static jlong
2247nIncAllocationCreateTyped(JNIEnv *_env, jobject _this, jlong con, jlong incCon, jlong alloc, jlong type, jint xBytesSize)
2248{
2249    LOG_API("nAllocationCreateTyped, con(%p), type(%p), mip(%i), usage(%i), ptr(%p)",
2250            incCon, (RsElement)type, mips, usage, (void *)pointer);
2251    size_t strideIn;
2252    void* pIn = NULL;
2253    RsAllocation ainI = NULL;
2254    if (alloc != 0) {
2255        pIn = dispatchTab.AllocationGetPointer((RsContext)con, (RsAllocation)alloc, 0,
2256                                               RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X, 0, 0,
2257                                               &strideIn, sizeof(size_t));
2258        /*
2259         * By definition stride is a roundup of xBytesSize with requiredAlignment, so requiredAlignment must
2260         * be strictly larger than the difference of (stride - xBytesSize).
2261         *
2262         * We can prove that as long as requiredAlignment satisfies the following two conditions, the
2263         * memory layout will be identical :
2264         * 1. Smaller or equal than stride;
2265         * 2. Larger than minRequiredAlignment.
2266         *
2267         * In this case we can simply choose the first power of 2 that satisfies both conditions.
2268         */
2269        size_t requiredAlignment = 16;
2270        size_t minRequiredAlignment = strideIn - xBytesSize;
2271        while (requiredAlignment <= minRequiredAlignment) {
2272            requiredAlignment <<= 1;
2273        }
2274        ainI = dispatchTabInc.AllocationCreateStrided((RsContext)incCon, (RsType)type,
2275                                                      RS_ALLOCATION_MIPMAP_NONE,
2276                                                      RS_ALLOCATION_USAGE_INCREMENTAL_SUPPORT | RS_ALLOCATION_USAGE_SHARED,
2277                                                      (uintptr_t)pIn, requiredAlignment);
2278    }
2279    return (jlong)(uintptr_t) ainI;
2280}
2281
2282static jobject
2283nAllocationGetByteBuffer(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jint xBytesSize, jint dimY, jint dimZ)
2284{
2285    LOG_API("nAllocationGetByteBuffer, con(%p), alloc(%p)", (RsContext)con, (RsAllocation)alloc);
2286    size_t strideIn = xBytesSize;
2287    void* ptr = NULL;
2288    if (alloc != 0 && dispatchTab.AllocationGetPointer != nullptr) {
2289        ptr = dispatchTab.AllocationGetPointer((RsContext)con, (RsAllocation)alloc, 0,
2290                                               RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X, dimZ, 0,
2291                                               &strideIn, sizeof(size_t));
2292    }
2293    if (ptr != NULL) {
2294        size_t bufferSize = strideIn;
2295        if (dimY > 0) {
2296            bufferSize *= dimY;
2297        }
2298        if (dimZ > 0) {
2299            bufferSize *= dimZ;
2300        }
2301        jobject byteBuffer = _env->NewDirectByteBuffer(ptr, (jlong) bufferSize);
2302        return byteBuffer;
2303    } else {
2304        return NULL;
2305    }
2306}
2307
2308static jlong
2309nAllocationGetStride(JNIEnv *_env, jobject _this, jlong con, jlong alloc)
2310{
2311    LOG_API("nAllocationGetStride, con(%p), alloc(%p)", (RsContext)con, (RsAllocation)alloc);
2312    size_t strideIn;
2313    void* ptr = NULL;
2314    if (alloc != 0 && dispatchTab.AllocationGetPointer != nullptr) {
2315        ptr = dispatchTab.AllocationGetPointer((RsContext)con, (RsAllocation)alloc, 0,
2316                                               RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X, 0, 0,
2317                                               &strideIn, sizeof(size_t));
2318    }
2319    return (jlong)strideIn;
2320}
2321
2322// ---------------------------------------------------------------------------
2323
2324
2325static const char *classPathName = "android/support/v8/renderscript/RenderScript";
2326
2327static JNINativeMethod methods[] = {
2328{"nLoadSO",                        "(ZILjava/lang/String;)Z",                 (bool*)nLoadSO },
2329{"nLoadIOSO",                      "()Z",                                     (bool*)nLoadIOSO },
2330{"nDeviceCreate",                  "()J",                                     (void*)nDeviceCreate },
2331{"nDeviceDestroy",                 "(J)V",                                    (void*)nDeviceDestroy },
2332{"nDeviceSetConfig",               "(JII)V",                                  (void*)nDeviceSetConfig },
2333{"nContextGetUserMessage",         "(J[I)I",                                  (void*)nContextGetUserMessage },
2334{"nContextGetErrorMessage",        "(J)Ljava/lang/String;",                   (void*)nContextGetErrorMessage },
2335{"nContextPeekMessage",            "(J[I)I",                                  (void*)nContextPeekMessage },
2336{"nContextInitToClient",           "(J)V",                                    (void*)nContextInitToClient },
2337{"nContextDeinitToClient",         "(J)V",                                    (void*)nContextDeinitToClient },
2338
2339
2340// All methods below are thread protected in java.
2341{"rsnContextCreate",                 "(JIIILjava/lang/String;)J",             (void*)nContextCreate },
2342{"rsnContextFinish",                 "(J)V",                                  (void*)nContextFinish },
2343{"rsnContextSetPriority",            "(JI)V",                                 (void*)nContextSetPriority },
2344{"rsnContextDestroy",                "(J)V",                                  (void*)nContextDestroy },
2345{"rsnContextDump",                   "(JI)V",                                 (void*)nContextDump },
2346{"rsnContextSendMessage",            "(JI[I)V",                               (void*)nContextSendMessage },
2347{"rsnClosureCreate",                 "(JJJ[J[J[I[J[J)J",                      (void*)nClosureCreate },
2348{"rsnInvokeClosureCreate",           "(JJ[B[J[J[I)J",                         (void*)nInvokeClosureCreate },
2349{"rsnClosureSetArg",                 "(JJIJI)V",                              (void*)nClosureSetArg },
2350{"rsnClosureSetGlobal",              "(JJJJI)V",                              (void*)nClosureSetGlobal },
2351{"rsnObjDestroy",                    "(JJ)V",                                 (void*)nObjDestroy },
2352
2353{"rsnElementCreate",                 "(JJIZI)J",                              (void*)nElementCreate },
2354{"rsnElementCreate2",                "(J[J[Ljava/lang/String;[I)J",           (void*)nElementCreate2 },
2355{"rsnElementGetSubElements",         "(JJ[J[Ljava/lang/String;[I)V",          (void*)nElementGetSubElements },
2356
2357{"rsnTypeCreate",                    "(JJIIIZZI)J",                           (void*)nTypeCreate },
2358
2359{"rsnAllocationCreateTyped",         "(JJIIJ)J",                              (void*)nAllocationCreateTyped },
2360{"rsnAllocationCreateFromBitmap",    "(JJILandroid/graphics/Bitmap;I)J",      (void*)nAllocationCreateFromBitmap },
2361{"rsnAllocationCreateBitmapBackedAllocation",    "(JJILandroid/graphics/Bitmap;I)J",      (void*)nAllocationCreateBitmapBackedAllocation },
2362{"rsnAllocationCubeCreateFromBitmap","(JJILandroid/graphics/Bitmap;I)J",      (void*)nAllocationCubeCreateFromBitmap },
2363
2364{"rsnAllocationCopyFromBitmap",      "(JJLandroid/graphics/Bitmap;)V",        (void*)nAllocationCopyFromBitmap },
2365{"rsnAllocationCopyToBitmap",        "(JJLandroid/graphics/Bitmap;)V",        (void*)nAllocationCopyToBitmap },
2366
2367{"rsnAllocationSyncAll",             "(JJI)V",                                (void*)nAllocationSyncAll },
2368{"rsnAllocationSetSurface",          "(JJLandroid/view/Surface;)V",           (void*)nAllocationSetSurface },
2369{"rsnAllocationIoSend",              "(JJ)V",                                 (void*)nAllocationIoSend },
2370{"rsnAllocationData1D",              "(JJIIILjava/lang/Object;IIIZ)V",        (void*)nAllocationData1D },
2371{"rsnAllocationElementData1D",       "(JJIII[BI)V",                           (void*)nAllocationElementData1D },
2372//{"rsnAllocationElementData",         "(JJIIIII[BI)V",                         (void*)nAllocationElementData },
2373{"rsnAllocationData2D",              "(JJIIIIIILjava/lang/Object;IIIZ)V",     (void*)nAllocationData2D },
2374{"rsnAllocationData2D",              "(JJIIIIIIJIIII)V",                      (void*)nAllocationData2D_alloc },
2375{"rsnAllocationData3D",              "(JJIIIIIIILjava/lang/Object;IIIZ)V",    (void*)nAllocationData3D },
2376{"rsnAllocationData3D",              "(JJIIIIIIIJIIII)V",                     (void*)nAllocationData3D_alloc },
2377{"rsnAllocationRead",                "(JJLjava/lang/Object;IIZ)V",            (void*)nAllocationRead },
2378{"rsnAllocationRead1D",              "(JJIIILjava/lang/Object;IIIZ)V",        (void*)nAllocationRead1D },
2379//{"rsnAllocationElementRead",         "(JJIIIII[BI)V",                         (void*)nAllocationElementRead },
2380{"rsnAllocationRead2D",              "(JJIIIIIILjava/lang/Object;IIIZ)V",     (void*)nAllocationRead2D },
2381//{"rsnAllocationRead3D",              "(JJIIIIIIILjava/lang/Object;IIIZ)V",  (void*)nAllocationRead3D },
2382{"rsnAllocationGetType",             "(JJ)J",                                 (void*)nAllocationGetType},
2383{"rsnAllocationResize1D",            "(JJI)V",                                (void*)nAllocationResize1D },
2384{"rsnAllocationGenerateMipmaps",     "(JJ)V",                                 (void*)nAllocationGenerateMipmaps },
2385
2386{"rsnScriptBindAllocation",          "(JJJIZ)V",                              (void*)nScriptBindAllocation },
2387{"rsnScriptSetTimeZone",             "(JJ[BZ)V",                              (void*)nScriptSetTimeZone },
2388{"rsnScriptInvoke",                  "(JJIZ)V",                               (void*)nScriptInvoke },
2389{"rsnScriptInvokeV",                 "(JJI[BZ)V",                             (void*)nScriptInvokeV },
2390{"rsnScriptForEach",                 "(JJJIJJZ)V",                            (void*)nScriptForEach },
2391{"rsnScriptForEach",                 "(JJJIJJ[BZ)V",                          (void*)nScriptForEachV },
2392{"rsnScriptForEach",                 "(JJI[JJ[B[I)V",                         (void*)nScriptForEachMulti },
2393{"rsnScriptForEachClipped",          "(JJJIJJIIIIIIZ)V",                      (void*)nScriptForEachClipped },
2394{"rsnScriptForEachClipped",          "(JJJIJJ[BIIIIIIZ)V",                    (void*)nScriptForEachClippedV },
2395{"rsnScriptReduce",                  "(JJIJJ[I)V",                            (void*)nScriptReduce },
2396{"rsnScriptReduceNew",               "(JJI[JJ[I)V",                           (void*)nScriptReduceNew },
2397{"rsnScriptSetVarI",                 "(JJIIZ)V",                              (void*)nScriptSetVarI },
2398{"rsnScriptSetVarJ",                 "(JJIJZ)V",                              (void*)nScriptSetVarJ },
2399{"rsnScriptSetVarF",                 "(JJIFZ)V",                              (void*)nScriptSetVarF },
2400{"rsnScriptSetVarD",                 "(JJIDZ)V",                              (void*)nScriptSetVarD },
2401{"rsnScriptSetVarV",                 "(JJI[BZ)V",                             (void*)nScriptSetVarV },
2402{"rsnScriptSetVarVE",                "(JJI[BJ[IZ)V",                          (void*)nScriptSetVarVE },
2403{"rsnScriptSetVarObj",               "(JJIJZ)V",                              (void*)nScriptSetVarObj },
2404
2405{"rsnScriptCCreate",                 "(JLjava/lang/String;Ljava/lang/String;[BI)J",  (void*)nScriptCCreate },
2406{"rsnScriptIntrinsicCreate",         "(JIJZ)J",                               (void*)nScriptIntrinsicCreate },
2407{"rsnScriptKernelIDCreate",          "(JJIIZ)J",                              (void*)nScriptKernelIDCreate },
2408{"rsnScriptInvokeIDCreate",          "(JJI)J",                                (void*)nScriptInvokeIDCreate },
2409{"rsnScriptFieldIDCreate",           "(JJIZ)J",                               (void*)nScriptFieldIDCreate },
2410{"rsnScriptGroupCreate",             "(J[J[J[J[J[J)J",                        (void*)nScriptGroupCreate },
2411{"rsnScriptGroup2Create",            "(JLjava/lang/String;Ljava/lang/String;[J)J", (void*)nScriptGroup2Create },
2412{"rsnScriptGroupSetInput",           "(JJJJ)V",                               (void*)nScriptGroupSetInput },
2413{"rsnScriptGroupSetOutput",          "(JJJJ)V",                               (void*)nScriptGroupSetOutput },
2414{"rsnScriptGroupExecute",            "(JJ)V",                                 (void*)nScriptGroupExecute },
2415{"rsnScriptGroup2Execute",           "(JJ)V",                                 (void*)nScriptGroup2Execute },
2416
2417{"rsnScriptIntrinsicBLAS_Single",    "(JJJIIIIIIIIIFJJFJIIIIZ)V",             (void*)nScriptIntrinsicBLAS_Single },
2418{"rsnScriptIntrinsicBLAS_Double",    "(JJJIIIIIIIIIDJJDJIIIIZ)V",             (void*)nScriptIntrinsicBLAS_Double },
2419{"rsnScriptIntrinsicBLAS_Complex",   "(JJJIIIIIIIIIFFJJFFJIIIIZ)V",           (void*)nScriptIntrinsicBLAS_Complex },
2420{"rsnScriptIntrinsicBLAS_Z",         "(JJJIIIIIIIIIDDJJDDJIIIIZ)V",           (void*)nScriptIntrinsicBLAS_Z },
2421
2422{"rsnScriptIntrinsicBLAS_BNNM",      "(JJJIIIJIJIJIIZ)V",                     (void*)nScriptIntrinsicBLAS_BNNM },
2423
2424{"rsnSamplerCreate",                 "(JIIIIIF)J",                            (void*)nSamplerCreate },
2425
2426{"rsnSystemGetPointerSize",          "()I",                                   (void*)nSystemGetPointerSize },
2427
2428// Entry points for Inc libRSSupport
2429{"nIncLoadSO",                       "(ILjava/lang/String;)Z",                (bool*)nIncLoadSO },
2430{"nIncDeviceCreate",                 "()J",                                   (void*)nIncDeviceCreate },
2431{"nIncDeviceDestroy",                "(J)V",                                  (void*)nIncDeviceDestroy },
2432{"rsnIncContextCreate",              "(JIII)J",                               (void*)nIncContextCreate },
2433{"rsnIncContextFinish",              "(J)V",                                  (void*)nIncContextFinish },
2434{"rsnIncContextDestroy",             "(J)V",                                  (void*)nIncContextDestroy },
2435{"rsnIncObjDestroy",                 "(JJ)V",                                 (void*)nIncObjDestroy },
2436{"rsnIncElementCreate",              "(JJIZI)J",                              (void*)nIncElementCreate },
2437{"rsnIncTypeCreate",                 "(JJIIIZZI)J",                           (void*)nIncTypeCreate },
2438{"rsnIncAllocationCreateTyped",      "(JJJJI)J",                              (void*)nIncAllocationCreateTyped },
2439{"rsnAllocationGetByteBuffer",       "(JJIII)Ljava/nio/ByteBuffer;",          (void*)nAllocationGetByteBuffer },
2440{"rsnAllocationGetStride",           "(JJ)J",                                 (void*)nAllocationGetStride },
2441};
2442
2443// ---------------------------------------------------------------------------
2444
2445jint JNI_OnLoad(JavaVM* vm, void* reserved)
2446{
2447    JNIEnv* env = NULL;
2448    jclass clazz = NULL;
2449    jint result = -1;
2450
2451    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
2452        //        __android_log_print(ANDROID_LOG_ERROR, LOG_TAG,
2453        //            "ERROR: GetEnv failed\n");
2454        goto bail;
2455    }
2456    if (env == NULL) {
2457        //        __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "ERROR: env == NULL");
2458        goto bail;
2459    }
2460
2461    clazz = env->FindClass(classPathName);
2462    if (clazz == NULL) {
2463        goto bail;
2464    }
2465
2466    if (env->RegisterNatives(clazz, methods, NELEM(methods)) < 0) {
2467        //        __android_log_print(ANDROID_LOG_ERROR, LOG_TAG,
2468        //            "ERROR: MediaPlayer native registration failed\n");
2469        goto bail;
2470    }
2471
2472    /* success -- return valid version number */
2473    result = JNI_VERSION_1_4;
2474
2475bail:
2476    return result;
2477}
2478