From ace2daf725dfc1aa700338fae71fe93a9d0fd865 Mon Sep 17 00:00:00 2001
From: Sven Gothel <sgothel@jausoft.com>
Date: Thu, 12 Apr 2012 20:21:06 +0200
Subject: JOGL/Native: Add JNIEnv functions

---
 src/jogl/native/JoglCommon.c | 61 ++++++++++++++++++++++++++++++++++++++++++++
 src/jogl/native/JoglCommon.h | 33 ++++++++++++++++++++++++
 2 files changed, 94 insertions(+)

(limited to 'src/jogl/native')

diff --git a/src/jogl/native/JoglCommon.c b/src/jogl/native/JoglCommon.c
index c1d6ad181..719e0df56 100644
--- a/src/jogl/native/JoglCommon.c
+++ b/src/jogl/native/JoglCommon.c
@@ -8,6 +8,10 @@
 static const char * const ClazzNameRuntimeException = "java/lang/RuntimeException";
 static jclass    runtimeExceptionClz=NULL;
 
+static JavaVM *_jvmHandle = NULL;
+static int _jvmVersion = 0;
+
+
 void JoglCommon_FatalError(JNIEnv *env, const char* msg, ...)
 {
     char buffer[512];
@@ -45,6 +49,19 @@ void JoglCommon_init(JNIEnv *env) {
             JoglCommon_FatalError(env, "JOGL: can't use %s", ClazzNameRuntimeException);
         }
     }
+    if(0 != (*env)->GetJavaVM(env, &_jvmHandle)) {
+        JoglCommon_FatalError(env, "JOGL: can't fetch JavaVM handle");
+    } else {
+        _jvmVersion = (*env)->GetVersion(env);
+    }
+}
+
+JavaVM *JoglCommon_GetJVMHandle() {
+    return _jvmHandle;
+}
+
+int JoglCommon_GetJVMVersion() {
+    return _jvmVersion;
 }
 
 jchar* JoglCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str)
@@ -57,6 +74,50 @@ jchar* JoglCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str)
     return strChars;
 }
 
+JNIEnv* JoglCommon_GetJNIEnv (int * shallBeDetached)
+{
+    JNIEnv* curEnv = NULL;
+    JNIEnv* newEnv = NULL;
+    int envRes;
+
+    if(NULL == _jvmHandle) {
+        fprintf(stderr, "JOGL: No JavaVM handle registered, call JoglCommon_init(..) 1st");
+        return NULL;
+    }
+
+    // retrieve this thread's JNIEnv curEnv - or detect it's detached
+    envRes = (*_jvmHandle)->GetEnv(_jvmHandle, (void **) &curEnv, _jvmVersion) ;
+    if( JNI_EDETACHED == envRes ) {
+        // detached thread - attach to JVM
+        if( JNI_OK != ( envRes = (*_jvmHandle)->AttachCurrentThread(_jvmHandle, (void**) &newEnv, NULL) ) ) {
+            fprintf(stderr, "JNIEnv: can't attach thread: %d\n", envRes);
+            return NULL;
+        }
+        curEnv = newEnv;
+    } else if( JNI_OK != envRes ) {
+        // oops ..
+        fprintf(stderr, "can't GetEnv: %d\n", envRes);
+        return NULL;
+    }
+    if (curEnv==NULL) {
+        fprintf(stderr, "env is NULL\n");
+        return NULL;
+    }
+    *shallBeDetached = NULL != newEnv;
+    return curEnv;
+}
+
+void JoglCommon_ReleaseJNIEnv (int shallBeDetached) {
+    if(NULL == _jvmHandle) {
+        fprintf(stderr, "JOGL: No JavaVM handle registered, call JoglCommon_init(..) 1st");
+        return NULL;
+    }
+
+    if(shallBeDetached) {
+        (*_jvmHandle)->DetachCurrentThread(_jvmHandle);
+    }
+}
+
 /*
  * Class:     jogamp_opengl_GLContextImpl
  * Method:    glGetStringInt
diff --git a/src/jogl/native/JoglCommon.h b/src/jogl/native/JoglCommon.h
index d82b445ce..b988336fa 100644
--- a/src/jogl/native/JoglCommon.h
+++ b/src/jogl/native/JoglCommon.h
@@ -7,9 +7,42 @@
 
 void JoglCommon_init(JNIEnv *env);
 
+/** Set by JoglCommon_init */
+JavaVM *JoglCommon_GetJVMHandle();
+
+/** Set by JoglCommon_init */
+int JoglCommon_GetJVMVersion();
+
 jchar* JoglCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str);
 
 void JoglCommon_FatalError(JNIEnv *env, const char* msg, ...);
 void JoglCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...);
 
+/**
+ *
+ * 1) Store jvmHandle and jvmVersion is done by 'JoglCommon_init(JNIEnv*)'
+ *    and internally used by 'JoglCommon_GetJNIEnv(..)' and 'JoglCommon_ReleaseJNIEnv(..)'.
+ *
+ * 2) Use current thread JNIEnv or attach current thread to JVM, generating new JNIEnv
+ *
+    int shallBeDetached = 0;
+    JNIEnv* env = NewtCommon_GetJNIEnv(&shallBeDetached);
+    if(NULL==env) {
+        DBG_PRINT("drawRect: null JNIEnv\n");
+        return;
+    }
+    
+ *
+ * 3) Use JNIEnv ..
+ *
+    .. your JNIEnv code here ..
+
+ *
+ * 4) Detach thread from JVM, if required
+ *
+    JoglCommon_ReleaseJNIEnv (shallBeDetached);
+ */
+JNIEnv* JoglCommon_GetJNIEnv (int * shallBeDetached);
+void JoglCommon_ReleaseJNIEnv (int shallBeDetached);
+
 #endif
-- 
cgit v1.2.3