android_renderscript_RenderScript.cpp revision 6d26e4f14a1874eb247542d98bb1554405e50377
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
34#define NELEM(m) (sizeof(m) / sizeof((m)[0]))
35
36template <typename... T>
37void UNUSED(T... t) {}
38#define PER_ARRAY_TYPE(flag, fnc, readonly, ...) {                                      \
39    jint len = 0;                                                                       \
40    void *ptr = nullptr;                                                                \
41    void *srcPtr = nullptr;                                                             \
42    size_t typeBytes = 0;                                                               \
43    jint relFlag = 0;                                                                   \
44    if (readonly) {                                                                     \
45        /* The on-release mode should only be JNI_ABORT for read-only accesses. */      \
46        /* readonly = true, also indicates we are copying to the allocation   . */      \
47        relFlag = JNI_ABORT;                                                            \
48    }                                                                                   \
49    switch(dataType) {                                                                  \
50    case RS_TYPE_FLOAT_32:                                                              \
51        len = _env->GetArrayLength((jfloatArray)data);                                  \
52        ptr = _env->GetFloatArrayElements((jfloatArray)data, flag);                     \
53        typeBytes = 4;                                                                  \
54        if (usePadding) {                                                               \
55            srcPtr = ptr;                                                               \
56            len = len / 3 * 4;                                                          \
57            if (count == 0) {                                                           \
58                count = len / 4;                                                        \
59            }                                                                           \
60            ptr = malloc (len * typeBytes);                                             \
61            if (readonly) {                                                             \
62                copyWithPadding(ptr, srcPtr, mSize, count);                             \
63                fnc(__VA_ARGS__);                                                       \
64            } else {                                                                    \
65                fnc(__VA_ARGS__);                                                       \
66                copyWithUnPadding(srcPtr, ptr, mSize, count);                           \
67            }                                                                           \
68            free(ptr);                                                                  \
69            ptr = srcPtr;                                                               \
70        } else {                                                                        \
71            fnc(__VA_ARGS__);                                                           \
72        }                                                                               \
73        _env->ReleaseFloatArrayElements((jfloatArray)data, (jfloat *)ptr, relFlag);     \
74        return;                                                                         \
75    case RS_TYPE_FLOAT_64:                                                              \
76        len = _env->GetArrayLength((jdoubleArray)data);                                 \
77        ptr = _env->GetDoubleArrayElements((jdoubleArray)data, flag);                   \
78        typeBytes = 8;                                                                  \
79        if (usePadding) {                                                               \
80            srcPtr = ptr;                                                               \
81            len = len / 3 * 4;                                                          \
82            if (count == 0) {                                                           \
83                count = len / 4;                                                        \
84            }                                                                           \
85            ptr = malloc (len * typeBytes);                                             \
86            if (readonly) {                                                             \
87                copyWithPadding(ptr, srcPtr, mSize, count);                             \
88                fnc(__VA_ARGS__);                                                       \
89            } else {                                                                    \
90                fnc(__VA_ARGS__);                                                       \
91                copyWithUnPadding(srcPtr, ptr, mSize, count);                           \
92            }                                                                           \
93            free(ptr);                                                                  \
94            ptr = srcPtr;                                                               \
95        } else {                                                                        \
96            fnc(__VA_ARGS__);                                                           \
97        }                                                                               \
98        _env->ReleaseDoubleArrayElements((jdoubleArray)data, (jdouble *)ptr, relFlag);  \
99        return;                                                                         \
100    case RS_TYPE_SIGNED_8:                                                              \
101    case RS_TYPE_UNSIGNED_8:                                                            \
102        len = _env->GetArrayLength((jbyteArray)data);                                   \
103        ptr = _env->GetByteArrayElements((jbyteArray)data, flag);                       \
104        typeBytes = 1;                                                                  \
105        if (usePadding) {                                                               \
106            srcPtr = ptr;                                                               \
107            len = len / 3 * 4;                                                          \
108            if (count == 0) {                                                           \
109                count = len / 4;                                                        \
110            }                                                                           \
111            ptr = malloc (len * typeBytes);                                             \
112            if (readonly) {                                                             \
113                copyWithPadding(ptr, srcPtr, mSize, count);                             \
114                fnc(__VA_ARGS__);                                                       \
115            } else {                                                                    \
116                fnc(__VA_ARGS__);                                                       \
117                copyWithUnPadding(srcPtr, ptr, mSize, count);                           \
118            }                                                                           \
119            free(ptr);                                                                  \
120            ptr = srcPtr;                                                               \
121        } else {                                                                        \
122            fnc(__VA_ARGS__);                                                           \
123        }                                                                               \
124        _env->ReleaseByteArrayElements((jbyteArray)data, (jbyte*)ptr, relFlag);         \
125        return;                                                                         \
126    case RS_TYPE_SIGNED_16:                                                             \
127    case RS_TYPE_UNSIGNED_16:                                                           \
128        len = _env->GetArrayLength((jshortArray)data);                                  \
129        ptr = _env->GetShortArrayElements((jshortArray)data, flag);                     \
130        typeBytes = 2;                                                                  \
131        if (usePadding) {                                                               \
132            srcPtr = ptr;                                                               \
133            len = len / 3 * 4;                                                          \
134            if (count == 0) {                                                           \
135                count = len / 4;                                                        \
136            }                                                                           \
137            ptr = malloc (len * typeBytes);                                             \
138            if (readonly) {                                                             \
139                copyWithPadding(ptr, srcPtr, mSize, count);                             \
140                fnc(__VA_ARGS__);                                                       \
141            } else {                                                                    \
142                fnc(__VA_ARGS__);                                                       \
143                copyWithUnPadding(srcPtr, ptr, mSize, count);                           \
144            }                                                                           \
145            free(ptr);                                                                  \
146            ptr = srcPtr;                                                               \
147        } else {                                                                        \
148            fnc(__VA_ARGS__);                                                           \
149        }                                                                               \
150        _env->ReleaseShortArrayElements((jshortArray)data, (jshort *)ptr, relFlag);     \
151        return;                                                                         \
152    case RS_TYPE_SIGNED_32:                                                             \
153    case RS_TYPE_UNSIGNED_32:                                                           \
154        len = _env->GetArrayLength((jintArray)data);                                    \
155        ptr = _env->GetIntArrayElements((jintArray)data, flag);                         \
156        typeBytes = 4;                                                                  \
157        if (usePadding) {                                                               \
158            srcPtr = ptr;                                                               \
159            len = len / 3 * 4;                                                          \
160            if (count == 0) {                                                           \
161                count = len / 4;                                                        \
162            }                                                                           \
163            ptr = malloc (len * typeBytes);                                             \
164            if (readonly) {                                                             \
165                copyWithPadding(ptr, srcPtr, mSize, count);                             \
166                fnc(__VA_ARGS__);                                                       \
167            } else {                                                                    \
168                fnc(__VA_ARGS__);                                                       \
169                copyWithUnPadding(srcPtr, ptr, mSize, count);                           \
170            }                                                                           \
171            free(ptr);                                                                  \
172            ptr = srcPtr;                                                               \
173        } else {                                                                        \
174            fnc(__VA_ARGS__);                                                           \
175        }                                                                               \
176        _env->ReleaseIntArrayElements((jintArray)data, (jint *)ptr, relFlag);           \
177        return;                                                                         \
178    case RS_TYPE_SIGNED_64:                                                             \
179    case RS_TYPE_UNSIGNED_64:                                                           \
180        len = _env->GetArrayLength((jlongArray)data);                                   \
181        ptr = _env->GetLongArrayElements((jlongArray)data, flag);                       \
182        typeBytes = 8;                                                                  \
183        if (usePadding) {                                                               \
184            srcPtr = ptr;                                                               \
185            len = len / 3 * 4;                                                          \
186            if (count == 0) {                                                           \
187                count = len / 4;                                                        \
188            }                                                                           \
189            ptr = malloc (len * typeBytes);                                             \
190            if (readonly) {                                                             \
191                copyWithPadding(ptr, srcPtr, mSize, count);                             \
192                fnc(__VA_ARGS__);                                                       \
193            } else {                                                                    \
194                fnc(__VA_ARGS__);                                                       \
195                copyWithUnPadding(srcPtr, ptr, mSize, count);                           \
196            }                                                                           \
197            free(ptr);                                                                  \
198            ptr = srcPtr;                                                               \
199        } else {                                                                        \
200            fnc(__VA_ARGS__);                                                           \
201        }                                                                               \
202        _env->ReleaseLongArrayElements((jlongArray)data, (jlong *)ptr, relFlag);        \
203        return;                                                                         \
204    default:                                                                            \
205        break;                                                                          \
206    }                                                                                   \
207    UNUSED(len, ptr, srcPtr, typeBytes, relFlag);                                       \
208}
209
210
211class AutoJavaStringToUTF8 {
212public:
213    AutoJavaStringToUTF8(JNIEnv* env, jstring str) : fEnv(env), fJStr(str) {
214        fCStr = env->GetStringUTFChars(str, NULL);
215        fLength = env->GetStringUTFLength(str);
216    }
217    ~AutoJavaStringToUTF8() {
218        fEnv->ReleaseStringUTFChars(fJStr, fCStr);
219    }
220    const char* c_str() const { return fCStr; }
221    jsize length() const { return fLength; }
222
223private:
224    JNIEnv*     fEnv;
225    jstring     fJStr;
226    const char* fCStr;
227    jsize       fLength;
228};
229
230class AutoJavaStringArrayToUTF8 {
231public:
232    AutoJavaStringArrayToUTF8(JNIEnv* env, jobjectArray strings, jsize stringsLength)
233    : mEnv(env), mStrings(strings), mStringsLength(stringsLength) {
234        mCStrings = NULL;
235        mSizeArray = NULL;
236        if (stringsLength > 0) {
237            mCStrings = (const char **)calloc(stringsLength, sizeof(char *));
238            mSizeArray = (size_t*)calloc(stringsLength, sizeof(size_t));
239            for (jsize ct = 0; ct < stringsLength; ct ++) {
240                jstring s = (jstring)mEnv->GetObjectArrayElement(mStrings, ct);
241                mCStrings[ct] = mEnv->GetStringUTFChars(s, NULL);
242                mSizeArray[ct] = mEnv->GetStringUTFLength(s);
243            }
244        }
245    }
246    ~AutoJavaStringArrayToUTF8() {
247        for (jsize ct=0; ct < mStringsLength; ct++) {
248            jstring s = (jstring)mEnv->GetObjectArrayElement(mStrings, ct);
249            mEnv->ReleaseStringUTFChars(s, mCStrings[ct]);
250        }
251        free(mCStrings);
252        free(mSizeArray);
253    }
254    const char **c_str() const { return mCStrings; }
255    size_t *c_str_len() const { return mSizeArray; }
256    jsize length() const { return mStringsLength; }
257
258private:
259    JNIEnv      *mEnv;
260    jobjectArray mStrings;
261    const char **mCStrings;
262    size_t      *mSizeArray;
263    jsize        mStringsLength;
264};
265
266
267// ---------------------------------------------------------------------------
268static dispatchTable dispatchTab;
269// Incremental Support lib
270static dispatchTable dispatchTabInc;
271
272static jboolean nLoadSO(JNIEnv *_env, jobject _this, jboolean useNative, jint deviceApi) {
273    void* handle = NULL;
274    if (useNative) {
275        handle = dlopen("libRS.so", RTLD_LAZY | RTLD_LOCAL);
276    } else {
277        handle = dlopen("libRSSupport.so", RTLD_LAZY | RTLD_LOCAL);
278    }
279    if (handle == NULL) {
280        LOG_API("couldn't dlopen %s, %s", filename, dlerror());
281        return false;
282    }
283
284    if (loadSymbols(handle, dispatchTab, deviceApi) == false) {
285        LOG_API("%s init failed!", filename);
286        return false;
287    }
288    LOG_API("Successfully loaded %s", filename);
289    return true;
290}
291
292static ioSuppDT ioDispatch;
293static jboolean nLoadIOSO(JNIEnv *_env, jobject _this) {
294    void* handleIO = NULL;
295    handleIO = dlopen("libRSSupportIO.so", RTLD_LAZY | RTLD_LOCAL);
296    if (handleIO == NULL) {
297        LOG_API("Couldn't load libRSSupportIO.so");
298        return false;
299    }
300    if (loadIOSuppSyms(handleIO, ioDispatch) == false) {
301        LOG_API("libRSSupportIO init failed!");
302        return false;
303    }
304    return true;
305}
306
307// ---------------------------------------------------------------------------
308
309static void copyWithPadding(void* ptr, void* srcPtr, int mSize, int count) {
310    int sizeBytesPad = mSize * 4;
311    int sizeBytes = mSize * 3;
312    uint8_t *dst = static_cast<uint8_t *>(ptr);
313    uint8_t *src = static_cast<uint8_t *>(srcPtr);
314    for (int i = 0; i < count; i++) {
315        memcpy(dst, src, sizeBytes);
316        dst += sizeBytesPad;
317        src += sizeBytes;
318    }
319}
320
321static void copyWithUnPadding(void* ptr, void* srcPtr, int mSize, int count) {
322    int sizeBytesPad = mSize * 4;
323    int sizeBytes = mSize * 3;
324    uint8_t *dst = static_cast<uint8_t *>(ptr);
325    uint8_t *src = static_cast<uint8_t *>(srcPtr);
326    for (int i = 0; i < count; i++) {
327        memcpy(dst, src, sizeBytes);
328        dst += sizeBytes;
329        src += sizeBytesPad;
330    }
331}
332
333
334// ---------------------------------------------------------------------------
335
336static void
337nContextFinish(JNIEnv *_env, jobject _this, jlong con)
338{
339    LOG_API("nContextFinish, con(%p)", (RsContext)con);
340    dispatchTab.ContextFinish((RsContext)con);
341}
342
343static jlong
344nClosureCreate(JNIEnv *_env, jobject _this, jlong con, jlong kernelID,
345               jlong returnValue, jlongArray fieldIDArray,
346               jlongArray valueArray, jintArray sizeArray,
347               jlongArray depClosureArray, jlongArray depFieldIDArray) {
348  jlong ret = 0;
349
350  jlong* jFieldIDs = _env->GetLongArrayElements(fieldIDArray, nullptr);
351  jsize fieldIDs_length = _env->GetArrayLength(fieldIDArray);
352  jlong* jValues = _env->GetLongArrayElements(valueArray, nullptr);
353  jsize values_length = _env->GetArrayLength(valueArray);
354  jint* jSizes = _env->GetIntArrayElements(sizeArray, nullptr);
355  jsize sizes_length = _env->GetArrayLength(sizeArray);
356  jlong* jDepClosures =
357      _env->GetLongArrayElements(depClosureArray, nullptr);
358  jsize depClosures_length = _env->GetArrayLength(depClosureArray);
359  jlong* jDepFieldIDs =
360      _env->GetLongArrayElements(depFieldIDArray, nullptr);
361  jsize depFieldIDs_length = _env->GetArrayLength(depFieldIDArray);
362
363  size_t numValues, numDependencies;
364  RsScriptFieldID* fieldIDs;
365  uintptr_t* values;
366  RsClosure* depClosures;
367  RsScriptFieldID* depFieldIDs;
368
369  if (fieldIDs_length != values_length || values_length != sizes_length) {
370      LOG_API("Unmatched field IDs, values, and sizes in closure creation.");
371      goto exit;
372  }
373
374  numValues = (size_t)fieldIDs_length;
375
376  if (depClosures_length != depFieldIDs_length) {
377      LOG_API("Unmatched closures and field IDs for dependencies in closure creation.");
378      goto exit;
379  }
380
381  numDependencies = (size_t)depClosures_length;
382
383  if (numDependencies > numValues) {
384      LOG_API("Unexpected number of dependencies in closure creation");
385      goto exit;
386  }
387
388  if (numValues > RS_CLOSURE_MAX_NUMBER_ARGS_AND_BINDINGS) {
389      LOG_API("Too many arguments or globals in closure creation");
390      goto exit;
391  }
392
393  fieldIDs = (RsScriptFieldID*)alloca(sizeof(RsScriptFieldID) * numValues);
394  if (fieldIDs == nullptr) {
395      goto exit;
396  }
397
398  for (size_t i = 0; i < numValues; i++) {
399    fieldIDs[i] = (RsScriptFieldID)jFieldIDs[i];
400  }
401
402  values = (uintptr_t*)alloca(sizeof(uintptr_t) * numValues);
403  if (values == nullptr) {
404      goto exit;
405  }
406
407  for (size_t i = 0; i < numValues; i++) {
408    values[i] = (uintptr_t)jValues[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, values, 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  uintptr_t* values;
465
466  if (fieldIDs_length != values_length || values_length != sizes_length) {
467      LOG_API("Unmatched field IDs, values, and sizes in closure creation.");
468      goto exit;
469  }
470
471  numValues = (size_t) fieldIDs_length;
472
473  if (numValues > RS_CLOSURE_MAX_NUMBER_ARGS_AND_BINDINGS) {
474      LOG_API("Too many arguments or globals in closure creation");
475      goto exit;
476  }
477
478  fieldIDs = (RsScriptFieldID*)alloca(sizeof(RsScriptFieldID) * numValues);
479  if (fieldIDs == nullptr) {
480      goto exit;
481  }
482
483  for (size_t i = 0; i < numValues; i++) {
484    fieldIDs[i] = (RsScriptFieldID)jFieldIDs[i];
485  }
486
487  values = (uintptr_t*)alloca(sizeof(uintptr_t) * numValues);
488  if (values == nullptr) {
489      goto exit;
490  }
491
492  for (size_t i = 0; i < numValues; i++) {
493    values[i] = (uintptr_t)jValues[i];
494  }
495
496  ret = (jlong)(uintptr_t)dispatchTab.InvokeClosureCreate(
497      (RsContext)con, (RsScriptInvokeID)invokeID, jParams, jParamLength,
498      fieldIDs, numValues, values, numValues,
499      (int*)jSizes, numValues);
500
501exit:
502
503  _env->ReleaseIntArrayElements (sizeArray,       jSizes,       JNI_ABORT);
504  _env->ReleaseLongArrayElements(valueArray,      jValues,      JNI_ABORT);
505  _env->ReleaseLongArrayElements(fieldIDArray,    jFieldIDs,    JNI_ABORT);
506  _env->ReleaseByteArrayElements(paramArray,      jParams,      JNI_ABORT);
507
508  return ret;
509}
510
511static void
512nClosureSetArg(JNIEnv *_env, jobject _this, jlong con, jlong closureID,
513               jint index, jlong value, jint size) {
514  dispatchTab.ClosureSetArg((RsContext)con, (RsClosure)closureID, (uint32_t)index,
515                  (uintptr_t)value, (size_t)size);
516}
517
518static void
519nClosureSetGlobal(JNIEnv *_env, jobject _this, jlong con, jlong closureID,
520                  jlong fieldID, jlong value, jint size) {
521  dispatchTab.ClosureSetGlobal((RsContext)con, (RsClosure)closureID,
522                     (RsScriptFieldID)fieldID, (uintptr_t)value, (size_t)size);
523}
524
525static long
526nScriptGroup2Create(JNIEnv *_env, jobject _this, jlong con, jstring name,
527                    jstring cacheDir, jlongArray closureArray) {
528  jlong ret = 0;
529
530  AutoJavaStringToUTF8 nameUTF(_env, name);
531  AutoJavaStringToUTF8 cacheDirUTF(_env, cacheDir);
532
533  jlong* jClosures = _env->GetLongArrayElements(closureArray, nullptr);
534  jsize numClosures = _env->GetArrayLength(closureArray);
535
536  RsClosure* closures;
537
538  if (numClosures > (jsize) RS_SCRIPT_GROUP_MAX_NUMBER_CLOSURES) {
539    LOG_API("Too many closures in script group");
540    goto exit;
541  }
542
543  closures = (RsClosure*)alloca(sizeof(RsClosure) * numClosures);
544  if (closures == nullptr) {
545      goto exit;
546  }
547
548  for (int i = 0; i < numClosures; i++) {
549    closures[i] = (RsClosure)jClosures[i];
550  }
551
552  ret = (jlong)(uintptr_t)dispatchTab.ScriptGroup2Create(
553      (RsContext)con, nameUTF.c_str(), nameUTF.length(),
554      cacheDirUTF.c_str(), cacheDirUTF.length(),
555      closures, numClosures);
556
557exit:
558
559  _env->ReleaseLongArrayElements(closureArray, jClosures, JNI_ABORT);
560
561  return ret;
562}
563
564static void
565nScriptGroup2Execute(JNIEnv *_env, jobject _this, jlong con, jlong groupID) {
566  dispatchTab.ScriptGroupExecute((RsContext)con, (RsScriptGroup2)groupID);
567}
568
569static void
570nObjDestroy(JNIEnv *_env, jobject _this, jlong con, jlong obj)
571{
572    LOG_API("nObjDestroy, con(%p) obj(%p)", (RsContext)con, (void *)obj);
573    dispatchTab.ObjDestroy((RsContext)con, (void *)obj);
574}
575
576// ---------------------------------------------------------------------------
577static jlong
578nDeviceCreate(JNIEnv *_env, jobject _this)
579{
580    LOG_API("nDeviceCreate");
581    return (jlong)(uintptr_t)dispatchTab.DeviceCreate();
582}
583
584static void
585nDeviceDestroy(JNIEnv *_env, jobject _this, jlong dev)
586{
587    LOG_API("nDeviceDestroy");
588    return dispatchTab.DeviceDestroy((RsDevice)dev);
589}
590
591static void
592nDeviceSetConfig(JNIEnv *_env, jobject _this, jlong dev, jint p, jint value)
593{
594    LOG_API("nDeviceSetConfig  dev(%p), param(%i), value(%i)", (void *)dev, p, value);
595    return dispatchTab.DeviceSetConfig((RsDevice)dev, (RsDeviceParam)p, value);
596}
597
598static jlong
599nContextCreate(JNIEnv *_env, jobject _this, jlong dev, jint ver, jint sdkVer,
600               jint ct, jstring nativeLibDirJava)
601{
602    LOG_API("nContextCreate");
603    // Access the NativeLibDir in the Java Context.
604    const char * nativeLibDir = _env->GetStringUTFChars(nativeLibDirJava, JNI_FALSE);
605    size_t length = (size_t)_env->GetStringUTFLength(nativeLibDirJava);
606
607    jlong id = (jlong)(uintptr_t)dispatchTab.ContextCreate((RsDevice)dev, ver,
608                                                           sdkVer,
609                                                           (RsContextType)ct, 0);
610    if (dispatchTab.SetNativeLibDir) {
611        dispatchTab.SetNativeLibDir((RsContext)id, nativeLibDir, length);
612    }
613
614    _env->ReleaseStringUTFChars(nativeLibDirJava, nativeLibDir);
615    return id;
616}
617
618
619static void
620nContextSetPriority(JNIEnv *_env, jobject _this, jlong con, jint p)
621{
622    LOG_API("ContextSetPriority, con(%p), priority(%i)", (RsContext)con, p);
623    dispatchTab.ContextSetPriority((RsContext)con, p);
624}
625
626
627
628static void
629nContextDestroy(JNIEnv *_env, jobject _this, jlong con)
630{
631    LOG_API("nContextDestroy, con(%p)", (RsContext)con);
632    dispatchTab.ContextDestroy((RsContext)con);
633}
634
635static void
636nContextDump(JNIEnv *_env, jobject _this, jlong con, jint bits)
637{
638    LOG_API("nContextDump, con(%p)  bits(%i)", (RsContext)con, bits);
639    dispatchTab.ContextDump((RsContext)con, bits);
640}
641
642
643static jstring
644nContextGetErrorMessage(JNIEnv *_env, jobject _this, jlong con)
645{
646    LOG_API("nContextGetErrorMessage, con(%p)", (RsContext)con);
647    char buf[1024];
648
649    size_t receiveLen;
650    uint32_t subID;
651    int id = dispatchTab.ContextGetMessage((RsContext)con,
652                                           buf, sizeof(buf),
653                                           &receiveLen, sizeof(receiveLen),
654                                           &subID, sizeof(subID));
655    if (!id && receiveLen) {
656        //        __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG,
657        //            "message receive buffer too small.  %zu", receiveLen);
658    }
659    return _env->NewStringUTF(buf);
660}
661
662static jint
663nContextGetUserMessage(JNIEnv *_env, jobject _this, jlong con, jintArray data)
664{
665    jint len = _env->GetArrayLength(data);
666    LOG_API("nContextGetMessage, con(%p), len(%i)", (RsContext)con, len);
667    jint *ptr = _env->GetIntArrayElements(data, NULL);
668    size_t receiveLen;
669    uint32_t subID;
670    int id = dispatchTab.ContextGetMessage((RsContext)con,
671                                           ptr, len * 4,
672                                           &receiveLen, sizeof(receiveLen),
673                                           &subID, sizeof(subID));
674    if (!id && receiveLen) {
675        //        __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG,
676        //            "message receive buffer too small.  %zu", receiveLen);
677    }
678    _env->ReleaseIntArrayElements(data, ptr, 0);
679    return (jint)id;
680}
681
682static jint
683nContextPeekMessage(JNIEnv *_env, jobject _this, jlong con, jintArray auxData)
684{
685    LOG_API("nContextPeekMessage, con(%p)", (RsContext)con);
686    jint *auxDataPtr = _env->GetIntArrayElements(auxData, NULL);
687    size_t receiveLen;
688    uint32_t subID;
689    int id = dispatchTab.ContextPeekMessage((RsContext)con, &receiveLen, sizeof(receiveLen),
690                                  &subID, sizeof(subID));
691    auxDataPtr[0] = (jint)subID;
692    auxDataPtr[1] = (jint)receiveLen;
693    _env->ReleaseIntArrayElements(auxData, auxDataPtr, 0);
694    return (jint)id;
695}
696
697static void nContextInitToClient(JNIEnv *_env, jobject _this, jlong con)
698{
699    LOG_API("nContextInitToClient, con(%p)", (RsContext)con);
700    dispatchTab.ContextInitToClient((RsContext)con);
701}
702
703static void nContextDeinitToClient(JNIEnv *_env, jobject _this, jlong con)
704{
705    LOG_API("nContextDeinitToClient, con(%p)", (RsContext)con);
706    dispatchTab.ContextDeinitToClient((RsContext)con);
707}
708
709static void
710nContextSendMessage(JNIEnv *_env, jobject _this, jlong con, jint id, jintArray data)
711{
712    jint *ptr = NULL;
713    jint len = 0;
714    if (data) {
715        len = _env->GetArrayLength(data);
716        jint *ptr = _env->GetIntArrayElements(data, NULL);
717    }
718    LOG_API("nContextSendMessage, con(%p), id(%i), len(%i)", (RsContext)con, id, len);
719    dispatchTab.ContextSendMessage((RsContext)con, id, (const uint8_t *)ptr, len * sizeof(int));
720    if (data) {
721        _env->ReleaseIntArrayElements(data, ptr, JNI_ABORT);
722    }
723}
724
725
726
727static jlong
728nElementCreate(JNIEnv *_env, jobject _this, jlong con, jlong type, jint kind,
729               jboolean norm, jint size)
730{
731    LOG_API("nElementCreate, con(%p), type(%i), kind(%i), norm(%i), size(%i)", (RsContext)con,
732            type, kind, norm, size);
733    return (jlong)(uintptr_t)dispatchTab.ElementCreate((RsContext)con,
734                                                       (RsDataType)type,
735                                                       (RsDataKind)kind,
736                                                       norm, size);
737}
738
739static jlong
740nElementCreate2(JNIEnv *_env, jobject _this, jlong con,
741                jlongArray _ids, jobjectArray _names, jintArray _arraySizes)
742{
743    int fieldCount = _env->GetArrayLength(_ids);
744    LOG_API("nElementCreate2, con(%p)", (RsContext)con);
745
746    jlong *jIds = _env->GetLongArrayElements(_ids, NULL);
747    jint *jArraySizes = _env->GetIntArrayElements(_arraySizes, NULL);
748
749    RsElement *ids = (RsElement*)malloc(fieldCount * sizeof(RsElement));
750    uint32_t *arraySizes = (uint32_t *)malloc(fieldCount * sizeof(uint32_t));
751
752    for(int i = 0; i < fieldCount; i ++) {
753        ids[i] = (RsElement)jIds[i];
754        arraySizes[i] = (uint32_t)jArraySizes[i];
755    }
756
757    AutoJavaStringArrayToUTF8 names(_env, _names, fieldCount);
758
759    const char **nameArray = names.c_str();
760    size_t *sizeArray = names.c_str_len();
761
762    jlong id = (jlong)(uintptr_t)dispatchTab.ElementCreate2((RsContext)con, (RsElement *)ids,
763                                                            fieldCount, nameArray,
764                                                            fieldCount * sizeof(size_t),  sizeArray,
765                                                            (const uint32_t *)arraySizes, fieldCount);
766
767    free(ids);
768    free(arraySizes);
769    _env->ReleaseLongArrayElements(_ids, jIds, JNI_ABORT);
770    _env->ReleaseIntArrayElements(_arraySizes, jArraySizes, JNI_ABORT);
771    return id;
772}
773
774
775
776
777static void
778nElementGetSubElements(JNIEnv *_env, jobject _this, jlong con, jlong id,
779                       jlongArray _IDs,
780                       jobjectArray _names,
781                       jintArray _arraySizes)
782{
783    uint32_t dataSize = _env->GetArrayLength(_IDs);
784    LOG_API("nElementGetSubElements, con(%p)", (RsContext)con);
785
786    uintptr_t *ids = (uintptr_t *)malloc(dataSize * sizeof(uintptr_t));
787    const char **names = (const char **)malloc((uint32_t)dataSize * sizeof(const char *));
788    uint32_t *arraySizes = (uint32_t *)malloc((uint32_t)dataSize * sizeof(uint32_t));
789
790    dispatchTab.ElementGetSubElements((RsContext)con, (RsElement)id, ids, names, arraySizes,
791                                      (uint32_t)dataSize);
792
793    for(uint32_t i = 0; i < dataSize; i++) {
794        const jlong id = (jlong)(uintptr_t)ids[i];
795        const jint arraySize = (jint)arraySizes[i];
796        _env->SetObjectArrayElement(_names, i, _env->NewStringUTF(names[i]));
797        _env->SetLongArrayRegion(_IDs, i, 1, &id);
798        _env->SetIntArrayRegion(_arraySizes, i, 1, &arraySize);
799    }
800
801    free(ids);
802    free(names);
803    free(arraySizes);
804}
805
806// -----------------------------------
807
808static jlong
809nTypeCreate(JNIEnv *_env, jobject _this, jlong con, jlong eid,
810            jint dimx, jint dimy, jint dimz, jboolean mips, jboolean faces, jint yuv)
811{
812    LOG_API("nTypeCreate, con(%p) eid(%p), x(%i), y(%i), z(%i), mips(%i), faces(%i), yuv(%i)",
813            (RsContext)con, eid, dimx, dimy, dimz, mips, faces, yuv);
814
815    return (jlong)(uintptr_t)dispatchTab.TypeCreate((RsContext)con, (RsElement)eid, dimx, dimy,
816                                                    dimz, mips, faces, yuv);
817}
818
819// -----------------------------------
820
821static jlong
822nAllocationCreateTyped(JNIEnv *_env, jobject _this, jlong con, jlong type, jint mips, jint usage,
823                       jlong pointer)
824{
825    LOG_API("nAllocationCreateTyped, con(%p), type(%p), mip(%i), usage(%i), ptr(%p)",
826            (RsContext)con, (RsElement)type, mips, usage, (void *)pointer);
827    return (jlong)(uintptr_t) dispatchTab.AllocationCreateTyped((RsContext)con, (RsType)type,
828                                                                (RsAllocationMipmapControl)mips,
829                                                                (uint32_t)usage, (uintptr_t)pointer);
830}
831
832static void
833nAllocationSyncAll(JNIEnv *_env, jobject _this, jlong con, jlong a, jint bits)
834{
835    LOG_API("nAllocationSyncAll, con(%p), a(%p), bits(0x%08x)", (RsContext)con, (RsAllocation)a, bits);
836    dispatchTab.AllocationSyncAll((RsContext)con, (RsAllocation)a, (RsAllocationUsageType)bits);
837}
838
839static void
840nAllocationSetSurface(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jobject sur)
841{
842    ioDispatch.sAllocationSetSurface(_env, _this, (RsContext)con, (RsAllocation)alloc, sur, dispatchTab);
843}
844
845static void
846nAllocationIoSend(JNIEnv *_env, jobject _this, jlong con, jlong alloc)
847{
848    dispatchTab.AllocationIoSend((RsContext)con, (RsAllocation)alloc);
849}
850
851static void
852nAllocationGenerateMipmaps(JNIEnv *_env, jobject _this, jlong con, jlong alloc)
853{
854    LOG_API("nAllocationGenerateMipmaps, con(%p), a(%p)", (RsContext)con, (RsAllocation)alloc);
855    dispatchTab.AllocationGenerateMipmaps((RsContext)con, (RsAllocation)alloc);
856}
857
858static size_t GetBitmapSize(JNIEnv *env, jobject jbitmap) {
859    AndroidBitmapInfo info;
860    memset(&info, 0, sizeof(info));
861    AndroidBitmap_getInfo(env, jbitmap, &info);
862    size_t s = info.width * info.height;
863    switch (info.format) {
864        case ANDROID_BITMAP_FORMAT_RGBA_8888: s *= 4; break;
865        case ANDROID_BITMAP_FORMAT_RGB_565: s *= 2; break;
866        case ANDROID_BITMAP_FORMAT_RGBA_4444: s *= 2; break;
867    }
868    return s;
869}
870
871static jlong
872nAllocationCreateFromBitmap(JNIEnv *_env, jobject _this, jlong con, jlong type, jint mip,
873                            jobject jbitmap, jint usage)
874{
875    jlong id = 0;
876    void *pixels = NULL;
877    AndroidBitmap_lockPixels(_env, jbitmap, &pixels);
878
879    if (pixels != NULL) {
880        id = (jlong)(uintptr_t)dispatchTab.AllocationCreateFromBitmap((RsContext)con,
881                                                                      (RsType)type,
882                                                                      (RsAllocationMipmapControl)mip,
883                                                                      pixels,
884                                                                      GetBitmapSize(_env, jbitmap),
885                                                                      usage);
886        AndroidBitmap_unlockPixels(_env, jbitmap);
887    }
888    return id;
889}
890
891static jlong
892nAllocationCreateBitmapBackedAllocation(JNIEnv *_env, jobject _this, jlong con, jlong type,
893                                        jint mip, jobject jbitmap, jint usage)
894{
895    jlong id = 0;
896    void *pixels = NULL;
897    AndroidBitmap_lockPixels(_env, jbitmap, &pixels);
898
899    if (pixels != NULL) {
900        id = (jlong)(uintptr_t)dispatchTab.AllocationCreateTyped((RsContext)con,
901                                                                 (RsType)type,
902                                                                 (RsAllocationMipmapControl)mip,
903                                                                 (uint32_t)usage,
904                                                                 (uintptr_t)pixels);
905        AndroidBitmap_unlockPixels(_env, jbitmap);
906    }
907    return id;
908}
909
910static jlong
911nAllocationCubeCreateFromBitmap(JNIEnv *_env, jobject _this, jlong con, jlong type,
912                                jint mip, jobject jbitmap, jint usage)
913{
914    void *pixels = NULL;
915    AndroidBitmap_lockPixels(_env, jbitmap, &pixels);
916
917    jlong id = 0;
918    if (pixels != NULL) {
919        id = (jlong)(uintptr_t)dispatchTab.AllocationCubeCreateFromBitmap((RsContext)con,
920                                                                          (RsType)type,
921                                                                          (RsAllocationMipmapControl)mip,
922                                                                          pixels,
923                                                                          GetBitmapSize(_env, jbitmap),
924                                                                          usage);
925        AndroidBitmap_unlockPixels(_env, jbitmap);
926    }
927    return id;
928}
929
930static void
931nAllocationCopyFromBitmap(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jobject jbitmap)
932{
933    AndroidBitmapInfo info;
934    memset(&info, 0, sizeof(info));
935    AndroidBitmap_getInfo(_env, jbitmap, &info);
936
937    void *pixels = NULL;
938    AndroidBitmap_lockPixels(_env, jbitmap, &pixels);
939
940    if (pixels != NULL) {
941        dispatchTab.Allocation2DData((RsContext)con, (RsAllocation)alloc, 0, 0, 0,
942                                     RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X, info.width,
943                                     info.height, pixels, GetBitmapSize(_env, jbitmap), 0);
944        AndroidBitmap_unlockPixels(_env, jbitmap);
945    }
946}
947
948static void
949nAllocationCopyToBitmap(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jobject jbitmap)
950{
951    AndroidBitmapInfo info;
952    memset(&info, 0, sizeof(info));
953    AndroidBitmap_getInfo(_env, jbitmap, &info);
954
955    void *pixels = NULL;
956    AndroidBitmap_lockPixels(_env, jbitmap, &pixels);
957
958    if (pixels != NULL) {
959        dispatchTab.AllocationCopyToBitmap((RsContext)con, (RsAllocation)alloc, pixels,
960                                           GetBitmapSize(_env, jbitmap));
961        AndroidBitmap_unlockPixels(_env, jbitmap);
962    }
963    //bitmap.notifyPixelsChanged();
964}
965
966// Copies from the Java object data into the Allocation pointed to by _alloc.
967static void
968nAllocationData1D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint offset, jint lod,
969                  jint count, jobject data, jint sizeBytes, jint dataType, jint mSize,
970                  jboolean usePadding)
971{
972    RsAllocation *alloc = (RsAllocation *)_alloc;
973    LOG_API("nAllocation1DData, con(%p), adapter(%p), offset(%i), count(%i), sizeBytes(%i), "
974            "dataType(%i)", (RsContext)con, (RsAllocation)alloc, offset, count, sizeBytes,
975            dataType);
976    PER_ARRAY_TYPE(nullptr, dispatchTab.Allocation1DData, true,
977                   (RsContext)con, alloc, offset, lod, count, ptr, sizeBytes);
978}
979
980
981static void
982nAllocationElementData1D(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jint xoff,
983                         jint lod, jint compIdx, jbyteArray data, jint sizeBytes)
984{
985    jint len = _env->GetArrayLength(data);
986    LOG_API("nAllocationElementData1D, con(%p), alloc(%p), xoff(%i), comp(%i), len(%i), "
987            "sizeBytes(%i)", (RsContext)con, (RsAllocation)alloc, xoff, compIdx, len,
988            sizeBytes);
989    jbyte *ptr = _env->GetByteArrayElements(data, nullptr);
990    dispatchTab.Allocation1DElementData((RsContext)con, (RsAllocation)alloc, xoff,
991                                        lod, ptr, sizeBytes, compIdx);
992    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
993}
994
995/*
996static void
997nAllocationElementData(JNIEnv *_env, jobject _this, jlong con, jlong alloc,
998                       jint xoff, jint yoff, jint zoff,
999                       jint lod, jint compIdx, jbyteArray data, jint sizeBytes)
1000{
1001    jint len = _env->GetArrayLength(data);
1002    LOG_API("nAllocationElementData, con(%p), alloc(%p), xoff(%i), yoff(%i), zoff(%i), comp(%i), len(%i), "
1003            "sizeBytes(%i)", (RsContext)con, (RsAllocation)alloc, xoff, yoff, zoff, compIdx, len,
1004            sizeBytes);
1005    jbyte *ptr = _env->GetByteArrayElements(data, nullptr);
1006    dispatchTab.AllocationElementData((RsContext)con, (RsAllocation)alloc,
1007                                      xoff, yoff, zoff,
1008                                      lod, ptr, sizeBytes, compIdx);
1009    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
1010}
1011*/
1012
1013// Copies from the Java object data into the Allocation pointed to by _alloc.
1014static void
1015nAllocationData2D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint xoff, jint yoff, jint lod, jint _face,
1016                  jint w, jint h, jobject data, jint sizeBytes, jint dataType, jint mSize,
1017                  jboolean usePadding)
1018{
1019    RsAllocation *alloc = (RsAllocation *)_alloc;
1020    RsAllocationCubemapFace face = (RsAllocationCubemapFace)_face;
1021    LOG_API("nAllocation2DData, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i) "
1022            "type(%i)", (RsContext)con, alloc, xoff, yoff, w, h, sizeBytes, dataType);
1023    int count = w * h;
1024    PER_ARRAY_TYPE(nullptr, dispatchTab.Allocation2DData, true,
1025                   (RsContext)con, alloc, xoff, yoff, lod, face, w, h, ptr, sizeBytes, 0);
1026}
1027
1028static void
1029nAllocationData2D_alloc(JNIEnv *_env, jobject _this, jlong con,
1030                        jlong dstAlloc, jint dstXoff, jint dstYoff,
1031                        jint dstMip, jint dstFace,
1032                        jint width, jint height,
1033                        jlong srcAlloc, jint srcXoff, jint srcYoff,
1034                        jint srcMip, jint srcFace)
1035{
1036    LOG_API("nAllocation2DData_s, con(%p), dstAlloc(%p), dstXoff(%i), dstYoff(%i),"
1037            " dstMip(%i), dstFace(%i), width(%i), height(%i),"
1038            " srcAlloc(%p), srcXoff(%i), srcYoff(%i), srcMip(%i), srcFace(%i)",
1039            (RsContext)con, (RsAllocation)dstAlloc, dstXoff, dstYoff, dstMip, dstFace,
1040            width, height, (RsAllocation)srcAlloc, srcXoff, srcYoff, srcMip, srcFace);
1041
1042    dispatchTab.AllocationCopy2DRange((RsContext)con,
1043                                      (RsAllocation)dstAlloc,
1044                                      dstXoff, dstYoff,
1045                                      dstMip, dstFace,
1046                                      width, height,
1047                                      (RsAllocation)srcAlloc,
1048                                      srcXoff, srcYoff,
1049                                      srcMip, srcFace);
1050}
1051
1052// Copies from the Java object data into the Allocation pointed to by _alloc.
1053static void
1054nAllocationData3D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint xoff, jint yoff, jint zoff, jint lod,
1055                  jint w, jint h, jint d, jobject data, jint sizeBytes, jint dataType,
1056                  jint mSize, jboolean usePadding)
1057{
1058    RsAllocation *alloc = (RsAllocation *)_alloc;
1059    LOG_API("nAllocation3DData, con(%p), alloc(%p), xoff(%i), yoff(%i), zoff(%i), lod(%i), w(%i),"
1060            " h(%i), d(%i), sizeBytes(%i)", (RsContext)con, (RsAllocation)alloc, xoff, yoff, zoff,
1061            lod, w, h, d, sizeBytes);
1062    int count = w * h * d;
1063    PER_ARRAY_TYPE(nullptr, dispatchTab.Allocation3DData, true,
1064                   (RsContext)con, alloc, xoff, yoff, zoff, lod, w, h, d, ptr, sizeBytes, 0);
1065}
1066
1067static void
1068nAllocationData3D_alloc(JNIEnv *_env, jobject _this, jlong con,
1069                        jlong dstAlloc, jint dstXoff, jint dstYoff, jint dstZoff,
1070                        jint dstMip,
1071                        jint width, jint height, jint depth,
1072                        jlong srcAlloc, jint srcXoff, jint srcYoff, jint srcZoff,
1073                        jint srcMip)
1074{
1075    LOG_API("nAllocationData3D_alloc, con(%p), dstAlloc(%p), dstXoff(%i), dstYoff(%i),"
1076            " dstMip(%i), width(%i), height(%i),"
1077            " srcAlloc(%p), srcXoff(%i), srcYoff(%i), srcMip(%i)",
1078            (RsContext)con, (RsAllocation)dstAlloc, dstXoff, dstYoff, dstMip, dstFace,
1079            width, height, (RsAllocation)srcAlloc, srcXoff, srcYoff, srcMip, srcFace);
1080
1081    dispatchTab.AllocationCopy3DRange((RsContext)con,
1082                                      (RsAllocation)dstAlloc,
1083                                      dstXoff, dstYoff, dstZoff, dstMip,
1084                                      width, height, depth,
1085                                      (RsAllocation)srcAlloc,
1086                                      srcXoff, srcYoff, srcZoff, srcMip);
1087}
1088
1089// Copies from the Allocation pointed to by _alloc into the Java object data.
1090static void
1091nAllocationRead(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jobject data, jint dataType,
1092                jint mSize, jboolean usePadding)
1093{
1094    RsAllocation *alloc = (RsAllocation *)_alloc;
1095    LOG_API("nAllocationRead, con(%p), alloc(%p)", (RsContext)con, (RsAllocation)alloc);
1096    int count = 0;
1097    PER_ARRAY_TYPE(0, dispatchTab.AllocationRead, false,
1098                   (RsContext)con, alloc, ptr, len * typeBytes);
1099}
1100
1101// Copies from the Allocation pointed to by _alloc into the Java object data.
1102static void
1103nAllocationRead1D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint offset, jint lod,
1104                  jint count, jobject data, jint sizeBytes, jint dataType,
1105                  jint mSize, jboolean usePadding)
1106{
1107    RsAllocation *alloc = (RsAllocation *)_alloc;
1108    LOG_API("nAllocation1DRead, con(%p), adapter(%p), offset(%i), count(%i), sizeBytes(%i), "
1109              "dataType(%i)", (RsContext)con, alloc, offset, count, sizeBytes, dataType);
1110    PER_ARRAY_TYPE(0, dispatchTab.Allocation1DRead, false,
1111                   (RsContext)con, alloc, offset, lod, count, ptr, sizeBytes);
1112}
1113
1114// Copies from the Element in the Allocation pointed to by _alloc into the Java array data.
1115/*
1116static void
1117nAllocationElementRead(JNIEnv *_env, jobject _this, jlong con, jlong _alloc,
1118                       jint xoff, jint yoff, jint zoff,
1119                       jint lod, jint compIdx, jobject data, jint sizeBytes)
1120{
1121    jint len = _env->GetArrayLength(data);
1122    LOG_API("nAllocationElementRead, con(%p), alloc(%p), xoff(%i), yoff(%i), zoff(%i), comp(%i), len(%i), "
1123            "sizeBytes(%i)", (RsContext)con, (RsAllocation)alloc, xoff, yoff, zoff, compIdx, len,
1124            sizeBytes);
1125    jbyte *ptr = _env->GetByteArrayElements(data, nullptr);
1126    dispatchTab.AllocationElementRead((RsContext)con, (RsAllocation)alloc,
1127                                      xoff, yoff, zoff,
1128                                      lod, ptr, sizeBytes, compIdx);
1129    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
1130}
1131*/
1132
1133// Copies from the Allocation pointed to by _alloc into the Java object data.
1134static void
1135nAllocationRead2D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint xoff, jint yoff, jint lod, jint _face,
1136                  jint w, jint h, jobject data, jint sizeBytes, jint dataType,
1137                  jint mSize, jboolean usePadding)
1138{
1139    RsAllocation *alloc = (RsAllocation *)_alloc;
1140    RsAllocationCubemapFace face = (RsAllocationCubemapFace)_face;
1141    LOG_API("nAllocation2DRead, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i) "
1142              "type(%i)", (RsContext)con, alloc, xoff, yoff, w, h, sizeBytes, dataType);
1143    int count = w * h;
1144    PER_ARRAY_TYPE(0, dispatchTab.Allocation2DRead, false,
1145                   (RsContext)con, alloc, xoff, yoff, lod, face, w, h, ptr, sizeBytes, 0);
1146}
1147
1148// Copies from the Allocation pointed to by _alloc into the Java object data.
1149/*
1150static void
1151nAllocationRead3D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint xoff, jint yoff, jint zoff, jint lod,
1152                  jint w, jint h, jint d, jobject data, int sizeBytes, int dataType,
1153                  jint mSize, jboolean usePadding)
1154{
1155    RsAllocation *alloc = (RsAllocation *)_alloc;
1156    LOG_API("nAllocation3DRead, con(%p), alloc(%p), xoff(%i), yoff(%i), zoff(%i), lod(%i), w(%i),"
1157            " h(%i), d(%i), sizeBytes(%i)", (RsContext)con, (RsAllocation)alloc, xoff, yoff, zoff,
1158            lod, w, h, d, sizeBytes);
1159    int count = w * h * d;
1160    PER_ARRAY_TYPE(nullptr, dispatchTab.Allocation3DRead, false,
1161                   (RsContext)con, alloc, xoff, yoff, zoff, lod, w, h, d, ptr, sizeBytes, 0);
1162}
1163*/
1164
1165static jlong
1166nAllocationGetType(JNIEnv *_env, jobject _this, jlong con, jlong a)
1167{
1168    LOG_API("nAllocationGetType, con(%p), a(%p)", (RsContext)con, (RsAllocation)a);
1169    return (jlong)(uintptr_t) dispatchTab.AllocationGetType((RsContext)con, (RsAllocation)a);
1170}
1171
1172static void
1173nAllocationResize1D(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jint dimX)
1174{
1175    LOG_API("nAllocationResize1D, con(%p), alloc(%p), sizeX(%i)", (RsContext)con,
1176            (RsAllocation)alloc, dimX);
1177    dispatchTab.AllocationResize1D((RsContext)con, (RsAllocation)alloc, dimX);
1178}
1179
1180// -----------------------------------
1181
1182static void
1183nScriptBindAllocation(JNIEnv *_env, jobject _this, jlong con, jlong script, jlong alloc, jint slot, jboolean mUseInc)
1184{
1185    LOG_API("nScriptBindAllocation, con(%p), script(%p), alloc(%p), slot(%i)",
1186            (RsContext)con, (RsScript)script, (RsAllocation)alloc, slot);
1187    if (mUseInc) {
1188        dispatchTabInc.ScriptBindAllocation((RsContext)con, (RsScript)script, (RsAllocation)alloc, slot);
1189    } else {
1190        dispatchTab.ScriptBindAllocation((RsContext)con, (RsScript)script, (RsAllocation)alloc, slot);
1191    }
1192}
1193
1194static void
1195nScriptSetVarI(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jint val, jboolean mUseInc)
1196{
1197    LOG_API("nScriptSetVarI, con(%p), s(%p), slot(%i), val(%i)", (RsContext)con,
1198            (void *)script, slot, val);
1199    if (mUseInc) {
1200        dispatchTabInc.ScriptSetVarI((RsContext)con, (RsScript)script, slot, val);
1201    } else {
1202        dispatchTab.ScriptSetVarI((RsContext)con, (RsScript)script, slot, val);
1203    }
1204}
1205
1206static void
1207nScriptSetVarObj(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jlong val, jboolean mUseInc)
1208{
1209    LOG_API("nScriptSetVarObj, con(%p), s(%p), slot(%i), val(%i)", (RsContext)con,
1210            (void *)script, slot, val);
1211    if (mUseInc) {
1212        dispatchTabInc.ScriptSetVarObj((RsContext)con, (RsScript)script, slot, (RsObjectBase)val);
1213    } else {
1214        dispatchTab.ScriptSetVarObj((RsContext)con, (RsScript)script, slot, (RsObjectBase)val);
1215    }
1216}
1217
1218static void
1219nScriptSetVarJ(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jlong val, jboolean mUseInc)
1220{
1221    LOG_API("nScriptSetVarJ, con(%p), s(%p), slot(%i), val(%lli)", (RsContext)con,
1222            (void *)script, slot, val);
1223    if (mUseInc) {
1224        dispatchTabInc.ScriptSetVarJ((RsContext)con, (RsScript)script, slot, val);
1225    } else {
1226        dispatchTab.ScriptSetVarJ((RsContext)con, (RsScript)script, slot, val);
1227    }
1228}
1229
1230static void
1231nScriptSetVarF(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, float val, jboolean mUseInc)
1232{
1233    LOG_API("nScriptSetVarF, con(%p), s(%p), slot(%i), val(%f)", (RsContext)con,
1234            (void *)script, slot, val);
1235    if (mUseInc) {
1236        dispatchTabInc.ScriptSetVarF((RsContext)con, (RsScript)script, slot, val);
1237    } else {
1238        dispatchTab.ScriptSetVarF((RsContext)con, (RsScript)script, slot, val);
1239    }
1240}
1241
1242static void
1243nScriptSetVarD(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, double val, jboolean mUseInc)
1244{
1245    LOG_API("nScriptSetVarD, con(%p), s(%p), slot(%i), val(%lf)", (RsContext)con,
1246            (void *)script, slot, val);
1247    if (mUseInc) {
1248        dispatchTabInc.ScriptSetVarD((RsContext)con, (RsScript)script, slot, val);
1249    } else {
1250        dispatchTab.ScriptSetVarD((RsContext)con, (RsScript)script, slot, val);
1251    }
1252}
1253
1254static void
1255nScriptSetVarV(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jbyteArray data, jboolean mUseInc)
1256{
1257    LOG_API("nScriptSetVarV, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
1258    jint len = _env->GetArrayLength(data);
1259    jbyte *ptr = _env->GetByteArrayElements(data, NULL);
1260    if (mUseInc) {
1261        dispatchTabInc.ScriptSetVarV((RsContext)con, (RsScript)script, slot, ptr, len);
1262    } else {
1263        dispatchTab.ScriptSetVarV((RsContext)con, (RsScript)script, slot, ptr, len);
1264    }
1265    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
1266}
1267
1268static void
1269nScriptSetVarVE(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jbyteArray data,
1270                jlong elem, jintArray dims, jboolean mUseInc)
1271{
1272    LOG_API("nScriptSetVarVE, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
1273    jint len = _env->GetArrayLength(data);
1274    jbyte *ptr = _env->GetByteArrayElements(data, NULL);
1275    jint dimsLen = _env->GetArrayLength(dims) * sizeof(int);
1276    jint *dimsPtr = _env->GetIntArrayElements(dims, NULL);
1277    if (mUseInc) {
1278        dispatchTabInc.ScriptSetVarVE((RsContext)con, (RsScript)script, slot, ptr, len, (RsElement)elem,
1279                                      (const uint32_t *)dimsPtr, dimsLen);
1280    } else {
1281        dispatchTab.ScriptSetVarVE((RsContext)con, (RsScript)script, slot, ptr, len, (RsElement)elem,
1282                                   (const uint32_t *)dimsPtr, dimsLen);
1283    }
1284    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
1285    _env->ReleaseIntArrayElements(dims, dimsPtr, JNI_ABORT);
1286}
1287
1288
1289static void
1290nScriptSetTimeZone(JNIEnv *_env, jobject _this, jlong con, jlong script, jbyteArray timeZone, jboolean mUseInc)
1291{
1292    LOG_API("nScriptCSetTimeZone, con(%p), s(%p), timeZone(%s)", (RsContext)con,
1293            (void *)script, (const char *)timeZone);
1294
1295    jint length = _env->GetArrayLength(timeZone);
1296    jbyte* timeZone_ptr;
1297    timeZone_ptr = (jbyte *) _env->GetPrimitiveArrayCritical(timeZone, (jboolean *)0);
1298    if (mUseInc) {
1299        dispatchTabInc.ScriptSetTimeZone((RsContext)con, (RsScript)script, (const char *)timeZone_ptr, length);
1300    } else {
1301        dispatchTab.ScriptSetTimeZone((RsContext)con, (RsScript)script, (const char *)timeZone_ptr, length);
1302    }
1303
1304    if (timeZone_ptr) {
1305        _env->ReleasePrimitiveArrayCritical(timeZone, timeZone_ptr, 0);
1306    }
1307}
1308
1309static void
1310nScriptInvoke(JNIEnv *_env, jobject _this, jlong con, jlong obj, jint slot, jboolean mUseInc)
1311{
1312    LOG_API("nScriptInvoke, con(%p), script(%p)", (RsContext)con, (void *)obj);
1313    if (mUseInc) {
1314        dispatchTabInc.ScriptInvoke((RsContext)con, (RsScript)obj, slot);
1315    } else {
1316        dispatchTab.ScriptInvoke((RsContext)con, (RsScript)obj, slot);
1317    }
1318}
1319
1320static void
1321nScriptInvokeV(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jbyteArray data, jboolean mUseInc)
1322{
1323    LOG_API("nScriptInvokeV, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
1324    jint len = _env->GetArrayLength(data);
1325    jbyte *ptr = _env->GetByteArrayElements(data, NULL);
1326    if (mUseInc) {
1327        dispatchTabInc.ScriptInvokeV((RsContext)con, (RsScript)script, slot, ptr, len);
1328    } else {
1329        dispatchTab.ScriptInvokeV((RsContext)con, (RsScript)script, slot, ptr, len);
1330    }
1331    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
1332}
1333
1334static void
1335nScriptForEach(JNIEnv *_env, jobject _this, jlong con, jlong incCon,
1336               jlong script, jint slot, jlong ain, jlong aout, jboolean mUseInc)
1337{
1338    LOG_API("nScriptForEach, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
1339    if (mUseInc) {
1340        dispatchTab.ContextFinish((RsContext)con);
1341        dispatchTabInc.ScriptForEach((RsContext)incCon, (RsScript)script, slot,
1342                                     (RsAllocation)ain, (RsAllocation)aout,
1343                                     NULL, 0, NULL, 0);
1344    } else {
1345        dispatchTab.ScriptForEach((RsContext)con, (RsScript)script, slot,
1346                                  (RsAllocation)ain, (RsAllocation)aout,
1347                                  NULL, 0, NULL, 0);
1348    }
1349}
1350static void
1351nScriptForEachV(JNIEnv *_env, jobject _this, jlong con, jlong incCon,
1352                jlong script, jint slot, jlong ain, jlong aout, jbyteArray params, jboolean mUseInc)
1353{
1354    LOG_API("nScriptForEach, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
1355    jint len = _env->GetArrayLength(params);
1356    jbyte *ptr = _env->GetByteArrayElements(params, NULL);
1357    if (mUseInc) {
1358        dispatchTab.ContextFinish((RsContext)con);
1359        dispatchTabInc.ScriptForEach((RsContext)incCon, (RsScript)script, slot,
1360                                     (RsAllocation)ain, (RsAllocation)aout,
1361                                     ptr, len, NULL, 0);
1362    } else {
1363        dispatchTab.ScriptForEach((RsContext)con, (RsScript)script, slot,
1364                                  (RsAllocation)ain, (RsAllocation)aout,
1365                                  ptr, len, NULL, 0);
1366    }
1367    _env->ReleaseByteArrayElements(params, ptr, JNI_ABORT);
1368}
1369
1370static void
1371nScriptForEachClipped(JNIEnv *_env, jobject _this, jlong con, jlong incCon,
1372                      jlong script, jint slot, jlong ain, jlong aout,
1373                      jint xstart, jint xend,
1374                      jint ystart, jint yend, jint zstart, jint zend, jboolean mUseInc)
1375{
1376    LOG_API("nScriptForEachClipped, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
1377    RsScriptCall sc;
1378    sc.xStart = xstart;
1379    sc.xEnd = xend;
1380    sc.yStart = ystart;
1381    sc.yEnd = yend;
1382    sc.zStart = zstart;
1383    sc.zEnd = zend;
1384    sc.strategy = RS_FOR_EACH_STRATEGY_DONT_CARE;
1385    sc.arrayStart = 0;
1386    sc.arrayEnd = 0;
1387    if (mUseInc) {
1388        dispatchTab.ContextFinish((RsContext)con);
1389        dispatchTabInc.ScriptForEach((RsContext)incCon, (RsScript)script, slot,
1390                                     (RsAllocation)ain, (RsAllocation)aout,
1391                                     NULL, 0, &sc, sizeof(sc));
1392    } else {
1393        dispatchTab.ScriptForEach((RsContext)con, (RsScript)script, slot,
1394                                  (RsAllocation)ain, (RsAllocation)aout,
1395                                  NULL, 0, &sc, sizeof(sc));
1396    }
1397}
1398
1399static void
1400nScriptForEachClippedV(JNIEnv *_env, jobject _this, jlong con, jlong incCon,
1401                       jlong script, jint slot, jlong ain, jlong aout,
1402                       jbyteArray params, jint xstart, jint xend,
1403                       jint ystart, jint yend, jint zstart, jint zend, jboolean mUseInc)
1404{
1405    LOG_API("nScriptForEachClipped, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
1406    jint len = _env->GetArrayLength(params);
1407    jbyte *ptr = _env->GetByteArrayElements(params, NULL);
1408    RsScriptCall sc;
1409    sc.xStart = xstart;
1410    sc.xEnd = xend;
1411    sc.yStart = ystart;
1412    sc.yEnd = yend;
1413    sc.zStart = zstart;
1414    sc.zEnd = zend;
1415    sc.strategy = RS_FOR_EACH_STRATEGY_DONT_CARE;
1416    sc.arrayStart = 0;
1417    sc.arrayEnd = 0;
1418    if (mUseInc) {
1419        dispatchTab.ContextFinish((RsContext)con);
1420        dispatchTabInc.ScriptForEach((RsContext)incCon, (RsScript)script, slot,
1421                                     (RsAllocation)ain, (RsAllocation)aout,
1422                                     ptr, len, &sc, sizeof(sc));
1423    } else {
1424        dispatchTab.ScriptForEach((RsContext)con, (RsScript)script, slot,
1425                                  (RsAllocation)ain, (RsAllocation)aout,
1426                                  ptr, len, &sc, sizeof(sc));
1427    }
1428    _env->ReleaseByteArrayElements(params, ptr, JNI_ABORT);
1429}
1430
1431// -----------------------------------
1432
1433static jlong
1434nScriptCCreate(JNIEnv *_env, jobject _this, jlong con,
1435               jstring resName, jstring cacheDir,
1436               jbyteArray scriptRef, jint length)
1437{
1438    LOG_API("nScriptCCreate, con(%p)", (RsContext)con);
1439
1440    AutoJavaStringToUTF8 resNameUTF(_env, resName);
1441    AutoJavaStringToUTF8 cacheDirUTF(_env, cacheDir);
1442    jlong ret = 0;
1443    jbyte* script_ptr = NULL;
1444    jint _exception = 0;
1445    jint remaining;
1446    if (!scriptRef) {
1447        _exception = 1;
1448        //jniThrowException(_env, "java/lang/IllegalArgumentException", "script == null");
1449        goto exit;
1450    }
1451    if (length < 0) {
1452        _exception = 1;
1453        //jniThrowException(_env, "java/lang/IllegalArgumentException", "length < 0");
1454        goto exit;
1455    }
1456    remaining = _env->GetArrayLength(scriptRef);
1457    if (remaining < length) {
1458        _exception = 1;
1459        //jniThrowException(_env, "java/lang/IllegalArgumentException",
1460        //        "length > script.length - offset");
1461        goto exit;
1462    }
1463    script_ptr = (jbyte *)
1464        _env->GetPrimitiveArrayCritical(scriptRef, (jboolean *)0);
1465
1466    //rsScriptCSetText(con, (const char *)script_ptr, length);
1467
1468    ret = (jlong)(uintptr_t)dispatchTab.ScriptCCreate((RsContext)con,
1469                                                      resNameUTF.c_str(), resNameUTF.length(),
1470                                                      cacheDirUTF.c_str(), cacheDirUTF.length(),
1471                                                      (const char *)script_ptr, length);
1472
1473exit:
1474    if (script_ptr) {
1475        _env->ReleasePrimitiveArrayCritical(scriptRef, script_ptr,
1476                _exception ? JNI_ABORT: 0);
1477    }
1478
1479    return (jlong)(uintptr_t)ret;
1480}
1481
1482static jlong
1483nScriptIntrinsicCreate(JNIEnv *_env, jobject _this, jlong con, jint id, jlong eid, jboolean mUseInc)
1484{
1485    LOG_API("nScriptIntrinsicCreate, con(%p) id(%i) element(%p)", (RsContext)con, id, (void *)eid);
1486    if (mUseInc) {
1487        return (jlong)(uintptr_t)dispatchTabInc.ScriptIntrinsicCreate((RsContext)con, id, (RsElement)eid);
1488    } else {
1489        return (jlong)(uintptr_t)dispatchTab.ScriptIntrinsicCreate((RsContext)con, id, (RsElement)eid);
1490    }
1491}
1492
1493static jlong
1494nScriptKernelIDCreate(JNIEnv *_env, jobject _this, jlong con, jlong sid, jint slot, jint sig, jboolean mUseInc)
1495{
1496    LOG_API("nScriptKernelIDCreate, con(%p) script(%p), slot(%i), sig(%i)", (RsContext)con,
1497            (void *)sid, slot, sig);
1498    if (mUseInc) {
1499        return (jlong)(uintptr_t)dispatchTabInc.ScriptKernelIDCreate((RsContext)con, (RsScript)sid,
1500                                                                     slot, sig);
1501    } else {
1502        return (jlong)(uintptr_t)dispatchTab.ScriptKernelIDCreate((RsContext)con, (RsScript)sid,
1503                                                                  slot, sig);
1504    }
1505}
1506
1507static jlong
1508nScriptInvokeIDCreate(JNIEnv *_env, jobject _this, jlong con, jlong sid, jint slot)
1509{
1510    LOG_API("nScriptInvokeIDCreate, con(%p) script(%p), slot(%i), sig(%i)", con,
1511            (void *)sid, slot);
1512    return (jlong)dispatchTab.ScriptInvokeIDCreate((RsContext)con, (RsScript)sid, slot);
1513}
1514
1515static jlong
1516nScriptFieldIDCreate(JNIEnv *_env, jobject _this, jlong con, jlong sid, jint slot, jboolean mUseInc)
1517{
1518    LOG_API("nScriptFieldIDCreate, con(%p) script(%p), slot(%i)", (RsContext)con, (void *)sid, slot);
1519    if (mUseInc) {
1520        return (jlong)(uintptr_t)dispatchTabInc.ScriptFieldIDCreate((RsContext)con, (RsScript)sid, slot);
1521    } else {
1522        return (jlong)(uintptr_t)dispatchTab.ScriptFieldIDCreate((RsContext)con, (RsScript)sid, slot);
1523    }
1524}
1525
1526static jlong
1527nScriptGroupCreate(JNIEnv *_env, jobject _this, jlong con, jlongArray _kernels, jlongArray _src,
1528    jlongArray _dstk, jlongArray _dstf, jlongArray _types)
1529{
1530    LOG_API("nScriptGroupCreate, con(%p)", (RsContext)con);
1531
1532    jint kernelsLen = _env->GetArrayLength(_kernels);
1533    jlong *jKernelsPtr = _env->GetLongArrayElements(_kernels, nullptr);
1534    RsScriptKernelID* kernelsPtr = (RsScriptKernelID*) malloc(sizeof(RsScriptKernelID) * kernelsLen);
1535    for(int i = 0; i < kernelsLen; ++i) {
1536        kernelsPtr[i] = (RsScriptKernelID)jKernelsPtr[i];
1537    }
1538
1539    jint srcLen = _env->GetArrayLength(_src);
1540    jlong *jSrcPtr = _env->GetLongArrayElements(_src, nullptr);
1541    RsScriptKernelID* srcPtr = (RsScriptKernelID*) malloc(sizeof(RsScriptKernelID) * srcLen);
1542    for(int i = 0; i < srcLen; ++i) {
1543        srcPtr[i] = (RsScriptKernelID)jSrcPtr[i];
1544    }
1545
1546    jint dstkLen = _env->GetArrayLength(_dstk);
1547    jlong *jDstkPtr = _env->GetLongArrayElements(_dstk, nullptr);
1548    RsScriptKernelID* dstkPtr = (RsScriptKernelID*) malloc(sizeof(RsScriptKernelID) * dstkLen);
1549    for(int i = 0; i < dstkLen; ++i) {
1550        dstkPtr[i] = (RsScriptKernelID)jDstkPtr[i];
1551    }
1552
1553    jint dstfLen = _env->GetArrayLength(_dstf);
1554    jlong *jDstfPtr = _env->GetLongArrayElements(_dstf, nullptr);
1555    RsScriptKernelID* dstfPtr = (RsScriptKernelID*) malloc(sizeof(RsScriptKernelID) * dstfLen);
1556    for(int i = 0; i < dstfLen; ++i) {
1557        dstfPtr[i] = (RsScriptKernelID)jDstfPtr[i];
1558    }
1559
1560    jint typesLen = _env->GetArrayLength(_types);
1561    jlong *jTypesPtr = _env->GetLongArrayElements(_types, nullptr);
1562    RsType* typesPtr = (RsType*) malloc(sizeof(RsType) * typesLen);
1563    for(int i = 0; i < typesLen; ++i) {
1564        typesPtr[i] = (RsType)jTypesPtr[i];
1565    }
1566
1567    jlong id = (jlong)(uintptr_t) dispatchTab.ScriptGroupCreate((RsContext)con,
1568                               (RsScriptKernelID *)kernelsPtr, kernelsLen * sizeof(RsScriptKernelID),
1569                               (RsScriptKernelID *)srcPtr, srcLen * sizeof(RsScriptKernelID),
1570                               (RsScriptKernelID *)dstkPtr, dstkLen * sizeof(RsScriptKernelID),
1571                               (RsScriptFieldID *)dstfPtr, dstfLen * sizeof(RsScriptKernelID),
1572                               (RsType *)typesPtr, typesLen * sizeof(RsType));
1573
1574    free(kernelsPtr);
1575    free(srcPtr);
1576    free(dstkPtr);
1577    free(dstfPtr);
1578    free(typesPtr);
1579    _env->ReleaseLongArrayElements(_kernels, jKernelsPtr, 0);
1580    _env->ReleaseLongArrayElements(_src, jSrcPtr, 0);
1581    _env->ReleaseLongArrayElements(_dstk, jDstkPtr, 0);
1582    _env->ReleaseLongArrayElements(_dstf, jDstfPtr, 0);
1583    _env->ReleaseLongArrayElements(_types, jTypesPtr, 0);
1584    return id;
1585}
1586
1587static void
1588nScriptGroupSetInput(JNIEnv *_env, jobject _this, jlong con, jlong gid, jlong kid, jlong alloc)
1589{
1590    LOG_API("nScriptGroupSetInput, con(%p) group(%p), kernelId(%p), alloc(%p)", (RsContext)con,
1591            (void *)gid, (void *)kid, (void *)alloc);
1592    dispatchTab.ScriptGroupSetInput((RsContext)con, (RsScriptGroup)gid, (RsScriptKernelID)kid,
1593                                    (RsAllocation)alloc);
1594}
1595
1596static void
1597nScriptGroupSetOutput(JNIEnv *_env, jobject _this, jlong con, jlong gid, jlong kid, jlong alloc)
1598{
1599    LOG_API("nScriptGroupSetOutput, con(%p) group(%p), kernelId(%p), alloc(%p)", (RsContext)con,
1600            (void *)gid, (void *)kid, (void *)alloc);
1601    dispatchTab.ScriptGroupSetOutput((RsContext)con, (RsScriptGroup)gid, (RsScriptKernelID)kid,
1602                                     (RsAllocation)alloc);
1603}
1604
1605static void
1606nScriptGroupExecute(JNIEnv *_env, jobject _this, jlong con, jlong gid)
1607{
1608    LOG_API("nScriptGroupSetOutput, con(%p) group(%p)", (RsContext)con, (void *)gid);
1609    dispatchTab.ScriptGroupExecute((RsContext)con, (RsScriptGroup)gid);
1610}
1611
1612// ---------------------------------------------------------------------------
1613
1614static jlong
1615nSamplerCreate(JNIEnv *_env, jobject _this, jlong con, jint magFilter, jint minFilter,
1616               jint wrapS, jint wrapT, jint wrapR, jfloat aniso)
1617{
1618    LOG_API("nSamplerCreate, con(%p)", (RsContext)con);
1619    return (jlong)(uintptr_t)dispatchTab.SamplerCreate((RsContext)con,
1620                                                       (RsSamplerValue)magFilter,
1621                                                       (RsSamplerValue)minFilter,
1622                                                       (RsSamplerValue)wrapS,
1623                                                       (RsSamplerValue)wrapT,
1624                                                       (RsSamplerValue)wrapR,
1625                                                       aniso);
1626}
1627
1628static jint
1629nSystemGetPointerSize(JNIEnv *_env, jobject _this) {
1630    return (jint)sizeof(void*);
1631}
1632
1633// ---------------------------------------------------------------------------
1634// For Incremental Intrinsic Support
1635static bool nIncLoadSO() {
1636    void* handle = NULL;
1637    handle = dlopen("libRSSupport.so", RTLD_LAZY | RTLD_LOCAL);
1638    if (handle == NULL) {
1639        LOG_API("couldn't dlopen %s, %s", filename, dlerror());
1640        return false;
1641    }
1642
1643    if (loadSymbols(handle, dispatchTabInc) == false) {
1644        LOG_API("%s init failed!", filename);
1645        return false;
1646    }
1647    LOG_API("Successfully loaded %s", filename);
1648    return true;
1649}
1650
1651// -----------------------------------
1652// To create/destroy a dummy context
1653static void
1654nIncObjDestroy(JNIEnv *_env, jobject _this, jlong con, jlong obj)
1655{
1656    LOG_API("nObjDestroy, con(%p) obj(%p)", (RsContext)con, (void *)obj);
1657    dispatchTabInc.ObjDestroy((RsContext)con, (void *)obj);
1658}
1659
1660
1661static jlong
1662nIncDeviceCreate(JNIEnv *_env, jobject _this)
1663{
1664    LOG_API("nDeviceCreate");
1665    return (jlong)(uintptr_t)dispatchTabInc.DeviceCreate();
1666}
1667
1668static void
1669nIncDeviceDestroy(JNIEnv *_env, jobject _this, jlong dev)
1670{
1671    LOG_API("nDeviceDestroy");
1672    return dispatchTabInc.DeviceDestroy((RsDevice)dev);
1673}
1674
1675static jlong
1676nIncContextCreate(JNIEnv *_env, jobject _this, jlong dev, jint ver, jint sdkVer, jint ct)
1677{
1678    LOG_API("nContextCreate");
1679    //The compat context for incremental support will be synchronous.
1680    return (jlong)(uintptr_t)dispatchTabInc.ContextCreate((RsDevice)dev, ver, sdkVer,
1681                                                          (RsContextType)ct,
1682                                                          RS_CONTEXT_SYNCHRONOUS);
1683}
1684
1685static void
1686nIncContextFinish(JNIEnv *_env, jobject _this, jlong con)
1687{
1688    LOG_API("nContextFinish, con(%p)", (RsContext)con);
1689    dispatchTabInc.ContextFinish((RsContext)con);
1690}
1691
1692static void
1693nIncContextDestroy(JNIEnv *_env, jobject _this, jlong con)
1694{
1695    LOG_API("nContextDestroy, con(%p)", (RsContext)con);
1696    dispatchTabInc.ContextDestroy((RsContext)con);
1697}
1698
1699// -----------------------------------
1700// Create dummy Element
1701static jlong
1702nIncElementCreate(JNIEnv *_env, jobject _this, jlong con, jlong type, jint kind, jboolean norm, jint size)
1703{
1704    LOG_API("nElementCreate, con(%p), type(%i), kind(%i), norm(%i), size(%i)", (RsContext)con,
1705            type, kind, norm, size);
1706    return (jlong)(uintptr_t)dispatchTabInc.ElementCreate((RsContext)con, (RsDataType)type,
1707                                                          (RsDataKind)kind, norm, size);
1708}
1709// -----------------------------------
1710// Create dummy Type
1711static jlong
1712nIncTypeCreate(JNIEnv *_env, jobject _this, jlong con, jlong eid,
1713            jint dimx, jint dimy, jint dimz, jboolean mips, jboolean faces, jint yuv)
1714{
1715    LOG_API("nTypeCreate, con(%p) eid(%p), x(%i), y(%i), z(%i), mips(%i), faces(%i), yuv(%i)",
1716            incCon, eid, dimx, dimy, dimz, mips, faces, yuv);
1717
1718    return (jlong)(uintptr_t)dispatchTabInc.TypeCreate((RsContext)con, (RsElement)eid, dimx, dimy,
1719                                                       dimz, mips, faces, yuv);
1720}
1721
1722// -----------------------------------
1723// Create Allocation from pointer
1724static jlong
1725nIncAllocationCreateTyped(JNIEnv *_env, jobject _this, jlong con, jlong incCon, jlong alloc, jlong type)
1726{
1727    LOG_API("nAllocationCreateTyped, con(%p), type(%p), mip(%i), usage(%i), ptr(%p)",
1728            incCon, (RsElement)type, mips, usage, (void *)pointer);
1729    size_t strideIn;
1730    void* pIn = NULL;
1731    RsAllocation ainI = NULL;
1732    if (alloc != 0) {
1733        pIn = dispatchTab.AllocationGetPointer((RsContext)con, (RsAllocation)alloc, 0,
1734                                               RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X, 0, 0,
1735                                               &strideIn, sizeof(size_t));
1736        ainI = dispatchTabInc.AllocationCreateTyped((RsContext)incCon, (RsType)type,
1737                                                    RS_ALLOCATION_MIPMAP_NONE,
1738                                                    RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED,
1739                                                    (uintptr_t)pIn);
1740    }
1741    return (jlong)(uintptr_t) ainI;
1742}
1743
1744// ---------------------------------------------------------------------------
1745
1746
1747static const char *classPathName = "android/support/v8/renderscript/RenderScript";
1748
1749static JNINativeMethod methods[] = {
1750{"nLoadSO",                        "(ZI)Z",                                   (bool*)nLoadSO },
1751{"nLoadIOSO",                      "()Z",                                     (bool*)nLoadIOSO },
1752{"nDeviceCreate",                  "()J",                                     (void*)nDeviceCreate },
1753{"nDeviceDestroy",                 "(J)V",                                    (void*)nDeviceDestroy },
1754{"nDeviceSetConfig",               "(JII)V",                                  (void*)nDeviceSetConfig },
1755{"nContextGetUserMessage",         "(J[I)I",                                  (void*)nContextGetUserMessage },
1756{"nContextGetErrorMessage",        "(J)Ljava/lang/String;",                   (void*)nContextGetErrorMessage },
1757{"nContextPeekMessage",            "(J[I)I",                                  (void*)nContextPeekMessage },
1758{"nContextInitToClient",           "(J)V",                                    (void*)nContextInitToClient },
1759{"nContextDeinitToClient",         "(J)V",                                    (void*)nContextDeinitToClient },
1760
1761
1762// All methods below are thread protected in java.
1763{"rsnContextCreate",                 "(JIIILjava/lang/String;)J",             (void*)nContextCreate },
1764{"rsnContextFinish",                 "(J)V",                                  (void*)nContextFinish },
1765{"rsnContextSetPriority",            "(JI)V",                                 (void*)nContextSetPriority },
1766{"rsnContextDestroy",                "(J)V",                                  (void*)nContextDestroy },
1767{"rsnContextDump",                   "(JI)V",                                 (void*)nContextDump },
1768{"rsnContextSendMessage",            "(JI[I)V",                               (void*)nContextSendMessage },
1769{"rsnClosureCreate",                 "(JJJ[J[J[I[J[J)J",                      (void*)nClosureCreate },
1770{"rsnInvokeClosureCreate",           "(JJ[B[J[J[I)J",                         (void*)nInvokeClosureCreate },
1771{"rsnClosureSetArg",                 "(JJIJI)V",                              (void*)nClosureSetArg },
1772{"rsnClosureSetGlobal",              "(JJJJI)V",                              (void*)nClosureSetGlobal },
1773{"rsnObjDestroy",                    "(JJ)V",                                 (void*)nObjDestroy },
1774
1775{"rsnElementCreate",                 "(JJIZI)J",                              (void*)nElementCreate },
1776{"rsnElementCreate2",                "(J[J[Ljava/lang/String;[I)J",           (void*)nElementCreate2 },
1777{"rsnElementGetSubElements",         "(JJ[J[Ljava/lang/String;[I)V",          (void*)nElementGetSubElements },
1778
1779{"rsnTypeCreate",                    "(JJIIIZZI)J",                           (void*)nTypeCreate },
1780
1781{"rsnAllocationCreateTyped",         "(JJIIJ)J",                              (void*)nAllocationCreateTyped },
1782{"rsnAllocationCreateFromBitmap",    "(JJILandroid/graphics/Bitmap;I)J",      (void*)nAllocationCreateFromBitmap },
1783{"rsnAllocationCreateBitmapBackedAllocation",    "(JJILandroid/graphics/Bitmap;I)J",      (void*)nAllocationCreateBitmapBackedAllocation },
1784{"rsnAllocationCubeCreateFromBitmap","(JJILandroid/graphics/Bitmap;I)J",      (void*)nAllocationCubeCreateFromBitmap },
1785
1786{"rsnAllocationCopyFromBitmap",      "(JJLandroid/graphics/Bitmap;)V",        (void*)nAllocationCopyFromBitmap },
1787{"rsnAllocationCopyToBitmap",        "(JJLandroid/graphics/Bitmap;)V",        (void*)nAllocationCopyToBitmap },
1788
1789{"rsnAllocationSyncAll",             "(JJI)V",                                (void*)nAllocationSyncAll },
1790{"rsnAllocationSetSurface",          "(JJLandroid/view/Surface;)V",           (void*)nAllocationSetSurface },
1791{"rsnAllocationIoSend",              "(JJ)V",                                 (void*)nAllocationIoSend },
1792{"rsnAllocationData1D",              "(JJIIILjava/lang/Object;IIIZ)V",        (void*)nAllocationData1D },
1793{"rsnAllocationElementData1D",       "(JJIII[BI)V",                           (void*)nAllocationElementData1D },
1794//{"rsnAllocationElementData",         "(JJIIIII[BI)V",                         (void*)nAllocationElementData },
1795{"rsnAllocationData2D",              "(JJIIIIIILjava/lang/Object;IIIZ)V",     (void*)nAllocationData2D },
1796{"rsnAllocationData2D",              "(JJIIIIIIJIIII)V",                      (void*)nAllocationData2D_alloc },
1797{"rsnAllocationData3D",              "(JJIIIIIIILjava/lang/Object;IIIZ)V",    (void*)nAllocationData3D },
1798{"rsnAllocationData3D",              "(JJIIIIIIIJIIII)V",                     (void*)nAllocationData3D_alloc },
1799{"rsnAllocationRead",                "(JJLjava/lang/Object;IIZ)V",            (void*)nAllocationRead },
1800{"rsnAllocationRead1D",              "(JJIIILjava/lang/Object;IIIZ)V",        (void*)nAllocationRead1D },
1801//{"rsnAllocationElementRead",         "(JJIIIII[BI)V",                         (void*)nAllocationElementRead },
1802{"rsnAllocationRead2D",              "(JJIIIIIILjava/lang/Object;IIIZ)V",     (void*)nAllocationRead2D },
1803//{"rsnAllocationRead3D",              "(JJIIIIIIILjava/lang/Object;IIIZ)V",  (void*)nAllocationRead3D },
1804{"rsnAllocationGetType",             "(JJ)J",                                 (void*)nAllocationGetType},
1805{"rsnAllocationResize1D",            "(JJI)V",                                (void*)nAllocationResize1D },
1806{"rsnAllocationGenerateMipmaps",     "(JJ)V",                                 (void*)nAllocationGenerateMipmaps },
1807
1808{"rsnScriptBindAllocation",          "(JJJIZ)V",                              (void*)nScriptBindAllocation },
1809{"rsnScriptSetTimeZone",             "(JJ[BZ)V",                              (void*)nScriptSetTimeZone },
1810{"rsnScriptInvoke",                  "(JJIZ)V",                               (void*)nScriptInvoke },
1811{"rsnScriptInvokeV",                 "(JJI[BZ)V",                             (void*)nScriptInvokeV },
1812{"rsnScriptForEach",                 "(JJJIJJZ)V",                            (void*)nScriptForEach },
1813{"rsnScriptForEach",                 "(JJJIJJ[BZ)V",                          (void*)nScriptForEachV },
1814{"rsnScriptForEachClipped",          "(JJJIJJIIIIIIZ)V",                      (void*)nScriptForEachClipped },
1815{"rsnScriptForEachClipped",          "(JJJIJJ[BIIIIIIZ)V",                    (void*)nScriptForEachClippedV },
1816{"rsnScriptSetVarI",                 "(JJIIZ)V",                              (void*)nScriptSetVarI },
1817{"rsnScriptSetVarJ",                 "(JJIJZ)V",                              (void*)nScriptSetVarJ },
1818{"rsnScriptSetVarF",                 "(JJIFZ)V",                              (void*)nScriptSetVarF },
1819{"rsnScriptSetVarD",                 "(JJIDZ)V",                              (void*)nScriptSetVarD },
1820{"rsnScriptSetVarV",                 "(JJI[BZ)V",                             (void*)nScriptSetVarV },
1821{"rsnScriptSetVarVE",                "(JJI[BJ[IZ)V",                          (void*)nScriptSetVarVE },
1822{"rsnScriptSetVarObj",               "(JJIJZ)V",                              (void*)nScriptSetVarObj },
1823
1824{"rsnScriptCCreate",                 "(JLjava/lang/String;Ljava/lang/String;[BI)J",  (void*)nScriptCCreate },
1825{"rsnScriptIntrinsicCreate",         "(JIJZ)J",                               (void*)nScriptIntrinsicCreate },
1826{"rsnScriptKernelIDCreate",          "(JJIIZ)J",                              (void*)nScriptKernelIDCreate },
1827{"rsnScriptInvokeIDCreate",          "(JJI)J",                                (void*)nScriptInvokeIDCreate },
1828{"rsnScriptFieldIDCreate",           "(JJIZ)J",                               (void*)nScriptFieldIDCreate },
1829{"rsnScriptGroupCreate",             "(J[J[J[J[J[J)J",                        (void*)nScriptGroupCreate },
1830{"rsnScriptGroup2Create",            "(JLjava/lang/String;Ljava/lang/String;[J)J", (void*)nScriptGroup2Create },
1831{"rsnScriptGroupSetInput",           "(JJJJ)V",                               (void*)nScriptGroupSetInput },
1832{"rsnScriptGroupSetOutput",          "(JJJJ)V",                               (void*)nScriptGroupSetOutput },
1833{"rsnScriptGroupExecute",            "(JJ)V",                                 (void*)nScriptGroupExecute },
1834{"rsnScriptGroup2Execute",           "(JJ)V",                                 (void*)nScriptGroup2Execute },
1835
1836{"rsnSamplerCreate",                 "(JIIIIIF)J",                            (void*)nSamplerCreate },
1837
1838{"rsnSystemGetPointerSize",          "()I",                                   (void*)nSystemGetPointerSize },
1839
1840// Entry points for Inc libRSSupport
1841{"nIncLoadSO",                       "()Z",                                   (bool*)nIncLoadSO },
1842{"nIncDeviceCreate",                 "()J",                                   (void*)nIncDeviceCreate },
1843{"nIncDeviceDestroy",                "(J)V",                                  (void*)nIncDeviceDestroy },
1844{"rsnIncContextCreate",              "(JIII)J",                               (void*)nIncContextCreate },
1845{"rsnIncContextFinish",              "(J)V",                                  (void*)nIncContextFinish },
1846{"rsnIncContextDestroy",             "(J)V",                                  (void*)nIncContextDestroy },
1847{"rsnIncObjDestroy",                 "(JJ)V",                                 (void*)nIncObjDestroy },
1848{"rsnIncElementCreate",              "(JJIZI)J",                              (void*)nIncElementCreate },
1849{"rsnIncTypeCreate",                 "(JJIIIZZI)J",                           (void*)nIncTypeCreate },
1850{"rsnIncAllocationCreateTyped",      "(JJJJ)J",                               (void*)nIncAllocationCreateTyped },
1851};
1852
1853// ---------------------------------------------------------------------------
1854
1855jint JNI_OnLoad(JavaVM* vm, void* reserved)
1856{
1857    JNIEnv* env = NULL;
1858    jclass clazz = NULL;
1859    jint result = -1;
1860
1861    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
1862        //        __android_log_print(ANDROID_LOG_ERROR, LOG_TAG,
1863        //            "ERROR: GetEnv failed\n");
1864        goto bail;
1865    }
1866    if (env == NULL) {
1867        //        __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "ERROR: env == NULL");
1868        goto bail;
1869    }
1870
1871    clazz = env->FindClass(classPathName);
1872    if (clazz == NULL) {
1873        goto bail;
1874    }
1875
1876    if (env->RegisterNatives(clazz, methods, NELEM(methods)) < 0) {
1877        //        __android_log_print(ANDROID_LOG_ERROR, LOG_TAG,
1878        //            "ERROR: MediaPlayer native registration failed\n");
1879        goto bail;
1880    }
1881
1882    /* success -- return valid version number */
1883    result = JNI_VERSION_1_4;
1884
1885bail:
1886    return result;
1887}
1888