Home | History | Annotate | Download | only in jni
      1 /*
      2 **
      3 ** Copyright 2009, The Android Open Source Project
      4 **
      5 ** Licensed under the Apache License, Version 2.0 (the "License");
      6 ** you may not use this file except in compliance with the License.
      7 ** You may obtain a copy of the License at
      8 **
      9 **     http://www.apache.org/licenses/LICENSE-2.0
     10 **
     11 ** Unless required by applicable law or agreed to in writing, software
     12 ** distributed under the License is distributed on an "AS IS" BASIS,
     13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 ** See the License for the specific language governing permissions and
     15 ** limitations under the License.
     16 */
     17 
     18 // This source file is automatically generated
     19 
     20 #pragma GCC diagnostic ignored "-Wunused-variable"
     21 #pragma GCC diagnostic ignored "-Wunused-function"
     22 
     23 #include <GLES/gl.h>
     24 #include <GLES/glext.h>
     25 
     26 #include <jni.h>
     27 #include <nativehelper/JNIHelp.h>
     28 #include <android_runtime/AndroidRuntime.h>
     29 #include <utils/misc.h>
     30 #include <assert.h>
     31 
     32 static int initialized = 0;
     33 
     34 static jclass nioAccessClass;
     35 static jclass bufferClass;
     36 static jmethodID getBasePointerID;
     37 static jmethodID getBaseArrayID;
     38 static jmethodID getBaseArrayOffsetID;
     39 static jfieldID positionID;
     40 static jfieldID limitID;
     41 static jfieldID elementSizeShiftID;
     42 
     43 
     44 /* special calls implemented in Android's GLES wrapper used to more
     45  * efficiently bound-check passed arrays */
     46 extern "C" {
     47 #ifdef GL_VERSION_ES_CM_1_1
     48 GL_API void GL_APIENTRY glColorPointerBounds(GLint size, GLenum type, GLsizei stride,
     49         const GLvoid *ptr, GLsizei count);
     50 GL_API void GL_APIENTRY glNormalPointerBounds(GLenum type, GLsizei stride,
     51         const GLvoid *pointer, GLsizei count);
     52 GL_API void GL_APIENTRY glTexCoordPointerBounds(GLint size, GLenum type,
     53         GLsizei stride, const GLvoid *pointer, GLsizei count);
     54 GL_API void GL_APIENTRY glVertexPointerBounds(GLint size, GLenum type,
     55         GLsizei stride, const GLvoid *pointer, GLsizei count);
     56 GL_API void GL_APIENTRY glPointSizePointerOESBounds(GLenum type,
     57         GLsizei stride, const GLvoid *pointer, GLsizei count);
     58 GL_API void GL_APIENTRY glMatrixIndexPointerOESBounds(GLint size, GLenum type,
     59         GLsizei stride, const GLvoid *pointer, GLsizei count);
     60 GL_API void GL_APIENTRY glWeightPointerOESBounds(GLint size, GLenum type,
     61         GLsizei stride, const GLvoid *pointer, GLsizei count);
     62 #endif
     63 #ifdef GL_ES_VERSION_2_0
     64 static void glVertexAttribPointerBounds(GLuint indx, GLint size, GLenum type,
     65         GLboolean normalized, GLsizei stride, const GLvoid *pointer, GLsizei count) {
     66     glVertexAttribPointer(indx, size, type, normalized, stride, pointer);
     67 }
     68 #endif
     69 #ifdef GL_ES_VERSION_3_0
     70 static void glVertexAttribIPointerBounds(GLuint indx, GLint size, GLenum type,
     71         GLsizei stride, const GLvoid *pointer, GLsizei count) {
     72     glVertexAttribIPointer(indx, size, type, stride, pointer);
     73 }
     74 #endif
     75 }
     76 
     77 /* Cache method IDs each time the class is loaded. */
     78 
     79 static void
     80 nativeClassInit(JNIEnv *_env, jclass glImplClass)
     81 {
     82     jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
     83     nioAccessClass = (jclass) _env->NewGlobalRef(nioAccessClassLocal);
     84 
     85     jclass bufferClassLocal = _env->FindClass("java/nio/Buffer");
     86     bufferClass = (jclass) _env->NewGlobalRef(bufferClassLocal);
     87 
     88     getBasePointerID = _env->GetStaticMethodID(nioAccessClass,
     89             "getBasePointer", "(Ljava/nio/Buffer;)J");
     90     getBaseArrayID = _env->GetStaticMethodID(nioAccessClass,
     91             "getBaseArray", "(Ljava/nio/Buffer;)Ljava/lang/Object;");
     92     getBaseArrayOffsetID = _env->GetStaticMethodID(nioAccessClass,
     93             "getBaseArrayOffset", "(Ljava/nio/Buffer;)I");
     94 
     95     positionID = _env->GetFieldID(bufferClass, "position", "I");
     96     limitID = _env->GetFieldID(bufferClass, "limit", "I");
     97     elementSizeShiftID =
     98         _env->GetFieldID(bufferClass, "_elementSizeShift", "I");
     99 }
    100 
    101 static void *
    102 getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining, jint *offset)
    103 {
    104     jint position;
    105     jint limit;
    106     jint elementSizeShift;
    107     jlong pointer;
    108 
    109     position = _env->GetIntField(buffer, positionID);
    110     limit = _env->GetIntField(buffer, limitID);
    111     elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
    112     *remaining = (limit - position) << elementSizeShift;
    113     pointer = _env->CallStaticLongMethod(nioAccessClass,
    114             getBasePointerID, buffer);
    115     if (pointer != 0L) {
    116         *array = NULL;
    117         return reinterpret_cast<void*>(pointer);
    118     }
    119 
    120     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
    121             getBaseArrayID, buffer);
    122     *offset = _env->CallStaticIntMethod(nioAccessClass,
    123             getBaseArrayOffsetID, buffer);
    124 
    125     return NULL;
    126 }
    127 
    128 class ByteArrayGetter {
    129 public:
    130     static void* Get(JNIEnv* _env, jbyteArray array, jboolean* is_copy) {
    131         return _env->GetByteArrayElements(array, is_copy);
    132     }
    133 };
    134 class BooleanArrayGetter {
    135 public:
    136     static void* Get(JNIEnv* _env, jbooleanArray array, jboolean* is_copy) {
    137         return _env->GetBooleanArrayElements(array, is_copy);
    138     }
    139 };
    140 class CharArrayGetter {
    141 public:
    142     static void* Get(JNIEnv* _env, jcharArray array, jboolean* is_copy) {
    143         return _env->GetCharArrayElements(array, is_copy);
    144     }
    145 };
    146 class ShortArrayGetter {
    147 public:
    148     static void* Get(JNIEnv* _env, jshortArray array, jboolean* is_copy) {
    149         return _env->GetShortArrayElements(array, is_copy);
    150     }
    151 };
    152 class IntArrayGetter {
    153 public:
    154     static void* Get(JNIEnv* _env, jintArray array, jboolean* is_copy) {
    155         return _env->GetIntArrayElements(array, is_copy);
    156     }
    157 };
    158 class LongArrayGetter {
    159 public:
    160     static void* Get(JNIEnv* _env, jlongArray array, jboolean* is_copy) {
    161         return _env->GetLongArrayElements(array, is_copy);
    162     }
    163 };
    164 class FloatArrayGetter {
    165 public:
    166     static void* Get(JNIEnv* _env, jfloatArray array, jboolean* is_copy) {
    167         return _env->GetFloatArrayElements(array, is_copy);
    168     }
    169 };
    170 class DoubleArrayGetter {
    171 public:
    172     static void* Get(JNIEnv* _env, jdoubleArray array, jboolean* is_copy) {
    173         return _env->GetDoubleArrayElements(array, is_copy);
    174     }
    175 };
    176 
    177 template<typename JTYPEARRAY, typename ARRAYGETTER>
    178 static void*
    179 getArrayPointer(JNIEnv *_env, JTYPEARRAY array, jboolean* is_copy) {
    180     return ARRAYGETTER::Get(_env, array, is_copy);
    181 }
    182 
    183 class ByteArrayReleaser {
    184 public:
    185     static void Release(JNIEnv* _env, jbyteArray array, jbyte* data, jboolean commit) {
    186         _env->ReleaseByteArrayElements(array, data, commit ? 0 : JNI_ABORT);
    187     }
    188 };
    189 class BooleanArrayReleaser {
    190 public:
    191     static void Release(JNIEnv* _env, jbooleanArray array, jboolean* data, jboolean commit) {
    192         _env->ReleaseBooleanArrayElements(array, data, commit ? 0 : JNI_ABORT);
    193     }
    194 };
    195 class CharArrayReleaser {
    196 public:
    197     static void Release(JNIEnv* _env, jcharArray array, jchar* data, jboolean commit) {
    198         _env->ReleaseCharArrayElements(array, data, commit ? 0 : JNI_ABORT);
    199     }
    200 };
    201 class ShortArrayReleaser {
    202 public:
    203     static void Release(JNIEnv* _env, jshortArray array, jshort* data, jboolean commit) {
    204         _env->ReleaseShortArrayElements(array, data, commit ? 0 : JNI_ABORT);
    205     }
    206 };
    207 class IntArrayReleaser {
    208 public:
    209     static void Release(JNIEnv* _env, jintArray array, jint* data, jboolean commit) {
    210         _env->ReleaseIntArrayElements(array, data, commit ? 0 : JNI_ABORT);
    211     }
    212 };
    213 class LongArrayReleaser {
    214 public:
    215     static void Release(JNIEnv* _env, jlongArray array, jlong* data, jboolean commit) {
    216         _env->ReleaseLongArrayElements(array, data, commit ? 0 : JNI_ABORT);
    217     }
    218 };
    219 class FloatArrayReleaser {
    220 public:
    221     static void Release(JNIEnv* _env, jfloatArray array, jfloat* data, jboolean commit) {
    222         _env->ReleaseFloatArrayElements(array, data, commit ? 0 : JNI_ABORT);
    223     }
    224 };
    225 class DoubleArrayReleaser {
    226 public:
    227     static void Release(JNIEnv* _env, jdoubleArray array, jdouble* data, jboolean commit) {
    228         _env->ReleaseDoubleArrayElements(array, data, commit ? 0 : JNI_ABORT);
    229     }
    230 };
    231 
    232 template<typename JTYPEARRAY, typename NTYPEARRAY, typename ARRAYRELEASER>
    233 static void
    234 releaseArrayPointer(JNIEnv *_env, JTYPEARRAY array, NTYPEARRAY data, jboolean commit) {
    235     ARRAYRELEASER::Release(_env, array, data, commit);
    236 }
    237 
    238 static void
    239 releasePointer(JNIEnv *_env, jarray array, void *data, jboolean commit)
    240 {
    241     _env->ReleasePrimitiveArrayCritical(array, data,
    242                        commit ? 0 : JNI_ABORT);
    243 }
    244 
    245 static void *
    246 getDirectBufferPointer(JNIEnv *_env, jobject buffer) {
    247     char* buf = (char*) _env->GetDirectBufferAddress(buffer);
    248     if (buf) {
    249         jint position = _env->GetIntField(buffer, positionID);
    250         jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
    251         buf += position << elementSizeShift;
    252     } else {
    253         jniThrowException(_env, "java/lang/IllegalArgumentException",
    254                           "Must use a native order direct Buffer");
    255     }
    256     return (void*) buf;
    257 }
    258 
    259 // --------------------------------------------------------------------------
    260 
    261 /*
    262  * returns the number of values glGet returns for a given pname.
    263  *
    264  * The code below is written such that pnames requiring only one values
    265  * are the default (and are not explicitely tested for). This makes the
    266  * checking code much shorter/readable/efficient.
    267  *
    268  * This means that unknown pnames (e.g.: extensions) will default to 1. If
    269  * that unknown pname needs more than 1 value, then the validation check
    270  * is incomplete and the app may crash if it passed the wrong number params.
    271  */
    272 static int getNeededCount(GLint pname) {
    273     int needed = 1;
    274 #ifdef GL_ES_VERSION_3_0
    275     // GLES 3.x pnames
    276     switch (pname) {
    277         case GL_MAX_VIEWPORT_DIMS:
    278             needed = 2;
    279             break;
    280 
    281         case GL_PROGRAM_BINARY_FORMATS:
    282             glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &needed);
    283             break;
    284     }
    285 #endif
    286 
    287 #ifdef GL_ES_VERSION_2_0
    288     // GLES 2.x pnames
    289     switch (pname) {
    290         case GL_ALIASED_LINE_WIDTH_RANGE:
    291         case GL_ALIASED_POINT_SIZE_RANGE:
    292             needed = 2;
    293             break;
    294 
    295         case GL_BLEND_COLOR:
    296         case GL_COLOR_CLEAR_VALUE:
    297         case GL_COLOR_WRITEMASK:
    298         case GL_SCISSOR_BOX:
    299         case GL_VIEWPORT:
    300             needed = 4;
    301             break;
    302 
    303         case GL_COMPRESSED_TEXTURE_FORMATS:
    304             glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &needed);
    305             break;
    306 
    307         case GL_SHADER_BINARY_FORMATS:
    308             glGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &needed);
    309             break;
    310     }
    311 #endif
    312 
    313 #ifdef GL_VERSION_ES_CM_1_1
    314     // GLES 1.x pnames
    315     switch (pname) {
    316         case GL_ALIASED_LINE_WIDTH_RANGE:
    317         case GL_ALIASED_POINT_SIZE_RANGE:
    318         case GL_DEPTH_RANGE:
    319         case GL_SMOOTH_LINE_WIDTH_RANGE:
    320         case GL_SMOOTH_POINT_SIZE_RANGE:
    321             needed = 2;
    322             break;
    323 
    324         case GL_CURRENT_NORMAL:
    325         case GL_POINT_DISTANCE_ATTENUATION:
    326             needed = 3;
    327             break;
    328 
    329         case GL_COLOR_CLEAR_VALUE:
    330         case GL_COLOR_WRITEMASK:
    331         case GL_CURRENT_COLOR:
    332         case GL_CURRENT_TEXTURE_COORDS:
    333         case GL_FOG_COLOR:
    334         case GL_LIGHT_MODEL_AMBIENT:
    335         case GL_SCISSOR_BOX:
    336         case GL_VIEWPORT:
    337             needed = 4;
    338             break;
    339 
    340         case GL_MODELVIEW_MATRIX:
    341         case GL_PROJECTION_MATRIX:
    342         case GL_TEXTURE_MATRIX:
    343             needed = 16;
    344             break;
    345 
    346         case GL_COMPRESSED_TEXTURE_FORMATS:
    347             glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &needed);
    348             break;
    349     }
    350 #endif
    351     return needed;
    352 }
    353 
    354 template <typename JTYPEARRAY, typename ARRAYGETTER, typename NTYPEARRAY,
    355           typename ARRAYRELEASER, typename CTYPE, void GET(GLenum, CTYPE*)>
    356 static void
    357 get
    358   (JNIEnv *_env, jobject _this, jint pname, JTYPEARRAY params_ref, jint offset) {
    359     jint _exception = 0;
    360     const char * _exceptionType;
    361     const char * _exceptionMessage;
    362     CTYPE *params_base = (CTYPE *) 0;
    363     jint _remaining;
    364     CTYPE *params = (CTYPE *) 0;
    365     int _needed = 0;
    366 
    367     if (!params_ref) {
    368         _exception = 1;
    369         _exceptionType = "java/lang/IllegalArgumentException";
    370         _exceptionMessage = "params == null";
    371         goto exit;
    372     }
    373     if (offset < 0) {
    374         _exception = 1;
    375         _exceptionType = "java/lang/IllegalArgumentException";
    376         _exceptionMessage = "offset < 0";
    377         goto exit;
    378     }
    379     _remaining = _env->GetArrayLength(params_ref) - offset;
    380     _needed = getNeededCount(pname);
    381     // if we didn't find this pname, we just assume the user passed
    382     // an array of the right size -- this might happen with extensions
    383     // or if we forget an enum here.
    384     if (_remaining < _needed) {
    385         _exception = 1;
    386         _exceptionType = "java/lang/IllegalArgumentException";
    387         _exceptionMessage = "length - offset < needed";
    388         goto exit;
    389     }
    390     params_base = (CTYPE *) getArrayPointer<JTYPEARRAY, ARRAYGETTER>(
    391         _env, params_ref, (jboolean *)0);
    392     params = params_base + offset;
    393 
    394     GET(
    395         (GLenum)pname,
    396         (CTYPE *)params
    397     );
    398 
    399 exit:
    400     if (params_base) {
    401         releaseArrayPointer<JTYPEARRAY, NTYPEARRAY, ARRAYRELEASER>(
    402             _env, params_ref, params_base, !_exception);
    403     }
    404     if (_exception) {
    405         jniThrowException(_env, _exceptionType, _exceptionMessage);
    406     }
    407 }
    408 
    409 
    410 template <typename CTYPE, typename JTYPEARRAY, typename ARRAYGETTER, typename NTYPEARRAY,
    411           typename ARRAYRELEASER, void GET(GLenum, CTYPE*)>
    412 static void
    413 getarray
    414   (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
    415     jint _exception = 0;
    416     const char * _exceptionType;
    417     const char * _exceptionMessage;
    418     JTYPEARRAY _array = (JTYPEARRAY) 0;
    419     jint _bufferOffset = (jint) 0;
    420     jint _remaining;
    421     CTYPE *params = (CTYPE *) 0;
    422     int _needed = 0;
    423 
    424     params = (CTYPE *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
    425     _remaining /= sizeof(CTYPE);    // convert from bytes to item count
    426     _needed = getNeededCount(pname);
    427     // if we didn't find this pname, we just assume the user passed
    428     // an array of the right size -- this might happen with extensions
    429     // or if we forget an enum here.
    430     if (_needed>0 && _remaining < _needed) {
    431         _exception = 1;
    432         _exceptionType = "java/lang/IllegalArgumentException";
    433         _exceptionMessage = "remaining() < needed";
    434         goto exit;
    435     }
    436     if (params == NULL) {
    437         char * _paramsBase = (char *) getArrayPointer<JTYPEARRAY, ARRAYGETTER>(
    438             _env, _array, (jboolean *) 0);
    439         params = (CTYPE *) (_paramsBase + _bufferOffset);
    440     }
    441     GET(
    442         (GLenum)pname,
    443         (CTYPE *)params
    444     );
    445 
    446 exit:
    447     if (_array) {
    448         releaseArrayPointer<JTYPEARRAY, NTYPEARRAY, ARRAYRELEASER>(
    449             _env, _array, (NTYPEARRAY)params, _exception ? JNI_FALSE : JNI_TRUE);
    450     }
    451     if (_exception) {
    452         jniThrowException(_env, _exceptionType, _exceptionMessage);
    453     }
    454 }
    455 
    456 // --------------------------------------------------------------------------
    457 /* GLbitfield glQueryMatrixxOES ( GLfixed *mantissa, GLint *exponent ) */
    458 static jint
    459 android_glQueryMatrixxOES___3II_3II
    460   (JNIEnv *_env, jobject _this, jintArray mantissa_ref, jint mantissaOffset, jintArray exponent_ref, jint exponentOffset) {
    461     jint _exception = 0;
    462     const char * _exceptionType = NULL;
    463     const char * _exceptionMessage = NULL;
    464     GLbitfield _returnValue = -1;
    465     GLfixed *mantissa_base = (GLfixed *) 0;
    466     jint _mantissaRemaining;
    467     GLfixed *mantissa = (GLfixed *) 0;
    468     GLint *exponent_base = (GLint *) 0;
    469     jint _exponentRemaining;
    470     GLint *exponent = (GLint *) 0;
    471 
    472     if (!mantissa_ref) {
    473         _exception = 1;
    474         _exceptionType = "java/lang/IllegalArgumentException";
    475         _exceptionMessage = "mantissa == null";
    476         goto exit;
    477     }
    478     if (mantissaOffset < 0) {
    479         _exception = 1;
    480         _exceptionType = "java/lang/IllegalArgumentException";
    481         _exceptionMessage = "mantissaOffset < 0";
    482         goto exit;
    483     }
    484     _mantissaRemaining = _env->GetArrayLength(mantissa_ref) - mantissaOffset;
    485     if (_mantissaRemaining < 16) {
    486         _exception = 1;
    487         _exceptionType = "java/lang/IllegalArgumentException";
    488         _exceptionMessage = "length - mantissaOffset < 16 < needed";
    489         goto exit;
    490     }
    491     mantissa_base = (GLfixed *)
    492         _env->GetIntArrayElements(mantissa_ref, (jboolean *)0);
    493     mantissa = mantissa_base + mantissaOffset;
    494 
    495     if (!exponent_ref) {
    496         _exception = 1;
    497         _exceptionType = "java/lang/IllegalArgumentException";
    498         _exceptionMessage = "exponent == null";
    499         goto exit;
    500     }
    501     if (exponentOffset < 0) {
    502         _exception = 1;
    503         _exceptionType = "java/lang/IllegalArgumentException";
    504         _exceptionMessage = "exponentOffset < 0";
    505         goto exit;
    506     }
    507     _exponentRemaining = _env->GetArrayLength(exponent_ref) - exponentOffset;
    508     if (_exponentRemaining < 16) {
    509         _exception = 1;
    510         _exceptionType = "java/lang/IllegalArgumentException";
    511         _exceptionMessage = "length - exponentOffset < 16 < needed";
    512         goto exit;
    513     }
    514     exponent_base = (GLint *)
    515         _env->GetIntArrayElements(exponent_ref, (jboolean *)0);
    516     exponent = exponent_base + exponentOffset;
    517 
    518     _returnValue = glQueryMatrixxOES(
    519         (GLfixed *)mantissa,
    520         (GLint *)exponent
    521     );
    522 
    523 exit:
    524     if (exponent_base) {
    525         _env->ReleaseIntArrayElements(exponent_ref, (jint*)exponent_base,
    526             _exception ? JNI_ABORT: 0);
    527     }
    528     if (mantissa_base) {
    529         _env->ReleaseIntArrayElements(mantissa_ref, (jint*)mantissa_base,
    530             _exception ? JNI_ABORT: 0);
    531     }
    532     if (_exception) {
    533         jniThrowException(_env, _exceptionType, _exceptionMessage);
    534     }
    535     return (jint)_returnValue;
    536 }
    537 
    538 /* GLbitfield glQueryMatrixxOES ( GLfixed *mantissa, GLint *exponent ) */
    539 static jint
    540 android_glQueryMatrixxOES__Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2
    541   (JNIEnv *_env, jobject _this, jobject mantissa_buf, jobject exponent_buf) {
    542     jint _exception = 0;
    543     const char * _exceptionType = NULL;
    544     const char * _exceptionMessage = NULL;
    545     jintArray _mantissaArray = (jintArray) 0;
    546     jint _mantissaBufferOffset = (jint) 0;
    547     jintArray _exponentArray = (jintArray) 0;
    548     jint _exponentBufferOffset = (jint) 0;
    549     GLbitfield _returnValue = -1;
    550     jint _mantissaRemaining;
    551     GLfixed *mantissa = (GLfixed *) 0;
    552     jint _exponentRemaining;
    553     GLint *exponent = (GLint *) 0;
    554 
    555     if (!mantissa_buf) {
    556         _exception = 1;
    557         _exceptionType = "java/lang/IllegalArgumentException";
    558         _exceptionMessage = "mantissa == null";
    559         goto exit;
    560     }
    561     mantissa = (GLfixed *)getPointer(_env, mantissa_buf, (jarray*)&_mantissaArray, &_mantissaRemaining, &_mantissaBufferOffset);
    562     if (_mantissaRemaining < 16) {
    563         _exception = 1;
    564         _exceptionType = "java/lang/IllegalArgumentException";
    565         _exceptionMessage = "remaining() < 16 < needed";
    566         goto exit;
    567     }
    568     if (!exponent_buf) {
    569         _exception = 1;
    570         _exceptionType = "java/lang/IllegalArgumentException";
    571         _exceptionMessage = "exponent == null";
    572         goto exit;
    573     }
    574     exponent = (GLint *)getPointer(_env, exponent_buf, (jarray*)&_exponentArray, &_exponentRemaining, &_exponentBufferOffset);
    575     if (_exponentRemaining < 16) {
    576         _exception = 1;
    577         _exceptionType = "java/lang/IllegalArgumentException";
    578         _exceptionMessage = "remaining() < 16 < needed";
    579         goto exit;
    580     }
    581     if (mantissa == NULL) {
    582         char * _mantissaBase = (char *)_env->GetIntArrayElements(_mantissaArray, (jboolean *) 0);
    583         mantissa = (GLfixed *) (_mantissaBase + _mantissaBufferOffset);
    584     }
    585     if (exponent == NULL) {
    586         char * _exponentBase = (char *)_env->GetIntArrayElements(_exponentArray, (jboolean *) 0);
    587         exponent = (GLint *) (_exponentBase + _exponentBufferOffset);
    588     }
    589     _returnValue = glQueryMatrixxOES(
    590         (GLfixed *)mantissa,
    591         (GLint *)exponent
    592     );
    593 
    594 exit:
    595     if (_exponentArray) {
    596         _env->ReleaseIntArrayElements(_exponentArray, (jint*)exponent, _exception ? JNI_ABORT : 0);
    597     }
    598     if (_mantissaArray) {
    599         _env->ReleaseIntArrayElements(_mantissaArray, (jint*)mantissa, _exception ? JNI_ABORT : 0);
    600     }
    601     if (_exception) {
    602         jniThrowException(_env, _exceptionType, _exceptionMessage);
    603     }
    604     return (jint)_returnValue;
    605 }
    606 
    607 static const char *classPathName = "android/opengl/GLES10Ext";
    608 
    609 static const JNINativeMethod methods[] = {
    610 {"_nativeClassInit", "()V", (void*)nativeClassInit },
    611 {"glQueryMatrixxOES", "([II[II)I", (void *) android_glQueryMatrixxOES___3II_3II },
    612 {"glQueryMatrixxOES", "(Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;)I", (void *) android_glQueryMatrixxOES__Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2 },
    613 };
    614 
    615 int register_android_opengl_jni_GLES10Ext(JNIEnv *_env)
    616 {
    617     int err;
    618     err = android::AndroidRuntime::registerNativeMethods(_env, classPathName, methods, NELEM(methods));
    619     return err;
    620 }
    621