android_renderscript_RenderScript.cpp revision 49b1621b2554895c774b534abb2c448803fae3ac
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 targetApi) {
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, targetApi) == 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* jFieldIDs = _env->GetLongArrayElements(fieldIDArray, nullptr);
349  jsize fieldIDs_length = _env->GetArrayLength(fieldIDArray);
350  RsScriptFieldID* fieldIDs =
351      (RsScriptFieldID*)alloca(sizeof(RsScriptFieldID) * fieldIDs_length);
352  for (int i = 0; i< fieldIDs_length; i++) {
353    fieldIDs[i] = (RsScriptFieldID)jFieldIDs[i];
354  }
355
356  jlong* jValues = _env->GetLongArrayElements(valueArray, nullptr);
357  jsize values_length = _env->GetArrayLength(valueArray);
358  uintptr_t* values = (uintptr_t*)alloca(sizeof(uintptr_t) * values_length);
359  for (int i = 0; i < values_length; i++) {
360    values[i] = (uintptr_t)jValues[i];
361  }
362
363  jint* sizes = _env->GetIntArrayElements(sizeArray, nullptr);
364  jsize sizes_length = _env->GetArrayLength(sizeArray);
365
366  jlong* jDepClosures =
367      _env->GetLongArrayElements(depClosureArray, nullptr);
368  jsize depClosures_length = _env->GetArrayLength(depClosureArray);
369  RsClosure* depClosures =
370      (RsClosure*)alloca(sizeof(RsClosure) * depClosures_length);
371  for (int i = 0; i < depClosures_length; i++) {
372    depClosures[i] = (RsClosure)jDepClosures[i];
373  }
374
375  jlong* jDepFieldIDs =
376      _env->GetLongArrayElements(depFieldIDArray, nullptr);
377  jsize depFieldIDs_length = _env->GetArrayLength(depFieldIDArray);
378  RsScriptFieldID* depFieldIDs =
379      (RsScriptFieldID*)alloca(sizeof(RsScriptFieldID) * depFieldIDs_length);
380  for (int i = 0; i < depClosures_length; i++) {
381    depFieldIDs[i] = (RsClosure)jDepFieldIDs[i];
382  }
383
384  return (jlong)(uintptr_t)dispatchTab.ClosureCreate(
385      (RsContext)con, (RsScriptKernelID)kernelID, (RsAllocation)returnValue,
386      fieldIDs, (size_t)fieldIDs_length, values, (size_t)values_length,
387      (int*)sizes, (size_t)sizes_length,
388      depClosures, (size_t)depClosures_length,
389      depFieldIDs, (size_t)depFieldIDs_length);
390}
391
392static jlong
393nInvokeClosureCreate(JNIEnv *_env, jobject _this, jlong con, jlong invokeID,
394                     jbyteArray paramArray, jlongArray fieldIDArray, jlongArray valueArray,
395                     jintArray sizeArray) {
396  jbyte* jParams = _env->GetByteArrayElements(paramArray, nullptr);
397  jsize jParamLength = _env->GetArrayLength(paramArray);
398
399  jlong* jFieldIDs = _env->GetLongArrayElements(fieldIDArray, nullptr);
400  jsize fieldIDs_length = _env->GetArrayLength(fieldIDArray);
401  RsScriptFieldID* fieldIDs =
402      (RsScriptFieldID*)alloca(sizeof(RsScriptFieldID) * fieldIDs_length);
403  for (int i = 0; i< fieldIDs_length; i++) {
404    fieldIDs[i] = (RsScriptFieldID)jFieldIDs[i];
405  }
406
407  jlong* jValues = _env->GetLongArrayElements(valueArray, nullptr);
408  jsize values_length = _env->GetArrayLength(valueArray);
409  uintptr_t* values = (uintptr_t*)alloca(sizeof(uintptr_t) * values_length);
410  for (int i = 0; i < values_length; i++) {
411    values[i] = (uintptr_t)jValues[i];
412  }
413
414  jint* sizes = _env->GetIntArrayElements(sizeArray, nullptr);
415  jsize sizes_length = _env->GetArrayLength(sizeArray);
416
417  return (jlong)(uintptr_t)dispatchTab.InvokeClosureCreate(
418      (RsContext)con, (RsScriptInvokeID)invokeID, jParams, jParamLength,
419      fieldIDs, (size_t)fieldIDs_length, values, (size_t)values_length,
420      (int*)sizes, (size_t)sizes_length);
421}
422
423static void
424nClosureSetArg(JNIEnv *_env, jobject _this, jlong con, jlong closureID,
425               jint index, jlong value, jint size) {
426  dispatchTab.ClosureSetArg((RsContext)con, (RsClosure)closureID, (uint32_t)index,
427                  (uintptr_t)value, (size_t)size);
428}
429
430static void
431nClosureSetGlobal(JNIEnv *_env, jobject _this, jlong con, jlong closureID,
432                  jlong fieldID, jlong value, jint size) {
433  dispatchTab.ClosureSetGlobal((RsContext)con, (RsClosure)closureID,
434                     (RsScriptFieldID)fieldID, (uintptr_t)value, (size_t)size);
435}
436
437static long
438nScriptGroup2Create(JNIEnv *_env, jobject _this, jlong con, jstring name,
439                    jstring cacheDir, jlongArray closureArray) {
440  AutoJavaStringToUTF8 nameUTF(_env, name);
441  AutoJavaStringToUTF8 cacheDirUTF(_env, cacheDir);
442
443  jlong* jClosures = _env->GetLongArrayElements(closureArray, nullptr);
444  jsize numClosures = _env->GetArrayLength(closureArray);
445  RsClosure* closures = (RsClosure*)alloca(sizeof(RsClosure) * numClosures);
446  for (int i = 0; i < numClosures; i++) {
447    closures[i] = (RsClosure)jClosures[i];
448  }
449
450  return (jlong)(uintptr_t)dispatchTab.ScriptGroup2Create(
451      (RsContext)con, nameUTF.c_str(), nameUTF.length(),
452      cacheDirUTF.c_str(), cacheDirUTF.length(),
453      closures, numClosures);
454}
455
456static void
457nScriptGroup2Execute(JNIEnv *_env, jobject _this, jlong con, jlong groupID) {
458  dispatchTab.ScriptGroupExecute((RsContext)con, (RsScriptGroup2)groupID);
459}
460
461static void
462nObjDestroy(JNIEnv *_env, jobject _this, jlong con, jlong obj)
463{
464    LOG_API("nObjDestroy, con(%p) obj(%p)", (RsContext)con, (void *)obj);
465    dispatchTab.ObjDestroy((RsContext)con, (void *)obj);
466}
467
468// ---------------------------------------------------------------------------
469static jlong
470nDeviceCreate(JNIEnv *_env, jobject _this)
471{
472    LOG_API("nDeviceCreate");
473    return (jlong)(uintptr_t)dispatchTab.DeviceCreate();
474}
475
476static void
477nDeviceDestroy(JNIEnv *_env, jobject _this, jlong dev)
478{
479    LOG_API("nDeviceDestroy");
480    return dispatchTab.DeviceDestroy((RsDevice)dev);
481}
482
483static void
484nDeviceSetConfig(JNIEnv *_env, jobject _this, jlong dev, jint p, jint value)
485{
486    LOG_API("nDeviceSetConfig  dev(%p), param(%i), value(%i)", (void *)dev, p, value);
487    return dispatchTab.DeviceSetConfig((RsDevice)dev, (RsDeviceParam)p, value);
488}
489
490static jlong
491nContextCreate(JNIEnv *_env, jobject _this, jlong dev, jint ver, jint sdkVer,
492               jint ct, jstring nativeLibDirJava)
493{
494    LOG_API("nContextCreate");
495    // Access the NativeLibDir in the Java Context.
496    const char * nativeLibDir = _env->GetStringUTFChars(nativeLibDirJava, JNI_FALSE);
497    size_t length = (size_t)_env->GetStringUTFLength(nativeLibDirJava);
498
499    jlong id = (jlong)(uintptr_t)dispatchTab.ContextCreate((RsDevice)dev, ver,
500                                                           sdkVer,
501                                                           (RsContextType)ct, 0);
502    if (dispatchTab.SetNativeLibDir) {
503        dispatchTab.SetNativeLibDir((RsContext)id, nativeLibDir, length);
504    }
505
506    _env->ReleaseStringUTFChars(nativeLibDirJava, nativeLibDir);
507    return id;
508}
509
510
511static void
512nContextSetPriority(JNIEnv *_env, jobject _this, jlong con, jint p)
513{
514    LOG_API("ContextSetPriority, con(%p), priority(%i)", (RsContext)con, p);
515    dispatchTab.ContextSetPriority((RsContext)con, p);
516}
517
518
519
520static void
521nContextDestroy(JNIEnv *_env, jobject _this, jlong con)
522{
523    LOG_API("nContextDestroy, con(%p)", (RsContext)con);
524    dispatchTab.ContextDestroy((RsContext)con);
525}
526
527static void
528nContextDump(JNIEnv *_env, jobject _this, jlong con, jint bits)
529{
530    LOG_API("nContextDump, con(%p)  bits(%i)", (RsContext)con, bits);
531    dispatchTab.ContextDump((RsContext)con, bits);
532}
533
534
535static jstring
536nContextGetErrorMessage(JNIEnv *_env, jobject _this, jlong con)
537{
538    LOG_API("nContextGetErrorMessage, con(%p)", (RsContext)con);
539    char buf[1024];
540
541    size_t receiveLen;
542    uint32_t subID;
543    int id = dispatchTab.ContextGetMessage((RsContext)con,
544                                           buf, sizeof(buf),
545                                           &receiveLen, sizeof(receiveLen),
546                                           &subID, sizeof(subID));
547    if (!id && receiveLen) {
548        //        __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG,
549        //            "message receive buffer too small.  %zu", receiveLen);
550    }
551    return _env->NewStringUTF(buf);
552}
553
554static jint
555nContextGetUserMessage(JNIEnv *_env, jobject _this, jlong con, jintArray data)
556{
557    jint len = _env->GetArrayLength(data);
558    LOG_API("nContextGetMessage, con(%p), len(%i)", (RsContext)con, len);
559    jint *ptr = _env->GetIntArrayElements(data, NULL);
560    size_t receiveLen;
561    uint32_t subID;
562    int id = dispatchTab.ContextGetMessage((RsContext)con,
563                                           ptr, len * 4,
564                                           &receiveLen, sizeof(receiveLen),
565                                           &subID, sizeof(subID));
566    if (!id && receiveLen) {
567        //        __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG,
568        //            "message receive buffer too small.  %zu", receiveLen);
569    }
570    _env->ReleaseIntArrayElements(data, ptr, 0);
571    return (jint)id;
572}
573
574static jint
575nContextPeekMessage(JNIEnv *_env, jobject _this, jlong con, jintArray auxData)
576{
577    LOG_API("nContextPeekMessage, con(%p)", (RsContext)con);
578    jint *auxDataPtr = _env->GetIntArrayElements(auxData, NULL);
579    size_t receiveLen;
580    uint32_t subID;
581    int id = dispatchTab.ContextPeekMessage((RsContext)con, &receiveLen, sizeof(receiveLen),
582                                  &subID, sizeof(subID));
583    auxDataPtr[0] = (jint)subID;
584    auxDataPtr[1] = (jint)receiveLen;
585    _env->ReleaseIntArrayElements(auxData, auxDataPtr, 0);
586    return (jint)id;
587}
588
589static void nContextInitToClient(JNIEnv *_env, jobject _this, jlong con)
590{
591    LOG_API("nContextInitToClient, con(%p)", (RsContext)con);
592    dispatchTab.ContextInitToClient((RsContext)con);
593}
594
595static void nContextDeinitToClient(JNIEnv *_env, jobject _this, jlong con)
596{
597    LOG_API("nContextDeinitToClient, con(%p)", (RsContext)con);
598    dispatchTab.ContextDeinitToClient((RsContext)con);
599}
600
601static void
602nContextSendMessage(JNIEnv *_env, jobject _this, jlong con, jint id, jintArray data)
603{
604    jint *ptr = NULL;
605    jint len = 0;
606    if (data) {
607        len = _env->GetArrayLength(data);
608        jint *ptr = _env->GetIntArrayElements(data, NULL);
609    }
610    LOG_API("nContextSendMessage, con(%p), id(%i), len(%i)", (RsContext)con, id, len);
611    dispatchTab.ContextSendMessage((RsContext)con, id, (const uint8_t *)ptr, len * sizeof(int));
612    if (data) {
613        _env->ReleaseIntArrayElements(data, ptr, JNI_ABORT);
614    }
615}
616
617
618
619static jlong
620nElementCreate(JNIEnv *_env, jobject _this, jlong con, jlong type, jint kind,
621               jboolean norm, jint size)
622{
623    LOG_API("nElementCreate, con(%p), type(%i), kind(%i), norm(%i), size(%i)", (RsContext)con,
624            type, kind, norm, size);
625    return (jlong)(uintptr_t)dispatchTab.ElementCreate((RsContext)con,
626                                                       (RsDataType)type,
627                                                       (RsDataKind)kind,
628                                                       norm, size);
629}
630
631static jlong
632nElementCreate2(JNIEnv *_env, jobject _this, jlong con,
633                jlongArray _ids, jobjectArray _names, jintArray _arraySizes)
634{
635    int fieldCount = _env->GetArrayLength(_ids);
636    LOG_API("nElementCreate2, con(%p)", (RsContext)con);
637
638    jlong *jIds = _env->GetLongArrayElements(_ids, NULL);
639    jint *jArraySizes = _env->GetIntArrayElements(_arraySizes, NULL);
640
641    RsElement *ids = (RsElement*)malloc(fieldCount * sizeof(RsElement));
642    uint32_t *arraySizes = (uint32_t *)malloc(fieldCount * sizeof(uint32_t));
643
644    for(int i = 0; i < fieldCount; i ++) {
645        ids[i] = (RsElement)jIds[i];
646        arraySizes[i] = (uint32_t)jArraySizes[i];
647    }
648
649    AutoJavaStringArrayToUTF8 names(_env, _names, fieldCount);
650
651    const char **nameArray = names.c_str();
652    size_t *sizeArray = names.c_str_len();
653
654    jlong id = (jlong)(uintptr_t)dispatchTab.ElementCreate2((RsContext)con, (RsElement *)ids,
655                                                            fieldCount, nameArray,
656                                                            fieldCount * sizeof(size_t),  sizeArray,
657                                                            (const uint32_t *)arraySizes, fieldCount);
658
659    free(ids);
660    free(arraySizes);
661    _env->ReleaseLongArrayElements(_ids, jIds, JNI_ABORT);
662    _env->ReleaseIntArrayElements(_arraySizes, jArraySizes, JNI_ABORT);
663    return id;
664}
665
666
667
668
669static void
670nElementGetSubElements(JNIEnv *_env, jobject _this, jlong con, jlong id,
671                       jlongArray _IDs,
672                       jobjectArray _names,
673                       jintArray _arraySizes)
674{
675    uint32_t dataSize = _env->GetArrayLength(_IDs);
676    LOG_API("nElementGetSubElements, con(%p)", (RsContext)con);
677
678    uintptr_t *ids = (uintptr_t *)malloc(dataSize * sizeof(uintptr_t));
679    const char **names = (const char **)malloc((uint32_t)dataSize * sizeof(const char *));
680    uint32_t *arraySizes = (uint32_t *)malloc((uint32_t)dataSize * sizeof(uint32_t));
681
682    dispatchTab.ElementGetSubElements((RsContext)con, (RsElement)id, ids, names, arraySizes,
683                                      (uint32_t)dataSize);
684
685    for(uint32_t i = 0; i < dataSize; i++) {
686        const jlong id = (jlong)(uintptr_t)ids[i];
687        const jint arraySize = (jint)arraySizes[i];
688        _env->SetObjectArrayElement(_names, i, _env->NewStringUTF(names[i]));
689        _env->SetLongArrayRegion(_IDs, i, 1, &id);
690        _env->SetIntArrayRegion(_arraySizes, i, 1, &arraySize);
691    }
692
693    free(ids);
694    free(names);
695    free(arraySizes);
696}
697
698// -----------------------------------
699
700static jlong
701nTypeCreate(JNIEnv *_env, jobject _this, jlong con, jlong eid,
702            jint dimx, jint dimy, jint dimz, jboolean mips, jboolean faces, jint yuv)
703{
704    LOG_API("nTypeCreate, con(%p) eid(%p), x(%i), y(%i), z(%i), mips(%i), faces(%i), yuv(%i)",
705            (RsContext)con, eid, dimx, dimy, dimz, mips, faces, yuv);
706
707    return (jlong)(uintptr_t)dispatchTab.TypeCreate((RsContext)con, (RsElement)eid, dimx, dimy,
708                                                    dimz, mips, faces, yuv);
709}
710
711// -----------------------------------
712
713static jlong
714nAllocationCreateTyped(JNIEnv *_env, jobject _this, jlong con, jlong type, jint mips, jint usage,
715                       jlong pointer)
716{
717    LOG_API("nAllocationCreateTyped, con(%p), type(%p), mip(%i), usage(%i), ptr(%p)",
718            (RsContext)con, (RsElement)type, mips, usage, (void *)pointer);
719    return (jlong)(uintptr_t) dispatchTab.AllocationCreateTyped((RsContext)con, (RsType)type,
720                                                                (RsAllocationMipmapControl)mips,
721                                                                (uint32_t)usage, (uintptr_t)pointer);
722}
723
724static void
725nAllocationSyncAll(JNIEnv *_env, jobject _this, jlong con, jlong a, jint bits)
726{
727    LOG_API("nAllocationSyncAll, con(%p), a(%p), bits(0x%08x)", (RsContext)con, (RsAllocation)a, bits);
728    dispatchTab.AllocationSyncAll((RsContext)con, (RsAllocation)a, (RsAllocationUsageType)bits);
729}
730
731static void
732nAllocationSetSurface(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jobject sur)
733{
734    ioDispatch.sAllocationSetSurface(_env, _this, (RsContext)con, (RsAllocation)alloc, sur, dispatchTab);
735}
736
737static void
738nAllocationIoSend(JNIEnv *_env, jobject _this, jlong con, jlong alloc)
739{
740    dispatchTab.AllocationIoSend((RsContext)con, (RsAllocation)alloc);
741}
742
743static void
744nAllocationGenerateMipmaps(JNIEnv *_env, jobject _this, jlong con, jlong alloc)
745{
746    LOG_API("nAllocationGenerateMipmaps, con(%p), a(%p)", (RsContext)con, (RsAllocation)alloc);
747    dispatchTab.AllocationGenerateMipmaps((RsContext)con, (RsAllocation)alloc);
748}
749
750static size_t GetBitmapSize(JNIEnv *env, jobject jbitmap) {
751    AndroidBitmapInfo info;
752    memset(&info, 0, sizeof(info));
753    AndroidBitmap_getInfo(env, jbitmap, &info);
754    size_t s = info.width * info.height;
755    switch (info.format) {
756        case ANDROID_BITMAP_FORMAT_RGBA_8888: s *= 4; break;
757        case ANDROID_BITMAP_FORMAT_RGB_565: s *= 2; break;
758        case ANDROID_BITMAP_FORMAT_RGBA_4444: s *= 2; break;
759    }
760    return s;
761}
762
763static jlong
764nAllocationCreateFromBitmap(JNIEnv *_env, jobject _this, jlong con, jlong type, jint mip,
765                            jobject jbitmap, jint usage)
766{
767    jlong id = 0;
768    void *pixels = NULL;
769    AndroidBitmap_lockPixels(_env, jbitmap, &pixels);
770
771    if (pixels != NULL) {
772        id = (jlong)(uintptr_t)dispatchTab.AllocationCreateFromBitmap((RsContext)con,
773                                                                      (RsType)type,
774                                                                      (RsAllocationMipmapControl)mip,
775                                                                      pixels,
776                                                                      GetBitmapSize(_env, jbitmap),
777                                                                      usage);
778        AndroidBitmap_unlockPixels(_env, jbitmap);
779    }
780    return id;
781}
782
783static jlong
784nAllocationCreateBitmapBackedAllocation(JNIEnv *_env, jobject _this, jlong con, jlong type,
785                                        jint mip, jobject jbitmap, jint usage)
786{
787    jlong id = 0;
788    void *pixels = NULL;
789    AndroidBitmap_lockPixels(_env, jbitmap, &pixels);
790
791    if (pixels != NULL) {
792        id = (jlong)(uintptr_t)dispatchTab.AllocationCreateTyped((RsContext)con,
793                                                                 (RsType)type,
794                                                                 (RsAllocationMipmapControl)mip,
795                                                                 (uint32_t)usage,
796                                                                 (uintptr_t)pixels);
797        AndroidBitmap_unlockPixels(_env, jbitmap);
798    }
799    return id;
800}
801
802static jlong
803nAllocationCubeCreateFromBitmap(JNIEnv *_env, jobject _this, jlong con, jlong type,
804                                jint mip, jobject jbitmap, jint usage)
805{
806    void *pixels = NULL;
807    AndroidBitmap_lockPixels(_env, jbitmap, &pixels);
808
809    jlong id = 0;
810    if (pixels != NULL) {
811        id = (jlong)(uintptr_t)dispatchTab.AllocationCubeCreateFromBitmap((RsContext)con,
812                                                                          (RsType)type,
813                                                                          (RsAllocationMipmapControl)mip,
814                                                                          pixels,
815                                                                          GetBitmapSize(_env, jbitmap),
816                                                                          usage);
817        AndroidBitmap_unlockPixels(_env, jbitmap);
818    }
819    return id;
820}
821
822static void
823nAllocationCopyFromBitmap(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jobject jbitmap)
824{
825    AndroidBitmapInfo info;
826    memset(&info, 0, sizeof(info));
827    AndroidBitmap_getInfo(_env, jbitmap, &info);
828
829    void *pixels = NULL;
830    AndroidBitmap_lockPixels(_env, jbitmap, &pixels);
831
832    if (pixels != NULL) {
833        dispatchTab.Allocation2DData((RsContext)con, (RsAllocation)alloc, 0, 0, 0,
834                                     RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X, info.width,
835                                     info.height, pixels, GetBitmapSize(_env, jbitmap), 0);
836        AndroidBitmap_unlockPixels(_env, jbitmap);
837    }
838}
839
840static void
841nAllocationCopyToBitmap(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jobject jbitmap)
842{
843    AndroidBitmapInfo info;
844    memset(&info, 0, sizeof(info));
845    AndroidBitmap_getInfo(_env, jbitmap, &info);
846
847    void *pixels = NULL;
848    AndroidBitmap_lockPixels(_env, jbitmap, &pixels);
849
850    if (pixels != NULL) {
851        dispatchTab.AllocationCopyToBitmap((RsContext)con, (RsAllocation)alloc, pixels,
852                                           GetBitmapSize(_env, jbitmap));
853        AndroidBitmap_unlockPixels(_env, jbitmap);
854    }
855    //bitmap.notifyPixelsChanged();
856}
857
858// Copies from the Java object data into the Allocation pointed to by _alloc.
859static void
860nAllocationData1D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint offset, jint lod,
861                  jint count, jobject data, jint sizeBytes, jint dataType, jint mSize,
862                  jboolean usePadding)
863{
864    RsAllocation *alloc = (RsAllocation *)_alloc;
865    LOG_API("nAllocation1DData, con(%p), adapter(%p), offset(%i), count(%i), sizeBytes(%i), "
866            "dataType(%i)", (RsContext)con, (RsAllocation)alloc, offset, count, sizeBytes,
867            dataType);
868    PER_ARRAY_TYPE(nullptr, dispatchTab.Allocation1DData, true,
869                   (RsContext)con, alloc, offset, lod, count, ptr, sizeBytes);
870}
871
872
873static void
874nAllocationElementData1D(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jint xoff,
875                         jint lod, jint compIdx, jbyteArray data, jint sizeBytes)
876{
877    jint len = _env->GetArrayLength(data);
878    LOG_API("nAllocationElementData1D, con(%p), alloc(%p), xoff(%i), comp(%i), len(%i), "
879            "sizeBytes(%i)", (RsContext)con, (RsAllocation)alloc, xoff, compIdx, len,
880            sizeBytes);
881    jbyte *ptr = _env->GetByteArrayElements(data, nullptr);
882    dispatchTab.Allocation1DElementData((RsContext)con, (RsAllocation)alloc, xoff,
883                                        lod, ptr, sizeBytes, compIdx);
884    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
885}
886
887/*
888static void
889nAllocationElementData(JNIEnv *_env, jobject _this, jlong con, jlong alloc,
890                       jint xoff, jint yoff, jint zoff,
891                       jint lod, jint compIdx, jbyteArray data, jint sizeBytes)
892{
893    jint len = _env->GetArrayLength(data);
894    LOG_API("nAllocationElementData, con(%p), alloc(%p), xoff(%i), yoff(%i), zoff(%i), comp(%i), len(%i), "
895            "sizeBytes(%i)", (RsContext)con, (RsAllocation)alloc, xoff, yoff, zoff, compIdx, len,
896            sizeBytes);
897    jbyte *ptr = _env->GetByteArrayElements(data, nullptr);
898    dispatchTab.AllocationElementData((RsContext)con, (RsAllocation)alloc,
899                                      xoff, yoff, zoff,
900                                      lod, ptr, sizeBytes, compIdx);
901    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
902}
903*/
904
905// Copies from the Java object data into the Allocation pointed to by _alloc.
906static void
907nAllocationData2D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint xoff, jint yoff, jint lod, jint _face,
908                  jint w, jint h, jobject data, jint sizeBytes, jint dataType, jint mSize,
909                  jboolean usePadding)
910{
911    RsAllocation *alloc = (RsAllocation *)_alloc;
912    RsAllocationCubemapFace face = (RsAllocationCubemapFace)_face;
913    LOG_API("nAllocation2DData, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i) "
914            "type(%i)", (RsContext)con, alloc, xoff, yoff, w, h, sizeBytes, dataType);
915    int count = w * h;
916    PER_ARRAY_TYPE(nullptr, dispatchTab.Allocation2DData, true,
917                   (RsContext)con, alloc, xoff, yoff, lod, face, w, h, ptr, sizeBytes, 0);
918}
919
920static void
921nAllocationData2D_alloc(JNIEnv *_env, jobject _this, jlong con,
922                        jlong dstAlloc, jint dstXoff, jint dstYoff,
923                        jint dstMip, jint dstFace,
924                        jint width, jint height,
925                        jlong srcAlloc, jint srcXoff, jint srcYoff,
926                        jint srcMip, jint srcFace)
927{
928    LOG_API("nAllocation2DData_s, con(%p), dstAlloc(%p), dstXoff(%i), dstYoff(%i),"
929            " dstMip(%i), dstFace(%i), width(%i), height(%i),"
930            " srcAlloc(%p), srcXoff(%i), srcYoff(%i), srcMip(%i), srcFace(%i)",
931            (RsContext)con, (RsAllocation)dstAlloc, dstXoff, dstYoff, dstMip, dstFace,
932            width, height, (RsAllocation)srcAlloc, srcXoff, srcYoff, srcMip, srcFace);
933
934    dispatchTab.AllocationCopy2DRange((RsContext)con,
935                                      (RsAllocation)dstAlloc,
936                                      dstXoff, dstYoff,
937                                      dstMip, dstFace,
938                                      width, height,
939                                      (RsAllocation)srcAlloc,
940                                      srcXoff, srcYoff,
941                                      srcMip, srcFace);
942}
943
944// Copies from the Java object data into the Allocation pointed to by _alloc.
945static void
946nAllocationData3D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint xoff, jint yoff, jint zoff, jint lod,
947                  jint w, jint h, jint d, jobject data, jint sizeBytes, jint dataType,
948                  jint mSize, jboolean usePadding)
949{
950    RsAllocation *alloc = (RsAllocation *)_alloc;
951    LOG_API("nAllocation3DData, con(%p), alloc(%p), xoff(%i), yoff(%i), zoff(%i), lod(%i), w(%i),"
952            " h(%i), d(%i), sizeBytes(%i)", (RsContext)con, (RsAllocation)alloc, xoff, yoff, zoff,
953            lod, w, h, d, sizeBytes);
954    int count = w * h * d;
955    PER_ARRAY_TYPE(nullptr, dispatchTab.Allocation3DData, true,
956                   (RsContext)con, alloc, xoff, yoff, zoff, lod, w, h, d, ptr, sizeBytes, 0);
957}
958
959static void
960nAllocationData3D_alloc(JNIEnv *_env, jobject _this, jlong con,
961                        jlong dstAlloc, jint dstXoff, jint dstYoff, jint dstZoff,
962                        jint dstMip,
963                        jint width, jint height, jint depth,
964                        jlong srcAlloc, jint srcXoff, jint srcYoff, jint srcZoff,
965                        jint srcMip)
966{
967    LOG_API("nAllocationData3D_alloc, con(%p), dstAlloc(%p), dstXoff(%i), dstYoff(%i),"
968            " dstMip(%i), width(%i), height(%i),"
969            " srcAlloc(%p), srcXoff(%i), srcYoff(%i), srcMip(%i)",
970            (RsContext)con, (RsAllocation)dstAlloc, dstXoff, dstYoff, dstMip, dstFace,
971            width, height, (RsAllocation)srcAlloc, srcXoff, srcYoff, srcMip, srcFace);
972
973    dispatchTab.AllocationCopy3DRange((RsContext)con,
974                                      (RsAllocation)dstAlloc,
975                                      dstXoff, dstYoff, dstZoff, dstMip,
976                                      width, height, depth,
977                                      (RsAllocation)srcAlloc,
978                                      srcXoff, srcYoff, srcZoff, srcMip);
979}
980
981// Copies from the Allocation pointed to by _alloc into the Java object data.
982static void
983nAllocationRead(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jobject data, jint dataType,
984                jint mSize, jboolean usePadding)
985{
986    RsAllocation *alloc = (RsAllocation *)_alloc;
987    LOG_API("nAllocationRead, con(%p), alloc(%p)", (RsContext)con, (RsAllocation)alloc);
988    int count = 0;
989    PER_ARRAY_TYPE(0, dispatchTab.AllocationRead, false,
990                   (RsContext)con, alloc, ptr, len * typeBytes);
991}
992
993// Copies from the Allocation pointed to by _alloc into the Java object data.
994static void
995nAllocationRead1D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint offset, jint lod,
996                  jint count, jobject data, jint sizeBytes, jint dataType,
997                  jint mSize, jboolean usePadding)
998{
999    RsAllocation *alloc = (RsAllocation *)_alloc;
1000    LOG_API("nAllocation1DRead, con(%p), adapter(%p), offset(%i), count(%i), sizeBytes(%i), "
1001              "dataType(%i)", (RsContext)con, alloc, offset, count, sizeBytes, dataType);
1002    PER_ARRAY_TYPE(0, dispatchTab.Allocation1DRead, false,
1003                   (RsContext)con, alloc, offset, lod, count, ptr, sizeBytes);
1004}
1005
1006// Copies from the Element in the Allocation pointed to by _alloc into the Java array data.
1007/*
1008static void
1009nAllocationElementRead(JNIEnv *_env, jobject _this, jlong con, jlong _alloc,
1010                       jint xoff, jint yoff, jint zoff,
1011                       jint lod, jint compIdx, jobject data, jint sizeBytes)
1012{
1013    jint len = _env->GetArrayLength(data);
1014    LOG_API("nAllocationElementRead, con(%p), alloc(%p), xoff(%i), yoff(%i), zoff(%i), comp(%i), len(%i), "
1015            "sizeBytes(%i)", (RsContext)con, (RsAllocation)alloc, xoff, yoff, zoff, compIdx, len,
1016            sizeBytes);
1017    jbyte *ptr = _env->GetByteArrayElements(data, nullptr);
1018    dispatchTab.AllocationElementRead((RsContext)con, (RsAllocation)alloc,
1019                                      xoff, yoff, zoff,
1020                                      lod, ptr, sizeBytes, compIdx);
1021    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
1022}
1023*/
1024
1025// Copies from the Allocation pointed to by _alloc into the Java object data.
1026static void
1027nAllocationRead2D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint xoff, jint yoff, jint lod, jint _face,
1028                  jint w, jint h, jobject data, jint sizeBytes, jint dataType,
1029                  jint mSize, jboolean usePadding)
1030{
1031    RsAllocation *alloc = (RsAllocation *)_alloc;
1032    RsAllocationCubemapFace face = (RsAllocationCubemapFace)_face;
1033    LOG_API("nAllocation2DRead, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i) "
1034              "type(%i)", (RsContext)con, alloc, xoff, yoff, w, h, sizeBytes, dataType);
1035    int count = w * h;
1036    PER_ARRAY_TYPE(0, dispatchTab.Allocation2DRead, false,
1037                   (RsContext)con, alloc, xoff, yoff, lod, face, w, h, ptr, sizeBytes, 0);
1038}
1039
1040// Copies from the Allocation pointed to by _alloc into the Java object data.
1041/*
1042static void
1043nAllocationRead3D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint xoff, jint yoff, jint zoff, jint lod,
1044                  jint w, jint h, jint d, jobject data, int sizeBytes, int dataType,
1045                  jint mSize, jboolean usePadding)
1046{
1047    RsAllocation *alloc = (RsAllocation *)_alloc;
1048    LOG_API("nAllocation3DRead, con(%p), alloc(%p), xoff(%i), yoff(%i), zoff(%i), lod(%i), w(%i),"
1049            " h(%i), d(%i), sizeBytes(%i)", (RsContext)con, (RsAllocation)alloc, xoff, yoff, zoff,
1050            lod, w, h, d, sizeBytes);
1051    int count = w * h * d;
1052    PER_ARRAY_TYPE(nullptr, dispatchTab.Allocation3DRead, false,
1053                   (RsContext)con, alloc, xoff, yoff, zoff, lod, w, h, d, ptr, sizeBytes, 0);
1054}
1055*/
1056
1057static jlong
1058nAllocationGetType(JNIEnv *_env, jobject _this, jlong con, jlong a)
1059{
1060    LOG_API("nAllocationGetType, con(%p), a(%p)", (RsContext)con, (RsAllocation)a);
1061    return (jlong)(uintptr_t) dispatchTab.AllocationGetType((RsContext)con, (RsAllocation)a);
1062}
1063
1064static void
1065nAllocationResize1D(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jint dimX)
1066{
1067    LOG_API("nAllocationResize1D, con(%p), alloc(%p), sizeX(%i)", (RsContext)con,
1068            (RsAllocation)alloc, dimX);
1069    dispatchTab.AllocationResize1D((RsContext)con, (RsAllocation)alloc, dimX);
1070}
1071
1072// -----------------------------------
1073
1074static void
1075nScriptBindAllocation(JNIEnv *_env, jobject _this, jlong con, jlong script, jlong alloc, jint slot, jboolean mUseInc)
1076{
1077    LOG_API("nScriptBindAllocation, con(%p), script(%p), alloc(%p), slot(%i)",
1078            (RsContext)con, (RsScript)script, (RsAllocation)alloc, slot);
1079    if (mUseInc) {
1080        dispatchTabInc.ScriptBindAllocation((RsContext)con, (RsScript)script, (RsAllocation)alloc, slot);
1081    } else {
1082        dispatchTab.ScriptBindAllocation((RsContext)con, (RsScript)script, (RsAllocation)alloc, slot);
1083    }
1084}
1085
1086static void
1087nScriptSetVarI(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jint val, jboolean mUseInc)
1088{
1089    LOG_API("nScriptSetVarI, con(%p), s(%p), slot(%i), val(%i)", (RsContext)con,
1090            (void *)script, slot, val);
1091    if (mUseInc) {
1092        dispatchTabInc.ScriptSetVarI((RsContext)con, (RsScript)script, slot, val);
1093    } else {
1094        dispatchTab.ScriptSetVarI((RsContext)con, (RsScript)script, slot, val);
1095    }
1096}
1097
1098static void
1099nScriptSetVarObj(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jlong val, jboolean mUseInc)
1100{
1101    LOG_API("nScriptSetVarObj, con(%p), s(%p), slot(%i), val(%i)", (RsContext)con,
1102            (void *)script, slot, val);
1103    if (mUseInc) {
1104        dispatchTabInc.ScriptSetVarObj((RsContext)con, (RsScript)script, slot, (RsObjectBase)val);
1105    } else {
1106        dispatchTab.ScriptSetVarObj((RsContext)con, (RsScript)script, slot, (RsObjectBase)val);
1107    }
1108}
1109
1110static void
1111nScriptSetVarJ(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jlong val, jboolean mUseInc)
1112{
1113    LOG_API("nScriptSetVarJ, con(%p), s(%p), slot(%i), val(%lli)", (RsContext)con,
1114            (void *)script, slot, val);
1115    if (mUseInc) {
1116        dispatchTabInc.ScriptSetVarJ((RsContext)con, (RsScript)script, slot, val);
1117    } else {
1118        dispatchTab.ScriptSetVarJ((RsContext)con, (RsScript)script, slot, val);
1119    }
1120}
1121
1122static void
1123nScriptSetVarF(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, float val, jboolean mUseInc)
1124{
1125    LOG_API("nScriptSetVarF, con(%p), s(%p), slot(%i), val(%f)", (RsContext)con,
1126            (void *)script, slot, val);
1127    if (mUseInc) {
1128        dispatchTabInc.ScriptSetVarF((RsContext)con, (RsScript)script, slot, val);
1129    } else {
1130        dispatchTab.ScriptSetVarF((RsContext)con, (RsScript)script, slot, val);
1131    }
1132}
1133
1134static void
1135nScriptSetVarD(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, double val, jboolean mUseInc)
1136{
1137    LOG_API("nScriptSetVarD, con(%p), s(%p), slot(%i), val(%lf)", (RsContext)con,
1138            (void *)script, slot, val);
1139    if (mUseInc) {
1140        dispatchTabInc.ScriptSetVarD((RsContext)con, (RsScript)script, slot, val);
1141    } else {
1142        dispatchTab.ScriptSetVarD((RsContext)con, (RsScript)script, slot, val);
1143    }
1144}
1145
1146static void
1147nScriptSetVarV(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jbyteArray data, jboolean mUseInc)
1148{
1149    LOG_API("nScriptSetVarV, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
1150    jint len = _env->GetArrayLength(data);
1151    jbyte *ptr = _env->GetByteArrayElements(data, NULL);
1152    if (mUseInc) {
1153        dispatchTabInc.ScriptSetVarV((RsContext)con, (RsScript)script, slot, ptr, len);
1154    } else {
1155        dispatchTab.ScriptSetVarV((RsContext)con, (RsScript)script, slot, ptr, len);
1156    }
1157    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
1158}
1159
1160static void
1161nScriptSetVarVE(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jbyteArray data,
1162                jlong elem, jintArray dims, jboolean mUseInc)
1163{
1164    LOG_API("nScriptSetVarVE, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
1165    jint len = _env->GetArrayLength(data);
1166    jbyte *ptr = _env->GetByteArrayElements(data, NULL);
1167    jint dimsLen = _env->GetArrayLength(dims) * sizeof(int);
1168    jint *dimsPtr = _env->GetIntArrayElements(dims, NULL);
1169    if (mUseInc) {
1170        dispatchTabInc.ScriptSetVarVE((RsContext)con, (RsScript)script, slot, ptr, len, (RsElement)elem,
1171                                      (const uint32_t *)dimsPtr, dimsLen);
1172    } else {
1173        dispatchTab.ScriptSetVarVE((RsContext)con, (RsScript)script, slot, ptr, len, (RsElement)elem,
1174                                   (const uint32_t *)dimsPtr, dimsLen);
1175    }
1176    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
1177    _env->ReleaseIntArrayElements(dims, dimsPtr, JNI_ABORT);
1178}
1179
1180
1181static void
1182nScriptSetTimeZone(JNIEnv *_env, jobject _this, jlong con, jlong script, jbyteArray timeZone, jboolean mUseInc)
1183{
1184    LOG_API("nScriptCSetTimeZone, con(%p), s(%p), timeZone(%s)", (RsContext)con,
1185            (void *)script, (const char *)timeZone);
1186
1187    jint length = _env->GetArrayLength(timeZone);
1188    jbyte* timeZone_ptr;
1189    timeZone_ptr = (jbyte *) _env->GetPrimitiveArrayCritical(timeZone, (jboolean *)0);
1190    if (mUseInc) {
1191        dispatchTabInc.ScriptSetTimeZone((RsContext)con, (RsScript)script, (const char *)timeZone_ptr, length);
1192    } else {
1193        dispatchTab.ScriptSetTimeZone((RsContext)con, (RsScript)script, (const char *)timeZone_ptr, length);
1194    }
1195
1196    if (timeZone_ptr) {
1197        _env->ReleasePrimitiveArrayCritical(timeZone, timeZone_ptr, 0);
1198    }
1199}
1200
1201static void
1202nScriptInvoke(JNIEnv *_env, jobject _this, jlong con, jlong obj, jint slot, jboolean mUseInc)
1203{
1204    LOG_API("nScriptInvoke, con(%p), script(%p)", (RsContext)con, (void *)obj);
1205    if (mUseInc) {
1206        dispatchTabInc.ScriptInvoke((RsContext)con, (RsScript)obj, slot);
1207    } else {
1208        dispatchTab.ScriptInvoke((RsContext)con, (RsScript)obj, slot);
1209    }
1210}
1211
1212static void
1213nScriptInvokeV(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jbyteArray data, jboolean mUseInc)
1214{
1215    LOG_API("nScriptInvokeV, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
1216    jint len = _env->GetArrayLength(data);
1217    jbyte *ptr = _env->GetByteArrayElements(data, NULL);
1218    if (mUseInc) {
1219        dispatchTabInc.ScriptInvokeV((RsContext)con, (RsScript)script, slot, ptr, len);
1220    } else {
1221        dispatchTab.ScriptInvokeV((RsContext)con, (RsScript)script, slot, ptr, len);
1222    }
1223    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
1224}
1225
1226static void
1227nScriptForEach(JNIEnv *_env, jobject _this, jlong con, jlong incCon,
1228               jlong script, jint slot, jlong ain, jlong aout, jboolean mUseInc)
1229{
1230    LOG_API("nScriptForEach, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
1231    if (mUseInc) {
1232        dispatchTab.ContextFinish((RsContext)con);
1233        dispatchTabInc.ScriptForEach((RsContext)incCon, (RsScript)script, slot,
1234                                     (RsAllocation)ain, (RsAllocation)aout,
1235                                     NULL, 0, NULL, 0);
1236    } else {
1237        dispatchTab.ScriptForEach((RsContext)con, (RsScript)script, slot,
1238                                  (RsAllocation)ain, (RsAllocation)aout,
1239                                  NULL, 0, NULL, 0);
1240    }
1241}
1242static void
1243nScriptForEachV(JNIEnv *_env, jobject _this, jlong con, jlong incCon,
1244                jlong script, jint slot, jlong ain, jlong aout, jbyteArray params, jboolean mUseInc)
1245{
1246    LOG_API("nScriptForEach, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
1247    jint len = _env->GetArrayLength(params);
1248    jbyte *ptr = _env->GetByteArrayElements(params, NULL);
1249    if (mUseInc) {
1250        dispatchTab.ContextFinish((RsContext)con);
1251        dispatchTabInc.ScriptForEach((RsContext)incCon, (RsScript)script, slot,
1252                                     (RsAllocation)ain, (RsAllocation)aout,
1253                                     ptr, len, NULL, 0);
1254    } else {
1255        dispatchTab.ScriptForEach((RsContext)con, (RsScript)script, slot,
1256                                  (RsAllocation)ain, (RsAllocation)aout,
1257                                  ptr, len, NULL, 0);
1258    }
1259    _env->ReleaseByteArrayElements(params, ptr, JNI_ABORT);
1260}
1261
1262static void
1263nScriptForEachClipped(JNIEnv *_env, jobject _this, jlong con, jlong incCon,
1264                      jlong script, jint slot, jlong ain, jlong aout,
1265                      jint xstart, jint xend,
1266                      jint ystart, jint yend, jint zstart, jint zend, jboolean mUseInc)
1267{
1268    LOG_API("nScriptForEachClipped, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
1269    RsScriptCall sc;
1270    sc.xStart = xstart;
1271    sc.xEnd = xend;
1272    sc.yStart = ystart;
1273    sc.yEnd = yend;
1274    sc.zStart = zstart;
1275    sc.zEnd = zend;
1276    sc.strategy = RS_FOR_EACH_STRATEGY_DONT_CARE;
1277    sc.arrayStart = 0;
1278    sc.arrayEnd = 0;
1279    if (mUseInc) {
1280        dispatchTab.ContextFinish((RsContext)con);
1281        dispatchTabInc.ScriptForEach((RsContext)incCon, (RsScript)script, slot,
1282                                     (RsAllocation)ain, (RsAllocation)aout,
1283                                     NULL, 0, &sc, sizeof(sc));
1284    } else {
1285        dispatchTab.ScriptForEach((RsContext)con, (RsScript)script, slot,
1286                                  (RsAllocation)ain, (RsAllocation)aout,
1287                                  NULL, 0, &sc, sizeof(sc));
1288    }
1289}
1290
1291static void
1292nScriptForEachClippedV(JNIEnv *_env, jobject _this, jlong con, jlong incCon,
1293                       jlong script, jint slot, jlong ain, jlong aout,
1294                       jbyteArray params, jint xstart, jint xend,
1295                       jint ystart, jint yend, jint zstart, jint zend, jboolean mUseInc)
1296{
1297    LOG_API("nScriptForEachClipped, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
1298    jint len = _env->GetArrayLength(params);
1299    jbyte *ptr = _env->GetByteArrayElements(params, NULL);
1300    RsScriptCall sc;
1301    sc.xStart = xstart;
1302    sc.xEnd = xend;
1303    sc.yStart = ystart;
1304    sc.yEnd = yend;
1305    sc.zStart = zstart;
1306    sc.zEnd = zend;
1307    sc.strategy = RS_FOR_EACH_STRATEGY_DONT_CARE;
1308    sc.arrayStart = 0;
1309    sc.arrayEnd = 0;
1310    if (mUseInc) {
1311        dispatchTab.ContextFinish((RsContext)con);
1312        dispatchTabInc.ScriptForEach((RsContext)incCon, (RsScript)script, slot,
1313                                     (RsAllocation)ain, (RsAllocation)aout,
1314                                     ptr, len, &sc, sizeof(sc));
1315    } else {
1316        dispatchTab.ScriptForEach((RsContext)con, (RsScript)script, slot,
1317                                  (RsAllocation)ain, (RsAllocation)aout,
1318                                  ptr, len, &sc, sizeof(sc));
1319    }
1320    _env->ReleaseByteArrayElements(params, ptr, JNI_ABORT);
1321}
1322
1323// -----------------------------------
1324
1325static jlong
1326nScriptCCreate(JNIEnv *_env, jobject _this, jlong con,
1327               jstring resName, jstring cacheDir,
1328               jbyteArray scriptRef, jint length)
1329{
1330    LOG_API("nScriptCCreate, con(%p)", (RsContext)con);
1331
1332    AutoJavaStringToUTF8 resNameUTF(_env, resName);
1333    AutoJavaStringToUTF8 cacheDirUTF(_env, cacheDir);
1334    jlong ret = 0;
1335    jbyte* script_ptr = NULL;
1336    jint _exception = 0;
1337    jint remaining;
1338    if (!scriptRef) {
1339        _exception = 1;
1340        //jniThrowException(_env, "java/lang/IllegalArgumentException", "script == null");
1341        goto exit;
1342    }
1343    if (length < 0) {
1344        _exception = 1;
1345        //jniThrowException(_env, "java/lang/IllegalArgumentException", "length < 0");
1346        goto exit;
1347    }
1348    remaining = _env->GetArrayLength(scriptRef);
1349    if (remaining < length) {
1350        _exception = 1;
1351        //jniThrowException(_env, "java/lang/IllegalArgumentException",
1352        //        "length > script.length - offset");
1353        goto exit;
1354    }
1355    script_ptr = (jbyte *)
1356        _env->GetPrimitiveArrayCritical(scriptRef, (jboolean *)0);
1357
1358    //rsScriptCSetText(con, (const char *)script_ptr, length);
1359
1360    ret = (jlong)(uintptr_t)dispatchTab.ScriptCCreate((RsContext)con,
1361                                                      resNameUTF.c_str(), resNameUTF.length(),
1362                                                      cacheDirUTF.c_str(), cacheDirUTF.length(),
1363                                                      (const char *)script_ptr, length);
1364
1365exit:
1366    if (script_ptr) {
1367        _env->ReleasePrimitiveArrayCritical(scriptRef, script_ptr,
1368                _exception ? JNI_ABORT: 0);
1369    }
1370
1371    return (jlong)(uintptr_t)ret;
1372}
1373
1374static jlong
1375nScriptIntrinsicCreate(JNIEnv *_env, jobject _this, jlong con, jint id, jlong eid, jboolean mUseInc)
1376{
1377    LOG_API("nScriptIntrinsicCreate, con(%p) id(%i) element(%p)", (RsContext)con, id, (void *)eid);
1378    if (mUseInc) {
1379        return (jlong)(uintptr_t)dispatchTabInc.ScriptIntrinsicCreate((RsContext)con, id, (RsElement)eid);
1380    } else {
1381        return (jlong)(uintptr_t)dispatchTab.ScriptIntrinsicCreate((RsContext)con, id, (RsElement)eid);
1382    }
1383}
1384
1385static jlong
1386nScriptKernelIDCreate(JNIEnv *_env, jobject _this, jlong con, jlong sid, jint slot, jint sig, jboolean mUseInc)
1387{
1388    LOG_API("nScriptKernelIDCreate, con(%p) script(%p), slot(%i), sig(%i)", (RsContext)con,
1389            (void *)sid, slot, sig);
1390    if (mUseInc) {
1391        return (jlong)(uintptr_t)dispatchTabInc.ScriptKernelIDCreate((RsContext)con, (RsScript)sid,
1392                                                                     slot, sig);
1393    } else {
1394        return (jlong)(uintptr_t)dispatchTab.ScriptKernelIDCreate((RsContext)con, (RsScript)sid,
1395                                                                  slot, sig);
1396    }
1397}
1398
1399static jlong
1400nScriptInvokeIDCreate(JNIEnv *_env, jobject _this, jlong con, jlong sid, jint slot)
1401{
1402    LOG_API("nScriptInvokeIDCreate, con(%p) script(%p), slot(%i), sig(%i)", con,
1403            (void *)sid, slot);
1404    return (jlong)dispatchTab.ScriptInvokeIDCreate((RsContext)con, (RsScript)sid, slot);
1405}
1406
1407static jlong
1408nScriptFieldIDCreate(JNIEnv *_env, jobject _this, jlong con, jlong sid, jint slot, jboolean mUseInc)
1409{
1410    LOG_API("nScriptFieldIDCreate, con(%p) script(%p), slot(%i)", (RsContext)con, (void *)sid, slot);
1411    if (mUseInc) {
1412        return (jlong)(uintptr_t)dispatchTabInc.ScriptFieldIDCreate((RsContext)con, (RsScript)sid, slot);
1413    } else {
1414        return (jlong)(uintptr_t)dispatchTab.ScriptFieldIDCreate((RsContext)con, (RsScript)sid, slot);
1415    }
1416}
1417
1418static jlong
1419nScriptGroupCreate(JNIEnv *_env, jobject _this, jlong con, jlongArray _kernels, jlongArray _src,
1420    jlongArray _dstk, jlongArray _dstf, jlongArray _types)
1421{
1422    LOG_API("nScriptGroupCreate, con(%p)", (RsContext)con);
1423
1424    jint kernelsLen = _env->GetArrayLength(_kernels);
1425    jlong *jKernelsPtr = _env->GetLongArrayElements(_kernels, nullptr);
1426    RsScriptKernelID* kernelsPtr = (RsScriptKernelID*) malloc(sizeof(RsScriptKernelID) * kernelsLen);
1427    for(int i = 0; i < kernelsLen; ++i) {
1428        kernelsPtr[i] = (RsScriptKernelID)jKernelsPtr[i];
1429    }
1430
1431    jint srcLen = _env->GetArrayLength(_src);
1432    jlong *jSrcPtr = _env->GetLongArrayElements(_src, nullptr);
1433    RsScriptKernelID* srcPtr = (RsScriptKernelID*) malloc(sizeof(RsScriptKernelID) * srcLen);
1434    for(int i = 0; i < srcLen; ++i) {
1435        srcPtr[i] = (RsScriptKernelID)jSrcPtr[i];
1436    }
1437
1438    jint dstkLen = _env->GetArrayLength(_dstk);
1439    jlong *jDstkPtr = _env->GetLongArrayElements(_dstk, nullptr);
1440    RsScriptKernelID* dstkPtr = (RsScriptKernelID*) malloc(sizeof(RsScriptKernelID) * dstkLen);
1441    for(int i = 0; i < dstkLen; ++i) {
1442        dstkPtr[i] = (RsScriptKernelID)jDstkPtr[i];
1443    }
1444
1445    jint dstfLen = _env->GetArrayLength(_dstf);
1446    jlong *jDstfPtr = _env->GetLongArrayElements(_dstf, nullptr);
1447    RsScriptKernelID* dstfPtr = (RsScriptKernelID*) malloc(sizeof(RsScriptKernelID) * dstfLen);
1448    for(int i = 0; i < dstfLen; ++i) {
1449        dstfPtr[i] = (RsScriptKernelID)jDstfPtr[i];
1450    }
1451
1452    jint typesLen = _env->GetArrayLength(_types);
1453    jlong *jTypesPtr = _env->GetLongArrayElements(_types, nullptr);
1454    RsType* typesPtr = (RsType*) malloc(sizeof(RsType) * typesLen);
1455    for(int i = 0; i < typesLen; ++i) {
1456        typesPtr[i] = (RsType)jTypesPtr[i];
1457    }
1458
1459    jlong id = (jlong)(uintptr_t) dispatchTab.ScriptGroupCreate((RsContext)con,
1460                               (RsScriptKernelID *)kernelsPtr, kernelsLen * sizeof(RsScriptKernelID),
1461                               (RsScriptKernelID *)srcPtr, srcLen * sizeof(RsScriptKernelID),
1462                               (RsScriptKernelID *)dstkPtr, dstkLen * sizeof(RsScriptKernelID),
1463                               (RsScriptFieldID *)dstfPtr, dstfLen * sizeof(RsScriptKernelID),
1464                               (RsType *)typesPtr, typesLen * sizeof(RsType));
1465
1466    free(kernelsPtr);
1467    free(srcPtr);
1468    free(dstkPtr);
1469    free(dstfPtr);
1470    free(typesPtr);
1471    _env->ReleaseLongArrayElements(_kernels, jKernelsPtr, 0);
1472    _env->ReleaseLongArrayElements(_src, jSrcPtr, 0);
1473    _env->ReleaseLongArrayElements(_dstk, jDstkPtr, 0);
1474    _env->ReleaseLongArrayElements(_dstf, jDstfPtr, 0);
1475    _env->ReleaseLongArrayElements(_types, jTypesPtr, 0);
1476    return id;
1477}
1478
1479static void
1480nScriptGroupSetInput(JNIEnv *_env, jobject _this, jlong con, jlong gid, jlong kid, jlong alloc)
1481{
1482    LOG_API("nScriptGroupSetInput, con(%p) group(%p), kernelId(%p), alloc(%p)", (RsContext)con,
1483            (void *)gid, (void *)kid, (void *)alloc);
1484    dispatchTab.ScriptGroupSetInput((RsContext)con, (RsScriptGroup)gid, (RsScriptKernelID)kid,
1485                                    (RsAllocation)alloc);
1486}
1487
1488static void
1489nScriptGroupSetOutput(JNIEnv *_env, jobject _this, jlong con, jlong gid, jlong kid, jlong alloc)
1490{
1491    LOG_API("nScriptGroupSetOutput, con(%p) group(%p), kernelId(%p), alloc(%p)", (RsContext)con,
1492            (void *)gid, (void *)kid, (void *)alloc);
1493    dispatchTab.ScriptGroupSetOutput((RsContext)con, (RsScriptGroup)gid, (RsScriptKernelID)kid,
1494                                     (RsAllocation)alloc);
1495}
1496
1497static void
1498nScriptGroupExecute(JNIEnv *_env, jobject _this, jlong con, jlong gid)
1499{
1500    LOG_API("nScriptGroupSetOutput, con(%p) group(%p)", (RsContext)con, (void *)gid);
1501    dispatchTab.ScriptGroupExecute((RsContext)con, (RsScriptGroup)gid);
1502}
1503
1504// ---------------------------------------------------------------------------
1505
1506static jlong
1507nSamplerCreate(JNIEnv *_env, jobject _this, jlong con, jint magFilter, jint minFilter,
1508               jint wrapS, jint wrapT, jint wrapR, jfloat aniso)
1509{
1510    LOG_API("nSamplerCreate, con(%p)", (RsContext)con);
1511    return (jlong)(uintptr_t)dispatchTab.SamplerCreate((RsContext)con,
1512                                                       (RsSamplerValue)magFilter,
1513                                                       (RsSamplerValue)minFilter,
1514                                                       (RsSamplerValue)wrapS,
1515                                                       (RsSamplerValue)wrapT,
1516                                                       (RsSamplerValue)wrapR,
1517                                                       aniso);
1518}
1519
1520static jint
1521nSystemGetPointerSize(JNIEnv *_env, jobject _this) {
1522    return (jint)sizeof(void*);
1523}
1524
1525// ---------------------------------------------------------------------------
1526// For Incremental Intrinsic Support
1527static bool nIncLoadSO(jint deviceApi) {
1528    void* handle = NULL;
1529    handle = dlopen("libRSSupport.so", RTLD_LAZY | RTLD_LOCAL);
1530    if (handle == NULL) {
1531        LOG_API("couldn't dlopen %s, %s", filename, dlerror());
1532        return false;
1533    }
1534
1535    if (loadSymbols(handle, dispatchTabInc, deviceApi) == false) {
1536        LOG_API("%s init failed!", filename);
1537        return false;
1538    }
1539    LOG_API("Successfully loaded %s", filename);
1540    return true;
1541}
1542
1543// -----------------------------------
1544// To create/destroy a dummy context
1545static void
1546nIncObjDestroy(JNIEnv *_env, jobject _this, jlong con, jlong obj)
1547{
1548    LOG_API("nObjDestroy, con(%p) obj(%p)", (RsContext)con, (void *)obj);
1549    dispatchTabInc.ObjDestroy((RsContext)con, (void *)obj);
1550}
1551
1552
1553static jlong
1554nIncDeviceCreate(JNIEnv *_env, jobject _this)
1555{
1556    LOG_API("nDeviceCreate");
1557    return (jlong)(uintptr_t)dispatchTabInc.DeviceCreate();
1558}
1559
1560static void
1561nIncDeviceDestroy(JNIEnv *_env, jobject _this, jlong dev)
1562{
1563    LOG_API("nDeviceDestroy");
1564    return dispatchTabInc.DeviceDestroy((RsDevice)dev);
1565}
1566
1567static jlong
1568nIncContextCreate(JNIEnv *_env, jobject _this, jlong dev, jint ver, jint sdkVer, jint ct)
1569{
1570    LOG_API("nContextCreate");
1571    //The compat context for incremental support will be synchronous.
1572    return (jlong)(uintptr_t)dispatchTabInc.ContextCreate((RsDevice)dev, ver, sdkVer,
1573                                                          (RsContextType)ct,
1574                                                          RS_CONTEXT_SYNCHRONOUS);
1575}
1576
1577static void
1578nIncContextFinish(JNIEnv *_env, jobject _this, jlong con)
1579{
1580    LOG_API("nContextFinish, con(%p)", (RsContext)con);
1581    dispatchTabInc.ContextFinish((RsContext)con);
1582}
1583
1584static void
1585nIncContextDestroy(JNIEnv *_env, jobject _this, jlong con)
1586{
1587    LOG_API("nContextDestroy, con(%p)", (RsContext)con);
1588    dispatchTabInc.ContextDestroy((RsContext)con);
1589}
1590
1591// -----------------------------------
1592// Create dummy Element
1593static jlong
1594nIncElementCreate(JNIEnv *_env, jobject _this, jlong con, jlong type, jint kind, jboolean norm, jint size)
1595{
1596    LOG_API("nElementCreate, con(%p), type(%i), kind(%i), norm(%i), size(%i)", (RsContext)con,
1597            type, kind, norm, size);
1598    return (jlong)(uintptr_t)dispatchTabInc.ElementCreate((RsContext)con, (RsDataType)type,
1599                                                          (RsDataKind)kind, norm, size);
1600}
1601// -----------------------------------
1602// Create dummy Type
1603static jlong
1604nIncTypeCreate(JNIEnv *_env, jobject _this, jlong con, jlong eid,
1605            jint dimx, jint dimy, jint dimz, jboolean mips, jboolean faces, jint yuv)
1606{
1607    LOG_API("nTypeCreate, con(%p) eid(%p), x(%i), y(%i), z(%i), mips(%i), faces(%i), yuv(%i)",
1608            incCon, eid, dimx, dimy, dimz, mips, faces, yuv);
1609
1610    return (jlong)(uintptr_t)dispatchTabInc.TypeCreate((RsContext)con, (RsElement)eid, dimx, dimy,
1611                                                       dimz, mips, faces, yuv);
1612}
1613
1614// -----------------------------------
1615// Create Allocation from pointer
1616static jlong
1617nIncAllocationCreateTyped(JNIEnv *_env, jobject _this, jlong con, jlong incCon, jlong alloc, jlong type)
1618{
1619    LOG_API("nAllocationCreateTyped, con(%p), type(%p), mip(%i), usage(%i), ptr(%p)",
1620            incCon, (RsElement)type, mips, usage, (void *)pointer);
1621    size_t strideIn;
1622    void* pIn = NULL;
1623    RsAllocation ainI = NULL;
1624    if (alloc != 0) {
1625        pIn = dispatchTab.AllocationGetPointer((RsContext)con, (RsAllocation)alloc, 0,
1626                                               RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X, 0, 0,
1627                                               &strideIn, sizeof(size_t));
1628        ainI = dispatchTabInc.AllocationCreateTyped((RsContext)incCon, (RsType)type,
1629                                                    RS_ALLOCATION_MIPMAP_NONE,
1630                                                    RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED,
1631                                                    (uintptr_t)pIn);
1632    }
1633    return (jlong)(uintptr_t) ainI;
1634}
1635
1636// ---------------------------------------------------------------------------
1637
1638
1639static const char *classPathName = "android/support/v8/renderscript/RenderScript";
1640
1641static JNINativeMethod methods[] = {
1642{"nLoadSO",                        "(ZI)Z",                                   (bool*)nLoadSO },
1643{"nLoadIOSO",                      "()Z",                                     (bool*)nLoadIOSO },
1644{"nDeviceCreate",                  "()J",                                     (void*)nDeviceCreate },
1645{"nDeviceDestroy",                 "(J)V",                                    (void*)nDeviceDestroy },
1646{"nDeviceSetConfig",               "(JII)V",                                  (void*)nDeviceSetConfig },
1647{"nContextGetUserMessage",         "(J[I)I",                                  (void*)nContextGetUserMessage },
1648{"nContextGetErrorMessage",        "(J)Ljava/lang/String;",                   (void*)nContextGetErrorMessage },
1649{"nContextPeekMessage",            "(J[I)I",                                  (void*)nContextPeekMessage },
1650{"nContextInitToClient",           "(J)V",                                    (void*)nContextInitToClient },
1651{"nContextDeinitToClient",         "(J)V",                                    (void*)nContextDeinitToClient },
1652
1653
1654// All methods below are thread protected in java.
1655{"rsnContextCreate",                 "(JIIILjava/lang/String;)J",             (void*)nContextCreate },
1656{"rsnContextFinish",                 "(J)V",                                  (void*)nContextFinish },
1657{"rsnContextSetPriority",            "(JI)V",                                 (void*)nContextSetPriority },
1658{"rsnContextDestroy",                "(J)V",                                  (void*)nContextDestroy },
1659{"rsnContextDump",                   "(JI)V",                                 (void*)nContextDump },
1660{"rsnContextSendMessage",            "(JI[I)V",                               (void*)nContextSendMessage },
1661{"rsnClosureCreate",                 "(JJJ[J[J[I[J[J)J",                      (void*)nClosureCreate },
1662{"rsnInvokeClosureCreate",           "(JJ[B[J[J[I)J",                         (void*)nInvokeClosureCreate },
1663{"rsnClosureSetArg",                 "(JJIJI)V",                              (void*)nClosureSetArg },
1664{"rsnClosureSetGlobal",              "(JJJJI)V",                              (void*)nClosureSetGlobal },
1665{"rsnObjDestroy",                    "(JJ)V",                                 (void*)nObjDestroy },
1666
1667{"rsnElementCreate",                 "(JJIZI)J",                              (void*)nElementCreate },
1668{"rsnElementCreate2",                "(J[J[Ljava/lang/String;[I)J",           (void*)nElementCreate2 },
1669{"rsnElementGetSubElements",         "(JJ[J[Ljava/lang/String;[I)V",          (void*)nElementGetSubElements },
1670
1671{"rsnTypeCreate",                    "(JJIIIZZI)J",                           (void*)nTypeCreate },
1672
1673{"rsnAllocationCreateTyped",         "(JJIIJ)J",                              (void*)nAllocationCreateTyped },
1674{"rsnAllocationCreateFromBitmap",    "(JJILandroid/graphics/Bitmap;I)J",      (void*)nAllocationCreateFromBitmap },
1675{"rsnAllocationCreateBitmapBackedAllocation",    "(JJILandroid/graphics/Bitmap;I)J",      (void*)nAllocationCreateBitmapBackedAllocation },
1676{"rsnAllocationCubeCreateFromBitmap","(JJILandroid/graphics/Bitmap;I)J",      (void*)nAllocationCubeCreateFromBitmap },
1677
1678{"rsnAllocationCopyFromBitmap",      "(JJLandroid/graphics/Bitmap;)V",        (void*)nAllocationCopyFromBitmap },
1679{"rsnAllocationCopyToBitmap",        "(JJLandroid/graphics/Bitmap;)V",        (void*)nAllocationCopyToBitmap },
1680
1681{"rsnAllocationSyncAll",             "(JJI)V",                                (void*)nAllocationSyncAll },
1682{"rsnAllocationSetSurface",          "(JJLandroid/view/Surface;)V",           (void*)nAllocationSetSurface },
1683{"rsnAllocationIoSend",              "(JJ)V",                                 (void*)nAllocationIoSend },
1684{"rsnAllocationData1D",              "(JJIIILjava/lang/Object;IIIZ)V",        (void*)nAllocationData1D },
1685{"rsnAllocationElementData1D",       "(JJIII[BI)V",                           (void*)nAllocationElementData1D },
1686//{"rsnAllocationElementData",         "(JJIIIII[BI)V",                         (void*)nAllocationElementData },
1687{"rsnAllocationData2D",              "(JJIIIIIILjava/lang/Object;IIIZ)V",     (void*)nAllocationData2D },
1688{"rsnAllocationData2D",              "(JJIIIIIIJIIII)V",                      (void*)nAllocationData2D_alloc },
1689{"rsnAllocationData3D",              "(JJIIIIIIILjava/lang/Object;IIIZ)V",    (void*)nAllocationData3D },
1690{"rsnAllocationData3D",              "(JJIIIIIIIJIIII)V",                     (void*)nAllocationData3D_alloc },
1691{"rsnAllocationRead",                "(JJLjava/lang/Object;IIZ)V",            (void*)nAllocationRead },
1692{"rsnAllocationRead1D",              "(JJIIILjava/lang/Object;IIIZ)V",        (void*)nAllocationRead1D },
1693//{"rsnAllocationElementRead",         "(JJIIIII[BI)V",                         (void*)nAllocationElementRead },
1694{"rsnAllocationRead2D",              "(JJIIIIIILjava/lang/Object;IIIZ)V",     (void*)nAllocationRead2D },
1695//{"rsnAllocationRead3D",              "(JJIIIIIIILjava/lang/Object;IIIZ)V",  (void*)nAllocationRead3D },
1696{"rsnAllocationGetType",             "(JJ)J",                                 (void*)nAllocationGetType},
1697{"rsnAllocationResize1D",            "(JJI)V",                                (void*)nAllocationResize1D },
1698{"rsnAllocationGenerateMipmaps",     "(JJ)V",                                 (void*)nAllocationGenerateMipmaps },
1699
1700{"rsnScriptBindAllocation",          "(JJJIZ)V",                              (void*)nScriptBindAllocation },
1701{"rsnScriptSetTimeZone",             "(JJ[BZ)V",                              (void*)nScriptSetTimeZone },
1702{"rsnScriptInvoke",                  "(JJIZ)V",                               (void*)nScriptInvoke },
1703{"rsnScriptInvokeV",                 "(JJI[BZ)V",                             (void*)nScriptInvokeV },
1704{"rsnScriptForEach",                 "(JJJIJJZ)V",                            (void*)nScriptForEach },
1705{"rsnScriptForEach",                 "(JJJIJJ[BZ)V",                          (void*)nScriptForEachV },
1706{"rsnScriptForEachClipped",          "(JJJIJJIIIIIIZ)V",                      (void*)nScriptForEachClipped },
1707{"rsnScriptForEachClipped",          "(JJJIJJ[BIIIIIIZ)V",                    (void*)nScriptForEachClippedV },
1708{"rsnScriptSetVarI",                 "(JJIIZ)V",                              (void*)nScriptSetVarI },
1709{"rsnScriptSetVarJ",                 "(JJIJZ)V",                              (void*)nScriptSetVarJ },
1710{"rsnScriptSetVarF",                 "(JJIFZ)V",                              (void*)nScriptSetVarF },
1711{"rsnScriptSetVarD",                 "(JJIDZ)V",                              (void*)nScriptSetVarD },
1712{"rsnScriptSetVarV",                 "(JJI[BZ)V",                             (void*)nScriptSetVarV },
1713{"rsnScriptSetVarVE",                "(JJI[BJ[IZ)V",                          (void*)nScriptSetVarVE },
1714{"rsnScriptSetVarObj",               "(JJIJZ)V",                              (void*)nScriptSetVarObj },
1715
1716{"rsnScriptCCreate",                 "(JLjava/lang/String;Ljava/lang/String;[BI)J",  (void*)nScriptCCreate },
1717{"rsnScriptIntrinsicCreate",         "(JIJZ)J",                               (void*)nScriptIntrinsicCreate },
1718{"rsnScriptKernelIDCreate",          "(JJIIZ)J",                              (void*)nScriptKernelIDCreate },
1719{"rsnScriptInvokeIDCreate",          "(JJI)J",                                (void*)nScriptInvokeIDCreate },
1720{"rsnScriptFieldIDCreate",           "(JJIZ)J",                               (void*)nScriptFieldIDCreate },
1721{"rsnScriptGroupCreate",             "(J[J[J[J[J[J)J",                        (void*)nScriptGroupCreate },
1722{"rsnScriptGroup2Create",            "(JLjava/lang/String;Ljava/lang/String;[J)J", (void*)nScriptGroup2Create },
1723{"rsnScriptGroupSetInput",           "(JJJJ)V",                               (void*)nScriptGroupSetInput },
1724{"rsnScriptGroupSetOutput",          "(JJJJ)V",                               (void*)nScriptGroupSetOutput },
1725{"rsnScriptGroupExecute",            "(JJ)V",                                 (void*)nScriptGroupExecute },
1726{"rsnScriptGroup2Execute",           "(JJ)V",                                 (void*)nScriptGroup2Execute },
1727
1728{"rsnSamplerCreate",                 "(JIIIIIF)J",                            (void*)nSamplerCreate },
1729
1730{"rsnSystemGetPointerSize",          "()I",                                   (void*)nSystemGetPointerSize },
1731
1732// Entry points for Inc libRSSupport
1733{"nIncLoadSO",                       "(I)Z",                                  (bool*)nIncLoadSO },
1734{"nIncDeviceCreate",                 "()J",                                   (void*)nIncDeviceCreate },
1735{"nIncDeviceDestroy",                "(J)V",                                  (void*)nIncDeviceDestroy },
1736{"rsnIncContextCreate",              "(JIII)J",                               (void*)nIncContextCreate },
1737{"rsnIncContextFinish",              "(J)V",                                  (void*)nIncContextFinish },
1738{"rsnIncContextDestroy",             "(J)V",                                  (void*)nIncContextDestroy },
1739{"rsnIncObjDestroy",                 "(JJ)V",                                 (void*)nIncObjDestroy },
1740{"rsnIncElementCreate",              "(JJIZI)J",                              (void*)nIncElementCreate },
1741{"rsnIncTypeCreate",                 "(JJIIIZZI)J",                           (void*)nIncTypeCreate },
1742{"rsnIncAllocationCreateTyped",      "(JJJJ)J",                               (void*)nIncAllocationCreateTyped },
1743};
1744
1745// ---------------------------------------------------------------------------
1746
1747jint JNI_OnLoad(JavaVM* vm, void* reserved)
1748{
1749    JNIEnv* env = NULL;
1750    jclass clazz = NULL;
1751    jint result = -1;
1752
1753    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
1754        //        __android_log_print(ANDROID_LOG_ERROR, LOG_TAG,
1755        //            "ERROR: GetEnv failed\n");
1756        goto bail;
1757    }
1758    if (env == NULL) {
1759        //        __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "ERROR: env == NULL");
1760        goto bail;
1761    }
1762
1763    clazz = env->FindClass(classPathName);
1764    if (clazz == NULL) {
1765        goto bail;
1766    }
1767
1768    if (env->RegisterNatives(clazz, methods, NELEM(methods)) < 0) {
1769        //        __android_log_print(ANDROID_LOG_ERROR, LOG_TAG,
1770        //            "ERROR: MediaPlayer native registration failed\n");
1771        goto bail;
1772    }
1773
1774    /* success -- return valid version number */
1775    result = JNI_VERSION_1_4;
1776
1777bail:
1778    return result;
1779}
1780