diff options
author | Sven Gothel <[email protected]> | 2013-11-29 02:24:01 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2013-11-29 02:24:01 +0100 |
commit | 586446311ea1ba87f98236d5347955bf99b465d6 (patch) | |
tree | 2bba93f117ec08bbb3ea96ee6cd2c44d97b04421 | |
parent | cb0afe743d21a3480e2d41744a904ac7d404612d (diff) |
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.
-rwxr-xr-x | make/scripts/tests-win.bat | 4 | ||||
-rwxr-xr-x | make/scripts/tests-x64-dbg.bat | 8 | ||||
-rw-r--r-- | make/scripts/tests.sh | 27 | ||||
-rw-r--r-- | src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java | 21 | ||||
-rw-r--r-- | src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClass.java | 17 | ||||
-rw-r--r-- | src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClassFactory.java | 30 | ||||
-rw-r--r-- | src/nativewindow/native/NativewindowCommon.c | 7 | ||||
-rw-r--r-- | src/nativewindow/native/NativewindowCommon.h | 3 | ||||
-rw-r--r-- | src/nativewindow/native/win32/GDImisc.c | 446 | ||||
-rw-r--r-- | src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java | 2 |
10 files changed, 373 insertions, 192 deletions
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<registeredFactories.size(); j++) { final RegisteredClassFactory rcf = registeredFactories.get(j); synchronized(rcf.sync) { if(null != rcf.sharedClass) { - GDIUtil.DestroyWindowClass(rcf.sharedClass.getHInstance(), rcf.sharedClass.getName()); + GDIUtil.DestroyWindowClass0(rcf.sharedClass.getHInstance(), rcf.sharedClass.getName(), rcf.sharedClass.getHDispThreadContext()); rcf.sharedClass = null; rcf.sharedRefCount = 0; rcf.classIter = 0; if(DEBUG) { - System.err.println("RegisteredClassFactory #"+j+"/"+registeredFactories.size()+" shutdownSharedClasses : "+rcf.sharedClass); + System.err.println("RegisteredClassFactory #"+j+"/"+registeredFactories.size()+": shutdownSharedClasses : "+rcf.sharedClass); } + } else if(DEBUG) { + System.err.println("RegisteredClassFactory #"+j+"/"+registeredFactories.size()+": null"); } } } @@ -86,9 +92,10 @@ public class RegisteredClassFactory { /** Application handle. */ public static long getHInstance() { return hInstance; } - public RegisteredClassFactory(String classBaseName, long wndProc) { + public RegisteredClassFactory(String classBaseName, long wndProc, boolean useDummyDispatchThread) { this.classBaseName = classBaseName; this.wndProc = wndProc; + this.useDummyDispatchThread = useDummyDispatchThread; synchronized(registeredFactories) { registeredFactories.add(this); } @@ -107,12 +114,21 @@ public class RegisteredClassFactory { // Retry with next clazz name, this could happen if more than one JVM is running clazzName = classBaseName + classIter; classIter++; - registered = GDIUtil.CreateWindowClass(hInstance, clazzName, wndProc); + registered = GDIUtil.CreateWindowClass0(hInstance, clazzName, wndProc); } if( !registered ) { throw new NativeWindowException("Error: Could not create WindowClass: "+clazzName); } - sharedClass = new RegisteredClass(hInstance, clazzName); + final long hDispatchThread; + if( useDummyDispatchThread ) { + hDispatchThread = GDIUtil.CreateDummyDispatchThread0(); + if( 0 == hDispatchThread ) { + throw new NativeWindowException("Error: Could not create DDT "+clazzName); + } + } else { + hDispatchThread = 0; + } + sharedClass = new RegisteredClass(hInstance, clazzName, hDispatchThread); if(DEBUG) { System.err.println("RegisteredClassFactory getSharedClass ("+sharedRefCount+") initialized: "+sharedClass); } @@ -137,7 +153,7 @@ public class RegisteredClassFactory { throw new InternalError("Error ("+sharedRefCount+"): SharedClass is null"); } if( 0 == sharedRefCount ) { - GDIUtil.DestroyWindowClass(sharedClass.getHInstance(), sharedClass.getName()); + GDIUtil.DestroyWindowClass0(sharedClass.getHInstance(), sharedClass.getName(), sharedClass.getHDispThreadContext()); if(DEBUG) { System.err.println("RegisteredClassFactory releaseSharedClass ("+sharedRefCount+") released: "+sharedClass); } diff --git a/src/nativewindow/native/NativewindowCommon.c b/src/nativewindow/native/NativewindowCommon.c index e909c0494..212bdf82f 100644 --- a/src/nativewindow/native/NativewindowCommon.c +++ b/src/nativewindow/native/NativewindowCommon.c @@ -1,6 +1,7 @@ #include "NativewindowCommon.h" #include <string.h> +#include <sys/time.h> 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 <jni.h> #include <stdlib.h> +#include <gluegen_stdint.h> 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"); |