1 /* 2 ** 3 ** Copyright 2006, 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 #include <nativehelper/JNIHelp.h> 19 #include <android_runtime/AndroidRuntime.h> 20 #include <android_runtime/android_view_Surface.h> 21 #include <android_runtime/android_graphics_SurfaceTexture.h> 22 #include <utils/misc.h> 23 24 25 #include <EGL/egl.h> 26 #include <GLES/gl.h> 27 #include <private/EGL/display.h> 28 29 #include <gui/Surface.h> 30 #include <gui/GLConsumer.h> 31 #include <gui/Surface.h> 32 33 #include <GraphicsJNI.h> 34 #include <SkBitmap.h> 35 #include <SkPixelRef.h> 36 37 #include <ui/ANativeObjectBase.h> 38 39 namespace android { 40 41 static jclass gConfig_class; 42 43 static jmethodID gConfig_ctorID; 44 45 static jfieldID gDisplay_EGLDisplayFieldID; 46 static jfieldID gContext_EGLContextFieldID; 47 static jfieldID gSurface_EGLSurfaceFieldID; 48 static jfieldID gConfig_EGLConfigFieldID; 49 50 static inline EGLDisplay getDisplay(JNIEnv* env, jobject o) { 51 if (!o) return EGL_NO_DISPLAY; 52 return (EGLDisplay)env->GetLongField(o, gDisplay_EGLDisplayFieldID); 53 } 54 static inline EGLSurface getSurface(JNIEnv* env, jobject o) { 55 if (!o) return EGL_NO_SURFACE; 56 return (EGLSurface)env->GetLongField(o, gSurface_EGLSurfaceFieldID); 57 } 58 static inline EGLContext getContext(JNIEnv* env, jobject o) { 59 if (!o) return EGL_NO_CONTEXT; 60 return (EGLContext)env->GetLongField(o, gContext_EGLContextFieldID); 61 } 62 static inline EGLConfig getConfig(JNIEnv* env, jobject o) { 63 if (!o) return 0; 64 return (EGLConfig)env->GetLongField(o, gConfig_EGLConfigFieldID); 65 } 66 67 static inline jboolean EglBoolToJBool(EGLBoolean eglBool) { 68 return eglBool == EGL_TRUE ? JNI_TRUE : JNI_FALSE; 69 } 70 71 static void nativeClassInit(JNIEnv *_env, jclass eglImplClass) 72 { 73 jclass config_class = _env->FindClass("com/google/android/gles_jni/EGLConfigImpl"); 74 gConfig_class = (jclass) _env->NewGlobalRef(config_class); 75 gConfig_ctorID = _env->GetMethodID(gConfig_class, "<init>", "(J)V"); 76 gConfig_EGLConfigFieldID = _env->GetFieldID(gConfig_class, "mEGLConfig", "J"); 77 78 jclass display_class = _env->FindClass("com/google/android/gles_jni/EGLDisplayImpl"); 79 gDisplay_EGLDisplayFieldID = _env->GetFieldID(display_class, "mEGLDisplay", "J"); 80 81 jclass context_class = _env->FindClass("com/google/android/gles_jni/EGLContextImpl"); 82 gContext_EGLContextFieldID = _env->GetFieldID(context_class, "mEGLContext", "J"); 83 84 jclass surface_class = _env->FindClass("com/google/android/gles_jni/EGLSurfaceImpl"); 85 gSurface_EGLSurfaceFieldID = _env->GetFieldID(surface_class, "mEGLSurface", "J"); 86 } 87 88 static const jint gNull_attrib_base[] = {EGL_NONE}; 89 90 static bool validAttribList(JNIEnv *_env, jintArray attrib_list) { 91 if (attrib_list == NULL) { 92 return true; 93 } 94 jsize len = _env->GetArrayLength(attrib_list); 95 if (len < 1) { 96 return false; 97 } 98 jint item = 0; 99 _env->GetIntArrayRegion(attrib_list, len-1, 1, &item); 100 return item == EGL_NONE; 101 } 102 103 static jint* beginNativeAttribList(JNIEnv *_env, jintArray attrib_list) { 104 if (attrib_list != NULL) { 105 return _env->GetIntArrayElements(attrib_list, (jboolean *)0); 106 } else { 107 return(jint*) gNull_attrib_base; 108 } 109 } 110 111 static void endNativeAttributeList(JNIEnv *_env, jintArray attrib_list, jint* attrib_base) { 112 if (attrib_list != NULL) { 113 _env->ReleaseIntArrayElements(attrib_list, attrib_base, 0); 114 } 115 } 116 117 static jboolean jni_eglInitialize(JNIEnv *_env, jobject _this, jobject display, 118 jintArray major_minor) { 119 if (display == NULL || (major_minor != NULL && 120 _env->GetArrayLength(major_minor) < 2)) { 121 jniThrowException(_env, "java/lang/IllegalArgumentException", NULL); 122 return JNI_FALSE; 123 } 124 125 EGLDisplay dpy = getDisplay(_env, display); 126 EGLBoolean success = eglInitialize(dpy, NULL, NULL); 127 if (success && major_minor) { 128 int len = _env->GetArrayLength(major_minor); 129 if (len) { 130 // we're exposing only EGL 1.0 131 jint* base = (jint *)_env->GetPrimitiveArrayCritical(major_minor, (jboolean *)0); 132 if (len >= 1) base[0] = 1; 133 if (len >= 2) base[1] = 0; 134 _env->ReleasePrimitiveArrayCritical(major_minor, base, 0); 135 } 136 } 137 return EglBoolToJBool(success); 138 } 139 140 static jboolean jni_eglQueryContext(JNIEnv *_env, jobject _this, jobject display, 141 jobject context, jint attribute, jintArray value) { 142 if (display == NULL || context == NULL || value == NULL 143 || _env->GetArrayLength(value) < 1) { 144 jniThrowException(_env, "java/lang/IllegalArgumentException", NULL); 145 return JNI_FALSE; 146 } 147 EGLDisplay dpy = getDisplay(_env, display); 148 EGLContext ctx = getContext(_env, context); 149 EGLBoolean success = EGL_FALSE; 150 int len = _env->GetArrayLength(value); 151 if (len) { 152 jint* base = _env->GetIntArrayElements(value, (jboolean *)0); 153 success = eglQueryContext(dpy, ctx, attribute, base); 154 _env->ReleaseIntArrayElements(value, base, 0); 155 } 156 return EglBoolToJBool(success); 157 } 158 159 static jboolean jni_eglQuerySurface(JNIEnv *_env, jobject _this, jobject display, 160 jobject surface, jint attribute, jintArray value) { 161 if (display == NULL || surface == NULL || value == NULL 162 || _env->GetArrayLength(value) < 1) { 163 jniThrowException(_env, "java/lang/IllegalArgumentException", NULL); 164 return JNI_FALSE; 165 } 166 EGLDisplay dpy = getDisplay(_env, display); 167 EGLContext sur = getSurface(_env, surface); 168 169 EGLBoolean success = EGL_FALSE; 170 int len = _env->GetArrayLength(value); 171 if (len) { 172 jint* base = _env->GetIntArrayElements(value, (jboolean *)0); 173 success = eglQuerySurface(dpy, sur, attribute, base); 174 _env->ReleaseIntArrayElements(value, base, 0); 175 } 176 return EglBoolToJBool(success); 177 } 178 179 static jint jni_getInitCount(JNIEnv *_env, jobject _clazz, jobject display) { 180 EGLDisplay dpy = getDisplay(_env, display); 181 return android::egl_get_init_count(dpy); 182 } 183 184 static jboolean jni_eglReleaseThread(JNIEnv *_env, jobject _this) { 185 return EglBoolToJBool(eglReleaseThread()); 186 } 187 188 static jboolean jni_eglChooseConfig(JNIEnv *_env, jobject _this, jobject display, 189 jintArray attrib_list, jobjectArray configs, jint config_size, jintArray num_config) { 190 if (display == NULL 191 || !validAttribList(_env, attrib_list) 192 || (configs != NULL && _env->GetArrayLength(configs) < config_size) 193 || (num_config != NULL && _env->GetArrayLength(num_config) < 1)) { 194 jniThrowException(_env, "java/lang/IllegalArgumentException", NULL); 195 return JNI_FALSE; 196 } 197 EGLDisplay dpy = getDisplay(_env, display); 198 EGLBoolean success = EGL_FALSE; 199 200 if (configs == NULL) { 201 config_size = 0; 202 } 203 EGLConfig nativeConfigs[config_size]; 204 205 int num = 0; 206 jint* attrib_base = beginNativeAttribList(_env, attrib_list); 207 success = eglChooseConfig(dpy, attrib_base, configs ? nativeConfigs : 0, config_size, &num); 208 endNativeAttributeList(_env, attrib_list, attrib_base); 209 210 if (num_config != NULL) { 211 _env->SetIntArrayRegion(num_config, 0, 1, (jint*) &num); 212 } 213 214 if (success && configs!=NULL) { 215 for (int i=0 ; i<num ; i++) { 216 jobject obj = _env->NewObject(gConfig_class, gConfig_ctorID, reinterpret_cast<jlong>(nativeConfigs[i])); 217 _env->SetObjectArrayElement(configs, i, obj); 218 } 219 } 220 return EglBoolToJBool(success); 221 } 222 223 static jlong jni_eglCreateContext(JNIEnv *_env, jobject _this, jobject display, 224 jobject config, jobject share_context, jintArray attrib_list) { 225 if (display == NULL || config == NULL || share_context == NULL 226 || !validAttribList(_env, attrib_list)) { 227 jniThrowException(_env, "java/lang/IllegalArgumentException", NULL); 228 return JNI_FALSE; 229 } 230 EGLDisplay dpy = getDisplay(_env, display); 231 EGLConfig cnf = getConfig(_env, config); 232 EGLContext shr = getContext(_env, share_context); 233 jint* base = beginNativeAttribList(_env, attrib_list); 234 EGLContext ctx = eglCreateContext(dpy, cnf, shr, base); 235 endNativeAttributeList(_env, attrib_list, base); 236 return reinterpret_cast<jlong>(ctx); 237 } 238 239 static jlong jni_eglCreatePbufferSurface(JNIEnv *_env, jobject _this, jobject display, 240 jobject config, jintArray attrib_list) { 241 if (display == NULL || config == NULL 242 || !validAttribList(_env, attrib_list)) { 243 jniThrowException(_env, "java/lang/IllegalArgumentException", NULL); 244 return JNI_FALSE; 245 } 246 EGLDisplay dpy = getDisplay(_env, display); 247 EGLConfig cnf = getConfig(_env, config); 248 jint* base = beginNativeAttribList(_env, attrib_list); 249 EGLSurface sur = eglCreatePbufferSurface(dpy, cnf, base); 250 endNativeAttributeList(_env, attrib_list, base); 251 return reinterpret_cast<jlong>(sur); 252 } 253 254 static void jni_eglCreatePixmapSurface(JNIEnv *_env, jobject _this, jobject out_sur, 255 jobject display, jobject config, jobject native_pixmap, 256 jintArray attrib_list) 257 { 258 jniThrowException(_env, "java/lang/UnsupportedOperationException", "eglCreatePixmapSurface"); 259 } 260 261 static jlong jni_eglCreateWindowSurface(JNIEnv *_env, jobject _this, jobject display, 262 jobject config, jobject native_window, jintArray attrib_list) { 263 if (display == NULL || config == NULL 264 || !validAttribList(_env, attrib_list)) { 265 jniThrowException(_env, "java/lang/IllegalArgumentException", NULL); 266 return JNI_FALSE; 267 } 268 EGLDisplay dpy = getDisplay(_env, display); 269 EGLContext cnf = getConfig(_env, config); 270 sp<ANativeWindow> window; 271 if (native_window == NULL) { 272 not_valid_surface: 273 jniThrowException(_env, "java/lang/IllegalArgumentException", 274 "Make sure the SurfaceView or associated SurfaceHolder has a valid Surface"); 275 return 0; 276 } 277 278 window = android_view_Surface_getNativeWindow(_env, native_window); 279 if (window == NULL) 280 goto not_valid_surface; 281 282 jint* base = beginNativeAttribList(_env, attrib_list); 283 EGLSurface sur = eglCreateWindowSurface(dpy, cnf, window.get(), base); 284 endNativeAttributeList(_env, attrib_list, base); 285 return reinterpret_cast<jlong>(sur); 286 } 287 288 static jlong jni_eglCreateWindowSurfaceTexture(JNIEnv *_env, jobject _this, jobject display, 289 jobject config, jobject native_window, jintArray attrib_list) { 290 if (display == NULL || config == NULL 291 || !validAttribList(_env, attrib_list)) { 292 jniThrowException(_env, "java/lang/IllegalArgumentException", NULL); 293 return 0; 294 } 295 EGLDisplay dpy = getDisplay(_env, display); 296 EGLContext cnf = getConfig(_env, config); 297 sp<ANativeWindow> window; 298 if (native_window == 0) { 299 not_valid_surface: 300 jniThrowException(_env, "java/lang/IllegalArgumentException", 301 "Make sure the SurfaceTexture is valid"); 302 return 0; 303 } 304 305 sp<IGraphicBufferProducer> producer(SurfaceTexture_getProducer(_env, native_window)); 306 window = new Surface(producer, true); 307 if (window == NULL) 308 goto not_valid_surface; 309 310 jint* base = beginNativeAttribList(_env, attrib_list); 311 EGLSurface sur = eglCreateWindowSurface(dpy, cnf, window.get(), base); 312 endNativeAttributeList(_env, attrib_list, base); 313 return reinterpret_cast<jlong>(sur); 314 } 315 316 static jboolean jni_eglGetConfigAttrib(JNIEnv *_env, jobject _this, jobject display, 317 jobject config, jint attribute, jintArray value) { 318 if (display == NULL || config == NULL 319 || (value == NULL || _env->GetArrayLength(value) < 1)) { 320 jniThrowException(_env, "java/lang/IllegalArgumentException", NULL); 321 return JNI_FALSE; 322 } 323 EGLDisplay dpy = getDisplay(_env, display); 324 EGLContext cnf = getConfig(_env, config); 325 EGLBoolean success = EGL_FALSE; 326 jint localValue; 327 success = eglGetConfigAttrib(dpy, cnf, attribute, &localValue); 328 if (success) { 329 _env->SetIntArrayRegion(value, 0, 1, &localValue); 330 } 331 return EglBoolToJBool(success); 332 } 333 334 static jboolean jni_eglGetConfigs(JNIEnv *_env, jobject _this, jobject display, 335 jobjectArray configs, jint config_size, jintArray num_config) { 336 if (display == NULL || (configs != NULL && _env->GetArrayLength(configs) < config_size) 337 || (num_config != NULL && _env->GetArrayLength(num_config) < 1)) { 338 jniThrowException(_env, "java/lang/IllegalArgumentException", NULL); 339 return JNI_FALSE; 340 } 341 EGLDisplay dpy = getDisplay(_env, display); 342 EGLBoolean success = EGL_FALSE; 343 if (configs == NULL) { 344 config_size = 0; 345 } 346 EGLConfig nativeConfigs[config_size]; 347 int num; 348 success = eglGetConfigs(dpy, configs ? nativeConfigs : 0, config_size, &num); 349 if (num_config != NULL) { 350 _env->SetIntArrayRegion(num_config, 0, 1, (jint*) &num); 351 } 352 if (success && configs) { 353 for (int i=0 ; i<num ; i++) { 354 jobject obj = _env->NewObject(gConfig_class, gConfig_ctorID, reinterpret_cast<jlong>(nativeConfigs[i])); 355 _env->SetObjectArrayElement(configs, i, obj); 356 } 357 } 358 return EglBoolToJBool(success); 359 } 360 361 static jint jni_eglGetError(JNIEnv *_env, jobject _this) { 362 EGLint error = eglGetError(); 363 return error; 364 } 365 366 static jlong jni_eglGetCurrentContext(JNIEnv *_env, jobject _this) { 367 return reinterpret_cast<jlong>(eglGetCurrentContext()); 368 } 369 370 static jlong jni_eglGetCurrentDisplay(JNIEnv *_env, jobject _this) { 371 return reinterpret_cast<jlong>(eglGetCurrentDisplay()); 372 } 373 374 static jlong jni_eglGetCurrentSurface(JNIEnv *_env, jobject _this, jint readdraw) { 375 if ((readdraw != EGL_READ) && (readdraw != EGL_DRAW)) { 376 jniThrowException(_env, "java/lang/IllegalArgumentException", NULL); 377 return 0; 378 } 379 return reinterpret_cast<jlong>(eglGetCurrentSurface(readdraw)); 380 } 381 382 static jboolean jni_eglDestroyContext(JNIEnv *_env, jobject _this, jobject display, jobject context) { 383 if (display == NULL || context == NULL) { 384 jniThrowException(_env, "java/lang/IllegalArgumentException", NULL); 385 return JNI_FALSE; 386 } 387 EGLDisplay dpy = getDisplay(_env, display); 388 EGLContext ctx = getContext(_env, context); 389 return EglBoolToJBool(eglDestroyContext(dpy, ctx)); 390 } 391 392 static jboolean jni_eglDestroySurface(JNIEnv *_env, jobject _this, jobject display, jobject surface) { 393 if (display == NULL || surface == NULL) { 394 jniThrowException(_env, "java/lang/IllegalArgumentException", NULL); 395 return JNI_FALSE; 396 } 397 EGLDisplay dpy = getDisplay(_env, display); 398 EGLSurface sur = getSurface(_env, surface); 399 return EglBoolToJBool(eglDestroySurface(dpy, sur)); 400 } 401 402 static jlong jni_eglGetDisplay(JNIEnv *_env, jobject _this, jobject native_display) { 403 return reinterpret_cast<jlong>(eglGetDisplay(EGL_DEFAULT_DISPLAY)); 404 } 405 406 static jboolean jni_eglMakeCurrent(JNIEnv *_env, jobject _this, jobject display, jobject draw, jobject read, jobject context) { 407 if (display == NULL || draw == NULL || read == NULL || context == NULL) { 408 jniThrowException(_env, "java/lang/IllegalArgumentException", NULL); 409 return JNI_FALSE; 410 } 411 EGLDisplay dpy = getDisplay(_env, display); 412 EGLSurface sdr = getSurface(_env, draw); 413 EGLSurface srd = getSurface(_env, read); 414 EGLContext ctx = getContext(_env, context); 415 return EglBoolToJBool(eglMakeCurrent(dpy, sdr, srd, ctx)); 416 } 417 418 static jstring jni_eglQueryString(JNIEnv *_env, jobject _this, jobject display, jint name) { 419 if (display == NULL) { 420 jniThrowException(_env, "java/lang/IllegalArgumentException", NULL); 421 return NULL; 422 } 423 EGLDisplay dpy = getDisplay(_env, display); 424 const char* chars = eglQueryString(dpy, name); 425 return _env->NewStringUTF(chars); 426 } 427 428 static jboolean jni_eglSwapBuffers(JNIEnv *_env, jobject _this, jobject display, jobject surface) { 429 if (display == NULL || surface == NULL) { 430 jniThrowException(_env, "java/lang/IllegalArgumentException", NULL); 431 return JNI_FALSE; 432 } 433 EGLDisplay dpy = getDisplay(_env, display); 434 EGLSurface sur = getSurface(_env, surface); 435 return EglBoolToJBool(eglSwapBuffers(dpy, sur)); 436 } 437 438 static jboolean jni_eglTerminate(JNIEnv *_env, jobject _this, jobject display) { 439 if (display == NULL) { 440 jniThrowException(_env, "java/lang/IllegalArgumentException", NULL); 441 return JNI_FALSE; 442 } 443 EGLDisplay dpy = getDisplay(_env, display); 444 return EglBoolToJBool(eglTerminate(dpy)); 445 } 446 447 static jboolean jni_eglCopyBuffers(JNIEnv *_env, jobject _this, jobject display, 448 jobject surface, jobject native_pixmap) { 449 if (display == NULL || surface == NULL || native_pixmap == NULL) { 450 jniThrowException(_env, "java/lang/IllegalArgumentException", NULL); 451 return JNI_FALSE; 452 } 453 // TODO: Implement this 454 return JNI_FALSE; 455 } 456 457 static jboolean jni_eglWaitGL(JNIEnv *_env, jobject _this) { 458 return EglBoolToJBool(eglWaitGL()); 459 } 460 461 static jboolean jni_eglWaitNative(JNIEnv *_env, jobject _this, jint engine, jobject bindTarget) { 462 return EglBoolToJBool(eglWaitNative(engine)); 463 } 464 465 466 static const char *classPathName = "com/google/android/gles_jni/EGLImpl"; 467 468 #define DISPLAY "Ljavax/microedition/khronos/egl/EGLDisplay;" 469 #define CONTEXT "Ljavax/microedition/khronos/egl/EGLContext;" 470 #define CONFIG "Ljavax/microedition/khronos/egl/EGLConfig;" 471 #define SURFACE "Ljavax/microedition/khronos/egl/EGLSurface;" 472 #define OBJECT "Ljava/lang/Object;" 473 #define STRING "Ljava/lang/String;" 474 475 static const JNINativeMethod methods[] = { 476 {"_nativeClassInit","()V", (void*)nativeClassInit }, 477 {"eglWaitGL", "()Z", (void*)jni_eglWaitGL }, 478 {"eglInitialize", "(" DISPLAY "[I)Z", (void*)jni_eglInitialize }, 479 {"eglQueryContext", "(" DISPLAY CONTEXT "I[I)Z", (void*)jni_eglQueryContext }, 480 {"eglQuerySurface", "(" DISPLAY SURFACE "I[I)Z", (void*)jni_eglQuerySurface }, 481 {"eglReleaseThread","()Z", (void*)jni_eglReleaseThread }, 482 {"getInitCount", "(" DISPLAY ")I", (void*)jni_getInitCount }, 483 {"eglChooseConfig", "(" DISPLAY "[I[" CONFIG "I[I)Z", (void*)jni_eglChooseConfig }, 484 {"_eglCreateContext","(" DISPLAY CONFIG CONTEXT "[I)J", (void*)jni_eglCreateContext }, 485 {"eglGetConfigs", "(" DISPLAY "[" CONFIG "I[I)Z", (void*)jni_eglGetConfigs }, 486 {"eglTerminate", "(" DISPLAY ")Z", (void*)jni_eglTerminate }, 487 {"eglCopyBuffers", "(" DISPLAY SURFACE OBJECT ")Z", (void*)jni_eglCopyBuffers }, 488 {"eglWaitNative", "(I" OBJECT ")Z", (void*)jni_eglWaitNative }, 489 {"eglGetError", "()I", (void*)jni_eglGetError }, 490 {"eglGetConfigAttrib", "(" DISPLAY CONFIG "I[I)Z", (void*)jni_eglGetConfigAttrib }, 491 {"_eglGetDisplay", "(" OBJECT ")J", (void*)jni_eglGetDisplay }, 492 {"_eglGetCurrentContext", "()J", (void*)jni_eglGetCurrentContext }, 493 {"_eglGetCurrentDisplay", "()J", (void*)jni_eglGetCurrentDisplay }, 494 {"_eglGetCurrentSurface", "(I)J", (void*)jni_eglGetCurrentSurface }, 495 {"_eglCreatePbufferSurface","(" DISPLAY CONFIG "[I)J", (void*)jni_eglCreatePbufferSurface }, 496 {"_eglCreatePixmapSurface", "(" SURFACE DISPLAY CONFIG OBJECT "[I)V", (void*)jni_eglCreatePixmapSurface }, 497 {"_eglCreateWindowSurface", "(" DISPLAY CONFIG OBJECT "[I)J", (void*)jni_eglCreateWindowSurface }, 498 {"_eglCreateWindowSurfaceTexture", "(" DISPLAY CONFIG OBJECT "[I)J", (void*)jni_eglCreateWindowSurfaceTexture }, 499 {"eglDestroyContext", "(" DISPLAY CONTEXT ")Z", (void*)jni_eglDestroyContext }, 500 {"eglDestroySurface", "(" DISPLAY SURFACE ")Z", (void*)jni_eglDestroySurface }, 501 {"eglMakeCurrent", "(" DISPLAY SURFACE SURFACE CONTEXT")Z", (void*)jni_eglMakeCurrent }, 502 {"eglQueryString", "(" DISPLAY "I)" STRING, (void*)jni_eglQueryString }, 503 {"eglSwapBuffers", "(" DISPLAY SURFACE ")Z", (void*)jni_eglSwapBuffers }, 504 }; 505 506 } // namespace android 507 508 int register_com_google_android_gles_jni_EGLImpl(JNIEnv *_env) 509 { 510 int err; 511 err = android::AndroidRuntime::registerNativeMethods(_env, 512 android::classPathName, android::methods, NELEM(android::methods)); 513 return err; 514 } 515