diff options
author | Sven Gothel <[email protected]> | 2010-04-27 07:18:54 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2010-04-27 07:18:54 +0200 |
commit | d370be30dc75cc3b63246f026090a7377bf07135 (patch) | |
tree | 1de511925eefc2f7237d0551fae1e3e417f55805 | |
parent | edaf669e1b8c8412c1fd4acfc799138b629bf031 (diff) |
- Fix GLProcAddressResolver regression: Use GLProcAddressResolver !
- X11GLXDrawableFactory:
- Move shared resource creation/destruction into it's own thread
- Remove the ATI hack (no XDisplay closing) for every Display,
this is only necessary for the shared XDisplay and in case of AWT.
- Newt
- Display: Only pumpMessages if device is ready.
- X11Display: Verify handle not null at DispatchMessage.
- Common recursive ToolkitLock implementation, from
src/nativewindow/classes/com/jogamp/nativewindow/impl/LockingNativeWindowFactory.java and
src/newt/classes/com/jogamp/newt/Window.java,
-> com.jogamp.nativewindow.impl.RecursiveToolkitLock
- Unique XLockDisplay/XUnlockDisplay call via X11Util to simplify debugging.
X11Util: Added debug code for XLockDisplay/XUnlockDisplay.
Added fast LongObjectHashMap
Added static lib loading and initialization.
Removed active and passive list, as well as unused methods,
to easy maintenance. Possible since the only 'uncloseable' Display
might be the shareable one.
- X11Lib: Added static initialization via X11Util
Test:
junit/com/jogamp/test/junit/jogl/demos/gl2/gears/TestGears*
- Add WindowListener for quit ..
31 files changed, 390 insertions, 390 deletions
diff --git a/make/config/jogl/glx-x11.cfg b/make/config/jogl/glx-x11.cfg index bbe805a04..f451fa7f3 100644 --- a/make/config/jogl/glx-x11.cfg +++ b/make/config/jogl/glx-x11.cfg @@ -20,9 +20,10 @@ GetProcAddressTableExpr glxProcAddressTable SkipProcAddressGen glXGetProcAddressARB Import com.jogamp.nativewindow.impl.x11.* +Import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver -CustomJavaCode GLX private static GLXProcAddressTable glxProcAddressTable = new GLXProcAddressTable(); +CustomJavaCode GLX private static GLXProcAddressTable glxProcAddressTable = new GLXProcAddressTable(new GLProcAddressResolver()); CustomJavaCode GLX public static GLXProcAddressTable getGLXProcAddressTable() { return glxProcAddressTable; } IncludeAs CustomJavaCode GLX glx-CustomJavaCode.java diff --git a/make/config/nativewindow/x11-CustomJavaCode.java b/make/config/nativewindow/x11-CustomJavaCode.java index 44bb1e8d0..6b5831215 100644 --- a/make/config/nativewindow/x11-CustomJavaCode.java +++ b/make/config/nativewindow/x11-CustomJavaCode.java @@ -1,3 +1,6 @@ + static { + X11Util.initSingleton(); // ensure it's loaded and setup + } /** Interface to C language function: <br> <code> XVisualInfo * XGetVisualInfo(Display * , long, XVisualInfo * , int * ); </code> */ public static XVisualInfo[] XGetVisualInfoCopied(long arg0, long arg1, XVisualInfo arg2, int[] arg3, int arg3_offset) diff --git a/make/java-run.sh b/make/java-run.sh index 5e48cef3a..15bcdcd85 100755 --- a/make/java-run.sh +++ b/make/java-run.sh @@ -16,4 +16,9 @@ shift MOSX=0 uname -a | grep -i Darwin && MOSX=1 -java $X_ARGS $* 2>&1 | tee java-run.log +# D_ARGS="-Dgluegen.debug.ProcAddressHelper=true -Dgluegen.debug.NativeLibrary=true -Dnativewindow.debug=all -Djogl.debug=all -Dnewt.debug=all" +# D_ARGS="-Dnativewindow.debug=all -Djogl.debug=all -Dnewt.debug=all -Djogl.debug.GLSLState" +# D_ARGS="-Dnativewindow.debug.X11Util=true -Djogl.debug.GLDrawableFactory=true" +# D_ARGS="-Dnativewindow.debug.X11Util=true" + +java $X_ARGS $D_ARGS $* 2>&1 | tee java-run.log diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLContextImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/GLContextImpl.java index 4f208ee85..826523a5c 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/GLContextImpl.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLContextImpl.java @@ -732,7 +732,9 @@ public abstract class GLContextImpl extends GLContext { System.err.println(getThreadName() + ": !!! Initializing OpenGL extension address table for " + this); } if (glProcAddressTable == null) { - glProcAddressTable = (ProcAddressTable) createInstance(gl.getGLProfile(), "ProcAddressTable", new Class[0], null); + glProcAddressTable = (ProcAddressTable) createInstance(gl.getGLProfile(), "ProcAddressTable", + new Class[] { FunctionAddressResolver.class } , + new Object[] { new GLProcAddressResolver() } ); // FIXME: cache ProcAddressTables by capability bits so we can // share them among contexts with the same capabilities } diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLContext.java index 48f80977c..12d713036 100755 --- a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLContext.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLContext.java @@ -39,6 +39,7 @@ import javax.media.nativewindow.*; import javax.media.opengl.*; import com.jogamp.opengl.impl.*; import com.jogamp.gluegen.runtime.ProcAddressTable; +import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver; import java.nio.*; import java.util.*; @@ -239,7 +240,7 @@ public abstract class EGLContext extends GLContextImpl { if (eglExtProcAddressTable == null) { // FIXME: cache ProcAddressTables by capability bits so we can // share them among contexts with the same capabilities - eglExtProcAddressTable = new EGLExtProcAddressTable(); + eglExtProcAddressTable = new EGLExtProcAddressTable(new GLProcAddressResolver()); } resetProcAddressTable(getEGLExtProcAddressTable()); super.updateGLProcAddressTable(major, minor, ctp); diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLContext.java index ebefaf466..77cd21730 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLContext.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLContext.java @@ -45,6 +45,7 @@ import javax.media.opengl.*; import javax.media.nativewindow.*; import com.jogamp.opengl.impl.*; import com.jogamp.gluegen.runtime.ProcAddressTable; +import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver; public abstract class MacOSXCGLContext extends GLContextImpl { @@ -262,7 +263,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl if (cglExtProcAddressTable == null) { // FIXME: cache ProcAddressTables by capability bits so we can // share them among contexts with the same capabilities - cglExtProcAddressTable = new CGLExtProcAddressTable(); + cglExtProcAddressTable = new CGLExtProcAddressTable(new GLProcAddressResolver()); } resetProcAddressTable(getCGLExtProcAddressTable()); super.updateGLProcAddressTable(major, minor, ctp); diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLContext.java index 0f1f9813f..360bddd74 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLContext.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLContext.java @@ -45,6 +45,7 @@ import javax.media.opengl.*; import javax.media.nativewindow.*; import com.jogamp.opengl.impl.*; import com.jogamp.gluegen.runtime.ProcAddressTable; +import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver; public class WindowsWGLContext extends GLContextImpl { protected long hglrc; @@ -384,7 +385,7 @@ public class WindowsWGLContext extends GLContextImpl { if (wglExtProcAddressTable == null) { // FIXME: cache ProcAddressTables by capability bits so we can // share them among contexts with the same capabilities - wglExtProcAddressTable = new WGLExtProcAddressTable(); + wglExtProcAddressTable = new WGLExtProcAddressTable(new GLProcAddressResolver()); } resetProcAddressTable(getWGLExtProcAddressTable()); super.updateGLProcAddressTable(major, minor, ctp); diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/GLXUtil.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/GLXUtil.java index ec0eaf94f..804a262fe 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/GLXUtil.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/GLXUtil.java @@ -38,7 +38,7 @@ import com.jogamp.nativewindow.impl.x11.*; public class GLXUtil { public static boolean isMultisampleAvailable(long display) { - X11Lib.XLockDisplay(display); + X11Util.XLockDisplay(display); try { String exts = GLX.glXGetClientString(display, GLX.GLX_EXTENSIONS); if (exts != null) { @@ -46,18 +46,18 @@ public class GLXUtil { } return false; } finally { - X11Lib.XUnlockDisplay(display); + X11Util.XUnlockDisplay(display); } } /** Workaround for apparent issue with ATI's proprietary drivers where direct contexts still send GLX tokens for GL calls */ public static String getVendorName(long display) { - X11Lib.XLockDisplay(display); + X11Util.XLockDisplay(display); try { return GLX.glXGetClientString(display, GLX.GLX_VENDOR); } finally { - X11Lib.XUnlockDisplay(display); + X11Util.XUnlockDisplay(display); } } diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11DummyGLXDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11DummyGLXDrawable.java index 1f148bead..03783f3b9 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11DummyGLXDrawable.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11DummyGLXDrawable.java @@ -64,11 +64,11 @@ public class X11DummyGLXDrawable extends X11OnscreenGLXDrawable { int scrn = screen.getIndex(); long visualID = config.getVisualID(); - X11Lib.XLockDisplay(dpy); + X11Util.XLockDisplay(dpy); try{ dummyWindow = X11Lib.CreateDummyWindow(dpy, scrn, visualID); } finally { - X11Lib.XUnlockDisplay(dpy); + X11Util.XUnlockDisplay(dpy); } nw.setSurfaceHandle( dummyWindow ); } diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXContext.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXContext.java index dce25978c..241c956dc 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXContext.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXContext.java @@ -48,6 +48,7 @@ import com.jogamp.opengl.impl.*; import com.jogamp.opengl.impl.x11.glx.*; import com.jogamp.nativewindow.impl.x11.*; import com.jogamp.gluegen.runtime.ProcAddressTable; +import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver; public abstract class X11GLXContext extends GLContextImpl { protected long context; @@ -407,13 +408,14 @@ public abstract class X11GLXContext extends GLContextImpl { } protected void releaseImplAfterLock() throws GLException { - getDrawableImpl().getFactoryImpl().lockToolkit(); + X11GLXDrawableFactory factory = (X11GLXDrawableFactory)drawable.getFactoryImpl(); + factory.lockToolkit(); try { if (!glXMakeContextCurrent(drawable.getNativeWindow().getDisplayHandle(), 0, 0, 0)) { throw new GLException("Error freeing OpenGL context"); } } finally { - getDrawableImpl().getFactoryImpl().unlockToolkit(); + factory.unlockToolkit(); } } @@ -474,7 +476,7 @@ public abstract class X11GLXContext extends GLContextImpl { if (glXExtProcAddressTable == null) { // FIXME: cache ProcAddressTables by capability bits so we can // share them among contexts with the same capabilities - glXExtProcAddressTable = new GLXExtProcAddressTable(); + glXExtProcAddressTable = new GLXExtProcAddressTable(new GLProcAddressResolver()); } resetProcAddressTable(getGLXExtProcAddressTable()); super.updateGLProcAddressTable(major, minor, ctp); diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawableFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawableFactory.java index 5e1a5da3a..b544404ad 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawableFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawableFactory.java @@ -50,6 +50,10 @@ import com.jogamp.nativewindow.impl.x11.*; public class X11GLXDrawableFactory extends GLDrawableFactoryImpl implements DynamicLookupHelper { + static { + X11Util.initSingleton(); // ensure it's loaded and setup + } + public X11GLXDrawableFactory() { super(); // Must initialize GLX support eagerly in case a pbuffer is the @@ -63,26 +67,33 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl implements Dyna new Object[] {}); } catch (JogampRuntimeException jre) { /* n/a .. */ } - X11GraphicsDevice sharedDevice = new X11GraphicsDevice(X11Util.createThreadLocalDisplay(null)); - vendorName = GLXUtil.getVendorName(sharedDevice.getHandle()); - isVendorATI = GLXUtil.isVendorATI(vendorName); - isVendorNVIDIA = GLXUtil.isVendorNVIDIA(vendorName); - if( isVendorATI() ) { - X11Util.markGlobalDisplayUndeletable(sharedDevice.getHandle()); // ATI hack .. + shareableResourceThread = new ShareableResourceThread(GLProfile.getDefault(), GLProfile.isAWTJOGLAvailable()); + shareableResourceThread.start(); + while (!shareableResourceThread.isInitialized()) { + synchronized(shareableResourceThread) { + try { + shareableResourceThread.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } } - sharedScreen = new X11GraphicsScreen(sharedDevice, 0); - X11Lib.XLockDisplay(sharedScreen.getDevice().getHandle()); + if(null==sharedScreen || null==sharedDrawable) { + throw new GLException("Couldn't init shared screen("+sharedScreen+")/drawable("+sharedDrawable+")"); + } + // We have to keep this within this thread, + // since we have a 'chicken-and-egg' problem otherwise on the <init> lock of this thread. + X11Util.XLockDisplay(sharedScreen.getDevice().getHandle()); try{ - sharedDrawable = new X11DummyGLXDrawable(sharedScreen, this, null); X11GLXContext ctx = (X11GLXContext) sharedDrawable.createContext(null); ctx.makeCurrent(); ctx.release(); sharedContext = ctx; - }finally{ - X11Lib.XUnlockDisplay(sharedScreen.getDevice().getHandle()); + } finally { + X11Util.XUnlockDisplay(sharedScreen.getDevice().getHandle()); } if(null==sharedContext) { - throw new GLException("Couldn't init shared resources"); + throw new GLException("Couldn't init shared context"); } if (DEBUG) { System.err.println("!!! Vendor: "+vendorName+", ATI: "+isVendorATI+", NV: "+isVendorNVIDIA); @@ -91,6 +102,71 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl implements Dyna } } + ShareableResourceThread shareableResourceThread; + + class ShareableResourceThread extends Thread { + volatile boolean shutdown = false; + volatile boolean initialized = false; + GLProfile glp; + boolean mayUseAWT; + + final void shutdown() { shutdown = true; } + final boolean isInitialized() { return initialized; } + + public ShareableResourceThread(GLProfile glp, boolean mayUseAWT) { + super("ShareableResourceThread-"+Thread.currentThread().getName()); + this.glp = glp; + this.mayUseAWT = mayUseAWT; + } + + public void run() { + synchronized(this) { + long tlsDisplay = X11Util.createThreadLocalDisplay(null); + X11GraphicsDevice sharedDevice = new X11GraphicsDevice(tlsDisplay); + vendorName = GLXUtil.getVendorName(sharedDevice.getHandle()); + isVendorATI = GLXUtil.isVendorATI(vendorName); + isVendorNVIDIA = GLXUtil.isVendorNVIDIA(vendorName); + sharedScreen = new X11GraphicsScreen(sharedDevice, 0); + X11Util.XLockDisplay(sharedScreen.getDevice().getHandle()); + try{ + sharedDrawable = new X11DummyGLXDrawable(sharedScreen, X11GLXDrawableFactory.this, glp); + } finally { + X11Util.XUnlockDisplay(sharedScreen.getDevice().getHandle()); + } + if(isVendorATI() && mayUseAWT) { + X11Util.markThreadLocalDisplayUncloseable(tlsDisplay); // failure to close with ATI and AWT usage + } + initialized = true; + this.notifyAll(); + + while (!shutdown) { + synchronized(this) { + try { + this.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + if(null!=sharedDrawable) { + sharedDrawable.destroy(); + sharedDrawable=null; + } + if(null!=sharedScreen) { + X11Util.closeThreadLocalDisplay(null); + sharedScreen = null; + sharedDevice=null; + } + // don't close pending XDisplay, since they might be a different thread as the opener + X11Util.shutdown( false, DEBUG ); + + initialized = false; + this.notifyAll(); + } + } + } + private X11GraphicsScreen sharedScreen; private String vendorName; private boolean isVendorATI; @@ -112,36 +188,36 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl implements Dyna } protected void shutdown() { - if (DEBUG) { + if (DEBUG) { System.err.println("!!! Shutdown Shared:"); System.err.println("!!! CTX : "+sharedContext); System.err.println("!!! Drawable: "+sharedDrawable); System.err.println("!!! Screen : "+sharedScreen); - Exception e = new Exception("Debug"); - e.printStackTrace(); - } - if(null!=sharedContext) { + } + if(null!=sharedContext) { sharedContext.destroy(); // implies release, if current - } - if(null!=sharedDrawable) { - sharedDrawable.destroy(); - } - if(null!=sharedScreen) { - X11GraphicsDevice sharedDevice = (X11GraphicsDevice) sharedScreen.getDevice(); - sharedScreen = null; - } - // X11Util.shutdown( !isVendorATI(), DEBUG ); // works NV .. but .. - // X11Util.shutdown( true, DEBUG ); // fails ATI, works NV .. but - X11Util.shutdown( false, DEBUG ); + sharedContext=null; + } + synchronized(shareableResourceThread) { + if (shareableResourceThread.isInitialized()) { + shareableResourceThread.shutdown(); + shareableResourceThread.notifyAll(); + while (shareableResourceThread.isInitialized()) { + try { + shareableResourceThread.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } + shareableResourceThread = null; } public GLDrawableImpl createOnscreenDrawable(NativeWindow target) { if (target == null) { throw new IllegalArgumentException("Null target"); } - if( isVendorATI() ) { - X11Util.markGlobalDisplayUndeletable(target.getDisplayHandle()); // ATI hack .. - } return new X11OnscreenGLXDrawable(this, target); } @@ -149,9 +225,6 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl implements Dyna if (target == null) { throw new IllegalArgumentException("Null target"); } - if( isVendorATI() ) { - X11Util.markGlobalDisplayUndeletable(target.getDisplayHandle()); // ATI hack .. - } return new X11OffscreenGLXDrawable(this, target); } @@ -204,9 +277,6 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl implements Dyna sharedContext.makeCurrent(); usedSharedContext=true; } - if( isVendorATI() ) { - X11Util.markGlobalDisplayUndeletable(target.getDisplayHandle()); // ATI hack .. - } try { pbufferDrawable = new X11PbufferGLXDrawable(this, target); } finally { @@ -220,11 +290,11 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl implements Dyna protected NativeWindow createOffscreenWindow(GLCapabilities capabilities, GLCapabilitiesChooser chooser, int width, int height) { NullWindow nw = null; - X11Lib.XLockDisplay(sharedScreen.getDevice().getHandle()); + X11Util.XLockDisplay(sharedScreen.getDevice().getHandle()); try{ nw = new NullWindow(X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capabilities, chooser, sharedScreen)); }finally{ - X11Lib.XUnlockDisplay(sharedScreen.getDevice().getHandle()); + X11Util.XUnlockDisplay(sharedScreen.getDevice().getHandle()); } if(nw != null) { nw.setSize(width, height); @@ -280,7 +350,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl implements Dyna long display = sharedScreen.getDevice().getHandle(); - X11Lib.XLockDisplay(display); + X11Util.XLockDisplay(display); try { int[] size = new int[1]; boolean res = X11Lib.XF86VidModeGetGammaRampSize(display, @@ -293,7 +363,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl implements Dyna gammaRampLength = size[0]; return gammaRampLength; } finally { - X11Lib.XUnlockDisplay(display); + X11Util.XUnlockDisplay(display); } } @@ -305,7 +375,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl implements Dyna } long display = sharedScreen.getDevice().getHandle(); - X11Lib.XLockDisplay(display); + X11Util.XLockDisplay(display); try { boolean res = X11Lib.XF86VidModeSetGammaRamp(display, X11Lib.DefaultScreen(display), @@ -315,7 +385,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl implements Dyna rampData, 0); return res; } finally { - X11Lib.XUnlockDisplay(display); + X11Util.XUnlockDisplay(display); } } @@ -332,7 +402,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl implements Dyna rampData.limit(3 * size); ShortBuffer blueRampData = rampData.slice(); long display = sharedScreen.getDevice().getHandle(); - X11Lib.XLockDisplay(display); + X11Util.XLockDisplay(display); try { boolean res = X11Lib.XF86VidModeGetGammaRamp(display, X11Lib.DefaultScreen(display), @@ -345,7 +415,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl implements Dyna } return rampData; } finally { - X11Lib.XUnlockDisplay(display); + X11Util.XUnlockDisplay(display); } } @@ -368,7 +438,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl implements Dyna rampData.limit(3 * size); ShortBuffer blueRampData = rampData.slice(); long display = sharedScreen.getDevice().getHandle(); - X11Lib.XLockDisplay(display); + X11Util.XLockDisplay(display); try { X11Lib.XF86VidModeSetGammaRamp(display, X11Lib.DefaultScreen(display), @@ -377,7 +447,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl implements Dyna greenRampData, blueRampData); } finally { - X11Lib.XUnlockDisplay(display); + X11Util.XUnlockDisplay(display); } } } diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfigurationFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfigurationFactory.java index e65fb5e90..a160734d3 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfigurationFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfigurationFactory.java @@ -81,7 +81,7 @@ public class X11GLXGraphicsConfigurationFactory extends GraphicsConfigurationFac long display = x11Screen.getDevice().getHandle(); NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); - X11Lib.XLockDisplay(display); + X11Util.XLockDisplay(display); try { int screen = x11Screen.getIndex(); boolean isMultisampleAvailable = GLXUtil.isMultisampleAvailable(display); @@ -107,7 +107,7 @@ public class X11GLXGraphicsConfigurationFactory extends GraphicsConfigurationFac } } catch (Throwable t) { } finally { - X11Lib.XUnlockDisplay(display); + X11Util.XUnlockDisplay(display); NativeWindowFactory.getDefaultFactory().getToolkitLock().unlock(); } @@ -191,7 +191,7 @@ public class X11GLXGraphicsConfigurationFactory extends GraphicsConfigurationFac NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); try { - X11Lib.XLockDisplay(display); + X11Util.XLockDisplay(display); try{ int screen = x11Screen.getIndex(); boolean isMultisampleAvailable = GLXUtil.isMultisampleAvailable(display); @@ -292,7 +292,7 @@ public class X11GLXGraphicsConfigurationFactory extends GraphicsConfigurationFac } } }finally{ - X11Lib.XUnlockDisplay(display); + X11Util.XUnlockDisplay(display); } } finally { NativeWindowFactory.getDefaultFactory().getToolkitLock().unlock(); @@ -324,7 +324,7 @@ public class X11GLXGraphicsConfigurationFactory extends GraphicsConfigurationFac NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); try { - X11Lib.XLockDisplay(display); + X11Util.XLockDisplay(display); try{ int screen = x11Screen.getIndex(); boolean isMultisampleAvailable = GLXUtil.isMultisampleAvailable(display); @@ -377,7 +377,7 @@ public class X11GLXGraphicsConfigurationFactory extends GraphicsConfigurationFac } retXVisualInfo = XVisualInfo.create(infos[chosen]); }finally{ - X11Lib.XUnlockDisplay(display); + X11Util.XUnlockDisplay(display); } } finally { NativeWindowFactory.getDefaultFactory().getToolkitLock().unlock(); diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OffscreenGLXDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OffscreenGLXDrawable.java index 14d07e74f..5771e9c42 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OffscreenGLXDrawable.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OffscreenGLXDrawable.java @@ -75,7 +75,7 @@ public class X11OffscreenGLXDrawable extends X11GLXDrawable { getFactoryImpl().lockToolkit(); try { - X11Lib.XLockDisplay(dpy); + X11Util.XLockDisplay(dpy); try{ pixmap = X11Lib.XCreatePixmap(dpy, X11Lib.RootWindow(dpy, screen), @@ -96,7 +96,7 @@ public class X11OffscreenGLXDrawable extends X11GLXDrawable { ", display " + toHexString(dpy)); } }finally{ - X11Lib.XUnlockDisplay(dpy); + X11Util.XUnlockDisplay(dpy); } } finally { getFactoryImpl().unlockToolkit(); @@ -111,7 +111,7 @@ public class X11OffscreenGLXDrawable extends X11GLXDrawable { getFactoryImpl().lockToolkit(); try { - X11Lib.XLockDisplay(display); + X11Util.XLockDisplay(display); try{ long drawable = nw.getSurfaceHandle(); if (DEBUG) { @@ -142,7 +142,7 @@ public class X11OffscreenGLXDrawable extends X11GLXDrawable { ((SurfaceChangeable)nw).setSurfaceHandle(0); }finally{ - X11Lib.XUnlockDisplay(display); + X11Util.XUnlockDisplay(display); } } finally { getFactoryImpl().unlockToolkit(); diff --git a/src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/Gears.java b/src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/Gears.java index 956f4f1e3..a5bf3fda7 100644 --- a/src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/Gears.java +++ b/src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/Gears.java @@ -65,6 +65,7 @@ public class Gears implements GLEventListener { gl.glEnable(GL2.GL_NORMALIZE); MouseListener gearsMouse = new TraceMouseAdapter(new GearsMouseAdapter()); + // MouseListener gearsMouse = new GearsMouseAdapter(); if (drawable instanceof Component) { Component comp = (Component) drawable; diff --git a/src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/QuitKeyAdapter.java b/src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/QuitAdapter.java index 443fd74b1..8581bc9f8 100644 --- a/src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/QuitKeyAdapter.java +++ b/src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/QuitAdapter.java @@ -36,16 +36,23 @@ package com.jogamp.test.junit.jogl.demos.gl2.gears; import com.jogamp.opengl.util.Animator; import com.jogamp.newt.event.*; -class QuitKeyAdapter extends KeyAdapter { +class QuitAdapter extends WindowAdapter implements WindowListener, KeyListener { boolean shouldQuit = false; public boolean shouldQuit() { return shouldQuit; } + public void windowDestroyNotify(WindowEvent e) { + System.out.println("QUIT Window "+Thread.currentThread()); + shouldQuit = true; + } + public void keyTyped(KeyEvent e) { if(e.getKeyChar()=='q') { - System.out.println("QUIT "+Thread.currentThread()); + System.out.println("QUIT Key "+Thread.currentThread()); shouldQuit = true; } } + public void keyPressed(KeyEvent e) {} + public void keyReleased(KeyEvent e) {} } diff --git a/src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/TestGearsAWT.java b/src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/TestGearsAWT.java index dc0923ee8..21487c519 100755 --- a/src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/TestGearsAWT.java +++ b/src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/TestGearsAWT.java @@ -36,7 +36,9 @@ import javax.media.opengl.*; import com.jogamp.opengl.util.Animator; import javax.media.opengl.awt.GLCanvas; import com.jogamp.newt.event.awt.AWTKeyAdapter; +import com.jogamp.newt.event.awt.AWTWindowAdapter; import com.jogamp.newt.event.TraceKeyAdapter; +import com.jogamp.newt.event.TraceWindowAdapter; import com.jogamp.test.junit.jogl.demos.gl2.gears.Gears; import java.awt.Frame; @@ -76,15 +78,15 @@ public class TestGearsAWT { glCanvas.addGLEventListener(new Gears()); Animator animator = new Animator(glCanvas); - QuitKeyAdapter quitKeyAdapter = new QuitKeyAdapter(); + QuitAdapter quitAdapter = new QuitAdapter(); - new AWTKeyAdapter(new TraceKeyAdapter()).addTo(glCanvas); - new AWTKeyAdapter(quitKeyAdapter).addTo(glCanvas); + new AWTKeyAdapter(new TraceKeyAdapter(quitAdapter)).addTo(glCanvas); + new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter)).addTo(frame); frame.setVisible(true); animator.start(); - while(!quitKeyAdapter.shouldQuit() && animator.isAnimating() && animator.getDuration()<duration) { + while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getDuration()<duration) { Thread.sleep(100); } diff --git a/src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/TestGearsNEWT.java b/src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/TestGearsNEWT.java index 835d19185..23c39290c 100755 --- a/src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/TestGearsNEWT.java +++ b/src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/TestGearsNEWT.java @@ -71,16 +71,16 @@ public class TestGearsNEWT { glWindow.addGLEventListener(new Gears()); Animator animator = new Animator(glWindow); - QuitKeyAdapter quitKeyAdapter = new QuitKeyAdapter(); + QuitAdapter quitAdapter = new QuitAdapter(); - glWindow.addKeyListener(new TraceKeyAdapter()); - glWindow.addKeyListener(quitKeyAdapter); + glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter)); + glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter)); glWindow.setSize(width, height); glWindow.setVisible(true); animator.start(); - while(!quitKeyAdapter.shouldQuit() && animator.isAnimating() && animator.getDuration()<duration) { + while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getDuration()<duration) { Thread.sleep(100); } diff --git a/src/junit/com/jogamp/test/junit/jogl/texture/TestTexture01AWT.java b/src/junit/com/jogamp/test/junit/jogl/texture/TestTexture01AWT.java index 4bbbaa271..dbd685760 100755 --- a/src/junit/com/jogamp/test/junit/jogl/texture/TestTexture01AWT.java +++ b/src/junit/com/jogamp/test/junit/jogl/texture/TestTexture01AWT.java @@ -97,10 +97,10 @@ public class TestTexture01AWT { animator.stop(); frame.setVisible(false); - frame.remove(glCanvas); frame.dispose(); frame=null; + glCanvas=null; } public static void main(String args[]) { diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/LockingNativeWindowFactory.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/LockingNativeWindowFactory.java index fd2478ab2..203ae3d12 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/LockingNativeWindowFactory.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/LockingNativeWindowFactory.java @@ -35,39 +35,7 @@ package com.jogamp.nativewindow.impl; import javax.media.nativewindow.*; public class LockingNativeWindowFactory extends NativeWindowFactoryImpl { - // Provides a generic basic and recursive locking mechanism for your discretion. - private ToolkitLock toolkitLock = new ToolkitLock() { - private Thread owner; - private int recursionCount; - - public synchronized void lock() { - Thread cur = Thread.currentThread(); - if (owner == cur) { - ++recursionCount; - return; - } - while (owner != null) { - try { - wait(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } - owner = cur; - } - - public synchronized void unlock() { - if (owner != Thread.currentThread()) { - throw new RuntimeException("Not owner"); - } - if (recursionCount > 0) { - --recursionCount; - return; - } - owner = null; - notifyAll(); - } - }; + private ToolkitLock toolkitLock = new RecursiveToolkitLock(); public ToolkitLock getToolkitLock() { return toolkitLock; diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/RecursiveToolkitLock.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/RecursiveToolkitLock.java new file mode 100644 index 000000000..06ce54368 --- /dev/null +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/RecursiveToolkitLock.java @@ -0,0 +1,83 @@ +package com.jogamp.nativewindow.impl; + +import javax.media.nativewindow.*; + +// +// Reentrance locking toolkit +// +public class RecursiveToolkitLock implements ToolkitLock { + private Thread owner; + private int recursionCount; + private Exception lockedStack = null; + private static final long timeout = 3000; // maximum wait 3s + + public Exception getLockedStack() { + return lockedStack; + } + + public Thread getOwner() { + return owner; + } + + public boolean isOwner() { + return isOwner(Thread.currentThread()); + } + + public synchronized boolean isOwner(Thread thread) { + return owner == thread ; + } + + public synchronized boolean isLocked() { + return null != owner; + } + + /** Recursive and blocking lockSurface() implementation */ + public synchronized void lock() { + Thread cur = Thread.currentThread(); + if (owner == cur) { + ++recursionCount; + return; + } + + long ts = System.currentTimeMillis(); + while (owner != null && (System.currentTimeMillis()-ts) < timeout) { + try { + wait(timeout); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + if(owner != null) { + lockedStack.printStackTrace(); + throw new RuntimeException("Waited "+timeout+"ms for: "+owner+" - "+cur); + } + owner = cur; + lockedStack = new Exception("Previously locked by "+owner); + } + + + /** Recursive and unblocking unlockSurface() implementation */ + public synchronized void unlock() { + unlock(null); + } + + /** Recursive and unblocking unlockSurface() implementation */ + public synchronized void unlock(Runnable releaseAfterUnlockBeforeNotify) { + Thread cur = Thread.currentThread(); + if (owner != cur) { + lockedStack.printStackTrace(); + throw new RuntimeException(cur+": Not owner, owner is "+owner); + } + if (recursionCount > 0) { + --recursionCount; + return; + } + owner = null; + lockedStack = null; + if(null!=releaseAfterUnlockBeforeNotify) { + releaseAfterUnlockBeforeNotify.run(); + } + notifyAll(); + } +} + diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11GraphicsConfigurationFactory.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11GraphicsConfigurationFactory.java index a6f52f3c0..0cd02558a 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11GraphicsConfigurationFactory.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11GraphicsConfigurationFactory.java @@ -58,7 +58,7 @@ public class X11GraphicsConfigurationFactory extends GraphicsConfigurationFactor int num[] = { -1 }; long display = screen.getDevice().getHandle(); - X11Lib.XLockDisplay(display); + X11Util.XLockDisplay(display); try { XVisualInfo[] xvis = X11Lib.XGetVisualInfoCopied(display, X11Lib.VisualIDMask|X11Lib.VisualScreenMask, xvi_temp, num, 0); @@ -68,7 +68,7 @@ public class X11GraphicsConfigurationFactory extends GraphicsConfigurationFactor return XVisualInfo.create(xvis[0]); } finally { - X11Lib.XUnlockDisplay(display); + X11Util.XUnlockDisplay(display); } } @@ -90,7 +90,7 @@ public class X11GraphicsConfigurationFactory extends GraphicsConfigurationFactor vinfo_template.setC_class(c_class); long display = screen.getDevice().getHandle(); - X11Lib.XLockDisplay(display); + X11Util.XLockDisplay(display); try { XVisualInfo[] vinfos = X11Lib.XGetVisualInfoCopied(display, X11Lib.VisualScreenMask, vinfo_template, num, 0); XVisualInfo best=null; @@ -111,7 +111,7 @@ public class X11GraphicsConfigurationFactory extends GraphicsConfigurationFactor return ret; } finally { - X11Lib.XUnlockDisplay(display); + X11Util.XUnlockDisplay(display); } } } diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11Util.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11Util.java index 5f5c10885..d93302e57 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11Util.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11Util.java @@ -37,6 +37,7 @@ import java.util.Map; import java.util.Collection; import java.util.ArrayList; import java.util.Iterator; +import com.jogamp.common.util.LongObjectHashMap; import javax.media.nativewindow.*; @@ -51,25 +52,29 @@ import com.jogamp.nativewindow.impl.*; */ public class X11Util { private static final boolean DEBUG = Debug.debug("X11Util"); + private static final boolean DEBUG_XDISPLAY_LOCK = false; static { NWJNILibLoader.loadNativeWindow("x11"); - installIOErrorHandler(); + initialize(); } - private X11Util() {} + public static void initSingleton() { + // just exist to ensure static init has been run + } - private static ThreadLocal currentDisplayMap = new ThreadLocal(); + private X11Util() {} // not exactly thread safe, but good enough for our purpose, // which is to tag a NamedDisplay uncloseable after creation. private static Object globalLock = new Object(); - private static Collection globalNamedDisplayActive = new ArrayList(); - private static Collection globalNamedDisplayPassive = new ArrayList(); + private static LongObjectHashMap globalNamedDisplayMap = new LongObjectHashMap(); + + private static ThreadLocal currentDisplayMap = new ThreadLocal(); public static final String nullDeviceName = "nil" ; - public static class NamedDisplay implements Cloneable { + public static class NamedDisplay extends RecursiveToolkitLock implements Cloneable { String name; long handle; int refCount; @@ -102,10 +107,9 @@ public class X11Util { */ public static int shutdown(boolean realXClosePendingDisplays, boolean verbose) { int num=0; - String msg; + String msg = null; if(DEBUG||verbose) { - msg = "X11Util.Display: Shutdown (active: "+globalNamedDisplayActive.size()+ - ", passive: "+globalNamedDisplayPassive.size() + ")"; + msg = "X11Util.Display: Shutdown (global: "+globalNamedDisplayMap.size()+ ")" ; if(DEBUG) { Exception e = new Exception(msg); e.printStackTrace(); @@ -114,36 +118,8 @@ public class X11Util { } } - msg = realXClosePendingDisplays ? "Close" : "Keep" ; - synchronized(globalLock) { - // for all passive displays .. - Collection namedDisplays = globalNamedDisplayPassive; - globalNamedDisplayPassive = new ArrayList(); - for(Iterator iter=namedDisplays.iterator(); iter.hasNext(); ) { - NamedDisplay ndpy = (NamedDisplay)iter.next(); - if(DEBUG||verbose) { - System.err.println(msg+" passive: "+ndpy); - } - if(realXClosePendingDisplays) { - X11Lib.XCloseDisplay(ndpy.getHandle()); - } - num++; - } - - // for all active displays .. - namedDisplays = globalNamedDisplayActive; - globalNamedDisplayActive = new ArrayList(); - for(Iterator iter=namedDisplays.iterator(); iter.hasNext(); ) { - NamedDisplay ndpy = (NamedDisplay)iter.next(); - if(DEBUG||verbose) { - System.err.println(msg+" active: "+ndpy); - } - if(realXClosePendingDisplays) { - X11Lib.XCloseDisplay(ndpy.getHandle()); - } - num++; - } + globalNamedDisplayMap.clear(); } return num; } @@ -162,24 +138,14 @@ public class X11Util { public static long createThreadLocalDisplay(String name) { NamedDisplay namedDpy = getCurrentDisplay(name); if(null==namedDpy) { - synchronized(globalLock) { - namedDpy = getNamedDisplay(globalNamedDisplayPassive, name); - if(null != namedDpy) { - if(!globalNamedDisplayPassive.remove(namedDpy)) { throw new RuntimeException("Internal: "+namedDpy); } - globalNamedDisplayActive.add(namedDpy); - addCurrentDisplay( namedDpy ); - } - } - } - if(null==namedDpy) { long dpy = X11Lib.XOpenDisplay(name); if(0==dpy) { throw new NativeWindowException("X11Util.Display: Unable to create a display("+name+") connection in Thread "+Thread.currentThread().getName()); } namedDpy = new NamedDisplay(name, dpy); + addCurrentDisplay( namedDpy ); synchronized(globalLock) { - globalNamedDisplayActive.add(namedDpy); - addCurrentDisplay( namedDpy ); + globalNamedDisplayMap.put(dpy, namedDpy); } if(DEBUG) { Exception e = new Exception("X11Util.Display: Created new TLS "+namedDpy+" in thread "+Thread.currentThread().getName()); @@ -203,7 +169,7 @@ public class X11Util { public static long closeThreadLocalDisplay(String name) { NamedDisplay namedDpy = getCurrentDisplay(name); if(null==namedDpy) { - throw new RuntimeException("X11Util.Display: Display("+name+") with given handle is not mapped to TLS in thread "+Thread.currentThread().getName()); + throw new RuntimeException("X11Util.Display: Display("+name+") with given name is not mapped to TLS in thread "+Thread.currentThread().getName()); } if(0==namedDpy.refCount) { throw new RuntimeException("X11Util.Display: "+namedDpy+" has refCount already 0 in thread "+Thread.currentThread().getName()); @@ -211,20 +177,18 @@ public class X11Util { long dpy = namedDpy.getHandle(); namedDpy.refCount--; if(0==namedDpy.refCount) { - synchronized(globalLock) { - if(!globalNamedDisplayActive.remove(namedDpy)) { throw new RuntimeException("Internal: "+namedDpy); } - if(namedDpy.isUncloseable()) { - globalNamedDisplayPassive.add(namedDpy); - } else { - X11Lib.XCloseDisplay(dpy); - } - removeCurrentDisplay(namedDpy); - } if(DEBUG) { String type = namedDpy.isUncloseable() ? "passive" : "real" ; Exception e = new Exception("X11Util.Display: Closing ( "+type+" ) TLS "+namedDpy+" in thread "+Thread.currentThread().getName()); e.printStackTrace(); } + removeCurrentDisplay(namedDpy); + synchronized(globalLock) { + if(null==globalNamedDisplayMap.remove(dpy)) { throw new RuntimeException("Internal: "+namedDpy); } + } + if(!namedDpy.isUncloseable()) { + X11Lib.XCloseDisplay(dpy); + } } else if(DEBUG) { Exception e = new Exception("X11Util.Display: Keep TLS "+namedDpy+" in thread "+Thread.currentThread().getName()); e.printStackTrace(); @@ -232,39 +196,64 @@ public class X11Util { return dpy; } - public static String getThreadLocalDisplayName(long handle) { - NamedDisplay ndpy = getNamedDisplay(getCurrentDisplayMapImpl().values(), handle); - return null != ndpy ? ndpy.getName() : null; + public static long closeThreadLocalDisplay(long handle) { + NamedDisplay ndpy; + synchronized(globalLock) { + ndpy = (NamedDisplay) globalNamedDisplayMap.get(handle); + } + if(null==ndpy) { + throw new RuntimeException("X11Util.Display: Display(0x"+Long.toHexString(handle)+") with given handle is not mapped, in thread "+Thread.currentThread().getName()); + } + return closeThreadLocalDisplay(ndpy.getName()); } - public static boolean markThreadLocalDisplayUndeletable(long handle) { - NamedDisplay ndpy = getNamedDisplay(getCurrentDisplayMapImpl().values(), handle); - if( null != ndpy ) { - ndpy.unCloseable=true; - return true; + public static void XLockDisplay(long handle) { + if(DEBUG_XDISPLAY_LOCK) { + NamedDisplay ndpy; + synchronized(globalLock) { + ndpy = (NamedDisplay) globalNamedDisplayMap.get(handle); + } + if(null==ndpy) { + throw new RuntimeException("X11Util.Display: Display(0x"+Long.toHexString(handle)+") with given handle is not mapped, thread "+Thread.currentThread().getName()); + } + ndpy.lock(); + try { + X11Lib.XLockDisplay(handle); + } catch (Throwable t) { + ndpy.unlock(); + throw new RuntimeException(t); + } + } else { + X11Lib.XLockDisplay(handle); } - return false; } - public static String getGlobalDisplayName(long handle, boolean active) { - String name; - synchronized(globalLock) { - NamedDisplay ndpy = getNamedDisplay(active ? globalNamedDisplayActive : globalNamedDisplayPassive, handle); - name = null != ndpy ? ndpy.getName() : null; + public static void XUnlockDisplay(long handle) { + if(DEBUG_XDISPLAY_LOCK) { + NamedDisplay ndpy; + synchronized(globalLock) { + ndpy = (NamedDisplay) globalNamedDisplayMap.get(handle); + } + if(null==ndpy) { + throw new RuntimeException("X11Util.Display: Display(0x"+Long.toHexString(handle)+") with given handle is not mapped, thread "+Thread.currentThread().getName()); + } + X11Lib.XUnlockDisplay(handle); + ndpy.unlock(); + } else { + X11Lib.XUnlockDisplay(handle); } - return name; } - public static boolean markGlobalDisplayUndeletable(long handle) { - boolean r=false; + public static boolean markThreadLocalDisplayUncloseable(long handle) { + NamedDisplay ndpy; synchronized(globalLock) { - NamedDisplay ndpy = getNamedDisplay(globalNamedDisplayActive, handle); - if( null != ndpy ) { - ndpy.unCloseable=true; - r=true; - } + ndpy = (NamedDisplay) globalNamedDisplayMap.get(handle); + } + if( null != ndpy ) { + ndpy.unCloseable=true; + return true; } - return r; + return false; } private static Map getCurrentDisplayMapImpl() { @@ -309,26 +298,5 @@ public class X11Util { return (NamedDisplay) displayMap.get(name); } - private static NamedDisplay getNamedDisplay(Collection namedDisplays, String name) { - if(null==name) name=nullDeviceName; - for(Iterator iter=namedDisplays.iterator(); iter.hasNext(); ) { - NamedDisplay ndpy = (NamedDisplay)iter.next(); - if (ndpy.getNameSafe().equals(name)) { - return ndpy; - } - } - return null; - } - - private static NamedDisplay getNamedDisplay(Collection namedDisplays, long handle) { - for(Iterator iter=namedDisplays.iterator(); iter.hasNext(); ) { - NamedDisplay ndpy = (NamedDisplay)iter.next(); - if (ndpy.getHandle()==handle) { - return ndpy; - } - } - return null; - } - - private static native void installIOErrorHandler(); + private static native void initialize(); } diff --git a/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsScreen.java b/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsScreen.java index 58b40efe0..a18ee91c2 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsScreen.java +++ b/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsScreen.java @@ -59,12 +59,12 @@ public class X11GraphicsScreen extends DefaultGraphicsScreen implements Cloneabl NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); try { long display = X11Util.createThreadLocalDefaultDisplay(); - X11Lib.XLockDisplay(display); + X11Util.XLockDisplay(display); try{ int scrnIdx = X11Lib.DefaultScreen(display); return createScreenDevice(display, scrnIdx); }finally{ - X11Lib.XUnlockDisplay(display); + X11Util.XUnlockDisplay(display); } } finally { NativeWindowFactory.getDefaultFactory().getToolkitLock().unlock(); @@ -76,12 +76,12 @@ public class X11GraphicsScreen extends DefaultGraphicsScreen implements Cloneabl NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); try { long display = getDevice().getHandle(); - X11Lib.XLockDisplay(display); + X11Util.XLockDisplay(display); try{ int scrnIdx = X11Lib.DefaultScreen(display); return X11Lib.DefaultVisualID(display, scrnIdx); }finally{ - X11Lib.XUnlockDisplay(display); + X11Util.XUnlockDisplay(display); } } finally { NativeWindowFactory.getDefaultFactory().getToolkitLock().unlock(); @@ -93,13 +93,13 @@ public class X11GraphicsScreen extends DefaultGraphicsScreen implements Cloneabl NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); try { long display = device.getHandle(); - X11Lib.XLockDisplay(display); + X11Util.XLockDisplay(display); try{ if(X11Lib.XineramaEnabled(display)) { screen = 0; // Xinerama -> 1 screen } }finally{ - X11Lib.XUnlockDisplay(display); + X11Util.XUnlockDisplay(display); } } finally { NativeWindowFactory.getDefaultFactory().getToolkitLock().unlock(); diff --git a/src/nativewindow/native/x11/Xmisc.c b/src/nativewindow/native/x11/Xmisc.c index 52449ae84..b8a5004c4 100644 --- a/src/nativewindow/native/x11/Xmisc.c +++ b/src/nativewindow/native/x11/Xmisc.c @@ -193,8 +193,6 @@ static void _throwNewRuntimeException(Display * unlockDisplay, JNIEnv *env, cons XUnlockDisplay(unlockDisplay); } - _initClazzAccess(env); - va_start(ap, msg); vsnprintf(buffer, sizeof(buffer), msg, ap); va_end(ap); @@ -246,10 +244,16 @@ static void x11IOErrorHandlerEnable(int onoff, JNIEnv * env) { } } +static int _initialized=0; + JNIEXPORT void JNICALL -Java_com_jogamp_nativewindow_impl_x11_X11Util_installIOErrorHandler(JNIEnv *env, jclass _unused) { - x11ErrorHandlerEnable(1, env); - x11IOErrorHandlerEnable(1, env); +Java_com_jogamp_nativewindow_impl_x11_X11Util_initialize(JNIEnv *env, jclass _unused) { + if(0==_initialized) { + _initClazzAccess(env); + x11ErrorHandlerEnable(1, env); + x11IOErrorHandlerEnable(1, env); + _initialized=1; + } } JNIEXPORT jlong JNICALL @@ -301,8 +305,6 @@ Java_com_jogamp_nativewindow_impl_x11_X11Lib_XGetVisualInfoCopied1__JJLjava_nio_ } if (_res == NULL) return NULL; - _initClazzAccess(env); - jbyteSource = (*env)->NewDirectByteBuffer(env, _res, count * sizeof(XVisualInfo)); jbyteCopy = (*env)->CallStaticObjectMethod(env, clazzInternalBufferUtil, cstrInternalBufferUtil, jbyteSource); diff --git a/src/newt/classes/com/jogamp/newt/Display.java b/src/newt/classes/com/jogamp/newt/Display.java index df4d5b4f8..951b8b172 100755 --- a/src/newt/classes/com/jogamp/newt/Display.java +++ b/src/newt/classes/com/jogamp/newt/Display.java @@ -148,7 +148,9 @@ public abstract class Display { "Display_"+display.getName()+"-"+current.getName(), new Runnable() { public void run() { - f_dpy.pumpMessagesImpl(); + if(null!=f_dpy.getGraphicsDevice()) { + f_dpy.pumpMessagesImpl(); + } } } ); display.edt = display.edtUtil.start(); display.edtUtil.invokeAndWait(new Runnable() { diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java index db1b694b9..1802cab8e 100755 --- a/src/newt/classes/com/jogamp/newt/Window.java +++ b/src/newt/classes/com/jogamp/newt/Window.java @@ -39,6 +39,7 @@ import com.jogamp.newt.util.EDTUtil; import com.jogamp.common.util.*; import javax.media.nativewindow.*; +import com.jogamp.nativewindow.impl.RecursiveToolkitLock; import java.util.ArrayList; import java.util.Iterator; @@ -283,7 +284,6 @@ public abstract class Window implements NativeWindow /** Recursive and unblocking unlockSurface() implementation */ public synchronized void unlockSurface() throws NativeWindowException { surfaceLock.unlock( new Runnable() { - final Screen f_screen = screen; public void run() { screen.getDisplay().unlockDisplay(); } @@ -956,78 +956,7 @@ public abstract class Window implements NativeWindow return sb.toString(); } - // - // Reentrance locking toolkit - // - public static class WindowToolkitLock implements ToolkitLock { - private Thread owner; - private int recursionCount; - private Exception lockedStack = null; - - public Exception getLockedStack() { - return lockedStack; - } - - public Thread getOwner() { - return owner; - } - - public boolean isOwner() { - return isOwner(Thread.currentThread()); - } - - public synchronized boolean isOwner(Thread thread) { - return owner == thread ; - } - - public synchronized boolean isLocked() { - return null != owner; - } - - /** Recursive and blocking lockSurface() implementation */ - public synchronized void lock() { - Thread cur = Thread.currentThread(); - if (owner == cur) { - ++recursionCount; - return; - } - while (owner != null) { - try { - wait(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } - owner = cur; - lockedStack = new Exception("Previously locked by "+owner); - } - - - /** Recursive and unblocking unlockSurface() implementation */ - public synchronized void unlock() { - unlock(null); - } - - /** Recursive and unblocking unlockSurface() implementation */ - public synchronized void unlock(Runnable releaseAfterUnlockBeforeNotify) { - Thread cur = Thread.currentThread(); - if (owner != cur) { - lockedStack.printStackTrace(); - throw new RuntimeException(cur+": Not owner, owner is "+owner); - } - if (recursionCount > 0) { - --recursionCount; - return; - } - owner = null; - lockedStack = null; - if(null!=releaseAfterUnlockBeforeNotify) { - releaseAfterUnlockBeforeNotify.run(); - } - notifyAll(); - } - } - private WindowToolkitLock destructionLock = new WindowToolkitLock(); - private WindowToolkitLock surfaceLock = new WindowToolkitLock(); + private RecursiveToolkitLock destructionLock = new RecursiveToolkitLock(); + private RecursiveToolkitLock surfaceLock = new RecursiveToolkitLock(); } diff --git a/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java b/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java index 8fb095661..963c0c0a7 100755 --- a/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java @@ -34,6 +34,7 @@ package com.jogamp.newt.impl.macosx; import javax.media.nativewindow.*; +import com.jogamp.nativewindow.impl.RecursiveToolkitLock; import com.jogamp.newt.util.MainThread; import com.jogamp.newt.*; @@ -213,7 +214,7 @@ public class MacWindow extends Window { } } - private WindowToolkitLock nsViewLock = new WindowToolkitLock(); + private RecursiveToolkitLock nsViewLock = new RecursiveToolkitLock(); public synchronized int lockSurface() throws NativeWindowException { nsViewLock.lock(); diff --git a/src/newt/classes/com/jogamp/newt/impl/x11/X11Display.java b/src/newt/classes/com/jogamp/newt/impl/x11/X11Display.java index 94d568f55..c2de0fe18 100755 --- a/src/newt/classes/com/jogamp/newt/impl/x11/X11Display.java +++ b/src/newt/classes/com/jogamp/newt/impl/x11/X11Display.java @@ -79,16 +79,19 @@ public class X11Display extends Display { } protected void dispatchMessagesNative() { + if(0==getHandle()) { + throw new RuntimeException("display handle null"); + } DispatchMessages(getHandle(), javaObjectAtom, windowDeleteAtom); } protected void lockDisplay() { super.lockDisplay(); - LockDisplay(getHandle()); + X11Util.XLockDisplay(getHandle()); } protected void unlockDisplay() { - UnlockDisplay(getHandle()); + X11Util.XUnlockDisplay(getHandle()); super.unlockDisplay(); } @@ -100,9 +103,6 @@ public class X11Display extends Display { // private static native boolean initIDs(); - private native void LockDisplay(long handle); - private native void UnlockDisplay(long handle); - private native void CompleteDisplay(long handle); private native void DispatchMessages(long display, long javaObjectAtom, long windowDeleteAtom); diff --git a/src/newt/classes/com/jogamp/newt/util/EDTUtil.java b/src/newt/classes/com/jogamp/newt/util/EDTUtil.java index f852bcf5c..2550eef82 100644 --- a/src/newt/classes/com/jogamp/newt/util/EDTUtil.java +++ b/src/newt/classes/com/jogamp/newt/util/EDTUtil.java @@ -62,27 +62,17 @@ public class EDTUtil { public ThreadGroup getThreadGroup() { return threadGroup; } - public Thread start() { - return start(false); - } - /** - * @param externalStimuli true indicates that another thread stimulates, - * ie. calls this TaskManager's run() loop method. - * Hence no own thread is started in this case. - * * @return The started Runnable, which handles the run-loop. - * Usefull in combination with externalStimuli=true, - * so an external stimuli can call it. */ - public Thread start(boolean externalStimuli) { + public Thread start() { synchronized(edtLock) { if(null==edt) { edt = new EventDispatchThread(threadGroup, name); } if(!edt.isRunning()) { shouldStop = false; - edt.start(externalStimuli); + edt.start(); } edtLock.notifyAll(); } @@ -166,7 +156,6 @@ public class EDTUtil { class EventDispatchThread extends Thread { boolean isRunning = false; - boolean externalStimuli = false; public EventDispatchThread(ThreadGroup tg, String name) { super(tg, name); @@ -176,14 +165,11 @@ public class EDTUtil { return isRunning; } - public void start(boolean externalStimuli) throws IllegalThreadStateException { + public void start() throws IllegalThreadStateException { synchronized(this) { - this.externalStimuli = externalStimuli; isRunning = true; } - if(!externalStimuli) { - super.start(); - } + super.start(); } /** @@ -194,8 +180,8 @@ public class EDTUtil { if(DEBUG) { System.out.println(Thread.currentThread()+": EDT run() START"); } - while(!shouldStop) { - try { + try { + while(!shouldStop) { // wait for something todo while(!shouldStop && tasks.size()==0) { synchronized(edtLock) { @@ -219,24 +205,23 @@ public class EDTUtil { } pumpMessages.run(); // event dispatch } - } catch (Throwable t) { - // handle errors .. - t.printStackTrace(); - } finally { - // epilog - unlock locked stuff } - if(externalStimuli) break; // no loop if called by external stimuli - } - synchronized(this) { - isRunning = !shouldStop; - } - if(!isRunning) { - synchronized(edtLock) { - edtLock.notifyAll(); + } catch (Throwable t) { + // handle errors .. + shouldStop = true; + throw new RuntimeException(t); + } finally { + synchronized(this) { + isRunning = !shouldStop; + } + if(!isRunning) { + synchronized(edtLock) { + edtLock.notifyAll(); + } + } + if(DEBUG) { + System.out.println(Thread.currentThread()+": EDT run() EXIT"); } - } - if(DEBUG) { - System.out.println(Thread.currentThread()+": EDT run() EXIT"); } } } diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index a4a5da7fc..21bc9b2ad 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -160,7 +160,7 @@ JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_impl_macosx_MacDisplay_initNSApp * Signature: ()V */ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_macosx_MacDisplay_dispatchMessages0 - (JNIEnv *env, jobject unused, jlong window, jint eventMask) + (JNIEnv *env, jobject unused) { NSEvent* event = NULL; NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c index 8d5920f65..70fc421e8 100755 --- a/src/newt/native/X11Window.c +++ b/src/newt/native/X11Window.c @@ -280,40 +280,6 @@ JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_impl_x11_X11Display_initIDs /* * Class: com_jogamp_newt_impl_x11_X11Display - * Method: LockDisplay - * Signature: (J)V - */ -JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Display_LockDisplay - (JNIEnv *env, jobject obj, jlong display) -{ - Display * dpy = (Display *)(intptr_t)display; - if(dpy==NULL) { - _FatalError(env, "invalid display connection.."); - } - XLockDisplay(dpy) ; - // DBG_PRINT1( "X11: LockDisplay 0x%X\n", dpy); -} - - -/* - * Class: com_jogamp_newt_impl_x11_X11Display - * Method: UnlockDisplay - * Signature: (J)V - */ -JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Display_UnlockDisplay - (JNIEnv *env, jobject obj, jlong display) -{ - Display * dpy = (Display *)(intptr_t)display; - if(dpy==NULL) { - _FatalError(env, "invalid display connection.."); - } - XUnlockDisplay(dpy) ; - // DBG_PRINT1( "X11: UnlockDisplay 0x%X\n", dpy); -} - - -/* - * Class: com_jogamp_newt_impl_x11_X11Display * Method: CompleteDisplay * Signature: (J)V */ |