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