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