diff options
author | djp <[email protected]> | 2003-06-08 19:27:01 +0000 |
---|---|---|
committer | djp <[email protected]> | 2003-06-08 19:27:01 +0000 |
commit | d49fd968963909f181423eae46c613189468fac3 (patch) | |
tree | b231329e6b65fd54aa24b3bcc0a3ecc623daec61 /src/net/java/games/jogl | |
parent | 9c8fb046dee5d832bea3f36dcbd43285054f49a0 (diff) |
Initial revision
git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/svn-server-sync/jogl/trunk@3 232f8b59-042b-4e1e-8c03-345bb8c30851
Diffstat (limited to 'src/net/java/games/jogl')
29 files changed, 5093 insertions, 0 deletions
diff --git a/src/net/java/games/jogl/Animator.java b/src/net/java/games/jogl/Animator.java new file mode 100644 index 000000000..d9f2c6729 --- /dev/null +++ b/src/net/java/games/jogl/Animator.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package net.java.games.jogl; + +/** <P> An Animator can be attached to a GLDrawable to drive its + display() method in a loop. For efficiency, it sets up the + rendering thread for the drawable to be its own internal thread, + so it can not be combined with manual repaints of the + surface. </P> + + <P> The Animator currently contains a workaround for a bug in + NVidia's drivers (80174). The current semantics are that once an + Animator is created with a given GLDrawable as a target, repaints + will likely be suspended for that GLDrawable until the Animator is + started. This prevents multithreaded access to the context (which + can be problematic) when the application's intent is for + single-threaded access within the Animator. It is not guaranteed + that repaints will be prevented during this time and applications + should not rely on this behavior for correctness. </P> +*/ + +public class Animator { + private GLDrawable drawable; + private Runnable runnable; + private Thread thread; + private boolean shouldStop; + + public Animator(GLDrawable drawable) { + this.drawable = drawable; + + // Workaround for NVidia driver bug 80174 + if (drawable instanceof GLCanvas) { + ((GLCanvas) drawable).willSetRenderingThread(); + } + } + + public synchronized void start() { + if (thread != null) { + throw new GLException("Already started"); + } + if (runnable == null) { + runnable = new Runnable() { + public void run() { + drawable.setRenderingThread(Thread.currentThread()); + drawable.setNoAutoRedrawMode(true); + boolean noException = false; + try { + while (!shouldStop) { + noException = false; + drawable.display(); + noException = true; + } + } finally { + shouldStop = false; + drawable.setNoAutoRedrawMode(false); + if (noException) { + try { + drawable.setRenderingThread(null); + } finally { + thread = null; + synchronized (Animator.this) { + Animator.this.notify(); + } + } + } + } + } + }; + } + thread = new Thread(runnable); + thread.start(); + } + + public synchronized void stop() { + shouldStop = true; + while (shouldStop && thread != null) { + try { + wait(); + } catch (InterruptedException e) { + } + } + } +} diff --git a/src/net/java/games/jogl/ComponentEvents.java b/src/net/java/games/jogl/ComponentEvents.java new file mode 100644 index 000000000..fc3208024 --- /dev/null +++ b/src/net/java/games/jogl/ComponentEvents.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package net.java.games.jogl; + +import java.awt.event.*; +import java.beans.PropertyChangeListener; + +/** Factors out the listener manipulation for the events supported by + all of the {@link GLDrawable} implementations. Provided to reduce + clutter in the documentation for GLDrawable. */ + +public interface ComponentEvents { + public void addComponentListener(ComponentListener l); + public void removeComponentListener(ComponentListener l); + public void addFocusListener(FocusListener l); + public void removeFocusListener(FocusListener l); + public void addHierarchyBoundsListener(HierarchyBoundsListener l); + public void removeHierarchyBoundsListener(HierarchyBoundsListener l); + public void addHierarchyListener(HierarchyListener l); + public void removeHierarchyListener(HierarchyListener l); + public void addInputMethodListener(InputMethodListener l); + public void removeInputMethodListener(InputMethodListener l); + public void addKeyListener(KeyListener l); + public void removeKeyListener(KeyListener l); + public void addMouseListener(MouseListener l); + public void removeMouseListener(MouseListener l); + public void addMouseMotionListener(MouseMotionListener l); + public void removeMouseMotionListener(MouseMotionListener l); + public void addMouseWheelListener(MouseWheelListener l); + public void removeMouseWheelListener(MouseWheelListener l); + public void addPropertyChangeListener(PropertyChangeListener listener); + public void removePropertyChangeListener(PropertyChangeListener listener); + public void addPropertyChangeListener(String propertyName, + PropertyChangeListener listener); + public void removePropertyChangeListener(String propertyName, + PropertyChangeListener listener); +} diff --git a/src/net/java/games/jogl/DefaultGLCapabilitiesChooser.java b/src/net/java/games/jogl/DefaultGLCapabilitiesChooser.java new file mode 100644 index 000000000..de7f500b5 --- /dev/null +++ b/src/net/java/games/jogl/DefaultGLCapabilitiesChooser.java @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package net.java.games.jogl; + +/** <P> The default implementation of the {@link + GLCapabilitiesChooser} interface, which provides consistent visual + selection behavior across platforms. The precise algorithm is + deliberately left loosely specified. Some properties are: </P> + + <UL> + + <LI> As long as there is at least one available non-null + GLCapabilities which matches the "stereo" option, will return a + valid index. + + <LI> Attempts to match as closely as possible the given + GLCapabilities, but will select one with fewer capabilities (i.e., + lower color depth) if necessary. + + <LI> Prefers hardware-accelerated visuals to + non-hardware-accelerated. + + <LI> If there is no exact match, prefers a more-capable visual to + a less-capable one. + + <LI> If there is more than one exact match, chooses an arbitrary + one. + + <LI> May select the opposite of a double- or single-buffered + visual (based on the user's request) in dire situations. + + <LI> Color depth (including alpha) mismatches are weighted higher + than depth buffer mismatches, which are in turn weighted higher + than accumulation buffer (including alpha) and stencil buffer + depth mismatches. + + </UL> +*/ + +public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser { + private static final boolean DEBUG = false; + + public int chooseCapabilities(GLCapabilities desired, GLCapabilities[] available) { + if (DEBUG) { + for (int i = 0; i < available.length; i++) { + System.err.println("Available " + i + ": " + available[i]); + } + } + + // Create score array + int[] scores = new int[available.length]; + int NO_SCORE = -9999999; + int DOUBLE_BUFFER_MISMATCH_PENALTY = 1000; + int STENCIL_MISMATCH_PENALTY = 500; + // Pseudo attempt to keep equal rank penalties scale-equivalent + // (e.g., stencil mismatch is 3 * accum because there are 3 accum + // components) + int COLOR_MISMATCH_PENALTY_SCALE = 36; + int DEPTH_MISMATCH_PENALTY_SCALE = 6; + int ACCUM_MISMATCH_PENALTY_SCALE = 1; + int STENCIL_MISMATCH_PENALTY_SCALE = 3; + for (int i = 0; i < scores.length; i++) { + scores[i] = NO_SCORE; + } + // Compute score for each + for (int i = 0; i < scores.length; i++) { + GLCapabilities cur = available[i]; + if (cur == null) { + continue; + } + if (desired.getStereo() != cur.getStereo()) { + continue; + } + int score = 0; + // Compute difference in color depth + // (Note that this decides the direction of all other penalties) + score += (COLOR_MISMATCH_PENALTY_SCALE * + ((cur.getRedBits() + cur.getGreenBits() + cur.getBlueBits() + cur.getAlphaBits()) - + (desired.getRedBits() + desired.getGreenBits() + desired.getBlueBits() + desired.getAlphaBits()))); + // Compute difference in depth buffer depth + score += (DEPTH_MISMATCH_PENALTY_SCALE * sign(score) * + Math.abs(cur.getDepthBits() - desired.getDepthBits())); + // Compute difference in accumulation buffer depth + score += (ACCUM_MISMATCH_PENALTY_SCALE * sign(score) * + Math.abs((cur.getAccumRedBits() + cur.getAccumGreenBits() + cur.getAccumBlueBits() + cur.getAccumAlphaBits()) - + (desired.getAccumRedBits() + desired.getAccumGreenBits() + desired.getAccumBlueBits() + desired.getAccumAlphaBits()))); + // Compute difference in stencil bits + score += STENCIL_MISMATCH_PENALTY_SCALE * sign(score) * (cur.getStencilBits() - desired.getStencilBits()); + if (cur.getDoubleBuffered() != desired.getDoubleBuffered()) { + score += sign(score) * DOUBLE_BUFFER_MISMATCH_PENALTY; + } + if ((desired.getStencilBits() > 0) && (cur.getStencilBits() == 0)) { + score += sign(score) * STENCIL_MISMATCH_PENALTY; + } + scores[i] = score; + } + // Now prefer hardware-accelerated visuals by pushing scores of + // non-hardware-accelerated visuals out + boolean gotHW = false; + int maxAbsoluteHWScore = 0; + for (int i = 0; i < scores.length; i++) { + int score = scores[i]; + if (score == NO_SCORE) { + continue; + } + GLCapabilities cur = available[i]; + if (cur.getHardwareAccelerated()) { + int absScore = Math.abs(score); + if (!gotHW || + (absScore > maxAbsoluteHWScore)) { + gotHW = true; + maxAbsoluteHWScore = absScore; + } + } + } + if (gotHW) { + for (int i = 0; i < scores.length; i++) { + int score = scores[i]; + if (score == NO_SCORE) { + continue; + } + GLCapabilities cur = available[i]; + if (!cur.getHardwareAccelerated()) { + if (score <= 0) { + score -= maxAbsoluteHWScore; + } else if (score > 0) { + score += maxAbsoluteHWScore; + } + scores[i] = score; + } + } + } + + if (DEBUG) { + System.err.print("Scores: ["); + for (int i = 0; i < available.length; i++) { + if (i > 0) { + System.err.print(","); + } + System.err.print(" " + scores[i]); + } + System.err.println(" ]"); + } + + // Ready to select. Choose score closest to 0. + int scoreClosestToZero = NO_SCORE; + int chosenIndex = -1; + for (int i = 0; i < scores.length; i++) { + int score = scores[i]; + if (score == NO_SCORE) { + continue; + } + // Don't substitute a positive score for a smaller negative score + if ((scoreClosestToZero == NO_SCORE) || + (Math.abs(score) < Math.abs(scoreClosestToZero) && + ((sign(scoreClosestToZero) < 0) || (sign(score) > 0)))) { + scoreClosestToZero = score; + chosenIndex = i; + } + } + if (chosenIndex < 0) { + throw new GLException("Unable to select one of the provided GLCapabilities"); + } + if (DEBUG) { + System.err.println("Chosen index: " + chosenIndex); + System.err.println("Chosen capabilities:"); + System.err.println(available[chosenIndex]); + } + + return chosenIndex; + } + + private static int sign(int score) { + if (score < 0) { + return -1; + } + return 1; + } +} diff --git a/src/net/java/games/jogl/GLCanvas.java b/src/net/java/games/jogl/GLCanvas.java new file mode 100644 index 000000000..21c06ee3f --- /dev/null +++ b/src/net/java/games/jogl/GLCanvas.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package net.java.games.jogl; + +import java.awt.Canvas; +import java.awt.Graphics; +import java.awt.GraphicsConfiguration; +import net.java.games.jogl.impl.*; + +// FIXME: Subclasses need to call resetGLFunctionAvailability() on their +// context whenever the displayChanged() function is called on our +// GLEventListeners + +/** A heavyweight AWT component which provides OpenGL rendering + support. This is the primary implementation of {@link GLDrawable}; + {@link GLJPanel} is provided for compatibility with Swing user + interfaces when adding a heavyweight doesn't work either because + of Z-ordering or LayoutManager problems. This class can not be + instantiated directly; use {@link GLDrawableFactory} to construct + them. */ + +public final class GLCanvas extends Canvas implements GLDrawable { + + private GLDrawableHelper drawableHelper = new GLDrawableHelper(); + private GLContext context; + + GLCanvas(GLCapabilities capabilities, GLCapabilitiesChooser chooser) { + super(); + context = GLContextFactory.getFactory().createGLContext(this, capabilities, chooser); + } + + GLCanvas(GraphicsConfiguration config, GLCapabilities capabilities, GLCapabilitiesChooser chooser) { + super(config); + context = GLContextFactory.getFactory().createGLContext(this, capabilities, chooser); + } + + public void display() { + context.invokeGL(displayAction, false, initAction); + } + + /** Overridden from Canvas; calls {@link #display}. Should not be + invoked by applications directly. */ + public void paint(Graphics g) { + if (!context.getNoAutoRedrawMode()) { + display(); + } + } + + /** Overridden from Canvas; causes {@link GLDrawableHelper#reshape} + to be called on all registered {@link GLEventListener}s. Called + automatically by the AWT; should not be invoked by applications + 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; + context.invokeGL(new Runnable() { + public void run() { + getGL().glViewport(fx, fy, fwidth, fheight); + drawableHelper.reshape(GLCanvas.this, fx, fy, fwidth, fheight); + } + }, true, initAction); + } + + public void addGLEventListener(GLEventListener listener) { + drawableHelper.addGLEventListener(listener); + } + + public void removeGLEventListener(GLEventListener listener) { + drawableHelper.removeGLEventListener(listener); + } + + public GL getGL() { + return context.getGL(); + } + + public void setGL(GL gl) { + context.setGL(gl); + } + + public GLU getGLU() { + return context.getGLU(); + } + + public void setGLU(GLU glu) { + context.setGLU(glu); + } + + void willSetRenderingThread() { + context.willSetRenderingThread(); + } + + public void setRenderingThread(Thread currentThreadOrNull) throws GLException { + context.setRenderingThread(currentThreadOrNull, initAction); + } + + public Thread getRenderingThread() { + return context.getRenderingThread(); + } + + public void setNoAutoRedrawMode(boolean noAutoRedraw) { + context.setNoAutoRedrawMode(noAutoRedraw); + } + + public boolean getNoAutoRedrawMode() { + return context.getNoAutoRedrawMode(); + } + + public boolean canCreateOffscreenDrawable() { + return context.canCreatePbufferContext(); + } + + public GLPbuffer createOffscreenDrawable(GLCapabilities capabilities, + int initialWidth, + int initialHeight) { + return new GLPbufferImpl(context.createPbufferContext(capabilities, initialWidth, initialHeight)); + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + class InitAction implements Runnable { + public void run() { + drawableHelper.init(GLCanvas.this); + } + } + private InitAction initAction = new InitAction(); + + class DisplayAction implements Runnable { + public void run() { + drawableHelper.display(GLCanvas.this); + } + } + private DisplayAction displayAction = new DisplayAction(); +} diff --git a/src/net/java/games/jogl/GLCapabilities.java b/src/net/java/games/jogl/GLCapabilities.java new file mode 100644 index 000000000..389617912 --- /dev/null +++ b/src/net/java/games/jogl/GLCapabilities.java @@ -0,0 +1,308 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package net.java.games.jogl; + +/** Specifies a set of OpenGL capabilities that a rendering context + must support, such as color depth and whether stereo is enabled. + It currently contains the minimal number of routines which allow + configuration on all supported window systems. */ + +public class GLCapabilities implements Cloneable { + private boolean doubleBuffered = true; + private boolean stereo = false; + private boolean hardwareAccelerated = true; + private int depthBits = 24; + private int stencilBits = 0; + private int redBits = 8; + private int greenBits = 8; + private int blueBits = 8; + private int alphaBits = 0; + private int accumRedBits = 0; + private int accumGreenBits = 0; + private int accumBlueBits = 0; + private int accumAlphaBits = 0; + // Shift bits from PIXELFORMATDESCRIPTOR not present because they + // are unlikely to be supported on Windows anyway + + // Bits for pbuffer creation + private boolean offscreenFloatingPointBuffers; + private boolean offscreenRenderToTexture; + private boolean offscreenRenderToTextureRectangle; + + /** Creates a GLCapabilities object. All attributes are in a default + state. + */ + public GLCapabilities() {} + + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } + + /** Indicates whether double-buffering is enabled. */ + public boolean getDoubleBuffered() { + return doubleBuffered; + } + + /** Enables or disables double buffering. */ + public void setDoubleBuffered(boolean onOrOff) { + doubleBuffered = onOrOff; + } + + /** Indicates whether stereo is enabled. */ + public boolean getStereo() { + return stereo; + } + + /** Enables or disables stereo viewing. */ + public void setStereo(boolean onOrOff) { + stereo = onOrOff; + } + + /** Indicates whether hardware acceleration is enabled. */ + public boolean getHardwareAccelerated() { + return hardwareAccelerated; + } + + /** Enables or disables hardware acceleration. */ + public void setHardwareAccelerated(boolean onOrOff) { + hardwareAccelerated = onOrOff; + } + + /** Returns the number of bits requested for the depth buffer. */ + public int getDepthBits() { + return depthBits; + } + + /** Sets the number of bits requested for the depth buffer. */ + public void setDepthBits(int depthBits) { + this.depthBits = depthBits; + } + + /** Returns the number of bits requested for the stencil buffer. */ + public int getStencilBits() { + return stencilBits; + } + + /** Sets the number of bits requested for the stencil buffer. */ + public void setStencilBits(int stencilBits) { + this.stencilBits = stencilBits; + } + + /** Returns the number of bits requested for the color buffer's red + component. On some systems only the color depth, which is the + sum of the red, green, and blue bits, is considered. */ + public int getRedBits() { + return redBits; + } + + /** Sets the number of bits requested for the color buffer's red + component. On some systems only the color depth, which is the + sum of the red, green, and blue bits, is considered. */ + public void setRedBits(int redBits) { + this.redBits = redBits; + } + + /** Returns the number of bits requested for the color buffer's + green component. On some systems only the color depth, which is + the sum of the red, green, and blue bits, is considered. */ + public int getGreenBits() { + return greenBits; + } + + /** Sets the number of bits requested for the color buffer's green + component. On some systems only the color depth, which is the + sum of the red, green, and blue bits, is considered. */ + public void setGreenBits(int greenBits) { + this.greenBits = greenBits; + } + + /** Returns the number of bits requested for the color buffer's blue + component. On some systems only the color depth, which is the + sum of the red, green, and blue bits, is considered. */ + public int getBlueBits() { + return blueBits; + } + + /** Sets the number of bits requested for the color buffer's blue + component. On some systems only the color depth, which is the + sum of the red, green, and blue bits, is considered. */ + public void setBlueBits(int blueBits) { + this.blueBits = blueBits; + } + + /** Returns the number of bits requested for the color buffer's + alpha component. On some systems only the color depth, which is + the sum of the red, green, and blue bits, is considered. */ + public int getAlphaBits() { + return alphaBits; + } + + /** Sets the number of bits requested for the color buffer's alpha + component. On some systems only the color depth, which is the + sum of the red, green, and blue bits, is considered. */ + public void setAlphaBits(int alphaBits) { + this.alphaBits = alphaBits; + } + + /** Returns the number of bits requested for the accumulation + buffer's red component. On some systems only the accumulation + buffer depth, which is the sum of the red, green, and blue bits, + is considered. */ + public int getAccumRedBits() { + return accumRedBits; + } + + /** Sets the number of bits requested for the accumulation buffer's + red component. On some systems only the accumulation buffer + depth, which is the sum of the red, green, and blue bits, is + considered. */ + public void setAccumRedBits(int accumRedBits) { + this.accumRedBits = accumRedBits; + } + + /** Returns the number of bits requested for the accumulation + buffer's green component. On some systems only the accumulation + buffer depth, which is the sum of the red, green, and blue bits, + is considered. */ + public int getAccumGreenBits() { + return accumGreenBits; + } + + /** Sets the number of bits requested for the accumulation buffer's + green component. On some systems only the accumulation buffer + depth, which is the sum of the red, green, and blue bits, is + considered. */ + public void setAccumGreenBits(int accumGreenBits) { + this.accumGreenBits = accumGreenBits; + } + + /** Returns the number of bits requested for the accumulation + buffer's blue component. On some systems only the accumulation + buffer depth, which is the sum of the red, green, and blue bits, + is considered. */ + public int getAccumBlueBits() { + return accumBlueBits; + } + + /** Sets the number of bits requested for the accumulation buffer's + blue component. On some systems only the accumulation buffer + depth, which is the sum of the red, green, and blue bits, is + considered. */ + public void setAccumBlueBits(int accumBlueBits) { + this.accumBlueBits = accumBlueBits; + } + + /** Returns the number of bits requested for the accumulation + buffer's alpha component. On some systems only the accumulation + buffer depth, which is the sum of the red, green, and blue bits, + is considered. */ + public int getAccumAlphaBits() { + return accumAlphaBits; + } + + /** Sets number of bits requested for accumulation buffer's alpha + component. On some systems only the accumulation buffer depth, + which is the sum of the red, green, and blue bits, is + considered. */ + public void setAccumAlphaBits(int accumAlphaBits) { + this.accumAlphaBits = accumAlphaBits; + } + + /** For offscreen surfaces only (pbuffers), indicates whether + floating-point buffers should be used if available. Defaults to + false. */ + public void setOffscreenFloatingPointBuffers(boolean onOrOff) { + offscreenFloatingPointBuffers = onOrOff; + } + + /** For offscreen surfaces only (pbuffers), returns whether + floating-point buffers should be used if available. Defaults to + false. */ + public boolean getOffscreenFloatingPointBuffers() { + return offscreenFloatingPointBuffers; + } + + /** For offscreen surfaces only (pbuffers), indicates whether the + render-to-texture extension should be used if available. + Defaults to false. */ + public void setOffscreenRenderToTexture(boolean onOrOff) { + offscreenRenderToTexture = onOrOff; + } + + /** For offscreen surfaces only (pbuffers), returns whether the + render-to-texture extension should be used if available. + Defaults to false. */ + public boolean getOffscreenRenderToTexture() { + return offscreenRenderToTexture; + } + + /** For offscreen surfaces only (pbuffers), indicates whether the + render-to-texture-rectangle extension should be used if + available. Defaults to false. */ + public void setOffscreenRenderToTextureRectangle(boolean onOrOff) { + offscreenRenderToTextureRectangle = onOrOff; + } + + /** For offscreen surfaces only (pbuffers), returns whether the + render-to-texture extension should be used. Defaults to false. */ + public boolean getOffscreenRenderToTextureRectangle() { + return offscreenRenderToTextureRectangle; + } + + /** Returns a textual representation of this GLCapabilities + object. */ + public String toString() { + return ("GLCapabilities [" + + "DoubleBuffered: " + doubleBuffered + + ", Stereo: " + stereo + + ", HardwareAccelerated: " + hardwareAccelerated + + ", DepthBits: " + depthBits + + ", StencilBits: " + stencilBits + + ", Red: " + redBits + + ", Green: " + greenBits + + ", Blue: " + blueBits + + ", Alpha: " + alphaBits + + ", Red Accum: " + accumRedBits + + ", Green Accum: " + accumGreenBits + + ", Blue Accum: " + accumBlueBits + + ", Alpha Accum: " + accumAlphaBits + + " ]"); + } +} diff --git a/src/net/java/games/jogl/GLCapabilitiesChooser.java b/src/net/java/games/jogl/GLCapabilitiesChooser.java new file mode 100644 index 000000000..16b0e2b76 --- /dev/null +++ b/src/net/java/games/jogl/GLCapabilitiesChooser.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 + * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package net.java.games.jogl; + +/** Provides a mechanism by which applications can customize the + window type selection for a given {@link GLCapabilities}. */ + +public interface GLCapabilitiesChooser { + /** Chooses the index (0..available.length - 1) of the {@link + GLCapabilities} most closely matching the desired one from the + list of all supported. Some of the entries in the + <code>available</code> array may be null; the chooser must + ignore these. */ + public int chooseCapabilities(GLCapabilities desired, GLCapabilities[] available); +} diff --git a/src/net/java/games/jogl/GLDrawable.java b/src/net/java/games/jogl/GLDrawable.java new file mode 100644 index 000000000..6197688b1 --- /dev/null +++ b/src/net/java/games/jogl/GLDrawable.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package net.java.games.jogl; + +import java.awt.Dimension; + +// FIXME: We need some way to tell when the device upon which the canvas is +// being displayed has changed (e.g., the user drags the canvas's parent +// window from one screen on multi-screen environment to another, when the +// user changes the display bit depth or screen resolution, etc). When this +// occurs, we need the canvas to reset the gl function pointer tables for the +// canvas, because the new device may have different capabilities (e.g., +// doesn't support as many opengl extensions) from the original device. This +// hook would also be useful in other GLDrawables (for example, offscreen +// buffers such as pbuffers, whose contents may or may not be invalidated when +// the display mode changes, depending on the vendor's GL implementation). +// +// Right now I'm not sure how hook into when this change occurs. There isn't +// any AWT event corresponding to a device change (as far as I can +// tell). We could constantly check the GraphicsConfiguration of the canvas's top-level +// parent to see if it has changed, but this would be very slow (we'd have to +// do it every time the context is made current). There has got to be a better +// solution, but I'm not sure what it is. + +// FIXME: Subclasses need to call resetGLFunctionAvailability() on their +// 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 extends ComponentEvents { + /** Adds a {@link GLEventListener} to this drawable. If multiple + listeners are added to a given drawable, they are notified of + events in an arbitrary order. */ + public void addGLEventListener(GLEventListener listener); + + /** Removes a {@link GLEventListener} from this drawable. Note that + if this is done from within a particular drawable's {@link + GLEventListener} handler (reshape, display, etc.) that it is not + guaranteed that all other listeners will be evaluated properly + during this update cycle. */ + public void removeGLEventListener(GLEventListener listener); + + /** Sets the size of this GLDrawable. */ + public void setSize(int width, int height); + + /** Sets the size of this GLDrawable. */ + public void setSize(Dimension d); + + /** Returns the size of this GLDrawable as a newly-created Dimension + object. */ + public Dimension getSize(); + + /** Stores the size of this GLDrawable into the user-provided + Dimension object, returning that object. If the provided + Dimension is null a new one will be allocated and returned. */ + public Dimension getSize(Dimension d); + + /** Returns the {@link GL} pipeline object this GLDrawable uses. */ + public GL getGL(); + + /** Sets the {@link GL} pipeline object this GLDrawable uses. */ + 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. */ + public void display(); + + /** <P> Changes this GLDrawable to allow OpenGL rendering only from + the supplied thread, which must either be the current thread or + null. Attempts by other threads to perform OpenGL operations + like rendering or resizing the window will be ignored as long as + the thread is set. Setting up the rendering thread is not + required but enables the system to perform additional + optimizations, in particular when the application requires + control over the rendering loop. Before exiting, + <code>setRenderingThread(null)</code> must be called or other + threads will be unable to perform OpenGL rendering to this + drawable. Throws {@link GLException} if the rendering thread for + this drawable has been set and attempts are made to set or clear + the rendering thread from another thread, or if the passed + thread is not equal to the current thread or null. </P> + + <P> <B>NOTE:</B> Currently this routine is only advisory, which + means that on some platforms the underlying optimizations are + disabled and setting the rendering thread has no effect. + Applications should not rely on setRenderingThread to prevent + rendering from other threads. <P> + + @throws GLException if the rendering thread for this drawable has + been set by another thread or if the passed thread is not equal + to the current thread or null + */ + public void setRenderingThread(Thread currentThreadOrNull) throws GLException; + + /** Returns the rendering thread for this drawable, or null if none + has been set. */ + public Thread getRenderingThread(); + + /** Disables automatic redraws of this drawable if possible. This is + provided as an overriding mechanism for applications which + perform animation on the drawable and for which the (currently + advisory) {@link #setRenderingThread} does not provide strict + enough guarantees. Its sole purpose is to avoid deadlocks that + are unfortunately all too easy to run into when both animating a + drawable from a given thread as well as having updates performed + by the AWT event thread (repaints, etc.). When it is enabled, + repaint requests driven by the AWT will not result in the OpenGL + event listeners' display methods being called from the AWT + thread, unless (as with GLJPanel) this is the only mechanism by + which repaints are done. The necessity of this API may be + rethought in a future release. Defaults to false. */ + public void setNoAutoRedrawMode(boolean noAutoRedraws); + + /** Returns whether automatic redraws are disabled for this + drawable. Defaults to false. */ + public boolean getNoAutoRedrawMode(); + + /** Indicates whether this drawable is capable of fabricating a + subordinate offscreen drawable for advanced rendering techniques + which require offscreen hardware-accelerated surfaces. */ + 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/GLDrawableFactory.java b/src/net/java/games/jogl/GLDrawableFactory.java new file mode 100644 index 000000000..17d5779df --- /dev/null +++ b/src/net/java/games/jogl/GLDrawableFactory.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package net.java.games.jogl; + +/** <P> Provides a virtual machine- and operating system-independent + mechanism for creating {@link net.java.games.jogl.GLCanvas} and {@link + net.java.games.jogl.GLJPanel} objects. </P> + + <P> The {@link net.java.games.jogl.GLCapabilities} objects passed in to the + various factory methods are used as a hint for the properties of + the returned drawable. The default capabilities selection + algorithm (equivalent to passing in a null {@link + GLCapabilitiesChooser}) is described in {@link + DefaultGLCapabilitiesChooser}. Sophisticated applications needing + to change the selection algorithm may pass in their own {@link + GLCapabilitiesChooser} which can select from the available pixel + formats. </P> + + <P> Because of the multithreaded nature of the Java platform's + window system toolkit, it is typically not possible to immediately + reject a given {@link GLCapabilities} as being unsupportable by + either returning <code>null</code> from the creation routines or + raising a {@link GLException}. The semantics of the rejection + process are (unfortunately) left unspecified for now. The current + implementation will cause a {@link GLException} to be raised + during the first repaint of the {@link GLCanvas} or {@link + GLJPanel} if the capabilities can not be met. </P> +*/ + +public class GLDrawableFactory { + private static GLDrawableFactory factory = new GLDrawableFactory(); + + private GLDrawableFactory() {} + + /** Returns the sole GLDrawableFactory instance. */ + public static GLDrawableFactory getFactory() { + return factory; + } + + /** Creates a {@link GLCanvas} with the specified capabilities using + the default capabilities selection algorithm. */ + public GLCanvas createGLCanvas(GLCapabilities capabilities) { + return createGLCanvas(capabilities, null); + } + + /** Creates a {@link GLCanvas} with the specified capabilities using + the supplied capabilities selection algorithm. A null chooser is + equivalent to using the {@link DefaultGLCapabilitiesChooser}. */ + public GLCanvas createGLCanvas(GLCapabilities capabilities, GLCapabilitiesChooser chooser) { + // FIXME: do we need to select a GraphicsConfiguration here as in + // GL4Java? If so, this class will have to be made abstract and + // we'll have to provide hooks into this package to get at the + // GLCanvas and GLJPanel constructors. + if (chooser == null) { + chooser = new DefaultGLCapabilitiesChooser(); + } + return new GLCanvas(capabilities, chooser); + } + + /** Creates a {@link GLJPanel} with the specified capabilities using + the default capabilities selection algorithm. */ + public GLJPanel createGLJPanel(GLCapabilities capabilities) { + return createGLJPanel(capabilities, null); + } + + /** Creates a {@link GLJPanel} with the specified capabilities using + the supplied capabilities selection algorithm. A null chooser is + equivalent to using the {@link DefaultGLCapabilitiesChooser}. */ + public GLJPanel createGLJPanel(GLCapabilities capabilities, GLCapabilitiesChooser chooser) { + if (chooser == null) { + chooser = new DefaultGLCapabilitiesChooser(); + } + return new GLJPanel(capabilities, chooser); + } +} diff --git a/src/net/java/games/jogl/GLEventListener.java b/src/net/java/games/jogl/GLEventListener.java new file mode 100644 index 000000000..8a768af87 --- /dev/null +++ b/src/net/java/games/jogl/GLEventListener.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package net.java.games.jogl; + +import java.util.EventListener; + +/** Declares events which client code can use to manage OpenGL + rendering into a {@link GLDrawable}. At the time any of these + methods is called, the drawable has made its associated OpenGL + context current, so it is valid to make OpenGL calls. */ + +public interface GLEventListener extends EventListener { + /** Called by the drawable immediately after the OpenGL context is + initialized for the first time. Can be used to perform one-time + OpenGL initialization such as setup of lights and display lists. + */ + public void init(GLDrawable drawable); + + /** Called by the drawable to initiate OpenGL rendering by the + client. After all GLEventListeners have been notified of a + display event, the drawable will swap its buffers if necessary. + */ + public void display(GLDrawable drawable); + + /** Called by the drawable during the first repaint after the + component has been resized. The client can update the viewport + and view volume of the window appropriately, for example by a + call to {@link net.java.games.jogl.GL#glViewport}; note that for + convenience the component has already called {@link + net.java.games.jogl.GL#glViewport}(x, y, width, height) when this method + is called, so the client may not have to do anything in this + method. + */ + public void reshape(GLDrawable drawable, int x, int y, int width, int height); + + /** Called by the drawable when the display mode or the display device + associated with the GLDrawable has changed. The two boolean parameters + indicate the types of change(s) that have occurred. (<b> !!! CURRENTLY + UNIMPLEMENTED !!! </b>) + <P> + + An example of a display <i>mode</i> change is when the bit depth changes (e.g., + from 32-bit to 16-bit color) on monitor upon which the GLDrawable is + currently being displayed. <p> + + An example of a display <i>device</i> change is when the user drags the + window containing the GLDrawable from one monitor to another in a + multiple-monitor setup. <p> + + The reason that this function handles both types of changes (instead of + handling mode and device changes in separate methods) is so that + applications have the opportunity to respond to display changes the most + efficient manner. For example, the application may need make fewer + adjustments to compensate for a device change if it knows that the mode + on the new device is identical the previous mode. + */ + public void displayChanged(GLDrawable drawable, boolean modeChanged, boolean deviceChanged); +} diff --git a/src/net/java/games/jogl/GLException.java b/src/net/java/games/jogl/GLException.java new file mode 100644 index 000000000..6e0d5965f --- /dev/null +++ b/src/net/java/games/jogl/GLException.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package net.java.games.jogl; + +/** A generic exception for OpenGL errors used throughout the binding + as a substitute for {@link RuntimeException}. */ + +public class GLException extends RuntimeException { + /** Constructs a GLException object. */ + public GLException() { + super(); + } + + /** Constructs a GLException object with the specified detail + message. */ + public GLException(String message) { + super(message); + } + + /** Constructs a GLException object with the specified detail + message and root cause. */ + public GLException(String message, Throwable cause) { + super(message, cause); + } + + /** Constructs a GLException object with the specified root + cause. */ + public GLException(Throwable cause) { + super(cause); + } +} diff --git a/src/net/java/games/jogl/GLJPanel.java b/src/net/java/games/jogl/GLJPanel.java new file mode 100644 index 000000000..787a4a8cc --- /dev/null +++ b/src/net/java/games/jogl/GLJPanel.java @@ -0,0 +1,316 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package net.java.games.jogl; + +import java.awt.Component; +import java.awt.Graphics; +import java.awt.GraphicsConfiguration; +import java.awt.Rectangle; +import java.awt.image.BufferedImage; +import java.awt.image.DataBufferByte; +import java.awt.image.DataBufferInt; +import javax.swing.JComponent; +import javax.swing.JPanel; +import net.java.games.jogl.impl.*; + +// FIXME: Subclasses need to call resetGLFunctionAvailability() on their +// context whenever the displayChanged() function is called on their +// GLEventListeners + +/** A lightweight Swing component which provides OpenGL rendering + support. Provided for compatibility with Swing user interfaces + when adding a heavyweight doesn't work either because of + Z-ordering or LayoutManager problems. Currently implemented using + offscreen (i.e., non-hardware accelerated) rendering, so + performance will likely be poor. This class can not be + instantiated directly; use {@link GLDrawableFactory} to construct + them. */ + +public final class GLJPanel extends JPanel implements GLDrawable { + private GLCapabilities capabilities; + private GLCapabilitiesChooser chooser; + private GLDrawableHelper drawableHelper = new GLDrawableHelper(); + private GLContext context; + private BufferedImage offscreenImage; + private int awtFormat; + private int glFormat; + private int glType; + private int glComps; + private DataBufferByte dbByte; + private DataBufferInt dbInt; + private Object semaphore = new Object(); + private boolean repaintDone; + + // For saving/restoring of OpenGL state during ReadPixels + private int[] swapbytes = new int[1]; + private int[] lsbfirst = new int[1]; + private int[] rowlength = new int[1]; + private int[] skiprows = new int[1]; + private int[] skippixels = new int[1]; + private int[] alignment = new int[1]; + + GLJPanel(GLCapabilities capabilities, GLCapabilitiesChooser chooser) { + super(); + this.capabilities = capabilities; + this.chooser = chooser; + } + + public void display() { + // Multithreaded redrawing of Swing components is not allowed + try { + synchronized(semaphore) { + repaintDone = false; + repaint(); + while (!repaintDone) { + semaphore.wait(); + } + } + } catch (InterruptedException e) { + } + } + + /** Overridden from JComponent; calls {@link #display}. Should not + be invoked by applications directly. */ + public void paintComponent(Graphics g) { + displayAction.setGraphics(g); + getContext().invokeGL(displayAction, false, initAction); + synchronized(semaphore) { + repaintDone = true; + semaphore.notifyAll(); + } + } + + /** Overridden from Canvas; causes {@link GLDrawableHelper#reshape} + to be called on all registered {@link GLEventListener}s. Called + automatically by the AWT; should not be invoked by applications + directly. */ + public void reshape(int x, int y, int width, int height) { + super.reshape(x, y, width, height); + // NOTE: we don't pay attention to the x and y provided since we + // are blitting into this component directly + final int fx = 0; + final int fy = 0; + final int fwidth = width; + final int fheight = height; + getContext().resizeOffscreenContext(width, height); + getContext().invokeGL(new Runnable() { + public void run() { + getGL().glViewport(fx, fy, fwidth, fheight); + drawableHelper.reshape(GLJPanel.this, fx, fy, fwidth, fheight); + if (offscreenImage != null && + (offscreenImage.getWidth() != getWidth() || + offscreenImage.getHeight() != getHeight())) { + offscreenImage.flush(); + offscreenImage = null; + } + } + }, true, initAction); + } + + public void addGLEventListener(GLEventListener listener) { + drawableHelper.addGLEventListener(listener); + } + + public void removeGLEventListener(GLEventListener listener) { + drawableHelper.removeGLEventListener(listener); + } + + public GL getGL() { + // must use getContext() because context is created lazily + return getContext().getGL(); + } + + public void setGL(GL gl) { + // must use getContext() because context is created lazily + getContext().setGL(gl); + } + + public GLU getGLU() { + // must use getContext() because context is created lazily + return getContext().getGLU(); + } + + public void setGLU(GLU glu) { + // must use getContext() because context is created lazily + getContext().setGLU(glu); + } + + public void setRenderingThread(Thread currentThreadOrNull) throws GLException { + // Not supported for GLJPanel because all repaint requests must be + // handled by the AWT thread + } + + public Thread getRenderingThread() { + return getContext().getRenderingThread(); + } + + public void setNoAutoRedrawMode(boolean noAutoRedraws) { + } + + public boolean getNoAutoRedrawMode() { + return false; + } + + public boolean canCreateOffscreenDrawable() { + // For now let's say no; maybe we can reimplement this class in + // terms of pbuffers (though not all vendors support them, and + // they seem to require an onscreen context) + return false; + } + + public GLPbuffer createOffscreenDrawable(GLCapabilities capabilities, + int initialWidth, + int initialHeight) { + throw new GLException("Not supported"); + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + private GLContext getContext() { + if (context == null) { + context = GLContextFactory.getFactory().createGLContext(null, capabilities, chooser); + } + return context; + } + + class InitAction implements Runnable { + public void run() { + drawableHelper.init(GLJPanel.this); + } + } + private InitAction initAction = new InitAction(); + + class DisplayAction implements Runnable { + private Graphics g; + + public void setGraphics(Graphics g) { + this.g = g; + } + + public void run() { + drawableHelper.display(GLJPanel.this); + // Must now copy pixels from offscreen context into surface + if (offscreenImage == null) { + int awtFormat = getContext().getOffscreenContextBufferedImageType(); + offscreenImage = new BufferedImage(getWidth(), getHeight(), awtFormat); + switch (awtFormat) { + case BufferedImage.TYPE_3BYTE_BGR: + glFormat = GL.GL_BGR; + glType = GL.GL_UNSIGNED_BYTE; + glComps = 3; + dbByte = (DataBufferByte) offscreenImage.getRaster().getDataBuffer(); + break; + + case BufferedImage.TYPE_INT_RGB: + glFormat = GL.GL_BGRA; + glType = GL.GL_UNSIGNED_BYTE; + glComps = 4; + dbInt = (DataBufferInt) offscreenImage.getRaster().getDataBuffer(); + break; + + case BufferedImage.TYPE_INT_ARGB: + glFormat = GL.GL_BGRA; + glType = GL.GL_UNSIGNED_BYTE; + glComps = 4; + dbInt = (DataBufferInt) offscreenImage.getRaster().getDataBuffer(); + break; + + default: + // FIXME: Support more off-screen image types (current + // offscreen context implementations don't use others, and + // some of the OpenGL formats aren't supported in the 1.1 + // headers, which we're currently using) + throw new GLException("Unsupported offscreen image type " + awtFormat); + } + } + + GL gl = getGL(); + // Save current modes + gl.glGetIntegerv(GL.GL_PACK_SWAP_BYTES, swapbytes); + gl.glGetIntegerv(GL.GL_PACK_LSB_FIRST, lsbfirst); + gl.glGetIntegerv(GL.GL_PACK_ROW_LENGTH, rowlength); + gl.glGetIntegerv(GL.GL_PACK_SKIP_ROWS, skiprows); + gl.glGetIntegerv(GL.GL_PACK_SKIP_PIXELS, skippixels); + gl.glGetIntegerv(GL.GL_PACK_ALIGNMENT, alignment); + + // Little endian machines (DEC Alpha, Intel X86, PPC (in LSB + // mode)... for example) could benefit from setting + // GL_PACK_LSB_FIRST to GL_TRUE instead of GL_FALSE, but this + // would require changing the generated bitmaps too. + gl.glPixelStorei(GL.GL_PACK_SWAP_BYTES, GL.GL_FALSE); + gl.glPixelStorei(GL.GL_PACK_LSB_FIRST, GL.GL_TRUE); + gl.glPixelStorei(GL.GL_PACK_ROW_LENGTH, getWidth()); + gl.glPixelStorei(GL.GL_PACK_SKIP_ROWS, 0); + gl.glPixelStorei(GL.GL_PACK_SKIP_PIXELS, 0); + gl.glPixelStorei(GL.GL_PACK_ALIGNMENT, 1); + + // Actually read the pixels. + gl.glReadBuffer(context.getOffscreenContextReadBuffer()); + if (dbByte != null) { + gl.glReadPixels(0, 0, getWidth(), getHeight(), glFormat, glType, dbByte.getData()); + } else if (dbInt != null) { + gl.glReadPixels(0, 0, getWidth(), getHeight(), glFormat, glType, dbInt.getData()); + } + + // Restore saved modes. + gl.glPixelStorei(GL.GL_PACK_SWAP_BYTES, swapbytes[0]); + gl.glPixelStorei(GL.GL_PACK_LSB_FIRST, lsbfirst[0]); + gl.glPixelStorei(GL.GL_PACK_ROW_LENGTH, rowlength[0]); + gl.glPixelStorei(GL.GL_PACK_SKIP_ROWS, skiprows[0]); + gl.glPixelStorei(GL.GL_PACK_SKIP_PIXELS, skippixels[0]); + gl.glPixelStorei(GL.GL_PACK_ALIGNMENT, alignment[0]); + + gl.glFlush(); + gl.glFinish(); + + if (context.offscreenImageNeedsVerticalFlip()) { + g.drawImage(offscreenImage, + 0, 0, getWidth(), getHeight(), + 0, getHeight(), getWidth(), 0, + GLJPanel.this); + } else { + g.drawImage(offscreenImage, 0, 0, getWidth(), getHeight(), GLJPanel.this); + } + } + } + private DisplayAction displayAction = new DisplayAction(); +} diff --git a/src/net/java/games/jogl/GLPbuffer.java b/src/net/java/games/jogl/GLPbuffer.java new file mode 100644 index 000000000..de85f6950 --- /dev/null +++ b/src/net/java/games/jogl/GLPbuffer.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package net.java.games.jogl; + +/** Offscreen rendering support via pbuffers. This class adds very + little functionality over the GLDrawable class; the only methods + are those which allow access to the pbuffer's contents as a + texture map. These methods are currently highly experimental and + may be removed in a future release. */ + +public interface GLPbuffer extends GLDrawable { + /** Binds this pbuffer to its internal texture target. Only valid to + call if offscreen render-to-texture has been specified in the + GLCapabilities for this GLPbuffer. If the + render-to-texture-rectangle capability has also been specified, + this will use e.g. wglBindTexImageARB as its implementation and + cause the texture to be bound to e.g. the + GL_TEXTURE_RECTANGLE_NV state; otherwise, during the display() + phase the pixels will have been copied into an internal texture + target and this will cause that to be bound to the GL_TEXTURE_2D + state. */ + public void bindTexture(); + + /** Unbinds the pbuffer from its internal texture target. */ + public void releaseTexture(); +} diff --git a/src/net/java/games/jogl/impl/FunctionAvailabilityCache.java b/src/net/java/games/jogl/impl/FunctionAvailabilityCache.java new file mode 100644 index 000000000..74a3e888d --- /dev/null +++ b/src/net/java/games/jogl/impl/FunctionAvailabilityCache.java @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package net.java.games.jogl.impl; + +import net.java.games.jogl.*; +import java.util.*; +import java.awt.Canvas; +import java.awt.Graphics; +import java.awt.GraphicsConfiguration; +import java.lang.reflect.*; + +/** + * A utility object intended to be used by implementations to act as a cache + * of which OpenGL functions are currently available on both the host machine + * and display. + */ +public final class FunctionAvailabilityCache { + + FunctionAvailabilityCache(GLContext context) + { + this.context = context; + } + + /** + * Flush the cache. The cache will be rebuilt lazily as calls to {@link + * #isFunctionAvailable(String)} are received. + */ + public void flush() + { + availabilityCache.clear(); + availableExtensionCache.clear(); + } + + public boolean isFunctionAvailable(String glFunctionName) + { + //System.err.println("!!! CHECKING FOR AVAILABILITY OF: "+glFunctionName); + + Boolean available = (Boolean)availabilityCache.get(glFunctionName); + + if (available == null) // not in availabilityCache + { + if (isPartOfAvailableExtensions(glFunctionName) || + isPartOfGLCore(context.getGL().glGetString(GL.GL_VERSION), glFunctionName)) + { + available = Boolean.TRUE; + } + else + { + available = Boolean.FALSE; + } + + availabilityCache.put(glFunctionName, available); + } + + return available.booleanValue(); + } + + public boolean isExtensionAvailable(String glExtensionName) { + initAvailableExtensions(); + return availableExtensionCache.contains(glExtensionName); + } + + protected void initAvailableExtensions() { + // if hash is empty (meaning it was flushed), pre-cache it with the list + // of extensions that are in the GL_EXTENSIONS string + if (availableExtensionCache.isEmpty()) { + GL gl = context.getGL(); + //System.err.println("!!! Pre-caching extension availability"); + String allAvailableExtensions = + gl.glGetString(GL.GL_EXTENSIONS) + " " + context.getPlatformExtensionsString(); + StringTokenizer tok = new StringTokenizer(allAvailableExtensions); + while (tok.hasMoreTokens()) { + String availableExt = tok.nextToken().trim(); + availableExt = availableExt.intern(); + availableExtensionCache.add(availableExt); + //System.err.println("!!! Available: " + availableExt); + } + + // put a dummy var in here so that the cache is no longer empty even if + // no extensions are in the GL_EXTENSIONS string + availableExtensionCache.add("<INTERNAL_DUMMY_PLACEHOLDER>"); + } + } + + protected boolean isPartOfAvailableExtensions(String glFunctionName) + { + initAvailableExtensions(); + + // First, find the extension to which the function corresponds + String extensionName = getExtensionCorrespondingToFunction(glFunctionName); + + // Now see if that extension is available + boolean extensionAvailable = availableExtensionCache.contains(extensionName); + + return extensionAvailable; + } + + /** + * Returns true if the given OpenGL function is part of the OpenGL core + * that corresponds to the give OpenGL version string. + * + * @param versionString must be of the form "X" or "X.Y" or "X.Y.Z", where + * X, Y, and Z are integers + @ @exception GLException if the glFunctionName passed in is + * not the name of any known OpenGL extension function. + */ + public static boolean isPartOfGLCore(String glVersionString, String glFunctionName) + { + String funcCoreVersionString = + StaticGLInfo.getFunctionAssociation(glFunctionName); + + if (funcCoreVersionString == null) { + // No extension string was found in the glext.h/wglext.h/glxext.h + // headers when building the StaticGLInfo class. So either it's a new + // extension that's not in those headers, or it's not an opengl + // extension. Either way it's an illegal argument. + throw new GLException( + "Function \"" + glFunctionName + "\" does not " + + "correspond to any known OpenGL extension or core version."); + } + + Version actualVersion; + try + { + actualVersion = new Version(funcCoreVersionString); + } + catch (IllegalArgumentException e) + { + // funcCoreVersionString is not an OpenGL version identifier (i.e., not + // of the form GL_VERSION_XXX). + // + // Since the association string returned from + // StaticGLInfo.getFunctionAssociation() was not null, this function + // must be an OpenGL extension function. + // + // Therefore this function can't be part of any OpenGL core. + return false; + } + + Version versionToCheck; + try + { + versionToCheck = new Version(glVersionString); + } + catch (IllegalArgumentException e) + { + // user did not supply a valid OpenGL version identifier + throw new IllegalArgumentException( + "Illegally formatted OpenGL version identifier: \"" + glVersionString + "\""); + } + + // See if the version number of glVersionString is less than or equal to + // the OpenGL specification number to which the given function actually + // belongs. + if (actualVersion.compareTo(versionToCheck) <= 0) + { + System.err.println( + glFunctionName + " is in core OpenGL " + glVersionString + + " because it is in OpenGL " + funcCoreVersionString); + return true; + } + + System.err.println( + glFunctionName + " is NOT a part of the OpenGL " + glVersionString + " core" + + "; it is part of OpenGL " + funcCoreVersionString); + + return false; + } + + /** Returns the extension name that corresponds to the given extension + * function. For example, it will return "GL_EXT_vertex_array" when the + * argument is "glNormalPointerEXT". + * + * Please see http://oss.sgi.com/projects/ogl-sample/registry/index.html for + * a list of extension names and the functions they expose. + */ + protected static String getExtensionCorrespondingToFunction(String glFunctionName) + { + // HACK: FIXME!!! return something I know is supported so I can test other + // functions. + return StaticGLInfo.getFunctionAssociation(glFunctionName); + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + private HashMap availabilityCache = new HashMap(50); + private HashSet availableExtensionCache = new HashSet(50); + private GLContext context; + + /** + * A class for storing and comparing revision version numbers. + */ + private static class Version implements Comparable + { + private int major, minor, sub; + public Version(int majorRev, int minorRev, int subMinorRev) + { + major = majorRev; + minor = minorRev; + sub = subMinorRev; + } + + /** + * @param versionString must be of the form "GL_VERSION_X" or + * "GL_VERSION_X_Y" or "GL_VERSION_X_Y_Z", where X, Y, and Z are integers. + * + * @exception IllegalArgumentException if the argument is not a valid + * OpenGL version identifier + */ + public Version(String versionString) + { + if (! versionString.startsWith("GL_VERSION_")) + { + // not a version string + throw new IllegalArgumentException( + "Illegal version identifier \"" + versionString + + "\"; does not start with \"GL_VERSION_\""); + } + + try + { + StringTokenizer tok = new StringTokenizer(versionString, "_"); + + tok.nextToken(); // GL_ + tok.nextToken(); // VERSION_ + if (!tok.hasMoreTokens()) { major = 0; return; } + major = Integer.valueOf(tok.nextToken()).intValue(); + if (!tok.hasMoreTokens()) { minor = 0; return; } + minor = Integer.valueOf(tok.nextToken()).intValue(); + if (!tok.hasMoreTokens()) { sub = 0; return; } + sub = Integer.valueOf(tok.nextToken()).intValue(); + } + catch (Exception e) + { + throw new IllegalArgumentException( + "Illegally formatted version identifier: \"" + versionString + "\""); + } + } + + public int compareTo(Object o) + { + Version vo = (Version)o; + if (major > vo.major) return 1; + else if (major < vo.major) return -1; + else if (minor > vo.minor) return 1; + else if (minor < vo.minor) return -1; + else if (sub > vo.sub) return 1; + else if (sub < vo.sub) return -1; + + return 0; // they are equal + } + + } // end class Version +} + diff --git a/src/net/java/games/jogl/impl/GLContext.java b/src/net/java/games/jogl/impl/GLContext.java new file mode 100644 index 000000000..98b1c6065 --- /dev/null +++ b/src/net/java/games/jogl/impl/GLContext.java @@ -0,0 +1,400 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package net.java.games.jogl.impl; + +import java.awt.Component; +import java.awt.EventQueue; +import net.java.games.jogl.*; + +public abstract class GLContext { + protected static final boolean DEBUG = false; + + static { + NativeLibLoader.load(); + } + + protected Component component; + + // Indicates whether the component (if an onscreen context) has been + // realized. Plausibly, before the component is realized the JAWT + // should return an error or NULL object from some of its + // operations; this appears to be the case on Win32 but is not true + // at least with Sun's current X11 implementation (1.4.x), which + // crashes with no other error reported if the DrawingSurfaceInfo is + // fetched from a locked DrawingSurface during the validation as a + // result of calling show() on the main thread. To work around this + // we prevent any JAWT or OpenGL operations from being done until + // the first event is received from the AWT event dispatch thread. + private boolean realized; + + // This avoids (as much as possible) losing the effects of + // setRenderingThread, which may need to be deferred if the + // component is not realized + private boolean deferredSetRenderingThread; + + protected GLCapabilities capabilities; + protected GLCapabilitiesChooser chooser; + protected GL gl; + // All GLU interfaces eventually route calls down to gluRoot. It can be + // static because GLU it doesn't actually need to own context, it just makes + // GL calls and assumes some context is active. + protected static final GLU gluRoot = new GLUImpl(); + protected static GLU glu = gluRoot; // this is the context's GLU interface + protected Thread renderingThread; + protected Runnable deferredReshapeAction; + + // This is a workaround for a bug in NVidia's drivers where + // vertex_array_range is only safe for single-threaded use; a bug + // has been filed, ID 80174. When an Animator is created for a + // GLDrawable, the expectation is that the Animator will be started + // shortly and that the user doesn't want rendering to occur from + // the AWT thread. However, there is a small window between when the + // Animator is created and attached to the GLDrawable and when it's + // started (and sets the rendering thread) when repaint events can + // be issued by the AWT thread if the component is realized. To work + // around this problem, we currently specify in the Animator's API + // that between the time it's created and started no redraws will + // occur. + protected volatile boolean willSetRenderingThread; + + // Flag for disabling all repaint and resize processing on the AWT + // thread to avoid application-level deadlocks; only really used for + // GLCanvas + protected boolean noAutoRedraw; + + // Offscreen context handling. Offscreen contexts should handle + // these resize requests in makeCurrent and clear the + // pendingOffscreenResize flag. + protected boolean pendingOffscreenResize; + protected int pendingOffscreenWidth; + protected int pendingOffscreenHeight; + + // Cache of the functions that are available to be called at the current + // moment in time + protected FunctionAvailabilityCache functionAvailability; + + public GLContext(Component component, GLCapabilities capabilities, GLCapabilitiesChooser chooser) { + this.component = component; + try { + this.capabilities = (GLCapabilities) capabilities.clone(); + } catch (CloneNotSupportedException e) { + throw new GLException(e); + } + this.chooser = chooser; + gl = createGL(); + functionAvailability = new FunctionAvailabilityCache(this); + } + + /** Runs the given runnable with this OpenGL context valid. */ + public synchronized void invokeGL(Runnable runnable, boolean isReshape, Runnable initAction) throws GLException { + Thread currentThread = null; + + // Defer JAWT and OpenGL operations until onscreen components are + // realized + if (!realized()) { + realized = EventQueue.isDispatchThread(); + } + + if (!realized() || + willSetRenderingThread || + (renderingThread != null && + renderingThread != (currentThread = Thread.currentThread()))) { + if (isReshape) { + deferredReshapeAction = runnable; + } + return; + } + + if (isReshape && noAutoRedraw) { + // Don't process reshape requests on the AWT thread + deferredReshapeAction = runnable; + return; + } + + if (renderingThread == null || deferredSetRenderingThread) { + deferredSetRenderingThread = false; + if (!makeCurrent(initAction)) { + // Couldn't make the thread current because the component has not yet + // been visualized, and therefore the context cannot be created. + // We'll defer any actions until invokeGL() is called again at a time + // when the component has been visualized. + if (isReshape) { + deferredReshapeAction = runnable; + } + return; + } + } + + // At this point the OpenGL context is current. Offscreen contexts + // handle resizing the backing bitmap in makeCurrent. Therefore we + // may need to free and make the context current again if we + // didn't actually make it current above. + if (pendingOffscreenResize && renderingThread != null) { + free(); + if (!makeCurrent(initAction)) { + throw new GLException("Error while resizing offscreen context"); + } + } + + boolean caughtException = false; + + try { + if (deferredReshapeAction != null) { + deferredReshapeAction.run(); + deferredReshapeAction = null; + } + runnable.run(); + swapBuffers(); + } catch (RuntimeException e) { + caughtException = true; + throw(e); + } finally { + if (caughtException) { + // Disallow setRenderingThread if display action is throwing exceptions + renderingThread = null; + } + if (renderingThread == null) { + free(); + } + } + } + + public GL getGL() { + return gl; + } + + public void setGL(GL gl) { + this.gl = gl; + } + + public GLU getGLU() { + return glu; + } + + public void setGLU(GLU glu) { + this.glu = glu; + } + + /** Gives a hint to the context that setRenderingThread will be + called in the near future; causes redraws to be halted. This is + a workaround for bugs in NVidia's drivers and is used only by + the Animator class. */ + public synchronized void willSetRenderingThread() { + this.willSetRenderingThread = true; + } + + public synchronized void setRenderingThread(Thread currentThreadOrNull, Runnable initAction) { + Thread currentThread = Thread.currentThread(); + if (currentThreadOrNull != null && currentThreadOrNull != currentThread) { + throw new GLException("Argument must be either the current thread or null"); + } + if (renderingThread != null && currentThreadOrNull != null) { + throw new GLException("Attempt to re-set or change rendering thread"); + } + if (renderingThread == null && currentThreadOrNull == null) { + throw new GLException("Attempt to clear rendering thread when already cleared"); + } + this.willSetRenderingThread = false; + if (currentThreadOrNull == null) { + renderingThread = null; + if (realized()) { + // We are guaranteed to own the context + free(); + } + } else { + renderingThread = currentThreadOrNull; + if (realized()) { + makeCurrent(initAction); + } + } + } + + public Thread getRenderingThread() { + return renderingThread; + } + + public void setNoAutoRedrawMode(boolean noAutoRedraw) { + this.noAutoRedraw = noAutoRedraw; + } + + public boolean getNoAutoRedrawMode() { + return noAutoRedraw; + } + + /** 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; + } + + /** Returns a non-null (but possibly empty) string containing the + space-separated list of available platform-dependent (e.g., WGL, + GLX) extensions. Can only be called while this context is + current. */ + public abstract String getPlatformExtensionsString(); + + /** + * Resets the cache of which GL functions are available for calling through this + * context. See {@link #isFunctionAvailable(String)} for more information on + * the definition of "available". + */ + protected void resetGLFunctionAvailability() { + functionAvailability.flush(); + } + + /** + * Returns true if the specified OpenGL core- or extension-function can be + * successfully called using this GL context given the current host (OpenGL + * <i>client</i>) and display (OpenGL <i>server</i>) configuration. + * + * See {@link GL#isFunctionAvailable(String)} for more details. + * + * @param glFunctionName the name of the OpenGL function (e.g., use + * "glPolygonOffsetEXT" to check if the {@link + * net.java.games.jogl.glPolygonOffsetEXT(float,float)} is available). + */ + protected boolean isFunctionAvailable(String glFunctionName) { + return functionAvailability.isFunctionAvailable(mapToRealGLFunctionName(glFunctionName)); + } + + /** + * Returns true if the specified OpenGL extension can be + * successfully called using this GL context given the current host (OpenGL + * <i>client</i>) and display (OpenGL <i>server</i>) configuration. + * + * See {@link GL#isExtensionAvailable(String)} for more details. + * + * @param glExtensionName the name of the OpenGL extension (e.g., + * "GL_VERTEX_PROGRAM_ARB"). + */ + public boolean isExtensionAvailable(String glExtensionName) { + return functionAvailability.isExtensionAvailable(mapToRealGLExtensionName(glExtensionName)); + } + + /** + * Pbuffer support; indicates whether this context is capable of + * creating a subordinate pbuffer context (distinct from an + * "offscreen context", which is typically software-rendered on all + * platforms). + */ + public abstract boolean canCreatePbufferContext(); + + /** + * Pbuffer support; creates a subordinate GLContext for a pbuffer + * associated with this context. + */ + public abstract GLContext createPbufferContext(GLCapabilities capabilities, + int initialWidth, + int initialHeight); + + /** + * Pbuffer support; given that this is a GLContext associated with a + * pbuffer, binds this pbuffer to its texture target. + */ + public abstract void bindPbufferToTexture(); + + /** + * Pbuffer support; given that this is a GLContext associated with a + * pbuffer, releases this pbuffer from its texture target. + */ + public abstract void releasePbufferFromTexture(); + + /** Maps the given "platform-independent" function name to a real function + name. Currently this is only used to map "glAllocateMemoryNV" and + associated routines to wglAllocateMemoryNV / glXAllocateMemoryNV. */ + protected abstract String mapToRealGLFunctionName(String glFunctionName); + + /** Maps the given "platform-independent" extension name to a real + function name. Currently this is only used to map + "GL_ARB_pbuffer" and "GL_ARB_pixel_format" to "WGL_ARB_pbuffer" + and "WGL_ARB_pixel_format" (not yet mapped to X11). */ + protected abstract String mapToRealGLExtensionName(String glExtensionName); + + /** Create the GL for this context. */ + protected abstract GL createGL(); + + /** Hook indicating whether the concrete GLContext implementation is + offscreen and therefore whether we need to process resize + requests. */ + protected abstract boolean isOffscreen(); + + /** Only called for offscreen contexts; returns the type of + BufferedImage required for reading this context's pixels. */ + public abstract int getOffscreenContextBufferedImageType(); + + /** Only called for offscreen contexts; returns the buffer from + which to read pixels (GL.GL_FRONT or GL.GL_BACK). */ + public abstract int getOffscreenContextReadBuffer(); + + /** On some platforms the mismatch between OpenGL's coordinate + system (origin at bottom left) and the window system's + coordinate system (origin at top left) necessitates a vertical + flip of pixels read from offscreen contexts. */ + public abstract boolean offscreenImageNeedsVerticalFlip(); + + /** Attempts to make the GL context current. If necessary, creates a + context and calls the initAction once the context is current. + Most error conditions cause an exception to be thrown, except + for the case where the context can not be created because the + component has not yet been visualized. In this case makeCurrent + returns false and the caller should abort any OpenGL event + processing and instead return immediately. */ + protected abstract boolean makeCurrent(Runnable initAction) throws GLException; + + /** Frees the OpenGL context. All error conditions cause a + GLException to be thrown. */ + protected abstract void free() throws GLException; + + /** Swaps the buffers of the OpenGL context if necessary. All error + conditions cause a GLException to be thrown. */ + protected abstract void swapBuffers() throws GLException; + + //---------------------------------------------------------------------- + // Internals only below this point + // + private boolean realized() { + return ((component == null) || realized || component.isDisplayable()); + } +} diff --git a/src/net/java/games/jogl/impl/GLContextFactory.java b/src/net/java/games/jogl/impl/GLContextFactory.java new file mode 100644 index 000000000..d76648ee8 --- /dev/null +++ b/src/net/java/games/jogl/impl/GLContextFactory.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package net.java.games.jogl.impl; + +import java.awt.Component; +import net.java.games.jogl.*; + +public abstract class GLContextFactory { + private static GLContextFactory factory; + + public static GLContextFactory getFactory() { + if (factory == null) { + try { + String osName = System.getProperty("os.name"); + String osNameLowerCase = osName.toLowerCase(); + Class factoryClass = null; + + // Because there are some complications with generating all + // platforms' Java glue code on all platforms (among them that we + // would have to include jawt.h and jawt_md.h in the jogl + // sources, which we currently don't have to do) we break the only + // static dependencies with platform-specific code here using reflection. + + if (osNameLowerCase.startsWith("wind")) { + factoryClass = Class.forName("net.java.games.jogl.impl.windows.WindowsGLContextFactory"); + } else if (osNameLowerCase.startsWith("darwin")) { + } else { + // Assume Linux, Solaris, etc. Should probably test for these explicitly. + factoryClass = Class.forName("net.java.games.jogl.impl.x11.X11GLContextFactory"); + } + + if (factoryClass == null) { + throw new GLException("OS " + osName + " not yet supported"); + } + + factory = (GLContextFactory) factoryClass.newInstance(); + } catch (ClassNotFoundException e) { + throw new GLException(e); + } catch (InstantiationException e) { + throw new GLException(e); + } catch (IllegalAccessException e) { + throw new GLException(e); + } + } + + return factory; + } + + public abstract GLContext createGLContext(Component component, + GLCapabilities capabilities, + GLCapabilitiesChooser chooser); +} diff --git a/src/net/java/games/jogl/impl/GLDrawableHelper.java b/src/net/java/games/jogl/impl/GLDrawableHelper.java new file mode 100644 index 000000000..d9def672f --- /dev/null +++ b/src/net/java/games/jogl/impl/GLDrawableHelper.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package net.java.games.jogl.impl; + +import java.util.*; +import net.java.games.jogl.*; + +/** Encapsulates the implementation of most of the GLDrawable's + methods to be able to share it between GLCanvas and GLJPanel. */ + +public class GLDrawableHelper { + private List listeners = new ArrayList(); + private GL gl; + // FIXME + // private GLU glu; + + public GLDrawableHelper() { + } + + public void addGLEventListener(GLEventListener listener) { + listeners.add(listener); + } + + public void removeGLEventListener(GLEventListener listener) { + listeners.remove(listener); + } + + public void init(GLDrawable drawable) { + // Note that we don't use iterator() since listeners may + // add/remove other listeners during initialization. We don't + // guarantee that all listeners will be evaluated if + // removeGLEventListener is called. + for (int i = 0; i < listeners.size(); i++) { + ((GLEventListener) listeners.get(i)).init(drawable); + } + } + + public void display(GLDrawable drawable) { + for (int i = 0; i < listeners.size(); i++) { + ((GLEventListener) listeners.get(i)).display(drawable); + } + } + + public void reshape(GLDrawable drawable, + int x, int y, int width, int height) { + for (int i = 0; i < listeners.size(); i++) { + ((GLEventListener) listeners.get(i)).reshape(drawable, x, y, width, height); + } + } +} diff --git a/src/net/java/games/jogl/impl/GLPbufferImpl.java b/src/net/java/games/jogl/impl/GLPbufferImpl.java new file mode 100644 index 000000000..d510a9c31 --- /dev/null +++ b/src/net/java/games/jogl/impl/GLPbufferImpl.java @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package net.java.games.jogl.impl; + +import java.awt.Dimension; +import java.awt.event.*; +import java.beans.PropertyChangeListener; + +import net.java.games.jogl.*; + +/** Platform-independent class exposing pbuffer functionality to + applications. This class is not exposed in the public API as it + would probably add no value; however it implements the GLDrawable + interface so can be interacted with via its display() method. */ + +public class GLPbufferImpl implements GLPbuffer { + // GLPbufferContext + private GLContext context; + private GLDrawableHelper drawableHelper = new GLDrawableHelper(); + + public GLPbufferImpl(GLContext context) { + this.context = context; + } + + public void display() { + context.invokeGL(displayAction, false, initAction); + } + + public void setSize(int width, int height) { + // FIXME + throw new GLException("Not yet implemented"); + } + + public void setSize(Dimension d) { + setSize(d.width, d.height); + } + + public Dimension getSize() { + return getSize(null); + } + + public Dimension getSize(Dimension d) { + // FIXME + throw new GLException("Not yet implemented"); + } + + public void addGLEventListener(GLEventListener listener) { + drawableHelper.addGLEventListener(listener); + } + + public void removeGLEventListener(GLEventListener listener) { + drawableHelper.removeGLEventListener(listener); + } + + public GL getGL() { + return context.getGL(); + } + + public void setGL(GL gl) { + context.setGL(gl); + } + + public GLU getGLU() { + return context.getGLU(); + } + + public void setGLU(GLU glu) { + context.setGLU(glu); + } + + void willSetRenderingThread() { + context.willSetRenderingThread(); + } + + public void setRenderingThread(Thread currentThreadOrNull) throws GLException { + // Not supported for pbuffers + } + + public Thread getRenderingThread() { + // Not supported for pbuffers + return null; + } + + public void setNoAutoRedrawMode(boolean noAutoRedraws) { + } + + public boolean getNoAutoRedrawMode() { + return false; + } + + public boolean canCreateOffscreenDrawable() { + return false; + } + + public GLPbuffer createOffscreenDrawable(GLCapabilities capabilities, + int initialWidth, + int initialHeight) { + throw new GLException("Not supported"); + } + + public void bindTexture() { + context.bindPbufferToTexture(); + } + + public void releaseTexture() { + context.releasePbufferFromTexture(); + } + + //---------------------------------------------------------------------- + // No-ops for ComponentEvents + // + + public void addComponentListener(ComponentListener l) {} + public void removeComponentListener(ComponentListener l) {} + public void addFocusListener(FocusListener l) {} + public void removeFocusListener(FocusListener l) {} + public void addHierarchyBoundsListener(HierarchyBoundsListener l) {} + public void removeHierarchyBoundsListener(HierarchyBoundsListener l) {} + public void addHierarchyListener(HierarchyListener l) {} + public void removeHierarchyListener(HierarchyListener l) {} + public void addInputMethodListener(InputMethodListener l) {} + public void removeInputMethodListener(InputMethodListener l) {} + public void addKeyListener(KeyListener l) {} + public void removeKeyListener(KeyListener l) {} + public void addMouseListener(MouseListener l) {} + public void removeMouseListener(MouseListener l) {} + public void addMouseMotionListener(MouseMotionListener l) {} + public void removeMouseMotionListener(MouseMotionListener l) {} + public void addMouseWheelListener(MouseWheelListener l) {} + public void removeMouseWheelListener(MouseWheelListener l) {} + public void addPropertyChangeListener(PropertyChangeListener listener) {} + public void removePropertyChangeListener(PropertyChangeListener listener) {} + public void addPropertyChangeListener(String propertyName, + PropertyChangeListener listener) {} + public void removePropertyChangeListener(String propertyName, + PropertyChangeListener listener) {} + + //---------------------------------------------------------------------- + // Internals only below this point + // + + class InitAction implements Runnable { + public void run() { + drawableHelper.init(GLPbufferImpl.this); + } + } + private InitAction initAction = new InitAction(); + + class DisplayAction implements Runnable { + public void run() { + drawableHelper.display(GLPbufferImpl.this); + } + } + private DisplayAction displayAction = new DisplayAction(); +} diff --git a/src/net/java/games/jogl/impl/JAWT_PlatformInfo.java b/src/net/java/games/jogl/impl/JAWT_PlatformInfo.java new file mode 100644 index 000000000..64da83ec4 --- /dev/null +++ b/src/net/java/games/jogl/impl/JAWT_PlatformInfo.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package net.java.games.jogl.impl; + +/** Marker class for all window system-specific JAWT data structures. */ + +public interface JAWT_PlatformInfo { +} diff --git a/src/net/java/games/jogl/impl/NativeLibLoader.java b/src/net/java/games/jogl/impl/NativeLibLoader.java new file mode 100644 index 000000000..65c199f05 --- /dev/null +++ b/src/net/java/games/jogl/impl/NativeLibLoader.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package net.java.games.jogl.impl; + +public class NativeLibLoader { + static { + System.loadLibrary("jawt"); + System.loadLibrary("jogl"); + } + + public static void load() { + } +} diff --git a/src/net/java/games/jogl/impl/macosx/MacOSXGLContext.java b/src/net/java/games/jogl/impl/macosx/MacOSXGLContext.java new file mode 100644 index 000000000..bcb33e602 --- /dev/null +++ b/src/net/java/games/jogl/impl/macosx/MacOSXGLContext.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package net.java.games.jogl.impl.macosx; + +import java.awt.Component; +import java.util.*; +import net.java.games.gluegen.opengl.*; // for PROCADDRESS_VAR_PREFIX +import net.java.games.jogl.*; +import net.java.games.jogl.impl.*; + +public abstract class MacOSXGLContext extends GLContext { + + public MacOSXGLContext(Component component, GLCapabilities capabilities, GLCapabilitiesChooser chooser) { + super(component, capabilities, chooser); + } + + protected GL createGL() + { + return new MacOSXGLImpl(this); + } + + protected String mapToRealGLFunctionName(String glFunctionName) { + return glFunctionName; + } + + protected abstract boolean isOffscreen(); + + public abstract int getOffscreenContextBufferedImageType(); + + public abstract int getOffscreenContextReadBuffer(); + + public abstract boolean offscreenImageNeedsVerticalFlip(); + + /** + * Creates and initializes an appropriate OpenGl context. Should only be + * called by {@link makeCurrent(Runnable)}. + */ + protected abstract void create(); + + protected synchronized boolean makeCurrent(Runnable initAction) throws GLException + { + throw new RuntimeException(" FIXME: not implemented "); + } + + protected synchronized void free() throws GLException { + throw new RuntimeException(" FIXME: not implemented "); + } + + protected abstract void swapBuffers() throws GLException; + + + protected void resetGLFunctionAvailability() { + throw new RuntimeException(" FIXME: not implemented "); + } + + protected void resetGLProcAddressTable() { + throw new RuntimeException(" FIXME: not implemented "); + } + + public net.java.games.jogl.impl.ProcAddressTable getGLProcAddressTable() { + throw new RuntimeException(" FIXME: not implemented "); + } + + public String getPlatformExtensionsString() { + throw new RuntimeException(" FIXME: not implemented "); + } + + protected boolean isFunctionAvailable(String glFunctionName) + { + throw new RuntimeException(" FIXME: not implemented "); + } + +} diff --git a/src/net/java/games/jogl/impl/windows/WindowsGLContext.java b/src/net/java/games/jogl/impl/windows/WindowsGLContext.java new file mode 100644 index 000000000..4575b6210 --- /dev/null +++ b/src/net/java/games/jogl/impl/windows/WindowsGLContext.java @@ -0,0 +1,365 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package net.java.games.jogl.impl.windows; + +import java.awt.Component; +import java.util.*; +import net.java.games.gluegen.opengl.*; // for PROCADDRESS_VAR_PREFIX +import net.java.games.jogl.*; +import net.java.games.jogl.impl.*; + +public abstract class WindowsGLContext extends GLContext { + private static JAWT jawt; + protected long hglrc; + protected long hdc; + private boolean wglGetExtensionsStringEXTInitialized; + private boolean wglGetExtensionsStringEXTAvailable; + private static final Map/*<String, String>*/ functionNameMap; + private static final Map/*<String, String>*/ extensionNameMap; + + static { + functionNameMap = new HashMap(); + functionNameMap.put("glAllocateMemoryNV", "wglAllocateMemoryNV"); + functionNameMap.put("glFreeMemoryNV", "wglFreeMemoryNV"); + + extensionNameMap = new HashMap(); + extensionNameMap.put("GL_ARB_pbuffer", "WGL_ARB_pbuffer"); + extensionNameMap.put("GL_ARB_pixel_format", "WGL_ARB_pixel_format"); + } + + public WindowsGLContext(Component component, GLCapabilities capabilities, GLCapabilitiesChooser chooser) { + super(component, capabilities, chooser); + } + + protected GL createGL() + { + return new WindowsGLImpl(this); + } + + protected String mapToRealGLFunctionName(String glFunctionName) { + String lookup = (String) functionNameMap.get(glFunctionName); + if (lookup != null) { + return lookup; + } + return glFunctionName; + } + + protected String mapToRealGLExtensionName(String glExtensionName) { + String lookup = (String) extensionNameMap.get(glExtensionName); + if (lookup != null) { + return lookup; + } + return glExtensionName; + } + + protected abstract boolean isOffscreen(); + + public abstract int getOffscreenContextBufferedImageType(); + + public abstract int getOffscreenContextReadBuffer(); + + public abstract boolean offscreenImageNeedsVerticalFlip(); + + /** + * Creates and initializes an appropriate OpenGl context. Should only be + * called by {@link makeCurrent(Runnable)}. + */ + protected abstract void create(); + + protected synchronized boolean makeCurrent(Runnable initAction) throws GLException { + boolean created = false; + if (hglrc == 0) { + create(); + if (DEBUG) { + System.err.println("!!! Created GL context for " + getClass().getName()); + } + created = true; + } + + if (!WGL.wglMakeCurrent(hdc, hglrc)) { + throw new GLException("Error making context current"); + } + + if (created) { + resetGLFunctionAvailability(); + initAction.run(); + } + return true; + } + + protected synchronized void free() throws GLException { + if (!WGL.wglMakeCurrent(0, 0)) { + throw new GLException("Error freeing OpenGL context"); + } + } + + protected abstract void swapBuffers() throws GLException; + + + protected void resetGLFunctionAvailability() { + super.resetGLFunctionAvailability(); + resetGLProcAddressTable(); + } + + protected void resetGLProcAddressTable() { + + if (DEBUG) { + System.err.println("!!! Initializing OpenGL extension address table"); + } + + net.java.games.jogl.impl.ProcAddressTable table = getGLProcAddressTable(); + + // if GL is no longer an interface, we'll have to re-implement the code + // below so it only iterates through gl methods (a non-interface might + // have constructors, custom methods, etc). For now we assume all methods + // will be gl methods. + GL gl = getGL(); + + Class tableClass = table.getClass(); + + java.lang.reflect.Field[] fields = tableClass.getDeclaredFields(); + + for (int i = 0; i < fields.length; ++i) { + String addressFieldName = fields[i].getName(); + if (!addressFieldName.startsWith(GLEmitter.PROCADDRESS_VAR_PREFIX)) + { + // not a proc address variable + continue; + } + int startOfMethodName = GLEmitter.PROCADDRESS_VAR_PREFIX.length(); + String glFuncName = addressFieldName.substring(startOfMethodName); + try + { + java.lang.reflect.Field addressField = tableClass.getDeclaredField(addressFieldName); + assert(addressField.getType() == Long.TYPE); + // get the current value of the proc address variable in the table object + long oldProcAddress = addressField.getLong(table); + long newProcAddress = WGL.wglGetProcAddress(glFuncName); + /* + System.err.println( + "!!! Address=" + (newProcAddress == 0 + ? "<NULL> " + : ("0x" + + Long.toHexString(newProcAddress))) + + "\tGL func: " + glFuncName); + */ + // set the current value of the proc address variable in the table object + addressField.setLong(gl, newProcAddress); + } catch (Exception e) { + throw new GLException( + "Cannot get GL proc address for method \"" + + glFuncName + "\": Couldn't get value of field \"" + addressFieldName + + "\" in class " + tableClass.getName(), e); + } + } + + } + + public net.java.games.jogl.impl.ProcAddressTable getGLProcAddressTable() { + if (glProcAddressTable == null) { + // FIXME: cache ProcAddressTables by capability bits so we can + // share them among contexts with the same capabilities + glProcAddressTable = + new net.java.games.jogl.impl.ProcAddressTable(); + } + return glProcAddressTable; + } + + public String getPlatformExtensionsString() { + if (!wglGetExtensionsStringEXTInitialized) { + wglGetExtensionsStringEXTAvailable = (WGL.wglGetProcAddress("wglGetExtensionsStringEXT") != 0); + wglGetExtensionsStringEXTInitialized = true; + } + if (wglGetExtensionsStringEXTAvailable) { + return gl.wglGetExtensionsStringEXT(); + } else { + return ""; + } + } + + protected boolean isFunctionAvailable(String glFunctionName) + { + boolean available = super.isFunctionAvailable(glFunctionName); + + // Sanity check for implementations that use proc addresses for run-time + // linking: if the function IS available, then make sure there's a proc + // address for it if it's an extension or not part of the OpenGL 1.1 core + // (post GL 1.1 functions are run-time linked on windows). + assert(!available || + (getGLProcAddressTable().getAddressFor(mapToRealGLFunctionName(glFunctionName)) != 0 || + FunctionAvailabilityCache.isPartOfGLCore("1.1", mapToRealGLFunctionName(glFunctionName))) + ); + + return available; + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + // Table that holds the addresses of the native C-language entry points for + // OpenGL functions. + private net.java.games.jogl.impl.ProcAddressTable glProcAddressTable; + + 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 (chooser == null) { + // Note: this code path isn't taken any more now that the + // DefaultGLCapabilitiesChooser is present. However, it is being + // left in place for debugging purposes. + pfd = glCapabilities2PFD(capabilities, onscreen); + pixelFormat = WGL.ChoosePixelFormat(hdc, pfd); + if (pixelFormat == 0) { + throw new GLException("Unable to choose appropriate pixel format"); + } + if (DEBUG) { + System.err.println("Chosen pixel format from ChoosePixelFormat:"); + PIXELFORMATDESCRIPTOR tmpPFD = new PIXELFORMATDESCRIPTOR(); + WGL.DescribePixelFormat(hdc, pixelFormat, tmpPFD.size(), tmpPFD); + System.err.println(pfd2GLCapabilities(tmpPFD)); + } + } else { + int numFormats = WGL.DescribePixelFormat(hdc, 1, 0, null); + if (numFormats == 0) { + throw new GLException("Unable to enumerate pixel formats of window for GLCapabilitiesChooser"); + } + GLCapabilities[] availableCaps = new GLCapabilities[numFormats]; + pfd = new PIXELFORMATDESCRIPTOR(); + 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); + 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("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"); + } + } + if (!WGL.SetPixelFormat(hdc, pixelFormat, pfd)) { + throw new GLException("Unable to set pixel format"); + } + hglrc = WGL.wglCreateContext(hdc); + if (hglrc == 0) { + throw new GLException("Unable to create OpenGL context"); + } + } + + 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 = new PIXELFORMATDESCRIPTOR(); + pfd.nSize((short) pfd.size()); + pfd.nVersion((short) 1); + int pfdFlags = (WGL.PFD_SUPPORT_OPENGL | + WGL.PFD_GENERIC_ACCELERATED); + if (caps.getDoubleBuffered()) { + pfdFlags |= WGL.PFD_DOUBLEBUFFER; + if (onscreen) { + pfdFlags |= WGL.PFD_SWAP_EXCHANGE; + } + } + 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.cDepthBits((byte) caps.getDepthBits()); + pfd.iLayerType((byte) WGL.PFD_MAIN_PLANE); + 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; + } +} diff --git a/src/net/java/games/jogl/impl/windows/WindowsGLContextFactory.java b/src/net/java/games/jogl/impl/windows/WindowsGLContextFactory.java new file mode 100644 index 000000000..15e622efb --- /dev/null +++ b/src/net/java/games/jogl/impl/windows/WindowsGLContextFactory.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package net.java.games.jogl.impl.windows; + +import java.awt.Component; +import net.java.games.jogl.*; +import net.java.games.jogl.impl.*; + +public class WindowsGLContextFactory extends GLContextFactory { + public GLContext createGLContext(Component component, + GLCapabilities capabilities, + GLCapabilitiesChooser chooser) { + if (component != null) { + return new WindowsOnscreenGLContext(component, capabilities, chooser); + } else { + return new WindowsOffscreenGLContext(capabilities, chooser); + } + } +} diff --git a/src/net/java/games/jogl/impl/windows/WindowsOffscreenGLContext.java b/src/net/java/games/jogl/impl/windows/WindowsOffscreenGLContext.java new file mode 100644 index 000000000..727517e63 --- /dev/null +++ b/src/net/java/games/jogl/impl/windows/WindowsOffscreenGLContext.java @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package net.java.games.jogl.impl.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) { + super(null, capabilities, chooser); + } + + protected GL createGL() + { + return new WindowsGLImpl(this); + } + + protected boolean isOffscreen() { + return true; + } + + public int getOffscreenContextBufferedImageType() { + if (capabilities.getAlphaBits() > 0) { + return BufferedImage.TYPE_INT_ARGB; + } else { + return BufferedImage.TYPE_INT_RGB; + } + } + + public int getOffscreenContextReadBuffer() { + // On Windows these contexts are always single-buffered + return GL.GL_FRONT; + } + + public boolean offscreenImageNeedsVerticalFlip() { + // We can take care of this in the DIB creation (see below) + return false; + } + + public boolean canCreatePbufferContext() { + // For now say no + return false; + } + + public synchronized GLContext createPbufferContext(GLCapabilities capabilities, + int initialWidth, + int initialHeight) { + throw new GLException("Not supported"); + } + + public void bindPbufferToTexture() { + throw new GLException("Should not call this"); + } + + public void releasePbufferFromTexture() { + throw new GLException("Should not call this"); + } + + protected synchronized boolean makeCurrent(Runnable initAction) throws GLException { + if (pendingOffscreenResize) { + if (pendingOffscreenWidth != width || pendingOffscreenWidth != height) { + if (hglrc != 0) { + destroy(); + } + width = pendingOffscreenWidth; + height = pendingOffscreenHeight; + pendingOffscreenResize = false; + } + } + return super.makeCurrent(initAction); + } + + protected synchronized 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); + + // CreateDIBSection doesn't really need the device context if we are + // producing a truecolor bitmap. + hbitmap = WGL.CreateDIBSection(0, info, WGL.DIB_RGB_COLORS, 0, 0, 0); + if (hbitmap == 0) { + throw new GLException("Error creating offscreen bitmap"); + } + hdc = WGL.CreateCompatibleDC(0); + if (hdc == 0) { + throw new GLException("Error creating device context for offscreen OpenGL context"); + } + if ((origbitmap = WGL.SelectObject(hdc, hbitmap)) == 0) { + throw new GLException("Error selecting bitmap into new device context"); + } + + choosePixelFormatAndCreateContext(false); + } + + private void destroy() { + // Must destroy OpenGL context, bitmap and device context + WGL.wglDeleteContext(hglrc); + WGL.SelectObject(hdc, origbitmap); + WGL.DeleteObject(hbitmap); + WGL.DeleteDC(hdc); + hglrc = 0; + 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 new file mode 100644 index 000000000..a5b7519cf --- /dev/null +++ b/src/net/java/games/jogl/impl/windows/WindowsOnscreenGLContext.java @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package net.java.games.jogl.impl.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; + + // Variables for pbuffer support + List pbuffersToInstantiate = new ArrayList(); + + public WindowsOnscreenGLContext(Component component, GLCapabilities capabilities, GLCapabilitiesChooser chooser) { + super(component, capabilities, chooser); + } + + protected GL createGL() + { + return new WindowsGLImpl(this); + } + + protected boolean isOffscreen() { + return false; + } + + public int getOffscreenContextBufferedImageType() { + throw new GLException("Should not call this"); + } + + public int getOffscreenContextReadBuffer() { + throw new GLException("Should not call this"); + } + + public boolean offscreenImageNeedsVerticalFlip() { + throw new GLException("Should not call this"); + } + + public boolean canCreatePbufferContext() { + return true; + } + + public synchronized GLContext createPbufferContext(GLCapabilities capabilities, + int initialWidth, + int initialHeight) { + WindowsPbufferGLContext ctx = new WindowsPbufferGLContext(capabilities, initialWidth, initialHeight); + pbuffersToInstantiate.add(ctx); + return ctx; + } + + public void bindPbufferToTexture() { + throw new GLException("Should not call this"); + } + + public void releasePbufferFromTexture() { + throw new GLException("Should not call this"); + } + + protected synchronized boolean makeCurrent(Runnable initAction) throws GLException { + try { + if (!lockSurface()) { + return false; + } + boolean ret = super.makeCurrent(initAction); + if (ret) { + // Instantiate any pending pbuffers + while (!pbuffersToInstantiate.isEmpty()) { + WindowsPbufferGLContext ctx = + (WindowsPbufferGLContext) pbuffersToInstantiate.remove(pbuffersToInstantiate.size() - 1); + ctx.createPbuffer(hdc, hglrc); + } + } + return ret; + } catch (RuntimeException e) { + try { + unlockSurface(); + } catch (Exception e2) { + // do nothing if unlockSurface throws + } + throw(e); + } + } + + protected synchronized void free() throws GLException { + try { + super.free(); + } finally { + unlockSurface(); + } + } + + protected synchronized void swapBuffers() throws GLException { + if (!WGL.SwapBuffers(hdc)) { + throw new GLException("Error swapping buffers"); + } + } + + 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 + 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"); + } + 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/WindowsPbufferGLContext.java b/src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java new file mode 100644 index 000000000..300e9cb85 --- /dev/null +++ b/src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java @@ -0,0 +1,413 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package net.java.games.jogl.impl.windows; + +import net.java.games.jogl.*; +import net.java.games.jogl.impl.*; + +public class WindowsPbufferGLContext extends WindowsGLContext { + private static final boolean DEBUG = false; + + 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 boolean rtt; // render-to-texture? + 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 + + public WindowsPbufferGLContext(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 + "))"); + } + } + + public boolean canCreatePbufferContext() { + return false; + } + + public GLContext createPbufferContext(GLCapabilities capabilities, + int initialWidth, + int initialHeight) { + throw new GLException("Not supported"); + } + + public void bindPbufferToTexture() { + if (!rtt) { + throw new GLException("Shouldn't try to bind a pbuffer to a texture if render-to-texture hasn't been " + + "specified in its GLCapabilities"); + } + GL gl = getGL(); + gl.glBindTexture(textureTarget, texture); + // Note: this test was on the rtt variable in NVidia's code but I + // think it doesn't make sense written that way + if (rect) { + if (!gl.wglBindTexImageARB(buffer, GL.WGL_FRONT_LEFT_ARB)) { + throw new GLException("Binding of pbuffer to texture failed: " + wglGetLastError()); + } + } + // Note that if the render-to-texture-rectangle extension is not + // specified, we perform a glCopyTexImage2D in swapBuffers(). + } + + public void releasePbufferFromTexture() { + if (!rtt) { + throw new GLException("Shouldn't try to bind a pbuffer to a texture if render-to-texture hasn't been " + + "specified in its GLCapabilities"); + } + if (rect) { + GL gl = getGL(); + if (!gl.wglReleaseTexImageARB(buffer, 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(); + + int[] iattributes = new int [2*MAX_ATTRIBS]; + float[] fattributes = new float[2*MAX_ATTRIBS]; + int nfattribs = 0; + int niattribs = 0; + + rtt = capabilities.getOffscreenRenderToTexture(); + rect = capabilities.getOffscreenRenderToTextureRectangle(); + boolean useFloat = capabilities.getOffscreenFloatingPointBuffers(); + + // 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) { + // 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) { + iattributes[niattribs++] = GL.WGL_FLOAT_COMPONENTS_NV; + iattributes[niattribs++] = GL.GL_TRUE; + } + + if (rtt) { + if (useFloat) { + 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, + fattributes, + MAX_PFORMATS, + pformats, + nformatsTmp)) { + 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] = GL.WGL_FLOAT_COMPONENTS_NV; + iattributes[6] = GL.WGL_SAMPLE_BUFFERS_EXT; + iattributes[7] = GL.WGL_SAMPLES_EXT; + int[] ivalues = new int[8]; + for (int i = 0; i < nformats; i++) { + if (!gl.wglGetPixelFormatAttribivARB(parentHdc, pformats[i], 0, 8, iattributes, ivalues)) { + 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 (ivalues[5] != 0) { + System.err.print(" [float]"); + } + System.err.println(); + } + } + + int format = pformats[0]; + + // 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; + + long tmpBuffer = gl.wglCreatePbufferARB(parentHdc, format, initWidth, initHeight, iattributes); + if (tmpBuffer == 0) { + throw new GLException("pbuffer creation error: wglCreatePbufferARB() failed: " + 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 ); + width = tmp[0]; + gl.wglQueryPbufferARB( buffer, GL.WGL_PBUFFER_HEIGHT_ARB, tmp ); + height = tmp[0]; + + if (DEBUG) { + System.err.println("Created pbuffer " + width + " x " + height); + } + } + + protected synchronized boolean makeCurrent(Runnable initAction) throws GLException { + created = false; + + if (buffer == 0) { + // pbuffer not instantiated yet + return false; + } + + boolean res = super.makeCurrent(initAction); + if (created) { + // Initialize render-to-texture support if requested + rtt = capabilities.getOffscreenRenderToTexture(); + rect = capabilities.getOffscreenRenderToTextureRectangle(); + + if (rtt) { + if (DEBUG) { + System.err.println("Initializing render-to-texture support"); + } + + GL gl = getGL(); + if (rect && !gl.isExtensionAvailable("GL_NV_texture_rectangle")) { + System.err.println("WindowsPbufferGLContext: WARNING: GL_NV_texture_rectangle extension not " + + "supported; skipping requested render_to_texture_rectangle support for pbuffer"); + rect = false; + } + if (rect) { + if (DEBUG) { + System.err.println(" Using render-to-texture-rectangle"); + } + textureTarget = GL.GL_TEXTURE_RECTANGLE_NV; + } else { + if (DEBUG) { + System.err.println(" Using vanilla render-to-texture"); + } + textureTarget = GL.GL_TEXTURE_2D; + } + int[] tmp = new int[1]; + gl.glGenTextures(1, tmp); + texture = tmp[0]; + gl.glBindTexture(textureTarget, texture); + gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST); + 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); + } + } + 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 getOffscreenContextBufferedImageType() { + throw new GLException("Should not call this"); + } + + public int getOffscreenContextReadBuffer() { + throw new GLException("Should not call this"); + } + + public boolean offscreenImageNeedsVerticalFlip() { + 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 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 && !rect) { + if (DEBUG) { + System.err.println("Copying pbuffer data to GL_TEXTURE_2D state"); + } + + GL gl = getGL(); + gl.glCopyTexImage2D(textureTarget, 0, GL.GL_RGB, 0, 0, width, height, 0); + } + } + + 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; + } +} diff --git a/src/net/java/games/jogl/impl/x11/X11GLContext.java b/src/net/java/games/jogl/impl/x11/X11GLContext.java new file mode 100644 index 000000000..8e9804578 --- /dev/null +++ b/src/net/java/games/jogl/impl/x11/X11GLContext.java @@ -0,0 +1,414 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package net.java.games.jogl.impl.x11; + +import java.awt.Component; +import java.util.*; +import net.java.games.gluegen.opengl.*; // for PROCADDRESS_VAR_PREFIX +import net.java.games.jogl.*; +import net.java.games.jogl.impl.*; + +public abstract class X11GLContext extends GLContext { + private static JAWT jawt; + protected long display; + protected long drawable; + protected long context; + private boolean glXQueryExtensionsStringInitialized; + private boolean glXQueryExtensionsStringAvailable; + private static final Map/*<String, String>*/ functionNameMap; + + static { + functionNameMap = new HashMap(); + functionNameMap.put("glAllocateMemoryNV", "glXAllocateMemoryNV"); + functionNameMap.put("glFreeMemoryNV", "glXFreeMemoryNV"); + } + + public X11GLContext(Component component, GLCapabilities capabilities, GLCapabilitiesChooser chooser) { + super(component, capabilities, chooser); + } + + protected GL createGL() + { + return new X11GLImpl(this); + } + + protected String mapToRealGLFunctionName(String glFunctionName) { + String lookup = (String) functionNameMap.get(glFunctionName); + if (lookup != null) { + return lookup; + } + return glFunctionName; + } + + protected String mapToRealGLExtensionName(String glExtensionName) { + return glExtensionName; + } + + protected abstract boolean isOffscreen(); + + public abstract int getOffscreenContextBufferedImageType(); + + public abstract int getOffscreenContextReadBuffer(); + + public abstract boolean offscreenImageNeedsVerticalFlip(); + + public synchronized void setRenderingThread(Thread currentThreadOrNull, Runnable initAction) { + this.willSetRenderingThread = false; + // FIXME: the JAWT on X11 grabs the AWT lock while the + // DrawingSurface is locked, which means that no other events can + // be processed. Currently we handle this by preventing the + // effects of setRenderingThread. We should figure out a better + // solution that is reasonably robust. Must file a bug to be fixed + // in the 1.5 JAWT. + } + + /** + * Creates and initializes an appropriate OpenGl context. Should only be + * called by {@link makeCurrent(Runnable)}. + */ + protected abstract void create(); + + protected synchronized boolean makeCurrent(Runnable initAction) throws GLException { + boolean created = false; + if (context == 0) { + create(); + if (DEBUG) { + System.err.println("!!! 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)) { + throw new GLException("Error making context current"); + } + + if (created) { + resetGLFunctionAvailability(); + initAction.run(); + } + return true; + } + + protected synchronized void free() throws GLException { + if (!GLX.glXMakeCurrent(display, 0, 0)) { + throw new GLException("Error freeing OpenGL context"); + } + } + + protected abstract void swapBuffers() throws GLException; + + + protected void resetGLFunctionAvailability() { + super.resetGLFunctionAvailability(); + resetGLProcAddressTable(); + } + + protected void resetGLProcAddressTable() { + + if (DEBUG) { + System.err.println("!!! Initializing OpenGL extension address table"); + } + + net.java.games.jogl.impl.ProcAddressTable table = getGLProcAddressTable(); + + // if GL is no longer an interface, we'll have to re-implement the code + // below so it only iterates through gl methods (a non-interface might + // have constructors, custom methods, etc). For now we assume all methods + // will be gl methods. + GL gl = getGL(); + + Class tableClass = table.getClass(); + + java.lang.reflect.Field[] fields = tableClass.getDeclaredFields(); + + for (int i = 0; i < fields.length; ++i) { + String addressFieldName = fields[i].getName(); + if (!addressFieldName.startsWith(GLEmitter.PROCADDRESS_VAR_PREFIX)) + { + // not a proc address variable + continue; + } + int startOfMethodName = GLEmitter.PROCADDRESS_VAR_PREFIX.length(); + String glFuncName = addressFieldName.substring(startOfMethodName); + try + { + java.lang.reflect.Field addressField = tableClass.getDeclaredField(addressFieldName); + assert(addressField.getType() == Long.TYPE); + // get the current value of the proc address variable in the table object + long oldProcAddress = addressField.getLong(table); + long newProcAddress = GLX.glXGetProcAddressARB(glFuncName); + /* + System.err.println( + "!!! Address=" + (newProcAddress == 0 + ? "<NULL> " + : ("0x" + + Long.toHexString(newProcAddress))) + + "\tGL func: " + glFuncName); + */ + // set the current value of the proc address variable in the table object + addressField.setLong(gl, newProcAddress); + } catch (Exception e) { + throw new GLException( + "Cannot get GL proc address for method \"" + + glFuncName + "\": Couldn't get value of field \"" + addressFieldName + + "\" in class " + tableClass.getName(), e); + } + } + + } + + public net.java.games.jogl.impl.ProcAddressTable getGLProcAddressTable() { + if (glProcAddressTable == null) { + // FIXME: cache ProcAddressTables by capability bits so we can + // share them among contexts with the same capabilities + glProcAddressTable = + new net.java.games.jogl.impl.ProcAddressTable(); + } + return glProcAddressTable; + } + + public synchronized String getPlatformExtensionsString() { + if (display == 0) { + throw new GLException("Context not current"); + } + if (!glXQueryExtensionsStringInitialized) { + glXQueryExtensionsStringAvailable = (GLX.glXGetProcAddressARB("glXQueryExtensionsString") != 0); + glXQueryExtensionsStringInitialized = true; + } + if (glXQueryExtensionsStringAvailable) { + return GLX.glXQueryExtensionsString(display, GLX.DefaultScreen(display)); + } else { + return ""; + } + } + + protected boolean isFunctionAvailable(String glFunctionName) + { + boolean available = super.isFunctionAvailable(glFunctionName); + + // Sanity check for implementations that use proc addresses for run-time + // linking: if the function IS available, then make sure there's a proc + // address for it if it's an extension or not part of the OpenGL 1.1 core + // (post GL 1.1 functions are run-time linked on windows). + assert(!available || + (getGLProcAddressTable().getAddressFor(mapToRealGLFunctionName(glFunctionName)) != 0 || + FunctionAvailabilityCache.isPartOfGLCore("1.1", mapToRealGLFunctionName(glFunctionName))) + ); + + return available; + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + // Table that holds the addresses of the native C-language entry points for + // OpenGL functions. + private net.java.games.jogl.impl.ProcAddressTable glProcAddressTable; + + 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; + } + + protected XVisualInfo chooseVisual() { + int screen = 0; // FIXME: provide way to specify this? + XVisualInfo vis = null; + if (chooser == null) { + // Note: this code path isn't taken any more now that the + // DefaultGLCapabilitiesChooser is present. However, it is being + // left in place for debugging purposes. + int[] attribs = glCapabilities2AttribList(capabilities); + vis = GLX.glXChooseVisual(display, screen, attribs); + if (vis == null) { + throw new GLException("Unable to find matching visual"); + } + if (DEBUG) { + System.err.println("Chosen visual from glXChooseVisual:"); + System.err.println(xvi2GLCapabilities(vis)); + } + } else { + int[] count = new int[1]; + XVisualInfo template = new XVisualInfo(); + template.screen(screen); + XVisualInfo[] infos = GLX.XGetVisualInfo(display, GLX.VisualScreenMask, template, count); + 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] = xvi2GLCapabilities(infos[i]); + } + int chosen = chooser.chooseCapabilities(capabilities, caps); + 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"); + } + } + return vis; + } + + protected long createContext(XVisualInfo vis, boolean onscreen) { + // FIXME: support sharing of display lists between contexts + return GLX.glXCreateContext(display, vis, 0, onscreen); + } + + // Helper routine for the overridden create() to call + protected void chooseVisualAndCreateContext(boolean onscreen) { + XVisualInfo vis = chooseVisual(); + // FIXME: support sharing of display lists between contexts + context = createContext(vis, onscreen); + if (context == 0) { + throw new GLException("Unable to create OpenGL context"); + } + } + + protected int[] glCapabilities2AttribList(GLCapabilities caps) { + int colorDepth = (caps.getRedBits() + + caps.getGreenBits() + + caps.getBlueBits()); + if (colorDepth < 15) { + throw new GLException("Bit depths < 15 (i.e., non-true-color) not supported"); + } + int[] res = new int[22]; + int idx = 0; + res[idx++] = GLX.GLX_RGBA; + if (caps.getDoubleBuffered()) { + res[idx++] = GLX.GLX_DOUBLEBUFFER; + } + if (caps.getStereo()) { + res[idx++] = GLX.GLX_STEREO; + } + res[idx++] = GLX.GLX_RED_SIZE; + res[idx++] = caps.getRedBits(); + res[idx++] = GLX.GLX_GREEN_SIZE; + res[idx++] = caps.getGreenBits(); + res[idx++] = GLX.GLX_BLUE_SIZE; + res[idx++] = caps.getBlueBits(); + res[idx++] = GLX.GLX_ALPHA_SIZE; + res[idx++] = caps.getAlphaBits(); + res[idx++] = GLX.GLX_DEPTH_SIZE; + res[idx++] = caps.getDepthBits(); + res[idx++] = GLX.GLX_STENCIL_SIZE; + res[idx++] = caps.getStencilBits(); + res[idx++] = GLX.GLX_ACCUM_RED_SIZE; + res[idx++] = caps.getAccumRedBits(); + res[idx++] = GLX.GLX_ACCUM_GREEN_SIZE; + res[idx++] = caps.getAccumGreenBits(); + res[idx++] = GLX.GLX_ACCUM_BLUE_SIZE; + res[idx++] = caps.getAccumBlueBits(); + res[idx++] = 0; + return res; + } + + protected GLCapabilities xvi2GLCapabilities(XVisualInfo info) { + int[] tmp = new int[1]; + int val = glXGetConfig(info, GLX.GLX_USE_GL, tmp); + if (val == 0) { + // Visual does not support OpenGL + return null; + } + val = glXGetConfig(info, GLX.GLX_RGBA, tmp); + if (val == 0) { + // Visual does not support RGBA + return null; + } + GLCapabilities res = new GLCapabilities(); + res.setDoubleBuffered(glXGetConfig(info, GLX.GLX_DOUBLEBUFFER, tmp) != 0); + res.setStereo (glXGetConfig(info, GLX.GLX_STEREO, tmp) != 0); + // Note: use of hardware acceleration is determined by + // glXCreateContext, not by the XVisualInfo. Optimistically claim + // that all GLCapabilities have the capability to be hardware + // accelerated. + res.setHardwareAccelerated(true); + res.setDepthBits (glXGetConfig(info, GLX.GLX_DEPTH_SIZE, tmp)); + res.setStencilBits (glXGetConfig(info, GLX.GLX_STENCIL_SIZE, tmp)); + res.setRedBits (glXGetConfig(info, GLX.GLX_RED_SIZE, tmp)); + res.setGreenBits (glXGetConfig(info, GLX.GLX_GREEN_SIZE, tmp)); + res.setBlueBits (glXGetConfig(info, GLX.GLX_BLUE_SIZE, tmp)); + res.setAlphaBits (glXGetConfig(info, GLX.GLX_ALPHA_SIZE, tmp)); + res.setAccumRedBits (glXGetConfig(info, GLX.GLX_ACCUM_RED_SIZE, tmp)); + res.setAccumGreenBits(glXGetConfig(info, GLX.GLX_ACCUM_GREEN_SIZE, tmp)); + res.setAccumBlueBits (glXGetConfig(info, GLX.GLX_ACCUM_BLUE_SIZE, tmp)); + res.setAccumAlphaBits(glXGetConfig(info, GLX.GLX_ACCUM_ALPHA_SIZE, tmp)); + return res; + } + + protected String glXGetConfigErrorCode(int err) { + switch (err) { + case GLX.GLX_NO_EXTENSION: return "GLX_NO_EXTENSION"; + case GLX.GLX_BAD_SCREEN: return "GLX_BAD_SCREEN"; + case GLX.GLX_BAD_ATTRIBUTE: return "GLX_BAD_ATTRIBUTE"; + case GLX.GLX_BAD_VISUAL: return "GLX_BAD_VISUAL"; + default: return "Unknown error code " + err; + } + } + + protected int glXGetConfig(XVisualInfo info, int attrib, int[] tmp) { + if (display == 0) { + throw new GLException("No display connection"); + } + int res = GLX.glXGetConfig(display, info, attrib, tmp); + if (res != 0) { + throw new GLException("glXGetConfig failed: error code " + glXGetConfigErrorCode(res)); + } + return tmp[0]; + } +} diff --git a/src/net/java/games/jogl/impl/x11/X11GLContextFactory.java b/src/net/java/games/jogl/impl/x11/X11GLContextFactory.java new file mode 100644 index 000000000..cf1e4be25 --- /dev/null +++ b/src/net/java/games/jogl/impl/x11/X11GLContextFactory.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package net.java.games.jogl.impl.x11; + +import java.awt.Component; +import net.java.games.jogl.*; +import net.java.games.jogl.impl.*; + +public class X11GLContextFactory extends GLContextFactory { + public GLContext createGLContext(Component component, + GLCapabilities capabilities, + GLCapabilitiesChooser chooser) { + if (component != null) { + return new X11OnscreenGLContext(component, capabilities, chooser); + } else { + return new X11OffscreenGLContext(capabilities, chooser); + } + } +} diff --git a/src/net/java/games/jogl/impl/x11/X11OffscreenGLContext.java b/src/net/java/games/jogl/impl/x11/X11OffscreenGLContext.java new file mode 100644 index 000000000..62fd380ee --- /dev/null +++ b/src/net/java/games/jogl/impl/x11/X11OffscreenGLContext.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package net.java.games.jogl.impl.x11; + +import java.awt.image.BufferedImage; +import net.java.games.jogl.*; +import net.java.games.jogl.impl.*; + +public class X11OffscreenGLContext extends X11GLContext { + private int pixmap; + private boolean isDoubleBuffered; + // Width and height of the underlying bitmap + private int width; + private int height; + + // Display connection for use by all offscreen surfaces + private long staticDisplay; + + public X11OffscreenGLContext(GLCapabilities capabilities, GLCapabilitiesChooser chooser) { + super(null, capabilities, chooser); + } + + protected GL createGL() + { + return new X11GLImpl(this); + } + + protected boolean isOffscreen() { + return true; + } + + public int getOffscreenContextBufferedImageType() { + if (capabilities.getAlphaBits() > 0) { + return BufferedImage.TYPE_INT_ARGB; + } else { + return BufferedImage.TYPE_INT_RGB; + } + } + + public int getOffscreenContextReadBuffer() { + if (isDoubleBuffered) { + return GL.GL_BACK; + } + return GL.GL_FRONT; + } + + public boolean offscreenImageNeedsVerticalFlip() { + // There doesn't seem to be a way to do this in the construction + // of the Pixmap or GLXPixmap + return true; + } + + public boolean canCreatePbufferContext() { + // For now say no + return false; + } + + public synchronized GLContext createPbufferContext(GLCapabilities capabilities, + int initialWidth, + int initialHeight) { + throw new GLException("Not supported"); + } + + public void bindPbufferToTexture() { + throw new GLException("Should not call this"); + } + + public void releasePbufferFromTexture() { + throw new GLException("Should not call this"); + } + + protected synchronized boolean makeCurrent(Runnable initAction) throws GLException { + ensureDisplayOpened(); + if (pendingOffscreenResize) { + if (pendingOffscreenWidth != width || pendingOffscreenWidth != height) { + if (context != 0) { + destroy(); + } + width = pendingOffscreenWidth; + height = pendingOffscreenHeight; + pendingOffscreenResize = false; + } + } + return super.makeCurrent(initAction); + } + + protected synchronized void swapBuffers() throws GLException { + } + + protected synchronized void free() throws GLException { + try { + super.free(); + } 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 = (glXGetConfig(vis, GLX.GLX_DOUBLEBUFFER, new int[1]) != 0); + } + + private void ensureDisplayOpened() { + if (staticDisplay == 0) { + staticDisplay = GLX.XOpenDisplay(null); + if (staticDisplay == 0) { + throw new GLException("Unable to open default display, needed for offscreen surface handling"); + } + } + display = staticDisplay; + } + + private void destroy() { + // 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; + } +} diff --git a/src/net/java/games/jogl/impl/x11/X11OnscreenGLContext.java b/src/net/java/games/jogl/impl/x11/X11OnscreenGLContext.java new file mode 100644 index 000000000..496e113a5 --- /dev/null +++ b/src/net/java/games/jogl/impl/x11/X11OnscreenGLContext.java @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package net.java.games.jogl.impl.x11; + +import java.awt.Component; +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; + + public X11OnscreenGLContext(Component component, GLCapabilities capabilities, GLCapabilitiesChooser chooser) { + super(component, capabilities, chooser); + } + + protected GL createGL() + { + return new X11GLImpl(this); + } + + protected boolean isOffscreen() { + return false; + } + + public int getOffscreenContextBufferedImageType() { + throw new GLException("Should not call this"); + } + + public int getOffscreenContextReadBuffer() { + throw new GLException("Should not call this"); + } + + public boolean offscreenImageNeedsVerticalFlip() { + throw new GLException("Should not call this"); + } + + public boolean canCreatePbufferContext() { + // For now say no + return false; + } + + public synchronized GLContext createPbufferContext(GLCapabilities capabilities, + int initialWidth, + int initialHeight) { + throw new GLException("Not yet supported"); + } + + public void bindPbufferToTexture() { + throw new GLException("Should not call this"); + } + + public void releasePbufferFromTexture() { + throw new GLException("Should not call this"); + } + + protected synchronized boolean makeCurrent(Runnable initAction) throws GLException { + try { + if (!lockSurface()) { + return false; + } + return super.makeCurrent(initAction); + } catch (RuntimeException e) { + try { + unlockSurface(); + } catch (Exception e2) { + // do nothing if unlockSurface throws + } + throw(e); + } + } + + protected synchronized void free() throws GLException { + try { + super.free(); + } finally { + unlockSurface(); + } + } + + protected synchronized 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; + } + 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(); + if (display == 0 || drawable == 0) { + // Widget not yet realized + ds.FreeDrawingSurfaceInfo(dsi); + ds.Unlock(); + getJAWT().FreeDrawingSurface(ds); + ds = null; + dsi = null; + x11dsi = null; + return false; + } + 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; + } + + protected void create() { + chooseVisualAndCreateContext(true); + } +} |