summaryrefslogtreecommitdiffstats
path: root/src/classes
diff options
context:
space:
mode:
Diffstat (limited to 'src/classes')
-rwxr-xr-xsrc/classes/com/sun/opengl/impl/GLWorkerThread.java155
-rwxr-xr-xsrc/classes/javax/media/opengl/Threading.java98
2 files changed, 224 insertions, 29 deletions
diff --git a/src/classes/com/sun/opengl/impl/GLWorkerThread.java b/src/classes/com/sun/opengl/impl/GLWorkerThread.java
new file mode 100755
index 000000000..7c1d7413b
--- /dev/null
+++ b/src/classes/com/sun/opengl/impl/GLWorkerThread.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ * Sun gratefully acknowledges that this software was originally authored
+ * and developed by Kenneth Bradley Russell and Christopher John Kline.
+ */
+
+package com.sun.opengl.impl;
+
+/** Singleton thread upon which all OpenGL work is performed by
+ default. Unfortunately many vendors' OpenGL drivers are not really
+ thread-safe and stability is much improved by performing OpenGL
+ work on at most one thread. This is the default behavior of the
+ GLAutoDrawable implementations according to the {@link
+ javax.media.opengl.Threading Threading} class. The GLWorkerThread
+ replaces the original AWT event queue thread-based mechanism for
+ two reasons: first, more than one AWT event queue thread may be
+ spawned, for example if a dialog is being shown; second, it avoids
+ blocking the AWT event queue thread during OpenGL rendering. */
+
+public class GLWorkerThread {
+ private static volatile boolean started;
+ private static volatile Thread thread;
+ private static Object lock;
+ private static volatile boolean shouldTerminate;
+
+ // The Runnable to execute on the worker thread -- no need for a
+ // queue since we don't have an invokeLater() primitive
+ private static volatile Runnable work;
+
+ /** Should only be called by Threading class if creation of the
+ GLWorkerThread was requested via the opengl.1thread system
+ property. */
+ public static void start() {
+ if (!started) {
+ synchronized (GLWorkerThread.class) {
+ if (!started) {
+ lock = new Object();
+ thread = new Thread(new WorkerRunnable(),
+ "JOGL GLWorkerThread");
+ started = true;
+ synchronized (lock) {
+ thread.start();
+ try {
+ lock.wait();
+ } catch (InterruptedException e) {
+ }
+ }
+ } else {
+ throw new RuntimeException("Should not start GLWorkerThread twice");
+ }
+ }
+ }
+ }
+
+ public static void invokeAndWait(Runnable runnable) {
+ if (!started) {
+ throw new RuntimeException("May not invokeAndWait on worker thread without starting it first");
+ }
+
+ Object lockTemp = lock;
+ if (lockTemp == null) {
+ return; // Terminating
+ }
+
+ synchronized (lockTemp) {
+ if (thread == null) {
+ // Terminating
+ return;
+ }
+
+ work = runnable;
+ lock.notifyAll();
+ try {
+ lock.wait();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /** Indicates whether the OpenGL worker thread was started, i.e.,
+ whether it is currently in use. */
+ public static boolean isStarted() {
+ return started;
+ }
+
+ /** Indicates whether the current thread is the OpenGL worker
+ thread. */
+ public static boolean isWorkerThread() {
+ return (Thread.currentThread() == thread);
+ }
+
+ static class WorkerRunnable implements Runnable {
+ public void run() {
+ // Notify starting thread that we're ready
+ synchronized (lock) {
+ lock.notifyAll();
+ }
+
+ while (!shouldTerminate) {
+ synchronized (lock) {
+ while ((work == null) && !shouldTerminate) {
+ try {
+ lock.wait();
+ } catch (InterruptedException e) {
+ }
+ }
+
+ if (shouldTerminate) {
+ thread = null;
+ lock = null;
+ return;
+ }
+
+ work.run();
+ work = null;
+ lock.notifyAll();
+ }
+ }
+ }
+ }
+}
diff --git a/src/classes/javax/media/opengl/Threading.java b/src/classes/javax/media/opengl/Threading.java
index 2799edc58..2f1aa4fb7 100755
--- a/src/classes/javax/media/opengl/Threading.java
+++ b/src/classes/javax/media/opengl/Threading.java
@@ -118,13 +118,26 @@ import com.sun.opengl.impl.*;
public class Threading {
private static boolean singleThreaded = true;
+ private static final int AWT = 1;
+ private static final int WORKER = 2;
+ private static int mode = AWT;
static {
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
String workaround = System.getProperty("opengl.1thread");
- if (workaround != null && (!workaround.equals("auto"))) {
- singleThreaded = Boolean.valueOf(workaround).booleanValue();
+ if (workaround != null) {
+ workaround = workaround.toLowerCase();
+ if (workaround.equals("true") ||
+ workaround.equals("auto") ||
+ workaround.equals("awt")) {
+ // Nothing to do; default = singleThreaded, mode = AWT
+ } else if (workaround.equals("worker")) {
+ singleThreaded = true;
+ mode = WORKER;
+ } else {
+ singleThreaded = false;
+ }
}
printWorkaroundNotice();
return null;
@@ -170,16 +183,23 @@ public class Threading {
throw new GLException("Should only call this in single-threaded mode");
}
- if (Java2D.isOGLPipelineActive()) {
- // FIXME: ideally only the QFT would be considered to be the
- // "OpenGL thread", but we can not currently run all of JOGL's
- // OpenGL work on that thread. For now, run the GLJPanel's
- // Java2D/JOGL bridge on the QFT but everything else on the
- // EDT, except when we're already on the QFT.
- return (Java2D.isQueueFlusherThread() ||
- EventQueue.isDispatchThread());
- } else {
- return EventQueue.isDispatchThread();
+ switch (mode) {
+ case AWT:
+ if (Java2D.isOGLPipelineActive()) {
+ // FIXME: ideally only the QFT would be considered to be the
+ // "OpenGL thread", but we can not currently run all of JOGL's
+ // OpenGL work on that thread. For now, run the GLJPanel's
+ // Java2D/JOGL bridge on the QFT but everything else on the
+ // EDT, except when we're already on the QFT.
+ return (Java2D.isQueueFlusherThread() ||
+ EventQueue.isDispatchThread());
+ } else {
+ return EventQueue.isDispatchThread();
+ }
+ case WORKER:
+ return GLWorkerThread.isWorkerThread();
+ default:
+ throw new InternalError("Illegal single-threading mode " + mode);
}
}
@@ -201,28 +221,48 @@ public class Threading {
throw new GLException ("Should only call this from other threads than the OpenGL thread");
}
- // FIXME: ideally should run all OpenGL work on the Java2D QFT
- // thread when it's enabled, but there are issues with this when
- // the GLJPanel is not using the Java2D bridge; would like to run
- // its OpenGL work on the QFT, but do the image drawing from the
- // EDT. Other issues still remain with the GLCanvas as well.
-
- // if (Java2D.isOGLPipelineActive()) {
- // Java2D.invokeWithOGLContextCurrent(null, r);
- // } else {
- try {
- EventQueue.invokeAndWait(r);
- } catch (InvocationTargetException e) {
- throw new GLException(e.getTargetException());
- } catch (InterruptedException e) {
- throw new GLException(e);
+ switch (mode) {
+ case AWT:
+ // FIXME: ideally should run all OpenGL work on the Java2D QFT
+ // thread when it's enabled, but there are issues with this when
+ // the GLJPanel is not using the Java2D bridge; would like to run
+ // its OpenGL work on the QFT, but do the image drawing from the
+ // EDT. Other issues still remain with the GLCanvas as well.
+
+ // if (Java2D.isOGLPipelineActive()) {
+ // Java2D.invokeWithOGLContextCurrent(null, r);
+ // } else {
+ try {
+ EventQueue.invokeAndWait(r);
+ } catch (InvocationTargetException e) {
+ throw new GLException(e.getTargetException());
+ } catch (InterruptedException e) {
+ throw new GLException(e);
+ }
+ // }
+ break;
+
+ case WORKER:
+ if (!GLWorkerThread.isStarted()) {
+ synchronized (GLWorkerThread.class) {
+ if (!GLWorkerThread.isStarted()) {
+ GLWorkerThread.start();
+ }
+ }
+ }
+ GLWorkerThread.invokeAndWait(r);
+ break;
+
+ default:
+ throw new InternalError("Illegal single-threading mode " + mode);
}
- // }
}
private static void printWorkaroundNotice() {
if (singleThreaded && Debug.verbose()) {
- System.err.println("Using single thread for performing OpenGL work in javax.media.opengl implementation");
+ System.err.println("Using " +
+ (mode == AWT ? "AWT" : "OpenGL worker") +
+ " thread for performing OpenGL work in javax.media.opengl implementation");
}
}
}