From fd06292d4a208cbd613f4bdce7cae12e075e70ec Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Thu, 5 Jul 2012 14:32:00 +0200 Subject: NativeWindow/Newt X11ErrorHandler enhancement / unification - don't throw exceptions. Handles also XAWT BadMatch X_SetInputFocus. X11ErrorHandler code now dumps proper information about the opcode and error message and the running Java thread. Having propery "nativewindow.debug.X11Util.XErrorStackDump" or "nativewindow.debug=all' set, a stack trace is dumped. Since the X11ErrorHandler may catch an XAWT error: BadMatch X_SetInputFocus, we cannot throw an exception and better keep running. --- src/nativewindow/native/NativewindowCommon.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'src/nativewindow/native/NativewindowCommon.c') diff --git a/src/nativewindow/native/NativewindowCommon.c b/src/nativewindow/native/NativewindowCommon.c index b866646a6..d2fdd5d69 100644 --- a/src/nativewindow/native/NativewindowCommon.c +++ b/src/nativewindow/native/NativewindowCommon.c @@ -1,5 +1,6 @@ #include "NativewindowCommon.h" +#include static const char * const ClazzNameRuntimeException = "java/lang/RuntimeException"; static jclass runtimeExceptionClz=NULL; @@ -45,6 +46,24 @@ int NativewindowCommon_init(JNIEnv *env) { return 0; } +const char * NativewindowCommon_GetStaticStringMethod(JNIEnv *jniEnv, jclass clazz, jmethodID jGetStrID, char *dest, int destSize, const char *altText) { + if(NULL != jniEnv && NULL != clazz && NULL != jGetStrID) { + jstring jstr = (jstring) (*jniEnv)->CallStaticObjectMethod(jniEnv, clazz, jGetStrID); + if(NULL != jstr) { + const char * str = (*jniEnv)->GetStringUTFChars(jniEnv, jstr, NULL); + if( NULL != str) { + strncpy(dest, str, destSize-1); + dest[destSize-1] = 0; // EOS + (*jniEnv)->ReleaseStringUTFChars(jniEnv, jstr, str); + return dest; + } + } + } + strncpy(dest, altText, destSize-1); + dest[destSize-1] = 0; // EOS + return dest; +} + jchar* NativewindowCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str) { jchar* strChars = NULL; -- cgit v1.2.3 From 3f2da22cfb682d0eb4fedec98b088f95371f8ef4 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Mon, 18 Mar 2013 08:16:25 +0100 Subject: NativeWindow OSXUtil RunOnMainThread: Use daemon attachment and do not detach; Add RunLater0(..) --- src/nativewindow/native/NativewindowCommon.c | 9 +++- src/nativewindow/native/NativewindowCommon.h | 2 +- src/nativewindow/native/macosx/OSXmisc.m | 65 ++++++++++++++++++---------- src/nativewindow/native/x11/Xmisc.c | 4 +- 4 files changed, 53 insertions(+), 27 deletions(-) (limited to 'src/nativewindow/native/NativewindowCommon.c') diff --git a/src/nativewindow/native/NativewindowCommon.c b/src/nativewindow/native/NativewindowCommon.c index d2fdd5d69..e909c0494 100644 --- a/src/nativewindow/native/NativewindowCommon.c +++ b/src/nativewindow/native/NativewindowCommon.c @@ -74,7 +74,7 @@ jchar* NativewindowCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str) return strChars; } -JNIEnv* NativewindowCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int * shallBeDetached) { +JNIEnv* NativewindowCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int asDaemon, int * shallBeDetached) { JNIEnv* curEnv = NULL; JNIEnv* newEnv = NULL; int envRes; @@ -83,7 +83,12 @@ JNIEnv* NativewindowCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int * 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) ) ) { + if( asDaemon ) { + envRes = (*jvmHandle)->AttachCurrentThreadAsDaemon(jvmHandle, (void**) &newEnv, NULL); + } else { + envRes = (*jvmHandle)->AttachCurrentThread(jvmHandle, (void**) &newEnv, NULL); + } + if( JNI_OK != envRes ) { fprintf(stderr, "JNIEnv: can't attach thread: %d\n", envRes); return NULL; } diff --git a/src/nativewindow/native/NativewindowCommon.h b/src/nativewindow/native/NativewindowCommon.h index 73b890c4f..a2975f3fd 100644 --- a/src/nativewindow/native/NativewindowCommon.h +++ b/src/nativewindow/native/NativewindowCommon.h @@ -13,6 +13,6 @@ jchar* NativewindowCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str) void NativewindowCommon_FatalError(JNIEnv *env, const char* msg, ...); void NativewindowCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...); -JNIEnv* NativewindowCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int * shallBeDetached); +JNIEnv* NativewindowCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int asDaemon, int * shallBeDetached); #endif diff --git a/src/nativewindow/native/macosx/OSXmisc.m b/src/nativewindow/native/macosx/OSXmisc.m index 81dcfa959..5d292d76e 100644 --- a/src/nativewindow/native/macosx/OSXmisc.m +++ b/src/nativewindow/native/macosx/OSXmisc.m @@ -689,7 +689,7 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_Uns - (void) jRun { int shallBeDetached = 0; - JNIEnv* env = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached); + JNIEnv* env = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, 1 /* asDaemon */, &shallBeDetached); DBG_PRINT2("MainRunnable.1 env: %d\n", (int)(NULL!=env)); if(NULL!=env) { DBG_PRINT2("MainRunnable.1.0\n"); @@ -699,7 +699,8 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_Uns if (shallBeDetached) { DBG_PRINT2("MainRunnable.1.3\n"); - (*jvmHandle)->DetachCurrentThread(jvmHandle); + // Keep attached on main thread ! + // (*jvmHandle)->DetachCurrentThread(jvmHandle); } } DBG_PRINT2("MainRunnable.X\n"); @@ -733,21 +734,12 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_Uns @end - -/* - * Class: Java_jogamp_nativewindow_macosx_OSXUtil - * Method: RunOnMainThread0 - * Signature: (ZLjava/lang/Runnable;)V - */ -JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_RunOnMainThread0 - (JNIEnv *env, jclass unused, jobject runnable) +static void RunOnThread (JNIEnv *env, jobject runnable, BOOL onMain, jint delayInMS) { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - - DBG_PRINT2( "RunOnMainThread0: isMainThread %d, NSApp %d, NSApp-isRunning %d\n", - (int)([NSThread isMainThread]), (int)(NULL!=NSApp), (int)([NSApp isRunning])); + DBG_PRINT2( "RunOnThread0: isMainThread %d, NSApp %d, NSApp-isRunning %d, onMain %d, delay %dms\n", + (int)([NSThread isMainThread]), (int)(NULL!=NSApp), (int)([NSApp isRunning]), (int)onMain, (int)delayInMS); - if ( NO == [NSThread isMainThread] ) { + if ( !onMain || NO == [NSThread isMainThread] ) { jobject runnableObj = (*env)->NewGlobalRef(env, runnable); JavaVM *jvmHandle = NULL; @@ -759,27 +751,56 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_RunOnMainThread0 jvmVersion = (*env)->GetVersion(env); } - DBG_PRINT2( "RunOnMainThread0.1.0\n"); + DBG_PRINT2( "RunOnThread.1.0\n"); MainRunnable * mr = [[MainRunnable alloc] initWithRunnable: runnableObj jvmHandle: jvmHandle jvmVersion: jvmVersion]; - [mr performSelectorOnMainThread:@selector(jRun) withObject:nil waitUntilDone:NO]; - DBG_PRINT2( "RunOnMainThread0.1.1\n"); + if( onMain ) { + [mr performSelectorOnMainThread:@selector(jRun) withObject:nil waitUntilDone:NO]; + } else { + NSTimeInterval delay = (double)delayInMS/1000.0; + [mr performSelector:@selector(jRun) withObject:nil afterDelay:delay]; + } + DBG_PRINT2( "RunOnThread.1.1\n"); [mr release]; - DBG_PRINT2( "RunOnMainThread0.1.2\n"); + DBG_PRINT2( "RunOnThread.1.2\n"); } else { - DBG_PRINT2( "RunOnMainThread0.2\n"); + DBG_PRINT2( "RunOnThread.2\n"); (*env)->CallVoidMethod(env, runnable, runnableRunID); } - DBG_PRINT2( "RunOnMainThread0.X\n"); + DBG_PRINT2( "RunOnThread.X\n"); +} +/* + * Class: Java_jogamp_nativewindow_macosx_OSXUtil + * Method: RunOnMainThread0 + * Signature: (ZLjava/lang/Runnable;)V + */ +JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_RunOnMainThread0 + (JNIEnv *env, jclass unused, jobject runnable) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + RunOnThread (env, runnable, YES, 0); [pool release]; } /* * Class: Java_jogamp_nativewindow_macosx_OSXUtil - * Method: RunOnMainThread0 + * Method: RunLater0 + * Signature: (ZLjava/lang/Runnable;I)V + */ +JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_RunLater0 + (JNIEnv *env, jclass unused, jobject runnable, jint delay) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + RunOnThread (env, runnable, NO, delay); + [pool release]; +} + +/* + * Class: Java_jogamp_nativewindow_macosx_OSXUtil + * Method: IsMainThread0 * Signature: (V)V */ JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_IsMainThread0 diff --git a/src/nativewindow/native/x11/Xmisc.c b/src/nativewindow/native/x11/Xmisc.c index 017c52df2..77e6ea978 100644 --- a/src/nativewindow/native/x11/Xmisc.c +++ b/src/nativewindow/native/x11/Xmisc.c @@ -197,7 +197,7 @@ static int x11ErrorHandler(Display *dpy, XErrorEvent *e) fflush(stderr); if( NULL != jvmHandle && ( errorHandlerDebug || errorHandlerThrowException ) ) { - jniEnv = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached); + jniEnv = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, 0 /* asDaemon */, &shallBeDetached); if(NULL == jniEnv) { fprintf(stderr, "Nativewindow X11 Error: null JNIEnv"); fflush(stderr); @@ -262,7 +262,7 @@ static int x11IOErrorHandler(Display *dpy) fflush(stderr); if( NULL != jvmHandle ) { - jniEnv = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached); + jniEnv = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, 0 /* asDaemon */, &shallBeDetached); if (NULL != jniEnv) { NativewindowCommon_FatalError(jniEnv, "Nativewindow X11 IOError: Display %p (%s): %s", dpy, dpyName, errnoStr); if (shallBeDetached) { -- cgit v1.2.3 From 586446311ea1ba87f98236d5347955bf99b465d6 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Fri, 29 Nov 2013 02:24:01 +0100 Subject: Bug 907 - Refine DummyDispatchThread (DDT) Handling: Proper OO integration in RegisteredClass; Safe DDT Post/WaitForReady handling and error cases ; ... Proper OO integration of DDT in RegisteredClass - DDT is optional to RegisteredClass[Factory], i.e. NEWT without DDT and DummyWindow with DDT. - Using native type DummyThreadContext per DDT passed as DDT handle to java referenced in RegisteredClass - Passing DDT handle to related native methods, if not null use DDT - otherwise work on current thread. The latter impacts CreateDummyWindow0 and DestroyWindow0. Safe DDT Post/WaitForReady handling and error cases ; ... - Wait until command it complete using a 3s timeout - Terminate thread if errors occur and throw an exception +++ Discussion: DDT Native Implementation Due to original code, the DDT is implemented in native code. Usually we should favor running the DDT from a java thread. However, since it's main purpose is _not_ to interact w/ java and the native implementation has less footprint (performance and memory) we shall be OK w/ it for now - as long the implementation IS SAFE. --- make/scripts/tests-win.bat | 4 +- make/scripts/tests-x64-dbg.bat | 8 +- make/scripts/tests.sh | 27 +- .../jogamp/nativewindow/windows/GDIUtil.java | 21 +- .../nativewindow/windows/RegisteredClass.java | 17 +- .../windows/RegisteredClassFactory.java | 30 +- src/nativewindow/native/NativewindowCommon.c | 7 + src/nativewindow/native/NativewindowCommon.h | 3 + src/nativewindow/native/win32/GDImisc.c | 446 ++++++++++++++------- .../jogamp/newt/driver/windows/DisplayDriver.java | 2 +- 10 files changed, 373 insertions(+), 192 deletions(-) (limited to 'src/nativewindow/native/NativewindowCommon.c') diff --git a/make/scripts/tests-win.bat b/make/scripts/tests-win.bat index fb224c882..d95b0025f 100755 --- a/make/scripts/tests-win.bat +++ b/make/scripts/tests-win.bat @@ -6,7 +6,7 @@ REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestMainVersion REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNewtAWTWrapper %* REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNEWT -time 30000 REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es1.newt.TestGearsES1NEWT %* -REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT %* +scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT %* REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT -vsync -time 4000 -x 10 -y 10 -width 100 -height 100 -screen 0 REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT -vsync -time 40000 -width 100 -height 100 -screen 0 %* REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsAWT -time 5000 @@ -18,7 +18,7 @@ REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestLa REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestElektronenMultipliziererNEWT %* REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.gl3.newt.TestGeomShader01TextureGL3NEWT %* -scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSimple %* +REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSimple %* REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieCube %* REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.TexCubeES2 %* diff --git a/make/scripts/tests-x64-dbg.bat b/make/scripts/tests-x64-dbg.bat index 851c1dbec..3e56a31a6 100755 --- a/make/scripts/tests-x64-dbg.bat +++ b/make/scripts/tests-x64-dbg.bat @@ -21,16 +21,18 @@ set CP_ALL=.;%BLD_DIR%\jar\jogl-all.jar;%BLD_DIR%\jar\jogl-test.jar;..\..\joal\% echo CP_ALL %CP_ALL% REM set D_ARGS="-Djogamp.debug=all" +set D_ARGS="-Djogl.debug=all" "-Dnativewindow.debug=all" +REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" +REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" "-Djogamp.debug=all" "-Djogl.debug.EGLDrawableFactory.DontQuery" +REM set D_ARGS="-Dnativewindow.debug.GDIUtil" "-Dnativewindow.debug.RegisteredClass" REM set D_ARGS="-Djogl.debug.GLContext" "-Djogl.debug.FBObject" REM set D_ARGS="-Djogl.debug.GLDrawable" "-Djogl.debug.EGLDrawableFactory.DontQuery" REM set D_ARGS="-Djogl.debug.GLDrawable" "-Djogl.debug.EGLDrawableFactory.QueryNativeTK" -REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" REM set D_ARGS="-Djogl.debug.GLDrawable" "-Djogl.debug.GLContext" "-Djogl.debug.GLCanvas" -REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" "-Djogamp.debug=all" "-Djogl.debug.EGLDrawableFactory.DontQuery" REM set D_ARGS="-Dnativewindow.debug.GraphicsConfiguration -Djogl.debug.CapabilitiesChooser -Djogl.debug.GLProfile" REM set D_ARGS="-Djogamp.debug.IOUtil" REM set D_ARGS="-Djogl.debug.GLSLCode" "-Djogl.debug.GLMediaPlayer" -set D_ARGS="-Djogl.debug.GLMediaPlayer" +REM set D_ARGS="-Djogl.debug.GLMediaPlayer" REM set D_ARGS="-Djogl.debug.GLMediaPlayer" "-Djogl.debug.AudioSink" REM set D_ARGS="-Djogl.debug.GLMediaPlayer" "-Djogl.debug.GLMediaPlayer.Native" REM set D_ARGS="-Djogl.debug.GLMediaPlayer.StreamWorker.delay=25" "-Djogl.debug.GLMediaPlayer" diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh index ce8005821..56a07e768 100644 --- a/make/scripts/tests.sh +++ b/make/scripts/tests.sh @@ -84,6 +84,17 @@ function jrun() { #D_ARGS="-Djogl.debug.DebugGL" #D_ARGS="-Djogl.debug.TraceGL" #D_ARGS="-Djogl.debug.DebugGL -Djogl.debug.TraceGL" + + #D_ARGS="-Djogamp.debug=all" + #D_ARGS="-Dnativewindow.debug=all" + #D_ARGS="-Djogl.debug=all" + #D_ARGS="-Dnewt.debug=all" + #D_ARGS="-Djogl.debug=all -Dnewt.debug=all" + D_ARGS="-Djogl.debug=all -Dnativewindow.debug=all" + #D_ARGS="-Djogamp.debug=all -Dnativewindow.debug=all -Djogl.debug=all -Dnewt.debug=all" + #D_ARGS="-Dnativewindow.debug=all -Djogl.debug=all -Dnewt.debug=all" + #D_ARGS="-Djogl.debug=all -Dnativewindow.debug=all -Dnewt.debug=all -Djogamp.debug.Lock" + #D_ARGS="-Dnativewindow.debug.X11Util.ATI_HAS_NO_XCLOSEDISPLAY_BUG" #D_ARGS="-Dnativewindow.debug.X11Util.ATI_HAS_NO_MULTITHREADING_BUG" #D_ARGS="-Djogl.disable.opengles" @@ -93,7 +104,7 @@ function jrun() { #D_ARGS="-Djogl.debug.FBObject" #D_ARGS="-Djogl.debug.GLSLCode" #D_ARGS="-Djogl.debug.GLSLCode -Djogl.debug.DebugGL" - #D_ARGS="-Djogl.debug=all -Dnewt.debug=all" + #D_ARGS="-Dnativewindow.debug.X11Util -Dnativewindow.debug.X11Util.TraceDisplayLifecycle -Djogl.debug.EGLDisplayUtil -Djogl.debug.GLDrawable" #D_ARGS="-Djogl.debug.GLContext -Dnativewindow.debug.JAWT -Dnewt.debug.Window" #D_ARGS="-Dnativewindow.debug.JAWT -Djogamp.debug.TaskBase.TraceSource" #D_ARGS="-Djogl.debug.GLContext.TraceSwitch" @@ -110,10 +121,6 @@ function jrun() { #D_ARGS="-Dnativewindow.debug.GraphicsConfiguration" #D_ARGS="-Djogl.debug.GLContext" #D_ARGS="-Djogl.debug.GLContext.NoProfileAliasing" - #D_ARGS="-Djogamp.debug=all" - #D_ARGS="-Djogamp.debug=all -Dnativewindow.debug=all -Djogl.debug=all -Dnewt.debug=all" - #D_ARGS="-Dnativewindow.debug=all -Djogl.debug=all -Dnewt.debug=all" - #D_ARGS="-Dnativewindow.debug.X11Util -Dnativewindow.debug.X11Util.TraceDisplayLifecycle -Djogl.debug.EGLDisplayUtil -Djogl.debug.GLDrawable" #D_ARGS="-Djogl.debug.GLDrawable -Dnativewindow.debug.X11Util -Dnativewindow.debug.NativeWindow -Dnewt.debug.Display -Dnewt.debug.Screen -Dnewt.debug.Window" #D_ARGS="-Djogl.debug.Animator -Djogl.debug.GLDrawable -Dnativewindow.debug.NativeWindow" #D_ARGS="-Djogl.debug=all -Dnewt.debug=all" @@ -122,8 +129,6 @@ function jrun() { #D_ARGS="-Djogl.debug.GLDrawable" #D_ARGS="-Djogl.debug.GLEventListenerState" #D_ARGS="-Djogl.fbo.force.none" - #D_ARGS="-Djogl.debug=all -Dnativewindow.debug=all -Dnewt.debug=all -Djogamp.debug.Lock" - #D_ARGS="-Djogl.debug=all" #D_ARGS="-Djogl.debug.EGLDrawableFactory.DontQuery -Djogl.debug.GLDrawable" #D_ARGS="-Djogl.debug.EGLDrawableFactory.QueryNativeTK -Djogl.debug.GLDrawable" #D_ARGS="-Djogl.debug.GLDebugMessageHandler" @@ -137,7 +142,7 @@ function jrun() { #D_ARGS="-Djogamp.debug.IOUtil -Djogl.debug.GLSLCode -Djogl.debug.GLMediaPlayer" #D_ARGS="-Djogl.debug.GLMediaPlayer -Djogl.debug.AudioSink" #D_ARGS="-Djogl.debug.GLMediaPlayer -Djogl.debug.GLMediaPlayer.Native" - D_ARGS="-Djogl.debug.GLMediaPlayer" + #D_ARGS="-Djogl.debug.GLMediaPlayer" #D_ARGS="-Djogl.debug.GLMediaPlayer.StreamWorker.delay=25 -Djogl.debug.GLMediaPlayer" #D_ARGS="-Djogl.debug.GLMediaPlayer.Native" #D_ARGS="-Djogl.debug.AudioSink" @@ -201,7 +206,6 @@ function jrun() { #D_ARGS="-Dnewt.debug.Window -Dnewt.debug.Window.MouseEvent -Dnewt.debug.Window.KeyEvent" #D_ARGS="-Dnewt.debug.Window" #D_ARGS="-Xprof" - #D_ARGS="-Dnativewindow.debug=all" #D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.Java2D -Djogl.debug.GLJPanel" #D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.Java2D -Djogl.debug.GLJPanel -Djogl.gljpanel.noglsl" #D_ARGS="-Djogl.debug.GLJPanel -Djogl.debug.DebugGL" @@ -225,7 +229,6 @@ function jrun() { #D_ARGS="-Dnewt.debug=all -Djogamp.debug.Lock -Djogamp.debug.Lock.TraceLock" #D_ARGS="-Djogl.debug.GLContext -Dnewt.debug=all -Djogamp.debug.Lock -Djogamp.common.utils.locks.Lock.timeout=10000" #D_ARGS="-Djogl.debug.GLContext -Dnewt.debug=all" - #D_ARGS="-Dnewt.debug=all" #D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.GLJPanel -Djogl.debug.TileRenderer -Djogl.debug.TileRenderer.PNG" #D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.GLJPanel -Djogl.debug.TileRenderer" #D_ARGS="-Djogl.debug.PNGImage" @@ -322,7 +325,7 @@ function testawtswt() { #testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2GLJPanelsAWT $* #testawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasAWT $* #testawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestLandscapeES2NewtCanvasAWT $* -#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $* +testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile00NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestLandscapeES2NEWT $* #testawtswt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasSWT $* @@ -345,7 +348,7 @@ function testawtswt() { # #testnoawt jogamp.opengl.openal.av.ALDummyUsage $* #testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieCube $* -testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSimple $* +#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSimple $* # # performance tests diff --git a/src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java b/src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java index bab4b5c6e..a872e63d8 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java +++ b/src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java @@ -59,7 +59,7 @@ public class GDIUtil implements ToolkitProperties { if( !initIDs0() ) { throw new NativeWindowException("GDI: Could not initialized native stub"); } - dummyWindowClassFactory = new RegisteredClassFactory(dummyWindowClassNameBase, getDummyWndProc0()); + dummyWindowClassFactory = new RegisteredClassFactory(dummyWindowClassNameBase, getDummyWndProc0(), true /* useDummyDispatchThread */); if(DEBUG) { System.out.println("GDI.initSingleton() dummyWindowClassFactory "+dummyWindowClassFactory); } @@ -98,8 +98,7 @@ public class GDIUtil implements ToolkitProperties { System.out.println("GDI.CreateDummyWindow() dummyWindowClassFactory "+dummyWindowClassFactory); System.out.println("GDI.CreateDummyWindow() dummyWindowClass "+dummyWindowClass); } - // FIXME return CreateDummyWindow0(dummyWindowClass.getHInstance(), dummyWindowClass.getName(), dummyWindowClass.getName(), x, y, width, height); - return CreateDummyWindowAndMessageLoop(dummyWindowClass.getHInstance(), dummyWindowClass.getName(), dummyWindowClass.getName(), x, y, width, height); + return CreateDummyWindow0(dummyWindowClass.getHInstance(), dummyWindowClass.getName(), dummyWindowClass.getHDispThreadContext(), dummyWindowClass.getName(), x, y, width, height); } } @@ -109,8 +108,7 @@ public class GDIUtil implements ToolkitProperties { if( null == dummyWindowClass ) { throw new InternalError("GDI Error ("+dummyWindowClassFactory.getSharedRefCount()+"): SharedClass is null"); } - // FIXME res = GDI.DestroyWindow(hwnd); - res = SendCloseMessage(hwnd); + res = DestroyWindow0(dummyWindowClass.getHDispThreadContext(), hwnd); dummyWindowClassFactory.releaseSharedClass(); } return res; @@ -128,8 +126,11 @@ public class GDIUtil implements ToolkitProperties { return IsChild0(win); } - public static native boolean CreateWindowClass(long hInstance, String clazzName, long wndProc); - public static native boolean DestroyWindowClass(long hInstance, String className); + private static final void dumpStack() { Thread.dumpStack(); } // Callback for JNI + + static native boolean CreateWindowClass0(long hInstance, String clazzName, long wndProc); + static native boolean DestroyWindowClass0(long hInstance, String className, long dispThreadCtx); + static native long CreateDummyDispatchThread0(); private static native boolean initIDs0(); private static native long getDummyWndProc0(); @@ -137,8 +138,6 @@ public class GDIUtil implements ToolkitProperties { private static native boolean IsChild0(long win); private static native boolean IsUndecorated0(long win); - private static native long CreateDummyWindow0(long hInstance, String className, String windowName, int x, int y, int width, int height); - - private static native long CreateDummyWindowAndMessageLoop(long hInstance, String className, String windowName, int x, int y, int width, int height); - private static native boolean SendCloseMessage(long win); + private static native long CreateDummyWindow0(long hInstance, String className, long dispThreadCtx, String windowName, int x, int y, int width, int height); + private static native boolean DestroyWindow0(long dispThreadCtx, long win); } diff --git a/src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClass.java b/src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClass.java index 976693e3a..1f6cb7c05 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClass.java +++ b/src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClass.java @@ -29,12 +29,14 @@ package jogamp.nativewindow.windows; public class RegisteredClass { - long hInstance; - String className; + private final long hInstance; + private final String className; + private final long hDDTCtx; - RegisteredClass(long hInst, String name) { - hInstance = hInst; - className = name; + RegisteredClass(long hInst, String name, long hDispatchThreadCtx) { + this.hInstance = hInst; + this.className = name; + this.hDDTCtx = hDispatchThreadCtx; } /** Application handle, same as {@link RegisteredClassFactory#getHInstance()}. */ @@ -43,6 +45,9 @@ public class RegisteredClass { /** Unique Window Class Name */ public final String getName() { return className; } + /** Unique associated dispatch thread context for this Window Class, or 0 for none. */ + public final long getHDispThreadContext() { return hDDTCtx; } + @Override - public final String toString() { return "RegisteredClass[handle 0x"+Long.toHexString(hInstance)+", "+className+"]"; } + public final String toString() { return "RegisteredClass[handle 0x"+Long.toHexString(hInstance)+", "+className+", dtx 0x"+Long.toHexString(hDDTCtx)+"]"; } } diff --git a/src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClassFactory.java b/src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClassFactory.java index 19a48d3bf..ee41fe192 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClassFactory.java +++ b/src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClassFactory.java @@ -49,6 +49,7 @@ public class RegisteredClassFactory { private final String classBaseName; private final long wndProc; + private final boolean useDummyDispatchThread; private RegisteredClass sharedClass = null; private int classIter = 0; @@ -59,24 +60,29 @@ public class RegisteredClassFactory { @Override public final String toString() { return "RegisteredClassFactory[moduleHandle "+toHexString(hInstance)+", "+classBaseName+ - ", wndProc "+toHexString(wndProc)+", shared[refCount "+sharedRefCount+", class "+sharedClass+"]]"; } + ", wndProc "+toHexString(wndProc)+", useDDT "+useDummyDispatchThread+", shared[refCount "+sharedRefCount+", class "+sharedClass+"]]"; } /** * Release the {@link RegisteredClass} of all {@link RegisteredClassFactory}. */ public static void shutdownSharedClasses() { synchronized(registeredFactories) { + if( DEBUG ) { + System.err.println("RegisteredClassFactory.shutdownSharedClasses: "+registeredFactories.size()); + } for(int j=0; j +#include static const char * const ClazzNameRuntimeException = "java/lang/RuntimeException"; static jclass runtimeExceptionClz=NULL; @@ -106,3 +107,9 @@ JNIEnv* NativewindowCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int as return curEnv; } +int64_t NativewindowCommon_CurrentTimeMillis() { + struct timeval tv; + gettimeofday(&tv,NULL); + return (int64_t)tv.tv_sec * 1000 + tv.tv_usec / 1000; +} + diff --git a/src/nativewindow/native/NativewindowCommon.h b/src/nativewindow/native/NativewindowCommon.h index a2975f3fd..a23fad9fd 100644 --- a/src/nativewindow/native/NativewindowCommon.h +++ b/src/nativewindow/native/NativewindowCommon.h @@ -4,6 +4,7 @@ #include #include +#include int NativewindowCommon_init(JNIEnv *env); @@ -15,4 +16,6 @@ void NativewindowCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, . JNIEnv* NativewindowCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int asDaemon, int * shallBeDetached); +int64_t NativewindowCommon_CurrentTimeMillis(); + #endif diff --git a/src/nativewindow/native/win32/GDImisc.c b/src/nativewindow/native/win32/GDImisc.c index d3ac3873c..b55988c11 100644 --- a/src/nativewindow/native/win32/GDImisc.c +++ b/src/nativewindow/native/win32/GDImisc.c @@ -20,8 +20,10 @@ #ifdef VERBOSE_ON #define DBG_PRINT(args...) fprintf(stderr, args); + #define DBG_PRINT_FLUSH(args...) fprintf(stderr, args); fflush(stderr); #else #define DBG_PRINT(args...) + #define DBG_PRINT_FLUSH(args...) #endif static const char * const ClazzNamePoint = "javax/media/nativewindow/util/Point"; @@ -30,12 +32,17 @@ static const char * const ClazzNamePointCstrSignature = "(II)V"; static jclass pointClz = NULL; static jmethodID pointCstr = NULL; +static jmethodID dumpStackID = NULL; -static volatile DWORD threadid = 0; +typedef struct { + HANDLE threadHandle; + DWORD threadId; + volatile BOOL threadReady; + volatile BOOL threadDead; +} DummyThreadContext; -typedef struct ThreadParam_s -{ - jlong jHInstance; +typedef struct { + HINSTANCE hInstance; const TCHAR* wndClassName; const TCHAR* wndName; jint x; @@ -44,17 +51,88 @@ typedef struct ThreadParam_s jint height; volatile HWND hWnd; volatile BOOL threadReady; -} ThreadParam; +} DummyThreadCommand; #define TM_OPENWIN WM_APP+1 #define TM_CLOSEWIN WM_APP+2 #define TM_STOP WM_APP+3 -DWORD WINAPI ThreadFunc(LPVOID param) +static const char * sTM_OPENWIN = "TM_OPENWIN"; +static const char * sTM_CLOSEWIN = "TM_CLOSEWIN"; +static const char * sTM_STOP = "TM_STOP"; + +/** 3s timeout */ +static const int64_t TIME_OUT = 3000000; + +static jboolean DDT_CheckAlive(JNIEnv *env, const char *msg, DummyThreadContext *ctx) { + if( ctx->threadDead ) { + NativewindowCommon_throwNewRuntimeException(env, "DDT is dead at %s", msg); + return JNI_FALSE; + } else { + DBG_PRINT_FLUSH("*** DDT-Check ALIVE @ %s\n", msg); + return JNI_TRUE; + } +} + +static jboolean DDT_WaitUntilCreated(JNIEnv *env, DummyThreadContext *ctx, BOOL created) { + const int64_t t0 = NativewindowCommon_CurrentTimeMillis(); + int64_t t1 = t0; + if( created ) { + while( !ctx->threadReady && t1-t0 < TIME_OUT ) { + t1 = NativewindowCommon_CurrentTimeMillis(); + } + if( !ctx->threadReady ) { + NativewindowCommon_throwNewRuntimeException(env, "TIMEOUT (%d ms) while waiting for DDT CREATED", (int)(t1-t0)); + return JNI_FALSE; + } + DBG_PRINT_FLUSH("*** DDT-Check CREATED\n"); + } else { + while( !ctx->threadDead && t1-t0 < TIME_OUT ) { + t1 = NativewindowCommon_CurrentTimeMillis(); + } + if( !ctx->threadDead ) { + NativewindowCommon_throwNewRuntimeException(env, "TIMEOUT (%d ms) while waiting for DDT DESTROYED", (int)(t1-t0)); + return JNI_FALSE; + } + DBG_PRINT_FLUSH("*** DDT-Check DEAD\n"); + } + return JNI_TRUE; +} + +static jboolean DDT_WaitUntilReady(JNIEnv *env, const char *msg, DummyThreadCommand *cmd) { + const int64_t t0 = NativewindowCommon_CurrentTimeMillis(); + int64_t t1 = t0; + while( !cmd->threadReady && t1-t0 < TIME_OUT ) { + t1 = NativewindowCommon_CurrentTimeMillis(); + } + if( !cmd->threadReady ) { + NativewindowCommon_throwNewRuntimeException(env, "TIMEOUT (%d ms) while waiting for DDT %s", (int)(t1-t0), msg); + return JNI_FALSE; + } + DBG_PRINT_FLUSH("*** DDT-Check READY @ %s\n", msg); + return JNI_TRUE; +} + +static HWND DummyWindowCreate + (HINSTANCE hInstance, const TCHAR* wndClassName, const TCHAR* wndName, jint x, jint y, jint width, jint height) +{ + DWORD dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; + DWORD dwStyle = WS_OVERLAPPEDWINDOW; + HWND hWnd = CreateWindowEx( dwExStyle, + wndClassName, + wndName, + dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, + x, y, width, height, + NULL, NULL, hInstance, NULL ); + return hWnd; +} + +static DWORD WINAPI DummyDispatchThreadFunc(LPVOID param) { MSG msg; BOOL bRet; - ThreadParam *startupThreadParam = (ThreadParam*)param; + BOOL bEOL=FALSE; + DummyThreadContext *threadContext = (DummyThreadContext*)param; /* there can not be any messages for us now, as the creator waits for threadReady before continuing, but we must use this PeekMessage() to @@ -62,42 +140,40 @@ DWORD WINAPI ThreadFunc(LPVOID param) PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE); /* now we can safely say: we have a qeue and are ready to receive messages */ - startupThreadParam->threadReady = TRUE; - - while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0) { - if (bRet == -1) { - return 0; + // threadContext->threadId = GetCurrentThreadId(); + threadContext->threadDead = FALSE; + threadContext->threadReady = TRUE; + + while( !bEOL && (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0 ) { + if ( -1 == bRet ) { + fprintf(stderr, "DummyDispatchThread (id %d): GetMessage Error %d, werr %d\n", + (int)threadContext->threadId, (int)bRet, (int)GetLastError()); + fflush(stderr); + bEOL = TRUE; + break; // EOL } else { switch(msg.message) { case TM_OPENWIN: { - ThreadParam *tParam = (ThreadParam*)msg.wParam; - HINSTANCE hInstance = (HINSTANCE) (intptr_t) tParam->jHInstance; - DWORD dwExStyle; - DWORD dwStyle; - - dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; - dwStyle = WS_OVERLAPPEDWINDOW; - - HWND hwnd = CreateWindowEx( dwExStyle, - tParam->wndClassName, - tParam->wndName, - dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, - tParam->x, tParam->y, tParam->width, tParam->height, - NULL, NULL, hInstance, NULL ); - - tParam->hWnd = hwnd; + DummyThreadCommand *tParam = (DummyThreadCommand*)msg.wParam; + DBG_PRINT_FLUSH("*** DDT-Dispatch OPENWIN\n"); + tParam->hWnd = DummyWindowCreate(tParam->hInstance, tParam->wndClassName, tParam->wndName, tParam->x, tParam->y, tParam->width, tParam->height); tParam->threadReady = TRUE; } break; case TM_CLOSEWIN: { - ThreadParam *tParam = (ThreadParam*)msg.wParam; - HWND hwnd = tParam->hWnd; - DestroyWindow(hwnd); + DummyThreadCommand *tParam = (DummyThreadCommand*)msg.wParam; + DBG_PRINT_FLUSH("*** DDT-Dispatch CLOSEWIN\n"); + DestroyWindow(tParam->hWnd); tParam->threadReady = TRUE; } break; - case TM_STOP: - return 0; + case TM_STOP: { + DummyThreadCommand *tParam = (DummyThreadCommand*)msg.wParam; + DBG_PRINT_FLUSH("*** DDT-Dispatch STOP -> DEAD\n"); + tParam->threadReady = TRUE; + bEOL = TRUE; + } + break; // EOL default: TranslateMessage(&msg); DispatchMessage(&msg); @@ -105,8 +181,12 @@ DWORD WINAPI ThreadFunc(LPVOID param) } } } + /* dead */ + DBG_PRINT_FLUSH("*** DDT-Dispatch DEAD\n"); + threadContext->threadDead = TRUE; + ExitThread(0); return 0; -} /* ThreadFunc */ +} HINSTANCE GetApplicationHandle() { @@ -115,11 +195,48 @@ HINSTANCE GetApplicationHandle() { /* Java->C glue code: * Java package: jogamp.nativewindow.windows.GDIUtil - * Java method: boolean CreateWindowClass(long hInstance, java.lang.String clazzName, long wndProc) - * C function: BOOL CreateWindowClass(HANDLE hInstance, LPCSTR clazzName, HANDLE wndProc); + * Java method: long CreateDummyDispatchThread0() + */ +JNIEXPORT jlong JNICALL +Java_jogamp_nativewindow_windows_GDIUtil_CreateDummyDispatchThread0 + (JNIEnv *env, jclass _unused) +{ + DWORD threadId = 0; + DummyThreadContext * dispThreadCtx = calloc(1, sizeof(DummyThreadContext)); + + dispThreadCtx->threadHandle = CreateThread(NULL, 0, DummyDispatchThreadFunc, (LPVOID)dispThreadCtx, 0, &threadId); + if( NULL == dispThreadCtx->threadHandle || 0 == threadId ) { + const HANDLE threadHandle = dispThreadCtx->threadHandle; + if( NULL != threadHandle ) { + TerminateThread(threadHandle, 0); + } + free(dispThreadCtx); + NativewindowCommon_throwNewRuntimeException(env, "DDT CREATE failed handle %p, id %d, werr %d", + (void*)threadHandle, (int)threadId, (int)GetLastError()); + return (jlong)0; + } + if( JNI_FALSE == DDT_WaitUntilCreated(env, dispThreadCtx, TRUE) ) { + const HANDLE threadHandle = dispThreadCtx->threadHandle; + if( NULL != threadHandle ) { + TerminateThread(threadHandle, 0); + } + free(dispThreadCtx); + NativewindowCommon_throwNewRuntimeException(env, "DDT CREATE (ack) failed handle %p, id %d, werr %d", + (void*)threadHandle, (int)threadId, (int)GetLastError()); + return (jlong)0; + } + DBG_PRINT_FLUSH("*** DDT Created %d\n", (int)threadId); + dispThreadCtx->threadId = threadId; + return (jlong) (intptr_t) dispThreadCtx; +} + +/* Java->C glue code: + * Java package: jogamp.nativewindow.windows.GDIUtil + * Java method: boolean CreateWindowClass0(long hInstance, java.lang.String clazzName, long wndProc) + * C function: BOOL CreateWindowClass0(HANDLE hInstance, LPCSTR clazzName, HANDLE wndProc); */ JNIEXPORT jboolean JNICALL -Java_jogamp_nativewindow_windows_GDIUtil_CreateWindowClass +Java_jogamp_nativewindow_windows_GDIUtil_CreateWindowClass0 (JNIEnv *env, jclass _unused, jlong jHInstance, jstring jClazzName, jlong wndProc) { HINSTANCE hInstance = (HINSTANCE) (intptr_t) jHInstance; @@ -127,11 +244,6 @@ Java_jogamp_nativewindow_windows_GDIUtil_CreateWindowClass WNDCLASS wc; jboolean res; - if( 0 != threadid ) { - NativewindowCommon_throwNewRuntimeException(env, "Native threadid already created 0x%X", (int)threadid); - return JNI_FALSE; - } - #ifdef UNICODE clazzName = NewtCommon_GetNullTerminatedStringChars(env, jClazzName); #else @@ -164,31 +276,20 @@ Java_jogamp_nativewindow_windows_GDIUtil_CreateWindowClass (*env)->ReleaseStringUTFChars(env, jClazzName, clazzName); #endif - if( JNI_TRUE == res ) { - ThreadParam tParam = {0}; - - CreateThread(NULL, 0, ThreadFunc, (LPVOID)&tParam, 0, (DWORD *)&threadid); - if(threadid) { - while(!tParam.threadReady) { /* nop */ } - } else { - res = JNI_FALSE; - } - } - return res; } /* Java->C glue code: * Java package: jogamp.nativewindow.windows.GDIUtil - * Java method: boolean DestroyWindowClass(long hInstance, java.lang.String className) - * C function: BOOL DestroyWindowClass(HANDLE hInstance, LPCSTR className); + * Java method: boolean DestroyWindowClass0(long hInstance, java.lang.String className, long dispThreadCtx) */ JNIEXPORT jboolean JNICALL -Java_jogamp_nativewindow_windows_GDIUtil_DestroyWindowClass - (JNIEnv *env, jclass _unused, jlong jHInstance, jstring jClazzName) +Java_jogamp_nativewindow_windows_GDIUtil_DestroyWindowClass0 + (JNIEnv *env, jclass gdiClazz, jlong jHInstance, jstring jClazzName, jlong jDispThreadCtx) { HINSTANCE hInstance = (HINSTANCE) (intptr_t) jHInstance; const TCHAR* clazzName = NULL; + DummyThreadContext * dispThreadCtx = (DummyThreadContext *) (intptr_t) jDispThreadCtx; jboolean res; #ifdef UNICODE @@ -205,39 +306,73 @@ Java_jogamp_nativewindow_windows_GDIUtil_DestroyWindowClass (*env)->ReleaseStringUTFChars(env, jClazzName, clazzName); #endif - if( 0 == threadid ) { - NativewindowCommon_throwNewRuntimeException(env, "Native threadid zero 0x%X", (int)threadid); - return JNI_FALSE; - } + if( NULL != dispThreadCtx) { + const HANDLE threadHandle = dispThreadCtx->threadHandle; + const DWORD threadId = dispThreadCtx->threadId; + DummyThreadCommand tParam = {0}; + tParam.threadReady = FALSE; + DBG_PRINT_FLUSH("*** DDT Destroy %d\n", (int)threadId); +#ifdef VERBOSE_ON + (*env)->CallStaticVoidMethod(env, gdiClazz, dumpStackID); +#endif - PostThreadMessage(threadid, TM_STOP, 0, 0); + if( JNI_FALSE == DDT_CheckAlive(env, sTM_STOP, dispThreadCtx) ) { + free(dispThreadCtx); + NativewindowCommon_throwNewRuntimeException(env, "DDT %s (alive) failed handle %p, id %d, werr %d", + sTM_STOP, (void*)threadHandle, (int)threadId, (int)GetLastError()); + return JNI_FALSE; + } + if ( 0 != PostThreadMessage(dispThreadCtx->threadId, TM_STOP, (WPARAM)&tParam, 0) ) { + if( JNI_FALSE == DDT_WaitUntilReady(env, sTM_STOP, &tParam) ) { + if( NULL != threadHandle ) { + TerminateThread(threadHandle, 0); + } + free(dispThreadCtx); + NativewindowCommon_throwNewRuntimeException(env, "DDT Post %s (ack) failed handle %p, id %d, werr %d", + sTM_STOP, (void*)threadHandle, (int)threadId, (int)GetLastError()); + return JNI_FALSE; + } + if( JNI_FALSE == DDT_WaitUntilCreated(env, dispThreadCtx, FALSE) ) { + if( NULL != threadHandle ) { + TerminateThread(threadHandle, 0); + } + free(dispThreadCtx); + NativewindowCommon_throwNewRuntimeException(env, "DDT KILL %s (ack) failed handle %p, id %d, werr %d", + sTM_STOP, (void*)threadHandle, (int)threadId, (int)GetLastError()); + return JNI_FALSE; + } + free(dispThreadCtx); // free after proper DDT shutdown! + } else { + if( NULL != threadHandle ) { + TerminateThread(threadHandle, 0); + } + free(dispThreadCtx); + NativewindowCommon_throwNewRuntimeException(env, "DDT Post %s failed handle %p, id %d, werr %d", + sTM_STOP, (void*)threadHandle, (int)threadId, (int)GetLastError()); + return JNI_FALSE; + } + } return res; } /* Java->C glue code: * Java package: jogamp.nativewindow.windows.GDIUtil - * Java method: long CreateDummyWindowAndMessageLoop(long hInstance, java.lang.String className, java.lang.String windowName, int x, int y, int width, int height) - * C function: HANDLE CreateDummyWindowAndMessageLoop(HANDLE hInstance, LPCSTR className, LPCSTR windowName, int x, int y, int width, int height); + * Java method: long CreateDummyWindow0(long hInstance, java.lang.String className, jlong dispThreadCtx, java.lang.String windowName, int x, int y, int width, int height) */ JNIEXPORT jlong JNICALL -Java_jogamp_nativewindow_windows_GDIUtil_CreateDummyWindowAndMessageLoop - (JNIEnv *env, jclass _unused, jlong jHInstance, jstring jWndClassName, jstring jWndName, jint x, jint y, jint width, jint height) +Java_jogamp_nativewindow_windows_GDIUtil_CreateDummyWindow0 + (JNIEnv *env, jclass _unused, jlong jHInstance, jstring jWndClassName, jlong jDispThreadCtx, jstring jWndName, jint x, jint y, jint width, jint height) { - volatile HWND hWnd = 0; - ThreadParam tParam = {0}; - - if( 0 == threadid ) { - NativewindowCommon_throwNewRuntimeException(env, "Native threadid zero 0x%X", (int)threadid); - return JNI_FALSE; - } + DummyThreadContext * dispThreadCtx = (DummyThreadContext *) (intptr_t) jDispThreadCtx; + DummyThreadCommand tParam = {0}; - tParam.jHInstance = jHInstance; + tParam.hInstance = (HINSTANCE) (intptr_t) jHInstance; tParam.x = x; tParam.y = y; tParam.width = width; tParam.height = height; - tParam.hWnd = hWnd; + tParam.hWnd = 0; tParam.threadReady = FALSE; #ifdef UNICODE @@ -248,9 +383,37 @@ Java_jogamp_nativewindow_windows_GDIUtil_CreateDummyWindowAndMessageLoop tParam.wndName = (*env)->GetStringUTFChars(env, jWndName, NULL); #endif - PostThreadMessage(threadid, TM_OPENWIN, (WPARAM)&tParam, 0); - - while(!tParam.threadReady) { /* nop */ } + if( NULL == dispThreadCtx ) { + tParam.hWnd = DummyWindowCreate(tParam.hInstance, tParam.wndClassName, tParam.wndName, tParam.x, tParam.y, tParam.width, tParam.height); + } else { + const HANDLE threadHandle = dispThreadCtx->threadHandle; + const DWORD threadId = dispThreadCtx->threadId; + if( JNI_FALSE == DDT_CheckAlive(env, sTM_OPENWIN, dispThreadCtx) ) { + free(dispThreadCtx); + NativewindowCommon_throwNewRuntimeException(env, "DDT %s (alive) failed handle %p, id %d, werr %d", + sTM_OPENWIN, (void*)threadHandle, (int)threadId, (int)GetLastError()); + } else { + if( 0 != PostThreadMessage(dispThreadCtx->threadId, TM_OPENWIN, (WPARAM)&tParam, 0) ) { + if( JNI_FALSE == DDT_WaitUntilReady(env, sTM_OPENWIN, &tParam) ) { + if( NULL != threadHandle ) { + TerminateThread(threadHandle, 0); + } + free(dispThreadCtx); + tParam.hWnd = 0; + NativewindowCommon_throwNewRuntimeException(env, "DDT Post %s (ack) failed handle %p, id %d, werr %d", + sTM_OPENWIN, (void*)threadHandle, (int)threadId, (int)GetLastError()); + } + } else { + if( NULL != threadHandle ) { + TerminateThread(threadHandle, 0); + } + free(dispThreadCtx); + tParam.hWnd = 0; + NativewindowCommon_throwNewRuntimeException(env, "DDT Post %s to handle %p, id %d failed, werr %d", + sTM_OPENWIN, (void*)threadHandle, (int)threadId, (int)GetLastError()); + } + } + } #ifdef UNICODE free((void*) tParam.wndClassName); @@ -260,62 +423,66 @@ Java_jogamp_nativewindow_windows_GDIUtil_CreateDummyWindowAndMessageLoop (*env)->ReleaseStringUTFChars(env, jWndName, tParam.wndName); #endif - return (jlong) (intptr_t) hWnd; + return (jlong) (intptr_t) tParam.hWnd; } -/* Java->C glue code: - * Java package: jogamp.nativewindow.windows.GDIUtil - * Java method: long CreateDummyWindow0(long hInstance, java.lang.String className, java.lang.String windowName, int x, int y, int width, int height) - * C function: HANDLE CreateDummyWindow0(HANDLE hInstance, LPCSTR className, LPCSTR windowName, int x, int y, int width, int height); +/* + * Class: jogamp_nativewindow_windows_GDIUtil + * Method: DestroyWindow0 */ -JNIEXPORT jlong JNICALL -Java_jogamp_nativewindow_windows_GDIUtil_CreateDummyWindow0 - (JNIEnv *env, jclass _unused, jlong jHInstance, jstring jWndClassName, jstring jWndName, jint x, jint y, jint width, jint height) +JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_windows_GDIUtil_DestroyWindow0 +(JNIEnv *env, jclass unused, jlong jDispThreadCtx, jlong jwin) { - HINSTANCE hInstance = (HINSTANCE) (intptr_t) jHInstance; - const TCHAR* wndClassName = NULL; - const TCHAR* wndName = NULL; - DWORD dwExStyle; - DWORD dwStyle; - HWND hWnd; - -#ifdef UNICODE - wndClassName = NewtCommon_GetNullTerminatedStringChars(env, jWndClassName); - wndName = NewtCommon_GetNullTerminatedStringChars(env, jWndName); -#else - wndClassName = (*env)->GetStringUTFChars(env, jWndClassName, NULL); - wndName = (*env)->GetStringUTFChars(env, jWndName, NULL); -#endif - - dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; - dwStyle = WS_OVERLAPPEDWINDOW; - - hWnd = CreateWindowEx( dwExStyle, - wndClassName, - wndName, - dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, - x, y, width, height, - NULL, NULL, hInstance, NULL ); + jboolean res = JNI_TRUE; + DummyThreadContext * dispThreadCtx = (DummyThreadContext *) (intptr_t) jDispThreadCtx; + HWND hWnd = (HWND) (intptr_t) jwin; + if( NULL == dispThreadCtx ) { + DestroyWindow(hWnd); + } else { + const HANDLE threadHandle = dispThreadCtx->threadHandle; + const DWORD threadId = dispThreadCtx->threadId; + DummyThreadCommand tParam = {0}; -#ifdef UNICODE - free((void*) wndClassName); - free((void*) wndName); -#else - (*env)->ReleaseStringUTFChars(env, jWndClassName, wndClassName); - (*env)->ReleaseStringUTFChars(env, jWndName, wndName); -#endif + tParam.hWnd = hWnd; + tParam.threadReady = FALSE; - return (jlong) (intptr_t) hWnd; + if( JNI_FALSE == DDT_CheckAlive(env, sTM_CLOSEWIN, dispThreadCtx) ) { + free(dispThreadCtx); + res = JNI_FALSE; + NativewindowCommon_throwNewRuntimeException(env, "DDT %s (alive) failed handle %p, id %d, werr %d", + sTM_CLOSEWIN, (void*)threadHandle, (int)threadId, (int)GetLastError()); + } else { + if ( 0 != PostThreadMessage(dispThreadCtx->threadId, TM_CLOSEWIN, (WPARAM)&tParam, 0) ) { + if( JNI_FALSE == DDT_WaitUntilReady(env, sTM_CLOSEWIN, &tParam) ) { + if( NULL != threadHandle ) { + TerminateThread(threadHandle, 0); + } + free(dispThreadCtx); + res = JNI_FALSE; + NativewindowCommon_throwNewRuntimeException(env, "DDT Post %s (ack) failed handle %p, id %d, werr %d", + sTM_CLOSEWIN, (void*)threadHandle, (int)threadId, (int)GetLastError()); + } + } else { + if( NULL != threadHandle ) { + TerminateThread(threadHandle, 0); + } + free(dispThreadCtx); + res = JNI_FALSE; + NativewindowCommon_throwNewRuntimeException(env, "DDT Post %s to handle %p, id %d failed, werr %d", + sTM_CLOSEWIN, (void*)threadHandle, (int)threadId, (int)GetLastError()); + } + } + } + return res; } - /* * Class: jogamp_nativewindow_windows_GDIUtil * Method: initIDs0 * Signature: ()Z */ JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_windows_GDIUtil_initIDs0 - (JNIEnv *env, jclass clazz) + (JNIEnv *env, jclass gdiClazz) { if(NativewindowCommon_init(env)) { jclass c = (*env)->FindClass(env, ClazzNamePoint); @@ -332,11 +499,15 @@ JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_windows_GDIUtil_initIDs0 NativewindowCommon_FatalError(env, "FatalError jogamp_nativewindow_windows_GDIUtil: can't fetch %s.%s %s", ClazzNamePoint, ClazzAnyCstrName, ClazzNamePointCstrSignature); } + dumpStackID = (*env)->GetStaticMethodID(env, gdiClazz, "dumpStack", "()V"); + if(NULL==dumpStackID) { + NativewindowCommon_FatalError(env, "FatalError jogamp_nativewindow_windows_GDIUtil: can't get method dumpStack"); + } } return JNI_TRUE; } -LRESULT CALLBACK DummyWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { +static LRESULT CALLBACK DummyWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { return DefWindowProc(hWnd,uMsg,wParam,lParam); } @@ -379,8 +550,8 @@ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_windows_GDIUtil_GetRelativeLo JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_windows_GDIUtil_IsChild0 (JNIEnv *env, jclass unused, jlong jwin) { - HWND hwnd = (HWND) (intptr_t) jwin; - LONG style = GetWindowLong(hwnd, GWL_STYLE); + HWND hWnd = (HWND) (intptr_t) jwin; + LONG style = GetWindowLong(hWnd, GWL_STYLE); BOOL bIsChild = 0 != (style & WS_CHILD) ; return bIsChild ? JNI_TRUE : JNI_FALSE; } @@ -392,34 +563,9 @@ JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_windows_GDIUtil_IsChild0 JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_windows_GDIUtil_IsUndecorated0 (JNIEnv *env, jclass unused, jlong jwin) { - HWND hwnd = (HWND) (intptr_t) jwin; - LONG style = GetWindowLong(hwnd, GWL_STYLE); + HWND hWnd = (HWND) (intptr_t) jwin; + LONG style = GetWindowLong(hWnd, GWL_STYLE); BOOL bIsUndecorated = 0 != (style & (WS_CHILD|WS_POPUP)) ; return bIsUndecorated ? JNI_TRUE : JNI_FALSE; } -/* - * Class: jogamp_nativewindow_windows_GDIUtil - * Method: SendCloseMessage - */ -JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_windows_GDIUtil_SendCloseMessage -(JNIEnv *env, jclass unused, jlong jwin) -{ - ThreadParam tParam = {0}; - volatile HWND hwnd = (HWND) (intptr_t) jwin; - - if( 0 == threadid ) { - NativewindowCommon_throwNewRuntimeException(env, "Native threadid zero 0x%X", (int)threadid); - return JNI_FALSE; - } - - tParam.hWnd = hwnd; - tParam.threadReady = FALSE; - - PostThreadMessage(threadid, TM_CLOSEWIN, (WPARAM)&tParam, 0); - - while(!tParam.threadReady) { /* nop */ } - - return JNI_TRUE; -} - diff --git a/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java index d8ff7ecb5..c4cfd98b3 100644 --- a/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java +++ b/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java @@ -51,7 +51,7 @@ public class DisplayDriver extends DisplayImpl { static { NEWTJNILibLoader.loadNEWT(); - sharedClassFactory = new RegisteredClassFactory(newtClassBaseName, WindowDriver.getNewtWndProc0()); + sharedClassFactory = new RegisteredClassFactory(newtClassBaseName, WindowDriver.getNewtWndProc0(), false /* useDummyDispatchThread */); if (!WindowDriver.initIDs0(RegisteredClassFactory.getHInstance())) { throw new NativeWindowException("Failed to initialize WindowsWindow jmethodIDs"); -- cgit v1.2.3 From 20b242387e6c329a2ba6261d39a05ffe9c39c6ab Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Sun, 5 Jan 2014 18:09:41 +0100 Subject: NativewindowCommon_init: Add define STDERR_TO_FILE (default undefined) to redirect stderr to file jogamp_stderr.log (Useful for Applets) --- src/nativewindow/native/NativewindowCommon.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/nativewindow/native/NativewindowCommon.c') diff --git a/src/nativewindow/native/NativewindowCommon.c b/src/nativewindow/native/NativewindowCommon.c index 212bdf82f..ec7ee7728 100644 --- a/src/nativewindow/native/NativewindowCommon.c +++ b/src/nativewindow/native/NativewindowCommon.c @@ -3,6 +3,8 @@ #include #include +// #define STDERR_TO_FILE 1 + static const char * const ClazzNameRuntimeException = "java/lang/RuntimeException"; static jclass runtimeExceptionClz=NULL; @@ -42,6 +44,11 @@ int NativewindowCommon_init(JNIEnv *env) { if(NULL==runtimeExceptionClz) { NativewindowCommon_FatalError(env, "Nativewindow: can't use %s", ClazzNameRuntimeException); } + #ifdef STDERR_TO_FILE + FILE * old_stderr = stderr; + FILE * new_stderr = freopen("jogamp_stderr.log", "w", stderr); + fprintf(stderr, "STDERR_TO_FILE: %p -> %p\n", old_stderr, new_stderr); + #endif return 1; } return 0; -- cgit v1.2.3 From 6647b4a63866a554c738e0b7b61e6dc40a6fb511 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Sat, 11 Jan 2014 02:11:47 +0100 Subject: [Jogl|Nativewindow|Newt]Common: Align all *Common_GetJNIEnv()/_ReleaseJNIEnv() Methods and Usage / Check arguments .. Since we still don't use inter-module native code sharing, align the JNIEnv get/release methods and usage. Most beneficary here is OSX and the GLDebugMessageHandle, both managed the JVM handle on their own - removed now. Also ensuring that *Common_init(..) is called for all modules on all platforms. --- src/jogl/native/GLContext.c | 2 +- src/jogl/native/GLDebugMessageHandler.c | 95 ++++--------- src/jogl/native/JoglCommon.c | 97 ++++++------- src/jogl/native/JoglCommon.h | 55 ++++++-- src/jogl/native/libav/ffmpeg_impl_template.c | 4 +- .../macosx/MacOSXWindowSystemInterface-calayer.m | 1 + .../jogamp_opengl_util_av_impl_OMXGLMediaPlayer.c | 5 +- src/nativewindow/native/NativewindowCommon.c | 110 ++++++++++----- src/nativewindow/native/NativewindowCommon.h | 61 ++++++++- src/nativewindow/native/macosx/OSXmisc.m | 34 ++--- src/nativewindow/native/win32/GDImisc.c | 2 +- src/nativewindow/native/x11/Xmisc.c | 126 +++++++---------- src/newt/native/MacWindow.m | 13 +- src/newt/native/NewtCommon.c | 96 +++++++++---- src/newt/native/NewtCommon.h | 26 ++-- src/newt/native/NewtMacWindow.h | 10 -- src/newt/native/NewtMacWindow.m | 152 ++++++--------------- 17 files changed, 431 insertions(+), 458 deletions(-) (limited to 'src/nativewindow/native/NativewindowCommon.c') diff --git a/src/jogl/native/GLContext.c b/src/jogl/native/GLContext.c index f10d0e421..9be9f82af 100644 --- a/src/jogl/native/GLContext.c +++ b/src/jogl/native/GLContext.c @@ -19,7 +19,7 @@ Java_jogamp_opengl_GLContextImpl_glGetStringInt(JNIEnv *env, jclass _unused, jin assert(ptr_glGetString != NULL); _res = (* ptr_glGetString) ((unsigned int) name); if (NULL == _res) return NULL; - return (*env)->NewStringUTF(env, _res); + return (*env)->NewStringUTF(env, (const char *)_res); } /* diff --git a/src/jogl/native/GLDebugMessageHandler.c b/src/jogl/native/GLDebugMessageHandler.c index 2e9d6033a..0aa7a01e7 100644 --- a/src/jogl/native/GLDebugMessageHandler.c +++ b/src/jogl/native/GLDebugMessageHandler.c @@ -49,8 +49,6 @@ JNIEXPORT jboolean JNICALL Java_jogamp_opengl_GLDebugMessageHandler_initIDs0 } typedef struct { - JavaVM *vm; - int version; jobject obj; int extType; } DebugHandlerType; @@ -60,39 +58,21 @@ typedef struct { static void GLDebugMessageARBCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, GLvoid *userParam) { DebugHandlerType * handle = (DebugHandlerType*) (intptr_t) userParam; - JavaVM *vm = handle->vm; - int version = handle->version; jobject obj = handle->obj; - JNIEnv *curEnv = NULL; - JNIEnv *newEnv = NULL; - int envRes ; - DBG_PRINT("GLDebugMessageARBCallback: 00 - %s, vm %p, version 0x%X, jobject %p, extType %d\n", - message, handle->vm, handle->version, (void*)handle->obj, handle->extType); - - // retrieve this thread's JNIEnv curEnv - or detect it's detached - envRes = (*vm)->GetEnv(vm, (void **) &curEnv, version) ; - DBG_PRINT("GLDebugMessageARBCallback: 01 - JVM Env: curEnv %p, res 0x%X\n", curEnv, envRes); - if( JNI_EDETACHED == envRes ) { - // detached thread - attach to JVM - if( JNI_OK != ( envRes = (*vm)->AttachCurrentThread(vm, (void**) &newEnv, NULL) ) ) { - fprintf(stderr, "GLDebugMessageARBCallback: can't attach thread: %d\n", envRes); - return; - } - curEnv = newEnv; - DBG_PRINT("GLDebugMessageARBCallback: 02 - attached .. \n"); - } else if( JNI_OK != envRes ) { - // oops .. - fprintf(stderr, "GLDebugMessageARBCallback: can't GetEnv: %d\n", envRes); + JNIEnv *env = NULL; + int shallBeDetached ; + DBG_PRINT("GLDebugMessageARBCallback: 00 - %s, jobject %p, extType %d\n", message, (void*)handle->obj, handle->extType); + + env = JoglCommon_GetJNIEnv (1 /* asDaemon */, &shallBeDetached); + if( NULL == env ) { + DBG_PRINT("GLDebugMessageARBCallback: Null JNIEnv\n"); return; } - (*curEnv)->CallVoidMethod(curEnv, obj, glDebugMessageARB, + (*env)->CallVoidMethod(env, obj, glDebugMessageARB, (jint) source, (jint) type, (jint) id, (jint) severity, - (*curEnv)->NewStringUTF(curEnv, message)); - if( NULL != newEnv ) { - // detached attached thread - (*vm)->DetachCurrentThread(vm); - DBG_PRINT("GLDebugMessageARBCallback: 04 - detached .. \n"); - } + (*env)->NewStringUTF(env, message)); + // detaching thread not required - daemon + // JoglCommon_ReleaseJNIEnv(shallBeDetached); DBG_PRINT("GLDebugMessageARBCallback: 0X\n"); /** * On Java 32bit on 64bit Windows and w/ GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB disables, @@ -104,39 +84,21 @@ static void GLDebugMessageARBCallback(GLenum source, GLenum type, GLuint id, GLe static void GLDebugMessageAMDCallback(GLuint id, GLenum category, GLenum severity, GLsizei length, const GLchar *message, GLvoid *userParam) { DebugHandlerType * handle = (DebugHandlerType*) (intptr_t) userParam; - JavaVM *vm = handle->vm; - int version = handle->version; jobject obj = handle->obj; - JNIEnv *curEnv = NULL; - JNIEnv *newEnv = NULL; - int envRes ; - DBG_PRINT("GLDebugMessageAMDCallback: 00 - %s, vm %p, version 0x%X, jobject %p, extType %d\n", - message, handle->vm, handle->version, (void*)handle->obj, handle->extType); - - // retrieve this thread's JNIEnv curEnv - or detect it's detached - envRes = (*vm)->GetEnv(vm, (void **) &curEnv, version) ; - DBG_PRINT("GLDebugMessageAMDCallback: 01 - JVM Env: curEnv %p, res 0x%X\n", curEnv, envRes); - if( JNI_EDETACHED == envRes ) { - // detached thread - attach to JVM - if( JNI_OK != ( envRes = (*vm)->AttachCurrentThread(vm, (void**) &newEnv, NULL) ) ) { - fprintf(stderr, "GLDebugMessageAMDCallback: can't attach thread: %d\n", envRes); - return; - } - curEnv = newEnv; - DBG_PRINT("GLDebugMessageAMDCallback: 02 - attached .. \n"); - } else if( JNI_OK != envRes ) { - // oops .. - fprintf(stderr, "GLDebugMessageAMDCallback: can't GetEnv: %d\n", envRes); + JNIEnv *env = NULL; + int shallBeDetached ; + DBG_PRINT("GLDebugMessageAMDCallback: 00 - %s, jobject %p, extType %d\n", message, (void*)handle->obj, handle->extType); + + env = JoglCommon_GetJNIEnv (1 /* asDaemon */, &shallBeDetached); + if( NULL == env ) { + DBG_PRINT("GLDebugMessageARBCallback: Null JNIEnv\n"); return; } - (*curEnv)->CallVoidMethod(curEnv, obj, glDebugMessageAMD, + (*env)->CallVoidMethod(env, obj, glDebugMessageAMD, (jint) id, (jint) category, (jint) severity, - (*curEnv)->NewStringUTF(curEnv, message)); - if( NULL != newEnv ) { - // detached attached thread - (*vm)->DetachCurrentThread(vm); - DBG_PRINT("GLDebugMessageAMDCallback: 04 - detached .. \n"); - } + (*env)->NewStringUTF(env, message)); + // detached attached thread not required - daemon + // JoglCommon_ReleaseJNIEnv(shallBeDetached); DBG_PRINT("GLDebugMessageAMDCallback: 0X\n"); /** * On Java 32bit on 64bit Windows, @@ -153,18 +115,10 @@ static void GLDebugMessageAMDCallback(GLuint id, GLenum category, GLenum severit JNIEXPORT jlong JNICALL Java_jogamp_opengl_GLDebugMessageHandler_register0 (JNIEnv *env, jobject obj, jlong procAddress, jint extType) { - JavaVM *vm; DebugHandlerType * handle = malloc(sizeof(DebugHandlerType)); - if(0 != (*env)->GetJavaVM(env, &vm)) { - vm = NULL; - JoglCommon_throwNewRuntimeException(env, "GetJavaVM failed"); - } - handle->vm = vm; - handle->version = (*env)->GetVersion(env); handle->obj = (*env)->NewGlobalRef(env, obj); handle->extType = extType; - DBG_PRINT("GLDebugMessageHandler.register0: vm %p, version 0x%X, jobject %p, extType %d\n", - handle->vm, handle->version, (void*)handle->obj, handle->extType); + DBG_PRINT("GLDebugMessageHandler.register0: jobject %p, extType %d\n", (void*)handle->obj, handle->extType); if(jogamp_opengl_GLDebugMessageHandler_EXT_ARB == extType) { _local_PFNGLDEBUGMESSAGECALLBACKARBPROC ptr_glDebugMessageCallbackARB; @@ -191,8 +145,7 @@ JNIEXPORT void JNICALL Java_jogamp_opengl_GLDebugMessageHandler_unregister0 { DebugHandlerType * handle = (DebugHandlerType*) (intptr_t) jhandle; - DBG_PRINT("GLDebugMessageHandler.unregister0: vm %p, version 0x%X, jobject %p, extType %d\n", - handle->vm, handle->version, (void*)handle->obj, handle->extType); + DBG_PRINT("GLDebugMessageHandler.unregister0: jobject %p, extType %d\n", (void*)handle->obj, handle->extType); if(JNI_FALSE == (*env)->IsSameObject(env, obj, handle->obj)) { JoglCommon_throwNewRuntimeException(env, "wrong handle (obj doesn't match)"); diff --git a/src/jogl/native/JoglCommon.c b/src/jogl/native/JoglCommon.c index 4170b13ec..e9984ada2 100644 --- a/src/jogl/native/JoglCommon.c +++ b/src/jogl/native/JoglCommon.c @@ -11,42 +11,38 @@ static JavaVM *_jvmHandle = NULL; static int _jvmVersion = 0; void JoglCommon_init(JNIEnv *env) { - if(NULL==runtimeExceptionClz) { + if(NULL==_jvmHandle) { + if(0 != (*env)->GetJavaVM(env, &_jvmHandle)) { + JoglCommon_FatalError(env, "JOGL: Can't fetch JavaVM handle"); + } else { + _jvmVersion = (*env)->GetVersion(env); + } jclass c = (*env)->FindClass(env, ClazzNameRuntimeException); if(NULL==c) { - JoglCommon_FatalError(env, "JOGL: can't find %s", ClazzNameRuntimeException); + JoglCommon_FatalError(env, "JOGL: Can't find %s", ClazzNameRuntimeException); } runtimeExceptionClz = (jclass)(*env)->NewGlobalRef(env, c); (*env)->DeleteLocalRef(env, c); if(NULL==runtimeExceptionClz) { - JoglCommon_FatalError(env, "JOGL: can't use %s", ClazzNameRuntimeException); + 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); - } } void JoglCommon_FatalError(JNIEnv *env, const char* msg, ...) { char buffer[512]; va_list ap; - int shallBeDetached = 0; - - if(NULL == env) { - env = JoglCommon_GetJNIEnv (&shallBeDetached); - } - va_start(ap, msg); - vsnprintf(buffer, sizeof(buffer), msg, ap); - va_end(ap); + if( NULL != msg ) { + va_start(ap, msg); + vsnprintf(buffer, sizeof(buffer), msg, ap); + va_end(ap); - fprintf(stderr, "%s\n", buffer); - if(NULL != env) { - (*env)->FatalError(env, buffer); - JoglCommon_ReleaseJNIEnv (shallBeDetached); + fprintf(stderr, "%s\n", buffer); + if(NULL != env) { + (*env)->FatalError(env, buffer); + } } } @@ -54,48 +50,42 @@ void JoglCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...) { char buffer[512]; va_list ap; - int shallBeDetached = 0; - if(NULL == env) { - env = JoglCommon_GetJNIEnv (&shallBeDetached); + if(NULL==_jvmHandle) { + JoglCommon_FatalError(env, "JOGL: NULL JVM handle, call JoglCommon_init 1st\n"); + return; } - va_start(ap, msg); - vsnprintf(buffer, sizeof(buffer), msg, ap); - va_end(ap); + if( NULL != msg ) { + va_start(ap, msg); + vsnprintf(buffer, sizeof(buffer), msg, ap); + va_end(ap); - if(NULL != env) { - (*env)->ThrowNew(env, runtimeExceptionClz, buffer); - JoglCommon_ReleaseJNIEnv (shallBeDetached); + if(NULL != env) { + (*env)->ThrowNew(env, runtimeExceptionClz, buffer); + } } } -JavaVM *JoglCommon_GetJVMHandle() { - return _jvmHandle; -} - -int JoglCommon_GetJVMVersion() { - return _jvmVersion; -} - jchar* JoglCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str) { jchar* strChars = NULL; - strChars = calloc((*env)->GetStringLength(env, str) + 1, sizeof(jchar)); - if (strChars != NULL) { - (*env)->GetStringRegion(env, str, 0, (*env)->GetStringLength(env, str), strChars); + if( NULL != env && 0 != str ) { + strChars = calloc((*env)->GetStringLength(env, str) + 1, sizeof(jchar)); + if (strChars != NULL) { + (*env)->GetStringRegion(env, str, 0, (*env)->GetStringLength(env, str), strChars); + } } return strChars; } -JNIEnv* JoglCommon_GetJNIEnv (int * shallBeDetached) -{ +JNIEnv* JoglCommon_GetJNIEnv (int asDaemon, int * shallBeDetached) { JNIEnv* curEnv = NULL; JNIEnv* newEnv = NULL; int envRes; - if(NULL == _jvmHandle) { - fprintf(stderr, "JOGL: No JavaVM handle registered, call JoglCommon_init(..) 1st"); + if(NULL==_jvmHandle) { + fprintf(stderr, "JOGL GetJNIEnv: NULL JVM handle, call JoglCommon_init 1st\n"); return NULL; } @@ -103,18 +93,23 @@ JNIEnv* JoglCommon_GetJNIEnv (int * shallBeDetached) 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); + if( asDaemon ) { + envRes = (*_jvmHandle)->AttachCurrentThreadAsDaemon(_jvmHandle, (void**) &newEnv, NULL); + } else { + envRes = (*_jvmHandle)->AttachCurrentThread(_jvmHandle, (void**) &newEnv, NULL); + } + if( JNI_OK != envRes ) { + fprintf(stderr, "JOGL GetJNIEnv: 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); + fprintf(stderr, "JOGL GetJNIEnv: Can't GetEnv: %d\n", envRes); return NULL; } if (curEnv==NULL) { - fprintf(stderr, "env is NULL\n"); + fprintf(stderr, "JOGL GetJNIEnv: env is NULL\n"); return NULL; } *shallBeDetached = NULL != newEnv; @@ -123,10 +118,8 @@ JNIEnv* JoglCommon_GetJNIEnv (int * shallBeDetached) void JoglCommon_ReleaseJNIEnv (int shallBeDetached) { if(NULL == _jvmHandle) { - fprintf(stderr, "JOGL: No JavaVM handle registered, call JoglCommon_init(..) 1st"); - } - - if(shallBeDetached) { + fprintf(stderr, "JOGL ReleaseJNIEnv: No JavaVM handle registered, call JoglCommon_init(..) 1st"); + } else if(shallBeDetached) { (*_jvmHandle)->DetachCurrentThread(_jvmHandle); } } diff --git a/src/jogl/native/JoglCommon.h b/src/jogl/native/JoglCommon.h index 023b4be03..2aeaf7d1d 100644 --- a/src/jogl/native/JoglCommon.h +++ b/src/jogl/native/JoglCommon.h @@ -1,3 +1,30 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ #ifndef JOGL_COMMON_H #define JOGL_COMMON_H 1 @@ -7,29 +34,25 @@ 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); -/** env may be NULL, in which case JoglCommon_GetJNIEnv() is being used. */ void JoglCommon_FatalError(JNIEnv *env, const char* msg, ...); - -/** env may be NULL, in which case JoglCommon_GetJNIEnv() is being used. */ 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(..)'. + * 1) Init static jvmHandle, jvmVersion and clazz references + * from an early initialization call w/ valid 'JNIEnv * env' + + JoglCommon_init(env); + * * 2) Use current thread JNIEnv or attach current thread to JVM, generating new JNIEnv * + + int asDaemon = 0; int shallBeDetached = 0; - JNIEnv* env = NewtCommon_GetJNIEnv(&shallBeDetached); + JNIEnv* env = JoglCommon_GetJNIEnv(asDaemon, &shallBeDetached); if(NULL==env) { DBG_PRINT("drawRect: null JNIEnv\n"); return; @@ -41,11 +64,13 @@ void JoglCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...); .. your JNIEnv code here .. * - * 4) Detach thread from JVM, if required + * 4) Detach thread from JVM if required, i.e. not attached as daemon! + * Not recommended for recurring _daemon_ threads (performance) * - JoglCommon_ReleaseJNIEnv (shallBeDetached); + JoglCommon_ReleaseJNIEnv(shallBeDetached); */ -JNIEnv* JoglCommon_GetJNIEnv (int * shallBeDetached); +JNIEnv* JoglCommon_GetJNIEnv (int asDaemon, int * shallBeDetached); + void JoglCommon_ReleaseJNIEnv (int shallBeDetached); #endif diff --git a/src/jogl/native/libav/ffmpeg_impl_template.c b/src/jogl/native/libav/ffmpeg_impl_template.c index 44acfe46a..e86b2a542 100644 --- a/src/jogl/native/libav/ffmpeg_impl_template.c +++ b/src/jogl/native/libav/ffmpeg_impl_template.c @@ -1499,7 +1499,7 @@ JNIEXPORT jint JNICALL FF_FUNC(seek0) int64_t pts1 = (int64_t) (pos1 * (int64_t) time_base.den) / (1000 * (int64_t) time_base.num); if(pAV->verbose) { - fprintf(stderr, "SEEK: vid %d, aid %d, pos0 %d, pos1 %d, pts: %"PRId64" -> %"PRId64"\n", pAV->vid, pAV->aid, pos0, pos1, pts0, pts1); + fprintf(stderr, "SEEK: vid %d, aid %d, pos0 %"PRId64", pos1 %d, pts: %"PRId64" -> %"PRId64"\n", pAV->vid, pAV->aid, pos0, pos1, pts0, pts1); } int flags = 0; if(pos1 < pos0) { @@ -1508,7 +1508,7 @@ JNIEXPORT jint JNICALL FF_FUNC(seek0) int res = -2; if(HAS_FUNC(sp_av_seek_frame)) { if(pAV->verbose) { - fprintf(stderr, "SEEK.0: pre : s %d / %"PRId64" -> t %d / %"PRId64"\n", pos0, pts0, pos1, pts1); + fprintf(stderr, "SEEK.0: pre : s %"PRId64" / %"PRId64" -> t %d / %"PRId64"\n", pos0, pts0, pos1, pts1); } sp_av_seek_frame(pAV->pFormatCtx, streamID, pts1, flags); } else if(HAS_FUNC(sp_avformat_seek_file)) { diff --git a/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m b/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m index 75917d2dc..7ce8c58cf 100644 --- a/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m +++ b/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m @@ -578,6 +578,7 @@ static const GLfloat gl_verts[] = { quirks, dedicatedFramePosSet, dedicatedFrameSizeSet, dedicatedLayoutSet, self, texWidth, texHeight, lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height, dFrame.origin.x, dFrame.origin.y, dFrame.size.width, dFrame.size.height); + (void)lRect; // silence if( dedicatedFrameSet ) { [super setFrame: dedicatedFrame]; diff --git a/src/jogl/native/openmax/jogamp_opengl_util_av_impl_OMXGLMediaPlayer.c b/src/jogl/native/openmax/jogamp_opengl_util_av_impl_OMXGLMediaPlayer.c index ec68a24aa..3166306ba 100644 --- a/src/jogl/native/openmax/jogamp_opengl_util_av_impl_OMXGLMediaPlayer.c +++ b/src/jogl/native/openmax/jogamp_opengl_util_av_impl_OMXGLMediaPlayer.c @@ -67,7 +67,7 @@ void OMXInstance_UpdateJavaAttributes(OMXToolBasicAV_t *pAV) return; } int shallBeDetached = 0; - JNIEnv * env = JoglCommon_GetJNIEnv (&shallBeDetached); + JNIEnv * env = JoglCommon_GetJNIEnv (1 /* daemon */, &shallBeDetached); if(NULL!=env) { (*env)->CallVoidMethod(env, (jobject)pAV->jni_instance, jni_mid_updateAttributes, pAV->width, pAV->height, @@ -75,7 +75,8 @@ void OMXInstance_UpdateJavaAttributes(OMXToolBasicAV_t *pAV) pAV->framerate, (uint32_t)(pAV->length*pAV->framerate), pAV->length, (*env)->NewStringUTF(env, pAV->videoCodec), (*env)->NewStringUTF(env, pAV->audioCodec) ); - JoglCommon_ReleaseJNIEnv (shallBeDetached); + // detaching thread not required - daemon + // JoglCommon_ReleaseJNIEnv(shallBeDetached); } } diff --git a/src/nativewindow/native/NativewindowCommon.c b/src/nativewindow/native/NativewindowCommon.c index ec7ee7728..e65f87272 100644 --- a/src/nativewindow/native/NativewindowCommon.c +++ b/src/nativewindow/native/NativewindowCommon.c @@ -8,41 +8,24 @@ static const char * const ClazzNameRuntimeException = "java/lang/RuntimeException"; static jclass runtimeExceptionClz=NULL; -void NativewindowCommon_FatalError(JNIEnv *env, const char* msg, ...) -{ - char buffer[512]; - va_list ap; - - va_start(ap, msg); - vsnprintf(buffer, sizeof(buffer), msg, ap); - va_end(ap); - - fprintf(stderr, "%s\n", buffer); - (*env)->FatalError(env, buffer); -} - -void NativewindowCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...) -{ - char buffer[512]; - va_list ap; - - va_start(ap, msg); - vsnprintf(buffer, sizeof(buffer), msg, ap); - va_end(ap); - - (*env)->ThrowNew(env, runtimeExceptionClz, buffer); -} +static JavaVM *_jvmHandle = NULL; +static int _jvmVersion = 0; int NativewindowCommon_init(JNIEnv *env) { - if(NULL==runtimeExceptionClz) { + if(NULL==_jvmHandle) { + if(0 != (*env)->GetJavaVM(env, &_jvmHandle)) { + NativewindowCommon_FatalError(env, "Nativewindow: Can't fetch JavaVM handle"); + } else { + _jvmVersion = (*env)->GetVersion(env); + } jclass c = (*env)->FindClass(env, ClazzNameRuntimeException); if(NULL==c) { - NativewindowCommon_FatalError(env, "Nativewindow: can't find %s", ClazzNameRuntimeException); + NativewindowCommon_FatalError(env, "Nativewindow: Can't find %s", ClazzNameRuntimeException); } runtimeExceptionClz = (jclass)(*env)->NewGlobalRef(env, c); (*env)->DeleteLocalRef(env, c); if(NULL==runtimeExceptionClz) { - NativewindowCommon_FatalError(env, "Nativewindow: can't use %s", ClazzNameRuntimeException); + NativewindowCommon_FatalError(env, "Nativewindow: Can't use %s", ClazzNameRuntimeException); } #ifdef STDERR_TO_FILE FILE * old_stderr = stderr; @@ -54,6 +37,44 @@ int NativewindowCommon_init(JNIEnv *env) { return 0; } +void NativewindowCommon_FatalError(JNIEnv *env, const char* msg, ...) +{ + char buffer[512]; + va_list ap; + + if( NULL != msg ) { + va_start(ap, msg); + vsnprintf(buffer, sizeof(buffer), msg, ap); + va_end(ap); + + fprintf(stderr, "%s\n", buffer); + if(NULL != env) { + (*env)->FatalError(env, buffer); + } + } +} + +void NativewindowCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...) +{ + char buffer[512]; + va_list ap; + + if(NULL==_jvmHandle) { + NativewindowCommon_FatalError(env, "Nativewindow: NULL JVM handle, call NativewindowCommon_init 1st\n"); + return; + } + + if( NULL != msg ) { + va_start(ap, msg); + vsnprintf(buffer, sizeof(buffer), msg, ap); + va_end(ap); + + if(NULL != env) { + (*env)->ThrowNew(env, runtimeExceptionClz, buffer); + } + } +} + const char * NativewindowCommon_GetStaticStringMethod(JNIEnv *jniEnv, jclass clazz, jmethodID jGetStrID, char *dest, int destSize, const char *altText) { if(NULL != jniEnv && NULL != clazz && NULL != jGetStrID) { jstring jstr = (jstring) (*jniEnv)->CallStaticObjectMethod(jniEnv, clazz, jGetStrID); @@ -75,45 +96,60 @@ const char * NativewindowCommon_GetStaticStringMethod(JNIEnv *jniEnv, jclass cla jchar* NativewindowCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str) { jchar* strChars = NULL; - strChars = calloc((*env)->GetStringLength(env, str) + 1, sizeof(jchar)); - if (strChars != NULL) { - (*env)->GetStringRegion(env, str, 0, (*env)->GetStringLength(env, str), strChars); + if( NULL != env && 0 != str ) { + strChars = calloc((*env)->GetStringLength(env, str) + 1, sizeof(jchar)); + if (strChars != NULL) { + (*env)->GetStringRegion(env, str, 0, (*env)->GetStringLength(env, str), strChars); + } } return strChars; } -JNIEnv* NativewindowCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int asDaemon, int * shallBeDetached) { +JNIEnv* NativewindowCommon_GetJNIEnv (int asDaemon, int * shallBeDetached) { JNIEnv* curEnv = NULL; JNIEnv* newEnv = NULL; int envRes; + if(NULL==_jvmHandle) { + fprintf(stderr, "Nativewindow GetJNIEnv: NULL JVM handle, call NativewindowCommon_init 1st\n"); + return NULL; + } + // retrieve this thread's JNIEnv curEnv - or detect it's detached - envRes = (*jvmHandle)->GetEnv(jvmHandle, (void **) &curEnv, jvmVersion) ; + envRes = (*_jvmHandle)->GetEnv(_jvmHandle, (void **) &curEnv, _jvmVersion) ; if( JNI_EDETACHED == envRes ) { // detached thread - attach to JVM if( asDaemon ) { - envRes = (*jvmHandle)->AttachCurrentThreadAsDaemon(jvmHandle, (void**) &newEnv, NULL); + envRes = (*_jvmHandle)->AttachCurrentThreadAsDaemon(_jvmHandle, (void**) &newEnv, NULL); } else { - envRes = (*jvmHandle)->AttachCurrentThread(jvmHandle, (void**) &newEnv, NULL); + envRes = (*_jvmHandle)->AttachCurrentThread(_jvmHandle, (void**) &newEnv, NULL); } if( JNI_OK != envRes ) { - fprintf(stderr, "JNIEnv: can't attach thread: %d\n", envRes); + fprintf(stderr, "Nativewindow GetJNIEnv: 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); + fprintf(stderr, "Nativewindow GetJNIEnv: Can't GetEnv: %d\n", envRes); return NULL; } if (curEnv==NULL) { - fprintf(stderr, "env is NULL\n"); + fprintf(stderr, "Nativewindow GetJNIEnv: env is NULL\n"); return NULL; } *shallBeDetached = NULL != newEnv; return curEnv; } +void NativewindowCommon_ReleaseJNIEnv (int shallBeDetached) { + if(NULL == _jvmHandle) { + fprintf(stderr, "Nativewindow ReleaseJNIEnv: No JavaVM handle registered, call NativewindowCommon_init(..) 1st"); + } else if(shallBeDetached) { + (*_jvmHandle)->DetachCurrentThread(_jvmHandle); + } +} + int64_t NativewindowCommon_CurrentTimeMillis() { struct timeval tv; gettimeofday(&tv,NULL); diff --git a/src/nativewindow/native/NativewindowCommon.h b/src/nativewindow/native/NativewindowCommon.h index a23fad9fd..f19552e33 100644 --- a/src/nativewindow/native/NativewindowCommon.h +++ b/src/nativewindow/native/NativewindowCommon.h @@ -1,3 +1,30 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ #ifndef NATIVEWINDOW_COMMON_H #define NATIVEWINDOW_COMMON_H 1 @@ -14,7 +41,39 @@ jchar* NativewindowCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str) void NativewindowCommon_FatalError(JNIEnv *env, const char* msg, ...); void NativewindowCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...); -JNIEnv* NativewindowCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int asDaemon, int * shallBeDetached); +/** + * + * 1) Init static jvmHandle, jvmVersion and clazz references + * from an early initialization call w/ valid 'JNIEnv * env' + + NativewindowCommon_init(env); + + * + * 2) Use current thread JNIEnv or attach current thread to JVM, generating new JNIEnv + * + + int asDaemon = 0; + int shallBeDetached = 0; + JNIEnv* env = NewtCommon_GetJNIEnv(asDaemon, &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, i.e. not attached as daemon! + * Not recommended for recurring _daemon_ threads (performance) + * + NewtCommon_ReleaseJNIEnv(shallBeDetached); + */ +JNIEnv* NativewindowCommon_GetJNIEnv (int asDaemon, int * shallBeDetached); + +void NativewindowCommon_ReleaseJNIEnv (int shallBeDetached); int64_t NativewindowCommon_CurrentTimeMillis(); diff --git a/src/nativewindow/native/macosx/OSXmisc.m b/src/nativewindow/native/macosx/OSXmisc.m index 6a7952eaf..4887cc3cf 100644 --- a/src/nativewindow/native/macosx/OSXmisc.m +++ b/src/nativewindow/native/macosx/OSXmisc.m @@ -75,11 +75,9 @@ static const char * const ClazzNameInsetsCstrSignature = "(IIII)V"; static jclass insetsClz = NULL; static jmethodID insetsCstr = NULL; -static int _initialized=0; - JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0(JNIEnv *env, jclass _unused) { - if(0==_initialized) { + if( NativewindowCommon_init(env) ) { jclass c; c = (*env)->FindClass(env, ClazzNamePoint); if(NULL==c) { @@ -119,7 +117,6 @@ Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0(JNIEnv *env, jclass _unused) { if(NULL==runnableRunID) { NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't fetch %s.run()V", ClazzNameRunnable); } - _initialized=1; } return JNI_TRUE; } @@ -775,12 +772,10 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_Uns @interface MainRunnable : NSObject { - JavaVM *jvmHandle; - int jvmVersion; jobject runnableObj; } -- (id) initWithRunnable: (jobject)runnable jvmHandle: (JavaVM*)jvm jvmVersion: (int)jvmVers; +- (id) initWithRunnable: (jobject)runnable; - (void) jRun; #ifdef DBG_LIFECYCLE @@ -794,10 +789,8 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_Uns @implementation MainRunnable -- (id) initWithRunnable: (jobject)runnable jvmHandle: (JavaVM*)jvm jvmVersion: (int)jvmVers +- (id) initWithRunnable: (jobject)runnable { - jvmHandle = jvm; - jvmVersion = jvmVers; runnableObj = runnable; return [super init]; } @@ -805,7 +798,7 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_Uns - (void) jRun { int shallBeDetached = 0; - JNIEnv* env = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, 1 /* asDaemon */, &shallBeDetached); + JNIEnv* env = NativewindowCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached); DBG_PRINT2("MainRunnable.1 env: %d\n", (int)(NULL!=env)); if(NULL!=env) { DBG_PRINT2("MainRunnable.1.0\n"); @@ -813,11 +806,9 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_Uns DBG_PRINT2("MainRunnable.1.1\n"); (*env)->DeleteGlobalRef(env, runnableObj); - if (shallBeDetached) { - DBG_PRINT2("MainRunnable.1.3\n"); - // Keep attached on main thread ! - // (*jvmHandle)->DetachCurrentThread(jvmHandle); - } + DBG_PRINT2("MainRunnable.1.3\n"); + // detaching thread not required - daemon + // NativewindowCommon_ReleaseJNIEnv(shallBeDetached); } DBG_PRINT2("MainRunnable.X\n"); } @@ -861,17 +852,8 @@ static void RunOnThread (JNIEnv *env, jobject runnable, BOOL onMain, jint delayI if ( forkOnMain ) { jobject runnableObj = (*env)->NewGlobalRef(env, runnable); - JavaVM *jvmHandle = NULL; - int jvmVersion = 0; - - if(0 != (*env)->GetJavaVM(env, &jvmHandle)) { - jvmHandle = NULL; - } else { - jvmVersion = (*env)->GetVersion(env); - } - DBG_PRINT2( "RunOnThread.1.0\n"); - MainRunnable * mr = [[MainRunnable alloc] initWithRunnable: runnableObj jvmHandle: jvmHandle jvmVersion: jvmVersion]; + MainRunnable * mr = [[MainRunnable alloc] initWithRunnable: runnableObj]; if( onMain ) { [mr performSelectorOnMainThread:@selector(jRun) withObject:nil waitUntilDone:NO]; diff --git a/src/nativewindow/native/win32/GDImisc.c b/src/nativewindow/native/win32/GDImisc.c index e28f68e7d..bec1d4922 100644 --- a/src/nativewindow/native/win32/GDImisc.c +++ b/src/nativewindow/native/win32/GDImisc.c @@ -487,7 +487,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_windows_GDIUtil_DestroyWindo JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_windows_GDIUtil_initIDs0 (JNIEnv *env, jclass gdiClazz) { - if(NativewindowCommon_init(env)) { + if( NativewindowCommon_init(env) ) { jclass c = (*env)->FindClass(env, ClazzNamePoint); if(NULL==c) { NativewindowCommon_FatalError(env, "FatalError jogamp_nativewindow_windows_GDIUtil: can't find %s", ClazzNamePoint); diff --git a/src/nativewindow/native/x11/Xmisc.c b/src/nativewindow/native/x11/Xmisc.c index 5e6909f6e..247dc1311 100644 --- a/src/nativewindow/native/x11/Xmisc.c +++ b/src/nativewindow/native/x11/Xmisc.c @@ -113,68 +113,56 @@ static jmethodID pointCstr = NULL; static void _initClazzAccess(JNIEnv *env) { jclass c; - if(!NativewindowCommon_init(env)) return; - - getCurrentThreadNameID = (*env)->GetStaticMethodID(env, X11UtilClazz, "getCurrentThreadName", "()Ljava/lang/String;"); - if(NULL==getCurrentThreadNameID) { - NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't get method getCurrentThreadName"); - } - dumpStackID = (*env)->GetStaticMethodID(env, X11UtilClazz, "dumpStack", "()V"); - if(NULL==dumpStackID) { - NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't get method dumpStack"); - } - - c = (*env)->FindClass(env, ClazzNameBuffers); - if(NULL==c) { - NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't find %s", ClazzNameBuffers); - } - clazzBuffers = (jclass)(*env)->NewGlobalRef(env, c); - (*env)->DeleteLocalRef(env, c); - if(NULL==clazzBuffers) { - NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't use %s", ClazzNameBuffers); - } - c = (*env)->FindClass(env, ClazzNameByteBuffer); - if(NULL==c) { - NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't find %s", ClazzNameByteBuffer); - } - clazzByteBuffer = (jclass)(*env)->NewGlobalRef(env, c); - (*env)->DeleteLocalRef(env, c); - if(NULL==c) { - NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't use %s", ClazzNameByteBuffer); - } - - cstrBuffers = (*env)->GetStaticMethodID(env, clazzBuffers, - ClazzNameBuffersStaticCstrName, ClazzNameBuffersStaticCstrSignature); - if(NULL==cstrBuffers) { - NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't create %s.%s %s", - ClazzNameBuffers, ClazzNameBuffersStaticCstrName, ClazzNameBuffersStaticCstrSignature); - } + if( NativewindowCommon_init(env) ) { + getCurrentThreadNameID = (*env)->GetStaticMethodID(env, X11UtilClazz, "getCurrentThreadName", "()Ljava/lang/String;"); + if(NULL==getCurrentThreadNameID) { + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't get method getCurrentThreadName"); + } + dumpStackID = (*env)->GetStaticMethodID(env, X11UtilClazz, "dumpStack", "()V"); + if(NULL==dumpStackID) { + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't get method dumpStack"); + } - c = (*env)->FindClass(env, ClazzNamePoint); - if(NULL==c) { - NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't find %s", ClazzNamePoint); - } - pointClz = (jclass)(*env)->NewGlobalRef(env, c); - (*env)->DeleteLocalRef(env, c); - if(NULL==pointClz) { - NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't use %s", ClazzNamePoint); - } - pointCstr = (*env)->GetMethodID(env, pointClz, ClazzAnyCstrName, ClazzNamePointCstrSignature); - if(NULL==pointCstr) { - NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't fetch %s.%s %s", - ClazzNamePoint, ClazzAnyCstrName, ClazzNamePointCstrSignature); - } -} + c = (*env)->FindClass(env, ClazzNameBuffers); + if(NULL==c) { + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't find %s", ClazzNameBuffers); + } + clazzBuffers = (jclass)(*env)->NewGlobalRef(env, c); + (*env)->DeleteLocalRef(env, c); + if(NULL==clazzBuffers) { + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't use %s", ClazzNameBuffers); + } + c = (*env)->FindClass(env, ClazzNameByteBuffer); + if(NULL==c) { + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't find %s", ClazzNameByteBuffer); + } + clazzByteBuffer = (jclass)(*env)->NewGlobalRef(env, c); + (*env)->DeleteLocalRef(env, c); + if(NULL==c) { + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't use %s", ClazzNameByteBuffer); + } -static JavaVM *jvmHandle = NULL; -static int jvmVersion = 0; + cstrBuffers = (*env)->GetStaticMethodID(env, clazzBuffers, + ClazzNameBuffersStaticCstrName, ClazzNameBuffersStaticCstrSignature); + if(NULL==cstrBuffers) { + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't create %s.%s %s", + ClazzNameBuffers, ClazzNameBuffersStaticCstrName, ClazzNameBuffersStaticCstrSignature); + } -static void setupJVMVars(JNIEnv * env) { - if( NULL != env && NULL == jvmHandle ) { - if(0 != (*env)->GetJavaVM(env, &jvmHandle)) { - jvmHandle = NULL; + c = (*env)->FindClass(env, ClazzNamePoint); + if(NULL==c) { + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't find %s", ClazzNamePoint); + } + pointClz = (jclass)(*env)->NewGlobalRef(env, c); + (*env)->DeleteLocalRef(env, c); + if(NULL==pointClz) { + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't use %s", ClazzNamePoint); + } + pointCstr = (*env)->GetMethodID(env, pointClz, ClazzAnyCstrName, ClazzNamePointCstrSignature); + if(NULL==pointCstr) { + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't fetch %s.%s %s", + ClazzNamePoint, ClazzAnyCstrName, ClazzNamePointCstrSignature); } - jvmVersion = (*env)->GetVersion(env); } } @@ -201,8 +189,8 @@ static int x11ErrorHandler(Display *dpy, XErrorEvent *e) (int)e->request_code, (int)e->minor_code, reqCodeStr); fflush(stderr); - if( NULL != jvmHandle && ( errorHandlerDebug || errorHandlerThrowException ) ) { - jniEnv = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, 0 /* asDaemon */, &shallBeDetached); + if( errorHandlerDebug || errorHandlerThrowException ) { + jniEnv = NativewindowCommon_GetJNIEnv(0 /* asDaemon */, &shallBeDetached); if(NULL == jniEnv) { fprintf(stderr, "Nativewindow X11 Error: null JNIEnv"); fflush(stderr); @@ -219,9 +207,7 @@ static int x11ErrorHandler(Display *dpy, XErrorEvent *e) e->error_code, errCodeStr, e->display, (int)e->resourceid, (int)e->serial, (int)e->request_code, (int)e->minor_code, reqCodeStr); } - if (shallBeDetached) { - (*jvmHandle)->DetachCurrentThread(jvmHandle); - } + NativewindowCommon_ReleaseJNIEnv(shallBeDetached); } } @@ -233,7 +219,6 @@ static void NativewindowCommon_x11ErrorHandlerEnable(JNIEnv * env, Display *dpy, if(onoff) { if(force || NULL==origErrorHandler) { XErrorHandler prevErrorHandler; - setupJVMVars(env); prevErrorHandler = XSetErrorHandler(x11ErrorHandler); if(x11ErrorHandler != prevErrorHandler) { // if forced don't overwrite w/ orig w/ our handler origErrorHandler = prevErrorHandler; @@ -265,14 +250,10 @@ static int x11IOErrorHandler(Display *dpy) fprintf(stderr, "Nativewindow X11 IOError: Display %p (%s): %s\n", dpy, dpyName, errnoStr); fflush(stderr); - if( NULL != jvmHandle ) { - jniEnv = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, 0 /* asDaemon */, &shallBeDetached); - if (NULL != jniEnv) { - NativewindowCommon_FatalError(jniEnv, "Nativewindow X11 IOError: Display %p (%s): %s", dpy, dpyName, errnoStr); - if (shallBeDetached) { - (*jvmHandle)->DetachCurrentThread(jvmHandle); - } - } + jniEnv = NativewindowCommon_GetJNIEnv(0 /* asDaemon */, &shallBeDetached); + if (NULL != jniEnv) { + NativewindowCommon_FatalError(jniEnv, "Nativewindow X11 IOError: Display %p (%s): %s", dpy, dpyName, errnoStr); + NativewindowCommon_ReleaseJNIEnv(shallBeDetached); } if(NULL!=origIOErrorHandler) { origIOErrorHandler(dpy); @@ -283,7 +264,6 @@ static int x11IOErrorHandler(Display *dpy) static void x11IOErrorHandlerEnable(int onoff, JNIEnv * env) { if(onoff) { if(NULL==origIOErrorHandler) { - setupJVMVars(env); origIOErrorHandler = XSetIOErrorHandler(x11IOErrorHandler); } } else { diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index c6fd805a5..130b2e3e3 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -113,18 +113,6 @@ static void setJavaWindowObject(JNIEnv *env, jobject newJavaWindowObject, NewtVi DBG_PRINT( "setJavaWindowObject.2: View %p - Set new javaWindowObject %p\n", view, newJavaWindowObject); jobject globJavaWindowObject = (*env)->NewGlobalRef(env, newJavaWindowObject); [view setJavaWindowObject: globJavaWindowObject]; - { - JavaVM *jvmHandle = NULL; - int jvmVersion = 0; - - if(0 != (*env)->GetJavaVM(env, &jvmHandle)) { - jvmHandle = NULL; - } else { - jvmVersion = (*env)->GetVersion(env); - } - [view setJVMHandle: jvmHandle]; - [view setJVMVersion: jvmVersion]; - } } DBG_PRINT( "setJavaWindowObject.X: View %p\n", view); } @@ -979,6 +967,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_close0 BOOL isNewtWin = [mWin isKindOfClass:[NewtMacWindow class]]; NSWindow *pWin = [mWin parentWindow]; DBG_PRINT( "windowClose.0 - %p [isNSWindow %d, isNewtWin %d], parent %p\n", mWin, isNSWin, isNewtWin, pWin); + (void)isNSWin; // silence if( !isNewtWin ) { NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin); return; diff --git a/src/newt/native/NewtCommon.c b/src/newt/native/NewtCommon.c index c294b6e0b..231d6182f 100644 --- a/src/newt/native/NewtCommon.c +++ b/src/newt/native/NewtCommon.c @@ -5,17 +5,43 @@ static const char * const ClazzNameRuntimeException = "java/lang/RuntimeException"; static jclass runtimeExceptionClz=NULL; +static JavaVM *_jvmHandle = NULL; +static int _jvmVersion = 0; + +void NewtCommon_init(JNIEnv *env) { + if(NULL==_jvmHandle) { + if(0 != (*env)->GetJavaVM(env, &_jvmHandle)) { + NewtCommon_FatalError(env, "NEWT: Can't fetch JavaVM handle"); + } else { + _jvmVersion = (*env)->GetVersion(env); + } + jclass c = (*env)->FindClass(env, ClazzNameRuntimeException); + if(NULL==c) { + NewtCommon_FatalError(env, "NEWT: Can't find %s", ClazzNameRuntimeException); + } + runtimeExceptionClz = (jclass)(*env)->NewGlobalRef(env, c); + (*env)->DeleteLocalRef(env, c); + if(NULL==runtimeExceptionClz) { + NewtCommon_FatalError(env, "NEWT: Can't use %s", ClazzNameRuntimeException); + } + } +} + void NewtCommon_FatalError(JNIEnv *env, const char* msg, ...) { char buffer[512]; va_list ap; - va_start(ap, msg); - vsnprintf(buffer, sizeof(buffer), msg, ap); - va_end(ap); + if( NULL != msg ) { + va_start(ap, msg); + vsnprintf(buffer, sizeof(buffer), msg, ap); + va_end(ap); - fprintf(stderr, "%s\n", buffer); - (*env)->FatalError(env, buffer); + fprintf(stderr, "%s\n", buffer); + if(NULL != env) { + (*env)->FatalError(env, buffer); + } + } } void NewtCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...) @@ -23,23 +49,18 @@ void NewtCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...) char buffer[512]; va_list ap; - va_start(ap, msg); - vsnprintf(buffer, sizeof(buffer), msg, ap); - va_end(ap); + if(NULL==_jvmHandle) { + NewtCommon_FatalError(env, "NEWT: NULL JVM handle, call NewtCommon_init 1st\n"); + return; + } - (*env)->ThrowNew(env, runtimeExceptionClz, buffer); -} + if( NULL != msg ) { + va_start(ap, msg); + vsnprintf(buffer, sizeof(buffer), msg, ap); + va_end(ap); -void NewtCommon_init(JNIEnv *env) { - if(NULL==runtimeExceptionClz) { - jclass c = (*env)->FindClass(env, ClazzNameRuntimeException); - if(NULL==c) { - NewtCommon_FatalError(env, "NEWT: can't find %s", ClazzNameRuntimeException); - } - runtimeExceptionClz = (jclass)(*env)->NewGlobalRef(env, c); - (*env)->DeleteLocalRef(env, c); - if(NULL==runtimeExceptionClz) { - NewtCommon_FatalError(env, "NEWT: can't use %s", ClazzNameRuntimeException); + if(NULL != env) { + (*env)->ThrowNew(env, runtimeExceptionClz, buffer); } } } @@ -65,42 +86,57 @@ const char * NewtCommon_GetStaticStringMethod(JNIEnv *jniEnv, jclass clazz, jmet jchar* NewtCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str) { jchar* strChars = NULL; - strChars = calloc((*env)->GetStringLength(env, str) + 1, sizeof(jchar)); - if (strChars != NULL) { - (*env)->GetStringRegion(env, str, 0, (*env)->GetStringLength(env, str), strChars); + if( NULL != env && 0 != str ) { + strChars = calloc((*env)->GetStringLength(env, str) + 1, sizeof(jchar)); + if (strChars != NULL) { + (*env)->GetStringRegion(env, str, 0, (*env)->GetStringLength(env, str), strChars); + } } return strChars; } -JNIEnv* NewtCommon_GetJNIEnv(JavaVM * jvmHandle, int jvmVersion, int asDaemon, int * shallBeDetached) { +JNIEnv* NewtCommon_GetJNIEnv(int asDaemon, int * shallBeDetached) { JNIEnv* curEnv = NULL; JNIEnv* newEnv = NULL; int envRes; + if(NULL==_jvmHandle) { + fprintf(stderr, "NEWT GetJNIEnv: NULL JVM handle, call NewtCommon_init 1st\n"); + return NULL; + } + // retrieve this thread's JNIEnv curEnv - or detect it's detached - envRes = (*jvmHandle)->GetEnv(jvmHandle, (void **) &curEnv, jvmVersion) ; + envRes = (*_jvmHandle)->GetEnv(_jvmHandle, (void **) &curEnv, _jvmVersion) ; if( JNI_EDETACHED == envRes ) { // detached thread - attach to JVM if( asDaemon ) { - envRes = (*jvmHandle)->AttachCurrentThreadAsDaemon(jvmHandle, (void**) &newEnv, NULL); + envRes = (*_jvmHandle)->AttachCurrentThreadAsDaemon(_jvmHandle, (void**) &newEnv, NULL); } else { - envRes = (*jvmHandle)->AttachCurrentThread(jvmHandle, (void**) &newEnv, NULL); + envRes = (*_jvmHandle)->AttachCurrentThread(_jvmHandle, (void**) &newEnv, NULL); } if( JNI_OK != envRes ) { - fprintf(stderr, "JNIEnv: can't attach thread: %d\n", envRes); + fprintf(stderr, "NEWT GetJNIEnv: 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); + fprintf(stderr, "NEWT GetJNIEnv: Can't GetEnv: %d\n", envRes); return NULL; } if (curEnv==NULL) { - fprintf(stderr, "env is NULL\n"); + fprintf(stderr, "NEWT GetJNIEnv: env is NULL\n"); return NULL; } *shallBeDetached = NULL != newEnv; return curEnv; } +void NewtCommon_ReleaseJNIEnv (int shallBeDetached) { + if(NULL == _jvmHandle) { + fprintf(stderr, "NEWT ReleaseJNIEnv: No JavaVM handle registered, call NewtCommon_init(..) 1st"); + } else if(shallBeDetached) { + (*_jvmHandle)->DetachCurrentThread(_jvmHandle); + } +} + diff --git a/src/newt/native/NewtCommon.h b/src/newt/native/NewtCommon.h index 9cc9e93a6..43db72b5b 100644 --- a/src/newt/native/NewtCommon.h +++ b/src/newt/native/NewtCommon.h @@ -42,23 +42,18 @@ void NewtCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...); /** * - * 1) Store jvmHandle and jvmVersion + * 1) Init static jvmHandle, jvmVersion and clazz references + * from an early initialization call w/ valid 'JNIEnv * env' - JavaVM *jvmHandle = NULL; - int jvmVersion = 0; - - if(0 != (*env)->GetJavaVM(env, &jvmHandle)) { - jvmHandle = NULL; - } else { - jvmVersion = (*env)->GetVersion(env); - } + NewtCommon_init(env); * * 2) Use current thread JNIEnv or attach current thread to JVM, generating new JNIEnv * + int asDaemon = 0; int shallBeDetached = 0; - JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached); + JNIEnv* env = NewtCommon_GetJNIEnv(asDaemon, &shallBeDetached); if(NULL==env) { DBG_PRINT("drawRect: null JNIEnv\n"); return; @@ -70,12 +65,13 @@ void NewtCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...); .. your JNIEnv code here .. * - * 4) Detach thread from JVM, if required + * 4) Detach thread from JVM if required, i.e. not attached as daemon! + * Not recommended for recurring _daemon_ threads (performance) * - if (shallBeDetached) { - (*jvmHandle)->DetachCurrentThread(jvmHandle); - } + NativewindowCommon_ReleaseJNIEnv(shallBeDetached); */ -JNIEnv* NewtCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int asDaemon, int * shallBeDetached); +JNIEnv* NewtCommon_GetJNIEnv (int asDaemon, int * shallBeDetached); + +void NewtCommon_ReleaseJNIEnv (int shallBeDetached); #endif diff --git a/src/newt/native/NewtMacWindow.h b/src/newt/native/NewtMacWindow.h index daf75bec7..8f6362ac2 100644 --- a/src/newt/native/NewtMacWindow.h +++ b/src/newt/native/NewtMacWindow.h @@ -53,10 +53,6 @@ { jobject javaWindowObject; - // This is set while messages are being dispatched and cleared afterward - JavaVM *jvmHandle; - int jvmVersion; - volatile BOOL destroyNotifySent; volatile int softLockCount; pthread_mutex_t softLockSync; @@ -80,12 +76,6 @@ #endif - (void) dealloc; -/* Set during event dispatching cycle */ -- (void) setJVMHandle: (JavaVM*) vm; -- (JavaVM*) getJVMHandle; -- (void) setJVMVersion: (int) ver; -- (int) getJVMVersion; - /* Register or deregister (NULL) the java Window object, ie, if NULL, no events are send */ - (void) setJavaWindowObject: (jobject) javaWindowObj; diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m index 5ccd9c658..b4133ac7e 100644 --- a/src/newt/native/NewtMacWindow.m +++ b/src/newt/native/NewtMacWindow.m @@ -193,8 +193,6 @@ static jmethodID windowRepaintID = NULL; id res = [super initWithFrame:frameRect]; javaWindowObject = NULL; - jvmHandle = NULL; - jvmVersion = 0; destroyNotifySent = NO; softLockCount = 0; @@ -244,25 +242,6 @@ static jmethodID windowRepaintID = NULL; [super dealloc]; } -- (void) setJVMHandle: (JavaVM*) vm -{ - jvmHandle = vm; -} -- (JavaVM*) getJVMHandle -{ - return jvmHandle; -} - -- (void) setJVMVersion: (int) ver -{ - jvmVersion = ver; -} - -- (int) getJVMVersion -{ - return jvmVersion; -} - - (void) setJavaWindowObject: (jobject) javaWindowObj { javaWindowObject = javaWindowObj; @@ -342,7 +321,7 @@ static jmethodID windowRepaintID = NULL; return; } int shallBeDetached = 0; - JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, 1 /* asDaemon */, &shallBeDetached); + JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached); if(NULL==env) { DBG_PRINT("drawRect: null JNIEnv\n"); return; @@ -354,9 +333,8 @@ static jmethodID windowRepaintID = NULL; dirtyRect.origin.x, viewFrame.size.height - dirtyRect.origin.y, dirtyRect.size.width, dirtyRect.size.height); - /* if (shallBeDetached) { - (*jvmHandle)->DetachCurrentThread(jvmHandle); - } */ + // detaching thread not required - daemon + // NewtCommon_ReleaseJNIEnv(shallBeDetached); } - (void) viewDidHide @@ -366,7 +344,7 @@ static jmethodID windowRepaintID = NULL; return; } int shallBeDetached = 0; - JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, 1 /* asDaemon */, &shallBeDetached); + JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached); if(NULL==env) { DBG_PRINT("viewDidHide: null JNIEnv\n"); return; @@ -374,9 +352,8 @@ static jmethodID windowRepaintID = NULL; (*env)->CallVoidMethod(env, javaWindowObject, visibleChangedID, JNI_FALSE, JNI_FALSE); - /* if (shallBeDetached) { - (*jvmHandle)->DetachCurrentThread(jvmHandle); - } */ + // detaching thread not required - daemon + // NewtCommon_ReleaseJNIEnv(shallBeDetached); [super viewDidHide]; } @@ -388,7 +365,7 @@ static jmethodID windowRepaintID = NULL; return; } int shallBeDetached = 0; - JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, 1 /* asDaemon */, &shallBeDetached); + JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached); if(NULL==env) { DBG_PRINT("viewDidUnhide: null JNIEnv\n"); return; @@ -396,9 +373,8 @@ static jmethodID windowRepaintID = NULL; (*env)->CallVoidMethod(env, javaWindowObject, visibleChangedID, JNI_FALSE, JNI_TRUE); - /* if (shallBeDetached) { - (*jvmHandle)->DetachCurrentThread(jvmHandle); - } */ + // detaching thread not required - daemon + // NewtCommon_ReleaseJNIEnv(shallBeDetached); [super viewDidUnhide]; } @@ -645,14 +621,9 @@ static jmethodID windowRepaintID = NULL; return; } int shallBeDetached = 0; - JNIEnv* env; - if( NULL != jvmHandle ) { - env = NewtCommon_GetJNIEnv(jvmHandle, [self getJVMVersion], 1 /* asDaemon */, &shallBeDetached); - } else { - env = NULL; - } + JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached); if(NULL==env) { - DBG_PRINT("sendMouseEvent: JVM %p JNIEnv %p\n", jvmHandle, env); + DBG_PRINT("sendMouseEvent: null JNIEnv\n"); return; } jint javaMods[] = { 0 } ; @@ -700,9 +671,8 @@ static jmethodID windowRepaintID = NULL; (jint) location.x, (jint) location.y, javaButtonNum, scrollDeltaY); - /* if (shallBeDetached) { - (*jvmHandle)->DetachCurrentThread(jvmHandle); - } */ + // detaching thread not required - daemon + // NewtCommon_ReleaseJNIEnv(shallBeDetached); } - (NSPoint) screenPos2NewtClientWinPos: (NSPoint) p @@ -754,14 +724,9 @@ static jmethodID windowRepaintID = NULL; return; } int shallBeDetached = 0; - JNIEnv* env; - if( NULL != jvmHandle ) { - env = NewtCommon_GetJNIEnv(jvmHandle, [self getJVMVersion], 1 /* asDaemon */, &shallBeDetached); - } else { - env = NULL; - } + JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached); if(NULL==env) { - DBG_PRINT("sendKeyEvent: JVM %p JNIEnv %p\n", jvmHandle, env); + DBG_PRINT("sendKeyEvent: null JNIEnv\n"); return; } @@ -792,9 +757,8 @@ static jmethodID windowRepaintID = NULL; evType, javaMods, keyCode, keyChar, keyChar); } - /* if (shallBeDetached) { - (*jvmHandle)->DetachCurrentThread(jvmHandle); - } */ + // detaching thread not required - daemon + // NewtCommon_ReleaseJNIEnv(shallBeDetached); } @end @@ -1038,23 +1002,16 @@ static jmethodID windowRepaintID = NULL; return; } int shallBeDetached = 0; - JavaVM *jvmHandle = [newtView getJVMHandle]; - JNIEnv* env; - if( NULL != jvmHandle ) { - env = NewtCommon_GetJNIEnv(jvmHandle, [newtView getJVMVersion], 1 /* asDaemon */, &shallBeDetached); - } else { - env = NULL; - } + JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached); if(NULL==env) { - DBG_PRINT("focusChanged: JVM %p JNIEnv %p\n", jvmHandle, env); + DBG_PRINT("focusChanged: null JNIEnv\n"); return; } (*env)->CallVoidMethod(env, javaWindowObject, focusChangedID, JNI_FALSE, (gained == YES) ? JNI_TRUE : JNI_FALSE); - /* if (shallBeDetached) { - (*jvmHandle)->DetachCurrentThread(jvmHandle); - } */ + // detaching thread not required - daemon + // NewtCommon_ReleaseJNIEnv(shallBeDetached); } - (void) keyDown: (NSEvent*) theEvent @@ -1147,37 +1104,31 @@ static jmethodID windowRepaintID = NULL; - (void)windowDidResize: (NSNotification*) notification { - JNIEnv* env = NULL; jobject javaWindowObject = NULL; int shallBeDetached = 0; - JavaVM *jvmHandle = NULL; + JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached); + if( NULL == env ) { + DBG_PRINT("windowDidResize: null JNIEnv\n"); + return; + } NewtView* newtView = (NewtView *) [self contentView]; if( [newtView isKindOfClass:[NewtView class]] ) { javaWindowObject = [newtView getJavaWindowObject]; - if (javaWindowObject != NULL) { - jvmHandle = [newtView getJVMHandle]; - if( NULL != jvmHandle ) { - env = NewtCommon_GetJNIEnv(jvmHandle, [newtView getJVMVersion], 1 /* asDaemon */, &shallBeDetached); - } - } } + if( NULL != javaWindowObject ) { + // update insets on every window resize for lack of better hook place + [self updateInsets: env jwin:javaWindowObject]; - // update insets on every window resize for lack of better hook place - [self updateInsets: env jwin:javaWindowObject]; - - if( NULL != env && NULL != javaWindowObject ) { NSRect frameRect = [self frame]; NSRect contentRect = [self contentRectForFrameRect: frameRect]; (*env)->CallVoidMethod(env, javaWindowObject, sizeChangedID, JNI_FALSE, (jint) contentRect.size.width, (jint) contentRect.size.height, JNI_FALSE); - - /* if (shallBeDetached) { - (*jvmHandle)->DetachCurrentThread(jvmHandle); - } */ } + // detaching thread not required - daemon + // NewtCommon_ReleaseJNIEnv(shallBeDetached); } - (void)windowDidMove: (NSNotification*) notification @@ -1192,15 +1143,9 @@ static jmethodID windowRepaintID = NULL; return; } int shallBeDetached = 0; - JavaVM *jvmHandle = [newtView getJVMHandle]; - JNIEnv* env; - if( NULL != jvmHandle ) { - env = NewtCommon_GetJNIEnv(jvmHandle, [newtView getJVMVersion], 1 /* asDaemon */, &shallBeDetached); - } else { - env = NULL; - } + JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached); if(NULL==env) { - DBG_PRINT("windowDidMove: JVM %p JNIEnv %p\n", jvmHandle, env); + DBG_PRINT("windowDidMove: null JNIEnv\n"); return; } @@ -1208,9 +1153,8 @@ static jmethodID windowRepaintID = NULL; p0 = [self getLocationOnScreen: p0]; (*env)->CallVoidMethod(env, javaWindowObject, positionChangedID, JNI_FALSE, (jint) p0.x, (jint) p0.y); - /* if (shallBeDetached) { - (*jvmHandle)->DetachCurrentThread(jvmHandle); - } */ + // detaching thread not required - daemon + // NewtCommon_ReleaseJNIEnv(shallBeDetached); } - (BOOL)windowShouldClose: (id) sender @@ -1226,13 +1170,12 @@ static jmethodID windowRepaintID = NULL; - (BOOL) windowClosingImpl: (BOOL) force { jboolean closed = JNI_FALSE; - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtView* newtView = (NewtView *) [self contentView]; if( ! [newtView isKindOfClass:[NewtView class]] ) { return NO; } - + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; [newtView cursorHide: NO enter: -1]; if( false == [newtView getDestroyNotifySent] ) { @@ -1240,26 +1183,16 @@ static jmethodID windowRepaintID = NULL; DBG_PRINT( "*************** windowWillClose.0: %p\n", (void *)(intptr_t)javaWindowObject); if (javaWindowObject == NULL) { DBG_PRINT("windowWillClose: null javaWindowObject\n"); + [pool release]; return NO; } int shallBeDetached = 0; - JavaVM *jvmHandle = [newtView getJVMHandle]; - JNIEnv* env = NULL; -NS_DURING - if( NULL != jvmHandle ) { - env = NewtCommon_GetJNIEnv(jvmHandle, [newtView getJVMVersion], 1 /* asDaemon */, &shallBeDetached); - } -NS_HANDLER - jvmHandle = NULL; - env = NULL; - [newtView setJVMHandle: NULL]; - DBG_PRINT("windowWillClose: JVMHandler Exception\n"); -NS_ENDHANDLER - DBG_PRINT("windowWillClose: JVM %p JNIEnv %p\n", jvmHandle, env); + JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached); if(NULL==env) { + DBG_PRINT("windowWillClose: null JNIEnv\n"); + [pool release]; return NO; } - [newtView setDestroyNotifySent: true]; // earmark assumption of being closed closed = (*env)->CallBooleanMethod(env, javaWindowObject, windowDestroyNotifyID, force ? JNI_TRUE : JNI_FALSE); if(!force && !closed) { @@ -1267,9 +1200,8 @@ NS_ENDHANDLER [newtView setDestroyNotifySent: false]; } - /* if (shallBeDetached) { - (*jvmHandle)->DetachCurrentThread(jvmHandle); - } */ + // detaching thread not required - daemon + // NewtCommon_ReleaseJNIEnv(shallBeDetached); DBG_PRINT( "*************** windowWillClose.X: %p, closed %d\n", (void *)(intptr_t)javaWindowObject, (int)closed); } else { DBG_PRINT( "*************** windowWillClose (skip)\n"); -- cgit v1.2.3