diff options
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 */ |