summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/classes/com/sun/opengl/impl/GLContextImpl.java6
-rw-r--r--src/classes/com/sun/opengl/impl/GLContextShareSet.java110
-rwxr-xr-xsrc/classes/com/sun/opengl/impl/Java2D.java104
-rwxr-xr-xsrc/classes/com/sun/opengl/impl/windows/WindowsExternalGLContext.java3
-rw-r--r--src/classes/javax/media/opengl/GLJPanel.java57
5 files changed, 227 insertions, 53 deletions
diff --git a/src/classes/com/sun/opengl/impl/GLContextImpl.java b/src/classes/com/sun/opengl/impl/GLContextImpl.java
index 5dbf08df6..d79de9f5a 100644
--- a/src/classes/com/sun/opengl/impl/GLContextImpl.java
+++ b/src/classes/com/sun/opengl/impl/GLContextImpl.java
@@ -66,9 +66,11 @@ public abstract class GLContextImpl extends GLContext {
public GLContextImpl(GLContext shareWith) {
setGL(createGL());
functionAvailability = new FunctionAvailabilityCache(this);
- if (shareWith != null || GLContextShareSet.isObjectTrackingDebuggingEnabled()) {
- GLContextShareSet.registerSharing(this, shareWith);
+ GLContext shareContext = Java2D.filterShareContext(shareWith);
+ if (shareContext != null) {
+ GLContextShareSet.registerSharing(this, shareContext);
}
+ GLContextShareSet.registerForObjectTracking(shareWith, this);
}
public int makeCurrent() throws GLException {
diff --git a/src/classes/com/sun/opengl/impl/GLContextShareSet.java b/src/classes/com/sun/opengl/impl/GLContextShareSet.java
index b0d1b1da4..283a56f85 100644
--- a/src/classes/com/sun/opengl/impl/GLContextShareSet.java
+++ b/src/classes/com/sun/opengl/impl/GLContextShareSet.java
@@ -62,17 +62,6 @@ public class GLContextShareSet {
private Map createdShares = new WeakHashMap();
private Map destroyedShares = new WeakHashMap();
- // When the Java2D/OpenGL pipeline is active and using FBOs to
- // render, we need to track the creation and destruction of
- // server-side OpenGL objects among contexts sharing these objects
- private GLObjectTracker tracker;
-
- public ShareSet() {
- if (isObjectTrackingEnabled()) {
- tracker = new GLObjectTracker();
- }
- }
-
public void add(GLContext ctx) {
if (allShares.put(ctx, dummyValue) == null) {
// FIXME: downcast to GLContextImpl undesirable
@@ -111,57 +100,26 @@ public class GLContextShareSet {
assert res == null : "State of ShareSet corrupted; thought context " +
ctx + " shouldn't have been in destroyed set but was";
}
-
- public GLObjectTracker getObjectTracker() {
- return tracker;
- }
- }
-
- private static boolean isObjectTrackingEnabled() {
- return (Java2D.isOGLPipelineActive() && Java2D.isFBOEnabled());
- }
-
- /** Indicates to callers whether sharing must be registered even for
- contexts which don't share textures and display lists with any
- others. */
- public static boolean isObjectTrackingDebuggingEnabled() {
- return forceTracking;
}
/** Indicate that contexts <code>share1</code> and
- <code>share2</code> will share textures and display lists. */
+ <code>share2</code> will share textures and display lists. Both
+ must be non-null. */
public static synchronized void registerSharing(GLContext share1, GLContext share2) {
+ if (share1 == null || share2 == null) {
+ throw new IllegalArgumentException("Both share1 and share2 must be non-null");
+ }
ShareSet share = entryFor(share1);
- if (share == null && (share2 != null)) {
+ if (share == null) {
share = entryFor(share2);
}
if (share == null) {
share = new ShareSet();
}
share.add(share1);
- if (share2 != null) {
- share.add(share2);
- }
+ share.add(share2);
addEntry(share1, share);
- if (share2 != null) {
- addEntry(share2, share);
- }
- GLObjectTracker tracker = share.getObjectTracker();
- if (tracker != null) {
- // FIXME: downcast to GLContextImpl undesirable
- GLContextImpl impl1 = (GLContextImpl) share1;
- GLContextImpl impl2 = (GLContextImpl) share2;
- if (impl1.getObjectTracker() == null) {
- impl1.setObjectTracker(tracker);
- }
- if ((impl2 != null) && (impl2.getObjectTracker() == null)) {
- impl2.setObjectTracker(tracker);
- }
- assert impl1.getObjectTracker() == tracker : "State of ShareSet corrupted; " +
- "got different-than-expected GLObjectTracker for context 1";
- assert (impl2 == null) || (impl2.getObjectTracker() == tracker) : "State of ShareSet corrupted; " +
- "got different-than-expected GLObjectTracker for context 2";
- }
+ addEntry(share2, share);
}
public static synchronized GLContext getShareContext(GLContext contextToCreate) {
@@ -186,6 +144,49 @@ public class GLContextShareSet {
}
}
+ /** Indicates that the two supplied contexts (which must be able to
+ share textures and display lists) should be in the same
+ namespace for tracking of server-side object creation and
+ deletion. Because the sharing necessary behind the scenes is
+ different than that requested at the user level, the two notions
+ are different. This must be called immediately after the
+ creation of the new context (which is the second argument)
+ before any server-side OpenGL objects have been created in that
+ context. */
+ public static synchronized void registerForObjectTracking(GLContext olderContextOrNull,
+ GLContext newContext) {
+ if (isObjectTrackingEnabled() || isObjectTrackingDebuggingEnabled()) {
+ if (olderContextOrNull != null &&
+ newContext != null) {
+ if (entryFor(olderContextOrNull) != entryFor(newContext)) {
+ throw new IllegalArgumentException("old and new contexts must be able to share textures and display lists");
+ }
+ }
+
+ // FIXME: downcast to GLContextImpl undesirable
+ GLContextImpl impl1 = (GLContextImpl) olderContextOrNull;
+ GLContextImpl impl2 = (GLContextImpl) newContext;
+ GLObjectTracker tracker = null;
+ // Don't share object trackers with the primordial share context from Java2D
+ GLContext j2dShareContext = Java2D.getShareContext();
+ if (impl1 != null && impl1 == j2dShareContext) {
+ impl1 = null;
+ }
+ if (impl1 != null) {
+ tracker = impl1.getObjectTracker();
+ assert (tracker != null)
+ : "registerForObjectTracking was not called properly for the older context";
+ }
+ if (tracker == null) {
+ tracker = new GLObjectTracker();
+ }
+ // Note that we don't assert that the tracker is non-null for
+ // impl2 because the way we use this functionality we actually
+ // overwrite the initially-set object tracker in the new context
+ impl2.setObjectTracker(tracker);
+ }
+ }
+
//----------------------------------------------------------------------
// Internals only below this point
//
@@ -199,4 +200,13 @@ public class GLContextShareSet {
shareMap.put(context, share);
}
}
+
+ private static boolean isObjectTrackingEnabled() {
+ return ((Java2D.isOGLPipelineActive() && Java2D.isFBOEnabled()) ||
+ isObjectTrackingDebuggingEnabled());
+ }
+
+ private static boolean isObjectTrackingDebuggingEnabled() {
+ return forceTracking;
+ }
}
diff --git a/src/classes/com/sun/opengl/impl/Java2D.java b/src/classes/com/sun/opengl/impl/Java2D.java
index c3eaa3b7c..cf9e8ff1e 100755
--- a/src/classes/com/sun/opengl/impl/Java2D.java
+++ b/src/classes/com/sun/opengl/impl/Java2D.java
@@ -40,6 +40,7 @@
package com.sun.opengl.impl;
import java.awt.*;
+import java.awt.image.*;
import java.lang.reflect.*;
import java.security.*;
@@ -59,6 +60,18 @@ public class Java2D {
private static Method getOGLScissorBoxMethod;
private static Method getOGLSurfaceIdentifierMethod;
+ // If FBOs are enabled in the Java2D/OpenGL pipeline, all contexts
+ // created by JOGL must share textures and display lists with the
+ // Java2D contexts in order to access the frame buffer object for
+ // potential rendering, and to simultaneously support sharing of
+ // textures and display lists with one another. Java2D has the
+ // notion of a single shared context with which all other contexts
+ // (on the same display device?) share textures and display lists;
+ // this is an approximation to that notion which will be refined
+ // later.
+ private static VolatileImage j2dFBOVolatileImage; // just a dummy image
+ private static GLContext j2dFBOShareContext;
+
static {
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
@@ -174,6 +187,12 @@ public class Java2D {
}
}
+ /** Returns the OpenGL viewport associated with the given Graphics
+ object, assuming that the Graphics object is associated with a
+ component of the specified width and height. The user should
+ call glViewport() with the returned rectangle's bounds in order
+ to get correct rendering results. Should only be called from the
+ Queue Flusher Thread. */
public static Rectangle getOGLViewport(Graphics g,
int componentWidth,
int componentHeight) {
@@ -192,6 +211,12 @@ public class Java2D {
}
}
+ /** Returns the OpenGL scissor region associated with the given
+ Graphics object, taking into account all clipping regions, etc.
+ To avoid destroying Java2D's previous rendering results, this
+ method should be called and the resulting rectangle's bounds
+ passed to a call to glScissor(). Should only be called from the
+ Queue Flusher Thread. */
public static Rectangle getOGLScissorBox(Graphics g) {
if (!isOGLPipelineActive()) {
throw new GLException("Java2D OpenGL pipeline not active (or necessary support not present)");
@@ -206,7 +231,12 @@ public class Java2D {
}
}
-
+ /** Returns an opaque "surface identifier" associated with the given
+ Graphics object. If this changes from invocation to invocation,
+ the underlying OpenGL drawable for the Graphics object has
+ changed and a new external GLDrawable and GLContext should be
+ created (and the old ones destroyed). Should only be called from
+ the Queue Flusher Thread.*/
public static Object getOGLSurfaceIdentifier(Graphics g) {
if (!isOGLPipelineActive()) {
throw new GLException("Java2D OpenGL pipeline not active (or necessary support not present)");
@@ -220,4 +250,76 @@ public class Java2D {
throw (InternalError) new InternalError().initCause(e);
}
}
+
+ /** Returns either the given GLContext or a substitute one with
+ which clients should share textures and display lists. Needed
+ when the Java2D/OpenGL pipeline is active and FBOs are being
+ used for rendering. FIXME: may need to alter the API in the
+ future to indicate which GraphicsDevice the source context is
+ associated with. */
+ public static GLContext filterShareContext(GLContext shareContext) {
+ initFBOShareContext();
+ if (j2dFBOShareContext != null) {
+ return j2dFBOShareContext;
+ }
+ return shareContext;
+ }
+
+ /** Returns the GLContext associated with the Java2D "share
+ context", with which all contexts created by JOGL must share
+ textures and display lists when the FBO option is enabled for
+ the Java2D/OpenGL pipeline. */
+ public static GLContext getShareContext() {
+ initFBOShareContext();
+ return j2dFBOShareContext;
+ }
+
+ //----------------------------------------------------------------------
+ // Internals only below this point
+ //
+
+ private static void initFBOShareContext() {
+ // Note 1: this must not be done in the static initalizer due to
+ // deadlock problems.
+
+ // Note 2: the first execution of this method must not be from the
+ // Java2D Queue Flusher Thread.
+
+ // Note that at this point it's basically impossible that we're
+ // executing on the Queue Flusher Thread since all calls (even
+ // from end users) should be going through this interface and
+ // we're still in the static initializer
+ if (isOGLPipelineActive() &&
+ isFBOEnabled() &&
+ j2dFBOVolatileImage == null) {
+ // Create a compatible VolatileImage (FIXME: may need one per
+ // display device, and may need to create them lazily, which may
+ // cause problems) and create a JOGL GLContext to wrap its
+ // GLContext.
+ //
+ // FIXME: this technique is not really adequate. The
+ // VolatileImage may be punted at any time, meaning that its
+ // OpenGL context will be destroyed and any shares of
+ // server-side objects with it will be gone. This context is
+ // currently the "pinch point" through which all of the shares
+ // with the set of contexts created by JOGL go through. Java2D
+ // has the notion of its own share context with which all of the
+ // contexts it creates internally share server-side objects;
+ // what is really needed is another API in OGLUtilities to
+ // invoke a Runnable with that share context current rather than
+ // the context associated with a particular Graphics object, so
+ // that JOGL can grab a handle to that persistent context.
+ j2dFBOVolatileImage =
+ GraphicsEnvironment.
+ getLocalGraphicsEnvironment().
+ getDefaultScreenDevice().
+ getDefaultConfiguration().
+ createCompatibleVolatileImage(2, 2);
+ invokeWithOGLContextCurrent(j2dFBOVolatileImage.getGraphics(), new Runnable() {
+ public void run() {
+ j2dFBOShareContext = GLDrawableFactory.getFactory().createExternalGLContext();
+ }
+ });
+ }
+ }
}
diff --git a/src/classes/com/sun/opengl/impl/windows/WindowsExternalGLContext.java b/src/classes/com/sun/opengl/impl/windows/WindowsExternalGLContext.java
index 694aa6b0d..a12f156f5 100755
--- a/src/classes/com/sun/opengl/impl/windows/WindowsExternalGLContext.java
+++ b/src/classes/com/sun/opengl/impl/windows/WindowsExternalGLContext.java
@@ -51,6 +51,9 @@ public class WindowsExternalGLContext extends WindowsGLContext {
public WindowsExternalGLContext() {
super(null, null);
hglrc = WGL.wglGetCurrentContext();
+ if (DEBUG) {
+ System.err.println(getThreadName() + ": !!! Created external OpenGL context " + toHexString(hglrc) + " for " + this);
+ }
GLContextShareSet.contextCreated(this);
resetGLFunctionAvailability();
}
diff --git a/src/classes/javax/media/opengl/GLJPanel.java b/src/classes/javax/media/opengl/GLJPanel.java
index ad5a7f769..1dd204239 100644
--- a/src/classes/javax/media/opengl/GLJPanel.java
+++ b/src/classes/javax/media/opengl/GLJPanel.java
@@ -80,6 +80,10 @@ public class GLJPanel extends JPanel implements GLAutoDrawable {
private static final boolean DEBUG = Debug.debug("GLJPanel");
private static final boolean VERBOSE = Debug.verbose();
+ // FIXME: remove these once debugging is done
+ private static final boolean HACK1 = Debug.debug("GLJPanel.hack1");
+ private static final boolean HACK2 = Debug.debug("GLJPanel.hack2");
+
private GLDrawableHelper drawableHelper = new GLDrawableHelper();
private volatile boolean isInitialized;
private volatile boolean shouldInitialize = false;
@@ -159,11 +163,23 @@ public class GLJPanel extends JPanel implements GLAutoDrawable {
// properly render into Java2D back buffer
private int[] drawBuffer = new int[1];
private int[] readBuffer = new int[1];
+ // This is required when the FBO option of the Java2D / OpenGL
+ // pipeline is active
+ private int[] frameBuffer = new int[1];
// These are always set to (0, 0) except when the Java2D / OpenGL
// pipeline is active
private int viewportX;
private int viewportY;
+ static {
+ // Force eager initialization of part of the Java2D class since
+ // otherwise it's likely it will try to be initialized while on
+ // the Queue Flusher Thread, which is not allowed
+ if (Java2D.isOGLPipelineActive() && Java2D.isFBOEnabled()) {
+ Java2D.getShareContext();
+ }
+ }
+
/** Creates a new GLJPanel component with a default set of OpenGL
capabilities and using the default OpenGL capabilities selection
mechanism. */
@@ -220,6 +236,9 @@ public class GLJPanel extends JPanel implements GLAutoDrawable {
private void captureJ2DState(GL gl) {
gl.glGetIntegerv(GL.GL_DRAW_BUFFER, drawBuffer, 0);
gl.glGetIntegerv(GL.GL_READ_BUFFER, readBuffer, 0);
+ if (Java2D.isFBOEnabled()) {
+ gl.glGetIntegerv(GL.GL_FRAMEBUFFER_BINDING_EXT, frameBuffer, 0);
+ }
}
private boolean preGL(Graphics g) {
@@ -249,6 +268,22 @@ public class GLJPanel extends JPanel implements GLAutoDrawable {
gl.glDrawBuffer(drawBuffer[0]);
gl.glReadBuffer(readBuffer[0]);
+
+ // If the FBO option is active, bind to the FBO from the Java2D
+ // context.
+ // Note that all of the plumbing in the context sharing stuff will
+ // allow us to bind to this object since it's in our namespace.
+ if (Java2D.isFBOEnabled()) {
+ if (DEBUG && VERBOSE) {
+ System.err.println("Binding to framebuffer object " + frameBuffer[0]);
+ }
+
+ gl.glBindTexture(GL.GL_TEXTURE_2D, 0);
+ gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, frameBuffer[0]);
+ // FIXME: do we need to do anything else? Bind Texture2D state
+ // or something else?
+ }
+
return true;
}
@@ -346,6 +381,28 @@ public class GLJPanel extends JPanel implements GLAutoDrawable {
joglDrawable = GLDrawableFactory.getFactory().createExternalGLDrawable();
joglContext = joglDrawable.createContext(shareWith);
}
+
+ // FIXME: remove these once debugging is done
+ if (HACK1) {
+ // Skip all GLContext manipulation This fixes the
+ // display of the icons and text (done with Java2D)
+ // in the JGears demo when FBO is active
+ return;
+ }
+ if (HACK2) {
+ // Do a little GLContext manipulation but skip all
+ // FBO-related manipulation and other stuff (as well
+ // as the user rendering).
+
+ // Note that the icons and text in the JGears demo
+ // disappear when this flag is used, so clearly any
+ // OpenGL context manipulation is messing up the
+ // Java2D context state when FBO is active.
+ joglContext.makeCurrent();
+ joglContext.release();
+ return;
+ }
+
drawableHelper.invokeGL(joglDrawable, joglContext, displayAction, initAction);
}
} finally {