android_renderscript_RenderScript.cpp revision ee956053d6e3f7a7a82e41853b9b251fdc226d7a
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 <surfaceflinger/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#include "android_runtime/android_view_Surface.h"
41
42#include <RenderScript.h>
43#include <RenderScriptEnv.h>
44
45//#define LOG_API LOGE
46#define LOG_API(...)
47
48using namespace android;
49
50// ---------------------------------------------------------------------------
51
52static void doThrow(JNIEnv* env, const char* exc, const char* msg = NULL)
53{
54    jclass npeClazz = env->FindClass(exc);
55    env->ThrowNew(npeClazz, msg);
56}
57
58static jfieldID gContextId = 0;
59static jfieldID gNativeBitmapID = 0;
60static jfieldID gTypeNativeCache = 0;
61
62static RsElement g_A_8 = NULL;
63static RsElement g_RGBA_4444 = NULL;
64static RsElement g_RGBA_8888 = NULL;
65static RsElement g_RGB_565 = NULL;
66
67static void _nInit(JNIEnv *_env, jclass _this)
68{
69    gContextId             = _env->GetFieldID(_this, "mContext", "I");
70
71    jclass bitmapClass = _env->FindClass("android/graphics/Bitmap");
72    gNativeBitmapID = _env->GetFieldID(bitmapClass, "mNativeBitmap", "I");
73
74    jclass typeClass = _env->FindClass("android/renderscript/Type");
75    gTypeNativeCache = _env->GetFieldID(typeClass, "mNativeCache", "I");
76}
77
78static void nInitElements(JNIEnv *_env, jobject _this, jint a8, jint rgba4444, jint rgba8888, jint rgb565)
79{
80    g_A_8 = reinterpret_cast<RsElement>(a8);
81    g_RGBA_4444 = reinterpret_cast<RsElement>(rgba4444);
82    g_RGBA_8888 = reinterpret_cast<RsElement>(rgba8888);
83    g_RGB_565 = reinterpret_cast<RsElement>(rgb565);
84}
85
86// ---------------------------------------------------------------------------
87
88static void
89nContextFinish(JNIEnv *_env, jobject _this, RsContext con)
90{
91    LOG_API("nContextFinish, con(%p)", con);
92    rsContextFinish(con);
93}
94
95static void
96nAssignName(JNIEnv *_env, jobject _this, RsContext con, jint obj, jbyteArray str)
97{
98    LOG_API("nAssignName, con(%p), obj(%p)", con, (void *)obj);
99    jint len = _env->GetArrayLength(str);
100    jbyte * cptr = (jbyte *) _env->GetPrimitiveArrayCritical(str, 0);
101    rsAssignName(con, (void *)obj, (const char *)cptr, len);
102    _env->ReleasePrimitiveArrayCritical(str, cptr, JNI_ABORT);
103}
104
105static jstring
106nGetName(JNIEnv *_env, jobject _this, RsContext con, jint obj)
107{
108    LOG_API("nGetName, con(%p), obj(%p)", con, (void *)obj);
109    const char *name = NULL;
110    rsGetName(con, (void *)obj, &name);
111    return _env->NewStringUTF(name);
112}
113
114static void
115nObjDestroy(JNIEnv *_env, jobject _this, RsContext con, jint obj)
116{
117    LOG_API("nObjDestroy, con(%p) obj(%p)", con, (void *)obj);
118    rsObjDestroy(con, (void *)obj);
119}
120
121
122static jint
123nFileOpen(JNIEnv *_env, jobject _this, RsContext con, jbyteArray str)
124{
125    LOG_API("nFileOpen, con(%p)", con);
126    jint len = _env->GetArrayLength(str);
127    jbyte * cptr = (jbyte *) _env->GetPrimitiveArrayCritical(str, 0);
128    jint ret = (jint)rsFileOpen(con, (const char *)cptr, len);
129    _env->ReleasePrimitiveArrayCritical(str, cptr, JNI_ABORT);
130    return ret;
131}
132
133// ---------------------------------------------------------------------------
134
135static jint
136nDeviceCreate(JNIEnv *_env, jobject _this)
137{
138    LOG_API("nDeviceCreate");
139    return (jint)rsDeviceCreate();
140}
141
142static void
143nDeviceDestroy(JNIEnv *_env, jobject _this, jint dev)
144{
145    LOG_API("nDeviceDestroy");
146    return rsDeviceDestroy((RsDevice)dev);
147}
148
149static void
150nDeviceSetConfig(JNIEnv *_env, jobject _this, jint dev, jint p, jint value)
151{
152    LOG_API("nDeviceSetConfig  dev(%p), param(%i), value(%i)", (void *)dev, p, value);
153    return rsDeviceSetConfig((RsDevice)dev, (RsDeviceParam)p, value);
154}
155
156static jint
157nContextCreate(JNIEnv *_env, jobject _this, jint dev, jint ver)
158{
159    LOG_API("nContextCreate");
160    return (jint)rsContextCreate((RsDevice)dev, ver);
161}
162
163static jint
164nContextCreateGL(JNIEnv *_env, jobject _this, jint dev, jint ver, jboolean useDepth)
165{
166    LOG_API("nContextCreateGL");
167    return (jint)rsContextCreateGL((RsDevice)dev, ver, useDepth);
168}
169
170static void
171nContextSetPriority(JNIEnv *_env, jobject _this, RsContext con, jint p)
172{
173    LOG_API("ContextSetPriority, con(%p), priority(%i)", con, p);
174    rsContextSetPriority(con, p);
175}
176
177
178
179static void
180nContextSetSurface(JNIEnv *_env, jobject _this, RsContext con, jint width, jint height, jobject wnd)
181{
182    LOG_API("nContextSetSurface, con(%p), width(%i), height(%i), surface(%p)", con, width, height, (Surface *)wnd);
183
184    Surface * window = NULL;
185    if (wnd == NULL) {
186
187    } else {
188        window = (Surface*) android_Surface_getNativeWindow(_env, wnd).get();
189    }
190
191    rsContextSetSurface(con, width, height, window);
192}
193
194static void
195nContextDestroy(JNIEnv *_env, jobject _this, RsContext con)
196{
197    LOG_API("nContextDestroy, con(%p)", con);
198    rsContextDestroy(con);
199}
200
201static void
202nContextDump(JNIEnv *_env, jobject _this, RsContext con, jint bits)
203{
204    LOG_API("nContextDump, con(%p)  bits(%i)", (RsContext)con, bits);
205    rsContextDump((RsContext)con, bits);
206}
207
208static void
209nContextPause(JNIEnv *_env, jobject _this, RsContext con)
210{
211    LOG_API("nContextPause, con(%p)", con);
212    rsContextPause(con);
213}
214
215static void
216nContextResume(JNIEnv *_env, jobject _this, RsContext con)
217{
218    LOG_API("nContextResume, con(%p)", con);
219    rsContextResume(con);
220}
221
222static jint
223nContextGetMessage(JNIEnv *_env, jobject _this, RsContext con, jintArray data, jboolean wait)
224{
225    jint len = _env->GetArrayLength(data);
226    LOG_API("nContextGetMessage, con(%p), len(%i)", con, len);
227    jint *ptr = _env->GetIntArrayElements(data, NULL);
228    size_t receiveLen;
229    int id = rsContextGetMessage(con, ptr, &receiveLen, len * 4, wait);
230    if (!id && receiveLen) {
231        LOGE("message receive buffer too small.  %i", receiveLen);
232    }
233    _env->ReleaseIntArrayElements(data, ptr, 0);
234    return id;
235}
236
237static void nContextInitToClient(JNIEnv *_env, jobject _this, RsContext con)
238{
239    LOG_API("nContextInitToClient, con(%p)", con);
240    rsContextInitToClient(con);
241}
242
243static void nContextDeinitToClient(JNIEnv *_env, jobject _this, RsContext con)
244{
245    LOG_API("nContextDeinitToClient, con(%p)", con);
246    rsContextDeinitToClient(con);
247}
248
249
250static jint
251nElementCreate(JNIEnv *_env, jobject _this, RsContext con, jint type, jint kind, jboolean norm, jint size)
252{
253    LOG_API("nElementCreate, con(%p), type(%i), kind(%i), norm(%i), size(%i)", con, type, kind, norm, size);
254    return (jint)rsElementCreate(con, (RsDataType)type, (RsDataKind)kind, norm, size);
255}
256
257static jint
258nElementCreate2(JNIEnv *_env, jobject _this, RsContext con, jintArray _ids, jobjectArray _names)
259{
260    int fieldCount = _env->GetArrayLength(_ids);
261    LOG_API("nElementCreate2, con(%p)", con);
262
263    jint *ids = _env->GetIntArrayElements(_ids, NULL);
264    const char ** nameArray = (const char **)calloc(fieldCount, sizeof(char *));
265    size_t* sizeArray = (size_t*)calloc(fieldCount, sizeof(size_t));
266
267    for (int ct=0; ct < fieldCount; ct++) {
268        jstring s = (jstring)_env->GetObjectArrayElement(_names, ct);
269        nameArray[ct] = _env->GetStringUTFChars(s, NULL);
270        sizeArray[ct] = _env->GetStringUTFLength(s);
271    }
272    jint id = (jint)rsElementCreate2(con, fieldCount, (RsElement *)ids, nameArray, sizeArray);
273    for (int ct=0; ct < fieldCount; ct++) {
274        jstring s = (jstring)_env->GetObjectArrayElement(_names, ct);
275        _env->ReleaseStringUTFChars(s, nameArray[ct]);
276    }
277    _env->ReleaseIntArrayElements(_ids, ids, JNI_ABORT);
278    free(nameArray);
279    free(sizeArray);
280    return (jint)id;
281}
282
283static void
284nElementGetNativeData(JNIEnv *_env, jobject _this, RsContext con, jint id, jintArray _elementData)
285{
286    int dataSize = _env->GetArrayLength(_elementData);
287    LOG_API("nElementGetNativeData, con(%p)", con);
288
289    // we will pack mType; mKind; mNormalized; mVectorSize; NumSubElements
290    assert(dataSize == 5);
291
292    uint32_t elementData[5];
293    rsElementGetNativeData(con, (RsElement)id, elementData, dataSize);
294
295    for(jint i = 0; i < dataSize; i ++) {
296        _env->SetIntArrayRegion(_elementData, i, 1, (const jint*)&elementData[i]);
297    }
298}
299
300
301static void
302nElementGetSubElements(JNIEnv *_env, jobject _this, RsContext con, jint id, jintArray _IDs, jobjectArray _names)
303{
304    int dataSize = _env->GetArrayLength(_IDs);
305    LOG_API("nElementGetSubElements, con(%p)", con);
306
307    uint32_t *ids = (uint32_t *)malloc((uint32_t)dataSize * sizeof(uint32_t));
308    const char **names = (const char **)malloc((uint32_t)dataSize * sizeof(const char *));
309
310    rsElementGetSubElements(con, (RsElement)id, ids, names, (uint32_t)dataSize);
311
312    for(jint i = 0; i < dataSize; i ++) {
313        _env->SetObjectArrayElement(_names, i, _env->NewStringUTF(names[i]));
314        _env->SetIntArrayRegion(_IDs, i, 1, (const jint*)&ids[i]);
315    }
316
317    free(ids);
318    free(names);
319}
320
321// -----------------------------------
322
323static void
324nTypeBegin(JNIEnv *_env, jobject _this, RsContext con, jint eID)
325{
326    LOG_API("nTypeBegin, con(%p) e(%p)", con, (RsElement)eID);
327    rsTypeBegin(con, (RsElement)eID);
328}
329
330static void
331nTypeAdd(JNIEnv *_env, jobject _this, RsContext con, jint dim, jint val)
332{
333    LOG_API("nTypeAdd, con(%p) dim(%i), val(%i)", con, dim, val);
334    rsTypeAdd(con, (RsDimension)dim, val);
335}
336
337static jint
338nTypeCreate(JNIEnv *_env, jobject _this, RsContext con)
339{
340    LOG_API("nTypeCreate, con(%p)", con);
341    return (jint)rsTypeCreate(con);
342}
343
344static void
345nTypeGetNativeData(JNIEnv *_env, jobject _this, RsContext con, jint id, jintArray _typeData)
346{
347    // We are packing 6 items: mDimX; mDimY; mDimZ;
348    // mDimLOD; mDimFaces; mElement; into typeData
349    int elementCount = _env->GetArrayLength(_typeData);
350
351    assert(elementCount == 6);
352    LOG_API("nTypeCreate, con(%p)", con);
353
354    uint32_t typeData[6];
355    rsTypeGetNativeData(con, (RsType)id, typeData, 6);
356
357    for(jint i = 0; i < elementCount; i ++) {
358        _env->SetIntArrayRegion(_typeData, i, 1, (const jint*)&typeData[i]);
359    }
360}
361
362static void * SF_LoadInt(JNIEnv *_env, jobject _obj, jfieldID _field, void *buffer)
363{
364    ((int32_t *)buffer)[0] = _env->GetIntField(_obj, _field);
365    return ((uint8_t *)buffer) + 4;
366}
367
368static void * SF_LoadShort(JNIEnv *_env, jobject _obj, jfieldID _field, void *buffer)
369{
370    ((int16_t *)buffer)[0] = _env->GetShortField(_obj, _field);
371    return ((uint8_t *)buffer) + 2;
372}
373
374static void * SF_LoadByte(JNIEnv *_env, jobject _obj, jfieldID _field, void *buffer)
375{
376    ((int8_t *)buffer)[0] = _env->GetByteField(_obj, _field);
377    return ((uint8_t *)buffer) + 1;
378}
379
380static void * SF_LoadFloat(JNIEnv *_env, jobject _obj, jfieldID _field, void *buffer)
381{
382    ((float *)buffer)[0] = _env->GetFloatField(_obj, _field);
383    return ((uint8_t *)buffer) + 4;
384}
385
386static void * SF_SaveInt(JNIEnv *_env, jobject _obj, jfieldID _field, void *buffer)
387{
388    _env->SetIntField(_obj, _field, ((int32_t *)buffer)[0]);
389    return ((uint8_t *)buffer) + 4;
390}
391
392static void * SF_SaveShort(JNIEnv *_env, jobject _obj, jfieldID _field, void *buffer)
393{
394    _env->SetShortField(_obj, _field, ((int16_t *)buffer)[0]);
395    return ((uint8_t *)buffer) + 2;
396}
397
398static void * SF_SaveByte(JNIEnv *_env, jobject _obj, jfieldID _field, void *buffer)
399{
400    _env->SetByteField(_obj, _field, ((int8_t *)buffer)[0]);
401    return ((uint8_t *)buffer) + 1;
402}
403
404static void * SF_SaveFloat(JNIEnv *_env, jobject _obj, jfieldID _field, void *buffer)
405{
406    _env->SetFloatField(_obj, _field, ((float *)buffer)[0]);
407    return ((uint8_t *)buffer) + 4;
408}
409
410struct TypeFieldCache {
411    jfieldID field;
412    int bits;
413    void * (*ptr)(JNIEnv *, jobject, jfieldID, void *buffer);
414    void * (*readPtr)(JNIEnv *, jobject, jfieldID, void *buffer);
415};
416
417struct TypeCache {
418    int fieldCount;
419    int size;
420    TypeFieldCache fields[1];
421};
422
423//{"nTypeFinalDestroy",              "(Landroid/renderscript/Type;)V",       (void*)nTypeFinalDestroy },
424static void
425nTypeFinalDestroy(JNIEnv *_env, jobject _this, RsContext con, jobject _type)
426{
427    TypeCache *tc = (TypeCache *)_env->GetIntField(_type, gTypeNativeCache);
428    free(tc);
429}
430
431// native void nTypeSetupFields(Type t, int[] types, int[] bits, Field[] IDs);
432static void
433nTypeSetupFields(JNIEnv *_env, jobject _this, RsContext con, jobject _type, jintArray _types, jintArray _bits, jobjectArray _IDs)
434{
435    int fieldCount = _env->GetArrayLength(_types);
436    size_t structSize = sizeof(TypeCache) + (sizeof(TypeFieldCache) * (fieldCount-1));
437    TypeCache *tc = (TypeCache *)malloc(structSize);
438    memset(tc, 0, structSize);
439
440    TypeFieldCache *tfc = &tc->fields[0];
441    tc->fieldCount = fieldCount;
442    _env->SetIntField(_type, gTypeNativeCache, (jint)tc);
443
444    jint *fType = _env->GetIntArrayElements(_types, NULL);
445    jint *fBits = _env->GetIntArrayElements(_bits, NULL);
446    for (int ct=0; ct < fieldCount; ct++) {
447        jobject field = _env->GetObjectArrayElement(_IDs, ct);
448        tfc[ct].field = _env->FromReflectedField(field);
449        tfc[ct].bits = fBits[ct];
450
451        switch(fType[ct]) {
452        case RS_TYPE_FLOAT_32:
453            tfc[ct].ptr = SF_LoadFloat;
454            tfc[ct].readPtr = SF_SaveFloat;
455            break;
456        case RS_TYPE_UNSIGNED_32:
457        case RS_TYPE_SIGNED_32:
458            tfc[ct].ptr = SF_LoadInt;
459            tfc[ct].readPtr = SF_SaveInt;
460            break;
461        case RS_TYPE_UNSIGNED_16:
462        case RS_TYPE_SIGNED_16:
463            tfc[ct].ptr = SF_LoadShort;
464            tfc[ct].readPtr = SF_SaveShort;
465            break;
466        case RS_TYPE_UNSIGNED_8:
467        case RS_TYPE_SIGNED_8:
468            tfc[ct].ptr = SF_LoadByte;
469            tfc[ct].readPtr = SF_SaveByte;
470            break;
471        }
472        tc->size += 4;
473    }
474
475    _env->ReleaseIntArrayElements(_types, fType, JNI_ABORT);
476    _env->ReleaseIntArrayElements(_bits, fBits, JNI_ABORT);
477}
478
479
480// -----------------------------------
481
482static jint
483nAllocationCreateTyped(JNIEnv *_env, jobject _this, RsContext con, jint e)
484{
485    LOG_API("nAllocationCreateTyped, con(%p), e(%p)", con, (RsElement)e);
486    return (jint) rsAllocationCreateTyped(con, (RsElement)e);
487}
488
489static void
490nAllocationUploadToTexture(JNIEnv *_env, jobject _this, RsContext con, jint a, jboolean genMip, jint mip)
491{
492    LOG_API("nAllocationUploadToTexture, con(%p), a(%p), genMip(%i), mip(%i)", con, (RsAllocation)a, genMip, mip);
493    rsAllocationUploadToTexture(con, (RsAllocation)a, genMip, mip);
494}
495
496static void
497nAllocationUploadToBufferObject(JNIEnv *_env, jobject _this, RsContext con, jint a)
498{
499    LOG_API("nAllocationUploadToBufferObject, con(%p), a(%p)", con, (RsAllocation)a);
500    rsAllocationUploadToBufferObject(con, (RsAllocation)a);
501}
502
503static RsElement SkBitmapToPredefined(SkBitmap::Config cfg)
504{
505    switch (cfg) {
506    case SkBitmap::kA8_Config:
507        return g_A_8;
508    case SkBitmap::kARGB_4444_Config:
509        return g_RGBA_4444;
510    case SkBitmap::kARGB_8888_Config:
511        return g_RGBA_8888;
512    case SkBitmap::kRGB_565_Config:
513        return g_RGB_565;
514
515    default:
516        break;
517    }
518    // If we don't have a conversion mark it as a user type.
519    LOGE("Unsupported bitmap type");
520    return NULL;
521}
522
523static int
524nAllocationCreateFromBitmap(JNIEnv *_env, jobject _this, RsContext con, jint dstFmt, jboolean genMips, jobject jbitmap)
525{
526    SkBitmap const * nativeBitmap =
527            (SkBitmap const *)_env->GetIntField(jbitmap, gNativeBitmapID);
528    const SkBitmap& bitmap(*nativeBitmap);
529    SkBitmap::Config config = bitmap.getConfig();
530
531    RsElement e = SkBitmapToPredefined(config);
532    if (e) {
533        bitmap.lockPixels();
534        const int w = bitmap.width();
535        const int h = bitmap.height();
536        const void* ptr = bitmap.getPixels();
537        jint id = (jint)rsAllocationCreateFromBitmap(con, w, h, (RsElement)dstFmt, e, genMips, ptr);
538        bitmap.unlockPixels();
539        return id;
540    }
541    return 0;
542}
543
544static void ReleaseBitmapCallback(void *bmp)
545{
546    SkBitmap const * nativeBitmap = (SkBitmap const *)bmp;
547    nativeBitmap->unlockPixels();
548}
549
550static int
551nAllocationCreateBitmapRef(JNIEnv *_env, jobject _this, RsContext con, jint type, jobject jbitmap)
552{
553    SkBitmap * nativeBitmap =
554            (SkBitmap *)_env->GetIntField(jbitmap, gNativeBitmapID);
555
556
557    nativeBitmap->lockPixels();
558    void* ptr = nativeBitmap->getPixels();
559    jint id = (jint)rsAllocationCreateBitmapRef(con, (RsType)type, ptr, nativeBitmap, ReleaseBitmapCallback);
560    return id;
561}
562
563static int
564nAllocationCreateFromAssetStream(JNIEnv *_env, jobject _this, RsContext con, jint dstFmt, jboolean genMips, jint native_asset)
565{
566    Asset* asset = reinterpret_cast<Asset*>(native_asset);
567    SkBitmap bitmap;
568    SkImageDecoder::DecodeMemory(asset->getBuffer(false), asset->getLength(),
569            &bitmap, SkBitmap::kNo_Config, SkImageDecoder::kDecodePixels_Mode);
570
571    SkBitmap::Config config = bitmap.getConfig();
572
573    RsElement e = SkBitmapToPredefined(config);
574
575    if (e) {
576        bitmap.lockPixels();
577        const int w = bitmap.width();
578        const int h = bitmap.height();
579        const void* ptr = bitmap.getPixels();
580        jint id = (jint)rsAllocationCreateFromBitmap(con, w, h, (RsElement)dstFmt, e, genMips, ptr);
581        bitmap.unlockPixels();
582        return id;
583    }
584    return 0;
585}
586
587static int
588nAllocationCreateFromBitmapBoxed(JNIEnv *_env, jobject _this, RsContext con, jint dstFmt, jboolean genMips, jobject jbitmap)
589{
590    SkBitmap const * nativeBitmap =
591            (SkBitmap const *)_env->GetIntField(jbitmap, gNativeBitmapID);
592    const SkBitmap& bitmap(*nativeBitmap);
593    SkBitmap::Config config = bitmap.getConfig();
594
595    RsElement e = SkBitmapToPredefined(config);
596
597    if (e) {
598        bitmap.lockPixels();
599        const int w = bitmap.width();
600        const int h = bitmap.height();
601        const void* ptr = bitmap.getPixels();
602        jint id = (jint)rsAllocationCreateFromBitmapBoxed(con, w, h, (RsElement)dstFmt, e, genMips, ptr);
603        bitmap.unlockPixels();
604        return id;
605    }
606    return 0;
607}
608
609
610static void
611nAllocationSubData1D_i(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint offset, jint count, jintArray data, int sizeBytes)
612{
613    jint len = _env->GetArrayLength(data);
614    LOG_API("nAllocation1DSubData_i, con(%p), adapter(%p), offset(%i), count(%i), len(%i), sizeBytes(%i)", con, (RsAllocation)alloc, offset, count, len, sizeBytes);
615    jint *ptr = _env->GetIntArrayElements(data, NULL);
616    rsAllocation1DSubData(con, (RsAllocation)alloc, offset, count, ptr, sizeBytes);
617    _env->ReleaseIntArrayElements(data, ptr, JNI_ABORT);
618}
619
620static void
621nAllocationSubData1D_s(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint offset, jint count, jshortArray data, int sizeBytes)
622{
623    jint len = _env->GetArrayLength(data);
624    LOG_API("nAllocation1DSubData_s, con(%p), adapter(%p), offset(%i), count(%i), len(%i), sizeBytes(%i)", con, (RsAllocation)alloc, offset, count, len, sizeBytes);
625    jshort *ptr = _env->GetShortArrayElements(data, NULL);
626    rsAllocation1DSubData(con, (RsAllocation)alloc, offset, count, ptr, sizeBytes);
627    _env->ReleaseShortArrayElements(data, ptr, JNI_ABORT);
628}
629
630static void
631nAllocationSubData1D_b(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint offset, jint count, jbyteArray data, int sizeBytes)
632{
633    jint len = _env->GetArrayLength(data);
634    LOG_API("nAllocation1DSubData_b, con(%p), adapter(%p), offset(%i), count(%i), len(%i), sizeBytes(%i)", con, (RsAllocation)alloc, offset, count, len, sizeBytes);
635    jbyte *ptr = _env->GetByteArrayElements(data, NULL);
636    rsAllocation1DSubData(con, (RsAllocation)alloc, offset, count, ptr, sizeBytes);
637    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
638}
639
640static void
641nAllocationSubData1D_f(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint offset, jint count, jfloatArray data, int sizeBytes)
642{
643    jint len = _env->GetArrayLength(data);
644    LOG_API("nAllocation1DSubData_f, con(%p), adapter(%p), offset(%i), count(%i), len(%i), sizeBytes(%i)", con, (RsAllocation)alloc, offset, count, len, sizeBytes);
645    jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
646    rsAllocation1DSubData(con, (RsAllocation)alloc, offset, count, ptr, sizeBytes);
647    _env->ReleaseFloatArrayElements(data, ptr, JNI_ABORT);
648}
649
650static void
651nAllocationSubData2D_i(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint xoff, jint yoff, jint w, jint h, jintArray data, int sizeBytes)
652{
653    jint len = _env->GetArrayLength(data);
654    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);
655    jint *ptr = _env->GetIntArrayElements(data, NULL);
656    rsAllocation2DSubData(con, (RsAllocation)alloc, xoff, yoff, w, h, ptr, sizeBytes);
657    _env->ReleaseIntArrayElements(data, ptr, JNI_ABORT);
658}
659
660static void
661nAllocationSubData2D_f(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint xoff, jint yoff, jint w, jint h, jfloatArray data, int sizeBytes)
662{
663    jint len = _env->GetArrayLength(data);
664    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);
665    jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
666    rsAllocation2DSubData(con, (RsAllocation)alloc, xoff, yoff, w, h, ptr, sizeBytes);
667    _env->ReleaseFloatArrayElements(data, ptr, JNI_ABORT);
668}
669
670static void
671nAllocationRead_i(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jintArray data)
672{
673    jint len = _env->GetArrayLength(data);
674    LOG_API("nAllocationRead_i, con(%p), alloc(%p), len(%i)", con, (RsAllocation)alloc, len);
675    jint *ptr = _env->GetIntArrayElements(data, NULL);
676    rsAllocationRead(con, (RsAllocation)alloc, ptr);
677    _env->ReleaseIntArrayElements(data, ptr, 0);
678}
679
680static void
681nAllocationRead_f(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jfloatArray data)
682{
683    jint len = _env->GetArrayLength(data);
684    LOG_API("nAllocationRead_f, con(%p), alloc(%p), len(%i)", con, (RsAllocation)alloc, len);
685    jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
686    rsAllocationRead(con, (RsAllocation)alloc, ptr);
687    _env->ReleaseFloatArrayElements(data, ptr, 0);
688}
689
690
691//{"nAllocationDataFromObject",      "(ILandroid/renderscript/Type;Ljava/lang/Object;)V",   (void*)nAllocationDataFromObject },
692static void
693nAllocationSubDataFromObject(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jobject _type, jint offset, jobject _o)
694{
695    LOG_API("nAllocationDataFromObject con(%p), alloc(%p)", con, (RsAllocation)alloc);
696
697    const TypeCache *tc = (TypeCache *)_env->GetIntField(_type, gTypeNativeCache);
698
699    void * bufAlloc = malloc(tc->size);
700    void * buf = bufAlloc;
701    for (int ct=0; ct < tc->fieldCount; ct++) {
702        const TypeFieldCache *tfc = &tc->fields[ct];
703        buf = tfc->ptr(_env, _o, tfc->field, buf);
704    }
705    rsAllocation1DSubData(con, (RsAllocation)alloc, offset, 1, bufAlloc, tc->size);
706    free(bufAlloc);
707}
708
709static void
710nAllocationSubReadFromObject(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jobject _type, jint offset, jobject _o)
711{
712    LOG_API("nAllocationReadFromObject con(%p), alloc(%p)", con, (RsAllocation)alloc);
713
714    assert(offset == 0);
715
716    const TypeCache *tc = (TypeCache *)_env->GetIntField(_type, gTypeNativeCache);
717
718    void * bufAlloc = malloc(tc->size);
719    void * buf = bufAlloc;
720    rsAllocationRead(con, (RsAllocation)alloc, bufAlloc);
721
722    for (int ct=0; ct < tc->fieldCount; ct++) {
723        const TypeFieldCache *tfc = &tc->fields[ct];
724        buf = tfc->readPtr(_env, _o, tfc->field, buf);
725    }
726    free(bufAlloc);
727}
728
729static jint
730nAllocationGetType(JNIEnv *_env, jobject _this, RsContext con, jint a)
731{
732    LOG_API("nAllocationGetType, con(%p), a(%p)", con, (RsAllocation)a);
733    return (jint) rsAllocationGetType(con, (RsAllocation)a);
734}
735
736// -----------------------------------
737
738static int
739nFileA3DCreateFromAssetStream(JNIEnv *_env, jobject _this, RsContext con, jint native_asset)
740{
741    LOGV("______nFileA3D %u", (uint32_t) native_asset);
742
743    Asset* asset = reinterpret_cast<Asset*>(native_asset);
744
745    jint id = (jint)rsFileA3DCreateFromAssetStream(con, asset->getBuffer(false), asset->getLength());
746    return id;
747}
748
749static int
750nFileA3DGetNumIndexEntries(JNIEnv *_env, jobject _this, RsContext con, jint fileA3D)
751{
752    int32_t numEntries = 0;
753    rsFileA3DGetNumIndexEntries(con, &numEntries, (RsFile)fileA3D);
754    return numEntries;
755}
756
757static void
758nFileA3DGetIndexEntries(JNIEnv *_env, jobject _this, RsContext con, jint fileA3D, jint numEntries, jintArray _ids, jobjectArray _entries)
759{
760    LOGV("______nFileA3D %u", (uint32_t) fileA3D);
761    RsFileIndexEntry *fileEntries = (RsFileIndexEntry*)malloc((uint32_t)numEntries * sizeof(RsFileIndexEntry));
762
763    rsFileA3DGetIndexEntries(con, fileEntries, (uint32_t)numEntries, (RsFile)fileA3D);
764
765    for(jint i = 0; i < numEntries; i ++) {
766        _env->SetObjectArrayElement(_entries, i, _env->NewStringUTF(fileEntries[i].objectName));
767        _env->SetIntArrayRegion(_ids, i, 1, (const jint*)&fileEntries[i].classID);
768    }
769
770    free(fileEntries);
771}
772
773static int
774nFileA3DGetEntryByIndex(JNIEnv *_env, jobject _this, RsContext con, jint fileA3D, jint index)
775{
776    LOGV("______nFileA3D %u", (uint32_t) fileA3D);
777    jint id = (jint)rsFileA3DGetEntryByIndex(con, (uint32_t)index, (RsFile)fileA3D);
778    return id;
779}
780
781// -----------------------------------
782
783static int
784nFontCreateFromFile(JNIEnv *_env, jobject _this, RsContext con, jstring fileName, jint fontSize, jint dpi)
785{
786    const char* fileNameUTF = _env->GetStringUTFChars(fileName, NULL);
787
788    jint id = (jint)rsFontCreateFromFile(con, fileNameUTF, fontSize, dpi);
789    return id;
790}
791
792
793// -----------------------------------
794
795static void
796nAdapter1DBindAllocation(JNIEnv *_env, jobject _this, RsContext con, jint adapter, jint alloc)
797{
798    LOG_API("nAdapter1DBindAllocation, con(%p), adapter(%p), alloc(%p)", con, (RsAdapter1D)adapter, (RsAllocation)alloc);
799    rsAdapter1DBindAllocation(con, (RsAdapter1D)adapter, (RsAllocation)alloc);
800}
801
802static void
803nAdapter1DSetConstraint(JNIEnv *_env, jobject _this, RsContext con, jint adapter, jint dim, jint value)
804{
805    LOG_API("nAdapter1DSetConstraint, con(%p), adapter(%p), dim(%i), value(%i)", con, (RsAdapter1D)adapter, dim, value);
806    rsAdapter1DSetConstraint(con, (RsAdapter1D)adapter, (RsDimension)dim, value);
807}
808
809static void
810nAdapter1DData_i(JNIEnv *_env, jobject _this, RsContext con, jint adapter, jintArray data)
811{
812    jint len = _env->GetArrayLength(data);
813    LOG_API("nAdapter1DData_i, con(%p), adapter(%p), len(%i)", con, (RsAdapter1D)adapter, len);
814    jint *ptr = _env->GetIntArrayElements(data, NULL);
815    rsAdapter1DData(con, (RsAdapter1D)adapter, ptr);
816    _env->ReleaseIntArrayElements(data, ptr, 0/*JNI_ABORT*/);
817}
818
819static void
820nAdapter1DSubData_i(JNIEnv *_env, jobject _this, RsContext con, jint adapter, jint offset, jint count, jintArray data)
821{
822    jint len = _env->GetArrayLength(data);
823    LOG_API("nAdapter1DSubData_i, con(%p), adapter(%p), offset(%i), count(%i), len(%i)", con, (RsAdapter1D)adapter, offset, count, len);
824    jint *ptr = _env->GetIntArrayElements(data, NULL);
825    rsAdapter1DSubData(con, (RsAdapter1D)adapter, offset, count, ptr);
826    _env->ReleaseIntArrayElements(data, ptr, 0/*JNI_ABORT*/);
827}
828
829static void
830nAdapter1DData_f(JNIEnv *_env, jobject _this, RsContext con, jint adapter, jfloatArray data)
831{
832    jint len = _env->GetArrayLength(data);
833    LOG_API("nAdapter1DData_f, con(%p), adapter(%p), len(%i)", con, (RsAdapter1D)adapter, len);
834    jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
835    rsAdapter1DData(con, (RsAdapter1D)adapter, ptr);
836    _env->ReleaseFloatArrayElements(data, ptr, 0/*JNI_ABORT*/);
837}
838
839static void
840nAdapter1DSubData_f(JNIEnv *_env, jobject _this, RsContext con, jint adapter, jint offset, jint count, jfloatArray data)
841{
842    jint len = _env->GetArrayLength(data);
843    LOG_API("nAdapter1DSubData_f, con(%p), adapter(%p), offset(%i), count(%i), len(%i)", con, (RsAdapter1D)adapter, offset, count, len);
844    jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
845    rsAdapter1DSubData(con, (RsAdapter1D)adapter, offset, count, ptr);
846    _env->ReleaseFloatArrayElements(data, ptr, 0/*JNI_ABORT*/);
847}
848
849static jint
850nAdapter1DCreate(JNIEnv *_env, jobject _this, RsContext con)
851{
852    LOG_API("nAdapter1DCreate, con(%p)", con);
853    return (jint)rsAdapter1DCreate(con);
854}
855
856// -----------------------------------
857
858static void
859nAdapter2DBindAllocation(JNIEnv *_env, jobject _this, RsContext con, jint adapter, jint alloc)
860{
861    LOG_API("nAdapter2DBindAllocation, con(%p), adapter(%p), alloc(%p)", con, (RsAdapter2D)adapter, (RsAllocation)alloc);
862    rsAdapter2DBindAllocation(con, (RsAdapter2D)adapter, (RsAllocation)alloc);
863}
864
865static void
866nAdapter2DSetConstraint(JNIEnv *_env, jobject _this, RsContext con, jint adapter, jint dim, jint value)
867{
868    LOG_API("nAdapter2DSetConstraint, con(%p), adapter(%p), dim(%i), value(%i)", con, (RsAdapter2D)adapter, dim, value);
869    rsAdapter2DSetConstraint(con, (RsAdapter2D)adapter, (RsDimension)dim, value);
870}
871
872static void
873nAdapter2DData_i(JNIEnv *_env, jobject _this, RsContext con, jint adapter, jintArray data)
874{
875    jint len = _env->GetArrayLength(data);
876    LOG_API("nAdapter2DData_i, con(%p), adapter(%p), len(%i)", con, (RsAdapter2D)adapter, len);
877    jint *ptr = _env->GetIntArrayElements(data, NULL);
878    rsAdapter2DData(con, (RsAdapter2D)adapter, ptr);
879    _env->ReleaseIntArrayElements(data, ptr, 0/*JNI_ABORT*/);
880}
881
882static void
883nAdapter2DData_f(JNIEnv *_env, jobject _this, RsContext con, jint adapter, jfloatArray data)
884{
885    jint len = _env->GetArrayLength(data);
886    LOG_API("nAdapter2DData_f, con(%p), adapter(%p), len(%i)", con, (RsAdapter2D)adapter, len);
887    jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
888    rsAdapter2DData(con, (RsAdapter2D)adapter, ptr);
889    _env->ReleaseFloatArrayElements(data, ptr, 0/*JNI_ABORT*/);
890}
891
892static void
893nAdapter2DSubData_i(JNIEnv *_env, jobject _this, RsContext con, jint adapter, jint xoff, jint yoff, jint w, jint h, jintArray data)
894{
895    jint len = _env->GetArrayLength(data);
896    LOG_API("nAdapter2DSubData_i, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i)",
897            con, (RsAdapter2D)adapter, xoff, yoff, w, h, len);
898    jint *ptr = _env->GetIntArrayElements(data, NULL);
899    rsAdapter2DSubData(con, (RsAdapter2D)adapter, xoff, yoff, w, h, ptr);
900    _env->ReleaseIntArrayElements(data, ptr, 0/*JNI_ABORT*/);
901}
902
903static void
904nAdapter2DSubData_f(JNIEnv *_env, jobject _this, RsContext con, jint adapter, jint xoff, jint yoff, jint w, jint h, jfloatArray data)
905{
906    jint len = _env->GetArrayLength(data);
907    LOG_API("nAdapter2DSubData_f, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i)",
908            con, (RsAdapter2D)adapter, xoff, yoff, w, h, len);
909    jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
910    rsAdapter2DSubData(con, (RsAdapter1D)adapter, xoff, yoff, w, h, ptr);
911    _env->ReleaseFloatArrayElements(data, ptr, 0/*JNI_ABORT*/);
912}
913
914static jint
915nAdapter2DCreate(JNIEnv *_env, jobject _this, RsContext con)
916{
917    LOG_API("nAdapter2DCreate, con(%p)", con);
918    return (jint)rsAdapter2DCreate(con);
919}
920
921// -----------------------------------
922
923static void
924nScriptBindAllocation(JNIEnv *_env, jobject _this, RsContext con, jint script, jint alloc, jint slot)
925{
926    LOG_API("nScriptBindAllocation, con(%p), script(%p), alloc(%p), slot(%i)", con, (RsScript)script, (RsAllocation)alloc, slot);
927    rsScriptBindAllocation(con, (RsScript)script, (RsAllocation)alloc, slot);
928}
929
930static void
931nScriptSetVarI(JNIEnv *_env, jobject _this, RsContext con, jint script, jint slot, jint val)
932{
933    LOG_API("nScriptSetVarI, con(%p), s(%p), slot(%i), val(%i), b(%f), a(%f)", con, (void *)script, slot, val);
934    rsScriptSetVarI(con, (RsScript)script, slot, val);
935}
936
937static void
938nScriptSetVarF(JNIEnv *_env, jobject _this, RsContext con, jint script, jint slot, float val)
939{
940    LOG_API("nScriptSetVarI, con(%p), s(%p), slot(%i), val(%i), b(%f), a(%f)", con, (void *)script, slot, val);
941    rsScriptSetVarF(con, (RsScript)script, slot, val);
942}
943
944static void
945nScriptSetVarV(JNIEnv *_env, jobject _this, RsContext con, jint script, jint slot, jbyteArray data)
946{
947    LOG_API("nScriptSetVarV, con(%p), s(%p), slot(%i)", con, (void *)script, slot);
948    jint len = _env->GetArrayLength(data);
949    jbyte *ptr = _env->GetByteArrayElements(data, NULL);
950    rsScriptSetVarV(con, (RsScript)script, slot, ptr, len);
951    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
952}
953
954
955static void
956nScriptSetTimeZone(JNIEnv *_env, jobject _this, RsContext con, jint script, jbyteArray timeZone)
957{
958    LOG_API("nScriptCSetTimeZone, con(%p), s(%p), timeZone(%s)", con, (void *)script, (const char *)timeZone);
959
960    jint length = _env->GetArrayLength(timeZone);
961    jbyte* timeZone_ptr;
962    timeZone_ptr = (jbyte *) _env->GetPrimitiveArrayCritical(timeZone, (jboolean *)0);
963
964    rsScriptSetTimeZone(con, (RsScript)script, (const char *)timeZone_ptr, length);
965
966    if (timeZone_ptr) {
967        _env->ReleasePrimitiveArrayCritical(timeZone, timeZone_ptr, 0);
968    }
969}
970
971static void
972nScriptInvoke(JNIEnv *_env, jobject _this, RsContext con, jint obj, jint slot)
973{
974    LOG_API("nScriptInvoke, con(%p), script(%p)", con, (void *)obj);
975    rsScriptInvoke(con, (RsScript)obj, slot);
976}
977
978static void
979nScriptInvokeV(JNIEnv *_env, jobject _this, RsContext con, jint script, jint slot, jbyteArray data)
980{
981    LOG_API("nScriptInvokeV, con(%p), s(%p), slot(%i)", con, (void *)script, slot);
982    jint len = _env->GetArrayLength(data);
983    jbyte *ptr = _env->GetByteArrayElements(data, NULL);
984    rsScriptInvokeV(con, (RsScript)script, slot, ptr, len);
985    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
986}
987
988
989// -----------------------------------
990
991static void
992nScriptCBegin(JNIEnv *_env, jobject _this, RsContext con)
993{
994    LOG_API("nScriptCBegin, con(%p)", con);
995    rsScriptCBegin(con);
996}
997
998static void
999nScriptCSetScript(JNIEnv *_env, jobject _this, RsContext con, jbyteArray scriptRef,
1000                  jint offset, jint length)
1001{
1002    LOG_API("!!! nScriptCSetScript, con(%p)", con);
1003    jint _exception = 0;
1004    jint remaining;
1005    jbyte* script_base = 0;
1006    jbyte* script_ptr;
1007    if (!scriptRef) {
1008        _exception = 1;
1009        //_env->ThrowNew(IAEClass, "script == null");
1010        goto exit;
1011    }
1012    if (offset < 0) {
1013        _exception = 1;
1014        //_env->ThrowNew(IAEClass, "offset < 0");
1015        goto exit;
1016    }
1017    if (length < 0) {
1018        _exception = 1;
1019        //_env->ThrowNew(IAEClass, "length < 0");
1020        goto exit;
1021    }
1022    remaining = _env->GetArrayLength(scriptRef) - offset;
1023    if (remaining < length) {
1024        _exception = 1;
1025        //_env->ThrowNew(IAEClass, "length > script.length - offset");
1026        goto exit;
1027    }
1028    script_base = (jbyte *)
1029        _env->GetPrimitiveArrayCritical(scriptRef, (jboolean *)0);
1030    script_ptr = script_base + offset;
1031
1032    rsScriptCSetText(con, (const char *)script_ptr, length);
1033
1034exit:
1035    if (script_base) {
1036        _env->ReleasePrimitiveArrayCritical(scriptRef, script_base,
1037                _exception ? JNI_ABORT: 0);
1038    }
1039}
1040
1041static jint
1042nScriptCCreate(JNIEnv *_env, jobject _this, RsContext con)
1043{
1044    LOG_API("nScriptCCreate, con(%p)", con);
1045    return (jint)rsScriptCCreate(con);
1046}
1047
1048// ---------------------------------------------------------------------------
1049
1050static void
1051nProgramStoreBegin(JNIEnv *_env, jobject _this, RsContext con, jint in, jint out)
1052{
1053    LOG_API("nProgramStoreBegin, con(%p), in(%p), out(%p)", con, (RsElement)in, (RsElement)out);
1054    rsProgramStoreBegin(con, (RsElement)in, (RsElement)out);
1055}
1056
1057static void
1058nProgramStoreDepthFunc(JNIEnv *_env, jobject _this, RsContext con, jint func)
1059{
1060    LOG_API("nProgramStoreDepthFunc, con(%p), func(%i)", con, func);
1061    rsProgramStoreDepthFunc(con, (RsDepthFunc)func);
1062}
1063
1064static void
1065nProgramStoreDepthMask(JNIEnv *_env, jobject _this, RsContext con, jboolean enable)
1066{
1067    LOG_API("nProgramStoreDepthMask, con(%p), enable(%i)", con, enable);
1068    rsProgramStoreDepthMask(con, enable);
1069}
1070
1071static void
1072nProgramStoreColorMask(JNIEnv *_env, jobject _this, RsContext con, jboolean r, jboolean g, jboolean b, jboolean a)
1073{
1074    LOG_API("nProgramStoreColorMask, con(%p), r(%i), g(%i), b(%i), a(%i)", con, r, g, b, a);
1075    rsProgramStoreColorMask(con, r, g, b, a);
1076}
1077
1078static void
1079nProgramStoreBlendFunc(JNIEnv *_env, jobject _this, RsContext con, int src, int dst)
1080{
1081    LOG_API("nProgramStoreBlendFunc, con(%p), src(%i), dst(%i)", con, src, dst);
1082    rsProgramStoreBlendFunc(con, (RsBlendSrcFunc)src, (RsBlendDstFunc)dst);
1083}
1084
1085static void
1086nProgramStoreDither(JNIEnv *_env, jobject _this, RsContext con, jboolean enable)
1087{
1088    LOG_API("nProgramStoreDither, con(%p), enable(%i)", con, enable);
1089    rsProgramStoreDither(con, enable);
1090}
1091
1092static jint
1093nProgramStoreCreate(JNIEnv *_env, jobject _this, RsContext con)
1094{
1095    LOG_API("nProgramStoreCreate, con(%p)", con);
1096    return (jint)rsProgramStoreCreate(con);
1097}
1098
1099// ---------------------------------------------------------------------------
1100
1101static void
1102nProgramBindConstants(JNIEnv *_env, jobject _this, RsContext con, jint vpv, jint slot, jint a)
1103{
1104    LOG_API("nProgramBindConstants, con(%p), vpf(%p), sloat(%i), a(%p)", con, (RsProgramVertex)vpv, slot, (RsAllocation)a);
1105    rsProgramBindConstants(con, (RsProgram)vpv, slot, (RsAllocation)a);
1106}
1107
1108static void
1109nProgramBindTexture(JNIEnv *_env, jobject _this, RsContext con, jint vpf, jint slot, jint a)
1110{
1111    LOG_API("nProgramBindTexture, con(%p), vpf(%p), slot(%i), a(%p)", con, (RsProgramFragment)vpf, slot, (RsAllocation)a);
1112    rsProgramBindTexture(con, (RsProgramFragment)vpf, slot, (RsAllocation)a);
1113}
1114
1115static void
1116nProgramBindSampler(JNIEnv *_env, jobject _this, RsContext con, jint vpf, jint slot, jint a)
1117{
1118    LOG_API("nProgramBindSampler, con(%p), vpf(%p), slot(%i), a(%p)", con, (RsProgramFragment)vpf, slot, (RsSampler)a);
1119    rsProgramBindSampler(con, (RsProgramFragment)vpf, slot, (RsSampler)a);
1120}
1121
1122// ---------------------------------------------------------------------------
1123
1124static jint
1125nProgramFragmentCreate(JNIEnv *_env, jobject _this, RsContext con, jintArray params)
1126{
1127    jint *paramPtr = _env->GetIntArrayElements(params, NULL);
1128    jint paramLen = _env->GetArrayLength(params);
1129
1130    LOG_API("nProgramFragmentCreate, con(%p), paramLen(%i)", con, paramLen);
1131
1132    jint ret = (jint)rsProgramFragmentCreate(con, (uint32_t *)paramPtr, paramLen);
1133    _env->ReleaseIntArrayElements(params, paramPtr, JNI_ABORT);
1134    return ret;
1135}
1136
1137static jint
1138nProgramFragmentCreate2(JNIEnv *_env, jobject _this, RsContext con, jstring shader, jintArray params)
1139{
1140    const char* shaderUTF = _env->GetStringUTFChars(shader, NULL);
1141    jint shaderLen = _env->GetStringUTFLength(shader);
1142    jint *paramPtr = _env->GetIntArrayElements(params, NULL);
1143    jint paramLen = _env->GetArrayLength(params);
1144
1145    LOG_API("nProgramFragmentCreate2, con(%p), shaderLen(%i), paramLen(%i)", con, shaderLen, paramLen);
1146
1147    jint ret = (jint)rsProgramFragmentCreate2(con, shaderUTF, shaderLen, (uint32_t *)paramPtr, paramLen);
1148    _env->ReleaseStringUTFChars(shader, shaderUTF);
1149    _env->ReleaseIntArrayElements(params, paramPtr, JNI_ABORT);
1150    return ret;
1151}
1152
1153
1154// ---------------------------------------------------------------------------
1155
1156static jint
1157nProgramVertexCreate(JNIEnv *_env, jobject _this, RsContext con, jboolean texMat)
1158{
1159    LOG_API("nProgramVertexCreate, con(%p), texMat(%i)", con, texMat);
1160    return (jint)rsProgramVertexCreate(con, texMat);
1161}
1162
1163static jint
1164nProgramVertexCreate2(JNIEnv *_env, jobject _this, RsContext con, jstring shader, jintArray params)
1165{
1166    const char* shaderUTF = _env->GetStringUTFChars(shader, NULL);
1167    jint shaderLen = _env->GetStringUTFLength(shader);
1168    jint *paramPtr = _env->GetIntArrayElements(params, NULL);
1169    jint paramLen = _env->GetArrayLength(params);
1170
1171    LOG_API("nProgramVertexCreate2, con(%p), shaderLen(%i), paramLen(%i)", con, shaderLen, paramLen);
1172
1173    jint ret = (jint)rsProgramVertexCreate2(con, shaderUTF, shaderLen, (uint32_t *)paramPtr, paramLen);
1174    _env->ReleaseStringUTFChars(shader, shaderUTF);
1175    _env->ReleaseIntArrayElements(params, paramPtr, JNI_ABORT);
1176    return ret;
1177}
1178
1179// ---------------------------------------------------------------------------
1180
1181static jint
1182nProgramRasterCreate(JNIEnv *_env, jobject _this, RsContext con, jboolean pointSmooth, jboolean lineSmooth, jboolean pointSprite)
1183{
1184    LOG_API("nProgramRasterCreate, con(%p), pointSmooth(%i), lineSmooth(%i), pointSprite(%i)",
1185            con, pointSmooth, lineSmooth, pointSprite);
1186    return (jint)rsProgramRasterCreate(con, pointSmooth, lineSmooth, pointSprite);
1187}
1188
1189static void
1190nProgramRasterSetLineWidth(JNIEnv *_env, jobject _this, RsContext con, jint vpr, jfloat v)
1191{
1192    LOG_API("nProgramRasterSetLineWidth, con(%p), vpf(%p), value(%f)", con, (RsProgramRaster)vpr, v);
1193    rsProgramRasterSetLineWidth(con, (RsProgramRaster)vpr, v);
1194}
1195
1196static void
1197nProgramRasterSetCullMode(JNIEnv *_env, jobject _this, RsContext con, jint vpr, jint v)
1198{
1199    LOG_API("nProgramRasterSetCullMode, con(%p), vpf(%p), value(%i)", con, (RsProgramRaster)vpr, v);
1200    rsProgramRasterSetCullMode(con, (RsProgramRaster)vpr, (RsCullMode)v);
1201}
1202
1203
1204// ---------------------------------------------------------------------------
1205
1206static void
1207nContextBindRootScript(JNIEnv *_env, jobject _this, RsContext con, jint script)
1208{
1209    LOG_API("nContextBindRootScript, con(%p), script(%p)", con, (RsScript)script);
1210    rsContextBindRootScript(con, (RsScript)script);
1211}
1212
1213static void
1214nContextBindProgramStore(JNIEnv *_env, jobject _this, RsContext con, jint pfs)
1215{
1216    LOG_API("nContextBindProgramStore, con(%p), pfs(%p)", con, (RsProgramStore)pfs);
1217    rsContextBindProgramStore(con, (RsProgramStore)pfs);
1218}
1219
1220static void
1221nContextBindProgramFragment(JNIEnv *_env, jobject _this, RsContext con, jint pf)
1222{
1223    LOG_API("nContextBindProgramFragment, con(%p), pf(%p)", con, (RsProgramFragment)pf);
1224    rsContextBindProgramFragment(con, (RsProgramFragment)pf);
1225}
1226
1227static void
1228nContextBindProgramVertex(JNIEnv *_env, jobject _this, RsContext con, jint pf)
1229{
1230    LOG_API("nContextBindProgramVertex, con(%p), pf(%p)", con, (RsProgramVertex)pf);
1231    rsContextBindProgramVertex(con, (RsProgramVertex)pf);
1232}
1233
1234static void
1235nContextBindProgramRaster(JNIEnv *_env, jobject _this, RsContext con, jint pf)
1236{
1237    LOG_API("nContextBindProgramRaster, con(%p), pf(%p)", con, (RsProgramRaster)pf);
1238    rsContextBindProgramRaster(con, (RsProgramRaster)pf);
1239}
1240
1241
1242// ---------------------------------------------------------------------------
1243
1244static void
1245nSamplerBegin(JNIEnv *_env, jobject _this, RsContext con)
1246{
1247    LOG_API("nSamplerBegin, con(%p)", con);
1248    rsSamplerBegin(con);
1249}
1250
1251static void
1252nSamplerSet(JNIEnv *_env, jobject _this, RsContext con, jint p, jint v)
1253{
1254    LOG_API("nSamplerSet, con(%p), param(%i), value(%i)", con, p, v);
1255    rsSamplerSet(con, (RsSamplerParam)p, (RsSamplerValue)v);
1256}
1257
1258static jint
1259nSamplerCreate(JNIEnv *_env, jobject _this, RsContext con)
1260{
1261    LOG_API("nSamplerCreate, con(%p)", con);
1262    return (jint)rsSamplerCreate(con);
1263}
1264
1265// ---------------------------------------------------------------------------
1266
1267static jint
1268nMeshCreate(JNIEnv *_env, jobject _this, RsContext con, jint vtxCount, jint idxCount)
1269{
1270    LOG_API("nMeshCreate, con(%p), vtxCount(%i), idxCount(%i)", con, vtxCount, idxCount);
1271    int id = (int)rsMeshCreate(con, vtxCount, idxCount);
1272    return id;
1273}
1274
1275static void
1276nMeshBindVertex(JNIEnv *_env, jobject _this, RsContext con, jint mesh, jint alloc, jint slot)
1277{
1278    LOG_API("nMeshBindVertex, con(%p), Mesh(%p), Alloc(%p), slot(%i)", con, (RsMesh)mesh, (RsAllocation)alloc, slot);
1279    rsMeshBindVertex(con, (RsMesh)mesh, (RsAllocation)alloc, slot);
1280}
1281
1282static void
1283nMeshBindIndex(JNIEnv *_env, jobject _this, RsContext con, jint mesh, jint alloc, jint primID, jint slot)
1284{
1285    LOG_API("nMeshBindIndex, con(%p), Mesh(%p), Alloc(%p)", con, (RsMesh)mesh, (RsAllocation)alloc);
1286    rsMeshBindIndex(con, (RsMesh)mesh, (RsAllocation)alloc, primID, slot);
1287}
1288
1289static jint
1290nMeshGetVertexBufferCount(JNIEnv *_env, jobject _this, RsContext con, jint mesh)
1291{
1292    LOG_API("nMeshGetVertexBufferCount, con(%p), Mesh(%p)", con, (RsMesh)mesh);
1293    jint vtxCount = 0;
1294    rsMeshGetVertexBufferCount(con, (RsMesh)mesh, &vtxCount);
1295    return vtxCount;
1296}
1297
1298static jint
1299nMeshGetIndexCount(JNIEnv *_env, jobject _this, RsContext con, jint mesh)
1300{
1301    LOG_API("nMeshGetIndexCount, con(%p), Mesh(%p)", con, (RsMesh)mesh);
1302    jint idxCount = 0;
1303    rsMeshGetIndexCount(con, (RsMesh)mesh, &idxCount);
1304    return idxCount;
1305}
1306
1307static void
1308nMeshGetVertices(JNIEnv *_env, jobject _this, RsContext con, jint mesh, jintArray _ids, int numVtxIDs)
1309{
1310    LOG_API("nMeshGetVertices, con(%p), Mesh(%p)", con, (RsMesh)mesh);
1311
1312    RsAllocation *allocs = (RsAllocation*)malloc((uint32_t)numVtxIDs * sizeof(RsAllocation));
1313    rsMeshGetVertices(con, (RsMesh)mesh, allocs, (uint32_t)numVtxIDs);
1314
1315    for(jint i = 0; i < numVtxIDs; i ++) {
1316        _env->SetIntArrayRegion(_ids, i, 1, (const jint*)&allocs[i]);
1317    }
1318
1319    free(allocs);
1320}
1321
1322static void
1323nMeshGetIndices(JNIEnv *_env, jobject _this, RsContext con, jint mesh, jintArray _idxIds, jintArray _primitives, int numIndices)
1324{
1325    LOG_API("nMeshGetVertices, con(%p), Mesh(%p)", con, (RsMesh)mesh);
1326
1327    RsAllocation *allocs = (RsAllocation*)malloc((uint32_t)numIndices * sizeof(RsAllocation));
1328    uint32_t *prims= (uint32_t*)malloc((uint32_t)numIndices * sizeof(uint32_t));
1329
1330    rsMeshGetIndices(con, (RsMesh)mesh, allocs, prims, (uint32_t)numIndices);
1331
1332    for(jint i = 0; i < numIndices; i ++) {
1333        _env->SetIntArrayRegion(_idxIds, i, 1, (const jint*)&allocs[i]);
1334        _env->SetIntArrayRegion(_primitives, i, 1, (const jint*)&prims[i]);
1335    }
1336
1337    free(allocs);
1338    free(prims);
1339}
1340
1341// ---------------------------------------------------------------------------
1342
1343
1344static const char *classPathName = "android/renderscript/RenderScript";
1345
1346static JNINativeMethod methods[] = {
1347{"_nInit",                         "()V",                                  (void*)_nInit },
1348{"nInitElements",                  "(IIII)V",                              (void*)nInitElements },
1349
1350{"nDeviceCreate",                  "()I",                                  (void*)nDeviceCreate },
1351{"nDeviceDestroy",                 "(I)V",                                 (void*)nDeviceDestroy },
1352{"nDeviceSetConfig",               "(III)V",                               (void*)nDeviceSetConfig },
1353{"nContextGetMessage",             "(I[IZ)I",                               (void*)nContextGetMessage },
1354{"nContextInitToClient",           "(I)V",                                  (void*)nContextInitToClient },
1355{"nContextDeinitToClient",         "(I)V",                                  (void*)nContextDeinitToClient },
1356
1357
1358// All methods below are thread protected in java.
1359{"rsnContextCreate",                 "(II)I",                                (void*)nContextCreate },
1360{"rsnContextCreateGL",               "(IIZ)I",                               (void*)nContextCreateGL },
1361{"rsnContextFinish",                 "(I)V",                                  (void*)nContextFinish },
1362{"rsnContextSetPriority",            "(II)V",                                 (void*)nContextSetPriority },
1363{"rsnContextSetSurface",             "(IIILandroid/view/Surface;)V",          (void*)nContextSetSurface },
1364{"rsnContextDestroy",                "(I)V",                                 (void*)nContextDestroy },
1365{"rsnContextDump",                   "(II)V",                                 (void*)nContextDump },
1366{"rsnContextPause",                  "(I)V",                                  (void*)nContextPause },
1367{"rsnContextResume",                 "(I)V",                                  (void*)nContextResume },
1368{"rsnAssignName",                    "(II[B)V",                               (void*)nAssignName },
1369{"rsnGetName",                       "(II)Ljava/lang/String;",               (void*)nGetName },
1370{"rsnObjDestroy",                    "(II)V",                                 (void*)nObjDestroy },
1371
1372{"rsnFileOpen",                      "(I[B)I",                                (void*)nFileOpen },
1373{"rsnFileA3DCreateFromAssetStream",  "(II)I",                                 (void*)nFileA3DCreateFromAssetStream },
1374{"rsnFileA3DGetNumIndexEntries",     "(II)I",                                 (void*)nFileA3DGetNumIndexEntries },
1375{"rsnFileA3DGetIndexEntries",        "(III[I[Ljava/lang/String;)V",          (void*)nFileA3DGetIndexEntries },
1376{"rsnFileA3DGetEntryByIndex",        "(III)I",                                (void*)nFileA3DGetEntryByIndex },
1377
1378{"rsnFontCreateFromFile",            "(ILjava/lang/String;II)I",             (void*)nFontCreateFromFile },
1379
1380{"rsnElementCreate",                 "(IIIZI)I",                              (void*)nElementCreate },
1381{"rsnElementCreate2",                "(I[I[Ljava/lang/String;)I",             (void*)nElementCreate2 },
1382{"rsnElementGetNativeData",          "(II[I)V",                               (void*)nElementGetNativeData },
1383{"rsnElementGetSubElements",         "(II[I[Ljava/lang/String;)V",           (void*)nElementGetSubElements },
1384
1385{"rsnTypeBegin",                     "(II)V",                                 (void*)nTypeBegin },
1386{"rsnTypeAdd",                       "(III)V",                                (void*)nTypeAdd },
1387{"rsnTypeCreate",                    "(I)I",                                  (void*)nTypeCreate },
1388{"rsnTypeFinalDestroy",              "(ILandroid/renderscript/Type;)V",       (void*)nTypeFinalDestroy },
1389{"rsnTypeSetupFields",               "(ILandroid/renderscript/Type;[I[I[Ljava/lang/reflect/Field;)V", (void*)nTypeSetupFields },
1390{"rsnTypeGetNativeData",             "(II[I)V",                                (void*)nTypeGetNativeData },
1391
1392{"rsnAllocationCreateTyped",         "(II)I",                                 (void*)nAllocationCreateTyped },
1393{"rsnAllocationCreateFromBitmap",    "(IIZLandroid/graphics/Bitmap;)I",       (void*)nAllocationCreateFromBitmap },
1394{"rsnAllocationCreateBitmapRef",     "(IILandroid/graphics/Bitmap;)I",        (void*)nAllocationCreateBitmapRef },
1395{"rsnAllocationCreateFromBitmapBoxed","(IIZLandroid/graphics/Bitmap;)I",      (void*)nAllocationCreateFromBitmapBoxed },
1396{"rsnAllocationCreateFromAssetStream","(IIZI)I",                              (void*)nAllocationCreateFromAssetStream },
1397{"rsnAllocationUploadToTexture",     "(IIZI)V",                               (void*)nAllocationUploadToTexture },
1398{"rsnAllocationUploadToBufferObject","(II)V",                                 (void*)nAllocationUploadToBufferObject },
1399{"rsnAllocationSubData1D",           "(IIII[II)V",                            (void*)nAllocationSubData1D_i },
1400{"rsnAllocationSubData1D",           "(IIII[SI)V",                            (void*)nAllocationSubData1D_s },
1401{"rsnAllocationSubData1D",           "(IIII[BI)V",                            (void*)nAllocationSubData1D_b },
1402{"rsnAllocationSubData1D",           "(IIII[FI)V",                            (void*)nAllocationSubData1D_f },
1403{"rsnAllocationSubData2D",           "(IIIIII[II)V",                          (void*)nAllocationSubData2D_i },
1404{"rsnAllocationSubData2D",           "(IIIIII[FI)V",                          (void*)nAllocationSubData2D_f },
1405{"rsnAllocationRead",                "(II[I)V",                               (void*)nAllocationRead_i },
1406{"rsnAllocationRead",                "(II[F)V",                               (void*)nAllocationRead_f },
1407{"rsnAllocationSubDataFromObject",   "(IILandroid/renderscript/Type;ILjava/lang/Object;)V",   (void*)nAllocationSubDataFromObject },
1408{"rsnAllocationSubReadFromObject",   "(IILandroid/renderscript/Type;ILjava/lang/Object;)V",   (void*)nAllocationSubReadFromObject },
1409{"rsnAllocationGetType",             "(II)I",                                 (void*)nAllocationGetType},
1410
1411{"rsnAdapter1DBindAllocation",       "(III)V",                                (void*)nAdapter1DBindAllocation },
1412{"rsnAdapter1DSetConstraint",        "(IIII)V",                               (void*)nAdapter1DSetConstraint },
1413{"rsnAdapter1DData",                 "(II[I)V",                               (void*)nAdapter1DData_i },
1414{"rsnAdapter1DData",                 "(II[F)V",                               (void*)nAdapter1DData_f },
1415{"rsnAdapter1DSubData",              "(IIII[I)V",                             (void*)nAdapter1DSubData_i },
1416{"rsnAdapter1DSubData",              "(IIII[F)V",                             (void*)nAdapter1DSubData_f },
1417{"rsnAdapter1DCreate",               "(I)I",                                  (void*)nAdapter1DCreate },
1418
1419{"rsnAdapter2DBindAllocation",       "(III)V",                                (void*)nAdapter2DBindAllocation },
1420{"rsnAdapter2DSetConstraint",        "(IIII)V",                               (void*)nAdapter2DSetConstraint },
1421{"rsnAdapter2DData",                 "(II[I)V",                               (void*)nAdapter2DData_i },
1422{"rsnAdapter2DData",                 "(II[F)V",                               (void*)nAdapter2DData_f },
1423{"rsnAdapter2DSubData",              "(IIIIII[I)V",                           (void*)nAdapter2DSubData_i },
1424{"rsnAdapter2DSubData",              "(IIIIII[F)V",                           (void*)nAdapter2DSubData_f },
1425{"rsnAdapter2DCreate",               "(I)I",                                  (void*)nAdapter2DCreate },
1426
1427{"rsnScriptBindAllocation",          "(IIII)V",                               (void*)nScriptBindAllocation },
1428{"rsnScriptSetTimeZone",             "(II[B)V",                               (void*)nScriptSetTimeZone },
1429{"rsnScriptInvoke",                  "(III)V",                                (void*)nScriptInvoke },
1430{"rsnScriptInvokeV",                 "(III[B)V",                              (void*)nScriptInvokeV },
1431{"rsnScriptSetVarI",                 "(IIII)V",                               (void*)nScriptSetVarI },
1432{"rsnScriptSetVarF",                 "(IIIF)V",                               (void*)nScriptSetVarF },
1433{"rsnScriptSetVarV",                 "(III[B)V",                              (void*)nScriptSetVarV },
1434
1435{"rsnScriptCBegin",                  "(I)V",                                  (void*)nScriptCBegin },
1436{"rsnScriptCSetScript",              "(I[BII)V",                              (void*)nScriptCSetScript },
1437{"rsnScriptCCreate",                 "(I)I",                                  (void*)nScriptCCreate },
1438
1439{"rsnProgramStoreBegin",             "(III)V",                                (void*)nProgramStoreBegin },
1440{"rsnProgramStoreDepthFunc",         "(II)V",                                 (void*)nProgramStoreDepthFunc },
1441{"rsnProgramStoreDepthMask",         "(IZ)V",                                 (void*)nProgramStoreDepthMask },
1442{"rsnProgramStoreColorMask",         "(IZZZZ)V",                              (void*)nProgramStoreColorMask },
1443{"rsnProgramStoreBlendFunc",         "(III)V",                                (void*)nProgramStoreBlendFunc },
1444{"rsnProgramStoreDither",            "(IZ)V",                                 (void*)nProgramStoreDither },
1445{"rsnProgramStoreCreate",            "(I)I",                                  (void*)nProgramStoreCreate },
1446
1447{"rsnProgramBindConstants",          "(IIII)V",                               (void*)nProgramBindConstants },
1448{"rsnProgramBindTexture",            "(IIII)V",                               (void*)nProgramBindTexture },
1449{"rsnProgramBindSampler",            "(IIII)V",                               (void*)nProgramBindSampler },
1450
1451{"rsnProgramFragmentCreate",         "(I[I)I",                                (void*)nProgramFragmentCreate },
1452{"rsnProgramFragmentCreate2",        "(ILjava/lang/String;[I)I",              (void*)nProgramFragmentCreate2 },
1453
1454{"rsnProgramRasterCreate",           "(IZZZ)I",                             (void*)nProgramRasterCreate },
1455{"rsnProgramRasterSetLineWidth",     "(IIF)V",                                (void*)nProgramRasterSetLineWidth },
1456{"rsnProgramRasterSetCullMode",      "(III)V",                                (void*)nProgramRasterSetCullMode },
1457
1458{"rsnProgramVertexCreate",           "(IZ)I",                                 (void*)nProgramVertexCreate },
1459{"rsnProgramVertexCreate2",          "(ILjava/lang/String;[I)I",              (void*)nProgramVertexCreate2 },
1460
1461{"rsnContextBindRootScript",         "(II)V",                                 (void*)nContextBindRootScript },
1462{"rsnContextBindProgramStore",       "(II)V",                                (void*)nContextBindProgramStore },
1463{"rsnContextBindProgramFragment",    "(II)V",                                 (void*)nContextBindProgramFragment },
1464{"rsnContextBindProgramVertex",      "(II)V",                                 (void*)nContextBindProgramVertex },
1465{"rsnContextBindProgramRaster",      "(II)V",                                 (void*)nContextBindProgramRaster },
1466
1467{"rsnSamplerBegin",                  "(I)V",                                  (void*)nSamplerBegin },
1468{"rsnSamplerSet",                    "(III)V",                                (void*)nSamplerSet },
1469{"rsnSamplerCreate",                 "(I)I",                                  (void*)nSamplerCreate },
1470
1471{"rsnMeshCreate",                    "(III)I",                                (void*)nMeshCreate },
1472{"rsnMeshBindVertex",                "(IIII)V",                               (void*)nMeshBindVertex },
1473{"rsnMeshBindIndex",                 "(IIIII)V",                              (void*)nMeshBindIndex },
1474
1475{"rsnMeshGetVertexBufferCount",      "(II)I",                                 (void*)nMeshGetVertexBufferCount },
1476{"rsnMeshGetIndexCount",             "(II)I",                                 (void*)nMeshGetIndexCount },
1477{"rsnMeshGetVertices",               "(II[II)V",                             (void*)nMeshGetVertices },
1478{"rsnMeshGetIndices",                "(II[I[II)V",                            (void*)nMeshGetIndices },
1479
1480};
1481
1482static int registerFuncs(JNIEnv *_env)
1483{
1484    return android::AndroidRuntime::registerNativeMethods(
1485            _env, classPathName, methods, NELEM(methods));
1486}
1487
1488// ---------------------------------------------------------------------------
1489
1490jint JNI_OnLoad(JavaVM* vm, void* reserved)
1491{
1492    JNIEnv* env = NULL;
1493    jint result = -1;
1494
1495    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
1496        LOGE("ERROR: GetEnv failed\n");
1497        goto bail;
1498    }
1499    assert(env != NULL);
1500
1501    if (registerFuncs(env) < 0) {
1502        LOGE("ERROR: MediaPlayer native registration failed\n");
1503        goto bail;
1504    }
1505
1506    /* success -- return valid version number */
1507    result = JNI_VERSION_1_4;
1508
1509bail:
1510    return result;
1511}
1512
1513