diff options
14 files changed, 271 insertions, 229 deletions
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 82f57f33e..3d213c54b 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 @@ -236,23 +236,9 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { System.err.println("!!! Screen : "+sharedScreen); } - // may cause JVM SIGSEGV ? - // X11Util.closePendingDisplayConnections(); - sharedResourcesRunner.releaseAndWait(); - if(X11Util.getOpenDisplayConnectionNumber() > 0) { - System.err.println("X11GLXDrawableFactory.shutdown(): Open (no close attempt) X11 Display Connection"); - X11Util.dumpOpenDisplayConnections(); - } - - if(X11Util.getPendingDisplayConnectionNumber()>0) { - System.err.println("X11GLXDrawableFactory.shutdown(): Pending X11 Display Connection"); - X11Util.dumpPendingDisplayConnections(); - } - - // don't close pending XDisplay, since this might be a different thread as the opener - X11Util.shutdown( false, DEBUG ); + X11Util.shutdown( true, DEBUG ); } protected GLDrawableImpl createOnscreenDrawableImpl(NativeSurface target) { diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/awt/X11AWTGLXGraphicsConfigurationFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/awt/X11AWTGLXGraphicsConfigurationFactory.java index 225dc25a4..4b5b72cc6 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/awt/X11AWTGLXGraphicsConfigurationFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/awt/X11AWTGLXGraphicsConfigurationFactory.java @@ -83,7 +83,7 @@ public class X11AWTGLXGraphicsConfigurationFactory extends GraphicsConfiguration long displayHandle = X11SunJDKReflection.graphicsDeviceGetDisplay(device); if(0==displayHandle) { - displayHandle = X11Util.createThreadLocalDisplay(null); + displayHandle = X11Util.createDisplay(null); if(DEBUG) { System.err.println("X11AWTGLXGraphicsConfigurationFactory: using a thread local X11 display"); } @@ -91,10 +91,12 @@ public class X11AWTGLXGraphicsConfigurationFactory extends GraphicsConfiguration if(DEBUG) { System.err.println("X11AWTGLXGraphicsConfigurationFactory: using AWT X11 display 0x"+Long.toHexString(displayHandle)); } + String name = X11Util.XDisplayString(displayHandle); + displayHandle = X11Util.createDisplay(name); } ((AWTGraphicsDevice)awtScreen.getDevice()).setSubType(NativeWindowFactory.TYPE_X11, displayHandle); X11GraphicsDevice x11Device = new X11GraphicsDevice(displayHandle); - + x11Device.setCloseDisplay(true); X11GraphicsScreen x11Screen = new X11GraphicsScreen(x11Device, awtScreen.getIndex()); if(DEBUG) { System.err.println("X11AWTGLXGraphicsConfigurationFactory: made "+x11Screen); diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java index c165a4833..d2a20f467 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java @@ -49,6 +49,7 @@ import com.jogamp.opengl.impl.*; import java.awt.Canvas; import java.awt.Color; import java.awt.Component; +import java.awt.EventQueue; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.GraphicsConfiguration; @@ -328,6 +329,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable { // Workaround for termination issues with applets -- // sun.applet.AppletPanel should probably be performing the // remove() call on the EDT rather than on its own thread + // Hint: User should run remove from EDT. if (ThreadingImpl.isAWTMode() && Thread.holdsLock(getTreeLock())) { // The user really should not be invoking remove() from this @@ -347,6 +349,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable { animator.resume(); } } + if(!regenerate) { + disposeAbstractGraphicsDeviceAction.run(); + } if(DEBUG) { System.err.println("dispose("+regenerate+") - stop"); @@ -401,6 +406,10 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable { <B>Overrides:</B> <DL><DD><CODE>addNotify</CODE> in class <CODE>java.awt.Component</CODE></DD></DL> */ public void addNotify() { + if(DEBUG) { + Exception ex1 = new Exception(Thread.currentThread().getName()+" - Info: addNotify - start"); + ex1.printStackTrace(); + } super.addNotify(); if (!Beans.isDesignTime()) { disableBackgroundErase(); @@ -419,8 +428,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable { try { awtConfig = chooseGraphicsConfiguration(capabilities, chooser, device); if(DEBUG) { - Exception e = new Exception("Info: Created Config: "+awtConfig); - e.printStackTrace(); + System.err.println(Thread.currentThread().getName()+" - Created Config: "+awtConfig); } if(null!=awtConfig) { // update .. @@ -444,21 +452,25 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable { } if(DEBUG) { - System.err.println("Created Drawable: "+drawable); + System.err.println(Thread.currentThread().getName()+" - Created Drawable: "+drawable); } } + if(DEBUG) { + System.err.println(Thread.currentThread().getName()+" - Info: addNotify - end"); + } } - /** Overridden to track when this component is removed from a + /** <p>Overridden to track when this component is removed from a container. Subclasses which override this method must call super.removeNotify() in their removeNotify() method in order to - function properly. <P> - + function properly. </p> + <p>User shall not call this method outside of EDT, read the AWT/Swing specs + about this.</p> <B>Overrides:</B> <DL><DD><CODE>removeNotify</CODE> in class <CODE>java.awt.Component</CODE></DD></DL> */ public void removeNotify() { if(DEBUG) { - Exception ex1 = new Exception("Info: removeNotify - start"); + Exception ex1 = new Exception(Thread.currentThread().getName()+" - Info: removeNotify - start"); ex1.printStackTrace(); } @@ -473,7 +485,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable { } } if(DEBUG) { - System.err.println("Info: removeNotify - end"); + System.err.println(Thread.currentThread().getName()+" - Info: removeNotify - end"); } } @@ -609,14 +621,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable { } } - private boolean disposeRegenerate; - private DisposeAction disposeAction = new DisposeAction(this); - class DisposeAction implements Runnable { - private GLCanvas canvas; - public DisposeAction(GLCanvas canvas) { - this.canvas = canvas; - } public void run() { drawableHelper.dispose(GLCanvas.this); @@ -632,7 +637,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable { if(disposeRegenerate) { // recreate GLDrawable to reflect it's new graphics configuration - drawable = GLDrawableFactory.getFactory(glProfile).createGLDrawable(NativeWindowFactory.getNativeWindow(canvas, awtConfig)); + drawable = GLDrawableFactory.getFactory(glProfile).createGLDrawable(NativeWindowFactory.getNativeWindow(GLCanvas.this, awtConfig)); if(DEBUG) { System.err.println("GLCanvas.dispose(true): new drawable: "+drawable); } @@ -643,6 +648,8 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable { } } } + private boolean disposeRegenerate; + private DisposeAction disposeAction = new DisposeAction(); private DisposeOnEventDispatchThreadAction disposeOnEventDispatchThreadAction = new DisposeOnEventDispatchThreadAction(); @@ -653,6 +660,25 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable { } } + class DisposeAbstractGraphicsDeviceAction implements Runnable { + public void run() { + AbstractGraphicsConfiguration aconfig = (null!=awtConfig) ? awtConfig.getNativeGraphicsConfiguration() : null; + AbstractGraphicsScreen ascreen = (null!=aconfig) ? aconfig.getScreen() : null; + AbstractGraphicsDevice adevice = (null!=ascreen) ? ascreen.getDevice() : null; + if(null!=adevice) { + String adeviceMsg=null; + if(DEBUG) { + adeviceMsg = adevice.toString(); + } + boolean closed = adevice.close(); + if(DEBUG) { + System.err.println("GLCanvas.dispose(false): closed GraphicsDevice: "+adeviceMsg+", result: "+closed); + } + } + } + } + DisposeAbstractGraphicsDeviceAction disposeAbstractGraphicsDeviceAction = new DisposeAbstractGraphicsDeviceAction(); + class InitAction implements Runnable { public void run() { drawableHelper.init(GLCanvas.this); diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java index 10aeefaf5..b9bbf71c2 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java @@ -631,22 +631,34 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable { private DisposeAction disposeAction = new DisposeAction(); class DisposeAction implements Runnable { - public void run() { - updater.dispose(GLJPanel.this); + public void run() { + updater.dispose(GLJPanel.this); - if(null!=disposeContext) { - disposeContext.destroy(); - disposeContext=null; - } - if(null!=disposeDrawable) { - disposeDrawable.setRealized(false); - } - if(disposeRegenerate && null!=disposeDrawable) { - disposeDrawable.setRealized(true); - disposeContext = (GLContextImpl) disposeDrawable.createContext(shareWith); - disposeContext.setSynchronized(true); + if (null != disposeContext) { + disposeContext.destroy(); + disposeContext = null; + } + if (null != disposeDrawable) { + disposeDrawable.setRealized(false); + } + if (null != disposeDrawable) { + if (disposeRegenerate) { + disposeDrawable.setRealized(true); + disposeContext = (GLContextImpl) disposeDrawable.createContext(shareWith); + disposeContext.setSynchronized(true); + } else { + AbstractGraphicsDevice adevice = disposeDrawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration().getScreen().getDevice(); + String adeviceMsg=null; + if(DEBUG) { + adeviceMsg = adevice.toString(); + } + boolean closed = adevice.close(); + if (DEBUG) { + System.err.println("GLJPanel.dispose(false): closed GraphicsDevice: " + adeviceMsg + ", result: " + closed); + } + } + } } - } } private DisposeOnEventDispatchThreadAction disposeOnEventDispatchThreadAction = diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/JAWTWindow.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/JAWTWindow.java index 00d64b4e4..8ef2ba227 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/JAWTWindow.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/JAWTWindow.java @@ -37,12 +37,10 @@ package com.jogamp.nativewindow.impl.jawt; -import com.jogamp.nativewindow.impl.*; import com.jogamp.common.util.locks.RecursiveLock; import java.awt.Component; import java.awt.Window; -import java.awt.GraphicsEnvironment; import javax.media.nativewindow.*; import javax.media.nativewindow.util.Point; import javax.media.nativewindow.util.Rectangle; @@ -69,10 +67,10 @@ public abstract class JAWTWindow implements NativeWindow { protected void init(Component windowObject) throws NativeWindowException { invalidate(); this.component = windowObject; - initNative(); + validateNative(); } - protected abstract void initNative() throws NativeWindowException; + protected abstract void validateNative() throws NativeWindowException; protected synchronized void invalidate() { component = null; diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/macosx/MacOSXJAWTWindow.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/macosx/MacOSXJAWTWindow.java index ed932ff91..bcaa66847 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/macosx/MacOSXJAWTWindow.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/macosx/MacOSXJAWTWindow.java @@ -54,7 +54,7 @@ public class MacOSXJAWTWindow extends JAWTWindow { super(comp, config); } - protected void initNative() throws NativeWindowException { + protected void validateNative() throws NativeWindowException { } protected int lockSurfaceImpl() throws NativeWindowException { diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/windows/WindowsJAWTWindow.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/windows/WindowsJAWTWindow.java index b6da7166d..d19a11f66 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/windows/WindowsJAWTWindow.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/windows/WindowsJAWTWindow.java @@ -54,7 +54,7 @@ public class WindowsJAWTWindow extends JAWTWindow { super(comp, config); } - protected void initNative() throws NativeWindowException { + protected void validateNative() throws NativeWindowException { } protected synchronized void invalidate() { diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/x11/X11JAWTWindow.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/x11/X11JAWTWindow.java index 4a2c9ada3..a5d36b6dd 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/x11/X11JAWTWindow.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/x11/X11JAWTWindow.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -38,14 +39,10 @@ package com.jogamp.nativewindow.impl.jawt.x11; import javax.media.nativewindow.*; import javax.media.nativewindow.awt.*; -import javax.media.nativewindow.x11.*; import com.jogamp.nativewindow.impl.x11.*; import com.jogamp.nativewindow.impl.jawt.*; -import com.jogamp.nativewindow.impl.*; -import java.awt.GraphicsDevice; -import java.awt.GraphicsEnvironment; public class X11JAWTWindow extends JAWTWindow { @@ -53,15 +50,31 @@ public class X11JAWTWindow extends JAWTWindow { super(comp, config); } - protected void initNative() throws NativeWindowException { - if(0==config.getScreen().getDevice().getHandle()) { - AWTGraphicsDevice awtDevice = (AWTGraphicsDevice) config.getScreen().getDevice(); - long displayHandle = X11SunJDKReflection.graphicsDeviceGetDisplay(awtDevice.getGraphicsDevice()); - if(0==displayHandle) { - displayHandle = X11Util.createThreadLocalDisplay(null); - } - awtDevice.setSubType(NativeWindowFactory.TYPE_X11, displayHandle); + protected void validateNative() throws NativeWindowException { + AWTGraphicsDevice awtDevice = (AWTGraphicsDevice) config.getScreen().getDevice(); + + if(awtDevice.getHandle() != 0) { + // subtype and handle set already, done + return; + } + + long displayHandle = 0; + + // first try a pre-existing attached native configuration, ie native X11GraphicsDevice + AbstractGraphicsConfiguration aconfig = (null!=config) ? config.getNativeGraphicsConfiguration() : null; + AbstractGraphicsScreen ascreen = (null!=aconfig) ? aconfig.getScreen() : null; + AbstractGraphicsDevice adevice = (null!=ascreen) ? ascreen.getDevice() : null; // X11GraphicsDevice + if(null!=adevice) { + displayHandle = adevice.getHandle(); + } + + if(0 == displayHandle) { + displayHandle = X11SunJDKReflection.graphicsDeviceGetDisplay(awtDevice.getGraphicsDevice()); + } + if(0==displayHandle) { + throw new InternalError("X11JAWTWindow: No X11 Display handle available"); } + awtDevice.setSubType(NativeWindowFactory.TYPE_X11, displayHandle); } protected int lockSurfaceImpl() throws NativeWindowException { 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 14e285187..524b142ec 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11Util.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11Util.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -35,7 +36,6 @@ package com.jogamp.nativewindow.impl.x11; import java.util.HashMap; import java.util.Map; import com.jogamp.common.util.LongObjectHashMap; -import com.jogamp.common.util.locks.RecursiveLock; import javax.media.nativewindow.*; @@ -44,13 +44,11 @@ import java.nio.Buffer; import java.nio.IntBuffer; import java.nio.ShortBuffer; import java.security.AccessController; +import java.util.ArrayList; +import java.util.List; /** - * Contains a thread safe X11 utility to retrieve thread local display connection,<br> - * as well as the static global display connection.<br> - * - * The TLS variant is thread safe per se, but be aware of the memory leak risk - * where an application heavily utilizing this class on temporary new threads.<br> + * Contains a thread safe X11 utility to retrieve display connections. */ public class X11Util { private static final boolean DEBUG = Debug.debug("X11Util"); @@ -123,29 +121,37 @@ public class X11Util { // which is to tag a NamedDisplay uncloseable after creation. private static Object globalLock = new Object(); private static LongObjectHashMap globalNamedDisplayMap = new LongObjectHashMap(); - - private static ThreadLocal currentDisplayMap = new ThreadLocal(); + private static List openDisplayList = new ArrayList(); + private static List pendingDisplayList = new ArrayList(); public static class NamedDisplay { String name; long handle; int refCount; boolean unCloseable; + Throwable creationStack; protected NamedDisplay(String name, long handle) { this.name=name; this.handle=handle; this.refCount=1; this.unCloseable=false; + if(DEBUG) { + this.creationStack=new Throwable("NamedDisplay Created at:"); + } else { + this.creationStack=null; + } } public final String getName() { return name; } public final long getHandle() { return handle; } public final int getRefCount() { return refCount; } - public void setUncloseable(boolean v) { unCloseable = v; } + public final void setUncloseable(boolean v) { unCloseable = v; } public final boolean isUncloseable() { return unCloseable; } + public final Throwable getCreationStack() { return creationStack; } + public Object clone() throws CloneNotSupportedException { return super.clone(); } @@ -156,116 +162,107 @@ public class X11Util { } /** Returns the number of unclosed X11 Displays. - * @param realXClosePendingDisplays if true, call XCloseDisplay on the remaining ones + * @param realXCloseAndPendingDisplays if true, {@link #closePendingDisplayConnections()} is called. */ - public static int shutdown(boolean realXClosePendingDisplays, boolean verbose) { + public static int shutdown(boolean realXCloseOpenAndPendingDisplays, boolean verbose) { int num=0; - if(DEBUG||verbose) { - String msg = "X11Util.Display: Shutdown (closePendingDisplays: "+realXClosePendingDisplays+ - ", global: "+globalNamedDisplayMap.size()+ ")" ; + if(DEBUG||verbose||pendingDisplayList.size() > 0) { + String msg = "X11Util.Display: Shutdown (close open / pending Displays: "+realXCloseOpenAndPendingDisplays+ + ", open (no close attempt): "+globalNamedDisplayMap.size()+"/"+openDisplayList.size()+ + ", open (no close attempt and uncloseable): "+pendingDisplayList.size()+")" ; if(DEBUG) { Exception e = new Exception(msg); e.printStackTrace(); - } else if(verbose) { + } else { System.err.println(msg); } + if( openDisplayList.size() > 0) { + X11Util.dumpOpenDisplayConnections(); + } + if( pendingDisplayList.size() > 0 ) { + X11Util.dumpPendingDisplayConnections(); + } } synchronized(globalLock) { + if(realXCloseOpenAndPendingDisplays) { + closePendingDisplayConnections(); + } + openDisplayList.clear(); + pendingDisplayList.clear(); globalNamedDisplayMap.clear(); } return num; } - /******************************* - ** - ** TLS Management - ** - *******************************/ - - /** Returns a clone of the thread local display map, you may {@link Object#wait()} on it */ - public static Map getCurrentDisplayMap() { - return (Map) ((HashMap)getCurrentDisplayMapImpl()).clone(); - } - - /** Returns this thread named display. If it doesn not exist, it is being created, otherwise the reference count is increased */ - public static long createThreadLocalDisplay(String name) { - name = validateDisplayName(name); - NamedDisplay namedDpy = getCurrentDisplay(name); - if(null==namedDpy) { - long dpy = XOpenDisplay(name); - if(0==dpy) { - throw new NativeWindowException("X11Util.Display: Unable to create a display("+name+") connection in Thread "+Thread.currentThread().getName()); - } - // if you like to debug and synchronize X11 commands .. - // setSynchronizeDisplay(dpy, true); - namedDpy = new NamedDisplay(name, dpy); - addCurrentDisplay( namedDpy ); - synchronized(globalLock) { - globalNamedDisplayMap.put(dpy, namedDpy); - } + /** + * Closing pending Display connections in reverse order. + * + * @return number of closed Display connections + */ + public static int closePendingDisplayConnections() { + int num=0; + synchronized(globalLock) { if(DEBUG) { - Exception e = new Exception("X11Util.Display: Created new TLS "+namedDpy+" in thread "+Thread.currentThread().getName()); - e.printStackTrace(); + System.err.println("X11Util: Closing Pending X11 Display Connections: "+pendingDisplayList.size()); } - } else { - namedDpy.refCount++; - if(DEBUG) { - Exception e = new Exception("X11Util.Display: Reused TLS "+namedDpy+" in thread "+Thread.currentThread().getName()); - e.printStackTrace(); + for(int i=pendingDisplayList.size()-1; i>=0; i--) { + NamedDisplay ndpy = (NamedDisplay) pendingDisplayList.get(i); + if(DEBUG) { + System.err.println("X11Util.closePendingDisplayConnections(): Closing ["+i+"]: "+ndpy); + } + XCloseDisplay(ndpy.getHandle()); + num++; } } - return namedDpy.getHandle(); + return num; } - /** Decrease the reference count of this thread named display. If it reaches 0, close it. - It returns the handle of the to be closed display. - It throws a RuntimeException in case the named display does not exist, - or the reference count goes below 0. - */ - public static long closeThreadLocalDisplay(String name) { - name = validateDisplayName(name); - NamedDisplay namedDpy = getCurrentDisplay(name); - if(null==namedDpy) { - 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()); + public static int getOpenDisplayConnectionNumber() { + synchronized(globalLock) { + return openDisplayList.size(); } - long dpy = namedDpy.getHandle(); - namedDpy.refCount--; - if(0==namedDpy.refCount) { - 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()) { - XCloseDisplay(dpy); + } + + public static void dumpOpenDisplayConnections() { + synchronized(globalLock) { + System.err.println("X11Util: Open X11 Display Connections: "+openDisplayList.size()); + for(int i=0; i<pendingDisplayList.size(); i++) { + NamedDisplay ndpy = (NamedDisplay) openDisplayList.get(i); + System.err.println("X11Util: ["+i+"]: "+ndpy); + if(null!=ndpy) { + Throwable t = ndpy.getCreationStack(); + if(null!=t) { + t.printStackTrace(); + } + } } - } else if(DEBUG) { - Exception e = new Exception("X11Util.Display: Keep TLS "+namedDpy+" in thread "+Thread.currentThread().getName()); - e.printStackTrace(); } - return dpy; } - public static long closeThreadLocalDisplay(long handle) { - NamedDisplay ndpy; + public static int getPendingDisplayConnectionNumber() { synchronized(globalLock) { - ndpy = (NamedDisplay) globalNamedDisplayMap.get(handle); + return pendingDisplayList.size(); } - if(null==ndpy) { - throw new RuntimeException("X11Util.Display: Display(0x"+Long.toHexString(handle)+") with given handle is not mapped, in thread "+Thread.currentThread().getName()); + } + + public static void dumpPendingDisplayConnections() { + synchronized(globalLock) { + System.err.println("X11Util: Pending X11 Display Connections: "+pendingDisplayList.size()); + for(int i=0; i<pendingDisplayList.size(); i++) { + NamedDisplay ndpy = (NamedDisplay) pendingDisplayList.get(i); + System.err.println("X11Util: ["+i+"]: "+ndpy); + if(null!=ndpy) { + Throwable t = ndpy.getCreationStack(); + if(null!=t) { + t.printStackTrace(); + } + } + } } - return closeThreadLocalDisplay(ndpy.getName()); } - public static boolean markThreadLocalDisplayUncloseable(long handle) { + public static boolean markDisplayUncloseable(long handle) { NamedDisplay ndpy; synchronized(globalLock) { ndpy = (NamedDisplay) globalNamedDisplayMap.get(handle); @@ -277,53 +274,6 @@ public class X11Util { return false; } - private static Map getCurrentDisplayMapImpl() { - Map displayMap = (Map) currentDisplayMap.get(); - if(null==displayMap) { - displayMap = new HashMap(); - currentDisplayMap.set( displayMap ); - } - return displayMap; - } - - /** maps the given display to the thread local display map - * and notifies all threads synchronized to this display map. */ - private static NamedDisplay addCurrentDisplay(NamedDisplay newDisplay) { - Map displayMap = getCurrentDisplayMapImpl(); - NamedDisplay oldDisplay = null; - synchronized(displayMap) { - oldDisplay = (NamedDisplay) displayMap.put(newDisplay.getName(), newDisplay); - displayMap.notifyAll(); - } - return oldDisplay; - } - - /** removes the mapping of the given name from the thread local display map - * and notifies all threads synchronized to this display map. */ - private static NamedDisplay removeCurrentDisplay(NamedDisplay ndpy) { - Map displayMap = getCurrentDisplayMapImpl(); - synchronized(displayMap) { - NamedDisplay ndpyDel = (NamedDisplay) displayMap.remove(ndpy.getName()); - if(ndpyDel!=ndpy) { - throw new RuntimeException("Wrong mapping req: "+ndpy+", got "+ndpyDel); - } - displayMap.notifyAll(); - } - return ndpy; - } - - /** Returns the thread local display mapped to the given name */ - private static NamedDisplay getCurrentDisplay(String name) { - Map displayMap = getCurrentDisplayMapImpl(); - return (NamedDisplay) displayMap.get(name); - } - - /******************************* - ** - ** Non TLS Functions - ** - *******************************/ - /** Returns this created named display. */ public static long createDisplay(String name) { name = validateDisplayName(name); @@ -336,6 +286,8 @@ public class X11Util { NamedDisplay namedDpy = new NamedDisplay(name, dpy); synchronized(globalLock) { globalNamedDisplayMap.put(dpy, namedDpy); + openDisplayList.add(namedDpy); + pendingDisplayList.add(namedDpy); } if(DEBUG) { Exception e = new Exception("X11Util.Display: Created new "+namedDpy+". Thread "+Thread.currentThread().getName()); @@ -349,11 +301,16 @@ public class X11Util { synchronized(globalLock) { namedDpy = (NamedDisplay) globalNamedDisplayMap.remove(handle); + if(namedDpy!=null) { + if(!openDisplayList.remove(namedDpy)) { throw new RuntimeException("Internal: "+namedDpy); } + } } if(null==namedDpy) { + X11Util.dumpPendingDisplayConnections(); throw new RuntimeException("X11Util.Display: Display(0x"+Long.toHexString(handle)+") with given handle is not mapped. Thread "+Thread.currentThread().getName()); } if(namedDpy.getHandle()!=handle) { + X11Util.dumpPendingDisplayConnections(); throw new RuntimeException("X11Util.Display: Display(0x"+Long.toHexString(handle)+") Mapping error: "+namedDpy+". Thread "+Thread.currentThread().getName()); } @@ -363,6 +320,9 @@ public class X11Util { } if(!namedDpy.isUncloseable()) { + synchronized(globalLock) { + if(!pendingDisplayList.remove(namedDpy)) { throw new RuntimeException("Internal: "+namedDpy); } + } XCloseDisplay(namedDpy.getHandle()); } } @@ -392,6 +352,7 @@ public class X11Util { ** Locked X11Lib wrapped functions ** *******************************/ + public static long XOpenDisplay(String arg0) { NativeWindowFactory.getDefaultToolkitLock().lock(); try { diff --git a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java index b003db8f5..581df5163 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java +++ b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java @@ -68,4 +68,16 @@ public interface AbstractGraphicsDevice extends Cloneable { * The lock implementation must be recursive. */ public void unlock(); + + /** + * Optionally closing the device.<br> + * The default implementation is a NOP operation, returning false.<br> + * The specific implementing, ie {@link javax.media.nativewindow.x11.X11GraphicsDevice}, + * shall have a enable/disable like {@link javax.media.nativewindow.x11.X11GraphicsDevice#setCloseDisplay(boolean, boolean)},<br> + * which shall be invoked at creation time to determine ownership/role of freeing the resource.<br> + * + * @return true if a specialized closing operation was successfully issued, otherwise false, + * ie no native closing operation was issued, which doesn't imply an error at all. + */ + public boolean close(); } diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java index ca0f106f5..b67688116 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java +++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java @@ -91,26 +91,6 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice } /** - * Set the internal ToolkitLock, which is used within the - * {@link #lock()} and {@link #unlock()} implementation. - * - * @param locker the ToolkitLock, if null, {@link com.jogamp.nativewindow.impl.NullToolkitLock} is being used - */ - protected void setToolkitLock(ToolkitLock locker) { - this.toolkitLock = ( null == locker ) ? NativeWindowFactoryImpl.getNullToolkitLock() : locker ; - } - - /** - * @return the used ToolkitLock - * - * @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long) - * @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long, javax.media.nativewindow.ToolkitLock) - */ - public final ToolkitLock getToolkitLock() { - return toolkitLock; - } - - /** * No lock is performed on the graphics device per default, * instead the aggregated recursive {@link ToolkitLock#lock()} is invoked. * @@ -132,7 +112,31 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice toolkitLock.unlock(); } + public boolean close() { + return false; + } + public String toString() { return getClass().toString()+"[type "+getType()+", handle 0x"+Long.toHexString(getHandle())+"]"; } + + /** + * Set the internal ToolkitLock, which is used within the + * {@link #lock()} and {@link #unlock()} implementation. + * + * @param locker the ToolkitLock, if null, {@link com.jogamp.nativewindow.impl.NullToolkitLock} is being used + */ + protected void setToolkitLock(ToolkitLock locker) { + this.toolkitLock = ( null == locker ) ? NativeWindowFactoryImpl.getNullToolkitLock() : locker ; + } + + /** + * @return the used ToolkitLock + * + * @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long) + * @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long, javax.media.nativewindow.ToolkitLock) + */ + public final ToolkitLock getToolkitLock() { + return toolkitLock; + } } diff --git a/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsDevice.java index 31744702d..c60597661 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsDevice.java +++ b/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsDevice.java @@ -32,12 +32,15 @@ package javax.media.nativewindow.x11; +import com.jogamp.nativewindow.impl.x11.X11Util; import javax.media.nativewindow.*; /** Encapsulates a graphics device on X11 platforms. */ public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneable { + boolean closeDisplay = false; + /** Constructs a new X11GraphicsDevice corresponding to the given native display handle and default * {@link javax.media.nativewindow.ToolkitLock} via {@link NativeWindowFactory#createDefaultToolkitLock(java.lang.String, long)}. */ @@ -62,5 +65,17 @@ public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneabl public Object clone() { return super.clone(); } + + public void setCloseDisplay(boolean close) { + closeDisplay = close; + } + public boolean close() { + if(closeDisplay && 0 != handle) { + X11Util.closeDisplay(handle); + handle = 0; + return true; + } + return true; + } } diff --git a/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsScreen.java b/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsScreen.java index 73af5f852..dca0d1de3 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsScreen.java +++ b/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsScreen.java @@ -53,13 +53,6 @@ public class X11GraphicsScreen extends DefaultGraphicsScreen implements Cloneabl return new X11GraphicsScreen(new X11GraphicsDevice(display), screenIdx); } - /** Creates a new X11GraphicsScreen using a thread local display connection */ - public static AbstractGraphicsScreen createDefault() { - long display = X11Util.createThreadLocalDisplay(null); - int scrnIdx = X11Util.DefaultScreen(display); - return createScreenDevice(display, scrnIdx); - } - public long getDefaultVisualID() { // It still could be an AWT hold handle .. long display = getDevice().getHandle(); diff --git a/src/newt/classes/com/jogamp/newt/impl/awt/AWTCanvas.java b/src/newt/classes/com/jogamp/newt/impl/awt/AWTCanvas.java index bbf75798e..9b0ec6907 100644 --- a/src/newt/classes/com/jogamp/newt/impl/awt/AWTCanvas.java +++ b/src/newt/classes/com/jogamp/newt/impl/awt/AWTCanvas.java @@ -37,12 +37,10 @@ import com.jogamp.newt.Window; import java.awt.Canvas; import java.awt.GraphicsDevice; -import java.awt.GraphicsEnvironment; import java.awt.GraphicsConfiguration; import javax.media.nativewindow.*; import javax.media.nativewindow.awt.*; -import com.jogamp.newt.impl.Debug; import java.lang.reflect.Method; import java.security.AccessController; import java.security.PrivilegedAction; @@ -102,6 +100,28 @@ public class AWTCanvas extends Canvas { } } + public void removeNotify() { + try { + dispose(); + } finally { + super.removeNotify(); + } + } + + private void dispose() { + if(null != awtConfig) { + AbstractGraphicsDevice adevice = awtConfig.getNativeGraphicsConfiguration().getScreen().getDevice(); + String adeviceMsg=null; + if(Window.DEBUG_IMPLEMENTATION) { + adeviceMsg = adevice.toString(); + } + boolean closed = adevice.close(); + if(Window.DEBUG_IMPLEMENTATION) { + System.err.println("AWTCanvas.dispose(): closed GraphicsDevice: "+adeviceMsg+", result: "+closed); + } + } + } + /** * Overridden to choose a GraphicsConfiguration on a parent container's * GraphicsDevice because both devices |