OSDN Git Service

Merge "Fix NPE with inPurgeable Bitmaps in getAllocationByteCount" into klp-dev
[android-x86/frameworks-base.git] / core / jni / android_opengl_GLES10Ext.cpp
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
29 static int initialized = 0;
30
31 static jclass nioAccessClass;
32 static jclass bufferClass;
33 static jmethodID getBasePointerID;
34 static jmethodID getBaseArrayID;
35 static jmethodID getBaseArrayOffsetID;
36 static jfieldID positionID;
37 static jfieldID limitID;
38 static jfieldID elementSizeShiftID;
39
40
41 /* special calls implemented in Android's GLES wrapper used to more
42  * efficiently bound-check passed arrays */
43 extern "C" {
44 #ifdef GL_VERSION_ES_CM_1_1
45 GL_API void GL_APIENTRY glColorPointerBounds(GLint size, GLenum type, GLsizei stride,
46         const GLvoid *ptr, GLsizei count);
47 GL_API void GL_APIENTRY glNormalPointerBounds(GLenum type, GLsizei stride,
48         const GLvoid *pointer, GLsizei count);
49 GL_API void GL_APIENTRY glTexCoordPointerBounds(GLint size, GLenum type,
50         GLsizei stride, const GLvoid *pointer, GLsizei count);
51 GL_API void GL_APIENTRY glVertexPointerBounds(GLint size, GLenum type,
52         GLsizei stride, const GLvoid *pointer, GLsizei count);
53 GL_API void GL_APIENTRY glPointSizePointerOESBounds(GLenum type,
54         GLsizei stride, const GLvoid *pointer, GLsizei count);
55 GL_API void GL_APIENTRY glMatrixIndexPointerOESBounds(GLint size, GLenum type,
56         GLsizei stride, const GLvoid *pointer, GLsizei count);
57 GL_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
61 static 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
67 static 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
76 static void
77 nativeClassInit(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
98 static void *
99 getPointer(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 (void *) (jint) 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
125 static void
126 releasePointer(JNIEnv *_env, jarray array, void *data, jboolean commit)
127 {
128     _env->ReleasePrimitiveArrayCritical(array, data,
129                        commit ? 0 : JNI_ABORT);
130 }
131
132 static void *
133 getDirectBufferPointer(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  */
159 static 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
228 template <typename JTYPEARRAY, typename CTYPE, void GET(GLenum, CTYPE*)>
229 static void
230 get
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
272 exit:
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
283 template <typename CTYPE, void GET(GLenum, CTYPE*)>
284 static void
285 getarray
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
317 exit:
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 ) */
328 static jint
329 android_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
393 exit:
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 ) */
409 static jint
410 android_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
452 exit:
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
465 static const char *classPathName = "android/opengl/GLES10Ext";
466
467 static 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
473 int 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 }