summaryrefslogtreecommitdiffstats
path: root/src/jogl/classes
diff options
context:
space:
mode:
Diffstat (limited to 'src/jogl/classes')
-rw-r--r--src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java2
-rw-r--r--src/jogl/classes/javax/media/opengl/GLContext.java4
-rw-r--r--src/jogl/classes/javax/media/opengl/Threading.java44
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLCanvas.java269
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLJPanel.java122
-rw-r--r--src/jogl/classes/jogamp/opengl/GLContextImpl.java28
-rw-r--r--src/jogl/classes/jogamp/opengl/GLWorkerThread.java11
-rw-r--r--src/jogl/classes/jogamp/opengl/ThreadingImpl.java106
-rw-r--r--src/jogl/classes/jogamp/opengl/ToolkitThreadingPlugin.java (renamed from src/jogl/classes/jogamp/opengl/ThreadingPlugin.java)11
-rw-r--r--src/jogl/classes/jogamp/opengl/awt/AWTThreadingPlugin.java41
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java46
11 files changed, 309 insertions, 375 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
index b4c7cddf0..f2cddca35 100644
--- a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
+++ b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
@@ -526,7 +526,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
assert display.getThread() != Thread.currentThread() : "Incorrect use of thread dispatching.";
display.syncExec(makeCurrentAndRunAction);
} else {
- Threading.invokeOnOpenGLThread(makeCurrentAndRunAction);
+ Threading.invokeOnOpenGLThread(true, makeCurrentAndRunAction);
}
}
diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java
index 41dce0d3b..51adce70c 100644
--- a/src/jogl/classes/javax/media/opengl/GLContext.java
+++ b/src/jogl/classes/javax/media/opengl/GLContext.java
@@ -66,9 +66,9 @@ import jogamp.opengl.GLContextImpl;
abstraction provides a stable object which clients can use to
refer to a given context. */
public abstract class GLContext {
- public static final boolean DEBUG = Debug.debug("GLContext");
+ public static final boolean DEBUG = Debug.debug("GLContext");
+ public static final boolean TRACE_SWITCH = DEBUG || Debug.isPropertyDefined("jogl.debug.GLContext.TraceSwitch", true);
- public static final boolean TRACE_SWITCH = Debug.isPropertyDefined("jogl.debug.GLContext.TraceSwitch", true);
/** Reflects property jogl.debug.DebugGL. If true, the debug pipeline is enabled at context creation. */
public final static boolean DEBUG_GL = Debug.isPropertyDefined("jogl.debug.DebugGL", true);
/** Reflects property jogl.debug.TraceGL. If true, the trace pipeline is enabled at context creation. */
diff --git a/src/jogl/classes/javax/media/opengl/Threading.java b/src/jogl/classes/javax/media/opengl/Threading.java
index 4871c1dd7..4788f9cf6 100644
--- a/src/jogl/classes/javax/media/opengl/Threading.java
+++ b/src/jogl/classes/javax/media/opengl/Threading.java
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2012 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
@@ -39,7 +40,7 @@
package javax.media.opengl;
-import jogamp.opengl.*;
+import jogamp.opengl.ThreadingImpl;
/** This API provides access to the threading model for the implementation of
the classes in this package.
@@ -133,21 +134,27 @@ public class Threading {
once disabled, partly to discourage careless use of this
method. This method should be called as early as possible in an
application. */
- public static void disableSingleThreading() {
+ public static final void disableSingleThreading() {
ThreadingImpl.disableSingleThreading();
}
/** Indicates whether OpenGL work is being automatically forced to a
single thread in this implementation. */
- public static boolean isSingleThreaded() {
+ public static final boolean isSingleThreaded() {
return ThreadingImpl.isSingleThreaded();
}
+ /** Indicates whether the current thread is the designated toolkit thread,
+ if such semantics exists. */
+ public static final boolean isToolkitThread() throws GLException {
+ return ThreadingImpl.isToolkitThread();
+ }
+
/** Indicates whether the current thread is the single thread on
which this implementation of the javax.media.opengl APIs
performs all of its OpenGL-related work. This method should only
be called if the single-thread model is in effect. */
- public static boolean isOpenGLThread() throws GLException {
+ public static final boolean isOpenGLThread() throws GLException {
return ThreadingImpl.isOpenGLThread();
}
@@ -159,8 +166,31 @@ public class Threading {
thread (i.e., if <code>isOpenGLThread()</code> returns
false). It is up to the end user to check to see whether the
current thread is the OpenGL thread and either execute the
- Runnable directly or perform the work inside it. */
- public static void invokeOnOpenGLThread(Runnable r) throws GLException {
- ThreadingImpl.invokeOnOpenGLThread(r);
+ Runnable directly or perform the work inside it.
+ **/
+ public static final void invokeOnOpenGLThread(boolean wait, Runnable r) throws GLException {
+ ThreadingImpl.invokeOnOpenGLThread(wait, r);
+ }
+
+ /**
+ * If {@link #isSingleThreaded()} <b>and</b> not {@link #isOpenGLThread()}
+ * <b>and</b> the <code>lock</code> is not being hold by this thread,
+ * invoke Runnable <code>r</code> on the OpenGL thread via {@link #invokeOnOpenGLThread(boolean, Runnable)}.
+ * <p>
+ * Otherwise invoke Runnable <code>r</code> on the current thread.
+ * </p>
+ *
+ * @param wait set to true for waiting until Runnable <code>r</code> is finished, otherwise false.
+ * @param r the Runnable to be executed
+ * @param lock optional lock object to be tested
+ * @throws GLException
+ */
+ public static final void invoke(boolean wait, Runnable r, Object lock) throws GLException {
+ if ( isSingleThreaded() && !isOpenGLThread() &&
+ ( null == lock || !Thread.holdsLock(lock) ) ) {
+ invokeOnOpenGLThread(wait, r);
+ } else {
+ r.run();
+ }
}
}
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
index 10d478b85..ea191810e 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
@@ -91,13 +91,9 @@ import com.jogamp.nativewindow.awt.AWTWindowClosingProtocol;
import com.jogamp.nativewindow.awt.JAWTWindow;
import com.jogamp.opengl.JoglVersion;
-import com.jogamp.common.util.locks.LockFactory;
-import com.jogamp.common.util.locks.RecursiveLock;
-
import jogamp.opengl.Debug;
import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLDrawableHelper;
-import jogamp.opengl.ThreadingImpl;
// FIXME: Subclasses need to call resetGLFunctionAvailability() on their
// context whenever the displayChanged() function is called on our
@@ -144,7 +140,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
private GLDrawableHelper drawableHelper = new GLDrawableHelper();
private AWTGraphicsConfiguration awtConfig;
- private GLDrawable drawable;
+ private volatile GLDrawable drawable;
private GLContextImpl context;
private boolean sendReshape = false;
@@ -377,24 +373,17 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
}
public GLContext createContext(GLContext shareWith) {
- drawableSync.lock();
- try {
- return (null != drawable) ? drawable.createContext(shareWith) : null;
- } finally {
- drawableSync.unlock();
- }
+ return (null != drawable) ? drawable.createContext(shareWith) : null;
}
public void setRealized(boolean realized) {
}
public boolean isRealized() {
- drawableSync.lock();
- try {
- return ( null != drawable ) ? drawable.isRealized() : false;
- } finally {
- drawableSync.unlock();
- }
+ return ( null != drawable ) ? drawable.isRealized() : false;
+ }
+ protected final boolean isRealizedImpl() {
+ return ( null != drawable ) ? drawable.isRealized() : false;
}
public int getDefaultCloseOperation() {
@@ -412,66 +401,43 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
}
return; // not yet available ..
}
- maybeDoSingleThreadedWorkaround(displayOnEventDispatchThreadAction,
- displayAction);
+ Threading.invoke(true, displayOnEventDispatchThreadAction, getTreeLock());
awtWindowClosingProtocol.addClosingListenerOneShot();
}
private void dispose(boolean regenerate) {
- drawableSync.lock();
- try {
- final GLAnimatorControl animator = getAnimator();
- if(DEBUG) {
- System.err.println(getThreadName()+": Info: dispose("+regenerate+") - START, hasContext " +
- (null!=context) + ", hasDrawable " + (null!=drawable)+", "+animator);
- Thread.dumpStack();
+ final GLAnimatorControl animator = getAnimator();
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Info: dispose("+regenerate+") - START, hasContext " +
+ (null!=context) + ", hasDrawable " + (null!=drawable)+", "+animator);
+ Thread.dumpStack();
+ }
+
+ if(null!=context) {
+ boolean animatorPaused = false;
+ if(null!=animator) {
+ // can't remove us from animator for recreational addNotify()
+ animatorPaused = animator.pause();
}
- if(null!=context) {
- boolean animatorPaused = false;
- if(null!=animator) {
- // can't remove us from animator for recreational addNotify()
- animatorPaused = animator.pause();
- }
+ disposeRegenerate=regenerate;
- disposeRegenerate=regenerate;
-
- 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);
- }
- }
-
- if(animatorPaused) {
- animator.resume();
- }
- }
-
- if(!regenerate) {
- disposeAbstractGraphicsDevice();
+ if(context.isCreated()) {
+ Threading.invoke(true, disposeOnEventDispatchThreadAction, getTreeLock());
}
- if(DEBUG) {
- System.err.println(getThreadName()+": dispose("+regenerate+") - END, "+animator);
+ if(animatorPaused) {
+ animator.resume();
}
- } finally {
- drawableSync.unlock();
+ }
+
+ if(!regenerate) {
+ disposeAbstractGraphicsDevice();
+ }
+
+ if(DEBUG) {
+ System.err.println(getThreadName()+": dispose("+regenerate+") - END, "+animator);
}
}
@@ -516,8 +482,6 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
}
}
- RecursiveLock drawableSync = LockFactory.createRecursiveLock();
-
/** Overridden to track when this component is added to a container.
Subclasses which override this method must call
super.addNotify() in their addNotify() method in order to
@@ -533,43 +497,38 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
Thread.dumpStack();
}
- drawableSync.lock();
- try {
- /**
- * 'super.addNotify()' determines the GraphicsConfiguration,
- * while calling this class's overriden 'getGraphicsConfiguration()' method
- * after which it creates the native peer.
- * Hence we have to set the 'awtConfig' before since it's GraphicsConfiguration
- * is being used in getGraphicsConfiguration().
- * This code order also allows recreation, ie re-adding the GLCanvas.
- */
- awtConfig = chooseGraphicsConfiguration(capsReqUser, capsReqUser, chooser, device);
- if(null==awtConfig) {
- throw new GLException("Error: NULL AWTGraphicsConfiguration");
- }
+ /**
+ * 'super.addNotify()' determines the GraphicsConfiguration,
+ * while calling this class's overriden 'getGraphicsConfiguration()' method
+ * after which it creates the native peer.
+ * Hence we have to set the 'awtConfig' before since it's GraphicsConfiguration
+ * is being used in getGraphicsConfiguration().
+ * This code order also allows recreation, ie re-adding the GLCanvas.
+ */
+ awtConfig = chooseGraphicsConfiguration(capsReqUser, capsReqUser, chooser, device);
+ if(null==awtConfig) {
+ throw new GLException("Error: NULL AWTGraphicsConfiguration");
+ }
- // before native peer is valid: X11
- disableBackgroundErase();
+ // before native peer is valid: X11
+ disableBackgroundErase();
- // issues getGraphicsConfiguration() and creates the native peer
- super.addNotify();
+ // issues getGraphicsConfiguration() and creates the native peer
+ super.addNotify();
- // after native peer is valid: Windows
- disableBackgroundErase();
+ // after native peer is valid: Windows
+ disableBackgroundErase();
- if (!Beans.isDesignTime()) {
- createDrawableAndContext();
- }
+ if (!Beans.isDesignTime()) {
+ createDrawableAndContext();
+ }
- // init drawable by paint/display makes the init sequence more equal
- // for all launch flavors (applet/javaws/..)
- // validateGLDrawable();
+ // init drawable by paint/display makes the init sequence more equal
+ // for all launch flavors (applet/javaws/..)
+ // validateGLDrawable();
- if(DEBUG) {
- System.err.println(getThreadName()+": Info: addNotify - end: peer: "+getPeer());
- }
- } finally {
- drawableSync.unlock();
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Info: addNotify - end: peer: "+getPeer());
}
}
@@ -591,22 +550,17 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
private boolean validateGLDrawable() {
boolean realized = false;
if (!Beans.isDesignTime()) {
- drawableSync.lock();
- try {
- if ( null != drawable ) {
- realized = drawable.isRealized();
- if ( !realized && 0 < drawable.getWidth() * drawable.getHeight() ) {
- drawable.setRealized(true);
- realized = true;
- sendReshape=true; // ensure a reshape is being send ..
- if(DEBUG) {
- System.err.println(getThreadName()+": Realized Drawable: "+drawable.toString());
- Thread.dumpStack();
- }
+ if ( null != drawable ) {
+ realized = drawable.isRealized();
+ if ( !realized && 0 < drawable.getWidth() * drawable.getHeight() ) {
+ drawable.setRealized(true);
+ realized = true;
+ sendReshape=true; // ensure a reshape is being send ..
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Realized Drawable: "+drawable.toString());
+ Thread.dumpStack();
}
}
- } finally {
- drawableSync.unlock();
}
}
return realized;
@@ -633,7 +587,6 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
if (Beans.isDesignTime()) {
super.removeNotify();
} else {
- drawableSync.lock();
try {
dispose(false);
} finally {
@@ -641,7 +594,6 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
drawable=null;
awtConfig=null;
super.removeNotify();
- drawableSync.unlock();
}
}
if(DEBUG) {
@@ -740,7 +692,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
}
public void swapBuffers() {
- maybeDoSingleThreadedWorkaround(swapBuffersOnEventDispatchThreadAction, swapBuffersAction);
+ Threading.invoke(true, swapBuffersOnEventDispatchThreadAction, getTreeLock());
}
public void setContextCreationFlags(int flags) {
@@ -772,30 +724,15 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
}
public NativeSurface getNativeSurface() {
- drawableSync.lock();
- try {
- return (null != drawable) ? drawable.getNativeSurface() : null;
- } finally {
- drawableSync.unlock();
- }
+ return (null != drawable) ? drawable.getNativeSurface() : null;
}
public long getHandle() {
- drawableSync.lock();
- try {
- return (null != drawable) ? drawable.getHandle() : 0;
- } finally {
- drawableSync.unlock();
- }
+ return (null != drawable) ? drawable.getHandle() : 0;
}
public GLDrawableFactory getFactory() {
- drawableSync.lock();
- try {
- return (null != drawable) ? drawable.getFactory() : null;
- } finally {
- drawableSync.unlock();
- }
+ return (null != drawable) ? drawable.getFactory() : null;
}
@Override
@@ -805,7 +742,6 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
return "AWT-GLCanvas[Realized "+isRealized()+
",\n\t"+((null!=drawable)?drawable.getClass().getName():"null-drawable")+
- ",\n\tRealized "+isRealized()+
",\n\tFactory "+getFactory()+
",\n\thandle 0x"+Long.toHexString(getHandle())+
",\n\tDrawable size "+dw+"x"+dh+
@@ -818,17 +754,8 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
// Internals only below this point
//
- private void maybeDoSingleThreadedWorkaround(Runnable eventDispatchThreadAction,
- Runnable invokeGLAction) {
- if (Threading.isSingleThreaded() &&
- !Threading.isOpenGLThread()) {
- Threading.invokeOnOpenGLThread(eventDispatchThreadAction);
- } else {
- drawableHelper.invokeGL(drawable, context, invokeGLAction, initAction);
- }
- }
-
- class PostDisposeAction implements Runnable {
+ private boolean disposeRegenerate;
+ private final Runnable postDisposeAction = new Runnable() {
public void run() {
context=null;
if(null!=drawable) {
@@ -852,20 +779,15 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
validateGLDrawable(); // immediate attempt to recreate the drawable
}
}
- }
- private boolean disposeRegenerate;
- private PostDisposeAction postDisposeAction = new PostDisposeAction();
+ };
- private DisposeOnEventDispatchThreadAction disposeOnEventDispatchThreadAction =
- new DisposeOnEventDispatchThreadAction();
-
- class DisposeOnEventDispatchThreadAction implements Runnable {
+ private final Runnable disposeOnEventDispatchThreadAction = new Runnable() {
public void run() {
drawableHelper.disposeGL(GLCanvas.this, drawable, context, postDisposeAction);
}
- }
+ };
- class DisposeAbstractGraphicsDeviceAction implements Runnable {
+ private final Runnable disposeAbstractGraphicsDeviceAction = new Runnable() {
public void run() {
if(null != awtConfig) {
final AbstractGraphicsConfiguration aconfig = awtConfig.getNativeGraphicsConfiguration();
@@ -883,8 +805,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
awtConfig=null;
}
}
- }
- private DisposeAbstractGraphicsDeviceAction disposeAbstractGraphicsDeviceAction = new DisposeAbstractGraphicsDeviceAction();
+ };
/**
* Disposes the AbstractGraphicsDevice within EDT,
@@ -906,14 +827,13 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
}
}
- class InitAction implements Runnable {
+ private final Runnable initAction = new Runnable() {
public void run() {
drawableHelper.init(GLCanvas.this);
}
- }
- private InitAction initAction = new InitAction();
+ };
- class DisplayAction implements Runnable {
+ private final Runnable displayAction = new Runnable() {
public void run() {
if (sendReshape) {
if(DEBUG) {
@@ -927,33 +847,28 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
drawableHelper.display(GLCanvas.this);
}
- }
- private DisplayAction displayAction = new DisplayAction();
+ };
- class SwapBuffersAction implements Runnable {
+ private final Runnable swapBuffersAction = new Runnable() {
public void run() {
drawable.swapBuffers();
}
- }
- private SwapBuffersAction swapBuffersAction = new SwapBuffersAction();
+ };
// Workaround for ATI driver bugs related to multithreading issues
// like simultaneous rendering via Animators to canvases that are
// being resized on the AWT event dispatch thread
- class DisplayOnEventDispatchThreadAction implements Runnable {
+ private final Runnable displayOnEventDispatchThreadAction = new Runnable() {
public void run() {
- drawableHelper.invokeGL(drawable, context, displayAction, initAction);
+ drawableHelper.invokeGL(drawable, context, displayAction, initAction);
}
- }
- private DisplayOnEventDispatchThreadAction displayOnEventDispatchThreadAction =
- new DisplayOnEventDispatchThreadAction();
- class SwapBuffersOnEventDispatchThreadAction implements Runnable {
+ };
+
+ private final Runnable swapBuffersOnEventDispatchThreadAction = new Runnable() {
public void run() {
- drawableHelper.invokeGL(drawable, context, swapBuffersAction, initAction);
- }
- }
- private SwapBuffersOnEventDispatchThreadAction swapBuffersOnEventDispatchThreadAction =
- new SwapBuffersOnEventDispatchThreadAction();
+ drawableHelper.invokeGL(drawable, context, swapBuffersAction, initAction);
+ }
+ };
// Disables the AWT's erasing of this Canvas's background on Windows
// in Java SE 6. This internal API is not available in previous
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
index 5291e48e4..5ca81a4b9 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
@@ -89,7 +89,6 @@ import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLDrawableFactoryImpl;
import jogamp.opengl.GLDrawableHelper;
import jogamp.opengl.GLDrawableImpl;
-import jogamp.opengl.ThreadingImpl;
import jogamp.opengl.awt.Java2D;
import jogamp.opengl.awt.Java2DGLContext;
@@ -269,7 +268,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
protected void dispose() {
if(DEBUG) {
- System.err.println("Info: dispose() - start - "+Thread.currentThread().getName());
+ System.err.println(getThreadName()+": GLJPanel.dispose() - start");
// Thread.dumpStack();
}
@@ -281,23 +280,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
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);
- }
+ Threading.invoke(true, disposeAction, getTreeLock());
}
if(null != backend) {
// not yet destroyed due to backend.isUsingOwnThreadManagment() == true
@@ -311,7 +294,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
if(DEBUG) {
- System.err.println("dispose() - stop");
+ System.err.println(getThreadName()+": GLJPanel.dispose() - stop");
}
}
@@ -368,9 +351,11 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
updater.setGraphics(g);
+
backend.doPaintComponent(g);
}
+
/** Overridden to track when this component is added to a container.
Subclasses which override this method must call
super.addNotify() in their addNotify() method in order to
@@ -381,7 +366,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
public void addNotify() {
super.addNotify();
if (DEBUG) {
- System.err.println("GLJPanel.addNotify()");
+ System.err.println(getThreadName()+": GLJPanel.addNotify()");
}
}
@@ -624,7 +609,7 @@ public void reshape(int x, int y, int width, int height) {
panelHeight = reshapeHeight;
if (DEBUG) {
- System.err.println("GLJPanel.handleReshape: (w,h) = (" +
+ System.err.println(getThreadName()+": GLJPanel.handleReshape: (w,h) = (" +
panelWidth + "," + panelHeight + ")");
}
@@ -632,7 +617,7 @@ public void reshape(int x, int y, int width, int height) {
backend.handleReshape();
handleReshape = false;
}
-
+
// This is used as the GLEventListener for the pbuffer-based backend
// as well as the callback mechanism for the other backends
class Updater implements GLEventListener {
@@ -660,7 +645,7 @@ public void reshape(int x, int y, int width, int height) {
}
if (sendReshape) {
if (DEBUG) {
- System.err.println("display: reshape(" + viewportX + "," + viewportY + " " + panelWidth + "x" + panelHeight + ")");
+ System.err.println(getThreadName()+": GLJPanel.display: reshape(" + viewportX + "," + viewportY + " " + panelWidth + "x" + panelHeight + ")");
}
drawableHelper.reshape(GLJPanel.this, viewportX, viewportY, panelWidth, panelHeight);
sendReshape = false;
@@ -682,7 +667,7 @@ public void reshape(int x, int y, int width, int height) {
return "AWT-GLJPanel[ "+((null!=backend)?backend.getDrawable().getClass().getName():"null-drawable")+"]";
}
- class PostDisposeAction implements Runnable {
+ private final Runnable postDisposeAction = new Runnable() {
public void run() {
if (backend != null && !backend.isUsingOwnThreadManagment()) {
backend.destroy();
@@ -690,38 +675,31 @@ public void reshape(int x, int y, int width, int height) {
isInitialized = false;
}
}
- }
- private PostDisposeAction postDisposeAction = new PostDisposeAction();
-
- private DisposeOnEventDispatchThreadAction disposeOnEventDispatchThreadAction =
- new DisposeOnEventDispatchThreadAction();
+ };
- class DisposeOnEventDispatchThreadAction implements Runnable {
+ private final Runnable disposeAction = new Runnable() {
public void run() {
drawableHelper.disposeGL(GLJPanel.this, backend.getDrawable(), backend.getContext(), postDisposeAction);
}
- }
-
- class InitAction implements Runnable {
+ };
+
+ private final Runnable updaterInitAction = new Runnable() {
public void run() {
updater.init(GLJPanel.this);
}
- }
- private InitAction initAction = new InitAction();
+ };
- class DisplayAction implements Runnable {
+ private final Runnable updaterDisplayAction = new Runnable() {
public void run() {
updater.display(GLJPanel.this);
}
- }
- private DisplayAction displayAction = new DisplayAction();
+ };
- class PaintImmediatelyAction implements Runnable {
+ private final Runnable paintImmediatelyAction = new Runnable() {
public void run() {
paintImmediately(0, 0, getWidth(), getHeight());
}
- }
- private PaintImmediatelyAction paintImmediatelyAction = new PaintImmediatelyAction();
+ };
private int getNextPowerOf2(int number) {
// Workaround for problems where 0 width or height are transiently
@@ -738,6 +716,10 @@ public void reshape(int x, int y, int width, int height) {
return tmp[0];
}
+ protected static String getThreadName() {
+ return Thread.currentThread().getName();
+ }
+
//----------------------------------------------------------------------
// Implementations of the various backends
//
@@ -980,7 +962,7 @@ public void reshape(int x, int y, int width, int height) {
public void initialize() {
if(DEBUG) {
- System.err.println("SoftwareBackend: initialize() - "+Thread.currentThread().getName());
+ System.err.println(getThreadName()+": SoftwareBackend: initialize()");
}
// Fall-through path: create an offscreen context instead
offscreenDrawable = (GLDrawableImpl) factory.createOffscreenDrawable(
@@ -999,7 +981,7 @@ public void reshape(int x, int y, int width, int height) {
public void destroy() {
if(DEBUG) {
- System.err.println("SoftwareBackend: destroy() - offscreenContext: "+(null!=offscreenContext)+" - offscreenDrawable: "+(null!=offscreenDrawable)+" - "+Thread.currentThread().getName());
+ System.err.println(getThreadName()+": SoftwareBackend: destroy() - offscreenContext: "+(null!=offscreenContext)+" - offscreenDrawable: "+(null!=offscreenDrawable));
}
if (offscreenContext != null) {
offscreenContext.destroy();
@@ -1058,7 +1040,7 @@ public void reshape(int x, int y, int width, int height) {
}
protected void doPaintComponentImpl() {
- drawableHelper.invokeGL(offscreenDrawable, offscreenContext, displayAction, initAction);
+ drawableHelper.invokeGL(offscreenDrawable, offscreenContext, updaterDisplayAction, updaterInitAction);
}
protected int getGLPixelType() {
@@ -1082,7 +1064,7 @@ public void reshape(int x, int y, int width, int height) {
throw new InternalError("Creating pbuffer twice without destroying it (memory leak / correctness bug)");
}
if(DEBUG) {
- System.err.println("PbufferBackend: initialize() - "+Thread.currentThread().getName());
+ System.err.println(getThreadName()+": PbufferBackend: initialize()");
}
try {
pbuffer = factory.createGLPbuffer(null /* default platform device */,
@@ -1097,7 +1079,7 @@ public void reshape(int x, int y, int width, int height) {
} catch (GLException e) {
if (DEBUG) {
e.printStackTrace();
- System.err.println("Info: GLJPanel: Falling back on software rendering because of problems creating pbuffer");
+ System.err.println(getThreadName()+": GLJPanel: Falling back on software rendering because of problems creating pbuffer");
}
hardwareAccelerationDisabled = true;
backend = null;
@@ -1108,7 +1090,7 @@ public void reshape(int x, int y, int width, int height) {
public void destroy() {
if(DEBUG) {
- System.err.println("PbufferBackend: destroy() - pbuffer: "+(null!=pbuffer)+" - "+Thread.currentThread().getName());
+ System.err.println(getThreadName()+": PbufferBackend: destroy() - pbuffer: "+(null!=pbuffer));
}
if (pbuffer != null) {
pbuffer.destroy();
@@ -1159,7 +1141,7 @@ public void reshape(int x, int y, int width, int height) {
if ((panelWidth > pbufferWidth) || (panelHeight > pbufferHeight) ||
(panelWidth < (pbufferWidth / shrinkFactor)) || (panelHeight < (pbufferHeight / shrinkFactor))) {
if (DEBUG) {
- System.err.println("Resizing pbuffer from (" + pbufferWidth + ", " + pbufferHeight + ") " +
+ System.err.println(getThreadName()+": Resizing pbuffer from (" + pbufferWidth + ", " + pbufferHeight + ") " +
" to fit (" + panelWidth + ", " + panelHeight + ")");
}
// Must destroy and recreate pbuffer to fit
@@ -1177,7 +1159,7 @@ public void reshape(int x, int y, int width, int height) {
readBackWidthInPixels = Math.max(1, panelWidth);
readBackHeightInPixels = Math.max(1, panelHeight);
if (DEBUG) {
- System.err.println("Warning: falling back to software rendering due to bugs in OpenGL drivers");
+ System.err.println(getThreadName()+": Warning: falling back to software rendering due to bugs in OpenGL drivers");
e.printStackTrace();
}
createAndInitializeBackend();
@@ -1189,7 +1171,7 @@ public void reshape(int x, int y, int width, int height) {
pbufferWidth = getNextPowerOf2(panelWidth);
pbufferHeight = getNextPowerOf2(panelHeight);
if (DEBUG && !hardwareAccelerationDisabled) {
- System.err.println("New pbuffer size is (" + pbufferWidth + ", " + pbufferHeight + ")");
+ System.err.println(getThreadName()+": New pbuffer size is (" + pbufferWidth + ", " + pbufferHeight + ")");
}
initialize();
}
@@ -1277,7 +1259,7 @@ public void reshape(int x, int y, int width, int height) {
public void initialize() {
if(DEBUG) {
- System.err.println("J2DOGL: initialize() - "+Thread.currentThread().getName());
+ System.err.println(getThreadName()+": J2DOGL: initialize()");
}
// No-op in this implementation; everything is done lazily
isInitialized = true;
@@ -1287,7 +1269,7 @@ public void reshape(int x, int y, int width, int height) {
Java2D.invokeWithOGLContextCurrent(null, new Runnable() {
public void run() {
if(DEBUG) {
- System.err.println("J2DOGL: destroy() - joglContext: "+(null!=joglContext)+" - joglDrawable: "+(null!=joglDrawable)+" - "+Thread.currentThread().getName());
+ System.err.println(getThreadName()+": J2DOGL: destroy() - joglContext: "+(null!=joglContext)+" - joglDrawable: "+(null!=joglDrawable));
}
if (joglContext != null) {
joglContext.destroy();
@@ -1347,12 +1329,12 @@ public void reshape(int x, int y, int width, int height) {
if (r == null) {
if (DEBUG) {
- System.err.println("Java2D.getOGLScissorBox() returned null");
+ System.err.println(getThreadName()+": Java2D.getOGLScissorBox() returned null");
}
return false;
}
if (DEBUG) {
- System.err.println("GLJPanel: gl.glScissor(" + r.x + ", " + r.y + ", " + r.width + ", " + r.height + ")");
+ System.err.println(getThreadName()+": GLJPanel: gl.glScissor(" + r.x + ", " + r.y + ", " + r.width + ", " + r.height + ")");
}
gl.glScissor(r.x, r.y, r.width, r.height);
@@ -1364,7 +1346,7 @@ public void reshape(int x, int y, int width, int height) {
(viewportY != oglViewport.y)) {
sendReshape = true;
if (DEBUG) {
- System.err.println("Sending reshape because viewport changed");
+ System.err.println(getThreadName()+": Sending reshape because viewport changed");
System.err.println(" viewportX (" + viewportX + ") ?= oglViewport.x (" + oglViewport.x + ")");
System.err.println(" viewportY (" + viewportY + ") ?= oglViewport.y (" + oglViewport.y + ")");
}
@@ -1393,14 +1375,14 @@ public void reshape(int x, int y, int width, int height) {
fbObjectWorkarounds = true;
createNewDepthBuffer = true;
if (DEBUG) {
- System.err.println("GLJPanel: ERR GL_FRAMEBUFFER_BINDING: Discovered Invalid J2D FBO("+frameBuffer[0]+"): "+FBObject.getStatusString(status) +
+ System.err.println(getThreadName()+": GLJPanel: ERR GL_FRAMEBUFFER_BINDING: Discovered Invalid J2D FBO("+frameBuffer[0]+"): "+FBObject.getStatusString(status) +
", frame_buffer_object workarounds to be necessary");
}
} else {
// Don't need the frameBufferTexture temporary any more
frameBufferTexture = null;
if (DEBUG) {
- System.err.println("GLJPanel: OK GL_FRAMEBUFFER_BINDING: "+frameBuffer[0]);
+ System.err.println(getThreadName()+": GLJPanel: OK GL_FRAMEBUFFER_BINDING: "+frameBuffer[0]);
}
}
}
@@ -1424,7 +1406,7 @@ public void reshape(int x, int y, int width, int height) {
gl.glGenRenderbuffers(1, frameBufferDepthBuffer, 0);
if (DEBUG) {
- System.err.println("GLJPanel: Generated frameBufferDepthBuffer " + frameBufferDepthBuffer[0] +
+ System.err.println(getThreadName()+": GLJPanel: Generated frameBufferDepthBuffer " + frameBufferDepthBuffer[0] +
" with width " + width[0] + ", height " + height[0]);
}
@@ -1447,7 +1429,7 @@ public void reshape(int x, int y, int width, int height) {
frameBufferTexture[0],
0);
if (DEBUG) {
- System.err.println("GLJPanel: frameBufferDepthBuffer: " + frameBufferDepthBuffer[0]);
+ System.err.println(getThreadName()+": GLJPanel: frameBufferDepthBuffer: " + frameBufferDepthBuffer[0]);
}
gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER,
GL.GL_DEPTH_ATTACHMENT,
@@ -1464,7 +1446,7 @@ public void reshape(int x, int y, int width, int height) {
}
} else {
if (DEBUG) {
- System.err.println("GLJPanel: Setting up drawBuffer " + drawBuffer[0] +
+ System.err.println(getThreadName()+": GLJPanel: Setting up drawBuffer " + drawBuffer[0] +
" and readBuffer " + readBuffer[0]);
}
@@ -1522,14 +1504,14 @@ public void reshape(int x, int y, int width, int height) {
Java2D.invokeWithOGLContextCurrent(g, new Runnable() {
public void run() {
if (DEBUG) {
- System.err.println("-- In invokeWithOGLContextCurrent - "+Thread.currentThread().getName());
+ System.err.println(getThreadName()+": GLJPanel.invokeWithOGLContextCurrent");
}
// Create no-op context representing Java2D context
if (j2dContext == null) {
j2dContext = factory.createExternalGLContext();
if (DEBUG) {
- System.err.println("-- Created External Context: "+j2dContext);
+ System.err.println(getThreadName()+": GLJPanel.Created External Context: "+j2dContext);
}
if (DEBUG) {
// j2dContext.setGL(new DebugGL2(j2dContext.getGL().getGL2()));
@@ -1552,7 +1534,7 @@ public void reshape(int x, int y, int width, int height) {
// (getGLInteger(gl, GL2.GL_DEPTH_BITS) < offscreenCaps.getDepthBits()) ||
(getGLInteger(gl, GL.GL_STENCIL_BITS) < offscreenCaps.getStencilBits())) {
if (DEBUG) {
- System.err.println("GLJPanel: Falling back to pbuffer-based support because Java2D context insufficient");
+ System.err.println(getThreadName()+": GLJPanel: Falling back to pbuffer-based support because Java2D context insufficient");
System.err.println(" Available Required");
System.err.println("GL_RED_BITS " + getGLInteger(gl, GL.GL_RED_BITS) + " " + offscreenCaps.getRedBits());
System.err.println("GL_GREEN_BITS " + getGLInteger(gl, GL.GL_GREEN_BITS) + " " + offscreenCaps.getGreenBits());
@@ -1587,13 +1569,13 @@ public void reshape(int x, int y, int width, int height) {
joglDrawable = null;
sendReshape = true;
if (DEBUG) {
- System.err.println("Sending reshape because surface changed");
+ System.err.println(getThreadName()+": Sending reshape because surface changed");
System.err.println("New surface = " + curSurface);
}
}
j2dSurface = curSurface;
if (DEBUG) {
- System.err.print("-- Surface type: ");
+ System.err.print(getThreadName()+": Surface type: ");
int surfaceType = Java2D.getOGLSurfaceType(g);
if (surfaceType == Java2D.UNDEFINED) {
System.err.println("UNDEFINED");
@@ -1645,7 +1627,7 @@ public void reshape(int x, int y, int width, int height) {
((Java2DGLContext) joglContext).setGraphics(g);
}
- drawableHelper.invokeGL(joglDrawable, joglContext, displayAction, initAction);
+ drawableHelper.invokeGL(joglDrawable, joglContext, updaterDisplayAction, updaterInitAction);
}
} finally {
j2dContext.release();
@@ -1665,11 +1647,11 @@ public void reshape(int x, int y, int width, int height) {
fbObjectWorkarounds = true;
createNewDepthBuffer = true;
if (DEBUG) {
- System.err.println("GLJPanel: Fetched ERR GL_FRAMEBUFFER_BINDING: "+frameBuffer[0]+" - NOT A FBO"+
+ System.err.println(getThreadName()+": GLJPanel: Fetched ERR GL_FRAMEBUFFER_BINDING: "+frameBuffer[0]+" - NOT A FBO"+
", frame_buffer_object workarounds to be necessary");
}
} else if (DEBUG) {
- System.err.println("GLJPanel: Fetched OK GL_FRAMEBUFFER_BINDING: "+frameBuffer[0]);
+ System.err.println(getThreadName()+": GLJPanel: Fetched OK GL_FRAMEBUFFER_BINDING: "+frameBuffer[0]);
}
if(fbObjectWorkarounds || !checkedForFBObjectWorkarounds) {
@@ -1684,7 +1666,7 @@ public void reshape(int x, int y, int width, int height) {
GL.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
frameBufferTexture, 0);
if (DEBUG) {
- System.err.println("GLJPanel: FBO COLOR_ATTACHMENT0: " + frameBufferTexture[0]);
+ System.err.println(getThreadName()+": GLJPanel: FBO COLOR_ATTACHMENT0: " + frameBufferTexture[0]);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 7fd9970a4..f21b61b48 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -247,7 +247,7 @@ public abstract class GLContextImpl extends GLContext {
}
private void release(boolean force) throws GLException {
if(TRACE_SWITCH) {
- System.err.println("GLContext.ContextSwitch: - release() - "+Thread.currentThread().getName()+": force: "+force+", "+lock);
+ System.err.println(getThreadName() +": GLContext.ContextSwitch: - release() - force: "+force+", "+lock);
}
if ( !lock.isOwner() ) {
throw new GLException("Context not current on current thread "+Thread.currentThread().getName()+": "+this);
@@ -267,11 +267,7 @@ public abstract class GLContextImpl extends GLContext {
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);
- }
+ System.err.println(getThreadName() +": GLContext.ContextSwitch: - "+(actualRelease?"switch":"keep ")+" - CONTEXT_RELEASE - "+lock);
}
}
}
@@ -285,7 +281,7 @@ public abstract class GLContextImpl extends GLContext {
if(lock.getHoldCount() > 2) {
throw new GLException("XXX: "+lock);
}
- if (DEBUG || TRACE_SWITCH) {
+ if (TRACE_SWITCH) {
System.err.println(getThreadName() + ": GLContextImpl.destroy.0: " + toHexString(contextHandle) +
", isShared "+GLContextShareSet.isShared(this)+" - "+lock);
}
@@ -321,7 +317,7 @@ public abstract class GLContextImpl extends GLContext {
}
} finally {
lock.unlock();
- if (DEBUG || TRACE_SWITCH) {
+ if (TRACE_SWITCH) {
System.err.println(getThreadName() + ": GLContextImpl.destroy.X: " + toHexString(contextHandle) +
", isShared "+GLContextShareSet.isShared(this)+" - "+lock);
}
@@ -415,19 +411,13 @@ public abstract class GLContextImpl extends GLContext {
// 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);
+ System.err.println(getThreadName() +": GLContext.ContextSwitch: - keep - CONTEXT_CURRENT - "+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);
}
@@ -460,7 +450,7 @@ public abstract class GLContextImpl extends GLContext {
}
if (res == CONTEXT_NOT_CURRENT) {
if(TRACE_SWITCH) {
- System.err.println("GLContext.ContextSwitch: - switch - CONTEXT_NOT_CURRENT - "+Thread.currentThread().getName()+" - "+lock);
+ System.err.println(getThreadName() +": GLContext.ContextSwitch: - switch - CONTEXT_NOT_CURRENT - "+lock);
}
} else {
setCurrent(this);
@@ -481,10 +471,10 @@ public abstract class GLContextImpl extends GLContext {
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);
+ System.err.println(getThreadName() +": GLContext.ContextSwitch: - switch - CONTEXT_CURRENT_NEW - "+lock);
}
} else if(TRACE_SWITCH) {
- System.err.println("GLContext.ContextSwitch: - switch - CONTEXT_CURRENT - "+Thread.currentThread().getName()+" - "+lock);
+ System.err.println(getThreadName() +": GLContext.ContextSwitch: - switch - CONTEXT_CURRENT - "+lock);
}
/* FIXME: refactor dependence on Java 2D / JOGL bridge
diff --git a/src/jogl/classes/jogamp/opengl/GLWorkerThread.java b/src/jogl/classes/jogamp/opengl/GLWorkerThread.java
index e717ec64c..f7d59e127 100644
--- a/src/jogl/classes/jogamp/opengl/GLWorkerThread.java
+++ b/src/jogl/classes/jogamp/opengl/GLWorkerThread.java
@@ -79,7 +79,7 @@ public class GLWorkerThread {
if (!started) {
lock = new Object();
thread = new Thread(new WorkerRunnable(),
- "JOGL GLWorkerThread");
+ "JOGL-GLWorkerThread-");
thread.setDaemon(true);
started = true;
synchronized (lock) {
@@ -149,6 +149,15 @@ public class GLWorkerThread {
}
}
+ public static void invoke(boolean wait, Runnable runnable)
+ throws InvocationTargetException, InterruptedException {
+ if(wait) {
+ invokeAndWait(runnable);
+ } else {
+ invokeLater(runnable);
+ }
+ }
+
public static void invokeAndWait(Runnable runnable)
throws InvocationTargetException, InterruptedException {
if (!started) {
diff --git a/src/jogl/classes/jogamp/opengl/ThreadingImpl.java b/src/jogl/classes/jogamp/opengl/ThreadingImpl.java
index 0ba86870d..61a47675f 100644
--- a/src/jogl/classes/jogamp/opengl/ThreadingImpl.java
+++ b/src/jogl/classes/jogamp/opengl/ThreadingImpl.java
@@ -38,12 +38,13 @@ import java.lang.reflect.InvocationTargetException;
import java.security.AccessController;
import java.security.PrivilegedAction;
-import com.jogamp.common.JogampRuntimeException;
-import com.jogamp.common.util.*;
import javax.media.nativewindow.NativeWindowFactory;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
+import com.jogamp.common.JogampRuntimeException;
+import com.jogamp.common.util.ReflectionUtil;
+
/** Implementation of the {@link javax.media.opengl.Threading} class. */
public class ThreadingImpl {
@@ -59,23 +60,23 @@ public class ThreadingImpl {
protected static final boolean DEBUG = Debug.debug("Threading");
- private static boolean singleThreaded = true;
- private static Mode mode = Mode.MT;
+ private static boolean singleThreaded;
+ private static Mode mode;
private static boolean hasAWT;
// We need to know whether we're running on X11 platforms to change
// our behavior when the Java2D/JOGL bridge is active
private static boolean _isX11;
- private static final ThreadingPlugin threadingPlugin;
+ private static final ToolkitThreadingPlugin threadingPlugin;
static {
threadingPlugin =
- AccessController.doPrivileged(new PrivilegedAction<ThreadingPlugin>() {
- public ThreadingPlugin run() {
- final String workaround;
+ AccessController.doPrivileged(new PrivilegedAction<ToolkitThreadingPlugin>() {
+ public ToolkitThreadingPlugin run() {
+ final String singleThreadProp;
{
final String w = Debug.getProperty("jogl.1thread", true);
- workaround = null != w ? w.toLowerCase() : null;
+ singleThreadProp = null != w ? w.toLowerCase() : null;
}
ClassLoader cl = ThreadingImpl.class.getClassLoader();
// Default to using the AWT thread on all platforms except
@@ -91,37 +92,42 @@ public class ThreadingImpl {
String osType = NativeWindowFactory.getNativeWindowType(false);
_isX11 = NativeWindowFactory.TYPE_X11.equals(osType);
- mode = ( hasAWT ? Mode.ST_AWT : Mode.ST_WORKER ); // default
+ // default setting
+ singleThreaded = true;
+ mode = ( hasAWT ? Mode.ST_AWT : Mode.ST_WORKER );
- if (workaround != null) {
- if (workaround.equals("true") ||
- workaround.equals("auto")) {
- // Nothing to do; singleThreaded and mode already set up
- } else if (workaround.equals("worker")) {
+ if (singleThreadProp != null) {
+ if (singleThreadProp.equals("true") ||
+ singleThreadProp.equals("auto")) {
+ singleThreaded = true;
+ mode = ( hasAWT ? Mode.ST_AWT : Mode.ST_WORKER );
+ } else if (singleThreadProp.equals("worker")) {
singleThreaded = true;
mode = Mode.ST_WORKER;
- } else if (hasAWT && workaround.equals("awt")) {
+ } else if (hasAWT && singleThreadProp.equals("awt")) {
singleThreaded = true;
mode = Mode.ST_AWT;
- } else {
+ } else if (singleThreadProp.equals("false")) {
singleThreaded = false;
mode = Mode.MT;
+ } else {
+ throw new RuntimeException("Unsupported value for property jogl.1thread: "+singleThreadProp+", should be [true/auto, worker, awt or false]");
}
}
- ThreadingPlugin threadingPlugin=null;
- if(Mode.ST_AWT == mode) {
+ ToolkitThreadingPlugin threadingPlugin=null;
+ if(hasAWT) {
// try to fetch the AWTThreadingPlugin
Exception error=null;
try {
- threadingPlugin = (ThreadingPlugin) ReflectionUtil.createInstance("jogamp.opengl.awt.AWTThreadingPlugin", cl);
+ threadingPlugin = (ToolkitThreadingPlugin) ReflectionUtil.createInstance("jogamp.opengl.awt.AWTThreadingPlugin", cl);
} catch (JogampRuntimeException jre) { error = jre; }
- if(null==threadingPlugin) {
+ if( Mode.ST_AWT == mode && null==threadingPlugin ) {
throw new GLException("Mode is AWT, but class 'jogamp.opengl.awt.AWTThreadingPlugin' is not available", error);
}
}
if(DEBUG) {
- System.err.println("Threading: jogl.1thread "+workaround+", singleThreaded "+singleThreaded+", hasAWT "+hasAWT+", mode "+mode+", plugin "+threadingPlugin);
+ System.err.println("Threading: jogl.1thread "+singleThreadProp+", singleThreaded "+singleThreaded+", hasAWT "+hasAWT+", mode "+mode+", plugin "+threadingPlugin);
}
return threadingPlugin;
}
@@ -147,7 +153,7 @@ public class ThreadingImpl {
once disabled, partly to discourage careless use of this
method. This method should be called as early as possible in an
application. */
- public static void disableSingleThreading() {
+ public static final void disableSingleThreading() {
singleThreaded = false;
if (Debug.verbose()) {
System.err.println("Application forced disabling of single-threading of javax.media.opengl implementation");
@@ -156,7 +162,7 @@ public class ThreadingImpl {
/** Indicates whether OpenGL work is being automatically forced to a
single thread in this implementation. */
- public static boolean isSingleThreaded() {
+ public static final boolean isSingleThreaded() {
return singleThreaded;
}
@@ -164,11 +170,7 @@ public class ThreadingImpl {
which this implementation of the javax.media.opengl APIs
performs all of its OpenGL-related work. This method should only
be called if the single-thread model is in effect. */
- public static boolean isOpenGLThread() throws GLException {
- if (!isSingleThreaded()) {
- throw new GLException("Should only call this in single-threaded mode");
- }
-
+ public static final boolean isOpenGLThread() throws GLException {
if(null!=threadingPlugin) {
return threadingPlugin.isOpenGLThread();
}
@@ -182,6 +184,13 @@ public class ThreadingImpl {
throw new InternalError("Illegal single-threading mode " + mode);
}
}
+
+ public static final boolean isToolkitThread() throws GLException {
+ if(null!=threadingPlugin) {
+ return threadingPlugin.isToolkitThread();
+ }
+ return false;
+ }
/** Executes the passed Runnable on the single thread used for all
OpenGL work in this javax.media.opengl API implementation. It is
@@ -192,43 +201,30 @@ public class ThreadingImpl {
false). It is up to the end user to check to see whether the
current thread is the OpenGL thread and either execute the
Runnable directly or perform the work inside it. */
- public static void invokeOnOpenGLThread(Runnable r) throws GLException {
- if (!isSingleThreaded()) {
- throw new GLException ("Should only call this in single-threaded mode");
- }
-
- if (isOpenGLThread()) {
- throw new GLException ("Should only call this from other threads than the OpenGL thread");
- }
-
+ public static final void invokeOnOpenGLThread(boolean wait, Runnable r) throws GLException {
if(null!=threadingPlugin) {
- threadingPlugin.invokeOnOpenGLThread(r);
+ threadingPlugin.invokeOnOpenGLThread(wait, r);
return;
}
switch (mode) {
- case ST_AWT:
- throw new InternalError();
-
case ST_WORKER:
- GLWorkerThread.start(); // singleton start via volatile-dbl-checked-locking
- try {
- GLWorkerThread.invokeAndWait(r);
- } catch (InvocationTargetException e) {
- throw new GLException(e.getTargetException());
- } catch (InterruptedException e) {
- throw new GLException(e);
- }
+ invokeOnWorkerThread(wait, r);
break;
default:
throw new InternalError("Illegal single-threading mode " + mode);
}
}
-
- /** This is a workaround for AWT-related deadlocks which only seem
- to show up in the context of applets */
- public static boolean isAWTMode() {
- return (mode == Mode.ST_AWT);
+
+ public static final void invokeOnWorkerThread(boolean wait, Runnable r) throws GLException {
+ GLWorkerThread.start(); // singleton start via volatile-dbl-checked-locking
+ try {
+ GLWorkerThread.invoke(wait, r);
+ } catch (InvocationTargetException e) {
+ throw new GLException(e.getTargetException());
+ } catch (InterruptedException e) {
+ throw new GLException(e);
+ }
}
}
diff --git a/src/jogl/classes/jogamp/opengl/ThreadingPlugin.java b/src/jogl/classes/jogamp/opengl/ToolkitThreadingPlugin.java
index 0b0748b59..22972953a 100644
--- a/src/jogl/classes/jogamp/opengl/ThreadingPlugin.java
+++ b/src/jogl/classes/jogamp/opengl/ToolkitThreadingPlugin.java
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2012 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
@@ -41,8 +42,12 @@ package jogamp.opengl;
import javax.media.opengl.*;
-public interface ThreadingPlugin {
- /** Indicates whether the current thread is the single thread on
+public interface ToolkitThreadingPlugin {
+ /** Indicates whether the current thread is the designated toolkit thread,
+ if such semantics exists. */
+ public boolean isToolkitThread() throws GLException;
+
+ /** Indicates whether the current thread is the thread on
which this implementation of the javax.media.opengl APIs
performs all of its OpenGL-related work. This method should only
be called if the single-thread model is in effect. */
@@ -57,6 +62,6 @@ public interface ThreadingPlugin {
false). It is up to the end user to check to see whether the
current thread is the OpenGL thread and either execute the
Runnable directly or perform the work inside it. */
- public void invokeOnOpenGLThread(Runnable r) throws GLException;
+ public void invokeOnOpenGLThread(boolean wait, Runnable r) throws GLException;
}
diff --git a/src/jogl/classes/jogamp/opengl/awt/AWTThreadingPlugin.java b/src/jogl/classes/jogamp/opengl/awt/AWTThreadingPlugin.java
index 901146fc4..73b7d197d 100644
--- a/src/jogl/classes/jogamp/opengl/awt/AWTThreadingPlugin.java
+++ b/src/jogl/classes/jogamp/opengl/awt/AWTThreadingPlugin.java
@@ -40,18 +40,24 @@
package jogamp.opengl.awt;
-import javax.media.opengl.*;
-
import java.awt.EventQueue;
import java.lang.reflect.InvocationTargetException;
-import jogamp.opengl.*;
+import javax.media.opengl.GLException;
+
+import jogamp.opengl.GLWorkerThread;
+import jogamp.opengl.ThreadingImpl;
+import jogamp.opengl.ToolkitThreadingPlugin;
-public class AWTThreadingPlugin implements ThreadingPlugin {
+public class AWTThreadingPlugin implements ToolkitThreadingPlugin {
public AWTThreadingPlugin() {}
- public boolean isOpenGLThread() throws GLException {
+ public final boolean isToolkitThread() throws GLException {
+ return EventQueue.isDispatchThread();
+ }
+
+ public final boolean isOpenGLThread() throws GLException {
switch (ThreadingImpl.getMode()) {
case ST_AWT:
// FIXME: See the FIXME below in 'invokeOnOpenGLThread'
@@ -76,7 +82,7 @@ public class AWTThreadingPlugin implements ThreadingPlugin {
}
}
- public void invokeOnOpenGLThread(Runnable r) throws GLException {
+ public final void invokeOnOpenGLThread(boolean wait, Runnable r) throws GLException {
switch (ThreadingImpl.getMode()) {
case ST_AWT:
// FIXME: ideally should run all OpenGL work on the Java2D QFT
@@ -87,11 +93,19 @@ public class AWTThreadingPlugin implements ThreadingPlugin {
// implementation, which attempts to grab the AWT lock on the
// QFT which is not allowed. For now, on X11 platforms,
// continue to perform this work on the EDT.
- if (Java2D.isOGLPipelineActive() && !ThreadingImpl.isX11()) {
- Java2D.invokeWithOGLContextCurrent(null, r);
+ if (wait && Java2D.isOGLPipelineActive() && !ThreadingImpl.isX11()) {
+ if(wait) {
+ Java2D.invokeWithOGLContextCurrent(null, r);
+ } else {
+
+ }
} else {
try {
- EventQueue.invokeAndWait(r);
+ if(wait) {
+ EventQueue.invokeAndWait(r);
+ } else {
+ EventQueue.invokeLater(r);
+ }
} catch (InvocationTargetException e) {
throw new GLException(e.getTargetException());
} catch (InterruptedException e) {
@@ -101,14 +115,7 @@ public class AWTThreadingPlugin implements ThreadingPlugin {
break;
case ST_WORKER:
- GLWorkerThread.start(); // singleton start via volatile-dbl-checked-locking
- try {
- GLWorkerThread.invokeAndWait(r);
- } catch (InvocationTargetException e) {
- throw new GLException(e.getTargetException());
- } catch (InterruptedException e) {
- throw new GLException(e);
- }
+ ThreadingImpl.invokeOnWorkerThread(wait, r);
break;
default:
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
index f4ab92a04..5cfd12ef5 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
@@ -55,6 +55,7 @@ import javax.media.opengl.GLProfile;
import jogamp.nativewindow.x11.X11Lib;
import jogamp.nativewindow.x11.X11Util;
+import jogamp.opengl.Debug;
import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLDrawableImpl;
@@ -63,8 +64,7 @@ import com.jogamp.gluegen.runtime.ProcAddressTable;
import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver;
public abstract class X11GLXContext extends GLContextImpl {
- protected static final boolean TRACE_CONTEXT_CURRENT = false; // true;
-
+ private static final boolean DEBUG_GLX_MAKECURRENT = Debug.debug("GLX_MAKE_CURRENT");
private static final Map<String, String> functionNameMap;
private static final Map<String, String> extensionNameMap;
private GLXExt _glXExt;
@@ -139,10 +139,10 @@ public abstract class X11GLXContext extends GLContextImpl {
boolean res = false;
try {
- if(TRACE_CONTEXT_CURRENT) {
- Throwable t = new Throwable(Thread.currentThread()+" - glXMakeContextCurrent("+toHexString(dpy)+", "+
- toHexString(writeDrawable)+", "+toHexString(readDrawable)+", "+toHexString(ctx)+") - GLX >= 1.3 "+ isGLXVersionGreaterEqualOneThree());
- t.printStackTrace();
+ if(DEBUG_GLX_MAKECURRENT) {
+ System.err.println(getThreadName()+": glXMakeContextCurrent(dpy "+toHexString(dpy)+", write "+ toHexString(writeDrawable)+
+ ", read "+toHexString(readDrawable)+", ctx "+toHexString(ctx)+") - GLX >= 1.3 "+ isGLXVersionGreaterEqualOneThree());
+ Thread.dumpStack();
}
if ( isGLXVersionGreaterEqualOneThree() ) {
res = GLX.glXMakeContextCurrent(dpy, writeDrawable, readDrawable, ctx);
@@ -153,8 +153,8 @@ public abstract class X11GLXContext extends GLContextImpl {
throw new InternalError("Given readDrawable but no driver support");
}
} catch (RuntimeException re) {
- if(DEBUG) {
- System.err.println("Warning: X11GLXContext.glXMakeContextCurrent failed: "+re+", with "+
+ if(TRACE_SWITCH) {
+ System.err.println(getThreadName()+": Warning: X11GLXContext.glXMakeContextCurrent failed: "+re+", with "+
"dpy "+toHexString(dpy)+
", write "+toHexString(writeDrawable)+
", read "+toHexString(readDrawable)+
@@ -190,7 +190,7 @@ public abstract class X11GLXContext extends GLContextImpl {
updateGLXProcAddressTable();
GLXExt _glXExt = getGLXExt();
if(DEBUG) {
- System.err.println("X11GLXContext.createContextARBImpl: "+getGLVersion(major, minor, ctp, "@creation") +
+ System.err.println(getThreadName()+": X11GLXContext.createContextARBImpl: "+getGLVersion(major, minor, ctp, "@creation") +
", handle "+toHexString(drawable.getHandle()) + ", share "+toHexString(share)+", direct "+direct+
", glXCreateContextAttribsARB: "+toHexString(glXExtProcAddressTable._addressof_glXCreateContextAttribsARB));
}
@@ -237,14 +237,14 @@ public abstract class X11GLXContext extends GLContextImpl {
X11Lib.XSync(display, false);
} catch (RuntimeException re) {
if(DEBUG) {
- Throwable t = new Throwable("Info: X11GLXContext.createContextARBImpl glXCreateContextAttribsARB failed with "+getGLVersion(major, minor, ctp, "@creation"), re);
+ Throwable t = new Throwable(getThreadName()+": Info: X11GLXContext.createContextARBImpl glXCreateContextAttribsARB failed with "+getGLVersion(major, minor, ctp, "@creation"), re);
t.printStackTrace();
}
}
if(0!=ctx) {
if (!glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), ctx)) {
if(DEBUG) {
- System.err.println("X11GLXContext.createContextARBImpl couldn't make current "+getGLVersion(major, minor, ctp, "@creation"));
+ System.err.println(getThreadName()+": X11GLXContext.createContextARBImpl couldn't make current "+getGLVersion(major, minor, ctp, "@creation"));
}
// release & destroy
glXMakeContextCurrent(display, 0, 0, 0);
@@ -295,14 +295,14 @@ public abstract class X11GLXContext extends GLContextImpl {
if(config.getFBConfigID()<0) {
// not able to use FBConfig
if(glp.isGL3()) {
- throw new GLException("Unable to create OpenGL >= 3.1 context");
+ throw new GLException(getThreadName()+": Unable to create OpenGL >= 3.1 context");
}
contextHandle = GLX.glXCreateContext(display, config.getXVisualInfo(), share, direct);
if (contextHandle == 0) {
- throw new GLException("Unable to create context(0)");
+ throw new GLException(getThreadName()+": Unable to create context(0)");
}
if (!glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), contextHandle)) {
- throw new GLException("Error making temp context(0) current: display "+toHexString(display)+", context "+toHexString(contextHandle)+", drawable "+drawable);
+ throw new GLException(getThreadName()+": Error making temp context(0) current: display "+toHexString(display)+", context "+toHexString(contextHandle)+", drawable "+drawable);
}
setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT); // use GL_VERSION
isDirect = GLX.glXIsDirect(display, contextHandle);
@@ -329,10 +329,10 @@ public abstract class X11GLXContext extends GLContextImpl {
// so we are able to use GetProcAddress
temp_ctx = GLX.glXCreateNewContext(display, config.getFBConfig(), GLX.GLX_RGBA_TYPE, share, direct);
if (temp_ctx == 0) {
- throw new GLException("Unable to create temp OpenGL context(1)");
+ throw new GLException(getThreadName()+": Unable to create temp OpenGL context(1)");
}
if (!glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), temp_ctx)) {
- throw new GLException("Error making temp context(1) current: display "+toHexString(display)+", context "+toHexString(temp_ctx)+", drawable "+drawable);
+ throw new GLException(getThreadName()+": Error making temp context(1) current: display "+toHexString(display)+", context "+toHexString(temp_ctx)+", drawable "+drawable);
}
setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT); // use GL_VERSION
glXMakeContextCurrent(display, 0, 0, 0); // release temp context
@@ -364,17 +364,17 @@ public abstract class X11GLXContext extends GLContextImpl {
glXMakeContextCurrent(display, 0, 0, 0);
GLX.glXDestroyContext(display, temp_ctx);
if (!glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), contextHandle)) {
- throw new GLException("Cannot make previous verified context current");
+ throw new GLException(getThreadName()+": Cannot make previous verified context current");
}
}
} else {
if(glp.isGL3()) {
glXMakeContextCurrent(display, 0, 0, 0);
GLX.glXDestroyContext(display, temp_ctx);
- throw new GLException("X11GLXContext.createContextImpl ctx !ARB, context > GL2 requested - requested: "+glp+", current: "+getGLVersion()+", ");
+ throw new GLException(getThreadName()+": X11GLXContext.createContextImpl ctx !ARB, context > GL2 requested - requested: "+glp+", current: "+getGLVersion()+", ");
}
if(DEBUG) {
- System.err.println("X11GLXContext.createContextImpl failed, fall back to !ARB context "+getGLVersion());
+ System.err.println(getThreadName()+": X11GLXContext.createContextImpl failed, fall back to !ARB context "+getGLVersion());
}
// continue with temp context for GL <= 3.0
@@ -382,7 +382,7 @@ public abstract class X11GLXContext extends GLContextImpl {
if (!glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), contextHandle)) {
glXMakeContextCurrent(display, 0, 0, 0);
GLX.glXDestroyContext(display, temp_ctx);
- throw new GLException("Error making context(1) current: display "+toHexString(display)+", context "+toHexString(contextHandle)+", drawable "+drawable);
+ throw new GLException(getThreadName()+": Error making context(1) current: display "+toHexString(display)+", context "+toHexString(contextHandle)+", drawable "+drawable);
}
if (DEBUG) {
System.err.println(getThreadName() + ": createContextImpl: OK (old-2) share "+share);
@@ -402,7 +402,7 @@ public abstract class X11GLXContext extends GLContextImpl {
X11Util.setX11ErrorHandler(true, DEBUG ? false : true);
try {
if (!glXMakeContextCurrent(dpy, drawable.getHandle(), drawableRead.getHandle(), contextHandle)) {
- throw new GLException("Error making context current: "+this);
+ throw new GLException(getThreadName()+": Error making context current: "+this);
}
} finally {
X11Util.setX11ErrorHandler(false, false);
@@ -415,7 +415,7 @@ public abstract class X11GLXContext extends GLContextImpl {
X11Util.setX11ErrorHandler(true, DEBUG ? false : true);
try {
if (!glXMakeContextCurrent(display, 0, 0, 0)) {
- throw new GLException("Error freeing OpenGL context");
+ throw new GLException(getThreadName()+": Error freeing OpenGL context");
}
} finally {
X11Util.setX11ErrorHandler(false, false);
@@ -431,7 +431,7 @@ public abstract class X11GLXContext extends GLContextImpl {
long src = source.getHandle();
long display = drawable.getNativeSurface().getDisplayHandle();
if (0 == display) {
- throw new GLException("Connection to X display not yet set up");
+ throw new GLException(getThreadName()+": Connection to X display not yet set up");
}
GLX.glXCopyContext(display, src, dst, mask);
// Should check for X errors and raise GLException