From a4e3f241cfba55e407c68eba91ffcc4beb0758b5 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Tue, 26 Oct 2010 23:23:39 +0200 Subject: Analysis of glXMakeCurrent freeze on ATI fglrx 8.78.6; Misc .. Analysis of glXMakeCurrent freeze on ATI fglrx 8.78.6 - Workaround in TestGLWindows01NEWT: same create/destroy order - Prove bug with simple native test app: jogl/test/native/displayMultiple02.c Misc: - Reverted d52181032830acdd5e4069a41ccd0daff5922d8a, ie reenable x11IOErrorHandler (nativewindow) - GLDrawableHelper: methods -> final - X11Util.NamedDisplay: remove unused RecursiveLock, Cloneable --- .../com/jogamp/opengl/impl/GLDrawableHelper.java | 38 +++++------ .../opengl/impl/x11/glx/X11GLXDrawableFactory.java | 4 +- .../test/junit/newt/TestGLWindows01NEWT.java | 77 ++++++++++++++++++++-- .../com/jogamp/nativewindow/impl/x11/X11Util.java | 21 ++++-- src/nativewindow/native/x11/Xmisc.c | 2 +- 5 files changed, 112 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableHelper.java b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableHelper.java index 4ad0dd4c3..c8cfd9a01 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableHelper.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableHelper.java @@ -62,7 +62,7 @@ public class GLDrawableHelper { reset(); } - public void reset() { + public final void reset() { synchronized(listenersLock) { listeners = new ArrayList(); listenersIter = false; @@ -75,7 +75,7 @@ public class GLDrawableHelper { animatorCtrl = null; } - public String toString() { + public final String toString() { StringBuffer sb = new StringBuffer(); sb.append("GLAnimatorControl: "+animatorCtrl+", "); synchronized(listenersLock) { @@ -94,11 +94,11 @@ public class GLDrawableHelper { return sb.toString(); } - public void addGLEventListener(GLEventListener listener) { + public final void addGLEventListener(GLEventListener listener) { addGLEventListener(-1, listener); } - public void addGLEventListener(int index, GLEventListener listener) { + public final void addGLEventListener(int index, GLEventListener listener) { synchronized(listenersLock) { if(0>index) { index = listeners.size(); @@ -116,7 +116,7 @@ public class GLDrawableHelper { } } - public void removeGLEventListener(GLEventListener listener) { + public final void removeGLEventListener(GLEventListener listener) { synchronized(listenersLock) { if(!listenersIter) { // fast path @@ -131,7 +131,7 @@ public class GLDrawableHelper { } } - public void dispose(GLAutoDrawable drawable) { + public final void dispose(GLAutoDrawable drawable) { synchronized(listenersLock) { listenersIter = true; for (int i=0; i < listeners.size(); i++) { @@ -154,7 +154,7 @@ public class GLDrawableHelper { return false; } - public void init(GLAutoDrawable drawable) { + public final void init(GLAutoDrawable drawable) { synchronized(listenersLock) { listenersIter = true; for (int i=0; i < listeners.size(); i++) { @@ -167,7 +167,7 @@ public class GLDrawableHelper { } } - public void display(GLAutoDrawable drawable) { + public final void display(GLAutoDrawable drawable) { synchronized(listenersLock) { listenersIter = true; for (int i=0; i < listeners.size(); i++) { @@ -190,7 +190,7 @@ public class GLDrawableHelper { listener.reshape(drawable, x, y, width, height); } - public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + public final void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { synchronized(listenersLock) { listenersIter = true; for (int i=0; i < listeners.size(); i++) { @@ -200,7 +200,7 @@ public class GLDrawableHelper { } } - private void execGLRunnables(GLAutoDrawable drawable) { + private final void execGLRunnables(GLAutoDrawable drawable) { if(glRunnables.size()>0) { // swap one-shot list asap ArrayList _glRunnables = null; @@ -218,7 +218,7 @@ public class GLDrawableHelper { } } - public void setAnimator(GLAnimatorControl animator) throws GLException { + public final void setAnimator(GLAnimatorControl animator) throws GLException { synchronized(glRunnablesLock) { if(animatorCtrl!=animator && null!=animator && null!=animatorCtrl) { throw new GLException("Trying to register GLAnimatorControl "+animator+", where "+animatorCtrl+" is already registered. Unregister first."); @@ -227,7 +227,7 @@ public class GLDrawableHelper { } } - public GLAnimatorControl getAnimator() { + public final GLAnimatorControl getAnimator() { synchronized(glRunnablesLock) { return animatorCtrl; } @@ -237,7 +237,7 @@ public class GLDrawableHelper { return ( null != animatorCtrl ) ? animatorCtrl.isAnimating() && animatorCtrl.getThread() != Thread.currentThread() : false ; } - public void invoke(GLAutoDrawable drawable, boolean wait, GLRunnable glRunnable) { + public final void invoke(GLAutoDrawable drawable, boolean wait, GLRunnable glRunnable) { if( null == drawable || null == glRunnable ) { return; } @@ -274,11 +274,11 @@ public class GLDrawableHelper { } } - public void setAutoSwapBufferMode(boolean onOrOff) { + public final void setAutoSwapBufferMode(boolean onOrOff) { autoSwapBufferMode = onOrOff; } - public boolean getAutoSwapBufferMode() { + public final boolean getAutoSwapBufferMode() { return autoSwapBufferMode; } @@ -289,10 +289,10 @@ public class GLDrawableHelper { the GLContext's public APIs, and putting it into a separate class helps ensure that we don't inadvertently use private methods of the GLContext or its implementing classes. */ - public void invokeGL(GLDrawable drawable, - GLContext context, - Runnable runnable, - Runnable initAction) { + public final void invokeGL(GLDrawable drawable, + GLContext context, + Runnable runnable, + Runnable initAction) { if(null==context) { if (DEBUG) { Exception e = new GLException(Thread.currentThread().getName()+"Info: GLDrawableHelper " + this + ".invokeGL(): NULL GLContext"); 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 5915ad55c..2828a90f1 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 @@ -162,8 +162,8 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { sharedDrawable=null; } if(null!=sharedScreen) { - // may cause deadlock: X11Util.closeThreadLocalDisplay(null); - sharedScreen = null; + // may cause deadlock: X11Util.closeThreadLocalDisplay(sharedScreen.getDevice().getHandle()); + sharedScreen = null; } // don't close pending XDisplay, since this might be a different thread as the opener X11Util.shutdown( false, DEBUG ); diff --git a/src/junit/com/jogamp/test/junit/newt/TestGLWindows01NEWT.java b/src/junit/com/jogamp/test/junit/newt/TestGLWindows01NEWT.java index 8d0561a81..73d962dfa 100644 --- a/src/junit/com/jogamp/test/junit/newt/TestGLWindows01NEWT.java +++ b/src/junit/com/jogamp/test/junit/newt/TestGLWindows01NEWT.java @@ -72,6 +72,7 @@ public class TestGLWindows01NEWT extends UITestCase { GLWindow glWindow; if(null!=screen) { boolean destroyWhenUnused = screen.getDestroyWhenUnused(); + Assert.assertEquals(destroyWhenUnused, screen.getDisplay().getDestroyWhenUnused()); glWindow = GLWindow.create(screen, caps); Assert.assertNotNull(glWindow); Assert.assertEquals(destroyWhenUnused, glWindow.getScreen().getDestroyWhenUnused()); @@ -244,14 +245,76 @@ public class TestGLWindows01NEWT extends UITestCase { } @Test - public void testWindowDecor03TwoWin() throws InterruptedException { + public void testWindowDecor03TwoWinOneDisplay() throws InterruptedException { + GLCapabilities caps = new GLCapabilities(glp); + Assert.assertNotNull(caps); + + Display display = NewtFactory.createDisplay(null); // local display + Assert.assertNotNull(display); + display.setDestroyWhenUnused(true); + + Screen screen1 = NewtFactory.createScreen(display, 0); // screen 0 + Assert.assertNotNull(screen1); + GLWindow window1 = createWindow(screen1, caps, width, height, + true /* onscreen */, false /* undecorated */, + false /*addGLEventListenerAfterVisible*/); + Assert.assertNotNull(window1); + + Screen screen2 = NewtFactory.createScreen(display, 0); // screen 0 + Assert.assertNotNull(screen2); + GLWindow window2 = createWindow(screen2, caps, width, height, + true /* onscreen */, false /* undecorated */, + false /*addGLEventListenerAfterVisible*/); + Assert.assertNotNull(window2); + + Assert.assertEquals(1,Display.getActiveDisplayNumber()); + + Assert.assertEquals(2,display.getReferenceCount()); + Assert.assertEquals(true,display.isNativeValid()); + Assert.assertNotNull(display.getEDTUtil()); + Assert.assertEquals(true,display.getEDTUtil().isRunning()); + + Assert.assertEquals(1,screen1.getReferenceCount()); + Assert.assertEquals(true,screen1.isNativeValid()); + + Assert.assertEquals(1,screen2.getReferenceCount()); + Assert.assertEquals(true,screen2.isNativeValid()); + + int state; + for(state=0; state*100 X11 Display). + // In such cases, closing displays shall happen in the same order as + // opening them, otherwise some driver related bug appears. + // You may test this, ie just reverse the destroy order below. + // See also native test: jogl/test/native/displayMultiple02.c + destroyWindow(window1, null, null, true); + destroyWindow(window2, null, null, true); Assert.assertEquals(0,Display.getActiveDisplayNumber()); @@ -308,7 +377,7 @@ public class TestGLWindows01NEWT extends UITestCase { Assert.assertNotNull(display2.getEDTUtil()); Assert.assertEquals(false,display2.getEDTUtil().isRunning()); Assert.assertEquals(0,screen2.getReferenceCount()); - Assert.assertEquals(false,screen2.isNativeValid()); + Assert.assertEquals(false,screen2.isNativeValid()); } public static void setDemoFields(GLEventListener demo, GLWindow glWindow) { 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 5e89e9f50..14e285187 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11Util.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11Util.java @@ -126,7 +126,7 @@ public class X11Util { private static ThreadLocal currentDisplayMap = new ThreadLocal(); - public static class NamedDisplay extends RecursiveLock implements Cloneable { + public static class NamedDisplay { String name; long handle; int refCount; @@ -142,6 +142,8 @@ public class X11Util { 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 boolean isUncloseable() { return unCloseable; } public Object clone() throws CloneNotSupportedException { @@ -158,9 +160,9 @@ public class X11Util { */ public static int shutdown(boolean realXClosePendingDisplays, boolean verbose) { int num=0; - String msg = null; if(DEBUG||verbose) { - msg = "X11Util.Display: Shutdown (global: "+globalNamedDisplayMap.size()+ ")" ; + String msg = "X11Util.Display: Shutdown (closePendingDisplays: "+realXClosePendingDisplays+ + ", global: "+globalNamedDisplayMap.size()+ ")" ; if(DEBUG) { Exception e = new Exception(msg); e.printStackTrace(); @@ -269,7 +271,7 @@ public class X11Util { ndpy = (NamedDisplay) globalNamedDisplayMap.get(handle); } if( null != ndpy ) { - ndpy.unCloseable=true; + ndpy.setUncloseable(true); return true; } return false; @@ -355,11 +357,22 @@ public class X11Util { throw new RuntimeException("X11Util.Display: Display(0x"+Long.toHexString(handle)+") Mapping error: "+namedDpy+". Thread "+Thread.currentThread().getName()); } + if(DEBUG) { + Exception e = new Exception("X11Util.Display: Closing new "+namedDpy+". Thread "+Thread.currentThread().getName()); + e.printStackTrace(); + } + if(!namedDpy.isUncloseable()) { XCloseDisplay(namedDpy.getHandle()); } } + public static NamedDisplay getNamedDisplay(long handle) { + synchronized(globalLock) { + return (NamedDisplay) globalNamedDisplayMap.get(handle); + } + } + /** * @return If name is null, it returns the previous queried NULL display name, * otherwise the name. */ diff --git a/src/nativewindow/native/x11/Xmisc.c b/src/nativewindow/native/x11/Xmisc.c index 57bc6fc59..31d57240f 100644 --- a/src/nativewindow/native/x11/Xmisc.c +++ b/src/nativewindow/native/x11/Xmisc.c @@ -253,7 +253,7 @@ Java_com_jogamp_nativewindow_impl_x11_X11Util_initialize(JNIEnv *env, jclass _un } _initClazzAccess(env); - // x11IOErrorHandlerEnable(1, env); // JAU FIXME: can't enable without disable + x11IOErrorHandlerEnable(1, env); _initialized=1; } } -- cgit v1.2.3