summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/native/jogl/MacOSXWindowSystemInterface.m6
-rw-r--r--src/net/java/games/jogl/Animator.java4
-rwxr-xr-xsrc/net/java/games/jogl/GLAutoDrawable.java68
-rw-r--r--src/net/java/games/jogl/GLCanvas.java71
-rwxr-xr-xsrc/net/java/games/jogl/GLContext.java7
-rw-r--r--src/net/java/games/jogl/GLDrawable.java103
-rw-r--r--src/net/java/games/jogl/GLDrawableFactory.java30
-rw-r--r--src/net/java/games/jogl/GLJPanel.java142
-rw-r--r--src/net/java/games/jogl/impl/GLContextFactory.java12
-rwxr-xr-xsrc/net/java/games/jogl/impl/GLContextImpl.java76
-rw-r--r--src/net/java/games/jogl/impl/GLDrawableHelper.java36
-rw-r--r--src/net/java/games/jogl/impl/GLDrawableImpl.java52
-rw-r--r--src/net/java/games/jogl/impl/GLPbufferImpl.java61
-rw-r--r--src/net/java/games/jogl/impl/macosx/MacOSXDummyGLContext.java32
-rw-r--r--src/net/java/games/jogl/impl/macosx/MacOSXGLContext.java119
-rw-r--r--src/net/java/games/jogl/impl/macosx/MacOSXGLContextFactory.java27
-rw-r--r--src/net/java/games/jogl/impl/macosx/MacOSXGLDrawable.java78
-rw-r--r--src/net/java/games/jogl/impl/macosx/MacOSXOffscreenGLContext.java45
-rw-r--r--src/net/java/games/jogl/impl/macosx/MacOSXOffscreenGLDrawable.java (renamed from src/net/java/games/jogl/GLContextHelper.java)39
-rw-r--r--src/net/java/games/jogl/impl/macosx/MacOSXOnscreenGLContext.java169
-rw-r--r--src/net/java/games/jogl/impl/macosx/MacOSXOnscreenGLDrawable.java236
-rw-r--r--src/net/java/games/jogl/impl/macosx/MacOSXPbufferGLContext.java132
-rw-r--r--src/net/java/games/jogl/impl/macosx/MacOSXPbufferGLDrawable.java152
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsGLContext.java515
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsGLContextFactory.java71
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsGLDrawable.java497
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsOffscreenGLContext.java103
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsOffscreenGLDrawable.java133
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsOnscreenGLContext.java193
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsOnscreenGLDrawable.java181
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java399
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsPbufferGLDrawable.java393
-rw-r--r--src/net/java/games/jogl/impl/x11/X11GLContext.java182
-rw-r--r--src/net/java/games/jogl/impl/x11/X11GLContextFactory.java23
-rw-r--r--src/net/java/games/jogl/impl/x11/X11GLDrawable.java172
-rw-r--r--src/net/java/games/jogl/impl/x11/X11OffscreenGLContext.java102
-rw-r--r--src/net/java/games/jogl/impl/x11/X11OffscreenGLDrawable.java143
-rw-r--r--src/net/java/games/jogl/impl/x11/X11OnscreenGLContext.java170
-rw-r--r--src/net/java/games/jogl/impl/x11/X11OnscreenGLDrawable.java174
-rw-r--r--src/net/java/games/jogl/impl/x11/X11PbufferGLContext.java266
-rw-r--r--src/net/java/games/jogl/impl/x11/X11PbufferGLDrawable.java254
41 files changed, 3218 insertions, 2450 deletions
diff --git a/src/native/jogl/MacOSXWindowSystemInterface.m b/src/native/jogl/MacOSXWindowSystemInterface.m
index 516bda0db..d74c083d6 100644
--- a/src/native/jogl/MacOSXWindowSystemInterface.m
+++ b/src/native/jogl/MacOSXWindowSystemInterface.m
@@ -163,13 +163,17 @@ void* createPBuffer(int renderTarget, int internalFormat, int width, int height)
}
Bool destroyPBuffer(void* context, void* buffer) {
- NSOpenGLContext *nsContext = (NSOpenGLContext*)context;
+ /* FIXME: not clear whether we need to perform the clearDrawable below */
+ /* FIXME: remove the context argument -- don't need it any more */
+ /* NSOpenGLContext *nsContext = (NSOpenGLContext*)context; */
NSOpenGLPixelBuffer *pBuffer = (NSOpenGLPixelBuffer*)buffer;
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ /*
if (nsContext != NULL) {
[nsContext clearDrawable];
}
+ */
[pBuffer release];
[pool release];
diff --git a/src/net/java/games/jogl/Animator.java b/src/net/java/games/jogl/Animator.java
index 06fb25cca..c2f7eeb6e 100644
--- a/src/net/java/games/jogl/Animator.java
+++ b/src/net/java/games/jogl/Animator.java
@@ -60,13 +60,13 @@ import net.java.games.jogl.impl.SingleThreadedWorkaround;
*/
public class Animator {
- private GLDrawable drawable;
+ private GLAutoDrawable drawable;
private Runnable runnable;
private Thread thread;
private boolean shouldStop;
/** Creates a new Animator for a particular drawable. */
- public Animator(GLDrawable drawable) {
+ public Animator(GLAutoDrawable drawable) {
this.drawable = drawable;
}
diff --git a/src/net/java/games/jogl/GLAutoDrawable.java b/src/net/java/games/jogl/GLAutoDrawable.java
index 2b7528069..d9afd4599 100755
--- a/src/net/java/games/jogl/GLAutoDrawable.java
+++ b/src/net/java/games/jogl/GLAutoDrawable.java
@@ -40,6 +40,12 @@
package net.java.games.jogl;
public interface GLAutoDrawable extends GLDrawable, ComponentEvents {
+ /**
+ * Returns the context associated with this drawable. The returned
+ * context will be synchronized.
+ */
+ public GLContext getContext();
+
/** 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. */
@@ -51,4 +57,66 @@ public interface GLAutoDrawable extends GLDrawable, ComponentEvents {
guaranteed that all other listeners will be evaluated properly
during this update cycle. */
public void removeGLEventListener(GLEventListener listener);
+
+ /** Causes OpenGL rendering to be performed for this GLAutoDrawable
+ by calling {@link GLEventListener#display} for all registered
+ {@link GLEventListener}s. Called automatically by the window
+ system toolkit upon receiving a repaint() request. this routine
+ may be called manually for better control over the rendering
+ process. It is legal to call another GLAutoDrawable's display
+ method from within {@link GLEventListener#display}. */
+ public void display();
+
+ /** 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
+ front and back buffers are swapped, displaying the results of
+ the render. When disabled, the user is responsible for calling
+ {@link #swapBuffers} manually. */
+ public void setAutoSwapBufferMode(boolean onOrOff);
+
+ /** Indicates whether automatic buffer swapping is enabled for this
+ drawable. See {@link #setAutoSwapBufferMode}. */
+ public boolean getAutoSwapBufferMode();
+
+ /** Returns the {@link GL} pipeline object this GLDrawable uses. If
+ this method is called outside of the {@link GLEventListener}'s
+ callback methods (init, display, etc.) it may return null. Users
+ should not rely on the identity of the returned GL object; for
+ example, users should not maintain a hash table with the GL
+ object as the key. Additionally, the GL object should not be
+ cached in client code, but should be re-fetched from the
+ GLDrawable at the beginning of each call to init, display,
+ etc. */
+ public GL getGL();
+
+ /** Sets the {@link GL} pipeline object this GLDrawable uses. This
+ should only be called from within the GLEventListener's callback
+ methods, and usually only from within the init() method, in
+ order to install a composable pipeline. See the JOGL demos for
+ examples. */
+ public void setGL(GL gl);
+
+ /** Returns the {@link GLU} pipeline object this GLDrawable uses. */
+ public GLU getGLU();
+
+ /** Sets the {@link GLU} pipeline object this GLDrawable uses. */
+ public void setGLU(GLU glu);
+
+ /** Indicates whether this drawable is capable of fabricating a
+ subordinate offscreen drawable for advanced rendering techniques
+ which require offscreen hardware-accelerated surfaces. Note that
+ this method is only guaranteed to return a correct result once
+ your GLEventListener's init() method has been called. */
+ public boolean canCreateOffscreenDrawable();
+
+ /** Creates a subordinate offscreen drawable (pbuffer) for this
+ drawable. This routine should only be called if {@link
+ #canCreateOffscreenDrawable} returns true. The passed
+ capabilities are matched according to the platform-dependent
+ pbuffer format selection algorithm, which currently can not be
+ overridden. */
+ public GLPbuffer createOffscreenDrawable(GLCapabilities capabilities,
+ int initialWidth,
+ int initialHeight);
}
diff --git a/src/net/java/games/jogl/GLCanvas.java b/src/net/java/games/jogl/GLCanvas.java
index e7a15ccf9..29ce3a701 100644
--- a/src/net/java/games/jogl/GLCanvas.java
+++ b/src/net/java/games/jogl/GLCanvas.java
@@ -63,18 +63,28 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
protected static final boolean DEBUG = Debug.debug("GLCanvas");
private GLDrawableHelper drawableHelper = new GLDrawableHelper();
+ private GLDrawable drawable;
private GLContextImpl context;
+ private boolean autoSwapBufferMode = true;
+ private boolean sendReshape = false;
public GLCanvas(GLCapabilities capabilities,
GLCapabilitiesChooser chooser,
- GLDrawable shareWith,
+ GLContext shareWith,
GraphicsDevice device) {
super(GLDrawableFactory.getFactory().chooseGraphicsConfiguration(capabilities, chooser, device));
- context = (GLContextImpl) GLContextFactory.getFactory().createGLContext(this, capabilities, chooser,
- GLContextHelper.getContext(shareWith));
+ drawable = GLDrawableFactory.getFactory().getGLDrawable(this, capabilities, chooser);
+ context = (GLContextImpl) drawable.createContext(shareWith);
context.setSynchronized(true);
}
+ public GLContext createContext(GLContext shareWith) {
+ return drawable.createContext(shareWith);
+ }
+
+ public void setRealized(boolean realized) {
+ }
+
public void display() {
maybeDoSingleThreadedWorkaround(displayOnEventDispatchThreadAction,
displayAction,
@@ -91,7 +101,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
create an OpenGL context for the component. */
public void addNotify() {
super.addNotify();
- context.setRealized();
+ drawable.setRealized(true);
if (DEBUG) {
System.err.println("GLCanvas.addNotify()");
}
@@ -101,6 +111,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
safe to have an OpenGL context for the component. */
public void removeNotify() {
context.destroy();
+ drawable.setRealized(false);
super.removeNotify();
if (DEBUG) {
System.err.println("GLCanvas.removeNotify()");
@@ -113,24 +124,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
directly. */
public void reshape(int x, int y, int width, int height) {
super.reshape(x, y, width, height);
- // Note: we ignore the given x and y within the parent component
- // since we are drawing directly into this heavyweight component.
- final int fx = 0;
- final int fy = 0;
- final int fwidth = width;
- final int fheight = height;
- final Runnable reshapeRunnable = new Runnable() {
- public void run() {
- getGL().glViewport(fx, fy, fwidth, fheight);
- drawableHelper.reshape(GLCanvas.this, fx, fy, fwidth, fheight);
- }
- };
- final Runnable reshapeOnEDTRunnable = new Runnable() {
- public void run() {
- drawableHelper.invokeGL(context, reshapeRunnable, true, initAction);
- }
- };
- maybeDoSingleThreadedWorkaround(reshapeOnEDTRunnable, reshapeRunnable, true);
+ sendReshape = true;
}
/** Overridden from Canvas to prevent Java2D's clearing of the
@@ -147,6 +141,10 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
drawableHelper.removeGLEventListener(listener);
}
+ public GLContext getContext() {
+ return context;
+ }
+
public GL getGL() {
return context.getGL();
}
@@ -164,11 +162,11 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
}
public void setAutoSwapBufferMode(boolean onOrOff) {
- context.setAutoSwapBufferMode(onOrOff);
+ drawableHelper.setAutoSwapBufferMode(onOrOff);
}
public boolean getAutoSwapBufferMode() {
- return context.getAutoSwapBufferMode();
+ return drawableHelper.getAutoSwapBufferMode();
}
public void swapBuffers() {
@@ -182,11 +180,8 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
public GLPbuffer createOffscreenDrawable(GLCapabilities capabilities,
int initialWidth,
int initialHeight) {
- return new GLPbufferImpl(context.createPbufferContext(capabilities, initialWidth, initialHeight));
- }
-
- GLContext getContext() {
- return context;
+ // FIXME: add option to not share textures and display lists with parent context
+ return new GLPbufferImpl(context.createPbufferDrawable(capabilities, initialWidth, initialHeight), getContext());
}
//----------------------------------------------------------------------
@@ -213,7 +208,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
throw new GLException(e);
}
} else {
- drawableHelper.invokeGL(context, invokeGLAction, isReshape, initAction);
+ drawableHelper.invokeGL(drawable, context, invokeGLAction, initAction);
}
}
@@ -226,6 +221,16 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
class DisplayAction implements Runnable {
public void run() {
+ if (sendReshape) {
+ // Note: we ignore the given x and y within the parent component
+ // since we are drawing directly into this heavyweight component.
+ int width = getWidth();
+ int height = getHeight();
+ getGL().glViewport(0, 0, width, height);
+ drawableHelper.reshape(GLCanvas.this, 0, 0, width, height);
+ sendReshape = false;
+ }
+
drawableHelper.display(GLCanvas.this);
}
}
@@ -233,7 +238,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
class SwapBuffersAction implements Runnable {
public void run() {
- context.swapBuffers();
+ drawable.swapBuffers();
}
}
private SwapBuffersAction swapBuffersAction = new SwapBuffersAction();
@@ -243,14 +248,14 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
// being resized on the AWT event dispatch thread
class DisplayOnEventDispatchThreadAction implements Runnable {
public void run() {
- drawableHelper.invokeGL(context, displayAction, false, initAction);
+ drawableHelper.invokeGL(drawable, context, displayAction, initAction);
}
}
private DisplayOnEventDispatchThreadAction displayOnEventDispatchThreadAction =
new DisplayOnEventDispatchThreadAction();
class SwapBuffersOnEventDispatchThreadAction implements Runnable {
public void run() {
- drawableHelper.invokeGL(context, swapBuffersAction, false, initAction);
+ drawableHelper.invokeGL(drawable, context, swapBuffersAction, initAction);
}
}
private SwapBuffersOnEventDispatchThreadAction swapBuffersOnEventDispatchThreadAction =
diff --git a/src/net/java/games/jogl/GLContext.java b/src/net/java/games/jogl/GLContext.java
index 3e12b542c..18b94bc96 100755
--- a/src/net/java/games/jogl/GLContext.java
+++ b/src/net/java/games/jogl/GLContext.java
@@ -118,13 +118,6 @@ public abstract class GLContext {
}
/**
- * 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
diff --git a/src/net/java/games/jogl/GLDrawable.java b/src/net/java/games/jogl/GLDrawable.java
index 93fa6c580..3eea12448 100644
--- a/src/net/java/games/jogl/GLDrawable.java
+++ b/src/net/java/games/jogl/GLDrawable.java
@@ -61,10 +61,32 @@ package net.java.games.jogl;
// context whenever the displayChanged() function is called on our
// GLEventListeners
-/** Abstracts common functionality among the OpenGL components {@link
- GLCanvas} and {@link GLJPanel}. */
+public interface GLDrawable {
+ /**
+ * Creates a new context for drawing to this drawable that will
+ * share display lists with the given GLContext.
+ *
+ * The GLContext <code>share</code> need not be associated with this
+ * GLDrawable.
+ */
+ public GLContext createContext(GLContext shareWith);
+
+ /**
+ * Indicates to on-screen GLDrawable implementations whether the
+ * underlying window has been created and can be drawn into. This
+ * must typically be called with an argument of <code>true</code> in
+ * the <code>addNotify</code> method of components performing OpenGL
+ * rendering and with an argument of <code>false</code> in the
+ * <code>removeNotify</code> method. Calling this method has no
+ * other effects. For example, if <code>removeNotify</code> is
+ * called on a Canvas implementation for which a GLDrawable has been
+ * created, it is also necessary to destroy all OpenGL contexts
+ * associated with that GLDrawable. This is not done automatically
+ * by the implementation. It is not necessary to call
+ * <code>setRealized</code> on either a GLCanvas or a GLJPanel.
+ */
+ public void setRealized(boolean realized);
-public interface GLDrawable extends ComponentEvents {
/** Requests a new width and height for this GLDrawable. Not all
drawables are able to respond to this request and may silently
ignore it. */
@@ -76,74 +98,9 @@ public interface GLDrawable extends ComponentEvents {
/** 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
- callback methods (init, display, etc.) it may return null. Users
- should not rely on the identity of the returned GL object; for
- example, users should not maintain a hash table with the GL
- object as the key. Additionally, the GL object should not be
- cached in client code, but should be re-fetched from the
- GLDrawable at the beginning of each call to init, display,
- etc. */
- public GL getGL();
-
- /** Sets the {@link GL} pipeline object this GLDrawable uses. This
- should only be called from within the GLEventListener's callback
- methods, and usually only from within the init() method, in
- order to install a composable pipeline. See the JOGL demos for
- examples. */
- public void setGL(GL gl);
-
- /** Returns the {@link GLU} pipeline object this GLDrawable uses. */
- public GLU getGLU();
-
- /** Sets the {@link GLU} pipeline object this GLDrawable uses. */
- public void setGLU(GLU glu);
-
- /** Causes OpenGL rendering to be performed for this GLDrawable by
- calling {@link GLEventListener#display} for all registered
- {@link GLEventListener}s. Called automatically by the window
- system toolkit upon receiving a repaint() request. When used in
- conjunction with {@link
- net.java.games.jogl.GLDrawable#setRenderingThread}, this routine
- may be called manually by the application's main loop for higher
- performance and better control over the rendering process. It is
- legal to call another GLDrawable's display method from within
- {@link GLEventListener#display}. */
- public void display();
-
- /** 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
- front and back buffers are swapped, displaying the results of
- the render. When disabled, the user is responsible for calling
- {@link #swapBuffers} manually. */
- public void setAutoSwapBufferMode(boolean onOrOff);
-
- /** Indicates whether automatic buffer swapping is enabled for this
- drawable. See {@link #setAutoSwapBufferMode}. */
- public boolean getAutoSwapBufferMode();
-
- /** Swaps the front and back buffers of this drawable. When
- automatic buffer swapping is enabled (as is the default), it is
- not necessary to call this method and doing so may have
- undefined results. */
- public void swapBuffers();
-
- /** Indicates whether this drawable is capable of fabricating a
- subordinate offscreen drawable for advanced rendering techniques
- which require offscreen hardware-accelerated surfaces. Note that
- this method is only guaranteed to return a correct result once
- your GLEventListener's init() method has been called. */
- public boolean canCreateOffscreenDrawable();
-
- /** Creates a subordinate offscreen drawable (pbuffer) for this
- drawable. This routine should only be called if {@link
- #canCreateOffscreenDrawable} returns true. The passed
- capabilities are matched according to the platform-dependent
- pbuffer format selection algorithm, which currently can not be
- overridden. */
- public GLPbuffer createOffscreenDrawable(GLCapabilities capabilities,
- int initialWidth,
- int initialHeight);
+ /** Swaps the front and back buffers of this drawable. For {@link
+ GLAutoDrawable} implementations, when automatic buffer swapping
+ is enabled (as is the default), it is not necessary to call this
+ method and doing so may have undefined results. */
+ public void swapBuffers() throws GLException;
}
diff --git a/src/net/java/games/jogl/GLDrawableFactory.java b/src/net/java/games/jogl/GLDrawableFactory.java
index c16be50ba..38a2b904f 100644
--- a/src/net/java/games/jogl/GLDrawableFactory.java
+++ b/src/net/java/games/jogl/GLDrawableFactory.java
@@ -118,8 +118,7 @@ public class GLDrawableFactory {
GLCapabilities capabilities,
GLCapabilitiesChooser chooser)
throws IllegalArgumentException, GLException {
- // FIXME
- throw new GLException("Not yet implemented");
+ return GLContextFactory.getFactory().getGLDrawable(target, capabilities, chooser);
}
//----------------------------------------------------------------------
@@ -136,15 +135,14 @@ public class GLDrawableFactory {
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. A null GraphicsDevice is
- equivalent to using that returned from
+ textures and display lists with the specified {@link GLContext};
+ the context must either be null or have been fabricated by
+ classes in this package. A null context indicates no sharing. A
+ null GraphicsDevice is equivalent to using that returned from
<code>GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice()</code>. */
public GLCanvas createGLCanvas(GLCapabilities capabilities,
GLCapabilitiesChooser chooser,
- GLDrawable shareWith,
+ GLContext shareWith,
GraphicsDevice device) {
if (chooser == null) {
chooser = new DefaultGLCapabilitiesChooser();
@@ -176,10 +174,10 @@ public class GLDrawableFactory {
/** Creates a {@link GLJPanel} with the specified capabilities using
the default capabilities selection algorithm. The panel 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 GLJPanel createGLJPanel(GLCapabilities capabilities, GLDrawable shareWith) {
+ GLContext}; the context must either be null or have been
+ fabricated by classes in this package. A null context indicates
+ no sharing. */
+ public GLJPanel createGLJPanel(GLCapabilities capabilities, GLContext shareWith) {
return createGLJPanel(capabilities, null, shareWith);
}
@@ -194,12 +192,12 @@ public class GLDrawableFactory {
the supplied capabilities selection algorithm. A null chooser is
equivalent to using the {@link DefaultGLCapabilitiesChooser}.
The panel 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. */
+ specified {@link GLContext}; the context must either be null or
+ have been fabricated by classes in this package. A null context
+ indicates no sharing. */
public GLJPanel createGLJPanel(GLCapabilities capabilities,
GLCapabilitiesChooser chooser,
- GLDrawable shareWith) {
+ GLContext shareWith) {
if (chooser == null) {
chooser = new DefaultGLCapabilitiesChooser();
}
diff --git a/src/net/java/games/jogl/GLJPanel.java b/src/net/java/games/jogl/GLJPanel.java
index 163330766..be8cc22e6 100644
--- a/src/net/java/games/jogl/GLJPanel.java
+++ b/src/net/java/games/jogl/GLJPanel.java
@@ -79,6 +79,7 @@ import net.java.games.jogl.impl.*;
public final class GLJPanel extends JPanel implements GLAutoDrawable {
protected static final boolean DEBUG = Debug.debug("GLJPanel");
+ protected static final boolean VERBOSE = Debug.verbose();
private GLDrawableHelper drawableHelper = new GLDrawableHelper();
private volatile boolean isInitialized;
@@ -86,7 +87,7 @@ public final class GLJPanel extends JPanel implements GLAutoDrawable {
// Data used for either pbuffers or pixmap-based offscreen surfaces
private GLCapabilities offscreenCaps;
private GLCapabilitiesChooser chooser;
- private GLDrawable shareWith;
+ private GLContext shareWith;
// This image is exactly the correct size to render into the panel
private BufferedImage offscreenImage;
// One of these is used to store the read back pixels before storing
@@ -102,6 +103,8 @@ public final class GLJPanel extends JPanel implements GLAutoDrawable {
private int awtFormat;
private int glFormat;
private int glType;
+ // Lazy reshape notification
+ private boolean sendReshape = true;
// Implementation using pbuffers
private static boolean hardwareAccelerationDisabled =
@@ -114,6 +117,7 @@ public final class GLJPanel extends JPanel implements GLAutoDrawable {
private Frame toplevel;
// Implementation using software rendering
+ private GLDrawableImpl offscreenDrawable;
private GLContextImpl offscreenContext;
// For saving/restoring of OpenGL state during ReadPixels
@@ -123,7 +127,7 @@ public final class GLJPanel extends JPanel implements GLAutoDrawable {
private int[] skippixels = new int[1];
private int[] alignment = new int[1];
- GLJPanel(GLCapabilities capabilities, GLCapabilitiesChooser chooser, GLDrawable shareWith) {
+ GLJPanel(GLCapabilities capabilities, GLCapabilitiesChooser chooser, GLContext shareWith) {
super();
// Works around problems on many vendors' cards; we don't need a
@@ -184,7 +188,7 @@ public final class GLJPanel extends JPanel implements GLAutoDrawable {
pbuffer.display();
}
} else {
- drawableHelper.invokeGL(offscreenContext, displayAction, false, initAction);
+ drawableHelper.invokeGL(offscreenDrawable, offscreenContext, displayAction, initAction);
}
}
@@ -205,15 +209,22 @@ public final class GLJPanel extends JPanel implements GLAutoDrawable {
if (!hardwareAccelerationDisabled) {
if (pbuffer != null) {
pbuffer.destroy();
+ pbuffer = null;
}
if (toplevel != null) {
toplevel.dispose();
+ toplevel = null;
+ heavyweight = null;
}
- pbuffer = null;
- heavyweight = null;
- toplevel = null;
} else {
- offscreenContext.destroy();
+ if (offscreenContext != null) {
+ offscreenContext.destroy();
+ offscreenContext = null;
+ }
+ if (offscreenDrawable != null) {
+ offscreenDrawable.destroy();
+ offscreenDrawable = null;
+ }
}
isInitialized = false;
super.removeNotify();
@@ -238,8 +249,6 @@ public final class GLJPanel extends JPanel implements GLAutoDrawable {
Runnable r = new Runnable() {
public void run() {
- GLContext context = null;
- GLDrawableHelper helper = drawableHelper;
readBackWidthInPixels = 0;
readBackHeightInPixels = 0;
@@ -256,9 +265,6 @@ public final class GLJPanel extends JPanel implements GLAutoDrawable {
if (pbuffer != null) {
pbuffer.destroy();
}
- if (toplevel != null) {
- toplevel.dispose();
- }
pbuffer = null;
isInitialized = false;
pbufferWidth = getNextPowerOf2(fwidth);
@@ -268,12 +274,6 @@ public final class GLJPanel extends JPanel implements GLAutoDrawable {
}
initialize();
}
- 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
@@ -285,8 +285,8 @@ public final class GLJPanel extends JPanel implements GLAutoDrawable {
readBackWidthInPixels = pbufferWidth;
readBackHeightInPixels = fheight;
} else {
- offscreenContext.resizeOffscreenContext(fwidth, fheight);
- context = offscreenContext;
+ offscreenContext.destroy();
+ offscreenDrawable.setSize(Math.max(1, fwidth), Math.max(1, fheight));
readBackWidthInPixels = fwidth;
readBackHeightInPixels = fheight;
}
@@ -298,19 +298,8 @@ public final class GLJPanel extends JPanel implements GLAutoDrawable {
panelWidth = fwidth;
panelHeight = fheight;
-
- 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);
- }
- }, true, initAction);
+
+ sendReshape = true;
}
};
if (EventQueue.isDispatchThread()) {
@@ -340,6 +329,25 @@ public final class GLJPanel extends JPanel implements GLAutoDrawable {
drawableHelper.removeGLEventListener(listener);
}
+ public GLContext createContext(GLContext shareWith) {
+ if (!hardwareAccelerationDisabled) {
+ return pbuffer.createContext(shareWith);
+ } else {
+ return offscreenDrawable.createContext(shareWith);
+ }
+ }
+
+ public void setRealized(boolean realized) {
+ }
+
+ public GLContext getContext() {
+ if (!hardwareAccelerationDisabled) {
+ return pbuffer.getContext();
+ } else {
+ return offscreenContext;
+ }
+ }
+
public GL getGL() {
if (!hardwareAccelerationDisabled) {
if (pbuffer == null) {
@@ -386,7 +394,7 @@ public final class GLJPanel extends JPanel implements GLAutoDrawable {
if (!hardwareAccelerationDisabled) {
pbuffer.setAutoSwapBufferMode(onOrOff);
} else {
- offscreenContext.setAutoSwapBufferMode(onOrOff);
+ drawableHelper.setAutoSwapBufferMode(onOrOff);
}
}
@@ -394,7 +402,7 @@ public final class GLJPanel extends JPanel implements GLAutoDrawable {
if (!hardwareAccelerationDisabled) {
return pbuffer.getAutoSwapBufferMode();
} else {
- return offscreenContext.getAutoSwapBufferMode();
+ return drawableHelper.getAutoSwapBufferMode();
}
}
@@ -402,7 +410,7 @@ public final class GLJPanel extends JPanel implements GLAutoDrawable {
if (!hardwareAccelerationDisabled) {
pbuffer.swapBuffers();
} else {
- drawableHelper.invokeGL(offscreenContext, swapBuffersAction, false, initAction);
+ drawableHelper.invokeGL(offscreenDrawable, offscreenContext, swapBuffersAction, initAction);
}
}
@@ -418,30 +426,24 @@ public final class GLJPanel extends JPanel implements GLAutoDrawable {
throw new GLException("Not supported");
}
- GLContext getContext() {
- if (!hardwareAccelerationDisabled) {
- return ((GLPbufferImpl) pbuffer).getContext();
- } else {
- return offscreenContext;
- }
- }
-
//----------------------------------------------------------------------
// Internals only below this point
//
private void disableHardwareRendering() {
- if (Debug.verbose()) {
+ if (VERBOSE) {
System.err.println("GLJPanel: Falling back on software rendering due to pbuffer problems");
}
hardwareAccelerationDisabled = true;
pbufferInitializationCompleted = false;
EventQueue.invokeLater(new Runnable() {
public void run() {
- toplevel.setVisible(false);
- // Should dispose of this -- not sure about stability on
- // various cards -- should test (FIXME)
- // toplevel.dispose();
+ if (toplevel != null) {
+ toplevel.setVisible(false);
+ toplevel.dispose();
+ toplevel = null;
+ heavyweight = null;
+ }
}
});
initialize();
@@ -460,7 +462,10 @@ public final class GLJPanel extends JPanel implements GLAutoDrawable {
heavyweight = GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities(), null, shareWith, null);
firstTime = true;
}
- if (heavyweight.canCreateOffscreenDrawable()) {
+ // FIXME: or'ing in true is a hack for lazy determination of
+ // canCreateOffscreenDrawable() on X11
+ // This will go away once pbuffer creation is more eager
+ if (heavyweight.canCreateOffscreenDrawable() || true) {
if (firstTime) {
toplevel = new Frame();
toplevel.setUndecorated(true);
@@ -488,6 +493,10 @@ public final class GLJPanel extends JPanel implements GLAutoDrawable {
isInitialized = true;
return;
} else {
+ if (VERBOSE) {
+ System.err.println("GLJPanel: Falling back on software rendering because no pbuffer support");
+ }
+
// If the heavyweight reports that it can't create an
// offscreen drawable (pbuffer), don't try again the next
// time, and fall through to the software rendering path
@@ -496,26 +505,18 @@ public final class GLJPanel extends JPanel implements GLAutoDrawable {
}
// Create an offscreen context instead
- offscreenContext = (GLContextImpl) GLContextFactory.getFactory().createGLContext(null, offscreenCaps, chooser,
- GLContextHelper.getContext(shareWith));
+ offscreenDrawable = GLContextFactory.getFactory().createOffscreenDrawable(offscreenCaps, chooser);
+ offscreenDrawable.setSize(Math.max(1, panelWidth), Math.max(1, panelHeight));
+ offscreenContext = (GLContextImpl) offscreenDrawable.createContext(shareWith);
offscreenContext.setSynchronized(true);
- offscreenContext.resizeOffscreenContext(panelWidth, panelHeight);
+
updater = new Updater();
- if (panelWidth > 0 && panelHeight > 0) {
- 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);
- }
- }, true, initAction);
- }
-
isInitialized = true;
}
+ // FIXME: it isn't clear whether this works any more given that
+ // we're accessing the GLDrawable inside of the GLPbuffer directly
+ // up in reshape() -- need to rethink and clean this up
class Updater implements GLEventListener {
private Graphics g;
@@ -542,6 +543,15 @@ public final class GLJPanel extends JPanel implements GLAutoDrawable {
}
public void display(GLAutoDrawable drawable) {
+ if (sendReshape) {
+ if (DEBUG) {
+ System.err.println("glViewport(0, 0, " + panelWidth + ", " + panelHeight + ")");
+ }
+ getGL().glViewport(0, 0, panelWidth, panelHeight);
+ drawableHelper.reshape(GLJPanel.this, 0, 0, panelWidth, panelHeight);
+ sendReshape = false;
+ }
+
drawableHelper.display(GLJPanel.this);
// Must now copy pixels from offscreen context into surface
@@ -697,7 +707,7 @@ public final class GLJPanel extends JPanel implements GLAutoDrawable {
// This one is used exclusively in the non-hardware-accelerated case
class SwapBuffersAction implements Runnable {
public void run() {
- offscreenContext.swapBuffers();
+ offscreenDrawable.swapBuffers();
}
}
private SwapBuffersAction swapBuffersAction = new SwapBuffersAction();
diff --git a/src/net/java/games/jogl/impl/GLContextFactory.java b/src/net/java/games/jogl/impl/GLContextFactory.java
index 40a90f883..bd5497619 100644
--- a/src/net/java/games/jogl/impl/GLContextFactory.java
+++ b/src/net/java/games/jogl/impl/GLContextFactory.java
@@ -98,8 +98,12 @@ public abstract class GLContextFactory {
GLCapabilitiesChooser chooser,
GraphicsDevice device);
- public abstract GLContext createGLContext(Component component,
- GLCapabilities capabilities,
- GLCapabilitiesChooser chooser,
- GLContext shareWith);
+ // GLCanvas support
+ public abstract GLDrawable getGLDrawable(Object target,
+ GLCapabilities capabilities,
+ GLCapabilitiesChooser chooser);
+
+ // GLJPanel support
+ public abstract GLDrawableImpl createOffscreenDrawable(GLCapabilities capabilities,
+ GLCapabilitiesChooser chooser);
}
diff --git a/src/net/java/games/jogl/impl/GLContextImpl.java b/src/net/java/games/jogl/impl/GLContextImpl.java
index 26547c8c3..fd164321f 100755
--- a/src/net/java/games/jogl/impl/GLContextImpl.java
+++ b/src/net/java/games/jogl/impl/GLContextImpl.java
@@ -50,14 +50,6 @@ public abstract class GLContextImpl extends GLContext {
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;
@@ -67,13 +59,7 @@ public abstract class GLContextImpl extends GLContext {
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;
+ public GLContextImpl(GLContext shareWith) {
setGL(createGL());
functionAvailability = new FunctionAvailabilityCache(this);
if (shareWith != null) {
@@ -115,6 +101,9 @@ public abstract class GLContextImpl extends GLContext {
protected abstract void releaseImpl() throws GLException;
public void destroy() {
+ if (lock.isHeld()) {
+ throw new GLException("Can not destroy context while it is current");
+ }
// Should we check the lock state? It should not be current on any
// thread.
destroyImpl();
@@ -148,27 +137,10 @@ public abstract class GLContextImpl extends GLContext {
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();
@@ -181,12 +153,12 @@ public abstract class GLContextImpl extends GLContext {
public abstract boolean canCreatePbufferContext();
/**
- * Pbuffer support; creates a subordinate GLContext for a pbuffer
+ * Pbuffer support; creates a subordinate GLDrawable for a pbuffer
* associated with this context.
*/
- public abstract GLContext createPbufferContext(GLCapabilities capabilities,
- int initialWidth,
- int initialHeight);
+ public abstract GLDrawableImpl createPbufferDrawable(GLCapabilities capabilities,
+ int initialWidth,
+ int initialHeight);
/**
* Pbuffer support; given that this is a GLContext associated with a
@@ -218,18 +190,6 @@ public abstract class GLContextImpl extends GLContext {
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
@@ -333,11 +293,6 @@ public abstract class GLContextImpl extends GLContext {
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
@@ -347,18 +302,11 @@ public abstract class GLContextImpl extends GLContext {
/** 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();
}
+
+ public static String toHexString(long hex) {
+ return "0x" + Long.toHexString(hex);
+ }
}
diff --git a/src/net/java/games/jogl/impl/GLDrawableHelper.java b/src/net/java/games/jogl/impl/GLDrawableHelper.java
index da164088f..0542b4db8 100644
--- a/src/net/java/games/jogl/impl/GLDrawableHelper.java
+++ b/src/net/java/games/jogl/impl/GLDrawableHelper.java
@@ -49,6 +49,7 @@ public class GLDrawableHelper {
private volatile List listeners = new ArrayList();
private static final boolean DEBUG = Debug.debug("GLDrawableHelper");
private static final boolean VERBOSE = Debug.verbose();
+ private boolean autoSwapBufferMode = true;
public GLDrawableHelper() {
}
@@ -84,17 +85,24 @@ public class GLDrawableHelper {
}
}
+ public void setAutoSwapBufferMode(boolean onOrOff) {
+ autoSwapBufferMode = onOrOff;
+ }
+
+ public boolean getAutoSwapBufferMode() {
+ return autoSwapBufferMode;
+ }
+
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,
+ public void invokeGL(GLDrawable drawable,
+ 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
@@ -107,35 +115,19 @@ public class GLDrawableHelper {
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_NOT_CURRENT) {
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();
+ if (autoSwapBufferMode) {
+ drawable.swapBuffers();
}
}
} finally {
diff --git a/src/net/java/games/jogl/impl/GLDrawableImpl.java b/src/net/java/games/jogl/impl/GLDrawableImpl.java
new file mode 100644
index 000000000..60a7e3fcf
--- /dev/null
+++ b/src/net/java/games/jogl/impl/GLDrawableImpl.java
@@ -0,0 +1,52 @@
+/*
+ * 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 net.java.games.jogl.*;
+
+public abstract class GLDrawableImpl implements GLDrawable {
+ /** For offscreen GLDrawables (pbuffers and "pixmap" drawables),
+ indicates that native resources should be reclaimed. */
+ public abstract void destroy() throws GLException;
+
+ public static String toHexString(long hex) {
+ return GLContextImpl.toHexString(hex);
+ }
+}
diff --git a/src/net/java/games/jogl/impl/GLPbufferImpl.java b/src/net/java/games/jogl/impl/GLPbufferImpl.java
index 4e8bd7c63..6e83f0d0e 100644
--- a/src/net/java/games/jogl/impl/GLPbufferImpl.java
+++ b/src/net/java/games/jogl/impl/GLPbufferImpl.java
@@ -52,20 +52,24 @@ import net.java.games.jogl.*;
interface so can be interacted with via its display() method. */
public class GLPbufferImpl implements GLPbuffer {
- // GLPbufferContext
+ private GLDrawableImpl pbufferDrawable;
private GLContextImpl context;
private GLDrawableHelper drawableHelper = new GLDrawableHelper();
private boolean isInitialized=false;
private int floatMode;
- public GLPbufferImpl(GLContext context) {
- this.context = (GLContextImpl) context;
+ public GLPbufferImpl(GLDrawableImpl pbufferDrawable,
+ GLContext parentContext) {
+ this.pbufferDrawable = pbufferDrawable;
+ context = (GLContextImpl) pbufferDrawable.createContext(parentContext);
+ context.setSynchronized(true);
}
- public void display() {
- maybeDoSingleThreadedWorkaround(displayOnEventDispatchThreadAction,
- displayAction,
- false);
+ public GLContext createContext(GLContext shareWith) {
+ return pbufferDrawable.createContext(shareWith);
+ }
+
+ public void setRealized(boolean realized) {
}
public void setSize(int width, int height) {
@@ -74,13 +78,17 @@ public class GLPbufferImpl implements GLPbuffer {
}
public int getWidth() {
- // FIXME
- throw new GLException("Not yet implemented");
+ return pbufferDrawable.getWidth();
}
public int getHeight() {
- // FIXME
- throw new GLException("Not yet implemented");
+ return pbufferDrawable.getHeight();
+ }
+
+ public void display() {
+ maybeDoSingleThreadedWorkaround(displayOnEventDispatchThreadAction,
+ displayAction,
+ false);
}
public void addGLEventListener(GLEventListener listener) {
@@ -91,6 +99,14 @@ public class GLPbufferImpl implements GLPbuffer {
drawableHelper.removeGLEventListener(listener);
}
+ public GLContext getContext() {
+ return context;
+ }
+
+ public GLDrawable getDrawable() {
+ return pbufferDrawable;
+ }
+
public GL getGL() {
return context.getGL();
}
@@ -108,11 +124,11 @@ public class GLPbufferImpl implements GLPbuffer {
}
public void setAutoSwapBufferMode(boolean onOrOff) {
- context.setAutoSwapBufferMode(onOrOff);
+ drawableHelper.setAutoSwapBufferMode(onOrOff);
}
public boolean getAutoSwapBufferMode() {
- return context.getAutoSwapBufferMode();
+ return drawableHelper.getAutoSwapBufferMode();
}
public void swapBuffers() {
@@ -141,15 +157,6 @@ public class GLPbufferImpl implements GLPbuffer {
context.releasePbufferFromTexture();
}
- public GLContext getContext() {
- return context;
- }
-
- // FIXME: workaround for problems with deferring reshape actions
- public GLDrawableHelper getDrawableHelper() {
- return drawableHelper;
- }
-
//----------------------------------------------------------------------
// No-ops for ComponentEvents
//
@@ -188,6 +195,7 @@ public class GLPbufferImpl implements GLPbuffer {
public void destroy() {
context.destroy();
+ pbufferDrawable.destroy();
}
public int getFloatingPointMode() {
@@ -221,7 +229,7 @@ public class GLPbufferImpl implements GLPbuffer {
throw new GLException(e);
}
} else {
- drawableHelper.invokeGL(context, invokeGLAction, isReshape, initAction);
+ drawableHelper.invokeGL(pbufferDrawable, context, invokeGLAction, initAction);
}
}
@@ -242,8 +250,9 @@ public class GLPbufferImpl implements GLPbuffer {
private DisplayAction displayAction = new DisplayAction();
class SwapBuffersAction implements Runnable {
+ // FIXME: currently a no-op
public void run() {
- context.swapBuffers();
+ pbufferDrawable.swapBuffers();
}
}
private SwapBuffersAction swapBuffersAction = new SwapBuffersAction();
@@ -253,14 +262,14 @@ public class GLPbufferImpl implements GLPbuffer {
// being resized on the AWT event dispatch thread
class DisplayOnEventDispatchThreadAction implements Runnable {
public void run() {
- drawableHelper.invokeGL(context, displayAction, false, initAction);
+ drawableHelper.invokeGL(pbufferDrawable, context, displayAction, initAction);
}
}
private DisplayOnEventDispatchThreadAction displayOnEventDispatchThreadAction =
new DisplayOnEventDispatchThreadAction();
class SwapBuffersOnEventDispatchThreadAction implements Runnable {
public void run() {
- drawableHelper.invokeGL(context, swapBuffersAction, false, initAction);
+ drawableHelper.invokeGL(pbufferDrawable, context, swapBuffersAction, initAction);
}
}
private SwapBuffersOnEventDispatchThreadAction swapBuffersOnEventDispatchThreadAction =
diff --git a/src/net/java/games/jogl/impl/macosx/MacOSXDummyGLContext.java b/src/net/java/games/jogl/impl/macosx/MacOSXDummyGLContext.java
index 29a3ef63b..1c48e1171 100644
--- a/src/net/java/games/jogl/impl/macosx/MacOSXDummyGLContext.java
+++ b/src/net/java/games/jogl/impl/macosx/MacOSXDummyGLContext.java
@@ -54,7 +54,7 @@ class MacOSXDummyGLContext extends MacOSXGLContext
private MacOSXGLImpl gl;
MacOSXDummyGLContext(MacOSXGLImpl gl) {
- super(null, null, null, null);
+ super(null, null);
this.gl = gl;
}
@@ -62,10 +62,6 @@ class MacOSXDummyGLContext extends MacOSXGLContext
return gl;
}
- protected boolean isOffscreen() {
- return false;
- }
-
public int getOffscreenContextReadBuffer() {
throw new GLException("Should not call this");
}
@@ -78,10 +74,12 @@ class MacOSXDummyGLContext extends MacOSXGLContext
throw new GLException("Should not call this");
}
- public synchronized GLContext createPbufferContext(GLCapabilities capabilities, int initialWidth, int initialHeight) {
+ public GLDrawableImpl createPbufferDrawable(GLCapabilities capabilities,
+ int initialWidth,
+ int initialHeight) {
throw new GLException("Should not call this");
}
-
+
public void bindPbufferToTexture() {
throw new GLException("Should not call this");
}
@@ -90,26 +88,6 @@ class MacOSXDummyGLContext extends MacOSXGLContext
throw new GLException("Should not call this");
}
- protected synchronized boolean makeCurrent(Runnable initAction) throws GLException {
- throw new GLException("Should not call this");
- }
-
- public synchronized void swapBuffers() throws GLException {
- throw new GLException("Should not call this");
- }
-
- protected synchronized void free() throws GLException {
- throw new GLException("Should not call this");
- }
-
- protected boolean create() {
- throw new GLException("Should not call this");
- }
-
- public void destroy() {
- throw new GLException("Should not call this");
- }
-
public void resetGLFunctionAvailability() {
super.resetGLFunctionAvailability();
}
diff --git a/src/net/java/games/jogl/impl/macosx/MacOSXGLContext.java b/src/net/java/games/jogl/impl/macosx/MacOSXGLContext.java
index 5471fcda4..56fba2900 100644
--- a/src/net/java/games/jogl/impl/macosx/MacOSXGLContext.java
+++ b/src/net/java/games/jogl/impl/macosx/MacOSXGLContext.java
@@ -47,20 +47,17 @@ import net.java.games.jogl.impl.*;
public abstract class MacOSXGLContext extends GLContextImpl
{
- private static JAWT jawt;
+ protected MacOSXGLDrawable drawable;
protected long nsContext; // NSOpenGLContext
- protected long nsView; // NSView
- protected long updater; // ContextUpdater
// Table that holds the addresses of the native C-language entry points for
// OpenGL functions.
private GLProcAddressTable glProcAddressTable;
- public MacOSXGLContext(Component component,
- GLCapabilities capabilities,
- GLCapabilitiesChooser chooser,
+ public MacOSXGLContext(MacOSXGLDrawable drawable,
GLContext shareWith)
{
- super(component, capabilities, chooser, shareWith);
+ super(shareWith);
+ this.drawable = drawable;
}
protected GL createGL()
@@ -78,34 +75,11 @@ public abstract class MacOSXGLContext extends GLContextImpl
return glExtensionName;
}
- protected boolean isFunctionAvailable(String glFunctionName)
- {
- return super.isFunctionAvailable(glFunctionName);
- }
-
- public boolean isExtensionAvailable(String glExtensionName) {
- if (glExtensionName.equals("GL_ARB_pbuffer") ||
- glExtensionName.equals("GL_ARB_pixel_format")) {
- return true;
- }
- return super.isExtensionAvailable(glExtensionName);
- }
-
- protected abstract boolean isOffscreen();
-
- public int getOffscreenContextReadBuffer() {
+ public int getOffscreenContextPixelDataType() {
throw new GLException("Should not call this");
}
- public int getOffscreenContextWidth() {
- throw new GLException("Should not call this");
- }
-
- public int getOffscreenContextHeight() {
- throw new GLException("Should not call this");
- }
-
- public int getOffscreenContextPixelDataType() {
+ public int getOffscreenContextReadBuffer() {
throw new GLException("Should not call this");
}
@@ -131,8 +105,9 @@ public abstract class MacOSXGLContext extends GLContextImpl
}
}
int[] viewNotReady = new int[1];
+ GLCapabilities capabilities = drawable.getCapabilities();
nsContext = CGL.createContext(share,
- nsView,
+ drawable.getView(),
capabilities.getDoubleBuffered() ? 1 : 0,
capabilities.getStereo() ? 1 : 0,
capabilities.getRedBits(),
@@ -160,38 +135,37 @@ public abstract class MacOSXGLContext extends GLContextImpl
}
throw new GLException("Error creating nsContext");
}
- //updater = CGL.updateContextRegister(nsContext, nsView); // gznote: not thread safe yet!
GLContextShareSet.contextCreated(this);
return true;
}
protected int makeCurrentImpl() throws GLException {
- boolean created = false;
- if (nsContext == 0) {
- if (!create()) {
- return CONTEXT_NOT_CURRENT;
- }
- if (DEBUG) {
- System.err.println("!!! Created GL nsContext for " + getClass().getName());
- }
- created = true;
+ boolean created = false;
+ if (nsContext == 0) {
+ if (!create()) {
+ return CONTEXT_NOT_CURRENT;
}
-
- if (!CGL.makeCurrentContext(nsContext, nsView)) {
- throw new GLException("Error making nsContext current");
+ if (DEBUG) {
+ System.err.println("!!! Created GL nsContext for " + getClass().getName());
}
+ created = true;
+ }
- if (created) {
- resetGLFunctionAvailability();
- return CONTEXT_CURRENT_NEW;
- }
- return CONTEXT_CURRENT;
+ if (!CGL.makeCurrentContext(nsContext, drawable.getView())) {
+ throw new GLException("Error making nsContext current");
+ }
+
+ if (created) {
+ resetGLFunctionAvailability();
+ return CONTEXT_CURRENT_NEW;
+ }
+ return CONTEXT_CURRENT;
}
protected void releaseImpl() throws GLException {
- if (!CGL.clearCurrentContext(nsContext, nsView)) {
- throw new GLException("Error freeing OpenGL nsContext");
- }
+ if (!CGL.clearCurrentContext(nsContext, drawable.getView())) {
+ throw new GLException("Error freeing OpenGL nsContext");
+ }
}
protected void destroyImpl() throws GLException {
@@ -199,15 +173,14 @@ public abstract class MacOSXGLContext extends GLContextImpl
if (!CGL.deleteContext(nsContext, 0)) {
throw new GLException("Unable to delete OpenGL context");
}
+ nsContext = 0;
+ GLContextShareSet.contextDestroyed(this);
if (DEBUG) {
System.err.println("!!! Destroyed OpenGL context " + nsContext);
}
- nsContext = 0;
}
}
- public abstract void swapBuffers() throws GLException;
-
protected long dynamicLookupFunction(String glFuncName) {
return CGL.getProcAddress(glFuncName);
}
@@ -247,6 +220,19 @@ public abstract class MacOSXGLContext extends GLContextImpl
CGL.setSwapInterval(nsContext, interval);
}
+ protected boolean isFunctionAvailable(String glFunctionName)
+ {
+ return super.isFunctionAvailable(glFunctionName);
+ }
+
+ public boolean isExtensionAvailable(String glExtensionName) {
+ if (glExtensionName.equals("GL_ARB_pbuffer") ||
+ glExtensionName.equals("GL_ARB_pixel_format")) {
+ return true;
+ }
+ return super.isExtensionAvailable(glExtensionName);
+ }
+
//----------------------------------------------------------------------
// Internals only below this point
//
@@ -254,23 +240,4 @@ public abstract class MacOSXGLContext extends GLContextImpl
protected long getNSContext() {
return nsContext;
}
-
- protected long getNSView() {
- return nsView;
- }
-
- protected JAWT getJAWT()
- {
- if (jawt == null)
- {
- JAWT j = new JAWT();
- j.version(JAWTFactory.JAWT_VERSION_1_4);
- if (!JAWTFactory.JAWT_GetAWT(j))
- {
- throw new RuntimeException("Unable to initialize JAWT");
- }
- jawt = j;
- }
- return jawt;
- }
}
diff --git a/src/net/java/games/jogl/impl/macosx/MacOSXGLContextFactory.java b/src/net/java/games/jogl/impl/macosx/MacOSXGLContextFactory.java
index 25f15b3f2..a3c502b7c 100644
--- a/src/net/java/games/jogl/impl/macosx/MacOSXGLContextFactory.java
+++ b/src/net/java/games/jogl/impl/macosx/MacOSXGLContextFactory.java
@@ -46,20 +46,31 @@ import net.java.games.jogl.*;
import net.java.games.jogl.impl.*;
public class MacOSXGLContextFactory extends GLContextFactory {
+ static {
+ NativeLibLoader.load();
+ }
+
public GraphicsConfiguration chooseGraphicsConfiguration(GLCapabilities capabilities,
GLCapabilitiesChooser chooser,
GraphicsDevice device) {
return null;
}
- public GLContext createGLContext(Component component,
- GLCapabilities capabilities,
- GLCapabilitiesChooser chooser,
- GLContext shareWith) {
- if (component != null) {
- return new MacOSXOnscreenGLContext(component, capabilities, chooser, shareWith);
- } else {
- return new MacOSXOffscreenGLContext(capabilities, chooser, shareWith);
+ public GLDrawable getGLDrawable(Object target,
+ GLCapabilities capabilities,
+ GLCapabilitiesChooser chooser) {
+ if (target == null) {
+ throw new IllegalArgumentException("Null target");
+ }
+ if (!(target instanceof Component)) {
+ throw new IllegalArgumentException("GLDrawables not supported for objects of type " +
+ target.getClass().getName() + " (only Components are supported in this implementation)");
}
+ return new MacOSXOnscreenGLDrawable((Component) target, capabilities, chooser);
+ }
+
+ public GLDrawableImpl createOffscreenDrawable(GLCapabilities capabilities,
+ GLCapabilitiesChooser chooser) {
+ return new MacOSXOffscreenGLDrawable(capabilities);
}
}
diff --git a/src/net/java/games/jogl/impl/macosx/MacOSXGLDrawable.java b/src/net/java/games/jogl/impl/macosx/MacOSXGLDrawable.java
new file mode 100644
index 000000000..b139678db
--- /dev/null
+++ b/src/net/java/games/jogl/impl/macosx/MacOSXGLDrawable.java
@@ -0,0 +1,78 @@
+/*
+ * 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.macosx;
+
+import java.awt.Component;
+
+import net.java.games.jogl.*;
+import net.java.games.jogl.impl.*;
+
+public abstract class MacOSXGLDrawable extends GLDrawableImpl {
+ protected static final boolean DEBUG = Debug.debug("MacOSXGLDrawable");
+
+ protected long nsView; // NSView
+ protected GLCapabilities capabilities;
+ protected GLCapabilitiesChooser chooser;
+
+ public MacOSXGLDrawable(GLCapabilities capabilities,
+ GLCapabilitiesChooser chooser) {
+ this.capabilities = (GLCapabilities) capabilities.clone();
+ this.chooser = chooser;
+ }
+
+ public void setRealized(boolean val) {
+ throw new GLException("Should not call this (should only be called for onscreen GLDrawables)");
+ }
+
+ public void destroy() {
+ throw new GLException("Should not call this (should only be called for offscreen GLDrawables)");
+ }
+
+ public void swapBuffers() throws GLException {
+ }
+
+ public GLCapabilities getCapabilities() {
+ return capabilities;
+ }
+
+ public long getView() {
+ return nsView;
+ }
+} \ No newline at end of file
diff --git a/src/net/java/games/jogl/impl/macosx/MacOSXOffscreenGLContext.java b/src/net/java/games/jogl/impl/macosx/MacOSXOffscreenGLContext.java
index 39aab5652..c6ac894b1 100644
--- a/src/net/java/games/jogl/impl/macosx/MacOSXOffscreenGLContext.java
+++ b/src/net/java/games/jogl/impl/macosx/MacOSXOffscreenGLContext.java
@@ -45,34 +45,21 @@ import net.java.games.jogl.impl.*;
public class MacOSXOffscreenGLContext extends MacOSXPbufferGLContext
{
- public MacOSXOffscreenGLContext(GLCapabilities capabilities,
- GLCapabilitiesChooser chooser,
+ public MacOSXOffscreenGLContext(MacOSXPbufferGLDrawable drawable,
GLContext shareWith) {
- super(capabilities, -1, -1);
+ super(drawable, shareWith);
}
- protected boolean isOffscreen() {
- return true;
- }
-
- public boolean offscreenImageNeedsVerticalFlip() {
- return true;
- }
-
- public int getOffscreenContextWidth() {
- return initWidth;
- }
-
- public int getOffscreenContextHeight() {
- return initWidth;
- }
-
public int getOffscreenContextPixelDataType() {
- return GL.GL_UNSIGNED_INT_8_8_8_8_REV;
+ return GL.GL_UNSIGNED_INT_8_8_8_8_REV;
}
public int getOffscreenContextReadBuffer() {
- return GL.GL_BACK;
+ return GL.GL_FRONT;
+ }
+
+ public boolean offscreenImageNeedsVerticalFlip() {
+ return true;
}
public void bindPbufferToTexture() {
@@ -82,20 +69,4 @@ public class MacOSXOffscreenGLContext extends MacOSXPbufferGLContext
public void releasePbufferFromTexture() {
throw new GLException("Should not call this");
}
-
- protected int makeCurrentImpl() throws GLException {
- if (pendingOffscreenResize && (nsContext != 0)) {
- if (pendingOffscreenWidth != width || pendingOffscreenHeight != height) {
- destroyPBuffer();
- initWidth = pendingOffscreenWidth;
- initHeight = pendingOffscreenHeight;
- createPbuffer(0, 0);
- pendingOffscreenResize = false;
- }
- }
- return super.makeCurrentImpl();
- }
-
- public void swapBuffers() throws GLException {
- }
}
diff --git a/src/net/java/games/jogl/GLContextHelper.java b/src/net/java/games/jogl/impl/macosx/MacOSXOffscreenGLDrawable.java
index f4878a723..d7da03ec0 100644
--- a/src/net/java/games/jogl/GLContextHelper.java
+++ b/src/net/java/games/jogl/impl/macosx/MacOSXOffscreenGLDrawable.java
@@ -37,32 +37,27 @@
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
-package net.java.games.jogl;
+package net.java.games.jogl.impl.macosx;
+import net.java.games.jogl.*;
import net.java.games.jogl.impl.*;
-/** This package-private class helps extract a GLContext from a
- GLDrawable. The getContext() method can not be placed in the
- public API of GLDrawable without exposing the GLContext class to
- the public API, which is not desired. */
+public class MacOSXOffscreenGLDrawable extends MacOSXPbufferGLDrawable {
-class GLContextHelper {
- static GLContext getContext(GLDrawable drawable) throws GLException {
- if (drawable == null) {
- return null;
- }
+ public MacOSXOffscreenGLDrawable(GLCapabilities capabilities) {
+ super(capabilities, 0, 0);
+ }
+
+ public GLContext createContext(GLContext shareWith) {
+ return new MacOSXOffscreenGLContext(this, shareWith);
+ }
- if (drawable instanceof GLCanvas) {
- return ((GLCanvas) drawable).getContext();
- } else if (drawable instanceof GLJPanel) {
- return ((GLJPanel) drawable).getContext();
- } else if (drawable instanceof GLPbufferImpl) {
- return ((GLPbufferImpl) drawable).getContext();
- } else {
- throw new GLException(
- "Sharing of contexts and display lists not supported among user-defined GLDrawables " +
- "(unknown drawable type " + drawable.getClass().getName() + ")"
- );
- }
+ public void setSize(int width, int height) {
+ destroy();
+ initWidth = width;
+ initHeight = height;
+ // Floating-point frame buffers are never used with offscreen
+ // drawables (in GLJPanel) so don't need a GL object here
+ createPbuffer(null);
}
}
diff --git a/src/net/java/games/jogl/impl/macosx/MacOSXOnscreenGLContext.java b/src/net/java/games/jogl/impl/macosx/MacOSXOnscreenGLContext.java
index 70da97f32..a8ffcf8ec 100644
--- a/src/net/java/games/jogl/impl/macosx/MacOSXOnscreenGLContext.java
+++ b/src/net/java/games/jogl/impl/macosx/MacOSXOnscreenGLContext.java
@@ -39,49 +39,22 @@
package net.java.games.jogl.impl.macosx;
-import java.awt.Component;
import java.util.*;
import net.java.games.jogl.*;
import net.java.games.jogl.impl.*;
-import java.security.*;
-
public class MacOSXOnscreenGLContext extends MacOSXGLContext {
- // Variables for lockSurface/unlockSurface
- private JAWT_DrawingSurface ds;
- 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;
-
+ protected MacOSXOnscreenGLDrawable drawable;
// Variables for pbuffer support
List pbuffersToInstantiate = new ArrayList();
- // Workaround for instance of 4796548
- private boolean firstLock = true;
-
- public MacOSXOnscreenGLContext(Component component,
- GLCapabilities capabilities,
- GLCapabilitiesChooser chooser,
+ public MacOSXOnscreenGLContext(MacOSXOnscreenGLDrawable drawable,
GLContext shareWith) {
- super(component, capabilities, chooser, shareWith);
+ super(drawable, shareWith);
+ this.drawable = drawable;
}
- protected boolean isOffscreen() {
- return false;
- }
-
public int getOffscreenContextReadBuffer() {
throw new GLException("Should not call this");
}
@@ -94,12 +67,12 @@ public class MacOSXOnscreenGLContext extends MacOSXGLContext {
return true;
}
- 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;
+ public GLDrawableImpl createPbufferDrawable(GLCapabilities capabilities,
+ int initialWidth,
+ int initialHeight) {
+ MacOSXPbufferGLDrawable buf = new MacOSXPbufferGLDrawable(capabilities, initialWidth, initialHeight);
+ pbuffersToInstantiate.add(buf);
+ return buf;
}
public void bindPbufferToTexture() {
@@ -110,17 +83,14 @@ public class MacOSXOnscreenGLContext extends MacOSXGLContext {
throw new GLException("Should not call this");
}
- public void setRealized() {
- realized = true;
- }
-
protected int makeCurrentImpl() throws GLException {
try {
- if (!realized) {
+ int lockRes = drawable.lockSurface();
+ if (lockRes == MacOSXOnscreenGLDrawable.LOCK_SURFACE_NOT_READY) {
return CONTEXT_NOT_CURRENT;
}
- if (!lockSurface()) {
- return CONTEXT_NOT_CURRENT;
+ if (lockRes == MacOSXOnscreenGLDrawable.LOCK_SURFACE_CHANGED) {
+ super.destroy();
}
int ret = super.makeCurrentImpl();
if ((ret == CONTEXT_CURRENT) ||
@@ -132,21 +102,21 @@ public class MacOSXOnscreenGLContext extends MacOSXGLContext {
// do this updating only upon reshape of this component or reshape or movement
// of an ancestor, but this also wasn't sufficient and left garbage on the
// screen in some situations.
- CGL.updateContext(nsContext, nsView);
+ CGL.updateContext(nsContext, drawable.getView());
// Instantiate any pending pbuffers
while (!pbuffersToInstantiate.isEmpty()) {
- MacOSXPbufferGLContext ctx =
- (MacOSXPbufferGLContext) pbuffersToInstantiate.remove(pbuffersToInstantiate.size() - 1);
- ctx.createPbuffer(nsView, nsContext);
+ MacOSXPbufferGLDrawable buf =
+ (MacOSXPbufferGLDrawable) pbuffersToInstantiate.remove(pbuffersToInstantiate.size() - 1);
+ buf.createPbuffer(getGL());
}
} else {
// View might not have been ready
- unlockSurface();
+ drawable.unlockSurface();
}
return ret;
} catch (RuntimeException e) {
try {
- unlockSurface();
+ drawable.unlockSurface();
} catch (Exception e2) {
// do nothing if unlockSurface throws
}
@@ -158,108 +128,13 @@ public class MacOSXOnscreenGLContext extends MacOSXGLContext {
try {
super.releaseImpl();
} finally {
- unlockSurface();
+ drawable.unlockSurface();
}
}
- protected void destroyImpl() throws GLException {
- realized = false;
- super.destroyImpl();
- }
-
public void swapBuffers() throws GLException {
- if (!CGL.flushBuffer(nsContext, nsView)) {
+ if (!CGL.flushBuffer(nsContext, drawable.getView())) {
throw new GLException("Error swapping buffers");
}
}
-
- private boolean lockSurface() throws GLException {
- if (nsView != 0) {
- throw new GLException("Surface already locked");
- }
-
- ds = getJAWT().GetDrawingSurface(component);
- if (ds == null) {
- // Widget not yet realized
- return false;
- }
-
- int res = ds.Lock();
- if ((res & JAWTFactory.JAWT_LOCK_ERROR) != 0) {
- throw new GLException("Unable to lock surface");
- }
-
- // See whether the surface changed and if so destroy the old
- // OpenGL nsContext so it will be recreated
- if ((res & JAWTFactory.JAWT_LOCK_SURFACE_CHANGED) != 0) {
- if (nsContext != 0) {
- //CGL.updateContextUnregister(nsContext, nsView, updater); // gznote: not thread safe yet!
- if (!CGL.deleteContext(nsContext, nsView)) {
- throw new GLException("Unable to delete old GL nsContext after surface changed");
- }
- }
- }
-
- if (firstLock) {
- AccessController.doPrivileged(new PrivilegedAction() {
- public Object run() {
- dsi = ds.GetDrawingSurfaceInfo();
- return null;
- }
- });
- } else {
- dsi = ds.GetDrawingSurfaceInfo();
- }
- if (dsi == null) {
- ds.Unlock();
- getJAWT().FreeDrawingSurface(ds);
- ds = null;
-
- // Widget not yet realized
- return false;
- }
-
- firstLock = false;
-
- macosxdsi = (JAWT_MacOSXDrawingSurfaceInfo) dsi.platformInfo();
- if (macosxdsi == null) {
- ds.FreeDrawingSurfaceInfo(dsi);
- ds.Unlock();
- getJAWT().FreeDrawingSurface(ds);
- ds = null;
- dsi = null;
-
- // Widget not yet realized
- return false;
- }
-
- nsView = macosxdsi.cocoaViewRef();
- if (nsView == 0) {
- ds.FreeDrawingSurfaceInfo(dsi);
- ds.Unlock();
- getJAWT().FreeDrawingSurface(ds);
- ds = null;
- dsi = null;
- macosxdsi = null;
-
- // Widget not yet realized
- return false;
- }
-
- return true;
- }
-
- private void unlockSurface() throws GLException {
- if (nsView == 0) {
- throw new GLException("Surface already unlocked");
- }
-
- ds.FreeDrawingSurfaceInfo(dsi);
- ds.Unlock();
- getJAWT().FreeDrawingSurface(ds);
- ds = null;
- dsi = null;
- macosxdsi = null;
- nsView = 0;
- }
}
diff --git a/src/net/java/games/jogl/impl/macosx/MacOSXOnscreenGLDrawable.java b/src/net/java/games/jogl/impl/macosx/MacOSXOnscreenGLDrawable.java
new file mode 100644
index 000000000..808a47472
--- /dev/null
+++ b/src/net/java/games/jogl/impl/macosx/MacOSXOnscreenGLDrawable.java
@@ -0,0 +1,236 @@
+/*
+ * 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.macosx;
+
+import java.awt.Component;
+import java.lang.ref.WeakReference;
+import java.security.*;
+import java.util.*;
+
+import net.java.games.jogl.*;
+import net.java.games.jogl.impl.*;
+
+public class MacOSXOnscreenGLDrawable extends MacOSXGLDrawable {
+ public static final int LOCK_SURFACE_NOT_READY = 1;
+ public static final int LOCK_SURFACE_CHANGED = 2;
+ public static final int LOCK_SUCCESS = 3;
+
+ private static JAWT jawt;
+ protected Component component;
+
+ private List/*<WeakReference<GLContext>>*/ createdContexts =
+ new ArrayList();
+
+ // Variables for lockSurface/unlockSurface
+ private JAWT_DrawingSurface ds;
+ 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;
+
+ // Workaround for instance of 4796548
+ private boolean firstLock = true;
+
+ public MacOSXOnscreenGLDrawable(Component component,
+ GLCapabilities capabilities,
+ GLCapabilitiesChooser chooser) {
+ super(capabilities, chooser);
+ this.component = component;
+ }
+
+ public GLContext createContext(GLContext shareWith) {
+ MacOSXOnscreenGLContext context =
+ new MacOSXOnscreenGLContext(this, shareWith);
+ // NOTE: we need to keep track of the created contexts in order to
+ // implement swapBuffers() because of how Mac OS X implements its
+ // OpenGL window interface
+ synchronized (this) {
+ List newContexts = new ArrayList();
+ newContexts.addAll(createdContexts);
+ newContexts.add(new WeakReference(context));
+ createdContexts = newContexts;
+ }
+ return context;
+ }
+
+ public void setRealized(boolean realized) {
+ this.realized = realized;
+ }
+
+ public void setSize(int width, int height) {
+ component.setSize(width, height);
+ }
+
+ public int getWidth() {
+ return component.getWidth();
+ }
+
+ public int getHeight() {
+ return component.getHeight();
+ }
+
+ public void swapBuffers() throws GLException {
+ for (Iterator iter = createdContexts.iterator(); iter.hasNext(); ) {
+ WeakReference ref = (WeakReference) iter.next();
+ MacOSXOnscreenGLContext ctx = (MacOSXOnscreenGLContext) ref.get();
+ // FIXME: clear out unreachable contexts
+ if (ctx != null) {
+ ctx.swapBuffers();
+ // FIXME: it isn't clear how to produce the same functionality
+ // as swapping an HDC's or GLXDrawable's buffers using the
+ // NSOpenGLContext API flushBuffer. Other platforms would
+ // associate the swapBuffer / flushBuffer API with the NSView
+ // rather than the NSOpenGLContext. For now, assume that
+ // calling flushBuffer on one context is the same as calling a
+ // "swapBuffers" function for the NSView.
+ return;
+ }
+ }
+ }
+
+ public int lockSurface() throws GLException {
+ if (!realized) {
+ return LOCK_SURFACE_NOT_READY;
+ }
+ if (nsView != 0) {
+ throw new GLException("Surface already locked");
+ }
+ ds = getJAWT().GetDrawingSurface(component);
+ if (ds == null) {
+ // Widget not yet realized
+ return LOCK_SURFACE_NOT_READY;
+ }
+ int res = ds.Lock();
+ if ((res & JAWTFactory.JAWT_LOCK_ERROR) != 0) {
+ throw new GLException("Unable to lock surface");
+ }
+ // See whether the surface changed and if so destroy the old
+ // OpenGL context so it will be recreated (NOTE: removeNotify
+ // should handle this case, but it may be possible that race
+ // conditions can cause this code to be triggered -- should test
+ // more)
+ int ret = LOCK_SUCCESS;
+ if ((res & JAWTFactory.JAWT_LOCK_SURFACE_CHANGED) != 0) {
+ ret = LOCK_SURFACE_CHANGED;
+ }
+ if (firstLock) {
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ dsi = ds.GetDrawingSurfaceInfo();
+ return null;
+ }
+ });
+ } else {
+ dsi = ds.GetDrawingSurfaceInfo();
+ }
+ if (dsi == null) {
+ // Widget not yet realized
+ ds.Unlock();
+ getJAWT().FreeDrawingSurface(ds);
+ ds = null;
+ return LOCK_SURFACE_NOT_READY;
+ }
+ firstLock = false;
+ macosxdsi = (JAWT_MacOSXDrawingSurfaceInfo) dsi.platformInfo();
+ if (macosxdsi == null) {
+ // Widget not yet realized
+ ds.FreeDrawingSurfaceInfo(dsi);
+ ds.Unlock();
+ getJAWT().FreeDrawingSurface(ds);
+ ds = null;
+ dsi = null;
+ return LOCK_SURFACE_NOT_READY;
+ }
+ nsView = macosxdsi.cocoaViewRef();
+ if (nsView == 0) {
+ // Widget not yet realized
+ ds.FreeDrawingSurfaceInfo(dsi);
+ ds.Unlock();
+ getJAWT().FreeDrawingSurface(ds);
+ ds = null;
+ dsi = null;
+ macosxdsi = null;
+ return LOCK_SURFACE_NOT_READY;
+ }
+ return ret;
+ }
+
+ public void unlockSurface() throws GLException {
+ if (nsView == 0) {
+ throw new GLException("Surface already unlocked");
+ }
+ ds.FreeDrawingSurfaceInfo(dsi);
+ ds.Unlock();
+ getJAWT().FreeDrawingSurface(ds);
+ ds = null;
+ dsi = null;
+ macosxdsi = null;
+ nsView = 0;
+ }
+
+ //----------------------------------------------------------------------
+ // Internals only below this point
+ //
+
+ private JAWT getJAWT()
+ {
+ if (jawt == null)
+ {
+ JAWT j = new JAWT();
+ j.version(JAWTFactory.JAWT_VERSION_1_4);
+ if (!JAWTFactory.JAWT_GetAWT(j))
+ {
+ throw new RuntimeException("Unable to initialize JAWT");
+ }
+ jawt = j;
+ }
+ return jawt;
+ }
+} \ No newline at end of file
diff --git a/src/net/java/games/jogl/impl/macosx/MacOSXPbufferGLContext.java b/src/net/java/games/jogl/impl/macosx/MacOSXPbufferGLContext.java
index b163bb9ce..02e5c1ead 100644
--- a/src/net/java/games/jogl/impl/macosx/MacOSXPbufferGLContext.java
+++ b/src/net/java/games/jogl/impl/macosx/MacOSXPbufferGLContext.java
@@ -7,7 +7,12 @@ import net.java.games.jogl.*;
import net.java.games.jogl.impl.*;
public class MacOSXPbufferGLContext extends MacOSXGLContext {
- private static final boolean DEBUG = Debug.debug("MacOSXPbufferGLContext");
+ protected MacOSXPbufferGLDrawable drawable;
+
+ // State for render-to-texture and render-to-texture-rectangle support
+ private int textureTarget; // e.g. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_NV
+ private int texture; // actual texture object
+
private static boolean isTigerOrLater;
static {
@@ -22,33 +27,20 @@ public class MacOSXPbufferGLContext extends MacOSXGLContext {
int minor = Integer.parseInt(tok.nextToken());
isTigerOrLater = ((major > 10) || (minor > 3));
}
-
- protected int initWidth;
- protected int initHeight;
-
- private long pBuffer;
-
- protected int width;
- protected int height;
-
- // State for render-to-texture and render-to-texture-rectangle support
- private boolean created;
- private int textureTarget; // e.g. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_NV
- private int texture; // actual texture object
- public MacOSXPbufferGLContext(GLCapabilities capabilities, int initialWidth, int initialHeight) {
- super(null, capabilities, null, null);
- this.initWidth = initialWidth;
- this.initHeight = initialHeight;
+ public MacOSXPbufferGLContext(MacOSXPbufferGLDrawable drawable,
+ GLContext shareWith) {
+ super(drawable, shareWith);
+ this.drawable = drawable;
}
public boolean canCreatePbufferContext() {
return false;
}
- public GLContext createPbufferContext(GLCapabilities capabilities,
- int initialWidth,
- int initialHeight) {
+ public GLDrawableImpl createPbufferDrawable(GLCapabilities capabilities,
+ int initialWidth,
+ int initialHeight) {
throw new GLException("Not supported");
}
@@ -58,56 +50,14 @@ public class MacOSXPbufferGLContext extends MacOSXGLContext {
// FIXME: not clear whether this is really necessary, but since
// the API docs seem to imply it is and since it doesn't seem to
// impact performance, leaving it in
- CGL.setContextTextureImageToPBuffer(nsContext, pBuffer, GL.GL_FRONT);
+ CGL.setContextTextureImageToPBuffer(nsContext, drawable.getPbuffer(), GL.GL_FRONT);
}
public void releasePbufferFromTexture() {
}
- public void createPbuffer(long parentView, long parentContext) {
- GL gl = getGL();
- // Must initally grab OpenGL function pointers while parent's
- // context is current because otherwise we don't have the cgl
- // extensions available to us
- resetGLFunctionAvailability();
-
- int renderTarget;
- if (capabilities.getOffscreenRenderToTextureRectangle()) {
- width = initWidth;
- height = initHeight;
- renderTarget = GL.GL_TEXTURE_RECTANGLE_EXT;
- } else {
- width = getNextPowerOf2(initWidth);
- height = getNextPowerOf2(initHeight);
- renderTarget = GL.GL_TEXTURE_2D;
- }
-
- int internalFormat = GL.GL_RGBA;
- if (capabilities.getOffscreenFloatingPointBuffers()) {
- if (!gl.isExtensionAvailable("GL_APPLE_float_pixels")) {
- throw new GLException("Floating-point support (GL_APPLE_float_pixels) not available");
- }
- switch (capabilities.getRedBits()) {
- case 16: internalFormat = GL.GL_RGBA_FLOAT16_APPLE; break;
- case 32: internalFormat = GL.GL_RGBA_FLOAT32_APPLE; break;
- default: throw new GLException("Invalid floating-point bit depth (only 16 and 32 supported)");
- }
- }
-
- pBuffer = CGL.createPBuffer(renderTarget, internalFormat, width, height);
- if (pBuffer == 0) {
- throw new GLException("pbuffer creation error: CGL.createPBuffer() failed");
- }
-
- if (DEBUG) {
- System.err.println("Created pbuffer 0x" + Long.toHexString(pBuffer) + ", " + width + " x " + height + " for " + this);
- }
- }
-
protected int makeCurrentImpl() throws GLException {
- created = false;
-
- if (pBuffer == 0) {
+ if (drawable.getPbuffer() == 0) {
if (DEBUG) {
System.err.println("Pbuffer not instantiated yet for " + this);
}
@@ -116,9 +66,9 @@ public class MacOSXPbufferGLContext extends MacOSXGLContext {
}
int res = super.makeCurrentImpl();
- if (created) {
+ if (res == CONTEXT_CURRENT_NEW) {
// Initialize render-to-texture support if requested
- boolean rect = capabilities.getOffscreenRenderToTextureRectangle();
+ boolean rect = drawable.getCapabilities().getOffscreenRenderToTextureRectangle();
GL gl = getGL();
if (rect) {
if (!gl.isExtensionAvailable("GL_EXT_texture_rectangle")) {
@@ -136,58 +86,17 @@ public class MacOSXPbufferGLContext extends MacOSXGLContext {
gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE);
gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE);
- gl.glCopyTexImage2D(textureTarget, 0, GL.GL_RGB, 0, 0, width, height, 0);
+ gl.glCopyTexImage2D(textureTarget, 0, GL.GL_RGB, 0, 0, drawable.getWidth(), drawable.getHeight(), 0);
}
return res;
}
- public void destroyPBuffer() {
- if (this.pBuffer != 0) {
- CGL.destroyPBuffer(nsContext, pBuffer);
- }
- this.pBuffer = 0;
-
- if (DEBUG) {
- System.err.println("Destroyed pbuffer " + width + " x " + height);
- }
- }
-
- public void handleModeSwitch(long parentView, long parentContext) {
- throw new GLException("Not yet implemented");
- }
-
- protected boolean isOffscreen() {
- // FIXME: currently the only caller of this won't cause proper
- // resizing of the pbuffer anyway.
- return false;
- }
-
- protected void destroyImpl() throws GLException {
- destroyPBuffer();
- }
-
- public void swapBuffers() throws GLException {
- // FIXME: do we need to do anything if the pbuffer is double-buffered?
- }
-
public int getFloatingPointMode() {
return GLPbuffer.APPLE_FLOAT;
}
- private int getNextPowerOf2(int number) {
- if (((number-1) & number) == 0) {
- //ex: 8 -> 0b1000; 8-1=7 -> 0b0111; 0b1000&0b0111 == 0
- return number;
- }
- int power = 0;
- while (number > 0) {
- number = number>>1;
- power++;
- }
- return (1<<power);
- }
-
protected boolean create() {
+ GLCapabilities capabilities = drawable.getCapabilities();
if (capabilities.getOffscreenFloatingPointBuffers() &&
!isTigerOrLater) {
throw new GLException("Floating-point pbuffers supported only on OS X 10.4 or later");
@@ -195,9 +104,8 @@ public class MacOSXPbufferGLContext extends MacOSXGLContext {
if (!super.create(true, capabilities.getOffscreenFloatingPointBuffers())) {
return false;
}
- created = true;
// Must now associate the pbuffer with our newly-created context
- CGL.setContextPBuffer(nsContext, pBuffer);
+ CGL.setContextPBuffer(nsContext, drawable.getPbuffer());
return true;
}
}
diff --git a/src/net/java/games/jogl/impl/macosx/MacOSXPbufferGLDrawable.java b/src/net/java/games/jogl/impl/macosx/MacOSXPbufferGLDrawable.java
new file mode 100644
index 000000000..fc5f3c22e
--- /dev/null
+++ b/src/net/java/games/jogl/impl/macosx/MacOSXPbufferGLDrawable.java
@@ -0,0 +1,152 @@
+/*
+ * 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.macosx;
+
+import net.java.games.jogl.*;
+import net.java.games.jogl.impl.*;
+
+public class MacOSXPbufferGLDrawable extends MacOSXGLDrawable {
+ private static final boolean DEBUG = Debug.debug("MacOSXPbufferGLContext");
+
+ protected int initWidth;
+ protected int initHeight;
+
+ protected long pBuffer;
+
+ protected int width;
+ protected int height;
+
+ // State for render-to-texture and render-to-texture-rectangle support
+ private int textureTarget; // e.g. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_NV
+ private int texture; // actual texture object
+
+ public MacOSXPbufferGLDrawable(GLCapabilities capabilities, int initialWidth, int initialHeight) {
+ super(capabilities, null);
+ this.initWidth = initialWidth;
+ this.initHeight = initialHeight;
+ }
+
+ public GLContext createContext(GLContext shareWith) {
+ return new MacOSXPbufferGLContext(this, shareWith);
+ }
+
+ public void destroy() {
+ if (this.pBuffer != 0) {
+ CGL.destroyPBuffer(0, pBuffer);
+ this.pBuffer = 0;
+
+ if (DEBUG) {
+ System.err.println("Destroyed pbuffer " + width + " x " + height);
+ }
+ }
+ }
+
+ public void setSize(int width, int height) {
+ // FIXME
+ throw new GLException("Not yet implemented");
+ }
+
+ public int getWidth() {
+ return width;
+ }
+
+ public int getHeight() {
+ return height;
+ }
+
+ public void createPbuffer(GL gl) {
+ int renderTarget;
+ if (capabilities.getOffscreenRenderToTextureRectangle()) {
+ width = initWidth;
+ height = initHeight;
+ renderTarget = GL.GL_TEXTURE_RECTANGLE_EXT;
+ } else {
+ width = getNextPowerOf2(initWidth);
+ height = getNextPowerOf2(initHeight);
+ renderTarget = GL.GL_TEXTURE_2D;
+ }
+
+ int internalFormat = GL.GL_RGBA;
+ if (capabilities.getOffscreenFloatingPointBuffers()) {
+ if (!gl.isExtensionAvailable("GL_APPLE_float_pixels")) {
+ throw new GLException("Floating-point support (GL_APPLE_float_pixels) not available");
+ }
+ switch (capabilities.getRedBits()) {
+ case 16: internalFormat = GL.GL_RGBA_FLOAT16_APPLE; break;
+ case 32: internalFormat = GL.GL_RGBA_FLOAT32_APPLE; break;
+ default: throw new GLException("Invalid floating-point bit depth (only 16 and 32 supported)");
+ }
+ }
+
+ pBuffer = CGL.createPBuffer(renderTarget, internalFormat, width, height);
+ if (pBuffer == 0) {
+ throw new GLException("pbuffer creation error: CGL.createPBuffer() failed");
+ }
+
+ if (DEBUG) {
+ System.err.println("Created pbuffer 0x" + toHexString(pBuffer) + ", " + width + " x " + height + " for " + this);
+ }
+ }
+
+ public GLCapabilities getCapabilities() {
+ return capabilities;
+ }
+
+ public long getPbuffer() {
+ return pBuffer;
+ }
+
+ public void swapBuffers() throws GLException {
+ // FIXME: do we need to do anything if the pbuffer is double-buffered?
+ }
+
+ private int getNextPowerOf2(int number) {
+ if (((number-1) & number) == 0) {
+ //ex: 8 -> 0b1000; 8-1=7 -> 0b0111; 0b1000&0b0111 == 0
+ return number;
+ }
+ int power = 0;
+ while (number > 0) {
+ number = number>>1;
+ power++;
+ }
+ return (1<<power);
+ }
+}
diff --git a/src/net/java/games/jogl/impl/windows/WindowsGLContext.java b/src/net/java/games/jogl/impl/windows/WindowsGLContext.java
index 338b11e6a..44f2894eb 100644
--- a/src/net/java/games/jogl/impl/windows/WindowsGLContext.java
+++ b/src/net/java/games/jogl/impl/windows/WindowsGLContext.java
@@ -39,19 +39,14 @@
package net.java.games.jogl.impl.windows;
-import java.awt.Component;
-import java.awt.GraphicsConfiguration;
-import java.awt.GraphicsDevice;
-import java.awt.Rectangle;
import java.util.*;
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 GLContextImpl {
- private static JAWT jawt;
+ protected WindowsGLDrawable drawable;
protected long hglrc;
- protected long hdc;
private boolean wglGetExtensionsStringEXTInitialized;
private boolean wglGetExtensionsStringEXTAvailable;
private static final Map/*<String, String>*/ functionNameMap;
@@ -63,9 +58,6 @@ public abstract class WindowsGLContext extends GLContextImpl {
private long hglu32;
private boolean haveWGLARBPbuffer = true;
- private static final int MAX_PFORMATS = 256;
- private static final int MAX_ATTRIBS = 256;
-
static {
functionNameMap = new HashMap();
functionNameMap.put("glAllocateMemoryNV", "wglAllocateMemoryNV");
@@ -76,11 +68,10 @@ public abstract class WindowsGLContext extends GLContextImpl {
extensionNameMap.put("GL_ARB_pixel_format", "WGL_ARB_pixel_format");
}
- public WindowsGLContext(Component component,
- GLCapabilities capabilities,
- GLCapabilitiesChooser chooser,
+ public WindowsGLContext(WindowsGLDrawable drawable,
GLContext shareWith) {
- super(component, capabilities, chooser, shareWith);
+ super(shareWith);
+ this.drawable = drawable;
}
protected GL createGL()
@@ -104,16 +95,6 @@ public abstract class WindowsGLContext extends GLContextImpl {
return glExtensionName;
}
- protected abstract boolean isOffscreen();
-
- public int getOffscreenContextWidth() {
- throw new GLException("Should not call this");
- }
-
- public int getOffscreenContextHeight() {
- throw new GLException("Should not call this");
- }
-
public int getOffscreenContextPixelDataType() {
throw new GLException("Should not call this");
}
@@ -126,7 +107,32 @@ public abstract class WindowsGLContext extends GLContextImpl {
* Creates and initializes an appropriate OpenGL context. Should only be
* called by {@link #makeCurrentImpl()}.
*/
- protected abstract void create();
+ protected void create() {
+ if (drawable.getHDC() == 0) {
+ throw new GLException("Internal error: attempted to create OpenGL context without an associated drawable");
+ }
+ hglrc = WGL.wglCreateContext(drawable.getHDC());
+ if (hglrc == 0) {
+ throw new GLException("Unable to create OpenGL context");
+ }
+ // Windows can set up sharing of display lists after creation time
+ WindowsGLContext other = (WindowsGLContext) GLContextShareSet.getShareContext(this);
+ if (other != null) {
+ long hglrc2 = other.getHGLRC();
+ if (hglrc2 == 0) {
+ throw new GLException("GLContextShareSet returned an invalid OpenGL context");
+ }
+ if (!WGL.wglShareLists(hglrc2, hglrc)) {
+ throw new GLException("wglShareLists(0x" + Long.toHexString(hglrc2) +
+ ", 0x" + Long.toHexString(hglrc) + ") failed: error code " +
+ WGL.GetLastError());
+ }
+ }
+ GLContextShareSet.contextCreated(this);
+ if (DEBUG) {
+ System.err.println(getThreadName() + ": !!! Created OpenGL context " + toHexString(hglrc) + " for " + this + ", device context " + toHexString(drawable.getHDC()));
+ }
+ }
protected int makeCurrentImpl() throws GLException {
boolean created = false;
@@ -149,12 +155,12 @@ public abstract class WindowsGLContext extends GLContextImpl {
}
if (!skipMakeCurrent) {
- if (!WGL.wglMakeCurrent(hdc, hglrc)) {
+ if (!WGL.wglMakeCurrent(drawable.getHDC(), hglrc)) {
throw new GLException("Error making context current: " + WGL.GetLastError());
} else {
if (DEBUG && VERBOSE) {
- System.err.println(getThreadName() + ": wglMakeCurrent(hdc " + hdcToString(hdc) +
- ", hglrc " + hdcToString(hglrc) + ") succeeded");
+ System.err.println(getThreadName() + ": wglMakeCurrent(hdc " + toHexString(drawable.getHDC()) +
+ ", hglrc " + toHexString(hglrc) + ") succeeded");
}
}
}
@@ -163,20 +169,6 @@ public abstract class WindowsGLContext extends GLContextImpl {
resetGLFunctionAvailability();
haveWGLARBPbuffer = (isExtensionAvailable("WGL_ARB_pbuffer") &&
isExtensionAvailable("WGL_ARB_pixel_format"));
- // Windows can set up sharing of display lists after creation time
- WindowsGLContext other = (WindowsGLContext) GLContextShareSet.getShareContext(this);
- if (other != null) {
- long hglrc2 = other.getHGLRC();
- if (hglrc2 == 0) {
- throw new GLException("GLContextShareSet returned an invalid OpenGL context");
- }
- if (!WGL.wglShareLists(hglrc2, hglrc)) {
- throw new GLException("wglShareLists(0x" + Long.toHexString(hglrc2) +
- ", 0x" + Long.toHexString(hglrc) + ") failed: error code " +
- WGL.GetLastError());
- }
- }
- GLContextShareSet.contextCreated(this);
return CONTEXT_CURRENT_NEW;
}
return CONTEXT_CURRENT;
@@ -195,15 +187,14 @@ public abstract class WindowsGLContext extends GLContextImpl {
if (!WGL.wglDeleteContext(hglrc)) {
throw new GLException("Unable to delete OpenGL context");
}
+ hglrc = 0;
+ GLContextShareSet.contextDestroyed(this);
if (DEBUG) {
- System.err.println(getThreadName() + ": !!! Destroyed OpenGL context " + hglrc);
+ System.err.println(getThreadName() + ": !!! Destroyed OpenGL context " + toHexString(hglrc));
}
- hglrc = 0;
}
}
- public abstract void swapBuffers() throws GLException;
-
protected long dynamicLookupFunction(String glFuncName) {
long res = WGL.wglGetProcAddress(glFuncName);
if (res == 0) {
@@ -272,444 +263,10 @@ public abstract class WindowsGLContext extends GLContextImpl {
// Internals only below this point
//
- protected JAWT getJAWT() {
- if (jawt == null) {
- JAWT j = new JAWT();
- j.version(JAWTFactory.JAWT_VERSION_1_4);
- if (!JAWTFactory.JAWT_GetAWT(j)) {
- throw new RuntimeException("Unable to initialize JAWT");
- }
- jawt = j;
- }
- return jawt;
- }
-
- // Helper routine for the overridden create() to call
- protected void choosePixelFormatAndCreateContext(boolean onscreen) {
- PIXELFORMATDESCRIPTOR pfd = null;
- int pixelFormat = 0;
- if (onscreen) {
- GLCapabilities[] availableCaps = null;
- int numFormats = 0;
- pfd = newPixelFormatDescriptor();
- GraphicsConfiguration config = component.getGraphicsConfiguration();
- GraphicsDevice device = config.getDevice();
- // Produce a recommended pixel format selection for the GLCapabilitiesChooser.
- // Use wglChoosePixelFormatARB if user requested multisampling and if we have it available
- GL dummyGL = null;
- if (capabilities.getSampleBuffers()) {
- dummyGL = WindowsGLContextFactory.getDummyGL(device);
- }
- int recommendedPixelFormat = -1;
- boolean haveWGLChoosePixelFormatARB = false;
- boolean haveWGLARBMultisample = false;
- if (dummyGL != null) {
- String availableWGLExtensions = WindowsGLContextFactory.getDummyGLExtensions(device);
- if (availableWGLExtensions.indexOf("WGL_ARB_pixel_format") >= 0) {
- haveWGLChoosePixelFormatARB = true;
- if (availableWGLExtensions.indexOf("WGL_ARB_multisample") >= 0) {
- haveWGLARBMultisample = true;
- }
- }
- }
- Rectangle rect = config.getBounds();
- long dc = 0;
- long rc = 0;
- boolean freeWGLC = false;
- if( dummyGL != null ) {
- dc = WindowsGLContextFactory.getDummyGLContext( device ).hdc;
- rc = WindowsGLContextFactory.getDummyGLContext( device ).hglrc;
- if( !WGL.wglMakeCurrent( dc, rc ) ) {
- System.err.println(getThreadName() + ": Error Making WGLC Current: " + WGL.GetLastError() );
- } else {
- freeWGLC = true;
- }
- }
- // Fallback path for older cards, in particular Intel Extreme motherboard graphics
- boolean gotAvailableCaps = false;
- if (dummyGL != null && haveWGLChoosePixelFormatARB) {
- int[] iattributes = new int [2 * MAX_ATTRIBS];
- int[] iresults = new int [2 * MAX_ATTRIBS];
- float[] fattributes = new float[2 * MAX_ATTRIBS];
- int niattribs = 0;
- int nfattribs = 0;
- iattributes[niattribs++] = GL.WGL_SUPPORT_OPENGL_ARB;
- iattributes[niattribs++] = GL.GL_TRUE;
- iattributes[niattribs++] = GL.WGL_DRAW_TO_WINDOW_ARB;
- iattributes[niattribs++] = GL.GL_TRUE;
- iattributes[niattribs++] = GL.WGL_PIXEL_TYPE_ARB;
- iattributes[niattribs++] = GL.WGL_TYPE_RGBA_ARB;
- iattributes[niattribs++] = GL.WGL_DOUBLE_BUFFER_ARB;
- if (capabilities.getDoubleBuffered()) {
- iattributes[niattribs++] = GL.GL_TRUE;
- } else {
- iattributes[niattribs++] = GL.GL_FALSE;
- }
- iattributes[niattribs++] = GL.WGL_STEREO_ARB;
- if (capabilities.getStereo()) {
- iattributes[niattribs++] = GL.GL_TRUE;
- } else {
- iattributes[niattribs++] = GL.GL_FALSE;
- }
- iattributes[niattribs++] = GL.WGL_DEPTH_BITS_ARB;
- iattributes[niattribs++] = capabilities.getDepthBits();
- iattributes[niattribs++] = GL.WGL_RED_BITS_ARB;
- iattributes[niattribs++] = capabilities.getRedBits();
- iattributes[niattribs++] = GL.WGL_GREEN_BITS_ARB;
- iattributes[niattribs++] = capabilities.getGreenBits();
- iattributes[niattribs++] = GL.WGL_BLUE_BITS_ARB;
- iattributes[niattribs++] = capabilities.getBlueBits();
- iattributes[niattribs++] = GL.WGL_ALPHA_BITS_ARB;
- iattributes[niattribs++] = capabilities.getAlphaBits();
- iattributes[niattribs++] = GL.WGL_STENCIL_BITS_ARB;
- iattributes[niattribs++] = capabilities.getStencilBits();
- if (capabilities.getAccumRedBits() > 0 ||
- capabilities.getAccumGreenBits() > 0 ||
- capabilities.getAccumBlueBits() > 0 ||
- capabilities.getAccumAlphaBits() > 0) {
- iattributes[niattribs++] = GL.WGL_ACCUM_BITS_ARB;
- iattributes[niattribs++] = (capabilities.getAccumRedBits() +
- capabilities.getAccumGreenBits() +
- capabilities.getAccumBlueBits() +
- capabilities.getAccumAlphaBits());
- iattributes[niattribs++] = GL.WGL_ACCUM_RED_BITS_ARB;
- iattributes[niattribs++] = capabilities.getAccumRedBits();
- iattributes[niattribs++] = GL.WGL_ACCUM_GREEN_BITS_ARB;
- iattributes[niattribs++] = capabilities.getAccumGreenBits();
- iattributes[niattribs++] = GL.WGL_ACCUM_BLUE_BITS_ARB;
- iattributes[niattribs++] = capabilities.getAccumBlueBits();
- iattributes[niattribs++] = GL.WGL_ACCUM_ALPHA_BITS_ARB;
- iattributes[niattribs++] = capabilities.getAccumAlphaBits();
- }
- if (haveWGLARBMultisample) {
- if (capabilities.getSampleBuffers()) {
- iattributes[niattribs++] = GL.WGL_SAMPLE_BUFFERS_ARB;
- iattributes[niattribs++] = GL.GL_TRUE;
- iattributes[niattribs++] = GL.WGL_SAMPLES_ARB;
- iattributes[niattribs++] = capabilities.getNumSamples();
- }
- }
-
- int[] pformats = new int[MAX_PFORMATS];
- int[] numFormatsTmp = new int[1];
- if (dummyGL.wglChoosePixelFormatARB(hdc,
- iattributes, 0,
- fattributes, 0,
- MAX_PFORMATS,
- pformats, 0,
- numFormatsTmp, 0)) {
- numFormats = numFormatsTmp[0];
- if (numFormats > 0) {
- // Remove one-basing of pixel format (added on later)
- recommendedPixelFormat = pformats[0] - 1;
- if (DEBUG) {
- System.err.println(getThreadName() + ": Used wglChoosePixelFormatARB to recommend pixel format " + recommendedPixelFormat);
- }
- }
- } else {
- if (DEBUG) {
- System.err.println(getThreadName() + ": wglChoosePixelFormatARB failed: " + WGL.GetLastError() );
- Thread.dumpStack();
- }
- }
- if (DEBUG) {
- if (recommendedPixelFormat < 0) {
- System.err.print(getThreadName() + ": wglChoosePixelFormatARB didn't recommend a pixel format");
- if (capabilities.getSampleBuffers()) {
- System.err.print(" for multisampled GLCapabilities");
- }
- System.err.println();
- }
- }
-
- // Produce a list of GLCapabilities to give to the
- // GLCapabilitiesChooser.
- // Use wglGetPixelFormatAttribivARB instead of
- // DescribePixelFormat to get higher-precision information
- // about the pixel format (should make the GLCapabilities
- // more precise as well...i.e., remove the
- // "HardwareAccelerated" bit, which is basically
- // meaningless, and put in whether it can render to a
- // window, to a pbuffer, or to a pixmap)
- niattribs = 0;
- iattributes[0] = GL.WGL_NUMBER_PIXEL_FORMATS_ARB;
- if (dummyGL.wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, iattributes, 0, iresults, 0)) {
- numFormats = iresults[0];
- // Should we be filtering out the pixel formats which aren't
- // applicable, as we are doing here?
- // We don't have enough information in the GLCapabilities to
- // represent those that aren't...
- iattributes[niattribs++] = GL.WGL_DRAW_TO_WINDOW_ARB;
- iattributes[niattribs++] = GL.WGL_ACCELERATION_ARB;
- iattributes[niattribs++] = GL.WGL_SUPPORT_OPENGL_ARB;
- iattributes[niattribs++] = GL.WGL_DEPTH_BITS_ARB;
- iattributes[niattribs++] = GL.WGL_STENCIL_BITS_ARB;
- iattributes[niattribs++] = GL.WGL_DOUBLE_BUFFER_ARB;
- iattributes[niattribs++] = GL.WGL_STEREO_ARB;
- iattributes[niattribs++] = GL.WGL_PIXEL_TYPE_ARB;
- iattributes[niattribs++] = GL.WGL_RED_BITS_ARB;
- iattributes[niattribs++] = GL.WGL_GREEN_BITS_ARB;
- iattributes[niattribs++] = GL.WGL_BLUE_BITS_ARB;
- iattributes[niattribs++] = GL.WGL_ALPHA_BITS_ARB;
- iattributes[niattribs++] = GL.WGL_ACCUM_RED_BITS_ARB;
- iattributes[niattribs++] = GL.WGL_ACCUM_GREEN_BITS_ARB;
- iattributes[niattribs++] = GL.WGL_ACCUM_BLUE_BITS_ARB;
- iattributes[niattribs++] = GL.WGL_ACCUM_ALPHA_BITS_ARB;
- if (haveWGLARBMultisample) {
- iattributes[niattribs++] = GL.WGL_SAMPLE_BUFFERS_ARB;
- iattributes[niattribs++] = GL.WGL_SAMPLES_ARB;
- }
-
- availableCaps = new GLCapabilities[numFormats];
- for (int i = 0; i < numFormats; i++) {
- if (!dummyGL.wglGetPixelFormatAttribivARB(hdc, i+1, 0, niattribs, iattributes, 0, iresults, 0)) {
- throw new GLException("Error getting pixel format attributes for pixel format " + (i + 1) + " of device context");
- }
- availableCaps[i] = iattributes2GLCapabilities(iattributes, iresults, niattribs, true);
- }
- if( freeWGLC ) {
- WGL.wglMakeCurrent( 0, 0 );
- }
- gotAvailableCaps = true;
- } else {
- int lastErr = WGL.GetLastError();
- // Intel Extreme graphics fails with a zero error code
- if (lastErr != 0) {
- throw new GLException("Unable to enumerate pixel formats of window using wglGetPixelFormatAttribivARB: error code " + WGL.GetLastError());
- }
- }
- }
-
- if (!gotAvailableCaps) {
- if (DEBUG) {
- if (!capabilities.getSampleBuffers()) {
- System.err.println(getThreadName() + ": Using ChoosePixelFormat because multisampling not requested");
- } else {
- System.err.println(getThreadName() + ": Using ChoosePixelFormat because no wglChoosePixelFormatARB: dummyGL = " + dummyGL);
- }
- }
- pfd = glCapabilities2PFD(capabilities, onscreen);
- // Remove one-basing of pixel format (added on later)
- recommendedPixelFormat = WGL.ChoosePixelFormat(hdc, pfd) - 1;
-
- numFormats = WGL.DescribePixelFormat(hdc, 1, 0, null);
- if (numFormats == 0) {
- throw new GLException("Unable to enumerate pixel formats of window for GLCapabilitiesChooser");
- }
- availableCaps = new GLCapabilities[numFormats];
- for (int i = 0; i < numFormats; i++) {
- if (WGL.DescribePixelFormat(hdc, 1 + i, pfd.size(), pfd) == 0) {
- throw new GLException("Error describing pixel format " + (1 + i) + " of device context");
- }
- availableCaps[i] = pfd2GLCapabilities(pfd);
- }
- }
-
- // Supply information to chooser
- pixelFormat = chooser.chooseCapabilities(capabilities, availableCaps, recommendedPixelFormat);
- if ((pixelFormat < 0) || (pixelFormat >= numFormats)) {
- throw new GLException("Invalid result " + pixelFormat +
- " from GLCapabilitiesChooser (should be between 0 and " +
- (numFormats - 1) + ")");
- }
- if (DEBUG) {
- System.err.println(getThreadName() + ": Chosen pixel format (" + pixelFormat + "):");
- System.err.println(availableCaps[pixelFormat]);
- }
- pixelFormat += 1; // one-base the index
- if (WGL.DescribePixelFormat(hdc, pixelFormat, pfd.size(), pfd) == 0) {
- throw new GLException("Error re-describing the chosen pixel format: " + WGL.GetLastError());
- }
- } else {
- // For now, use ChoosePixelFormat for offscreen surfaces until
- // we figure out how to properly choose an offscreen-
- // compatible pixel format
- pfd = glCapabilities2PFD(capabilities, onscreen);
- pixelFormat = WGL.ChoosePixelFormat(hdc, pfd);
- }
- if (!WGL.SetPixelFormat(hdc, pixelFormat, pfd)) {
- int lastError = WGL.GetLastError();
- if (DEBUG) {
- System.err.println(getThreadName() + ": SetPixelFormat failed: current context = " + WGL.wglGetCurrentContext() +
- ", current DC = " + WGL.wglGetCurrentDC());
- System.err.println(getThreadName() + ": GetPixelFormat(hdc " + hdcToString(hdc) + ") returns " + WGL.GetPixelFormat(hdc));
- }
- throw new GLException("Unable to set pixel format " + pixelFormat + " for device context " + hdcToString(hdc) + ": error code " + lastError);
- }
- hglrc = WGL.wglCreateContext(hdc);
- if (DEBUG) {
- System.err.println(getThreadName() + ": !!! Created OpenGL context " + hglrc + " for device context " + hdcToString(hdc) + " using pixel format " + pixelFormat);
- }
- if (hglrc == 0) {
- throw new GLException("Unable to create OpenGL context");
- }
- }
-
protected long getHGLRC() {
return hglrc;
}
- static PIXELFORMATDESCRIPTOR glCapabilities2PFD(GLCapabilities caps, boolean onscreen) {
- int colorDepth = (caps.getRedBits() +
- caps.getGreenBits() +
- caps.getBlueBits());
- if (colorDepth < 15) {
- throw new GLException("Bit depths < 15 (i.e., non-true-color) not supported");
- }
- PIXELFORMATDESCRIPTOR pfd = newPixelFormatDescriptor();
- int pfdFlags = (WGL.PFD_SUPPORT_OPENGL |
- WGL.PFD_GENERIC_ACCELERATED);
- if (caps.getDoubleBuffered()) {
- pfdFlags |= WGL.PFD_DOUBLEBUFFER;
- }
- if (onscreen) {
- pfdFlags |= WGL.PFD_DRAW_TO_WINDOW;
- } else {
- pfdFlags |= WGL.PFD_DRAW_TO_BITMAP;
- }
- pfd.dwFlags(pfdFlags);
- pfd.iPixelType((byte) WGL.PFD_TYPE_RGBA);
- pfd.cColorBits((byte) colorDepth);
- pfd.cRedBits ((byte) caps.getRedBits());
- pfd.cGreenBits((byte) caps.getGreenBits());
- pfd.cBlueBits ((byte) caps.getBlueBits());
- pfd.cAlphaBits((byte) caps.getAlphaBits());
- int accumDepth = (caps.getAccumRedBits() +
- caps.getAccumGreenBits() +
- caps.getAccumBlueBits());
- pfd.cAccumBits ((byte) accumDepth);
- pfd.cAccumRedBits ((byte) caps.getAccumRedBits());
- pfd.cAccumGreenBits((byte) caps.getAccumGreenBits());
- pfd.cAccumBlueBits ((byte) caps.getAccumBlueBits());
- pfd.cAccumAlphaBits((byte) caps.getAccumAlphaBits());
- pfd.cDepthBits((byte) caps.getDepthBits());
- pfd.cStencilBits((byte) caps.getStencilBits());
- pfd.iLayerType((byte) WGL.PFD_MAIN_PLANE);
- return pfd;
- }
-
- static PIXELFORMATDESCRIPTOR newPixelFormatDescriptor() {
- PIXELFORMATDESCRIPTOR pfd = new PIXELFORMATDESCRIPTOR();
- pfd.nSize((short) pfd.size());
- pfd.nVersion((short) 1);
- return pfd;
- }
-
- static GLCapabilities pfd2GLCapabilities(PIXELFORMATDESCRIPTOR pfd) {
- if ((pfd.dwFlags() & WGL.PFD_SUPPORT_OPENGL) == 0) {
- return null;
- }
- GLCapabilities res = new GLCapabilities();
- res.setRedBits (pfd.cRedBits());
- res.setGreenBits (pfd.cGreenBits());
- res.setBlueBits (pfd.cBlueBits());
- res.setAlphaBits (pfd.cAlphaBits());
- res.setAccumRedBits (pfd.cAccumRedBits());
- res.setAccumGreenBits(pfd.cAccumGreenBits());
- res.setAccumBlueBits (pfd.cAccumBlueBits());
- res.setAccumAlphaBits(pfd.cAccumAlphaBits());
- res.setDepthBits (pfd.cDepthBits());
- res.setStencilBits (pfd.cStencilBits());
- res.setDoubleBuffered((pfd.dwFlags() & WGL.PFD_DOUBLEBUFFER) != 0);
- res.setStereo ((pfd.dwFlags() & WGL.PFD_STEREO) != 0);
- res.setHardwareAccelerated(((pfd.dwFlags() & WGL.PFD_GENERIC_FORMAT) == 0) ||
- ((pfd.dwFlags() & WGL.PFD_GENERIC_ACCELERATED) != 0));
- return res;
- }
-
- static GLCapabilities iattributes2GLCapabilities(int[] iattribs,
- int[] iresults,
- int niattribs,
- boolean requireRenderToWindow) {
- GLCapabilities res = new GLCapabilities();
- for (int i = 0; i < niattribs; i++) {
- switch (iattribs[i]) {
- case GL.WGL_DRAW_TO_WINDOW_ARB:
- if (iresults[i] != GL.GL_TRUE)
- return null;
- break;
-
- case GL.WGL_ACCELERATION_ARB:
- res.setHardwareAccelerated(iresults[i] == GL.WGL_FULL_ACCELERATION_ARB);
- break;
-
- case GL.WGL_SUPPORT_OPENGL_ARB:
- if (iresults[i] != GL.GL_TRUE)
- return null;
- break;
-
- case GL.WGL_DEPTH_BITS_ARB:
- res.setDepthBits(iresults[i]);
- break;
-
- case GL.WGL_STENCIL_BITS_ARB:
- res.setStencilBits(iresults[i]);
- break;
-
- case GL.WGL_DOUBLE_BUFFER_ARB:
- res.setDoubleBuffered(iresults[i] == GL.GL_TRUE);
- break;
-
- case GL.WGL_STEREO_ARB:
- res.setStereo(iresults[i] == GL.GL_TRUE);
- break;
-
- case GL.WGL_PIXEL_TYPE_ARB:
- if (iresults[i] != GL.WGL_TYPE_RGBA_ARB)
- return null;
- break;
-
- case GL.WGL_RED_BITS_ARB:
- res.setRedBits(iresults[i]);
- break;
-
- case GL.WGL_GREEN_BITS_ARB:
- res.setGreenBits(iresults[i]);
- break;
-
- case GL.WGL_BLUE_BITS_ARB:
- res.setBlueBits(iresults[i]);
- break;
-
- case GL.WGL_ALPHA_BITS_ARB:
- res.setAlphaBits(iresults[i]);
- break;
-
- case GL.WGL_ACCUM_RED_BITS_ARB:
- res.setAccumRedBits(iresults[i]);
- break;
-
- case GL.WGL_ACCUM_GREEN_BITS_ARB:
- res.setAccumGreenBits(iresults[i]);
- break;
-
- case GL.WGL_ACCUM_BLUE_BITS_ARB:
- res.setAccumBlueBits(iresults[i]);
- break;
-
- case GL.WGL_ACCUM_ALPHA_BITS_ARB:
- res.setAccumAlphaBits(iresults[i]);
- break;
-
- case GL.WGL_SAMPLE_BUFFERS_ARB:
- res.setSampleBuffers(iresults[i] == GL.GL_TRUE);
- break;
-
- case GL.WGL_SAMPLES_ARB:
- res.setNumSamples(iresults[i]);
- break;
-
- default:
- throw new GLException("Unknown pixel format attribute " + iattribs[i]);
- }
- }
- return res;
- }
-
- protected static String hdcToString(long hdc) {
- return "0x" + Long.toHexString(hdc);
- }
-
protected boolean haveWGLARBPbuffer() {
return haveWGLARBPbuffer;
}
diff --git a/src/net/java/games/jogl/impl/windows/WindowsGLContextFactory.java b/src/net/java/games/jogl/impl/windows/WindowsGLContextFactory.java
index dd6f8daca..d99554fcf 100644
--- a/src/net/java/games/jogl/impl/windows/WindowsGLContextFactory.java
+++ b/src/net/java/games/jogl/impl/windows/WindowsGLContextFactory.java
@@ -59,6 +59,10 @@ public class WindowsGLContextFactory extends GLContextFactory {
private static final boolean DEBUG = Debug.debug("WindowsGLContextFactory");
private static final boolean VERBOSE = Debug.verbose();
+ static {
+ NativeLibLoader.load();
+ }
+
// On Windows we want to be able to use some extension routines like
// wglChoosePixelFormatARB during the creation of the user's first
// GLContext. However, this and other routines' function pointers
@@ -139,17 +143,31 @@ public class WindowsGLContextFactory extends GLContextFactory {
return null;
}
- public GLContext createGLContext(Component component,
- GLCapabilities capabilities,
- GLCapabilitiesChooser chooser,
- GLContext shareWith) {
- if (component != null) {
- return new WindowsOnscreenGLContext(component, capabilities, chooser, shareWith);
- } else {
- return new WindowsOffscreenGLContext(capabilities, chooser, shareWith);
+ public GLDrawable getGLDrawable(Object target,
+ GLCapabilities capabilities,
+ GLCapabilitiesChooser chooser) {
+ if (target == null) {
+ throw new IllegalArgumentException("Null target");
+ }
+ if (!(target instanceof Component)) {
+ throw new IllegalArgumentException("GLDrawables not supported for objects of type " +
+ target.getClass().getName() + " (only Components are supported in this implementation)");
}
+ return new WindowsOnscreenGLDrawable((Component) target, capabilities, chooser);
}
-
+
+ public GLDrawableImpl createOffscreenDrawable(GLCapabilities capabilities,
+ GLCapabilitiesChooser chooser) {
+ return new WindowsOffscreenGLDrawable(capabilities, chooser);
+ }
+
+ // Return cached GL drawable
+ public static WindowsGLDrawable getDummyGLDrawable( final GraphicsDevice device ) {
+ checkForDummyContext( device );
+ NativeWindowStruct nws = (NativeWindowStruct) dummyContextMap.get(device);
+ return nws.getWindowsDrawable();
+ }
+
// Return cached GL context
public static WindowsGLContext getDummyGLContext( final GraphicsDevice device ) {
checkForDummyContext( device );
@@ -188,7 +206,9 @@ public class WindowsGLContextFactory extends GLContextFactory {
GLCapabilities caps = new GLCapabilities();
caps.setDepthBits( 16 );
// Create a context that we use to query pixel formats
- WindowsOnscreenGLContext context = new WindowsOnscreenGLContext( null, caps, null, null );
+
+ WindowsOnscreenGLDrawable drawable = new WindowsOnscreenGLDrawable(null, caps, null);
+ WindowsOnscreenGLContext context = new WindowsOnscreenGLContext( drawable, null );
// Start a native thread and grab native screen resources from the thread
NativeWindowThread nwt = new NativeWindowThread( rect );
nwt.start();
@@ -198,7 +218,7 @@ public class WindowsGLContextFactory extends GLContextFactory {
Thread.yield();
}
// Choose a hardware accelerated pixel format
- PIXELFORMATDESCRIPTOR pfd = context.glCapabilities2PFD( caps, true );
+ PIXELFORMATDESCRIPTOR pfd = drawable.glCapabilities2PFD( caps, true );
int pixelFormat = WGL.ChoosePixelFormat( tempHDC, pfd );
if( pixelFormat == 0 ) {
System.err.println("Pixel Format is Zero");
@@ -220,6 +240,7 @@ public class WindowsGLContextFactory extends GLContextFactory {
// Store native handles for later use
NativeWindowStruct nws = new NativeWindowStruct();
nws.setHWND( hWnd );
+ nws.setWindowsDrawable( drawable );
nws.setWindowsContext( context );
nws.setWindowThread( nwt );
long currentHDC = WGL.wglGetCurrentDC();
@@ -230,7 +251,7 @@ public class WindowsGLContextFactory extends GLContextFactory {
return;
}
// Grab function pointers
- context.hdc = tempHDC;
+ drawable.hdc = tempHDC;
context.hglrc = tempHGLRC;
context.resetGLFunctionAvailability();
context.createGL();
@@ -259,6 +280,7 @@ public class WindowsGLContextFactory extends GLContextFactory {
*/
static class NativeWindowStruct {
private long HWND;
+ private WindowsGLDrawable windowsDrawable;
private WindowsGLContext windowsContext;
private Thread windowThread;
@@ -266,7 +288,7 @@ public class WindowsGLContextFactory extends GLContextFactory {
}
public long getHDC() {
- return( windowsContext.hdc );
+ return( windowsDrawable.hdc );
}
public long getHGLRC() {
@@ -281,10 +303,18 @@ public class WindowsGLContextFactory extends GLContextFactory {
return( HWND );
}
+ public void setWindowsDrawable( WindowsGLDrawable drawable ) {
+ windowsDrawable = drawable;
+ }
+
public void setWindowsContext( WindowsGLContext context ) {
windowsContext = context;
}
+ public WindowsGLDrawable getWindowsDrawable() {
+ return( windowsDrawable );
+ }
+
public WindowsGLContext getWindowsContext() {
return( windowsContext );
}
@@ -358,4 +388,19 @@ public class WindowsGLContextFactory extends GLContextFactory {
}
}
}
+
+
+ static String wglGetLastError() {
+ int err = WGL.GetLastError();
+ String detail = null;
+ switch (err) {
+ case WGL.ERROR_INVALID_PIXEL_FORMAT: detail = "ERROR_INVALID_PIXEL_FORMAT"; break;
+ case WGL.ERROR_NO_SYSTEM_RESOURCES: detail = "ERROR_NO_SYSTEM_RESOURCES"; break;
+ case WGL.ERROR_INVALID_DATA: detail = "ERROR_INVALID_DATA"; break;
+ case WGL.ERROR_PROC_NOT_FOUND: detail = "ERROR_PROC_NOT_FOUND"; break;
+ case WGL.ERROR_INVALID_WINDOW_HANDLE:detail = "ERROR_INVALID_WINDOW_HANDLE"; break;
+ default: detail = "(Unknown error code " + err + ")"; break;
+ }
+ return detail;
+ }
}
diff --git a/src/net/java/games/jogl/impl/windows/WindowsGLDrawable.java b/src/net/java/games/jogl/impl/windows/WindowsGLDrawable.java
new file mode 100644
index 000000000..42e83c05d
--- /dev/null
+++ b/src/net/java/games/jogl/impl/windows/WindowsGLDrawable.java
@@ -0,0 +1,497 @@
+/*
+ * 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.windows;
+
+import java.awt.Component;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
+
+import net.java.games.jogl.*;
+import net.java.games.jogl.impl.*;
+
+public abstract class WindowsGLDrawable extends GLDrawableImpl {
+ protected static final boolean DEBUG = Debug.debug("WindowsGLDrawable");
+
+ protected long hdc;
+ protected Component component;
+ protected GLCapabilities capabilities;
+ protected GLCapabilitiesChooser chooser;
+ protected boolean pixelFormatChosen;
+
+ protected static final int MAX_PFORMATS = 256;
+ protected static final int MAX_ATTRIBS = 256;
+
+ public WindowsGLDrawable(Component component,
+ GLCapabilities capabilities,
+ GLCapabilitiesChooser chooser) {
+ this.component = component;
+ this.capabilities = (GLCapabilities) capabilities.clone();
+ this.chooser = chooser;
+ }
+
+ public void setRealized(boolean val) {
+ throw new GLException("Should not call this (should only be called for onscreen GLDrawables)");
+ }
+
+ public void destroy() {
+ throw new GLException("Should not call this (should only be called for offscreen GLDrawables)");
+ }
+
+ public void swapBuffers() throws GLException {
+ }
+
+ public long getHDC() {
+ return hdc;
+ }
+
+ public void choosePixelFormat(boolean onscreen) {
+ PIXELFORMATDESCRIPTOR pfd = null;
+ int pixelFormat = 0;
+ if (onscreen) {
+ GLCapabilities[] availableCaps = null;
+ int numFormats = 0;
+ pfd = newPixelFormatDescriptor();
+ GraphicsConfiguration config = component.getGraphicsConfiguration();
+ GraphicsDevice device = config.getDevice();
+ // Produce a recommended pixel format selection for the GLCapabilitiesChooser.
+ // Use wglChoosePixelFormatARB if user requested multisampling and if we have it available
+ GL dummyGL = null;
+ if (capabilities.getSampleBuffers()) {
+ dummyGL = WindowsGLContextFactory.getDummyGL(device);
+ }
+ int recommendedPixelFormat = -1;
+ boolean haveWGLChoosePixelFormatARB = false;
+ boolean haveWGLARBMultisample = false;
+ if (dummyGL != null) {
+ String availableWGLExtensions = WindowsGLContextFactory.getDummyGLExtensions(device);
+ if (availableWGLExtensions.indexOf("WGL_ARB_pixel_format") >= 0) {
+ haveWGLChoosePixelFormatARB = true;
+ if (availableWGLExtensions.indexOf("WGL_ARB_multisample") >= 0) {
+ haveWGLARBMultisample = true;
+ }
+ }
+ }
+ long dc = 0;
+ long rc = 0;
+ boolean freeWGLC = false;
+ if( dummyGL != null ) {
+ dc = WindowsGLContextFactory.getDummyGLDrawable( device ).hdc;
+ rc = WindowsGLContextFactory.getDummyGLContext( device ).hglrc;
+ if( !WGL.wglMakeCurrent( dc, rc ) ) {
+ System.err.println(getThreadName() + ": Error Making WGLC Current: " + WGL.GetLastError() );
+ } else {
+ freeWGLC = true;
+ }
+ }
+ // Fallback path for older cards, in particular Intel Extreme motherboard graphics
+ boolean gotAvailableCaps = false;
+ if (dummyGL != null && haveWGLChoosePixelFormatARB) {
+ int[] iattributes = new int [2 * MAX_ATTRIBS];
+ int[] iresults = new int [2 * MAX_ATTRIBS];
+ float[] fattributes = new float[2 * MAX_ATTRIBS];
+ int niattribs = 0;
+ int nfattribs = 0;
+ iattributes[niattribs++] = GL.WGL_SUPPORT_OPENGL_ARB;
+ iattributes[niattribs++] = GL.GL_TRUE;
+ iattributes[niattribs++] = GL.WGL_DRAW_TO_WINDOW_ARB;
+ iattributes[niattribs++] = GL.GL_TRUE;
+ iattributes[niattribs++] = GL.WGL_PIXEL_TYPE_ARB;
+ iattributes[niattribs++] = GL.WGL_TYPE_RGBA_ARB;
+ iattributes[niattribs++] = GL.WGL_DOUBLE_BUFFER_ARB;
+ if (capabilities.getDoubleBuffered()) {
+ iattributes[niattribs++] = GL.GL_TRUE;
+ } else {
+ iattributes[niattribs++] = GL.GL_FALSE;
+ }
+ iattributes[niattribs++] = GL.WGL_STEREO_ARB;
+ if (capabilities.getStereo()) {
+ iattributes[niattribs++] = GL.GL_TRUE;
+ } else {
+ iattributes[niattribs++] = GL.GL_FALSE;
+ }
+ iattributes[niattribs++] = GL.WGL_DEPTH_BITS_ARB;
+ iattributes[niattribs++] = capabilities.getDepthBits();
+ iattributes[niattribs++] = GL.WGL_RED_BITS_ARB;
+ iattributes[niattribs++] = capabilities.getRedBits();
+ iattributes[niattribs++] = GL.WGL_GREEN_BITS_ARB;
+ iattributes[niattribs++] = capabilities.getGreenBits();
+ iattributes[niattribs++] = GL.WGL_BLUE_BITS_ARB;
+ iattributes[niattribs++] = capabilities.getBlueBits();
+ iattributes[niattribs++] = GL.WGL_ALPHA_BITS_ARB;
+ iattributes[niattribs++] = capabilities.getAlphaBits();
+ iattributes[niattribs++] = GL.WGL_STENCIL_BITS_ARB;
+ iattributes[niattribs++] = capabilities.getStencilBits();
+ if (capabilities.getAccumRedBits() > 0 ||
+ capabilities.getAccumGreenBits() > 0 ||
+ capabilities.getAccumBlueBits() > 0 ||
+ capabilities.getAccumAlphaBits() > 0) {
+ iattributes[niattribs++] = GL.WGL_ACCUM_BITS_ARB;
+ iattributes[niattribs++] = (capabilities.getAccumRedBits() +
+ capabilities.getAccumGreenBits() +
+ capabilities.getAccumBlueBits() +
+ capabilities.getAccumAlphaBits());
+ iattributes[niattribs++] = GL.WGL_ACCUM_RED_BITS_ARB;
+ iattributes[niattribs++] = capabilities.getAccumRedBits();
+ iattributes[niattribs++] = GL.WGL_ACCUM_GREEN_BITS_ARB;
+ iattributes[niattribs++] = capabilities.getAccumGreenBits();
+ iattributes[niattribs++] = GL.WGL_ACCUM_BLUE_BITS_ARB;
+ iattributes[niattribs++] = capabilities.getAccumBlueBits();
+ iattributes[niattribs++] = GL.WGL_ACCUM_ALPHA_BITS_ARB;
+ iattributes[niattribs++] = capabilities.getAccumAlphaBits();
+ }
+ if (haveWGLARBMultisample) {
+ if (capabilities.getSampleBuffers()) {
+ iattributes[niattribs++] = GL.WGL_SAMPLE_BUFFERS_ARB;
+ iattributes[niattribs++] = GL.GL_TRUE;
+ iattributes[niattribs++] = GL.WGL_SAMPLES_ARB;
+ iattributes[niattribs++] = capabilities.getNumSamples();
+ }
+ }
+
+ int[] pformats = new int[MAX_PFORMATS];
+ int[] numFormatsTmp = new int[1];
+ if (dummyGL.wglChoosePixelFormatARB(hdc,
+ iattributes, 0,
+ fattributes, 0,
+ MAX_PFORMATS,
+ pformats, 0,
+ numFormatsTmp, 0)) {
+ numFormats = numFormatsTmp[0];
+ if (numFormats > 0) {
+ // Remove one-basing of pixel format (added on later)
+ recommendedPixelFormat = pformats[0] - 1;
+ if (DEBUG) {
+ System.err.println(getThreadName() + ": Used wglChoosePixelFormatARB to recommend pixel format " + recommendedPixelFormat);
+ }
+ }
+ } else {
+ if (DEBUG) {
+ System.err.println(getThreadName() + ": wglChoosePixelFormatARB failed: " + WGL.GetLastError() );
+ Thread.dumpStack();
+ }
+ }
+ if (DEBUG) {
+ if (recommendedPixelFormat < 0) {
+ System.err.print(getThreadName() + ": wglChoosePixelFormatARB didn't recommend a pixel format");
+ if (capabilities.getSampleBuffers()) {
+ System.err.print(" for multisampled GLCapabilities");
+ }
+ System.err.println();
+ }
+ }
+
+ // Produce a list of GLCapabilities to give to the
+ // GLCapabilitiesChooser.
+ // Use wglGetPixelFormatAttribivARB instead of
+ // DescribePixelFormat to get higher-precision information
+ // about the pixel format (should make the GLCapabilities
+ // more precise as well...i.e., remove the
+ // "HardwareAccelerated" bit, which is basically
+ // meaningless, and put in whether it can render to a
+ // window, to a pbuffer, or to a pixmap)
+ niattribs = 0;
+ iattributes[0] = GL.WGL_NUMBER_PIXEL_FORMATS_ARB;
+ if (dummyGL.wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, iattributes, 0, iresults, 0)) {
+ numFormats = iresults[0];
+ // Should we be filtering out the pixel formats which aren't
+ // applicable, as we are doing here?
+ // We don't have enough information in the GLCapabilities to
+ // represent those that aren't...
+ iattributes[niattribs++] = GL.WGL_DRAW_TO_WINDOW_ARB;
+ iattributes[niattribs++] = GL.WGL_ACCELERATION_ARB;
+ iattributes[niattribs++] = GL.WGL_SUPPORT_OPENGL_ARB;
+ iattributes[niattribs++] = GL.WGL_DEPTH_BITS_ARB;
+ iattributes[niattribs++] = GL.WGL_STENCIL_BITS_ARB;
+ iattributes[niattribs++] = GL.WGL_DOUBLE_BUFFER_ARB;
+ iattributes[niattribs++] = GL.WGL_STEREO_ARB;
+ iattributes[niattribs++] = GL.WGL_PIXEL_TYPE_ARB;
+ iattributes[niattribs++] = GL.WGL_RED_BITS_ARB;
+ iattributes[niattribs++] = GL.WGL_GREEN_BITS_ARB;
+ iattributes[niattribs++] = GL.WGL_BLUE_BITS_ARB;
+ iattributes[niattribs++] = GL.WGL_ALPHA_BITS_ARB;
+ iattributes[niattribs++] = GL.WGL_ACCUM_RED_BITS_ARB;
+ iattributes[niattribs++] = GL.WGL_ACCUM_GREEN_BITS_ARB;
+ iattributes[niattribs++] = GL.WGL_ACCUM_BLUE_BITS_ARB;
+ iattributes[niattribs++] = GL.WGL_ACCUM_ALPHA_BITS_ARB;
+ if (haveWGLARBMultisample) {
+ iattributes[niattribs++] = GL.WGL_SAMPLE_BUFFERS_ARB;
+ iattributes[niattribs++] = GL.WGL_SAMPLES_ARB;
+ }
+
+ availableCaps = new GLCapabilities[numFormats];
+ for (int i = 0; i < numFormats; i++) {
+ if (!dummyGL.wglGetPixelFormatAttribivARB(hdc, i+1, 0, niattribs, iattributes, 0, iresults, 0)) {
+ throw new GLException("Error getting pixel format attributes for pixel format " + (i + 1) + " of device context");
+ }
+ availableCaps[i] = iattributes2GLCapabilities(iattributes, iresults, niattribs, true);
+ }
+ if( freeWGLC ) {
+ WGL.wglMakeCurrent( 0, 0 );
+ }
+ gotAvailableCaps = true;
+ } else {
+ int lastErr = WGL.GetLastError();
+ // Intel Extreme graphics fails with a zero error code
+ if (lastErr != 0) {
+ throw new GLException("Unable to enumerate pixel formats of window using wglGetPixelFormatAttribivARB: error code " + WGL.GetLastError());
+ }
+ }
+ }
+
+ if (!gotAvailableCaps) {
+ if (DEBUG) {
+ if (!capabilities.getSampleBuffers()) {
+ System.err.println(getThreadName() + ": Using ChoosePixelFormat because multisampling not requested");
+ } else {
+ System.err.println(getThreadName() + ": Using ChoosePixelFormat because no wglChoosePixelFormatARB: dummyGL = " + dummyGL);
+ }
+ }
+ pfd = glCapabilities2PFD(capabilities, onscreen);
+ // Remove one-basing of pixel format (added on later)
+ recommendedPixelFormat = WGL.ChoosePixelFormat(hdc, pfd) - 1;
+
+ numFormats = WGL.DescribePixelFormat(hdc, 1, 0, null);
+ if (numFormats == 0) {
+ throw new GLException("Unable to enumerate pixel formats of window for GLCapabilitiesChooser");
+ }
+ availableCaps = new GLCapabilities[numFormats];
+ for (int i = 0; i < numFormats; i++) {
+ if (WGL.DescribePixelFormat(hdc, 1 + i, pfd.size(), pfd) == 0) {
+ throw new GLException("Error describing pixel format " + (1 + i) + " of device context");
+ }
+ availableCaps[i] = pfd2GLCapabilities(pfd);
+ }
+ }
+
+ // Supply information to chooser
+ pixelFormat = chooser.chooseCapabilities(capabilities, availableCaps, recommendedPixelFormat);
+ if ((pixelFormat < 0) || (pixelFormat >= numFormats)) {
+ throw new GLException("Invalid result " + pixelFormat +
+ " from GLCapabilitiesChooser (should be between 0 and " +
+ (numFormats - 1) + ")");
+ }
+ if (DEBUG) {
+ System.err.println(getThreadName() + ": Chosen pixel format (" + pixelFormat + "):");
+ System.err.println(availableCaps[pixelFormat]);
+ }
+ pixelFormat += 1; // one-base the index
+ if (WGL.DescribePixelFormat(hdc, pixelFormat, pfd.size(), pfd) == 0) {
+ throw new GLException("Error re-describing the chosen pixel format: " + WGL.GetLastError());
+ }
+ } else {
+ // For now, use ChoosePixelFormat for offscreen surfaces until
+ // we figure out how to properly choose an offscreen-
+ // compatible pixel format
+ pfd = glCapabilities2PFD(capabilities, onscreen);
+ pixelFormat = WGL.ChoosePixelFormat(hdc, pfd);
+ }
+ if (!WGL.SetPixelFormat(hdc, pixelFormat, pfd)) {
+ int lastError = WGL.GetLastError();
+ if (DEBUG) {
+ System.err.println(getThreadName() + ": SetPixelFormat failed: current context = " + WGL.wglGetCurrentContext() +
+ ", current DC = " + WGL.wglGetCurrentDC());
+ System.err.println(getThreadName() + ": GetPixelFormat(hdc " + toHexString(hdc) + ") returns " + WGL.GetPixelFormat(hdc));
+ }
+ throw new GLException("Unable to set pixel format " + pixelFormat + " for device context " + toHexString(hdc) + ": error code " + lastError);
+ }
+ pixelFormatChosen = true;
+ }
+
+ static PIXELFORMATDESCRIPTOR glCapabilities2PFD(GLCapabilities caps, boolean onscreen) {
+ int colorDepth = (caps.getRedBits() +
+ caps.getGreenBits() +
+ caps.getBlueBits());
+ if (colorDepth < 15) {
+ throw new GLException("Bit depths < 15 (i.e., non-true-color) not supported");
+ }
+ PIXELFORMATDESCRIPTOR pfd = newPixelFormatDescriptor();
+ int pfdFlags = (WGL.PFD_SUPPORT_OPENGL |
+ WGL.PFD_GENERIC_ACCELERATED);
+ if (caps.getDoubleBuffered()) {
+ pfdFlags |= WGL.PFD_DOUBLEBUFFER;
+ }
+ if (onscreen) {
+ pfdFlags |= WGL.PFD_DRAW_TO_WINDOW;
+ } else {
+ pfdFlags |= WGL.PFD_DRAW_TO_BITMAP;
+ }
+ pfd.dwFlags(pfdFlags);
+ pfd.iPixelType((byte) WGL.PFD_TYPE_RGBA);
+ pfd.cColorBits((byte) colorDepth);
+ pfd.cRedBits ((byte) caps.getRedBits());
+ pfd.cGreenBits((byte) caps.getGreenBits());
+ pfd.cBlueBits ((byte) caps.getBlueBits());
+ pfd.cAlphaBits((byte) caps.getAlphaBits());
+ int accumDepth = (caps.getAccumRedBits() +
+ caps.getAccumGreenBits() +
+ caps.getAccumBlueBits());
+ pfd.cAccumBits ((byte) accumDepth);
+ pfd.cAccumRedBits ((byte) caps.getAccumRedBits());
+ pfd.cAccumGreenBits((byte) caps.getAccumGreenBits());
+ pfd.cAccumBlueBits ((byte) caps.getAccumBlueBits());
+ pfd.cAccumAlphaBits((byte) caps.getAccumAlphaBits());
+ pfd.cDepthBits((byte) caps.getDepthBits());
+ pfd.cStencilBits((byte) caps.getStencilBits());
+ pfd.iLayerType((byte) WGL.PFD_MAIN_PLANE);
+ return pfd;
+ }
+
+ static PIXELFORMATDESCRIPTOR newPixelFormatDescriptor() {
+ PIXELFORMATDESCRIPTOR pfd = new PIXELFORMATDESCRIPTOR();
+ pfd.nSize((short) pfd.size());
+ pfd.nVersion((short) 1);
+ return pfd;
+ }
+
+ static GLCapabilities pfd2GLCapabilities(PIXELFORMATDESCRIPTOR pfd) {
+ if ((pfd.dwFlags() & WGL.PFD_SUPPORT_OPENGL) == 0) {
+ return null;
+ }
+ GLCapabilities res = new GLCapabilities();
+ res.setRedBits (pfd.cRedBits());
+ res.setGreenBits (pfd.cGreenBits());
+ res.setBlueBits (pfd.cBlueBits());
+ res.setAlphaBits (pfd.cAlphaBits());
+ res.setAccumRedBits (pfd.cAccumRedBits());
+ res.setAccumGreenBits(pfd.cAccumGreenBits());
+ res.setAccumBlueBits (pfd.cAccumBlueBits());
+ res.setAccumAlphaBits(pfd.cAccumAlphaBits());
+ res.setDepthBits (pfd.cDepthBits());
+ res.setStencilBits (pfd.cStencilBits());
+ res.setDoubleBuffered((pfd.dwFlags() & WGL.PFD_DOUBLEBUFFER) != 0);
+ res.setStereo ((pfd.dwFlags() & WGL.PFD_STEREO) != 0);
+ res.setHardwareAccelerated(((pfd.dwFlags() & WGL.PFD_GENERIC_FORMAT) == 0) ||
+ ((pfd.dwFlags() & WGL.PFD_GENERIC_ACCELERATED) != 0));
+ return res;
+ }
+
+ static GLCapabilities iattributes2GLCapabilities(int[] iattribs,
+ int[] iresults,
+ int niattribs,
+ boolean requireRenderToWindow) {
+ GLCapabilities res = new GLCapabilities();
+ for (int i = 0; i < niattribs; i++) {
+ switch (iattribs[i]) {
+ case GL.WGL_DRAW_TO_WINDOW_ARB:
+ if (iresults[i] != GL.GL_TRUE)
+ return null;
+ break;
+
+ case GL.WGL_ACCELERATION_ARB:
+ res.setHardwareAccelerated(iresults[i] == GL.WGL_FULL_ACCELERATION_ARB);
+ break;
+
+ case GL.WGL_SUPPORT_OPENGL_ARB:
+ if (iresults[i] != GL.GL_TRUE)
+ return null;
+ break;
+
+ case GL.WGL_DEPTH_BITS_ARB:
+ res.setDepthBits(iresults[i]);
+ break;
+
+ case GL.WGL_STENCIL_BITS_ARB:
+ res.setStencilBits(iresults[i]);
+ break;
+
+ case GL.WGL_DOUBLE_BUFFER_ARB:
+ res.setDoubleBuffered(iresults[i] == GL.GL_TRUE);
+ break;
+
+ case GL.WGL_STEREO_ARB:
+ res.setStereo(iresults[i] == GL.GL_TRUE);
+ break;
+
+ case GL.WGL_PIXEL_TYPE_ARB:
+ if (iresults[i] != GL.WGL_TYPE_RGBA_ARB)
+ return null;
+ break;
+
+ case GL.WGL_RED_BITS_ARB:
+ res.setRedBits(iresults[i]);
+ break;
+
+ case GL.WGL_GREEN_BITS_ARB:
+ res.setGreenBits(iresults[i]);
+ break;
+
+ case GL.WGL_BLUE_BITS_ARB:
+ res.setBlueBits(iresults[i]);
+ break;
+
+ case GL.WGL_ALPHA_BITS_ARB:
+ res.setAlphaBits(iresults[i]);
+ break;
+
+ case GL.WGL_ACCUM_RED_BITS_ARB:
+ res.setAccumRedBits(iresults[i]);
+ break;
+
+ case GL.WGL_ACCUM_GREEN_BITS_ARB:
+ res.setAccumGreenBits(iresults[i]);
+ break;
+
+ case GL.WGL_ACCUM_BLUE_BITS_ARB:
+ res.setAccumBlueBits(iresults[i]);
+ break;
+
+ case GL.WGL_ACCUM_ALPHA_BITS_ARB:
+ res.setAccumAlphaBits(iresults[i]);
+ break;
+
+ case GL.WGL_SAMPLE_BUFFERS_ARB:
+ res.setSampleBuffers(iresults[i] == GL.GL_TRUE);
+ break;
+
+ case GL.WGL_SAMPLES_ARB:
+ res.setNumSamples(iresults[i]);
+ break;
+
+ default:
+ throw new GLException("Unknown pixel format attribute " + iattribs[i]);
+ }
+ }
+ return res;
+ }
+
+ protected static String getThreadName() {
+ return Thread.currentThread().getName();
+ }
+}
diff --git a/src/net/java/games/jogl/impl/windows/WindowsOffscreenGLContext.java b/src/net/java/games/jogl/impl/windows/WindowsOffscreenGLContext.java
index d944a8684..a2fae5971 100644
--- a/src/net/java/games/jogl/impl/windows/WindowsOffscreenGLContext.java
+++ b/src/net/java/games/jogl/impl/windows/WindowsOffscreenGLContext.java
@@ -39,38 +39,13 @@
package net.java.games.jogl.impl.windows;
-import java.awt.image.BufferedImage;
import net.java.games.jogl.*;
import net.java.games.jogl.impl.*;
public class WindowsOffscreenGLContext extends WindowsGLContext {
- private long origbitmap;
- private long hbitmap;
- // Width and height of the underlying bitmap
- private int width;
- private int height;
-
- public WindowsOffscreenGLContext(GLCapabilities capabilities,
- GLCapabilitiesChooser chooser,
+ public WindowsOffscreenGLContext(WindowsOffscreenGLDrawable drawable,
GLContext shareWith) {
- super(null, capabilities, chooser, shareWith);
- }
-
- protected GL createGL()
- {
- return new WindowsGLImpl(this);
- }
-
- protected boolean isOffscreen() {
- return true;
- }
-
- public int getOffscreenContextWidth() {
- return width;
- }
-
- public int getOffscreenContextHeight() {
- return height;
+ super(drawable, shareWith);
}
public int getOffscreenContextPixelDataType() {
@@ -92,9 +67,9 @@ public class WindowsOffscreenGLContext extends WindowsGLContext {
return false;
}
- public GLContext createPbufferContext(GLCapabilities capabilities,
- int initialWidth,
- int initialHeight) {
+ public GLDrawableImpl createPbufferDrawable(GLCapabilities capabilities,
+ int initialWidth,
+ int initialHeight) {
throw new GLException("Not supported");
}
@@ -105,72 +80,4 @@ public class WindowsOffscreenGLContext extends WindowsGLContext {
public void releasePbufferFromTexture() {
throw new GLException("Should not call this");
}
-
- protected int makeCurrentImpl() throws GLException {
- if (pendingOffscreenResize) {
- if (pendingOffscreenWidth != width || pendingOffscreenHeight != height) {
- if (hglrc != 0) {
- destroyImpl();
- }
- width = pendingOffscreenWidth;
- height = pendingOffscreenHeight;
- pendingOffscreenResize = false;
- }
- }
- return super.makeCurrentImpl();
- }
-
- protected void destroyImpl() {
- if (hglrc != 0) {
- super.destroyImpl();
- // Must destroy OpenGL context, bitmap and device context
- WGL.SelectObject(hdc, origbitmap);
- WGL.DeleteObject(hbitmap);
- WGL.DeleteDC(hdc);
- origbitmap = 0;
- hbitmap = 0;
- hdc = 0;
- }
- }
-
- public void swapBuffers() throws GLException {
- }
-
- protected void create() {
- BITMAPINFO info = new BITMAPINFO();
- BITMAPINFOHEADER header = info.bmiHeader();
- int bitsPerPixel = (capabilities.getRedBits() +
- capabilities.getGreenBits() +
- capabilities.getBlueBits());
- header.biSize(header.size());
- header.biWidth(width);
- // NOTE: negating the height causes the DIB to be in top-down row
- // order rather than bottom-up; ends up being correct during pixel
- // readback
- header.biHeight(-1 * height);
- header.biPlanes((short) 1);
- header.biBitCount((short) bitsPerPixel);
- header.biXPelsPerMeter(0);
- header.biYPelsPerMeter(0);
- header.biClrUsed(0);
- header.biClrImportant(0);
- header.biCompression(WGL.BI_RGB);
- header.biSizeImage(width * height * bitsPerPixel / 8);
-
- hdc = WGL.CreateCompatibleDC(0);
- if (hdc == 0) {
- System.out.println("LastError: " + WGL.GetLastError());
- throw new GLException("Error creating device context for offscreen OpenGL context");
- }
- hbitmap = WGL.CreateDIBSection(hdc, info, WGL.DIB_RGB_COLORS, 0, 0, 0);
- if (hbitmap == 0) {
- throw new GLException("Error creating offscreen bitmap of width " + width +
- ", height " + height);
- }
- if ((origbitmap = WGL.SelectObject(hdc, hbitmap)) == 0) {
- throw new GLException("Error selecting bitmap into new device context");
- }
-
- choosePixelFormatAndCreateContext(false);
- }
}
diff --git a/src/net/java/games/jogl/impl/windows/WindowsOffscreenGLDrawable.java b/src/net/java/games/jogl/impl/windows/WindowsOffscreenGLDrawable.java
new file mode 100644
index 000000000..03d76574a
--- /dev/null
+++ b/src/net/java/games/jogl/impl/windows/WindowsOffscreenGLDrawable.java
@@ -0,0 +1,133 @@
+/*
+ * 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.windows;
+
+import net.java.games.jogl.*;
+import net.java.games.jogl.impl.*;
+
+public class WindowsOffscreenGLDrawable extends WindowsGLDrawable {
+ private long origbitmap;
+ private long hbitmap;
+ // Width and height of the underlying bitmap
+ private int width;
+ private int height;
+
+ public WindowsOffscreenGLDrawable(GLCapabilities capabilities,
+ GLCapabilitiesChooser chooser) {
+ super(null, capabilities, chooser);
+ }
+
+ public GLContext createContext(GLContext shareWith) {
+ return new WindowsOffscreenGLContext(this, shareWith);
+ }
+
+ public void setSize(int newWidth, int newHeight) {
+ width = newWidth;
+ height = newHeight;
+ if (hdc != 0) {
+ destroy();
+ }
+ create();
+ }
+
+ public int getWidth() {
+ return width;
+ }
+
+ public int getHeight() {
+ return height;
+ }
+
+ private void create() {
+ BITMAPINFO info = new BITMAPINFO();
+ BITMAPINFOHEADER header = info.bmiHeader();
+ int bitsPerPixel = (capabilities.getRedBits() +
+ capabilities.getGreenBits() +
+ capabilities.getBlueBits());
+ header.biSize(header.size());
+ header.biWidth(width);
+ // NOTE: negating the height causes the DIB to be in top-down row
+ // order rather than bottom-up; ends up being correct during pixel
+ // readback
+ header.biHeight(-1 * height);
+ header.biPlanes((short) 1);
+ header.biBitCount((short) bitsPerPixel);
+ header.biXPelsPerMeter(0);
+ header.biYPelsPerMeter(0);
+ header.biClrUsed(0);
+ header.biClrImportant(0);
+ header.biCompression(WGL.BI_RGB);
+ header.biSizeImage(width * height * bitsPerPixel / 8);
+
+ hdc = WGL.CreateCompatibleDC(0);
+ if (hdc == 0) {
+ System.out.println("LastError: " + WGL.GetLastError());
+ throw new GLException("Error creating device context for offscreen OpenGL context");
+ }
+ hbitmap = WGL.CreateDIBSection(hdc, info, WGL.DIB_RGB_COLORS, 0, 0, 0);
+ if (hbitmap == 0) {
+ WGL.DeleteDC(hdc);
+ hdc = 0;
+ throw new GLException("Error creating offscreen bitmap of width " + width +
+ ", height " + height);
+ }
+ if ((origbitmap = WGL.SelectObject(hdc, hbitmap)) == 0) {
+ WGL.DeleteObject(hbitmap);
+ hbitmap = 0;
+ WGL.DeleteDC(hdc);
+ hdc = 0;
+ throw new GLException("Error selecting bitmap into new device context");
+ }
+
+ choosePixelFormat(false);
+ }
+
+ public void destroy() {
+ if (hdc != 0) {
+ // Must destroy bitmap and device context
+ WGL.SelectObject(hdc, origbitmap);
+ WGL.DeleteObject(hbitmap);
+ WGL.DeleteDC(hdc);
+ origbitmap = 0;
+ hbitmap = 0;
+ hdc = 0;
+ }
+ }
+}
diff --git a/src/net/java/games/jogl/impl/windows/WindowsOnscreenGLContext.java b/src/net/java/games/jogl/impl/windows/WindowsOnscreenGLContext.java
index d4af4b3b7..c71f35ff0 100644
--- a/src/net/java/games/jogl/impl/windows/WindowsOnscreenGLContext.java
+++ b/src/net/java/games/jogl/impl/windows/WindowsOnscreenGLContext.java
@@ -39,68 +39,20 @@
package net.java.games.jogl.impl.windows;
-import java.awt.Component;
import java.util.*;
import net.java.games.jogl.*;
import net.java.games.jogl.impl.*;
public class WindowsOnscreenGLContext extends WindowsGLContext {
- // Variables for lockSurface/unlockSurface
- JAWT_DrawingSurface ds;
- 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;
-
+ protected WindowsOnscreenGLDrawable drawable;
// Variables for pbuffer support
- List pbuffersToInstantiate = new ArrayList();
+ protected List pbuffersToInstantiate = new ArrayList();
- public WindowsOnscreenGLContext(Component component,
- GLCapabilities capabilities,
- GLCapabilitiesChooser chooser,
+ public WindowsOnscreenGLContext(WindowsOnscreenGLDrawable drawable,
GLContext shareWith) {
- 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
- // choosePixelFormatAndCreateContext calls
- // Component.getGraphicsConfiguration(), which grabs the tree
- // lock. To avoid deadlock we have to lock the tree lock before
- // grabbing the GLContext's lock if we're going to create an
- // OpenGL context during this call. This code might not be
- // completely correct, and we might need to uniformly grab the AWT
- // tree lock, which might become a performance issue...
- if (hglrc == 0) {
- synchronized(component.getTreeLock()) {
- super.invokeGL(runnable, isReshape, initAction);
- }
- } else {
- super.invokeGL(runnable, isReshape, initAction);
- }
- }
- */
-
- protected GL createGL()
- {
- return new WindowsGLImpl(this);
- }
-
- protected boolean isOffscreen() {
- return false;
+ super(drawable, shareWith);
+ this.drawable = drawable;
}
public int getOffscreenContextReadBuffer() {
@@ -115,13 +67,12 @@ public class WindowsOnscreenGLContext extends WindowsGLContext {
return haveWGLARBPbuffer();
}
- public GLContext createPbufferContext(GLCapabilities capabilities,
- int initialWidth,
- int initialHeight) {
- WindowsPbufferGLContext ctx = new WindowsPbufferGLContext(capabilities, initialWidth, initialHeight);
- ctx.setSynchronized(true);
- pbuffersToInstantiate.add(ctx);
- return ctx;
+ public GLDrawableImpl createPbufferDrawable(GLCapabilities capabilities,
+ int initialWidth,
+ int initialHeight) {
+ WindowsPbufferGLDrawable buf = new WindowsPbufferGLDrawable(capabilities, initialWidth, initialHeight);
+ pbuffersToInstantiate.add(buf);
+ return buf;
}
public void bindPbufferToTexture() {
@@ -132,32 +83,47 @@ public class WindowsOnscreenGLContext extends WindowsGLContext {
throw new GLException("Should not call this");
}
- public void setRealized() {
- realized = true;
- }
-
protected int makeCurrentImpl() throws GLException {
try {
- if (!realized) {
+ int lockRes = drawable.lockSurface();
+ if (lockRes == WindowsOnscreenGLDrawable.LOCK_SURFACE_NOT_READY) {
return CONTEXT_NOT_CURRENT;
}
- if (!lockSurface()) {
- return CONTEXT_NOT_CURRENT;
+ if (lockRes == WindowsOnscreenGLDrawable.LOCK_SURFACE_CHANGED) {
+ if (hglrc != 0) {
+ if (!WGL.wglDeleteContext(hglrc)) {
+ throw new GLException("Unable to delete old GL context after surface changed");
+ }
+ GLContextShareSet.contextDestroyed(this);
+ if (DEBUG) {
+ System.err.println(getThreadName() + ": !!! Destroyed OpenGL context " + toHexString(hglrc) + " due to JAWT_LOCK_SURFACE_CHANGED");
+ }
+ hglrc = 0;
+ }
}
int ret = super.makeCurrentImpl();
if ((ret == CONTEXT_CURRENT) ||
(ret == CONTEXT_CURRENT_NEW)) {
// Instantiate any pending pbuffers
- while (!pbuffersToInstantiate.isEmpty()) {
- WindowsPbufferGLContext ctx =
- (WindowsPbufferGLContext) pbuffersToInstantiate.remove(pbuffersToInstantiate.size() - 1);
- ctx.createPbuffer(hdc, hglrc);
+ // NOTE that we supply the drawable a GL instance for our
+ // context and that we eliminate all pipelines for it -- see
+ // WindowsPbufferGLDrawable.destroy()
+ if (!pbuffersToInstantiate.isEmpty()) {
+ GL tmpGL = createGL();
+ while (!pbuffersToInstantiate.isEmpty()) {
+ WindowsPbufferGLDrawable buf =
+ (WindowsPbufferGLDrawable) pbuffersToInstantiate.remove(pbuffersToInstantiate.size() - 1);
+ buf.createPbuffer(tmpGL, drawable.getHDC());
+ if (DEBUG) {
+ System.err.println(getThreadName() + ": created pbuffer " + buf);
+ }
+ }
}
}
return ret;
} catch (RuntimeException e) {
try {
- unlockSurface();
+ drawable.unlockSurface();
} catch (Exception e2) {
// do nothing if unlockSurface throws
}
@@ -169,88 +135,7 @@ public class WindowsOnscreenGLContext extends WindowsGLContext {
try {
super.releaseImpl();
} finally {
- unlockSurface();
- }
- }
-
- 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");
+ drawable.unlockSurface();
}
}
-
- private boolean lockSurface() throws GLException {
- if (hdc != 0) {
- throw new GLException("Surface already locked");
- }
- ds = getJAWT().GetDrawingSurface(component);
- if (ds == null) {
- // Widget not yet realized
- return false;
- }
- int res = ds.Lock();
- if ((res & JAWTFactory.JAWT_LOCK_ERROR) != 0) {
- throw new GLException("Unable to lock surface");
- }
- // See whether the surface changed and if so destroy the old
- // OpenGL context so it will be recreated (NOTE: removeNotify
- // should handle this case, but it may be possible that race
- // conditions can cause this code to be triggered -- should test
- // more)
- if ((res & JAWTFactory.JAWT_LOCK_SURFACE_CHANGED) != 0) {
- if (hglrc != 0) {
- if (!WGL.wglDeleteContext(hglrc)) {
- throw new GLException("Unable to delete old GL context after surface changed");
- }
- GLContextShareSet.contextDestroyed(this);
- if (DEBUG) {
- System.err.println(getThreadName() + ": !!! Destroyed OpenGL context " + hglrc + " due to JAWT_LOCK_SURFACE_CHANGED");
- }
- hglrc = 0;
- }
- }
- dsi = ds.GetDrawingSurfaceInfo();
- if (dsi == null) {
- // Widget not yet realized
- ds.Unlock();
- getJAWT().FreeDrawingSurface(ds);
- ds = null;
- return false;
- }
- win32dsi = (JAWT_Win32DrawingSurfaceInfo) dsi.platformInfo();
- hdc = win32dsi.hdc();
- if (hdc == 0) {
- // Widget not yet realized
- ds.FreeDrawingSurfaceInfo(dsi);
- ds.Unlock();
- getJAWT().FreeDrawingSurface(ds);
- ds = null;
- dsi = null;
- win32dsi = null;
- return false;
- }
- return true;
- }
-
- private void unlockSurface() {
- if (hdc == 0) {
- throw new GLException("Surface already unlocked");
- }
- ds.FreeDrawingSurfaceInfo(dsi);
- ds.Unlock();
- getJAWT().FreeDrawingSurface(ds);
- ds = null;
- dsi = null;
- win32dsi = null;
- hdc = 0;
- }
-
- protected void create() {
- choosePixelFormatAndCreateContext(true);
- }
}
diff --git a/src/net/java/games/jogl/impl/windows/WindowsOnscreenGLDrawable.java b/src/net/java/games/jogl/impl/windows/WindowsOnscreenGLDrawable.java
new file mode 100644
index 000000000..50cf5c9f4
--- /dev/null
+++ b/src/net/java/games/jogl/impl/windows/WindowsOnscreenGLDrawable.java
@@ -0,0 +1,181 @@
+/*
+ * 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.windows;
+
+import java.awt.Component;
+
+import net.java.games.jogl.*;
+import net.java.games.jogl.impl.*;
+
+public class WindowsOnscreenGLDrawable extends WindowsGLDrawable {
+ public static final int LOCK_SURFACE_NOT_READY = 1;
+ public static final int LOCK_SURFACE_CHANGED = 2;
+ public static final int LOCK_SUCCESS = 3;
+ private static JAWT jawt;
+
+ // Variables for lockSurface/unlockSurface
+ private JAWT_DrawingSurface ds;
+ private JAWT_DrawingSurfaceInfo dsi;
+ private 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;
+
+ public WindowsOnscreenGLDrawable(Component component,
+ GLCapabilities capabilities,
+ GLCapabilitiesChooser chooser) {
+ super(component, capabilities, chooser);
+ }
+
+ public GLContext createContext(GLContext shareWith) {
+ return new WindowsOnscreenGLContext(this, shareWith);
+ }
+
+ public void setRealized(boolean realized) {
+ this.realized = realized;
+ }
+
+ public void setSize(int width, int height) {
+ component.setSize(width, height);
+ }
+
+ public int getWidth() {
+ return component.getWidth();
+ }
+
+ public int getHeight() {
+ return component.getHeight();
+ }
+
+ public void swapBuffers() throws GLException {
+ if (!WGL.SwapBuffers(hdc) && (WGL.GetLastError() != 0)) {
+ throw new GLException("Error swapping buffers");
+ }
+ }
+
+ public int lockSurface() throws GLException {
+ if (!realized) {
+ return LOCK_SURFACE_NOT_READY;
+ }
+ if (hdc != 0) {
+ throw new GLException("Surface already locked");
+ }
+ ds = getJAWT().GetDrawingSurface(component);
+ if (ds == null) {
+ // Widget not yet realized
+ return LOCK_SURFACE_NOT_READY;
+ }
+ int res = ds.Lock();
+ if ((res & JAWTFactory.JAWT_LOCK_ERROR) != 0) {
+ throw new GLException("Unable to lock surface");
+ }
+ // See whether the surface changed and if so destroy the old
+ // OpenGL context so it will be recreated (NOTE: removeNotify
+ // should handle this case, but it may be possible that race
+ // conditions can cause this code to be triggered -- should test
+ // more)
+ int ret = LOCK_SUCCESS;
+ if ((res & JAWTFactory.JAWT_LOCK_SURFACE_CHANGED) != 0) {
+ ret = LOCK_SURFACE_CHANGED;
+ }
+ dsi = ds.GetDrawingSurfaceInfo();
+ if (dsi == null) {
+ // Widget not yet realized
+ ds.Unlock();
+ getJAWT().FreeDrawingSurface(ds);
+ ds = null;
+ return LOCK_SURFACE_NOT_READY;
+ }
+ win32dsi = (JAWT_Win32DrawingSurfaceInfo) dsi.platformInfo();
+ hdc = win32dsi.hdc();
+ if (hdc == 0) {
+ // Widget not yet realized
+ ds.FreeDrawingSurfaceInfo(dsi);
+ ds.Unlock();
+ getJAWT().FreeDrawingSurface(ds);
+ ds = null;
+ dsi = null;
+ win32dsi = null;
+ return LOCK_SURFACE_NOT_READY;
+ }
+ if (!pixelFormatChosen) {
+ choosePixelFormat(true);
+ }
+ return ret;
+ }
+
+ public void unlockSurface() {
+ if (hdc == 0) {
+ throw new GLException("Surface already unlocked");
+ }
+ ds.FreeDrawingSurfaceInfo(dsi);
+ ds.Unlock();
+ getJAWT().FreeDrawingSurface(ds);
+ ds = null;
+ dsi = null;
+ win32dsi = null;
+ hdc = 0;
+ }
+
+ //----------------------------------------------------------------------
+ // Internals only below this point
+ //
+
+ private JAWT getJAWT() {
+ if (jawt == null) {
+ JAWT j = new JAWT();
+ j.version(JAWTFactory.JAWT_VERSION_1_4);
+ if (!JAWTFactory.JAWT_GetAWT(j)) {
+ throw new RuntimeException("Unable to initialize JAWT");
+ }
+ jawt = j;
+ }
+ return jawt;
+ }
+}
diff --git a/src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java b/src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java
index d58d15d02..ca2f4aaa9 100644
--- a/src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java
+++ b/src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java
@@ -43,55 +43,27 @@ import net.java.games.jogl.*;
import net.java.games.jogl.impl.*;
public class WindowsPbufferGLContext extends WindowsGLContext {
- private static final boolean DEBUG = Debug.debug("WindowsPbufferGLContext");
-
- private int initWidth;
- private int initHeight;
-
- private long buffer; // pbuffer handle
- private int width;
- private int height;
-
- // FIXME: kept around because we create the OpenGL context lazily to
- // better integrate with the WindowsGLContext framework
- private long parentHglrc;
-
- private static final int MAX_PFORMATS = 256;
- private static final int MAX_ATTRIBS = 256;
-
// State for render-to-texture and render-to-texture-rectangle support
- private boolean created;
+ private WindowsPbufferGLDrawable drawable;
private boolean rtt; // render-to-texture?
private boolean hasRTT; // render-to-texture extension available?
private boolean rect; // render-to-texture-rectangle?
private int textureTarget; // e.g. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_NV
private int texture; // actual texture object
- private int floatMode;
-
- public WindowsPbufferGLContext(GLCapabilities capabilities, int initialWidth, int initialHeight) {
- super(null, capabilities, null, null);
- this.initWidth = initialWidth;
- this.initHeight = initialHeight;
- if (initWidth <= 0 || initHeight <= 0) {
- throw new GLException("Initial width and height of pbuffer must be positive (were (" +
- initWidth + ", " + initHeight + "))");
- }
- if (DEBUG) {
- System.out.println("Pbuffer caps on init: " + capabilities +
- (capabilities.getOffscreenRenderToTexture() ? " [rtt]" : "") +
- (capabilities.getOffscreenRenderToTextureRectangle() ? " [rect]" : "") +
- (capabilities.getOffscreenFloatingPointBuffers() ? " [float]" : ""));
- }
+ public WindowsPbufferGLContext(WindowsPbufferGLDrawable drawable,
+ GLContext shareWith) {
+ super(drawable, shareWith);
+ this.drawable = drawable;
}
public boolean canCreatePbufferContext() {
return false;
}
- public GLContext createPbufferContext(GLCapabilities capabilities,
- int initialWidth,
- int initialHeight) {
+ public GLDrawableImpl createPbufferDrawable(GLCapabilities capabilities,
+ int initialWidth,
+ int initialHeight) {
throw new GLException("Not supported");
}
@@ -103,10 +75,11 @@ public class WindowsPbufferGLContext extends WindowsGLContext {
GL gl = getGL();
gl.glBindTexture(textureTarget, texture);
if (rtt && hasRTT) {
- if (!gl.wglBindTexImageARB(buffer, GL.WGL_FRONT_LEFT_ARB)) {
+ if (!gl.wglBindTexImageARB(drawable.getPbuffer(), GL.WGL_FRONT_LEFT_ARB)) {
throw new GLException("Binding of pbuffer to texture failed: " + wglGetLastError());
}
}
+ // FIXME: comment is wrong now
// Note that if the render-to-texture extension is not supported,
// we perform a glCopyTexImage2D in swapBuffers().
}
@@ -118,289 +91,32 @@ public class WindowsPbufferGLContext extends WindowsGLContext {
}
if (rtt && hasRTT) {
GL gl = getGL();
- if (!gl.wglReleaseTexImageARB(buffer, GL.WGL_FRONT_LEFT_ARB)) {
+ if (!gl.wglReleaseTexImageARB(drawable.getPbuffer(), GL.WGL_FRONT_LEFT_ARB)) {
throw new GLException("Releasing of pbuffer from texture failed: " + wglGetLastError());
}
}
}
- public void createPbuffer(long parentHdc, long parentHglrc) {
- GL gl = getGL();
- // Must initally grab OpenGL function pointers while parent's
- // context is current because otherwise we don't have the wgl
- // extensions available to us
- resetGLFunctionAvailability();
-
- int[] iattributes = new int [2*MAX_ATTRIBS];
- float[] fattributes = new float[2*MAX_ATTRIBS];
- int nfattribs = 0;
- int niattribs = 0;
-
- if (DEBUG) {
- System.out.println("Pbuffer caps: " + capabilities +
- (capabilities.getOffscreenRenderToTexture() ? " [rtt]" : "") +
- (capabilities.getOffscreenRenderToTextureRectangle() ? " [rect]" : "") +
- (capabilities.getOffscreenFloatingPointBuffers() ? " [float]" : ""));
- }
-
- rtt = capabilities.getOffscreenRenderToTexture();
- rect = capabilities.getOffscreenRenderToTextureRectangle();
- boolean useFloat = capabilities.getOffscreenFloatingPointBuffers();
- boolean ati = false;
-
- // Since we are trying to create a pbuffer, the pixel format we
- // request (and subsequently use) must be "p-buffer capable".
- iattributes[niattribs++] = GL.WGL_DRAW_TO_PBUFFER_ARB;
- iattributes[niattribs++] = GL.GL_TRUE;
-
- if (rtt && !rect) {
- throw new GLException("Render-to-texture-rectangle requires render-to-texture to be specified");
- }
-
- if (rect) {
- if (!gl.isExtensionAvailable("GL_NV_texture_rectangle")) {
- throw new GLException("Render-to-texture-rectangle requires GL_NV_texture_rectangle extension");
- }
- }
-
- if (useFloat) {
- if (!gl.isExtensionAvailable("WGL_ATI_pixel_format_float") &&
- !gl.isExtensionAvailable("WGL_NV_float_buffer")) {
- throw new GLException("Floating-point pbuffers not supported by this hardware");
- }
-
- // Prefer NVidia extension over ATI
- if (gl.isExtensionAvailable("WGL_NV_float_buffer")) {
- ati = false;
- floatMode = GLPbuffer.NV_FLOAT;
- } else {
- ati = true;
- floatMode = GLPbuffer.ATI_FLOAT;
- }
- if (DEBUG) {
- System.err.println("Using " + (ati ? "ATI" : "NVidia") + " floating-point extension");
- }
- }
-
- if (useFloat && ati) {
- if (rtt) {
- throw new GLException("Render-to-floating-point-texture not supported on ATI hardware");
- } else {
- iattributes[niattribs++] = GL.WGL_PIXEL_TYPE_ARB;
- iattributes[niattribs++] = GL.WGL_TYPE_RGBA_FLOAT_ATI;
- }
- } else {
- if (!rtt) {
- // Currently we don't support non-truecolor visuals in the
- // GLCapabilities, so we don't offer the option of making
- // color-index pbuffers.
- iattributes[niattribs++] = GL.WGL_PIXEL_TYPE_ARB;
- iattributes[niattribs++] = GL.WGL_TYPE_RGBA_ARB;
- }
- }
-
- iattributes[niattribs++] = GL.WGL_DOUBLE_BUFFER_ARB;
- if (capabilities.getDoubleBuffered()) {
- iattributes[niattribs++] = GL.GL_TRUE;
- } else {
- iattributes[niattribs++] = GL.GL_FALSE;
- }
-
- iattributes[niattribs++] = GL.WGL_DEPTH_BITS_ARB;
- iattributes[niattribs++] = capabilities.getDepthBits();
-
- iattributes[niattribs++] = GL.WGL_RED_BITS_ARB;
- iattributes[niattribs++] = capabilities.getRedBits();
-
- iattributes[niattribs++] = GL.WGL_GREEN_BITS_ARB;
- iattributes[niattribs++] = capabilities.getGreenBits();
-
- iattributes[niattribs++] = GL.WGL_BLUE_BITS_ARB;
- iattributes[niattribs++] = capabilities.getBlueBits();
-
- iattributes[niattribs++] = GL.WGL_ALPHA_BITS_ARB;
- iattributes[niattribs++] = capabilities.getAlphaBits();
-
- iattributes[niattribs++] = GL.WGL_STENCIL_BITS_ARB;
- if (capabilities.getStencilBits() > 0) {
- iattributes[niattribs++] = GL.GL_TRUE;
- } else {
- iattributes[niattribs++] = GL.GL_FALSE;
- }
-
- if (capabilities.getAccumRedBits() > 0 ||
- capabilities.getAccumGreenBits() > 0 ||
- capabilities.getAccumBlueBits() > 0) {
- iattributes[niattribs++] = GL.WGL_ACCUM_BITS_ARB;
- iattributes[niattribs++] = GL.GL_TRUE;
- }
-
- if (useFloat && !ati) {
- iattributes[niattribs++] = GL.WGL_FLOAT_COMPONENTS_NV;
- iattributes[niattribs++] = GL.GL_TRUE;
- }
-
- if (rtt) {
- if (useFloat) {
- assert(!ati);
- if (!rect) {
- throw new GLException("Render-to-floating-point-texture only supported on NVidia hardware with render-to-texture-rectangle");
- }
- iattributes[niattribs++] = GL.WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV;
- iattributes[niattribs++] = GL.GL_TRUE;
- } else {
- iattributes[niattribs++] = rect ? GL.WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV : GL.WGL_BIND_TO_TEXTURE_RGB_ARB;
- iattributes[niattribs++] = GL.GL_TRUE;
- }
- }
-
- iattributes[niattribs++] = GL.WGL_SUPPORT_OPENGL_ARB;
- iattributes[niattribs++] = GL.GL_TRUE;
-
- int[] pformats = new int[MAX_PFORMATS];
- int nformats;
- int[] nformatsTmp = new int[1];
- if (!gl.wglChoosePixelFormatARB(parentHdc,
- iattributes, 0,
- fattributes, 0,
- MAX_PFORMATS,
- pformats, 0,
- nformatsTmp, 0)) {
- throw new GLException("pbuffer creation error: wglChoosePixelFormatARB() failed");
- }
- nformats = nformatsTmp[0];
- if (nformats <= 0) {
- throw new GLException("pbuffer creation error: Couldn't find a suitable pixel format");
- }
-
- if (DEBUG) {
- System.err.println("" + nformats + " suitable pixel formats found");
- // query pixel format
- iattributes[0] = GL.WGL_RED_BITS_ARB;
- iattributes[1] = GL.WGL_GREEN_BITS_ARB;
- iattributes[2] = GL.WGL_BLUE_BITS_ARB;
- iattributes[3] = GL.WGL_ALPHA_BITS_ARB;
- iattributes[4] = GL.WGL_DEPTH_BITS_ARB;
- iattributes[5] = (useFloat ? (ati ? GL.WGL_PIXEL_TYPE_ARB : GL.WGL_FLOAT_COMPONENTS_NV) : GL.WGL_RED_BITS_ARB);
- iattributes[6] = GL.WGL_SAMPLE_BUFFERS_EXT;
- iattributes[7] = GL.WGL_SAMPLES_EXT;
- iattributes[8] = GL.WGL_DRAW_TO_PBUFFER_ARB;
- int[] ivalues = new int[9];
- for (int i = 0; i < nformats; i++) {
- if (!gl.wglGetPixelFormatAttribivARB(parentHdc, pformats[i], 0, 9, iattributes, 0, ivalues, 0)) {
- throw new GLException("Error while querying pixel format " + pformats[i] +
- "'s (index " + i + "'s) capabilities for debugging");
- }
- System.err.print("pixel format " + pformats[i] + " (index " + i + "): ");
- System.err.print( "r: " + ivalues[0]);
- System.err.print(" g: " + ivalues[1]);
- System.err.print(" b: " + ivalues[2]);
- System.err.print(" a: " + ivalues[3]);
- System.err.print(" depth: " + ivalues[4]);
- System.err.print(" multisample: " + ivalues[6]);
- System.err.print(" samples: " + ivalues[7]);
- if (useFloat) {
- if (ati) {
- if (ivalues[5] == GL.WGL_TYPE_RGBA_FLOAT_ATI) {
- System.err.print(" [ati float]");
- } else if (ivalues[5] != GL.WGL_TYPE_RGBA_ARB) {
- System.err.print(" [unknown pixel type " + ivalues[5] + "]");
- }
- } else {
- if (ivalues[5] != 0) {
- System.err.print(" [float]");
- }
- }
- }
-
- if (ivalues[8] != 0) {
- System.err.print(" [pbuffer]");
- }
- System.err.println();
- }
- }
-
- long tmpBuffer = 0;
- int whichFormat = 0;
- // Loop is a workaround for bugs in NVidia's recent drivers
- do {
- int format = pformats[whichFormat];
-
- // Create the p-buffer.
- niattribs = 0;
-
- if (rtt) {
- iattributes[niattribs++] = GL.WGL_TEXTURE_FORMAT_ARB;
- if (useFloat) {
- iattributes[niattribs++] = GL.WGL_TEXTURE_FLOAT_RGB_NV;
- } else {
- iattributes[niattribs++] = GL.WGL_TEXTURE_RGBA_ARB;
- }
-
- iattributes[niattribs++] = GL.WGL_TEXTURE_TARGET_ARB;
- iattributes[niattribs++] = rect ? GL.WGL_TEXTURE_RECTANGLE_NV : GL.WGL_TEXTURE_2D_ARB;
-
- iattributes[niattribs++] = GL.WGL_MIPMAP_TEXTURE_ARB;
- iattributes[niattribs++] = GL.GL_FALSE;
-
- iattributes[niattribs++] = GL.WGL_PBUFFER_LARGEST_ARB;
- iattributes[niattribs++] = GL.GL_FALSE;
- }
-
- iattributes[niattribs++] = 0;
-
- tmpBuffer = gl.wglCreatePbufferARB(parentHdc, format, initWidth, initHeight, iattributes, 0);
- ++whichFormat;
- } while ((tmpBuffer == 0) && (whichFormat < nformats));
-
- if (tmpBuffer == 0) {
- throw new GLException("pbuffer creation error: wglCreatePbufferARB() failed: tried " + nformats +
- " pixel formats, last error was: " + wglGetLastError());
- }
-
- // Get the device context.
- long tmpHdc = gl.wglGetPbufferDCARB(tmpBuffer);
- if (tmpHdc == 0) {
- throw new GLException("pbuffer creation error: wglGetPbufferDCARB() failed");
- }
-
- this.parentHglrc = parentHglrc;
-
- // Set up instance variables
- buffer = tmpBuffer;
- hdc = tmpHdc;
-
- // Determine the actual width and height we were able to create.
- int[] tmp = new int[1];
- gl.wglQueryPbufferARB( buffer, GL.WGL_PBUFFER_WIDTH_ARB, tmp, 0 );
- width = tmp[0];
- gl.wglQueryPbufferARB( buffer, GL.WGL_PBUFFER_HEIGHT_ARB, tmp, 0 );
- height = tmp[0];
-
- if (DEBUG) {
- System.err.println("Created pbuffer " + width + " x " + height);
- }
- }
-
protected int makeCurrentImpl() throws GLException {
- created = false;
-
- if (buffer == 0) {
- // pbuffer not instantiated yet
+ if (drawable.getHDC() == 0) {
+ // pbuffer not instantiated (yet?)
if (DEBUG) {
- System.err.println("pbuffer not instantiated yet");
+ System.err.println("pbuffer not instantiated");
}
return CONTEXT_NOT_CURRENT;
}
int res = super.makeCurrentImpl();
- if (DEBUG) {
- System.err.println("super.makeCurrent() = " + res + ", created = " + created);
+ if (DEBUG && VERBOSE) {
+ System.err.println("super.makeCurrent() = " + res);
}
- if (created) {
+ if (res == CONTEXT_CURRENT_NEW) {
+ GLCapabilities capabilities = drawable.getCapabilities();
+
// Initialize render-to-texture support if requested
rtt = capabilities.getOffscreenRenderToTexture();
rect = capabilities.getOffscreenRenderToTextureRectangle();
+ GL gl = getGL();
if (rtt) {
if (DEBUG) {
@@ -412,7 +128,6 @@ public class WindowsPbufferGLContext extends WindowsGLContext {
"supported; implementing render_to_texture support using slow texture readback");
} else {
hasRTT = true;
- GL gl = getGL();
if (rect && !gl.isExtensionAvailable("GL_NV_texture_rectangle")) {
System.err.println("WindowsPbufferGLContext: WARNING: GL_NV_texture_rectangle extension not " +
@@ -438,23 +153,13 @@ public class WindowsPbufferGLContext extends WindowsGLContext {
gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE);
gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE);
- gl.glCopyTexImage2D(textureTarget, 0, GL.GL_RGB, 0, 0, width, height, 0);
+ gl.glCopyTexImage2D(textureTarget, 0, GL.GL_RGB, 0, 0, drawable.getWidth(), drawable.getHeight(), 0);
}
}
}
return res;
}
- public void handleModeSwitch(long parentHdc, long parentHglrc) {
- throw new GLException("Not yet implemented");
- }
-
- protected boolean isOffscreen() {
- // FIXME: currently the only caller of this won't cause proper
- // resizing of the pbuffer anyway.
- return false;
- }
-
public int getOffscreenContextReadBuffer() {
throw new GLException("Should not call this");
}
@@ -463,67 +168,11 @@ public class WindowsPbufferGLContext extends WindowsGLContext {
throw new GLException("Should not call this");
}
- protected void create() {
- created = true;
- // Create a gl context for the p-buffer.
- hglrc = WGL.wglCreateContext(hdc);
- if (hglrc == 0) {
- throw new GLException("pbuffer creation error: wglCreateContext() failed");
- }
-
- // FIXME: provide option to not share display lists with subordinate pbuffer?
- if (!WGL.wglShareLists(parentHglrc, hglrc)) {
- throw new GLException("pbuffer: wglShareLists() failed");
- }
- }
-
- protected void destroyImpl() throws GLException {
- if (hglrc != 0) {
- super.destroyImpl();
- // Must release DC and pbuffer
- // NOTE that since the context is not current, glGetError() can
- // not be called here, so we skip the use of any composable
- // pipelines
- GL gl = createGL();
- if (gl.wglReleasePbufferDCARB(buffer, hdc) == 0) {
- throw new GLException("Error releasing pbuffer device context: error code " + WGL.GetLastError());
- }
- hdc = 0;
- if (!gl.wglDestroyPbufferARB(buffer)) {
- throw new GLException("Error destroying pbuffer: error code " + WGL.GetLastError());
- }
- buffer = 0;
- }
- }
-
- public void swapBuffers() throws GLException {
- // FIXME: do we need to do anything if the pbuffer is double-buffered?
- // For now, just grab the pixels for the render-to-texture support.
- if (rtt && !hasRTT) {
- if (DEBUG) {
- System.err.println("Copying pbuffer data to GL_TEXTURE_2D state");
- }
-
- GL gl = getGL();
- gl.glCopyTexSubImage2D(textureTarget, 0, 0, 0, 0, 0, width, height);
- }
- }
-
public int getFloatingPointMode() {
- return floatMode;
+ return drawable.getFloatingPointMode();
}
- private String wglGetLastError() {
- int err = WGL.GetLastError();
- String detail = null;
- switch (err) {
- case WGL.ERROR_INVALID_PIXEL_FORMAT: detail = "ERROR_INVALID_PIXEL_FORMAT"; break;
- case WGL.ERROR_NO_SYSTEM_RESOURCES: detail = "ERROR_NO_SYSTEM_RESOURCES"; break;
- case WGL.ERROR_INVALID_DATA: detail = "ERROR_INVALID_DATA"; break;
- case WGL.ERROR_PROC_NOT_FOUND: detail = "ERROR_PROC_NOT_FOUND"; break;
- case WGL.ERROR_INVALID_WINDOW_HANDLE:detail = "ERROR_INVALID_WINDOW_HANDLE"; break;
- default: detail = "(Unknown error code " + err + ")"; break;
- }
- return detail;
+ private static String wglGetLastError() {
+ return WindowsGLContextFactory.wglGetLastError();
}
}
diff --git a/src/net/java/games/jogl/impl/windows/WindowsPbufferGLDrawable.java b/src/net/java/games/jogl/impl/windows/WindowsPbufferGLDrawable.java
new file mode 100644
index 000000000..6917b281d
--- /dev/null
+++ b/src/net/java/games/jogl/impl/windows/WindowsPbufferGLDrawable.java
@@ -0,0 +1,393 @@
+/*
+ * 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.windows;
+
+import net.java.games.jogl.*;
+import net.java.games.jogl.impl.*;
+
+public class WindowsPbufferGLDrawable extends WindowsGLDrawable {
+ private int initWidth;
+ private int initHeight;
+
+ private GL cachedGL; // cached GL instance from parent GLCanvas,
+ // needed to destroy pbuffer
+ private long buffer; // pbuffer handle
+ private int width;
+ private int height;
+
+ private int floatMode;
+
+ public WindowsPbufferGLDrawable(GLCapabilities capabilities, int initialWidth, int initialHeight) {
+ super(null, capabilities, null);
+ this.initWidth = initialWidth;
+ this.initHeight = initialHeight;
+ if (initWidth <= 0 || initHeight <= 0) {
+ throw new GLException("Initial width and height of pbuffer must be positive (were (" +
+ initWidth + ", " + initHeight + "))");
+ }
+
+ if (DEBUG) {
+ System.out.println("Pbuffer caps on init: " + capabilities +
+ (capabilities.getOffscreenRenderToTexture() ? " [rtt]" : "") +
+ (capabilities.getOffscreenRenderToTextureRectangle() ? " [rect]" : "") +
+ (capabilities.getOffscreenFloatingPointBuffers() ? " [float]" : ""));
+ }
+ }
+
+ public GLContext createContext(GLContext shareWith) {
+ return new WindowsPbufferGLContext(this, shareWith);
+ }
+
+ public void destroy() {
+ if (hdc != 0) {
+ // Must release DC and pbuffer
+ // NOTE that since the context is not current, glGetError() can
+ // not be called here, so we skip the use of any composable
+ // pipelines (see WindowsOnscreenGLContext.makeCurrentImpl)
+ GL gl = cachedGL;
+ if (gl.wglReleasePbufferDCARB(buffer, hdc) == 0) {
+ throw new GLException("Error releasing pbuffer device context: error code " + WGL.GetLastError());
+ }
+ hdc = 0;
+ if (!gl.wglDestroyPbufferARB(buffer)) {
+ throw new GLException("Error destroying pbuffer: error code " + WGL.GetLastError());
+ }
+ buffer = 0;
+ }
+ }
+
+ public void setSize(int width, int height) {
+ // FIXME
+ throw new GLException("Not yet implemented");
+ }
+
+ public int getWidth() {
+ return width;
+ }
+
+ public int getHeight() {
+ return height;
+ }
+
+ public void createPbuffer(GL gl, long parentHdc) {
+ int[] iattributes = new int [2*MAX_ATTRIBS];
+ float[] fattributes = new float[2*MAX_ATTRIBS];
+ int nfattribs = 0;
+ int niattribs = 0;
+
+ if (DEBUG) {
+ System.out.println("Pbuffer parentHdc = " + toHexString(parentHdc));
+ System.out.println("Pbuffer caps: " + capabilities +
+ (capabilities.getOffscreenRenderToTexture() ? " [rtt]" : "") +
+ (capabilities.getOffscreenRenderToTextureRectangle() ? " [rect]" : "") +
+ (capabilities.getOffscreenFloatingPointBuffers() ? " [float]" : ""));
+ }
+
+ boolean rtt = capabilities.getOffscreenRenderToTexture();
+ boolean rect = capabilities.getOffscreenRenderToTextureRectangle();
+ boolean useFloat = capabilities.getOffscreenFloatingPointBuffers();
+ boolean ati = false;
+
+ // Since we are trying to create a pbuffer, the pixel format we
+ // request (and subsequently use) must be "p-buffer capable".
+ iattributes[niattribs++] = GL.WGL_DRAW_TO_PBUFFER_ARB;
+ iattributes[niattribs++] = GL.GL_TRUE;
+
+ if (rtt && !rect) {
+ throw new GLException("Render-to-texture-rectangle requires render-to-texture to be specified");
+ }
+
+ if (rect) {
+ if (!gl.isExtensionAvailable("GL_NV_texture_rectangle")) {
+ throw new GLException("Render-to-texture-rectangle requires GL_NV_texture_rectangle extension");
+ }
+ }
+
+ if (useFloat) {
+ if (!gl.isExtensionAvailable("WGL_ATI_pixel_format_float") &&
+ !gl.isExtensionAvailable("WGL_NV_float_buffer")) {
+ throw new GLException("Floating-point pbuffers not supported by this hardware");
+ }
+
+ // Prefer NVidia extension over ATI
+ if (gl.isExtensionAvailable("WGL_NV_float_buffer")) {
+ ati = false;
+ floatMode = GLPbuffer.NV_FLOAT;
+ } else {
+ ati = true;
+ floatMode = GLPbuffer.ATI_FLOAT;
+ }
+ if (DEBUG) {
+ System.err.println("Using " + (ati ? "ATI" : "NVidia") + " floating-point extension");
+ }
+ }
+
+ if (useFloat && ati) {
+ if (rtt) {
+ throw new GLException("Render-to-floating-point-texture not supported on ATI hardware");
+ } else {
+ iattributes[niattribs++] = GL.WGL_PIXEL_TYPE_ARB;
+ iattributes[niattribs++] = GL.WGL_TYPE_RGBA_FLOAT_ATI;
+ }
+ } else {
+ if (!rtt) {
+ // Currently we don't support non-truecolor visuals in the
+ // GLCapabilities, so we don't offer the option of making
+ // color-index pbuffers.
+ iattributes[niattribs++] = GL.WGL_PIXEL_TYPE_ARB;
+ iattributes[niattribs++] = GL.WGL_TYPE_RGBA_ARB;
+ }
+ }
+
+ iattributes[niattribs++] = GL.WGL_DOUBLE_BUFFER_ARB;
+ if (capabilities.getDoubleBuffered()) {
+ iattributes[niattribs++] = GL.GL_TRUE;
+ } else {
+ iattributes[niattribs++] = GL.GL_FALSE;
+ }
+
+ iattributes[niattribs++] = GL.WGL_DEPTH_BITS_ARB;
+ iattributes[niattribs++] = capabilities.getDepthBits();
+
+ iattributes[niattribs++] = GL.WGL_RED_BITS_ARB;
+ iattributes[niattribs++] = capabilities.getRedBits();
+
+ iattributes[niattribs++] = GL.WGL_GREEN_BITS_ARB;
+ iattributes[niattribs++] = capabilities.getGreenBits();
+
+ iattributes[niattribs++] = GL.WGL_BLUE_BITS_ARB;
+ iattributes[niattribs++] = capabilities.getBlueBits();
+
+ iattributes[niattribs++] = GL.WGL_ALPHA_BITS_ARB;
+ iattributes[niattribs++] = capabilities.getAlphaBits();
+
+ iattributes[niattribs++] = GL.WGL_STENCIL_BITS_ARB;
+ if (capabilities.getStencilBits() > 0) {
+ iattributes[niattribs++] = GL.GL_TRUE;
+ } else {
+ iattributes[niattribs++] = GL.GL_FALSE;
+ }
+
+ if (capabilities.getAccumRedBits() > 0 ||
+ capabilities.getAccumGreenBits() > 0 ||
+ capabilities.getAccumBlueBits() > 0) {
+ iattributes[niattribs++] = GL.WGL_ACCUM_BITS_ARB;
+ iattributes[niattribs++] = GL.GL_TRUE;
+ }
+
+ if (useFloat && !ati) {
+ iattributes[niattribs++] = GL.WGL_FLOAT_COMPONENTS_NV;
+ iattributes[niattribs++] = GL.GL_TRUE;
+ }
+
+ if (rtt) {
+ if (useFloat) {
+ assert(!ati);
+ if (!rect) {
+ throw new GLException("Render-to-floating-point-texture only supported on NVidia hardware with render-to-texture-rectangle");
+ }
+ iattributes[niattribs++] = GL.WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV;
+ iattributes[niattribs++] = GL.GL_TRUE;
+ } else {
+ iattributes[niattribs++] = rect ? GL.WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV : GL.WGL_BIND_TO_TEXTURE_RGB_ARB;
+ iattributes[niattribs++] = GL.GL_TRUE;
+ }
+ }
+
+ iattributes[niattribs++] = GL.WGL_SUPPORT_OPENGL_ARB;
+ iattributes[niattribs++] = GL.GL_TRUE;
+
+ int[] pformats = new int[MAX_PFORMATS];
+ int nformats;
+ int[] nformatsTmp = new int[1];
+ if (!gl.wglChoosePixelFormatARB(parentHdc,
+ iattributes, 0,
+ fattributes, 0,
+ MAX_PFORMATS,
+ pformats, 0,
+ nformatsTmp, 0)) {
+ throw new GLException("pbuffer creation error: wglChoosePixelFormatARB() failed");
+ }
+ nformats = nformatsTmp[0];
+ if (nformats <= 0) {
+ throw new GLException("pbuffer creation error: Couldn't find a suitable pixel format");
+ }
+
+ if (DEBUG) {
+ System.err.println("" + nformats + " suitable pixel formats found");
+ // query pixel format
+ iattributes[0] = GL.WGL_RED_BITS_ARB;
+ iattributes[1] = GL.WGL_GREEN_BITS_ARB;
+ iattributes[2] = GL.WGL_BLUE_BITS_ARB;
+ iattributes[3] = GL.WGL_ALPHA_BITS_ARB;
+ iattributes[4] = GL.WGL_DEPTH_BITS_ARB;
+ iattributes[5] = (useFloat ? (ati ? GL.WGL_PIXEL_TYPE_ARB : GL.WGL_FLOAT_COMPONENTS_NV) : GL.WGL_RED_BITS_ARB);
+ iattributes[6] = GL.WGL_SAMPLE_BUFFERS_EXT;
+ iattributes[7] = GL.WGL_SAMPLES_EXT;
+ iattributes[8] = GL.WGL_DRAW_TO_PBUFFER_ARB;
+ int[] ivalues = new int[9];
+ for (int i = 0; i < nformats; i++) {
+ if (!gl.wglGetPixelFormatAttribivARB(parentHdc, pformats[i], 0, 9, iattributes, 0, ivalues, 0)) {
+ throw new GLException("Error while querying pixel format " + pformats[i] +
+ "'s (index " + i + "'s) capabilities for debugging");
+ }
+ System.err.print("pixel format " + pformats[i] + " (index " + i + "): ");
+ System.err.print( "r: " + ivalues[0]);
+ System.err.print(" g: " + ivalues[1]);
+ System.err.print(" b: " + ivalues[2]);
+ System.err.print(" a: " + ivalues[3]);
+ System.err.print(" depth: " + ivalues[4]);
+ System.err.print(" multisample: " + ivalues[6]);
+ System.err.print(" samples: " + ivalues[7]);
+ if (useFloat) {
+ if (ati) {
+ if (ivalues[5] == GL.WGL_TYPE_RGBA_FLOAT_ATI) {
+ System.err.print(" [ati float]");
+ } else if (ivalues[5] != GL.WGL_TYPE_RGBA_ARB) {
+ System.err.print(" [unknown pixel type " + ivalues[5] + "]");
+ }
+ } else {
+ if (ivalues[5] != 0) {
+ System.err.print(" [float]");
+ }
+ }
+ }
+
+ if (ivalues[8] != 0) {
+ System.err.print(" [pbuffer]");
+ }
+ System.err.println();
+ }
+ }
+
+ long tmpBuffer = 0;
+ int whichFormat = 0;
+ // Loop is a workaround for bugs in NVidia's recent drivers
+ do {
+ int format = pformats[whichFormat];
+
+ // Create the p-buffer.
+ niattribs = 0;
+
+ if (rtt) {
+ iattributes[niattribs++] = GL.WGL_TEXTURE_FORMAT_ARB;
+ if (useFloat) {
+ iattributes[niattribs++] = GL.WGL_TEXTURE_FLOAT_RGB_NV;
+ } else {
+ iattributes[niattribs++] = GL.WGL_TEXTURE_RGBA_ARB;
+ }
+
+ iattributes[niattribs++] = GL.WGL_TEXTURE_TARGET_ARB;
+ iattributes[niattribs++] = rect ? GL.WGL_TEXTURE_RECTANGLE_NV : GL.WGL_TEXTURE_2D_ARB;
+
+ iattributes[niattribs++] = GL.WGL_MIPMAP_TEXTURE_ARB;
+ iattributes[niattribs++] = GL.GL_FALSE;
+
+ iattributes[niattribs++] = GL.WGL_PBUFFER_LARGEST_ARB;
+ iattributes[niattribs++] = GL.GL_FALSE;
+ }
+
+ iattributes[niattribs++] = 0;
+
+ tmpBuffer = gl.wglCreatePbufferARB(parentHdc, format, initWidth, initHeight, iattributes, 0);
+ ++whichFormat;
+ } while ((tmpBuffer == 0) && (whichFormat < nformats));
+
+ if (tmpBuffer == 0) {
+ throw new GLException("pbuffer creation error: wglCreatePbufferARB() failed: tried " + nformats +
+ " pixel formats, last error was: " + wglGetLastError());
+ }
+
+ // Get the device context.
+ long tmpHdc = gl.wglGetPbufferDCARB(tmpBuffer);
+ if (tmpHdc == 0) {
+ throw new GLException("pbuffer creation error: wglGetPbufferDCARB() failed");
+ }
+
+ // Set up instance variables
+ buffer = tmpBuffer;
+ hdc = tmpHdc;
+ cachedGL = gl;
+
+ // Determine the actual width and height we were able to create.
+ int[] tmp = new int[1];
+ gl.wglQueryPbufferARB( buffer, GL.WGL_PBUFFER_WIDTH_ARB, tmp, 0 );
+ width = tmp[0];
+ gl.wglQueryPbufferARB( buffer, GL.WGL_PBUFFER_HEIGHT_ARB, tmp, 0 );
+ height = tmp[0];
+
+ if (DEBUG) {
+ System.err.println("Created pbuffer " + width + " x " + height);
+ }
+ }
+
+ public GLCapabilities getCapabilities() {
+ return capabilities;
+ }
+
+ public long getPbuffer() {
+ return buffer;
+ }
+
+ public int getFloatingPointMode() {
+ return floatMode;
+ }
+
+ public void swapBuffers() throws GLException {
+ // FIXME: this doesn't make sense any more because we don't have
+ // access to our OpenGL context here
+ /*
+ // FIXME: do we need to do anything if the pbuffer is double-buffered?
+ // For now, just grab the pixels for the render-to-texture support.
+ if (rtt && !hasRTT) {
+ if (DEBUG) {
+ System.err.println("Copying pbuffer data to GL_TEXTURE_2D state");
+ }
+
+ GL gl = getGL();
+ gl.glCopyTexSubImage2D(textureTarget, 0, 0, 0, 0, 0, width, height);
+ }
+ */
+ }
+
+ private static String wglGetLastError() {
+ return WindowsGLContextFactory.wglGetLastError();
+ }
+}
diff --git a/src/net/java/games/jogl/impl/x11/X11GLContext.java b/src/net/java/games/jogl/impl/x11/X11GLContext.java
index 7077c855e..a43def0b8 100644
--- a/src/net/java/games/jogl/impl/x11/X11GLContext.java
+++ b/src/net/java/games/jogl/impl/x11/X11GLContext.java
@@ -47,9 +47,7 @@ import net.java.games.jogl.*;
import net.java.games.jogl.impl.*;
public abstract class X11GLContext extends GLContextImpl {
- protected long display;
- protected long drawable;
- protected long visualID;
+ protected X11GLDrawable drawable;
protected long context;
private boolean glXQueryExtensionsStringInitialized;
private boolean glXQueryExtensionsStringAvailable;
@@ -84,11 +82,10 @@ public abstract class X11GLContext extends GLContextImpl {
});
}
- public X11GLContext(Component component,
- GLCapabilities capabilities,
- GLCapabilitiesChooser chooser,
+ public X11GLContext(X11GLDrawable drawable,
GLContext shareWith) {
- super(component, capabilities, chooser, shareWith);
+ super(shareWith);
+ this.drawable = drawable;
}
protected GL createGL()
@@ -108,16 +105,6 @@ public abstract class X11GLContext extends GLContextImpl {
return glExtensionName;
}
- protected abstract boolean isOffscreen();
-
- public int getOffscreenContextWidth() {
- throw new GLException("Should not call this");
- }
-
- public int getOffscreenContextHeight() {
- throw new GLException("Should not call this");
- }
-
public int getOffscreenContextPixelDataType() {
throw new GLException("Should not call this");
}
@@ -126,18 +113,32 @@ public abstract class X11GLContext extends GLContextImpl {
public abstract boolean offscreenImageNeedsVerticalFlip();
- /**
- * Creates and initializes an appropriate OpenGl context. Should only be
- * called by {@link makeCurrentImpl()}.
+ /** Helper routine which usually just turns around and calls
+ * createContext (except for pbuffers, which use a different context
+ * creation mechanism). Should only be called by {@link
+ * makeCurrentImpl()}.
*/
protected abstract void create();
-
- public boolean isExtensionAvailable(String glExtensionName) {
- if (glExtensionName.equals("GL_ARB_pbuffer") ||
- glExtensionName.equals("GL_ARB_pixel_format")) {
- return isGLX13;
+
+ /**
+ * Creates and initializes an appropriate OpenGL context. Should only be
+ * called by {@link create()}.
+ */
+ protected void createContext(boolean onscreen) {
+ XVisualInfo vis = drawable.chooseVisual(onscreen);
+ X11GLContext other = (X11GLContext) GLContextShareSet.getShareContext(this);
+ long share = 0;
+ if (other != null) {
+ share = other.getContext();
+ if (share == 0) {
+ throw new GLException("GLContextShareSet returned an invalid OpenGL context");
+ }
}
- return super.isExtensionAvailable(glExtensionName);
+ context = GLX.glXCreateContext(drawable.getDisplay(), vis, share, onscreen);
+ if (context == 0) {
+ throw new GLException("Unable to create OpenGL context");
+ }
+ GLContextShareSet.contextCreated(this);
}
protected int makeCurrentImpl() throws GLException {
@@ -145,19 +146,20 @@ public abstract class X11GLContext extends GLContextImpl {
if (context == 0) {
create();
if (DEBUG) {
- System.err.println("!!! Created GL context for " + getClass().getName());
+ System.err.println(getThreadName() + ": !!! Created GL context for " + getClass().getName());
}
created = true;
}
- if (drawable == 0) {
- throw new GLException("Unable to make context current; drawable was null");
- }
- // 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)
- if (!GLX.glXMakeCurrent(display, (int) drawable, context)) {
+ if (!GLX.glXMakeCurrent(drawable.getDisplay(), drawable.getDrawable(), context)) {
throw new GLException("Error making context current");
+ } else {
+ mostRecentDisplay = drawable.getDisplay();
+ if (DEBUG && VERBOSE) {
+ System.err.println(getThreadName() + ": glXMakeCurrent(display " + toHexString(drawable.getDisplay()) +
+ ", drawable " + toHexString(drawable.getDrawable()) +
+ ", context " + toHexString(context) + ") succeeded");
+ }
}
if (created) {
@@ -168,7 +170,7 @@ public abstract class X11GLContext extends GLContextImpl {
}
protected void releaseImpl() throws GLException {
- if (!GLX.glXMakeCurrent(display, 0, 0)) {
+ if (!GLX.glXMakeCurrent(drawable.getDisplay(), 0, 0)) {
throw new GLException("Error freeing OpenGL context");
}
}
@@ -177,16 +179,16 @@ public abstract class X11GLContext extends GLContextImpl {
lockAWT();
if (context != 0) {
GLX.glXDestroyContext(mostRecentDisplay, context);
+ context = 0;
+ mostRecentDisplay = 0;
+ GLContextShareSet.contextDestroyed(this);
if (DEBUG) {
System.err.println("!!! Destroyed OpenGL context " + context);
}
- context = 0;
}
unlockAWT();
}
- public abstract void swapBuffers() throws GLException;
-
protected long dynamicLookupFunction(String glFuncName) {
long res = 0;
if (!isLinuxAMD64) {
@@ -216,12 +218,12 @@ public abstract class X11GLContext extends GLContextImpl {
// Figure out whether we are running GLX version 1.3 or above and
// therefore have pbuffer support
- if (display == 0) {
+ if (drawable.getDisplay() == 0) {
throw new GLException("Expected non-null DISPLAY for querying GLX version");
}
int[] major = new int[1];
int[] minor = new int[1];
- if (!GLX.glXQueryVersion(display, major, 0, minor, 0)) {
+ if (!GLX.glXQueryVersion(drawable.getDisplay(), major, 0, minor, 0)) {
throw new GLException("glXQueryVersion failed");
}
if (DEBUG) {
@@ -253,7 +255,7 @@ public abstract class X11GLContext extends GLContextImpl {
}
public synchronized String getPlatformExtensionsString() {
- if (display == 0) {
+ if (drawable.getDisplay() == 0) {
throw new GLException("Context not current");
}
if (!glXQueryExtensionsStringInitialized) {
@@ -263,7 +265,7 @@ public abstract class X11GLContext extends GLContextImpl {
if (glXQueryExtensionsStringAvailable) {
lockAWT();
try {
- String ret = GLX.glXQueryExtensionsString(display, GLX.DefaultScreen(display));
+ String ret = GLX.glXQueryExtensionsString(drawable.getDisplay(), GLX.DefaultScreen(drawable.getDisplay()));
if (DEBUG) {
System.err.println("!!! GLX extensions: " + ret);
}
@@ -292,97 +294,17 @@ public abstract class X11GLContext extends GLContextImpl {
return available;
}
- //----------------------------------------------------------------------
- // Internals only below this point
- //
-
- protected JAWT getJAWT() {
- return X11GLContextFactory.getJAWT();
- }
-
- protected XVisualInfo chooseVisual() {
- if (!isOffscreen()) {
- // The visual has already been chosen by the time we get here;
- // it's specified by the GraphicsConfiguration of the
- // GLCanvas. Fortunately, the JAWT supplies the visual ID for
- // the component in a portable fashion, so all we have to do is
- // use XGetVisualInfo with a VisualIDMask to get the
- // corresponding XVisualInfo to pass into glXChooseVisual.
- int[] count = new int[1];
- XVisualInfo template = new XVisualInfo();
- // FIXME: probably not 64-bit clean
- template.visualid((int) visualID);
- XVisualInfo[] infos = GLX.XGetVisualInfo(display, GLX.VisualIDMask, template, count, 0);
- if (infos == null || infos.length == 0) {
- throw new GLException("Error while getting XVisualInfo for visual ID " + visualID);
- }
- // FIXME: the storage for the infos array is leaked (should
- // clean it up somehow when we're done with the visual we're
- // returning)
- return infos[0];
- } else {
- // It isn't clear to me whether we need this much code to handle
- // the offscreen case, where we're creating a pixmap into which
- // to render...this is what we (incorrectly) used to do for the
- // onscreen case
-
- int screen = 0; // FIXME: provide way to specify this?
- XVisualInfo vis = null;
- int[] count = new int[1];
- XVisualInfo template = new XVisualInfo();
- template.screen(screen);
- XVisualInfo[] infos = GLX.XGetVisualInfo(display, GLX.VisualScreenMask, template, count, 0);
- if (infos == null) {
- throw new GLException("Error while enumerating available XVisualInfos");
- }
- GLCapabilities[] caps = new GLCapabilities[infos.length];
- for (int i = 0; i < infos.length; i++) {
- caps[i] = X11GLContextFactory.xvi2GLCapabilities(display, infos[i]);
- }
- int chosen = chooser.chooseCapabilities(capabilities, caps, -1);
- if (chosen < 0 || chosen >= caps.length) {
- throw new GLException("GLCapabilitiesChooser specified invalid index (expected 0.." + (caps.length - 1) + ")");
- }
- if (DEBUG) {
- System.err.println("Chosen visual (" + chosen + "):");
- System.err.println(caps[chosen]);
- }
- vis = infos[chosen];
- if (vis == null) {
- throw new GLException("GLCapabilitiesChooser chose an invalid visual");
- }
- // FIXME: the storage for the infos array is leaked (should
- // clean it up somehow when we're done with the visual we're
- // returning)
-
- return vis;
- }
- }
-
- protected long createContext(XVisualInfo vis, boolean onscreen) {
- X11GLContext other = (X11GLContext) GLContextShareSet.getShareContext(this);
- long share = 0;
- if (other != null) {
- share = other.getContext();
- if (share == 0) {
- throw new GLException("GLContextShareSet returned an invalid OpenGL context");
- }
- }
- long res = GLX.glXCreateContext(display, vis, share, onscreen);
- if (res != 0) {
- GLContextShareSet.contextCreated(this);
+ public boolean isExtensionAvailable(String glExtensionName) {
+ if (glExtensionName.equals("GL_ARB_pbuffer") ||
+ glExtensionName.equals("GL_ARB_pixel_format")) {
+ return isGLX13;
}
- return res;
+ return super.isExtensionAvailable(glExtensionName);
}
- // Helper routine for the overridden create() to call
- protected void chooseVisualAndCreateContext(boolean onscreen) {
- XVisualInfo vis = chooseVisual();
- context = createContext(vis, onscreen);
- if (context == 0) {
- throw new GLException("Unable to create OpenGL context");
- }
- }
+ //----------------------------------------------------------------------
+ // Internals only below this point
+ //
protected long getContext() {
return context;
diff --git a/src/net/java/games/jogl/impl/x11/X11GLContextFactory.java b/src/net/java/games/jogl/impl/x11/X11GLContextFactory.java
index 3be11c002..78d03a28a 100644
--- a/src/net/java/games/jogl/impl/x11/X11GLContextFactory.java
+++ b/src/net/java/games/jogl/impl/x11/X11GLContextFactory.java
@@ -119,15 +119,22 @@ public class X11GLContextFactory extends GLContextFactory {
return null;
}
- public GLContext createGLContext(Component component,
- GLCapabilities capabilities,
- GLCapabilitiesChooser chooser,
- GLContext shareWith) {
- if (component != null) {
- return new X11OnscreenGLContext(component, capabilities, chooser, shareWith);
- } else {
- return new X11OffscreenGLContext(capabilities, chooser, shareWith);
+ public GLDrawable getGLDrawable(Object target,
+ GLCapabilities capabilities,
+ GLCapabilitiesChooser chooser) {
+ if (target == null) {
+ throw new IllegalArgumentException("Null target");
}
+ if (!(target instanceof Component)) {
+ throw new IllegalArgumentException("GLDrawables not supported for objects of type " +
+ target.getClass().getName() + " (only Components are supported in this implementation)");
+ }
+ return new X11OnscreenGLDrawable((Component) target);
+ }
+
+ public GLDrawableImpl createOffscreenDrawable(GLCapabilities capabilities,
+ GLCapabilitiesChooser chooser) {
+ return new X11OffscreenGLDrawable(capabilities, chooser);
}
public static GLCapabilities xvi2GLCapabilities(long display, XVisualInfo info) {
diff --git a/src/net/java/games/jogl/impl/x11/X11GLDrawable.java b/src/net/java/games/jogl/impl/x11/X11GLDrawable.java
new file mode 100644
index 000000000..32098ab43
--- /dev/null
+++ b/src/net/java/games/jogl/impl/x11/X11GLDrawable.java
@@ -0,0 +1,172 @@
+/*
+ * 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.x11;
+
+import java.awt.Component;
+
+import net.java.games.jogl.*;
+import net.java.games.jogl.impl.*;
+
+public abstract class X11GLDrawable extends GLDrawableImpl {
+ protected static final boolean DEBUG = Debug.debug("X11GLDrawable");
+
+ protected long display;
+ protected long drawable;
+ protected long visualID;
+ protected Component component;
+ protected GLCapabilities capabilities;
+ protected GLCapabilitiesChooser chooser;
+
+ public X11GLDrawable(Component component,
+ GLCapabilities capabilities,
+ GLCapabilitiesChooser chooser) {
+ this.component = component;
+ this.capabilities = (capabilities == null) ? null :
+ ((GLCapabilities) capabilities.clone());
+ this.chooser = chooser;
+ }
+
+ public void setRealized(boolean val) {
+ throw new GLException("Should not call this (should only be called for onscreen GLDrawables)");
+ }
+
+ public void destroy() {
+ throw new GLException("Should not call this (should only be called for offscreen GLDrawables)");
+ }
+
+ public void swapBuffers() throws GLException {
+ }
+
+ public long getDisplay() {
+ return display;
+ }
+
+ public long getDrawable() {
+ return drawable;
+ }
+
+ //---------------------------------------------------------------------------
+ // Internals only below this point
+ //
+
+ protected XVisualInfo chooseVisual(boolean onscreen) {
+ if (display == 0) {
+ throw new GLException("null display");
+ }
+
+ // FIXME
+ if (onscreen) {
+ // The visual has already been chosen by the time we get here;
+ // it's specified by the GraphicsConfiguration of the
+ // GLCanvas. Fortunately, the JAWT supplies the visual ID for
+ // the component in a portable fashion, so all we have to do is
+ // use XGetVisualInfo with a VisualIDMask to get the
+ // corresponding XVisualInfo to pass into glXChooseVisual.
+ int[] count = new int[1];
+ XVisualInfo template = new XVisualInfo();
+ // FIXME: probably not 64-bit clean
+ template.visualid((int) visualID);
+ lockAWT();
+ XVisualInfo[] infos = GLX.XGetVisualInfo(display, GLX.VisualIDMask, template, count, 0);
+ unlockAWT();
+ if (infos == null || infos.length == 0) {
+ throw new GLException("Error while getting XVisualInfo for visual ID " + visualID);
+ }
+ // FIXME: the storage for the infos array is leaked (should
+ // clean it up somehow when we're done with the visual we're
+ // returning)
+ return infos[0];
+ } else {
+ // It isn't clear to me whether we need this much code to handle
+ // the offscreen case, where we're creating a pixmap into which
+ // to render...this is what we (incorrectly) used to do for the
+ // onscreen case
+
+ int screen = 0; // FIXME: provide way to specify this?
+ XVisualInfo vis = null;
+ int[] count = new int[1];
+ XVisualInfo template = new XVisualInfo();
+ template.screen(screen);
+ XVisualInfo[] infos = null;
+ GLCapabilities[] caps = null;
+ lockAWT();
+ try {
+ infos = GLX.XGetVisualInfo(display, GLX.VisualScreenMask, template, count, 0);
+ if (infos == null) {
+ throw new GLException("Error while enumerating available XVisualInfos");
+ }
+ caps = new GLCapabilities[infos.length];
+ for (int i = 0; i < infos.length; i++) {
+ caps[i] = X11GLContextFactory.xvi2GLCapabilities(display, infos[i]);
+ }
+ } finally {
+ unlockAWT();
+ }
+ int chosen = chooser.chooseCapabilities(capabilities, caps, -1);
+ if (chosen < 0 || chosen >= caps.length) {
+ throw new GLException("GLCapabilitiesChooser specified invalid index (expected 0.." + (caps.length - 1) + ")");
+ }
+ if (DEBUG) {
+ System.err.println("Chosen visual (" + chosen + "):");
+ System.err.println(caps[chosen]);
+ }
+ vis = infos[chosen];
+ if (vis == null) {
+ throw new GLException("GLCapabilitiesChooser chose an invalid visual");
+ }
+ // FIXME: the storage for the infos array is leaked (should
+ // clean it up somehow when we're done with the visual we're
+ // returning)
+
+ return vis;
+ }
+ }
+
+
+ // These synchronization primitives prevent the AWT from making
+ // requests from the X server asynchronously to this code.
+ protected void lockAWT() {
+ X11GLContextFactory.lockAWT();
+ }
+
+ protected void unlockAWT() {
+ X11GLContextFactory.unlockAWT();
+ }
+}
diff --git a/src/net/java/games/jogl/impl/x11/X11OffscreenGLContext.java b/src/net/java/games/jogl/impl/x11/X11OffscreenGLContext.java
index c493d3380..4397c72d8 100644
--- a/src/net/java/games/jogl/impl/x11/X11OffscreenGLContext.java
+++ b/src/net/java/games/jogl/impl/x11/X11OffscreenGLContext.java
@@ -39,46 +39,24 @@
package net.java.games.jogl.impl.x11;
-import java.awt.image.BufferedImage;
import net.java.games.jogl.*;
import net.java.games.jogl.impl.*;
public class X11OffscreenGLContext extends X11GLContext {
- private long pixmap;
- private boolean isDoubleBuffered;
- // Width and height of the underlying bitmap
- private int width;
- private int height;
+ private X11OffscreenGLDrawable drawable;
- public X11OffscreenGLContext(GLCapabilities capabilities,
- GLCapabilitiesChooser chooser,
+ public X11OffscreenGLContext(X11OffscreenGLDrawable drawable,
GLContext shareWith) {
- super(null, capabilities, chooser, shareWith);
- }
-
- protected GL createGL()
- {
- return new X11GLImpl(this);
- }
-
- protected boolean isOffscreen() {
- return true;
- }
-
- public int getOffscreenContextWidth() {
- return width;
- }
-
- public int getOffscreenContextHeight() {
- return height;
+ super(drawable, shareWith);
+ this.drawable = drawable;
}
public int getOffscreenContextPixelDataType() {
- return GL.GL_UNSIGNED_BYTE;
+ return GL.GL_UNSIGNED_BYTE;
}
public int getOffscreenContextReadBuffer() {
- if (isDoubleBuffered) {
+ if (drawable.isDoubleBuffered()) {
return GL.GL_BACK;
}
return GL.GL_FRONT;
@@ -95,9 +73,9 @@ public class X11OffscreenGLContext extends X11GLContext {
return false;
}
- public GLContext createPbufferContext(GLCapabilities capabilities,
- int initialWidth,
- int initialHeight) {
+ public GLDrawableImpl createPbufferDrawable(GLCapabilities capabilities,
+ int initialWidth,
+ int initialHeight) {
throw new GLException("Not supported");
}
@@ -109,67 +87,7 @@ public class X11OffscreenGLContext extends X11GLContext {
throw new GLException("Should not call this");
}
- protected int makeCurrentImpl() throws GLException {
- display = X11GLContextFactory.getDisplayConnection();
- if (pendingOffscreenResize) {
- if (pendingOffscreenWidth != width || pendingOffscreenHeight != height) {
- if (context != 0) {
- destroy();
- }
- width = pendingOffscreenWidth;
- height = pendingOffscreenHeight;
- pendingOffscreenResize = false;
- }
- }
- mostRecentDisplay = display;
- return super.makeCurrentImpl();
- }
-
- public void swapBuffers() throws GLException {
- }
-
- protected void releaseImpl() throws GLException {
- try {
- super.releaseImpl();
- } finally {
- display = 0;
- }
- }
-
protected void create() {
- XVisualInfo vis = chooseVisual();
- int bitsPerPixel = vis.depth();
-
- if (display == 0) {
- throw new GLException("No active display");
- }
- int screen = GLX.DefaultScreen(display);
- pixmap = GLX.XCreatePixmap(display, (int) GLX.RootWindow(display, screen), width, height, bitsPerPixel);
- if (pixmap == 0) {
- throw new GLException("XCreatePixmap failed");
- }
- drawable = GLX.glXCreateGLXPixmap(display, vis, pixmap);
- if (drawable == 0) {
- throw new GLException("glXCreateGLXPixmap failed");
- }
- context = createContext(vis, false);
- if (context == 0) {
- throw new GLException("Unable to create OpenGL context");
- }
- isDoubleBuffered = (X11GLContextFactory.glXGetConfig(display, vis, GLX.GLX_DOUBLEBUFFER, new int[1], 0) != 0);
- }
-
- protected void destroyImpl() {
- if (context != 0) {
- super.destroyImpl();
- // Must destroy OpenGL context, pixmap and GLXPixmap
- GLX.glXDestroyContext(display, context);
- GLX.glXDestroyGLXPixmap(display, (int) drawable);
- GLX.XFreePixmap(display, pixmap);
- context = 0;
- drawable = 0;
- pixmap = 0;
- GLContextShareSet.contextDestroyed(this);
- }
+ createContext(false);
}
}
diff --git a/src/net/java/games/jogl/impl/x11/X11OffscreenGLDrawable.java b/src/net/java/games/jogl/impl/x11/X11OffscreenGLDrawable.java
new file mode 100644
index 000000000..7b60612df
--- /dev/null
+++ b/src/net/java/games/jogl/impl/x11/X11OffscreenGLDrawable.java
@@ -0,0 +1,143 @@
+/*
+ * 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.x11;
+
+import net.java.games.jogl.*;
+import net.java.games.jogl.impl.*;
+
+public class X11OffscreenGLDrawable extends X11GLDrawable {
+ private long pixmap;
+ private boolean isDoubleBuffered;
+ // Width and height of the underlying bitmap
+ private int width;
+ private int height;
+
+ public X11OffscreenGLDrawable(GLCapabilities capabilities,
+ GLCapabilitiesChooser chooser) {
+ super(null, capabilities, chooser);
+ }
+
+ public GLContext createContext(GLContext shareWith) {
+ return new X11OffscreenGLContext(this, shareWith);
+ }
+
+ public void setSize(int newWidth, int newHeight) {
+ width = newWidth;
+ height = newHeight;
+ if (pixmap != 0) {
+ destroy();
+ }
+ create();
+ }
+
+ public int getWidth() {
+ return width;
+ }
+
+ public int getHeight() {
+ return height;
+ }
+
+ private void create() {
+ display = X11GLContextFactory.getDisplayConnection();
+ XVisualInfo vis = chooseVisual(false);
+ int bitsPerPixel = vis.depth();
+
+ lockAWT();
+ try {
+ int screen = GLX.DefaultScreen(display);
+ pixmap = GLX.XCreatePixmap(display, (int) GLX.RootWindow(display, screen), width, height, bitsPerPixel);
+ if (pixmap == 0) {
+ throw new GLException("XCreatePixmap failed");
+ }
+ drawable = GLX.glXCreateGLXPixmap(display, vis, pixmap);
+ if (drawable == 0) {
+ GLX.XFreePixmap(display, pixmap);
+ pixmap = 0;
+ throw new GLException("glXCreateGLXPixmap failed");
+ }
+ isDoubleBuffered = (X11GLContextFactory.glXGetConfig(display, vis, GLX.GLX_DOUBLEBUFFER, new int[1], 0) != 0);
+ if (DEBUG) {
+ System.err.println("Created pixmap " + toHexString(pixmap) +
+ ", GLXPixmap " + toHexString(drawable) +
+ ", display " + toHexString(display));
+ }
+ } finally {
+ unlockAWT();
+ }
+ }
+
+ public void destroy() {
+ if (pixmap != 0) {
+ if (DEBUG) {
+ System.err.println("Destroying pixmap " + toHexString(pixmap) +
+ ", GLXPixmap " + toHexString(drawable) +
+ ", display " + toHexString(display));
+ }
+
+ // Must destroy pixmap and GLXPixmap
+ lockAWT();
+
+ if (DEBUG) {
+ long cur = GLX.glXGetCurrentContext();
+ if (cur != 0) {
+ System.err.println("WARNING: found context " + toHexString(cur) + " current during pixmap destruction");
+ }
+ }
+
+ // FIXME: workaround for crashes on NVidia hardware when
+ // destroying pixmap (no context is current at the point of the
+ // crash, at least from the point of view of
+ // glXGetCurrentContext)
+ GLX.glXMakeCurrent(display, 0, 0);
+
+ GLX.glXDestroyGLXPixmap(display, drawable);
+ GLX.XFreePixmap(display, pixmap);
+ unlockAWT();
+ drawable = 0;
+ pixmap = 0;
+ display = 0;
+ }
+ }
+
+ public boolean isDoubleBuffered() {
+ return isDoubleBuffered;
+ }
+}
diff --git a/src/net/java/games/jogl/impl/x11/X11OnscreenGLContext.java b/src/net/java/games/jogl/impl/x11/X11OnscreenGLContext.java
index 5a6fe23bb..1828f8378 100644
--- a/src/net/java/games/jogl/impl/x11/X11OnscreenGLContext.java
+++ b/src/net/java/games/jogl/impl/x11/X11OnscreenGLContext.java
@@ -39,47 +39,20 @@
package net.java.games.jogl.impl.x11;
-import java.awt.Component;
import java.util.*;
import net.java.games.jogl.*;
import net.java.games.jogl.impl.*;
public class X11OnscreenGLContext extends X11GLContext {
- // Variables for lockSurface/unlockSurface
- private JAWT_DrawingSurface ds;
- 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;
-
+ protected X11OnscreenGLDrawable drawable;
// Variables for pbuffer support
List pbuffersToInstantiate = new ArrayList();
- public X11OnscreenGLContext(Component component,
- GLCapabilities capabilities,
- GLCapabilitiesChooser chooser,
+ public X11OnscreenGLContext(X11OnscreenGLDrawable drawable,
GLContext shareWith) {
- super(component, capabilities, chooser, shareWith);
- }
-
- protected GL createGL()
- {
- return new X11GLImpl(this);
- }
-
- protected boolean isOffscreen() {
- return false;
+ super(drawable, shareWith);
+ this.drawable = drawable;
}
public int getOffscreenContextReadBuffer() {
@@ -91,17 +64,15 @@ public class X11OnscreenGLContext extends X11GLContext {
}
public boolean canCreatePbufferContext() {
- // FIXME: should we gate this on GLX 1.3 being available?
- return true;
+ return isExtensionAvailable("GL_ARB_pbuffer");
}
- public GLContext createPbufferContext(GLCapabilities capabilities,
- int initialWidth,
- int initialHeight) {
- X11PbufferGLContext ctx = new X11PbufferGLContext(capabilities, initialWidth, initialHeight);
- ctx.setSynchronized(true);
- pbuffersToInstantiate.add(ctx);
- return ctx;
+ public GLDrawableImpl createPbufferDrawable(GLCapabilities capabilities,
+ int initialWidth,
+ int initialHeight) {
+ X11PbufferGLDrawable buf = new X11PbufferGLDrawable(capabilities, initialWidth, initialHeight);
+ pbuffersToInstantiate.add(buf);
+ return buf;
}
public void bindPbufferToTexture() {
@@ -112,39 +83,39 @@ public class X11OnscreenGLContext extends X11GLContext {
throw new GLException("Should not call this");
}
- public void setSwapInterval(int interval) {
- GL gl = getGL();
- if (gl.isExtensionAvailable("GLX_SGI_swap_control")) {
- gl.glXSwapIntervalSGI(interval);
- }
- }
-
- public void setRealized() {
- realized = true;
- }
-
protected int makeCurrentImpl() throws GLException {
try {
- if (!realized) {
+ int lockRes = drawable.lockSurface();
+ if (lockRes == X11OnscreenGLDrawable.LOCK_SURFACE_NOT_READY) {
return CONTEXT_NOT_CURRENT;
}
- if (!lockSurface()) {
- return CONTEXT_NOT_CURRENT;
+ if (lockRes == X11OnscreenGLDrawable.LOCK_SURFACE_CHANGED) {
+ if (context != 0) {
+ GLX.glXDestroyContext(mostRecentDisplay, context);
+ GLContextShareSet.contextDestroyed(this);
+ if (DEBUG) {
+ System.err.println(getThreadName() + ": !!! Destroyed OpenGL context " + toHexString(context) + " due to JAWT_LOCK_SURFACE_CHANGED");
+ }
+ context = 0;
+ }
}
int ret = super.makeCurrentImpl();
if ((ret == CONTEXT_CURRENT) ||
(ret == CONTEXT_CURRENT_NEW)) {
// Instantiate any pending pbuffers
while (!pbuffersToInstantiate.isEmpty()) {
- X11PbufferGLContext ctx =
- (X11PbufferGLContext) pbuffersToInstantiate.remove(pbuffersToInstantiate.size() - 1);
- ctx.createPbuffer(display, context, getGL());
+ X11PbufferGLDrawable buf =
+ (X11PbufferGLDrawable) pbuffersToInstantiate.remove(pbuffersToInstantiate.size() - 1);
+ buf.createPbuffer(getGL(), drawable.getDisplay());
+ if (DEBUG) {
+ System.err.println(getThreadName() + ": created pbuffer " + buf);
+ }
}
}
return ret;
} catch (RuntimeException e) {
try {
- unlockSurface();
+ drawable.unlockSurface();
} catch (Exception e2) {
// do nothing if unlockSurface throws
}
@@ -156,88 +127,11 @@ public class X11OnscreenGLContext extends X11GLContext {
try {
super.releaseImpl();
} finally {
- unlockSurface();
- }
- }
-
- 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)
- GLX.glXSwapBuffers(display, (int) drawable);
- }
-
- private boolean lockSurface() throws GLException {
- if (drawable != 0) {
- throw new GLException("Surface already locked");
- }
- ds = getJAWT().GetDrawingSurface(component);
- if (ds == null) {
- // Widget not yet realized
- return false;
+ drawable.unlockSurface();
}
- int res = ds.Lock();
- if ((res & JAWTFactory.JAWT_LOCK_ERROR) != 0) {
- throw new GLException("Unable to lock surface");
- }
- // See whether the surface changed and if so destroy the old
- // OpenGL context so it will be recreated
- if ((res & JAWTFactory.JAWT_LOCK_SURFACE_CHANGED) != 0) {
- if (context != 0) {
- GLX.glXDestroyContext(display, context);
- context = 0;
- }
- }
- dsi = ds.GetDrawingSurfaceInfo();
- if (dsi == null) {
- // Widget not yet realized
- ds.Unlock();
- getJAWT().FreeDrawingSurface(ds);
- ds = null;
- return false;
- }
- x11dsi = (JAWT_X11DrawingSurfaceInfo) dsi.platformInfo();
- display = x11dsi.display();
- drawable = x11dsi.drawable();
- visualID = x11dsi.visualID();
- if (display == 0 || drawable == 0) {
- // Widget not yet realized
- ds.FreeDrawingSurfaceInfo(dsi);
- ds.Unlock();
- getJAWT().FreeDrawingSurface(ds);
- ds = null;
- dsi = null;
- x11dsi = null;
- display = 0;
- drawable = 0;
- visualID = 0;
- return false;
- }
- mostRecentDisplay = display;
- return true;
- }
-
- private void unlockSurface() {
- if (drawable == 0) {
- throw new GLException("Surface already unlocked");
- }
- ds.FreeDrawingSurfaceInfo(dsi);
- ds.Unlock();
- getJAWT().FreeDrawingSurface(ds);
- ds = null;
- dsi = null;
- x11dsi = null;
- display = 0;
- drawable = 0;
- visualID = 0;
}
protected void create() {
- chooseVisualAndCreateContext(true);
- }
+ createContext(true);
+ }
}
diff --git a/src/net/java/games/jogl/impl/x11/X11OnscreenGLDrawable.java b/src/net/java/games/jogl/impl/x11/X11OnscreenGLDrawable.java
new file mode 100644
index 000000000..9b9705122
--- /dev/null
+++ b/src/net/java/games/jogl/impl/x11/X11OnscreenGLDrawable.java
@@ -0,0 +1,174 @@
+/*
+ * 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.x11;
+
+import java.awt.Component;
+
+import net.java.games.jogl.*;
+import net.java.games.jogl.impl.*;
+
+public class X11OnscreenGLDrawable extends X11GLDrawable {
+ public static final int LOCK_SURFACE_NOT_READY = 1;
+ public static final int LOCK_SURFACE_CHANGED = 2;
+ public static final int LOCK_SUCCESS = 3;
+
+ // Variables for lockSurface/unlockSurface
+ private JAWT_DrawingSurface ds;
+ 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;
+
+ public X11OnscreenGLDrawable(Component component) {
+ super(component, null, null);
+ }
+
+ public GLContext createContext(GLContext shareWith) {
+ return new X11OnscreenGLContext(this, shareWith);
+ }
+
+ public void setRealized(boolean realized) {
+ this.realized = realized;
+ }
+
+ public void setSize(int width, int height) {
+ component.setSize(width, height);
+ }
+
+ public int getWidth() {
+ return component.getWidth();
+ }
+
+ public int getHeight() {
+ return component.getHeight();
+ }
+
+ public void swapBuffers() throws GLException {
+ lockAWT();
+ GLX.glXSwapBuffers(display, drawable);
+ unlockAWT();
+ }
+
+ public int lockSurface() throws GLException {
+ if (!realized) {
+ return LOCK_SURFACE_NOT_READY;
+ }
+ if (drawable != 0) {
+ throw new GLException("Surface already locked");
+ }
+ ds = getJAWT().GetDrawingSurface(component);
+ if (ds == null) {
+ // Widget not yet realized
+ return LOCK_SURFACE_NOT_READY;
+ }
+ int res = ds.Lock();
+ if ((res & JAWTFactory.JAWT_LOCK_ERROR) != 0) {
+ throw new GLException("Unable to lock surface");
+ }
+ // See whether the surface changed and if so destroy the old
+ // OpenGL context so it will be recreated (NOTE: removeNotify
+ // should handle this case, but it may be possible that race
+ // conditions can cause this code to be triggered -- should test
+ // more)
+ int ret = LOCK_SUCCESS;
+ if ((res & JAWTFactory.JAWT_LOCK_SURFACE_CHANGED) != 0) {
+ ret = LOCK_SURFACE_CHANGED;
+ }
+ dsi = ds.GetDrawingSurfaceInfo();
+ if (dsi == null) {
+ // Widget not yet realized
+ ds.Unlock();
+ getJAWT().FreeDrawingSurface(ds);
+ ds = null;
+ return LOCK_SURFACE_NOT_READY;
+ }
+ x11dsi = (JAWT_X11DrawingSurfaceInfo) dsi.platformInfo();
+ display = x11dsi.display();
+ drawable = x11dsi.drawable();
+ visualID = x11dsi.visualID();
+ if (display == 0 || drawable == 0) {
+ // Widget not yet realized
+ ds.FreeDrawingSurfaceInfo(dsi);
+ ds.Unlock();
+ getJAWT().FreeDrawingSurface(ds);
+ ds = null;
+ dsi = null;
+ x11dsi = null;
+ display = 0;
+ drawable = 0;
+ visualID = 0;
+ return LOCK_SURFACE_NOT_READY;
+ }
+ return ret;
+ }
+
+ public void unlockSurface() {
+ if (drawable == 0) {
+ throw new GLException("Surface already unlocked");
+ }
+ ds.FreeDrawingSurfaceInfo(dsi);
+ ds.Unlock();
+ getJAWT().FreeDrawingSurface(ds);
+ ds = null;
+ dsi = null;
+ x11dsi = null;
+ display = 0;
+ drawable = 0;
+ visualID = 0;
+ }
+
+ //----------------------------------------------------------------------
+ // Internals only below this point
+ //
+
+ private JAWT getJAWT() {
+ return X11GLContextFactory.getJAWT();
+ }
+}
diff --git a/src/net/java/games/jogl/impl/x11/X11PbufferGLContext.java b/src/net/java/games/jogl/impl/x11/X11PbufferGLContext.java
index 30a60ba61..bebbdb91c 100644
--- a/src/net/java/games/jogl/impl/x11/X11PbufferGLContext.java
+++ b/src/net/java/games/jogl/impl/x11/X11PbufferGLContext.java
@@ -43,40 +43,21 @@ import net.java.games.jogl.*;
import net.java.games.jogl.impl.*;
public class X11PbufferGLContext extends X11GLContext {
- private static final boolean DEBUG = Debug.debug("X11PbufferGLContext");
+ private X11PbufferGLDrawable drawable;
- private int initWidth;
- private int initHeight;
-
- private long buffer; // GLXPbuffer
- private GLXFBConfig fbConfig;
- private int width;
- private int height;
-
- // FIXME: kept around because we create the OpenGL context lazily to
- // better integrate with the X11GLContext framework
- private long parentContext;
-
- private static final int MAX_PFORMATS = 256;
- private static final int MAX_ATTRIBS = 256;
-
- public X11PbufferGLContext(GLCapabilities capabilities, int initialWidth, int initialHeight) {
- super(null, capabilities, null, null);
- this.initWidth = initialWidth;
- this.initHeight = initialHeight;
- if (initWidth <= 0 || initHeight <= 0) {
- throw new GLException("Initial width and height of pbuffer must be positive (were (" +
- initWidth + ", " + initHeight + "))");
- }
+ public X11PbufferGLContext(X11PbufferGLDrawable drawable,
+ GLContext shareWith) {
+ super(drawable, shareWith);
+ this.drawable = drawable;
}
public boolean canCreatePbufferContext() {
return false;
}
- public GLContext createPbufferContext(GLCapabilities capabilities,
- int initialWidth,
- int initialHeight) {
+ public GLDrawableImpl createPbufferDrawable(GLCapabilities capabilities,
+ int initialWidth,
+ int initialHeight) {
throw new GLException("Not supported");
}
@@ -90,169 +71,40 @@ public class X11PbufferGLContext extends X11GLContext {
throw new GLException("Not yet implemented");
}
- public void createPbuffer(long display, long parentContext, GL gl) {
- if (display == 0) {
- throw new GLException("Null display");
- }
-
- if (parentContext == 0) {
- throw new GLException("Null parentContext");
- }
-
- if (capabilities.getOffscreenRenderToTexture()) {
- throw new GLException("Render-to-texture pbuffers not supported yet on X11");
- }
-
- if (capabilities.getOffscreenRenderToTextureRectangle()) {
- throw new GLException("Render-to-texture-rectangle pbuffers not supported yet on X11");
- }
-
- int[] iattributes = new int [2*MAX_ATTRIBS];
- float[] fattributes = new float[2*MAX_ATTRIBS];
- int nfattribs = 0;
- int niattribs = 0;
-
- // Since we are trying to create a pbuffer, the GLXFBConfig we
- // request (and subsequently use) must be "p-buffer capable".
- iattributes[niattribs++] = GL.GLX_DRAWABLE_TYPE;
- iattributes[niattribs++] = GL.GLX_PBUFFER_BIT;
-
- iattributes[niattribs++] = GL.GLX_RENDER_TYPE;
- iattributes[niattribs++] = GL.GLX_RGBA_BIT;
-
- iattributes[niattribs++] = GLX.GLX_DOUBLEBUFFER;
- if (capabilities.getDoubleBuffered()) {
- iattributes[niattribs++] = GL.GL_TRUE;
- } else {
- iattributes[niattribs++] = GL.GL_FALSE;
- }
-
- iattributes[niattribs++] = GLX.GLX_DEPTH_SIZE;
- iattributes[niattribs++] = capabilities.getDepthBits();
-
- iattributes[niattribs++] = GLX.GLX_RED_SIZE;
- iattributes[niattribs++] = capabilities.getRedBits();
-
- iattributes[niattribs++] = GLX.GLX_GREEN_SIZE;
- iattributes[niattribs++] = capabilities.getGreenBits();
-
- iattributes[niattribs++] = GLX.GLX_BLUE_SIZE;
- iattributes[niattribs++] = capabilities.getBlueBits();
-
- iattributes[niattribs++] = GLX.GLX_ALPHA_SIZE;
- iattributes[niattribs++] = capabilities.getAlphaBits();
-
- if (capabilities.getStencilBits() > 0) {
- iattributes[niattribs++] = GLX.GLX_STENCIL_SIZE;
- iattributes[niattribs++] = capabilities.getStencilBits();
- }
-
- if (capabilities.getAccumRedBits() > 0 ||
- capabilities.getAccumGreenBits() > 0 ||
- capabilities.getAccumBlueBits() > 0) {
- iattributes[niattribs++] = GLX.GLX_ACCUM_RED_SIZE;
- iattributes[niattribs++] = capabilities.getAccumRedBits();
- iattributes[niattribs++] = GLX.GLX_ACCUM_GREEN_SIZE;
- iattributes[niattribs++] = capabilities.getAccumGreenBits();
- iattributes[niattribs++] = GLX.GLX_ACCUM_BLUE_SIZE;
- iattributes[niattribs++] = capabilities.getAccumBlueBits();
- }
-
- if (capabilities.getOffscreenFloatingPointBuffers()) {
- if (!gl.isExtensionAvailable("GLX_NV_float_buffer")) {
- throw new GLException("Floating-point pbuffers on X11 currently require NVidia hardware");
- }
- iattributes[niattribs++] = GLX.GLX_FLOAT_COMPONENTS_NV;
- iattributes[niattribs++] = GL.GL_TRUE;
- }
-
- // FIXME: add FSAA support? Don't want to get into a situation
- // where we have to retry the glXChooseFBConfig call if it fails
- // due to a lack of an antialiased visual...
-
- iattributes[niattribs++] = 0; // null-terminate
-
- int screen = 0; // FIXME: provide way to specify this?
- int[] nelementsTmp = new int[1];
- GLXFBConfig[] fbConfigs = GLX.glXChooseFBConfig(display, screen, iattributes, 0, nelementsTmp, 0);
- if (fbConfigs == null || fbConfigs.length == 0 || fbConfigs[0] == null) {
- throw new GLException("pbuffer creation error: glXChooseFBConfig() failed");
- }
- // Note that we currently don't allow selection of anything but
- // the first GLXFBConfig in the returned list
- GLXFBConfig fbConfig = fbConfigs[0];
- int nelements = nelementsTmp[0];
- if (nelements <= 0) {
- throw new GLException("pbuffer creation error: couldn't find a suitable frame buffer configuration");
- }
-
- if (DEBUG) {
- System.err.println("Found " + fbConfigs.length + " matching GLXFBConfigs");
- System.err.println("Parameters of default one:");
- System.err.println("render type: 0x" + Integer.toHexString(queryFBConfig(display, fbConfig, GLX.GLX_RENDER_TYPE)));
- System.err.println("rgba: " + ((queryFBConfig(display, fbConfig, GLX.GLX_RENDER_TYPE) & GLX.GLX_RGBA_BIT) != 0));
- System.err.println("r: " + queryFBConfig(display, fbConfig, GLX.GLX_RED_SIZE));
- System.err.println("g: " + queryFBConfig(display, fbConfig, GLX.GLX_GREEN_SIZE));
- System.err.println("b: " + queryFBConfig(display, fbConfig, GLX.GLX_BLUE_SIZE));
- System.err.println("a: " + queryFBConfig(display, fbConfig, GLX.GLX_ALPHA_SIZE));
- System.err.println("depth: " + queryFBConfig(display, fbConfig, GLX.GLX_DEPTH_SIZE));
- System.err.println("double buffered: " + queryFBConfig(display, fbConfig, GLX.GLX_DOUBLEBUFFER));
- }
-
- // Create the p-buffer.
- niattribs = 0;
-
- iattributes[niattribs++] = GL.GLX_PBUFFER_WIDTH;
- iattributes[niattribs++] = initWidth;
- iattributes[niattribs++] = GL.GLX_PBUFFER_HEIGHT;
- iattributes[niattribs++] = initHeight;
-
- iattributes[niattribs++] = 0;
-
- long tmpBuffer = GLX.glXCreatePbuffer(display, fbConfig, iattributes, 0);
- if (tmpBuffer == 0) {
- // FIXME: query X error code for detail error message
- throw new GLException("pbuffer creation error: glXCreatePbuffer() failed");
- }
-
- // Set up instance variables
- this.display = display;
- mostRecentDisplay = display;
- this.parentContext = parentContext;
- buffer = tmpBuffer;
- this.fbConfig = fbConfig;
-
- // Determine the actual width and height we were able to create.
- int[] tmp = new int[1];
- GLX.glXQueryDrawable(display, (int) buffer, GL.GLX_WIDTH, tmp, 0);
- width = tmp[0];
- GLX.glXQueryDrawable(display, (int) buffer, GL.GLX_HEIGHT, tmp, 0);
- height = tmp[0];
-
- if (DEBUG) {
- System.err.println("Created pbuffer " + width + " x " + height);
- }
- }
-
protected int makeCurrentImpl() throws GLException {
- if (buffer == 0) {
- // pbuffer not instantiated yet
+ if (drawable.getDrawable() == 0) {
+ // pbuffer not instantiated (yet?)
+ if (DEBUG) {
+ System.err.println("pbuffer not instantiated");
+ }
return CONTEXT_NOT_CURRENT;
}
+ // Note that we have to completely override makeCurrentImpl
+ // because the underlying makeCurrent call differs for pbuffers
lockAWT();
try {
boolean created = false;
if (context == 0) {
create();
if (DEBUG) {
- System.err.println("!!! Created GL context for " + getClass().getName());
+ System.err.println(getThreadName() + ": !!! Created GL context for " + getClass().getName());
}
created = true;
}
- if (!GLX.glXMakeContextCurrent(display, buffer, buffer, context)) {
+ if (!GLX.glXMakeContextCurrent(drawable.getDisplay(),
+ drawable.getDrawable(),
+ drawable.getDrawable(),
+ context)) {
throw new GLException("Error making context current");
+ } else {
+ mostRecentDisplay = drawable.getDisplay();
+ if (DEBUG && VERBOSE) {
+ System.err.println(getThreadName() + ": glXMakeCurrent(display " + toHexString(drawable.getDisplay()) +
+ ", drawable " + toHexString(drawable.getDrawable()) +
+ ", context " + toHexString(context) + ") succeeded");
+ }
}
if (created) {
@@ -268,7 +120,7 @@ public class X11PbufferGLContext extends X11GLContext {
protected void releaseImpl() throws GLException {
lockAWT();
try {
- if (!GLX.glXMakeContextCurrent(display, 0, 0, 0)) {
+ if (!GLX.glXMakeContextCurrent(drawable.getDisplay(), 0, 0, 0)) {
throw new GLException("Error freeing OpenGL context");
}
} finally {
@@ -276,16 +128,6 @@ public class X11PbufferGLContext extends X11GLContext {
}
}
- public void handleModeSwitch(long parentHdc, long parentHglrc) {
- throw new GLException("Not yet implemented");
- }
-
- protected boolean isOffscreen() {
- // FIXME: currently the only caller of this won't cause proper
- // resizing of the pbuffer anyway.
- return false;
- }
-
public int getOffscreenContextReadBuffer() {
throw new GLException("Should not call this");
}
@@ -294,50 +136,34 @@ public class X11PbufferGLContext extends X11GLContext {
throw new GLException("Should not call this");
}
+ public int getFloatingPointMode() {
+ return drawable.getFloatingPointMode();
+ }
+
protected void create() {
if (DEBUG) {
- System.err.println("Creating context for pbuffer " + width + " x " + height);
+ System.err.println("Creating context for pbuffer " + drawable.getWidth() +
+ " x " + drawable.getHeight());
}
// Create a gl context for the p-buffer.
- // FIXME: provide option to not share display lists with subordinate pbuffer?
- context = GLX.glXCreateNewContext(display, fbConfig, GL.GLX_RGBA_TYPE, parentContext, true);
+ X11GLContext other = (X11GLContext) GLContextShareSet.getShareContext(this);
+ long share = 0;
+ if (other != null) {
+ share = other.getContext();
+ if (share == 0) {
+ throw new GLException("GLContextShareSet returned an invalid OpenGL context");
+ }
+ }
+ context = GLX.glXCreateNewContext(drawable.getDisplay(), drawable.getFBConfig(), GL.GLX_RGBA_TYPE, share, true);
if (context == 0) {
throw new GLException("pbuffer creation error: glXCreateNewContext() failed");
}
+ GLContextShareSet.contextCreated(this);
if (DEBUG) {
- System.err.println("Created context for pbuffer " + width + " x " + height);
- }
- }
-
- protected void destroyImpl() throws GLException {
- lockAWT();
- try {
- if (context != 0) {
- super.destroyImpl();
- GLX.glXDestroyPbuffer(display, buffer);
- buffer = 0;
- }
- } finally {
- unlockAWT();
- }
- }
-
- public void swapBuffers() throws GLException {
- // FIXME: do we need to do anything if the pbuffer is double-buffered?
- }
-
- public int getFloatingPointMode() {
- // Floating-point pbuffers currently require NVidia hardware on X11
- return GLPbuffer.NV_FLOAT;
- }
-
- private int queryFBConfig(long display, GLXFBConfig fbConfig, int attrib) {
- int[] tmp = new int[1];
- if (GLX.glXGetFBConfigAttrib(display, fbConfig, attrib, tmp, 0) != 0) {
- throw new GLException("glXGetFBConfigAttrib failed");
+ System.err.println("Created context for pbuffer " + drawable.getWidth() +
+ " x " + drawable.getHeight());
}
- return tmp[0];
}
}
diff --git a/src/net/java/games/jogl/impl/x11/X11PbufferGLDrawable.java b/src/net/java/games/jogl/impl/x11/X11PbufferGLDrawable.java
new file mode 100644
index 000000000..fc37f331b
--- /dev/null
+++ b/src/net/java/games/jogl/impl/x11/X11PbufferGLDrawable.java
@@ -0,0 +1,254 @@
+/*
+ * 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.x11;
+
+import net.java.games.jogl.*;
+import net.java.games.jogl.impl.*;
+
+public class X11PbufferGLDrawable extends X11GLDrawable {
+ private int initWidth;
+ private int initHeight;
+
+ // drawable in superclass is a GLXPbuffer
+ private GLXFBConfig fbConfig;
+ private int width;
+ private int height;
+
+ protected static final int MAX_PFORMATS = 256;
+ protected static final int MAX_ATTRIBS = 256;
+
+ public X11PbufferGLDrawable(GLCapabilities capabilities, int initialWidth, int initialHeight) {
+ super(null, capabilities, null);
+ this.initWidth = initialWidth;
+ this.initHeight = initialHeight;
+ if (initWidth <= 0 || initHeight <= 0) {
+ throw new GLException("Initial width and height of pbuffer must be positive (were (" +
+ initWidth + ", " + initHeight + "))");
+ }
+
+ if (DEBUG) {
+ System.out.println("Pbuffer caps on init: " + capabilities +
+ (capabilities.getOffscreenRenderToTexture() ? " [rtt]" : "") +
+ (capabilities.getOffscreenRenderToTextureRectangle() ? " [rect]" : "") +
+ (capabilities.getOffscreenFloatingPointBuffers() ? " [float]" : ""));
+ }
+ }
+
+ public GLContext createContext(GLContext shareWith) {
+ return new X11PbufferGLContext(this, shareWith);
+ }
+
+ public void destroy() {
+ lockAWT();
+ if (drawable != 0) {
+ GLX.glXDestroyPbuffer(display, drawable);
+ }
+ unlockAWT();
+ display = 0;
+ }
+
+ public void setSize(int width, int height) {
+ // FIXME
+ throw new GLException("Not yet implemented");
+ }
+
+ public int getWidth() {
+ return width;
+ }
+
+ public int getHeight() {
+ return height;
+ }
+
+ public void createPbuffer(GL gl, long display) {
+ if (display == 0) {
+ throw new GLException("Null display");
+ }
+
+ if (capabilities.getOffscreenRenderToTexture()) {
+ throw new GLException("Render-to-texture pbuffers not supported yet on X11");
+ }
+
+ if (capabilities.getOffscreenRenderToTextureRectangle()) {
+ throw new GLException("Render-to-texture-rectangle pbuffers not supported yet on X11");
+ }
+
+ int[] iattributes = new int [2*MAX_ATTRIBS];
+ float[] fattributes = new float[2*MAX_ATTRIBS];
+ int nfattribs = 0;
+ int niattribs = 0;
+
+ // Since we are trying to create a pbuffer, the GLXFBConfig we
+ // request (and subsequently use) must be "p-buffer capable".
+ iattributes[niattribs++] = GL.GLX_DRAWABLE_TYPE;
+ iattributes[niattribs++] = GL.GLX_PBUFFER_BIT;
+
+ iattributes[niattribs++] = GL.GLX_RENDER_TYPE;
+ iattributes[niattribs++] = GL.GLX_RGBA_BIT;
+
+ iattributes[niattribs++] = GLX.GLX_DOUBLEBUFFER;
+ if (capabilities.getDoubleBuffered()) {
+ iattributes[niattribs++] = GL.GL_TRUE;
+ } else {
+ iattributes[niattribs++] = GL.GL_FALSE;
+ }
+
+ iattributes[niattribs++] = GLX.GLX_DEPTH_SIZE;
+ iattributes[niattribs++] = capabilities.getDepthBits();
+
+ iattributes[niattribs++] = GLX.GLX_RED_SIZE;
+ iattributes[niattribs++] = capabilities.getRedBits();
+
+ iattributes[niattribs++] = GLX.GLX_GREEN_SIZE;
+ iattributes[niattribs++] = capabilities.getGreenBits();
+
+ iattributes[niattribs++] = GLX.GLX_BLUE_SIZE;
+ iattributes[niattribs++] = capabilities.getBlueBits();
+
+ iattributes[niattribs++] = GLX.GLX_ALPHA_SIZE;
+ iattributes[niattribs++] = capabilities.getAlphaBits();
+
+ if (capabilities.getStencilBits() > 0) {
+ iattributes[niattribs++] = GLX.GLX_STENCIL_SIZE;
+ iattributes[niattribs++] = capabilities.getStencilBits();
+ }
+
+ if (capabilities.getAccumRedBits() > 0 ||
+ capabilities.getAccumGreenBits() > 0 ||
+ capabilities.getAccumBlueBits() > 0) {
+ iattributes[niattribs++] = GLX.GLX_ACCUM_RED_SIZE;
+ iattributes[niattribs++] = capabilities.getAccumRedBits();
+ iattributes[niattribs++] = GLX.GLX_ACCUM_GREEN_SIZE;
+ iattributes[niattribs++] = capabilities.getAccumGreenBits();
+ iattributes[niattribs++] = GLX.GLX_ACCUM_BLUE_SIZE;
+ iattributes[niattribs++] = capabilities.getAccumBlueBits();
+ }
+
+ if (capabilities.getOffscreenFloatingPointBuffers()) {
+ if (!gl.isExtensionAvailable("GLX_NV_float_buffer")) {
+ throw new GLException("Floating-point pbuffers on X11 currently require NVidia hardware");
+ }
+ iattributes[niattribs++] = GLX.GLX_FLOAT_COMPONENTS_NV;
+ iattributes[niattribs++] = GL.GL_TRUE;
+ }
+
+ // FIXME: add FSAA support? Don't want to get into a situation
+ // where we have to retry the glXChooseFBConfig call if it fails
+ // due to a lack of an antialiased visual...
+
+ iattributes[niattribs++] = 0; // null-terminate
+
+ int screen = 0; // FIXME: provide way to specify this?
+ int[] nelementsTmp = new int[1];
+ GLXFBConfig[] fbConfigs = GLX.glXChooseFBConfig(display, screen, iattributes, 0, nelementsTmp, 0);
+ if (fbConfigs == null || fbConfigs.length == 0 || fbConfigs[0] == null) {
+ throw new GLException("pbuffer creation error: glXChooseFBConfig() failed");
+ }
+ // Note that we currently don't allow selection of anything but
+ // the first GLXFBConfig in the returned list
+ GLXFBConfig fbConfig = fbConfigs[0];
+ int nelements = nelementsTmp[0];
+ if (nelements <= 0) {
+ throw new GLException("pbuffer creation error: couldn't find a suitable frame buffer configuration");
+ }
+
+ if (DEBUG) {
+ System.err.println("Found " + fbConfigs.length + " matching GLXFBConfigs");
+ System.err.println("Parameters of default one:");
+ System.err.println("render type: 0x" + Integer.toHexString(queryFBConfig(display, fbConfig, GLX.GLX_RENDER_TYPE)));
+ System.err.println("rgba: " + ((queryFBConfig(display, fbConfig, GLX.GLX_RENDER_TYPE) & GLX.GLX_RGBA_BIT) != 0));
+ System.err.println("r: " + queryFBConfig(display, fbConfig, GLX.GLX_RED_SIZE));
+ System.err.println("g: " + queryFBConfig(display, fbConfig, GLX.GLX_GREEN_SIZE));
+ System.err.println("b: " + queryFBConfig(display, fbConfig, GLX.GLX_BLUE_SIZE));
+ System.err.println("a: " + queryFBConfig(display, fbConfig, GLX.GLX_ALPHA_SIZE));
+ System.err.println("depth: " + queryFBConfig(display, fbConfig, GLX.GLX_DEPTH_SIZE));
+ System.err.println("double buffered: " + queryFBConfig(display, fbConfig, GLX.GLX_DOUBLEBUFFER));
+ }
+
+ // Create the p-buffer.
+ niattribs = 0;
+
+ iattributes[niattribs++] = GL.GLX_PBUFFER_WIDTH;
+ iattributes[niattribs++] = initWidth;
+ iattributes[niattribs++] = GL.GLX_PBUFFER_HEIGHT;
+ iattributes[niattribs++] = initHeight;
+
+ iattributes[niattribs++] = 0;
+
+ long tmpBuffer = GLX.glXCreatePbuffer(display, fbConfig, iattributes, 0);
+ if (tmpBuffer == 0) {
+ // FIXME: query X error code for detail error message
+ throw new GLException("pbuffer creation error: glXCreatePbuffer() failed");
+ }
+
+ // Set up instance variables
+ this.display = display;
+ drawable = tmpBuffer;
+ this.fbConfig = fbConfig;
+
+ // Determine the actual width and height we were able to create.
+ int[] tmp = new int[1];
+ GLX.glXQueryDrawable(display, drawable, GL.GLX_WIDTH, tmp, 0);
+ width = tmp[0];
+ GLX.glXQueryDrawable(display, drawable, GL.GLX_HEIGHT, tmp, 0);
+ height = tmp[0];
+
+ if (DEBUG) {
+ System.err.println("Created pbuffer " + width + " x " + height);
+ }
+ }
+
+ public int getFloatingPointMode() {
+ // Floating-point pbuffers currently require NVidia hardware on X11
+ return GLPbuffer.NV_FLOAT;
+ }
+
+ public GLXFBConfig getFBConfig() {
+ return fbConfig;
+ }
+
+ private int queryFBConfig(long display, GLXFBConfig fbConfig, int attrib) {
+ int[] tmp = new int[1];
+ if (GLX.glXGetFBConfigAttrib(display, fbConfig, attrib, tmp, 0) != 0) {
+ throw new GLException("glXGetFBConfigAttrib failed");
+ }
+ return tmp[0];
+ }
+}