android_renderscript_RenderScript.cpp revision 768bc02d815a94ad29146f1ed60c847d1af118cc
1/*
2 * Copyright (C) 2006 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 <utils/misc.h>
25
26#include <ui/Surface.h>
27
28#include <core/SkBitmap.h>
29#include <core/SkPixelRef.h>
30#include <core/SkStream.h>
31#include <core/SkTemplates.h>
32#include <images/SkImageDecoder.h>
33
34#include <utils/Asset.h>
35#include <utils/ResourceTypes.h>
36
37#include "jni.h"
38#include "JNIHelp.h"
39#include "android_runtime/AndroidRuntime.h"
40
41#include <RenderScript.h>
42#include <RenderScriptEnv.h>
43
44//#define LOG_API LOGE
45#define LOG_API(...)
46
47using namespace android;
48
49// ---------------------------------------------------------------------------
50
51static void doThrow(JNIEnv* env, const char* exc, const char* msg = NULL)
52{
53    jclass npeClazz = env->FindClass(exc);
54    env->ThrowNew(npeClazz, msg);
55}
56
57static jfieldID gContextId = 0;
58static jfieldID gNativeBitmapID = 0;
59static jfieldID gTypeNativeCache = 0;
60
61static RsElement g_A_8 = NULL;
62static RsElement g_RGBA_4444 = NULL;
63static RsElement g_RGBA_8888 = NULL;
64static RsElement g_RGB_565 = NULL;
65
66static void _nInit(JNIEnv *_env, jclass _this)
67{
68    gContextId             = _env->GetFieldID(_this, "mContext", "I");
69
70    jclass bitmapClass = _env->FindClass("android/graphics/Bitmap");
71    gNativeBitmapID = _env->GetFieldID(bitmapClass, "mNativeBitmap", "I");
72
73    jclass typeClass = _env->FindClass("android/renderscript/Type");
74    gTypeNativeCache = _env->GetFieldID(typeClass, "mNativeCache", "I");
75}
76
77static void nInitElements(JNIEnv *_env, jobject _this, jint a8, jint rgba4444, jint rgba8888, jint rgb565)
78{
79    g_A_8 = reinterpret_cast<RsElement>(a8);
80    g_RGBA_4444 = reinterpret_cast<RsElement>(rgba4444);
81    g_RGBA_8888 = reinterpret_cast<RsElement>(rgba8888);
82    g_RGB_565 = reinterpret_cast<RsElement>(rgb565);
83}
84
85// ---------------------------------------------------------------------------
86
87static void
88nAssignName(JNIEnv *_env, jobject _this, jint obj, jbyteArray str)
89{
90    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
91    LOG_API("nAssignName, con(%p), obj(%p)", con, (void *)obj);
92
93    jint len = _env->GetArrayLength(str);
94    jbyte * cptr = (jbyte *) _env->GetPrimitiveArrayCritical(str, 0);
95    rsAssignName(con, (void *)obj, (const char *)cptr, len);
96    _env->ReleasePrimitiveArrayCritical(str, cptr, JNI_ABORT);
97}
98
99static void
100nObjDestroy(JNIEnv *_env, jobject _this, jint obj)
101{
102    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
103    LOG_API("nObjDestroy, con(%p) obj(%p)", con, (void *)obj);
104    rsObjDestroy(con, (void *)obj);
105}
106
107static void
108nObjDestroyOOB(JNIEnv *_env, jobject _this, jint obj)
109{
110    // This function only differs from nObjDestroy in that it calls the
111    // special Out Of Band version of ObjDestroy which is thread safe.
112    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
113    LOG_API("nObjDestroyOOB, con(%p) obj(%p)", con, (void *)obj);
114    rsObjDestroyOOB(con, (void *)obj);
115}
116
117static jint
118nFileOpen(JNIEnv *_env, jobject _this, jbyteArray str)
119{
120    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
121    LOG_API("nFileOpen, con(%p)", con);
122
123    jint len = _env->GetArrayLength(str);
124    jbyte * cptr = (jbyte *) _env->GetPrimitiveArrayCritical(str, 0);
125    jint ret = (jint)rsFileOpen(con, (const char *)cptr, len);
126    _env->ReleasePrimitiveArrayCritical(str, cptr, JNI_ABORT);
127    return ret;
128}
129
130// ---------------------------------------------------------------------------
131
132static jint
133nDeviceCreate(JNIEnv *_env, jobject _this)
134{
135    LOG_API("nDeviceCreate");
136    return (jint)rsDeviceCreate();
137}
138
139static void
140nDeviceDestroy(JNIEnv *_env, jobject _this, jint dev)
141{
142    LOG_API("nDeviceDestroy");
143    return rsDeviceDestroy((RsDevice)dev);
144}
145
146static jint
147nContextCreate(JNIEnv *_env, jobject _this, jint dev, jobject wnd, jint ver, jboolean useDepth)
148{
149    LOG_API("nContextCreate");
150
151    if (wnd == NULL) {
152        not_valid_surface:
153        doThrow(_env, "java/lang/IllegalArgumentException",
154                "Make sure the SurfaceView or associated SurfaceHolder has a valid Surface");
155        return 0;
156    }
157    jclass surface_class = _env->FindClass("android/view/Surface");
158    jfieldID surfaceFieldID = _env->GetFieldID(surface_class, "mSurface", "I");
159    Surface * window = (Surface*)_env->GetIntField(wnd, surfaceFieldID);
160    if (window == NULL)
161        goto not_valid_surface;
162
163    return (jint)rsContextCreate((RsDevice)dev, window, ver, useDepth);
164}
165
166static void
167nContextDestroy(JNIEnv *_env, jobject _this, jint con)
168{
169    LOG_API("nContextDestroy, con(%p)", (RsContext)con);
170    return rsContextDestroy((RsContext)con);
171}
172
173
174static void
175nElementBegin(JNIEnv *_env, jobject _this)
176{
177    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
178    LOG_API("nElementBegin, con(%p)", con);
179    rsElementBegin(con);
180}
181
182
183static void
184nElementAdd(JNIEnv *_env, jobject _this, jint kind, jint type, jboolean norm, jint bits, jstring name)
185{
186    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
187    const char* n = NULL;
188    if (name) {
189        n = _env->GetStringUTFChars(name, NULL);
190    }
191    LOG_API("nElementAdd, con(%p), kind(%i), type(%i), norm(%i), bits(%i)", con, kind, type, norm, bits);
192    rsElementAdd(con, (RsDataKind)kind, (RsDataType)type, norm != 0, (size_t)bits, n);
193    if (n) {
194        _env->ReleaseStringUTFChars(name, n);
195    }
196}
197
198static jint
199nElementCreate(JNIEnv *_env, jobject _this)
200{
201    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
202    LOG_API("nElementCreate, con(%p)", con);
203    return (jint)rsElementCreate(con);
204}
205
206// -----------------------------------
207
208static void
209nTypeBegin(JNIEnv *_env, jobject _this, jint eID)
210{
211    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
212    LOG_API("nTypeBegin, con(%p) e(%p)", con, (RsElement)eID);
213    rsTypeBegin(con, (RsElement)eID);
214}
215
216static void
217nTypeAdd(JNIEnv *_env, jobject _this, jint dim, jint val)
218{
219    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
220    LOG_API("nTypeAdd, con(%p) dim(%i), val(%i)", con, dim, val);
221    rsTypeAdd(con, (RsDimension)dim, val);
222}
223
224static jint
225nTypeCreate(JNIEnv *_env, jobject _this)
226{
227    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
228    LOG_API("nTypeCreate, con(%p)", con);
229    return (jint)rsTypeCreate(con);
230}
231
232static void * SF_LoadInt(JNIEnv *_env, jobject _obj, jfieldID _field, void *buffer)
233{
234    ((int32_t *)buffer)[0] = _env->GetIntField(_obj, _field);
235    return ((uint8_t *)buffer) + 4;
236}
237
238static void * SF_LoadShort(JNIEnv *_env, jobject _obj, jfieldID _field, void *buffer)
239{
240    ((int16_t *)buffer)[0] = _env->GetShortField(_obj, _field);
241    return ((uint8_t *)buffer) + 2;
242}
243
244static void * SF_LoadByte(JNIEnv *_env, jobject _obj, jfieldID _field, void *buffer)
245{
246    ((int8_t *)buffer)[0] = _env->GetByteField(_obj, _field);
247    return ((uint8_t *)buffer) + 1;
248}
249
250static void * SF_LoadFloat(JNIEnv *_env, jobject _obj, jfieldID _field, void *buffer)
251{
252    ((float *)buffer)[0] = _env->GetFloatField(_obj, _field);
253    return ((uint8_t *)buffer) + 4;
254}
255
256static void * SF_SaveInt(JNIEnv *_env, jobject _obj, jfieldID _field, void *buffer)
257{
258    _env->SetIntField(_obj, _field, ((int32_t *)buffer)[0]);
259    return ((uint8_t *)buffer) + 4;
260}
261
262static void * SF_SaveShort(JNIEnv *_env, jobject _obj, jfieldID _field, void *buffer)
263{
264    _env->SetShortField(_obj, _field, ((int16_t *)buffer)[0]);
265    return ((uint8_t *)buffer) + 2;
266}
267
268static void * SF_SaveByte(JNIEnv *_env, jobject _obj, jfieldID _field, void *buffer)
269{
270    _env->SetByteField(_obj, _field, ((int8_t *)buffer)[0]);
271    return ((uint8_t *)buffer) + 1;
272}
273
274static void * SF_SaveFloat(JNIEnv *_env, jobject _obj, jfieldID _field, void *buffer)
275{
276    _env->SetFloatField(_obj, _field, ((float *)buffer)[0]);
277    return ((uint8_t *)buffer) + 4;
278}
279
280struct TypeFieldCache {
281    jfieldID field;
282    int bits;
283    void * (*ptr)(JNIEnv *, jobject, jfieldID, void *buffer);
284    void * (*readPtr)(JNIEnv *, jobject, jfieldID, void *buffer);
285};
286
287struct TypeCache {
288    int fieldCount;
289    int size;
290    TypeFieldCache fields[1];
291};
292
293//{"nTypeFinalDestroy",              "(Landroid/renderscript/Type;)V",       (void*)nTypeFinalDestroy },
294static void
295nTypeFinalDestroy(JNIEnv *_env, jobject _this, jobject _type)
296{
297    TypeCache *tc = (TypeCache *)_env->GetIntField(_type, gTypeNativeCache);
298    free(tc);
299}
300
301// native void nTypeSetupFields(Type t, int[] types, int[] bits, Field[] IDs);
302static void
303nTypeSetupFields(JNIEnv *_env, jobject _this, jobject _type, jintArray _types, jintArray _bits, jobjectArray _IDs)
304{
305    int fieldCount = _env->GetArrayLength(_types);
306    size_t structSize = sizeof(TypeCache) + (sizeof(TypeFieldCache) * (fieldCount-1));
307    TypeCache *tc = (TypeCache *)malloc(structSize);
308    memset(tc, 0, structSize);
309
310    TypeFieldCache *tfc = &tc->fields[0];
311    tc->fieldCount = fieldCount;
312    _env->SetIntField(_type, gTypeNativeCache, (jint)tc);
313
314    jint *fType = _env->GetIntArrayElements(_types, NULL);
315    jint *fBits = _env->GetIntArrayElements(_bits, NULL);
316    for (int ct=0; ct < fieldCount; ct++) {
317        jobject field = _env->GetObjectArrayElement(_IDs, ct);
318        tfc[ct].field = _env->FromReflectedField(field);
319        tfc[ct].bits = fBits[ct];
320
321        switch(fType[ct]) {
322        case RS_TYPE_FLOAT:
323            tfc[ct].ptr = SF_LoadFloat;
324            tfc[ct].readPtr = SF_SaveFloat;
325            break;
326        case RS_TYPE_UNSIGNED:
327        case RS_TYPE_SIGNED:
328            switch(tfc[ct].bits) {
329            case 32:
330                tfc[ct].ptr = SF_LoadInt;
331                tfc[ct].readPtr = SF_SaveInt;
332                break;
333            case 16:
334                tfc[ct].ptr = SF_LoadShort;
335                tfc[ct].readPtr = SF_SaveShort;
336                break;
337            case 8:
338                tfc[ct].ptr = SF_LoadByte;
339                tfc[ct].readPtr = SF_SaveByte;
340                break;
341            }
342            break;
343        }
344        tc->size += 4;
345    }
346
347    _env->ReleaseIntArrayElements(_types, fType, JNI_ABORT);
348    _env->ReleaseIntArrayElements(_bits, fBits, JNI_ABORT);
349}
350
351
352// -----------------------------------
353
354static jint
355nAllocationCreateTyped(JNIEnv *_env, jobject _this, jint e)
356{
357    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
358    LOG_API("nAllocationCreateTyped, con(%p), e(%p)", con, (RsElement)e);
359    return (jint) rsAllocationCreateTyped(con, (RsElement)e);
360}
361
362static void
363nAllocationUploadToTexture(JNIEnv *_env, jobject _this, jint a, jint mip)
364{
365    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
366    LOG_API("nAllocationUploadToTexture, con(%p), a(%p), mip(%i)", con, (RsAllocation)a, mip);
367    rsAllocationUploadToTexture(con, (RsAllocation)a, mip);
368}
369
370static void
371nAllocationUploadToBufferObject(JNIEnv *_env, jobject _this, jint a)
372{
373    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
374    LOG_API("nAllocationUploadToBufferObject, con(%p), a(%p)", con, (RsAllocation)a);
375    rsAllocationUploadToBufferObject(con, (RsAllocation)a);
376}
377
378static RsElement SkBitmapToPredefined(SkBitmap::Config cfg)
379{
380    switch (cfg) {
381    case SkBitmap::kA8_Config:
382        return g_A_8;
383    case SkBitmap::kARGB_4444_Config:
384        return g_RGBA_4444;
385    case SkBitmap::kARGB_8888_Config:
386        return g_RGBA_8888;
387    case SkBitmap::kRGB_565_Config:
388        return g_RGB_565;
389
390    default:
391        break;
392    }
393    // If we don't have a conversion mark it as a user type.
394    LOGE("Unsupported bitmap type");
395    return NULL;
396}
397
398static int
399nAllocationCreateFromBitmap(JNIEnv *_env, jobject _this, jint dstFmt, jboolean genMips, jobject jbitmap)
400{
401    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
402    SkBitmap const * nativeBitmap =
403            (SkBitmap const *)_env->GetIntField(jbitmap, gNativeBitmapID);
404    const SkBitmap& bitmap(*nativeBitmap);
405    SkBitmap::Config config = bitmap.getConfig();
406
407    RsElement e = SkBitmapToPredefined(config);
408    if (e) {
409        bitmap.lockPixels();
410        const int w = bitmap.width();
411        const int h = bitmap.height();
412        const void* ptr = bitmap.getPixels();
413        jint id = (jint)rsAllocationCreateFromBitmap(con, w, h, (RsElement)dstFmt, e, genMips, ptr);
414        bitmap.unlockPixels();
415        return id;
416    }
417    return 0;
418}
419
420static int
421nAllocationCreateFromAssetStream(JNIEnv *_env, jobject _this, jint dstFmt, jboolean genMips, jint native_asset)
422{
423    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
424
425    Asset* asset = reinterpret_cast<Asset*>(native_asset);
426    SkBitmap bitmap;
427    SkImageDecoder::DecodeMemory(asset->getBuffer(false), asset->getLength(),
428            &bitmap, SkBitmap::kNo_Config, SkImageDecoder::kDecodePixels_Mode);
429
430    SkBitmap::Config config = bitmap.getConfig();
431
432    RsElement e = SkBitmapToPredefined(config);
433
434    if (e) {
435        bitmap.lockPixels();
436        const int w = bitmap.width();
437        const int h = bitmap.height();
438        const void* ptr = bitmap.getPixels();
439        jint id = (jint)rsAllocationCreateFromBitmap(con, w, h, (RsElement)dstFmt, e, genMips, ptr);
440        bitmap.unlockPixels();
441        return id;
442    }
443    return 0;
444}
445
446static int
447nAllocationCreateFromBitmapBoxed(JNIEnv *_env, jobject _this, jint dstFmt, jboolean genMips, jobject jbitmap)
448{
449    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
450    SkBitmap const * nativeBitmap =
451            (SkBitmap const *)_env->GetIntField(jbitmap, gNativeBitmapID);
452    const SkBitmap& bitmap(*nativeBitmap);
453    SkBitmap::Config config = bitmap.getConfig();
454
455    RsElement e = SkBitmapToPredefined(config);
456
457    if (e) {
458        bitmap.lockPixels();
459        const int w = bitmap.width();
460        const int h = bitmap.height();
461        const void* ptr = bitmap.getPixels();
462        jint id = (jint)rsAllocationCreateFromBitmapBoxed(con, w, h, (RsElement)dstFmt, e, genMips, ptr);
463        bitmap.unlockPixels();
464        return id;
465    }
466    return 0;
467}
468
469
470static void
471nAllocationSubData1D_i(JNIEnv *_env, jobject _this, jint alloc, jint offset, jint count, jintArray data, int sizeBytes)
472{
473    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
474    jint len = _env->GetArrayLength(data);
475    LOG_API("nAllocation1DSubData_i, con(%p), adapter(%p), offset(%i), count(%i), len(%i), sizeBytes(%i)", con, (RsAllocation)alloc, offset, count, len, sizeBytes);
476    jint *ptr = _env->GetIntArrayElements(data, NULL);
477    rsAllocation1DSubData(con, (RsAllocation)alloc, offset, count, ptr, sizeBytes);
478    _env->ReleaseIntArrayElements(data, ptr, JNI_ABORT);
479}
480
481static void
482nAllocationSubData1D_s(JNIEnv *_env, jobject _this, jint alloc, jint offset, jint count, jshortArray data, int sizeBytes)
483{
484    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
485    jint len = _env->GetArrayLength(data);
486    LOG_API("nAllocation1DSubData_s, con(%p), adapter(%p), offset(%i), count(%i), len(%i), sizeBytes(%i)", con, (RsAllocation)alloc, offset, count, len, sizeBytes);
487    jshort *ptr = _env->GetShortArrayElements(data, NULL);
488    rsAllocation1DSubData(con, (RsAllocation)alloc, offset, count, ptr, sizeBytes);
489    _env->ReleaseShortArrayElements(data, ptr, JNI_ABORT);
490}
491
492static void
493nAllocationSubData1D_b(JNIEnv *_env, jobject _this, jint alloc, jint offset, jint count, jbyteArray data, int sizeBytes)
494{
495    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
496    jint len = _env->GetArrayLength(data);
497    LOG_API("nAllocation1DSubData_b, con(%p), adapter(%p), offset(%i), count(%i), len(%i), sizeBytes(%i)", con, (RsAllocation)alloc, offset, count, len, sizeBytes);
498    jbyte *ptr = _env->GetByteArrayElements(data, NULL);
499    rsAllocation1DSubData(con, (RsAllocation)alloc, offset, count, ptr, sizeBytes);
500    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
501}
502
503static void
504nAllocationSubData1D_f(JNIEnv *_env, jobject _this, jint alloc, jint offset, jint count, jfloatArray data, int sizeBytes)
505{
506    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
507    jint len = _env->GetArrayLength(data);
508    LOG_API("nAllocation1DSubData_f, con(%p), adapter(%p), offset(%i), count(%i), len(%i), sizeBytes(%i)", con, (RsAllocation)alloc, offset, count, len, sizeBytes);
509    jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
510    rsAllocation1DSubData(con, (RsAllocation)alloc, offset, count, ptr, sizeBytes);
511    _env->ReleaseFloatArrayElements(data, ptr, JNI_ABORT);
512}
513
514static void
515nAllocationSubData2D_i(JNIEnv *_env, jobject _this, jint alloc, jint xoff, jint yoff, jint w, jint h, jintArray data, int sizeBytes)
516{
517    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
518    jint len = _env->GetArrayLength(data);
519    LOG_API("nAllocation2DSubData_i, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i)", con, (RsAllocation)alloc, xoff, yoff, w, h, len);
520    jint *ptr = _env->GetIntArrayElements(data, NULL);
521    rsAllocation2DSubData(con, (RsAllocation)alloc, xoff, yoff, w, h, ptr, sizeBytes);
522    _env->ReleaseIntArrayElements(data, ptr, JNI_ABORT);
523}
524
525static void
526nAllocationSubData2D_f(JNIEnv *_env, jobject _this, jint alloc, jint xoff, jint yoff, jint w, jint h, jfloatArray data, int sizeBytes)
527{
528    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
529    jint len = _env->GetArrayLength(data);
530    LOG_API("nAllocation2DSubData_i, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i)", con, (RsAllocation)alloc, xoff, yoff, w, h, len);
531    jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
532    rsAllocation2DSubData(con, (RsAllocation)alloc, xoff, yoff, w, h, ptr, sizeBytes);
533    _env->ReleaseFloatArrayElements(data, ptr, JNI_ABORT);
534}
535
536static void
537nAllocationRead_i(JNIEnv *_env, jobject _this, jint alloc, jintArray data)
538{
539    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
540    jint len = _env->GetArrayLength(data);
541    LOG_API("nAllocationRead_i, con(%p), alloc(%p), len(%i)", con, (RsAllocation)alloc, len);
542    jint *ptr = _env->GetIntArrayElements(data, NULL);
543    rsAllocationRead(con, (RsAllocation)alloc, ptr);
544    _env->ReleaseIntArrayElements(data, ptr, 0);
545}
546
547static void
548nAllocationRead_f(JNIEnv *_env, jobject _this, jint alloc, jfloatArray data)
549{
550    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
551    jint len = _env->GetArrayLength(data);
552    LOG_API("nAllocationRead_f, con(%p), alloc(%p), len(%i)", con, (RsAllocation)alloc, len);
553    jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
554    rsAllocationRead(con, (RsAllocation)alloc, ptr);
555    _env->ReleaseFloatArrayElements(data, ptr, 0);
556}
557
558
559//{"nAllocationDataFromObject",      "(ILandroid/renderscript/Type;Ljava/lang/Object;)V",   (void*)nAllocationDataFromObject },
560static void
561nAllocationSubDataFromObject(JNIEnv *_env, jobject _this, jint alloc, jobject _type, jint offset, jobject _o)
562{
563    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
564    LOG_API("nAllocationDataFromObject con(%p), alloc(%p)", con, (RsAllocation)alloc);
565
566    const TypeCache *tc = (TypeCache *)_env->GetIntField(_type, gTypeNativeCache);
567
568    void * bufAlloc = malloc(tc->size);
569    void * buf = bufAlloc;
570    for (int ct=0; ct < tc->fieldCount; ct++) {
571        const TypeFieldCache *tfc = &tc->fields[ct];
572        buf = tfc->ptr(_env, _o, tfc->field, buf);
573    }
574    rsAllocation1DSubData(con, (RsAllocation)alloc, offset, 1, bufAlloc, tc->size);
575    free(bufAlloc);
576}
577
578static void
579nAllocationSubReadFromObject(JNIEnv *_env, jobject _this, jint alloc, jobject _type, jint offset, jobject _o)
580{
581    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
582    LOG_API("nAllocationReadFromObject con(%p), alloc(%p)", con, (RsAllocation)alloc);
583
584    assert(offset == 0);
585
586    const TypeCache *tc = (TypeCache *)_env->GetIntField(_type, gTypeNativeCache);
587
588    void * bufAlloc = malloc(tc->size);
589    void * buf = bufAlloc;
590    rsAllocationRead(con, (RsAllocation)alloc, bufAlloc);
591
592    for (int ct=0; ct < tc->fieldCount; ct++) {
593        const TypeFieldCache *tfc = &tc->fields[ct];
594        buf = tfc->readPtr(_env, _o, tfc->field, buf);
595    }
596    free(bufAlloc);
597}
598
599// -----------------------------------
600
601static void
602nTriangleMeshBegin(JNIEnv *_env, jobject _this, jint v, jint i)
603{
604    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
605    LOG_API("nTriangleMeshBegin, con(%p), vertex(%p), index(%p)", con, (RsElement)v, (RsElement)i);
606    rsTriangleMeshBegin(con, (RsElement)v, (RsElement)i);
607}
608
609static void
610nTriangleMeshAddVertex_XY(JNIEnv *_env, jobject _this, jfloat x, jfloat y)
611{
612    float v[] = {x, y};
613    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
614    LOG_API("nTriangleMeshAddVertex_XY, con(%p), x(%f), y(%f)", con, x, y);
615    rsTriangleMeshAddVertex(con, v);
616}
617
618static void
619nTriangleMeshAddVertex_XYZ(JNIEnv *_env, jobject _this, jfloat x, jfloat y, jfloat z)
620{
621    float v[] = {x, y, z};
622    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
623    LOG_API("nTriangleMeshAddVertex_XYZ, con(%p), x(%f), y(%f), z(%f)", con, x, y, z);
624    rsTriangleMeshAddVertex(con, v);
625}
626
627static void
628nTriangleMeshAddVertex_XY_ST(JNIEnv *_env, jobject _this, jfloat x, jfloat y, jfloat s, jfloat t)
629{
630    float v[] = {s, t, x, y};
631    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
632    LOG_API("nTriangleMeshAddVertex_XY_ST, con(%p), x(%f), y(%f), s(%f), t(%f)", con, x, y, s, t);
633    rsTriangleMeshAddVertex(con, v);
634}
635
636static void
637nTriangleMeshAddVertex_XYZ_ST(JNIEnv *_env, jobject _this, jfloat x, jfloat y, jfloat z, jfloat s, jfloat t)
638{
639    float v[] = {s, t, x, y, z};
640    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
641    LOG_API("nTriangleMeshAddVertex_XYZ_ST, con(%p), x(%f), y(%f), z(%f), s(%f), t(%f)", con, x, y, z, s, t);
642    rsTriangleMeshAddVertex(con, v);
643}
644
645static void
646nTriangleMeshAddVertex_XYZ_ST_NORM(JNIEnv *_env, jobject _this, jfloat x, jfloat y, jfloat z, jfloat s, jfloat t, jfloat nx, jfloat ny, jfloat nz)
647{
648    float v[] = {nx, ny, nz, s, t, x, y, z};
649    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
650    LOG_API("nTriangleMeshAddVertex_XYZ_ST, con(%p), x(%f), y(%f), z(%f), s(%f), t(%f)", con, x, y, z, s, t);
651    rsTriangleMeshAddVertex(con, v);
652}
653
654static void
655nTriangleMeshAddTriangle(JNIEnv *_env, jobject _this, jint i1, jint i2, jint i3)
656{
657    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
658    LOG_API("nTriangleMeshAddTriangle, con(%p), i1(%i), i2(%i), i3(%i)", con, i1, i2, i3);
659    rsTriangleMeshAddTriangle(con, i1, i2, i3);
660}
661
662static jint
663nTriangleMeshCreate(JNIEnv *_env, jobject _this)
664{
665    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
666    LOG_API("nTriangleMeshCreate, con(%p)", con);
667    return (jint) rsTriangleMeshCreate(con);
668}
669
670// -----------------------------------
671
672static void
673nAdapter1DBindAllocation(JNIEnv *_env, jobject _this, jint adapter, jint alloc)
674{
675    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
676    LOG_API("nAdapter1DBindAllocation, con(%p), adapter(%p), alloc(%p)", con, (RsAdapter1D)adapter, (RsAllocation)alloc);
677    rsAdapter1DBindAllocation(con, (RsAdapter1D)adapter, (RsAllocation)alloc);
678}
679
680static void
681nAdapter1DSetConstraint(JNIEnv *_env, jobject _this, jint adapter, jint dim, jint value)
682{
683    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
684    LOG_API("nAdapter1DSetConstraint, con(%p), adapter(%p), dim(%i), value(%i)", con, (RsAdapter1D)adapter, dim, value);
685    rsAdapter1DSetConstraint(con, (RsAdapter1D)adapter, (RsDimension)dim, value);
686}
687
688static void
689nAdapter1DData_i(JNIEnv *_env, jobject _this, jint adapter, jintArray data)
690{
691    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
692    jint len = _env->GetArrayLength(data);
693    LOG_API("nAdapter1DData_i, con(%p), adapter(%p), len(%i)", con, (RsAdapter1D)adapter, len);
694    jint *ptr = _env->GetIntArrayElements(data, NULL);
695    rsAdapter1DData(con, (RsAdapter1D)adapter, ptr);
696    _env->ReleaseIntArrayElements(data, ptr, 0/*JNI_ABORT*/);
697}
698
699static void
700nAdapter1DSubData_i(JNIEnv *_env, jobject _this, jint adapter, jint offset, jint count, jintArray data)
701{
702    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
703    jint len = _env->GetArrayLength(data);
704    LOG_API("nAdapter1DSubData_i, con(%p), adapter(%p), offset(%i), count(%i), len(%i)", con, (RsAdapter1D)adapter, offset, count, len);
705    jint *ptr = _env->GetIntArrayElements(data, NULL);
706    rsAdapter1DSubData(con, (RsAdapter1D)adapter, offset, count, ptr);
707    _env->ReleaseIntArrayElements(data, ptr, 0/*JNI_ABORT*/);
708}
709
710static void
711nAdapter1DData_f(JNIEnv *_env, jobject _this, jint adapter, jfloatArray data)
712{
713    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
714    jint len = _env->GetArrayLength(data);
715    LOG_API("nAdapter1DData_f, con(%p), adapter(%p), len(%i)", con, (RsAdapter1D)adapter, len);
716    jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
717    rsAdapter1DData(con, (RsAdapter1D)adapter, ptr);
718    _env->ReleaseFloatArrayElements(data, ptr, 0/*JNI_ABORT*/);
719}
720
721static void
722nAdapter1DSubData_f(JNIEnv *_env, jobject _this, jint adapter, jint offset, jint count, jfloatArray data)
723{
724    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
725    jint len = _env->GetArrayLength(data);
726    LOG_API("nAdapter1DSubData_f, con(%p), adapter(%p), offset(%i), count(%i), len(%i)", con, (RsAdapter1D)adapter, offset, count, len);
727    jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
728    rsAdapter1DSubData(con, (RsAdapter1D)adapter, offset, count, ptr);
729    _env->ReleaseFloatArrayElements(data, ptr, 0/*JNI_ABORT*/);
730}
731
732static jint
733nAdapter1DCreate(JNIEnv *_env, jobject _this)
734{
735    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
736    LOG_API("nAdapter1DCreate, con(%p)", con);
737    return (jint)rsAdapter1DCreate(con);
738}
739
740// -----------------------------------
741
742static void
743nAdapter2DBindAllocation(JNIEnv *_env, jobject _this, jint adapter, jint alloc)
744{
745    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
746    LOG_API("nAdapter2DBindAllocation, con(%p), adapter(%p), alloc(%p)", con, (RsAdapter2D)adapter, (RsAllocation)alloc);
747    rsAdapter2DBindAllocation(con, (RsAdapter2D)adapter, (RsAllocation)alloc);
748}
749
750static void
751nAdapter2DSetConstraint(JNIEnv *_env, jobject _this, jint adapter, jint dim, jint value)
752{
753    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
754    LOG_API("nAdapter2DSetConstraint, con(%p), adapter(%p), dim(%i), value(%i)", con, (RsAdapter2D)adapter, dim, value);
755    rsAdapter2DSetConstraint(con, (RsAdapter2D)adapter, (RsDimension)dim, value);
756}
757
758static void
759nAdapter2DData_i(JNIEnv *_env, jobject _this, jint adapter, jintArray data)
760{
761    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
762    jint len = _env->GetArrayLength(data);
763    LOG_API("nAdapter2DData_i, con(%p), adapter(%p), len(%i)", con, (RsAdapter2D)adapter, len);
764    jint *ptr = _env->GetIntArrayElements(data, NULL);
765    rsAdapter2DData(con, (RsAdapter2D)adapter, ptr);
766    _env->ReleaseIntArrayElements(data, ptr, 0/*JNI_ABORT*/);
767}
768
769static void
770nAdapter2DData_f(JNIEnv *_env, jobject _this, jint adapter, jfloatArray data)
771{
772    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
773    jint len = _env->GetArrayLength(data);
774    LOG_API("nAdapter2DData_f, con(%p), adapter(%p), len(%i)", con, (RsAdapter2D)adapter, len);
775    jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
776    rsAdapter2DData(con, (RsAdapter2D)adapter, ptr);
777    _env->ReleaseFloatArrayElements(data, ptr, 0/*JNI_ABORT*/);
778}
779
780static void
781nAdapter2DSubData_i(JNIEnv *_env, jobject _this, jint adapter, jint xoff, jint yoff, jint w, jint h, jintArray data)
782{
783    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
784    jint len = _env->GetArrayLength(data);
785    LOG_API("nAdapter2DSubData_i, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i)",
786            con, (RsAdapter2D)adapter, xoff, yoff, w, h, len);
787    jint *ptr = _env->GetIntArrayElements(data, NULL);
788    rsAdapter2DSubData(con, (RsAdapter2D)adapter, xoff, yoff, w, h, ptr);
789    _env->ReleaseIntArrayElements(data, ptr, 0/*JNI_ABORT*/);
790}
791
792static void
793nAdapter2DSubData_f(JNIEnv *_env, jobject _this, jint adapter, jint xoff, jint yoff, jint w, jint h, jfloatArray data)
794{
795    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
796    jint len = _env->GetArrayLength(data);
797    LOG_API("nAdapter2DSubData_f, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i)",
798            con, (RsAdapter2D)adapter, xoff, yoff, w, h, len);
799    jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
800    rsAdapter2DSubData(con, (RsAdapter1D)adapter, xoff, yoff, w, h, ptr);
801    _env->ReleaseFloatArrayElements(data, ptr, 0/*JNI_ABORT*/);
802}
803
804static jint
805nAdapter2DCreate(JNIEnv *_env, jobject _this)
806{
807    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
808    LOG_API("nAdapter2DCreate, con(%p)", con);
809    return (jint)rsAdapter2DCreate(con);
810}
811
812// -----------------------------------
813
814static void
815nScriptBindAllocation(JNIEnv *_env, jobject _this, jint script, jint alloc, jint slot)
816{
817    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
818    LOG_API("nScriptBindAllocation, con(%p), script(%p), alloc(%p), slot(%i)", con, (RsScript)script, (RsAllocation)alloc, slot);
819    rsScriptBindAllocation(con, (RsScript)script, (RsAllocation)alloc, slot);
820}
821
822static void
823nScriptSetClearColor(JNIEnv *_env, jobject _this, jint script, jfloat r, jfloat g, jfloat b, jfloat a)
824{
825    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
826    LOG_API("nScriptSetClearColor, con(%p), s(%p), r(%f), g(%f), b(%f), a(%f)", con, (void *)script, r, g, b, a);
827    rsScriptSetClearColor(con, (RsScript)script, r, g, b, a);
828}
829
830static void
831nScriptSetClearDepth(JNIEnv *_env, jobject _this, jint script, jfloat d)
832{
833    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
834    LOG_API("nScriptCSetClearDepth, con(%p), s(%p), depth(%f)", con, (void *)script, d);
835    rsScriptSetClearDepth(con, (RsScript)script, d);
836}
837
838static void
839nScriptSetClearStencil(JNIEnv *_env, jobject _this, jint script, jint stencil)
840{
841    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
842    LOG_API("nScriptCSetClearStencil, con(%p), s(%p), stencil(%i)", con, (void *)script, stencil);
843    rsScriptSetClearStencil(con, (RsScript)script, stencil);
844}
845
846static void
847nScriptSetTimeZone(JNIEnv *_env, jobject _this, jint script, jbyteArray timeZone)
848{
849    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
850    LOG_API("nScriptCSetTimeZone, con(%p), s(%p), timeZone(%s)", con, (void *)script, (const char *)timeZone);
851
852    jint length = _env->GetArrayLength(timeZone);
853    jbyte* timeZone_ptr;
854    timeZone_ptr = (jbyte *) _env->GetPrimitiveArrayCritical(timeZone, (jboolean *)0);
855
856    rsScriptSetTimeZone(con, (RsScript)script, (const char *)timeZone_ptr, length);
857
858    if (timeZone_ptr) {
859        _env->ReleasePrimitiveArrayCritical(timeZone, timeZone_ptr, 0);
860    }
861}
862
863static void
864nScriptSetType(JNIEnv *_env, jobject _this, jint type, jboolean writable, jstring _str, jint slot)
865{
866    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
867    LOG_API("nScriptCAddType, con(%p), type(%p), writable(%i), slot(%i)", con, (RsType)type, writable, slot);
868    const char* n = NULL;
869    if (_str) {
870        n = _env->GetStringUTFChars(_str, NULL);
871    }
872    rsScriptSetType(con, (RsType)type, slot, writable, n);
873    if (n) {
874        _env->ReleaseStringUTFChars(_str, n);
875    }
876}
877
878static void
879nScriptSetInvoke(JNIEnv *_env, jobject _this, jstring _str, jint slot)
880{
881    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
882    LOG_API("nScriptSetInvoke, con(%p)", con);
883    const char* n = NULL;
884    if (_str) {
885        n = _env->GetStringUTFChars(_str, NULL);
886    }
887    rsScriptSetInvoke(con, n, slot);
888    if (n) {
889        _env->ReleaseStringUTFChars(_str, n);
890    }
891}
892
893static void
894nScriptInvoke(JNIEnv *_env, jobject _this, jint obj, jint slot)
895{
896    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
897    LOG_API("nScriptInvoke, con(%p), script(%p)", con, (void *)obj);
898    rsScriptInvoke(con, (RsScript)obj, slot);
899}
900
901static void
902nScriptSetRoot(JNIEnv *_env, jobject _this, jboolean isRoot)
903{
904    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
905    LOG_API("nScriptCSetRoot, con(%p), isRoot(%i)", con, isRoot);
906    rsScriptSetRoot(con, isRoot);
907}
908
909// -----------------------------------
910
911static void
912nScriptCBegin(JNIEnv *_env, jobject _this)
913{
914    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
915    LOG_API("nScriptCBegin, con(%p)", con);
916    rsScriptCBegin(con);
917}
918
919static void
920nScriptCSetScript(JNIEnv *_env, jobject _this, jbyteArray scriptRef,
921                  jint offset, jint length)
922{
923    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
924    LOG_API("!!! nScriptCSetScript, con(%p)", con);
925    jint _exception = 0;
926    jint remaining;
927    jbyte* script_base = 0;
928    jbyte* script_ptr;
929    if (!scriptRef) {
930        _exception = 1;
931        //_env->ThrowNew(IAEClass, "script == null");
932        goto exit;
933    }
934    if (offset < 0) {
935        _exception = 1;
936        //_env->ThrowNew(IAEClass, "offset < 0");
937        goto exit;
938    }
939    if (length < 0) {
940        _exception = 1;
941        //_env->ThrowNew(IAEClass, "length < 0");
942        goto exit;
943    }
944    remaining = _env->GetArrayLength(scriptRef) - offset;
945    if (remaining < length) {
946        _exception = 1;
947        //_env->ThrowNew(IAEClass, "length > script.length - offset");
948        goto exit;
949    }
950    script_base = (jbyte *)
951        _env->GetPrimitiveArrayCritical(scriptRef, (jboolean *)0);
952    script_ptr = script_base + offset;
953
954    rsScriptCSetText(con, (const char *)script_ptr, length);
955
956exit:
957    if (script_base) {
958        _env->ReleasePrimitiveArrayCritical(scriptRef, script_base,
959                _exception ? JNI_ABORT: 0);
960    }
961}
962
963static jint
964nScriptCCreate(JNIEnv *_env, jobject _this)
965{
966    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
967    LOG_API("nScriptCCreate, con(%p)", con);
968    return (jint)rsScriptCCreate(con);
969}
970
971static void
972nScriptCAddDefineI32(JNIEnv *_env, jobject _this, jstring name, jint value)
973{
974    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
975    const char* n = _env->GetStringUTFChars(name, NULL);
976    LOG_API("nScriptCAddDefineI32, con(%p) name(%s) value(%d)", con, n, value);
977    rsScriptCSetDefineI32(con, n, value);
978    _env->ReleaseStringUTFChars(name, n);
979}
980
981static void
982nScriptCAddDefineF(JNIEnv *_env, jobject _this, jstring name, jfloat value)
983{
984    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
985    const char* n = _env->GetStringUTFChars(name, NULL);
986    LOG_API("nScriptCAddDefineF, con(%p) name(%s) value(%f)", con, n, value);
987    rsScriptCSetDefineF(con, n, value);
988    _env->ReleaseStringUTFChars(name, n);
989}
990
991// ---------------------------------------------------------------------------
992
993static void
994nProgramFragmentStoreBegin(JNIEnv *_env, jobject _this, jint in, jint out)
995{
996    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
997    LOG_API("nProgramFragmentStoreBegin, con(%p), in(%p), out(%p)", con, (RsElement)in, (RsElement)out);
998    rsProgramFragmentStoreBegin(con, (RsElement)in, (RsElement)out);
999}
1000
1001static void
1002nProgramFragmentStoreDepthFunc(JNIEnv *_env, jobject _this, jint func)
1003{
1004    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
1005    LOG_API("nProgramFragmentStoreDepthFunc, con(%p), func(%i)", con, func);
1006    rsProgramFragmentStoreDepthFunc(con, (RsDepthFunc)func);
1007}
1008
1009static void
1010nProgramFragmentStoreDepthMask(JNIEnv *_env, jobject _this, jboolean enable)
1011{
1012    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
1013    LOG_API("nProgramFragmentStoreDepthMask, con(%p), enable(%i)", con, enable);
1014    rsProgramFragmentStoreDepthMask(con, enable);
1015}
1016
1017static void
1018nProgramFragmentStoreColorMask(JNIEnv *_env, jobject _this, jboolean r, jboolean g, jboolean b, jboolean a)
1019{
1020    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
1021    LOG_API("nProgramFragmentStoreColorMask, con(%p), r(%i), g(%i), b(%i), a(%i)", con, r, g, b, a);
1022    rsProgramFragmentStoreColorMask(con, r, g, b, a);
1023}
1024
1025static void
1026nProgramFragmentStoreBlendFunc(JNIEnv *_env, jobject _this, int src, int dst)
1027{
1028    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
1029    LOG_API("nProgramFragmentStoreBlendFunc, con(%p), src(%i), dst(%i)", con, src, dst);
1030    rsProgramFragmentStoreBlendFunc(con, (RsBlendSrcFunc)src, (RsBlendDstFunc)dst);
1031}
1032
1033static void
1034nProgramFragmentStoreDither(JNIEnv *_env, jobject _this, jboolean enable)
1035{
1036    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
1037    LOG_API("nProgramFragmentStoreDither, con(%p), enable(%i)", con, enable);
1038    rsProgramFragmentStoreDither(con, enable);
1039}
1040
1041static jint
1042nProgramFragmentStoreCreate(JNIEnv *_env, jobject _this)
1043{
1044    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
1045    LOG_API("nProgramFragmentStoreCreate, con(%p)", con);
1046
1047    return (jint)rsProgramFragmentStoreCreate(con);
1048}
1049
1050// ---------------------------------------------------------------------------
1051
1052static void
1053nProgramFragmentBegin(JNIEnv *_env, jobject _this, jint in, jint out, jboolean pointSpriteEnable)
1054{
1055    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
1056    LOG_API("nProgramFragmentBegin, con(%p), in(%p), out(%p) PointSprite(%i)", con, (RsElement)in, (RsElement)out, pointSpriteEnable);
1057    rsProgramFragmentBegin(con, (RsElement)in, (RsElement)out, pointSpriteEnable);
1058}
1059
1060static void
1061nProgramFragmentBindTexture(JNIEnv *_env, jobject _this, jint vpf, jint slot, jint a)
1062{
1063    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
1064    LOG_API("nProgramFragmentBindTexture, con(%p), vpf(%p), slot(%i), a(%p)", con, (RsProgramFragment)vpf, slot, (RsAllocation)a);
1065    rsProgramFragmentBindTexture(con, (RsProgramFragment)vpf, slot, (RsAllocation)a);
1066}
1067
1068static void
1069nProgramFragmentBindSampler(JNIEnv *_env, jobject _this, jint vpf, jint slot, jint a)
1070{
1071    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
1072    LOG_API("nProgramFragmentBindSampler, con(%p), vpf(%p), slot(%i), a(%p)", con, (RsProgramFragment)vpf, slot, (RsSampler)a);
1073    rsProgramFragmentBindSampler(con, (RsProgramFragment)vpf, slot, (RsSampler)a);
1074}
1075
1076static void
1077nProgramFragmentSetSlot(JNIEnv *_env, jobject _this, jint slot, jboolean enable, jint env, jint vt)
1078{
1079    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
1080    LOG_API("nProgramFragmentSetType, con(%p), slot(%i), enable(%i), env(%i), vt(%p)", con, slot, enable, env, (RsType)vt);
1081    rsProgramFragmentSetSlot(con, slot, enable, (RsTexEnvMode)env, (RsType)vt);
1082}
1083
1084static jint
1085nProgramFragmentCreate(JNIEnv *_env, jobject _this, jint slot, jboolean enable)
1086{
1087    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
1088    LOG_API("nProgramFragmentCreate, con(%p)", con);
1089    return (jint)rsProgramFragmentCreate(con);
1090}
1091
1092// ---------------------------------------------------------------------------
1093
1094static void
1095nProgramVertexBegin(JNIEnv *_env, jobject _this, jint in, jint out)
1096{
1097    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
1098    LOG_API("nProgramVertexBegin, con(%p), in(%p), out(%p)", con, (RsElement)in, (RsElement)out);
1099    rsProgramVertexBegin(con, (RsElement)in, (RsElement)out);
1100}
1101
1102static void
1103nProgramVertexBindAllocation(JNIEnv *_env, jobject _this, jint vpv, jint a)
1104{
1105    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
1106    LOG_API("nProgramVertexBindAllocation, con(%p), vpf(%p), a(%p)", con, (RsProgramVertex)vpv, (RsAllocation)a);
1107    rsProgramVertexBindAllocation(con, (RsProgramFragment)vpv, (RsAllocation)a);
1108}
1109
1110static void
1111nProgramVertexSetTextureMatrixEnable(JNIEnv *_env, jobject _this, jboolean enable)
1112{
1113    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
1114    LOG_API("nProgramVertexSetTextureMatrixEnable, con(%p), enable(%i)", con, enable);
1115    rsProgramVertexSetTextureMatrixEnable(con, enable);
1116}
1117
1118static void
1119nProgramVertexAddLight(JNIEnv *_env, jobject _this, jint light)
1120{
1121    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
1122    LOG_API("nProgramVertexAddLight, con(%p), light(%p)", con, (RsLight)light);
1123    rsProgramVertexAddLight(con, (RsLight)light);
1124}
1125
1126static jint
1127nProgramVertexCreate(JNIEnv *_env, jobject _this)
1128{
1129    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
1130    LOG_API("nProgramVertexCreate, con(%p)", con);
1131    return (jint)rsProgramVertexCreate(con);
1132}
1133
1134
1135
1136// ---------------------------------------------------------------------------
1137
1138static void
1139nContextBindRootScript(JNIEnv *_env, jobject _this, jint script)
1140{
1141    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
1142    LOG_API("nContextBindRootScript, con(%p), script(%p)", con, (RsScript)script);
1143    rsContextBindRootScript(con, (RsScript)script);
1144}
1145
1146static void
1147nContextBindProgramFragmentStore(JNIEnv *_env, jobject _this, jint pfs)
1148{
1149    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
1150    LOG_API("nContextBindProgramFragmentStore, con(%p), pfs(%p)", con, (RsProgramFragmentStore)pfs);
1151    rsContextBindProgramFragmentStore(con, (RsProgramFragmentStore)pfs);
1152}
1153
1154static void
1155nContextBindProgramFragment(JNIEnv *_env, jobject _this, jint pf)
1156{
1157    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
1158    LOG_API("nContextBindProgramFragment, con(%p), pf(%p)", con, (RsProgramFragment)pf);
1159    rsContextBindProgramFragment(con, (RsProgramFragment)pf);
1160}
1161
1162static void
1163nContextBindProgramVertex(JNIEnv *_env, jobject _this, jint pf)
1164{
1165    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
1166    LOG_API("nContextBindProgramVertex, con(%p), pf(%p)", con, (RsProgramVertex)pf);
1167    rsContextBindProgramVertex(con, (RsProgramVertex)pf);
1168}
1169
1170static void
1171nContextAddDefineI32(JNIEnv *_env, jobject _this, jstring name, jint value)
1172{
1173    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
1174    const char* n = _env->GetStringUTFChars(name, NULL);
1175    LOG_API("nScriptCAddDefineI32, con(%p) name(%s) value(%d)", con, n, value);
1176    rsContextSetDefineI32(con, n, value);
1177    _env->ReleaseStringUTFChars(name, n);
1178}
1179
1180static void
1181nContextAddDefineF(JNIEnv *_env, jobject _this, jstring name, jfloat value)
1182{
1183    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
1184    const char* n = _env->GetStringUTFChars(name, NULL);
1185    LOG_API("nScriptCAddDefineF, con(%p) name(%s) value(%f)", con, n, value);
1186    rsContextSetDefineF(con, n, value);
1187    _env->ReleaseStringUTFChars(name, n);
1188}
1189
1190
1191// ---------------------------------------------------------------------------
1192
1193static void
1194nSamplerBegin(JNIEnv *_env, jobject _this)
1195{
1196    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
1197    LOG_API("nSamplerBegin, con(%p)", con);
1198    rsSamplerBegin(con);
1199}
1200
1201static void
1202nSamplerSet(JNIEnv *_env, jobject _this, jint p, jint v)
1203{
1204    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
1205    LOG_API("nSamplerSet, con(%p), param(%i), value(%i)", con, p, v);
1206    rsSamplerSet(con, (RsSamplerParam)p, (RsSamplerValue)v);
1207}
1208
1209static jint
1210nSamplerCreate(JNIEnv *_env, jobject _this)
1211{
1212    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
1213    LOG_API("nSamplerCreate, con(%p)", con);
1214    return (jint)rsSamplerCreate(con);
1215}
1216
1217// ---------------------------------------------------------------------------
1218
1219static void
1220nLightBegin(JNIEnv *_env, jobject _this)
1221{
1222    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
1223    LOG_API("nLightBegin, con(%p)", con);
1224    rsLightBegin(con);
1225}
1226
1227static void
1228nLightSetIsMono(JNIEnv *_env, jobject _this, jboolean isMono)
1229{
1230    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
1231    LOG_API("nLightSetIsMono, con(%p), isMono(%i)", con, isMono);
1232    rsLightSetMonochromatic(con, isMono);
1233}
1234
1235static void
1236nLightSetIsLocal(JNIEnv *_env, jobject _this, jboolean isLocal)
1237{
1238    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
1239    LOG_API("nLightSetIsLocal, con(%p), isLocal(%i)", con, isLocal);
1240    rsLightSetLocal(con, isLocal);
1241}
1242
1243static jint
1244nLightCreate(JNIEnv *_env, jobject _this)
1245{
1246    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
1247    LOG_API("nLightCreate, con(%p)", con);
1248    return (jint)rsLightCreate(con);
1249}
1250
1251static void
1252nLightSetColor(JNIEnv *_env, jobject _this, jint light, float r, float g, float b)
1253{
1254    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
1255    LOG_API("nLightSetColor, con(%p), light(%p), r(%f), g(%f), b(%f)", con, (RsLight)light, r, g, b);
1256    rsLightSetColor(con, (RsLight)light, r, g, b);
1257}
1258
1259static void
1260nLightSetPosition(JNIEnv *_env, jobject _this, jint light, float x, float y, float z)
1261{
1262    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
1263    LOG_API("nLightSetPosition, con(%p), light(%p), x(%f), y(%f), z(%f)", con, (RsLight)light, x, y, z);
1264    rsLightSetPosition(con, (RsLight)light, x, y, z);
1265}
1266
1267// ---------------------------------------------------------------------------
1268
1269static jint
1270nSimpleMeshCreate(JNIEnv *_env, jobject _this, jint batchID, jint indexID, jintArray vtxIDs, jint primID)
1271{
1272    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
1273    jint len = _env->GetArrayLength(vtxIDs);
1274    LOG_API("nSimpleMeshCreate, con(%p), batchID(%i), indexID(%i), vtxIDs.len(%i), primID(%i)",
1275            con, batchID, indexID, len, primID);
1276    jint *ptr = _env->GetIntArrayElements(vtxIDs, NULL);
1277    int id = (int)rsSimpleMeshCreate(con, (void *)batchID, (void *)indexID, (void **)ptr, len, primID);
1278    _env->ReleaseIntArrayElements(vtxIDs, ptr, 0/*JNI_ABORT*/);
1279    return id;
1280}
1281
1282static void
1283nSimpleMeshBindVertex(JNIEnv *_env, jobject _this, jint s, jint alloc, jint slot)
1284{
1285    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
1286    LOG_API("nSimpleMeshBindVertex, con(%p), SimpleMesh(%p), Alloc(%p), slot(%i)", con, (RsSimpleMesh)s, (RsAllocation)alloc, slot);
1287    rsSimpleMeshBindVertex(con, (RsSimpleMesh)s, (RsAllocation)alloc, slot);
1288}
1289
1290static void
1291nSimpleMeshBindIndex(JNIEnv *_env, jobject _this, jint s, jint alloc)
1292{
1293    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
1294    LOG_API("nSimpleMeshBindIndex, con(%p), SimpleMesh(%p), Alloc(%p)", con, (RsSimpleMesh)s, (RsAllocation)alloc);
1295    rsSimpleMeshBindIndex(con, (RsSimpleMesh)s, (RsAllocation)alloc);
1296}
1297
1298// ---------------------------------------------------------------------------
1299
1300
1301static const char *classPathName = "android/renderscript/RenderScript";
1302
1303static JNINativeMethod methods[] = {
1304{"_nInit",                         "()V",                                  (void*)_nInit },
1305{"nInitElements",                  "(IIII)V",                              (void*)nInitElements },
1306
1307{"nDeviceCreate",                  "()I",                                  (void*)nDeviceCreate },
1308{"nDeviceDestroy",                 "(I)V",                                 (void*)nDeviceDestroy },
1309{"nContextCreate",                 "(ILandroid/view/Surface;IZ)I",         (void*)nContextCreate },
1310{"nContextDestroy",                "(I)V",                                 (void*)nContextDestroy },
1311{"nAssignName",                    "(I[B)V",                               (void*)nAssignName },
1312{"nObjDestroy",                    "(I)V",                                 (void*)nObjDestroy },
1313{"nObjDestroyOOB",                 "(I)V",                                 (void*)nObjDestroyOOB },
1314
1315{"nFileOpen",                      "([B)I",                                (void*)nFileOpen },
1316
1317{"nElementBegin",                  "()V",                                  (void*)nElementBegin },
1318{"nElementAdd",                    "(IIZILjava/lang/String;)V",            (void*)nElementAdd },
1319{"nElementCreate",                 "()I",                                  (void*)nElementCreate },
1320
1321{"nTypeBegin",                     "(I)V",                                 (void*)nTypeBegin },
1322{"nTypeAdd",                       "(II)V",                                (void*)nTypeAdd },
1323{"nTypeCreate",                    "()I",                                  (void*)nTypeCreate },
1324{"nTypeFinalDestroy",              "(Landroid/renderscript/Type;)V",       (void*)nTypeFinalDestroy },
1325{"nTypeSetupFields",               "(Landroid/renderscript/Type;[I[I[Ljava/lang/reflect/Field;)V", (void*)nTypeSetupFields },
1326
1327{"nAllocationCreateTyped",         "(I)I",                                 (void*)nAllocationCreateTyped },
1328{"nAllocationCreateFromBitmap",    "(IZLandroid/graphics/Bitmap;)I",       (void*)nAllocationCreateFromBitmap },
1329{"nAllocationCreateFromBitmapBoxed","(IZLandroid/graphics/Bitmap;)I",      (void*)nAllocationCreateFromBitmapBoxed },
1330{"nAllocationCreateFromAssetStream","(IZI)I",                              (void*)nAllocationCreateFromAssetStream },
1331{"nAllocationUploadToTexture",     "(II)V",                                (void*)nAllocationUploadToTexture },
1332{"nAllocationUploadToBufferObject","(I)V",                                 (void*)nAllocationUploadToBufferObject },
1333{"nAllocationSubData1D",           "(III[II)V",                            (void*)nAllocationSubData1D_i },
1334{"nAllocationSubData1D",           "(III[SI)V",                            (void*)nAllocationSubData1D_s },
1335{"nAllocationSubData1D",           "(III[BI)V",                            (void*)nAllocationSubData1D_b },
1336{"nAllocationSubData1D",           "(III[FI)V",                            (void*)nAllocationSubData1D_f },
1337{"nAllocationSubData2D",           "(IIIII[II)V",                          (void*)nAllocationSubData2D_i },
1338{"nAllocationSubData2D",           "(IIIII[FI)V",                          (void*)nAllocationSubData2D_f },
1339{"nAllocationRead",                "(I[I)V",                               (void*)nAllocationRead_i },
1340{"nAllocationRead",                "(I[F)V",                               (void*)nAllocationRead_f },
1341{"nAllocationSubDataFromObject",   "(ILandroid/renderscript/Type;ILjava/lang/Object;)V",   (void*)nAllocationSubDataFromObject },
1342{"nAllocationSubReadFromObject",   "(ILandroid/renderscript/Type;ILjava/lang/Object;)V",   (void*)nAllocationSubReadFromObject },
1343
1344{"nTriangleMeshBegin",             "(II)V",                                (void*)nTriangleMeshBegin },
1345{"nTriangleMeshAddVertex_XY",      "(FF)V",                                (void*)nTriangleMeshAddVertex_XY },
1346{"nTriangleMeshAddVertex_XYZ",     "(FFF)V",                               (void*)nTriangleMeshAddVertex_XYZ },
1347{"nTriangleMeshAddVertex_XY_ST",   "(FFFF)V",                              (void*)nTriangleMeshAddVertex_XY_ST },
1348{"nTriangleMeshAddVertex_XYZ_ST",  "(FFFFF)V",                             (void*)nTriangleMeshAddVertex_XYZ_ST },
1349{"nTriangleMeshAddVertex_XYZ_ST_NORM",  "(FFFFFFFF)V",                     (void*)nTriangleMeshAddVertex_XYZ_ST_NORM },
1350{"nTriangleMeshAddTriangle",       "(III)V",                               (void*)nTriangleMeshAddTriangle },
1351{"nTriangleMeshCreate",            "()I",                                  (void*)nTriangleMeshCreate },
1352
1353{"nAdapter1DBindAllocation",       "(II)V",                                (void*)nAdapter1DBindAllocation },
1354{"nAdapter1DSetConstraint",        "(III)V",                               (void*)nAdapter1DSetConstraint },
1355{"nAdapter1DData",                 "(I[I)V",                               (void*)nAdapter1DData_i },
1356{"nAdapter1DData",                 "(I[F)V",                               (void*)nAdapter1DData_f },
1357{"nAdapter1DSubData",              "(III[I)V",                             (void*)nAdapter1DSubData_i },
1358{"nAdapter1DSubData",              "(III[F)V",                             (void*)nAdapter1DSubData_f },
1359{"nAdapter1DCreate",               "()I",                                  (void*)nAdapter1DCreate },
1360
1361{"nAdapter2DBindAllocation",       "(II)V",                                (void*)nAdapter2DBindAllocation },
1362{"nAdapter2DSetConstraint",        "(III)V",                               (void*)nAdapter2DSetConstraint },
1363{"nAdapter2DData",                 "(I[I)V",                               (void*)nAdapter2DData_i },
1364{"nAdapter2DData",                 "(I[F)V",                               (void*)nAdapter2DData_f },
1365{"nAdapter2DSubData",              "(IIIII[I)V",                           (void*)nAdapter2DSubData_i },
1366{"nAdapter2DSubData",              "(IIIII[F)V",                           (void*)nAdapter2DSubData_f },
1367{"nAdapter2DCreate",               "()I",                                  (void*)nAdapter2DCreate },
1368
1369{"nScriptBindAllocation",          "(III)V",                               (void*)nScriptBindAllocation },
1370{"nScriptSetClearColor",           "(IFFFF)V",                             (void*)nScriptSetClearColor },
1371{"nScriptSetClearDepth",           "(IF)V",                                (void*)nScriptSetClearDepth },
1372{"nScriptSetClearStencil",         "(II)V",                                (void*)nScriptSetClearStencil },
1373{"nScriptSetTimeZone",             "(I[B)V",                               (void*)nScriptSetTimeZone },
1374{"nScriptSetType",                 "(IZLjava/lang/String;I)V",             (void*)nScriptSetType },
1375{"nScriptSetRoot",                 "(Z)V",                                 (void*)nScriptSetRoot },
1376{"nScriptSetInvokable",            "(Ljava/lang/String;I)V",               (void*)nScriptSetInvoke },
1377{"nScriptInvoke",                  "(II)V",                                (void*)nScriptInvoke },
1378
1379{"nScriptCBegin",                  "()V",                                  (void*)nScriptCBegin },
1380{"nScriptCSetScript",              "([BII)V",                              (void*)nScriptCSetScript },
1381{"nScriptCCreate",                 "()I",                                  (void*)nScriptCCreate },
1382{"nScriptCAddDefineI32",           "(Ljava/lang/String;I)V",               (void*)nScriptCAddDefineI32 },
1383{"nScriptCAddDefineF",             "(Ljava/lang/String;F)V",               (void*)nScriptCAddDefineF },
1384
1385{"nProgramFragmentStoreBegin",     "(II)V",                                (void*)nProgramFragmentStoreBegin },
1386{"nProgramFragmentStoreDepthFunc", "(I)V",                                 (void*)nProgramFragmentStoreDepthFunc },
1387{"nProgramFragmentStoreDepthMask", "(Z)V",                                 (void*)nProgramFragmentStoreDepthMask },
1388{"nProgramFragmentStoreColorMask", "(ZZZZ)V",                              (void*)nProgramFragmentStoreColorMask },
1389{"nProgramFragmentStoreBlendFunc", "(II)V",                                (void*)nProgramFragmentStoreBlendFunc },
1390{"nProgramFragmentStoreDither",    "(Z)V",                                 (void*)nProgramFragmentStoreDither },
1391{"nProgramFragmentStoreCreate",    "()I",                                  (void*)nProgramFragmentStoreCreate },
1392
1393{"nProgramFragmentBegin",          "(IIZ)V",                               (void*)nProgramFragmentBegin },
1394{"nProgramFragmentBindTexture",    "(III)V",                               (void*)nProgramFragmentBindTexture },
1395{"nProgramFragmentBindSampler",    "(III)V",                               (void*)nProgramFragmentBindSampler },
1396{"nProgramFragmentSetSlot",        "(IZII)V",                              (void*)nProgramFragmentSetSlot },
1397{"nProgramFragmentCreate",         "()I",                                  (void*)nProgramFragmentCreate },
1398
1399{"nProgramVertexBindAllocation",   "(II)V",                                (void*)nProgramVertexBindAllocation },
1400{"nProgramVertexBegin",            "(II)V",                                (void*)nProgramVertexBegin },
1401{"nProgramVertexSetTextureMatrixEnable",   "(Z)V",                         (void*)nProgramVertexSetTextureMatrixEnable },
1402{"nProgramVertexAddLight",         "(I)V",                                 (void*)nProgramVertexAddLight },
1403{"nProgramVertexCreate",           "()I",                                  (void*)nProgramVertexCreate },
1404
1405{"nLightBegin",                    "()V",                                  (void*)nLightBegin },
1406{"nLightSetIsMono",                "(Z)V",                                 (void*)nLightSetIsMono },
1407{"nLightSetIsLocal",               "(Z)V",                                 (void*)nLightSetIsLocal },
1408{"nLightCreate",                   "()I",                                  (void*)nLightCreate },
1409{"nLightSetColor",                 "(IFFF)V",                              (void*)nLightSetColor },
1410{"nLightSetPosition",              "(IFFF)V",                              (void*)nLightSetPosition },
1411
1412{"nContextBindRootScript",         "(I)V",                                 (void*)nContextBindRootScript },
1413{"nContextBindProgramFragmentStore","(I)V",                                (void*)nContextBindProgramFragmentStore },
1414{"nContextBindProgramFragment",    "(I)V",                                 (void*)nContextBindProgramFragment },
1415{"nContextBindProgramVertex",      "(I)V",                                 (void*)nContextBindProgramVertex },
1416
1417{"nSamplerBegin",                  "()V",                                  (void*)nSamplerBegin },
1418{"nSamplerSet",                    "(II)V",                                (void*)nSamplerSet },
1419{"nSamplerCreate",                 "()I",                                  (void*)nSamplerCreate },
1420
1421{"nSimpleMeshCreate",              "(II[II)I",                             (void*)nSimpleMeshCreate },
1422{"nSimpleMeshBindVertex",          "(III)V",                               (void*)nSimpleMeshBindVertex },
1423{"nSimpleMeshBindIndex",           "(II)V",                                (void*)nSimpleMeshBindIndex },
1424
1425};
1426
1427static int registerFuncs(JNIEnv *_env)
1428{
1429    return android::AndroidRuntime::registerNativeMethods(
1430            _env, classPathName, methods, NELEM(methods));
1431}
1432
1433// ---------------------------------------------------------------------------
1434
1435jint JNI_OnLoad(JavaVM* vm, void* reserved)
1436{
1437    JNIEnv* env = NULL;
1438    jint result = -1;
1439
1440    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
1441        LOGE("ERROR: GetEnv failed\n");
1442        goto bail;
1443    }
1444    assert(env != NULL);
1445
1446    if (registerFuncs(env) < 0) {
1447        LOGE("ERROR: MediaPlayer native registration failed\n");
1448        goto bail;
1449    }
1450
1451    /* success -- return valid version number */
1452    result = JNI_VERSION_1_4;
1453
1454bail:
1455    return result;
1456}
1457