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 } 479