aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/java/games
diff options
context:
space:
mode:
Diffstat (limited to 'src/net/java/games')
-rw-r--r--src/net/java/games/jogl/Animator.java44
-rwxr-xr-xsrc/net/java/games/jogl/GLAutoDrawable.java (renamed from src/net/java/games/jogl/impl/GLContextInitActionPair.java)30
-rw-r--r--src/net/java/games/jogl/GLCanvas.java54
-rwxr-xr-xsrc/net/java/games/jogl/GLContext.java156
-rw-r--r--src/net/java/games/jogl/GLDrawable.java84
-rw-r--r--src/net/java/games/jogl/GLDrawableFactory.java110
-rw-r--r--src/net/java/games/jogl/GLEventListener.java16
-rw-r--r--src/net/java/games/jogl/GLJPanel.java58
-rw-r--r--src/net/java/games/jogl/GLPbuffer.java2
-rw-r--r--src/net/java/games/jogl/impl/FunctionAvailabilityCache.java4
-rw-r--r--src/net/java/games/jogl/impl/GLContext.java764
-rwxr-xr-xsrc/net/java/games/jogl/impl/GLContextImpl.java364
-rwxr-xr-xsrc/net/java/games/jogl/impl/GLContextLock.java118
-rw-r--r--src/net/java/games/jogl/impl/GLContextShareSet.java4
-rwxr-xr-xsrc/net/java/games/jogl/impl/GLContextStack.java127
-rw-r--r--src/net/java/games/jogl/impl/GLDrawableHelper.java80
-rw-r--r--src/net/java/games/jogl/impl/GLPbufferImpl.java46
-rw-r--r--src/net/java/games/jogl/impl/macosx/MacOSXGLContext.java14
-rw-r--r--src/net/java/games/jogl/impl/macosx/MacOSXOffscreenGLContext.java6
-rw-r--r--src/net/java/games/jogl/impl/macosx/MacOSXOnscreenGLContext.java47
-rw-r--r--src/net/java/games/jogl/impl/macosx/MacOSXPbufferGLContext.java6
-rw-r--r--src/net/java/games/jogl/impl/mipmap/BuildMipmap.java65
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsGLContext.java13
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsOffscreenGLContext.java12
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsOnscreenGLContext.java48
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java6
-rw-r--r--src/net/java/games/jogl/impl/x11/X11GLContext.java22
-rw-r--r--src/net/java/games/jogl/impl/x11/X11OffscreenGLContext.java16
-rw-r--r--src/net/java/games/jogl/impl/x11/X11OnscreenGLContext.java46
-rw-r--r--src/net/java/games/jogl/impl/x11/X11PbufferGLContext.java10
30 files changed, 1070 insertions, 1302 deletions
diff --git a/src/net/java/games/jogl/Animator.java b/src/net/java/games/jogl/Animator.java
index ebb6d9aed..06fb25cca 100644
--- a/src/net/java/games/jogl/Animator.java
+++ b/src/net/java/games/jogl/Animator.java
@@ -68,11 +68,6 @@ public class Animator {
/** Creates a new Animator for a particular drawable. */
public Animator(GLDrawable drawable) {
this.drawable = drawable;
-
- // Workaround for NVidia driver bug 80174
- if (drawable instanceof GLCanvas) {
- ((GLCanvas) drawable).willSetRenderingThread();
- }
}
/** Starts this animator. */
@@ -85,23 +80,6 @@ public class Animator {
public void run() {
boolean noException = false;
try {
- // Try to get OpenGL context optimization since we know we
- // will be rendering this one drawable continually from
- // this thread; make the context current once instead of
- // making it current and freeing it each frame.
- drawable.setRenderingThread(Thread.currentThread());
-
- // Since setRenderingThread is currently advisory (because
- // of the poor JAWT implementation in the Motif AWT, which
- // performs excessive locking) we also prevent repaint(),
- // which is called from the AWT thread, from having an
- // effect for better multithreading behavior. This call is
- // not strictly necessary, but if end users write their
- // own animation loops which update multiple drawables per
- // tick then it may be necessary to enforce the order of
- // updates.
- drawable.setNoAutoRedrawMode(true);
-
while (!shouldStop) {
noException = false;
drawable.display();
@@ -109,25 +87,9 @@ public class Animator {
}
} finally {
shouldStop = false;
- drawable.setNoAutoRedrawMode(false);
- try {
- // The surface is already unlocked and rendering
- // thread is already null if an exception occurred
- // during display(), so don't disable the rendering
- // thread again.
- if (noException) {
- // Destruction of the underlying GLContext may have
- // disabled the setRenderingThread optimization out
- // from under us
- if (drawable.getRenderingThread() != null) {
- drawable.setRenderingThread(null);
- }
- }
- } finally {
- synchronized (Animator.this) {
- thread = null;
- Animator.this.notify();
- }
+ synchronized (Animator.this) {
+ thread = null;
+ Animator.this.notify();
}
}
}
diff --git a/src/net/java/games/jogl/impl/GLContextInitActionPair.java b/src/net/java/games/jogl/GLAutoDrawable.java
index 379dda3ee..2b7528069 100755
--- a/src/net/java/games/jogl/impl/GLContextInitActionPair.java
+++ b/src/net/java/games/jogl/GLAutoDrawable.java
@@ -20,7 +20,7 @@
* 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
+ * MIDROSYSTEMS, 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
@@ -37,22 +37,18 @@
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
-package net.java.games.jogl.impl;
+package net.java.games.jogl;
-public class GLContextInitActionPair {
- private GLContext ctx;
- private Runnable initAction;
+public interface GLAutoDrawable extends GLDrawable, ComponentEvents {
+ /** Adds a {@link GLEventListener} to this drawable. If multiple
+ listeners are added to a given drawable, they are notified of
+ events in an arbitrary order. */
+ public void addGLEventListener(GLEventListener listener);
- public GLContextInitActionPair(GLContext ctx, Runnable initAction) {
- this.ctx = ctx;
- this.initAction = initAction;
- }
-
- public GLContext getContext() {
- return ctx;
- }
-
- public Runnable getInitAction() {
- return initAction;
- }
+ /** Removes a {@link GLEventListener} from this drawable. Note that
+ if this is done from within a particular drawable's {@link
+ GLEventListener} handler (reshape, display, etc.) that it is not
+ guaranteed that all other listeners will be evaluated properly
+ during this update cycle. */
+ public void removeGLEventListener(GLEventListener listener);
}
diff --git a/src/net/java/games/jogl/GLCanvas.java b/src/net/java/games/jogl/GLCanvas.java
index f73a006ae..e7a15ccf9 100644
--- a/src/net/java/games/jogl/GLCanvas.java
+++ b/src/net/java/games/jogl/GLCanvas.java
@@ -43,6 +43,7 @@ import java.awt.Canvas;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
import net.java.games.jogl.impl.*;
// FIXME: Subclasses need to call resetGLFunctionAvailability() on their
@@ -57,20 +58,21 @@ import net.java.games.jogl.impl.*;
instantiated directly; use {@link GLDrawableFactory} to construct
them. */
-public final class GLCanvas extends Canvas implements GLDrawable {
+public class GLCanvas extends Canvas implements GLAutoDrawable {
protected static final boolean DEBUG = Debug.debug("GLCanvas");
private GLDrawableHelper drawableHelper = new GLDrawableHelper();
- private GLContext context;
-
- GLCanvas(GraphicsConfiguration config,
- GLCapabilities capabilities,
- GLCapabilitiesChooser chooser,
- GLDrawable shareWith) {
- super(config);
- context = GLContextFactory.getFactory().createGLContext(this, capabilities, chooser,
- GLContextHelper.getContext(shareWith));
+ private GLContextImpl context;
+
+ public GLCanvas(GLCapabilities capabilities,
+ GLCapabilitiesChooser chooser,
+ GLDrawable shareWith,
+ GraphicsDevice device) {
+ super(GLDrawableFactory.getFactory().chooseGraphicsConfiguration(capabilities, chooser, device));
+ context = (GLContextImpl) GLContextFactory.getFactory().createGLContext(this, capabilities, chooser,
+ GLContextHelper.getContext(shareWith));
+ context.setSynchronized(true);
}
public void display() {
@@ -82,9 +84,7 @@ public final class GLCanvas extends Canvas implements GLDrawable {
/** Overridden from Canvas; calls {@link #display}. Should not be
invoked by applications directly. */
public void paint(Graphics g) {
- if (!context.getNoAutoRedrawMode()) {
- display();
- }
+ display();
}
/** Overridden from Canvas; used to indicate when it's safe to
@@ -127,7 +127,7 @@ public final class GLCanvas extends Canvas implements GLDrawable {
};
final Runnable reshapeOnEDTRunnable = new Runnable() {
public void run() {
- context.invokeGL(reshapeRunnable, true, initAction);
+ drawableHelper.invokeGL(context, reshapeRunnable, true, initAction);
}
};
maybeDoSingleThreadedWorkaround(reshapeOnEDTRunnable, reshapeRunnable, true);
@@ -163,26 +163,6 @@ public final class GLCanvas extends Canvas implements GLDrawable {
context.setGLU(glu);
}
- void willSetRenderingThread() {
- context.willSetRenderingThread();
- }
-
- public void setRenderingThread(Thread currentThreadOrNull) throws GLException {
- context.setRenderingThread(currentThreadOrNull, initAction);
- }
-
- public Thread getRenderingThread() {
- return context.getRenderingThread();
- }
-
- public void setNoAutoRedrawMode(boolean noAutoRedraw) {
- context.setNoAutoRedrawMode(noAutoRedraw);
- }
-
- public boolean getNoAutoRedrawMode() {
- return context.getNoAutoRedrawMode();
- }
-
public void setAutoSwapBufferMode(boolean onOrOff) {
context.setAutoSwapBufferMode(onOrOff);
}
@@ -233,7 +213,7 @@ public final class GLCanvas extends Canvas implements GLDrawable {
throw new GLException(e);
}
} else {
- context.invokeGL(invokeGLAction, isReshape, initAction);
+ drawableHelper.invokeGL(context, invokeGLAction, isReshape, initAction);
}
}
@@ -263,14 +243,14 @@ public final class GLCanvas extends Canvas implements GLDrawable {
// being resized on the AWT event dispatch thread
class DisplayOnEventDispatchThreadAction implements Runnable {
public void run() {
- context.invokeGL(displayAction, false, initAction);
+ drawableHelper.invokeGL(context, displayAction, false, initAction);
}
}
private DisplayOnEventDispatchThreadAction displayOnEventDispatchThreadAction =
new DisplayOnEventDispatchThreadAction();
class SwapBuffersOnEventDispatchThreadAction implements Runnable {
public void run() {
- context.invokeGL(swapBuffersAction, false, initAction);
+ drawableHelper.invokeGL(context, swapBuffersAction, false, initAction);
}
}
private SwapBuffersOnEventDispatchThreadAction swapBuffersOnEventDispatchThreadAction =
diff --git a/src/net/java/games/jogl/GLContext.java b/src/net/java/games/jogl/GLContext.java
new file mode 100755
index 000000000..3e12b542c
--- /dev/null
+++ b/src/net/java/games/jogl/GLContext.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2003 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
+ * MIDROSYSTEMS, 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 net.java.games.jogl;
+
+public abstract class GLContext {
+ public static final int CONTEXT_NOT_CURRENT = 0;
+ public static final int CONTEXT_CURRENT = 1;
+ public static final int CONTEXT_CURRENT_NEW = 2;
+
+ private static ThreadLocal currentContext = new ThreadLocal();
+
+ /**
+ * Returns the GLDrawable to which this context may be used to
+ * draw.
+ */
+ // FIXME
+ // public abstract GLDrawable getGLDrawable();
+
+ /**
+ * Makes this GLContext current on the calling thread.
+ *
+ * There are two return values that indicate success and one that
+ * indicates failure. A return value of CONTEXT_CURRENT_NEW
+ * indicates that that context has been made current, and that
+ * this is the first time this context has been made current, or
+ * that the state of the underlying context or drawable may have
+ * changed since the last time this context was made current. In
+ * this case, the application may wish to initialize the state. A
+ * return value of CONTEXT_CURRENT indicates that the context has
+ * been made currrent, with its previous state restored.
+ *
+ * If the context could not be made current (for example, because
+ * the underlying drawable has not ben realized on the display) ,
+ * a value of CONTEXT_NOT_CURRENT is returned.
+ *
+ * If the context is in use by another thread at the time of the
+ * call, then if isSynchronized() is true the call will
+ * block. If isSynchronized() is false, an exception will be
+ * thrown and the context will remain current on the other thread.
+ *
+ * @return CONTEXT_CURRENT if the context was successfully made current
+ * @return CONTEXT_CURRENT_NEW if the context was successfully made
+ * current, but need to be initialized.
+ *
+ * @return CONTEXT_NOT_CURRENT if the context could not be made current.
+ *
+ * @throws GLException if synchronization is disabled and the
+ * context is current on another thread, or because the context
+ * could not be created or made current due to non-recoverable,
+ * window system-specific errors.
+ */
+ public abstract int makeCurrent() throws GLException;
+
+ /**
+ * Releases control of this GLContext from the current thread.
+ *
+ * @throw GLException if the context had not previously been made
+ * current on the current thread
+ */
+ public abstract void release() throws GLException;
+
+ /**
+ * Returns the context which is current on the current thread. If no
+ * context is current, returns null.
+ *
+ * @return the context current on this thread, or null if no context
+ * is current.
+ */
+ public static GLContext getCurrent() {
+ return (GLContext) currentContext.get();
+ }
+
+ /**
+ * Sets the current context object on the current thread. This
+ * method is called by GLContext implementations during {@link
+ * #makeCurrent} and does not need to be called by end users.
+ *
+ */
+ public static void setCurrent(GLContext cur) {
+ currentContext.set(cur);
+ }
+
+ /**
+ * For onscreen GLDrawables, indicates to the GLContext
+ * implementation that the underlying window has been created and
+ * can be drawn into.
+ */
+ public abstract void setRealized();
+
+ /**
+ * Destroys this OpenGL context and frees its associated resources.
+ * <P>
+ * For onscreen GLDrawables, should be used to indicate to the
+ * GLContext implementation that the underlying window has been
+ * destroyed.
+ */
+ public abstract void destroy();
+
+ /**
+ * Returns true if 'makeCurrent' will exhibit synchronized behavior.
+ */
+ public abstract boolean isSynchronized();
+
+ /**
+ * Determines whether 'makeCurrent' will exhibit synchronized behavior.
+ */
+ public abstract void setSynchronized(boolean isSynchronized);
+
+ // 'GL' and 'GLU' pipelines allow instrumenting the actual
+ // pipeline for debugging, tracing, etc.
+
+ public abstract GL getGL();
+
+ public abstract GLU getGLU();
+
+ public abstract void setGL(GL gl);
+
+ public abstract void setGLU(GLU glu);
+}
diff --git a/src/net/java/games/jogl/GLDrawable.java b/src/net/java/games/jogl/GLDrawable.java
index 9ca86ca79..93fa6c580 100644
--- a/src/net/java/games/jogl/GLDrawable.java
+++ b/src/net/java/games/jogl/GLDrawable.java
@@ -39,8 +39,6 @@
package net.java.games.jogl;
-import java.awt.Dimension;
-
// FIXME: We need some way to tell when the device upon which the canvas is
// being displayed has changed (e.g., the user drags the canvas's parent
// window from one screen on multi-screen environment to another, when the
@@ -67,32 +65,16 @@ import java.awt.Dimension;
GLCanvas} and {@link GLJPanel}. */
public interface GLDrawable extends ComponentEvents {
- /** Adds a {@link GLEventListener} to this drawable. If multiple
- listeners are added to a given drawable, they are notified of
- events in an arbitrary order. */
- public void addGLEventListener(GLEventListener listener);
-
- /** Removes a {@link GLEventListener} from this drawable. Note that
- if this is done from within a particular drawable's {@link
- GLEventListener} handler (reshape, display, etc.) that it is not
- guaranteed that all other listeners will be evaluated properly
- during this update cycle. */
- public void removeGLEventListener(GLEventListener listener);
-
- /** Sets the size of this GLDrawable. */
+ /** Requests a new width and height for this GLDrawable. Not all
+ drawables are able to respond to this request and may silently
+ ignore it. */
public void setSize(int width, int height);
- /** Sets the size of this GLDrawable. */
- public void setSize(Dimension d);
-
- /** Returns the size of this GLDrawable as a newly-created Dimension
- object. */
- public Dimension getSize();
+ /** Returns the current width of this GLDrawable. */
+ public int getWidth();
- /** Stores the size of this GLDrawable into the user-provided
- Dimension object, returning that object. If the provided
- Dimension is null a new one will be allocated and returned. */
- public Dimension getSize(Dimension d);
+ /** Returns the current height of this GLDrawable. */
+ public int getHeight();
/** Returns the {@link GL} pipeline object this GLDrawable uses. If
this method is called outside of the {@link GLEventListener}'s
@@ -130,58 +112,6 @@ public interface GLDrawable extends ComponentEvents {
{@link GLEventListener#display}. */
public void display();
- /** <P> Changes this GLDrawable to allow OpenGL rendering only from
- the supplied thread, which must either be the current thread or
- null. Attempts by other threads to perform OpenGL operations
- like rendering or resizing the window will be ignored as long as
- the thread is set. Setting up the rendering thread is not
- required but enables the system to perform additional
- optimizations, in particular when the application requires
- control over the rendering loop. Before exiting,
- <code>setRenderingThread(null)</code> must be called or other
- threads will be unable to perform OpenGL rendering to this
- drawable. Throws {@link GLException} if the rendering thread for
- this drawable has been set and attempts are made to set or clear
- the rendering thread from another thread, or if the passed
- thread is not equal to the current thread or null. Also throws
- {@link GLException} if the current thread attempts to call
- <code>setRenderingThread</code> on more than one drawable. </P>
-
- <P> <B>NOTE:</B> Currently this routine is only advisory, which
- means that on some platforms the underlying optimizations are
- disabled and setting the rendering thread has no effect.
- Applications should not rely on setRenderingThread to prevent
- rendering from other threads. <P>
-
- @throws GLException if the rendering thread for this drawable has
- been set by another thread or if the passed thread is not equal
- to the current thread or null
- */
- public void setRenderingThread(Thread currentThreadOrNull) throws GLException;
-
- /** Returns the rendering thread for this drawable, or null if none
- has been set. */
- public Thread getRenderingThread();
-
- /** Disables automatic redraws of this drawable if possible. This is
- provided as an overriding mechanism for applications which
- perform animation on the drawable and for which the (currently
- advisory) {@link #setRenderingThread} does not provide strict
- enough guarantees. Its sole purpose is to avoid deadlocks that
- are unfortunately all too easy to run into when both animating a
- drawable from a given thread as well as having updates performed
- by the AWT event thread (repaints, etc.). When it is enabled,
- repaint requests driven by the AWT will not result in the OpenGL
- event listeners' display methods being called from the AWT
- thread, unless (as with GLJPanel) this is the only mechanism by
- which repaints are done. The necessity of this API may be
- rethought in a future release. Defaults to false. */
- public void setNoAutoRedrawMode(boolean noAutoRedraws);
-
- /** Returns whether automatic redraws are disabled for this
- drawable. Defaults to false. */
- public boolean getNoAutoRedrawMode();
-
/** Enables or disables automatic buffer swapping for this drawable.
By default this property is set to true; when true, after all
GLEventListeners have been called for a display() event, the
diff --git a/src/net/java/games/jogl/GLDrawableFactory.java b/src/net/java/games/jogl/GLDrawableFactory.java
index 8204fde7d..c16be50ba 100644
--- a/src/net/java/games/jogl/GLDrawableFactory.java
+++ b/src/net/java/games/jogl/GLDrawableFactory.java
@@ -39,6 +39,7 @@
package net.java.games.jogl;
+import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import net.java.games.jogl.impl.*;
@@ -78,44 +79,57 @@ public class GLDrawableFactory {
return factory;
}
- /** Creates a {@link GLCanvas} on the default graphics device with
- the specified capabilities using the default capabilities
- selection algorithm. */
- public GLCanvas createGLCanvas(GLCapabilities capabilities) {
- return createGLCanvas(capabilities, null, null);
+ /**
+ * Selects an AWT GraphicsConfiguration on the specified
+ * GraphicsDevice compatible with the supplied GLCapabilities. This
+ * method is intended to be used by applications which do not use
+ * the supplied GLCanvas class but instead wrap their own Canvas
+ * with a GLDrawable. Some platforms (specifically X11) require the
+ * GraphicsConfiguration to be specified when the platform-specific
+ * window system object, such as a Canvas, is created. This method
+ * returns null on platforms on which the OpenGL pixel format
+ * selection process is performed later.
+ *
+ * @see java.awt.Canvas(java.awt.GraphicsConfiguration)
+ */
+ public GraphicsConfiguration
+ chooseGraphicsConfiguration(GLCapabilities capabilities,
+ GLCapabilitiesChooser chooser,
+ GraphicsDevice device) {
+ return GLContextFactory.getFactory().chooseGraphicsConfiguration(capabilities, chooser, device);
}
- /** Creates a {@link GLCanvas} on the default graphics device with
- the specified capabilities using the default capabilities
- selection algorithm. The canvas will share textures and display
- lists with the specified {@link GLDrawable}; the drawable must
- either be null or have been fabricated from this factory or by
- classes in this package. A null drawable indicates no
- sharing. */
- public GLCanvas createGLCanvas(GLCapabilities capabilities, GLDrawable shareWith) {
- return createGLCanvas(capabilities, null, shareWith);
+ /**
+ * Returns a GLDrawable that wraps a platform-specific window system
+ * object, such as an AWT or LCDUI Canvas. On platforms which
+ * support it, selects a pixel format compatible with the supplied
+ * GLCapabilities, or if the passed GLCapabilities object is null,
+ * uses a default set of capabilities. On these platforms, uses
+ * either the supplied GLCapabilitiesChooser object, or if the
+ * passed GLCapabilitiesChooser object is null, uses a
+ * DefaultGLCapabilitiesChooser instance.
+ *
+ * @throw IllegalArgumentException if the passed target is either
+ * null or its data type is not supported by this GLDrawableFactory.
+ * @throw GLException if any window system-specific errors caused
+ * the creation of the GLDrawable to fail.
+ */
+ public GLDrawable getGLDrawable(Object target,
+ GLCapabilities capabilities,
+ GLCapabilitiesChooser chooser)
+ throws IllegalArgumentException, GLException {
+ // FIXME
+ throw new GLException("Not yet implemented");
}
+
+ //----------------------------------------------------------------------
+ // Methods to create high-level objects
/** Creates a {@link GLCanvas} on the default graphics device with
- the specified capabilities using the supplied capabilities
- selection algorithm. A null chooser is equivalent to using the
- {@link DefaultGLCapabilitiesChooser}. */
- public GLCanvas createGLCanvas(GLCapabilities capabilities, GLCapabilitiesChooser chooser) {
- return createGLCanvas(capabilities, chooser, null);
- }
-
- /** Creates a {@link GLCanvas} on the default graphics device with
- the specified capabilities using the supplied capabilities
- selection algorithm. A null chooser is equivalent to using the
- {@link DefaultGLCapabilitiesChooser}. The canvas will share
- textures and display lists with the specified {@link
- GLDrawable}; the drawable must either be null or have been
- fabricated from this factory or by classes in this package. A
- null drawable indicates no sharing. */
- public GLCanvas createGLCanvas(GLCapabilities capabilities,
- GLCapabilitiesChooser chooser,
- GLDrawable shareWith) {
- return createGLCanvas(capabilities, chooser, shareWith, null);
+ the specified capabilities using the default capabilities
+ selection algorithm. */
+ public GLCanvas createGLCanvas(GLCapabilities capabilities) {
+ return createGLCanvas(capabilities, null, null, null);
}
/** Creates a {@link GLCanvas} on the specified graphics device with
@@ -147,11 +161,10 @@ public class GLDrawableFactory {
// least in the Sun AWT implementation) that this will result in
// equivalent behavior to calling the no-arg super() constructor
// for Canvas.
- return new GLCanvas(GLContextFactory.getFactory().
- chooseGraphicsConfiguration(capabilities, chooser, device),
- capabilities,
+ return new GLCanvas(capabilities,
chooser,
- shareWith);
+ shareWith,
+ device);
}
/** Creates a {@link GLJPanel} with the specified capabilities using
@@ -192,4 +205,27 @@ public class GLDrawableFactory {
}
return new GLJPanel(capabilities, chooser, shareWith);
}
+
+ /**
+ * Returns true if it is possible to create a GLPbuffer with the
+ * given capabilites and dimensions.
+ */
+ public boolean canCreateGLPbuffer(GLCapabilities capabilities,
+ int initialWidth,
+ int initialHeight) {
+ // FIXME
+ throw new GLException("Not yet implemented");
+ }
+
+
+ /**
+ * Creates a GLPbuffer with the given capabilites and dimensions.
+ */
+ public GLPbuffer createGLPbuffer(GLCapabilities capabilities,
+ int initialWidth,
+ int initialHeight,
+ GLContext shareWith) {
+ // FIXME
+ throw new GLException("Not yet implemented");
+ }
}
diff --git a/src/net/java/games/jogl/GLEventListener.java b/src/net/java/games/jogl/GLEventListener.java
index 0f345e6c7..a680716a0 100644
--- a/src/net/java/games/jogl/GLEventListener.java
+++ b/src/net/java/games/jogl/GLEventListener.java
@@ -51,17 +51,17 @@ public interface GLEventListener extends EventListener {
initialized. Can be used to perform one-time OpenGL
initialization such as setup of lights and display lists. Note
that this method may be called more than once if the underlying
- OpenGL context for the GLDrawable is destroyed and recreated,
+ OpenGL context for the GLAutoDrawable is destroyed and recreated,
for example if a GLCanvas is removed from the widget hierarchy
and later added again.
*/
- public void init(GLDrawable drawable);
+ public void init(GLAutoDrawable drawable);
/** Called by the drawable to initiate OpenGL rendering by the
client. After all GLEventListeners have been notified of a
display event, the drawable will swap its buffers if necessary.
*/
- public void display(GLDrawable drawable);
+ public void display(GLAutoDrawable drawable);
/** Called by the drawable during the first repaint after the
component has been resized. The client can update the viewport
@@ -71,20 +71,20 @@ public interface GLEventListener extends EventListener {
y, width, height)</code> when this method is called, so the
client may not have to do anything in this method.
*/
- public void reshape(GLDrawable drawable, int x, int y, int width, int height);
+ public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height);
/** Called by the drawable when the display mode or the display device
- associated with the GLDrawable has changed. The two boolean parameters
+ associated with the GLAutoDrawable has changed. The two boolean parameters
indicate the types of change(s) that have occurred. (<b> !!! CURRENTLY
UNIMPLEMENTED !!! </b>)
<P>
An example of a display <i>mode</i> change is when the bit depth changes (e.g.,
- from 32-bit to 16-bit color) on monitor upon which the GLDrawable is
+ from 32-bit to 16-bit color) on monitor upon which the GLAutoDrawable is
currently being displayed. <p>
An example of a display <i>device</i> change is when the user drags the
- window containing the GLDrawable from one monitor to another in a
+ window containing the GLAutoDrawable from one monitor to another in a
multiple-monitor setup. <p>
The reason that this function handles both types of changes (instead of
@@ -94,5 +94,5 @@ public interface GLEventListener extends EventListener {
adjustments to compensate for a device change if it knows that the mode
on the new device is identical the previous mode.
*/
- public void displayChanged(GLDrawable drawable, boolean modeChanged, boolean deviceChanged);
+ public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged);
}
diff --git a/src/net/java/games/jogl/GLJPanel.java b/src/net/java/games/jogl/GLJPanel.java
index 87c9ee9b3..163330766 100644
--- a/src/net/java/games/jogl/GLJPanel.java
+++ b/src/net/java/games/jogl/GLJPanel.java
@@ -77,7 +77,7 @@ import net.java.games.jogl.impl.*;
methods as side-effect-free as possible.
*/
-public final class GLJPanel extends JPanel implements GLDrawable {
+public final class GLJPanel extends JPanel implements GLAutoDrawable {
protected static final boolean DEBUG = Debug.debug("GLJPanel");
private GLDrawableHelper drawableHelper = new GLDrawableHelper();
@@ -114,7 +114,7 @@ public final class GLJPanel extends JPanel implements GLDrawable {
private Frame toplevel;
// Implementation using software rendering
- private GLContext offscreenContext;
+ private GLContextImpl offscreenContext;
// For saving/restoring of OpenGL state during ReadPixels
private int[] swapbytes = new int[1];
@@ -184,7 +184,7 @@ public final class GLJPanel extends JPanel implements GLDrawable {
pbuffer.display();
}
} else {
- offscreenContext.invokeGL(displayAction, false, initAction);
+ drawableHelper.invokeGL(offscreenContext, displayAction, false, initAction);
}
}
@@ -239,6 +239,7 @@ public final class GLJPanel extends JPanel implements GLDrawable {
Runnable r = new Runnable() {
public void run() {
GLContext context = null;
+ GLDrawableHelper helper = drawableHelper;
readBackWidthInPixels = 0;
readBackHeightInPixels = 0;
@@ -269,6 +270,11 @@ public final class GLJPanel extends JPanel implements GLDrawable {
}
GLPbufferImpl pbufferImpl = (GLPbufferImpl) pbuffer;
context = pbufferImpl.getContext();
+ // FIXME: hack workaround for fact that reshapes may be
+ // deferred; must rethink this and defer them manually
+ // until the next display()
+ helper = pbufferImpl.getDrawableHelper();
+
// It looks like NVidia's drivers (at least the ones on my
// notebook) are buggy and don't allow a rectangle of less than
// the pbuffer's width to be read...this doesn't really matter
@@ -293,8 +299,14 @@ public final class GLJPanel extends JPanel implements GLDrawable {
panelWidth = fwidth;
panelHeight = fheight;
- context.invokeGL(new Runnable() {
+ if (DEBUG) {
+ System.err.println("Doing invokeGL of reshape action");
+ }
+ helper.invokeGL(context, new Runnable() {
public void run() {
+ if (DEBUG) {
+ System.err.println("glViewport(0, 0, " + panelWidth + ", " + panelHeight + ")");
+ }
getGL().glViewport(0, 0, panelWidth, panelHeight);
drawableHelper.reshape(GLJPanel.this, 0, 0, panelWidth, panelHeight);
}
@@ -370,22 +382,6 @@ public final class GLJPanel extends JPanel implements GLDrawable {
}
}
- public void setRenderingThread(Thread currentThreadOrNull) throws GLException {
- // Not supported for GLJPanel because all repaint requests must be
- // handled by the AWT thread
- }
-
- public Thread getRenderingThread() {
- return null;
- }
-
- public void setNoAutoRedrawMode(boolean noAutoRedraws) {
- }
-
- public boolean getNoAutoRedrawMode() {
- return false;
- }
-
public void setAutoSwapBufferMode(boolean onOrOff) {
if (!hardwareAccelerationDisabled) {
pbuffer.setAutoSwapBufferMode(onOrOff);
@@ -406,7 +402,7 @@ public final class GLJPanel extends JPanel implements GLDrawable {
if (!hardwareAccelerationDisabled) {
pbuffer.swapBuffers();
} else {
- offscreenContext.invokeGL(swapBuffersAction, false, initAction);
+ drawableHelper.invokeGL(offscreenContext, swapBuffersAction, false, initAction);
}
}
@@ -461,7 +457,7 @@ public final class GLJPanel extends JPanel implements GLDrawable {
// The pbuffer shares textures and display lists with the
// heavyweight, so by transitivity the pbuffer will share with
// it as well.
- heavyweight = GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities(), shareWith);
+ heavyweight = GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities(), null, shareWith, null);
firstTime = true;
}
if (heavyweight.canCreateOffscreenDrawable()) {
@@ -500,13 +496,17 @@ public final class GLJPanel extends JPanel implements GLDrawable {
}
// Create an offscreen context instead
- offscreenContext = GLContextFactory.getFactory().createGLContext(null, offscreenCaps, chooser,
- GLContextHelper.getContext(shareWith));
+ offscreenContext = (GLContextImpl) GLContextFactory.getFactory().createGLContext(null, offscreenCaps, chooser,
+ GLContextHelper.getContext(shareWith));
+ offscreenContext.setSynchronized(true);
offscreenContext.resizeOffscreenContext(panelWidth, panelHeight);
updater = new Updater();
if (panelWidth > 0 && panelHeight > 0) {
- offscreenContext.invokeGL(new Runnable() {
+ drawableHelper.invokeGL(offscreenContext, new Runnable() {
public void run() {
+ if (DEBUG) {
+ System.err.println("glViewport(0, 0, " + panelWidth + ", " + panelHeight + ")");
+ }
getGL().glViewport(0, 0, panelWidth, panelHeight);
drawableHelper.reshape(GLJPanel.this, 0, 0, panelWidth, panelHeight);
}
@@ -523,7 +523,7 @@ public final class GLJPanel extends JPanel implements GLDrawable {
this.g = g;
}
- public void init(GLDrawable drawable) {
+ public void init(GLAutoDrawable drawable) {
if (!hardwareAccelerationDisabled) {
if (DEBUG) {
System.err.println("GLJPanel$Updater.init(): pbufferInitializationCompleted = true");
@@ -541,7 +541,7 @@ public final class GLJPanel extends JPanel implements GLDrawable {
drawableHelper.init(GLJPanel.this);
}
- public void display(GLDrawable drawable) {
+ public void display(GLAutoDrawable drawable) {
drawableHelper.display(GLJPanel.this);
// Must now copy pixels from offscreen context into surface
@@ -672,11 +672,11 @@ public final class GLJPanel extends JPanel implements GLDrawable {
}
}
- public void reshape(GLDrawable drawable, int x, int y, int width, int height) {
+ public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
// This is handled above and dispatched directly to the appropriate context
}
- public void displayChanged(GLDrawable drawable, boolean modeChanged, boolean deviceChanged) {
+ public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {
}
}
diff --git a/src/net/java/games/jogl/GLPbuffer.java b/src/net/java/games/jogl/GLPbuffer.java
index b073388f5..4dd3c1e00 100644
--- a/src/net/java/games/jogl/GLPbuffer.java
+++ b/src/net/java/games/jogl/GLPbuffer.java
@@ -46,7 +46,7 @@ package net.java.games.jogl;
buffers. These methods are currently highly experimental and may
be removed in a future release. */
-public interface GLPbuffer extends GLDrawable {
+public interface GLPbuffer extends GLAutoDrawable {
/** Indicates the GL_APPLE_float_pixels extension is being used for this pbuffer. */
public static final int APPLE_FLOAT = 1;
diff --git a/src/net/java/games/jogl/impl/FunctionAvailabilityCache.java b/src/net/java/games/jogl/impl/FunctionAvailabilityCache.java
index be5e26067..87f2b1819 100644
--- a/src/net/java/games/jogl/impl/FunctionAvailabilityCache.java
+++ b/src/net/java/games/jogl/impl/FunctionAvailabilityCache.java
@@ -54,7 +54,7 @@ import java.lang.reflect.*;
public final class FunctionAvailabilityCache {
private static final boolean DEBUG = Debug.debug("FunctionAvailabilityCache");
- FunctionAvailabilityCache(GLContext context)
+ FunctionAvailabilityCache(GLContextImpl context)
{
this.context = context;
}
@@ -243,7 +243,7 @@ public final class FunctionAvailabilityCache {
private HashMap availabilityCache = new HashMap(50);
private HashSet availableExtensionCache = new HashSet(50);
- private GLContext context;
+ private GLContextImpl context;
/**
* A class for storing and comparing revision version numbers.
diff --git a/src/net/java/games/jogl/impl/GLContext.java b/src/net/java/games/jogl/impl/GLContext.java
deleted file mode 100644
index 41fa98c4b..000000000
--- a/src/net/java/games/jogl/impl/GLContext.java
+++ /dev/null
@@ -1,764 +0,0 @@
-/*
- * Copyright (c) 2003 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 net.java.games.jogl.impl;
-
-import java.awt.Component;
-import net.java.games.jogl.*;
-import net.java.games.gluegen.runtime.*;
-
-public abstract class GLContext {
- protected static final boolean DEBUG = Debug.debug("GLContext");
- protected static final boolean VERBOSE = Debug.verbose();
- protected static final boolean NO_FREE = Debug.isPropertyDefined("jogl.GLContext.nofree");
-
- static {
- NativeLibLoader.load();
- }
-
- protected Component component;
-
- // Indicates whether the component (if an onscreen context) has been
- // realized. Plausibly, before the component is realized the JAWT
- // should return an error or NULL object from some of its
- // operations; this appears to be the case on Win32 but is not true
- // at least with Sun's current X11 implementation (1.4.x), which
- // crashes with no other error reported if the DrawingSurfaceInfo is
- // fetched from a locked DrawingSurface during the validation as a
- // result of calling show() on the main thread. To work around this
- // we prevent any JAWT or OpenGL operations from being done until
- // addNotify() is called on the component.
- protected boolean realized;
-
- protected GLCapabilities capabilities;
- protected GLCapabilitiesChooser chooser;
- protected GL gl;
- protected static final GLUProcAddressTable gluProcAddressTable = new GLUProcAddressTable();
- protected static boolean haveResetGLUProcAddressTable;
- protected GLU glu = new GLUImpl(gluProcAddressTable);
- protected Thread renderingThread;
- protected Runnable deferredReshapeAction;
- // Support for OpenGL context destruction and recreation in the face
- // of the setRenderingThread optimization, which makes the context
- // permanently current on the animation thread. FIXME: should make
- // this more uniform and general, possibly by implementing in terms
- // of Runnables; however, necessary sequence of operations in
- // invokeGL makes this tricky.
- protected boolean deferredDestroy;
- protected boolean deferredSetRealized;
-
- // Error checking for setRenderingThread to ensure that one thread
- // doesn't attempt to call setRenderingThread on more than one
- // drawable
- protected static final ThreadLocal perThreadRenderingContext = new ThreadLocal();
-
- // This is a workaround for a bug in NVidia's drivers where
- // vertex_array_range is only safe for single-threaded use; a bug
- // has been filed, ID 80174. When an Animator is created for a
- // GLDrawable, the expectation is that the Animator will be started
- // shortly and that the user doesn't want rendering to occur from
- // the AWT thread. However, there is a small window between when the
- // Animator is created and attached to the GLDrawable and when it's
- // started (and sets the rendering thread) when repaint events can
- // be issued by the AWT thread if the component is realized. To work
- // around this problem, we currently specify in the Animator's API
- // that between the time it's created and started no redraws will
- // occur.
- protected volatile boolean willSetRenderingThread;
-
- // Flag for disabling all repaint and resize processing on the AWT
- // thread to avoid application-level deadlocks; only really used for
- // GLCanvas
- protected boolean noAutoRedraw;
-
- // Flag for enabling / disabling automatic swapping of the front and
- // back buffers
- protected boolean autoSwapBuffers = true;
-
- // Offscreen context handling. Offscreen contexts should handle
- // these resize requests in makeCurrent and clear the
- // pendingOffscreenResize flag.
- protected boolean pendingOffscreenResize;
- protected int pendingOffscreenWidth;
- protected int pendingOffscreenHeight;
-
- // Cache of the functions that are available to be called at the current
- // moment in time
- protected FunctionAvailabilityCache functionAvailability;
-
- // Support for recursive makeCurrent() calls as well as calling
- // other drawables' display() methods from within another one's
- protected static final ThreadLocal perThreadContextStack = new ThreadLocal() {
- protected synchronized Object initialValue() {
- return new GLContextStack();
- }
- };
- // This thread-local variable helps implement setRenderingThread()'s
- // optimized context handling. When the bottommost invokeGL() on the
- // execution stack finishes for the rendering thread for that
- // context, we pop the context off the context stack but do not free
- // it, instead storing it in this thread-local variable. This gives
- // us enough information to recover the context stack state in
- // subsequent invokeGL() calls.
- protected static final ThreadLocal perThreadSavedCurrentContext = new ThreadLocal() {
- protected synchronized Object initialValue() {
- return new GLContextInitActionPair(null, null);
- }
- };
-
- public GLContext(Component component,
- GLCapabilities capabilities,
- GLCapabilitiesChooser chooser,
- GLContext shareWith) {
- this.component = component;
- this.capabilities = (GLCapabilities) capabilities.clone();
- this.chooser = chooser;
- setGL(createGL());
- functionAvailability = new FunctionAvailabilityCache(this);
- if (shareWith != null) {
- GLContextShareSet.registerSharing(this, shareWith);
- }
- }
-
- /** Runs the given runnable with this OpenGL context valid. */
- public synchronized void invokeGL(Runnable runnable, boolean isReshape, Runnable initAction) throws GLException {
- // Could be more clever about not calling this every time, but
- // Thread.currentThread() is very fast and this makes the logic simpler
- Thread currentThread = Thread.currentThread();
-
- // Defer JAWT and OpenGL operations until onscreen components are
- // realized
- if (!isRealized() ||
- willSetRenderingThread ||
- (renderingThread != null &&
- renderingThread != currentThread)) {
- // Support for removeNotify()/addNotify() when the
- // setRenderingThread optimization is in effect and before the
- // animation thread gets a chance to handle either request
- if (!isRealized() && deferredSetRealized) {
- setRealized();
- deferredSetRealized = false;
- } else {
- if (isReshape) {
- deferredReshapeAction = runnable;
- }
- return;
- }
- }
-
- if (isReshape && noAutoRedraw && !SingleThreadedWorkaround.doWorkaround()) {
- // Don't process reshape requests on the AWT thread
- deferredReshapeAction = runnable;
- return;
- }
-
- if (deferredDestroy) {
- deferredDestroy = false;
- if (renderingThread != null) {
- // Need to disable the setRenderingThread optimization to free
- // up the context
- setRenderingThread(null, initAction);
- }
- destroy();
- return;
- }
-
- // The goal of this code is to optimize OpenGL context handling as
- // much as possible. In particular:
- //
- // - setRenderingThread() works by making the "bottommost" OpenGL
- // context current once and not freeing it until the rendering
- // thread has been unset. Note that subsequent pushes of other
- // contexts will still necessarily cause them to be made current
- // and freed.
- //
- // - If the same context is pushed on the per-thread context stack
- // more than once back-to-back, the subsequent pushes will not
- // actually cause a makeCurrent/free to occur.
- //
- // Complexities occur because setRenderingThread() can be called
- // at any time. Currently we implement the rendering thread
- // optimization by popping it off the OpenGL context stack and
- // storing it in a thread-local variable.
-
- GLContextStack ctxStack = getPerThreadContextStack();
- GLContext savedPerThreadContext = getPerThreadSavedCurrentContext();
- Runnable savedPerThreadInitAction = getPerThreadSavedInitAction();
- setPerThreadSavedCurrentContext(null, null);
- if (ctxStack.size() == 0 &&
- savedPerThreadContext != null) {
- // The setRenderingThread optimization moved the current context
- // into thread-local storage. Put it back on the context stack,
- // because we might need to free it later.
- ctxStack.push(savedPerThreadContext, savedPerThreadInitAction);
- }
-
- GLContext curContext = ctxStack.peekContext();
- Runnable curInitAction = ctxStack.peekInitAction();
- boolean mustDoMakeCurrent = true;
-
- if (curContext == this) {
- mustDoMakeCurrent = false;
- }
-
- if (mustDoMakeCurrent) {
- if (curContext != null) {
- if (DEBUG && VERBOSE) {
- System.err.println(getThreadName() + ": Freeing context " + curContext + " due to recursive makeCurrent");
- }
- curContext.free();
- }
-
- if (!makeCurrent(initAction)) {
- // Couldn't make the thread current because the component has not yet
- // been visualized, and therefore the context cannot be created.
- // We'll defer any actions until invokeGL() is called again at a time
- // when the component has been visualized.
- if (isReshape) {
- deferredReshapeAction = runnable;
- }
-
- // Clean up after ourselves on the way out.
- // NOTE that this is an abbreviated version of the code below
- // and should probably be refactored/cleaned up -- this bug
- // fix was done without a lot of intense thought about the
- // situation
- if (curContext != null) {
- curContext.makeCurrent(curInitAction);
- }
- return;
- }
- if (DEBUG && VERBOSE) {
- System.err.println(getThreadName() + ": Making context " + this + " current");
- }
- }
- ctxStack.push(this, initAction);
-
- // At this point the OpenGL context is current. Offscreen contexts
- // handle resizing the backing bitmap in makeCurrent. Therefore we
- // may need to free and make the context current again if we
- // didn't actually make it current above.
- if (pendingOffscreenResize && renderingThread != null) {
- ctxStack.pop();
- free();
- if (!makeCurrent(initAction)) {
- throw new GLException("Error while resizing offscreen context");
- }
- ctxStack.push(this, initAction);
- }
-
- RuntimeException userException = null;
- GLException internalException = null;
-
- try {
- if (deferredReshapeAction != null) {
- deferredReshapeAction.run();
- deferredReshapeAction = null;
- }
- runnable.run();
- if (autoSwapBuffers && !isReshape) {
- swapBuffers();
- }
- } catch (RuntimeException e) {
- userException = e;
- throw(userException);
- } finally {
- if (userException != null) {
- // Disallow setRenderingThread if display action is throwing exceptions
- renderingThread = null;
- }
-
- boolean mustSkipFreeForRenderingThread = false;
- if (currentThread == renderingThread && curContext == null) {
- mustSkipFreeForRenderingThread = true;
- setPerThreadSavedCurrentContext(this, initAction);
- }
-
- // Always pop myself off the per-thread context stack
- ctxStack.pop();
-
- // Free the context unless the setRenderingThread optimization
- // kicks in.
- if (mustDoMakeCurrent && !mustSkipFreeForRenderingThread) {
- if (DEBUG && VERBOSE) {
- System.err.println(getThreadName() + ": Freeing context " + this);
- }
-
- try {
- free();
- } catch (GLException e) {
- internalException = e;
- }
-
- if (curContext != null) {
- if (DEBUG && VERBOSE) {
- System.err.println(getThreadName() + ": Making context " + curContext + " current again");
- }
- try {
- curContext.makeCurrent(curInitAction);
- } catch (GLException e) {
- internalException = e;
- }
- }
- }
-
- // Check to see whether we pushed any remaining entry on the
- // per-thread context stack. If so, put it back in thread-local
- // storage unless the rendering thread optimization was recently
- // disabled.
- if (savedPerThreadContext != null) {
- assert(savedPerThreadContext == curContext);
- ctxStack.pop();
- if (savedPerThreadContext.getRenderingThread() == null) {
- try {
- savedPerThreadContext.free();
- } catch (GLException e) {
- internalException = e;
- }
- } else {
- setPerThreadSavedCurrentContext(savedPerThreadContext, savedPerThreadInitAction);
- }
- }
-
- // Make sure the end user's exception shows up in any stack
- // traces; the rethrow of the userException above should take
- // precedence if the internalException will otherwise squelch it
- if (internalException != null) {
- if (userException != null &&
- internalException.getCause() == null) {
- internalException.initCause(userException);
- throw(internalException);
- } else if (userException == null) {
- throw(internalException);
- }
- }
- }
- }
-
- public GL getGL() {
- return gl;
- }
-
- public void setGL(GL gl) {
- this.gl = gl;
- // Also reset the GL object for the pure-Java GLU implementation
- ((GLUImpl) glu).setGL(gl);
- }
-
- public GLU getGLU() {
- return glu;
- }
-
- public void setGLU(GLU glu) {
- this.glu = glu;
- }
-
- /** Gives a hint to the context that setRenderingThread will be
- called in the near future; causes redraws to be halted. This is
- a workaround for bugs in NVidia's drivers and is used only by
- the Animator class. */
- public synchronized void willSetRenderingThread() {
- this.willSetRenderingThread = true;
- }
-
- public synchronized void setRenderingThread(Thread currentThreadOrNull, Runnable initAction) {
- if (SingleThreadedWorkaround.doWorkaround()) {
- willSetRenderingThread = false;
- return;
- }
-
- Thread currentThread = Thread.currentThread();
- if (currentThreadOrNull != null && currentThreadOrNull != currentThread) {
- throw new GLException("Argument must be either the current thread or null");
- }
- if (renderingThread != null && currentThreadOrNull != null) {
- throw new GLException("Attempt to re-set or change rendering thread");
- }
- if (renderingThread == null && currentThreadOrNull == null) {
- throw new GLException("Attempt to clear rendering thread when already cleared");
- }
-
- Object currentThreadRenderingContext = perThreadRenderingContext.get();
- if (currentThreadOrNull != null &&
- currentThreadRenderingContext != null &&
- currentThreadRenderingContext != this) {
- throw new GLException("Attempt to call setRenderingThread on more than one drawable in this thread");
- }
-
- this.willSetRenderingThread = false;
- if (currentThreadOrNull == null) {
- renderingThread = null;
- perThreadRenderingContext.set(null);
- // Just in case the end user wasn't planning on drawing the
- // drawable even once more (which would give us a chance to free
- // the context), try to free the context now by performing an
- // invokeGL with a do-nothing action
- invokeGL(new Runnable() {
- public void run() {
- }
- }, false, initAction);
- } else {
- renderingThread = currentThreadOrNull;
- perThreadRenderingContext.set(this);
- }
- }
-
- public Thread getRenderingThread() {
- return renderingThread;
- }
-
- public void setNoAutoRedrawMode(boolean noAutoRedraw) {
- this.noAutoRedraw = noAutoRedraw;
- }
-
- public boolean getNoAutoRedrawMode() {
- return noAutoRedraw;
- }
-
- public void setAutoSwapBufferMode(boolean autoSwapBuffers) {
- this.autoSwapBuffers = autoSwapBuffers;
- }
-
- public boolean getAutoSwapBufferMode() {
- return autoSwapBuffers;
- }
-
- /** Swaps the buffers of the OpenGL context if necessary. All error
- conditions cause a GLException to be thrown. */
- public abstract void swapBuffers() throws GLException;
-
- /** Routine needed only for offscreen contexts in order to resize
- the underlying bitmap. Called by GLJPanel. */
- public void resizeOffscreenContext(int newWidth, int newHeight) {
- if (!isOffscreen()) {
- throw new GLException("Should only call for offscreen OpenGL contexts");
- }
- pendingOffscreenResize = true;
- pendingOffscreenWidth = newWidth;
- pendingOffscreenHeight = newHeight;
- }
-
- /** Indicates which floating-point pbuffer implementation is in
- use. Returns one of GLPbuffer.APPLE_FLOAT, GLPbuffer.ATI_FLOAT,
- or GLPbuffer.NV_FLOAT. */
- public int getFloatingPointMode() throws GLException {
- throw new GLException("Not supported on non-pbuffer contexts");
- }
-
- /** Returns a non-null (but possibly empty) string containing the
- space-separated list of available platform-dependent (e.g., WGL,
- GLX) extensions. Can only be called while this context is
- current. */
- public abstract String getPlatformExtensionsString();
-
- /**
- * Resets the cache of which GL functions are available for calling through this
- * context. See {@link #isFunctionAvailable(String)} for more information on
- * the definition of "available".
- */
- protected void resetGLFunctionAvailability() {
- // In order to be able to allow the user to uniformly install the
- // debug and trace pipelines in their GLEventListener.init()
- // method (for both GLCanvas and GLJPanel), we need to reset the
- // actual GL object in the GLDrawable as well
- setGL(createGL());
-
- functionAvailability.flush();
- if (!haveResetGLUProcAddressTable) {
- if (DEBUG) {
- System.err.println(getThreadName() + ": !!! Initializing GLU extension address table");
- }
- resetProcAddressTable(gluProcAddressTable);
- haveResetGLUProcAddressTable = true; // Only need to do this once globally
- }
- recomputeSingleThreadedWorkaround();
- }
-
- /**
- * Returns true if the specified OpenGL core- or extension-function can be
- * successfully called using this GL context given the current host (OpenGL
- * <i>client</i>) and display (OpenGL <i>server</i>) configuration.
- *
- * See {@link GL#isFunctionAvailable(String)} for more details.
- *
- * @param glFunctionName the name of the OpenGL function (e.g., use
- * "glPolygonOffsetEXT" to check if the {@link
- * net.java.games.jogl.GL#glPolygonOffsetEXT(float,float)} is available).
- */
- protected boolean isFunctionAvailable(String glFunctionName) {
- return functionAvailability.isFunctionAvailable(mapToRealGLFunctionName(glFunctionName));
- }
-
- /**
- * Returns true if the specified OpenGL extension can be
- * successfully called using this GL context given the current host (OpenGL
- * <i>client</i>) and display (OpenGL <i>server</i>) configuration.
- *
- * See {@link GL#isExtensionAvailable(String)} for more details.
- *
- * @param glExtensionName the name of the OpenGL extension (e.g.,
- * "GL_VERTEX_PROGRAM_ARB").
- */
- public boolean isExtensionAvailable(String glExtensionName) {
- return functionAvailability.isExtensionAvailable(mapToRealGLExtensionName(glExtensionName));
- }
-
- /**
- * Pbuffer support; indicates whether this context is capable of
- * creating a subordinate pbuffer context (distinct from an
- * "offscreen context", which is typically software-rendered on all
- * platforms).
- */
- public abstract boolean canCreatePbufferContext();
-
- /**
- * Pbuffer support; creates a subordinate GLContext for a pbuffer
- * associated with this context.
- */
- public abstract GLContext createPbufferContext(GLCapabilities capabilities,
- int initialWidth,
- int initialHeight);
-
- /**
- * Pbuffer support; given that this is a GLContext associated with a
- * pbuffer, binds this pbuffer to its texture target.
- */
- public abstract void bindPbufferToTexture();
-
- /**
- * Pbuffer support; given that this is a GLContext associated with a
- * pbuffer, releases this pbuffer from its texture target.
- */
- public abstract void releasePbufferFromTexture();
-
- /*
- * Sets the swap interval for onscreen OpenGL contexts. Has no
- * effect for offscreen contexts.
- */
- public void setSwapInterval(final int interval) {
- }
-
- /** Maps the given "platform-independent" function name to a real function
- name. Currently this is only used to map "glAllocateMemoryNV" and
- associated routines to wglAllocateMemoryNV / glXAllocateMemoryNV. */
- protected abstract String mapToRealGLFunctionName(String glFunctionName);
-
- /** Maps the given "platform-independent" extension name to a real
- function name. Currently this is only used to map
- "GL_ARB_pbuffer" and "GL_ARB_pixel_format" to "WGL_ARB_pbuffer"
- and "WGL_ARB_pixel_format" (not yet mapped to X11). */
- protected abstract String mapToRealGLExtensionName(String glExtensionName);
-
- /** Create the GL for this context. */
- protected abstract GL createGL();
-
- /** Hook indicating whether the concrete GLContext implementation is
- offscreen and therefore whether we need to process resize
- requests. */
- protected abstract boolean isOffscreen();
-
- /** Only called for offscreen contexts; returns the buffer from
- which to read pixels (GL.GL_FRONT or GL.GL_BACK). */
- public abstract int getOffscreenContextReadBuffer();
-
- /** Only called for offscreen contexts; needed by glReadPixels */
- public abstract int getOffscreenContextWidth();
-
- /** Only called for offscreen contexts; needed by glReadPixels */
- public abstract int getOffscreenContextHeight();
-
- /** Only called for offscreen contexts; needed by glReadPixels */
- public abstract int getOffscreenContextPixelDataType();
-
- /** On some platforms the mismatch between OpenGL's coordinate
- system (origin at bottom left) and the window system's
- coordinate system (origin at top left) necessitates a vertical
- flip of pixels read from offscreen contexts. */
- public abstract boolean offscreenImageNeedsVerticalFlip();
-
- /** Attempts to make the GL context current. If necessary, creates a
- context and calls the initAction once the context is current.
- Most error conditions cause an exception to be thrown, except
- for the case where the context can not be created because the
- component has not yet been visualized. In this case makeCurrent
- returns false and the caller should abort any OpenGL event
- processing and instead return immediately. */
- protected abstract boolean makeCurrent(Runnable initAction) throws GLException;
-
- /** Frees the OpenGL context. All error conditions cause a
- GLException to be thrown. */
- protected abstract void free() throws GLException;
-
- /** Inform the system that the associated heavyweight widget has
- been realized and that it is safe to create an associated OpenGL
- context. If the widget is later destroyed then destroy() should
- be called, which will cause the underlying OpenGL context to be
- destroyed as well as the realized bit to be set to false. */
- public void setRealized() {
- if (getRenderingThread() != null &&
- Thread.currentThread() != getRenderingThread()) {
- deferredSetRealized = true;
- return;
- }
- setRealized(true);
- }
-
- /** Sets only the "realized" bit. Should be called by subclasses
- from within the destroy() implementation. */
- protected synchronized void setRealized(boolean realized) {
- this.realized = realized;
- if (DEBUG) {
- System.err.println(getThreadName() + ": GLContext.setRealized(" + realized + ") for context " + this);
- }
- }
-
- /** Indicates whether the component associated with this context has
- been realized. */
- public synchronized boolean getRealized() {
- return realized;
- }
-
- /** Destroys the underlying OpenGL context and changes the realized
- state to false. This should be called when the widget is being
- destroyed. */
- public synchronized void destroy() throws GLException {
- if (getRenderingThread() != null &&
- Thread.currentThread() != getRenderingThread()) {
- if (DEBUG) {
- System.err.println(getThreadName() + ": Deferred destroy for context " + this);
- }
- deferredDestroy = true;
- return;
- }
- setRealized(false);
- GLContextShareSet.contextDestroyed(this);
- destroyImpl();
- }
-
- /** Destroys the underlying OpenGL context. */
- protected abstract void destroyImpl() throws GLException;
-
- public synchronized boolean isRealized() {
- return (component == null || getRealized());
- }
-
- /** Helper routine which resets a ProcAddressTable generated by the
- GLEmitter by looking up anew all of its function pointers. */
- protected void resetProcAddressTable(Object table) {
- Class tableClass = table.getClass();
- java.lang.reflect.Field[] fields = tableClass.getDeclaredFields();
-
- for (int i = 0; i < fields.length; ++i) {
- String addressFieldName = fields[i].getName();
- if (!addressFieldName.startsWith(ProcAddressHelper.PROCADDRESS_VAR_PREFIX)) {
- // not a proc address variable
- continue;
- }
- int startOfMethodName = ProcAddressHelper.PROCADDRESS_VAR_PREFIX.length();
- String glFuncName = addressFieldName.substring(startOfMethodName);
- try {
- java.lang.reflect.Field addressField = tableClass.getDeclaredField(addressFieldName);
- assert(addressField.getType() == Long.TYPE);
- long newProcAddress = dynamicLookupFunction(glFuncName);
- // set the current value of the proc address variable in the table object
- addressField.setLong(table, newProcAddress);
- if (DEBUG) {
- // System.err.println(glFuncName + " = 0x" + Long.toHexString(newProcAddress));
- }
- } catch (Exception e) {
- throw new GLException("Cannot get GL proc address for method \"" +
- glFuncName + "\": Couldn't set value of field \"" + addressFieldName +
- "\" in class " + tableClass.getName(), e);
- }
- }
- }
-
- /** Dynamically looks up the given function. */
- protected abstract long dynamicLookupFunction(String glFuncName);
-
- /** Indicates whether the underlying OpenGL context has been
- created. This is used to manage sharing of display lists and
- textures between contexts. */
- public abstract boolean isCreated();
-
- /** Support for recursive makeCurrent() calls as well as calling
- other drawables' display() methods from within another one's */
- protected static GLContextStack getPerThreadContextStack() {
- return (GLContextStack) perThreadContextStack.get();
- }
-
- /** Support for setRenderingThread()'s optimized context handling */
- protected static GLContext getPerThreadSavedCurrentContext() {
- return ((GLContextInitActionPair) perThreadSavedCurrentContext.get()).getContext();
- }
-
- /** Support for setRenderingThread()'s optimized context handling */
- protected static Runnable getPerThreadSavedInitAction() {
- return ((GLContextInitActionPair) perThreadSavedCurrentContext.get()).getInitAction();
- }
-
- /** Support for setRenderingThread()'s optimized context handling */
- protected static void setPerThreadSavedCurrentContext(GLContext context, Runnable initAction) {
- perThreadSavedCurrentContext.set(new GLContextInitActionPair(context, initAction));
- }
-
- /** Support for automatic detection of whether we need to enable the
- single-threaded workaround for ATI and other vendors' cards.
- Should be called by subclasses for onscreen rendering inside
- their makeCurrent() implementation once the context is
- current. */
- private void recomputeSingleThreadedWorkaround() {
- GL gl = getGL();
- String str = gl.glGetString(GL.GL_VENDOR);
- if (str != null && str.indexOf("ATI") >= 0) {
- // Doing this instead of calling setRenderingThread(null) should
- // be OK since we are doing this very early in the maintenance
- // of the per-thread context stack, before we are actually
- // pushing any GLContext objects on it
- SingleThreadedWorkaround.shouldDoWorkaround();
- if( SingleThreadedWorkaround.doWorkaround() ) {
- renderingThread = null;
- }
- }
- }
-
- protected static String getThreadName() {
- return Thread.currentThread().getName();
- }
-}
diff --git a/src/net/java/games/jogl/impl/GLContextImpl.java b/src/net/java/games/jogl/impl/GLContextImpl.java
new file mode 100755
index 000000000..26547c8c3
--- /dev/null
+++ b/src/net/java/games/jogl/impl/GLContextImpl.java
@@ -0,0 +1,364 @@
+/*
+ * Copyright (c) 2003 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
+ * MIDROSYSTEMS, 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 net.java.games.jogl.impl;
+
+import java.awt.Component;
+
+import net.java.games.jogl.*;
+import net.java.games.gluegen.runtime.*;
+
+public abstract class GLContextImpl extends GLContext {
+ protected GLContextLock lock = new GLContextLock();
+ protected static final boolean DEBUG = Debug.debug("GLContextImpl");
+ protected static final boolean VERBOSE = Debug.verbose();
+ protected static final boolean NO_FREE = Debug.isPropertyDefined("jogl.GLContext.nofree");
+
+ static {
+ NativeLibLoader.load();
+ }
+
+ protected GLCapabilities capabilities;
+ protected GLCapabilitiesChooser chooser;
+ protected Component component;
+
+ // Cache of the functions that are available to be called at the current
+ // moment in time
+ protected FunctionAvailabilityCache functionAvailability;
+
+ protected GL gl;
+ protected GLU glu = new GLUImpl(gluProcAddressTable);
+ protected static final GLUProcAddressTable gluProcAddressTable = new GLUProcAddressTable();
+ protected static boolean haveResetGLUProcAddressTable;
+
+ public GLContextImpl(Component component,
+ GLCapabilities capabilities,
+ GLCapabilitiesChooser chooser,
+ GLContext shareWith) {
+ this.component = component;
+ this.capabilities = (GLCapabilities) capabilities.clone();
+ this.chooser = chooser;
+ setGL(createGL());
+ functionAvailability = new FunctionAvailabilityCache(this);
+ if (shareWith != null) {
+ GLContextShareSet.registerSharing(this, shareWith);
+ }
+ }
+
+ public int makeCurrent() throws GLException {
+ lock.lock();
+ int res = 0;
+ try {
+ res = makeCurrentImpl();
+ } catch (GLException e) {
+ lock.unlock();
+ throw(e);
+ }
+ if (res == CONTEXT_NOT_CURRENT) {
+ lock.unlock();
+ } else {
+ setCurrent(this);
+ }
+ return res;
+ }
+
+ protected abstract int makeCurrentImpl() throws GLException;
+
+ public void release() throws GLException {
+ if (!lock.isHeld()) {
+ throw new GLException("Context not current on current thread");
+ }
+ setCurrent(null);
+ try {
+ releaseImpl();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ protected abstract void releaseImpl() throws GLException;
+
+ public void destroy() {
+ // Should we check the lock state? It should not be current on any
+ // thread.
+ destroyImpl();
+ }
+
+ protected abstract void destroyImpl() throws GLException;
+
+ public boolean isSynchronized() {
+ return !lock.getFailFastMode();
+ }
+
+ public void setSynchronized(boolean isSynchronized) {
+ lock.setFailFastMode(!isSynchronized);
+ }
+
+ public GL getGL() {
+ return gl;
+ }
+
+ public void setGL(GL gl) {
+ this.gl = gl;
+ // Also reset the GL object for the pure-Java GLU implementation
+ ((GLUImpl) glu).setGL(gl);
+ }
+
+ public GLU getGLU() {
+ return glu;
+ }
+
+ public void setGLU(GLU glu) {
+ this.glu = glu;
+ }
+
+ // Subclasses for onscreen GLContexts should override this to
+ // receive a notification from the GLCanvas or other implementation
+ // upon addNotify
+ public void setRealized() {
+ }
+
+ //----------------------------------------------------------------------
+ // Helpers for various context implementations
+ //
+
+ // Flag for enabling / disabling automatic swapping of the front and
+ // back buffers
+ protected boolean autoSwapBuffers = true;
+
+ // Offscreen context handling. Offscreen contexts should handle
+ // these resize requests in makeCurrent and clear the
+ // pendingOffscreenResize flag.
+ protected boolean pendingOffscreenResize;
+ protected int pendingOffscreenWidth;
+ protected int pendingOffscreenHeight;
+
+ /** Create the GL for this context. */
+ protected abstract GL createGL();
+
+ /**
+ * Pbuffer support; indicates whether this context is capable of
+ * creating a subordinate pbuffer context (distinct from an
+ * "offscreen context", which is typically software-rendered on all
+ * platforms).
+ */
+ public abstract boolean canCreatePbufferContext();
+
+ /**
+ * Pbuffer support; creates a subordinate GLContext for a pbuffer
+ * associated with this context.
+ */
+ public abstract GLContext createPbufferContext(GLCapabilities capabilities,
+ int initialWidth,
+ int initialHeight);
+
+ /**
+ * Pbuffer support; given that this is a GLContext associated with a
+ * pbuffer, binds this pbuffer to its texture target.
+ */
+ public abstract void bindPbufferToTexture();
+
+ /**
+ * Pbuffer support; given that this is a GLContext associated with a
+ * pbuffer, releases this pbuffer from its texture target.
+ */
+ public abstract void releasePbufferFromTexture();
+
+ /*
+ * Sets the swap interval for onscreen OpenGL contexts. Has no
+ * effect for offscreen contexts.
+ */
+ public void setSwapInterval(final int interval) {
+ }
+
+ /** Maps the given "platform-independent" function name to a real function
+ name. Currently this is only used to map "glAllocateMemoryNV" and
+ associated routines to wglAllocateMemoryNV / glXAllocateMemoryNV. */
+ protected abstract String mapToRealGLFunctionName(String glFunctionName);
+
+ /** Maps the given "platform-independent" extension name to a real
+ function name. Currently this is only used to map
+ "GL_ARB_pbuffer" and "GL_ARB_pixel_format" to "WGL_ARB_pbuffer"
+ and "WGL_ARB_pixel_format" (not yet mapped to X11). */
+ protected abstract String mapToRealGLExtensionName(String glExtensionName);
+
+ public void setAutoSwapBufferMode(boolean autoSwapBuffers) {
+ this.autoSwapBuffers = autoSwapBuffers;
+ }
+
+ public boolean getAutoSwapBufferMode() {
+ return autoSwapBuffers;
+ }
+
+ /** Swaps the buffers of the OpenGL context if necessary. All error
+ conditions cause a GLException to be thrown. */
+ public abstract void swapBuffers() throws GLException;
+
+ /** Returns a non-null (but possibly empty) string containing the
+ space-separated list of available platform-dependent (e.g., WGL,
+ GLX) extensions. Can only be called while this context is
+ current. */
+ public abstract String getPlatformExtensionsString();
+
+ /** Helper routine which resets a ProcAddressTable generated by the
+ GLEmitter by looking up anew all of its function pointers. */
+ protected void resetProcAddressTable(Object table) {
+ Class tableClass = table.getClass();
+ java.lang.reflect.Field[] fields = tableClass.getDeclaredFields();
+
+ for (int i = 0; i < fields.length; ++i) {
+ String addressFieldName = fields[i].getName();
+ if (!addressFieldName.startsWith(ProcAddressHelper.PROCADDRESS_VAR_PREFIX)) {
+ // not a proc address variable
+ continue;
+ }
+ int startOfMethodName = ProcAddressHelper.PROCADDRESS_VAR_PREFIX.length();
+ String glFuncName = addressFieldName.substring(startOfMethodName);
+ try {
+ java.lang.reflect.Field addressField = tableClass.getDeclaredField(addressFieldName);
+ assert(addressField.getType() == Long.TYPE);
+ long newProcAddress = dynamicLookupFunction(glFuncName);
+ // set the current value of the proc address variable in the table object
+ addressField.setLong(table, newProcAddress);
+ if (DEBUG) {
+ // System.err.println(glFuncName + " = 0x" + Long.toHexString(newProcAddress));
+ }
+ } catch (Exception e) {
+ throw new GLException("Cannot get GL proc address for method \"" +
+ glFuncName + "\": Couldn't set value of field \"" + addressFieldName +
+ "\" in class " + tableClass.getName(), e);
+ }
+ }
+ }
+
+ /** Dynamically looks up the given function. */
+ protected abstract long dynamicLookupFunction(String glFuncName);
+
+ /** Indicates whether the underlying OpenGL context has been
+ created. This is used to manage sharing of display lists and
+ textures between contexts. */
+ public abstract boolean isCreated();
+
+ /**
+ * Resets the cache of which GL functions are available for calling through this
+ * context. See {@link #isFunctionAvailable(String)} for more information on
+ * the definition of "available".
+ */
+ protected void resetGLFunctionAvailability() {
+ // In order to be able to allow the user to uniformly install the
+ // debug and trace pipelines in their GLEventListener.init()
+ // method (for both GLCanvas and GLJPanel), we need to reset the
+ // actual GL object in the GLDrawable as well
+ setGL(createGL());
+
+ functionAvailability.flush();
+ if (!haveResetGLUProcAddressTable) {
+ if (DEBUG) {
+ System.err.println(getThreadName() + ": !!! Initializing GLU extension address table");
+ }
+ resetProcAddressTable(gluProcAddressTable);
+ haveResetGLUProcAddressTable = true; // Only need to do this once globally
+ }
+ }
+
+ /**
+ * Returns true if the specified OpenGL core- or extension-function can be
+ * successfully called using this GL context given the current host (OpenGL
+ * <i>client</i>) and display (OpenGL <i>server</i>) configuration.
+ *
+ * See {@link GL#isFunctionAvailable(String)} for more details.
+ *
+ * @param glFunctionName the name of the OpenGL function (e.g., use
+ * "glPolygonOffsetEXT" to check if the {@link
+ * net.java.games.jogl.GL#glPolygonOffsetEXT(float,float)} is available).
+ */
+ protected boolean isFunctionAvailable(String glFunctionName) {
+ return functionAvailability.isFunctionAvailable(mapToRealGLFunctionName(glFunctionName));
+ }
+
+ /**
+ * Returns true if the specified OpenGL extension can be
+ * successfully called using this GL context given the current host (OpenGL
+ * <i>client</i>) and display (OpenGL <i>server</i>) configuration.
+ *
+ * See {@link GL#isExtensionAvailable(String)} for more details.
+ *
+ * @param glExtensionName the name of the OpenGL extension (e.g.,
+ * "GL_VERTEX_PROGRAM_ARB").
+ */
+ public boolean isExtensionAvailable(String glExtensionName) {
+ return functionAvailability.isExtensionAvailable(mapToRealGLExtensionName(glExtensionName));
+ }
+
+ /** Indicates which floating-point pbuffer implementation is in
+ use. Returns one of GLPbuffer.APPLE_FLOAT, GLPbuffer.ATI_FLOAT,
+ or GLPbuffer.NV_FLOAT. */
+ public int getFloatingPointMode() throws GLException {
+ throw new GLException("Not supported on non-pbuffer contexts");
+ }
+
+ /** Hook indicating whether the concrete GLContext implementation is
+ offscreen and therefore whether we need to process resize
+ requests. */
+ protected abstract boolean isOffscreen();
+
+ /** On some platforms the mismatch between OpenGL's coordinate
+ system (origin at bottom left) and the window system's
+ coordinate system (origin at top left) necessitates a vertical
+ flip of pixels read from offscreen contexts. */
+ public abstract boolean offscreenImageNeedsVerticalFlip();
+
+ /** Only called for offscreen contexts; needed by glReadPixels */
+ public abstract int getOffscreenContextPixelDataType();
+
+ /** Routine needed only for offscreen contexts in order to resize
+ the underlying bitmap. Called by GLJPanel. */
+ public void resizeOffscreenContext(int newWidth, int newHeight) {
+ if (!isOffscreen()) {
+ throw new GLException("Should only call for offscreen OpenGL contexts");
+ }
+ pendingOffscreenResize = true;
+ pendingOffscreenWidth = newWidth;
+ pendingOffscreenHeight = newHeight;
+ }
+
+ protected static String getThreadName() {
+ return Thread.currentThread().getName();
+ }
+}
diff --git a/src/net/java/games/jogl/impl/GLContextLock.java b/src/net/java/games/jogl/impl/GLContextLock.java
new file mode 100755
index 000000000..7e40cbe46
--- /dev/null
+++ b/src/net/java/games/jogl/impl/GLContextLock.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2003 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
+ * MIDROSYSTEMS, 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 net.java.games.jogl.impl;
+
+import net.java.games.jogl.*;
+
+/** Implements the makeCurrent / release locking behavior of the
+ GLContext class. When "fail fast mode" is enabled, attempts to
+ lock the same GLContextLock on more than one thread cause
+ GLException to be raised. This lock is not recursive. Attempts to
+ lock it more than once on a given thread will cause GLException to
+ be raised. */
+
+public class GLContextLock {
+ private Object lock = new Object();
+ private Thread owner;
+ private boolean failFastMode = true;
+
+ /** Locks this GLContextLock on the current thread. If fail fast
+ mode is enabled and the GLContextLock is already owned by
+ another thread, throws GLException. */
+ public void lock() throws GLException {
+ synchronized(lock) {
+ Thread current = Thread.currentThread();
+ if (owner == null) {
+ owner = current;
+ } else if (owner != current) {
+ while (owner != null) {
+ if (failFastMode) {
+ throw new GLException("Attempt to make context current on thread " + current +
+ " which is already current on thread " + owner);
+ } else {
+ try {
+ lock.wait();
+ } catch (InterruptedException e) {
+ throw new GLException(e);
+ }
+ }
+ }
+ owner = current;
+ } else {
+ throw new GLException("Attempt to make the same context current twice on thread " + current);
+ }
+ }
+ }
+
+ /** Unlocks this GLContextLock. */
+ public void unlock() throws GLException {
+ synchronized (lock) {
+ Thread current = Thread.currentThread();
+ if (owner == current) {
+ owner = null;
+ lock.notifyAll();
+ } else {
+ if (owner != null) {
+ throw new GLException("Attempt by thread " + current +
+ " to release context owned by thread " + owner);
+ } else {
+ throw new GLException("Attempt by thread " + current +
+ " to release unowned context");
+ }
+ }
+ }
+ }
+
+ /** Indicates whether this lock is held by the current thread. */
+ public boolean isHeld() {
+ synchronized(lock) {
+ Thread current = Thread.currentThread();
+ return (owner == current);
+ }
+ }
+
+ public void setFailFastMode(boolean onOrOff) {
+ failFastMode = onOrOff;
+ }
+
+ public boolean getFailFastMode() {
+ return failFastMode;
+ }
+}
diff --git a/src/net/java/games/jogl/impl/GLContextShareSet.java b/src/net/java/games/jogl/impl/GLContextShareSet.java
index 60c6b7d59..f2e1c595a 100644
--- a/src/net/java/games/jogl/impl/GLContextShareSet.java
+++ b/src/net/java/games/jogl/impl/GLContextShareSet.java
@@ -41,6 +41,7 @@ package net.java.games.jogl.impl;
import java.lang.ref.*;
import java.util.*;
+import net.java.games.jogl.*;
/** Provides a mechanism by which OpenGL contexts can share textures
and display lists in the face of multithreading and asynchronous
@@ -61,7 +62,8 @@ public class GLContextShareSet {
public void add(GLContext ctx) {
if (allShares.put(ctx, dummyValue) == null) {
- if (ctx.isCreated()) {
+ // FIXME: downcast to GLContextImpl undesirable
+ if (((GLContextImpl) ctx).isCreated()) {
createdShares.put(ctx, dummyValue);
} else {
destroyedShares.put(ctx, dummyValue);
diff --git a/src/net/java/games/jogl/impl/GLContextStack.java b/src/net/java/games/jogl/impl/GLContextStack.java
deleted file mode 100755
index 089d53525..000000000
--- a/src/net/java/games/jogl/impl/GLContextStack.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (c) 2003 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 net.java.games.jogl.impl;
-
-import java.util.*;
-
-/** Implements a stack of GLContext objects along with the initActions
- that need to be run if their creation is necessary. This is used
- to detect redundant makeCurrent() calls and to allow one drawable
- to call display() of another from within the first drawable's
- display() method. */
-
-public class GLContextStack {
- private ArrayList data = new ArrayList();
-
- /** Pushes this GLContext on the stack. The passed context must be non-null. */
- public void push(GLContext ctx, Runnable initAction) {
- if (ctx == null) {
- throw new IllegalArgumentException("Null contexts are not allowed here");
- }
-
- data.add(new GLContextInitActionPair(ctx, initAction));
- }
-
- /** Removes and returns the top GLContext and associated
- initialization action, or null if there is none. */
- public GLContextInitActionPair pop() {
- if (data.size() == 0) {
- return null;
- }
-
- return (GLContextInitActionPair) data.remove(data.size() - 1);
- }
-
- /** Returns the top GLContext and associated initialization action
- without removing it, or null if there is none. */
- public GLContextInitActionPair peek() {
- return peek(0);
- }
-
- /** Returns the <i>i</i>th GLContext and associated initialization
- action from the top without removing it, or null if there is
- none. */
- public GLContextInitActionPair peek(int i) {
- if (data.size() - i <= 0) {
- return null;
- }
-
- return (GLContextInitActionPair) data.get(data.size() - i - 1);
- }
-
- /** Returns the top GLContext without removing it, or null if there
- is none. */
- public GLContext peekContext() {
- return peekContext(0);
- }
-
- /** Returns the <i>i</i>th GLContext from the top without removing
- it, or null if there is none. */
- public GLContext peekContext(int i) {
- GLContextInitActionPair pair = peek(i);
- if (pair == null) {
- return null;
- }
-
- return pair.getContext();
- }
-
- /** Returns the top initialization action without removing it, or
- null if there is none. */
- public Runnable peekInitAction() {
- return peekInitAction(0);
- }
-
- /** Returns the <i>i</i>th initialization action from the top
- without removing it, or null if there is none. */
- public Runnable peekInitAction(int i) {
- GLContextInitActionPair pair = peek(i);
- if (pair == null) {
- return null;
- }
-
- return pair.getInitAction();
- }
-
- /** Returns the number of entries on the GLContext stack. */
- public int size() {
- return data.size();
- }
-}
diff --git a/src/net/java/games/jogl/impl/GLDrawableHelper.java b/src/net/java/games/jogl/impl/GLDrawableHelper.java
index dd5d7c17f..da164088f 100644
--- a/src/net/java/games/jogl/impl/GLDrawableHelper.java
+++ b/src/net/java/games/jogl/impl/GLDrawableHelper.java
@@ -42,11 +42,13 @@ package net.java.games.jogl.impl;
import java.util.*;
import net.java.games.jogl.*;
-/** Encapsulates the implementation of most of the GLDrawable's
+/** Encapsulates the implementation of most of the GLAutoDrawable's
methods to be able to share it between GLCanvas and GLJPanel. */
public class GLDrawableHelper {
private volatile List listeners = new ArrayList();
+ private static final boolean DEBUG = Debug.debug("GLDrawableHelper");
+ private static final boolean VERBOSE = Debug.verbose();
public GLDrawableHelper() {
}
@@ -63,22 +65,92 @@ public class GLDrawableHelper {
listeners = newListeners;
}
- public void init(GLDrawable drawable) {
+ public void init(GLAutoDrawable drawable) {
for (Iterator iter = listeners.iterator(); iter.hasNext(); ) {
((GLEventListener) iter.next()).init(drawable);
}
}
- public void display(GLDrawable drawable) {
+ public void display(GLAutoDrawable drawable) {
for (Iterator iter = listeners.iterator(); iter.hasNext(); ) {
((GLEventListener) iter.next()).display(drawable);
}
}
- public void reshape(GLDrawable drawable,
+ public void reshape(GLAutoDrawable drawable,
int x, int y, int width, int height) {
for (Iterator iter = listeners.iterator(); iter.hasNext(); ) {
((GLEventListener) iter.next()).reshape(drawable, x, y, width, height);
}
}
+
+ private static final ThreadLocal perThreadInitAction = new ThreadLocal();
+ private Runnable deferredReshapeAction;
+ /** Principal helper method which runs a Runnable with the context
+ made current. This could have been made part of GLContext, but a
+ desired goal is to be able to implement the GLCanvas in terms of
+ the GLContext's public APIs, and putting it into a separate
+ class helps ensure that we don't inadvertently use private
+ methods of the GLContext or its implementing classes. */
+ public void invokeGL(GLContext context,
+ Runnable runnable,
+ boolean isReshape,
+ Runnable initAction) {
+ // Support for recursive makeCurrent() calls as well as calling
+ // other drawables' display() methods from within another one's
+ GLContext lastContext = GLContext.getCurrent();
+ Runnable lastInitAction = (Runnable) perThreadInitAction.get();
+ if (lastContext != null) {
+ lastContext.release();
+ }
+
+ int res = 0;
+ try {
+ res = context.makeCurrent();
+ if (res == GLContext.CONTEXT_NOT_CURRENT) {
+ if (isReshape) {
+ if (DEBUG) {
+ System.err.println("GLDrawableHelper " + this + ".invokeGL(): Deferring reshape action");
+ }
+ deferredReshapeAction = runnable;
+ }
+ } else {
+ if (res == GLContext.CONTEXT_CURRENT_NEW) {
+ if (DEBUG) {
+ System.err.println("GLDrawableHelper " + this + ".invokeGL(): Running initAction");
+ }
+ initAction.run();
+ }
+ if (deferredReshapeAction != null) {
+ if (DEBUG) {
+ System.err.println("GLDrawableHelper " + this + ".invokeGL(): Running deferred reshape action");
+ }
+ Runnable act = deferredReshapeAction;
+ deferredReshapeAction = null;
+ act.run();
+ }
+ if (DEBUG && VERBOSE) {
+ System.err.println("GLDrawableHelper " + this + ".invokeGL(): Running runnable");
+ }
+ runnable.run();
+ // FIXME: must phrase this in terms of new GLDrawable swap buffer functionality
+ if (((GLContextImpl) context).getAutoSwapBufferMode()) {
+ ((GLContextImpl) context).swapBuffers();
+ }
+ }
+ } finally {
+ try {
+ if (res != GLContext.CONTEXT_NOT_CURRENT) {
+ context.release();
+ }
+ } catch (Exception e) {
+ }
+ if (lastContext != null) {
+ int res2 = lastContext.makeCurrent();
+ if (res2 == GLContext.CONTEXT_CURRENT_NEW) {
+ lastInitAction.run();
+ }
+ }
+ }
+ }
}
diff --git a/src/net/java/games/jogl/impl/GLPbufferImpl.java b/src/net/java/games/jogl/impl/GLPbufferImpl.java
index 7b17c3010..4e8bd7c63 100644
--- a/src/net/java/games/jogl/impl/GLPbufferImpl.java
+++ b/src/net/java/games/jogl/impl/GLPbufferImpl.java
@@ -53,13 +53,13 @@ import net.java.games.jogl.*;
public class GLPbufferImpl implements GLPbuffer {
// GLPbufferContext
- private GLContext context;
+ private GLContextImpl context;
private GLDrawableHelper drawableHelper = new GLDrawableHelper();
private boolean isInitialized=false;
private int floatMode;
public GLPbufferImpl(GLContext context) {
- this.context = context;
+ this.context = (GLContextImpl) context;
}
public void display() {
@@ -73,15 +73,12 @@ public class GLPbufferImpl implements GLPbuffer {
throw new GLException("Not yet implemented");
}
- public void setSize(Dimension d) {
- setSize(d.width, d.height);
- }
-
- public Dimension getSize() {
- return getSize(null);
+ public int getWidth() {
+ // FIXME
+ throw new GLException("Not yet implemented");
}
- public Dimension getSize(Dimension d) {
+ public int getHeight() {
// FIXME
throw new GLException("Not yet implemented");
}
@@ -110,26 +107,6 @@ public class GLPbufferImpl implements GLPbuffer {
context.setGLU(glu);
}
- void willSetRenderingThread() {
- // Not supported for pbuffers
- }
-
- public void setRenderingThread(Thread currentThreadOrNull) throws GLException {
- // Not supported for pbuffers
- }
-
- public Thread getRenderingThread() {
- // Not supported for pbuffers
- return null;
- }
-
- public void setNoAutoRedrawMode(boolean noAutoRedraws) {
- }
-
- public boolean getNoAutoRedrawMode() {
- return false;
- }
-
public void setAutoSwapBufferMode(boolean onOrOff) {
context.setAutoSwapBufferMode(onOrOff);
}
@@ -168,6 +145,11 @@ public class GLPbufferImpl implements GLPbuffer {
return context;
}
+ // FIXME: workaround for problems with deferring reshape actions
+ public GLDrawableHelper getDrawableHelper() {
+ return drawableHelper;
+ }
+
//----------------------------------------------------------------------
// No-ops for ComponentEvents
//
@@ -239,7 +221,7 @@ public class GLPbufferImpl implements GLPbuffer {
throw new GLException(e);
}
} else {
- context.invokeGL(invokeGLAction, isReshape, initAction);
+ drawableHelper.invokeGL(context, invokeGLAction, isReshape, initAction);
}
}
@@ -271,14 +253,14 @@ public class GLPbufferImpl implements GLPbuffer {
// being resized on the AWT event dispatch thread
class DisplayOnEventDispatchThreadAction implements Runnable {
public void run() {
- context.invokeGL(displayAction, false, initAction);
+ drawableHelper.invokeGL(context, displayAction, false, initAction);
}
}
private DisplayOnEventDispatchThreadAction displayOnEventDispatchThreadAction =
new DisplayOnEventDispatchThreadAction();
class SwapBuffersOnEventDispatchThreadAction implements Runnable {
public void run() {
- context.invokeGL(swapBuffersAction, false, initAction);
+ drawableHelper.invokeGL(context, swapBuffersAction, false, initAction);
}
}
private SwapBuffersOnEventDispatchThreadAction swapBuffersOnEventDispatchThreadAction =
diff --git a/src/net/java/games/jogl/impl/macosx/MacOSXGLContext.java b/src/net/java/games/jogl/impl/macosx/MacOSXGLContext.java
index 8cc33f8ff..b921116db 100644
--- a/src/net/java/games/jogl/impl/macosx/MacOSXGLContext.java
+++ b/src/net/java/games/jogl/impl/macosx/MacOSXGLContext.java
@@ -45,7 +45,7 @@ import net.java.games.gluegen.runtime.*; // for PROCADDRESS_VAR_PREFIX
import net.java.games.jogl.*;
import net.java.games.jogl.impl.*;
-public abstract class MacOSXGLContext extends GLContext
+public abstract class MacOSXGLContext extends GLContextImpl
{
private static JAWT jawt;
protected long nsContext; // NSOpenGLContext
@@ -119,7 +119,7 @@ public abstract class MacOSXGLContext extends GLContext
/**
* Creates and initializes an appropriate OpenGl nsContext. Should only be
- * called by {@link makeCurrent(Runnable)}.
+ * called by {@link makeCurrentImpl()}.
*/
protected boolean create(boolean pbuffer, boolean floatingPoint) {
MacOSXGLContext other = (MacOSXGLContext) GLContextShareSet.getShareContext(this);
@@ -165,7 +165,7 @@ public abstract class MacOSXGLContext extends GLContext
return true;
}
- protected synchronized boolean makeCurrent(Runnable initAction) throws GLException {
+ protected int makeCurrentImpl() throws GLException {
boolean created = false;
if (nsContext == 0) {
if (!create()) {
@@ -183,14 +183,12 @@ public abstract class MacOSXGLContext extends GLContext
if (created) {
resetGLFunctionAvailability();
- if (initAction != null) {
- initAction.run();
- }
+ return CONTEXT_CURRENT_NEW;
}
- return true;
+ return CONTEXT_CURRENT;
}
- protected synchronized void free() throws GLException {
+ protected void releaseImpl() throws GLException {
if (!CGL.clearCurrentContext(nsContext, nsView)) {
throw new GLException("Error freeing OpenGL nsContext");
}
diff --git a/src/net/java/games/jogl/impl/macosx/MacOSXOffscreenGLContext.java b/src/net/java/games/jogl/impl/macosx/MacOSXOffscreenGLContext.java
index 37b2302c0..39aab5652 100644
--- a/src/net/java/games/jogl/impl/macosx/MacOSXOffscreenGLContext.java
+++ b/src/net/java/games/jogl/impl/macosx/MacOSXOffscreenGLContext.java
@@ -83,7 +83,7 @@ public class MacOSXOffscreenGLContext extends MacOSXPbufferGLContext
throw new GLException("Should not call this");
}
- protected synchronized boolean makeCurrent(Runnable initAction) throws GLException {
+ protected int makeCurrentImpl() throws GLException {
if (pendingOffscreenResize && (nsContext != 0)) {
if (pendingOffscreenWidth != width || pendingOffscreenHeight != height) {
destroyPBuffer();
@@ -93,9 +93,9 @@ public class MacOSXOffscreenGLContext extends MacOSXPbufferGLContext
pendingOffscreenResize = false;
}
}
- return super.makeCurrent(initAction);
+ return super.makeCurrentImpl();
}
- public synchronized void swapBuffers() throws GLException {
+ public void swapBuffers() throws GLException {
}
}
diff --git a/src/net/java/games/jogl/impl/macosx/MacOSXOnscreenGLContext.java b/src/net/java/games/jogl/impl/macosx/MacOSXOnscreenGLContext.java
index ba4eee0ef..f2398aab8 100644
--- a/src/net/java/games/jogl/impl/macosx/MacOSXOnscreenGLContext.java
+++ b/src/net/java/games/jogl/impl/macosx/MacOSXOnscreenGLContext.java
@@ -53,6 +53,18 @@ public class MacOSXOnscreenGLContext extends MacOSXGLContext {
private JAWT_DrawingSurfaceInfo dsi;
private JAWT_MacOSXDrawingSurfaceInfo macosxdsi;
+ // Indicates whether the component (if an onscreen context) has been
+ // realized. Plausibly, before the component is realized the JAWT
+ // should return an error or NULL object from some of its
+ // operations; this appears to be the case on Win32 but is not true
+ // at least with Sun's current X11 implementation (1.4.x), which
+ // crashes with no other error reported if the DrawingSurfaceInfo is
+ // fetched from a locked DrawingSurface during the validation as a
+ // result of calling show() on the main thread. To work around this
+ // we prevent any JAWT or OpenGL operations from being done until
+ // addNotify() is called on the component.
+ protected boolean realized;
+
// Variables for pbuffer support
List pbuffersToInstantiate = new ArrayList();
@@ -82,8 +94,9 @@ public class MacOSXOnscreenGLContext extends MacOSXGLContext {
return true;
}
- public synchronized GLContext createPbufferContext(GLCapabilities capabilities, int initialWidth, int initialHeight) {
+ public GLContext createPbufferContext(GLCapabilities capabilities, int initialWidth, int initialHeight) {
MacOSXPbufferGLContext ctx = new MacOSXPbufferGLContext(capabilities, initialWidth, initialHeight);
+ ctx.setSynchronized(true);
GLContextShareSet.registerSharing(this, ctx);
pbuffersToInstantiate.add(ctx);
return ctx;
@@ -97,22 +110,17 @@ public class MacOSXOnscreenGLContext extends MacOSXGLContext {
throw new GLException("Should not call this");
}
- public synchronized void setRenderingThread(Thread currentThreadOrNull, Runnable initAction) {
- this.willSetRenderingThread = false;
- // FIXME: the JAWT in the Panther developer release
- // requires all JAWT operations to be done on the AWT
- // thread. This means that setRenderingThread won't work
- // yet on this platform. This method can be deleted once
- // the update for that release ships.
- }
-
- protected synchronized boolean makeCurrent(Runnable initAction) throws GLException {
+ protected int makeCurrentImpl() throws GLException {
try {
+ if (!realized) {
+ return CONTEXT_NOT_CURRENT;
+ }
if (!lockSurface()) {
- return false;
+ return CONTEXT_NOT_CURRENT;
}
- boolean ret = super.makeCurrent(initAction);
- if (ret) {
+ int ret = super.makeCurrentImpl();
+ if ((ret == CONTEXT_CURRENT) ||
+ (ret == CONTEXT_CURRENT_NEW)) {
// Assume the canvas might have been resized or moved and tell the OpenGL
// context to update itself. This used to be done only upon receiving a
// reshape event but that doesn't appear to be sufficient. An experiment
@@ -142,15 +150,20 @@ public class MacOSXOnscreenGLContext extends MacOSXGLContext {
}
}
- protected synchronized void free() throws GLException {
+ protected void releaseImpl() throws GLException {
try {
- super.free();
+ super.releaseImpl();
} finally {
unlockSurface();
}
}
- public synchronized void swapBuffers() throws GLException {
+ protected void destroyImpl() throws GLException {
+ realized = false;
+ super.destroyImpl();
+ }
+
+ public void swapBuffers() throws GLException {
if (!CGL.flushBuffer(nsContext, nsView)) {
throw new GLException("Error swapping buffers");
}
diff --git a/src/net/java/games/jogl/impl/macosx/MacOSXPbufferGLContext.java b/src/net/java/games/jogl/impl/macosx/MacOSXPbufferGLContext.java
index 6c8004bee..b163bb9ce 100644
--- a/src/net/java/games/jogl/impl/macosx/MacOSXPbufferGLContext.java
+++ b/src/net/java/games/jogl/impl/macosx/MacOSXPbufferGLContext.java
@@ -104,7 +104,7 @@ public class MacOSXPbufferGLContext extends MacOSXGLContext {
}
}
- protected synchronized boolean makeCurrent(Runnable initAction) throws GLException {
+ protected int makeCurrentImpl() throws GLException {
created = false;
if (pBuffer == 0) {
@@ -112,10 +112,10 @@ public class MacOSXPbufferGLContext extends MacOSXGLContext {
System.err.println("Pbuffer not instantiated yet for " + this);
}
// pbuffer not instantiated yet
- return false;
+ return CONTEXT_NOT_CURRENT;
}
- boolean res = super.makeCurrent(initAction);
+ int res = super.makeCurrentImpl();
if (created) {
// Initialize render-to-texture support if requested
boolean rect = capabilities.getOffscreenRenderToTextureRectangle();
diff --git a/src/net/java/games/jogl/impl/mipmap/BuildMipmap.java b/src/net/java/games/jogl/impl/mipmap/BuildMipmap.java
index 9c9c3122b..06a6a02bc 100644
--- a/src/net/java/games/jogl/impl/mipmap/BuildMipmap.java
+++ b/src/net/java/games/jogl/impl/mipmap/BuildMipmap.java
@@ -46,7 +46,8 @@ import java.io.*;
*/
public class BuildMipmap {
- private static boolean DEBUG = Debug.debug("BuildMipmap");
+ private static final boolean DEBUG = Debug.debug("BuildMipmap");
+ private static final boolean VERBOSE = Debug.verbose();
/** Creates a new instance of BuildMipmap */
public BuildMipmap() {
@@ -663,16 +664,18 @@ public class BuildMipmap {
gl.glTexImage2D( target, level, internalFormat, newwidth, newheight, 0, format, type, srcImage );
if (DEBUG) {
System.err.println("GL Error(" + level + "): " + gl.glGetError() );
- try {
- File file = new File( "glu2DMipmapJ" + level + ".bin" );
- FileOutputStream fos = new FileOutputStream( file );
- srcImage.limit( Mipmap.image_size( newwidth, newheight, format, type ) );
- fos.getChannel().write( srcImage );
- srcImage.clear();
- fos.close();
- } catch( IOException e ) {
- System.err.println("IOException");
- System.err.println(e.getMessage());
+ if (VERBOSE) {
+ try {
+ File file = new File( "glu2DMipmapJ" + level + ".bin" );
+ FileOutputStream fos = new FileOutputStream( file );
+ srcImage.limit( Mipmap.image_size( newwidth, newheight, format, type ) );
+ fos.getChannel().write( srcImage );
+ srcImage.clear();
+ fos.close();
+ } catch( IOException e ) {
+ System.err.println("IOException");
+ System.err.println(e.getMessage());
+ }
}
}
}
@@ -769,15 +772,17 @@ public class BuildMipmap {
gl.glTexImage2D( target, level, internalFormat, newwidth, newheight, 0, format, type, srcImage );
if (DEBUG) {
System.err.println("GL Error(" + level + "): " + gl.glGetError() );
- try {
- File file = new File( "glu2DMipmapJ" + level + ".bin" );
- FileOutputStream fos = new FileOutputStream( file );
- srcImage.limit( Mipmap.image_size( newwidth, newheight, format, type ) );
- fos.getChannel().write( srcImage );
- srcImage.clear();
- } catch( IOException e ) {
- System.err.println("IOException");
- System.err.println(e.getMessage());
+ if (VERBOSE) {
+ try {
+ File file = new File( "glu2DMipmapJ" + level + ".bin" );
+ FileOutputStream fos = new FileOutputStream( file );
+ srcImage.limit( Mipmap.image_size( newwidth, newheight, format, type ) );
+ fos.getChannel().write( srcImage );
+ srcImage.clear();
+ } catch( IOException e ) {
+ System.err.println("IOException");
+ System.err.println(e.getMessage());
+ }
}
}
}
@@ -817,15 +822,17 @@ public class BuildMipmap {
gl.glTexImage2D( target, level, internalFormat, newwidth, newheight, 0, format, type, newMipmapImage );
if (DEBUG) {
System.err.println("GL Error: " + gl.glGetError() );
- try {
- File file = new File( "glu2DMipmapJ" + level + ".bin" );
- FileOutputStream fos = new FileOutputStream( file );
- srcImage.limit( Mipmap.image_size( newwidth, newheight, format, type ) );
- fos.getChannel().write( newMipmapImage );
- srcImage.clear();
- } catch( IOException e ) {
- System.err.println("IOException");
- System.err.println(e.getMessage());
+ if (VERBOSE) {
+ try {
+ File file = new File( "glu2DMipmapJ" + level + ".bin" );
+ FileOutputStream fos = new FileOutputStream( file );
+ srcImage.limit( Mipmap.image_size( newwidth, newheight, format, type ) );
+ fos.getChannel().write( newMipmapImage );
+ srcImage.clear();
+ } catch( IOException e ) {
+ System.err.println("IOException");
+ System.err.println(e.getMessage());
+ }
}
}
}
diff --git a/src/net/java/games/jogl/impl/windows/WindowsGLContext.java b/src/net/java/games/jogl/impl/windows/WindowsGLContext.java
index e938c8023..338b11e6a 100644
--- a/src/net/java/games/jogl/impl/windows/WindowsGLContext.java
+++ b/src/net/java/games/jogl/impl/windows/WindowsGLContext.java
@@ -48,7 +48,7 @@ import net.java.games.gluegen.runtime.*; // for PROCADDRESS_VAR_PREFIX
import net.java.games.jogl.*;
import net.java.games.jogl.impl.*;
-public abstract class WindowsGLContext extends GLContext {
+public abstract class WindowsGLContext extends GLContextImpl {
private static JAWT jawt;
protected long hglrc;
protected long hdc;
@@ -124,11 +124,11 @@ public abstract class WindowsGLContext extends GLContext {
/**
* Creates and initializes an appropriate OpenGL context. Should only be
- * called by {@link #makeCurrent(Runnable)}.
+ * called by {@link #makeCurrentImpl()}.
*/
protected abstract void create();
- protected synchronized boolean makeCurrent(Runnable initAction) throws GLException {
+ protected int makeCurrentImpl() throws GLException {
boolean created = false;
if (hglrc == 0) {
create();
@@ -177,13 +177,12 @@ public abstract class WindowsGLContext extends GLContext {
}
}
GLContextShareSet.contextCreated(this);
-
- initAction.run();
+ return CONTEXT_CURRENT_NEW;
}
- return true;
+ return CONTEXT_CURRENT;
}
- protected synchronized void free() throws GLException {
+ protected void releaseImpl() throws GLException {
if (!NO_FREE) {
if (!WGL.wglMakeCurrent(0, 0)) {
throw new GLException("Error freeing OpenGL context: " + WGL.GetLastError());
diff --git a/src/net/java/games/jogl/impl/windows/WindowsOffscreenGLContext.java b/src/net/java/games/jogl/impl/windows/WindowsOffscreenGLContext.java
index c70607da7..d944a8684 100644
--- a/src/net/java/games/jogl/impl/windows/WindowsOffscreenGLContext.java
+++ b/src/net/java/games/jogl/impl/windows/WindowsOffscreenGLContext.java
@@ -92,9 +92,9 @@ public class WindowsOffscreenGLContext extends WindowsGLContext {
return false;
}
- public synchronized GLContext createPbufferContext(GLCapabilities capabilities,
- int initialWidth,
- int initialHeight) {
+ public GLContext createPbufferContext(GLCapabilities capabilities,
+ int initialWidth,
+ int initialHeight) {
throw new GLException("Not supported");
}
@@ -106,7 +106,7 @@ public class WindowsOffscreenGLContext extends WindowsGLContext {
throw new GLException("Should not call this");
}
- protected synchronized boolean makeCurrent(Runnable initAction) throws GLException {
+ protected int makeCurrentImpl() throws GLException {
if (pendingOffscreenResize) {
if (pendingOffscreenWidth != width || pendingOffscreenHeight != height) {
if (hglrc != 0) {
@@ -117,7 +117,7 @@ public class WindowsOffscreenGLContext extends WindowsGLContext {
pendingOffscreenResize = false;
}
}
- return super.makeCurrent(initAction);
+ return super.makeCurrentImpl();
}
protected void destroyImpl() {
@@ -133,7 +133,7 @@ public class WindowsOffscreenGLContext extends WindowsGLContext {
}
}
- public synchronized void swapBuffers() throws GLException {
+ public void swapBuffers() throws GLException {
}
protected void create() {
diff --git a/src/net/java/games/jogl/impl/windows/WindowsOnscreenGLContext.java b/src/net/java/games/jogl/impl/windows/WindowsOnscreenGLContext.java
index 0dc1818fb..d4af4b3b7 100644
--- a/src/net/java/games/jogl/impl/windows/WindowsOnscreenGLContext.java
+++ b/src/net/java/games/jogl/impl/windows/WindowsOnscreenGLContext.java
@@ -51,6 +51,18 @@ public class WindowsOnscreenGLContext extends WindowsGLContext {
JAWT_DrawingSurfaceInfo dsi;
JAWT_Win32DrawingSurfaceInfo win32dsi;
+ // Indicates whether the component (if an onscreen context) has been
+ // realized. Plausibly, before the component is realized the JAWT
+ // should return an error or NULL object from some of its
+ // operations; this appears to be the case on Win32 but is not true
+ // at least with Sun's current X11 implementation (1.4.x), which
+ // crashes with no other error reported if the DrawingSurfaceInfo is
+ // fetched from a locked DrawingSurface during the validation as a
+ // result of calling show() on the main thread. To work around this
+ // we prevent any JAWT or OpenGL operations from being done until
+ // addNotify() is called on the component.
+ protected boolean realized;
+
// Variables for pbuffer support
List pbuffersToInstantiate = new ArrayList();
@@ -61,6 +73,7 @@ public class WindowsOnscreenGLContext extends WindowsGLContext {
super(component, capabilities, chooser, shareWith);
}
+ /*
public void invokeGL(Runnable runnable, boolean isReshape, Runnable initAction) throws GLException {
// Unfortunately, invokeGL can be called with the AWT tree lock
// held, and the Windows onscreen implementation of
@@ -79,6 +92,7 @@ public class WindowsOnscreenGLContext extends WindowsGLContext {
super.invokeGL(runnable, isReshape, initAction);
}
}
+ */
protected GL createGL()
{
@@ -101,10 +115,11 @@ public class WindowsOnscreenGLContext extends WindowsGLContext {
return haveWGLARBPbuffer();
}
- public synchronized GLContext createPbufferContext(GLCapabilities capabilities,
- int initialWidth,
- int initialHeight) {
+ public GLContext createPbufferContext(GLCapabilities capabilities,
+ int initialWidth,
+ int initialHeight) {
WindowsPbufferGLContext ctx = new WindowsPbufferGLContext(capabilities, initialWidth, initialHeight);
+ ctx.setSynchronized(true);
pbuffersToInstantiate.add(ctx);
return ctx;
}
@@ -117,13 +132,21 @@ public class WindowsOnscreenGLContext extends WindowsGLContext {
throw new GLException("Should not call this");
}
- protected synchronized boolean makeCurrent(Runnable initAction) throws GLException {
+ public void setRealized() {
+ realized = true;
+ }
+
+ protected int makeCurrentImpl() throws GLException {
try {
+ if (!realized) {
+ return CONTEXT_NOT_CURRENT;
+ }
if (!lockSurface()) {
- return false;
+ return CONTEXT_NOT_CURRENT;
}
- boolean ret = super.makeCurrent(initAction);
- if (ret) {
+ int ret = super.makeCurrentImpl();
+ if ((ret == CONTEXT_CURRENT) ||
+ (ret == CONTEXT_CURRENT_NEW)) {
// Instantiate any pending pbuffers
while (!pbuffersToInstantiate.isEmpty()) {
WindowsPbufferGLContext ctx =
@@ -142,15 +165,20 @@ public class WindowsOnscreenGLContext extends WindowsGLContext {
}
}
- protected synchronized void free() throws GLException {
+ protected void releaseImpl() throws GLException {
try {
- super.free();
+ super.releaseImpl();
} finally {
unlockSurface();
}
}
- public synchronized void swapBuffers() throws GLException {
+ protected void destroyImpl() throws GLException {
+ realized = false;
+ super.destroyImpl();
+ }
+
+ public void swapBuffers() throws GLException {
if (!WGL.SwapBuffers(hdc) && (WGL.GetLastError() != 0)) {
throw new GLException("Error swapping buffers");
}
diff --git a/src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java b/src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java
index 26108a5cd..d58d15d02 100644
--- a/src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java
+++ b/src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java
@@ -382,7 +382,7 @@ public class WindowsPbufferGLContext extends WindowsGLContext {
}
}
- protected synchronized boolean makeCurrent(Runnable initAction) throws GLException {
+ protected int makeCurrentImpl() throws GLException {
created = false;
if (buffer == 0) {
@@ -390,10 +390,10 @@ public class WindowsPbufferGLContext extends WindowsGLContext {
if (DEBUG) {
System.err.println("pbuffer not instantiated yet");
}
- return false;
+ return CONTEXT_NOT_CURRENT;
}
- boolean res = super.makeCurrent(initAction);
+ int res = super.makeCurrentImpl();
if (DEBUG) {
System.err.println("super.makeCurrent() = " + res + ", created = " + created);
}
diff --git a/src/net/java/games/jogl/impl/x11/X11GLContext.java b/src/net/java/games/jogl/impl/x11/X11GLContext.java
index 837b7b791..7077c855e 100644
--- a/src/net/java/games/jogl/impl/x11/X11GLContext.java
+++ b/src/net/java/games/jogl/impl/x11/X11GLContext.java
@@ -46,7 +46,7 @@ import net.java.games.gluegen.runtime.*; // for PROCADDRESS_VAR_PREFIX
import net.java.games.jogl.*;
import net.java.games.jogl.impl.*;
-public abstract class X11GLContext extends GLContext {
+public abstract class X11GLContext extends GLContextImpl {
protected long display;
protected long drawable;
protected long visualID;
@@ -126,19 +126,9 @@ public abstract class X11GLContext extends GLContext {
public abstract boolean offscreenImageNeedsVerticalFlip();
- public synchronized void setRenderingThread(Thread currentThreadOrNull, Runnable initAction) {
- this.willSetRenderingThread = false;
- // FIXME: the JAWT on X11 grabs the AWT lock while the
- // DrawingSurface is locked, which means that no other events can
- // be processed. Currently we handle this by preventing the
- // effects of setRenderingThread. We should figure out a better
- // solution that is reasonably robust. Must file a bug to be fixed
- // in the 1.5 JAWT.
- }
-
/**
* Creates and initializes an appropriate OpenGl context. Should only be
- * called by {@link makeCurrent(Runnable)}.
+ * called by {@link makeCurrentImpl()}.
*/
protected abstract void create();
@@ -150,7 +140,7 @@ public abstract class X11GLContext extends GLContext {
return super.isExtensionAvailable(glExtensionName);
}
- protected synchronized boolean makeCurrent(Runnable initAction) throws GLException {
+ protected int makeCurrentImpl() throws GLException {
boolean created = false;
if (context == 0) {
create();
@@ -172,12 +162,12 @@ public abstract class X11GLContext extends GLContext {
if (created) {
resetGLFunctionAvailability();
- initAction.run();
+ return CONTEXT_CURRENT_NEW;
}
- return true;
+ return CONTEXT_CURRENT;
}
- protected synchronized void free() throws GLException {
+ protected void releaseImpl() throws GLException {
if (!GLX.glXMakeCurrent(display, 0, 0)) {
throw new GLException("Error freeing OpenGL context");
}
diff --git a/src/net/java/games/jogl/impl/x11/X11OffscreenGLContext.java b/src/net/java/games/jogl/impl/x11/X11OffscreenGLContext.java
index 2e30e2b18..c493d3380 100644
--- a/src/net/java/games/jogl/impl/x11/X11OffscreenGLContext.java
+++ b/src/net/java/games/jogl/impl/x11/X11OffscreenGLContext.java
@@ -95,9 +95,9 @@ public class X11OffscreenGLContext extends X11GLContext {
return false;
}
- public synchronized GLContext createPbufferContext(GLCapabilities capabilities,
- int initialWidth,
- int initialHeight) {
+ public GLContext createPbufferContext(GLCapabilities capabilities,
+ int initialWidth,
+ int initialHeight) {
throw new GLException("Not supported");
}
@@ -109,7 +109,7 @@ public class X11OffscreenGLContext extends X11GLContext {
throw new GLException("Should not call this");
}
- protected synchronized boolean makeCurrent(Runnable initAction) throws GLException {
+ protected int makeCurrentImpl() throws GLException {
display = X11GLContextFactory.getDisplayConnection();
if (pendingOffscreenResize) {
if (pendingOffscreenWidth != width || pendingOffscreenHeight != height) {
@@ -122,15 +122,15 @@ public class X11OffscreenGLContext extends X11GLContext {
}
}
mostRecentDisplay = display;
- return super.makeCurrent(initAction);
+ return super.makeCurrentImpl();
}
- public synchronized void swapBuffers() throws GLException {
+ public void swapBuffers() throws GLException {
}
- protected synchronized void free() throws GLException {
+ protected void releaseImpl() throws GLException {
try {
- super.free();
+ super.releaseImpl();
} finally {
display = 0;
}
diff --git a/src/net/java/games/jogl/impl/x11/X11OnscreenGLContext.java b/src/net/java/games/jogl/impl/x11/X11OnscreenGLContext.java
index 2fd340d79..5a6fe23bb 100644
--- a/src/net/java/games/jogl/impl/x11/X11OnscreenGLContext.java
+++ b/src/net/java/games/jogl/impl/x11/X11OnscreenGLContext.java
@@ -51,6 +51,18 @@ public class X11OnscreenGLContext extends X11GLContext {
private JAWT_DrawingSurfaceInfo dsi;
private JAWT_X11DrawingSurfaceInfo x11dsi;
+ // Indicates whether the component (if an onscreen context) has been
+ // realized. Plausibly, before the component is realized the JAWT
+ // should return an error or NULL object from some of its
+ // operations; this appears to be the case on Win32 but is not true
+ // at least with Sun's current X11 implementation (1.4.x), which
+ // crashes with no other error reported if the DrawingSurfaceInfo is
+ // fetched from a locked DrawingSurface during the validation as a
+ // result of calling show() on the main thread. To work around this
+ // we prevent any JAWT or OpenGL operations from being done until
+ // addNotify() is called on the component.
+ protected boolean realized;
+
// Variables for pbuffer support
List pbuffersToInstantiate = new ArrayList();
@@ -83,10 +95,11 @@ public class X11OnscreenGLContext extends X11GLContext {
return true;
}
- public synchronized GLContext createPbufferContext(GLCapabilities capabilities,
- int initialWidth,
- int initialHeight) {
+ public GLContext createPbufferContext(GLCapabilities capabilities,
+ int initialWidth,
+ int initialHeight) {
X11PbufferGLContext ctx = new X11PbufferGLContext(capabilities, initialWidth, initialHeight);
+ ctx.setSynchronized(true);
pbuffersToInstantiate.add(ctx);
return ctx;
}
@@ -106,13 +119,21 @@ public class X11OnscreenGLContext extends X11GLContext {
}
}
- protected synchronized boolean makeCurrent(Runnable initAction) throws GLException {
+ public void setRealized() {
+ realized = true;
+ }
+
+ protected int makeCurrentImpl() throws GLException {
try {
+ if (!realized) {
+ return CONTEXT_NOT_CURRENT;
+ }
if (!lockSurface()) {
- return false;
+ return CONTEXT_NOT_CURRENT;
}
- boolean ret = super.makeCurrent(initAction);
- if (ret) {
+ int ret = super.makeCurrentImpl();
+ if ((ret == CONTEXT_CURRENT) ||
+ (ret == CONTEXT_CURRENT_NEW)) {
// Instantiate any pending pbuffers
while (!pbuffersToInstantiate.isEmpty()) {
X11PbufferGLContext ctx =
@@ -131,15 +152,20 @@ public class X11OnscreenGLContext extends X11GLContext {
}
}
- protected synchronized void free() throws GLException {
+ protected void releaseImpl() throws GLException {
try {
- super.free();
+ super.releaseImpl();
} finally {
unlockSurface();
}
}
- public synchronized void swapBuffers() throws GLException {
+ protected void destroyImpl() throws GLException {
+ realized = false;
+ super.destroyImpl();
+ }
+
+ public void swapBuffers() throws GLException {
// FIXME: this cast to int would be wrong on 64-bit platforms
// where the argument type to glXMakeCurrent would change (should
// probably make GLXDrawable, and maybe XID, Opaque as long)
diff --git a/src/net/java/games/jogl/impl/x11/X11PbufferGLContext.java b/src/net/java/games/jogl/impl/x11/X11PbufferGLContext.java
index 7733472fb..30a60ba61 100644
--- a/src/net/java/games/jogl/impl/x11/X11PbufferGLContext.java
+++ b/src/net/java/games/jogl/impl/x11/X11PbufferGLContext.java
@@ -234,10 +234,10 @@ public class X11PbufferGLContext extends X11GLContext {
}
}
- protected synchronized boolean makeCurrent(Runnable initAction) throws GLException {
+ protected int makeCurrentImpl() throws GLException {
if (buffer == 0) {
// pbuffer not instantiated yet
- return false;
+ return CONTEXT_NOT_CURRENT;
}
lockAWT();
@@ -257,15 +257,15 @@ public class X11PbufferGLContext extends X11GLContext {
if (created) {
resetGLFunctionAvailability();
- initAction.run();
+ return CONTEXT_CURRENT_NEW;
}
- return true;
+ return CONTEXT_CURRENT;
} finally {
unlockAWT();
}
}
- protected synchronized void free() throws GLException {
+ protected void releaseImpl() throws GLException {
lockAWT();
try {
if (!GLX.glXMakeContextCurrent(display, 0, 0, 0)) {