From b6aa455d21fbcfc256ae8f8f4d66493c17e23f4c Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Thu, 1 Dec 2011 21:40:12 +0100 Subject: New GLProfile.ShutdownType: SHARED_ONLY / COMPLETE - Enhance/Fix Lifecycle Management - Leave Platform, .. TempJarCache untouched. - GLDrawableFactoryImpl*: Leave DynamicLibraryBundle(lib-binding) untouched, for NativeLibrary, JNILibLoaderBase (JNI libs), .. consistency. - SHARED_ONLY: shutdown shared GLDrawableFactoryImpl* resources and NativeWindowFactory - COMPLETE: additionally shutdown GLContext* Clear all cached GL/GLX proc-address and device/context mappings. - Use new "GLProfile.shutdown(GLProfile.ShutdownType.SHARED_ONLY)" in Applets - X11GLXDrawableFactory Shutdown: Uncomment close/destroy of shared resources. - JAWTWindow.destroy(): Close the delegated device. In case it's X11 this closes the exclusive opened X11 Display. --- doc/Implementation/Lifecycle.txt | 41 ++++++++ make/scripts/tests.sh | 7 +- .../javax/media/opengl/GLDrawableFactory.java | 13 +-- src/jogl/classes/javax/media/opengl/GLProfile.java | 33 +++++- .../classes/jogamp/opengl/awt/VersionApplet.java | 12 ++- .../jogamp/opengl/egl/EGLDrawableFactory.java | 77 ++++++++------ .../macosx/cgl/MacOSXCGLDrawableFactory.java | 39 ++++--- .../windows/wgl/WindowsWGLDrawableFactory.java | 40 ++++--- .../opengl/x11/glx/X11GLXDrawableFactory.java | 49 +++++---- .../media/nativewindow/AbstractGraphicsDevice.java | 9 +- .../media/nativewindow/DefaultGraphicsDevice.java | 4 + .../media/nativewindow/x11/X11GraphicsDevice.java | 4 +- .../jogamp/nativewindow/jawt/JAWTWindow.java | 1 + .../jogamp/newt/awt/applet/JOGLNewtApplet1Run.java | 5 +- .../test/junit/jogl/acore/TestGLProfile01NEWT.java | 11 -- .../junit/jogl/acore/TestShutdownCompleteAWT.java | 117 +++++++++++++++++++++ .../junit/jogl/acore/TestShutdownCompleteNEWT.java | 101 ++++++++++++++++++ .../junit/jogl/acore/TestShutdownSharedAWT.java | 116 ++++++++++++++++++++ .../junit/jogl/acore/TestShutdownSharedNEWT.java | 101 ++++++++++++++++++ .../test/junit/jogl/glsl/TestGLSLSimple01NEWT.java | 7 -- .../TestTransformFeedbackVaryingsBug407NEWT.java | 5 - .../opengl/test/junit/newt/TestCloseNewtAWT.java | 2 - .../test/junit/newt/TestScreenMode01NEWT.java | 2 +- 23 files changed, 666 insertions(+), 130 deletions(-) create mode 100644 doc/Implementation/Lifecycle.txt create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownCompleteAWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownCompleteNEWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownSharedAWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownSharedNEWT.java diff --git a/doc/Implementation/Lifecycle.txt b/doc/Implementation/Lifecycle.txt new file mode 100644 index 000000000..3bdeafb65 --- /dev/null +++ b/doc/Implementation/Lifecycle.txt @@ -0,0 +1,41 @@ + +Persistent Resources - JVM Lifetime (1) +======================================== + +- Platform + +- JNILibLoaderBase + Contains a set of loaded JNI libraries via System.load(..) + +- JVMUtil + Only issues JVM startup initialization + +- TempJarCache + Contains a TempFileCache for all cached JarFile, + referenced by URL + +Initialization Sequence: +========================== + +Deinitialization is reverse ofc. + +- GLProfile + - Platform (1) + - JVMUtil (1) + - JNILibLoaderBase (1) + - TempJarCache (1) + + - NativeWindowFactory + - X11Util + + - GLDrawableFactory / GLDrawableFactoryImpl + - X11GLXDrawableFactory, EGLDrawableFactory, ... (all platforms) + - *DynamicLookupHelper .. + - NativeLibrary .. + + - GLContext + - proc-address-tables (GL, GLX..) + - context version mapping + + + diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh index e13e051d0..dfb5076e9 100755 --- a/make/scripts/tests.sh +++ b/make/scripts/tests.sh @@ -50,6 +50,7 @@ function jrun() { #D_ARGS="-Djogl.debug.ExtensionAvailabilityCache -Djogl.debug=all -Dnativewindow.debug=all -Djogamp.debug.ProcAddressHelper=true -Djogamp.debug.NativeLibrary=true -Djogamp.debug.NativeLibrary.Lookup=true" #D_ARGS="-Dnativewindow.debug=all -Djogl.debug=all -Dnewt.debug=all" + D_ARGS="-Djogamp.debug=all -Dnativewindow.debug=all -Djogl.debug=all -Dnewt.debug=all" #D_ARGS="-Dnewt.debug.MainThread" #D_ARGS="-Djogl.debug=all -Dnativewindow.debug=all" #D_ARGS="-Djogl.debug.GLContext -Djogl.debug.ExtensionAvailabilityCache" @@ -167,6 +168,10 @@ function testswt() { #testnoawt com.jogamp.newt.opengl.GLWindow $* #testnoawt com.jogamp.opengl.test.junit.jogl.offscreen.TestOffscreen01GLPBufferNEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.offscreen.TestOffscreen02BitmapNEWT $* +testawt com.jogamp.opengl.test.junit.jogl.acore.TestShutdownCompleteAWT $* +#testawt com.jogamp.opengl.test.junit.jogl.acore.TestShutdownSharedAWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestShutdownCompleteNEWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestShutdownSharedNEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile01NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLDebug00NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLDebug01NEWT $* @@ -175,7 +180,7 @@ function testswt() { #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextListNEWT2 $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES1NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT $* -testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT2 $* +#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT2 $* #testnoawt com.jogamp.opengl.test.junit.newt.TestRemoteWindow01NEWT $* #testnoawt com.jogamp.opengl.test.junit.newt.TestRemoteGLWindows01NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNEWT $* diff --git a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java index cc71c53cf..5fff1ce02 100644 --- a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java +++ b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java @@ -54,6 +54,7 @@ import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.NativeWindowFactory; import javax.media.nativewindow.ProxySurface; +import javax.media.opengl.GLProfile.ShutdownType; /**

Provides a virtual machine- and operating system-independent mechanism for creating {@link GLDrawable}s.

@@ -173,21 +174,21 @@ public abstract class GLDrawableFactory { eglFactory = tmp; } - protected static void shutdown() { + protected static void shutdown(ShutdownType shutdownType) { if (isInit) { // volatile: ok synchronized (GLDrawableFactory.class) { if (isInit) { isInit=false; unregisterFactoryShutdownHook(); - shutdownImpl(); + shutdownImpl(shutdownType); } } } } - private static void shutdownImpl() { + private static void shutdownImpl(ShutdownType shutdownType) { synchronized(glDrawableFactories) { for(int i=0; i() { @@ -238,7 +239,7 @@ public abstract class GLDrawableFactory { protected void enterThreadCriticalZone() {}; protected void leaveThreadCriticalZone() {}; - protected abstract void destroy(); + protected abstract void destroy(ShutdownType shutdownType); /** * Retrieve the default device {@link AbstractGraphicsDevice#getConnection() connection}, diff --git a/src/jogl/classes/javax/media/opengl/GLProfile.java b/src/jogl/classes/javax/media/opengl/GLProfile.java index 6591f4ae1..7f0c9b3d3 100644 --- a/src/jogl/classes/javax/media/opengl/GLProfile.java +++ b/src/jogl/classes/javax/media/opengl/GLProfile.java @@ -114,6 +114,10 @@ public class GLProfile { synchronized(GLProfile.class) { if(!initialized) { initialized = true; + if(DEBUG) { + System.err.println("GLProfile.initSingleton(firstUIActionOnProcess: "+firstUIActionOnProcess+") - thread "+Thread.currentThread().getName()); + Thread.dumpStack(); + } Platform.initSingleton(); // run the whole static initialization privileged to speed up, @@ -146,20 +150,41 @@ public class GLProfile { getProfileMap(device); } + /** + * Shutdown type for {@link GLProfile#shutdown(ShutdownType)}. + *

+ * {@link #SHARED_ONLY} For thread based resources only, suitable for eg. {@link java.applet.Applet Applet} restart.
+ * {@link #COMPLETE} Everything.
+ *

+ */ + public enum ShutdownType { + /* Shared thread based resources only, eg. for Applets */ + SHARED_ONLY, + /* Everything */ + COMPLETE; + } + /** * Manual shutdown method, may be called after your last JOGL use * within the running JVM.
* It releases all temporary created resources, ie issues {@link javax.media.opengl.GLDrawableFactory#shutdown()}.
* The shutdown implementation is called via the JVM shutdown hook, if not manually invoked here.
- * Invoke shutdown() manually is recommended, due to the unreliable JVM state within the shutdown hook.
+ * Invoke shutdown(type) manually is recommended, due to the unreliable JVM state within the shutdown hook.
+ * @param type the shutdown type, see {@link ShutdownType}. */ - public static void shutdown() { + public static void shutdown(ShutdownType type) { if(initialized) { // volatile: ok synchronized(GLProfile.class) { if(initialized) { initialized = false; - GLDrawableFactory.shutdown(); // may utilize static GLContext mappings - GLContext.shutdown(); // does not utilize shared resources of GLDrawableFactory + if(DEBUG) { + System.err.println("GLProfile.shutdown(type: "+type+") - thread "+Thread.currentThread().getName()); + Thread.dumpStack(); + } + GLDrawableFactory.shutdown(type); + if(ShutdownType.COMPLETE == type) { + GLContext.shutdown(); + } NativeWindowFactory.shutdown(); } } diff --git a/src/jogl/classes/jogamp/opengl/awt/VersionApplet.java b/src/jogl/classes/jogamp/opengl/awt/VersionApplet.java index 5856bf3a0..b7c90a18b 100644 --- a/src/jogl/classes/jogamp/opengl/awt/VersionApplet.java +++ b/src/jogl/classes/jogamp/opengl/awt/VersionApplet.java @@ -67,6 +67,8 @@ public class VersionApplet extends Applet { private synchronized void my_init() { if(null != canvas) { return; } + setEnabled(true); + GLProfile glp = GLProfile.getDefault(); GLCapabilities glcaps = new GLCapabilities(glp); @@ -120,30 +122,36 @@ public class VersionApplet extends Applet { remove(canvas); canvas.destroy(); canvas = null; - remove(tareaVersion); - tareaVersion=null; + remove(tareaVersion.getParent()); // remove the grid + tareaVersion = null; + tareaCaps = null; + setEnabled(false); } } public void init() { System.err.println("VersionApplet: init() - begin"); + GLProfile.initSingleton(false); my_init(); System.err.println("VersionApplet: init() - end"); } public void start() { System.err.println("VersionApplet: start() - begin"); + canvas.setVisible(true); System.err.println("VersionApplet: start() - end"); } public void stop() { System.err.println("VersionApplet: stop() - begin"); + canvas.setVisible(false); System.err.println("VersionApplet: stop() - end"); } public void destroy() { System.err.println("VersionApplet: destroy() - start"); my_release(); + GLProfile.shutdown(GLProfile.ShutdownType.SHARED_ONLY); System.err.println("VersionApplet: destroy() - end"); } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java index fe4adb564..f6988a73f 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java @@ -39,6 +39,7 @@ package jogamp.opengl.egl; import javax.media.nativewindow.*; import javax.media.nativewindow.egl.EGLGraphicsDevice; import javax.media.opengl.*; +import javax.media.opengl.GLProfile.ShutdownType; import com.jogamp.common.JogampRuntimeException; import com.jogamp.common.util.*; @@ -50,6 +51,9 @@ import java.util.HashMap; import java.util.List; public class EGLDrawableFactory extends GLDrawableFactoryImpl { + private static GLDynamicLookupHelper eglES1DynamicLookupHelper = null; + private static GLDynamicLookupHelper eglES2DynamicLookupHelper = null; + public EGLDrawableFactory() { super(); @@ -68,55 +72,66 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { // to a dynamic one, where there can be 2 instances // for each ES profile with their own ProcAddressTable. - GLDynamicLookupHelper tmp=null; - try { - tmp = new GLDynamicLookupHelper(new EGLES1DynamicLibraryBundleInfo()); - } catch (GLException gle) { - if(DEBUG) { - gle.printStackTrace(); + synchronized(EGLDrawableFactory.class) { + if(null==eglES1DynamicLookupHelper) { + GLDynamicLookupHelper tmp=null; + try { + tmp = new GLDynamicLookupHelper(new EGLES1DynamicLibraryBundleInfo()); + } catch (GLException gle) { + if(DEBUG) { + gle.printStackTrace(); + } + } + eglES1DynamicLookupHelper = tmp; + if(null!=eglES1DynamicLookupHelper && eglES1DynamicLookupHelper.isLibComplete()) { + EGL.resetProcAddressTable(eglES1DynamicLookupHelper); + } } } - eglES1DynamicLookupHelper = tmp; - if(null!=eglES1DynamicLookupHelper && eglES1DynamicLookupHelper.isLibComplete()) { - EGL.resetProcAddressTable(eglES1DynamicLookupHelper); - } - tmp=null; - try { - tmp = new GLDynamicLookupHelper(new EGLES2DynamicLibraryBundleInfo()); - } catch (GLException gle) { - if(DEBUG) { - gle.printStackTrace(); + synchronized(EGLDrawableFactory.class) { + if(null==eglES2DynamicLookupHelper) { + GLDynamicLookupHelper tmp=null; + try { + tmp = new GLDynamicLookupHelper(new EGLES2DynamicLibraryBundleInfo()); + } catch (GLException gle) { + if(DEBUG) { + gle.printStackTrace(); + } + } + eglES2DynamicLookupHelper = tmp; + if(null!=eglES2DynamicLookupHelper && eglES2DynamicLookupHelper.isLibComplete()) { + EGL.resetProcAddressTable(eglES2DynamicLookupHelper); + } } } - eglES2DynamicLookupHelper = tmp; - if(null!=eglES2DynamicLookupHelper && eglES2DynamicLookupHelper.isLibComplete()) { - EGL.resetProcAddressTable(eglES2DynamicLookupHelper); - } if(null != eglES1DynamicLookupHelper || null != eglES2DynamicLookupHelper) { defaultDevice = new EGLGraphicsDevice(AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT); sharedMap = new HashMap(); } } - protected final void destroy() { + protected final void destroy(ShutdownType shutdownType) { if(null != sharedMap) { sharedMap.clear(); sharedMap = null; } defaultDevice = null; - if(null != eglES1DynamicLookupHelper) { - eglES1DynamicLookupHelper.destroy(); - eglES1DynamicLookupHelper = null; - } - if(null != eglES2DynamicLookupHelper) { - eglES2DynamicLookupHelper.destroy(); - eglES2DynamicLookupHelper = null; - } + /** + * Pulling away the native library may cause havoc .. + * + if(ShutdownType.COMPLETE == shutdownType) { + if(null != eglES1DynamicLookupHelper) { + eglES1DynamicLookupHelper.destroy(); + eglES1DynamicLookupHelper = null; + } + if(null != eglES2DynamicLookupHelper) { + eglES2DynamicLookupHelper.destroy(); + eglES2DynamicLookupHelper = null; + } + } */ } - private GLDynamicLookupHelper eglES1DynamicLookupHelper; - private GLDynamicLookupHelper eglES2DynamicLookupHelper; private HashMap/**/ sharedMap; private EGLGraphicsDevice defaultDevice; diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java index 4543424a6..45445067e 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java @@ -61,6 +61,7 @@ import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; +import javax.media.opengl.GLProfile.ShutdownType; import jogamp.nativewindow.WrappedSurface; import jogamp.opengl.DesktopGLDynamicLookupHelper; @@ -72,24 +73,30 @@ import com.jogamp.common.JogampRuntimeException; import com.jogamp.common.util.ReflectionUtil; public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl { + private static DesktopGLDynamicLookupHelper macOSXCGLDynamicLookupHelper = null; + public MacOSXCGLDrawableFactory() { super(); - DesktopGLDynamicLookupHelper tmp = null; - try { - tmp = new DesktopGLDynamicLookupHelper(new MacOSXCGLDynamicLibraryBundleInfo()); - } catch (GLException gle) { - if(DEBUG) { - gle.printStackTrace(); + synchronized(MacOSXCGLDrawableFactory.class) { + if(null==macOSXCGLDynamicLookupHelper) { + DesktopGLDynamicLookupHelper tmp = null; + try { + tmp = new DesktopGLDynamicLookupHelper(new MacOSXCGLDynamicLibraryBundleInfo()); + } catch (GLException gle) { + if(DEBUG) { + gle.printStackTrace(); + } + } + macOSXCGLDynamicLookupHelper = tmp; + /** FIXME ?? + if(null!=macOSXCGLDynamicLookupHelper) { + CGL.getCGLProcAddressTable().reset(macOSXCGLDynamicLookupHelper); + } */ } } - macOSXCGLDynamicLookupHelper = tmp; if(null!=macOSXCGLDynamicLookupHelper) { - /** FIXME ?? - CGL.getCGLProcAddressTable().reset(macOSXCGLDynamicLookupHelper); - */ - // Register our GraphicsConfigurationFactory implementations // The act of constructing them causes them to be registered MacOSXCGLGraphicsConfigurationFactory.registerFactory(); @@ -105,23 +112,25 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl { } } - protected final void destroy() { + protected final void destroy(ShutdownType shutdownType) { if(null != sharedMap) { sharedMap.clear(); sharedMap = null; } defaultDevice = null; - if(null != macOSXCGLDynamicLookupHelper) { + /** + * Pulling away the native library may cause havoc .. + * + if(ShutdownType.COMPLETE == shutdownType && null != macOSXCGLDynamicLookupHelper) { macOSXCGLDynamicLookupHelper.destroy(); macOSXCGLDynamicLookupHelper = null; - } + } */ } public GLDynamicLookupHelper getGLDynamicLookupHelper(int profile) { return macOSXCGLDynamicLookupHelper; } - private DesktopGLDynamicLookupHelper macOSXCGLDynamicLookupHelper; private HashMap sharedMap = new HashMap(); private MacOSXGraphicsDevice defaultDevice; diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java index 8e9bf553b..917402b0a 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java @@ -61,6 +61,7 @@ import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; +import javax.media.opengl.GLProfile.ShutdownType; import com.jogamp.common.JogampRuntimeException; import com.jogamp.common.nio.PointerBuffer; @@ -80,22 +81,29 @@ import jogamp.opengl.GLDynamicLookupHelper; import jogamp.opengl.SharedResourceRunner; public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { + private static DesktopGLDynamicLookupHelper windowsWGLDynamicLookupHelper = null; + public WindowsWGLDrawableFactory() { super(); - DesktopGLDynamicLookupHelper tmp = null; - try { - tmp = new DesktopGLDynamicLookupHelper(new WindowsWGLDynamicLibraryBundleInfo()); - } catch (GLException gle) { - if(DEBUG) { - gle.printStackTrace(); + synchronized(WindowsWGLDrawableFactory.class) { + if(null==windowsWGLDynamicLookupHelper) { + DesktopGLDynamicLookupHelper tmp = null; + try { + tmp = new DesktopGLDynamicLookupHelper(new WindowsWGLDynamicLibraryBundleInfo()); + } catch (GLException gle) { + if(DEBUG) { + gle.printStackTrace(); + } + } + windowsWGLDynamicLookupHelper = tmp; + if(null!=windowsWGLDynamicLookupHelper) { + WGL.getWGLProcAddressTable().reset(windowsWGLDynamicLookupHelper); + } } } - windowsWGLDynamicLookupHelper = tmp; if(null!=windowsWGLDynamicLookupHelper) { - WGL.getWGLProcAddressTable().reset(windowsWGLDynamicLookupHelper); - // Register our GraphicsConfigurationFactory implementations // The act of constructing them causes them to be registered WindowsWGLGraphicsConfigurationFactory.registerFactory(); @@ -119,7 +127,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { } } - protected final void destroy() { + protected final void destroy(ShutdownType shutdownType) { if(null != sharedResourceRunner) { sharedResourceRunner.releaseAndWait(); sharedResourceRunner = null; @@ -129,12 +137,13 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { sharedMap = null; } defaultDevice = null; - if(null != windowsWGLDynamicLookupHelper) { - // FIXME: If closing the native library NativeLibrary.close(), - // reload of Applets doesn't work. Dunno why. - // windowsWGLDynamicLookupHelper.destroy(); + /** + * Pulling away the native library may cause havoc .. + * + if(ShutdownType.COMPLETE == shutdownType && null != windowsWGLDynamicLookupHelper) { + windowsWGLDynamicLookupHelper.destroy(); windowsWGLDynamicLookupHelper = null; - } + } */ RegisteredClassFactory.shutdownSharedClasses(); } @@ -143,7 +152,6 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { return windowsWGLDynamicLookupHelper; } - private DesktopGLDynamicLookupHelper windowsWGLDynamicLookupHelper; private WindowsGraphicsDevice defaultDevice; private SharedResourceImplementation sharedResourceImpl; private SharedResourceRunner sharedResourceRunner; diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java index d2b9242be..96153dd27 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java @@ -57,6 +57,7 @@ import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; +import javax.media.opengl.GLProfile.ShutdownType; import jogamp.nativewindow.WrappedSurface; import jogamp.nativewindow.x11.X11Lib; @@ -78,22 +79,29 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { public static final VersionNumber versionOneThree = new VersionNumber(1, 3, 0); public static final VersionNumber versionOneFour = new VersionNumber(1, 4, 0); + private static DesktopGLDynamicLookupHelper x11GLXDynamicLookupHelper = null; + public X11GLXDrawableFactory() { super(); - DesktopGLDynamicLookupHelper tmp = null; - try { - tmp = new DesktopGLDynamicLookupHelper(new X11GLXDynamicLibraryBundleInfo()); - } catch (GLException gle) { - if(DEBUG) { - gle.printStackTrace(); + synchronized(X11GLXDrawableFactory.class) { + if(null==x11GLXDynamicLookupHelper) { + DesktopGLDynamicLookupHelper tmp = null; + try { + tmp = new DesktopGLDynamicLookupHelper(new X11GLXDynamicLibraryBundleInfo()); + } catch (GLException gle) { + if(DEBUG) { + gle.printStackTrace(); + } + } + x11GLXDynamicLookupHelper = tmp; + if(null!=x11GLXDynamicLookupHelper) { + GLX.getGLXProcAddressTable().reset(x11GLXDynamicLookupHelper); + } } } - x11GLXDynamicLookupHelper = tmp; - if(null!=x11GLXDynamicLookupHelper) { - GLX.getGLXProcAddressTable().reset(x11GLXDynamicLookupHelper); - + if(null!=x11GLXDynamicLookupHelper) { // Register our GraphicsConfigurationFactory implementations // The act of constructing them causes them to be registered X11GLXGraphicsConfigurationFactory.registerFactory(); @@ -111,7 +119,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { } } - protected final void destroy() { + protected final void destroy(ShutdownType shutdownType) { if(null != sharedResourceRunner) { sharedResourceRunner.releaseAndWait(); sharedResourceRunner = null; @@ -121,10 +129,13 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { sharedMap = null; } defaultDevice = null; - if(null != x11GLXDynamicLookupHelper) { + /** + * Pulling away the native library may cause havoc .. + * + if(ShutdownType.COMPLETE == shutdownType && null != x11GLXDynamicLookupHelper) { x11GLXDynamicLookupHelper.destroy(); x11GLXDynamicLookupHelper = null; - } + } */ // Don't really close pending Display connections, // since this may trigger a JVM exception @@ -135,7 +146,6 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { return x11GLXDynamicLookupHelper; } - private DesktopGLDynamicLookupHelper x11GLXDynamicLookupHelper; private X11GraphicsDevice defaultDevice; private SharedResourceImplementation sharedResourceImpl; private SharedResourceRunner sharedResourceRunner; @@ -273,17 +283,19 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { System.err.println("!!! Screen : " + sr.screen); System.err.println("!!! Drawable: " + sr.drawable); System.err.println("!!! CTX : " + sr.context); + Thread.dumpStack(); } if (null != sr.context) { // may cause JVM SIGSEGV: - // sr.context.makeCurrent(); - // sr.context.destroy(); + sr.context.makeCurrent(); + sr.context.destroy(); sr.context = null; } if (null != sr.drawable) { - // may cause JVM SIGSEGV: sr.drawable.destroy(); + // may cause JVM SIGSEGV: + sr.drawable.destroy(); sr.drawable = null; } @@ -292,7 +304,8 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { } if (null != sr.device) { - // may cause JVM SIGSEGV: sr.device.close(); + // may cause JVM SIGSEGV: + sr.device.close(); sr.device = null; } } diff --git a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java index 83b437612..fa25c214f 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java +++ b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java @@ -110,14 +110,15 @@ public interface AbstractGraphicsDevice extends Cloneable { public void unlock(); /** - * Optionally closing the device.
- * The default implementation is a NOP operation, returning false.
+ * Optionally closing the device. + *

+ * The default implementation is a NOP, just setting the handle to null. + *

* The specific implementing, ie {@link javax.media.nativewindow.x11.X11GraphicsDevice}, * shall have a enable/disable like {@link javax.media.nativewindow.x11.X11GraphicsDevice#setCloseDisplay(boolean, boolean)},
* which shall be invoked at creation time to determine ownership/role of freeing the resource.
* - * @return true if a specialized closing operation was successfully issued, otherwise false, - * ie no native closing operation was issued, which doesn't imply an error at all. + * @return true if the handle was not null, otherwise false. */ public boolean close(); } diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java index 331167244..187959a67 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java +++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java @@ -140,6 +140,10 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice } public boolean close() { + if(0 != handle) { + handle = 0; + return true; + } return false; } diff --git a/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsDevice.java index ac4aacec7..73c8cfd52 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsDevice.java +++ b/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsDevice.java @@ -96,10 +96,8 @@ public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneabl System.err.println(Thread.currentThread().getName() + " - X11GraphicsDevice.close(): "+this); } X11Util.closeDisplay(handle); - handle = 0; - return true; } - return false; + return super.close(); } } diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTWindow.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTWindow.java index 712d5ddae..938760801 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTWindow.java +++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTWindow.java @@ -356,6 +356,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface public synchronized void destroy() { invalidate(); + getGraphicsConfiguration().getScreen().getDevice().close(); component = null; // don't dispose the AWT component, since we are merely an immutable uplink } diff --git a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java index 76abb261d..ebcc0dd27 100755 --- a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java +++ b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java @@ -271,10 +271,7 @@ public class JOGLNewtApplet1Run extends Applet { } base.destroy(); // destroy glWindow unrecoverable base=null; - if(DEBUG) { - System.err.println("JOGLNewtApplet1Run.destroy() .. GLProfile.shutdown() .."); - } - GLProfile.shutdown(); + GLProfile.shutdown(GLProfile.ShutdownType.SHARED_ONLY); if(DEBUG) { System.err.println("JOGLNewtApplet1Run.destroy() END"); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile01NEWT.java index 7813482e1..6a5f76ff9 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile01NEWT.java @@ -137,17 +137,6 @@ public class TestGLProfile01NEWT extends UITestCase { dumpVersion(glp); } - @Test - public void test06GLProfileShutdownRecreate() throws InterruptedException { - GLProfile.shutdown(); - GLProfile.initSingleton(true); - System.out.println("GLProfile.getDefault(): "+GLProfile.getDefault()); - System.out.println("GLProfile.getDefaultDesktopDevice(): "+GLProfile.getDefaultDesktopDevice()); - System.out.println("GLProfile.getDefaultEGLDevice(): "+GLProfile.getDefaultEGLDevice()); - System.out.println("GLProfile.getDefaultDevice(): "+GLProfile.getDefaultDevice()); - } - - protected void dumpVersion(GLProfile glp) throws InterruptedException { GLCapabilities caps = new GLCapabilities(glp); GLWindow glWindow = GLWindow.create(caps); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownCompleteAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownCompleteAWT.java new file mode 100644 index 000000000..6b7f1454d --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownCompleteAWT.java @@ -0,0 +1,117 @@ +/** + * Copyright 2010 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. + */ + +package com.jogamp.opengl.test.junit.jogl.acore; + +import java.awt.Frame; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; + +import org.junit.Assert; +import org.junit.Test; + +import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; + +public class TestShutdownCompleteAWT extends UITestCase { + + static long duration = 300; // ms + + protected void runTestGL() throws InterruptedException, InvocationTargetException { + final Frame frame = new Frame("Gears AWT Test"); + Assert.assertNotNull(frame); + + final GLCanvas glCanvas = new GLCanvas(new GLCapabilities(GLProfile.getDefault())); + Assert.assertNotNull(glCanvas); + frame.add(glCanvas); + frame.setSize(256, 256); + + glCanvas.addGLEventListener(new Gears(1)); + + Animator animator = new Animator(glCanvas); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(true); + }}); + + animator.setUpdateFPSFrames(60, System.err); + animator.start(); + Assert.assertEquals(true, animator.isAnimating()); + Assert.assertEquals(true, glCanvas.isVisible()); + Assert.assertEquals(true, glCanvas.isDisplayable()); + + while(animator.isAnimating() && animator.getTotalFPSDuration()