diff options
9 files changed, 134 insertions, 128 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java index 42097bd6d..b4c7cddf0 100644 --- a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java +++ b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java @@ -480,7 +480,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { */ protected boolean isRenderThread() { if (Threading.isSingleThreaded()) { - if (ThreadingImpl.getMode() != ThreadingImpl.WORKER) { + if (ThreadingImpl.getMode() != ThreadingImpl.Mode.ST_WORKER) { final Display display = getDisplay(); return display != null && display.getThread() == Thread.currentThread(); } @@ -521,7 +521,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { * The non-null action to dispatch. */ private void runInDesignatedGLThread(final Runnable makeCurrentAndRunAction) { - if (ThreadingImpl.getMode() != ThreadingImpl.WORKER) { + if (ThreadingImpl.getMode() != ThreadingImpl.Mode.ST_WORKER) { final Display display = getDisplay(); assert display.getThread() != Thread.currentThread() : "Incorrect use of thread dispatching."; display.syncExec(makeCurrentAndRunAction); diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java index f928bc126..41dce0d3b 100644 --- a/src/jogl/classes/javax/media/opengl/GLContext.java +++ b/src/jogl/classes/javax/media/opengl/GLContext.java @@ -122,6 +122,10 @@ public abstract class GLContext { private int currentSwapInterval; protected void resetStates() { + if (DEBUG) { + System.err.println(getThreadName() + ": GLContext.resetStates()"); + // Thread.dumpStack(); + } ctxMajorVersion=-1; ctxMinorVersion=-1; ctxOptions=0; @@ -260,7 +264,7 @@ public abstract class GLContext { public static GL getCurrentGL() throws GLException { GLContext glc = getCurrent(); if(null==glc) { - throw new GLException("No OpenGL context current on this thread"); + throw new GLException(getThreadName()+": No OpenGL context current on this thread"); } return glc.getGL(); } @@ -288,7 +292,7 @@ public abstract class GLContext { */ public final void validateCurrent() throws GLException { if(getCurrent() != this) { - throw new GLException("Given GL context not current"); + throw new GLException(getThreadName()+": This context is not current. Current context: "+getCurrent()+", this context "+this); } } @@ -299,7 +303,7 @@ public abstract class GLContext { */ protected static void setCurrent(GLContext cur) { if(TRACE_SWITCH) { - System.err.println("GLContext.ContextSwitch: - setCurrent() - "+Thread.currentThread().getName()+": "+cur); + System.err.println(getThreadName()+": GLContext.ContextSwitch: - setCurrent() - "+cur); } currentContext.set(cur); } @@ -624,9 +628,7 @@ public abstract class GLContext { * @throws GLException if the context is not current. */ public final boolean setSwapInterval(int interval) throws GLException { - if (!isCurrent()) { - throw new GLException("This context is not current. Current context: "+getCurrent()+", this context "+this); - } + validateCurrent(); if(0<=interval) { if( setSwapIntervalImpl(interval) ) { currentSwapInterval = interval; @@ -665,18 +667,13 @@ public abstract class GLContext { public final boolean queryMaxSwapGroups(int[] maxGroups, int maxGroups_offset, int[] maxBarriers, int maxBarriers_offset) { - - if (!isCurrent()) { - throw new GLException("This context is not current. Current context: "+getCurrent()+", this context "+this); - } + validateCurrent(); return queryMaxSwapGroupsImpl(maxGroups, maxGroups_offset, maxBarriers, maxBarriers_offset); } protected boolean queryMaxSwapGroupsImpl(int[] maxGroups, int maxGroups_offset, int[] maxBarriers, int maxBarriers_offset) { return false; } public final boolean joinSwapGroup(int group) { - if (!isCurrent()) { - throw new GLException("This context is not current. Current context: "+getCurrent()+", this context "+this); - } + validateCurrent(); return joinSwapGroupImpl(group); } protected boolean joinSwapGroupImpl(int group) { /** nop per default .. **/ return false; } @@ -685,9 +682,7 @@ public abstract class GLContext { return currentSwapGroup; } public final boolean bindSwapBarrier(int group, int barrier) { - if (!isCurrent()) { - throw new GLException("This context is not current. Current context: "+getCurrent()+", this context "+this); - } + validateCurrent(); return bindSwapBarrierImpl(group, barrier); } protected boolean bindSwapBarrierImpl(int group, int barrier) { /** nop per default .. **/ return false; } @@ -875,7 +870,6 @@ public abstract class GLContext { deviceVersionsAvailableSet.add(devKey); if (DEBUG) { System.err.println(getThreadName() + ": createContextARB: SET mappedVersionsAvailableSet "+devKey); - // Thread.dumpStack(); } } } diff --git a/src/jogl/classes/javax/media/opengl/Threading.java b/src/jogl/classes/javax/media/opengl/Threading.java index d0f3ebb93..4871c1dd7 100644 --- a/src/jogl/classes/javax/media/opengl/Threading.java +++ b/src/jogl/classes/javax/media/opengl/Threading.java @@ -101,17 +101,17 @@ import jogamp.opengl.*; In addition to specifying programmatically whether the single thread for OpenGL work is enabled, users may switch it on and off - using the system property <code>opengl.1thread</code>. Valid values + using the system property <code>jogl.1thread</code>. Valid values for this system property are: <PRE> - -Dopengl.1thread=false Disable single-threading of OpenGL work - -Dopengl.1thread=true Enable single-threading of OpenGL work (default -- on a newly-created worker thread) - -Dopengl.1thread=auto Select default single-threading behavior (currently on) - -Dopengl.1thread=awt Enable single-threading of OpenGL work on AWT event dispatch thread (current default on all - platforms, and also the default behavior older releases) - -Dopengl.1thread=worker Enable single-threading of OpenGL work on newly-created worker thread (not suitable for Mac - OS X or X11 platforms, and risky on Windows in applet environments) + -Djogl.1thread=false Disable single-threading of OpenGL work, hence use multithreading. + -Djogl.1thread=true Enable single-threading of OpenGL work (default -- on a newly-created worker thread) + -Djogl.1thread=auto Select default single-threading behavior (currently on) + -Djogl.1thread=awt Enable single-threading of OpenGL work on AWT event dispatch thread (current default on all + platforms, and also the default behavior older releases) + -Djogl.1thread=worker Enable single-threading of OpenGL work on newly-created worker thread (not suitable for Mac + OS X or X11 platforms, and risky on Windows in applet environments) </PRE> */ diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java index d8d9ddf6b..10d478b85 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java @@ -140,11 +140,7 @@ import jogamp.opengl.ThreadingImpl; @SuppressWarnings("serial") public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosingProtocol, OffscreenLayerOption { - private static final boolean DEBUG; - - static { - DEBUG = Debug.debug("GLCanvas"); - } + private static final boolean DEBUG = Debug.debug("GLCanvas"); private GLDrawableHelper drawableHelper = new GLDrawableHelper(); private AWTGraphicsConfiguration awtConfig; @@ -330,14 +326,14 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing final GraphicsConfiguration compatible = (null!=config)?config.getAWTGraphicsConfiguration():null; boolean equalCaps = config.getChosenCapabilities().equals(awtConfig.getChosenCapabilities()); if(DEBUG) { - Exception e = new Exception("Info: Call Stack: "+Thread.currentThread().getName()); - e.printStackTrace(); + System.err.println(getThreadName()+": Info:"); System.err.println("Created Config (n): HAVE GC "+chosen); System.err.println("Created Config (n): THIS GC "+gc); System.err.println("Created Config (n): Choosen GC "+compatible); System.err.println("Created Config (n): HAVE CF "+awtConfig); System.err.println("Created Config (n): Choosen CF "+config); System.err.println("Created Config (n): EQUALS CAPS "+equalCaps); + Thread.dumpStack(); } if (compatible != null) { @@ -412,7 +408,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing public void display() { if( !validateGLDrawable() ) { if(DEBUG) { - System.err.println("Info: GLCanvas display - skipped GL render, drawable not valid yet"); + System.err.println(getThreadName()+": Info: GLCanvas display - skipped GL render, drawable not valid yet"); } return; // not yet available .. } @@ -427,9 +423,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing try { final GLAnimatorControl animator = getAnimator(); if(DEBUG) { - Exception ex1 = new Exception("Info: dispose("+regenerate+") - START, hasContext " + + System.err.println(getThreadName()+": Info: dispose("+regenerate+") - START, hasContext " + (null!=context) + ", hasDrawable " + (null!=drawable)+", "+animator); - ex1.printStackTrace(); + Thread.dumpStack(); } if(null!=context) { @@ -472,7 +468,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing } if(DEBUG) { - System.err.println("dispose("+regenerate+") - END, "+animator); + System.err.println(getThreadName()+": dispose("+regenerate+") - END, "+animator); } } finally { drawableSync.unlock(); @@ -533,8 +529,8 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing @Override public void addNotify() { if(DEBUG) { - Exception ex1 = new Exception(Thread.currentThread().getName()+" - Info: addNotify - start, bounds: "+this.getBounds()); - ex1.printStackTrace(); + System.err.println(getThreadName()+": Info: addNotify - start, bounds: "+this.getBounds()); + Thread.dumpStack(); } drawableSync.lock(); @@ -570,7 +566,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing // validateGLDrawable(); if(DEBUG) { - System.err.println(Thread.currentThread().getName()+" - Info: addNotify - end: peer: "+getPeer()); + System.err.println(getThreadName()+": Info: addNotify - end: peer: "+getPeer()); } } finally { drawableSync.unlock(); @@ -604,10 +600,8 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing realized = true; sendReshape=true; // ensure a reshape is being send .. if(DEBUG) { - String msg = Thread.currentThread().getName()+" - Realized Drawable: "+drawable.toString(); - // System.err.println(msg); - Throwable t = new Throwable(msg); - t.printStackTrace(); + System.err.println(getThreadName()+": Realized Drawable: "+drawable.toString()); + Thread.dumpStack(); } } } @@ -630,8 +624,8 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing @Override public void removeNotify() { if(DEBUG) { - Exception ex1 = new Exception(Thread.currentThread().getName()+" - Info: removeNotify - start"); - ex1.printStackTrace(); + System.err.println(getThreadName()+": Info: removeNotify - start"); + Thread.dumpStack(); } awtWindowClosingProtocol.removeClosingListener(); @@ -651,7 +645,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing } } if(DEBUG) { - System.err.println(Thread.currentThread().getName()+" - Info: removeNotify - end, peer: "+getPeer()); + System.err.println(getThreadName()+": Info: removeNotify - end, peer: "+getPeer()); } } @@ -853,7 +847,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing createDrawableAndContext(); if(DEBUG) { - System.err.println("GLCanvas.dispose(true): new drawable: "+drawable); + System.err.println(getThreadName()+": GLCanvas.dispose(true): new drawable: "+drawable); } validateGLDrawable(); // immediate attempt to recreate the drawable } @@ -884,7 +878,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing } boolean closed = adevice.close(); if(DEBUG) { - System.err.println(Thread.currentThread().getName() + " - GLCanvas.dispose(false): closed GraphicsDevice: "+adeviceMsg+", result: "+closed); + System.err.println(getThreadName()+": GLCanvas.dispose(false): closed GraphicsDevice: "+adeviceMsg+", result: "+closed); } awtConfig=null; } @@ -923,7 +917,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing public void run() { if (sendReshape) { if(DEBUG) { - System.err.println(Thread.currentThread().getName()+" - reshape: "+getWidth()+"x"+getHeight()); + System.err.println(getThreadName()+": Reshape: "+getWidth()+"x"+getHeight()); } // Note: we ignore the given x and y within the parent component // since we are drawing directly into this heavyweight component. @@ -994,7 +988,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing } disableBackgroundEraseInitialized = true; if(DEBUG) { - System.err.println("GLCanvas: TK disableBackgroundErase method found: "+ + System.err.println(getThreadName()+": GLCanvas: TK disableBackgroundErase method found: "+ (null!=disableBackgroundEraseMethod)); } } @@ -1006,7 +1000,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing t = e; } if(DEBUG) { - System.err.println("GLCanvas: TK disableBackgroundErase error: "+t); + System.err.println(getThreadName()+": GLCanvas: TK disableBackgroundErase error: "+t); } } } @@ -1069,6 +1063,10 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing return config; } + protected static String getThreadName() { + return Thread.currentThread().getName(); + } + /** * A most simple JOGL AWT test entry */ diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java index af8282752..7fd9970a4 100644 --- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java @@ -286,7 +286,7 @@ public abstract class GLContextImpl extends GLContext { throw new GLException("XXX: "+lock); } if (DEBUG || TRACE_SWITCH) { - System.err.println(getThreadName() + ": GLContextImpl.destroy.0 - "+Thread.currentThread().getName()+": " + toHexString(contextHandle) + + System.err.println(getThreadName() + ": GLContextImpl.destroy.0: " + toHexString(contextHandle) + ", isShared "+GLContextShareSet.isShared(this)+" - "+lock); } if (contextHandle != 0) { @@ -661,7 +661,10 @@ public abstract class GLContextImpl extends GLContext { } if ( !GLContext.getAvailableGLVersionsSet(device) ) { - mapGLVersions(device); + if(!mapGLVersions(device)) { + // none of the ARB context creation calls was successful, bail out + return 0; + } } int reqMajor; @@ -690,19 +693,26 @@ public abstract class GLContextImpl extends GLContext { return _ctx; } - private final void mapGLVersions(AbstractGraphicsDevice device) { + private final boolean mapGLVersions(AbstractGraphicsDevice device) { synchronized (GLContext.deviceVersionAvailable) { + boolean success = false; // Following GLProfile.GL_PROFILE_LIST_ALL order of profile detection { GL4bc, GL3bc, GL2, GL4, GL3, GL2GL3, GLES2, GL2ES2, GLES1, GL2ES1 } - createContextARBMapVersionsAvailable(4, true /* compat */); // GL4bc - createContextARBMapVersionsAvailable(3, true /* compat */); // GL3bc - createContextARBMapVersionsAvailable(2, true /* compat */); // GL2 - createContextARBMapVersionsAvailable(4, false /* core */); // GL4 - createContextARBMapVersionsAvailable(3, false /* core */); // GL3 - GLContext.setAvailableGLVersionsSet(device); + success |= createContextARBMapVersionsAvailable(4, true /* compat */); // GL4bc + success |= createContextARBMapVersionsAvailable(3, true /* compat */); // GL3bc + success |= createContextARBMapVersionsAvailable(2, true /* compat */); // GL2 + success |= createContextARBMapVersionsAvailable(4, false /* core */); // GL4 + success |= createContextARBMapVersionsAvailable(3, false /* core */); // GL3 + if(success) { + // only claim GL versions set [and hence detected] if ARB context creation was successful + GLContext.setAvailableGLVersionsSet(device); + } else if (DEBUG) { + System.err.println(getThreadName() + ": createContextARB-MapVersions NONE for :"+device); + } + return success; } } - private final void createContextARBMapVersionsAvailable(int reqMajor, boolean compat) { + private final boolean createContextARBMapVersionsAvailable(int reqMajor, boolean compat) { long _context; int reqProfile = compat ? CTX_PROFILE_COMPAT : CTX_PROFILE_CORE ; int ctp = CTX_IS_ARB_CREATED | CTX_PROFILE_CORE; // default @@ -725,8 +735,10 @@ public abstract class GLContextImpl extends GLContext { majorMax=3; minorMax=GLContext.getMaxMinor(majorMax); majorMin=3; minorMin=1; } else /* if( glp.isGL2() ) */ { + // our minimum desktop OpenGL runtime requirements are 1.1, + // nevertheless we restrict ARB context creation to 2.0 to spare us futile attempts majorMax=3; minorMax=0; - majorMin=1; minorMin=1; // our minimum desktop OpenGL runtime requirements + majorMin=2; minorMin=0; } _context = createContextARBVersions(0, true, ctp, /* max */ majorMax, minorMax, @@ -734,8 +746,8 @@ public abstract class GLContextImpl extends GLContext { /* res */ major, minor); if(0==_context && !compat) { - ctp &= ~CTX_PROFILE_COMPAT ; - ctp |= CTX_PROFILE_CORE ; + // try w/ FORWARD instead of CORE + ctp &= ~CTX_PROFILE_CORE ; ctp |= CTX_OPTION_FORWARD ; _context = createContextARBVersions(0, true, ctp, /* max */ majorMax, minorMax, @@ -744,8 +756,8 @@ public abstract class GLContextImpl extends GLContext { if(0==_context) { // Try a compatible one .. even though not requested .. last resort ctp &= ~CTX_PROFILE_CORE ; - ctp |= CTX_PROFILE_COMPAT ; ctp &= ~CTX_OPTION_FORWARD ; + ctp |= CTX_PROFILE_COMPAT ; _context = createContextARBVersions(0, true, ctp, /* max */ majorMax, minorMax, /* min */ majorMin, minorMin, @@ -757,23 +769,19 @@ public abstract class GLContextImpl extends GLContext { // ctxMajorVersion, ctxMinorVersion, ctxOptions is being set by // createContextARBVersions(..) -> setGLFunctionAvailbility(..) -> setContextVersion(..) GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile, ctxMajorVersion, ctxMinorVersion, ctxOptions); - /** - * TODO: GLES2_TRUE_DESKTOP (see: GLContextImpl, GLProfile) - * Hack to enable GLES2 for desktop profiles w/ ES2 compatibility, - * however .. a consequent implementation would need to have all GL2ES2 - * implementing profile to also implement GLES2! - * Let's rely on GL2ES2 and let the user/impl. query isGLES2Compatible() - if( isGLES2Compatible() && null == GLContext.getAvailableGLVersion(device, 2, GLContext.CTX_PROFILE_ES) ) { - GLContext.mapAvailableGLVersion(device, 2, GLContext.CTX_PROFILE_ES, ctxMajorVersion, ctxMinorVersion, ctxOptions); - }*/ destroyContextARBImpl(_context); if (DEBUG) { System.err.println(getThreadName() + ": createContextARB-MapVersionsAvailable HAVE: " +reqMajor+"."+reqProfile+ " -> "+getGLVersion()); } - } else if (DEBUG) { - System.err.println(getThreadName() + ": createContextARB-MapVersionsAvailable NOPE: "+reqMajor+"."+reqProfile); + // only reset [and hence modify] this context state if ARB context creation was successful + resetStates(); + return true; + } else { + if (DEBUG) { + System.err.println(getThreadName() + ": createContextARB-MapVersionsAvailable NOPE: "+reqMajor+"."+reqProfile); + } + return false; } - resetStates(); } private final long createContextARBVersions(long share, boolean direct, int ctxOptionFlags, @@ -1126,7 +1134,8 @@ public abstract class GLContextImpl extends GLContext { } else { isHardwareRasterizer = ! ( glRendererLowerCase.contains("software") /* Mesa3D */ || glRendererLowerCase.contains("mesa x11") /* Mesa3D*/ || - glRendererLowerCase.contains("softpipe") /* Gallium */ + glRendererLowerCase.contains("softpipe") /* Gallium */ || + glRendererLowerCase.contains("llvmpipe") /* Gallium */ ); } return isHardwareRasterizer; diff --git a/src/jogl/classes/jogamp/opengl/GLWorkerThread.java b/src/jogl/classes/jogamp/opengl/GLWorkerThread.java index ac9655fbb..e717ec64c 100644 --- a/src/jogl/classes/jogamp/opengl/GLWorkerThread.java +++ b/src/jogl/classes/jogamp/opengl/GLWorkerThread.java @@ -40,8 +40,10 @@ package jogamp.opengl; import java.lang.reflect.InvocationTargetException; -import java.util.*; -import javax.media.opengl.*; +import java.util.ArrayList; +import java.util.List; + +import javax.media.opengl.GLContext; /** Singleton thread upon which all OpenGL work is performed by default. Unfortunately many vendors' OpenGL drivers are not really @@ -64,7 +66,7 @@ public class GLWorkerThread { // The Runnable to execute immediately on the worker thread private static volatile Runnable work; // Queue of Runnables to be asynchronously invoked - private static List queue = new LinkedList(); + private static List<Runnable> queue = new ArrayList<Runnable>(); /** Should only be called by Threading class if creation of the GLWorkerThread was requested via the opengl.1thread system @@ -141,7 +143,7 @@ public class GLWorkerThread { */ } else { - throw new RuntimeException("Should not start GLWorkerThread twice"); + throw new RuntimeException(getThreadName()+": Should not start GLWorkerThread twice"); } } } @@ -150,7 +152,7 @@ public class GLWorkerThread { public static void invokeAndWait(Runnable runnable) throws InvocationTargetException, InterruptedException { if (!started) { - throw new RuntimeException("May not invokeAndWait on worker thread without starting it first"); + throw new RuntimeException(getThreadName()+": May not invokeAndWait on worker thread without starting it first"); } Object lockTemp = lock; @@ -177,7 +179,7 @@ public class GLWorkerThread { public static void invokeLater(Runnable runnable) { if (!started) { - throw new RuntimeException("May not invokeLater on worker thread without starting it first"); + throw new RuntimeException(getThreadName()+": May not invokeLater on worker thread without starting it first"); } Object lockTemp = lock; @@ -208,6 +210,10 @@ public class GLWorkerThread { return (Thread.currentThread() == thread); } + protected static String getThreadName() { + return Thread.currentThread().getName(); + } + static class WorkerRunnable implements Runnable { public void run() { // Notify starting thread that we're ready @@ -252,10 +258,10 @@ public class GLWorkerThread { while (!queue.isEmpty()) { try { - Runnable curAsync = (Runnable) queue.remove(0); + Runnable curAsync = queue.remove(0); curAsync.run(); } catch (Throwable t) { - System.err.println("Exception occurred on JOGL OpenGL worker thread:"); + System.err.println(getThreadName()+": Exception occurred on JOGL OpenGL worker thread:"); t.printStackTrace(); } } diff --git a/src/jogl/classes/jogamp/opengl/ThreadingImpl.java b/src/jogl/classes/jogamp/opengl/ThreadingImpl.java index 07d5c3402..0ba86870d 100644 --- a/src/jogl/classes/jogamp/opengl/ThreadingImpl.java +++ b/src/jogl/classes/jogamp/opengl/ThreadingImpl.java @@ -47,13 +47,20 @@ import javax.media.opengl.GLProfile; /** Implementation of the {@link javax.media.opengl.Threading} class. */ public class ThreadingImpl { - public static final int AWT = 1; - public static final int WORKER = 2; + public enum Mode { + MT(0), ST_AWT(1), ST_WORKER(2); + + public final int id; + + Mode(int id){ + this.id = id; + } + } protected static final boolean DEBUG = Debug.debug("Threading"); private static boolean singleThreaded = true; - private static int mode; + private static Mode mode = Mode.MT; 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 @@ -65,7 +72,11 @@ public class ThreadingImpl { threadingPlugin = AccessController.doPrivileged(new PrivilegedAction<ThreadingPlugin>() { public ThreadingPlugin run() { - String workaround = Debug.getProperty("jogl.1thread", true); + final String workaround; + { + final String w = Debug.getProperty("jogl.1thread", true); + workaround = null != w ? w.toLowerCase() : null; + } ClassLoader cl = ThreadingImpl.class.getClassLoader(); // Default to using the AWT thread on all platforms except // Windows. On OS X there is instability apparently due to @@ -80,50 +91,48 @@ public class ThreadingImpl { String osType = NativeWindowFactory.getNativeWindowType(false); _isX11 = NativeWindowFactory.TYPE_X11.equals(osType); - int defaultMode = ( hasAWT ? AWT : WORKER ); - - mode = defaultMode; + mode = ( hasAWT ? Mode.ST_AWT : Mode.ST_WORKER ); // default + if (workaround != null) { - workaround = workaround.toLowerCase(); if (workaround.equals("true") || workaround.equals("auto")) { // Nothing to do; singleThreaded and mode already set up } else if (workaround.equals("worker")) { singleThreaded = true; - mode = WORKER; + mode = Mode.ST_WORKER; } else if (hasAWT && workaround.equals("awt")) { singleThreaded = true; - mode = AWT; + mode = Mode.ST_AWT; } else { singleThreaded = false; + mode = Mode.MT; } } - printWorkaroundNotice(); - + ThreadingPlugin threadingPlugin=null; - if(hasAWT) { + if(Mode.ST_AWT == mode) { // try to fetch the AWTThreadingPlugin Exception error=null; try { threadingPlugin = (ThreadingPlugin) ReflectionUtil.createInstance("jogamp.opengl.awt.AWTThreadingPlugin", cl); } catch (JogampRuntimeException jre) { error = jre; } - if(AWT == mode && null==threadingPlugin) { + if(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); + } return threadingPlugin; } }); - if(DEBUG) { - System.err.println("Threading: hasAWT "+hasAWT+", mode "+((mode==AWT)?"AWT":"WORKER")+", plugin "+threadingPlugin); - } } /** No reason to ever instantiate this class */ private ThreadingImpl() {} public static boolean isX11() { return _isX11; } - public static int getMode() { return mode; } + public static Mode getMode() { return mode; } /** If an implementation of the javax.media.opengl APIs offers a multithreading option but the default behavior is single-threading, @@ -165,9 +174,9 @@ public class ThreadingImpl { } switch (mode) { - case AWT: + case ST_AWT: throw new InternalError(); - case WORKER: + case ST_WORKER: return GLWorkerThread.isWorkerThread(); default: throw new InternalError("Illegal single-threading mode " + mode); @@ -198,10 +207,10 @@ public class ThreadingImpl { } switch (mode) { - case AWT: + case ST_AWT: throw new InternalError(); - case WORKER: + case ST_WORKER: GLWorkerThread.start(); // singleton start via volatile-dbl-checked-locking try { GLWorkerThread.invokeAndWait(r); @@ -220,14 +229,6 @@ public class ThreadingImpl { /** 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 == AWT); - } - - private static void printWorkaroundNotice() { - if (singleThreaded && Debug.verbose()) { - System.err.println("Using " + - (mode == AWT ? "AWT" : "OpenGL worker") + - " thread for performing OpenGL work in javax.media.opengl implementation"); - } + return (mode == Mode.ST_AWT); } } diff --git a/src/jogl/classes/jogamp/opengl/awt/AWTThreadingPlugin.java b/src/jogl/classes/jogamp/opengl/awt/AWTThreadingPlugin.java index dd493f5ee..901146fc4 100644 --- a/src/jogl/classes/jogamp/opengl/awt/AWTThreadingPlugin.java +++ b/src/jogl/classes/jogamp/opengl/awt/AWTThreadingPlugin.java @@ -42,8 +42,6 @@ package jogamp.opengl.awt; import javax.media.opengl.*; -import java.awt.event.*; - import java.awt.EventQueue; import java.lang.reflect.InvocationTargetException; @@ -55,14 +53,14 @@ public class AWTThreadingPlugin implements ThreadingPlugin { public boolean isOpenGLThread() throws GLException { switch (ThreadingImpl.getMode()) { - case ThreadingImpl.AWT: + case ST_AWT: // FIXME: See the FIXME below in 'invokeOnOpenGLThread' if (Java2D.isOGLPipelineActive() && !ThreadingImpl.isX11()) { return Java2D.isQueueFlusherThread(); } else { return EventQueue.isDispatchThread(); } - case ThreadingImpl.WORKER: + case ST_WORKER: if (Java2D.isOGLPipelineActive()) { // FIXME: ideally only the QFT would be considered to be the // "OpenGL thread", but we can not currently run all of @@ -80,7 +78,7 @@ public class AWTThreadingPlugin implements ThreadingPlugin { public void invokeOnOpenGLThread(Runnable r) throws GLException { switch (ThreadingImpl.getMode()) { - case ThreadingImpl.AWT: + case ST_AWT: // FIXME: ideally should run all OpenGL work on the Java2D QFT // thread when it's enabled, but unfortunately there are // deadlock issues on X11 platforms when making our @@ -102,7 +100,7 @@ public class AWTThreadingPlugin implements ThreadingPlugin { } break; - case ThreadingImpl.WORKER: + case ST_WORKER: GLWorkerThread.start(); // singleton start via volatile-dbl-checked-locking try { GLWorkerThread.invokeAndWait(r); diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java index 08e064da5..f4ab92a04 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java @@ -262,7 +262,7 @@ public abstract class X11GLXContext extends GLContextImpl { protected boolean createImpl(GLContextImpl shareWith) { // covers the whole context creation loop incl createContextARBImpl and destroyContextARBImpl - X11Util.setX11ErrorHandler(true, true); + X11Util.setX11ErrorHandler(true, DEBUG ? false : true); try { return createImplRaw(shareWith); } finally { @@ -399,7 +399,7 @@ public abstract class X11GLXContext extends GLContextImpl { long dpy = drawable.getNativeSurface().getDisplayHandle(); if (GLX.glXGetCurrentContext() != contextHandle) { - X11Util.setX11ErrorHandler(true, true); + X11Util.setX11ErrorHandler(true, DEBUG ? false : true); try { if (!glXMakeContextCurrent(dpy, drawable.getHandle(), drawableRead.getHandle(), contextHandle)) { throw new GLException("Error making context current: "+this); @@ -412,7 +412,7 @@ public abstract class X11GLXContext extends GLContextImpl { protected void releaseImpl() throws GLException { long display = drawable.getNativeSurface().getDisplayHandle(); - X11Util.setX11ErrorHandler(true, true); + X11Util.setX11ErrorHandler(true, DEBUG ? false : true); try { if (!glXMakeContextCurrent(display, 0, 0, 0)) { throw new GLException("Error freeing OpenGL context"); |