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#include <GLES/gl.h>
21#include <GLES/glext.h>
22
23#include <jni.h>
24#include <JNIHelp.h>
25#include <android_runtime/AndroidRuntime.h>
26#include <utils/misc.h>
27#include <assert.h>
28
29static int initialized = 0;
30
31static jclass nioAccessClass;
32static jclass bufferClass;
33static jmethodID getBasePointerID;
34static jmethodID getBaseArrayID;
35static jmethodID getBaseArrayOffsetID;
36static jfieldID positionID;
37static jfieldID limitID;
38static jfieldID elementSizeShiftID;
39
40
41/* special calls implemented in Android's GLES wrapper used to more
42 * efficiently bound-check passed arrays */
43extern "C" {
44#ifdef GL_VERSION_ES_CM_1_1
45GL_API void GL_APIENTRY glColorPointerBounds(GLint size, GLenum type, GLsizei stride,
46        const GLvoid *ptr, GLsizei count);
47GL_API void GL_APIENTRY glNormalPointerBounds(GLenum type, GLsizei stride,
48        const GLvoid *pointer, GLsizei count);
49GL_API void GL_APIENTRY glTexCoordPointerBounds(GLint size, GLenum type,
50        GLsizei stride, const GLvoid *pointer, GLsizei count);
51GL_API void GL_APIENTRY glVertexPointerBounds(GLint size, GLenum type,
52        GLsizei stride, const GLvoid *pointer, GLsizei count);
53GL_API void GL_APIENTRY glPointSizePointerOESBounds(GLenum type,
54        GLsizei stride, const GLvoid *pointer, GLsizei count);
55GL_API void GL_APIENTRY glMatrixIndexPointerOESBounds(GLint size, GLenum type,
56        GLsizei stride, const GLvoid *pointer, GLsizei count);
57GL_API void GL_APIENTRY glWeightPointerOESBounds(GLint size, GLenum type,
58        GLsizei stride, const GLvoid *pointer, GLsizei count);
59#endif
60#ifdef GL_ES_VERSION_2_0
61static void glVertexAttribPointerBounds(GLuint indx, GLint size, GLenum type,
62        GLboolean normalized, GLsizei stride, const GLvoid *pointer, GLsizei count) {
63    glVertexAttribPointer(indx, size, type, normalized, stride, pointer);
64}
65#endif
66#ifdef GL_ES_VERSION_3_0
67static void glVertexAttribIPointerBounds(GLuint indx, GLint size, GLenum type,
68        GLsizei stride, const GLvoid *pointer, GLsizei count) {
69    glVertexAttribIPointer(indx, size, type, stride, pointer);
70}
71#endif
72}
73
74/* Cache method IDs each time the class is loaded. */
75
76static void
77nativeClassInit(JNIEnv *_env, jclass glImplClass)
78{
79    jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
80    nioAccessClass = (jclass) _env->NewGlobalRef(nioAccessClassLocal);
81
82    jclass bufferClassLocal = _env->FindClass("java/nio/Buffer");
83    bufferClass = (jclass) _env->NewGlobalRef(bufferClassLocal);
84
85    getBasePointerID = _env->GetStaticMethodID(nioAccessClass,
86            "getBasePointer", "(Ljava/nio/Buffer;)J");
87    getBaseArrayID = _env->GetStaticMethodID(nioAccessClass,
88            "getBaseArray", "(Ljava/nio/Buffer;)Ljava/lang/Object;");
89    getBaseArrayOffsetID = _env->GetStaticMethodID(nioAccessClass,
90            "getBaseArrayOffset", "(Ljava/nio/Buffer;)I");
91
92    positionID = _env->GetFieldID(bufferClass, "position", "I");
93    limitID = _env->GetFieldID(bufferClass, "limit", "I");
94    elementSizeShiftID =
95        _env->GetFieldID(bufferClass, "_elementSizeShift", "I");
96}
97
98static void *
99getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining, jint *offset)
100{
101    jint position;
102    jint limit;
103    jint elementSizeShift;
104    jlong pointer;
105
106    position = _env->GetIntField(buffer, positionID);
107    limit = _env->GetIntField(buffer, limitID);
108    elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
109    *remaining = (limit - position) << elementSizeShift;
110    pointer = _env->CallStaticLongMethod(nioAccessClass,
111            getBasePointerID, buffer);
112    if (pointer != 0L) {
113        *array = NULL;
114        return reinterpret_cast<void*>(pointer);
115    }
116
117    *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
118            getBaseArrayID, buffer);
119    *offset = _env->CallStaticIntMethod(nioAccessClass,
120            getBaseArrayOffsetID, buffer);
121
122    return NULL;
123}
124
125static void
126releasePointer(JNIEnv *_env, jarray array, void *data, jboolean commit)
127{
128    _env->ReleasePrimitiveArrayCritical(array, data,
129                       commit ? 0 : JNI_ABORT);
130}
131
132static void *
133getDirectBufferPointer(JNIEnv *_env, jobject buffer) {
134    char* buf = (char*) _env->GetDirectBufferAddress(buffer);
135    if (buf) {
136        jint position = _env->GetIntField(buffer, positionID);
137        jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
138        buf += position << elementSizeShift;
139    } else {
140        jniThrowException(_env, "java/lang/IllegalArgumentException",
141                          "Must use a native order direct Buffer");
142    }
143    return (void*) buf;
144}
145
146// --------------------------------------------------------------------------
147
148/*
149 * returns the number of values glGet returns for a given pname.
150 *
151 * The code below is written such that pnames requiring only one values
152 * are the default (and are not explicitely tested for). This makes the
153 * checking code much shorter/readable/efficient.
154 *
155 * This means that unknown pnames (e.g.: extensions) will default to 1. If
156 * that unknown pname needs more than 1 value, then the validation check
157 * is incomplete and the app may crash if it passed the wrong number params.
158 */
159static int getNeededCount(GLint pname) {
160    int needed = 1;
161#ifdef GL_ES_VERSION_2_0
162    // GLES 2.x pnames
163    switch (pname) {
164        case GL_ALIASED_LINE_WIDTH_RANGE:
165        case GL_ALIASED_POINT_SIZE_RANGE:
166            needed = 2;
167            break;
168
169        case GL_BLEND_COLOR:
170        case GL_COLOR_CLEAR_VALUE:
171        case GL_COLOR_WRITEMASK:
172        case GL_SCISSOR_BOX:
173        case GL_VIEWPORT:
174            needed = 4;
175            break;
176
177        case GL_COMPRESSED_TEXTURE_FORMATS:
178            glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &needed);
179            break;
180
181        case GL_SHADER_BINARY_FORMATS:
182            glGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &needed);
183            break;
184    }
185#endif
186
187#ifdef GL_VERSION_ES_CM_1_1
188    // GLES 1.x pnames
189    switch (pname) {
190        case GL_ALIASED_LINE_WIDTH_RANGE:
191        case GL_ALIASED_POINT_SIZE_RANGE:
192        case GL_DEPTH_RANGE:
193        case GL_SMOOTH_LINE_WIDTH_RANGE:
194        case GL_SMOOTH_POINT_SIZE_RANGE:
195            needed = 2;
196            break;
197
198        case GL_CURRENT_NORMAL:
199        case GL_POINT_DISTANCE_ATTENUATION:
200            needed = 3;
201            break;
202
203        case GL_COLOR_CLEAR_VALUE:
204        case GL_COLOR_WRITEMASK:
205        case GL_CURRENT_COLOR:
206        case GL_CURRENT_TEXTURE_COORDS:
207        case GL_FOG_COLOR:
208        case GL_LIGHT_MODEL_AMBIENT:
209        case GL_SCISSOR_BOX:
210        case GL_VIEWPORT:
211            needed = 4;
212            break;
213
214        case GL_MODELVIEW_MATRIX:
215        case GL_PROJECTION_MATRIX:
216        case GL_TEXTURE_MATRIX:
217            needed = 16;
218            break;
219
220        case GL_COMPRESSED_TEXTURE_FORMATS:
221            glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &needed);
222            break;
223    }
224#endif
225    return needed;
226}
227
228template <typename JTYPEARRAY, typename CTYPE, void GET(GLenum, CTYPE*)>
229static void
230get
231  (JNIEnv *_env, jobject _this, jint pname, JTYPEARRAY params_ref, jint offset) {
232    jint _exception = 0;
233    const char * _exceptionType;
234    const char * _exceptionMessage;
235    CTYPE *params_base = (CTYPE *) 0;
236    jint _remaining;
237    CTYPE *params = (CTYPE *) 0;
238    int _needed = 0;
239
240    if (!params_ref) {
241        _exception = 1;
242        _exceptionType = "java/lang/IllegalArgumentException";
243        _exceptionMessage = "params == null";
244        goto exit;
245    }
246    if (offset < 0) {
247        _exception = 1;
248        _exceptionType = "java/lang/IllegalArgumentException";
249        _exceptionMessage = "offset < 0";
250        goto exit;
251    }
252    _remaining = _env->GetArrayLength(params_ref) - offset;
253    _needed = getNeededCount(pname);
254    // if we didn't find this pname, we just assume the user passed
255    // an array of the right size -- this might happen with extensions
256    // or if we forget an enum here.
257    if (_remaining < _needed) {
258        _exception = 1;
259        _exceptionType = "java/lang/IllegalArgumentException";
260        _exceptionMessage = "length - offset < needed";
261        goto exit;
262    }
263    params_base = (CTYPE *)
264        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
265    params = params_base + offset;
266
267    GET(
268        (GLenum)pname,
269        (CTYPE *)params
270    );
271
272exit:
273    if (params_base) {
274        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
275            _exception ? JNI_ABORT: 0);
276    }
277    if (_exception) {
278        jniThrowException(_env, _exceptionType, _exceptionMessage);
279    }
280}
281
282
283template <typename CTYPE, void GET(GLenum, CTYPE*)>
284static void
285getarray
286  (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
287    jint _exception = 0;
288    const char * _exceptionType;
289    const char * _exceptionMessage;
290    jarray _array = (jarray) 0;
291    jint _bufferOffset = (jint) 0;
292    jint _remaining;
293    CTYPE *params = (CTYPE *) 0;
294    int _needed = 0;
295
296    params = (CTYPE *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
297    _remaining /= sizeof(CTYPE);    // convert from bytes to item count
298    _needed = getNeededCount(pname);
299    // if we didn't find this pname, we just assume the user passed
300    // an array of the right size -- this might happen with extensions
301    // or if we forget an enum here.
302    if (_needed>0 && _remaining < _needed) {
303        _exception = 1;
304        _exceptionType = "java/lang/IllegalArgumentException";
305        _exceptionMessage = "remaining() < needed";
306        goto exit;
307    }
308    if (params == NULL) {
309        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
310        params = (CTYPE *) (_paramsBase + _bufferOffset);
311    }
312    GET(
313        (GLenum)pname,
314        (CTYPE *)params
315    );
316
317exit:
318    if (_array) {
319        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
320    }
321    if (_exception) {
322        jniThrowException(_env, _exceptionType, _exceptionMessage);
323    }
324}
325
326// --------------------------------------------------------------------------
327/* GLbitfield glQueryMatrixxOES ( GLfixed *mantissa, GLint *exponent ) */
328static jint
329android_glQueryMatrixxOES___3II_3II
330  (JNIEnv *_env, jobject _this, jintArray mantissa_ref, jint mantissaOffset, jintArray exponent_ref, jint exponentOffset) {
331    jint _exception = 0;
332    const char * _exceptionType = NULL;
333    const char * _exceptionMessage = NULL;
334    GLbitfield _returnValue = -1;
335    GLfixed *mantissa_base = (GLfixed *) 0;
336    jint _mantissaRemaining;
337    GLfixed *mantissa = (GLfixed *) 0;
338    GLint *exponent_base = (GLint *) 0;
339    jint _exponentRemaining;
340    GLint *exponent = (GLint *) 0;
341
342    if (!mantissa_ref) {
343        _exception = 1;
344        _exceptionType = "java/lang/IllegalArgumentException";
345        _exceptionMessage = "mantissa == null";
346        goto exit;
347    }
348    if (mantissaOffset < 0) {
349        _exception = 1;
350        _exceptionType = "java/lang/IllegalArgumentException";
351        _exceptionMessage = "mantissaOffset < 0";
352        goto exit;
353    }
354    _mantissaRemaining = _env->GetArrayLength(mantissa_ref) - mantissaOffset;
355    if (_mantissaRemaining < 16) {
356        _exception = 1;
357        _exceptionType = "java/lang/IllegalArgumentException";
358        _exceptionMessage = "length - mantissaOffset < 16 < needed";
359        goto exit;
360    }
361    mantissa_base = (GLfixed *)
362        _env->GetPrimitiveArrayCritical(mantissa_ref, (jboolean *)0);
363    mantissa = mantissa_base + mantissaOffset;
364
365    if (!exponent_ref) {
366        _exception = 1;
367        _exceptionType = "java/lang/IllegalArgumentException";
368        _exceptionMessage = "exponent == null";
369        goto exit;
370    }
371    if (exponentOffset < 0) {
372        _exception = 1;
373        _exceptionType = "java/lang/IllegalArgumentException";
374        _exceptionMessage = "exponentOffset < 0";
375        goto exit;
376    }
377    _exponentRemaining = _env->GetArrayLength(exponent_ref) - exponentOffset;
378    if (_exponentRemaining < 16) {
379        _exception = 1;
380        _exceptionType = "java/lang/IllegalArgumentException";
381        _exceptionMessage = "length - exponentOffset < 16 < needed";
382        goto exit;
383    }
384    exponent_base = (GLint *)
385        _env->GetPrimitiveArrayCritical(exponent_ref, (jboolean *)0);
386    exponent = exponent_base + exponentOffset;
387
388    _returnValue = glQueryMatrixxOES(
389        (GLfixed *)mantissa,
390        (GLint *)exponent
391    );
392
393exit:
394    if (exponent_base) {
395        _env->ReleasePrimitiveArrayCritical(exponent_ref, exponent_base,
396            _exception ? JNI_ABORT: 0);
397    }
398    if (mantissa_base) {
399        _env->ReleasePrimitiveArrayCritical(mantissa_ref, mantissa_base,
400            _exception ? JNI_ABORT: 0);
401    }
402    if (_exception) {
403        jniThrowException(_env, _exceptionType, _exceptionMessage);
404    }
405    return (jint)_returnValue;
406}
407
408/* GLbitfield glQueryMatrixxOES ( GLfixed *mantissa, GLint *exponent ) */
409static jint
410android_glQueryMatrixxOES__Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2
411  (JNIEnv *_env, jobject _this, jobject mantissa_buf, jobject exponent_buf) {
412    jint _exception = 0;
413    const char * _exceptionType = NULL;
414    const char * _exceptionMessage = NULL;
415    jarray _mantissaArray = (jarray) 0;
416    jint _mantissaBufferOffset = (jint) 0;
417    jarray _exponentArray = (jarray) 0;
418    jint _exponentBufferOffset = (jint) 0;
419    GLbitfield _returnValue = -1;
420    jint _mantissaRemaining;
421    GLfixed *mantissa = (GLfixed *) 0;
422    jint _exponentRemaining;
423    GLint *exponent = (GLint *) 0;
424
425    mantissa = (GLfixed *)getPointer(_env, mantissa_buf, &_mantissaArray, &_mantissaRemaining, &_mantissaBufferOffset);
426    if (_mantissaRemaining < 16) {
427        _exception = 1;
428        _exceptionType = "java/lang/IllegalArgumentException";
429        _exceptionMessage = "remaining() < 16 < needed";
430        goto exit;
431    }
432    exponent = (GLint *)getPointer(_env, exponent_buf, &_exponentArray, &_exponentRemaining, &_exponentBufferOffset);
433    if (_exponentRemaining < 16) {
434        _exception = 1;
435        _exceptionType = "java/lang/IllegalArgumentException";
436        _exceptionMessage = "remaining() < 16 < needed";
437        goto exit;
438    }
439    if (mantissa == NULL) {
440        char * _mantissaBase = (char *)_env->GetPrimitiveArrayCritical(_mantissaArray, (jboolean *) 0);
441        mantissa = (GLfixed *) (_mantissaBase + _mantissaBufferOffset);
442    }
443    if (exponent == NULL) {
444        char * _exponentBase = (char *)_env->GetPrimitiveArrayCritical(_exponentArray, (jboolean *) 0);
445        exponent = (GLint *) (_exponentBase + _exponentBufferOffset);
446    }
447    _returnValue = glQueryMatrixxOES(
448        (GLfixed *)mantissa,
449        (GLint *)exponent
450    );
451
452exit:
453    if (_exponentArray) {
454        releasePointer(_env, _exponentArray, exponent, _exception ? JNI_FALSE : JNI_TRUE);
455    }
456    if (_mantissaArray) {
457        releasePointer(_env, _mantissaArray, mantissa, _exception ? JNI_FALSE : JNI_TRUE);
458    }
459    if (_exception) {
460        jniThrowException(_env, _exceptionType, _exceptionMessage);
461    }
462    return (jint)_returnValue;
463}
464
465static const char *classPathName = "android/opengl/GLES10Ext";
466
467static JNINativeMethod methods[] = {
468{"_nativeClassInit", "()V", (void*)nativeClassInit },
469{"glQueryMatrixxOES", "([II[II)I", (void *) android_glQueryMatrixxOES___3II_3II },
470{"glQueryMatrixxOES", "(Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;)I", (void *) android_glQueryMatrixxOES__Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2 },
471};
472
473int register_android_opengl_jni_GLES10Ext(JNIEnv *_env)
474{
475    int err;
476    err = android::AndroidRuntime::registerNativeMethods(_env, classPathName, methods, NELEM(methods));
477    return err;
478}
479