aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/classes/com/sun/opengl/impl/GLContextImpl.java45
-rw-r--r--src/classes/com/sun/opengl/impl/GLContextShareSet.java34
-rwxr-xr-xsrc/classes/com/sun/opengl/impl/GLObjectTracker.java127
-rw-r--r--src/classes/javax/media/opengl/GLJPanel.java3
4 files changed, 175 insertions, 34 deletions
diff --git a/src/classes/com/sun/opengl/impl/GLContextImpl.java b/src/classes/com/sun/opengl/impl/GLContextImpl.java
index 4a6885f45..8e38ec276 100644
--- a/src/classes/com/sun/opengl/impl/GLContextImpl.java
+++ b/src/classes/com/sun/opengl/impl/GLContextImpl.java
@@ -61,6 +61,9 @@ public abstract class GLContextImpl extends GLContext {
// Tracks creation and deletion of server-side OpenGL objects when
// the Java2D/OpenGL pipeline is active and using FBOs to render
private GLObjectTracker tracker;
+ // Supports deletion of these objects when no other context is
+ // current which can support immediate deletion of them
+ private GLObjectTracker deletedObjectTracker;
protected GL gl;
public GLContextImpl(GLContext shareWith) {
@@ -77,7 +80,11 @@ public abstract class GLContextImpl extends GLContext {
if (shareContext != null) {
GLContextShareSet.registerSharing(this, shareContext);
}
- GLContextShareSet.registerForObjectTracking(shareWith, this);
+ // Always indicate real behind-the-scenes sharing to track deleted objects
+ if (shareContext == null) {
+ shareContext = Java2D.filterShareContext(shareWith);
+ }
+ GLContextShareSet.registerForObjectTracking(shareWith, this, shareContext);
}
public int makeCurrent() throws GLException {
@@ -119,6 +126,12 @@ public abstract class GLContextImpl extends GLContext {
lock.unlock();
} else {
setCurrent(this);
+
+ // Try cleaning up any stale server-side OpenGL objects
+ // FIXME: not sure what to do here if this throws
+ if (deletedObjectTracker != null) {
+ deletedObjectTracker.clean(getGL());
+ }
}
return res;
}
@@ -151,23 +164,11 @@ public abstract class GLContextImpl extends GLContext {
// If we are tracking creation and destruction of server-side
// OpenGL objects, we must decrement the reference count of the
// GLObjectTracker upon context destruction.
- try {
- int res = makeCurrent();
- if (res != CONTEXT_CURRENT) {
- // FIXME: we really need to behave better than this
- throw new GLException("Unable to make context current to destroy tracked server-side OpenGL objects");
- }
- try {
- tracker.unref(getGL());
- } finally {
- release();
- }
- } catch (GLException e) {
- // FIXME: should probably do something more intelligent here
- if (DEBUG) {
- e.printStackTrace();
- }
- }
+ //
+ // Note that we can only eagerly delete these server-side
+ // objects if there is another context currrent right now
+ // which shares textures and display lists with this one.
+ tracker.unref(deletedObjectTracker);
}
}
@@ -352,6 +353,14 @@ public abstract class GLContextImpl extends GLContext {
return tracker;
}
+ public void setDeletedObjectTracker(GLObjectTracker deletedObjectTracker) {
+ this.deletedObjectTracker = deletedObjectTracker;
+ }
+
+ public GLObjectTracker getDeletedObjectTracker() {
+ return deletedObjectTracker;
+ }
+
public boolean hasWaiters() {
return lock.hasWaiters();
}
diff --git a/src/classes/com/sun/opengl/impl/GLContextShareSet.java b/src/classes/com/sun/opengl/impl/GLContextShareSet.java
index 20a9364fb..293402899 100644
--- a/src/classes/com/sun/opengl/impl/GLContextShareSet.java
+++ b/src/classes/com/sun/opengl/impl/GLContextShareSet.java
@@ -52,6 +52,7 @@ import javax.media.opengl.*;
public class GLContextShareSet {
private static boolean forceTracking = Debug.isPropertyDefined("jogl.glcontext.forcetracking");
+ private static final boolean DEBUG = Debug.debug("GLContextShareSet");
// This class is implemented with a WeakHashMap that goes from the
// contexts as keys to a complex data structure as value that tracks
@@ -157,7 +158,8 @@ public class GLContextShareSet {
before any server-side OpenGL objects have been created in that
context. */
public static synchronized void registerForObjectTracking(GLContext olderContextOrNull,
- GLContext newContext) {
+ GLContext newContext,
+ GLContext realShareContext) {
if (isObjectTrackingEnabled() || isObjectTrackingDebuggingEnabled()) {
if (olderContextOrNull != null &&
newContext != null) {
@@ -170,6 +172,36 @@ public class GLContextShareSet {
GLContextImpl impl1 = (GLContextImpl) olderContextOrNull;
GLContextImpl impl2 = (GLContextImpl) newContext;
GLObjectTracker tracker = null;
+
+ GLObjectTracker deletedObjectTracker = null;
+ GLContextImpl shareImpl = (GLContextImpl) realShareContext;
+ // Before we zap the "user-level" object trackers, make sure
+ // that all contexts in the share set share the destroyed object
+ // tracker
+ if (shareImpl != null) {
+ deletedObjectTracker = shareImpl.getDeletedObjectTracker();
+ }
+ if (deletedObjectTracker == null) {
+ // Must create one and possibly set it up in the older context
+ deletedObjectTracker = new GLObjectTracker();
+ if (DEBUG) {
+ System.err.println("Created deletedObjectTracker " + deletedObjectTracker + " because " +
+ ((shareImpl == null) ? "shareImpl was null" : "shareImpl's (" + shareImpl + ") deletedObjectTracker was null"));
+ }
+
+ if (shareImpl != null) {
+ // FIXME: think should really assert in this case
+ shareImpl.setDeletedObjectTracker(deletedObjectTracker);
+ if (DEBUG) {
+ System.err.println("Set deletedObjectTracker " + deletedObjectTracker + " in shareImpl context " + shareImpl);
+ }
+ }
+ }
+ impl2.setDeletedObjectTracker(deletedObjectTracker);
+ if (DEBUG) {
+ System.err.println("Set deletedObjectTracker " + deletedObjectTracker + " in impl2 context " + impl2);
+ }
+
// Don't share object trackers with the primordial share context from Java2D
if (Java2D.isOGLPipelineActive()) {
// FIXME: probably need to do something different here
diff --git a/src/classes/com/sun/opengl/impl/GLObjectTracker.java b/src/classes/com/sun/opengl/impl/GLObjectTracker.java
index 663a7df70..dec7892de 100755
--- a/src/classes/com/sun/opengl/impl/GLObjectTracker.java
+++ b/src/classes/com/sun/opengl/impl/GLObjectTracker.java
@@ -402,22 +402,96 @@ public class GLObjectTracker {
remove(getList(VERTEX_SHADERS_EXT), obj, 1);
}
+ //----------------------------------------------------------------------
+ // Reference count maintenance and manual deletion
+ //
+
+ public synchronized void transferAll(GLObjectTracker other) {
+ for (int i = 0; i < lists.length; i++) {
+ getList(i).addAll(other.lists[i]);
+ if (other.lists[i] != null) {
+ other.lists[i].clear();
+ }
+ }
+ dirty = true;
+ }
+
public synchronized void ref() {
++refCount;
}
- public synchronized void unref(GL gl) {
- if (--refCount == 0) {
- for (int i = 0; i < lists.length; i++) {
- ObjectList list = lists[i];
- if (list != null) {
- list.delete(gl);
- lists[i] = null;
+ public void unref(GLObjectTracker deletedObjectPool) {
+ boolean tryDelete = false;
+ synchronized (this) {
+ if (--refCount == 0) {
+ tryDelete = true;
+ }
+ }
+ if (tryDelete) {
+ // See whether we should try to do the work now or whether we
+ // have to postpone
+ GLContext cur = GLContext.getCurrent();
+ if ((cur != null) &&
+ (cur instanceof GLContextImpl)) {
+ GLContextImpl curImpl = (GLContextImpl) cur;
+ if (deletedObjectPool != null &&
+ deletedObjectPool == curImpl.getDeletedObjectTracker()) {
+ // Should be safe to delete these objects now
+ try {
+ delete(curImpl.getGL());
+ return;
+ } catch (GLException e) {
+ // Shouldn't happen, but if it does, transfer all objects
+ // to the deleted object pool hoping we can later clean
+ // them up
+ deletedObjectPool.transferAll(this);
+ throw(e);
+ }
+ }
+ }
+ // If we get here, we couldn't attempt to delete the objects
+ // right now; instead try to transfer them to the
+ // deletedObjectPool for later cleanup (FIXME: should consider
+ // throwing an exception if deletedObjectPool is null, since
+ // that shouldn't happen)
+ if (DEBUG) {
+ String s = null;
+ if (cur == null) {
+ s = "current context was null";
+ } else if (!(cur instanceof GLContextImpl)) {
+ s = "current context was not a GLContextImpl";
+ } else if (deletedObjectPool == null) {
+ s = "no current deletedObjectPool";
+ } else if (deletedObjectPool != ((GLContextImpl) cur).getDeletedObjectTracker()) {
+ s = "deletedObjectTracker didn't match";
+ if (((GLContextImpl) cur).getDeletedObjectTracker() == null) {
+ s += " (other was null)";
+ }
+ } else {
+ s = "unknown reason";
}
+ System.err.println("Deferred destruction of server-side OpenGL objects into " + deletedObjectPool + ": " + s);
+ }
+
+ if (deletedObjectPool != null) {
+ deletedObjectPool.transferAll(this);
+ }
+ }
+ }
+
+ public void clean(GL gl) {
+ if (dirty) {
+ try {
+ delete(gl);
+ dirty = false;
+ } catch (GLException e) {
+ // FIXME: not sure what to do here; probably a bad idea to be
+ // throwing exceptions during an otherwise-successful makeCurrent
}
}
}
+
//----------------------------------------------------------------------
// Internals only below this point
//
@@ -459,8 +533,7 @@ public class GLObjectTracker {
public ObjectList(Deleter deleter) {
this.deleter = deleter;
- capacity = MIN_CAPACITY;
- data = new int[capacity];
+ clear();
}
public void add(int obj) {
@@ -475,6 +548,15 @@ public class GLObjectTracker {
data[size++] = obj;
}
+ public void addAll(ObjectList other) {
+ if (other == null) {
+ return;
+ }
+ for (int i = 0; i < other.size; i++) {
+ add(other.data[i]);
+ }
+ }
+
public boolean remove(int value) {
for (int i = 0; i < size; i++) {
if (data[i] == value) {
@@ -506,19 +588,30 @@ public class GLObjectTracker {
}
public void delete(GL gl) {
- for (int i = 0; i < size; i++) {
+ // Just in case we start throwing exceptions during deletion,
+ // make sure we make progress rather than going into an infinite
+ // loop
+ while (size > 0) {
+ int obj = data[size - 1];
+ --size;
if (DEBUG) {
- System.err.println("Deleting server-side OpenGL object " + data[i] +
+ System.err.println("Deleting server-side OpenGL object " + obj +
((name != null) ? (" (" + name + ")") : ""));
}
- deleter.delete(gl, data[i]);
+ deleter.delete(gl, obj);
}
+ }
+
+ public void clear() {
size = 0;
+ capacity = MIN_CAPACITY;
+ data = new int[capacity];
}
}
private ObjectList[] lists = new ObjectList[NUM_OBJECT_TYPES];
private int refCount;
+ private boolean dirty;
private void add(ObjectList list, int n, IntBuffer ids) {
int pos = ids.position();
@@ -727,4 +820,14 @@ public class GLObjectTracker {
}
return list;
}
+
+ private void delete(GL gl) {
+ for (int i = 0; i < lists.length; i++) {
+ ObjectList list = lists[i];
+ if (list != null) {
+ list.delete(gl);
+ lists[i] = null;
+ }
+ }
+ }
}
diff --git a/src/classes/javax/media/opengl/GLJPanel.java b/src/classes/javax/media/opengl/GLJPanel.java
index 8d9b3c851..445ea3c4d 100644
--- a/src/classes/javax/media/opengl/GLJPanel.java
+++ b/src/classes/javax/media/opengl/GLJPanel.java
@@ -506,13 +506,10 @@ public class GLJPanel extends JPanel implements GLAutoDrawable {
if (curSurface != null) {
if (j2dSurface != curSurface) {
if (joglContext != null) {
- // Note that the following operation may make the
- // joglContext current briefly
joglContext.destroy();
joglContext = null;
joglDrawable = null;
sendReshape = true;
- j2dContext.makeCurrent();
if (DEBUG) {
System.err.println("Sending reshape because surface changed");
System.err.println("New surface = " + curSurface);