diff options
Diffstat (limited to 'src/jogl/classes')
-rw-r--r-- | src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java | 2 | ||||
-rw-r--r-- | src/jogl/classes/javax/media/opengl/GLContext.java | 4 | ||||
-rw-r--r-- | src/jogl/classes/javax/media/opengl/Threading.java | 44 | ||||
-rw-r--r-- | src/jogl/classes/javax/media/opengl/awt/GLCanvas.java | 269 | ||||
-rw-r--r-- | src/jogl/classes/javax/media/opengl/awt/GLJPanel.java | 122 | ||||
-rw-r--r-- | src/jogl/classes/jogamp/opengl/GLContextImpl.java | 28 | ||||
-rw-r--r-- | src/jogl/classes/jogamp/opengl/GLWorkerThread.java | 11 | ||||
-rw-r--r-- | src/jogl/classes/jogamp/opengl/ThreadingImpl.java | 106 | ||||
-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.java | 41 | ||||
-rw-r--r-- | src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java | 46 |
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 |