diff options
Diffstat (limited to 'src/jogl/classes/javax/media/opengl')
27 files changed, 6327 insertions, 0 deletions
diff --git a/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java b/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java new file mode 100644 index 000000000..782d041a5 --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2003-2009 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package javax.media.opengl; + +import javax.media.nativewindow.Capabilities; +import javax.media.nativewindow.NativeWindowException; + +/** <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. + + <LI> If a valid windowSystemRecommendedChoice parameter is + supplied, chooses that instead of using the cross-platform code. + + </UL> +*/ + +public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser { + private static final boolean DEBUG = false; // FIXME: Debug.debug("DefaultGLCapabilitiesChooser"); + + public int chooseCapabilities(Capabilities desired, + Capabilities[] available, + int windowSystemRecommendedChoice) { + GLCapabilities _desired = (GLCapabilities) desired; + GLCapabilities[] _available = (GLCapabilities[]) available; + + if (DEBUG) { + System.err.println("Desired: " + _desired); + for (int i = 0; i < _available.length; i++) { + System.err.println("Available " + i + ": " + _available[i]); + } + System.err.println("Window system's recommended choice: " + windowSystemRecommendedChoice); + } + + if (windowSystemRecommendedChoice >= 0 && + windowSystemRecommendedChoice < _available.length && + _available[windowSystemRecommendedChoice] != null) { + if (DEBUG) { + System.err.println("Choosing window system's recommended choice of " + windowSystemRecommendedChoice); + System.err.println(_available[windowSystemRecommendedChoice]); + } + return windowSystemRecommendedChoice; + } + + // 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 NativeWindowException("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/jogl/classes/javax/media/opengl/GLArrayData.java b/src/jogl/classes/javax/media/opengl/GLArrayData.java new file mode 100644 index 000000000..d17ee6a06 --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/GLArrayData.java @@ -0,0 +1,114 @@ + +package javax.media.opengl; + +import java.nio.*; + +/** + * + * The total number of bytes hold by the referenced buffer is: + * getComponentSize()* getComponentNumber() * getElementNumber() + * + */ +public interface GLArrayData { + + /** + * Returns true if this data set is intended for a GLSL vertex shader attribute, + * otherwise false, ie intended for fixed function vertex pointer + */ + public boolean isVertexAttribute(); + + /** + * The index of the predefined array index, see list below, + * or -1 in case of a shader attribute array. + * + * @see javax.media.opengl.GL#GL_VERTEX_ARRAY + * @see javax.media.opengl.GL#GL_NORMAL_ARRAY + * @see javax.media.opengl.GL#GL_COLOR_ARRAY + * @see javax.media.opengl.GL#GL_TEXTURE_COORD_ARRAY + */ + public int getIndex(); + + /** + * The name of the reflecting shader array attribute. + */ + public String getName(); + + /** + * Set a new name for this array. + */ + public void setName(String newName); + + + /** + * Returns the shader attribute location for this name, + * -1 if not yet determined + */ + public int getLocation(); + + /** + * Sets the determined location of the shader attribute + * This is usually done within ShaderState. + * + * @see javax.media.opengl.glsl.ShaderState#glVertexAttribPointer(GL2ES2, GLArrayData) + */ + public void setLocation(int v); + + /** + * Determines wheather the data is server side (VBO), + * or a client side array (false). + */ + public boolean isVBO(); + + /** + * The offset, if it's an VBO, otherwise -1 + */ + public long getOffset(); + + /** + * The VBO name, if it's an VBO, otherwise -1 + */ + public int getVBOName(); + + /** + * The Buffer holding the data, may be null in case of VBO + */ + public Buffer getBuffer(); + + /** + * The number of components per element + */ + public int getComponentNumber(); + + /** + * The component's GL data type, ie. GL_FLOAT + */ + public int getComponentType(); + + /** + * The components size in bytes + */ + public int getComponentSize(); + + /** + * Return the number of elements. + */ + public int getElementNumber(); + + /** + * True, if GL shall normalize fixed point data while converting + * them into float + */ + public boolean getNormalized(); + + /** + * The distance to the next payload, + * allowing interleaved arrays. + */ + public int getStride(); + + public String toString(); + + public void destroy(GL gl); + +} + diff --git a/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java new file mode 100644 index 000000000..6b1067701 --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package javax.media.opengl; + +import javax.media.opengl.glu.*; + +/** A higher-level abstraction than {@link GLDrawable} which supplies + an event based mechanism ({@link GLEventListener}) for performing + OpenGL rendering. A GLAutoDrawable automatically creates a primary + rendering context which is associated with the GLAutoDrawable for + the lifetime of the object. This context has the {@link + GLContext#setSynchronized synchronized} property enabled so that + calls to {@link GLContext#makeCurrent makeCurrent} will block if + the context is current on another thread. This allows the internal + GLContext for the GLAutoDrawable to be used both by the event + based rendering mechanism as well by end users directly.<P> + + The implementation shall initialize itself as soon as possible, + ie if the attached {@link javax.media.nativewindow.NativeWindow NativeWindow} is become visible. + The following protocol shall be satisfied: + <ul> + <li> Create the {@link GLDrawable} with the requested {@link GLCapabilities}</li> + <li> Notify {@link GLDrawable} to validate the {@link GLCapabilities} by calling {@link GLDrawable#setRealized setRealized(true)}.</li> + <li> Create the new {@link GLContext}.</li> + <li> Initialize all OpenGL resources by calling {@link GLEventListener#init init(..)} for all + registered {@link GLEventListener}s. This can be done immediatly, or with the followup {@link #display display(..)} call.</li> + <li> Send a reshape event by calling {@link GLEventListener#reshape reshape(..)} for all + registered {@link GLEventListener}s. This shall be done after the {@link GLEventListener#init init(..)} calls.</li> + </ul><P> + + Another implementation detail is the drawable reconfiguration. One use case is where a window is being + dragged to another screen with a different pixel configuration, ie {@link GLCapabilities}. The implementation + shall be able to detect such cases in conjunction with the associated {@link javax.media.nativewindow.NativeWindow NativeWindow}.<br> + For example, AWT's {@link java.awt.Canvas} 's {@link java.awt.Canvas#getGraphicsConfiguration getGraphicsConfiguration()} + is capable to determine a display device change. This is demonstrated within {@link javax.media.opengl.awt.GLCanvas}'s + and NEWT's <code>AWTCanvas</code> {@link javax.media.opengl.awt.GLCanvas#getGraphicsConfiguration getGraphicsConfiguration()} + specialization. Another demonstration is NEWT's {@link javax.media.nativewindow.NativeWindow NativeWindow} + implementation on the the Windows platform, which utilizes the native platform's <i>MonitorFromWindow(HWND)</i> function.<br> + All OpenGL resources shall be regenerated, while the drawable's {@link GLCapabilities} has + to be choosen again. The following protocol shall be satisfied. + <ul> + <li> Controlled disposal:</li> + <ul> + <li> Dispose all OpenGL resources by calling {@link GLEventListener#dispose dispose(..)} for all + registered {@link GLEventListener}s.</li> + <li> Destroy the {@link GLContext}.</li> + <li> Notify {@link GLDrawable} of the invalid state by calling {@link GLDrawable#setRealized setRealized(false)}.</li> + </ul> + <li> Controlled regeneration:</li> + <ul> + <li> Create the new {@link GLDrawable} with the requested {@link GLCapabilities} + <li> Notify {@link GLDrawable} to revalidate the {@link GLCapabilities} by calling {@link GLDrawable#setRealized setRealized(true)}.</li> + <li> Create the new {@link GLContext}.</li> + <li> Initialize all OpenGL resources by calling {@link GLEventListener#init init(..)} for all + registered {@link GLEventListener}s. This can be done immediatly, or with the followup {@link #display display(..)} call.</li> + <li> Send a reshape event by calling {@link GLEventListener#reshape reshape(..)} for all + registered {@link GLEventListener}s. This shall be done after the {@link GLEventListener#init init(..)} calls.</li> + </ul> + </ul> + Note: Current graphics driver keep the surface configuration for a given window, even if the window is moved to + a monitor with a different pixel configuration, ie 32bpp to 16bpp. However, it is best to not assume such behavior + and make your application comply with the above protocol.<P> + + However, to not introduce to much breakage with older applications and because of the situation + mentioned above, the <code>boolean</code> system property <code>jogl.screenchange.action</code> will control the + screen change action as follows:<br> + + <PRE> + -Djogl.screenchange.action=false Disable the drawable reconfiguration (the default) + -Djogl.screenchange.action=true Enable the drawable reconfiguration + </PRE> + */ +public interface GLAutoDrawable extends GLDrawable { + /** Flag reflecting wheather the drawable reconfiguration will be issued in + * case a screen device change occured, e.g. in a multihead environment, + * where you drag the window to another monitor. */ + public static final boolean SCREEN_CHANGE_ACTION_ENABLED = Boolean.getBoolean("jogl.screenchange.action"); + + /** FIXME: + ** Invalid state, the resources are not yet ready to render. * + public static final int STATE_INVALID = 0; + + ** Valid state, all resources are ready to render, + and all registered {@link GLEventListener#init init(..)} are called. * + public static final int STATE_VALID = 1; + + ** Destroying state, currently executing the {@link #destroy()} method. * + public static final int STATE_DESTROYING = 2; */ + + /** + * Returns the context associated with this drawable. The returned + * context will be synchronized. + * Don't rely on it's identity, the context may change. + */ + public GLContext getContext(); + + /** + * Associate a new context to this drawable. + */ + public void setContext(GLContext context); + + /** 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); + + /** FIXME: Returns the current state, + {@link #STATE_INVALID}, {@link #STATE_VALID} or {@link #STATE_DESTROYING}. + Tool to determine, e.g. if a {@link GLEventListener#dispose dispose(..)} + event is send in the context of the destruction of this GLAutoDrawable. + public int getCurrentState(); */ + + /** Destroys all resources associated with this GLAutoDrawable, + inclusive the GLContext. + If a window is attached to it's implementation, it shall be closed. + Causes disposing of all OpenGL resources + by calling {@link GLEventListener#dispose dispose(..)} for all + registered {@link GLEventListener}s. Called automatically by the + window system toolkit upon receiving a destroy notification. This + routine may be called manually. */ + public void destroy(); + + /** Causes OpenGL rendering to be performed for this GLAutoDrawable + by calling {@link GLEventListener#display display(..)} for all + registered {@link GLEventListener}s. Called automatically by the + window system toolkit upon receiving a repaint() request. this + routine may be called manually for better control over the + rendering process. It is legal to call another GLAutoDrawable's + display method from within the {@link GLEventListener#display + display(..)} callback.<p> + In case of a new generated OpenGL context, + the implementation shall call {@link GLEventListener#init init(..)} for all + registered {@link GLEventListener}s <i>before</i> making the + actual {@link GLEventListener#display display(..)} calls, + in case this has not been done yet.*/ + public void display(); + + /** Enables or disables automatic buffer swapping for this drawable. + By default this property is set to true; when true, after all + GLEventListeners have been called for a display() event, the + front and back buffers are swapped, displaying the results of + the render. When disabled, the user is responsible for calling + {@link #swapBuffers(..)} manually. */ + public void setAutoSwapBufferMode(boolean onOrOff); + + /** Indicates whether automatic buffer swapping is enabled for this + drawable. See {@link #setAutoSwapBufferMode}. */ + public boolean getAutoSwapBufferMode(); + + /** Returns the {@link GL} pipeline object this GLAutoDrawable uses. + If this method is called outside of the {@link + GLEventListener}'s callback methods (init, display, etc.) it may + return null. Users should not rely on the identity of the + returned GL object; for example, users should not maintain a + hash table with the GL object as the key. Additionally, the GL + object should not be cached in client code, but should be + re-fetched from the GLAutoDrawable at the beginning of each call + to init, display, etc. */ + public GL getGL(); + + /** Sets the {@link GL} pipeline object this GLAutoDrawable uses. + This should only be called from within the GLEventListener's + callback methods, and usually only from within the init() + method, in order to install a composable pipeline. See the JOGL + demos for examples. */ + public void setGL(GL gl); +} diff --git a/src/jogl/classes/javax/media/opengl/GLBase.java b/src/jogl/classes/javax/media/opengl/GLBase.java new file mode 100644 index 000000000..efd2eedd1 --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/GLBase.java @@ -0,0 +1,129 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + */ + +package javax.media.opengl; + +import java.nio.*; + +/** + * The base interface from which all GL profiles derive, providing + * checked conversion down to concrete profiles, and access to the + * OpenGL context associated with the GL. + */ +public interface GLBase { + + /** + * Indicates whether this GL object conforms to any of the common GL profiles. + * @return whether this GL object conforms to any of the common GL profiles + */ + public boolean isGL(); + + /** + * Indicates whether this GL object conforms to the GL3 profile. + * The GL3 profile reflects OpenGL versions greater or equal 3.1 + * @return whether this GL object conforms to the GL3 profile + */ + public boolean isGL3(); + + /** + * Indicates whether this GL object conforms to the GL2 profile. + * The GL2 profile reflects OpenGL versions greater or equal 1.5 + * @return whether this GL object conforms to the GL2 profile + */ + public boolean isGL2(); + + /** + * Indicates whether this GL object conforms to the GLES1 profile. + * @return whether this GL object conforms to the GLES1 profile + */ + public boolean isGLES1(); + + /** + * Indicates whether this GL object conforms to the GLES2 profile. + * @return whether this GL object conforms to the GLES2 profile + */ + public boolean isGLES2(); + + /** + * Indicates whether this GL object conforms to one of the OpenGL ES compatible profiles. + * @return whether this GL object conforms to one of the OpenGL ES profiles + */ + public boolean isGLES(); + + /** + * Indicates whether this GL object conforms to the GL2ES1 compatible profile. + * @return whether this GL object conforms to the GL2ES1 profile + */ + public boolean isGL2ES1(); + + /** + * Indicates whether this GL object conforms to the GL2ES2 compatible profile. + * @return whether this GL object conforms to the GL2ES2 profile + */ + public boolean isGL2ES2(); + + /** Indicates whether this GL object supports GLSL. */ + public boolean hasGLSL(); + + /** + * Casts this object to the GL interface. + * @return this object cast to the GL interface + * @throws GLException if this GLObject is not a GL implementation + */ + public GL getGL() throws GLException; + + /** + * Casts this object to the GL3 interface. + * @return this object cast to the GL3 interface + * @throws GLException if this GLObject is not a GL3 implementation + */ + public GL3 getGL3() throws GLException; + + /** + * Casts this object to the GL2 interface. + * @return this object cast to the GL2 interface + * @throws GLException if this GLObject is not a GL2 implementation + */ + public GL2 getGL2() throws GLException; + + /** + * Casts this object to the GLES1 interface. + * @return this object cast to the GLES1 interface + * @throws GLException if this GLObject is not a GLES1 implementation + */ + public GLES1 getGLES1() throws GLException; + + /** + * Casts this object to the GLES2 interface. + * @return this object cast to the GLES2 interface + * @throws GLException if this GLObject is not a GLES2 implementation + */ + public GLES2 getGLES2() throws GLException; + + /** + * Casts this object to the GL2ES1 interface. + * @return this object cast to the GL2ES1 interface + * @throws GLException if this GLObject is not a GL2ES1 implementation + */ + public GL2ES1 getGL2ES1() throws GLException; + + /** + * Casts this object to the GL2ES2 interface. + * @return this object cast to the GL2ES2 interface + * @throws GLException if this GLObject is not a GL2ES2 implementation + */ + public GL2ES2 getGL2ES2() throws GLException; + + /** + * Returns the GLContext with which this GL object is associated. + * @return the GLContext with which this GL object is associated + */ + public GLContext getContext(); + + /** + * Returns the GLProfile with which this GL object is associated. + * @return the GLProfile with which this GL object is associated + */ + public GLProfile getGLProfile(); +} diff --git a/src/jogl/classes/javax/media/opengl/GLCapabilities.java b/src/jogl/classes/javax/media/opengl/GLCapabilities.java new file mode 100644 index 000000000..37e35d4f0 --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/GLCapabilities.java @@ -0,0 +1,329 @@ +/* + * Copyright (c) 2003-2009 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package javax.media.opengl; + +import javax.media.nativewindow.Capabilities; + +/** Specifies a set of OpenGL capabilities.<br> + At creation time of a {@link GLDrawable} using {@link GLDrawableFactory}, + an instance of this class is passed, + describing the desired capabilities that a rendering context + must support, such as the OpenGL profile, color depth and whether stereo is enabled.<br> + + The actual capabilites of created {@link GLDrawable}s are then reflected by their own + GLCapabilites instance, which can be queried with {@link GLDrawable#getGLCapabilities()}.<br> + + It currently contains the minimal number of routines which allow + configuration on all supported window systems. */ +public class GLCapabilities extends Capabilities implements Cloneable { + private GLProfile glProfile = null; + private boolean doubleBuffered = true; + private boolean stereo = false; + private boolean hardwareAccelerated = true; + private int depthBits = 24; + private int stencilBits = 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 + + // Support for full-scene antialiasing (FSAA) + private boolean sampleBuffers = false; + private int numSamples = 2; + + // Bits for pbuffer creation + private boolean pbufferFloatingPointBuffers; + private boolean pbufferRenderToTexture; + private boolean pbufferRenderToTextureRectangle; + + /** Creates a GLCapabilities object. All attributes are in a default state. + * @param glp GLProfile, or null for the default GLProfile + */ + public GLCapabilities(GLProfile glp) { + glProfile = (null!=glp)?glp:GLProfile.getDefault(); + } + + public Object clone() { + try { + return super.clone(); + } catch (RuntimeException e) { + throw new GLException(e); + } + } + + public boolean equals(Object obj) { + if(!(obj instanceof GLCapabilities)) { + return false; + } + GLCapabilities other = (GLCapabilities)obj; + boolean res = super.equals(obj) && + other.getGLProfile()==glProfile && + other.getDoubleBuffered()==doubleBuffered && + other.getStereo()==stereo && + other.getHardwareAccelerated()==hardwareAccelerated && + other.getDepthBits()==depthBits && + other.getStencilBits()==stencilBits && + other.getAccumRedBits()==accumRedBits && + other.getAccumGreenBits()==accumGreenBits && + other.getAccumBlueBits()==accumBlueBits && + other.getAccumAlphaBits()==accumAlphaBits && + other.getSampleBuffers()==sampleBuffers && + other.getPbufferFloatingPointBuffers()==pbufferFloatingPointBuffers && + other.getPbufferRenderToTexture()==pbufferRenderToTexture && + other.getPbufferRenderToTextureRectangle()==pbufferRenderToTextureRectangle; + if(sampleBuffers) { + res = res && other.getNumSamples()==numSamples; + } + return res; + } + + /** Returns the GL profile you desire or used by the drawable. */ + public GLProfile getGLProfile() { + return glProfile; + } + + /** Sets the GL profile you desire */ + public void setGLProfile(GLProfile profile) { + glProfile=profile; + } + + /** 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 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; + } + + /** Indicates whether sample buffers for full-scene antialiasing + (FSAA) should be allocated for this drawable. Defaults to + false. */ + public void setSampleBuffers(boolean onOrOff) { + sampleBuffers = onOrOff; + } + + /** Returns whether sample buffers for full-scene antialiasing + (FSAA) should be allocated for this drawable. Defaults to + false. */ + public boolean getSampleBuffers() { + return sampleBuffers; + } + + /** If sample buffers are enabled, indicates the number of buffers + to be allocated. Defaults to 2. */ + public void setNumSamples(int numSamples) { + this.numSamples = numSamples; + } + + /** Returns the number of sample buffers to be allocated if sample + buffers are enabled. Defaults to 2. */ + public int getNumSamples() { + return numSamples; + } + + /** For pbuffers only, indicates whether floating-point buffers + should be used if available. Defaults to false. */ + public void setPbufferFloatingPointBuffers(boolean onOrOff) { + pbufferFloatingPointBuffers = onOrOff; + } + + /** For pbuffers only, returns whether floating-point buffers should + be used if available. Defaults to false. */ + public boolean getPbufferFloatingPointBuffers() { + return pbufferFloatingPointBuffers; + } + + /** For pbuffers only, indicates whether the render-to-texture + extension should be used if available. Defaults to false. */ + public void setPbufferRenderToTexture(boolean onOrOff) { + pbufferRenderToTexture = onOrOff; + } + + /** For pbuffers only, returns whether the render-to-texture + extension should be used if available. Defaults to false. */ + public boolean getPbufferRenderToTexture() { + return pbufferRenderToTexture; + } + + /** For pbuffers only, indicates whether the + render-to-texture-rectangle extension should be used if + available. Defaults to false. */ + public void setPbufferRenderToTextureRectangle(boolean onOrOff) { + pbufferRenderToTextureRectangle = onOrOff; + } + + /** For pbuffers only, returns whether the render-to-texture + extension should be used. Defaults to false. */ + public boolean getPbufferRenderToTextureRectangle() { + return pbufferRenderToTextureRectangle; + } + + /** Returns a textual representation of this GLCapabilities + object. */ + public String toString() { + StringBuffer msg = new StringBuffer(); + msg.append("GLCapabilities["); + msg.append(super.toString()); + msg.append(", GL profile: " + glProfile + + ", DoubleBuffered: " + doubleBuffered + + ", Stereo: " + stereo + + ", HardwareAccelerated: " + hardwareAccelerated + + ", DepthBits: " + depthBits + + ", StencilBits: " + stencilBits + + ", Red Accum: " + accumRedBits + + ", Green Accum: " + accumGreenBits + + ", Blue Accum: " + accumBlueBits + + ", Alpha Accum: " + accumAlphaBits + + ", Multisample: " + sampleBuffers + + ", Num samples: "+(sampleBuffers ? numSamples : 0)); + msg.append(", PBuffer-FloatingPointBuffers: "+pbufferFloatingPointBuffers+ + ", PBuffer-RenderToTexture: "+pbufferRenderToTexture+ + ", PBuffer-RenderToTextureRectangle: "+pbufferRenderToTextureRectangle+ "]"); + return msg.toString(); + } +} diff --git a/src/jogl/classes/javax/media/opengl/GLCapabilitiesChooser.java b/src/jogl/classes/javax/media/opengl/GLCapabilitiesChooser.java new file mode 100644 index 000000000..38cda8cdf --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/GLCapabilitiesChooser.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2003-2009 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package javax.media.opengl; + +import javax.media.nativewindow.CapabilitiesChooser; + +/** Provides a mechanism by which applications can customize the + window type selection for a given {@link GLCapabilities}. + Developers can implement this interface and pass an instance into + the appropriate method of {@link GLDrawableFactory}; the chooser + will be called during the OpenGL context creation process. Note + that this is only a marker interface; its signature is the same as + {@link CapabilitiesChooser}, but the array of {@link Capabilities} + objects passed to {@link #chooseCapabilities chooseCapabilities} + will actually be an array of {@link GLCapabilities}. */ + +public interface GLCapabilitiesChooser extends CapabilitiesChooser { +} diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java new file mode 100644 index 000000000..ef7fa8189 --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/GLContext.java @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package javax.media.opengl; + +import com.sun.opengl.impl.Debug; +import java.util.HashMap; + +/** Abstraction for an OpenGL rendering context. In order to perform + OpenGL rendering, a context must be "made current" on the current + thread. OpenGL rendering semantics specify that only one context + may be current on the current thread at any given time, and also + that a given context may be current on only one thread at any + given time. Because components can be added to and removed from + the component hierarchy at any time, it is possible that the + underlying OpenGL context may need to be destroyed and recreated + multiple times over the lifetime of a given component. This + process is handled by the implementation, and the GLContext + abstraction provides a stable object which clients can use to + refer to a given context. */ + +public abstract class GLContext { + protected static final boolean DEBUG = Debug.isPropertyDefined("jogl.debug.GLContext"); // Debug.debug("GLContext"); + + /** Indicates that the context was not made current during the last call to {@link #makeCurrent makeCurrent}. */ + public static final int CONTEXT_NOT_CURRENT = 0; + /** Indicates that the context was made current during the last call to {@link #makeCurrent makeCurrent}. */ + public static final int CONTEXT_CURRENT = 1; + /** Indicates that a newly-created context was made current during the last call to {@link #makeCurrent makeCurrent}. */ + public static final int CONTEXT_CURRENT_NEW = 2; + + private static ThreadLocal currentContext = new ThreadLocal(); + + private HashMap/*<int, Object>*/ attachedObjects = new HashMap(); + + /** + * Returns the GLDrawable to which this context may be used to + * draw. + */ + public abstract GLDrawable getGLDrawable(); + + /** + * Makes this GLContext current on the calling thread. + * + * There are two return values that indicate success and one that + * indicates failure. A return value of CONTEXT_CURRENT_NEW + * indicates that that context has been made current, and that + * this is the first time this context has been made current, or + * that the state of the underlying context or drawable may have + * changed since the last time this context was made current. In + * this case, the application may wish to initialize the state. A + * return value of CONTEXT_CURRENT indicates that the context has + * been made currrent, with its previous state restored. + * + * If the context could not be made current (for example, because + * the underlying drawable has not ben realized on the display) , + * a value of CONTEXT_NOT_CURRENT is returned. + * + * If the context is in use by another thread at the time of the + * call, then if isSynchronized() is true the call will + * block. If isSynchronized() is false, an exception will be + * thrown and the context will remain current on the other thread. + * + * @return CONTEXT_CURRENT if the context was successfully made current + * @return CONTEXT_CURRENT_NEW if the context was successfully made + * current, but need to be initialized. + * + * @return CONTEXT_NOT_CURRENT if the context could not be made current. + * + * @throws GLException if synchronization is disabled and the + * context is current on another thread, or because the context + * could not be created or made current due to non-recoverable, + * window system-specific errors. + */ + public abstract int makeCurrent() throws GLException; + + /** + * Releases control of this GLContext from the current thread. + * + * @throws GLException if the context had not previously been made + * current on the current thread + */ + public abstract void release() throws GLException; + + /** + * Copies selected groups of OpenGL state variables from the + * supplied source context into this one. The <code>mask</code> + * parameter indicates which groups of state variables are to be + * copied. <code>mask</code> contains the bitwise OR of the same + * symbolic names that are passed to the GL command {@link + * GL#glPushAttrib glPushAttrib}. The single symbolic constant + * {@link GL#GL_ALL_ATTRIB_BITS GL_ALL_ATTRIB_BITS} can be used to + * copy the maximum possible portion of rendering state. <P> + * + * Not all values for GL state can be copied. For example, pixel + * pack and unpack state, render mode state, and select and feedback + * state are not copied. The state that can be copied is exactly the + * state that is manipulated by the GL command {@link + * GL#glPushAttrib glPushAttrib}. <P> + * + * On most platforms, this context may not be current to any thread, + * including the calling thread, when this method is called. Some + * platforms have additional requirements such as whether this + * context or the source context must occasionally be made current + * in order for the results of the copy to be seen; these + * requirements are beyond the scope of this specification. + * + * @param source the source OpenGL context from which to copy state + * @param mask a mask of symbolic names indicating which groups of state to copy + + * @throws GLException if an OpenGL-related error occurred + */ + public abstract void copy(GLContext source, int mask) throws GLException; + + /** + * Returns the GL object bound to this thread current context. + * If no context is current, throw an GLException + * + * @return the current context's GL object on this thread + * @thows GLException if no context is current + */ + public static GL getCurrentGL() throws GLException { + GLContext glc = getCurrent(); + if(null==glc) { + throw new GLException("No OpenGL context current on this thread"); + } + return glc.getGL(); + } + + /** + * Returns this thread current context. + * If no context is current, returns null. + * + * @return the context current on this thread, or null if no context + * is current. + */ + public static GLContext getCurrent() { + return (GLContext) currentContext.get(); + } + + /** + * Sets the thread-local variable returned by {@link #getCurrent} + * and has no other side-effects. For use by third parties adding + * new GLContext implementations; not for use by end users. + */ + protected static void setCurrent(GLContext cur) { + if(DEBUG) { + Exception e = new Exception("setCurrent: "+Thread.currentThread()+", "+currentContext.get()+" -> "+cur); + e.printStackTrace(); + } + + currentContext.set(cur); + } + + /** + * Destroys this OpenGL context and frees its associated + * resources. The context should have been released before this + * method is called. + */ + public abstract void destroy(); + + /** + * Returns true if 'makeCurrent' will exhibit synchronized behavior. + */ + public abstract boolean isSynchronized(); + + /** + * Determines whether 'makeCurrent' will exhibit synchronized behavior. + */ + public abstract void setSynchronized(boolean isSynchronized); + + /** + * Returns the GL pipeline object for this GLContext. + */ + public abstract GL getGL(); + + /** + * Sets the GL pipeline object for this GLContext. + */ + public abstract void setGL(GL gl); + + /** + * Returns the attached user object for the given name to this GLContext. + */ + public Object getAttachedObject(int name) { + return attachedObjects.get(new Integer(name)); + } + + /** + * Returns the attached user object for the given name to this GLContext. + */ + public Object getAttachedObject(String name) { + return attachedObjects.get(name); + } + + /** + * Sets the attached user object for the given name to this GLContext. + * Returns the previously set object or null. + */ + public Object putAttachedObject(int name, Object obj) { + return attachedObjects.put(new Integer(name), obj); + } + + /** + * Sets the attached user object for the given name to this GLContext. + * Returns the previously set object or null. + */ + public Object putAttachedObject(String name, Object obj) { + return attachedObjects.put(name, obj); + } + + /** + * Classname, GL, GLDrawable + */ + public final String toString() { + return getClass().getName()+" ["+getGL()+ + ",\n\tDrawable: "+ getGLDrawable()+"] "; + } + + /** 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(); +} diff --git a/src/jogl/classes/javax/media/opengl/GLDrawable.java b/src/jogl/classes/javax/media/opengl/GLDrawable.java new file mode 100644 index 000000000..0cde24ff9 --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/GLDrawable.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package javax.media.opengl; + +import javax.media.nativewindow.*; + +/** An abstraction for an OpenGL rendering target. A GLDrawable's + primary functionality is to create OpenGL contexts which can be + used to perform rendering. A GLDrawable does not automatically + create an OpenGL context, but all implementations of {@link + GLAutoDrawable} do so upon creation. */ + +public interface GLDrawable { + /** + * Creates a new context for drawing to this drawable that will + * optionally share display lists and other server-side OpenGL + * objects with the specified GLContext. <P> + * + * The GLContext <code>share</code> need not be associated with this + * GLDrawable and may be null if sharing of display lists and other + * objects is not desired. See the note in the overview + * documentation on + * <a href="../../../overview-summary.html#SHARING">context sharing</a>. + */ + public GLContext createContext(GLContext shareWith); + + /** + * Indicates to on-screen GLDrawable implementations whether the + * underlying window has been created and can be drawn into. End + * users do not need to call this method; it is not necessary to + * call <code>setRealized</code> on a GLCanvas, a GLJPanel, or a + * GLPbuffer, as these perform the appropriate calls on their + * underlying GLDrawables internally. + * + * <P> + * + * Developers implementing new OpenGL components for various window + * toolkits need to call this method against GLDrawables obtained + * from the GLDrawableFactory via the {@link + * GLDrawableFactory#getGLDrawable + * GLDrawableFactory.getGLDrawable()} method. It must typically be + * called with an argument of <code>true</code> when the component + * associated with the GLDrawable is realized and with an argument + * of <code>false</code> just before the component is unrealized. + * For the AWT, this means calling <code>setRealized(true)</code> in + * the <code>addNotify</code> method and with an argument of + * <code>false</code> in the <code>removeNotify</code> method. + * + * <P> + * + * <code>GLDrawable</code> implementations should handle multiple + * cycles of <code>setRealized(true)</code> / + * <code>setRealized(false)</code> calls. Most, if not all, Java + * window toolkits have a persistent object associated with a given + * component, regardless of whether that component is currently + * realized. The <CODE>GLDrawable</CODE> object associated with a + * particular component is intended to be similarly persistent. A + * <CODE>GLDrawable</CODE> is intended to be created for a given + * component when it is constructed and live as long as that + * component. <code>setRealized</code> allows the + * <code>GLDrawable</code> to re-initialize and destroy any + * associated resources as the component becomes realized and + * unrealized, respectively. + * + * <P> + * + * With an argument of <code>true</code>, + * the minimum implementation shall call + * {@link NativeWindow#lockSurface() NativeWindow's lockSurface()} and if successfull: + * <ul> + * <li> Update the {@link GLCapabilities}, which are associated with + * the attached {@link NativeWindow}'s {@link AbstractGraphicsConfiguration}.</li> + * <li> Release the lock with {@link NativeWindow#unlockSurface() NativeWindow's unlockSurface()}.</li> + * </ul><br> + * This is important since {@link NativeWindow#lockSurface() NativeWindow's lockSurface()} + * ensures resolving the window/surface handles, and the drawable's {@link GLCapabilities} + * might have changed. + * + * <P> + * + * Calling this method has no other effects. For example, if + * <code>removeNotify</code> is called on a Canvas implementation + * for which a GLDrawable has been created, it is also necessary to + * destroy all OpenGL contexts associated with that GLDrawable. This + * is not done automatically by the implementation. + */ + public void setRealized(boolean realized); + + /** Returns the current width of this GLDrawable. */ + public int getWidth(); + + /** Returns the current height of this GLDrawable. */ + public int getHeight(); + + /** Swaps the front and back buffers of this drawable. For {@link + GLAutoDrawable} implementations, when automatic buffer swapping + is enabled (as is the default), this method is called + automatically and should not be called by the end user. */ + public void swapBuffers() throws GLException; + + /** Fetches the {@link GLCapabilities} corresponding to the chosen + OpenGL capabilities (pixel format / visual / GLProfile) for this drawable.<br> + On some platforms, the pixel format is not directly associated + with the drawable; a best attempt is made to return a reasonable + value in this case. <br> + This object shall be directly associated to the attached {@link NativeWindow}'s + {@link AbstractGraphicsConfiguration}, and if changes are necessary, + they should reflect those as well. + @return A copy of the queried object. + */ + public GLCapabilities getChosenGLCapabilities(); + + /** Fetches the {@link GLProfile} for this drawable. + Returns the GLProfile object, no copy. + */ + public GLProfile getGLProfile(); + + public NativeWindow getNativeWindow(); + + public GLDrawableFactory getFactory(); + + public String toString(); +} diff --git a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java new file mode 100644 index 000000000..5da62c30a --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package javax.media.opengl; + +import javax.media.nativewindow.*; + +import java.lang.reflect.*; +import java.security.*; +import com.sun.opengl.impl.*; +import com.sun.nativewindow.impl.NWReflection; + +/** <P> Provides a virtual machine- and operating system-independent + mechanism for creating {@link GLDrawable}s. </P> + + <P> The {@link javax.media.opengl.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. The GLCapabilitiesChooser mechanism may not be supported + by all implementations or on all platforms, in which case any + passed GLCapabilitiesChooser will be ignored. </P> + + <P> Because of the multithreaded nature of the Java platform's + Abstract Window 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. Pbuffers are always + created immediately and their creation will fail with a {@link + GLException} if errors occur. </P> + + <P> The concrete GLDrawableFactory subclass instantiated by {@link + #getFactory getFactory} can be changed by setting the system + property <code>opengl.factory.class.name</code> to the + fully-qualified name of the desired class. </P> +*/ + +public abstract class GLDrawableFactory { + /** Creates a new GLDrawableFactory instance. End users do not need + to call this method. */ + protected GLDrawableFactory() { + } + + private static final GLDrawableFactory eglFactory; + private static final GLDrawableFactory nativeOSFactory; + private static final String nativeOSType; + + /** + * Instantiate singleton factories if available, EGLES1, EGLES2 and the OS native ones. + */ + static { + GLDrawableFactory tmp = null; + try { + tmp = (GLDrawableFactory) NWReflection.createInstance("com.sun.opengl.impl.egl.EGLDrawableFactory"); + } catch (Throwable t) { + if (GLProfile.DEBUG) { + System.err.println("GLDrawableFactory.static - EGLDrawableFactory - not available"); + t.printStackTrace(); + } + } + eglFactory = tmp; + + nativeOSType = NativeWindowFactory.getNativeWindowType(false); + + String factoryClassName = null; + tmp = null; + try { + factoryClassName = + (String) AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + return System.getProperty("opengl.factory.class.name"); + } + }); + + if (null == factoryClassName) { + if ( nativeOSType.equals(NativeWindowFactory.TYPE_EGL) ) { + // use egl*Factory .. + } else if ( nativeOSType.equals(NativeWindowFactory.TYPE_X11) ) { + factoryClassName = "com.sun.opengl.impl.x11.glx.X11GLXDrawableFactory"; + } else if ( nativeOSType.equals(NativeWindowFactory.TYPE_WINDOWS) ) { + factoryClassName = "com.sun.opengl.impl.windows.wgl.WindowsWGLDrawableFactory"; + } else if ( nativeOSType.equals(NativeWindowFactory.TYPE_MACOSX) ) { + // FIXME: remove this residual dependence on the AWT + factoryClassName = "com.sun.opengl.impl.macosx.cgl.awt.MacOSXAWTCGLDrawableFactory"; + } else { + throw new GLException("Unsupported NativeWindow type: "+nativeOSType); + } + } + if (null != factoryClassName) { + tmp = (GLDrawableFactory) NWReflection.createInstance(factoryClassName); + } + } catch (Throwable t) { + if (GLProfile.DEBUG) { + System.err.println("GLDrawableFactory.static - Native Platform: "+nativeOSType+" - not available: "+factoryClassName); + t.printStackTrace(); + } + } + nativeOSFactory = tmp; + } + + /** + * Returns the sole GLDrawableFactory instance. + * + * @arg glProfile GLProfile to determine the factory type, ie EGLDrawableFactory, + * or one of the native GLDrawableFactory's, ie X11/GLX, Windows/WGL or MacOSX/CGL. + */ + public static GLDrawableFactory getFactory(GLProfile glProfile) throws GLException { + return getFactoryImpl(glProfile.getImplName()); + } + + protected static GLDrawableFactory getFactoryImpl(String glProfileImplName) throws GLException { + if ( GLProfile.usesNativeGLES(glProfileImplName) ) { + if(null==eglFactory) throw new GLException("GLDrawableFactory unavailable for EGL: "+glProfileImplName); + return eglFactory; + } + if(null==nativeOSFactory) throw new GLException("GLDrawableFactory unavailable for Native Platform "+nativeOSType); + return nativeOSFactory; + } + + /** Shuts down this GLDrawableFactory, releasing resources + associated with it. Before calling this method you should first + destroy any GLContexts and GLDrawables that have been created + and are still in use. No further OpenGL calls may be made after + shutting down the GLDrawableFactory. */ + public void shutdown() { + } + + /** + * Returns a GLDrawable that wraps a platform-specific window system + * object, such as an AWT or LCDUI Canvas. + * On platforms which support pixel format, the NativeWindow's AbstractGraphicsConfiguration + * is being used. + * support it, selects a pixel format compatible with the supplied + * GLCapabilities, or if the passed GLCapabilities object is null, + * uses a default set of capabilities. On these platforms, uses + * either the supplied GLCapabilitiesChooser object, or if the + * passed GLCapabilitiesChooser object is null, uses a + * DefaultGLCapabilitiesChooser instance. + * + * @throws IllegalArgumentException if the passed target is null + * @throws GLException if any window system-specific errors caused + * the creation of the GLDrawable to fail. + * + * @see javax.media.nativewindow.GraphicsConfigurationFactory#chooseGraphicsConfiguration(Capabilities, CapabilitiesChooser, AbstractGraphicsScreen) + */ + public abstract GLDrawable createGLDrawable(NativeWindow target) + throws IllegalArgumentException, GLException; + + //---------------------------------------------------------------------- + // Methods to create high-level objects + + /** + * Returns true if it is possible to create a GLPbuffer. Some older + * graphics cards do not have this capability. + */ + public abstract boolean canCreateGLPbuffer(); + + /** + * Creates a GLPbuffer with the given capabilites and dimensions. <P> + * + * See the note in the overview documentation on + * <a href="../../../overview-summary.html#SHARING">context sharing</a>. + * + * @throws GLException if any window system-specific errors caused + * the creation of the GLPbuffer to fail. + */ + public abstract GLPbuffer createGLPbuffer(GLCapabilities capabilities, + GLCapabilitiesChooser chooser, + int initialWidth, + int initialHeight, + GLContext shareWith) + throws GLException; + + //---------------------------------------------------------------------- + // Methods for interacting with third-party OpenGL libraries + + /** + * <P> Creates a GLContext object representing an existing OpenGL + * context in an external (third-party) OpenGL-based library. This + * GLContext object may be used to draw into this preexisting + * context using its {@link GL} and {@link + * javax.media.opengl.glu.GLU} objects. New contexts created through + * {@link GLDrawable}s may share textures and display lists with + * this external context. </P> + * + * <P> The underlying OpenGL context must be current on the current + * thread at the time this method is called. The user is responsible + * for the maintenance of the underlying OpenGL context; calls to + * <code>makeCurrent</code> and <code>release</code> on the returned + * GLContext object have no effect. If the underlying OpenGL context + * is destroyed, the <code>destroy</code> method should be called on + * the <code>GLContext</code>. A new <code>GLContext</code> object + * should be created for each newly-created underlying OpenGL + * context. + * + * @throws GLException if any window system-specific errors caused + * the creation of the external GLContext to fail. + */ + public abstract GLContext createExternalGLContext() + throws GLException; + + /** + * Returns true if it is possible to create an external GLDrawable + * object via {@link #createExternalGLDrawable}. + */ + public abstract boolean canCreateExternalGLDrawable(); + + /** + * <P> Creates a {@link GLDrawable} object representing an existing + * OpenGL drawable in an external (third-party) OpenGL-based + * library. This GLDrawable object may be used to create new, + * fully-functional {@link GLContext}s on the OpenGL drawable. This + * is useful when interoperating with a third-party OpenGL-based + * library and it is essential to not perturb the state of the + * library's existing context, even to the point of not sharing + * textures or display lists with that context. </P> + * + * <P> An underlying OpenGL context must be current on the desired + * drawable and the current thread at the time this method is + * called. The user is responsible for the maintenance of the + * underlying drawable. If one or more contexts are created on the + * drawable using {@link GLDrawable#createContext}, and the drawable + * is deleted by the third-party library, the user is responsible + * for calling {@link GLContext#destroy} on these contexts. </P> + * + * <P> Calls to <code>setSize</code>, <code>getWidth</code> and + * <code>getHeight</code> are illegal on the returned GLDrawable. If + * these operations are required by the user, they must be performed + * by the third-party library. </P> + * + * <P> It is legal to create both an external GLContext and + * GLDrawable representing the same third-party OpenGL entities. + * This can be used, for example, to query current state information + * using the external GLContext and then create and set up new + * GLContexts using the external GLDrawable. </P> + * + * <P> This functionality may not be available on all platforms and + * {@link #canCreateExternalGLDrawable} should be called first to + * see if it is present. For example, on X11 platforms, this API + * requires the presence of GLX 1.3 or later. + * + * @throws GLException if any window system-specific errors caused + * the creation of the external GLDrawable to fail. + */ + public abstract GLDrawable createExternalGLDrawable() + throws GLException; +} diff --git a/src/jogl/classes/javax/media/opengl/GLEventListener.java b/src/jogl/classes/javax/media/opengl/GLEventListener.java new file mode 100644 index 000000000..15fae4a39 --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/GLEventListener.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package javax.media.opengl; + +import java.util.EventListener; + +/** Declares events which client code can use to manage OpenGL + rendering into a {@link GLAutoDrawable}. 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. Can be used to perform one-time OpenGL + initialization per GLContext, such as setup of lights and display lists.<p> + + Note that this method may be called more than once if the underlying + OpenGL context for the GLAutoDrawable is destroyed and + recreated, for example if a GLCanvas is removed from the widget + hierarchy and later added again. + */ + public void init(GLAutoDrawable drawable); + + /** Notifies the listener to perform the release of all OpenGL + resources per GLContext, such as memory buffers and GLSL programs.<P> + + Called by the drawable before the OpenGL context is + destroyed by an external event, like a reconfiguration of the + {@link GLAutoDrawable} closing an attached window, + but also manually by calling {@link GLAutoDrawable#destroy destroy}.<P> + + Note that this event does not imply the end of life of the application. + It could be produced with a followup call to {@link #init(GLAutoDrawable)} + in case the GLContext has been recreated, + e.g. due to a pixel configuration change in a multihead environment. + */ + public void dispose(GLAutoDrawable drawable); + + /** Called by the drawable to initiate OpenGL rendering by the + client. After all GLEventListeners have been notified of a + display event, the drawable will swap its buffers if {@link + GLAutoDrawable#setAutoSwapBufferMode setAutoSwapBufferMode} is + enabled. */ + public void display(GLAutoDrawable drawable); + + /** Called by the drawable during the first repaint after the + component has been resized. The client can update the viewport + and view volume of the window appropriately, for example by a + call to {@link javax.media.opengl.GL#glViewport}; note that for + convenience the component has already called <code>glViewport(x, + y, width, height)</code> when this method is called, so the + client may not have to do anything in this method. + */ + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height); +} diff --git a/src/jogl/classes/javax/media/opengl/GLException.java b/src/jogl/classes/javax/media/opengl/GLException.java new file mode 100644 index 000000000..644042e15 --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/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 + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package javax.media.opengl; + +/** 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/jogl/classes/javax/media/opengl/GLPbuffer.java b/src/jogl/classes/javax/media/opengl/GLPbuffer.java new file mode 100644 index 000000000..0250365b0 --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/GLPbuffer.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package javax.media.opengl; + +/** Provides offscreen rendering support via pbuffers. The principal + addition of this interface is a {@link #destroy} method to + deallocate the pbuffer and its associated resources. It also + contains experimental methods for accessing the pbuffer's contents + as a texture map and enabling rendering to floating-point frame + buffers. These methods are not guaranteed to be supported on all + platforms and may be deprecated in a future release. */ + +public interface GLPbuffer extends GLAutoDrawable { + /** Indicates the GL_APPLE_float_pixels extension is being used for this pbuffer. */ + public static final int APPLE_FLOAT = 1; + + /** Indicates the GL_ATI_texture_float extension is being used for this pbuffer. */ + public static final int ATI_FLOAT = 2; + + /** Indicates the GL_NV_float_buffer extension is being used for this pbuffer. */ + public static final int NV_FLOAT = 3; + + /** Binds this pbuffer to its internal texture target. Only valid to + call if offscreen render-to-texture has been specified in the + NWCapabilities 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(); + + /** Destroys the native resources associated with this pbuffer. It + is not valid to call display() or any other routines on this + pbuffer after it has been destroyed. Before destroying the + pbuffer, the application must destroy any additional OpenGL + contexts which have been created for the pbuffer via {@link + #createContext}. */ + public void destroy(); + + /** Indicates which vendor's extension is being used to support + floating point channels in this pbuffer if that capability was + requested in the NWCapabilities during pbuffer creation. Returns + one of NV_FLOAT, ATI_FLOAT or APPLE_FLOAT, or throws GLException + if floating-point channels were not requested for this pbuffer. + This function may only be called once the init method for this + pbuffer's GLEventListener has been called. */ + public int getFloatingPointMode(); +} diff --git a/src/jogl/classes/javax/media/opengl/GLProfile.java b/src/jogl/classes/javax/media/opengl/GLProfile.java new file mode 100644 index 000000000..57f4fb46a --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/GLProfile.java @@ -0,0 +1,836 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + */ + +package javax.media.opengl; + +import javax.media.opengl.fixedfunc.*; +import java.lang.reflect.*; +import java.util.HashMap; +import java.security.*; +import com.sun.opengl.impl.*; +import com.sun.nativewindow.impl.NWReflection; + +/** + * Specifies the the OpenGL profile. + * + * This class static singleton initialization queries the availability of all OpenGL Profiles + * and instantiates singleton GLProfile objects for each available profile. + * + * The platform default profile may be used, using {@link GLProfile#GetProfileDefault()}, + * or more specialized versions using the other static GetProfile methods. + */ +public class GLProfile implements Cloneable { + public static final boolean DEBUG = Debug.debug("GLProfile"); + + // + // Public (user-visible) profiles + // + + /** The desktop OpenGL profile 3.x, with x >= 1 */ + public static final String GL3 = "GL3"; + + /** The desktop OpenGL profile 1.x up to 3.0 */ + public static final String GL2 = "GL2"; + + /** The embedded OpenGL profile ES 1.x, with x >= 0 */ + public static final String GLES1 = "GLES1"; + + /** The embedded OpenGL profile ES 2.x, with x >= 0 */ + public static final String GLES2 = "GLES2"; + + /** The intersection of the desktop GL2 and embedded ES1 profile */ + public static final String GL2ES1 = "GL2ES1"; + + /** The intersection of the desktop GL3, GL2 and embedded ES2 profile */ + public static final String GL2ES2 = "GL2ES2"; + + /** + * All GL Profiles in the order of default detection: GL2, GL2ES2, GL2ES1, GLES2, GLES1, GL3 + */ + public static final String[] GL_PROFILE_LIST_ALL = new String[] { GL2, GL2ES2, GL2ES1, GLES2, GLES1, GL3 }; + + /** + * All GL2ES2 Profiles in the order of default detection: GL2ES2, GL2, GLES2, GL3 + */ + public static final String[] GL_PROFILE_LIST_GL2ES2 = new String[] { GL2ES2, GL2, GLES2, GL3 }; + + /** + * All GL2ES1 Profiles in the order of default detection: GL2ES1, GL2, GLES1 + */ + public static final String[] GL_PROFILE_LIST_GL2ES1 = new String[] { GL2ES1, GL2, GLES1 }; + + /** Returns a default GLProfile object, reflecting the best for the running platform. + * It selects the first of the set {@link GLProfile#GL_PROFILE_LIST_ALL} + */ + public static final GLProfile getDefault() { + if(null==defaultGLProfile) { + throw new GLException("No default profile available"); // should never be reached + } + return defaultGLProfile; + } + + /** Returns a GLProfile object. + * Verfifies the given profile and chooses an apropriate implementation. + * + * @throws GLException if no implementation for the given profile is found. + */ + public static final GLProfile get(String profile) + throws GLException + { + if(null==profile) return getDefault(); + GLProfile glProfile = (GLProfile) mappedProfiles.get(profile); + if(null==glProfile) { + throw new GLException("No implementation for profile "+profile+" available"); + } + return glProfile; + } + + /** + * Returns a profile, implementing the interface GL2ES1. + * It selects the first of the set: {@link GLProfile#GL_PROFILE_LIST_GL2ES1} + * + * @throws GLException if no implementation for the given profile is found. + */ + public static final GLProfile getGL2ES1() + throws GLException + { + return get(GL_PROFILE_LIST_GL2ES1); + } + + /** + * Returns a profile, implementing the interface GL2ES2. + * It selects the first of the set: {@link GLProfile#GL_PROFILE_LIST_GL2ES2} + * + * @throws GLException if no implementation for the given profile is found. + */ + public static final GLProfile getGL2ES2() + throws GLException + { + return get(GL_PROFILE_LIST_GL2ES2); + } + + /** + * Returns the first profile from the given list, + * where an implementation is available. + * + * @throws GLException if no implementation for the given profile is found. + */ + public static final GLProfile get(String[] profiles) + throws GLException + { + for(int i=0; i<profiles.length; i++) { + String profile = profiles[i]; + GLProfile glProfile = (GLProfile) mappedProfiles.get(profile); + if(null!=glProfile) { + return glProfile; + } + } + throw new GLException("Profiles "+list2String(profiles)+" not available"); + } + + /** Indicates whether the native OpenGL ES1 profile is in use. + * This requires an EGL interface. + */ + public static final boolean usesNativeGLES1(String profileImpl) { + return GLES1.equals(profileImpl) || GL2ES1.equals(profileImpl) ; + } + + /** Indicates whether the native OpenGL ES2 profile is in use. + * This requires an EGL interface. + */ + public static final boolean usesNativeGLES2(String profileImpl) { + return GLES2.equals(profileImpl) || GL2ES2.equals(profileImpl) ; + } + + /** Indicates whether either of the native OpenGL ES profiles are in use. */ + public static final boolean usesNativeGLES(String profileImpl) { + return usesNativeGLES2(profileImpl) || usesNativeGLES1(profileImpl); + } + + private static final String getGLImplBaseClassName(String profileImpl) { + if(GL3.equals(profileImpl)) { + return "com.sun.opengl.impl.gl3.GL3"; + } else if(GL2.equals(profileImpl)) { + return "com.sun.opengl.impl.gl2.GL2"; + } else if(GL2ES12.equals(profileImpl)) { + return "com.sun.opengl.impl.gl2es12.GL2ES12"; + } else if(GLES1.equals(profileImpl) || GL2ES1.equals(profileImpl)) { + return "com.sun.opengl.impl.es1.GLES1"; + } else if(GLES2.equals(profileImpl) || GL2ES2.equals(profileImpl)) { + return "com.sun.opengl.impl.es2.GLES2"; + } else { + throw new GLException("unsupported profile \"" + profileImpl + "\""); + } + } + + public final String getGLImplBaseClassName() { + return getGLImplBaseClassName(profileImpl); + } + + public Object clone() { + try { + return super.clone(); + } catch (Exception e) { + throw new GLException(e); + } + } + + /** + * @param o GLProfile object to compare with + * @return true if given Object is a GLProfile and + * if both, profile and profileImpl is equal with this. + */ + public final boolean equals(Object o) { + if(o instanceof GLProfile) { + GLProfile glp = (GLProfile)o; + return profile.equals(glp.getName()) && + profileImpl.equals(glp.getImplName()) ; + } + return false; + } + + /** + * @param glp GLProfile to compare with + * @throws GLException if given GLProfile and this aren't equal + */ + public final void verifyEquality(GLProfile glp) + throws GLException + { + if(!this.equals(glp)) throw new GLException("GLProfiles are not equal: "+this+" != "+glp); + } + + public final String getName() { + return profile; + } + + public final String getImplName() { + return profileImpl; + } + + /** Indicates whether this profile is capable of GL3. */ + public final boolean isGL3() { + return GL3.equals(profile); + } + + /** Indicates whether this profile is capable of GL2. */ + public final boolean isGL2() { + return GL2.equals(profile); + } + + /** Indicates whether this profile is capable of GLES1. */ + public final boolean isGLES1() { + return GLES1.equals(profile); + } + + /** Indicates whether this profile is capable of GLES2. */ + public final boolean isGLES2() { + return GLES2.equals(profile); + } + + /** Indicates whether this profile is capable of GL2ES1. */ + public final boolean isGL2ES1() { + return GL2ES1.equals(profile) || isGL2() || isGLES1() ; + } + + /** Indicates whether this profile is capable os GL2ES2. */ + public final boolean isGL2ES2() { + return GL2ES2.equals(profile) || isGL2() || isGL3() || isGLES2() ; + } + + /** Indicates whether this profile uses the native OpenGL ES1 implementations. */ + public final boolean usesNativeGLES1() { + return GLES1.equals(profileImpl) || GL2ES1.equals(profileImpl) ; + } + + /** Indicates whether this profile uses the native OpenGL ES2 implementations. */ + public final boolean usesNativeGLES2() { + return GLES2.equals(profileImpl) || GL2ES2.equals(profileImpl) ; + } + + /** Indicates whether this profile uses either of the native OpenGL ES implementations. */ + public final boolean usesNativeGLES() { + return usesNativeGLES2() || usesNativeGLES1(); + } + + /** Indicates whether this profile supports GLSL. */ + public final boolean hasGLSL() { + return isGL2ES2() ; + } + + /** + * General validation if type is a valid GL data type + * for the current profile + */ + public boolean isValidDataType(int type, boolean throwException) { + switch(type) { + case GL.GL_UNSIGNED_BYTE: + case GL.GL_BYTE: + case GL.GL_UNSIGNED_SHORT: + case GL.GL_SHORT: + case GL.GL_FLOAT: + case GL.GL_FIXED: + return true; + case javax.media.opengl.GL2ES2.GL_INT: + case javax.media.opengl.GL2ES2.GL_UNSIGNED_INT: + if( isGL2ES2() ) { + return true; + } + case javax.media.opengl.GL2.GL_DOUBLE: + if( isGL3() ) { + return true; + } + case javax.media.opengl.GL2.GL_2_BYTES: + case javax.media.opengl.GL2.GL_3_BYTES: + case javax.media.opengl.GL2.GL_4_BYTES: + if( isGL2() ) { + return true; + } + } + if(throwException) { + throw new GLException("Illegal data type on profile "+this+": "+type); + } + return false; + } + + public boolean isValidArrayDataType(int index, int comps, int type, + boolean isVertexAttribPointer, boolean throwException) { + String arrayName = getGLArrayName(index); + if(isGLES1()) { + if(isVertexAttribPointer) { + if(throwException) { + throw new GLException("Illegal array type for "+arrayName+" on profile GLES1: VertexAttribPointer"); + } + return false; + } + switch(index) { + case GLPointerFunc.GL_VERTEX_ARRAY: + case GLPointerFunc.GL_TEXTURE_COORD_ARRAY: + switch(type) { + case GL.GL_BYTE: + case GL.GL_SHORT: + case GL.GL_FIXED: + case GL.GL_FLOAT: + break; + default: + if(throwException) { + throw new GLException("Illegal data type for "+arrayName+" on profile GLES1: "+type); + } + return false; + } + switch(comps) { + case 0: + case 2: + case 3: + case 4: + break; + default: + if(throwException) { + throw new GLException("Illegal component number for "+arrayName+" on profile GLES1: "+comps); + } + return false; + } + break; + case GLPointerFunc.GL_NORMAL_ARRAY: + switch(type) { + case GL.GL_BYTE: + case GL.GL_SHORT: + case GL.GL_FIXED: + case GL.GL_FLOAT: + break; + default: + if(throwException) { + throw new GLException("Illegal data type for "+arrayName+" on profile GLES1: "+type); + } + return false; + } + switch(comps) { + case 0: + case 3: + break; + default: + if(throwException) { + throw new GLException("Illegal component number for "+arrayName+" on profile GLES1: "+comps); + } + return false; + } + break; + case GLPointerFunc.GL_COLOR_ARRAY: + switch(type) { + case GL.GL_UNSIGNED_BYTE: + case GL.GL_FIXED: + case GL.GL_FLOAT: + break; + default: + if(throwException) { + throw new GLException("Illegal data type for "+arrayName+" on profile GLES1: "+type); + } + return false; + } + switch(comps) { + case 0: + case 4: + break; + default: + if(throwException) { + throw new GLException("Illegal component number for "+arrayName+" on profile GLES1: "+comps); + } + return false; + } + break; + } + } else if(isGLES2()) { + // simply ignore !isVertexAttribPointer case, since it is simulated anyway .. + switch(type) { + case GL.GL_UNSIGNED_BYTE: + case GL.GL_BYTE: + case GL.GL_UNSIGNED_SHORT: + case GL.GL_SHORT: + case GL.GL_FLOAT: + case GL.GL_FIXED: + break; + default: + if(throwException) { + throw new GLException("Illegal data type for "+arrayName+" on profile GLES2: "+type); + } + return false; + } + switch(comps) { + case 0: + case 1: + case 2: + case 3: + case 4: + break; + default: + if(throwException) { + throw new GLException("Illegal component number for "+arrayName+" on profile GLES1: "+comps); + } + return false; + } + } else if( isGL2ES2() ) { + if(isVertexAttribPointer) { + switch(type) { + case GL.GL_UNSIGNED_BYTE: + case GL.GL_BYTE: + case GL.GL_UNSIGNED_SHORT: + case GL.GL_SHORT: + case GL.GL_FLOAT: + case javax.media.opengl.GL2ES2.GL_INT: + case javax.media.opengl.GL2ES2.GL_UNSIGNED_INT: + case javax.media.opengl.GL2.GL_DOUBLE: + break; + default: + if(throwException) { + throw new GLException("Illegal data type for "+arrayName+" on profile GL2: "+type); + } + return false; + } + switch(comps) { + case 0: + case 1: + case 2: + case 3: + case 4: + break; + default: + if(throwException) { + throw new GLException("Illegal component number for "+arrayName+" on profile GL2: "+comps); + } + return false; + } + } else { + switch(index) { + case GLPointerFunc.GL_VERTEX_ARRAY: + switch(type) { + case GL.GL_SHORT: + case GL.GL_FLOAT: + case javax.media.opengl.GL2ES2.GL_INT: + case javax.media.opengl.GL2.GL_DOUBLE: + break; + default: + if(throwException) { + throw new GLException("Illegal data type for "+arrayName+" on profile GL2: "+type); + } + return false; + } + switch(comps) { + case 0: + case 2: + case 3: + case 4: + break; + default: + if(throwException) { + throw new GLException("Illegal component number for "+arrayName+" on profile GL2: "+comps); + } + return false; + } + break; + case GLPointerFunc.GL_NORMAL_ARRAY: + switch(type) { + case GL.GL_BYTE: + case GL.GL_SHORT: + case GL.GL_FLOAT: + case javax.media.opengl.GL2ES2.GL_INT: + case javax.media.opengl.GL2.GL_DOUBLE: + break; + default: + if(throwException) { + throw new GLException("Illegal data type for "+arrayName+" on profile GL2: "+type); + } + return false; + } + switch(comps) { + case 0: + case 3: + break; + default: + if(throwException) { + throw new GLException("Illegal component number for "+arrayName+" on profile GLES1: "+comps); + } + return false; + } + break; + case GLPointerFunc.GL_COLOR_ARRAY: + switch(type) { + case GL.GL_UNSIGNED_BYTE: + case GL.GL_BYTE: + case GL.GL_UNSIGNED_SHORT: + case GL.GL_SHORT: + case GL.GL_FLOAT: + case javax.media.opengl.GL2ES2.GL_INT: + case javax.media.opengl.GL2ES2.GL_UNSIGNED_INT: + case javax.media.opengl.GL2.GL_DOUBLE: + break; + default: + if(throwException) { + throw new GLException("Illegal data type for "+arrayName+" on profile GL2: "+type); + } + return false; + } + switch(comps) { + case 0: + case 3: + case 4: + break; + default: + if(throwException) { + throw new GLException("Illegal component number for "+arrayName+" on profile GL2: "+comps); + } + return false; + } + break; + case GLPointerFunc.GL_TEXTURE_COORD_ARRAY: + switch(type) { + case GL.GL_SHORT: + case GL.GL_FLOAT: + case javax.media.opengl.GL2ES2.GL_INT: + case javax.media.opengl.GL2.GL_DOUBLE: + break; + default: + if(throwException) { + throw new GLException("Illegal data type for "+arrayName+" on profile GL2: "+type); + } + return false; + } + switch(comps) { + case 0: + case 1: + case 2: + case 3: + case 4: + break; + default: + if(throwException) { + throw new GLException("Illegal component number for "+arrayName+" on profile GL2: "+comps); + } + return false; + } + break; + } + } + } + return true; + } + + public String toString() { + return "GLProfile[" + profile + "/" + profileImpl + "]"; + } + + // The intersection between desktop OpenGL and the union of the OpenGL ES profiles + // This is here only to avoid having separate GL2ES1Impl and GL2ES2Impl classes + private static final String GL2ES12 = "GL2ES12"; + + private static final boolean hasGL3Impl; + private static final boolean hasGL2Impl; + private static final boolean hasGL2ES12Impl; + private static final boolean hasGLES2Impl; + private static final boolean hasGLES1Impl; + + /** The JVM/process wide default GL profile **/ + private static GLProfile defaultGLProfile; + + /** All GLProfiles */ + private static final HashMap/*<String, GLProfile>*/ mappedProfiles; + + /** + * Tries the profiles implementation and native libraries. + * Throws an GLException if no profile could be found at all. + */ + static { + boolean hasDesktopGL = false; + boolean hasDesktopGLES12 = false; + boolean hasNativeOSFactory = false; + + try { + // See DRIHack.java for an explanation of why this is necessary + DRIHack.begin(); + NativeLibLoader.loadGLDesktop(); + DRIHack.end(); + hasDesktopGL = true; + } catch (Throwable t) { + if (DEBUG) { + System.err.println("GLProfile.static Desktop GL Library not available"); + t.printStackTrace(); + } + } + + try { + // See DRIHack.java for an explanation of why this is necessary + DRIHack.begin(); + NativeLibLoader.loadGLDesktopES12(); + DRIHack.end(); + hasDesktopGLES12 = true; + } catch (Throwable t) { + if (DEBUG) { + System.err.println("GLProfile.static Desktop GL ES12 Library not available"); + t.printStackTrace(); + } + } + + if(hasDesktopGL||hasDesktopGLES12) { + try { + hasNativeOSFactory = null!=GLDrawableFactory.getFactoryImpl(GL2); + } catch (Throwable t) { + if (DEBUG) { + System.err.println("GLProfile.static - Native platform GLDrawable factory not available"); + t.printStackTrace(); + } + } + } + + if(!hasNativeOSFactory) { + hasDesktopGLES12=false; + hasDesktopGL=false; + } + + // FIXME: check for real GL3 availability .. ? + hasGL3Impl = hasDesktopGL && NWReflection.isClassAvailable("com.sun.opengl.impl.gl3.GL3Impl"); + hasGL2Impl = hasDesktopGL && NWReflection.isClassAvailable("com.sun.opengl.impl.gl2.GL2Impl"); + + hasGL2ES12Impl = hasDesktopGLES12 && NWReflection.isClassAvailable("com.sun.opengl.impl.gl2es12.GL2ES12Impl"); + + boolean btest = false; + + boolean hasEGLDynLookup = NWReflection.isClassAvailable("com.sun.opengl.impl.egl.EGLDynamicLookupHelper"); + boolean hasEGLDrawableFactory = false; + try { + if(hasEGLDynLookup) { + hasEGLDrawableFactory = null!=GLDrawableFactory.getFactoryImpl(GLES2); + btest = hasEGLDrawableFactory && + NWReflection.isClassAvailable("com.sun.opengl.impl.es2.GLES2Impl") && + null!=com.sun.opengl.impl.egl.EGLDynamicLookupHelper.getDynamicLookupHelper(2); + } + } catch (Throwable t) { + if (DEBUG) { + System.err.println("GLProfile.static - GL ES2 Factory/Library not available"); + t.printStackTrace(); + } + } + hasGLES2Impl = btest; + + btest = false; + try { + if(hasEGLDynLookup) { + btest = hasEGLDrawableFactory && + NWReflection.isClassAvailable("com.sun.opengl.impl.es1.GLES1Impl") && + null!=com.sun.opengl.impl.egl.EGLDynamicLookupHelper.getDynamicLookupHelper(1); + } + } catch (Throwable t) { + if (DEBUG) { + System.err.println("GLProfile.static - GL ES1 Factory/Library not available"); + t.printStackTrace(); + } + } + hasGLES1Impl = btest; + + if (DEBUG) { + System.err.println("GLProfile.static hasNativeOSFactory "+hasNativeOSFactory); + System.err.println("GLProfile.static hasDesktopGLES12 "+hasDesktopGLES12); + System.err.println("GLProfile.static hasDesktopGL "+hasDesktopGL); + System.err.println("GLProfile.static hasGL3Impl "+hasGL3Impl); + System.err.println("GLProfile.static hasGL2Impl "+hasGL2Impl); + System.err.println("GLProfile.static hasGL2ES12Impl "+hasGL2ES12Impl); + System.err.println("GLProfile.static hasGLES2Impl "+hasGLES2Impl); + System.err.println("GLProfile.static hasGLES1Impl "+hasGLES1Impl); + } + + HashMap/*<String, GLProfile>*/ _mappedProfiles = new HashMap(GL_PROFILE_LIST_ALL.length); + for(int i=0; i<GL_PROFILE_LIST_ALL.length; i++) { + String profile = GL_PROFILE_LIST_ALL[i]; + String profileImpl = computeProfileImpl(profile); + if(null!=profileImpl) { + GLProfile glProfile = new GLProfile(profile, profileImpl); + _mappedProfiles.put(profile, glProfile); + if (DEBUG) { + System.err.println("GLProfile.static map "+glProfile); + } + if(null==defaultGLProfile) { + defaultGLProfile=glProfile; + if (DEBUG) { + System.err.println("GLProfile.static default "+glProfile); + } + } + } else { + if (DEBUG) { + System.err.println("GLProfile.static map *** no mapping for "+profile); + } + } + } + mappedProfiles = _mappedProfiles; // final .. + if(null==defaultGLProfile) { + throw new GLException("No profile available: "+list2String(GL_PROFILE_LIST_ALL)); + } + } + + private static final String list2String(String[] list) { + StringBuffer msg = new StringBuffer(); + msg.append("["); + for (int i = 0; i < list.length; i++) { + if (i > 0) + msg.append(", "); + msg.append(list[i]); + } + msg.append("]"); + return msg.toString(); + } + + /** + * Returns the profile implementation + */ + private static String computeProfileImpl(String profile) { + if (GL2ES1.equals(profile)) { + if(hasGL2Impl) { + return GL2; + } else if(hasGL2ES12Impl) { + return GL2ES12; + } else if(hasGLES1Impl) { + return GLES1; + } + } else if (GL2ES2.equals(profile)) { + if(hasGL2ES12Impl) { + return GL2ES12; + } else if(hasGL2Impl) { + return GL2; + } else if(hasGL3Impl) { + return GL3; + } else if(hasGLES2Impl) { + return GLES2; + } + } else if(GL3.equals(profile) && hasGL3Impl) { + return GL3; + } else if(GL2.equals(profile) && hasGL2Impl) { + return GL2; + } else if(GLES2.equals(profile) && hasGLES2Impl) { + return GLES2; + } else if(GLES1.equals(profile) && hasGLES1Impl) { + return GLES1; + } + return null; + } + + public static String getGLTypeName(int type) { + switch (type) { + case GL.GL_UNSIGNED_BYTE: + return "GL_UNSIGNED_BYTE"; + case GL.GL_BYTE: + return "GL_BYTE"; + case GL.GL_UNSIGNED_SHORT: + return "GL_UNSIGNED_SHORT"; + case GL.GL_SHORT: + return "GL_SHORT"; + case GL.GL_FLOAT: + return "GL_FLOAT"; + case GL.GL_FIXED: + return "GL_FIXED"; + case javax.media.opengl.GL2ES2.GL_INT: + return "GL_INT"; + case javax.media.opengl.GL2ES2.GL_UNSIGNED_INT: + return "GL_UNSIGNED_INT"; + case javax.media.opengl.GL2.GL_DOUBLE: + return "GL_DOUBLE"; + case javax.media.opengl.GL2.GL_2_BYTES: + return "GL_2_BYTES"; + case javax.media.opengl.GL2.GL_3_BYTES: + return "GL_3_BYTES"; + case javax.media.opengl.GL2.GL_4_BYTES: + return "GL_4_BYTES"; + } + return null; + } + + public static String getGLArrayName(int array) { + switch(array) { + case GLPointerFunc.GL_VERTEX_ARRAY: + return "GL_VERTEX_ARRAY"; + case GLPointerFunc.GL_NORMAL_ARRAY: + return "GL_NORMAL_ARRAY"; + case GLPointerFunc.GL_COLOR_ARRAY: + return "GL_COLOR_ARRAY"; + case GLPointerFunc.GL_TEXTURE_COORD_ARRAY: + return "GL_TEXTURE_COORD_ARRAY"; + } + return null; + } + + private GLProfile(String profile, String profileImpl) { + this.profile = profile; + this.profileImpl = profileImpl; + } + + private String profileImpl = null; + private String profile = null; +} diff --git a/src/jogl/classes/javax/media/opengl/GLUniformData.java b/src/jogl/classes/javax/media/opengl/GLUniformData.java new file mode 100644 index 000000000..8b5fb1a03 --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/GLUniformData.java @@ -0,0 +1,156 @@ + +package javax.media.opengl; + +import java.nio.*; + +public class GLUniformData { + + /** + * int atom + * + * Number of objects is 1 + * + * @arg components number of elements of one object, ie 4 for GL_FLOAT_VEC4, + */ + public GLUniformData(String name, int val) { + init(name, 1, new Integer(val)); + } + + /** + * float atom + * + * Number of objects is 1 + * + * @arg components number of elements of one object, ie 4 for GL_FLOAT_VEC4, + */ + public GLUniformData(String name, float val) { + init(name, 1, new Float(val)); + } + + /** + * Multiple IntBuffer Vector + * + * Number of objects is calculated by data.limit()/components + * + * @arg components number of elements of one object, ie 4 for GL_FLOAT_VEC4, + */ + public GLUniformData(String name, int components, IntBuffer data) { + init(name, components, data); + } + + /** + * Multiple FloatBuffer Vector + * + * Number of objects is calculated by data.limit()/components + * + * @arg components number of elements of one object, ie 4 for GL_FLOAT_VEC4, + */ + public GLUniformData(String name, int components, FloatBuffer data) { + init(name, components, data); + } + + /** + * Multiple FloatBuffer Matrix + * + * Number of objects is calculated by data.limit()/(rows*columns) + * + * @arg rows the matrix rows + * @arg column the matrix column + */ + public GLUniformData(String name, int rows, int columns, FloatBuffer data) { + init(name, rows, columns, data); + } + + public void setData(int data) { init(new Integer(data)); } + public void setData(float data) { init(new Float(data)); } + public void setData(IntBuffer data) { init(data); } + public void setData(FloatBuffer data) { init(data); } + + public int intValue() { return ((Integer)data).intValue(); }; + public float floatValue() { return ((Float)data).floatValue(); }; + public IntBuffer intBufferValue() { return (IntBuffer)data; }; + public FloatBuffer floatBufferValue() { return (FloatBuffer)data; }; + + public String toString() { + return "GLUniformData[name "+name+ + ", location "+location+ + ", size "+rows+"*"+columns+ + ", count "+count+ + ", matrix "+isMatrix+ + ", data "+data+ + "]"; + } + + private void init(String name, int rows, int columns, Object data) { + if( 2>rows || rows>4 || 2>columns || columns>4 ) { + throw new GLException("rowsXcolumns must be within [2..4]X[2..4], is: "+rows+"X"+columns); + } + this.name=name; + this.rows=rows; + this.columns=columns; + this.isMatrix=true; + this.location=-1; + init(data); + } + + private void init(String name, int components, Object data) { + if( 1>components || components>4 ) { + throw new GLException("components must be within [1..4], is: "+components); + } + this.name=name; + this.columns=components; + this.rows=1; + this.isMatrix=false; + this.location=-1; + init(data); + } + + private void init(Object data) { + if(data instanceof Buffer) { + int sz = rows*columns; + Buffer buffer = (Buffer)data; + if(buffer.limit()<sz || 0!=buffer.limit()%sz) { + throw new GLException("data buffer size invalid: new buffer limit: "+buffer.limit()+"\n\t"+this); + } + this.count=buffer.limit()/(rows*columns); + } else { + if(isMatrix) { + throw new GLException("Atom type not allowed for matrix : "+this); + } + this.count=1; + } + this.data=data; + } + + public String getName() { return name; } + + public int getLocation() { return location; } + + /** + * Sets the determined location of the shader uniform. + */ + public void setLocation(int location) { this.location=location; } + + public Object getObject() { + return data; + } + public Buffer getBuffer() { + return (data instanceof Buffer)?(Buffer)data:null; + } + public boolean isBuffer() { + return (data instanceof Buffer); + } + public boolean isMatrix() { return isMatrix; } + + public int count() { return count; } + public int components() { return rows*columns; } + public int rows() { return rows; } + public int columns() { return columns; } + + private String name; + private int location; + private int rows, columns; + private int count; + private Object data; + private boolean isMatrix; +} diff --git a/src/jogl/classes/javax/media/opengl/Threading.java b/src/jogl/classes/javax/media/opengl/Threading.java new file mode 100755 index 000000000..fecf6c78b --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/Threading.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package javax.media.opengl; + +import com.sun.opengl.impl.*; + +/** This API provides access to the threading model for the implementation of + the classes in this package. + + <P> + + OpenGL is specified as a thread-safe API, but in practice there + are multithreading-related issues on most, if not all, of the + platforms which support it. For example, some OpenGL + implementations do not behave well when one context is made + current first on one thread, released, and then made current on a + second thread, although this is legal according to the OpenGL + specification. On other platforms there are other problems. + + <P> + + Due to these limitations, and due to the inherent multithreading + in the Java platform (in particular, in the Abstract Window + Toolkit), it is often necessary to limit the multithreading + occurring in the typical application using the OpenGL API. + + <P> + + In the current reference implementation, for instance, multithreading + has been limited by + forcing all OpenGL-related work for GLAutoDrawables on to a single + thread. In other words, if an application uses only the + GLAutoDrawable and GLEventListener callback mechanism, it is + guaranteed to have the most correct single-threaded behavior on + all platforms. + + <P> + + Applications using the GLContext makeCurrent/release API directly + will inherently break this single-threaded model, as these methods + require that the OpenGL context be made current on the current + thread immediately. For applications wishing to integrate better + with an implementation that uses the single-threaded model, this + class provides public access to the mechanism used by the implementation. + + <P> + + Users can execute Runnables on the + internal thread used for performing OpenGL work, and query whether + the current thread is already this thread. Using these mechanisms + the user can move work from the current thread on to the internal + OpenGL thread if desired. + + <P> + + This class also provides mechanisms for querying whether this + internal serialization of OpenGL work is in effect, and a + programmatic way of disabling it. In the current reference + implementation it is enabled by default, although it could be + disabled in the future if OpenGL drivers become more robust on + all platforms. + + <P> + + In addition to specifying programmatically whether the single + thread for OpenGL work is enabled, users may switch it on and off + using the system property <code>opengl.1thread</code>. Valid values + for this system property are: + + <PRE> + -Dopengl.1thread=false Disable single-threading of OpenGL work + -Dopengl.1thread=true Enable single-threading of OpenGL work (default -- on a newly-created worker thread) + -Dopengl.1thread=auto Select default single-threading behavior (currently on) + -Dopengl.1thread=awt Enable single-threading of OpenGL work on AWT event dispatch thread (current default on all + platforms, and also the default behavior older releases) + -Dopengl.1thread=worker Enable single-threading of OpenGL work on newly-created worker thread (not suitable for Mac + OS X or X11 platforms, and risky on Windows in applet environments) + </PRE> +*/ + +public class Threading { + + /** No reason to ever instantiate this class */ + private Threading() {} + + /** If an implementation of the javax.media.opengl APIs offers a + multithreading option but the default behavior is single-threading, + this API provides a mechanism for end users to disable single-threading + in this implementation. Users are strongly discouraged from + calling this method unless they are aware of all of the + consequences and are prepared to enforce some amount of + threading restrictions in their applications. Disabling + single-threading, for example, may have unintended consequences + on GLAutoDrawable implementations such as GLCanvas, GLJPanel and + GLPbuffer. Currently there is no supported way to re-enable it + once disabled, partly to discourage careless use of this + method. This method should be called as early as possible in an + application. */ + public static void disableSingleThreading() { + ThreadingImpl.disableSingleThreading(); + } + + /** Indicates whether OpenGL work is being automatically forced to a + single thread in this implementation. */ + public static boolean isSingleThreaded() { + return ThreadingImpl.isSingleThreaded(); + } + + /** Indicates whether the current thread is the single thread on + which this implementation of the javax.media.opengl APIs + performs all of its OpenGL-related work. This method should only + be called if the single-thread model is in effect. */ + public static boolean isOpenGLThread() throws GLException { + return ThreadingImpl.isOpenGLThread(); + } + + /** Executes the passed Runnable on the single thread used for all + OpenGL work in this javax.media.opengl API implementation. It is + not specified exactly which thread is used for this + purpose. This method should only be called if the single-thread + model is in use and if the current thread is not the OpenGL + thread (i.e., if <code>isOpenGLThread()</code> returns + false). It is up to the end user to check to see whether the + current thread is the OpenGL thread and either execute the + Runnable directly or perform the work inside it. */ + public static void invokeOnOpenGLThread(Runnable r) throws GLException { + ThreadingImpl.invokeOnOpenGLThread(r); + } +} diff --git a/src/jogl/classes/javax/media/opengl/awt/AWTGLAutoDrawable.java b/src/jogl/classes/javax/media/opengl/awt/AWTGLAutoDrawable.java new file mode 100644 index 000000000..d92cec389 --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/awt/AWTGLAutoDrawable.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package javax.media.opengl.awt; + +import javax.media.opengl.*; +import javax.media.opengl.glu.*; + +public interface AWTGLAutoDrawable extends GLAutoDrawable, ComponentEvents { + /** Requests a new width and height for this AWTGLAutoDrawable. */ + public void setSize(int width, int height); + + /** Schedules a repaint of the component at some point in the + future. */ + public void repaint(); +} diff --git a/src/jogl/classes/javax/media/opengl/awt/ComponentEvents.java b/src/jogl/classes/javax/media/opengl/awt/ComponentEvents.java new file mode 100644 index 000000000..0c4f63c2d --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/awt/ComponentEvents.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package javax.media.opengl.awt; + +import javax.media.opengl.*; +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/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java new file mode 100644 index 000000000..4282e9985 --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java @@ -0,0 +1,710 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package javax.media.opengl.awt; + +import javax.media.opengl.*; +import javax.media.nativewindow.*; +import javax.media.nativewindow.awt.*; + +import com.sun.opengl.impl.*; + +import java.awt.Canvas; +import java.awt.Color; +import java.awt.Component; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.Container; +import java.awt.Window; +import java.awt.event.WindowEvent; +import java.awt.event.WindowAdapter; +import java.awt.geom.*; +import java.beans.*; +import java.lang.reflect.*; +import java.security.*; + +// 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. */ + +public class GLCanvas extends Canvas implements AWTGLAutoDrawable { + + private static final boolean DEBUG = Debug.debug("GLCanvas"); + + static private GLProfile defaultGLProfile = GLProfile.getDefault(); + private GLProfile glProfile; + private GLDrawableHelper drawableHelper = new GLDrawableHelper(); + private GraphicsConfiguration chosen; + private AWTGraphicsConfiguration awtConfig; + private GLDrawable drawable; + private GLContextImpl context; + private boolean autoSwapBufferMode = true; + private boolean sendReshape = false; + + // copy of the cstr args .. + private GLCapabilities capabilities; + private GLCapabilitiesChooser chooser; + private GLContext shareWith; + private GraphicsDevice device; + + /** Creates a new GLCanvas component with a default set of OpenGL + capabilities, using the default OpenGL capabilities selection + mechanism, on the default screen device. */ + public GLCanvas() { + this(null); + } + + /** Creates a new GLCanvas component with the requested set of + OpenGL capabilities, using the default OpenGL capabilities + selection mechanism, on the default screen device. */ + public GLCanvas(GLCapabilities capabilities) { + this(capabilities, null, null, null); + } + + /** Creates a new GLCanvas component. The passed GLCapabilities + specifies the OpenGL capabilities for the component; if null, a + default set of capabilities is used. The GLCapabilitiesChooser + specifies the algorithm for selecting one of the available + GLCapabilities for the component; a DefaultGLCapabilitesChooser + is used if null is passed for this argument. The passed + GLContext specifies an OpenGL context with which to share + textures, display lists and other OpenGL state, and may be null + if sharing is not desired. See the note in the overview + documentation on <a + href="../../../overview-summary.html#SHARING">context + sharing</a>. The passed GraphicsDevice indicates the screen on + which to create the GLCanvas; the GLDrawableFactory uses the + default screen device of the local GraphicsEnvironment if null + is passed for this argument. */ + public GLCanvas(GLCapabilities capabilities, + GLCapabilitiesChooser chooser, + GLContext shareWith, + GraphicsDevice device) { + /* + * Workaround for Xinerama, always pass null so we can detect whether + * super.getGraphicsConfiguration() is returning the Canvas' GC (null), + * or an ancestor component's GC (non-null) in the overridden version + * below. + */ + super(); + + if(null==capabilities) { + capabilities = new GLCapabilities(defaultGLProfile); + } + glProfile = capabilities.getGLProfile(); + + this.capabilities = capabilities; + this.chooser = chooser; + this.shareWith=shareWith; + this.device = device; + } + + protected interface DestroyMethod { + public void destroyMethod(); + } + + protected final static Object addClosingListener(Component c, final DestroyMethod d) { + WindowAdapter cl = null; + Window w = getWindow(c); + if(null!=w) { + cl = new WindowAdapter() { + public void windowClosing(WindowEvent e) { + // we have to issue this call rigth away, + // otherwise the window gets destroyed + d.destroyMethod(); + } + }; + w.addWindowListener(cl); + } + return cl; + } + + protected final static Window getWindow(Component c) { + while ( c!=null && ! ( c instanceof Window ) ) { + c = c.getParent(); + } + return (Window)c; + } + + /** + * Overridden to choose a GraphicsConfiguration on a parent container's + * GraphicsDevice because both devices + */ + public GraphicsConfiguration getGraphicsConfiguration() { + /* + * Workaround for problems with Xinerama and java.awt.Component.checkGD + * when adding to a container on a different graphics device than the + * one that this Canvas is associated with. + * + * GC will be null unless: + * - A native peer has assigned it. This means we have a native + * peer, and are already comitted to a graphics configuration. + * - This canvas has been added to a component hierarchy and has + * an ancestor with a non-null GC, but the native peer has not + * yet been created. This means we can still choose the GC on + * all platforms since the peer hasn't been created. + */ + final GraphicsConfiguration gc = super.getGraphicsConfiguration(); + /* + * chosen is only non-null on platforms where the GLDrawableFactory + * returns a non-null GraphicsConfiguration (in the GLCanvas + * constructor). + * + * if gc is from this Canvas' native peer then it should equal chosen, + * otherwise it is from an ancestor component that this Canvas is being + * added to, and we go into this block. + */ + if (gc != null && chosen != null && !chosen.equals(gc)) { + /* + * Check for compatibility with gc. If they differ by only the + * device then return a new GCconfig with the super-class' GDevice + * (and presumably the same visual ID in Xinerama). + * + */ + if (!chosen.getDevice().getIDstring().equals(gc.getDevice().getIDstring())) { + /* + * Here we select a GraphicsConfiguration on the alternate + * device that is presumably identical to the chosen + * configuration, but on the other device. + * + * Should really check to ensure that we select a configuration + * with the same X visual ID for Xinerama screens, otherwise the + * GLDrawable may have the wrong visual ID (I don't think this + * ever gets updated). May need to add a method to + * X11GLDrawableFactory to do this in a platform specific + * manner. + * + * However, on platforms where we can actually get into this + * block, both devices should have the same visual list, and the + * same configuration should be selected here. + */ + AWTGraphicsConfiguration config = chooseGraphicsConfiguration((GLCapabilities)awtConfig.getRequestedCapabilities(), chooser, gc.getDevice()); + final GraphicsConfiguration compatible = (null!=config)?config.getGraphicsConfiguration():null; + boolean equalCaps = config.getChosenCapabilities().equals(awtConfig.getChosenCapabilities()); + if(DEBUG) { + Exception e = new Exception("Call Stack: "+Thread.currentThread().getName()); + e.printStackTrace(); + System.err.println("!!! Created Config (n): HAVE GC "+chosen); + System.err.println("!!! Created Config (n): THIS GC "+gc); + System.err.println("!!! Created Config (n): Choosen GC "+compatible); + System.err.println("!!! Created Config (n): HAVE CF "+awtConfig); + System.err.println("!!! Created Config (n): Choosen CF "+config); + System.err.println("!!! Created Config (n): EQUALS CAPS "+equalCaps); + } + + if (compatible != null) { + /* + * Save the new GC for equals test above, and to return to + * any outside callers of this method. + */ + chosen = compatible; + + awtConfig = config; + + if( !equalCaps && GLAutoDrawable.SCREEN_CHANGE_ACTION_ENABLED ) { + dispose(true); + } + } + } + + /* + * If a compatible GC was not found in the block above, this will + * return the GC that was selected in the constructor (and might + * cause an exception in Component.checkGD when adding to a + * container, but in this case that would be the desired behavior). + * + */ + return chosen; + } else if (gc == null) { + /* + * The GC is null, which means we have no native peer, and are not + * part of a (realized) component hierarchy. So we return the + * desired visual that was selected in the constructor (possibly + * null). + */ + return chosen; + } + + /* + * Otherwise we have not explicitly selected a GC in the constructor, so + * just return what Canvas would have. + */ + return gc; + } + + public GLContext createContext(GLContext shareWith) { + return drawable.createContext(shareWith); + } + + public void setRealized(boolean realized) { + } + + private Object closingListener = null; + private Object closingListenerLock = new Object(); + + public void display() { + maybeDoSingleThreadedWorkaround(displayOnEventDispatchThreadAction, + displayAction); + if(null==closingListener) { + synchronized(closingListenerLock) { + if(null==closingListener) { + closingListener=addClosingListener(this, new DestroyMethod() { + public void destroyMethod() { destroy(); } }); + } + } + } + } + + protected void dispose(boolean regenerate) { + if(DEBUG) { + Exception ex1 = new Exception("dispose("+regenerate+") - start"); + ex1.printStackTrace(); + } + disposeRegenerate=regenerate; + + if (Threading.isSingleThreaded() && + !Threading.isOpenGLThread()) { + // Workaround for termination issues with applets -- + // sun.applet.AppletPanel should probably be performing the + // remove() call on the EDT rather than on its own thread + if (ThreadingImpl.isAWTMode() && + Thread.holdsLock(getTreeLock())) { + // The user really should not be invoking remove() from this + // thread -- but since he/she is, we can not go over to the + // EDT at this point. Try to destroy the context from here. + drawableHelper.invokeGL(drawable, context, disposeAction, null); + } else { + Threading.invokeOnOpenGLThread(disposeOnEventDispatchThreadAction); + } + } else { + drawableHelper.invokeGL(drawable, context, disposeAction, null); + } + + if(DEBUG) { + System.err.println("dispose("+regenerate+") - stop"); + } + } + + /** + * Just an alias for removeNotify + */ + public void destroy() { + removeNotify(); + } + + /** Overridden to cause OpenGL rendering to be performed during + repaint cycles. Subclasses which override this method must call + super.paint() in their paint() method in order to function + properly. <P> + + <B>Overrides:</B> + <DL><DD><CODE>paint</CODE> in class <CODE>java.awt.Component</CODE></DD></DL> */ + public void paint(Graphics g) { + if (Beans.isDesignTime()) { + // Make GLCanvas behave better in NetBeans GUI builder + g.setColor(Color.BLACK); + g.fillRect(0, 0, getWidth(), getHeight()); + FontMetrics fm = g.getFontMetrics(); + String name = getName(); + if (name == null) { + name = getClass().getName(); + int idx = name.lastIndexOf('.'); + if (idx >= 0) { + name = name.substring(idx + 1); + } + } + Rectangle2D bounds = fm.getStringBounds(name, g); + g.setColor(Color.WHITE); + g.drawString(name, + (int) ((getWidth() - bounds.getWidth()) / 2), + (int) ((getHeight() + bounds.getHeight()) / 2)); + return; + } + + display(); + } + + /** Overridden to track when this component is added to a container. + Subclasses which override this method must call + super.addNotify() in their addNotify() method in order to + function properly. <P> + + <B>Overrides:</B> + <DL><DD><CODE>addNotify</CODE> in class <CODE>java.awt.Component</CODE></DD></DL> */ + public void addNotify() { + super.addNotify(); + if (!Beans.isDesignTime()) { + disableBackgroundErase(); + + if(null==device) { + GraphicsConfiguration gc = super.getGraphicsConfiguration(); + if(null!=gc) { + device = gc.getDevice(); + } + } + + /* + * Save the chosen capabilities for use in getGraphicsConfiguration(). + */ + awtConfig = chooseGraphicsConfiguration(capabilities, chooser, device); + if(DEBUG) { + Exception e = new Exception("Created Config: "+awtConfig); + e.printStackTrace(); + } + if(null!=awtConfig) { + // update .. + chosen = awtConfig.getGraphicsConfiguration(); + + } + if(null==awtConfig) { + throw new GLException("Error: AWTGraphicsConfiguration is null"); + } + drawable = GLDrawableFactory.getFactory(glProfile).createGLDrawable(NativeWindowFactory.getNativeWindow(this, awtConfig)); + context = (GLContextImpl) drawable.createContext(shareWith); + context.setSynchronized(true); + + if(DEBUG) { + System.err.println("Created Drawable: "+drawable); + } + drawable.setRealized(true); + } + } + + /** Overridden to track when this component is removed from a + container. Subclasses which override this method must call + super.removeNotify() in their removeNotify() method in order to + function properly. <P> + + <B>Overrides:</B> + <DL><DD><CODE>removeNotify</CODE> in class <CODE>java.awt.Component</CODE></DD></DL> */ + public void removeNotify() { + if(DEBUG) { + Exception ex1 = new Exception("removeNotify - start"); + ex1.printStackTrace(); + } + + if (Beans.isDesignTime()) { + super.removeNotify(); + } else { + try { + dispose(false); + } finally { + drawable=null; + super.removeNotify(); + } + } + if(DEBUG) { + System.out.println("removeNotify - end"); + } + } + + /** Overridden to cause {@link GLDrawableHelper#reshape} to be + called on all registered {@link GLEventListener}s. Subclasses + which override this method must call super.reshape() in + their reshape() method in order to function properly. <P> + + <B>Overrides:</B> + <DL><DD><CODE>reshape</CODE> in class <CODE>java.awt.Component</CODE></DD></DL> */ + public void reshape(int x, int y, int width, int height) { + super.reshape(x, y, width, height); + sendReshape = true; + } + + /** <B>Overrides:</B> + <DL><DD><CODE>update</CODE> in class <CODE>java.awt.Component</CODE></DD></DL> */ + // Overridden from Canvas to prevent the AWT's clearing of the + // canvas from interfering with the OpenGL rendering. + public void update(Graphics g) { + paint(g); + } + + public void addGLEventListener(GLEventListener listener) { + drawableHelper.addGLEventListener(listener); + } + + public void removeGLEventListener(GLEventListener listener) { + drawableHelper.removeGLEventListener(listener); + } + + public void setContext(GLContext ctx) { + context=(GLContextImpl)ctx; + } + + public GLContext getContext() { + return context; + } + + public GL getGL() { + if (Beans.isDesignTime()) { + return null; + } + GLContext context = getContext(); + return (context == null) ? null : context.getGL(); + } + + public void setGL(GL gl) { + GLContext context = getContext(); + if (context != null) { + context.setGL(gl); + } + } + + + public void setAutoSwapBufferMode(boolean onOrOff) { + drawableHelper.setAutoSwapBufferMode(onOrOff); + } + + public boolean getAutoSwapBufferMode() { + return drawableHelper.getAutoSwapBufferMode(); + } + + public void swapBuffers() { + maybeDoSingleThreadedWorkaround(swapBuffersOnEventDispatchThreadAction, swapBuffersAction); + } + + public GLProfile getGLProfile() { + return glProfile; + } + + public GLCapabilities getChosenGLCapabilities() { + if (awtConfig == null) { + throw new GLException("No AWTGraphicsConfiguration: "+this); + } + + return (GLCapabilities)awtConfig.getChosenCapabilities(); + } + + public GLCapabilities getRequestedGLCapabilities() { + if (awtConfig == null) { + throw new GLException("No AWTGraphicsConfiguration: "+this); + } + + return (GLCapabilities)awtConfig.getRequestedCapabilities(); + } + + public NativeWindow getNativeWindow() { + return drawable.getNativeWindow(); + } + + public GLDrawableFactory getFactory() { + return drawable.getFactory(); + } + + public String toString() { + return "AWT-GLCanvas[ "+awtConfig+", "+((null!=drawable)?drawable.getClass().getName():"null-drawable")+", "+drawableHelper+"]"; + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + private void maybeDoSingleThreadedWorkaround(Runnable eventDispatchThreadAction, + Runnable invokeGLAction) { + if (Threading.isSingleThreaded() && + !Threading.isOpenGLThread()) { + Threading.invokeOnOpenGLThread(eventDispatchThreadAction); + } else { + drawableHelper.invokeGL(drawable, context, invokeGLAction, initAction); + } + } + + private boolean disposeRegenerate; + private DisposeAction disposeAction = new DisposeAction(this); + + class DisposeAction implements Runnable { + private GLCanvas canvas; + public DisposeAction(GLCanvas canvas) { + this.canvas = canvas; + } + public void run() { + drawableHelper.dispose(GLCanvas.this); + + if(null!=context) { + context.makeCurrent(); // implicit wait for lock .. + context.destroy(); + context=null; + } + + if(null!=drawable) { + drawable.setRealized(false); + } + + if(disposeRegenerate) { + // recreate GLDrawable to reflect it's new graphics configuration + drawable = GLDrawableFactory.getFactory(glProfile).createGLDrawable(NativeWindowFactory.getNativeWindow(canvas, awtConfig)); + if(DEBUG) { + System.err.println("GLCanvas.dispose(true): new drawable: "+drawable); + } + drawable.setRealized(true); + context = (GLContextImpl) drawable.createContext(shareWith); + context.setSynchronized(true); + sendReshape=true; // ensure a reshape is being send .. + } + } + } + + private DisposeOnEventDispatchThreadAction disposeOnEventDispatchThreadAction = + new DisposeOnEventDispatchThreadAction(); + + class DisposeOnEventDispatchThreadAction implements Runnable { + public void run() { + drawableHelper.invokeGL(drawable, context, disposeAction, null); + } + } + + class InitAction implements Runnable { + public void run() { + drawableHelper.init(GLCanvas.this); + } + } + private InitAction initAction = new InitAction(); + + class DisplayAction implements Runnable { + public void run() { + if (sendReshape) { + // Note: we ignore the given x and y within the parent component + // since we are drawing directly into this heavyweight component. + int width = getWidth(); + int height = getHeight(); + getGL().glViewport(0, 0, width, height); + drawableHelper.reshape(GLCanvas.this, 0, 0, width, height); + sendReshape = false; + } + + drawableHelper.display(GLCanvas.this); + } + } + private DisplayAction displayAction = new DisplayAction(); + + class SwapBuffersAction implements Runnable { + public void run() { + drawable.swapBuffers(); + } + } + private SwapBuffersAction swapBuffersAction = new SwapBuffersAction(); + + // Workaround for ATI driver bugs related to multithreading issues + // like simultaneous rendering via Animators to canvases that are + // being resized on the AWT event dispatch thread + class DisplayOnEventDispatchThreadAction implements Runnable { + public void run() { + drawableHelper.invokeGL(drawable, context, displayAction, initAction); + } + } + private DisplayOnEventDispatchThreadAction displayOnEventDispatchThreadAction = + new DisplayOnEventDispatchThreadAction(); + class SwapBuffersOnEventDispatchThreadAction implements Runnable { + public void run() { + drawableHelper.invokeGL(drawable, context, swapBuffersAction, initAction); + } + } + private SwapBuffersOnEventDispatchThreadAction swapBuffersOnEventDispatchThreadAction = + new SwapBuffersOnEventDispatchThreadAction(); + + // Disables the AWT's erasing of this Canvas's background on Windows + // in Java SE 6. This internal API is not available in previous + // releases, but the system property + // -Dsun.awt.noerasebackground=true can be specified to get similar + // results globally in previous releases. + private static boolean disableBackgroundEraseInitialized; + private static Method disableBackgroundEraseMethod; + private void disableBackgroundErase() { + if (!disableBackgroundEraseInitialized) { + try { + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + try { + Class clazz = getToolkit().getClass(); + while (clazz != null && disableBackgroundEraseMethod == null) { + try { + disableBackgroundEraseMethod = + clazz.getDeclaredMethod("disableBackgroundErase", + new Class[] { Canvas.class }); + disableBackgroundEraseMethod.setAccessible(true); + } catch (Exception e) { + clazz = clazz.getSuperclass(); + } + } + } catch (Exception e) { + } + return null; + } + }); + } catch (Exception e) { + } + disableBackgroundEraseInitialized = true; + } + if (disableBackgroundEraseMethod != null) { + try { + disableBackgroundEraseMethod.invoke(getToolkit(), new Object[] { this }); + } catch (Exception e) { + // FIXME: workaround for 6504460 (incorrect backport of 6333613 in 5.0u10) + // throw new GLException(e); + } + } + } + + private static AWTGraphicsConfiguration chooseGraphicsConfiguration(GLCapabilities capabilities, + GLCapabilitiesChooser chooser, + GraphicsDevice device) { + // Make GLCanvas behave better in NetBeans GUI builder + if (Beans.isDesignTime()) { + return null; + } + + AbstractGraphicsScreen aScreen = AWTGraphicsScreen.createScreenDevice(device); + AWTGraphicsConfiguration config = (AWTGraphicsConfiguration) + GraphicsConfigurationFactory.getFactory(AWTGraphicsDevice.class).chooseGraphicsConfiguration(capabilities, + chooser, + aScreen); + if (config == null) { + throw new GLException("Error: Couldn't fetch AWTGraphicsConfiguration"); + } + + return config; + } +} diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java new file mode 100644 index 000000000..5da6a892f --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java @@ -0,0 +1,1582 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package javax.media.opengl.awt; + +import javax.media.opengl.*; +import javax.media.nativewindow.*; +import javax.media.nativewindow.awt.*; + +import java.awt.*; +import java.awt.geom.*; +import java.awt.image.*; +import java.beans.*; +import javax.swing.*; +import java.nio.*; +import java.security.*; +import javax.swing.JComponent; +import javax.swing.JPanel; +import com.sun.opengl.impl.*; +import com.sun.opengl.impl.awt.*; + +// 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. <P> + + The GLJPanel can be made transparent by creating it with a + GLCapabilities object with alpha bits specified and calling {@link + #setOpaque}(false). Pixels with resulting OpenGL alpha values less + than 1.0 will be overlaid on any underlying Swing rendering. <P> + + Notes specific to the Reference Implementation: This component + attempts to use hardware-accelerated rendering via pbuffers and + falls back on to software rendering if problems occur. + Note that because this component attempts to use pbuffers for + rendering, and because pbuffers can not be resized, somewhat + surprising behavior may occur during resize operations; the {@link + GLEventListener#init} method may be called multiple times as the + pbuffer is resized to be able to cover the size of the GLJPanel. + This behavior is correct, as the textures and display lists for + the GLJPanel will have been lost during the resize operation. The + application should attempt to make its GLEventListener.init() + methods as side-effect-free as possible. <P> + +*/ + +public class GLJPanel extends JPanel implements AWTGLAutoDrawable { + private static final boolean DEBUG = Debug.debug("GLJPanel"); + private static final boolean VERBOSE = Debug.verbose(); + + private GLDrawableHelper drawableHelper = new GLDrawableHelper(); + private volatile boolean isInitialized; + + // Data used for either pbuffers or pixmap-based offscreen surfaces + private GLCapabilities offscreenCaps; + private GLProfile glProfile; + private GLDrawableFactoryImpl factory; + private GLCapabilitiesChooser chooser; + private GLContext shareWith; + // Width of the actual GLJPanel + private int panelWidth = 0; + private int panelHeight = 0; + // Lazy reshape notification + private boolean handleReshape = false; + private boolean sendReshape = true; + + // The backend in use + private Backend backend; + + // Used by all backends either directly or indirectly to hook up callbacks + private Updater updater = new Updater(); + + // Turns off the pbuffer-based backend (used by default, unless the + // Java 2D / OpenGL pipeline is in use) + private static boolean hardwareAccelerationDisabled = + Debug.isPropertyDefined("jogl.gljpanel.nohw"); + + // Turns off the fallback to software-based rendering from + // pbuffer-based rendering + private static boolean softwareRenderingDisabled = + Debug.isPropertyDefined("jogl.gljpanel.nosw"); + + // Indicates whether the Java 2D OpenGL pipeline is enabled + private boolean oglPipelineEnabled = + Java2D.isOGLPipelineActive() && + !Debug.isPropertyDefined("jogl.gljpanel.noogl"); + + // For handling reshape events lazily + private int reshapeX; + private int reshapeY; + private int reshapeWidth; + private int reshapeHeight; + + // These are always set to (0, 0) except when the Java2D / OpenGL + // pipeline is active + private int viewportX; + private int viewportY; + + static { + // Force eager initialization of part of the Java2D class since + // otherwise it's likely it will try to be initialized while on + // the Queue Flusher Thread, which is not allowed + if (Java2D.isOGLPipelineActive() && Java2D.isFBOEnabled()) { + Java2D.getShareContext(GraphicsEnvironment. + getLocalGraphicsEnvironment(). + getDefaultScreenDevice()); + } + } + + /** Creates a new GLJPanel component with a default set of OpenGL + capabilities and using the default OpenGL capabilities selection + mechanism. */ + public GLJPanel() { + this(null); + } + + /** Creates a new GLJPanel component with the requested set of + OpenGL capabilities, using the default OpenGL capabilities + selection mechanism. */ + public GLJPanel(GLCapabilities capabilities) { + this(capabilities, null, null); + } + + /** Creates a new GLJPanel component. The passed GLCapabilities + specifies the OpenGL capabilities for the component; if null, a + default set of capabilities is used. The GLCapabilitiesChooser + specifies the algorithm for selecting one of the available + GLCapabilities for the component; a DefaultGLCapabilitesChooser + is used if null is passed for this argument. The passed + GLContext specifies an OpenGL context with which to share + textures, display lists and other OpenGL state, and may be null + if sharing is not desired. See the note in the overview documentation on + <a href="../../../overview-summary.html#SHARING">context sharing</a>. + */ + public GLJPanel(GLCapabilities capabilities, GLCapabilitiesChooser chooser, GLContext shareWith) { + super(); + + // Works around problems on many vendors' cards; we don't need a + // back buffer for the offscreen surface anyway + if (capabilities != null) { + offscreenCaps = (GLCapabilities) capabilities.clone(); + } else { + offscreenCaps = new GLCapabilities(null); + } + offscreenCaps.setDoubleBuffered(false); + this.glProfile = offscreenCaps.getGLProfile(); + this.factory = GLDrawableFactoryImpl.getFactoryImpl(glProfile); + this.chooser = ((chooser != null) ? chooser : new DefaultGLCapabilitiesChooser()); + this.shareWith = shareWith; + } + + public void display() { + if (EventQueue.isDispatchThread()) { + // Want display() to be synchronous, so call paintImmediately() + paintImmediately(0, 0, getWidth(), getHeight()); + } else { + // Multithreaded redrawing of Swing components is not allowed, + // so do everything on the event dispatch thread + try { + EventQueue.invokeAndWait(paintImmediatelyAction); + } catch (Exception e) { + throw new GLException(e); + } + } + } + + protected void dispose(boolean regenerate) { + if(DEBUG) { + Exception ex1 = new Exception("dispose("+regenerate+") - start"); + ex1.printStackTrace(); + } + if (backend != null) { + disposeRegenerate=regenerate; + disposeContext=backend.getContext(); + disposeDrawable=backend.getDrawable(); + + if (Threading.isSingleThreaded() && + !Threading.isOpenGLThread()) { + // Workaround for termination issues with applets -- + // sun.applet.AppletPanel should probably be performing the + // remove() call on the EDT rather than on its own thread + if (ThreadingImpl.isAWTMode() && + Thread.holdsLock(getTreeLock())) { + // The user really should not be invoking remove() from this + // thread -- but since he/she is, we can not go over to the + // EDT at this point. Try to destroy the context from here. + drawableHelper.invokeGL(disposeDrawable, disposeContext, disposeAction, null); + } else { + Threading.invokeOnOpenGLThread(disposeOnEventDispatchThreadAction); + } + } else { + drawableHelper.invokeGL(disposeDrawable, disposeContext, disposeAction, null); + } + + backend.setContext(disposeContext); + if(null==disposeContext) { + isInitialized = false; + } + } + + if(DEBUG) { + System.err.println("dispose("+regenerate+") - stop"); + } + } + + /** + * Just an alias for removeNotify + */ + public void destroy() { + removeNotify(); + } + + /** Overridden to cause OpenGL rendering to be performed during + repaint cycles. Subclasses which override this method must call + super.paintComponent() in their paintComponent() method in order + to function properly. <P> + + <B>Overrides:</B> + <DL><DD><CODE>paintComponent</CODE> in class <CODE>javax.swing.JComponent</CODE></DD></DL> */ + protected void paintComponent(final Graphics g) { + if (Beans.isDesignTime()) { + // Make GLJPanel behave better in NetBeans GUI builder + g.setColor(Color.BLACK); + g.fillRect(0, 0, getWidth(), getHeight()); + FontMetrics fm = g.getFontMetrics(); + String name = getName(); + if (name == null) { + name = getClass().getName(); + int idx = name.lastIndexOf('.'); + if (idx >= 0) { + name = name.substring(idx + 1); + } + } + Rectangle2D bounds = fm.getStringBounds(name, g); + g.setColor(Color.WHITE); + g.drawString(name, + (int) ((getWidth() - bounds.getWidth()) / 2), + (int) ((getHeight() + bounds.getHeight()) / 2)); + return; + } + + if (backend == null || !isInitialized) { + createAndInitializeBackend(); + } + + if (!isInitialized) { + return; + } + + // NOTE: must do this when the context is not current as it may + // involve destroying the pbuffer (current context) and + // re-creating it -- tricky to do properly while the context is + // current + if (handleReshape) { + handleReshape(); + } + + updater.setGraphics(g); + backend.doPaintComponent(g); + } + + /** Overridden to track when this component is added to a container. + Subclasses which override this method must call + super.addNotify() in their addNotify() method in order to + function properly. <P> + + <B>Overrides:</B> + <DL><DD><CODE>addNotify</CODE> in class <CODE>java.awt.Component</CODE></DD></DL> */ + public void addNotify() { + super.addNotify(); + if (DEBUG) { + System.err.println("GLJPanel.addNotify()"); + } + } + + /** Overridden to track when this component is removed from a + container. Subclasses which override this method must call + super.removeNotify() in their removeNotify() method in order to + function properly. <P> + + <B>Overrides:</B> + <DL><DD><CODE>removeNotify</CODE> in class <CODE>java.awt.Component</CODE></DD></DL> */ + public void removeNotify() { + if(DEBUG) { + Exception ex1 = new Exception("removeNotify - start"); + ex1.printStackTrace(); + } + dispose(false); + if (backend != null) { + backend.destroy(); + backend = null; + } + isInitialized = false; + super.removeNotify(); + if(DEBUG) { + System.out.println("removeNotify - end"); + } + } + + /** Overridden to cause {@link GLDrawableHelper#reshape} to be + called on all registered {@link GLEventListener}s. Subclasses + which override this method must call super.reshape() in + their reshape() method in order to function properly. <P> + + <B>Overrides:</B> + <DL><DD><CODE>reshape</CODE> in class <CODE>java.awt.Component</CODE></DD></DL> */ + public void reshape(int x, int y, int width, int height) { + super.reshape(x, y, width, height); + + reshapeX = x; + reshapeY = y; + reshapeWidth = width; + reshapeHeight = height; + handleReshape = true; + } + + public void setOpaque(boolean opaque) { + if (backend != null) { + backend.setOpaque(opaque); + } + super.setOpaque(opaque); + } + + public void addGLEventListener(GLEventListener listener) { + drawableHelper.addGLEventListener(listener); + } + + public void removeGLEventListener(GLEventListener listener) { + drawableHelper.removeGLEventListener(listener); + } + + public GLContext createContext(GLContext shareWith) { + return backend.createContext(shareWith); + } + + public void setRealized(boolean realized) { + } + + public void setContext(GLContext ctx) { + if (backend == null) { + return; + } + backend.setContext(ctx); + } + + public GLContext getContext() { + if (backend == null) { + return null; + } + return backend.getContext(); + } + + public GL getGL() { + if (Beans.isDesignTime()) { + return null; + } + GLContext context = getContext(); + return (context == null) ? null : context.getGL(); + } + + public void setGL(GL gl) { + GLContext context = getContext(); + if (context != null) { + context.setGL(gl); + } + } + + public void setAutoSwapBufferMode(boolean onOrOff) { + // In the current implementation this is a no-op. Both the pbuffer + // and pixmap based rendering paths use a single-buffered surface + // so swapping the buffers doesn't do anything. We also don't + // currently have the provision to skip copying the data to the + // Swing portion of the GLJPanel in any of the rendering paths. + } + + public boolean getAutoSwapBufferMode() { + // In the current implementation this is a no-op. Both the pbuffer + // and pixmap based rendering paths use a single-buffered surface + // so swapping the buffers doesn't do anything. We also don't + // currently have the provision to skip copying the data to the + // Swing portion of the GLJPanel in any of the rendering paths. + return true; + } + + public void swapBuffers() { + // In the current implementation this is a no-op. Both the pbuffer + // and pixmap based rendering paths use a single-buffered surface + // so swapping the buffers doesn't do anything. We also don't + // currently have the provision to skip copying the data to the + // Swing portion of the GLJPanel in any of the rendering paths. + } + + /** For a translucent GLJPanel (one for which {@link #setOpaque + setOpaque}(false) has been called), indicates whether the + application should preserve the OpenGL color buffer + (GL_COLOR_BUFFER_BIT) for correct rendering of the GLJPanel and + underlying widgets which may show through portions of the + GLJPanel with alpha values less than 1. Most Swing + implementations currently expect the GLJPanel to be completely + cleared (e.g., by <code>glClear(GL_COLOR_BUFFER_BIT | + GL_DEPTH_BUFFER_BIT)</code>), but for certain optimized Swing + implementations which use OpenGL internally, it may be possible + to perform OpenGL rendering using the GLJPanel into the same + OpenGL drawable as the Swing implementation uses. */ + public boolean shouldPreserveColorBufferIfTranslucent() { + return oglPipelineEnabled; + } + + public GLCapabilities getChosenGLCapabilities() { + return backend.getChosenGLCapabilities(); + } + + public final GLProfile getGLProfile() { + return glProfile; + } + + public NativeWindow getNativeWindow() { + throw new GLException("FIXME"); + } + + public final GLDrawableFactory getFactory() { + return factory; + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + private void createAndInitializeBackend() { + if (panelWidth == 0 || + panelHeight == 0) { + // See whether we have a non-zero size yet and can go ahead with + // initialization + if (reshapeWidth == 0 || + reshapeHeight == 0) { + return; + } + + // Pull down reshapeWidth and reshapeHeight into panelWidth and + // panelHeight eagerly in order to complete initialization, and + // force a reshape later + panelWidth = reshapeWidth; + panelHeight = reshapeHeight; + } + + do { + if (backend == null) { + if (oglPipelineEnabled) { + backend = new J2DOGLBackend(); + } else { + if (!hardwareAccelerationDisabled && + factory.canCreateGLPbuffer()) { + backend = new PbufferBackend(); + } else { + if (softwareRenderingDisabled) { + throw new GLException("Fallback to software rendering disabled by user"); + } + backend = new SoftwareBackend(); + } + } + } + + if (!isInitialized) { + backend.initialize(); + } + // The backend might set itself to null, indicating it punted to + // a different implementation -- try again + } while (backend == null); + + if(null==closingListener) { + synchronized(closingListenerLock) { + if(null==closingListener) { + closingListener=GLCanvas.addClosingListener(this, new GLCanvas.DestroyMethod() { + public void destroyMethod() { destroy(); } }); + } + } + } + } + private Object closingListener = null; + private Object closingListenerLock = new Object(); + + private void handleReshape() { + panelWidth = reshapeWidth; + panelHeight = reshapeHeight; + + if (DEBUG) { + System.err.println("GLJPanel.handleReshape: (w,h) = (" + + panelWidth + "," + panelHeight + ")"); + } + + sendReshape = true; + backend.handleReshape(); + handleReshape = false; + } + + // This is used as the GLEventListener for the pbuffer-based backend + // as well as the callback mechanism for the other backends + class Updater implements GLEventListener { + private Graphics g; + + public void setGraphics(Graphics g) { + this.g = g; + } + + public void init(GLAutoDrawable drawable) { + if (!backend.preGL(g)) { + return; + } + drawableHelper.init(GLJPanel.this); + backend.postGL(g, false); + } + + public void dispose(GLAutoDrawable drawable) { + drawableHelper.dispose(GLJPanel.this); + } + + public void display(GLAutoDrawable drawable) { + if (!backend.preGL(g)) { + return; + } + if (sendReshape) { + if (DEBUG) { + System.err.println("glViewport(" + viewportX + ", " + viewportY + ", " + panelWidth + ", " + panelHeight + ")"); + } + getGL().getGL2().glViewport(viewportX, viewportY, panelWidth, panelHeight); + drawableHelper.reshape(GLJPanel.this, viewportX, viewportY, panelWidth, panelHeight); + sendReshape = false; + } + + drawableHelper.display(GLJPanel.this); + backend.postGL(g, true); + } + + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + // This is handled above and dispatched directly to the appropriate context + } + + public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) { + } + } + + public String toString() { + return "AWT-GLJPanel[ "+((null!=backend)?backend.getDrawable().getClass().getName():"null-drawable")+", "+drawableHelper+"]"; + } + + private boolean disposeRegenerate; + private GLContext disposeContext; + private GLDrawable disposeDrawable; + private DisposeAction disposeAction = new DisposeAction(); + + class DisposeAction implements Runnable { + public void run() { + updater.dispose(GLJPanel.this); + + if(null!=disposeContext) { + disposeContext.destroy(); + disposeContext=null; + } + if(null!=disposeDrawable) { + disposeDrawable.setRealized(false); + } + if(disposeRegenerate && null!=disposeDrawable) { + disposeDrawable.setRealized(true); + disposeContext = (GLContextImpl) disposeDrawable.createContext(shareWith); + disposeContext.setSynchronized(true); + } + } + } + + private DisposeOnEventDispatchThreadAction disposeOnEventDispatchThreadAction = + new DisposeOnEventDispatchThreadAction(); + + class DisposeOnEventDispatchThreadAction implements Runnable { + public void run() { + drawableHelper.invokeGL(disposeDrawable, disposeContext, disposeAction, null); + } + } + + + class InitAction implements Runnable { + public void run() { + updater.init(GLJPanel.this); + } + } + private InitAction initAction = new InitAction(); + + class DisplayAction implements Runnable { + public void run() { + updater.display(GLJPanel.this); + } + } + private DisplayAction displayAction = new DisplayAction(); + + class PaintImmediatelyAction implements Runnable { + public void run() { + paintImmediately(0, 0, getWidth(), getHeight()); + } + } + private PaintImmediatelyAction paintImmediatelyAction = new PaintImmediatelyAction(); + + private int getNextPowerOf2(int number) { + // Workaround for problems where 0 width or height are transiently + // seen during layout + if (number == 0) { + return 2; + } + + if (((number-1) & number) == 0) { + //ex: 8 -> 0b1000; 8-1=7 -> 0b0111; 0b1000&0b0111 == 0 + return number; + } + int power = 0; + while (number > 0) { + number = number>>1; + power++; + } + return (1<<power); + } + + private int getGLInteger(GL gl, int which) { + int[] tmp = new int[1]; + gl.glGetIntegerv(which, tmp, 0); + return tmp[0]; + } + + //---------------------------------------------------------------------- + // Implementations of the various backends + // + + // Abstraction of the different rendering backends: i.e., pure + // software / pixmap rendering, pbuffer-based acceleration, Java 2D + // / JOGL bridge + static interface Backend { + // Called each time the backend needs to initialize itself + public void initialize(); + + // Called when the backend should clean up its resources + public void destroy(); + + // Called when the opacity of the GLJPanel is changed + public void setOpaque(boolean opaque); + + // Called to manually create an additional OpenGL context against + // this GLJPanel + public GLContext createContext(GLContext shareWith); + + // Called to set the current backend's GLContext + public void setContext(GLContext ctx); + + // Called to get the current backend's GLContext + public GLContext getContext(); + + // Called to get the current backend's GLDrawable + public GLDrawable getDrawable(); + + // Called to fetch the "real" GLCapabilities for the backend + public GLCapabilities getChosenGLCapabilities(); + + // Called to fetch the "real" GLProfile for the backend + public GLProfile getGLProfile(); + + // Called to handle a reshape event. When this is called, the + // OpenGL context associated with the backend is not current, to + // make it easier to destroy and re-create pbuffers if necessary. + public void handleReshape(); + + // Called before the OpenGL work is done in init() and display(). + // If false is returned, this render is aborted. + public boolean preGL(Graphics g); + + // Called after the OpenGL work is done in init() and display(). + // The isDisplay argument indicates whether this was called on + // behalf of a call to display() rather than init(). + public void postGL(Graphics g, boolean isDisplay); + + // Called from within paintComponent() to initiate the render + public void doPaintComponent(Graphics g); + } + + // Base class used by both the software (pixmap) and pbuffer + // backends, both of which rely on reading back the OpenGL frame + // buffer and drawing it with a BufferedImage + abstract class AbstractReadbackBackend implements Backend { + // This image is exactly the correct size to render into the panel + protected BufferedImage offscreenImage; + // One of these is used to store the read back pixels before storing + // in the BufferedImage + protected ByteBuffer readBackBytes; + protected IntBuffer readBackInts; + protected int readBackWidthInPixels; + protected int readBackHeightInPixels; + + private int awtFormat; + private int glFormat; + private int glType; + + // For saving/restoring of OpenGL state during ReadPixels + private int[] swapbytes = 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]; + + public void setOpaque(boolean opaque) { + if (opaque != isOpaque()) { + if (offscreenImage != null) { + offscreenImage.flush(); + offscreenImage = null; + } + } + } + + public boolean preGL(Graphics g) { + // Empty in this implementation + return true; + } + + public void postGL(Graphics g, boolean isDisplay) { + if (isDisplay) { + // Must now copy pixels from offscreen context into surface + if (offscreenImage == null) { + if (panelWidth > 0 && panelHeight > 0) { + // It looks like NVidia's drivers (at least the ones on my + // notebook) are buggy and don't allow a sub-rectangle to be + // read from a pbuffer...this doesn't really matter because + // it's the Graphics.drawImage() calls that are the + // bottleneck + + int awtFormat = 0; + + // Should be more flexible in these BufferedImage formats; + // perhaps see what the preferred image types are on the + // given platform + if (isOpaque()) { + awtFormat = BufferedImage.TYPE_INT_RGB; + } else { + awtFormat = BufferedImage.TYPE_INT_ARGB; + } + + offscreenImage = new BufferedImage(panelWidth, + panelHeight, + awtFormat); + switch (awtFormat) { + case BufferedImage.TYPE_3BYTE_BGR: + glFormat = GL2.GL_BGR; + glType = GL2.GL_UNSIGNED_BYTE; + readBackBytes = ByteBuffer.allocate(readBackWidthInPixels * readBackHeightInPixels * 3); + break; + + case BufferedImage.TYPE_INT_RGB: + case BufferedImage.TYPE_INT_ARGB: + glFormat = GL2.GL_BGRA; + glType = getGLPixelType(); + readBackInts = IntBuffer.allocate(readBackWidthInPixels * readBackHeightInPixels); + 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); + } + } + } + + if (offscreenImage != null) { + GL2 gl = getGL().getGL2(); + // Save current modes + gl.glGetIntegerv(GL2.GL_PACK_SWAP_BYTES, swapbytes, 0); + gl.glGetIntegerv(GL2.GL_PACK_ROW_LENGTH, rowlength, 0); + gl.glGetIntegerv(GL2.GL_PACK_SKIP_ROWS, skiprows, 0); + gl.glGetIntegerv(GL2.GL_PACK_SKIP_PIXELS, skippixels, 0); + gl.glGetIntegerv(GL2.GL_PACK_ALIGNMENT, alignment, 0); + + gl.glPixelStorei(GL2.GL_PACK_SWAP_BYTES, GL.GL_FALSE); + gl.glPixelStorei(GL2.GL_PACK_ROW_LENGTH, readBackWidthInPixels); + gl.glPixelStorei(GL2.GL_PACK_SKIP_ROWS, 0); + gl.glPixelStorei(GL2.GL_PACK_SKIP_PIXELS, 0); + gl.glPixelStorei(GL2.GL_PACK_ALIGNMENT, 1); + + // Actually read the pixels. + gl.glReadBuffer(GL2.GL_FRONT); + if (readBackBytes != null) { + gl.glReadPixels(0, 0, readBackWidthInPixels, readBackHeightInPixels, glFormat, glType, readBackBytes); + } else if (readBackInts != null) { + gl.glReadPixels(0, 0, readBackWidthInPixels, readBackHeightInPixels, glFormat, glType, readBackInts); + } + + // Restore saved modes. + gl.glPixelStorei(GL2.GL_PACK_SWAP_BYTES, swapbytes[0]); + gl.glPixelStorei(GL2.GL_PACK_ROW_LENGTH, rowlength[0]); + gl.glPixelStorei(GL2.GL_PACK_SKIP_ROWS, skiprows[0]); + gl.glPixelStorei(GL2.GL_PACK_SKIP_PIXELS, skippixels[0]); + gl.glPixelStorei(GL2.GL_PACK_ALIGNMENT, alignment[0]); + + if (readBackBytes != null || readBackInts != null) { + // Copy temporary data into raster of BufferedImage for faster + // blitting Note that we could avoid this copy in the cases + // where !offscreenContext.offscreenImageNeedsVerticalFlip(), + // but that's the software rendering path which is very slow + // anyway + Object src = null; + Object dest = null; + int srcIncr = 0; + int destIncr = 0; + + if (readBackBytes != null) { + src = readBackBytes.array(); + dest = ((DataBufferByte) offscreenImage.getRaster().getDataBuffer()).getData(); + srcIncr = readBackWidthInPixels * 3; + destIncr = offscreenImage.getWidth() * 3; + } else { + src = readBackInts.array(); + dest = ((DataBufferInt) offscreenImage.getRaster().getDataBuffer()).getData(); + srcIncr = readBackWidthInPixels; + destIncr = offscreenImage.getWidth(); + } + + if (flipVertically()) { + int srcPos = 0; + int destPos = (offscreenImage.getHeight() - 1) * destIncr; + for (; destPos >= 0; srcPos += srcIncr, destPos -= destIncr) { + System.arraycopy(src, srcPos, dest, destPos, destIncr); + } + } else { + int srcPos = 0; + int destEnd = destIncr * offscreenImage.getHeight(); + for (int destPos = 0; destPos < destEnd; srcPos += srcIncr, destPos += destIncr) { + System.arraycopy(src, srcPos, dest, destPos, destIncr); + } + } + + // Note: image will be drawn back in paintComponent() for + // correctness on all platforms + } + } + } + } + + public void doPaintComponent(Graphics g) { + doPaintComponentImpl(); + if (offscreenImage != null) { + // Draw resulting image in one shot + g.drawImage(offscreenImage, 0, 0, + offscreenImage.getWidth(), + offscreenImage.getHeight(), + GLJPanel.this); + } + } + + protected abstract void doPaintComponentImpl(); + protected abstract int getGLPixelType(); + protected abstract boolean flipVertically(); + } + + class SoftwareBackend extends AbstractReadbackBackend { + // Implementation using software rendering + private GLDrawableImpl offscreenDrawable; + private GLContextImpl offscreenContext; + + public void initialize() { + // Fall-through path: create an offscreen context instead + offscreenDrawable = factory.createOffscreenDrawable(offscreenCaps, + chooser, + Math.max(1, panelWidth), + Math.max(1, panelHeight)); + offscreenContext = (GLContextImpl) offscreenDrawable.createContext(shareWith); + offscreenContext.setSynchronized(true); + isInitialized = true; + } + + public void destroy() { + if (offscreenContext != null) { + offscreenContext.destroy(); + offscreenContext = null; + } + if (offscreenDrawable != null) { + offscreenDrawable.destroy(); + offscreenDrawable = null; + } + } + + public GLContext createContext(GLContext shareWith) { + return offscreenDrawable.createContext(shareWith); + } + + public void setContext(GLContext ctx) { + offscreenContext=(GLContextImpl)ctx; + } + + public GLContext getContext() { + return offscreenContext; + } + + public GLDrawable getDrawable() { + return offscreenDrawable; + } + + public GLCapabilities getChosenGLCapabilities() { + if (offscreenDrawable == null) { + return null; + } + return offscreenDrawable.getChosenGLCapabilities(); + } + + public GLProfile getGLProfile() { + if (offscreenDrawable == null) { + return null; + } + return offscreenDrawable.getGLProfile(); + } + + public void handleReshape() { + destroy(); + initialize(); + readBackWidthInPixels = Math.max(1, panelWidth); + readBackHeightInPixels = Math.max(1, panelHeight); + + if (offscreenImage != null) { + offscreenImage.flush(); + offscreenImage = null; + } + } + + protected void doPaintComponentImpl() { + drawableHelper.invokeGL(offscreenDrawable, offscreenContext, displayAction, initAction); + } + + protected int getGLPixelType() { + return offscreenContext.getOffscreenContextPixelDataType(); + } + + protected boolean flipVertically() { + return offscreenContext.offscreenImageNeedsVerticalFlip(); + } + } + + class PbufferBackend extends AbstractReadbackBackend { + private GLPbuffer pbuffer; + private int pbufferWidth = 256; + private int pbufferHeight = 256; + + public void initialize() { + if (pbuffer != null) { + throw new InternalError("Creating pbuffer twice without destroying it (memory leak / correctness bug)"); + } + try { + pbuffer = factory.createGLPbuffer(offscreenCaps, + null, + pbufferWidth, + pbufferHeight, + shareWith); + pbuffer.addGLEventListener(updater); + isInitialized = true; + } catch (GLException e) { + if (DEBUG) { + e.printStackTrace(); + System.err.println("GLJPanel: Falling back on software rendering because of problems creating pbuffer"); + } + hardwareAccelerationDisabled = true; + backend = null; + isInitialized = false; + createAndInitializeBackend(); + } + } + + public void destroy() { + if (pbuffer != null) { + pbuffer.destroy(); + pbuffer = null; + } + } + + public GLContext createContext(GLContext shareWith) { + return pbuffer.createContext(shareWith); + } + + public void setContext(GLContext ctx) { + if (pbuffer == null && Beans.isDesignTime()) { + return; + } + pbuffer.setContext(ctx); + } + + public GLContext getContext() { + // Workaround for crashes in NetBeans GUI builder + if (pbuffer == null && Beans.isDesignTime()) { + return null; + } + return pbuffer.getContext(); + } + + public GLDrawable getDrawable() { + return pbuffer; + } + + public GLCapabilities getChosenGLCapabilities() { + if (pbuffer == null) { + return null; + } + return pbuffer.getChosenGLCapabilities(); + } + + public GLProfile getGLProfile() { + if (pbuffer == null) { + return null; + } + return pbuffer.getGLProfile(); + } + + public void handleReshape() { + // Use factor larger than 2 during shrinks for some hysteresis + float shrinkFactor = 2.5f; + if ((panelWidth > pbufferWidth) || (panelHeight > pbufferHeight) || + (panelWidth < (pbufferWidth / shrinkFactor)) || (panelHeight < (pbufferHeight / shrinkFactor))) { + if (DEBUG) { + System.err.println("Resizing pbuffer from (" + pbufferWidth + ", " + pbufferHeight + ") " + + " to fit (" + panelWidth + ", " + panelHeight + ")"); + } + // Must destroy and recreate pbuffer to fit + if (pbuffer != null) { + // Watch for errors during pbuffer destruction (due to + // buggy / bad OpenGL drivers, in particular SiS) and fall + // back to software rendering + try { + pbuffer.destroy(); + } catch (GLException e) { + hardwareAccelerationDisabled = true; + backend = null; + isInitialized = false; + // Just disabled hardware acceleration during this resize operation; do a fixup + readBackWidthInPixels = Math.max(1, panelWidth); + readBackHeightInPixels = Math.max(1, panelHeight); + if (DEBUG) { + System.err.println("WARNING: falling back to software rendering due to bugs in OpenGL drivers"); + e.printStackTrace(); + } + createAndInitializeBackend(); + return; + } + } + pbuffer = null; + isInitialized = false; + pbufferWidth = getNextPowerOf2(panelWidth); + pbufferHeight = getNextPowerOf2(panelHeight); + if (DEBUG && !hardwareAccelerationDisabled) { + System.err.println("New pbuffer size is (" + pbufferWidth + ", " + pbufferHeight + ")"); + } + initialize(); + } + + // It looks like NVidia's drivers (at least the ones on my + // notebook) are buggy and don't allow a rectangle of less than + // the pbuffer's width to be read...this doesn't really matter + // because it's the Graphics.drawImage() calls that are the + // bottleneck. Should probably make the size of the offscreen + // image be the exact size of the pbuffer to save some work on + // resize operations... + readBackWidthInPixels = pbufferWidth; + readBackHeightInPixels = panelHeight; + + if (offscreenImage != null) { + offscreenImage.flush(); + offscreenImage = null; + } + } + + protected void doPaintComponentImpl() { + pbuffer.display(); + } + + protected int getGLPixelType() { + // This seems to be a good choice on all platforms + return GL2.GL_UNSIGNED_INT_8_8_8_8_REV; + } + + protected boolean flipVertically() { + return true; + } + } + + class J2DOGLBackend implements Backend { + // Opaque Object identifier representing the Java2D surface we are + // drawing to; used to determine when to destroy and recreate JOGL + // context + private Object j2dSurface; + // Graphics object being used during Java2D update action + // (absolutely essential to cache this) + private Graphics cached2DGraphics; + // No-op context representing the Java2D OpenGL context + private GLContext j2dContext; + // Context associated with no-op drawable representing the JOGL + // OpenGL context + private GLDrawable joglDrawable; + // The real OpenGL context JOGL uses to render + private GLContext joglContext; + // State captured from Java2D OpenGL context necessary in order to + // properly render into Java2D back buffer + private int[] drawBuffer = new int[1]; + private int[] readBuffer = new int[1]; + // This is required when the FBO option of the Java2D / OpenGL + // pipeline is active + private int[] frameBuffer = new int[1]; + // Current (as of this writing) NVidia drivers have a couple of bugs + // relating to the sharing of framebuffer and renderbuffer objects + // between contexts. It appears we have to (a) reattach the color + // attachment and (b) actually create new depth buffer storage and + // attach it in order for the FBO to behave properly in our context. + private boolean checkedForFBObjectWorkarounds; + private boolean fbObjectWorkarounds; + private int[] frameBufferDepthBuffer; + private int[] frameBufferTexture; + private boolean createNewDepthBuffer; + // Current (as of this writing) ATI drivers have problems when the + // same FBO is bound in two different contexts. Here we check for + // this case and explicitly release the FBO from Java2D's context + // before switching to ours. Java2D will re-bind the FBO when it + // makes its context current the next time. Interestingly, if we run + // this code path on NVidia hardware, it breaks the rendering + // results -- no output is generated. This doesn't appear to be an + // interaction with the abovementioned NVidia-specific workarounds, + // as even if we disable that code the FBO is still reported as + // incomplete in our context. + private boolean checkedGLVendor; + private boolean vendorIsATI; + + // Holding on to this GraphicsConfiguration is a workaround for a + // problem in the Java 2D / JOGL bridge when FBOs are enabled; see + // comment related to Issue 274 below + private GraphicsConfiguration workaroundConfig; + + public void initialize() { + // No-op in this implementation; everything is done lazily + isInitialized = true; + } + + public void destroy() { + Java2D.invokeWithOGLContextCurrent(null, new Runnable() { + public void run() { + if (joglContext != null) { + joglContext.destroy(); + joglContext = null; + } + joglDrawable = null; + if (j2dContext != null) { + j2dContext.destroy(); + j2dContext = null; + } + } + }); + } + + public void setOpaque(boolean opaque) { + // Empty in this implementation + } + + public GLContext createContext(GLContext shareWith) { + // FIXME: should implement this, but it was not properly + // implemented before the refactoring anyway + throw new GLException("Not yet implemented"); + } + + public void setContext(GLContext ctx) { + joglContext=ctx; + } + + public GLContext getContext() { + return joglContext; + } + + public GLDrawable getDrawable() { + return joglDrawable; + } + + public GLCapabilities getChosenGLCapabilities() { + // FIXME: should do better than this; is it possible to using only platform-independent code? + return new GLCapabilities(null); + } + + public GLProfile getGLProfile() { + // FIXME: should do better than this; is it possible to using only platform-independent code? + return GLProfile.getDefault(); + } + + public void handleReshape() { + // Empty in this implementation + } + + public boolean preGL(Graphics g) { + GL2 gl = joglContext.getGL().getGL2(); + // Set up needed state in JOGL context from Java2D context + gl.glEnable(GL2.GL_SCISSOR_TEST); + Rectangle r = Java2D.getOGLScissorBox(g); + + if (r == null) { + if (DEBUG && VERBOSE) { + System.err.println("Java2D.getOGLScissorBox() returned null"); + } + return false; + } + if (DEBUG && VERBOSE) { + System.err.println("GLJPanel: gl.glScissor(" + r.x + ", " + r.y + ", " + r.width + ", " + r.height + ")"); + } + + gl.glScissor(r.x, r.y, r.width, r.height); + Rectangle oglViewport = Java2D.getOGLViewport(g, panelWidth, panelHeight); + // If the viewport X or Y changes, in addition to the panel's + // width or height, we need to send a reshape operation to the + // client + if ((viewportX != oglViewport.x) || + (viewportY != oglViewport.y)) { + sendReshape = true; + if (DEBUG) { + System.err.println("Sending reshape because viewport changed"); + System.err.println(" viewportX (" + viewportX + ") ?= oglViewport.x (" + oglViewport.x + ")"); + System.err.println(" viewportY (" + viewportY + ") ?= oglViewport.y (" + oglViewport.y + ")"); + } + } + viewportX = oglViewport.x; + viewportY = oglViewport.y; + + // If the FBO option is active, bind to the FBO from the Java2D + // context. + // Note that all of the plumbing in the context sharing stuff will + // allow us to bind to this object since it's in our namespace. + if (Java2D.isFBOEnabled() && + Java2D.getOGLSurfaceType(g) == Java2D.FBOBJECT) { + if (DEBUG && VERBOSE) { + System.err.println("GLJPanel: Binding to framebuffer object " + frameBuffer[0]); + } + + // The texture target for Java2D's OpenGL pipeline when using FBOs + // -- either GL_TEXTURE_2D or GL_TEXTURE_RECTANGLE_ARB + int fboTextureTarget = Java2D.getOGLTextureType(g); + + if (!checkedForFBObjectWorkarounds) { + checkedForFBObjectWorkarounds = true; + gl.glBindTexture(fboTextureTarget, 0); + gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, frameBuffer[0]); + if (gl.glCheckFramebufferStatus(GL2.GL_FRAMEBUFFER) != + GL2.GL_FRAMEBUFFER_COMPLETE) { + // Need to do workarounds + fbObjectWorkarounds = true; + createNewDepthBuffer = true; + if (DEBUG) { + System.err.println("-- GLJPanel: discovered frame_buffer_object workarounds to be necessary"); + } + } else { + // Don't need the frameBufferTexture temporary any more + frameBufferTexture = null; + } + } + + if (fbObjectWorkarounds && createNewDepthBuffer) { + if (frameBufferDepthBuffer == null) + frameBufferDepthBuffer = new int[1]; + + // Create our own depth renderbuffer and associated storage + // If we have an old one, delete it + if (frameBufferDepthBuffer[0] != 0) { + gl.glDeleteRenderbuffers(1, frameBufferDepthBuffer, 0); + frameBufferDepthBuffer[0] = 0; + } + + gl.glBindTexture(fboTextureTarget, frameBufferTexture[0]); + int[] width = new int[1]; + int[] height = new int[1]; + gl.glGetTexLevelParameteriv(fboTextureTarget, 0, GL2.GL_TEXTURE_WIDTH, width, 0); + gl.glGetTexLevelParameteriv(fboTextureTarget, 0, GL2.GL_TEXTURE_HEIGHT, height, 0); + + gl.glGenRenderbuffers(1, frameBufferDepthBuffer, 0); + if (DEBUG) { + System.err.println("GLJPanel: Generated frameBufferDepthBuffer " + frameBufferDepthBuffer[0] + + " with width " + width[0] + ", height " + height[0]); + } + + gl.glBindRenderbuffer(GL2.GL_RENDERBUFFER, frameBufferDepthBuffer[0]); + // FIXME: may need a loop here like in Java2D + gl.glRenderbufferStorage(GL2.GL_RENDERBUFFER, GL2.GL_DEPTH_COMPONENT24, width[0], height[0]); + + gl.glBindRenderbuffer(GL2.GL_RENDERBUFFER, 0); + createNewDepthBuffer = false; + } + + gl.glBindTexture(fboTextureTarget, 0); + gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, frameBuffer[0]); + + if (fbObjectWorkarounds) { + // Hook up the color and depth buffer attachment points for this framebuffer + gl.glFramebufferTexture2D(GL2.GL_FRAMEBUFFER, + GL2.GL_COLOR_ATTACHMENT0, + fboTextureTarget, + frameBufferTexture[0], + 0); + if (DEBUG && VERBOSE) { + System.err.println("GLJPanel: frameBufferDepthBuffer: " + frameBufferDepthBuffer[0]); + } + gl.glFramebufferRenderbuffer(GL2.GL_FRAMEBUFFER, + GL2.GL_DEPTH_ATTACHMENT, + GL2.GL_RENDERBUFFER, + frameBufferDepthBuffer[0]); + } + + if (DEBUG) { + int status = gl.glCheckFramebufferStatus(GL2.GL_FRAMEBUFFER); + if (status != GL2.GL_FRAMEBUFFER_COMPLETE) { + throw new GLException("Error: framebuffer was incomplete: status = 0x" + + Integer.toHexString(status)); + } + } + } else { + if (DEBUG && VERBOSE) { + System.err.println("GLJPanel: Setting up drawBuffer " + drawBuffer[0] + + " and readBuffer " + readBuffer[0]); + } + + gl.glDrawBuffer(drawBuffer[0]); + gl.glReadBuffer(readBuffer[0]); + } + + return true; + } + + public void postGL(Graphics g, boolean isDisplay) { + // Cause OpenGL pipeline to flush its results because + // otherwise it's possible we will buffer up multiple frames' + // rendering results, resulting in apparent mouse lag + GL gl = getGL(); + gl.glFinish(); + + if (Java2D.isFBOEnabled() && + Java2D.getOGLSurfaceType(g) == Java2D.FBOBJECT) { + // Unbind the framebuffer from our context to work around + // apparent driver bugs or at least unspecified behavior causing + // OpenGL to run out of memory with certain cards and drivers + gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0); + } + } + + public void doPaintComponent(final Graphics g) { + // This is a workaround for an issue in the Java 2D / JOGL + // bridge (reported by an end user as JOGL Issue 274) where Java + // 2D can occasionally leave its internal OpenGL context current + // to the on-screen window rather than its internal "scratch" + // pbuffer surface to which the FBO is attached. JOGL expects to + // find a stable OpenGL drawable (on Windows, an HDC) upon which + // it can create another OpenGL context. It turns out that, on + // Windows, when Java 2D makes its internal OpenGL context + // current against the window in order to put pixels on the + // screen, it gets the device context for the window, makes its + // context current, and releases the device context. This means + // that when JOGL's Runnable gets to run below, the HDC is + // already invalid. The workaround for this is to force Java 2D + // to make its context current to the scratch surface, which we + // can do by executing an empty Runnable with the "shared" + // context current. This will be fixed in a Java SE 6 update + // release, hopefully 6u2. + if (Java2D.isFBOEnabled()) { + if (workaroundConfig == null) { + workaroundConfig = GraphicsEnvironment. + getLocalGraphicsEnvironment(). + getDefaultScreenDevice(). + getDefaultConfiguration(); + } + Java2D.invokeWithOGLSharedContextCurrent(workaroundConfig, new Runnable() { public void run() {}}); + } + + Java2D.invokeWithOGLContextCurrent(g, new Runnable() { + public void run() { + if (DEBUG && VERBOSE) { + System.err.println("-- In invokeWithOGLContextCurrent"); + } + + // Create no-op context representing Java2D context + if (j2dContext == null) { + j2dContext = factory.createExternalGLContext(); + if (DEBUG) { + j2dContext.setGL(new DebugGL2(j2dContext.getGL().getGL2())); + } + + // Check to see whether we can support the requested + // capabilities or need to fall back to a pbuffer + // FIXME: add more checks? + + j2dContext.makeCurrent(); + GL gl = j2dContext.getGL(); + if ((getGLInteger(gl, GL2.GL_RED_BITS) < offscreenCaps.getRedBits()) || + (getGLInteger(gl, GL2.GL_GREEN_BITS) < offscreenCaps.getGreenBits()) || + (getGLInteger(gl, GL2.GL_BLUE_BITS) < offscreenCaps.getBlueBits()) || + // (getGLInteger(gl, GL2.GL_ALPHA_BITS) < offscreenCaps.getAlphaBits()) || + (getGLInteger(gl, GL2.GL_ACCUM_RED_BITS) < offscreenCaps.getAccumRedBits()) || + (getGLInteger(gl, GL2.GL_ACCUM_GREEN_BITS) < offscreenCaps.getAccumGreenBits()) || + (getGLInteger(gl, GL2.GL_ACCUM_BLUE_BITS) < offscreenCaps.getAccumBlueBits()) || + (getGLInteger(gl, GL2.GL_ACCUM_ALPHA_BITS) < offscreenCaps.getAccumAlphaBits()) || + // (getGLInteger(gl, GL2.GL_DEPTH_BITS) < offscreenCaps.getDepthBits()) || + (getGLInteger(gl, GL2.GL_STENCIL_BITS) < offscreenCaps.getStencilBits())) { + if (DEBUG) { + System.err.println("GLJPanel: Falling back to pbuffer-based support because Java2D context insufficient"); + System.err.println(" Available Required"); + System.err.println("GL_RED_BITS " + getGLInteger(gl, GL2.GL_RED_BITS) + " " + offscreenCaps.getRedBits()); + System.err.println("GL_GREEN_BITS " + getGLInteger(gl, GL2.GL_GREEN_BITS) + " " + offscreenCaps.getGreenBits()); + System.err.println("GL_BLUE_BITS " + getGLInteger(gl, GL2.GL_BLUE_BITS) + " " + offscreenCaps.getBlueBits()); + System.err.println("GL_ALPHA_BITS " + getGLInteger(gl, GL2.GL_ALPHA_BITS) + " " + offscreenCaps.getAlphaBits()); + System.err.println("GL_ACCUM_RED_BITS " + getGLInteger(gl, GL2.GL_ACCUM_RED_BITS) + " " + offscreenCaps.getAccumRedBits()); + System.err.println("GL_ACCUM_GREEN_BITS " + getGLInteger(gl, GL2.GL_ACCUM_GREEN_BITS) + " " + offscreenCaps.getAccumGreenBits()); + System.err.println("GL_ACCUM_BLUE_BITS " + getGLInteger(gl, GL2.GL_ACCUM_BLUE_BITS) + " " + offscreenCaps.getAccumBlueBits()); + System.err.println("GL_ACCUM_ALPHA_BITS " + getGLInteger(gl, GL2.GL_ACCUM_ALPHA_BITS) + " " + offscreenCaps.getAccumAlphaBits()); + System.err.println("GL_DEPTH_BITS " + getGLInteger(gl, GL2.GL_DEPTH_BITS) + " " + offscreenCaps.getDepthBits()); + System.err.println("GL_STENCIL_BITS " + getGLInteger(gl, GL2.GL_STENCIL_BITS) + " " + offscreenCaps.getStencilBits()); + } + isInitialized = false; + backend = null; + oglPipelineEnabled = false; + handleReshape = true; + j2dContext.release(); + j2dContext.destroy(); + j2dContext = null; + return; + } + j2dContext.release(); + } + + j2dContext.makeCurrent(); + try { + captureJ2DState(j2dContext.getGL(), g); + Object curSurface = Java2D.getOGLSurfaceIdentifier(g); + if (curSurface != null) { + if (j2dSurface != curSurface) { + if (joglContext != null) { + joglContext.destroy(); + joglContext = null; + joglDrawable = null; + sendReshape = true; + if (DEBUG) { + System.err.println("Sending reshape because surface changed"); + System.err.println("New surface = " + curSurface); + } + } + j2dSurface = curSurface; + } + if (joglContext == null) { + if (factory.canCreateExternalGLDrawable()) { + joglDrawable = factory.createExternalGLDrawable(); + joglContext = joglDrawable.createContext(shareWith); + } else if (factory.canCreateContextOnJava2DSurface()) { + // Mac OS X code path + joglContext = factory.createContextOnJava2DSurface(g, shareWith); + } + if (DEBUG) { + joglContext.setGL(new DebugGL2(joglContext.getGL().getGL2())); + } + + if (Java2D.isFBOEnabled() && + Java2D.getOGLSurfaceType(g) == Java2D.FBOBJECT && + fbObjectWorkarounds) { + createNewDepthBuffer = true; + } + } + if (joglContext instanceof Java2DGLContext) { + // Mac OS X code path + ((Java2DGLContext) joglContext).setGraphics(g); + } + + if (DEBUG && VERBOSE && Java2D.isFBOEnabled()) { + System.err.print("-- Surface type: "); + int surfaceType = Java2D.getOGLSurfaceType(g); + if (surfaceType == Java2D.UNDEFINED) { + System.err.println("UNDEFINED"); + } else if (surfaceType == Java2D.WINDOW) { + System.err.println("WINDOW"); + } else if (surfaceType == Java2D.PBUFFER) { + System.err.println("PBUFFER"); + } else if (surfaceType == Java2D.TEXTURE) { + System.err.println("TEXTURE"); + } else if (surfaceType == Java2D.FLIP_BACKBUFFER) { + System.err.println("FLIP_BACKBUFFER"); + } else if (surfaceType == Java2D.FBOBJECT) { + System.err.println("FBOBJECT"); + } else { + System.err.println("(Unknown surface type " + surfaceType + ")"); + } + } + + drawableHelper.invokeGL(joglDrawable, joglContext, displayAction, initAction); + } + } finally { + j2dContext.release(); + } + } + }); + } + + private void captureJ2DState(GL gl, Graphics g) { + gl.glGetIntegerv(GL2.GL_DRAW_BUFFER, drawBuffer, 0); + gl.glGetIntegerv(GL2.GL_READ_BUFFER, readBuffer, 0); + if (Java2D.isFBOEnabled() && + Java2D.getOGLSurfaceType(g) == Java2D.FBOBJECT) { + if (DEBUG && VERBOSE) { + System.err.println("GLJPanel: Fetching GL_FRAMEBUFFER_BINDING_EXT"); + } + gl.glGetIntegerv(GL2.GL_FRAMEBUFFER_BINDING, frameBuffer, 0); + + if (fbObjectWorkarounds || + !checkedForFBObjectWorkarounds) { + // See above for description of what we are doing here + if (frameBufferTexture == null) + frameBufferTexture = new int[1]; + + // Query the framebuffer for its color buffer so we can hook + // it back up in our context (should not be necessary) + gl.glGetFramebufferAttachmentParameteriv(GL2.GL_FRAMEBUFFER, + GL2.GL_COLOR_ATTACHMENT0, + GL2.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, + frameBufferTexture, 0); + if (DEBUG && VERBOSE) { + System.err.println("GLJPanel: FBO COLOR_ATTACHMENT0: " + frameBufferTexture[0]); + } + } + + if (!checkedGLVendor) { + checkedGLVendor = true; + String vendor = gl.glGetString(GL2.GL_VENDOR); + + if ((vendor != null) && + vendor.startsWith("ATI")) { + vendorIsATI = true; + } + } + + if (vendorIsATI) { + // Unbind the FBO from Java2D's context as it appears that + // driver bugs on ATI's side are causing problems if the FBO is + // simultaneously bound to more than one context. Java2D will + // re-bind the FBO during the next validation of its context. + // Note: this breaks rendering at least on NVidia hardware + gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, 0); + } + } + } + } +} diff --git a/src/jogl/classes/javax/media/opengl/fixedfunc/GLLightingFunc.java b/src/jogl/classes/javax/media/opengl/fixedfunc/GLLightingFunc.java new file mode 100644 index 000000000..5563ea9c8 --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/fixedfunc/GLLightingFunc.java @@ -0,0 +1,49 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + */ + +package javax.media.opengl.fixedfunc; + +import java.nio.*; + +import javax.media.opengl.*; + +public interface GLLightingFunc { + public static final int GL_LIGHT0 = 0x4000; + public static final int GL_LIGHT1 = 0x4001; + public static final int GL_LIGHT2 = 0x4002; + public static final int GL_LIGHT3 = 0x4003; + public static final int GL_LIGHT4 = 0x4004; + public static final int GL_LIGHT5 = 0x4005; + public static final int GL_LIGHT6 = 0x4006; + public static final int GL_LIGHT7 = 0x4007; + public static final int GL_LIGHTING = 0xB50; + public static final int GL_AMBIENT = 0x1200; + public static final int GL_DIFFUSE = 0x1201; + public static final int GL_SPECULAR = 0x1202; + public static final int GL_POSITION = 0x1203; + public static final int GL_SPOT_DIRECTION = 0x1204; + public static final int GL_SPOT_EXPONENT = 0x1205; + public static final int GL_SPOT_CUTOFF = 0x1206; + public static final int GL_CONSTANT_ATTENUATION = 0x1207; + public static final int GL_LINEAR_ATTENUATION = 0x1208; + public static final int GL_QUADRATIC_ATTENUATION = 0x1209; + public static final int GL_EMISSION = 0x1600; + public static final int GL_SHININESS = 0x1601; + public static final int GL_AMBIENT_AND_DIFFUSE = 0x1602; + public static final int GL_COLOR_MATERIAL = 0xB57; + public static final int GL_NORMALIZE = 0xBA1; + + public static final int GL_FLAT = 0x1D00; + public static final int GL_SMOOTH = 0x1D01; + + public void glLightfv(int light, int pname, java.nio.FloatBuffer params); + public void glLightfv(int light, int pname, float[] params, int params_offset); + public void glMaterialf(int face, int pname, float param); + public void glMaterialfv(int face, int pname, java.nio.FloatBuffer params); + public void glMaterialfv(int face, int pname, float[] params, int params_offset); + public void glColor4f(float red, float green, float blue, float alpha); + public void glShadeModel(int mode); + +} + diff --git a/src/jogl/classes/javax/media/opengl/fixedfunc/GLMatrixFunc.java b/src/jogl/classes/javax/media/opengl/fixedfunc/GLMatrixFunc.java new file mode 100644 index 000000000..61757abde --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/fixedfunc/GLMatrixFunc.java @@ -0,0 +1,76 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + */ + +package javax.media.opengl.fixedfunc; + +import java.nio.*; + +import javax.media.opengl.*; + +public interface GLMatrixFunc { + + public static final int GL_MATRIX_MODE = 0x0BA0; + public static final int GL_MODELVIEW = 0x1700; + public static final int GL_PROJECTION = 0x1701; + // public static final int GL_TEXTURE = 0x1702; // Use GL.GL_TEXTURE due to ambiguous GL usage + public static final int GL_MODELVIEW_MATRIX = 0x0BA6; + public static final int GL_PROJECTION_MATRIX = 0x0BA7; + public static final int GL_TEXTURE_MATRIX = 0x0BA8; + + /** + * glGetFloatv + * @param pname GL_MODELVIEW_MATRIX, GL_PROJECTION_MATRIX or GL_TEXTURE_MATRIX + * @param params the FloatBuffer's position remains unchanged, + * which is the same behavior than the native JOGL GL impl + */ + public void glGetFloatv(int pname, java.nio.FloatBuffer params); + public void glGetFloatv(int pname, float[] params, int params_offset); + /** + * glGetIntegerv + * @param pname GL_MATRIX_MODE + * @param params the FloatBuffer's position remains unchanged + * which is the same behavior than the native JOGL GL impl + */ + public void glGetIntegerv(int pname, IntBuffer params); + public void glGetIntegerv(int pname, int[] params, int params_offset); + + /** + * sets the current matrix + * @param pname GL_MODELVIEW, GL_PROJECTION or GL.GL_TEXTURE + */ + public void glMatrixMode(int mode) ; + + public void glPushMatrix(); + public void glPopMatrix(); + + public void glLoadIdentity() ; + + /** + * glLoadMatrixf + * @param params the FloatBuffer's position remains unchanged, + * which is the same behavior than the native JOGL GL impl + */ + public void glLoadMatrixf(java.nio.FloatBuffer m) ; + public void glLoadMatrixf(float[] m, int m_offset); + + /** + * glMultMatrixf + * @param params the FloatBuffer's position remains unchanged, + * which is the same behavior than the native JOGL GL impl + */ + public void glMultMatrixf(java.nio.FloatBuffer m) ; + public void glMultMatrixf(float[] m, int m_offset); + + public void glTranslatef(float x, float y, float z) ; + + public void glRotatef(float angle, float x, float y, float z); + + public void glScalef(float x, float y, float z) ; + + public void glOrthof(float left, float right, float bottom, float top, float zNear, float zFar) ; + + public void glFrustumf(float left, float right, float bottom, float top, float zNear, float zFar); + +} + diff --git a/src/jogl/classes/javax/media/opengl/fixedfunc/GLPointerFunc.java b/src/jogl/classes/javax/media/opengl/fixedfunc/GLPointerFunc.java new file mode 100644 index 000000000..ed7bef5d4 --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/fixedfunc/GLPointerFunc.java @@ -0,0 +1,38 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + */ + +package javax.media.opengl.fixedfunc; + +import java.nio.*; + +import javax.media.opengl.*; + +public interface GLPointerFunc { + public static final int GL_VERTEX_ARRAY = 0x8074; + public static final int GL_NORMAL_ARRAY = 0x8075; + public static final int GL_COLOR_ARRAY = 0x8076; + public static final int GL_TEXTURE_COORD_ARRAY = 0x8078; + + public void glEnableClientState(int arrayName); + public void glDisableClientState(int arrayName); + + public void glVertexPointer(GLArrayData array); + public void glVertexPointer(int size, int type, int stride, java.nio.Buffer pointer); + public void glVertexPointer(int size, int type, int stride, long pointer_buffer_offset); + + public void glColorPointer(GLArrayData array); + public void glColorPointer(int size, int type, int stride, java.nio.Buffer pointer); + public void glColorPointer(int size, int type, int stride, long pointer_buffer_offset); + public void glColor4f(float red, float green, float blue, float alpha); + + public void glNormalPointer(GLArrayData array); + public void glNormalPointer(int type, int stride, java.nio.Buffer pointer); + public void glNormalPointer(int type, int stride, long pointer_buffer_offset); + + public void glTexCoordPointer(GLArrayData array); + public void glTexCoordPointer(int size, int type, int stride, java.nio.Buffer pointer); + public void glTexCoordPointer(int size, int type, int stride, long pointer_buffer_offset); + +} + diff --git a/src/jogl/classes/javax/media/opengl/glu/GLUnurbs.java b/src/jogl/classes/javax/media/opengl/glu/GLUnurbs.java new file mode 100755 index 000000000..2641115d0 --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/glu/GLUnurbs.java @@ -0,0 +1,8 @@ +package javax.media.opengl.glu; + +/** + * Wrapper for a GLU NURBS object. + */ + +public interface GLUnurbs { +} diff --git a/src/jogl/classes/javax/media/opengl/glu/GLUquadric.java b/src/jogl/classes/javax/media/opengl/glu/GLUquadric.java new file mode 100755 index 000000000..d5a7a11f3 --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/glu/GLUquadric.java @@ -0,0 +1,33 @@ +package javax.media.opengl.glu; + +import javax.media.opengl.GL; +import com.sun.opengl.util.ImmModeSink; + +/** + * Wrapper for a GLU quadric object. + */ + +public interface GLUquadric { + // enable/disables the Immediate Mode Sink module. + // This defaults to false for GLUgl2, + // and is always true for GLUes1. + public void enableImmModeSink(boolean val); + + public boolean isImmModeSinkEnabled(); + + // set Immediate Mode usage. + // This defaults to false at GLU creation time. + // If enabled rendering will happen immediately, + // otherwise rendering will be hold in the ImmModeSink + // object, to be rendered deferred. + public void setImmMode(boolean val); + + public boolean getImmMode(); + + // creates a new ImmModeSink (VBO Buffers) and + // returns the old vbo buffer with it's rendering result + public ImmModeSink replaceImmModeSink(); + + // gl may be null, then the GL client states are not disabled + public void resetImmModeSink(GL gl); +} diff --git a/src/jogl/classes/javax/media/opengl/glu/GLUtessellator.java b/src/jogl/classes/javax/media/opengl/glu/GLUtessellator.java new file mode 100755 index 000000000..cb7bd9d76 --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/glu/GLUtessellator.java @@ -0,0 +1,66 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package javax.media.opengl.glu; + +/** + * The <b>GLUtessellator</b> object is used to hold the data, such as the + * vertices, edges and callback objects, to describe and tessellate complex + * polygons. A <b>GLUtessellator</b> object is used with the + * {@link GLU GLU} tessellator methods and + * {@link GLUtessellatorCallback GLU callbacks}. + * + * @author Eric Veach, July 1994 + * @author Java Port: Pepijn Van Eechhoudt, July 2003 + * @author Java Port: Nathan Parker Burg, August 2003 + */ +public interface GLUtessellator {} diff --git a/src/jogl/classes/javax/media/opengl/glu/GLUtessellatorCallback.java b/src/jogl/classes/javax/media/opengl/glu/GLUtessellatorCallback.java new file mode 100755 index 000000000..4b5ec63b7 --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/glu/GLUtessellatorCallback.java @@ -0,0 +1,356 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package javax.media.opengl.glu; + +/** + * <b>GLUtessellatorCallback</b> interface provides methods that the user will + * override to define the callbacks for a tessellation object. + * + * @author Eric Veach, July 1994 + * @author Java Port: Pepijn Van Eeckhoudt, July 2003 + * @author Java Port: Nathan Parker Burg, August 2003 + */ +public interface GLUtessellatorCallback { + /** + * The <b>begin</b> callback method is invoked like + * {@link javax.media.opengl.GL#glBegin glBegin} to indicate the start of a + * (triangle) primitive. The method takes a single argument of type int. If + * the <b>GLU_TESS_BOUNDARY_ONLY</b> property is set to <b>GL_FALSE</b>, then + * the argument is set to either <b>GL_TRIANGLE_FAN</b>, + * <b>GL_TRIANGLE_STRIP</b>, or <b>GL_TRIANGLES</b>. If the + * <b>GLU_TESS_BOUNDARY_ONLY</b> property is set to <b>GL_TRUE</b>, then the + * argument will be set to <b>GL_LINE_LOOP</b>. + * + * @param type + * Specifics the type of begin/end pair being defined. The following + * values are valid: <b>GL_TRIANGLE_FAN</b>, <b>GL_TRIANGLE_STRIP</b>, + * <b>GL_TRIANGLES</b> or <b>GL_LINE_LOOP</b>. + * + * @see GLU#gluTessCallback gluTessCallback + * @see #end end + * @see #begin begin + */ + public void begin(int type); + + /** + * The same as the {@link #begin begin} callback method except that + * it takes an additional reference argument. This reference is + * identical to the opaque reference provided when {@link + * GLU#gluTessBeginPolygon gluTessBeginPolygon} was called. + * + * @param type + * Specifics the type of begin/end pair being defined. The following + * values are valid: <b>GL_TRIANGLE_FAN</b>, <b>GL_TRIANGLE_STRIP</b>, + * <b>GL_TRIANGLES</b> or <b>GL_LINE_LOOP</b>. + * @param polygonData + * Specifics a reference to user-defined data. + * + * @see GLU#gluTessCallback gluTessCallback + * @see #endData endData + * @see #begin begin + */ + public void beginData(int type, Object polygonData); + + + /** + * The <b>edgeFlag</b> callback method is similar to + * {@link javax.media.opengl.GL#glEdgeFlag glEdgeFlag}. The method takes + * a single boolean boundaryEdge that indicates which edges lie on the + * polygon boundary. If the boundaryEdge is <b>GL_TRUE</b>, then each vertex + * that follows begins an edge that lies on the polygon boundary, that is, + * an edge that separates an interior region from an exterior one. If the + * boundaryEdge is <b>GL_FALSE</b>, then each vertex that follows begins an + * edge that lies in the polygon interior. The edge flag callback (if + * defined) is invoked before the first vertex callback.<P> + * + * Since triangle fans and triangle strips do not support edge flags, the + * begin callback is not called with <b>GL_TRIANGLE_FAN</b> or + * <b>GL_TRIANGLE_STRIP</b> if a non-null edge flag callback is provided. + * (If the callback is initialized to null, there is no impact on + * performance). Instead, the fans and strips are converted to independent + * triangles. + * + * @param boundaryEdge + * Specifics which edges lie on the polygon boundary. + * + * @see GLU#gluTessCallback gluTessCallback + * @see #edgeFlagData edgeFlagData + */ + public void edgeFlag(boolean boundaryEdge); + + + /** + * The same as the {@link #edgeFlag edgeFlage} callback method + * except that it takes an additional reference argument. This + * reference is identical to the opaque reference provided when + * {@link GLU#gluTessBeginPolygon gluTessBeginPolygon} was called. + * + * @param boundaryEdge + * Specifics which edges lie on the polygon boundary. + * @param polygonData + * Specifics a reference to user-defined data. + * + * @see GLU#gluTessCallback gluTessCallback + * @see #edgeFlag edgeFlag + */ + public void edgeFlagData(boolean boundaryEdge, Object polygonData); + + + /** + * The <b>vertex</b> callback method is invoked between the {@link + * #begin begin} and {@link #end end} callback methods. It is + * similar to {@link javax.media.opengl.GL#glVertex3f glVertex3f}, + * and it defines the vertices of the triangles created by the + * tessellation process. The method takes a reference as its only + * argument. This reference is identical to the opaque reference + * provided by the user when the vertex was described (see {@link + * GLU#gluTessVertex gluTessVertex}). + * + * @param vertexData + * Specifics a reference to the vertices of the triangles created + * by the tessellation process. + * + * @see GLU#gluTessCallback gluTessCallback + * @see #vertexData vertexData + */ + public void vertex(Object vertexData); + + + /** + * The same as the {@link #vertex vertex} callback method except + * that it takes an additional reference argument. This reference is + * identical to the opaque reference provided when {@link + * GLU#gluTessBeginPolygon gluTessBeginPolygon} was called. + * + * @param vertexData + * Specifics a reference to the vertices of the triangles created + * by the tessellation process. + * @param polygonData + * Specifics a reference to user-defined data. + * + * @see GLU#gluTessCallback gluTessCallback + * @see #vertex vertex + */ + public void vertexData(Object vertexData, Object polygonData); + + + /** + * The end callback serves the same purpose as + * {@link javax.media.opengl.GL#glEnd glEnd}. It indicates the end of a + * primitive and it takes no arguments. + * + * @see GLU#gluTessCallback gluTessCallback + * @see #begin begin + * @see #endData endData + */ + public void end(); + + + /** + * The same as the {@link #end end} callback method except that it + * takes an additional reference argument. This reference is + * identical to the opaque reference provided when {@link + * GLU#gluTessBeginPolygon gluTessBeginPolygon} was called. + * + * @param polygonData + * Specifics a reference to user-defined data. + * + * @see GLU#gluTessCallback gluTessCallback + * @see #beginData beginData + * @see #end end + */ + public void endData(Object polygonData); + + + /** + * The <b>combine</b> callback method is called to create a new vertex when + * the tessellation detects an intersection, or wishes to merge features. The + * method takes four arguments: an array of three elements each of type + * double, an array of four references, an array of four elements each of + * type float, and a reference to a reference.<P> + * + * The vertex is defined as a linear combination of up to four existing + * vertices, stored in <i>data</i>. The coefficients of the linear combination + * are given by <i>weight</i>; these weights always add up to 1. All vertex + * pointers are valid even when some of the weights are 0. <i>coords</i> gives + * the location of the new vertex.<P> + * + * The user must allocate another vertex, interpolate parameters using + * <i>data</i> and <i>weight</i>, and return the new vertex pointer in + * <i>outData</i>. This handle is supplied during rendering callbacks. The + * user is responsible for freeing the memory some time after + * {@link GLU#gluTessEndPolygon gluTessEndPolygon} is + * called.<P> + * + * For example, if the polygon lies in an arbitrary plane in 3-space, and a + * color is associated with each vertex, the <b>GLU_TESS_COMBINE</b> + * callback might look like this: + * </UL> + * <PRE> + * void myCombine(double[] coords, Object[] data, + * float[] weight, Object[] outData) + * { + * MyVertex newVertex = new MyVertex(); + * + * newVertex.x = coords[0]; + * newVertex.y = coords[1]; + * newVertex.z = coords[2]; + * newVertex.r = weight[0]*data[0].r + + * weight[1]*data[1].r + + * weight[2]*data[2].r + + * weight[3]*data[3].r; + * newVertex.g = weight[0]*data[0].g + + * weight[1]*data[1].g + + * weight[2]*data[2].g + + * weight[3]*data[3].g; + * newVertex.b = weight[0]*data[0].b + + * weight[1]*data[1].b + + * weight[2]*data[2].b + + * weight[3]*data[3].b; + * newVertex.a = weight[0]*data[0].a + + * weight[1]*data[1].a + + * weight[2]*data[2].a + + * weight[3]*data[3].a; + * outData = newVertex; + * }</PRE> + * + * @param coords + * Specifics the location of the new vertex. + * @param data + * Specifics the vertices used to create the new vertex. + * @param weight + * Specifics the weights used to create the new vertex. + * @param outData + * Reference user the put the coodinates of the new vertex. + * + * @see GLU#gluTessCallback gluTessCallback + * @see #combineData combineData + */ + public void combine(double[] coords, Object[] data, + float[] weight, Object[] outData); + + + /** + * The same as the {@link #combine combine} callback method except + * that it takes an additional reference argument. This reference is + * identical to the opaque reference provided when {@link + * GLU#gluTessBeginPolygon gluTessBeginPolygon} was called. + * + * @param coords + * Specifics the location of the new vertex. + * @param data + * Specifics the vertices used to create the new vertex. + * @param weight + * Specifics the weights used to create the new vertex. + * @param outData + * Reference user the put the coodinates of the new vertex. + * @param polygonData + * Specifics a reference to user-defined data. + * + * @see GLU#gluTessCallback gluTessCallback + * @see #combine combine + */ + public void combineData(double[] coords, Object[] data, + float[] weight, Object[] outData, + Object polygonData); + + + /** + * The <b>error</b> callback method is called when an error is encountered. + * The one argument is of type int; it indicates the specific error that + * occurred and will be set to one of <b>GLU_TESS_MISSING_BEGIN_POLYGON</b>, + * <b>GLU_TESS_MISSING_END_POLYGON</b>, <b>GLU_TESS_MISSING_BEGIN_CONTOUR</b>, + * <b>GLU_TESS_MISSING_END_CONTOUR</b>, <b>GLU_TESS_COORD_TOO_LARGE</b>, + * <b>GLU_TESS_NEED_COMBINE_CALLBACK</b> or <b>GLU_OUT_OF_MEMORY</b>. + * Character strings describing these errors can be retrieved with the + * {@link GLU#gluErrorString gluErrorString} call.<P> + * + * The GLU library will recover from the first four errors by inserting the + * missing call(s). <b>GLU_TESS_COORD_TOO_LARGE</b> indicates that some + * vertex coordinate exceeded the predefined constant + * <b>GLU_TESS_MAX_COORD</b> in absolute value, and that the value has been + * clamped. (Coordinate values must be small enough so that two can be + * multiplied together without overflow.) + * <b>GLU_TESS_NEED_COMBINE_CALLBACK</b> indicates that the tessellation + * detected an intersection between two edges in the input data, and the + * <b>GLU_TESS_COMBINE</b> or <b>GLU_TESS_COMBINE_DATA</b> callback was not + * provided. No output is generated. <b>GLU_OUT_OF_MEMORY</b> indicates that + * there is not enough memory so no output is generated. + * + * @param errnum + * Specifics the error number code. + * + * @see GLU#gluTessCallback gluTessCallback + * @see #errorData errorData + */ + public void error(int errnum); + + + /** + * The same as the {@link #error error} callback method except that + * it takes an additional reference argument. This reference is + * identical to the opaque reference provided when {@link + * GLU#gluTessBeginPolygon gluTessBeginPolygon} was called. + * + * @param errnum + * Specifics the error number code. + * @param polygonData + * Specifics a reference to user-defined data. + * + * @see GLU#gluTessCallback gluTessCallback + * @see #error error + */ + public void errorData(int errnum, Object polygonData); + + //void mesh(com.sun.opengl.impl.tessellator.GLUmesh mesh); +} diff --git a/src/jogl/classes/javax/media/opengl/glu/GLUtessellatorCallbackAdapter.java b/src/jogl/classes/javax/media/opengl/glu/GLUtessellatorCallbackAdapter.java new file mode 100755 index 000000000..bf6f2d29a --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/glu/GLUtessellatorCallbackAdapter.java @@ -0,0 +1,84 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package javax.media.opengl.glu; + +/** + * The <b>GLUtessellatorCallbackAdapter</b> provides a default implementation of + * {@link GLUtessellatorCallback GLUtessellatorCallback} + * with empty callback methods. This class can be extended to provide user + * defined callback methods. + * + * @author Eric Veach, July 1994 + * @author Java Port: Pepijn Van Eechhoudt, July 2003 + * @author Java Port: Nathan Parker Burg, August 2003 + */ + +public class GLUtessellatorCallbackAdapter implements GLUtessellatorCallback { + public void begin(int type) {} + public void edgeFlag(boolean boundaryEdge) {} + public void vertex(Object vertexData) {} + public void end() {} +// public void mesh(com.sun.opengl.impl.tessellator.GLUmesh mesh) {} + public void error(int errnum) {} + public void combine(double[] coords, Object[] data, + float[] weight, Object[] outData) {} + public void beginData(int type, Object polygonData) {} + public void edgeFlagData(boolean boundaryEdge, + Object polygonData) {} + public void vertexData(Object vertexData, Object polygonData) {} + public void endData(Object polygonData) {} + public void errorData(int errnum, Object polygonData) {} + public void combineData(double[] coords, Object[] data, + float[] weight, Object[] outData, + Object polygonData) {} +} |