1391109083f683c990bdbc5ca3a5f521a9a3fc98dJesse Hall#include <jni.h>
2391109083f683c990bdbc5ca3a5f521a9a3fc98dJesse Hall#include <JNIHelp.h>
3bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian#include <android_runtime/AndroidRuntime.h>
4bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian#include <utils/misc.h>
5bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian#include <assert.h>
6bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian
7bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopianstatic int initialized = 0;
8bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian
9bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopianstatic jclass nioAccessClass;
10bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopianstatic jclass bufferClass;
11bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopianstatic jmethodID getBasePointerID;
12bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopianstatic jmethodID getBaseArrayID;
13bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopianstatic jmethodID getBaseArrayOffsetID;
14bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopianstatic jfieldID positionID;
15bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopianstatic jfieldID limitID;
16bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopianstatic jfieldID elementSizeShiftID;
17bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian
18bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian
19bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian/* special calls implemented in Android's GLES wrapper used to more
20bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian * efficiently bound-check passed arrays */
21bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopianextern "C" {
22bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian#ifdef GL_VERSION_ES_CM_1_1
23bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias AgopianGL_API void GL_APIENTRY glColorPointerBounds(GLint size, GLenum type, GLsizei stride,
24bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        const GLvoid *ptr, GLsizei count);
25bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias AgopianGL_API void GL_APIENTRY glNormalPointerBounds(GLenum type, GLsizei stride,
26bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        const GLvoid *pointer, GLsizei count);
27bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias AgopianGL_API void GL_APIENTRY glTexCoordPointerBounds(GLint size, GLenum type,
28bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        GLsizei stride, const GLvoid *pointer, GLsizei count);
29bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias AgopianGL_API void GL_APIENTRY glVertexPointerBounds(GLint size, GLenum type,
30bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        GLsizei stride, const GLvoid *pointer, GLsizei count);
31bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias AgopianGL_API void GL_APIENTRY glPointSizePointerOESBounds(GLenum type,
32bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        GLsizei stride, const GLvoid *pointer, GLsizei count);
33bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias AgopianGL_API void GL_APIENTRY glMatrixIndexPointerOESBounds(GLint size, GLenum type,
34bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        GLsizei stride, const GLvoid *pointer, GLsizei count);
35bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias AgopianGL_API void GL_APIENTRY glWeightPointerOESBounds(GLint size, GLenum type,
36bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        GLsizei stride, const GLvoid *pointer, GLsizei count);
37bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian#endif
38bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian#ifdef GL_ES_VERSION_2_0
39bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopianstatic void glVertexAttribPointerBounds(GLuint indx, GLint size, GLenum type,
40bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        GLboolean normalized, GLsizei stride, const GLvoid *pointer, GLsizei count) {
41bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    glVertexAttribPointer(indx, size, type, normalized, stride, pointer);
42bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian}
43bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian#endif
44071fc660597efdfa5ebc58b427252393e628a497Jesse Hall#ifdef GL_ES_VERSION_3_0
45071fc660597efdfa5ebc58b427252393e628a497Jesse Hallstatic void glVertexAttribIPointerBounds(GLuint indx, GLint size, GLenum type,
46071fc660597efdfa5ebc58b427252393e628a497Jesse Hall        GLsizei stride, const GLvoid *pointer, GLsizei count) {
47071fc660597efdfa5ebc58b427252393e628a497Jesse Hall    glVertexAttribIPointer(indx, size, type, stride, pointer);
48071fc660597efdfa5ebc58b427252393e628a497Jesse Hall}
49071fc660597efdfa5ebc58b427252393e628a497Jesse Hall#endif
50bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian}
51bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian
52bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian/* Cache method IDs each time the class is loaded. */
53bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian
54bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopianstatic void
55bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias AgopiannativeClassInit(JNIEnv *_env, jclass glImplClass)
56bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian{
57bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
58bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    nioAccessClass = (jclass) _env->NewGlobalRef(nioAccessClassLocal);
59bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian
60bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    jclass bufferClassLocal = _env->FindClass("java/nio/Buffer");
61bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    bufferClass = (jclass) _env->NewGlobalRef(bufferClassLocal);
62bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian
63bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    getBasePointerID = _env->GetStaticMethodID(nioAccessClass,
64bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian            "getBasePointer", "(Ljava/nio/Buffer;)J");
65bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    getBaseArrayID = _env->GetStaticMethodID(nioAccessClass,
66bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian            "getBaseArray", "(Ljava/nio/Buffer;)Ljava/lang/Object;");
67bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    getBaseArrayOffsetID = _env->GetStaticMethodID(nioAccessClass,
68bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian            "getBaseArrayOffset", "(Ljava/nio/Buffer;)I");
69bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian
70bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    positionID = _env->GetFieldID(bufferClass, "position", "I");
71bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    limitID = _env->GetFieldID(bufferClass, "limit", "I");
72bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    elementSizeShiftID =
73bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        _env->GetFieldID(bufferClass, "_elementSizeShift", "I");
74bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian}
75bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian
76bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopianstatic void *
77bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias AgopiangetPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining, jint *offset)
78bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian{
79bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    jint position;
80bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    jint limit;
81bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    jint elementSizeShift;
82bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    jlong pointer;
83bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian
84bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    position = _env->GetIntField(buffer, positionID);
85bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    limit = _env->GetIntField(buffer, limitID);
86bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
87bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    *remaining = (limit - position) << elementSizeShift;
88bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    pointer = _env->CallStaticLongMethod(nioAccessClass,
89bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian            getBasePointerID, buffer);
90bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    if (pointer != 0L) {
91bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        *array = NULL;
92d8f096114da14f9793d4cca6022ca41b70ab9daaAshok Bhat        return reinterpret_cast<void*>(pointer);
93bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    }
94bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian
95bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
96bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian            getBaseArrayID, buffer);
97bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    *offset = _env->CallStaticIntMethod(nioAccessClass,
98bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian            getBaseArrayOffsetID, buffer);
99bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian
100bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    return NULL;
101bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian}
102bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian
1034e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchiclass ByteArrayGetter {
1044e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchipublic:
1054e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    static void* Get(JNIEnv* _env, jbyteArray array, jboolean* is_copy) {
1064e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi        return _env->GetByteArrayElements(array, is_copy);
1074e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    }
1084e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi};
1094e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchiclass BooleanArrayGetter {
1104e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchipublic:
1114e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    static void* Get(JNIEnv* _env, jbooleanArray array, jboolean* is_copy) {
1124e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi        return _env->GetBooleanArrayElements(array, is_copy);
1134e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    }
1144e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi};
1154e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchiclass CharArrayGetter {
1164e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchipublic:
1174e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    static void* Get(JNIEnv* _env, jcharArray array, jboolean* is_copy) {
1184e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi        return _env->GetCharArrayElements(array, is_copy);
1194e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    }
1204e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi};
1214e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchiclass ShortArrayGetter {
1224e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchipublic:
1234e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    static void* Get(JNIEnv* _env, jshortArray array, jboolean* is_copy) {
1244e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi        return _env->GetShortArrayElements(array, is_copy);
1254e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    }
1264e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi};
1274e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchiclass IntArrayGetter {
1284e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchipublic:
1294e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    static void* Get(JNIEnv* _env, jintArray array, jboolean* is_copy) {
1304e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi        return _env->GetIntArrayElements(array, is_copy);
1314e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    }
1324e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi};
1334e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchiclass LongArrayGetter {
1344e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchipublic:
1354e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    static void* Get(JNIEnv* _env, jlongArray array, jboolean* is_copy) {
1364e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi        return _env->GetLongArrayElements(array, is_copy);
1374e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    }
1384e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi};
1394e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchiclass FloatArrayGetter {
1404e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchipublic:
1414e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    static void* Get(JNIEnv* _env, jfloatArray array, jboolean* is_copy) {
1424e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi        return _env->GetFloatArrayElements(array, is_copy);
1434e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    }
1444e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi};
1454e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchiclass DoubleArrayGetter {
1464e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchipublic:
1474e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    static void* Get(JNIEnv* _env, jdoubleArray array, jboolean* is_copy) {
1484e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi        return _env->GetDoubleArrayElements(array, is_copy);
1494e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    }
1504e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi};
1514e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi
1524e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchitemplate<typename JTYPEARRAY, typename ARRAYGETTER>
1534e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchistatic void*
1544e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi YamauchigetArrayPointer(JNIEnv *_env, JTYPEARRAY array, jboolean* is_copy) {
1554e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    return ARRAYGETTER::Get(_env, array, is_copy);
1564e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi}
1574e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi
1584e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchiclass ByteArrayReleaser {
1594e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchipublic:
1604e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    static void Release(JNIEnv* _env, jbyteArray array, jbyte* data, jboolean commit) {
1614e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi        _env->ReleaseByteArrayElements(array, data, commit ? 0 : JNI_ABORT);
1624e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    }
1634e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi};
1644e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchiclass BooleanArrayReleaser {
1654e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchipublic:
1664e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    static void Release(JNIEnv* _env, jbooleanArray array, jboolean* data, jboolean commit) {
1674e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi        _env->ReleaseBooleanArrayElements(array, data, commit ? 0 : JNI_ABORT);
1684e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    }
1694e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi};
1704e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchiclass CharArrayReleaser {
1714e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchipublic:
1724e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    static void Release(JNIEnv* _env, jcharArray array, jchar* data, jboolean commit) {
1734e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi        _env->ReleaseCharArrayElements(array, data, commit ? 0 : JNI_ABORT);
1744e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    }
1754e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi};
1764e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchiclass ShortArrayReleaser {
1774e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchipublic:
1784e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    static void Release(JNIEnv* _env, jshortArray array, jshort* data, jboolean commit) {
1794e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi        _env->ReleaseShortArrayElements(array, data, commit ? 0 : JNI_ABORT);
1804e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    }
1814e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi};
1824e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchiclass IntArrayReleaser {
1834e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchipublic:
1844e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    static void Release(JNIEnv* _env, jintArray array, jint* data, jboolean commit) {
1854e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi        _env->ReleaseIntArrayElements(array, data, commit ? 0 : JNI_ABORT);
1864e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    }
1874e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi};
1884e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchiclass LongArrayReleaser {
1894e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchipublic:
1904e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    static void Release(JNIEnv* _env, jlongArray array, jlong* data, jboolean commit) {
1914e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi        _env->ReleaseLongArrayElements(array, data, commit ? 0 : JNI_ABORT);
1924e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    }
1934e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi};
1944e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchiclass FloatArrayReleaser {
1954e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchipublic:
1964e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    static void Release(JNIEnv* _env, jfloatArray array, jfloat* data, jboolean commit) {
1974e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi        _env->ReleaseFloatArrayElements(array, data, commit ? 0 : JNI_ABORT);
1984e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    }
1994e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi};
2004e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchiclass DoubleArrayReleaser {
2014e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchipublic:
2024e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    static void Release(JNIEnv* _env, jdoubleArray array, jdouble* data, jboolean commit) {
2034e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi        _env->ReleaseDoubleArrayElements(array, data, commit ? 0 : JNI_ABORT);
2044e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    }
2054e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi};
2064e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi
2074e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchitemplate<typename JTYPEARRAY, typename NTYPEARRAY, typename ARRAYRELEASER>
2084e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchistatic void
2094e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi YamauchireleaseArrayPointer(JNIEnv *_env, JTYPEARRAY array, NTYPEARRAY data, jboolean commit) {
2104e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    ARRAYRELEASER::Release(_env, array, data, commit);
2114e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi}
2124e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi
213bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopianstatic void
214bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias AgopianreleasePointer(JNIEnv *_env, jarray array, void *data, jboolean commit)
215bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian{
216bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    _env->ReleasePrimitiveArrayCritical(array, data,
217bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian                       commit ? 0 : JNI_ABORT);
218bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian}
219bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian
220bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopianstatic void *
221bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias AgopiangetDirectBufferPointer(JNIEnv *_env, jobject buffer) {
222bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    char* buf = (char*) _env->GetDirectBufferAddress(buffer);
223bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    if (buf) {
224bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        jint position = _env->GetIntField(buffer, positionID);
225bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
226bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        buf += position << elementSizeShift;
227bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    } else {
228bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        jniThrowException(_env, "java/lang/IllegalArgumentException",
229bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian                          "Must use a native order direct Buffer");
230bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    }
231bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    return (void*) buf;
232bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian}
233bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian
234bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian// --------------------------------------------------------------------------
235bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian
236bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian/*
237bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian * returns the number of values glGet returns for a given pname.
238bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian *
239bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian * The code below is written such that pnames requiring only one values
240bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian * are the default (and are not explicitely tested for). This makes the
241bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian * checking code much shorter/readable/efficient.
242bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian *
243bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian * This means that unknown pnames (e.g.: extensions) will default to 1. If
244bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian * that unknown pname needs more than 1 value, then the validation check
245bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian * is incomplete and the app may crash if it passed the wrong number params.
246bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian */
247bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopianstatic int getNeededCount(GLint pname) {
248bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    int needed = 1;
249bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian#ifdef GL_ES_VERSION_2_0
250bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    // GLES 2.x pnames
251bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    switch (pname) {
252bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        case GL_ALIASED_LINE_WIDTH_RANGE:
253bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        case GL_ALIASED_POINT_SIZE_RANGE:
254bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian            needed = 2;
255bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian            break;
256bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian
257bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        case GL_BLEND_COLOR:
258bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        case GL_COLOR_CLEAR_VALUE:
259bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        case GL_COLOR_WRITEMASK:
260bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        case GL_SCISSOR_BOX:
261bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        case GL_VIEWPORT:
262bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian            needed = 4;
263bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian            break;
264bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian
265bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        case GL_COMPRESSED_TEXTURE_FORMATS:
266bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian            glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &needed);
267bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian            break;
268bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian
269bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        case GL_SHADER_BINARY_FORMATS:
270bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian            glGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &needed);
271bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian            break;
272bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    }
273bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian#endif
274bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian
275bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian#ifdef GL_VERSION_ES_CM_1_1
276bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    // GLES 1.x pnames
277bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    switch (pname) {
278bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        case GL_ALIASED_LINE_WIDTH_RANGE:
279bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        case GL_ALIASED_POINT_SIZE_RANGE:
280bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        case GL_DEPTH_RANGE:
281bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        case GL_SMOOTH_LINE_WIDTH_RANGE:
282bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        case GL_SMOOTH_POINT_SIZE_RANGE:
283bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian            needed = 2;
284bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian            break;
285bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian
286bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        case GL_CURRENT_NORMAL:
287bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        case GL_POINT_DISTANCE_ATTENUATION:
288bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian            needed = 3;
289bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian            break;
290bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian
291bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        case GL_COLOR_CLEAR_VALUE:
292bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        case GL_COLOR_WRITEMASK:
293bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        case GL_CURRENT_COLOR:
294bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        case GL_CURRENT_TEXTURE_COORDS:
295bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        case GL_FOG_COLOR:
296bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        case GL_LIGHT_MODEL_AMBIENT:
297bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        case GL_SCISSOR_BOX:
298bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        case GL_VIEWPORT:
299bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian            needed = 4;
300bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian            break;
301bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian
302bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        case GL_MODELVIEW_MATRIX:
303bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        case GL_PROJECTION_MATRIX:
304bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        case GL_TEXTURE_MATRIX:
305bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian            needed = 16;
306bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian            break;
307bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian
308bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        case GL_COMPRESSED_TEXTURE_FORMATS:
309bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian            glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &needed);
310bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian            break;
311bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    }
312bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian#endif
313bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    return needed;
314bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian}
315bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian
3164e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchitemplate <typename JTYPEARRAY, typename ARRAYGETTER, typename NTYPEARRAY,
3174e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi          typename ARRAYRELEASER, typename CTYPE, void GET(GLenum, CTYPE*)>
318bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopianstatic void
319bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopianget
320bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian  (JNIEnv *_env, jobject _this, jint pname, JTYPEARRAY params_ref, jint offset) {
321bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    jint _exception = 0;
322bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    const char * _exceptionType;
323bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    const char * _exceptionMessage;
324bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    CTYPE *params_base = (CTYPE *) 0;
325bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    jint _remaining;
326bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    CTYPE *params = (CTYPE *) 0;
327bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    int _needed = 0;
328bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian
329bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    if (!params_ref) {
330bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        _exception = 1;
331bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        _exceptionType = "java/lang/IllegalArgumentException";
332bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        _exceptionMessage = "params == null";
333bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        goto exit;
334bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    }
335bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    if (offset < 0) {
336bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        _exception = 1;
337bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        _exceptionType = "java/lang/IllegalArgumentException";
338bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        _exceptionMessage = "offset < 0";
339bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        goto exit;
340bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    }
341bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    _remaining = _env->GetArrayLength(params_ref) - offset;
342bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    _needed = getNeededCount(pname);
343bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    // if we didn't find this pname, we just assume the user passed
344bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    // an array of the right size -- this might happen with extensions
345bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    // or if we forget an enum here.
346bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    if (_remaining < _needed) {
347bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        _exception = 1;
348bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        _exceptionType = "java/lang/IllegalArgumentException";
349bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        _exceptionMessage = "length - offset < needed";
350bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        goto exit;
351bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    }
3524e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    params_base = (CTYPE *) getArrayPointer<JTYPEARRAY, ARRAYGETTER>(
3534e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi        _env, params_ref, (jboolean *)0);
354bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    params = params_base + offset;
355bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian
356bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    GET(
357bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        (GLenum)pname,
358bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        (CTYPE *)params
359bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    );
360bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian
361bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopianexit:
362bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    if (params_base) {
3634e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi        releaseArrayPointer<JTYPEARRAY, NTYPEARRAY, ARRAYRELEASER>(
3644e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi            _env, params_ref, params_base, !_exception);
365bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    }
366bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    if (_exception) {
367bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        jniThrowException(_env, _exceptionType, _exceptionMessage);
368bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    }
369bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian}
370bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian
371bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian
3724e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchitemplate <typename CTYPE, typename JTYPEARRAY, typename ARRAYGETTER, typename NTYPEARRAY,
3734e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi          typename ARRAYRELEASER, void GET(GLenum, CTYPE*)>
374bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopianstatic void
375bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopiangetarray
376bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian  (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
377bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    jint _exception = 0;
378bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    const char * _exceptionType;
379bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    const char * _exceptionMessage;
3804e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    JTYPEARRAY _array = (JTYPEARRAY) 0;
381bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    jint _bufferOffset = (jint) 0;
382bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    jint _remaining;
383bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    CTYPE *params = (CTYPE *) 0;
384bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    int _needed = 0;
385bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian
3864e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi    params = (CTYPE *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
38742137d2e72cebb41f70c4a306877587fd0ea8c20Andy McFadden    _remaining /= sizeof(CTYPE);    // convert from bytes to item count
388bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    _needed = getNeededCount(pname);
389bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    // if we didn't find this pname, we just assume the user passed
390bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    // an array of the right size -- this might happen with extensions
391bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    // or if we forget an enum here.
392bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    if (_needed>0 && _remaining < _needed) {
393bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        _exception = 1;
394bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        _exceptionType = "java/lang/IllegalArgumentException";
395bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        _exceptionMessage = "remaining() < needed";
396bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        goto exit;
397bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    }
398bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    if (params == NULL) {
3994e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi        char * _paramsBase = (char *) getArrayPointer<JTYPEARRAY, ARRAYGETTER>(
4004e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi            _env, _array, (jboolean *) 0);
401bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        params = (CTYPE *) (_paramsBase + _bufferOffset);
402bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    }
403bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    GET(
404bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        (GLenum)pname,
405bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        (CTYPE *)params
406bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    );
407bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian
408bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopianexit:
409bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    if (_array) {
4104e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi        releaseArrayPointer<JTYPEARRAY, NTYPEARRAY, ARRAYRELEASER>(
4114e7de461c18278a31be83e7c9074a02fbb6e9475Hiroshi Yamauchi            _env, _array, (NTYPEARRAY)params, _exception ? JNI_FALSE : JNI_TRUE);
412bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    }
413bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    if (_exception) {
414bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian        jniThrowException(_env, _exceptionType, _exceptionMessage);
415bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian    }
416bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian}
417bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian
418bf13ba5e77804ca7466acb7100cdaf7c14cc0fb7Mathias Agopian// --------------------------------------------------------------------------
419