static jint jni_eglCreateWindowSurfaceTexture(JNIEnv *_env, jobject _this, jobject display,
        jobject config, jobject native_window, jintArray attrib_list) {
    if (display == NULL || config == NULL
        || !validAttribList(_env, attrib_list)) {
        jniThrowException(_env, "java/lang/IllegalArgumentException", NULL);
        return JNI_FALSE;
    }
    EGLDisplay dpy = getDisplay(_env, display);
    EGLContext cnf = getConfig(_env, config);
    sp<ANativeWindow> window;
    if (native_window == 0) {
not_valid_surface:
        jniThrowException(_env, "java/lang/IllegalArgumentException",
                "Make sure the SurfaceTexture is valid");
        return 0;
    }
    
    sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(_env, native_window));

    window = new SurfaceTextureClient(surfaceTexture);
    if (window == NULL)
        goto not_valid_surface;

    jint* base = beginNativeAttribList(_env, attrib_list);
    EGLSurface sur = eglCreateWindowSurface(dpy, cnf, window.get(), base);
    endNativeAttributeList(_env, attrib_list, base);
    return (jint)sur;
}
static jboolean jni_eglChooseConfig(JNIEnv *_env, jobject _this, jobject display,
        jintArray attrib_list, jobjectArray configs, jint config_size, jintArray num_config) {
    if (display == NULL
        || !validAttribList(_env, attrib_list)
        || (configs != NULL && _env->GetArrayLength(configs) < config_size)
        || (num_config != NULL && _env->GetArrayLength(num_config) < 1)) {
        jniThrowException(_env, "java/lang/IllegalArgumentException", NULL);
        return JNI_FALSE;
    }
    EGLDisplay dpy = getDisplay(_env, display);
    jboolean success = JNI_FALSE;

    if (configs == NULL) {
        config_size = 0;
    }
    EGLConfig nativeConfigs[config_size];

    int num = 0;
    jint* attrib_base = beginNativeAttribList(_env, attrib_list);
    success = eglChooseConfig(dpy, attrib_base, configs ? nativeConfigs : 0, config_size, &num);
    endNativeAttributeList(_env, attrib_list, attrib_base);

    if (num_config != NULL) {
        _env->SetIntArrayRegion(num_config, 0, 1, (jint*) &num);
    }

    if (success && configs!=NULL) {
        for (int i=0 ; i<num ; i++) {
            jobject obj = _env->NewObject(gConfig_class, gConfig_ctorID, (jint)nativeConfigs[i]);
            _env->SetObjectArrayElement(configs, i, obj);
        }
    }
    return success;
}
static jint jni_eglCreateWindowSurface(JNIEnv *_env, jobject _this, jobject display,
        jobject config, jobject native_window, jintArray attrib_list) {
    if (display == NULL || config == NULL
        || !validAttribList(_env, attrib_list)) {
        jniThrowException(_env, "java/lang/IllegalArgumentException", NULL);
        return JNI_FALSE;
    }
    EGLDisplay dpy = getDisplay(_env, display);
    EGLContext cnf = getConfig(_env, config);
    sp<ANativeWindow> window;
    if (native_window == NULL) {
not_valid_surface:
        jniThrowException(_env, "java/lang/IllegalArgumentException",
                "Make sure the SurfaceView or associated SurfaceHolder has a valid Surface");
        return 0;
    }

    window = android_view_Surface_getNativeWindow(_env, native_window);
    if (window == NULL)
        goto not_valid_surface;

    jint* base = beginNativeAttribList(_env, attrib_list);
    EGLSurface sur = eglCreateWindowSurface(dpy, cnf, window.get(), base);
    endNativeAttributeList(_env, attrib_list, base);
    return (jint)sur;
}
static jint jni_eglCreateWindowSurface(JNIEnv *_env, jobject _this, jobject display,
        jobject config, jobject native_window, jintArray attrib_list) {
    if (display == NULL || config == NULL
        || !validAttribList(_env, attrib_list)) {
        doThrow(_env, "java/lang/IllegalArgumentException");
        return JNI_FALSE;
    }
    EGLDisplay dpy = getDisplay(_env, display);
    EGLContext cnf = getConfig(_env, config);
    Surface* window = 0;
    if (native_window == NULL) {
not_valid_surface:
        doThrow(_env, "java/lang/IllegalArgumentException",
                "Make sure the SurfaceView or associated SurfaceHolder has a valid Surface");
        return 0;
    }
    window = (Surface*)_env->GetIntField(native_window, gSurface_SurfaceFieldID);
    if (window == NULL)
        goto not_valid_surface;

    jint* base = beginNativeAttribList(_env, attrib_list);
    EGLSurface sur = eglCreateWindowSurface(dpy, cnf, window, base);
    endNativeAttributeList(_env, attrib_list, base);
    return (jint)sur;
}
static jlong jni_eglCreateWindowSurfaceTexture(JNIEnv *_env, jobject _this, jobject display,
        jobject config, jobject native_window, jintArray attrib_list) {
    if (display == NULL || config == NULL
        || !validAttribList(_env, attrib_list)) {
        jniThrowException(_env, "java/lang/IllegalArgumentException", NULL);
        return 0;
    }
    EGLDisplay dpy = getDisplay(_env, display);
    EGLContext cnf = getConfig(_env, config);
    sp<ANativeWindow> window;
    if (native_window == 0) {
not_valid_surface:
        jniThrowException(_env, "java/lang/IllegalArgumentException",
                "Make sure the SurfaceTexture is valid");
        return 0;
    }

    sp<IGraphicBufferProducer> producer(SurfaceTexture_getProducer(_env, native_window));
    window = new Surface(producer, true);
    if (window == NULL)
        goto not_valid_surface;

    jint* base = beginNativeAttribList(_env, attrib_list);
    EGLSurface sur = eglCreateWindowSurface(dpy, cnf, window.get(), base);
    endNativeAttributeList(_env, attrib_list, base);
    return reinterpret_cast<jlong>(sur);
}
static jint jni_eglCreatePbufferSurface(JNIEnv *_env, jobject _this, jobject display,
        jobject config, jintArray attrib_list) {
    if (display == NULL || config == NULL
        || !validAttribList(_env, attrib_list)) {
        jniThrowException(_env, "java/lang/IllegalArgumentException", NULL);
        return JNI_FALSE;
    }
    EGLDisplay dpy = getDisplay(_env, display);
    EGLConfig  cnf = getConfig(_env, config);
    jint* base = beginNativeAttribList(_env, attrib_list);
    EGLSurface sur = eglCreatePbufferSurface(dpy, cnf, base);
    endNativeAttributeList(_env, attrib_list, base);
    return (jint)sur;
}
static jint jni_eglCreateContext(JNIEnv *_env, jobject _this, jobject display,
        jobject config, jobject share_context, jintArray attrib_list) {
    if (display == NULL || config == NULL || share_context == NULL
        || !validAttribList(_env, attrib_list)) {
        jniThrowException(_env, "java/lang/IllegalArgumentException", NULL);
        return JNI_FALSE;
    }
    EGLDisplay dpy = getDisplay(_env, display);
    EGLConfig  cnf = getConfig(_env, config);
    EGLContext shr = getContext(_env, share_context);
    jint* base = beginNativeAttribList(_env, attrib_list);
    EGLContext ctx = eglCreateContext(dpy, cnf, shr, base);
    endNativeAttributeList(_env, attrib_list, base);
    return (jint)ctx;
}
static void jni_eglCreatePixmapSurface(JNIEnv *_env, jobject _this, jobject out_sur,
        jobject display, jobject config, jobject native_pixmap,
        jintArray attrib_list)
{
    if (display == NULL || config == NULL || native_pixmap == NULL
        || !validAttribList(_env, attrib_list)) {
        jniThrowException(_env, "java/lang/IllegalArgumentException", NULL);
        return;
    }
    EGLDisplay dpy = getDisplay(_env, display);
    EGLConfig  cnf = getConfig(_env, config);
    jint* base = 0;

    SkBitmap const * nativeBitmap =
            (SkBitmap const *)_env->GetIntField(native_pixmap,
                    gBitmap_NativeBitmapFieldID);
    SkPixelRef* ref = nativeBitmap ? nativeBitmap->pixelRef() : 0;
    if (ref == NULL) {
        jniThrowException(_env, "java/lang/IllegalArgumentException", "Bitmap has no PixelRef");
        return;
    }

    SkSafeRef(ref);
    ref->lockPixels();

    egl_native_pixmap_t pixmap;
    pixmap.version = sizeof(pixmap);
    pixmap.width  = nativeBitmap->width();
    pixmap.height = nativeBitmap->height();
    pixmap.stride = nativeBitmap->rowBytes() / nativeBitmap->bytesPerPixel();
    pixmap.format = convertPixelFormat(nativeBitmap->config());
    pixmap.data   = (uint8_t*)ref->pixels();

    base = beginNativeAttribList(_env, attrib_list);
    EGLSurface sur = eglCreatePixmapSurface(dpy, cnf, &pixmap, base);
    endNativeAttributeList(_env, attrib_list, base);

    if (sur != EGL_NO_SURFACE) {
        _env->SetIntField(out_sur, gSurface_EGLSurfaceFieldID, (int)sur);
        _env->SetIntField(out_sur, gSurface_NativePixelRefFieldID, (int)ref);
    } else {
        ref->unlockPixels();
        SkSafeUnref(ref);
    }
}