summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/jogl/classes/javax/media/opengl/GLContext.java7
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLCanvas.java80
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLJPanel.java52
-rw-r--r--src/jogl/classes/jogamp/opengl/GLContextImpl.java288
-rw-r--r--src/jogl/classes/jogamp/opengl/GLDrawableHelper.java189
-rw-r--r--src/jogl/classes/jogamp/opengl/GLPbufferImpl.java13
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java1
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java1
-rw-r--r--src/newt/classes/com/jogamp/newt/opengl/GLWindow.java11
9 files changed, 378 insertions, 264 deletions
diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java
index 38c2d79e5..2d304b77c 100644
--- a/src/jogl/classes/javax/media/opengl/GLContext.java
+++ b/src/jogl/classes/javax/media/opengl/GLContext.java
@@ -295,8 +295,11 @@ public abstract class GLContext {
/**
* Destroys this OpenGL context and frees its associated
- * resources. The context should have been released before this
- * method is called.
+ * resources.
+ * <p>
+ * The context may be current w/o recursion when calling <code>destroy()</code>,
+ * in which case this method destroys the context and releases the lock.
+ * </p>
*/
public abstract void destroy();
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
index 1b234ef3a..cd341593e 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
@@ -59,6 +59,7 @@ import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.OffscreenLayerOption;
import javax.media.nativewindow.WindowClosingProtocol;
import javax.media.nativewindow.AbstractGraphicsDevice;
@@ -441,25 +442,25 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
disposeRegenerate=regenerate;
- if (Threading.isSingleThreaded() &&
- !Threading.isOpenGLThread()) {
- // 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
- // thread -- but since he/she is, we can not go over to the
- // EDT at this point. Try to destroy the context from here.
- if(context.isCreated()) {
- drawableHelper.invokeGL(drawable, context, disposeAction, null);
+ if(context.isCreated()) {
+ if (Threading.isSingleThreaded() &&
+ !Threading.isOpenGLThread()) {
+ // 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
+ // thread -- but since he/she is, we can not go over to the
+ // EDT at this point. Try to destroy the context from here.
+ drawableHelper.disposeGL(GLCanvas.this, drawable, context, postDisposeAction);
+ } else {
+ Threading.invokeOnOpenGLThread(disposeOnEventDispatchThreadAction);
+ }
+ } else {
+ drawableHelper.disposeGL(GLCanvas.this, drawable, context, postDisposeAction);
}
- } else if(context.isCreated()) {
- Threading.invokeOnOpenGLThread(disposeOnEventDispatchThreadAction);
- }
- } else if(context.isCreated()) {
- drawableHelper.invokeGL(drawable, context, disposeAction, null);
}
if(animatorPaused) {
@@ -834,16 +835,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
}
}
- class DisposeAction implements Runnable {
+ class PostDisposeAction implements Runnable {
public void run() {
- drawableHelper.dispose(GLCanvas.this);
-
- if(null!=context) {
- context.makeCurrent(); // implicit wait for lock ..
- context.destroy();
- context=null;
- }
-
+ context=null;
if(null!=drawable) {
final JAWTWindow jawtWindow = (JAWTWindow)drawable.getNativeSurface();
drawable.setRealized(false);
@@ -867,21 +861,22 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
}
}
private boolean disposeRegenerate;
- private DisposeAction disposeAction = new DisposeAction();
+ private PostDisposeAction postDisposeAction = new PostDisposeAction();
private DisposeOnEventDispatchThreadAction disposeOnEventDispatchThreadAction =
new DisposeOnEventDispatchThreadAction();
class DisposeOnEventDispatchThreadAction implements Runnable {
public void run() {
- drawableHelper.invokeGL(drawable, context, disposeAction, null);
+ drawableHelper.disposeGL(GLCanvas.this, drawable, context, postDisposeAction);
}
}
class DisposeAbstractGraphicsDeviceAction implements Runnable {
public void run() {
if(null != awtConfig) {
- final AbstractGraphicsDevice adevice = awtConfig.getScreen().getDevice();
+ final AbstractGraphicsConfiguration aconfig = awtConfig.getNativeGraphicsConfiguration();
+ final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice();
final String adeviceMsg;
if(DEBUG) {
adeviceMsg = adevice.toString();
@@ -1091,9 +1086,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
}
GLCapabilitiesImmutable caps = new GLCapabilities( GLProfile.getDefault(GLProfile.getDefaultDesktopDevice()) );
- Frame frame = new Frame("JOGL AWT Test");
+ final Frame frame = new Frame("JOGL AWT Test");
- GLCanvas glCanvas = new GLCanvas(caps);
+ final GLCanvas glCanvas = new GLCanvas(caps);
frame.add(glCanvas);
frame.setSize(128, 128);
@@ -1102,24 +1097,15 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
GL gl = drawable.getGL();
System.err.println(JoglVersion.getGLInfo(gl, null));
}
-
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
- }
-
- public void display(GLAutoDrawable drawable) {
- }
-
- public void dispose(GLAutoDrawable drawable) {
- }
+ public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
+ public void display(GLAutoDrawable drawable) { }
+ public void dispose(GLAutoDrawable drawable) { }
});
- final Frame _frame = frame;
- final GLCanvas _glCanvas = glCanvas;
-
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
- _frame.setVisible(true);
+ frame.setVisible(true);
}});
} catch (Throwable t) {
t.printStackTrace();
@@ -1128,9 +1114,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
- _frame.setVisible(false);
- _frame.remove(_glCanvas);
- _frame.dispose();
+ frame.dispose();
}});
} catch (Throwable t) {
t.printStackTrace();
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
index 0d28ab31b..7a87882ca 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
@@ -284,27 +284,24 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
animatorPaused = animator.pause();
}
- final GLDrawable drawable = backend.getDrawable();
- final GLContext context = backend.getContext();
-
- if (Threading.isSingleThreaded() &&
- !Threading.isOpenGLThread()) {
- // 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
- if (ThreadingImpl.isAWTMode() &&
- Thread.holdsLock(getTreeLock())) {
- // The user really should not be invoking remove() from this
- // thread -- but since he/she is, we can not go over to the
- // EDT at this point. Try to destroy the context from here.
- if(context.isCreated()) {
- drawableHelper.invokeGL(drawable, context, disposeAction, null);
- }
- } else if(context.isCreated()) {
- Threading.invokeOnOpenGLThread(disposeOnEventDispatchThreadAction);
+ if(backend.getContext().isCreated()) {
+ if (Threading.isSingleThreaded() &&
+ !Threading.isOpenGLThread()) {
+ // 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
+ if (ThreadingImpl.isAWTMode() &&
+ Thread.holdsLock(getTreeLock())) {
+ // The user really should not be invoking remove() from this
+ // thread -- but since he/she is, we can not go over to the
+ // EDT at this point. Try to destroy the context from here.
+ drawableHelper.disposeGL(GLJPanel.this, backend.getDrawable(), backend.getContext(), postDisposeAction);
+ } else {
+ Threading.invokeOnOpenGLThread(disposeOnEventDispatchThreadAction);
+ }
+ } else {
+ drawableHelper.disposeGL(GLJPanel.this, backend.getDrawable(), backend.getContext(), postDisposeAction);
}
- } else if(context.isCreated()) {
- drawableHelper.invokeGL(drawable, context, disposeAction, null);
}
if(null != backend) {
// not yet destroyed due to backend.isUsingOwnThreadManagment() == true
@@ -689,12 +686,8 @@ public void reshape(int x, int y, int width, int height) {
return "AWT-GLJPanel[ "+((null!=backend)?backend.getDrawable().getClass().getName():"null-drawable")+"]";
}
- private DisposeAction disposeAction = new DisposeAction();
-
- class DisposeAction implements Runnable {
+ class PostDisposeAction implements Runnable {
public void run() {
- updater.dispose(GLJPanel.this);
-
if (backend != null && !backend.isUsingOwnThreadManagment()) {
backend.destroy();
backend = null;
@@ -702,13 +695,14 @@ public void reshape(int x, int y, int width, int height) {
}
}
}
+ private PostDisposeAction postDisposeAction = new PostDisposeAction();
private DisposeOnEventDispatchThreadAction disposeOnEventDispatchThreadAction =
new DisposeOnEventDispatchThreadAction();
class DisposeOnEventDispatchThreadAction implements Runnable {
public void run() {
- drawableHelper.invokeGL(backend.getDrawable(), backend.getContext(), disposeAction, null);
+ drawableHelper.disposeGL(GLJPanel.this, backend.getDrawable(), backend.getContext(), postDisposeAction);
}
}
@@ -1579,15 +1573,13 @@ public void reshape(int x, int y, int width, int height) {
backend = null;
oglPipelineEnabled = false;
handleReshape = true;
- j2dContext.release();
j2dContext.destroy();
j2dContext = null;
return;
}
- j2dContext.release();
+ } else {
+ j2dContext.makeCurrent();
}
-
- j2dContext.makeCurrent();
try {
captureJ2DState(j2dContext.getGL(), g);
Object curSurface = Java2D.getOGLSurfaceIdentifier(g);
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 28bb11f1e..4701ab544 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -69,6 +69,8 @@ import javax.media.opengl.GLPipelineFactory;
import javax.media.opengl.GLProfile;
public abstract class GLContextImpl extends GLContext {
+ public static final boolean TRACE_SWITCH = Debug.isPropertyDefined("jogl.debug.GLContext.TraceSwitch", true);
+
// RecursiveLock maintains a queue of waiting Threads, ensuring the longest waiting thread will be notified at unlock.
protected RecursiveLock lock = LockFactory.createRecursiveLock();
@@ -213,74 +215,94 @@ public abstract class GLContextImpl extends GLContext {
*/
protected void drawableUpdatedNotify() throws GLException { }
- boolean lockFailFast = true;
- Object lockFailFastSync = new Object();
+ volatile boolean lockFailFast = true;
public boolean isSynchronized() {
- synchronized (lockFailFastSync) {
- return !lockFailFast;
- }
+ return !lockFailFast; // volatile: ok
}
public void setSynchronized(boolean isSynchronized) {
- synchronized (lockFailFastSync) {
- lockFailFast = !isSynchronized;
- }
+ lockFailFast = !isSynchronized; // volatile: ok
}
- private final void lockConsiderFailFast() {
- synchronized (lockFailFastSync) {
- if(lockFailFast && lock.isLockedByOtherThread()) {
- throw new GLException("Error: Attempt to make context current on thread " + Thread.currentThread() +
- " which is already current on thread " + lock.getOwner());
+ 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();
}
- lock.lock();
}
public abstract Object getPlatformGLExtensions();
// Note: the surface is locked within [makeCurrent .. swap .. release]
public void release() throws GLException {
+ release(false);
+ }
+ private void release(boolean force) throws GLException {
if ( !lock.isOwner() ) {
throw new GLException("Context not current on current thread");
}
- setCurrent(null);
+ final boolean actualRelease = force || lock.getHoldCount() == 1 ;
try {
- releaseImpl();
+ if( actualRelease ) {
+ setCurrent(null);
+ if (contextHandle != 0) { // allow dbl-release
+ releaseImpl();
+ }
+ }
} finally {
- if (drawable.isSurfaceLocked()) {
- drawable.unlockSurface();
- }
+ drawable.unlockSurface();
lock.unlock();
+ if(TRACE_SWITCH) {
+ if( actualRelease ) {
+ System.err.println("GLContext.ContextSwitch: - switch - CONTEXT_RELEASE - "+Thread.currentThread().getName()+" - "+lock);
+ } else {
+ System.err.println("GLContext.ContextSwitch: - keep - CONTEXT_RELEASE - "+Thread.currentThread().getName()+" - "+lock);
+ }
+ }
}
}
protected abstract void releaseImpl() throws GLException;
public final void destroy() {
- if ( lock.isOwner() ) {
- // release current context
- if(null != glDebugHandler) {
- glDebugHandler.enable(false);
- }
- release();
- }
-
// 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();
+ lockConsiderFailFast(); // holdCount++ -> 1 or 2
try {
+ if(lock.getHoldCount() > 2) {
+ throw new GLException("XXX: "+lock);
+ }
+ if (DEBUG || TRACE_SWITCH) {
+ System.err.println("GLContextImpl.destroy.0: " + toHexString(contextHandle) +
+ ", isShared "+GLContextShareSet.isShared(this)+" - "+lock);
+ }
if (contextHandle != 0) {
int lockRes = drawable.lockSurface();
if (NativeSurface.LOCK_SURFACE_NOT_READY == lockRes) {
// this would be odd ..
throw new GLException("Surface not ready to lock: "+drawable);
}
- try {
- if (DEBUG) {
- System.err.println("GLContextImpl.destroy: " + toHexString(contextHandle) +
- ", isShared "+GLContextShareSet.isShared(this));
+ // 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;
@@ -294,6 +316,10 @@ public abstract class GLContextImpl extends GLContext {
}
} finally {
lock.unlock();
+ if (DEBUG || TRACE_SWITCH) {
+ System.err.println("GLContextImpl.destroy.X: " + toHexString(contextHandle) +
+ ", isShared "+GLContextShareSet.isShared(this)+" - "+lock);
+ }
}
resetStates();
@@ -362,55 +388,75 @@ public abstract class GLContextImpl extends GLContext {
* @see #destroyContextARBImpl
*/
public int makeCurrent() throws GLException {
- // One context can only be current by one thread,
- // and one thread can only have one context current!
- final GLContext current = getCurrent();
- if (current != null) {
- if (current == this) {
- // Assume we don't need to make this context current again
- // For Mac OS X, however, we need to update the context to track resizes
- drawableUpdatedNotify();
- return CONTEXT_CURRENT;
- } else {
- current.release();
- }
- }
-
- if (GLWorkerThread.isStarted() &&
- !GLWorkerThread.isWorkerThread()) {
- // Kick the GLWorkerThread off its current context
- GLWorkerThread.invokeLater(new Runnable() { public void run() {} });
- }
-
- if (!isCreated()) {
- // verify if the drawable has chosen Capabilities
- if (null == getGLDrawable().getChosenGLCapabilities()) {
- throw new GLException("drawable has no chosen GLCapabilities: "+getGLDrawable());
- }
- if(DEBUG_GL) {
- // only impacts w/ createContextARB(..)
- additionalCtxCreationFlags |= GLContext.CTX_OPTION_DEBUG ;
- }
- }
-
+ boolean unlockContextAndDrawable = false;
lockConsiderFailFast();
- int res = 0;
+ int res = CONTEXT_NOT_CURRENT;
try {
- res = makeCurrentLocking();
-
- /* FIXME: refactor dependence on Java 2D / JOGL bridge
- if ((tracker != null) &&
- (res == CONTEXT_CURRENT_NEW)) {
- // Increase reference count of GLObjectTracker
- tracker.ref();
- }
- */
- } catch (GLException e) {
- lock.unlock();
- throw(e);
+ // 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 {
+ if (NativeSurface.LOCK_SURFACE_CHANGED == lockRes) {
+ drawable.updateHandle();
+ }
+ // One context can only be current by one thread,
+ // and one thread can only have one context current!
+ final GLContext current = getCurrent();
+ if (current != null) {
+ if (current == this) {
+ // Assume we don't need to make this context current again
+ // For Mac OS X, however, we need to update the context to track resizes
+ drawableUpdatedNotify();
+ if(TRACE_SWITCH) {
+ System.err.println("GLContext.ContextSwitch: - keep - CONTEXT_CURRENT - "+Thread.currentThread().getName()+" - "+lock);
+ }
+ return CONTEXT_CURRENT;
+ } else {
+ current.release();
+ }
+ }
+ if (GLWorkerThread.isStarted() &&
+ !GLWorkerThread.isWorkerThread()) {
+ // Kick the GLWorkerThread off its current context
+ GLWorkerThread.invokeLater(new Runnable() { public void run() {} });
+ }
+
+ if (0 == drawable.getHandle()) {
+ throw new GLException("drawable has invalid handle: "+drawable);
+ }
+ res = makeCurrentWithinLock(lockRes);
+ unlockContextAndDrawable = CONTEXT_NOT_CURRENT == res;
+
+ /**
+ * FIXME: refactor dependence on Java 2D / JOGL bridge
+ if ((tracker != null) &&
+ (res == CONTEXT_CURRENT_NEW)) {
+ // Increase reference count of GLObjectTracker
+ tracker.ref();
+ }
+ */
+ } catch (RuntimeException e) {
+ unlockContextAndDrawable = true;
+ throw e;
+ } finally {
+ if (unlockContextAndDrawable) {
+ drawable.unlockSurface();
+ }
+ }
+ } catch (RuntimeException e) {
+ unlockContextAndDrawable = true;
+ throw e;
+ } finally {
+ if (unlockContextAndDrawable) {
+ lock.unlock();
+ }
}
if (res == CONTEXT_NOT_CURRENT) {
- lock.unlock();
+ if(TRACE_SWITCH) {
+ System.err.println("GLContext.ContextSwitch: - switch - CONTEXT_NOT_CURRENT - "+Thread.currentThread().getName()+" - "+lock);
+ }
} else {
setCurrent(this);
if(res == CONTEXT_CURRENT_NEW) {
@@ -429,6 +475,11 @@ public abstract class GLContextImpl extends GLContext {
if(TRACE_GL) {
gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", null, gl, new Object[] { System.err } ) );
}
+ if(TRACE_SWITCH) {
+ System.err.println("GLContext.ContextSwitch: - switch - CONTEXT_CURRENT_NEW - "+Thread.currentThread().getName()+" - "+lock);
+ }
+ } else if(TRACE_SWITCH) {
+ System.err.println("GLContext.ContextSwitch: - switch - CONTEXT_CURRENT - "+Thread.currentThread().getName()+" - "+lock);
}
/* FIXME: refactor dependence on Java 2D / JOGL bridge
@@ -443,66 +494,47 @@ public abstract class GLContextImpl extends GLContext {
return res;
}
- // Note: the surface is locked within [makeCurrent .. swap .. release]
- protected final int makeCurrentLocking() throws GLException {
- boolean shallUnlockSurface = false;
- int lockRes = drawable.lockSurface();
- try {
- if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) {
- return CONTEXT_NOT_CURRENT;
- }
- try {
- if (NativeSurface.LOCK_SURFACE_CHANGED == lockRes) {
- drawable.updateHandle();
- }
- if (0 == drawable.getHandle()) {
- throw new GLException("drawable has invalid handle: "+drawable);
- }
- if (!isCreated()) {
- final GLContextImpl shareWith = (GLContextImpl) GLContextShareSet.getShareContext(this);
+ private final int makeCurrentWithinLock(int surfaceLockRes) throws GLException {
+ if (!isCreated()) {
+ if(DEBUG_GL) {
+ // only impacts w/ createContextARB(..)
+ additionalCtxCreationFlags |= GLContext.CTX_OPTION_DEBUG ;
+ }
+
+ final GLContextImpl shareWith = (GLContextImpl) GLContextShareSet.getShareContext(this);
+ if (null != shareWith) {
+ shareWith.getDrawableImpl().lockSurface();
+ }
+ final boolean created;
+ try {
+ created = createImpl(shareWith); // may throws exception if fails!
+ } finally {
if (null != shareWith) {
- shareWith.getDrawableImpl().lockSurface();
- }
- boolean created;
- try {
- created = createImpl(shareWith); // may throws exception if fails!
- } finally {
- if (null != shareWith) {
- shareWith.getDrawableImpl().unlockSurface();
- }
- }
- if (DEBUG) {
- if(created) {
- System.err.println(getThreadName() + ": !!! Create GL context OK: " + toHexString(contextHandle) + " for " + getClass().getName());
- } else {
- System.err.println(getThreadName() + ": !!! Create GL context FAILED for " + getClass().getName());
- }
- }
- if(!created) {
- shallUnlockSurface = true;
- return CONTEXT_NOT_CURRENT;
+ shareWith.getDrawableImpl().unlockSurface();
+ }
+ }
+ if (DEBUG) {
+ if(created) {
+ System.err.println(getThreadName() + ": !!! Create GL context OK: " + toHexString(contextHandle) + " for " + getClass().getName());
+ } else {
+ System.err.println(getThreadName() + ": !!! Create GL context FAILED for " + getClass().getName());
}
- GLContextShareSet.contextCreated(this);
- return CONTEXT_CURRENT_NEW;
- }
- makeCurrentImpl();
- return CONTEXT_CURRENT;
- } catch (RuntimeException e) {
- shallUnlockSurface = true;
- throw e;
- }
- } finally {
- if (shallUnlockSurface) {
- drawable.unlockSurface();
+ }
+ if(!created) {
+ return CONTEXT_NOT_CURRENT;
+ }
+ GLContextShareSet.contextCreated(this);
+ return CONTEXT_CURRENT_NEW;
}
- }
+ makeCurrentImpl();
+ return CONTEXT_CURRENT;
}
protected abstract void makeCurrentImpl() throws GLException;
/**
* Platform dependent entry point for context creation.<br>
*
- * This method is called from {@link #makeCurrentLocking()} .. {@link #makeCurrent()} .<br>
+ * This method is called from {@link #makeCurrentWithinLock()} .. {@link #makeCurrent()} .<br>
*
* The implementation shall verify this context with a
* <code>MakeContextCurrent</code> call.<br>
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
index 41b4ea878..509839f55 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
@@ -57,6 +57,9 @@ import com.jogamp.opengl.util.Animator;
methods to be able to share it between GLCanvas and GLJPanel. */
public class GLDrawableHelper {
+ /** true if property <code>jogl.debug.GLDrawable.PerfStats</code> is defined. */
+ private static final boolean PERF_STATS = Debug.isPropertyDefined("jogl.debug.GLDrawable.PerfStats", true);
+
protected static final boolean DEBUG = GLDrawableImpl.DEBUG;
private Object listenersLock = new Object();
private ArrayList<GLEventListener> listeners;
@@ -128,6 +131,10 @@ public class GLDrawableHelper {
/**
* Issues {@link javax.media.opengl.GLEventListener#dispose(javax.media.opengl.GLAutoDrawable)}
* to all listeners.
+ * <p>
+ * Please consider using {@link #disposeGL(GLAutoDrawable, GLDrawable, GLContext, Runnable)}
+ * for correctness!
+ * </p>
* @param drawable
*/
public final void dispose(GLAutoDrawable drawable) {
@@ -137,7 +144,7 @@ public class GLDrawableHelper {
}
}
}
-
+
private boolean init(GLEventListener l, GLAutoDrawable drawable, boolean sendReshape) {
if(listenersToBeInit.remove(l)) {
l.init(drawable);
@@ -307,6 +314,8 @@ public class GLDrawableHelper {
* ie. {@link Animator#getThread()}.
* @deprecated this is an experimental feature,
* intended for measuring performance in regards to GL context switch
+ * and only being used if {@link #PERF_STATS} is enabled
+ * by defining property <code>jogl.debug.GLDrawable.PerfStats</code>.
*/
public final void setSkipContextReleaseThread(Thread t) {
skipContextReleaseThread = t;
@@ -318,7 +327,7 @@ public class GLDrawableHelper {
public final Thread getSkipContextReleaseThread() {
return skipContextReleaseThread;
}
-
+
private static final ThreadLocal<Runnable> perThreadInitAction = new ThreadLocal<Runnable>();
/** Principal helper method which runs a Runnable with the context
@@ -328,8 +337,6 @@ public class GLDrawableHelper {
class helps ensure that we don't inadvertently use private
methods of the GLContext or its implementing classes.<br>
* <br>
- * Remark: In case this method is called to dispose the GLDrawable/GLAutoDrawable,
- * <code>initAction</code> shall be <code>null</code> to mark this cause.<br>
*
* @param drawable
* @param context
@@ -348,12 +355,112 @@ public class GLDrawableHelper {
return;
}
- final boolean isDisposeAction = null==initAction ;
-
- if( isDisposeAction && !context.isCreated() ) {
- throw new GLException(Thread.currentThread().getName()+" GLDrawableHelper " + this + ".invokeGL(): Dispose case (no init action given): Native context is not created: "+context);
+ if(PERF_STATS) {
+ invokeGLImplStats(drawable, context, runnable, initAction, null);
+ } else {
+ invokeGLImpl(drawable, context, runnable, initAction, null);
}
+ }
+ /**
+ * Principal helper method which runs {@link #dispose(GLAutoDrawable)} with the context
+ * made current and destroys the context afterwards while holding the lock.
+ *
+ * @param autoDrawable
+ * @param drawable
+ * @param context
+ * @param postAction
+ */
+ public final void disposeGL(GLAutoDrawable autoDrawable,
+ GLDrawable drawable,
+ GLContext context,
+ Runnable postAction) {
+ if(PERF_STATS) {
+ invokeGLImplStats(drawable, context, null, null, autoDrawable);
+ } else {
+ invokeGLImpl(drawable, context, null, null, autoDrawable);
+ }
+ if(null != postAction) {
+ postAction.run();
+ }
+ }
+
+ private final void invokeGLImpl(GLDrawable drawable,
+ GLContext context,
+ Runnable runnable,
+ Runnable initAction,
+ GLAutoDrawable disposeAutoDrawable) {
+ final Thread currentThread = Thread.currentThread();
+
+ final boolean isDisposeAction = null==initAction ;
+
+ // Support for recursive makeCurrent() calls as well as calling
+ // other drawables' display() methods from within another one's
+ GLContext lastContext = GLContext.getCurrent();
+ Runnable lastInitAction = null;
+ if (lastContext != null) {
+ if (lastContext == context) {
+ lastContext = null; // utilize recursive locking
+ } else {
+ lastInitAction = perThreadInitAction.get();
+ lastContext.release();
+ }
+ }
+ int res = GLContext.CONTEXT_NOT_CURRENT;
+
+ try {
+ res = context.makeCurrent();
+ if (res != GLContext.CONTEXT_NOT_CURRENT) {
+ if(!isDisposeAction) {
+ perThreadInitAction.set(initAction);
+ if (res == GLContext.CONTEXT_CURRENT_NEW) {
+ if (DEBUG) {
+ System.err.println("GLDrawableHelper " + this + ".invokeGL(): Running initAction");
+ }
+ initAction.run();
+ }
+ runnable.run();
+ if (autoSwapBufferMode) {
+ drawable.swapBuffers();
+ }
+ } else {
+ if(res == GLContext.CONTEXT_CURRENT_NEW) {
+ throw new GLException(currentThread.getName()+" GLDrawableHelper " + this + ".invokeGL(): Dispose case (no init action given): Native context was not created (new ctx): "+context);
+ }
+ if(listeners.size()>0) {
+ dispose(disposeAutoDrawable);
+ }
+ }
+ }
+ } finally {
+ try {
+ if(isDisposeAction) {
+ context.destroy();
+ } else if( res != GLContext.CONTEXT_NOT_CURRENT ) {
+ context.release();
+ }
+ } catch (Exception e) {
+ System.err.println("Catched: "+e.getMessage());
+ e.printStackTrace();
+ }
+ if (lastContext != null) {
+ final int res2 = lastContext.makeCurrent();
+ if (null != lastInitAction && res2 == GLContext.CONTEXT_CURRENT_NEW) {
+ lastInitAction.run();
+ }
+ }
+ }
+ }
+
+ private final void invokeGLImplStats(GLDrawable drawable,
+ GLContext context,
+ Runnable runnable,
+ Runnable initAction,
+ GLAutoDrawable disposeAutoDrawable) {
+ final Thread currentThread = Thread.currentThread();
+
+ final boolean isDisposeAction = null==initAction ;
+
// Support for recursive makeCurrent() calls as well as calling
// other drawables' display() methods from within another one's
int res = GLContext.CONTEXT_NOT_CURRENT;
@@ -361,7 +468,9 @@ public class GLDrawableHelper {
Runnable lastInitAction = null;
if (lastContext != null) {
if (lastContext == context) {
- res = GLContext.CONTEXT_CURRENT;
+ if( currentThread == skipContextReleaseThread ) {
+ res = GLContext.CONTEXT_CURRENT;
+ } // else: utilize recursive locking
lastContext = null;
} else {
lastInitAction = perThreadInitAction.get();
@@ -369,17 +478,18 @@ public class GLDrawableHelper {
}
}
- /**
long t0 = System.currentTimeMillis();
- long td1 = 0; // makeCurrent
+ long tdA = 0; // makeCurrent
long tdR = 0; // render time
- long td2 = 0; // swapBuffers
- long td3 = 0; // release
- boolean scr = true; */
-
+ long tdS = 0; // swapBuffers
+ long tdX = 0; // release
+ boolean ctxClaimed = false;
+ boolean ctxReleased = false;
+ boolean ctxDestroyed = false;
try {
if (res == GLContext.CONTEXT_NOT_CURRENT) {
res = context.makeCurrent();
+ ctxClaimed = true;
}
if (res != GLContext.CONTEXT_NOT_CURRENT) {
if(!isDisposeAction) {
@@ -390,39 +500,50 @@ public class GLDrawableHelper {
}
initAction.run();
}
- }
- // tdR = System.currentTimeMillis();
- // td1 = tdR - t0; // makeCurrent
- if(null!=runnable) {
+ tdR = System.currentTimeMillis();
+ tdA = tdR - t0; // makeCurrent
runnable.run();
- // td2 = System.currentTimeMillis();
- // tdR = td2 - tdR; // render time
- if (autoSwapBufferMode && !isDisposeAction && drawable != null) {
+ tdS = System.currentTimeMillis();
+ tdR = tdS - tdR; // render time
+ if (autoSwapBufferMode) {
drawable.swapBuffers();
- // td3 = System.currentTimeMillis();
- // td2 = td3 - td2; // swapBuffers
+ tdX = System.currentTimeMillis();
+ tdS = tdX - tdS; // swapBuffers
+ }
+ } else {
+ if(res == GLContext.CONTEXT_CURRENT_NEW) {
+ throw new GLException(currentThread.getName()+" GLDrawableHelper " + this + ".invokeGL(): Dispose case (no init action given): Native context was not created (new ctx): "+context);
+ }
+ if(listeners.size()>0) {
+ dispose(disposeAutoDrawable);
}
}
}
} finally {
- if(res != GLContext.CONTEXT_NOT_CURRENT &&
- (null == skipContextReleaseThread || Thread.currentThread()!=skipContextReleaseThread) ) {
- try {
+ try {
+ if(isDisposeAction) {
+ context.destroy();
+ ctxDestroyed = true;
+ } else if( res != GLContext.CONTEXT_NOT_CURRENT &&
+ (null == skipContextReleaseThread || currentThread != skipContextReleaseThread) ) {
context.release();
- // scr = false;
- } catch (Exception e) {
+ ctxReleased = true;
}
+ } catch (Exception e) {
+ System.err.println("Catched: "+e.getMessage());
+ e.printStackTrace();
}
- // td3 = System.currentTimeMillis() - td3; // release
+
+ tdX = System.currentTimeMillis() - tdX; // release / destroy
if (lastContext != null) {
- int res2 = lastContext.makeCurrent();
+ final int res2 = lastContext.makeCurrent();
if (null != lastInitAction && res2 == GLContext.CONTEXT_CURRENT_NEW) {
lastInitAction.run();
}
}
}
- // long td0 = System.currentTimeMillis() - t0;
- // System.err.println("td0 "+td0+"ms, fps "+(1.0/(td0/1000.0))+", td-makeCurrent: "+td1+"ms, td-render "+tdR+"ms, td-swap "+td2+"ms, td-release "+td3+"ms, skip ctx release: "+scr);
+ long td = System.currentTimeMillis() - t0;
+ System.err.println("td0 "+td+"ms, fps "+(1.0/(td/1000.0))+", td-makeCurrent: "+tdA+"ms, td-render "+tdR+"ms, td-swap "+tdS+"ms, td-release "+tdX+"ms, ctx claimed: "+ctxClaimed+", ctx release: "+ctxReleased+", ctx destroyed "+ctxDestroyed);
}
-
+
}
diff --git a/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java b/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java
index ae83965e9..10d5a3f27 100644
--- a/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java
@@ -99,28 +99,21 @@ public class GLPbufferImpl implements GLPbuffer {
return true;
}
- class DisposeAction implements Runnable {
- public void run() {
- // Lock: Covered by DestroyAction ..
- drawableHelper.dispose(GLPbufferImpl.this);
- }
- }
- DisposeAction disposeAction = new DisposeAction();
-
public void destroy() {
if(pbufferDrawable.isRealized()) {
final AbstractGraphicsDevice adevice = pbufferDrawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice();
if (null != context && context.isCreated()) {
try {
- drawableHelper.invokeGL(pbufferDrawable, context, disposeAction, null);
+ drawableHelper.disposeGL(GLPbufferImpl.this, pbufferDrawable, context, null);
} catch (GLException gle) {
gle.printStackTrace();
}
- context.destroy();
+ context = null;
// drawableHelper.reset();
}
pbufferDrawable.destroy();
+ pbufferDrawable = null;
if(null != adevice) {
adevice.close();
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
index 1e55879f7..3dd7a7f08 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
@@ -234,7 +234,6 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
gle.printStackTrace();
}
} finally {
- context.release();
context.destroy();
}
}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
index 235aea499..acced638f 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
@@ -283,7 +283,6 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
if (null != sr.context) {
// may cause JVM SIGSEGV:
- sr.context.makeCurrent();
sr.context.destroy();
sr.context = null;
}
diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
index d03a475ee..1a15a9664 100644
--- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
+++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
@@ -355,14 +355,6 @@ public class GLWindow implements GLAutoDrawable, Window, NEWTEventConsumer, FPSC
// Hide methods here ..
protected class GLLifecycleHook implements WindowImpl.LifecycleHook {
- private class DisposeAction implements Runnable {
- public final void run() {
- // Lock: Covered by DestroyAction ..
- helper.dispose(GLWindow.this);
- }
- }
- DisposeAction disposeAction = new DisposeAction();
-
public synchronized void destroyActionPreLock() {
// nop
}
@@ -380,11 +372,10 @@ public class GLWindow implements GLAutoDrawable, Window, NEWTEventConsumer, FPSC
// Catch dispose GLExceptions by GLEventListener, just 'print' them
// so we can continue with the destruction.
try {
- helper.invokeGL(drawable, context, disposeAction, null);
+ helper.disposeGL(GLWindow.this, drawable, context, null);
} catch (GLException gle) {
gle.printStackTrace();
}
- context.destroy();
}
drawable.setRealized(false);
}