aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/classes/com/sun/opengl/impl/GLContextImpl.java10
-rw-r--r--src/classes/com/sun/opengl/impl/GLContextLock.java8
-rwxr-xr-xsrc/classes/com/sun/opengl/impl/GLWorkerThread.java79
3 files changed, 84 insertions, 13 deletions
diff --git a/src/classes/com/sun/opengl/impl/GLContextImpl.java b/src/classes/com/sun/opengl/impl/GLContextImpl.java
index a4eee6652..4a6885f45 100644
--- a/src/classes/com/sun/opengl/impl/GLContextImpl.java
+++ b/src/classes/com/sun/opengl/impl/GLContextImpl.java
@@ -96,6 +96,12 @@ public abstract class GLContextImpl extends GLContext {
}
}
+ if (GLWorkerThread.isStarted() &&
+ !GLWorkerThread.isWorkerThread()) {
+ // Kick the GLWorkerThread off its current context
+ GLWorkerThread.invokeLater(new Runnable() { public void run() {} });
+ }
+
lock.lock();
int res = 0;
try {
@@ -345,4 +351,8 @@ public abstract class GLContextImpl extends GLContext {
public GLObjectTracker getObjectTracker() {
return tracker;
}
+
+ public boolean hasWaiters() {
+ return lock.hasWaiters();
+ }
}
diff --git a/src/classes/com/sun/opengl/impl/GLContextLock.java b/src/classes/com/sun/opengl/impl/GLContextLock.java
index 9fb4d66e5..753ef14f8 100644
--- a/src/classes/com/sun/opengl/impl/GLContextLock.java
+++ b/src/classes/com/sun/opengl/impl/GLContextLock.java
@@ -52,6 +52,7 @@ public class GLContextLock {
private Object lock = new Object();
private Thread owner;
private boolean failFastMode = true;
+ private volatile int waiters;
/** Locks this GLContextLock on the current thread. If fail fast
mode is enabled and the GLContextLock is already owned by
@@ -68,9 +69,12 @@ public class GLContextLock {
" which is already current on thread " + owner);
} else {
try {
+ ++waiters;
lock.wait();
} catch (InterruptedException e) {
throw new GLException(e);
+ } finally {
+ --waiters;
}
}
}
@@ -115,4 +119,8 @@ public class GLContextLock {
public boolean getFailFastMode() {
return failFastMode;
}
+
+ public boolean hasWaiters() {
+ return (waiters != 0);
+ }
}
diff --git a/src/classes/com/sun/opengl/impl/GLWorkerThread.java b/src/classes/com/sun/opengl/impl/GLWorkerThread.java
index 4091d1a77..57938c8bc 100755
--- a/src/classes/com/sun/opengl/impl/GLWorkerThread.java
+++ b/src/classes/com/sun/opengl/impl/GLWorkerThread.java
@@ -41,6 +41,7 @@ package com.sun.opengl.impl;
import java.lang.reflect.InvocationTargetException;
import java.security.*;
+import java.util.*;
import javax.media.opengl.*;
/** Singleton thread upon which all OpenGL work is performed by
@@ -61,9 +62,10 @@ public class GLWorkerThread {
private static volatile boolean shouldTerminate;
private static volatile Throwable exception;
- // The Runnable to execute on the worker thread -- no need for a
- // queue since we don't have an invokeLater() primitive
+ // 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();
/** Should only be called by Threading class if creation of the
GLWorkerThread was requested via the opengl.1thread system
@@ -162,14 +164,35 @@ public class GLWorkerThread {
}
work = runnable;
- lock.notifyAll();
- lock.wait();
+ lockTemp.notifyAll();
+ lockTemp.wait();
if (exception != null) {
throw new InvocationTargetException(exception);
}
}
}
+ public static void invokeLater(Runnable runnable) {
+ if (!started) {
+ throw new RuntimeException("May not invokeLater on worker thread without starting it first");
+ }
+
+ Object lockTemp = lock;
+ if (lockTemp == null) {
+ return; // Terminating
+ }
+
+ synchronized (lockTemp) {
+ if (thread == null) {
+ // Terminating
+ return;
+ }
+
+ queue.add(runnable);
+ lockTemp.notifyAll();
+ }
+ }
+
/** Indicates whether the OpenGL worker thread was started, i.e.,
whether it is currently in use. */
public static boolean isStarted() {
@@ -191,11 +214,19 @@ public class GLWorkerThread {
while (!shouldTerminate) {
synchronized (lock) {
- while ((work == null) && !shouldTerminate) {
+ while (!shouldTerminate &&
+ (work == null) &&
+ queue.isEmpty()) {
try {
- lock.wait();
+ // Avoid race conditions with wanting to release contexts on this thread
+ lock.wait(1000);
} catch (InterruptedException e) {
}
+
+ if (GLContext.getCurrent() != null) {
+ // Test later to see whether we need to release this context
+ break;
+ }
}
if (shouldTerminate) {
@@ -205,13 +236,35 @@ public class GLWorkerThread {
return;
}
- try {
- work.run();
- } catch (Throwable t) {
- exception = t;
- } finally {
- work = null;
- lock.notifyAll();
+ if (work != null) {
+ try {
+ work.run();
+ } catch (Throwable t) {
+ exception = t;
+ } finally {
+ work = null;
+ lock.notifyAll();
+ }
+ }
+
+ while (!queue.isEmpty()) {
+ try {
+ Runnable curAsync = (Runnable) queue.remove(0);
+ curAsync.run();
+ } catch (Throwable t) {
+ System.out.println("Exception occurred on JOGL OpenGL worker thread:");
+ t.printStackTrace();
+ }
+ }
+
+ // See about releasing current context
+ GLContext curContext = GLContext.getCurrent();
+ if (curContext != null &&
+ (curContext instanceof GLContextImpl)) {
+ GLContextImpl impl = (GLContextImpl) curContext;
+ if (impl.hasWaiters()) {
+ impl.release();
+ }
}
}
}