summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2012-05-13 20:00:21 +0200
committerSven Gothel <[email protected]>2012-05-13 22:05:35 +0200
commitdf6c9accd84b801d86c8f6f9ce35e02ffd417f71 (patch)
tree9dd593bf6ed9631ef8ac723b5e07c87ae3e347d7
parent78d9e7c84f03ac7b83ad2933cac884ce9ecac161 (diff)
GLContext*: Remove '[set/is]Synchronized(..)' - Defaults to wait for locks: 1. Drawable, 2. GLContext
Remove deadlock situation where thread-1 (Animator Thread) holds the GLContext-Lock and acquires the Surface-Lock, while thread-2 (UI/Main/EDT) holds the Surface-Lock and attempts to create the GLContext and hence acquires the GLContext-Lock. A GLContext-Lock and hence makeing the GLContext current requires to hold the Surface-Lock. The prev. code acquired the locks in reverse order and allowed the deadlock as described above. This fix acquires the locks in the proper natural order 1 - Surface-Lock 2 - GLContext-Lock This fix also renders the use of the non-synchronized behavior invalid, since it is bogus not to wait for the GLContext lock where it waits for the Surface lock. It also seems nonsense not to wait for any of both locks and our code always waited for both (synchronized := true). The GLContext [set/is]Synchronized(..) methods are removed and waiting for the lock per default is the correct behavior.
-rwxr-xr-xmake/scripts/tests.sh2
-rw-r--r--src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java1
-rw-r--r--src/jogl/classes/javax/media/opengl/GLContext.java10
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLCanvas.java1
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLJPanel.java3
-rw-r--r--src/jogl/classes/jogamp/opengl/GLContextImpl.java119
-rw-r--r--src/jogl/classes/jogamp/opengl/GLPbufferImpl.java1
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java1
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java1
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java1
-rw-r--r--src/newt/classes/com/jogamp/newt/opengl/GLWindow.java1
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLSimple01NEWT.java1
12 files changed, 50 insertions, 92 deletions
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh
index c9615dd8b..3f178ec96 100755
--- a/make/scripts/tests.sh
+++ b/make/scripts/tests.sh
@@ -230,7 +230,7 @@ testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLContextSurfaceLockNEWT $
#testnoawt com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es1.newt.TestGearsES1NEWT $*
#testawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $*
+testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es1.newt.TestRedSquareES1NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestRedSquareES2NEWT $*
#testnoawt com.jogamp.opengl.test.junit.newt.TestWindows01NEWT $*
diff --git a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
index f2cddca35..73ad97f5c 100644
--- a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
+++ b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
@@ -239,7 +239,6 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
drawable.setRealized(true);
context = drawable.createContext(shareWith);
- context.setSynchronized(true);
/* Register SWT listeners (e.g. PaintListener) to render/resize GL surface. */
/* TODO: verify that these do not need to be manually de-registered when destroying the SWT component */
diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java
index 815da277c..e23fa74f9 100644
--- a/src/jogl/classes/javax/media/opengl/GLContext.java
+++ b/src/jogl/classes/javax/media/opengl/GLContext.java
@@ -319,16 +319,6 @@ public abstract class GLContext {
public abstract void destroy();
/**
- * Returns true if 'makeCurrent' will exhibit synchronized behavior.
- */
- public abstract boolean isSynchronized();
-
- /**
- * Determines whether 'makeCurrent' will exhibit synchronized behavior.
- */
- public abstract void setSynchronized(boolean isSynchronized);
-
- /**
* Returns the GL pipeline object for this GLContext.
*
* @return the aggregated GL instance, or null if this context was not yet made current.
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
index a8d3c03a8..0d32655b9 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
@@ -541,7 +541,6 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
try {
drawable = GLDrawableFactory.getFactory(capsReqUser.getGLProfile()).createGLDrawable(jawtWindow);
context = (GLContextImpl) drawable.createContext(shareWith);
- context.setSynchronized(true);
context.setContextCreationFlags(additionalCtxCreationFlags);
} finally {
jawtWindow.unlockSurface();
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
index db3f189cb..167b99374 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
@@ -974,7 +974,6 @@ public void reshape(int x, int y, int width, int height) {
Math.max(1, panelHeight));
offscreenDrawable.setRealized(true);
offscreenContext = (GLContextImpl) offscreenDrawable.createContext(shareWith);
- offscreenContext.setSynchronized(true);
offscreenContext.setContextCreationFlags(additionalCtxCreationFlags);
isInitialized = true;
@@ -1600,7 +1599,6 @@ public void reshape(int x, int y, int width, int height) {
if (factory.canCreateExternalGLDrawable(device)) {
joglDrawable = factory.createExternalGLDrawable();
joglContext = joglDrawable.createContext(j2dContext);
- joglContext.setSynchronized(true);
if (DEBUG) {
System.err.println("-- Created External Drawable: "+joglDrawable);
System.err.println("-- Created Context: "+joglContext);
@@ -1608,7 +1606,6 @@ public void reshape(int x, int y, int width, int height) {
} else if (factory.canCreateContextOnJava2DSurface(device)) {
// Mac OS X code path
joglContext = factory.createContextOnJava2DSurface(g, j2dContext);
- joglContext.setSynchronized(true);
if (DEBUG) {
System.err.println("-- Created Context: "+joglContext);
}
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index f34856414..996042ffd 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -214,31 +214,6 @@ public abstract class GLContextImpl extends GLContext {
*/
protected void drawableUpdatedNotify() throws GLException { }
- volatile boolean lockFailFast = true;
-
- public boolean isSynchronized() {
- return !lockFailFast; // volatile: ok
- }
-
- public void setSynchronized(boolean isSynchronized) {
- lockFailFast = !isSynchronized; // volatile: ok
- }
-
- private final void lockConsiderFailFast() {
- if( lockFailFast ) { // volatile: ok
- try {
- if( !lock.tryLock(0) ) { // immediate return w/ false, if lock is already held by other thread
- throw new GLException("Error: Attempt to make context current on thread " + Thread.currentThread().getName() +
- " which is already current on thread " + lock.getOwner().getName());
- }
- } catch (InterruptedException ie) {
- throw new GLException(ie);
- }
- } else {
- lock.lock();
- }
- }
-
public abstract Object getPlatformGLExtensions();
// Note: the surface is locked within [makeCurrent .. swap .. release]
@@ -274,13 +249,6 @@ public abstract class GLContextImpl extends GLContext {
protected abstract void releaseImpl() throws GLException;
public final void destroy() {
- // Must hold the lock around the destroy operation to make sure we
- // don't destroy the context out from under another thread rendering to it
- lockConsiderFailFast(); // holdCount++ -> 1 or 2
- try {
- if(lock.getHoldCount() > 2) {
- throw new GLException("XXX: "+lock);
- }
if (DEBUG || TRACE_SWITCH) {
System.err.println(getThreadName() + ": GLContextImpl.destroy.0: " + toHexString(contextHandle) +
", isShared "+GLContextShareSet.isShared(this)+" - "+lock);
@@ -291,39 +259,47 @@ public abstract class GLContextImpl extends GLContext {
// this would be odd ..
throw new GLException("Surface not ready to lock: "+drawable);
}
- // release current context
- if(null != glDebugHandler) {
- if(lock.getHoldCount() == 1) {
- // needs current context to disable debug handler
- makeCurrent();
- }
- glDebugHandler.enable(false);
- }
- if(lock.getHoldCount() > 1) {
- // pending release() after makeCurrent()
- release(true);
- }
try {
- destroyImpl();
- contextHandle = 0;
- glDebugHandler = null;
- // this maybe impl. in a platform specific way to release remaining shared ctx.
- if(GLContextShareSet.contextDestroyed(this) && !GLContextShareSet.hasCreatedSharedLeft(this)) {
- GLContextShareSet.unregisterSharing(this);
+ // Must hold the lock around the destroy operation to make sure we
+ // don't destroy the context while another thread renders to it.
+ // FIXME: This is actually impossible now, since we acquired the surface lock already,
+ // which is a prerequisite to acquire the context lock.
+ lock.lock(); // holdCount++ -> 1 or 2
+ if(lock.getHoldCount() > 2) {
+ throw new GLException("XXX: "+lock);
+ }
+ try {
+ // release current context
+ if(null != glDebugHandler) {
+ if(lock.getHoldCount() == 1) {
+ // needs current context to disable debug handler
+ makeCurrent();
+ }
+ glDebugHandler.enable(false);
+ }
+ if(lock.getHoldCount() > 1) {
+ // pending release() after makeCurrent()
+ release(true);
+ }
+ destroyImpl();
+ contextHandle = 0;
+ glDebugHandler = null;
+ // this maybe impl. in a platform specific way to release remaining shared ctx.
+ if(GLContextShareSet.contextDestroyed(this) && !GLContextShareSet.hasCreatedSharedLeft(this)) {
+ GLContextShareSet.unregisterSharing(this);
+ }
+ } finally {
+ lock.unlock();
+ if (TRACE_SWITCH) {
+ System.err.println(getThreadName() + ": GLContextImpl.destroy.X: " + toHexString(contextHandle) +
+ ", isShared "+GLContextShareSet.isShared(this)+" - "+lock);
+ }
}
} finally {
drawable.unlockSurface();
}
}
- } finally {
- lock.unlock();
- if (TRACE_SWITCH) {
- System.err.println(getThreadName() + ": GLContextImpl.destroy.X: " + toHexString(contextHandle) +
- ", isShared "+GLContextShareSet.isShared(this)+" - "+lock);
- }
- }
-
- resetStates();
+ resetStates();
}
protected abstract void destroyImpl() throws GLException;
@@ -390,18 +366,20 @@ public abstract class GLContextImpl extends GLContext {
*/
public int makeCurrent() throws GLException {
boolean unlockContextAndDrawable = false;
- lockConsiderFailFast();
int res = CONTEXT_NOT_CURRENT;
+
+ // Note: the surface is locked within [makeCurrent .. swap .. release]
+ int lockRes = drawable.lockSurface();
+ if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) {
+ return CONTEXT_NOT_CURRENT;
+ }
try {
- // Note: the surface is locked within [makeCurrent .. swap .. release]
- int lockRes = drawable.lockSurface();
- if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) {
- return CONTEXT_NOT_CURRENT;
+ if (NativeSurface.LOCK_SURFACE_CHANGED == lockRes) {
+ drawable.updateHandle();
}
- try {
- if (NativeSurface.LOCK_SURFACE_CHANGED == lockRes) {
- drawable.updateHandle();
- }
+
+ lock.lock();
+ try {
// One context can only be current by one thread,
// and one thread can only have one context current!
final GLContext current = getCurrent();
@@ -437,7 +415,7 @@ public abstract class GLContextImpl extends GLContext {
throw e;
} finally {
if (unlockContextAndDrawable) {
- drawable.unlockSurface();
+ lock.unlock();
}
}
} catch (RuntimeException e) {
@@ -445,9 +423,10 @@ public abstract class GLContextImpl extends GLContext {
throw e;
} finally {
if (unlockContextAndDrawable) {
- lock.unlock();
+ drawable.unlockSurface();
}
}
+
if (res == CONTEXT_NOT_CURRENT) {
if(TRACE_SWITCH) {
System.err.println(getThreadName() +": GLContext.ContextSwitch: - switch - CONTEXT_NOT_CURRENT - "+lock);
diff --git a/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java b/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java
index 10d5a3f27..0f4f7f8e2 100644
--- a/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java
@@ -85,7 +85,6 @@ public class GLPbufferImpl implements GLPbuffer {
}
this.pbufferDrawable = pbufferDrawable;
context = (GLContextImpl) pbufferDrawable.createContext(parentContext);
- context.setSynchronized(true);
}
public GLContext createContext(GLContext shareWith) {
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
index b696e1ba3..71c0d5539 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
@@ -221,7 +221,6 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
drawable.setRealized(true);
final GLContext context = drawable.createContext(null);
if (null != context) {
- context.setSynchronized(true);
try {
context.makeCurrent(); // could cause exception
madeCurrent = context.isCurrent();
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java
index f4069d430..494bb307e 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java
@@ -307,7 +307,6 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
if (null == sharedContext) {
throw new GLException("Couldn't create shared context for drawable: "+sharedDrawable);
}
- sharedContext.setSynchronized(true);
boolean hasARBPixelFormat;
boolean hasARBMultisample;
boolean hasARBPBuffer;
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
index 223c504e4..092d3439e 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
@@ -245,7 +245,6 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
if (null == sharedContext) {
throw new GLException("Couldn't create shared context for drawable: "+sharedDrawable);
}
- sharedContext.setSynchronized(true);
boolean madeCurrent = false;
sharedContext.makeCurrent();
try {
diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
index 34e0df64f..f89193754 100644
--- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
+++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
@@ -421,7 +421,6 @@ public class GLWindow implements GLAutoDrawable, Window, NEWTEventConsumer, FPSC
}
drawable.setRealized(true);
context = drawable.createContext(sharedContext);
- context.setSynchronized(true);
context.setContextCreationFlags(additionalCtxCreationFlags);
}
if(Window.DEBUG_IMPLEMENTATION) {
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLSimple01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLSimple01NEWT.java
index ba43cc263..dde7252e8 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLSimple01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLSimple01NEWT.java
@@ -65,7 +65,6 @@ public class TestGLSLSimple01NEWT extends UITestCase {
Assert.assertTrue(window.isNativeValid());
GLContext context = window.getContext();
- context.setSynchronized(true);
// trigger native creation of drawable/context
window.display();