android_renderscript_RenderScript.cpp revision 6d056f6d36b9016574c94ec903e873feb2ad31b1
1/*
2 * Copyright (C) 2011-2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "libRS_jni"
18
19#include <stdlib.h>
20#include <stdio.h>
21#include <fcntl.h>
22#include <unistd.h>
23#include <math.h>
24#include <android/bitmap.h>
25#include <android/log.h>
26
27#include <rsEnv.h>
28#include "rsDispatch.h"
29#include <dlfcn.h>
30
31//#define LOG_API ALOG
32#define LOG_API(...)
33#define LOG_ERR(...) __android_log_print(ANDROID_LOG_ERROR, "RenderScript JNI", __VA_ARGS__);
34#define RS_JNI_VERSION 2301
35
36#define NELEM(m) (sizeof(m) / sizeof((m)[0]))
37
38template <typename... T>
39void UNUSED(T... t) {}
40#define PER_ARRAY_TYPE(flag, fnc, readonly, ...) {                                      \
41    jint len = 0;                                                                       \
42    void *ptr = nullptr;                                                                \
43    void *srcPtr = nullptr;                                                             \
44    size_t typeBytes = 0;                                                               \
45    jint relFlag = 0;                                                                   \
46    if (readonly) {                                                                     \
47        /* The on-release mode should only be JNI_ABORT for read-only accesses. */      \
48        /* readonly = true, also indicates we are copying to the allocation   . */      \
49        relFlag = JNI_ABORT;                                                            \
50    }                                                                                   \
51    switch(dataType) {                                                                  \
52    case RS_TYPE_FLOAT_32:                                                              \
53        len = _env->GetArrayLength((jfloatArray)data);                                  \
54        ptr = _env->GetFloatArrayElements((jfloatArray)data, flag);                     \
55        typeBytes = 4;                                                                  \
56        if (usePadding) {                                                               \
57            srcPtr = ptr;                                                               \
58            len = len / 3 * 4;                                                          \
59            if (count == 0) {                                                           \
60                count = len / 4;                                                        \
61            }                                                                           \
62            ptr = malloc (len * typeBytes);                                             \
63            if (readonly) {                                                             \
64                copyWithPadding(ptr, srcPtr, mSize, count);                             \
65                fnc(__VA_ARGS__);                                                       \
66            } else {                                                                    \
67                fnc(__VA_ARGS__);                                                       \
68                copyWithUnPadding(srcPtr, ptr, mSize, count);                           \
69            }                                                                           \
70            free(ptr);                                                                  \
71            ptr = srcPtr;                                                               \
72        } else {                                                                        \
73            fnc(__VA_ARGS__);                                                           \
74        }                                                                               \
75        _env->ReleaseFloatArrayElements((jfloatArray)data, (jfloat *)ptr, relFlag);     \
76        return;                                                                         \
77    case RS_TYPE_FLOAT_64:                                                              \
78        len = _env->GetArrayLength((jdoubleArray)data);                                 \
79        ptr = _env->GetDoubleArrayElements((jdoubleArray)data, flag);                   \
80        typeBytes = 8;                                                                  \
81        if (usePadding) {                                                               \
82            srcPtr = ptr;                                                               \
83            len = len / 3 * 4;                                                          \
84            if (count == 0) {                                                           \
85                count = len / 4;                                                        \
86            }                                                                           \
87            ptr = malloc (len * typeBytes);                                             \
88            if (readonly) {                                                             \
89                copyWithPadding(ptr, srcPtr, mSize, count);                             \
90                fnc(__VA_ARGS__);                                                       \
91            } else {                                                                    \
92                fnc(__VA_ARGS__);                                                       \
93                copyWithUnPadding(srcPtr, ptr, mSize, count);                           \
94            }                                                                           \
95            free(ptr);                                                                  \
96            ptr = srcPtr;                                                               \
97        } else {                                                                        \
98            fnc(__VA_ARGS__);                                                           \
99        }                                                                               \
100        _env->ReleaseDoubleArrayElements((jdoubleArray)data, (jdouble *)ptr, relFlag);  \
101        return;                                                                         \
102    case RS_TYPE_SIGNED_8:                                                              \
103    case RS_TYPE_UNSIGNED_8:                                                            \
104        len = _env->GetArrayLength((jbyteArray)data);                                   \
105        ptr = _env->GetByteArrayElements((jbyteArray)data, flag);                       \
106        typeBytes = 1;                                                                  \
107        if (usePadding) {                                                               \
108            srcPtr = ptr;                                                               \
109            len = len / 3 * 4;                                                          \
110            if (count == 0) {                                                           \
111                count = len / 4;                                                        \
112            }                                                                           \
113            ptr = malloc (len * typeBytes);                                             \
114            if (readonly) {                                                             \
115                copyWithPadding(ptr, srcPtr, mSize, count);                             \
116                fnc(__VA_ARGS__);                                                       \
117            } else {                                                                    \
118                fnc(__VA_ARGS__);                                                       \
119                copyWithUnPadding(srcPtr, ptr, mSize, count);                           \
120            }                                                                           \
121            free(ptr);                                                                  \
122            ptr = srcPtr;                                                               \
123        } else {                                                                        \
124            fnc(__VA_ARGS__);                                                           \
125        }                                                                               \
126        _env->ReleaseByteArrayElements((jbyteArray)data, (jbyte*)ptr, relFlag);         \
127        return;                                                                         \
128    case RS_TYPE_SIGNED_16:                                                             \
129    case RS_TYPE_UNSIGNED_16:                                                           \
130        len = _env->GetArrayLength((jshortArray)data);                                  \
131        ptr = _env->GetShortArrayElements((jshortArray)data, flag);                     \
132        typeBytes = 2;                                                                  \
133        if (usePadding) {                                                               \
134            srcPtr = ptr;                                                               \
135            len = len / 3 * 4;                                                          \
136            if (count == 0) {                                                           \
137                count = len / 4;                                                        \
138            }                                                                           \
139            ptr = malloc (len * typeBytes);                                             \
140            if (readonly) {                                                             \
141                copyWithPadding(ptr, srcPtr, mSize, count);                             \
142                fnc(__VA_ARGS__);                                                       \
143            } else {                                                                    \
144                fnc(__VA_ARGS__);                                                       \
145                copyWithUnPadding(srcPtr, ptr, mSize, count);                           \
146            }                                                                           \
147            free(ptr);                                                                  \
148            ptr = srcPtr;                                                               \
149        } else {                                                                        \
150            fnc(__VA_ARGS__);                                                           \
151        }                                                                               \
152        _env->ReleaseShortArrayElements((jshortArray)data, (jshort *)ptr, relFlag);     \
153        return;                                                                         \
154    case RS_TYPE_SIGNED_32:                                                             \
155    case RS_TYPE_UNSIGNED_32:                                                           \
156        len = _env->GetArrayLength((jintArray)data);                                    \
157        ptr = _env->GetIntArrayElements((jintArray)data, flag);                         \
158        typeBytes = 4;                                                                  \
159        if (usePadding) {                                                               \
160            srcPtr = ptr;                                                               \
161            len = len / 3 * 4;                                                          \
162            if (count == 0) {                                                           \
163                count = len / 4;                                                        \
164            }                                                                           \
165            ptr = malloc (len * typeBytes);                                             \
166            if (readonly) {                                                             \
167                copyWithPadding(ptr, srcPtr, mSize, count);                             \
168                fnc(__VA_ARGS__);                                                       \
169            } else {                                                                    \
170                fnc(__VA_ARGS__);                                                       \
171                copyWithUnPadding(srcPtr, ptr, mSize, count);                           \
172            }                                                                           \
173            free(ptr);                                                                  \
174            ptr = srcPtr;                                                               \
175        } else {                                                                        \
176            fnc(__VA_ARGS__);                                                           \
177        }                                                                               \
178        _env->ReleaseIntArrayElements((jintArray)data, (jint *)ptr, relFlag);           \
179        return;                                                                         \
180    case RS_TYPE_SIGNED_64:                                                             \
181    case RS_TYPE_UNSIGNED_64:                                                           \
182        len = _env->GetArrayLength((jlongArray)data);                                   \
183        ptr = _env->GetLongArrayElements((jlongArray)data, flag);                       \
184        typeBytes = 8;                                                                  \
185        if (usePadding) {                                                               \
186            srcPtr = ptr;                                                               \
187            len = len / 3 * 4;                                                          \
188            if (count == 0) {                                                           \
189                count = len / 4;                                                        \
190            }                                                                           \
191            ptr = malloc (len * typeBytes);                                             \
192            if (readonly) {                                                             \
193                copyWithPadding(ptr, srcPtr, mSize, count);                             \
194                fnc(__VA_ARGS__);                                                       \
195            } else {                                                                    \
196                fnc(__VA_ARGS__);                                                       \
197                copyWithUnPadding(srcPtr, ptr, mSize, count);                           \
198            }                                                                           \
199            free(ptr);                                                                  \
200            ptr = srcPtr;                                                               \
201        } else {                                                                        \
202            fnc(__VA_ARGS__);                                                           \
203        }                                                                               \
204        _env->ReleaseLongArrayElements((jlongArray)data, (jlong *)ptr, relFlag);        \
205        return;                                                                         \
206    default:                                                                            \
207        break;                                                                          \
208    }                                                                                   \
209    UNUSED(len, ptr, srcPtr, typeBytes, relFlag);                                       \
210}
211
212
213class AutoJavaStringToUTF8 {
214public:
215    AutoJavaStringToUTF8(JNIEnv* env, jstring str) : fEnv(env), fJStr(str) {
216        fCStr = env->GetStringUTFChars(str, NULL);
217        fLength = env->GetStringUTFLength(str);
218    }
219    ~AutoJavaStringToUTF8() {
220        fEnv->ReleaseStringUTFChars(fJStr, fCStr);
221    }
222    const char* c_str() const { return fCStr; }
223    jsize length() const { return fLength; }
224
225private:
226    JNIEnv*     fEnv;
227    jstring     fJStr;
228    const char* fCStr;
229    jsize       fLength;
230};
231
232class AutoJavaStringArrayToUTF8 {
233public:
234    AutoJavaStringArrayToUTF8(JNIEnv* env, jobjectArray strings, jsize stringsLength)
235    : mEnv(env), mStrings(strings), mStringsLength(stringsLength) {
236        mCStrings = NULL;
237        mSizeArray = NULL;
238        if (stringsLength > 0) {
239            mCStrings = (const char **)calloc(stringsLength, sizeof(char *));
240            mSizeArray = (size_t*)calloc(stringsLength, sizeof(size_t));
241            for (jsize ct = 0; ct < stringsLength; ct ++) {
242                jstring s = (jstring)mEnv->GetObjectArrayElement(mStrings, ct);
243                mCStrings[ct] = mEnv->GetStringUTFChars(s, NULL);
244                mSizeArray[ct] = mEnv->GetStringUTFLength(s);
245            }
246        }
247    }
248    ~AutoJavaStringArrayToUTF8() {
249        for (jsize ct=0; ct < mStringsLength; ct++) {
250            jstring s = (jstring)mEnv->GetObjectArrayElement(mStrings, ct);
251            mEnv->ReleaseStringUTFChars(s, mCStrings[ct]);
252        }
253        free(mCStrings);
254        free(mSizeArray);
255    }
256    const char **c_str() const { return mCStrings; }
257    size_t *c_str_len() const { return mSizeArray; }
258    jsize length() const { return mStringsLength; }
259
260private:
261    JNIEnv      *mEnv;
262    jobjectArray mStrings;
263    const char **mCStrings;
264    size_t      *mSizeArray;
265    jsize        mStringsLength;
266};
267
268
269// ---------------------------------------------------------------------------
270static dispatchTable dispatchTab;
271// Incremental Support lib
272static dispatchTable dispatchTabInc;
273
274static jboolean nLoadSO(JNIEnv *_env, jobject _this, jboolean useNative, jint targetApi, jstring libPath) {
275    void* handle = NULL;
276    if (useNative) {
277        handle = dlopen("libRS.so", RTLD_LAZY | RTLD_LOCAL);
278    } else {
279        // For API 9+, dlopen the full path of libRSSupport.
280        if (libPath != NULL) {
281            const char * libPathJni = _env->GetStringUTFChars(libPath, JNI_FALSE);
282            handle = dlopen(libPathJni, RTLD_LAZY | RTLD_LOCAL);
283            _env->ReleaseStringUTFChars(libPath, libPathJni);
284        } else {
285            handle = dlopen("libRSSupport.so", RTLD_LAZY | RTLD_LOCAL);
286        }
287    }
288    if (handle == NULL) {
289        LOG_ERR("couldn't dlopen %s; librsjni version: %d", dlerror(), RS_JNI_VERSION);
290        return false;
291    }
292
293    if (loadSymbols(handle, dispatchTab, targetApi) == false) {
294        LOG_ERR("Dispatch table init failed! librsjni version: %d", RS_JNI_VERSION);
295        dlclose(handle);
296        return false;
297    }
298    LOG_API("Successfully loaded runtime");
299    return true;
300}
301
302static ioSuppDT ioDispatch;
303static jboolean nLoadIOSO(JNIEnv *_env, jobject _this) {
304    void* handleIO = NULL;
305    handleIO = dlopen("libRSSupportIO.so", RTLD_LAZY | RTLD_LOCAL);
306    if (handleIO == NULL) {
307        LOG_ERR("Couldn't load libRSSupportIO.so, librsjni version: %d", RS_JNI_VERSION);
308        return false;
309    }
310    if (loadIOSuppSyms(handleIO, ioDispatch) == false) {
311        LOG_ERR("libRSSupportIO init failed! librsjni version: %d", RS_JNI_VERSION);
312        return false;
313    }
314    return true;
315}
316
317// ---------------------------------------------------------------------------
318
319static void copyWithPadding(void* ptr, void* srcPtr, int mSize, int count) {
320    int sizeBytesPad = mSize * 4;
321    int sizeBytes = mSize * 3;
322    uint8_t *dst = static_cast<uint8_t *>(ptr);
323    uint8_t *src = static_cast<uint8_t *>(srcPtr);
324    for (int i = 0; i < count; i++) {
325        memcpy(dst, src, sizeBytes);
326        dst += sizeBytesPad;
327        src += sizeBytes;
328    }
329}
330
331static void copyWithUnPadding(void* ptr, void* srcPtr, int mSize, int count) {
332    int sizeBytesPad = mSize * 4;
333    int sizeBytes = mSize * 3;
334    uint8_t *dst = static_cast<uint8_t *>(ptr);
335    uint8_t *src = static_cast<uint8_t *>(srcPtr);
336    for (int i = 0; i < count; i++) {
337        memcpy(dst, src, sizeBytes);
338        dst += sizeBytes;
339        src += sizeBytesPad;
340    }
341}
342
343
344// ---------------------------------------------------------------------------
345
346static void
347nContextFinish(JNIEnv *_env, jobject _this, jlong con)
348{
349    LOG_API("nContextFinish, con(%p)", (RsContext)con);
350    dispatchTab.ContextFinish((RsContext)con);
351}
352
353static jlong
354nClosureCreate(JNIEnv *_env, jobject _this, jlong con, jlong kernelID,
355               jlong returnValue, jlongArray fieldIDArray,
356               jlongArray valueArray, jintArray sizeArray,
357               jlongArray depClosureArray, jlongArray depFieldIDArray) {
358  jlong ret = 0;
359
360  jlong* jFieldIDs = _env->GetLongArrayElements(fieldIDArray, nullptr);
361  jsize fieldIDs_length = _env->GetArrayLength(fieldIDArray);
362  jlong* jValues = _env->GetLongArrayElements(valueArray, nullptr);
363  jsize values_length = _env->GetArrayLength(valueArray);
364  jint* jSizes = _env->GetIntArrayElements(sizeArray, nullptr);
365  jsize sizes_length = _env->GetArrayLength(sizeArray);
366  jlong* jDepClosures =
367      _env->GetLongArrayElements(depClosureArray, nullptr);
368  jsize depClosures_length = _env->GetArrayLength(depClosureArray);
369  jlong* jDepFieldIDs =
370      _env->GetLongArrayElements(depFieldIDArray, nullptr);
371  jsize depFieldIDs_length = _env->GetArrayLength(depFieldIDArray);
372
373  size_t numValues, numDependencies;
374  RsScriptFieldID* fieldIDs;
375  RsClosure* depClosures;
376  RsScriptFieldID* depFieldIDs;
377
378  if (fieldIDs_length != values_length || values_length != sizes_length) {
379      LOG_ERR("Unmatched field IDs, values, and sizes in closure creation.");
380      goto exit;
381  }
382
383  numValues = (size_t)fieldIDs_length;
384
385  if (depClosures_length != depFieldIDs_length) {
386      LOG_ERR("Unmatched closures and field IDs for dependencies in closure creation.");
387      goto exit;
388  }
389
390  numDependencies = (size_t)depClosures_length;
391
392  if (numDependencies > numValues) {
393      LOG_ERR("Unexpected number of dependencies in closure creation");
394      goto exit;
395  }
396
397  if (numValues > RS_CLOSURE_MAX_NUMBER_ARGS_AND_BINDINGS) {
398      LOG_ERR("Too many arguments or globals in closure creation");
399      goto exit;
400  }
401
402  fieldIDs = (RsScriptFieldID*)alloca(sizeof(RsScriptFieldID) * numValues);
403  if (fieldIDs == nullptr) {
404      goto exit;
405  }
406
407  for (size_t i = 0; i < numValues; i++) {
408    fieldIDs[i] = (RsScriptFieldID)jFieldIDs[i];
409  }
410
411  depClosures = (RsClosure*)alloca(sizeof(RsClosure) * numDependencies);
412  if (depClosures == nullptr) {
413      goto exit;
414  }
415
416  for (size_t i = 0; i < numDependencies; i++) {
417    depClosures[i] = (RsClosure)jDepClosures[i];
418  }
419
420  depFieldIDs = (RsScriptFieldID*)alloca(sizeof(RsScriptFieldID) * numDependencies);
421  if (depFieldIDs == nullptr) {
422      goto exit;
423  }
424
425  for (size_t i = 0; i < numDependencies; i++) {
426    depFieldIDs[i] = (RsClosure)jDepFieldIDs[i];
427  }
428
429  ret = (jlong)(uintptr_t)dispatchTab.ClosureCreate(
430      (RsContext)con, (RsScriptKernelID)kernelID, (RsAllocation)returnValue,
431      fieldIDs, numValues, jValues, numValues,
432      (int*)jSizes, numValues,
433      depClosures, numDependencies,
434      depFieldIDs, numDependencies);
435
436exit:
437
438  _env->ReleaseLongArrayElements(depFieldIDArray, jDepFieldIDs, JNI_ABORT);
439  _env->ReleaseLongArrayElements(depClosureArray, jDepClosures, JNI_ABORT);
440  _env->ReleaseIntArrayElements (sizeArray,       jSizes,       JNI_ABORT);
441  _env->ReleaseLongArrayElements(valueArray,      jValues,      JNI_ABORT);
442  _env->ReleaseLongArrayElements(fieldIDArray,    jFieldIDs,    JNI_ABORT);
443
444  return ret;
445}
446
447static jlong
448nInvokeClosureCreate(JNIEnv *_env, jobject _this, jlong con, jlong invokeID,
449                     jbyteArray paramArray, jlongArray fieldIDArray, jlongArray valueArray,
450                     jintArray sizeArray) {
451  jlong ret = 0;
452
453  jbyte* jParams = _env->GetByteArrayElements(paramArray, nullptr);
454  jsize jParamLength = _env->GetArrayLength(paramArray);
455  jlong* jFieldIDs = _env->GetLongArrayElements(fieldIDArray, nullptr);
456  jsize fieldIDs_length = _env->GetArrayLength(fieldIDArray);
457  jlong* jValues = _env->GetLongArrayElements(valueArray, nullptr);
458  jsize values_length = _env->GetArrayLength(valueArray);
459  jint* jSizes = _env->GetIntArrayElements(sizeArray, nullptr);
460  jsize sizes_length = _env->GetArrayLength(sizeArray);
461
462  size_t numValues;
463  RsScriptFieldID* fieldIDs;
464
465  if (fieldIDs_length != values_length || values_length != sizes_length) {
466      LOG_ERR("Unmatched field IDs, values, and sizes in closure creation.");
467      goto exit;
468  }
469
470  numValues = (size_t) fieldIDs_length;
471
472  if (numValues > RS_CLOSURE_MAX_NUMBER_ARGS_AND_BINDINGS) {
473      LOG_ERR("Too many arguments or globals in closure creation");
474      goto exit;
475  }
476
477  fieldIDs = (RsScriptFieldID*)alloca(sizeof(RsScriptFieldID) * numValues);
478  if (fieldIDs == nullptr) {
479      goto exit;
480  }
481
482  for (size_t i = 0; i < numValues; i++) {
483    fieldIDs[i] = (RsScriptFieldID)jFieldIDs[i];
484  }
485
486  ret = (jlong)(uintptr_t)dispatchTab.InvokeClosureCreate(
487      (RsContext)con, (RsScriptInvokeID)invokeID, jParams, jParamLength,
488      fieldIDs, numValues, jValues, numValues,
489      (int*)jSizes, numValues);
490
491exit:
492
493  _env->ReleaseIntArrayElements (sizeArray,       jSizes,       JNI_ABORT);
494  _env->ReleaseLongArrayElements(valueArray,      jValues,      JNI_ABORT);
495  _env->ReleaseLongArrayElements(fieldIDArray,    jFieldIDs,    JNI_ABORT);
496  _env->ReleaseByteArrayElements(paramArray,      jParams,      JNI_ABORT);
497
498  return ret;
499}
500
501static void
502nClosureSetArg(JNIEnv *_env, jobject _this, jlong con, jlong closureID,
503               jint index, jlong value, jint size) {
504  // Size is signed with -1 indicating the values is an Allocation
505  dispatchTab.ClosureSetArg((RsContext)con, (RsClosure)closureID, (uint32_t)index,
506                  (uintptr_t)value, size);
507}
508
509static void
510nClosureSetGlobal(JNIEnv *_env, jobject _this, jlong con, jlong closureID,
511                  jlong fieldID, jlong value, jint size) {
512  // Size is signed with -1 indicating the values is an Allocation
513  dispatchTab.ClosureSetGlobal((RsContext)con, (RsClosure)closureID,
514                     (RsScriptFieldID)fieldID, (int64_t)value, size);
515}
516
517static long
518nScriptGroup2Create(JNIEnv *_env, jobject _this, jlong con, jstring name,
519                    jstring cacheDir, jlongArray closureArray) {
520  jlong ret = 0;
521
522  AutoJavaStringToUTF8 nameUTF(_env, name);
523  AutoJavaStringToUTF8 cacheDirUTF(_env, cacheDir);
524
525  jlong* jClosures = _env->GetLongArrayElements(closureArray, nullptr);
526  jsize numClosures = _env->GetArrayLength(closureArray);
527
528  RsClosure* closures;
529
530  if (numClosures > (jsize) RS_SCRIPT_GROUP_MAX_NUMBER_CLOSURES) {
531    LOG_ERR("Too many closures in script group");
532    goto exit;
533  }
534
535  closures = (RsClosure*)alloca(sizeof(RsClosure) * numClosures);
536  if (closures == nullptr) {
537      goto exit;
538  }
539
540  for (int i = 0; i < numClosures; i++) {
541    closures[i] = (RsClosure)jClosures[i];
542  }
543
544  ret = (jlong)(uintptr_t)dispatchTab.ScriptGroup2Create(
545      (RsContext)con, nameUTF.c_str(), nameUTF.length(),
546      cacheDirUTF.c_str(), cacheDirUTF.length(),
547      closures, numClosures);
548
549exit:
550
551  _env->ReleaseLongArrayElements(closureArray, jClosures, JNI_ABORT);
552
553  return ret;
554}
555
556static void
557nScriptGroup2Execute(JNIEnv *_env, jobject _this, jlong con, jlong groupID) {
558  dispatchTab.ScriptGroupExecute((RsContext)con, (RsScriptGroup2)groupID);
559}
560
561static void
562nObjDestroy(JNIEnv *_env, jobject _this, jlong con, jlong obj)
563{
564    LOG_API("nObjDestroy, con(%p) obj(%p)", (RsContext)con, (void *)obj);
565    dispatchTab.ObjDestroy((RsContext)con, (void *)obj);
566}
567
568
569static void
570nScriptIntrinsicBLAS_Single(JNIEnv *_env, jobject _this, jlong con, jlong incCon, jlong id, jint func, jint TransA,
571                            jint TransB, jint Side, jint Uplo, jint Diag, jint M, jint N, jint K,
572                            jfloat alpha, jlong A, jlong B, jfloat beta, jlong C, jint incX, jint incY,
573                            jint KL, jint KU, jboolean mUseInc) {
574    RsBlasCall call;
575    memset(&call, 0, sizeof(call));
576    call.func = (RsBlasFunction)func;
577    call.transA = (RsBlasTranspose)TransA;
578    call.transB = (RsBlasTranspose)TransB;
579    call.side = (RsBlasSide)Side;
580    call.uplo = (RsBlasUplo)Uplo;
581    call.diag = (RsBlasDiag)Diag;
582    call.M = M;
583    call.N = N;
584    call.K = K;
585    call.alpha.f = alpha;
586    call.beta.f = beta;
587    call.incX = incX;
588    call.incY = incY;
589    call.KL = KL;
590    call.KU = KU;
591
592    RsAllocation in_allocs[3];
593    in_allocs[0] = (RsAllocation)A;
594    in_allocs[1] = (RsAllocation)B;
595    in_allocs[2] = (RsAllocation)C;
596
597    if (mUseInc) {
598        dispatchTab.ContextFinish((RsContext)con);
599        dispatchTabInc.ScriptForEachMulti((RsContext)incCon, (RsScript)id, 0,
600                                          in_allocs, NELEM(in_allocs), nullptr,
601                                          &call, sizeof(call), nullptr, 0);
602    } else {
603        dispatchTab.ScriptForEachMulti((RsContext)con, (RsScript)id, 0,
604                                       in_allocs, NELEM(in_allocs), nullptr,
605                                       &call, sizeof(call), nullptr, 0);
606    }
607}
608
609static void
610nScriptIntrinsicBLAS_Double(JNIEnv *_env, jobject _this, jlong con, jlong incCon, jlong id, jint func, jint TransA,
611                            jint TransB, jint Side, jint Uplo, jint Diag, jint M, jint N, jint K,
612                            jdouble alpha, jlong A, jlong B, jdouble beta, jlong C, jint incX, jint incY,
613                            jint KL, jint KU, jboolean mUseInc) {
614    RsBlasCall call;
615    memset(&call, 0, sizeof(call));
616    call.func = (RsBlasFunction)func;
617    call.transA = (RsBlasTranspose)TransA;
618    call.transB = (RsBlasTranspose)TransB;
619    call.side = (RsBlasSide)Side;
620    call.uplo = (RsBlasUplo)Uplo;
621    call.diag = (RsBlasDiag)Diag;
622    call.M = M;
623    call.N = N;
624    call.K = K;
625    call.alpha.d = alpha;
626    call.beta.d = beta;
627    call.incX = incX;
628    call.incY = incY;
629    call.KL = KL;
630    call.KU = KU;
631
632    RsAllocation in_allocs[3];
633    in_allocs[0] = (RsAllocation)A;
634    in_allocs[1] = (RsAllocation)B;
635    in_allocs[2] = (RsAllocation)C;
636
637    if (mUseInc) {
638        dispatchTab.ContextFinish((RsContext)con);
639        dispatchTabInc.ScriptForEachMulti((RsContext)incCon, (RsScript)id, 0,
640                                          in_allocs, NELEM(in_allocs), nullptr,
641                                          &call, sizeof(call), nullptr, 0);
642    } else {
643        dispatchTab.ScriptForEachMulti((RsContext)con, (RsScript)id, 0,
644                                        in_allocs, NELEM(in_allocs), nullptr,
645                                        &call, sizeof(call), nullptr, 0);
646    }
647}
648
649static void
650nScriptIntrinsicBLAS_Complex(JNIEnv *_env, jobject _this, jlong con, jlong incCon, jlong id, jint func, jint TransA,
651                             jint TransB, jint Side, jint Uplo, jint Diag, jint M, jint N, jint K,
652                             jfloat alphaX, jfloat alphaY, jlong A, jlong B, jfloat betaX,
653                             jfloat betaY, jlong C, jint incX, jint incY, jint KL, jint KU, jboolean mUseInc) {
654    RsBlasCall call;
655    memset(&call, 0, sizeof(call));
656    call.func = (RsBlasFunction)func;
657    call.transA = (RsBlasTranspose)TransA;
658    call.transB = (RsBlasTranspose)TransB;
659    call.side = (RsBlasSide)Side;
660    call.uplo = (RsBlasUplo)Uplo;
661    call.diag = (RsBlasDiag)Diag;
662    call.M = M;
663    call.N = N;
664    call.K = K;
665    call.alpha.c.r = alphaX;
666    call.alpha.c.i = alphaY;
667    call.beta.c.r = betaX;
668    call.beta.c.i = betaY;
669    call.incX = incX;
670    call.incY = incY;
671    call.KL = KL;
672    call.KU = KU;
673
674    RsAllocation in_allocs[3];
675    in_allocs[0] = (RsAllocation)A;
676    in_allocs[1] = (RsAllocation)B;
677    in_allocs[2] = (RsAllocation)C;
678
679
680    if (mUseInc) {
681        dispatchTab.ContextFinish((RsContext)con);
682        dispatchTabInc.ScriptForEachMulti((RsContext)incCon, (RsScript)id, 0,
683                                          in_allocs, NELEM(in_allocs), nullptr,
684                                          &call, sizeof(call), nullptr, 0);
685    } else {
686        dispatchTab.ScriptForEachMulti((RsContext)con, (RsScript)id, 0,
687                                       in_allocs, NELEM(in_allocs), nullptr,
688                                       &call, sizeof(call), nullptr, 0);
689    }
690}
691
692static void
693nScriptIntrinsicBLAS_Z(JNIEnv *_env, jobject _this, jlong con, jlong incCon, jlong id, jint func, jint TransA,
694                       jint TransB, jint Side, jint Uplo, jint Diag, jint M, jint N, jint K,
695                       jdouble alphaX, jdouble alphaY, jlong A, jlong B, jdouble betaX,
696                       jdouble betaY, jlong C, jint incX, jint incY, jint KL, jint KU, jboolean mUseInc) {
697    RsBlasCall call;
698    memset(&call, 0, sizeof(call));
699    call.func = (RsBlasFunction)func;
700    call.transA = (RsBlasTranspose)TransA;
701    call.transB = (RsBlasTranspose)TransB;
702    call.side = (RsBlasSide)Side;
703    call.uplo = (RsBlasUplo)Uplo;
704    call.diag = (RsBlasDiag)Diag;
705    call.M = M;
706    call.N = N;
707    call.K = K;
708    call.alpha.z.r = alphaX;
709    call.alpha.z.i = alphaY;
710    call.beta.z.r = betaX;
711    call.beta.z.i = betaY;
712    call.incX = incX;
713    call.incY = incY;
714    call.KL = KL;
715    call.KU = KU;
716
717    RsAllocation in_allocs[3];
718    in_allocs[0] = (RsAllocation)A;
719    in_allocs[1] = (RsAllocation)B;
720    in_allocs[2] = (RsAllocation)C;
721
722
723    if (mUseInc) {
724        dispatchTab.ContextFinish((RsContext)con);
725        dispatchTabInc.ScriptForEachMulti((RsContext)incCon, (RsScript)id, 0,
726                                          in_allocs, NELEM(in_allocs), nullptr,
727                                          &call, sizeof(call), nullptr, 0);
728    } else {
729        dispatchTab.ScriptForEachMulti((RsContext)con, (RsScript)id, 0,
730                                        in_allocs, NELEM(in_allocs), nullptr,
731                                        &call, sizeof(call), nullptr, 0);
732    }
733}
734
735
736static void
737nScriptIntrinsicBLAS_BNNM(JNIEnv *_env, jobject _this, jlong con, jlong incCon, jlong id, jint M, jint N, jint K,
738                          jlong A, jint a_offset, jlong B, jint b_offset, jlong C, jint c_offset,
739                          jint c_mult_int, jboolean mUseInc) {
740    RsBlasCall call;
741    memset(&call, 0, sizeof(call));
742    call.func = RsBlas_bnnm;
743    call.M = M;
744    call.N = N;
745    call.K = K;
746    call.a_offset = a_offset & 0xFF;
747    call.b_offset = b_offset & 0xFF;
748    call.c_offset = c_offset;
749    call.c_mult_int = c_mult_int;
750
751    RsAllocation in_allocs[3];
752    in_allocs[0] = (RsAllocation)A;
753    in_allocs[1] = (RsAllocation)B;
754    in_allocs[2] = (RsAllocation)C;
755
756    if (mUseInc) {
757        dispatchTab.ContextFinish((RsContext)con);
758        dispatchTabInc.ScriptForEachMulti((RsContext)incCon, (RsScript)id, 0,
759                                          in_allocs, NELEM(in_allocs), nullptr,
760                                          &call, sizeof(call), nullptr, 0);
761    } else {
762        dispatchTab.ScriptForEachMulti((RsContext)con, (RsScript)id, 0,
763                                        in_allocs, NELEM(in_allocs), nullptr,
764                                        &call, sizeof(call), nullptr, 0);
765    }
766}
767// ---------------------------------------------------------------------------
768static jlong
769nDeviceCreate(JNIEnv *_env, jobject _this)
770{
771    LOG_API("nDeviceCreate");
772    return (jlong)(uintptr_t)dispatchTab.DeviceCreate();
773}
774
775static void
776nDeviceDestroy(JNIEnv *_env, jobject _this, jlong dev)
777{
778    LOG_API("nDeviceDestroy");
779    return dispatchTab.DeviceDestroy((RsDevice)dev);
780}
781
782static void
783nDeviceSetConfig(JNIEnv *_env, jobject _this, jlong dev, jint p, jint value)
784{
785    LOG_API("nDeviceSetConfig  dev(%p), param(%i), value(%i)", (void *)dev, p, value);
786    return dispatchTab.DeviceSetConfig((RsDevice)dev, (RsDeviceParam)p, value);
787}
788
789static jlong
790nContextCreate(JNIEnv *_env, jobject _this, jlong dev, jint ver, jint sdkVer,
791               jint ct, jstring nativeLibDirJava)
792{
793    LOG_API("nContextCreate");
794    // Access the NativeLibDir in the Java Context.
795    const char * nativeLibDir = _env->GetStringUTFChars(nativeLibDirJava, JNI_FALSE);
796    size_t length = (size_t)_env->GetStringUTFLength(nativeLibDirJava);
797
798    jlong id = (jlong)(uintptr_t)dispatchTab.ContextCreate((RsDevice)dev, ver,
799                                                           sdkVer,
800                                                           (RsContextType)ct, 0);
801    if (dispatchTab.SetNativeLibDir) {
802        dispatchTab.SetNativeLibDir((RsContext)id, nativeLibDir, length);
803    }
804
805    _env->ReleaseStringUTFChars(nativeLibDirJava, nativeLibDir);
806    return id;
807}
808
809
810static void
811nContextSetPriority(JNIEnv *_env, jobject _this, jlong con, jint p)
812{
813    LOG_API("ContextSetPriority, con(%p), priority(%i)", (RsContext)con, p);
814    dispatchTab.ContextSetPriority((RsContext)con, p);
815}
816
817
818
819static void
820nContextDestroy(JNIEnv *_env, jobject _this, jlong con)
821{
822    LOG_API("nContextDestroy, con(%p)", (RsContext)con);
823    dispatchTab.ContextDestroy((RsContext)con);
824}
825
826static void
827nContextDump(JNIEnv *_env, jobject _this, jlong con, jint bits)
828{
829    LOG_API("nContextDump, con(%p)  bits(%i)", (RsContext)con, bits);
830    dispatchTab.ContextDump((RsContext)con, bits);
831}
832
833
834static jstring
835nContextGetErrorMessage(JNIEnv *_env, jobject _this, jlong con)
836{
837    LOG_API("nContextGetErrorMessage, con(%p)", (RsContext)con);
838    char buf[1024];
839
840    size_t receiveLen;
841    uint32_t subID;
842    int id = dispatchTab.ContextGetMessage((RsContext)con,
843                                           buf, sizeof(buf),
844                                           &receiveLen, sizeof(receiveLen),
845                                           &subID, sizeof(subID));
846    if (!id && receiveLen) {
847        //        __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG,
848        //            "message receive buffer too small.  %zu", receiveLen);
849    }
850    return _env->NewStringUTF(buf);
851}
852
853static jint
854nContextGetUserMessage(JNIEnv *_env, jobject _this, jlong con, jintArray data)
855{
856    jint len = _env->GetArrayLength(data);
857    LOG_API("nContextGetMessage, con(%p), len(%i)", (RsContext)con, len);
858    jint *ptr = _env->GetIntArrayElements(data, NULL);
859    size_t receiveLen;
860    uint32_t subID;
861    int id = dispatchTab.ContextGetMessage((RsContext)con,
862                                           ptr, len * 4,
863                                           &receiveLen, sizeof(receiveLen),
864                                           &subID, sizeof(subID));
865    if (!id && receiveLen) {
866        //        __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG,
867        //            "message receive buffer too small.  %zu", receiveLen);
868    }
869    _env->ReleaseIntArrayElements(data, ptr, 0);
870    return (jint)id;
871}
872
873static jint
874nContextPeekMessage(JNIEnv *_env, jobject _this, jlong con, jintArray auxData)
875{
876    LOG_API("nContextPeekMessage, con(%p)", (RsContext)con);
877    jint *auxDataPtr = _env->GetIntArrayElements(auxData, NULL);
878    size_t receiveLen;
879    uint32_t subID;
880    int id = dispatchTab.ContextPeekMessage((RsContext)con, &receiveLen, sizeof(receiveLen),
881                                  &subID, sizeof(subID));
882    auxDataPtr[0] = (jint)subID;
883    auxDataPtr[1] = (jint)receiveLen;
884    _env->ReleaseIntArrayElements(auxData, auxDataPtr, 0);
885    return (jint)id;
886}
887
888static void nContextInitToClient(JNIEnv *_env, jobject _this, jlong con)
889{
890    LOG_API("nContextInitToClient, con(%p)", (RsContext)con);
891    dispatchTab.ContextInitToClient((RsContext)con);
892}
893
894static void nContextDeinitToClient(JNIEnv *_env, jobject _this, jlong con)
895{
896    LOG_API("nContextDeinitToClient, con(%p)", (RsContext)con);
897    dispatchTab.ContextDeinitToClient((RsContext)con);
898}
899
900static void
901nContextSendMessage(JNIEnv *_env, jobject _this, jlong con, jint id, jintArray data)
902{
903    jint *ptr = NULL;
904    jint len = 0;
905    if (data) {
906        len = _env->GetArrayLength(data);
907        ptr = _env->GetIntArrayElements(data, NULL);
908    }
909    LOG_API("nContextSendMessage, con(%p), id(%i), len(%i)", (RsContext)con, id, len);
910    dispatchTab.ContextSendMessage((RsContext)con, id, (const uint8_t *)ptr, len * sizeof(int));
911    if (data) {
912        _env->ReleaseIntArrayElements(data, ptr, JNI_ABORT);
913    }
914}
915
916
917
918static jlong
919nElementCreate(JNIEnv *_env, jobject _this, jlong con, jlong type, jint kind,
920               jboolean norm, jint size)
921{
922    LOG_API("nElementCreate, con(%p), type(%i), kind(%i), norm(%i), size(%i)", (RsContext)con,
923            type, kind, norm, size);
924    return (jlong)(uintptr_t)dispatchTab.ElementCreate((RsContext)con,
925                                                       (RsDataType)type,
926                                                       (RsDataKind)kind,
927                                                       norm, size);
928}
929
930static jlong
931nElementCreate2(JNIEnv *_env, jobject _this, jlong con,
932                jlongArray _ids, jobjectArray _names, jintArray _arraySizes)
933{
934    int fieldCount = _env->GetArrayLength(_ids);
935    LOG_API("nElementCreate2, con(%p)", (RsContext)con);
936
937    jlong *jIds = _env->GetLongArrayElements(_ids, NULL);
938    jint *jArraySizes = _env->GetIntArrayElements(_arraySizes, NULL);
939
940    RsElement *ids = (RsElement*)malloc(fieldCount * sizeof(RsElement));
941    uint32_t *arraySizes = (uint32_t *)malloc(fieldCount * sizeof(uint32_t));
942
943    for(int i = 0; i < fieldCount; i ++) {
944        ids[i] = (RsElement)jIds[i];
945        arraySizes[i] = (uint32_t)jArraySizes[i];
946    }
947
948    AutoJavaStringArrayToUTF8 names(_env, _names, fieldCount);
949
950    const char **nameArray = names.c_str();
951    size_t *sizeArray = names.c_str_len();
952
953    jlong id = (jlong)(uintptr_t)dispatchTab.ElementCreate2((RsContext)con, (RsElement *)ids,
954                                                            fieldCount, nameArray,
955                                                            fieldCount * sizeof(size_t),  sizeArray,
956                                                            (const uint32_t *)arraySizes, fieldCount);
957
958    free(ids);
959    free(arraySizes);
960    _env->ReleaseLongArrayElements(_ids, jIds, JNI_ABORT);
961    _env->ReleaseIntArrayElements(_arraySizes, jArraySizes, JNI_ABORT);
962    return id;
963}
964
965
966
967
968static void
969nElementGetSubElements(JNIEnv *_env, jobject _this, jlong con, jlong id,
970                       jlongArray _IDs,
971                       jobjectArray _names,
972                       jintArray _arraySizes)
973{
974    uint32_t dataSize = _env->GetArrayLength(_IDs);
975    LOG_API("nElementGetSubElements, con(%p)", (RsContext)con);
976
977    uintptr_t *ids = (uintptr_t *)malloc(dataSize * sizeof(uintptr_t));
978    const char **names = (const char **)malloc((uint32_t)dataSize * sizeof(const char *));
979    uint32_t *arraySizes = (uint32_t *)malloc((uint32_t)dataSize * sizeof(uint32_t));
980
981    dispatchTab.ElementGetSubElements((RsContext)con, (RsElement)id, ids, names, arraySizes,
982                                      (uint32_t)dataSize);
983
984    for(uint32_t i = 0; i < dataSize; i++) {
985        const jlong id = (jlong)(uintptr_t)ids[i];
986        const jint arraySize = (jint)arraySizes[i];
987        _env->SetObjectArrayElement(_names, i, _env->NewStringUTF(names[i]));
988        _env->SetLongArrayRegion(_IDs, i, 1, &id);
989        _env->SetIntArrayRegion(_arraySizes, i, 1, &arraySize);
990    }
991
992    free(ids);
993    free(names);
994    free(arraySizes);
995}
996
997// -----------------------------------
998
999static jlong
1000nTypeCreate(JNIEnv *_env, jobject _this, jlong con, jlong eid,
1001            jint dimx, jint dimy, jint dimz, jboolean mips, jboolean faces, jint yuv)
1002{
1003    LOG_API("nTypeCreate, con(%p) eid(%p), x(%i), y(%i), z(%i), mips(%i), faces(%i), yuv(%i)",
1004            (RsContext)con, eid, dimx, dimy, dimz, mips, faces, yuv);
1005
1006    return (jlong)(uintptr_t)dispatchTab.TypeCreate((RsContext)con, (RsElement)eid, dimx, dimy,
1007                                                    dimz, mips, faces, yuv);
1008}
1009
1010// -----------------------------------
1011
1012static jlong
1013nAllocationCreateTyped(JNIEnv *_env, jobject _this, jlong con, jlong type, jint mips, jint usage,
1014                       jlong pointer)
1015{
1016    LOG_API("nAllocationCreateTyped, con(%p), type(%p), mip(%i), usage(%i), ptr(%p)",
1017            (RsContext)con, (RsElement)type, mips, usage, (void *)pointer);
1018    return (jlong)(uintptr_t) dispatchTab.AllocationCreateTyped((RsContext)con, (RsType)type,
1019                                                                (RsAllocationMipmapControl)mips,
1020                                                                (uint32_t)usage, (uintptr_t)pointer);
1021}
1022
1023static void
1024nAllocationSyncAll(JNIEnv *_env, jobject _this, jlong con, jlong a, jint bits)
1025{
1026    LOG_API("nAllocationSyncAll, con(%p), a(%p), bits(0x%08x)", (RsContext)con, (RsAllocation)a, bits);
1027    dispatchTab.AllocationSyncAll((RsContext)con, (RsAllocation)a, (RsAllocationUsageType)bits);
1028}
1029
1030static void
1031nAllocationSetSurface(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jobject sur)
1032{
1033    ioDispatch.sAllocationSetSurface(_env, _this, (RsContext)con, (RsAllocation)alloc, sur, dispatchTab);
1034}
1035
1036static void
1037nAllocationIoSend(JNIEnv *_env, jobject _this, jlong con, jlong alloc)
1038{
1039    dispatchTab.AllocationIoSend((RsContext)con, (RsAllocation)alloc);
1040}
1041
1042static void
1043nAllocationGenerateMipmaps(JNIEnv *_env, jobject _this, jlong con, jlong alloc)
1044{
1045    LOG_API("nAllocationGenerateMipmaps, con(%p), a(%p)", (RsContext)con, (RsAllocation)alloc);
1046    dispatchTab.AllocationGenerateMipmaps((RsContext)con, (RsAllocation)alloc);
1047}
1048
1049static size_t GetBitmapSize(JNIEnv *env, jobject jbitmap) {
1050    AndroidBitmapInfo info;
1051    memset(&info, 0, sizeof(info));
1052    AndroidBitmap_getInfo(env, jbitmap, &info);
1053    size_t s = info.width * info.height;
1054    switch (info.format) {
1055        case ANDROID_BITMAP_FORMAT_RGBA_8888: s *= 4; break;
1056        case ANDROID_BITMAP_FORMAT_RGB_565: s *= 2; break;
1057        case ANDROID_BITMAP_FORMAT_RGBA_4444: s *= 2; break;
1058    }
1059    return s;
1060}
1061
1062static jlong
1063nAllocationCreateFromBitmap(JNIEnv *_env, jobject _this, jlong con, jlong type, jint mip,
1064                            jobject jbitmap, jint usage)
1065{
1066    jlong id = 0;
1067    void *pixels = NULL;
1068    AndroidBitmap_lockPixels(_env, jbitmap, &pixels);
1069
1070    if (pixels != NULL) {
1071        id = (jlong)(uintptr_t)dispatchTab.AllocationCreateFromBitmap((RsContext)con,
1072                                                                      (RsType)type,
1073                                                                      (RsAllocationMipmapControl)mip,
1074                                                                      pixels,
1075                                                                      GetBitmapSize(_env, jbitmap),
1076                                                                      usage);
1077        AndroidBitmap_unlockPixels(_env, jbitmap);
1078    }
1079    return id;
1080}
1081
1082static jlong
1083nAllocationCreateBitmapBackedAllocation(JNIEnv *_env, jobject _this, jlong con, jlong type,
1084                                        jint mip, jobject jbitmap, jint usage)
1085{
1086    jlong id = 0;
1087    void *pixels = NULL;
1088    AndroidBitmap_lockPixels(_env, jbitmap, &pixels);
1089
1090    if (pixels != NULL) {
1091        id = (jlong)(uintptr_t)dispatchTab.AllocationCreateTyped((RsContext)con,
1092                                                                 (RsType)type,
1093                                                                 (RsAllocationMipmapControl)mip,
1094                                                                 (uint32_t)usage,
1095                                                                 (uintptr_t)pixels);
1096        AndroidBitmap_unlockPixels(_env, jbitmap);
1097    }
1098    return id;
1099}
1100
1101static jlong
1102nAllocationCubeCreateFromBitmap(JNIEnv *_env, jobject _this, jlong con, jlong type,
1103                                jint mip, jobject jbitmap, jint usage)
1104{
1105    void *pixels = NULL;
1106    AndroidBitmap_lockPixels(_env, jbitmap, &pixels);
1107
1108    jlong id = 0;
1109    if (pixels != NULL) {
1110        id = (jlong)(uintptr_t)dispatchTab.AllocationCubeCreateFromBitmap((RsContext)con,
1111                                                                          (RsType)type,
1112                                                                          (RsAllocationMipmapControl)mip,
1113                                                                          pixels,
1114                                                                          GetBitmapSize(_env, jbitmap),
1115                                                                          usage);
1116        AndroidBitmap_unlockPixels(_env, jbitmap);
1117    }
1118    return id;
1119}
1120
1121static void
1122nAllocationCopyFromBitmap(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jobject jbitmap)
1123{
1124    AndroidBitmapInfo info;
1125    memset(&info, 0, sizeof(info));
1126    AndroidBitmap_getInfo(_env, jbitmap, &info);
1127
1128    void *pixels = NULL;
1129    AndroidBitmap_lockPixels(_env, jbitmap, &pixels);
1130
1131    if (pixels != NULL) {
1132        dispatchTab.Allocation2DData((RsContext)con, (RsAllocation)alloc, 0, 0, 0,
1133                                     RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X, info.width,
1134                                     info.height, pixels, GetBitmapSize(_env, jbitmap), 0);
1135        AndroidBitmap_unlockPixels(_env, jbitmap);
1136    }
1137}
1138
1139static void
1140nAllocationCopyToBitmap(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jobject jbitmap)
1141{
1142    AndroidBitmapInfo info;
1143    memset(&info, 0, sizeof(info));
1144    AndroidBitmap_getInfo(_env, jbitmap, &info);
1145
1146    void *pixels = NULL;
1147    AndroidBitmap_lockPixels(_env, jbitmap, &pixels);
1148
1149    if (pixels != NULL) {
1150        dispatchTab.AllocationCopyToBitmap((RsContext)con, (RsAllocation)alloc, pixels,
1151                                           GetBitmapSize(_env, jbitmap));
1152        AndroidBitmap_unlockPixels(_env, jbitmap);
1153    }
1154    //bitmap.notifyPixelsChanged();
1155}
1156
1157// Copies from the Java object data into the Allocation pointed to by _alloc.
1158static void
1159nAllocationData1D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint offset, jint lod,
1160                  jint count, jobject data, jint sizeBytes, jint dataType, jint mSize,
1161                  jboolean usePadding)
1162{
1163    RsAllocation *alloc = (RsAllocation *)_alloc;
1164    LOG_API("nAllocation1DData, con(%p), adapter(%p), offset(%i), count(%i), sizeBytes(%i), "
1165            "dataType(%i)", (RsContext)con, (RsAllocation)alloc, offset, count, sizeBytes,
1166            dataType);
1167    PER_ARRAY_TYPE(nullptr, dispatchTab.Allocation1DData, true,
1168                   (RsContext)con, alloc, offset, lod, count, ptr, sizeBytes);
1169}
1170
1171
1172static void
1173nAllocationElementData1D(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jint xoff,
1174                         jint lod, jint compIdx, jbyteArray data, jint sizeBytes)
1175{
1176    jint len = _env->GetArrayLength(data);
1177    LOG_API("nAllocationElementData1D, con(%p), alloc(%p), xoff(%i), comp(%i), len(%i), "
1178            "sizeBytes(%i)", (RsContext)con, (RsAllocation)alloc, xoff, compIdx, len,
1179            sizeBytes);
1180    jbyte *ptr = _env->GetByteArrayElements(data, nullptr);
1181    dispatchTab.Allocation1DElementData((RsContext)con, (RsAllocation)alloc, xoff,
1182                                        lod, ptr, sizeBytes, compIdx);
1183    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
1184}
1185
1186/*
1187static void
1188nAllocationElementData(JNIEnv *_env, jobject _this, jlong con, jlong alloc,
1189                       jint xoff, jint yoff, jint zoff,
1190                       jint lod, jint compIdx, jbyteArray data, jint sizeBytes)
1191{
1192    jint len = _env->GetArrayLength(data);
1193    LOG_API("nAllocationElementData, con(%p), alloc(%p), xoff(%i), yoff(%i), zoff(%i), comp(%i), len(%i), "
1194            "sizeBytes(%i)", (RsContext)con, (RsAllocation)alloc, xoff, yoff, zoff, compIdx, len,
1195            sizeBytes);
1196    jbyte *ptr = _env->GetByteArrayElements(data, nullptr);
1197    dispatchTab.AllocationElementData((RsContext)con, (RsAllocation)alloc,
1198                                      xoff, yoff, zoff,
1199                                      lod, ptr, sizeBytes, compIdx);
1200    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
1201}
1202*/
1203
1204// Copies from the Java object data into the Allocation pointed to by _alloc.
1205static void
1206nAllocationData2D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint xoff, jint yoff, jint lod, jint _face,
1207                  jint w, jint h, jobject data, jint sizeBytes, jint dataType, jint mSize,
1208                  jboolean usePadding)
1209{
1210    RsAllocation *alloc = (RsAllocation *)_alloc;
1211    RsAllocationCubemapFace face = (RsAllocationCubemapFace)_face;
1212    LOG_API("nAllocation2DData, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i) "
1213            "type(%i)", (RsContext)con, alloc, xoff, yoff, w, h, sizeBytes, dataType);
1214    int count = w * h;
1215    PER_ARRAY_TYPE(nullptr, dispatchTab.Allocation2DData, true,
1216                   (RsContext)con, alloc, xoff, yoff, lod, face, w, h, ptr, sizeBytes, 0);
1217}
1218
1219static void
1220nAllocationData2D_alloc(JNIEnv *_env, jobject _this, jlong con,
1221                        jlong dstAlloc, jint dstXoff, jint dstYoff,
1222                        jint dstMip, jint dstFace,
1223                        jint width, jint height,
1224                        jlong srcAlloc, jint srcXoff, jint srcYoff,
1225                        jint srcMip, jint srcFace)
1226{
1227    LOG_API("nAllocation2DData_s, con(%p), dstAlloc(%p), dstXoff(%i), dstYoff(%i),"
1228            " dstMip(%i), dstFace(%i), width(%i), height(%i),"
1229            " srcAlloc(%p), srcXoff(%i), srcYoff(%i), srcMip(%i), srcFace(%i)",
1230            (RsContext)con, (RsAllocation)dstAlloc, dstXoff, dstYoff, dstMip, dstFace,
1231            width, height, (RsAllocation)srcAlloc, srcXoff, srcYoff, srcMip, srcFace);
1232
1233    dispatchTab.AllocationCopy2DRange((RsContext)con,
1234                                      (RsAllocation)dstAlloc,
1235                                      dstXoff, dstYoff,
1236                                      dstMip, dstFace,
1237                                      width, height,
1238                                      (RsAllocation)srcAlloc,
1239                                      srcXoff, srcYoff,
1240                                      srcMip, srcFace);
1241}
1242
1243// Copies from the Java object data into the Allocation pointed to by _alloc.
1244static void
1245nAllocationData3D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint xoff, jint yoff, jint zoff, jint lod,
1246                  jint w, jint h, jint d, jobject data, jint sizeBytes, jint dataType,
1247                  jint mSize, jboolean usePadding)
1248{
1249    RsAllocation *alloc = (RsAllocation *)_alloc;
1250    LOG_API("nAllocation3DData, con(%p), alloc(%p), xoff(%i), yoff(%i), zoff(%i), lod(%i), w(%i),"
1251            " h(%i), d(%i), sizeBytes(%i)", (RsContext)con, (RsAllocation)alloc, xoff, yoff, zoff,
1252            lod, w, h, d, sizeBytes);
1253    int count = w * h * d;
1254    PER_ARRAY_TYPE(nullptr, dispatchTab.Allocation3DData, true,
1255                   (RsContext)con, alloc, xoff, yoff, zoff, lod, w, h, d, ptr, sizeBytes, 0);
1256}
1257
1258static void
1259nAllocationData3D_alloc(JNIEnv *_env, jobject _this, jlong con,
1260                        jlong dstAlloc, jint dstXoff, jint dstYoff, jint dstZoff,
1261                        jint dstMip,
1262                        jint width, jint height, jint depth,
1263                        jlong srcAlloc, jint srcXoff, jint srcYoff, jint srcZoff,
1264                        jint srcMip)
1265{
1266    LOG_API("nAllocationData3D_alloc, con(%p), dstAlloc(%p), dstXoff(%i), dstYoff(%i),"
1267            " dstMip(%i), width(%i), height(%i),"
1268            " srcAlloc(%p), srcXoff(%i), srcYoff(%i), srcMip(%i)",
1269            (RsContext)con, (RsAllocation)dstAlloc, dstXoff, dstYoff, dstMip, dstFace,
1270            width, height, (RsAllocation)srcAlloc, srcXoff, srcYoff, srcMip, srcFace);
1271
1272    dispatchTab.AllocationCopy3DRange((RsContext)con,
1273                                      (RsAllocation)dstAlloc,
1274                                      dstXoff, dstYoff, dstZoff, dstMip,
1275                                      width, height, depth,
1276                                      (RsAllocation)srcAlloc,
1277                                      srcXoff, srcYoff, srcZoff, srcMip);
1278}
1279
1280// Copies from the Allocation pointed to by _alloc into the Java object data.
1281static void
1282nAllocationRead(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jobject data, jint dataType,
1283                jint mSize, jboolean usePadding)
1284{
1285    RsAllocation *alloc = (RsAllocation *)_alloc;
1286    LOG_API("nAllocationRead, con(%p), alloc(%p)", (RsContext)con, (RsAllocation)alloc);
1287    int count = 0;
1288    PER_ARRAY_TYPE(0, dispatchTab.AllocationRead, false,
1289                   (RsContext)con, alloc, ptr, len * typeBytes);
1290}
1291
1292// Copies from the Allocation pointed to by _alloc into the Java object data.
1293static void
1294nAllocationRead1D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint offset, jint lod,
1295                  jint count, jobject data, jint sizeBytes, jint dataType,
1296                  jint mSize, jboolean usePadding)
1297{
1298    RsAllocation *alloc = (RsAllocation *)_alloc;
1299    LOG_API("nAllocation1DRead, con(%p), adapter(%p), offset(%i), count(%i), sizeBytes(%i), "
1300              "dataType(%i)", (RsContext)con, alloc, offset, count, sizeBytes, dataType);
1301    PER_ARRAY_TYPE(0, dispatchTab.Allocation1DRead, false,
1302                   (RsContext)con, alloc, offset, lod, count, ptr, sizeBytes);
1303}
1304
1305// Copies from the Element in the Allocation pointed to by _alloc into the Java array data.
1306/*
1307static void
1308nAllocationElementRead(JNIEnv *_env, jobject _this, jlong con, jlong _alloc,
1309                       jint xoff, jint yoff, jint zoff,
1310                       jint lod, jint compIdx, jobject data, jint sizeBytes)
1311{
1312    jint len = _env->GetArrayLength(data);
1313    LOG_API("nAllocationElementRead, con(%p), alloc(%p), xoff(%i), yoff(%i), zoff(%i), comp(%i), len(%i), "
1314            "sizeBytes(%i)", (RsContext)con, (RsAllocation)alloc, xoff, yoff, zoff, compIdx, len,
1315            sizeBytes);
1316    jbyte *ptr = _env->GetByteArrayElements(data, nullptr);
1317    dispatchTab.AllocationElementRead((RsContext)con, (RsAllocation)alloc,
1318                                      xoff, yoff, zoff,
1319                                      lod, ptr, sizeBytes, compIdx);
1320    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
1321}
1322*/
1323
1324// Copies from the Allocation pointed to by _alloc into the Java object data.
1325static void
1326nAllocationRead2D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint xoff, jint yoff, jint lod, jint _face,
1327                  jint w, jint h, jobject data, jint sizeBytes, jint dataType,
1328                  jint mSize, jboolean usePadding)
1329{
1330    RsAllocation *alloc = (RsAllocation *)_alloc;
1331    RsAllocationCubemapFace face = (RsAllocationCubemapFace)_face;
1332    LOG_API("nAllocation2DRead, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i) "
1333              "type(%i)", (RsContext)con, alloc, xoff, yoff, w, h, sizeBytes, dataType);
1334    int count = w * h;
1335    PER_ARRAY_TYPE(0, dispatchTab.Allocation2DRead, false,
1336                   (RsContext)con, alloc, xoff, yoff, lod, face, w, h, ptr, sizeBytes, 0);
1337}
1338
1339// Copies from the Allocation pointed to by _alloc into the Java object data.
1340/*
1341static void
1342nAllocationRead3D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint xoff, jint yoff, jint zoff, jint lod,
1343                  jint w, jint h, jint d, jobject data, int sizeBytes, int dataType,
1344                  jint mSize, jboolean usePadding)
1345{
1346    RsAllocation *alloc = (RsAllocation *)_alloc;
1347    LOG_API("nAllocation3DRead, con(%p), alloc(%p), xoff(%i), yoff(%i), zoff(%i), lod(%i), w(%i),"
1348            " h(%i), d(%i), sizeBytes(%i)", (RsContext)con, (RsAllocation)alloc, xoff, yoff, zoff,
1349            lod, w, h, d, sizeBytes);
1350    int count = w * h * d;
1351    PER_ARRAY_TYPE(nullptr, dispatchTab.Allocation3DRead, false,
1352                   (RsContext)con, alloc, xoff, yoff, zoff, lod, w, h, d, ptr, sizeBytes, 0);
1353}
1354*/
1355
1356static jlong
1357nAllocationGetType(JNIEnv *_env, jobject _this, jlong con, jlong a)
1358{
1359    LOG_API("nAllocationGetType, con(%p), a(%p)", (RsContext)con, (RsAllocation)a);
1360    return (jlong)(uintptr_t) dispatchTab.AllocationGetType((RsContext)con, (RsAllocation)a);
1361}
1362
1363static void
1364nAllocationResize1D(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jint dimX)
1365{
1366    LOG_API("nAllocationResize1D, con(%p), alloc(%p), sizeX(%i)", (RsContext)con,
1367            (RsAllocation)alloc, dimX);
1368    dispatchTab.AllocationResize1D((RsContext)con, (RsAllocation)alloc, dimX);
1369}
1370
1371// -----------------------------------
1372
1373static void
1374nScriptBindAllocation(JNIEnv *_env, jobject _this, jlong con, jlong script, jlong alloc, jint slot, jboolean mUseInc)
1375{
1376    LOG_API("nScriptBindAllocation, con(%p), script(%p), alloc(%p), slot(%i)",
1377            (RsContext)con, (RsScript)script, (RsAllocation)alloc, slot);
1378    if (mUseInc) {
1379        dispatchTabInc.ScriptBindAllocation((RsContext)con, (RsScript)script, (RsAllocation)alloc, slot);
1380    } else {
1381        dispatchTab.ScriptBindAllocation((RsContext)con, (RsScript)script, (RsAllocation)alloc, slot);
1382    }
1383}
1384
1385static void
1386nScriptSetVarI(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jint val, jboolean mUseInc)
1387{
1388    LOG_API("nScriptSetVarI, con(%p), s(%p), slot(%i), val(%i)", (RsContext)con,
1389            (void *)script, slot, val);
1390    if (mUseInc) {
1391        dispatchTabInc.ScriptSetVarI((RsContext)con, (RsScript)script, slot, val);
1392    } else {
1393        dispatchTab.ScriptSetVarI((RsContext)con, (RsScript)script, slot, val);
1394    }
1395}
1396
1397static void
1398nScriptSetVarObj(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jlong val, jboolean mUseInc)
1399{
1400    LOG_API("nScriptSetVarObj, con(%p), s(%p), slot(%i), val(%i)", (RsContext)con,
1401            (void *)script, slot, val);
1402    if (mUseInc) {
1403        dispatchTabInc.ScriptSetVarObj((RsContext)con, (RsScript)script, slot, (RsObjectBase)val);
1404    } else {
1405        dispatchTab.ScriptSetVarObj((RsContext)con, (RsScript)script, slot, (RsObjectBase)val);
1406    }
1407}
1408
1409static void
1410nScriptSetVarJ(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jlong val, jboolean mUseInc)
1411{
1412    LOG_API("nScriptSetVarJ, con(%p), s(%p), slot(%i), val(%lli)", (RsContext)con,
1413            (void *)script, slot, val);
1414    if (mUseInc) {
1415        dispatchTabInc.ScriptSetVarJ((RsContext)con, (RsScript)script, slot, val);
1416    } else {
1417        dispatchTab.ScriptSetVarJ((RsContext)con, (RsScript)script, slot, val);
1418    }
1419}
1420
1421static void
1422nScriptSetVarF(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, float val, jboolean mUseInc)
1423{
1424    LOG_API("nScriptSetVarF, con(%p), s(%p), slot(%i), val(%f)", (RsContext)con,
1425            (void *)script, slot, val);
1426    if (mUseInc) {
1427        dispatchTabInc.ScriptSetVarF((RsContext)con, (RsScript)script, slot, val);
1428    } else {
1429        dispatchTab.ScriptSetVarF((RsContext)con, (RsScript)script, slot, val);
1430    }
1431}
1432
1433static void
1434nScriptSetVarD(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, double val, jboolean mUseInc)
1435{
1436    LOG_API("nScriptSetVarD, con(%p), s(%p), slot(%i), val(%lf)", (RsContext)con,
1437            (void *)script, slot, val);
1438    if (mUseInc) {
1439        dispatchTabInc.ScriptSetVarD((RsContext)con, (RsScript)script, slot, val);
1440    } else {
1441        dispatchTab.ScriptSetVarD((RsContext)con, (RsScript)script, slot, val);
1442    }
1443}
1444
1445static void
1446nScriptSetVarV(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jbyteArray data, jboolean mUseInc)
1447{
1448    LOG_API("nScriptSetVarV, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
1449    jint len = _env->GetArrayLength(data);
1450    jbyte *ptr = _env->GetByteArrayElements(data, NULL);
1451    if (mUseInc) {
1452        dispatchTabInc.ScriptSetVarV((RsContext)con, (RsScript)script, slot, ptr, len);
1453    } else {
1454        dispatchTab.ScriptSetVarV((RsContext)con, (RsScript)script, slot, ptr, len);
1455    }
1456    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
1457}
1458
1459static void
1460nScriptSetVarVE(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jbyteArray data,
1461                jlong elem, jintArray dims, jboolean mUseInc)
1462{
1463    LOG_API("nScriptSetVarVE, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
1464    jint len = _env->GetArrayLength(data);
1465    jbyte *ptr = _env->GetByteArrayElements(data, NULL);
1466    jint dimsLen = _env->GetArrayLength(dims) * sizeof(int);
1467    jint *dimsPtr = _env->GetIntArrayElements(dims, NULL);
1468    if (mUseInc) {
1469        dispatchTabInc.ScriptSetVarVE((RsContext)con, (RsScript)script, slot, ptr, len, (RsElement)elem,
1470                                      (const uint32_t *)dimsPtr, dimsLen);
1471    } else {
1472        dispatchTab.ScriptSetVarVE((RsContext)con, (RsScript)script, slot, ptr, len, (RsElement)elem,
1473                                   (const uint32_t *)dimsPtr, dimsLen);
1474    }
1475    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
1476    _env->ReleaseIntArrayElements(dims, dimsPtr, JNI_ABORT);
1477}
1478
1479
1480static void
1481nScriptSetTimeZone(JNIEnv *_env, jobject _this, jlong con, jlong script, jbyteArray timeZone, jboolean mUseInc)
1482{
1483    LOG_API("nScriptCSetTimeZone, con(%p), s(%p), timeZone(%s)", (RsContext)con,
1484            (void *)script, (const char *)timeZone);
1485
1486    jint length = _env->GetArrayLength(timeZone);
1487    jbyte* timeZone_ptr;
1488    timeZone_ptr = (jbyte *) _env->GetPrimitiveArrayCritical(timeZone, (jboolean *)0);
1489    if (mUseInc) {
1490        dispatchTabInc.ScriptSetTimeZone((RsContext)con, (RsScript)script, (const char *)timeZone_ptr, length);
1491    } else {
1492        dispatchTab.ScriptSetTimeZone((RsContext)con, (RsScript)script, (const char *)timeZone_ptr, length);
1493    }
1494
1495    if (timeZone_ptr) {
1496        _env->ReleasePrimitiveArrayCritical(timeZone, timeZone_ptr, 0);
1497    }
1498}
1499
1500static void
1501nScriptInvoke(JNIEnv *_env, jobject _this, jlong con, jlong obj, jint slot, jboolean mUseInc)
1502{
1503    LOG_API("nScriptInvoke, con(%p), script(%p)", (RsContext)con, (void *)obj);
1504    if (mUseInc) {
1505        dispatchTabInc.ScriptInvoke((RsContext)con, (RsScript)obj, slot);
1506    } else {
1507        dispatchTab.ScriptInvoke((RsContext)con, (RsScript)obj, slot);
1508    }
1509}
1510
1511static void
1512nScriptInvokeV(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jbyteArray data, jboolean mUseInc)
1513{
1514    LOG_API("nScriptInvokeV, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
1515    jint len = _env->GetArrayLength(data);
1516    jbyte *ptr = _env->GetByteArrayElements(data, NULL);
1517    if (mUseInc) {
1518        dispatchTabInc.ScriptInvokeV((RsContext)con, (RsScript)script, slot, ptr, len);
1519    } else {
1520        dispatchTab.ScriptInvokeV((RsContext)con, (RsScript)script, slot, ptr, len);
1521    }
1522    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
1523}
1524
1525static void
1526nScriptForEach(JNIEnv *_env, jobject _this, jlong con, jlong incCon,
1527               jlong script, jint slot, jlong ain, jlong aout, jboolean mUseInc)
1528{
1529    LOG_API("nScriptForEach, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
1530    if (mUseInc) {
1531        dispatchTab.ContextFinish((RsContext)con);
1532        dispatchTabInc.ScriptForEach((RsContext)incCon, (RsScript)script, slot,
1533                                     (RsAllocation)ain, (RsAllocation)aout,
1534                                     NULL, 0, NULL, 0);
1535    } else {
1536        dispatchTab.ScriptForEach((RsContext)con, (RsScript)script, slot,
1537                                  (RsAllocation)ain, (RsAllocation)aout,
1538                                  NULL, 0, NULL, 0);
1539    }
1540}
1541
1542static void
1543nScriptForEachV(JNIEnv *_env, jobject _this, jlong con, jlong incCon,
1544                jlong script, jint slot, jlong ain, jlong aout, jbyteArray params, jboolean mUseInc)
1545{
1546    LOG_API("nScriptForEach, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
1547    jint len = _env->GetArrayLength(params);
1548    jbyte *ptr = _env->GetByteArrayElements(params, NULL);
1549    if (mUseInc) {
1550        dispatchTab.ContextFinish((RsContext)con);
1551        dispatchTabInc.ScriptForEach((RsContext)incCon, (RsScript)script, slot,
1552                                     (RsAllocation)ain, (RsAllocation)aout,
1553                                     ptr, len, NULL, 0);
1554    } else {
1555        dispatchTab.ScriptForEach((RsContext)con, (RsScript)script, slot,
1556                                  (RsAllocation)ain, (RsAllocation)aout,
1557                                  ptr, len, NULL, 0);
1558    }
1559    _env->ReleaseByteArrayElements(params, ptr, JNI_ABORT);
1560}
1561
1562static void
1563nScriptForEachClipped(JNIEnv *_env, jobject _this, jlong con, jlong incCon,
1564                      jlong script, jint slot, jlong ain, jlong aout,
1565                      jint xstart, jint xend,
1566                      jint ystart, jint yend, jint zstart, jint zend, jboolean mUseInc)
1567{
1568    LOG_API("nScriptForEachClipped, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
1569    RsScriptCall sc;
1570    sc.xStart = xstart;
1571    sc.xEnd = xend;
1572    sc.yStart = ystart;
1573    sc.yEnd = yend;
1574    sc.zStart = zstart;
1575    sc.zEnd = zend;
1576    sc.strategy = RS_FOR_EACH_STRATEGY_DONT_CARE;
1577    sc.arrayStart = 0;
1578    sc.arrayEnd = 0;
1579    if (mUseInc) {
1580        dispatchTab.ContextFinish((RsContext)con);
1581        dispatchTabInc.ScriptForEach((RsContext)incCon, (RsScript)script, slot,
1582                                     (RsAllocation)ain, (RsAllocation)aout,
1583                                     NULL, 0, &sc, sizeof(sc));
1584    } else {
1585        dispatchTab.ScriptForEach((RsContext)con, (RsScript)script, slot,
1586                                  (RsAllocation)ain, (RsAllocation)aout,
1587                                  NULL, 0, &sc, sizeof(sc));
1588    }
1589}
1590
1591static void
1592nScriptForEachClippedV(JNIEnv *_env, jobject _this, jlong con, jlong incCon,
1593                       jlong script, jint slot, jlong ain, jlong aout,
1594                       jbyteArray params, jint xstart, jint xend,
1595                       jint ystart, jint yend, jint zstart, jint zend, jboolean mUseInc)
1596{
1597    LOG_API("nScriptForEachClipped, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
1598    jint len = _env->GetArrayLength(params);
1599    jbyte *ptr = _env->GetByteArrayElements(params, NULL);
1600    RsScriptCall sc;
1601    sc.xStart = xstart;
1602    sc.xEnd = xend;
1603    sc.yStart = ystart;
1604    sc.yEnd = yend;
1605    sc.zStart = zstart;
1606    sc.zEnd = zend;
1607    sc.strategy = RS_FOR_EACH_STRATEGY_DONT_CARE;
1608    sc.arrayStart = 0;
1609    sc.arrayEnd = 0;
1610    if (mUseInc) {
1611        dispatchTab.ContextFinish((RsContext)con);
1612        dispatchTabInc.ScriptForEach((RsContext)incCon, (RsScript)script, slot,
1613                                     (RsAllocation)ain, (RsAllocation)aout,
1614                                     ptr, len, &sc, sizeof(sc));
1615    } else {
1616        dispatchTab.ScriptForEach((RsContext)con, (RsScript)script, slot,
1617                                  (RsAllocation)ain, (RsAllocation)aout,
1618                                  ptr, len, &sc, sizeof(sc));
1619    }
1620    _env->ReleaseByteArrayElements(params, ptr, JNI_ABORT);
1621}
1622
1623static void
1624nScriptForEachMulti(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot,
1625                    jlongArray ains, jlong aout, jbyteArray params,
1626                    jintArray limits)
1627{
1628    LOG_API("nScriptForEach, con(%p), s(%p), slot(%i) ains(%p) aout(%" PRId64 ")", (RsContext)con, (void *)script, slot, ains, aout);
1629
1630    jint   in_len = 0;
1631    jlong *in_ptr = nullptr;
1632
1633    RsAllocation *in_allocs = nullptr;
1634
1635    if (ains != nullptr) {
1636        in_len = _env->GetArrayLength(ains);
1637        if (in_len > (jint)RS_KERNEL_MAX_ARGUMENTS) {
1638            LOG_ERR("Too many arguments in kernel launch.");
1639            // TODO (b/20758983): Report back to Java and throw an exception
1640            return;
1641        }
1642
1643        // TODO (b/20760800): Check in_ptr is not null
1644        in_ptr = _env->GetLongArrayElements(ains, nullptr);
1645        if (sizeof(RsAllocation) == sizeof(jlong)) {
1646            in_allocs = (RsAllocation*)in_ptr;
1647
1648        } else {
1649            // Convert from 64-bit jlong types to the native pointer type.
1650
1651            in_allocs = (RsAllocation*)alloca(in_len * sizeof(RsAllocation));
1652            if (in_allocs == nullptr) {
1653                LOG_ERR("Failed launching kernel for lack of memory.");
1654                _env->ReleaseLongArrayElements(ains, in_ptr, JNI_ABORT);
1655                return;
1656            }
1657
1658            for (int index = in_len; --index >= 0;) {
1659                in_allocs[index] = (RsAllocation)in_ptr[index];
1660            }
1661        }
1662    }
1663
1664    jint   param_len = 0;
1665    jbyte *param_ptr = nullptr;
1666
1667    if (params != nullptr) {
1668        param_len = _env->GetArrayLength(params);
1669        param_ptr = _env->GetByteArrayElements(params, nullptr);
1670    }
1671
1672    RsScriptCall sc, *sca = nullptr;
1673    uint32_t sc_size = 0;
1674
1675    jint  limit_len = 0;
1676    jint *limit_ptr = nullptr;
1677
1678    if (limits != nullptr) {
1679        limit_len = _env->GetArrayLength(limits);
1680        limit_ptr = _env->GetIntArrayElements(limits, nullptr);
1681
1682        if (limit_len != 6) {
1683            LOG_ERR("LaunchOptions cannot be recognized.");
1684            goto exit;
1685        }
1686
1687        sc.xStart     = limit_ptr[0];
1688        sc.xEnd       = limit_ptr[1];
1689        sc.yStart     = limit_ptr[2];
1690        sc.yEnd       = limit_ptr[3];
1691        sc.zStart     = limit_ptr[4];
1692        sc.zEnd       = limit_ptr[5];
1693        sc.strategy   = RS_FOR_EACH_STRATEGY_DONT_CARE;
1694        sc.arrayStart = 0;
1695        sc.arrayEnd = 0;
1696        sc.array2Start = 0;
1697        sc.array2End = 0;
1698        sc.array3Start = 0;
1699        sc.array3End = 0;
1700        sc.array4Start = 0;
1701        sc.array4End = 0;
1702
1703        sca = &sc;
1704    }
1705
1706    dispatchTabInc.ScriptForEachMulti((RsContext)con, (RsScript)script, slot,
1707                                      in_allocs, in_len, (RsAllocation)aout,
1708                                      param_ptr, param_len, sca, sc_size);
1709
1710exit:
1711
1712    if (ains != nullptr) {
1713        _env->ReleaseLongArrayElements(ains, in_ptr, JNI_ABORT);
1714    }
1715
1716    if (params != nullptr) {
1717        _env->ReleaseByteArrayElements(params, param_ptr, JNI_ABORT);
1718    }
1719
1720    if (limits != nullptr) {
1721        _env->ReleaseIntArrayElements(limits, limit_ptr, JNI_ABORT);
1722    }
1723}
1724
1725static void
1726nScriptReduce(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot,
1727              jlong ain, jlong aout, jintArray limits)
1728{
1729    LOG_API("nScriptReduce, con(%p), s(%p), slot(%i) ain(%" PRId64 ") aout(%" PRId64 ")", (RsContext)con, (void *)script, slot, ain, aout);
1730
1731    RsScriptCall sc, *sca = nullptr;
1732    uint32_t sc_size = 0;
1733
1734    jint  limit_len = 0;
1735    jint *limit_ptr = nullptr;
1736
1737    bool limitLengthValid = true;
1738
1739    // If the caller passed limits, reflect them in the RsScriptCall.
1740    if (limits != nullptr) {
1741        limit_len = _env->GetArrayLength(limits);
1742        limit_ptr = _env->GetIntArrayElements(limits, nullptr);
1743
1744        // We expect to be passed an array [x1, x2] which specifies
1745        // the sub-range for a 1-dimensional reduction.
1746        if (limit_len == 2) {
1747            sc.xStart     = limit_ptr[0];
1748            sc.xEnd       = limit_ptr[1];
1749            sc.yStart     = 0;
1750            sc.yEnd       = 0;
1751            sc.zStart     = 0;
1752            sc.zEnd       = 0;
1753            sc.strategy   = RS_FOR_EACH_STRATEGY_DONT_CARE;
1754            sc.arrayStart = 0;
1755            sc.arrayEnd = 0;
1756            sc.array2Start = 0;
1757            sc.array2End = 0;
1758            sc.array3Start = 0;
1759            sc.array3End = 0;
1760            sc.array4Start = 0;
1761            sc.array4End = 0;
1762
1763            sca = &sc;
1764            sc_size = sizeof(sc);
1765        } else {
1766            LOG_ERR("LaunchOptions cannot be recognized.");
1767            limitLengthValid = false;
1768        }
1769    }
1770
1771    if (limitLengthValid) {
1772        dispatchTab.ScriptReduce((RsContext)con, (RsScript)script, slot,
1773                                 (RsAllocation)ain, (RsAllocation)aout,
1774                                 sca, sc_size);
1775    }
1776
1777    if (limits != nullptr) {
1778        _env->ReleaseIntArrayElements(limits, limit_ptr, JNI_ABORT);
1779    }
1780}
1781
1782// -----------------------------------
1783
1784static jlong
1785nScriptCCreate(JNIEnv *_env, jobject _this, jlong con,
1786               jstring resName, jstring cacheDir,
1787               jbyteArray scriptRef, jint length)
1788{
1789    LOG_API("nScriptCCreate, con(%p)", (RsContext)con);
1790
1791    AutoJavaStringToUTF8 resNameUTF(_env, resName);
1792    AutoJavaStringToUTF8 cacheDirUTF(_env, cacheDir);
1793    jlong ret = 0;
1794    jbyte* script_ptr = NULL;
1795    jint _exception = 0;
1796    jint remaining;
1797    if (!scriptRef) {
1798        _exception = 1;
1799        //jniThrowException(_env, "java/lang/IllegalArgumentException", "script == null");
1800        goto exit;
1801    }
1802    if (length < 0) {
1803        _exception = 1;
1804        //jniThrowException(_env, "java/lang/IllegalArgumentException", "length < 0");
1805        goto exit;
1806    }
1807    remaining = _env->GetArrayLength(scriptRef);
1808    if (remaining < length) {
1809        _exception = 1;
1810        //jniThrowException(_env, "java/lang/IllegalArgumentException",
1811        //        "length > script.length - offset");
1812        goto exit;
1813    }
1814    script_ptr = (jbyte *)
1815        _env->GetPrimitiveArrayCritical(scriptRef, (jboolean *)0);
1816
1817    //rsScriptCSetText(con, (const char *)script_ptr, length);
1818
1819    ret = (jlong)(uintptr_t)dispatchTab.ScriptCCreate((RsContext)con,
1820                                                      resNameUTF.c_str(), resNameUTF.length(),
1821                                                      cacheDirUTF.c_str(), cacheDirUTF.length(),
1822                                                      (const char *)script_ptr, length);
1823
1824exit:
1825    if (script_ptr) {
1826        _env->ReleasePrimitiveArrayCritical(scriptRef, script_ptr,
1827                _exception ? JNI_ABORT: 0);
1828    }
1829
1830    return (jlong)(uintptr_t)ret;
1831}
1832
1833static jlong
1834nScriptIntrinsicCreate(JNIEnv *_env, jobject _this, jlong con, jint id, jlong eid, jboolean mUseInc)
1835{
1836    LOG_API("nScriptIntrinsicCreate, con(%p) id(%i) element(%p)", (RsContext)con, id, (void *)eid);
1837    if (mUseInc) {
1838        return (jlong)(uintptr_t)dispatchTabInc.ScriptIntrinsicCreate((RsContext)con, id, (RsElement)eid);
1839    } else {
1840        return (jlong)(uintptr_t)dispatchTab.ScriptIntrinsicCreate((RsContext)con, id, (RsElement)eid);
1841    }
1842}
1843
1844static jlong
1845nScriptKernelIDCreate(JNIEnv *_env, jobject _this, jlong con, jlong sid, jint slot, jint sig, jboolean mUseInc)
1846{
1847    LOG_API("nScriptKernelIDCreate, con(%p) script(%p), slot(%i), sig(%i)", (RsContext)con,
1848            (void *)sid, slot, sig);
1849    if (mUseInc) {
1850        return (jlong)(uintptr_t)dispatchTabInc.ScriptKernelIDCreate((RsContext)con, (RsScript)sid,
1851                                                                     slot, sig);
1852    } else {
1853        return (jlong)(uintptr_t)dispatchTab.ScriptKernelIDCreate((RsContext)con, (RsScript)sid,
1854                                                                  slot, sig);
1855    }
1856}
1857
1858static jlong
1859nScriptInvokeIDCreate(JNIEnv *_env, jobject _this, jlong con, jlong sid, jint slot)
1860{
1861    LOG_API("nScriptInvokeIDCreate, con(%p) script(%p), slot(%i), sig(%i)", con,
1862            (void *)sid, slot);
1863    return (jlong)dispatchTab.ScriptInvokeIDCreate((RsContext)con, (RsScript)sid, slot);
1864}
1865
1866static jlong
1867nScriptFieldIDCreate(JNIEnv *_env, jobject _this, jlong con, jlong sid, jint slot, jboolean mUseInc)
1868{
1869    LOG_API("nScriptFieldIDCreate, con(%p) script(%p), slot(%i)", (RsContext)con, (void *)sid, slot);
1870    if (mUseInc) {
1871        return (jlong)(uintptr_t)dispatchTabInc.ScriptFieldIDCreate((RsContext)con, (RsScript)sid, slot);
1872    } else {
1873        return (jlong)(uintptr_t)dispatchTab.ScriptFieldIDCreate((RsContext)con, (RsScript)sid, slot);
1874    }
1875}
1876
1877static jlong
1878nScriptGroupCreate(JNIEnv *_env, jobject _this, jlong con, jlongArray _kernels, jlongArray _src,
1879    jlongArray _dstk, jlongArray _dstf, jlongArray _types)
1880{
1881    LOG_API("nScriptGroupCreate, con(%p)", (RsContext)con);
1882
1883    jint kernelsLen = _env->GetArrayLength(_kernels);
1884    jlong *jKernelsPtr = _env->GetLongArrayElements(_kernels, nullptr);
1885    RsScriptKernelID* kernelsPtr = (RsScriptKernelID*) malloc(sizeof(RsScriptKernelID) * kernelsLen);
1886    for(int i = 0; i < kernelsLen; ++i) {
1887        kernelsPtr[i] = (RsScriptKernelID)jKernelsPtr[i];
1888    }
1889
1890    jint srcLen = _env->GetArrayLength(_src);
1891    jlong *jSrcPtr = _env->GetLongArrayElements(_src, nullptr);
1892    RsScriptKernelID* srcPtr = (RsScriptKernelID*) malloc(sizeof(RsScriptKernelID) * srcLen);
1893    for(int i = 0; i < srcLen; ++i) {
1894        srcPtr[i] = (RsScriptKernelID)jSrcPtr[i];
1895    }
1896
1897    jint dstkLen = _env->GetArrayLength(_dstk);
1898    jlong *jDstkPtr = _env->GetLongArrayElements(_dstk, nullptr);
1899    RsScriptKernelID* dstkPtr = (RsScriptKernelID*) malloc(sizeof(RsScriptKernelID) * dstkLen);
1900    for(int i = 0; i < dstkLen; ++i) {
1901        dstkPtr[i] = (RsScriptKernelID)jDstkPtr[i];
1902    }
1903
1904    jint dstfLen = _env->GetArrayLength(_dstf);
1905    jlong *jDstfPtr = _env->GetLongArrayElements(_dstf, nullptr);
1906    RsScriptKernelID* dstfPtr = (RsScriptKernelID*) malloc(sizeof(RsScriptKernelID) * dstfLen);
1907    for(int i = 0; i < dstfLen; ++i) {
1908        dstfPtr[i] = (RsScriptKernelID)jDstfPtr[i];
1909    }
1910
1911    jint typesLen = _env->GetArrayLength(_types);
1912    jlong *jTypesPtr = _env->GetLongArrayElements(_types, nullptr);
1913    RsType* typesPtr = (RsType*) malloc(sizeof(RsType) * typesLen);
1914    for(int i = 0; i < typesLen; ++i) {
1915        typesPtr[i] = (RsType)jTypesPtr[i];
1916    }
1917
1918    jlong id = (jlong)(uintptr_t) dispatchTab.ScriptGroupCreate((RsContext)con,
1919                               (RsScriptKernelID *)kernelsPtr, kernelsLen * sizeof(RsScriptKernelID),
1920                               (RsScriptKernelID *)srcPtr, srcLen * sizeof(RsScriptKernelID),
1921                               (RsScriptKernelID *)dstkPtr, dstkLen * sizeof(RsScriptKernelID),
1922                               (RsScriptFieldID *)dstfPtr, dstfLen * sizeof(RsScriptKernelID),
1923                               (RsType *)typesPtr, typesLen * sizeof(RsType));
1924
1925    free(kernelsPtr);
1926    free(srcPtr);
1927    free(dstkPtr);
1928    free(dstfPtr);
1929    free(typesPtr);
1930    _env->ReleaseLongArrayElements(_kernels, jKernelsPtr, 0);
1931    _env->ReleaseLongArrayElements(_src, jSrcPtr, 0);
1932    _env->ReleaseLongArrayElements(_dstk, jDstkPtr, 0);
1933    _env->ReleaseLongArrayElements(_dstf, jDstfPtr, 0);
1934    _env->ReleaseLongArrayElements(_types, jTypesPtr, 0);
1935    return id;
1936}
1937
1938static void
1939nScriptGroupSetInput(JNIEnv *_env, jobject _this, jlong con, jlong gid, jlong kid, jlong alloc)
1940{
1941    LOG_API("nScriptGroupSetInput, con(%p) group(%p), kernelId(%p), alloc(%p)", (RsContext)con,
1942            (void *)gid, (void *)kid, (void *)alloc);
1943    dispatchTab.ScriptGroupSetInput((RsContext)con, (RsScriptGroup)gid, (RsScriptKernelID)kid,
1944                                    (RsAllocation)alloc);
1945}
1946
1947static void
1948nScriptGroupSetOutput(JNIEnv *_env, jobject _this, jlong con, jlong gid, jlong kid, jlong alloc)
1949{
1950    LOG_API("nScriptGroupSetOutput, con(%p) group(%p), kernelId(%p), alloc(%p)", (RsContext)con,
1951            (void *)gid, (void *)kid, (void *)alloc);
1952    dispatchTab.ScriptGroupSetOutput((RsContext)con, (RsScriptGroup)gid, (RsScriptKernelID)kid,
1953                                     (RsAllocation)alloc);
1954}
1955
1956static void
1957nScriptGroupExecute(JNIEnv *_env, jobject _this, jlong con, jlong gid)
1958{
1959    LOG_API("nScriptGroupSetOutput, con(%p) group(%p)", (RsContext)con, (void *)gid);
1960    dispatchTab.ScriptGroupExecute((RsContext)con, (RsScriptGroup)gid);
1961}
1962
1963// ---------------------------------------------------------------------------
1964
1965static jlong
1966nSamplerCreate(JNIEnv *_env, jobject _this, jlong con, jint magFilter, jint minFilter,
1967               jint wrapS, jint wrapT, jint wrapR, jfloat aniso)
1968{
1969    LOG_API("nSamplerCreate, con(%p)", (RsContext)con);
1970    return (jlong)(uintptr_t)dispatchTab.SamplerCreate((RsContext)con,
1971                                                       (RsSamplerValue)magFilter,
1972                                                       (RsSamplerValue)minFilter,
1973                                                       (RsSamplerValue)wrapS,
1974                                                       (RsSamplerValue)wrapT,
1975                                                       (RsSamplerValue)wrapR,
1976                                                       aniso);
1977}
1978
1979static jint
1980nSystemGetPointerSize(JNIEnv *_env, jobject _this) {
1981    return (jint)sizeof(void*);
1982}
1983
1984// ---------------------------------------------------------------------------
1985// For Incremental Intrinsic Support
1986static jboolean nIncLoadSO(JNIEnv *_env, jobject _this, jint deviceApi, jstring libPath) {
1987    void* handle = NULL;
1988    // For API 9+, dlopen the full path of libRSSupport.
1989    if (libPath != NULL) {
1990        const char * libPathJni = _env->GetStringUTFChars(libPath, JNI_FALSE);
1991        handle = dlopen(libPathJni, RTLD_LAZY | RTLD_LOCAL);
1992        _env->ReleaseStringUTFChars(libPath, libPathJni);
1993    } else {
1994        handle = dlopen("libRSSupport.so", RTLD_LAZY | RTLD_LOCAL);
1995    }
1996
1997    if (handle == NULL) {
1998        LOG_ERR("couldn't dlopen %s;  librsjni version: %d", dlerror(), RS_JNI_VERSION);
1999        return false;
2000    }
2001
2002    if (loadSymbols(handle, dispatchTabInc, deviceApi) == false) {
2003        LOG_ERR("Dispatch Table init failed! librsjni version: %d", RS_JNI_VERSION);
2004        dlclose(handle);
2005        return false;
2006    }
2007    dispatchTabInc.AllocationCreateStrided = (AllocationCreateStridedFnPtr)dlsym(handle, "rsAllocationCreateStrided");
2008    if (dispatchTabInc.AllocationCreateStrided == NULL) {
2009        LOG_ERR("Couldn't initialize dispatchTabInc.AllocationCreateStrided");
2010        dlclose(handle);
2011        return false;
2012    }
2013    LOG_API("Successfully loaded compat runtime");
2014    return true;
2015}
2016
2017// -----------------------------------
2018// To create/destroy a dummy context
2019static void
2020nIncObjDestroy(JNIEnv *_env, jobject _this, jlong con, jlong obj)
2021{
2022    LOG_API("nObjDestroy, con(%p) obj(%p)", (RsContext)con, (void *)obj);
2023    dispatchTabInc.ObjDestroy((RsContext)con, (void *)obj);
2024}
2025
2026
2027static jlong
2028nIncDeviceCreate(JNIEnv *_env, jobject _this)
2029{
2030    LOG_API("nDeviceCreate");
2031    return (jlong)(uintptr_t)dispatchTabInc.DeviceCreate();
2032}
2033
2034static void
2035nIncDeviceDestroy(JNIEnv *_env, jobject _this, jlong dev)
2036{
2037    LOG_API("nDeviceDestroy");
2038    return dispatchTabInc.DeviceDestroy((RsDevice)dev);
2039}
2040
2041static jlong
2042nIncContextCreate(JNIEnv *_env, jobject _this, jlong dev, jint ver, jint sdkVer, jint ct)
2043{
2044    LOG_API("nContextCreate");
2045    //The compat context for incremental support will be synchronous.
2046    return (jlong)(uintptr_t)dispatchTabInc.ContextCreate((RsDevice)dev, ver, sdkVer,
2047                                                          (RsContextType)ct,
2048                                                          RS_CONTEXT_SYNCHRONOUS);
2049}
2050
2051static void
2052nIncContextFinish(JNIEnv *_env, jobject _this, jlong con)
2053{
2054    LOG_API("nContextFinish, con(%p)", (RsContext)con);
2055    dispatchTabInc.ContextFinish((RsContext)con);
2056}
2057
2058static void
2059nIncContextDestroy(JNIEnv *_env, jobject _this, jlong con)
2060{
2061    LOG_API("nContextDestroy, con(%p)", (RsContext)con);
2062    dispatchTabInc.ContextDestroy((RsContext)con);
2063}
2064
2065// -----------------------------------
2066// Create dummy Element
2067static jlong
2068nIncElementCreate(JNIEnv *_env, jobject _this, jlong con, jlong type, jint kind, jboolean norm, jint size)
2069{
2070    LOG_API("nElementCreate, con(%p), type(%i), kind(%i), norm(%i), size(%i)", (RsContext)con,
2071            type, kind, norm, size);
2072    return (jlong)(uintptr_t)dispatchTabInc.ElementCreate((RsContext)con, (RsDataType)type,
2073                                                          (RsDataKind)kind, norm, size);
2074}
2075// -----------------------------------
2076// Create dummy Type
2077static jlong
2078nIncTypeCreate(JNIEnv *_env, jobject _this, jlong con, jlong eid,
2079            jint dimx, jint dimy, jint dimz, jboolean mips, jboolean faces, jint yuv)
2080{
2081    LOG_API("nTypeCreate, con(%p) eid(%p), x(%i), y(%i), z(%i), mips(%i), faces(%i), yuv(%i)",
2082            incCon, eid, dimx, dimy, dimz, mips, faces, yuv);
2083
2084    return (jlong)(uintptr_t)dispatchTabInc.TypeCreate((RsContext)con, (RsElement)eid, dimx, dimy,
2085                                                       dimz, mips, faces, yuv);
2086}
2087
2088// -----------------------------------
2089// Create Allocation from pointer
2090static jlong
2091nIncAllocationCreateTyped(JNIEnv *_env, jobject _this, jlong con, jlong incCon, jlong alloc, jlong type, jint xBytesSize)
2092{
2093    LOG_API("nAllocationCreateTyped, con(%p), type(%p), mip(%i), usage(%i), ptr(%p)",
2094            incCon, (RsElement)type, mips, usage, (void *)pointer);
2095    size_t strideIn;
2096    void* pIn = NULL;
2097    RsAllocation ainI = NULL;
2098    if (alloc != 0) {
2099        pIn = dispatchTab.AllocationGetPointer((RsContext)con, (RsAllocation)alloc, 0,
2100                                               RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X, 0, 0,
2101                                               &strideIn, sizeof(size_t));
2102        /*
2103         * By definition stride is a roundup of xBytesSize with requiredAlignment, so requiredAlignment must
2104         * be strictly larger than the difference of (stride - xBytesSize).
2105         *
2106         * We can prove that as long as requiredAlignment satisfies the following two conditions, the
2107         * memory layout will be identical :
2108         * 1. Smaller or equal than stride;
2109         * 2. Larger than minRequiredAlignment.
2110         *
2111         * In this case we can simply choose the first power of 2 that satisfies both conditions.
2112         */
2113        size_t requiredAlignment = 16;
2114        size_t minRequiredAlignment = strideIn - xBytesSize;
2115        while (requiredAlignment <= minRequiredAlignment) {
2116            requiredAlignment <<= 1;
2117        }
2118        ainI = dispatchTabInc.AllocationCreateStrided((RsContext)incCon, (RsType)type,
2119                                                      RS_ALLOCATION_MIPMAP_NONE,
2120                                                      RS_ALLOCATION_USAGE_INCREMENTAL_SUPPORT | RS_ALLOCATION_USAGE_SHARED,
2121                                                      (uintptr_t)pIn, requiredAlignment);
2122    }
2123    return (jlong)(uintptr_t) ainI;
2124}
2125
2126// ---------------------------------------------------------------------------
2127
2128
2129static const char *classPathName = "android/support/v8/renderscript/RenderScript";
2130
2131static JNINativeMethod methods[] = {
2132{"nLoadSO",                        "(ZILjava/lang/String;)Z",                 (bool*)nLoadSO },
2133{"nLoadIOSO",                      "()Z",                                     (bool*)nLoadIOSO },
2134{"nDeviceCreate",                  "()J",                                     (void*)nDeviceCreate },
2135{"nDeviceDestroy",                 "(J)V",                                    (void*)nDeviceDestroy },
2136{"nDeviceSetConfig",               "(JII)V",                                  (void*)nDeviceSetConfig },
2137{"nContextGetUserMessage",         "(J[I)I",                                  (void*)nContextGetUserMessage },
2138{"nContextGetErrorMessage",        "(J)Ljava/lang/String;",                   (void*)nContextGetErrorMessage },
2139{"nContextPeekMessage",            "(J[I)I",                                  (void*)nContextPeekMessage },
2140{"nContextInitToClient",           "(J)V",                                    (void*)nContextInitToClient },
2141{"nContextDeinitToClient",         "(J)V",                                    (void*)nContextDeinitToClient },
2142
2143
2144// All methods below are thread protected in java.
2145{"rsnContextCreate",                 "(JIIILjava/lang/String;)J",             (void*)nContextCreate },
2146{"rsnContextFinish",                 "(J)V",                                  (void*)nContextFinish },
2147{"rsnContextSetPriority",            "(JI)V",                                 (void*)nContextSetPriority },
2148{"rsnContextDestroy",                "(J)V",                                  (void*)nContextDestroy },
2149{"rsnContextDump",                   "(JI)V",                                 (void*)nContextDump },
2150{"rsnContextSendMessage",            "(JI[I)V",                               (void*)nContextSendMessage },
2151{"rsnClosureCreate",                 "(JJJ[J[J[I[J[J)J",                      (void*)nClosureCreate },
2152{"rsnInvokeClosureCreate",           "(JJ[B[J[J[I)J",                         (void*)nInvokeClosureCreate },
2153{"rsnClosureSetArg",                 "(JJIJI)V",                              (void*)nClosureSetArg },
2154{"rsnClosureSetGlobal",              "(JJJJI)V",                              (void*)nClosureSetGlobal },
2155{"rsnObjDestroy",                    "(JJ)V",                                 (void*)nObjDestroy },
2156
2157{"rsnElementCreate",                 "(JJIZI)J",                              (void*)nElementCreate },
2158{"rsnElementCreate2",                "(J[J[Ljava/lang/String;[I)J",           (void*)nElementCreate2 },
2159{"rsnElementGetSubElements",         "(JJ[J[Ljava/lang/String;[I)V",          (void*)nElementGetSubElements },
2160
2161{"rsnTypeCreate",                    "(JJIIIZZI)J",                           (void*)nTypeCreate },
2162
2163{"rsnAllocationCreateTyped",         "(JJIIJ)J",                              (void*)nAllocationCreateTyped },
2164{"rsnAllocationCreateFromBitmap",    "(JJILandroid/graphics/Bitmap;I)J",      (void*)nAllocationCreateFromBitmap },
2165{"rsnAllocationCreateBitmapBackedAllocation",    "(JJILandroid/graphics/Bitmap;I)J",      (void*)nAllocationCreateBitmapBackedAllocation },
2166{"rsnAllocationCubeCreateFromBitmap","(JJILandroid/graphics/Bitmap;I)J",      (void*)nAllocationCubeCreateFromBitmap },
2167
2168{"rsnAllocationCopyFromBitmap",      "(JJLandroid/graphics/Bitmap;)V",        (void*)nAllocationCopyFromBitmap },
2169{"rsnAllocationCopyToBitmap",        "(JJLandroid/graphics/Bitmap;)V",        (void*)nAllocationCopyToBitmap },
2170
2171{"rsnAllocationSyncAll",             "(JJI)V",                                (void*)nAllocationSyncAll },
2172{"rsnAllocationSetSurface",          "(JJLandroid/view/Surface;)V",           (void*)nAllocationSetSurface },
2173{"rsnAllocationIoSend",              "(JJ)V",                                 (void*)nAllocationIoSend },
2174{"rsnAllocationData1D",              "(JJIIILjava/lang/Object;IIIZ)V",        (void*)nAllocationData1D },
2175{"rsnAllocationElementData1D",       "(JJIII[BI)V",                           (void*)nAllocationElementData1D },
2176//{"rsnAllocationElementData",         "(JJIIIII[BI)V",                         (void*)nAllocationElementData },
2177{"rsnAllocationData2D",              "(JJIIIIIILjava/lang/Object;IIIZ)V",     (void*)nAllocationData2D },
2178{"rsnAllocationData2D",              "(JJIIIIIIJIIII)V",                      (void*)nAllocationData2D_alloc },
2179{"rsnAllocationData3D",              "(JJIIIIIIILjava/lang/Object;IIIZ)V",    (void*)nAllocationData3D },
2180{"rsnAllocationData3D",              "(JJIIIIIIIJIIII)V",                     (void*)nAllocationData3D_alloc },
2181{"rsnAllocationRead",                "(JJLjava/lang/Object;IIZ)V",            (void*)nAllocationRead },
2182{"rsnAllocationRead1D",              "(JJIIILjava/lang/Object;IIIZ)V",        (void*)nAllocationRead1D },
2183//{"rsnAllocationElementRead",         "(JJIIIII[BI)V",                         (void*)nAllocationElementRead },
2184{"rsnAllocationRead2D",              "(JJIIIIIILjava/lang/Object;IIIZ)V",     (void*)nAllocationRead2D },
2185//{"rsnAllocationRead3D",              "(JJIIIIIIILjava/lang/Object;IIIZ)V",  (void*)nAllocationRead3D },
2186{"rsnAllocationGetType",             "(JJ)J",                                 (void*)nAllocationGetType},
2187{"rsnAllocationResize1D",            "(JJI)V",                                (void*)nAllocationResize1D },
2188{"rsnAllocationGenerateMipmaps",     "(JJ)V",                                 (void*)nAllocationGenerateMipmaps },
2189
2190{"rsnScriptBindAllocation",          "(JJJIZ)V",                              (void*)nScriptBindAllocation },
2191{"rsnScriptSetTimeZone",             "(JJ[BZ)V",                              (void*)nScriptSetTimeZone },
2192{"rsnScriptInvoke",                  "(JJIZ)V",                               (void*)nScriptInvoke },
2193{"rsnScriptInvokeV",                 "(JJI[BZ)V",                             (void*)nScriptInvokeV },
2194{"rsnScriptForEach",                 "(JJJIJJZ)V",                            (void*)nScriptForEach },
2195{"rsnScriptForEach",                 "(JJJIJJ[BZ)V",                          (void*)nScriptForEachV },
2196{"rsnScriptForEach",                 "(JJI[JJ[B[I)V",                         (void*)nScriptForEachMulti },
2197{"rsnScriptForEachClipped",          "(JJJIJJIIIIIIZ)V",                      (void*)nScriptForEachClipped },
2198{"rsnScriptForEachClipped",          "(JJJIJJ[BIIIIIIZ)V",                    (void*)nScriptForEachClippedV },
2199{"rsnScriptReduce",                  "(JJIJJ[I)V",                            (void*)nScriptReduce },
2200{"rsnScriptSetVarI",                 "(JJIIZ)V",                              (void*)nScriptSetVarI },
2201{"rsnScriptSetVarJ",                 "(JJIJZ)V",                              (void*)nScriptSetVarJ },
2202{"rsnScriptSetVarF",                 "(JJIFZ)V",                              (void*)nScriptSetVarF },
2203{"rsnScriptSetVarD",                 "(JJIDZ)V",                              (void*)nScriptSetVarD },
2204{"rsnScriptSetVarV",                 "(JJI[BZ)V",                             (void*)nScriptSetVarV },
2205{"rsnScriptSetVarVE",                "(JJI[BJ[IZ)V",                          (void*)nScriptSetVarVE },
2206{"rsnScriptSetVarObj",               "(JJIJZ)V",                              (void*)nScriptSetVarObj },
2207
2208{"rsnScriptCCreate",                 "(JLjava/lang/String;Ljava/lang/String;[BI)J",  (void*)nScriptCCreate },
2209{"rsnScriptIntrinsicCreate",         "(JIJZ)J",                               (void*)nScriptIntrinsicCreate },
2210{"rsnScriptKernelIDCreate",          "(JJIIZ)J",                              (void*)nScriptKernelIDCreate },
2211{"rsnScriptInvokeIDCreate",          "(JJI)J",                                (void*)nScriptInvokeIDCreate },
2212{"rsnScriptFieldIDCreate",           "(JJIZ)J",                               (void*)nScriptFieldIDCreate },
2213{"rsnScriptGroupCreate",             "(J[J[J[J[J[J)J",                        (void*)nScriptGroupCreate },
2214{"rsnScriptGroup2Create",            "(JLjava/lang/String;Ljava/lang/String;[J)J", (void*)nScriptGroup2Create },
2215{"rsnScriptGroupSetInput",           "(JJJJ)V",                               (void*)nScriptGroupSetInput },
2216{"rsnScriptGroupSetOutput",          "(JJJJ)V",                               (void*)nScriptGroupSetOutput },
2217{"rsnScriptGroupExecute",            "(JJ)V",                                 (void*)nScriptGroupExecute },
2218{"rsnScriptGroup2Execute",           "(JJ)V",                                 (void*)nScriptGroup2Execute },
2219
2220{"rsnScriptIntrinsicBLAS_Single",    "(JJJIIIIIIIIIFJJFJIIIIZ)V",             (void*)nScriptIntrinsicBLAS_Single },
2221{"rsnScriptIntrinsicBLAS_Double",    "(JJJIIIIIIIIIDJJDJIIIIZ)V",             (void*)nScriptIntrinsicBLAS_Double },
2222{"rsnScriptIntrinsicBLAS_Complex",   "(JJJIIIIIIIIIFFJJFFJIIIIZ)V",           (void*)nScriptIntrinsicBLAS_Complex },
2223{"rsnScriptIntrinsicBLAS_Z",         "(JJJIIIIIIIIIDDJJDDJIIIIZ)V",           (void*)nScriptIntrinsicBLAS_Z },
2224
2225{"rsnScriptIntrinsicBLAS_BNNM",      "(JJJIIIJIJIJIIZ)V",                     (void*)nScriptIntrinsicBLAS_BNNM },
2226
2227{"rsnSamplerCreate",                 "(JIIIIIF)J",                            (void*)nSamplerCreate },
2228
2229{"rsnSystemGetPointerSize",          "()I",                                   (void*)nSystemGetPointerSize },
2230
2231// Entry points for Inc libRSSupport
2232{"nIncLoadSO",                       "(ILjava/lang/String;)Z",                (bool*)nIncLoadSO },
2233{"nIncDeviceCreate",                 "()J",                                   (void*)nIncDeviceCreate },
2234{"nIncDeviceDestroy",                "(J)V",                                  (void*)nIncDeviceDestroy },
2235{"rsnIncContextCreate",              "(JIII)J",                               (void*)nIncContextCreate },
2236{"rsnIncContextFinish",              "(J)V",                                  (void*)nIncContextFinish },
2237{"rsnIncContextDestroy",             "(J)V",                                  (void*)nIncContextDestroy },
2238{"rsnIncObjDestroy",                 "(JJ)V",                                 (void*)nIncObjDestroy },
2239{"rsnIncElementCreate",              "(JJIZI)J",                              (void*)nIncElementCreate },
2240{"rsnIncTypeCreate",                 "(JJIIIZZI)J",                           (void*)nIncTypeCreate },
2241{"rsnIncAllocationCreateTyped",      "(JJJJI)J",                              (void*)nIncAllocationCreateTyped },
2242};
2243
2244// ---------------------------------------------------------------------------
2245
2246jint JNI_OnLoad(JavaVM* vm, void* reserved)
2247{
2248    JNIEnv* env = NULL;
2249    jclass clazz = NULL;
2250    jint result = -1;
2251
2252    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
2253        //        __android_log_print(ANDROID_LOG_ERROR, LOG_TAG,
2254        //            "ERROR: GetEnv failed\n");
2255        goto bail;
2256    }
2257    if (env == NULL) {
2258        //        __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "ERROR: env == NULL");
2259        goto bail;
2260    }
2261
2262    clazz = env->FindClass(classPathName);
2263    if (clazz == NULL) {
2264        goto bail;
2265    }
2266
2267    if (env->RegisterNatives(clazz, methods, NELEM(methods)) < 0) {
2268        //        __android_log_print(ANDROID_LOG_ERROR, LOG_TAG,
2269        //            "ERROR: MediaPlayer native registration failed\n");
2270        goto bail;
2271    }
2272
2273    /* success -- return valid version number */
2274    result = JNI_VERSION_1_4;
2275
2276bail:
2277    return result;
2278}
2279