aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKenneth Russel <[email protected]>2001-06-26 06:06:04 +0000
committerKenneth Russel <[email protected]>2001-06-26 06:06:04 +0000
commit61718067af10833ee7b1c3f0fb6b9d6acf1814fe (patch)
treede383b450955f7c59bcb39e66f7523d293fe4641
parent60fcc879a7b52bdec425ab3968313dff04006bc1 (diff)
*** empty log message ***
-rw-r--r--gl4java/awt/GLAnimCanvas.java1562
-rw-r--r--gl4java/awt/GLCanvas.java2245
2 files changed, 1992 insertions, 1815 deletions
diff --git a/gl4java/awt/GLAnimCanvas.java b/gl4java/awt/GLAnimCanvas.java
index 89b0970..b16206c 100644
--- a/gl4java/awt/GLAnimCanvas.java
+++ b/gl4java/awt/GLAnimCanvas.java
@@ -1,747 +1,815 @@
-/**
- * @(#) GLAnimCanvas.java
- */
-
-package gl4java.awt;
-
-import gl4java.*;
-
-import java.awt.*;
-import java.awt.event.*;
-import java.lang.Math;
-
-
-/**
- * This is meant as an base class writing
- * Animations. A clean usage of multi-threading compatible
- * with JAVA2 is implemented here !
- *
- * <p>
- *
- * If you are interessting in further Documentation and/or
- * the history of GL4Java follow the following link.
- *
- * <pre>
- <a href="../../GL4Java.html">The GL4Java Documentation</a>
- * </pre>
- *
- * <p>
- * There are two ways of using a GLAnimCanvas: the {@link
- * gl4java.GLEventListener} model or the subclassing model. Earlier
- * versions of OpenGL for Java only supported the subclassing model.
- * The default implementations of {@link gl4java.awt.GLCanvas#init},
- * {@link gl4java.awt.GLCanvas#display},
- * {@link gl4java.awt.GLCanvas#reshape} and
- # {@link gl4java.awt.GLCanvas#doCleanup}
- * now send events to GLEventListeners; they can
- * still be overridden as before to support the subclassing model.
- *
- * <p>
- * If using the subclassing model, you should override the following
- * methods for your needs:
- * <pre>
- <a href="GLCanvas.html#init()">preInit - initialisation before creating GLContext</a>
- <a href="GLAnimCanvas.html#init()">init - 1st initialisation</a>
- <a href="GLCanvas.html#doCleanup()">doCleanup - OGL cleanup prior to context deletion</a>
- <a href="GLAnimCanvas.html#display()">display - render one frame</a>
- <a href="GLCanvas.html#reshape(int, int)">reshape - to reshape (window resize)</a>
- <a href="GLAnimCanvas.html#ReInit()">ReInit - ReInitialisation after stop for setSuspended(false)</a>
- * </pre>
- *
- * <p>
- *
- * This code uses repaint() to fire a sDisplay call by the AWT-Event thread !
- * and sleep to suspend for a given Frames per secounds value as default !!
- *
- * To switch this behavior for a better performance, and responsiveness
- * so that sDisplay is called by the animation thread itself
- * call:
- *
- * <pre>
- <a href="GLAnimCanvas.html#setUseRepaint(boolean)">setUseRepaint(false)</a>
- * </pre>
- * <p>
- *
- * This code sleep's for a given Frames per secounds after each frame
- * as default !!
- *
- * To switch this behavior for a better performance,
- * so that much frames are rendered as the machine can do !
- * call:
- *
- * <pre>
- <a href="GLAnimCanvas.html#setUseFpsSleep(boolean)">setUseFpsSleep(false)</a>
- * </pre>
- * <p>
- * But be sure, that the other threads may not have enough time or i
- * may not get the cpu power ...
- *
- * The following settings for setUseRepaint and setUseFpsSleep looks fine:
- *
- * <pre>
- <p>
- A JVM with operating system threads has: <b>native-threads</b>
- <p>
- A JVM where all JVM threads runs in one operating-system-thread
- has: <b>green-threads</b>
-
- <a name="table">
- <table border>
- <tr>
- <th><th>green-threads<th>native-threads
- <tr>
- <td align=center><a href="GLAnimCanvas.html#setUseRepaint(boolean)"><code>setUseRepaint</code></a>
- <td align=center><code>true</code>
- <td align=center><code> true & false </code>
- <tr>
- <td align=center><a href="GLAnimCanvas.html#setUseFpsSleep(boolean)"><code>setUseFpsSleep</code></a>
- <td align=center><code>true</code>
- <td align=center><code> true & false </code>
-
- </table>
- </a>
- * </pre>
- *
- * If you play with setUseRepaint or setUseFpsSleep,
- * be shure to have a Java VM with native-thread support,
- * because a GL-Context can be shared by many threads,
- * but one thread can have just one GL-Context !
- *
- * <p>
- *
- * Since GL4Java 2.5.2 and using a JVM >= 1.3
- * the multithreading support is stable !
- *
- * <p>
- *
- * (comments welcome)
- *
- * <p>
- * To use real fps settings, the following functions provides you to do so:
- * <pre>
- <a href="GLAnimCanvas.html#setAnimateFps(double)">setAnimateFps</a>
- <a href="GLAnimCanvas.html#getMaxFps()">getMaxFps</a>
- * </pre>
- * Like the first animation run, this class renders a view frames (default 10)
- * to subtract the render time from the sleep time !
- *
- * @see gl4java.awt.GLCanvas
- * @version 2.0, 21. April 1999
- * @author Sven Goethel
- *
- */
-public class GLAnimCanvas extends GLCanvas
- implements Runnable
-{
- /**
- * To support frames per scounds,
- * instead of killing the machine :-)
- *
- * A little GUI is supported !
- *
- * @see gl4java.awt.GLAnimCanvas#run
- */
- protected double FramesPerSec=20;
- protected long mSecPerFrame=0;
-
- protected static int globalThreadNumber=0;
-
- public static int getGlobalThreadNumber()
- {
- return globalThreadNumber;
- }
-
- /**
- * the delays ..
- */
- protected long dFpsMilli = 0;
-
- /**
- * The thread for referencing Thread (Animation)
- *
- * @see gl4java.awt.GLAnimCanvas#stop
- * @see gl4java.awt.GLAnimCanvas#start
- * @see gl4java.awt.GLAnimCanvas#run
- */
- protected Thread killme = null;
-
- /**
- * Instead of using suspend (JAVA2)
- *
- * @see gl4java.awt.GLAnimCanvas#run
- */
- protected boolean threadSuspended = false;
-
- static {
- if(GLContext.loadNativeLibraries(null, null, null)==false)
- System.out.println("GLAnimCanvas could not load def. native libs.");
- }
-
- /**
- *
- * Constructor
- *
- * @see gl4java.awt.GLCanvas#GLCanvas
- *
- */
- public GLAnimCanvas( int width, int height,
- String gl_Name,
- String glu_Name
- )
- {
- super( width, height, gl_Name, glu_Name );
- setAnimateFps(FramesPerSec);
- }
-
- /**
- *
- * Constructor
- *
- * Uses the default GLFunc and GLUFunc implementation !
- *
- * @see gl4java.awt.GLCanvas#GLCanvas
- *
- */
- public GLAnimCanvas( int width, int height )
- {
- super( width, height);
- setAnimateFps(FramesPerSec);
- }
-
- /**
- *
- * Constructor
- *
- * @see gl4java.awt.GLCanvas#GLCanvas
- *
- */
- public GLAnimCanvas( GLCapabilities capabilities,
- int width, int height,
- String gl_Name,
- String glu_Name
- )
- {
- super( capabilities, width, height, gl_Name, glu_Name );
- setAnimateFps(FramesPerSec);
- }
-
- /**
- *
- * Constructor
- *
- * Uses the default GLFunc and GLUFunc implementation !
- *
- * @see gl4java.awt.GLCanvas#GLCanvas
- *
- */
- public GLAnimCanvas( GLCapabilities capabilities,
- int width, int height )
- {
- super( capabilities, width, height);
- setAnimateFps(FramesPerSec);
- }
-
- /**
- *
- * Constructor
- *
- * @see gl4java.awt.GLCanvas#GLCanvas
- */
- public GLAnimCanvas( GraphicsConfiguration config,
- GLCapabilities capabilities,
- int width, int height,
- String gl_Name,
- String glu_Name
- )
- {
- super( config, capabilities,
- width, height, gl_Name, glu_Name );
- setAnimateFps(FramesPerSec);
- }
-
- /**
- *
- * Constructor
- *
- * Uses the default GLFunc and GLUFunc implementation !
- *
- * @see gl4java.awt.GLCanvas#GLCanvas
- */
- public GLAnimCanvas( GraphicsConfiguration config,
- GLCapabilities capabilities,
- int width, int height )
- {
- super( config, capabilities,
- width, height);
- setAnimateFps(FramesPerSec);
- }
-
- /**
- * ReInit should be overwritten by you,
- * to enter your re-initialisation within setSuspended(false)
- *
- * @see gl4java.awt.GLAnimCanvas#setSuspended
- */
- public void ReInit()
- {
- }
-
- protected boolean useRepaint = true;
-
- protected boolean useFpsSleep = true;
-
- /**
- * The normal behavior is to use 'repaint'
- * within the AWT-Event Thread to render.
- * <p>
- * If you have serious reasons, e.g. measuring performance,
- * you can change it while invoke this function with 'false'.
- * In this case, the thread itself calls the sDisplay method !
- *
- * On fast good multi-threading machines (native-thread-JVM),
- * this should increase the performance and the responsiveness !
- * <p>
- *
- * @param b if true, uses repaint (default), otherwise directly sDisplay
- * @see gl4java.awt.GLCanvas#sDisplay
- * @see gl4java.awt.GLAnimCanvas#setUseFpsSleep
- */
- public void setUseRepaint(boolean b)
- {
- useRepaint = b;
- }
-
- /**
- * The normal behavior is to use FpsSleep
- *
- * But you can overwrite this behavior and
- * drop the Frame Per Secound sleeps -
- * so that much frames are rendered as the machine can do !
- * <p>
- *
- * @param b if true, uses Fps sleeping, else not !
- * @see gl4java.awt.GLCanvas#sDisplay
- * @see gl4java.awt.GLAnimCanvas#setUseRepaint
- */
- public void setUseFpsSleep(boolean b)
- {
- useFpsSleep = b;
- }
-
- public boolean getUseRepaint()
- {
- return useRepaint;
- }
-
- public boolean getUseFpsSleep()
- {
- return useFpsSleep;
- }
-
- /**
- * HERE WE DO HAVE OUR RUNNING THREAD !
- * WE NEED STUFF LIKE THAT FOR ANIMATION ;-)
- */
- public void start()
- {
- if(killme == null)
- {
- killme = new Thread(this);
- killme.start();
-
- resetFpsCounter();
- }
- }
-
- public synchronized void stop()
- {
- killme = null;
- threadSuspended=false;
-
- notifyAll();
- }
-
- /**
- * You should call this before releasing/dispose this Window !
- * Also you can overwrite this class,
- * to dispose your own elements, e.g. a Frame etc. -
- * but be shure that you call
- * cvsDispose implementation call this one !
- *
- * This function calls gljDestroy of GLContext !
- *
- * @see gl4java.GLContext#gljDestroy
- * @see gl4java.awt.GLCanvas#cvsDispose
- * @see gl4java.awt.GLCanvas#doCleanup
- */
- public void cvsDispose()
- {
- stop();
- super.cvsDispose();
- }
-
- protected boolean shallWeRender = true;
- protected boolean isRunning = false;
-
- private long _fDelay = 0;
- private long _fDelay_Frames = 10;
- private boolean _fDelaySync=true;
- private boolean _fDelayRun=false;
-
- /**
- * The running loop for animations
- * which initiates the call of display
- *
- * @see gl4java.awt.GLAnimCanvas#setSuspended
- * @see gl4java.awt.GLCanvas#display
- */
- public void run()
- {
- Thread thisThread = Thread.currentThread();
-
- isRunning = true;
-
- synchronized (this) {
- globalThreadNumber++;
- }
-
- while (killme==thisThread)
- {
- if(cvsIsInit())
- {
- /* DRAW THE TINGS .. */
- if (shallWeRender)
- {
- if(useRepaint)
- repaint();
- else
- sDisplay();
- } else {
- synchronized (this) {
- threadSuspended=true;
- }
- }
-
- if(fps_isCounting)
- fps_frames++;
-
- }
-
- try {
- if(useFpsSleep)
- {
- if(useRepaint)
- {
- if(mSecPerFrame<_f_dur)
- dFpsMilli=_f_dur;
- else
- dFpsMilli=mSecPerFrame;
- }
- else
- {
- dFpsMilli= mSecPerFrame - _f_dur;
- if (dFpsMilli<=0)
- dFpsMilli= 1;
- }
-
- Thread.currentThread().sleep(dFpsMilli, 0 );
- } else {
- Thread.yield();
- }
-
- if (threadSuspended) {
- stopFpsCounter();
- synchronized (this) {
- while (threadSuspended)
- wait();
- }
- }
- } catch (InterruptedException e)
- {}
- }
-
- if(glj!=null)
- glj.gljFree(); // just to be sure ..
-
- synchronized (this) {
- globalThreadNumber--;
- }
-
- isRunning = false;
- }
-
- /**
- * Here we can (re)start or suspend animation ...
- *
- * If the thread should be (re)started and is not alive -> killed,
- * or never be started, it will be started !
- *
- * @param suspend if true the thread will be suspended,
- * if false, the thread will be (re)started
- *
- * @see gl4java.awt.GLAnimCanvas#isAlive
- * @see gl4java.awt.GLAnimCanvas#start
- */
- public void setSuspended(boolean suspend)
- {
- setSuspended(suspend, false);
- }
-
- /**
- * Here we can (re)start or suspend animation ...
- *
- * If the thread should be (re)started and is not alive -> killed,
- * or never be started, it will be started !
- *
- * @param suspend if true the thread will be suspended,
- * if false, the thread will be (re)started
- *
- * @param reInit if true the ReInit will be called additionally,
- * where the user can set additional initialisations
- *
- * @see gl4java.awt.GLAnimCanvas#isAlive
- * @see gl4java.awt.GLAnimCanvas#start
- * @see gl4java.awt.GLAnimCanvas#run
- */
- public synchronized void setSuspended(boolean suspend, boolean reInit)
- {
- if(suspend) {
- shallWeRender=false;
- } else if(isAlive()==false) {
- start();
- } else {
- // the thread is alive, but suspended and should be
- // re-started
- shallWeRender=true;
- resetFpsCounter();
-
- if(reInit)
- ReInit();
-
- threadSuspended=false;
- notifyAll();
- }
- }
-
- /**
- * is the thread alive, means is started and not died ?
- *
- * @see gl4java.awt.GLAnimCanvas#run
- * @see gl4java.awt.GLAnimCanvas#setSuspended
- * @see gl4java.awt.GLAnimCanvas#start
- * @see gl4java.awt.GLAnimCanvas#stop
- */
- public boolean isAlive()
- {
- if(killme==null) return false;
- return killme.isAlive();
- }
-
- /**
- * is the thread suspended, means is started but waiting,
- * or not alive (ok :-| - but it is practical)
- *
- * @see gl4java.awt.GLAnimCanvas#run
- * @see gl4java.awt.GLAnimCanvas#setSuspended
- * @see gl4java.awt.GLAnimCanvas#start
- * @see gl4java.awt.GLAnimCanvas#stop
- */
- public boolean isSuspended()
- {
- if(killme==null) return true;
- return threadSuspended;
- }
-
- private double fps=0; // frame-per-sec
- private long fps_duration =0; // milli-secs
- private long fps_start=0; // milli-secs
- private long fps_frames =0; // number of frames
- private boolean fps_isCounting =true; // shall i count
-
- /**
- * resets the Fps Counter
- * <p>
- * this function is called automatically by
- * start and after setSuspended suspends the
- * animation thread !
- *
- * @see gl4java.awt.GLAnimCanvas#start
- * @see gl4java.awt.GLAnimCanvas#setSuspended
- * @see gl4java.awt.GLAnimCanvas#resetFpsCounter
- * @see gl4java.awt.GLAnimCanvas#stopFpsCounter
- * @see gl4java.awt.GLAnimCanvas#getFps
- * @see gl4java.awt.GLAnimCanvas#getFpsDuration
- * @see gl4java.awt.GLAnimCanvas#getFpsFrames
- * @see gl4java.awt.GLAnimCanvas#setVerboseFps
- */
- public void resetFpsCounter()
- {
- fps=0; // frame-per-sec
- fps_duration =0; // milli-secs
- fps_frames =0; // number of frames
- fps_isCounting =true; // shall i count
- fps_start=System.currentTimeMillis();
- }
-
- /**
- * stops the Fps Counter and sets all values
- * fot the getFps* methods
- * <p>
- * this function is called automatically by
- * run, if the thread is suspended via setSuspended(true)
- * <p>
- * All data's are print out on System.out
- * if GLContext.gljClassDebug is set !
- *
- * @see gl4java.awt.GLAnimCanvas#run
- * @see gl4java.awt.GLAnimCanvas#setSuspended
- * @see gl4java.awt.GLAnimCanvas#resetFpsCounter
- * @see gl4java.awt.GLAnimCanvas#getFps
- * @see gl4java.awt.GLAnimCanvas#getFpsDuration
- * @see gl4java.awt.GLAnimCanvas#getFpsFrames
- * @see gl4java.awt.GLAnimCanvas#setVerboseFps
- */
- public void stopFpsCounter()
- {
- if(fps_isCounting==true)
- {
- long fps_end=System.currentTimeMillis();
- fps_duration = fps_end-fps_start;
- double timed= ((double)fps_duration)/1000.0;
- if(timed==0) timed=1.0;
- fps = ((double)fps_frames)/timed ;
- fps_isCounting=false;
- }
- if(GLContext.gljClassDebug)
- {
- System.out.println("\nfps = "+String.valueOf(fps));
- System.out.println("time = "+String.valueOf(fps_duration)+" ms");
- System.out.println("frames = "+String.valueOf(fps_frames));
- if(fps_frames==0) fps_frames=1;
- System.out.println("time/f = "+String.valueOf(fps_duration/fps_frames)+" ms");
- }
- }
-
- /**
- * sets if the Fps data shall be printed to System.out
- * while stopFpsCounter is called !
- * <p>
- * GLContext.gljClassDebug is set to true by default !
- *
- * @see gl4java.awt.GLAnimCanvas#run
- * @see gl4java.awt.GLAnimCanvas#setSuspended
- * @see gl4java.awt.GLAnimCanvas#resetFpsCounter
- * @see gl4java.awt.GLAnimCanvas#stopFpsCounter
- * @see gl4java.awt.GLAnimCanvas#getFps
- * @see gl4java.awt.GLAnimCanvas#getFpsDuration
- * @see gl4java.awt.GLAnimCanvas#getFpsFrames
- * @see gl4java.awt.GLAnimCanvas#setVerboseFps
- *
- * @deprecated Now GLContext.gljClassDebug is used !
- * calculated, no pre-sync needed.
- * @see gl4java.GLContext#gljClassDebug
- */
- public void setVerboseFps(boolean v)
- {
- System.out.println("GLAnimCanvas.setVerboseFps(boolean) is deprecated and without functionality. Please set gl4java.GLContext.gljClassDebug instead for verbose output !");
- }
-
- /**
- * returns the calculated frames per secounds
- * <p>
- * this data is avaiable after calling stopFpsCounter
- *
- * @see gl4java.awt.GLAnimCanvas#resetFpsCounter
- * @see gl4java.awt.GLAnimCanvas#stopFpsCounter
- * @see gl4java.awt.GLAnimCanvas#getFps
- * @see gl4java.awt.GLAnimCanvas#getFpsDuration
- * @see gl4java.awt.GLAnimCanvas#getFpsFrames
- * @see gl4java.awt.GLAnimCanvas#setVerboseFps
- */
- public double getFps()
- {
- return fps;
- }
-
- /**
- * returns the calculated duration in millisecs
- * <p>
- * this data is avaiable after calling stopFpsCounter
- *
- * @see gl4java.awt.GLAnimCanvas#resetFpsCounter
- * @see gl4java.awt.GLAnimCanvas#stopFpsCounter
- * @see gl4java.awt.GLAnimCanvas#getFps
- * @see gl4java.awt.GLAnimCanvas#getFpsDuration
- * @see gl4java.awt.GLAnimCanvas#getFpsFrames
- * @see gl4java.awt.GLAnimCanvas#setVerboseFps
- */
- public long getFpsDuration()
- {
- return fps_duration;
- }
-
- /**
- * returns the calculated frames number
- * <p>
- * this data is avaiable after calling stopFpsCounter
- *
- * @see gl4java.awt.GLAnimCanvas#resetFpsCounter
- * @see gl4java.awt.GLAnimCanvas#stopFpsCounter
- * @see gl4java.awt.GLAnimCanvas#getFps
- * @see gl4java.awt.GLAnimCanvas#getFpsDuration
- * @see gl4java.awt.GLAnimCanvas#getFpsFrames
- * @see gl4java.awt.GLAnimCanvas#setVerboseFps
- */
- public long getFpsFrames()
- {
- return fps_frames;
- }
-
- /**
- * Just set the FramePerSecounds for Animation
- *
- * @deprecated Now the frames per seconds are allways
- * calculated, no pre-sync needed.
- * @see #setAnimateFps(double)
- */
- public void setAnimateFps(double fps, int synFrames)
- {
- setAnimateFps(fps);
- }
-
- /**
- * Just set the FramePerSecounds for Animation
- *
- * @see gl4java.awt.GLAnimCanvas#getMaxFps
- */
- public void setAnimateFps(double fps)
- {
- FramesPerSec=fps;
- mSecPerFrame = (long) ( (1.0/FramesPerSec) * 1000.0 ) ;
- if(GLContext.gljClassDebug)
- {
- System.out.println("\nset fps := "+
- String.valueOf(fps)+
- " -> "+String.valueOf(mSecPerFrame)+
- " [ms/frame]"
- );
- }
- resetFpsCounter();
- }
-
- /**
- * Just get the maximum number of Frames per secounds,
- * which is calculated with the time, one frame needs to render !
- *
- * this value is avaiable after the thread is started
- * and the first frames are rendered !
- *
- * @see gl4java.awt.GLAnimCanvas#setAnimateFps
- */
- public double getMaxFps()
- {
- return (1.0/(double)_f_dur)*1000.0;
- }
-
-}
-
+/**
+ * @(#) GLAnimCanvas.java
+ */
+
+package gl4java.awt;
+
+import gl4java.*;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.lang.Math;
+
+
+/**
+ * This is meant as an base class writing
+ * Animations. A clean usage of multi-threading compatible
+ * with JAVA2 is implemented here !
+ *
+ * <p>
+ *
+ * If you are interessting in further Documentation and/or
+ * the history of GL4Java follow the following link.
+ *
+ * <pre>
+ <a href="../../GL4Java.html">The GL4Java Documentation</a>
+ * </pre>
+ *
+ * <p>
+ * There are two ways of using a GLAnimCanvas: the {@link
+ * gl4java.GLEventListener} model or the subclassing model. Earlier
+ * versions of OpenGL for Java only supported the subclassing model.
+ * The default implementations of {@link gl4java.awt.GLCanvas#init},
+ * {@link gl4java.awt.GLCanvas#display},
+ * {@link gl4java.awt.GLCanvas#reshape} and
+ # {@link gl4java.awt.GLCanvas#doCleanup}
+ * now send events to GLEventListeners; they can
+ * still be overridden as before to support the subclassing model.
+ *
+ * <p>
+ * If using the subclassing model, you should override the following
+ * methods for your needs:
+ * <pre>
+ <a href="GLCanvas.html#init()">preInit - initialisation before creating GLContext</a>
+ <a href="GLAnimCanvas.html#init()">init - 1st initialisation</a>
+ <a href="GLCanvas.html#doCleanup()">doCleanup - OGL cleanup prior to context deletion</a>
+ <a href="GLAnimCanvas.html#display()">display - render one frame</a>
+ <a href="GLCanvas.html#reshape(int, int)">reshape - to reshape (window resize)</a>
+ <a href="GLAnimCanvas.html#ReInit()">ReInit - ReInitialisation after stop for setSuspended(false)</a>
+ * </pre>
+ *
+ * <p>
+ *
+ * This code uses repaint() to fire a sDisplay call by the AWT-Event thread !
+ * and sleep to suspend for a given Frames per secounds value as default !!
+ *
+ * To switch this behavior for a better performance, and responsiveness
+ * so that sDisplay is called by the animation thread itself
+ * call:
+ *
+ * <pre>
+ <a href="GLAnimCanvas.html#setUseRepaint(boolean)">setUseRepaint(false)</a>
+ * </pre>
+ * <p>
+ *
+ * This code sleep's for a given Frames per secounds after each frame
+ * as default !!
+ *
+ * To switch this behavior for a better performance,
+ * so that much frames are rendered as the machine can do !
+ * call:
+ *
+ * <pre>
+ <a href="GLAnimCanvas.html#setUseFpsSleep(boolean)">setUseFpsSleep(false)</a>
+ * </pre>
+ * <p>
+ * But be sure, that the other threads may not have enough time or i
+ * may not get the cpu power ...
+ *
+ * The following settings for setUseRepaint and setUseFpsSleep looks fine:
+ *
+ * <pre>
+ <p>
+ A JVM with operating system threads has: <b>native-threads</b>
+ <p>
+ A JVM where all JVM threads runs in one operating-system-thread
+ has: <b>green-threads</b>
+
+ <a name="table">
+ <table border>
+ <tr>
+ <th><th>green-threads<th>native-threads
+ <tr>
+ <td align=center><a href="GLAnimCanvas.html#setUseRepaint(boolean)"><code>setUseRepaint</code></a>
+ <td align=center><code>true</code>
+ <td align=center><code> true & false </code>
+ <tr>
+ <td align=center><a href="GLAnimCanvas.html#setUseFpsSleep(boolean)"><code>setUseFpsSleep</code></a>
+ <td align=center><code>true</code>
+ <td align=center><code> true & false </code>
+
+ </table>
+ </a>
+ * </pre>
+ *
+ * If you play with setUseRepaint or setUseFpsSleep,
+ * be shure to have a Java VM with native-thread support,
+ * because a GL-Context can be shared by many threads,
+ * but one thread can have just one GL-Context !
+ *
+ * <p>
+ *
+ * Since GL4Java 2.5.2 and using a JVM >= 1.3
+ * the multithreading support is stable !
+ *
+ * <p>
+ *
+ * (comments welcome)
+ *
+ * <p>
+ * To use real fps settings, the following functions provides you to do so:
+ * <pre>
+ <a href="GLAnimCanvas.html#setAnimateFps(double)">setAnimateFps</a>
+ <a href="GLAnimCanvas.html#getMaxFps()">getMaxFps</a>
+ * </pre>
+ * Like the first animation run, this class renders a view frames (default 10)
+ * to subtract the render time from the sleep time !
+ *
+ * @see gl4java.awt.GLCanvas
+ * @version 2.0, 21. April 1999
+ * @author Sven Goethel
+ *
+ */
+public class GLAnimCanvas extends GLCanvas
+ implements Runnable
+{
+ /**
+ * To support frames per scounds,
+ * instead of killing the machine :-)
+ *
+ * A little GUI is supported !
+ *
+ * @see gl4java.awt.GLAnimCanvas#run
+ */
+ protected double FramesPerSec=20;
+ protected long mSecPerFrame=0;
+
+ protected static int globalThreadNumber=0;
+
+ public static int getGlobalThreadNumber()
+ {
+ return globalThreadNumber;
+ }
+
+ /**
+ * the delays ..
+ */
+ protected long dFpsMilli = 0;
+
+ /**
+ * The thread for referencing Thread (Animation)
+ *
+ * @see gl4java.awt.GLAnimCanvas#stop
+ * @see gl4java.awt.GLAnimCanvas#start
+ * @see gl4java.awt.GLAnimCanvas#run
+ */
+ protected Thread killme = null;
+
+ /**
+ * Instead of using suspend (JAVA2)
+ *
+ * @see gl4java.awt.GLAnimCanvas#run
+ */
+ protected boolean threadSuspended = false;
+
+ static {
+ if(GLContext.loadNativeLibraries(null, null, null)==false)
+ System.out.println("GLAnimCanvas could not load def. native libs.");
+ }
+
+ /**
+ *
+ * Constructor
+ *
+ * @see gl4java.awt.GLCanvas#GLCanvas
+ *
+ */
+ public GLAnimCanvas( int width, int height,
+ String gl_Name,
+ String glu_Name
+ )
+ {
+ super( width, height, gl_Name, glu_Name );
+ setAnimateFps(FramesPerSec);
+ }
+
+ /**
+ *
+ * Constructor
+ *
+ * Uses the default GLFunc and GLUFunc implementation !
+ *
+ * @see gl4java.awt.GLCanvas#GLCanvas
+ *
+ */
+ public GLAnimCanvas( int width, int height )
+ {
+ super( width, height);
+ setAnimateFps(FramesPerSec);
+ }
+
+ /**
+ *
+ * Constructor
+ *
+ * @see gl4java.awt.GLCanvas#GLCanvas
+ *
+ */
+ public GLAnimCanvas( GLCapabilities capabilities,
+ int width, int height,
+ String gl_Name,
+ String glu_Name
+ )
+ {
+ super( capabilities, width, height, gl_Name, glu_Name );
+ setAnimateFps(FramesPerSec);
+ }
+
+ /**
+ *
+ * Constructor
+ *
+ * Uses the default GLFunc and GLUFunc implementation !
+ *
+ * @see gl4java.awt.GLCanvas#GLCanvas
+ *
+ */
+ public GLAnimCanvas( GLCapabilities capabilities,
+ int width, int height )
+ {
+ super( capabilities, width, height);
+ setAnimateFps(FramesPerSec);
+ }
+
+ /**
+ *
+ * Constructor
+ *
+ * @see gl4java.awt.GLCanvas#GLCanvas
+ */
+ public GLAnimCanvas( GraphicsConfiguration config,
+ GLCapabilities capabilities,
+ int width, int height,
+ String gl_Name,
+ String glu_Name
+ )
+ {
+ super( config, capabilities,
+ width, height, gl_Name, glu_Name );
+ setAnimateFps(FramesPerSec);
+ }
+
+ /**
+ *
+ * Constructor
+ *
+ * Uses the default GLFunc and GLUFunc implementation !
+ *
+ * @see gl4java.awt.GLCanvas#GLCanvas
+ */
+ public GLAnimCanvas( GraphicsConfiguration config,
+ GLCapabilities capabilities,
+ int width, int height )
+ {
+ super( config, capabilities,
+ width, height);
+ setAnimateFps(FramesPerSec);
+ }
+
+ /**
+ * ReInit should be overwritten by you,
+ * to enter your re-initialisation within setSuspended(false)
+ *
+ * @see gl4java.awt.GLAnimCanvas#setSuspended
+ */
+ public void ReInit()
+ {
+ }
+
+ protected boolean useRepaint = true;
+
+ protected boolean useFpsSleep = true;
+
+ protected boolean useYield = true;
+
+ protected boolean useSDisplay = true;
+
+ /**
+ * The normal behavior is to use 'repaint'
+ * within the AWT-Event Thread to render.
+ * <p>
+ * If you have serious reasons, e.g. measuring performance,
+ * you can change it while invoke this function with 'false'.
+ * In this case, the thread itself calls the sDisplay method !
+ *
+ * On fast good multi-threading machines (native-thread-JVM),
+ * this should increase the performance and the responsiveness !
+ * <p>
+ *
+ * @param b if true, uses repaint (default), otherwise directly sDisplay
+ * @see gl4java.awt.GLCanvas#sDisplay
+ * @see gl4java.awt.GLAnimCanvas#setUseFpsSleep
+ */
+ public void setUseRepaint(boolean b)
+ {
+ useRepaint = b;
+ }
+
+ /**
+ * The normal behavior is to use FpsSleep
+ *
+ * But you can overwrite this behavior and
+ * drop the Frame Per Secound sleeps -
+ * so that much frames are rendered as the machine can do !
+ * <p>
+ *
+ * @param b if true, uses Fps sleeping, else not !
+ * @see gl4java.awt.GLCanvas#sDisplay
+ * @see gl4java.awt.GLAnimCanvas#setUseRepaint
+ */
+ public void setUseFpsSleep(boolean b)
+ {
+ useFpsSleep = b;
+ }
+
+ /** If useFpsSleep is disabled, the library still performs a
+ Thread.yield() automatically -- use this to disable this */
+ public void setUseYield(boolean b) {
+ useYield = b;
+ }
+
+ /** The default behavior, if not using repaints, is to call
+ sDisplay() in the thread's main loop; set this to false to
+ call display() directly. */
+ public void setUseSDisplay(boolean val) {
+ useSDisplay = val;
+ }
+
+ public boolean getUseRepaint()
+ {
+ return useRepaint;
+ }
+
+ public boolean getUseFpsSleep()
+ {
+ return useFpsSleep;
+ }
+
+ public boolean getUseYield()
+ {
+ return useYield;
+ }
+
+ public boolean getUseSDisplay()
+ {
+ return useSDisplay;
+ }
+
+ /**
+ * HERE WE DO HAVE OUR RUNNING THREAD !
+ * WE NEED STUFF LIKE THAT FOR ANIMATION ;-)
+ */
+ public void start()
+ {
+ if(killme == null)
+ {
+ killme = new Thread(this);
+ killme.start();
+
+ resetFpsCounter();
+ }
+ }
+
+ public synchronized void stop()
+ {
+ killme = null;
+ threadSuspended=false;
+
+ notifyAll();
+ }
+
+ /**
+ * You should call this before releasing/dispose this Window !
+ * Also you can overwrite this class,
+ * to dispose your own elements, e.g. a Frame etc. -
+ * but be shure that you call
+ * cvsDispose implementation call this one !
+ *
+ * This function calls gljDestroy of GLContext !
+ *
+ * @see gl4java.GLContext#gljDestroy
+ * @see gl4java.awt.GLCanvas#cvsDispose
+ * @see gl4java.awt.GLCanvas#doCleanup
+ */
+ public void cvsDispose()
+ {
+ stop();
+ super.cvsDispose();
+ }
+
+ protected boolean shallWeRender = true;
+ protected boolean isRunning = false;
+
+ private long _fDelay = 0;
+ private long _fDelay_Frames = 10;
+ private boolean _fDelaySync=true;
+ private boolean _fDelayRun=false;
+
+ /**
+ * The running loop for animations
+ * which initiates the call of display
+ *
+ * @see gl4java.awt.GLAnimCanvas#setSuspended
+ * @see gl4java.awt.GLCanvas#display
+ */
+ public void run()
+ {
+ Thread thisThread = Thread.currentThread();
+
+ isRunning = true;
+
+ boolean firstRender = true;
+
+ int numInitRetries = 1;
+ int numMakeCurrentRetries = 1;
+
+ synchronized (this) {
+ globalThreadNumber++;
+ }
+
+ while (killme==thisThread)
+ {
+ if(cvsIsInit())
+ {
+ if (firstRender) {
+ if (!getAutoMakeContextCurrent()) {
+ synchronized (this) {
+ if (!glj.gljMakeCurrent()) {
+ System.err.println("Error making context current (" +
+ numMakeCurrentRetries + ")...");
+ ++numMakeCurrentRetries;
+ try {
+ Thread.currentThread().sleep(100);
+ } catch (Exception e) {
+ }
+ continue;
+ }
+ }
+ System.err.println("Context made current in AnimCanvas's thread");
+ }
+ firstRender = false;
+ }
+
+ /* DRAW THE TINGS .. */
+ if (shallWeRender)
+ {
+ if(useRepaint)
+ repaint();
+ else {
+ if (useSDisplay) {
+ sDisplay();
+ } else {
+ display();
+ }
+ }
+ } else {
+ synchronized (this) {
+ threadSuspended=true;
+ }
+ }
+
+ if(fps_isCounting)
+ fps_frames++;
+
+ } else {
+ System.err.println("Waiting for canvas to initialize (" +
+ numInitRetries + ")...");
+ ++numInitRetries;
+ try {
+ Thread.currentThread().sleep(100);
+ } catch (Exception e) {
+ }
+ }
+
+ try {
+ if(useFpsSleep)
+ {
+ if(useRepaint)
+ {
+ if(mSecPerFrame<_f_dur)
+ dFpsMilli=_f_dur;
+ else
+ dFpsMilli=mSecPerFrame;
+ }
+ else
+ {
+ dFpsMilli= mSecPerFrame - _f_dur;
+ if (dFpsMilli<=0)
+ dFpsMilli= 1;
+ }
+
+ Thread.currentThread().sleep(dFpsMilli, 0 );
+ } else {
+ if (useYield) {
+ Thread.yield();
+ }
+ }
+
+ if (threadSuspended) {
+ stopFpsCounter();
+ synchronized (this) {
+ while (threadSuspended)
+ wait();
+ }
+ }
+ } catch (InterruptedException e)
+ {}
+ }
+
+ if (getAutoMakeContextCurrent()) {
+ if(glj!=null)
+ glj.gljFree(); // just to be sure ..
+ }
+
+ synchronized (this) {
+ globalThreadNumber--;
+ }
+
+ isRunning = false;
+ }
+
+ /**
+ * Here we can (re)start or suspend animation ...
+ *
+ * If the thread should be (re)started and is not alive -> killed,
+ * or never be started, it will be started !
+ *
+ * @param suspend if true the thread will be suspended,
+ * if false, the thread will be (re)started
+ *
+ * @see gl4java.awt.GLAnimCanvas#isAlive
+ * @see gl4java.awt.GLAnimCanvas#start
+ */
+ public void setSuspended(boolean suspend)
+ {
+ setSuspended(suspend, false);
+ }
+
+ /**
+ * Here we can (re)start or suspend animation ...
+ *
+ * If the thread should be (re)started and is not alive -> killed,
+ * or never be started, it will be started !
+ *
+ * @param suspend if true the thread will be suspended,
+ * if false, the thread will be (re)started
+ *
+ * @param reInit if true the ReInit will be called additionally,
+ * where the user can set additional initialisations
+ *
+ * @see gl4java.awt.GLAnimCanvas#isAlive
+ * @see gl4java.awt.GLAnimCanvas#start
+ * @see gl4java.awt.GLAnimCanvas#run
+ */
+ public synchronized void setSuspended(boolean suspend, boolean reInit)
+ {
+ if(suspend) {
+ shallWeRender=false;
+ } else if(isAlive()==false) {
+ start();
+ } else {
+ // the thread is alive, but suspended and should be
+ // re-started
+ shallWeRender=true;
+ resetFpsCounter();
+
+ if(reInit)
+ ReInit();
+
+ threadSuspended=false;
+ notifyAll();
+ }
+ }
+
+ /**
+ * is the thread alive, means is started and not died ?
+ *
+ * @see gl4java.awt.GLAnimCanvas#run
+ * @see gl4java.awt.GLAnimCanvas#setSuspended
+ * @see gl4java.awt.GLAnimCanvas#start
+ * @see gl4java.awt.GLAnimCanvas#stop
+ */
+ public boolean isAlive()
+ {
+ if(killme==null) return false;
+ return killme.isAlive();
+ }
+
+ /**
+ * is the thread suspended, means is started but waiting,
+ * or not alive (ok :-| - but it is practical)
+ *
+ * @see gl4java.awt.GLAnimCanvas#run
+ * @see gl4java.awt.GLAnimCanvas#setSuspended
+ * @see gl4java.awt.GLAnimCanvas#start
+ * @see gl4java.awt.GLAnimCanvas#stop
+ */
+ public boolean isSuspended()
+ {
+ if(killme==null) return true;
+ return threadSuspended;
+ }
+
+ private double fps=0; // frame-per-sec
+ private long fps_duration =0; // milli-secs
+ private long fps_start=0; // milli-secs
+ private long fps_frames =0; // number of frames
+ private boolean fps_isCounting =true; // shall i count
+
+ /**
+ * resets the Fps Counter
+ * <p>
+ * this function is called automatically by
+ * start and after setSuspended suspends the
+ * animation thread !
+ *
+ * @see gl4java.awt.GLAnimCanvas#start
+ * @see gl4java.awt.GLAnimCanvas#setSuspended
+ * @see gl4java.awt.GLAnimCanvas#resetFpsCounter
+ * @see gl4java.awt.GLAnimCanvas#stopFpsCounter
+ * @see gl4java.awt.GLAnimCanvas#getFps
+ * @see gl4java.awt.GLAnimCanvas#getFpsDuration
+ * @see gl4java.awt.GLAnimCanvas#getFpsFrames
+ * @see gl4java.awt.GLAnimCanvas#setVerboseFps
+ */
+ public void resetFpsCounter()
+ {
+ fps=0; // frame-per-sec
+ fps_duration =0; // milli-secs
+ fps_frames =0; // number of frames
+ fps_isCounting =true; // shall i count
+ fps_start=System.currentTimeMillis();
+ }
+
+ /**
+ * stops the Fps Counter and sets all values
+ * fot the getFps* methods
+ * <p>
+ * this function is called automatically by
+ * run, if the thread is suspended via setSuspended(true)
+ * <p>
+ * All data's are print out on System.out
+ * if GLContext.gljClassDebug is set !
+ *
+ * @see gl4java.awt.GLAnimCanvas#run
+ * @see gl4java.awt.GLAnimCanvas#setSuspended
+ * @see gl4java.awt.GLAnimCanvas#resetFpsCounter
+ * @see gl4java.awt.GLAnimCanvas#getFps
+ * @see gl4java.awt.GLAnimCanvas#getFpsDuration
+ * @see gl4java.awt.GLAnimCanvas#getFpsFrames
+ * @see gl4java.awt.GLAnimCanvas#setVerboseFps
+ */
+ public void stopFpsCounter()
+ {
+ if(fps_isCounting==true)
+ {
+ long fps_end=System.currentTimeMillis();
+ fps_duration = fps_end-fps_start;
+ double timed= ((double)fps_duration)/1000.0;
+ if(timed==0) timed=1.0;
+ fps = ((double)fps_frames)/timed ;
+ fps_isCounting=false;
+ }
+ if(GLContext.gljClassDebug)
+ {
+ System.out.println("\nfps = "+String.valueOf(fps));
+ System.out.println("time = "+String.valueOf(fps_duration)+" ms");
+ System.out.println("frames = "+String.valueOf(fps_frames));
+ if(fps_frames==0) fps_frames=1;
+ System.out.println("time/f = "+String.valueOf(fps_duration/fps_frames)+" ms");
+ }
+ }
+
+ /**
+ * sets if the Fps data shall be printed to System.out
+ * while stopFpsCounter is called !
+ * <p>
+ * GLContext.gljClassDebug is set to true by default !
+ *
+ * @see gl4java.awt.GLAnimCanvas#run
+ * @see gl4java.awt.GLAnimCanvas#setSuspended
+ * @see gl4java.awt.GLAnimCanvas#resetFpsCounter
+ * @see gl4java.awt.GLAnimCanvas#stopFpsCounter
+ * @see gl4java.awt.GLAnimCanvas#getFps
+ * @see gl4java.awt.GLAnimCanvas#getFpsDuration
+ * @see gl4java.awt.GLAnimCanvas#getFpsFrames
+ * @see gl4java.awt.GLAnimCanvas#setVerboseFps
+ *
+ * @deprecated Now GLContext.gljClassDebug is used !
+ * calculated, no pre-sync needed.
+ * @see gl4java.GLContext#gljClassDebug
+ */
+ public void setVerboseFps(boolean v)
+ {
+ System.out.println("GLAnimCanvas.setVerboseFps(boolean) is deprecated and without functionality. Please set gl4java.GLContext.gljClassDebug instead for verbose output !");
+ }
+
+ /**
+ * returns the calculated frames per secounds
+ * <p>
+ * this data is avaiable after calling stopFpsCounter
+ *
+ * @see gl4java.awt.GLAnimCanvas#resetFpsCounter
+ * @see gl4java.awt.GLAnimCanvas#stopFpsCounter
+ * @see gl4java.awt.GLAnimCanvas#getFps
+ * @see gl4java.awt.GLAnimCanvas#getFpsDuration
+ * @see gl4java.awt.GLAnimCanvas#getFpsFrames
+ * @see gl4java.awt.GLAnimCanvas#setVerboseFps
+ */
+ public double getFps()
+ {
+ return fps;
+ }
+
+ /**
+ * returns the calculated duration in millisecs
+ * <p>
+ * this data is avaiable after calling stopFpsCounter
+ *
+ * @see gl4java.awt.GLAnimCanvas#resetFpsCounter
+ * @see gl4java.awt.GLAnimCanvas#stopFpsCounter
+ * @see gl4java.awt.GLAnimCanvas#getFps
+ * @see gl4java.awt.GLAnimCanvas#getFpsDuration
+ * @see gl4java.awt.GLAnimCanvas#getFpsFrames
+ * @see gl4java.awt.GLAnimCanvas#setVerboseFps
+ */
+ public long getFpsDuration()
+ {
+ return fps_duration;
+ }
+
+ /**
+ * returns the calculated frames number
+ * <p>
+ * this data is avaiable after calling stopFpsCounter
+ *
+ * @see gl4java.awt.GLAnimCanvas#resetFpsCounter
+ * @see gl4java.awt.GLAnimCanvas#stopFpsCounter
+ * @see gl4java.awt.GLAnimCanvas#getFps
+ * @see gl4java.awt.GLAnimCanvas#getFpsDuration
+ * @see gl4java.awt.GLAnimCanvas#getFpsFrames
+ * @see gl4java.awt.GLAnimCanvas#setVerboseFps
+ */
+ public long getFpsFrames()
+ {
+ return fps_frames;
+ }
+
+ /**
+ * Just set the FramePerSecounds for Animation
+ *
+ * @deprecated Now the frames per seconds are allways
+ * calculated, no pre-sync needed.
+ * @see #setAnimateFps(double)
+ */
+ public void setAnimateFps(double fps, int synFrames)
+ {
+ setAnimateFps(fps);
+ }
+
+ /**
+ * Just set the FramePerSecounds for Animation
+ *
+ * @see gl4java.awt.GLAnimCanvas#getMaxFps
+ */
+ public void setAnimateFps(double fps)
+ {
+ FramesPerSec=fps;
+ mSecPerFrame = (long) ( (1.0/FramesPerSec) * 1000.0 ) ;
+ if(GLContext.gljClassDebug)
+ {
+ System.out.println("\nset fps := "+
+ String.valueOf(fps)+
+ " -> "+String.valueOf(mSecPerFrame)+
+ " [ms/frame]"
+ );
+ }
+ resetFpsCounter();
+ }
+
+ /**
+ * Just get the maximum number of Frames per secounds,
+ * which is calculated with the time, one frame needs to render !
+ *
+ * this value is avaiable after the thread is started
+ * and the first frames are rendered !
+ *
+ * @see gl4java.awt.GLAnimCanvas#setAnimateFps
+ */
+ public double getMaxFps()
+ {
+ return (1.0/(double)_f_dur)*1000.0;
+ }
+
+}
+
diff --git a/gl4java/awt/GLCanvas.java b/gl4java/awt/GLCanvas.java
index 73c9bba..0b89bf8 100644
--- a/gl4java/awt/GLCanvas.java
+++ b/gl4java/awt/GLCanvas.java
@@ -1,1068 +1,1177 @@
-/**
- * @(#) GLCanvas.java
- */
-
-
-package gl4java.awt;
-
-import gl4java.*;
-import gl4java.drawable.*;
-import gl4java.drawable.utils.*;
-
-import java.awt.*;
-import java.awt.event.*;
-import java.util.EventListener;
-
-/**
- * This is meant as an base class writing
- * easy render functions. A clean usage of multi-threading compatible
- * with JAVA2 is implemented in GLAnimCanvas !
- *
- * <p>
- *
- * If you are interessting in further Documentation and/or
- * the history of GL4Java follow the following link.
- *
- * <pre>
- <a href="../../GL4Java.html">The GL4Java Documentation</a>
- * </pre>
- * <p>
- *
- * There are two ways of using a GLCanvas: the {@link
- * gl4java.drawable.GLEventListener} model or the subclassing model. Earlier
- * versions of OpenGL for Java only supported the subclassing model.
- * The default implementations of {@link #init}, {@link #display},
- * {@link #reshape} and {@link #doCleanup}
- * now send events to GLEventListeners; they can
- * still be overridden as before to support the subclassing model.
- *
- * <p>
- * If using the subclassing model, you should override the following
- * methods for your needs:
- * <pre>
- <a href="GLCanvas.html#init()">preInit - initialisation before creating GLContext</a>
- <a href="GLCanvas.html#init()">init - 1st initialisation after creating GLContext</a>
- <a href="GLCanvas.html#doCleanup()">doCleanup - OGL cleanup prior to context deletion</a>
- <a href="GLCanvas.html#display()">display - render your frame</a>
- <a href="GLCanvas.html#reshape(int, int)">reshape - to reshape (window resize), gljResize() is allready invoked !</a>
- * </pre>
- *
- * To check if you can use the GLContext and GL and GLU methods,
- * use the function
- * <pre>
- <a href="GLCanvas.html#cvsIsInit()">cvsIsInit</a>
- * </pre>
- * <p>
- * IF you remove/release a GLCanvas,
- * e.g. you want to close/dispose it�s Window (which contains this GLCanvas),
- * you HAVE TO call:
- *
- * <pre>
- <a href="GLCanvas.html#cvsDispose()">cvsDispose</a>
- * </pre>
- * You should call this before releasing/dispose this Window !
- * Also you can overwrite this class,
- * to dispose your own elements, e.g. a Frame etc. -
- * but be shure that you call
- * cvsDispose implementation call this one !
- *
- * <p>
- * We do override the following Canvas methods.
- *
- * <pre>
- <a href="GLCanvas.html#update(java.awt.Graphics)">update</a>
- <a href="GLCanvas.html#paint(java.awt.Graphics)">paint</a>
- * </pre>
- * <p>
- *
- * @see gl4java.awt.GLAnimCanvas
- * @version 2.0, 21. April 1999
- * @author Sven Goethel
- * */
-public class GLCanvas extends Canvas
- implements GLEnum, GLUEnum,
- ComponentListener, WindowListener, MouseListener,
- GLDrawable
-{
- protected GLContext glj = null;
- public GLFunc gl = null;
- public GLUFunc glu = null;
-
- protected Dimension size = null;
- protected boolean mustResize = false;
-
- protected boolean needCvsDispose = false;
-
- /**
- * Visual pre-set for doubleBuffer, default: true
- * This value is updated after a GLContext is created with the
- * original updated value of GLContext !
- *
- * @see gl4java.awt.GLCanvas#preInit
- * @see gl4java.awt.GLCanvas#paint
- */
- protected boolean doubleBuffer = true;
-
- /**
- * Visual pre-set for stencil-bit number, default: 0
- * This value is updated after a GLContext is created with the
- * original updated value of GLContext !
- *
- * @see gl4java.awt.GLCanvas#preInit
- * @see gl4java.awt.GLCanvas#paint
- */
- protected int stencilBits = 0;
-
- /**
- * Visual pre-set for accumulator buffer size, default: 0
- * This value is updated after a GLContext is created with the
- * original updated value of GLContext !
- *
- * This value has a special behavior.
- * For input - within the contructor,
- * it is the value for each component !
- *
- * The output value, after the constructor returns,
- * it is the summary of all accumulation bits of all components !
- *
- * @see gl4java.awt.GLCanvas#preInit
- * @see gl4java.awt.GLCanvas#paint
- */
- protected int accumSize = 0;
-
- /**
- * Visual pre-set for stereoView, default: false
- * This value is updated after a GLContext is created with the
- * original updated value of GLContext !
- *
- * @see gl4java.awt.GLCanvas#preInit
- * @see gl4java.awt.GLCanvas#paint
- */
- protected boolean stereoView = false;
-
- /**
- * Visual pre-set for RGBA usage, default: true - of course ;-)
- * This value is updated after a GLContext is created with the
- * original updated value of GLContext !
- *
- * @see gl4java.awt.GLCanvas#preInit
- * @see gl4java.awt.GLCanvas#paint
- */
- protected boolean rgba = true;
-
- protected GLCapabilities capabilities = null;
-
- /**
- * Visual pre-set for RGBA usage, default: true - of course ;-)
- * This value is updated after a GLContext is created with the
- * original updated value of GLContext !
- *
- * @see gl4java.awt.GLCanvas#preInit
- * @see gl4java.awt.GLCanvas#paint
- */
- protected boolean createOwnWindow = false;
-
- /**
- * The context with wich display lists and textures will be shared.
- *
- * @see gl4java.awt.GLCanvas#preInit
- * @see gl4java.awt.GLCanvas#paint
- */
- protected GLContext sharedGLContext;
-
- // The list of GLEventListeners
- private GLEventListenerList listeners = new GLEventListenerList();
-
- static {
- if(GLContext.doLoadNativeLibraries(null, null, null)==false)
- System.out.println("GLCanvas could not load def. native libs.");
- }
-
- /**
- *
- * Constructor
- *
- * @param width the canvas initial-prefered width
- * @param height the canvas initial-prefered height
- *
- * @param gl_Name The name of the GLFunc implementation
- * If gl_Name==null, the default class will be used !
- *
- * @param glu_Name The name of the GLUFunc implementation
- * If gl_LibName==null, the default class will be used !
- *
- */
- public GLCanvas( GLCapabilities capabilities,
- int width, int height,
- String gl_Name,
- String glu_Name
- )
- {
- super( );
-
- this.capabilities=capabilities;
-
- if( (gl=GLContext.createGLFunc(gl_Name)) ==null)
- {
- System.out.println("GLFunc implementation "+gl_Name+" not created");
- }
- if( (glu=GLContext.createGLUFunc(glu_Name)) ==null)
- {
- System.out.println("GLUFunc implementation "+glu_Name+" not created");
- }
-
- size = new Dimension(width, height);
-
- setSize(size);
-
- }
-
- /**
- *
- * Constructor
- *
- * @param width the canvas initial-prefered width
- * @param height the canvas initial-prefered height
- *
- * @param gl_Name The name of the GLFunc implementation
- * If gl_Name==null, the default class will be used !
- *
- * @param glu_Name The name of the GLUFunc implementation
- * If gl_LibName==null, the default class will be used !
- *
- */
- public GLCanvas( GLCapabilities capabilities,
- int width, int height
- )
- {
- this(capabilities, width, height, null, null);
- }
-
- /**
- *
- * Constructor
- *
- * @param width the canvas initial-prefered width
- * @param height the canvas initial-prefered height
- *
- * @param gl_Name The name of the GLFunc implementation
- * If gl_Name==null, the default class will be used !
- *
- * @param glu_Name The name of the GLUFunc implementation
- * If gl_LibName==null, the default class will be used !
- *
- */
- public GLCanvas( int width, int height,
- String gl_Name,
- String glu_Name
- )
- {
- this(null, width, height, gl_Name, glu_Name);
- }
-
- /**
- *
- * Constructor
- *
- * Uses the default GLFunc and GLUFunc implementation !
- *
- * @param width the canvas initial-prefered width
- * @param height the canvas initial-prefered height
- *
- */
- public GLCanvas( int width, int height )
- {
- this(width, height, null, null);
- }
-
- /**
- *
- * Constructor (JDK 1.2 or later)
- *
- * @param config the GraphicsConfiguration for this canvas (>= JDK 1.2)
- *
- * @param width the canvas initial-prefered width
- * @param height the canvas initial-prefered height
- *
- * @param gl_Name The name of the GLFunc implementation
- * If gl_Name==null, the default class will be used !
- *
- * @param glu_Name The name of the GLUFunc implementation
- * If gl_LibName==null, the default class will be used !
- *
- */
- public GLCanvas( GraphicsConfiguration config,
- GLCapabilities capabilities,
- int width, int height,
- String gl_Name,
- String glu_Name
- )
- {
- super( config );
-
- this.capabilities=capabilities;
-
- if( (gl=GLContext.createGLFunc(gl_Name)) ==null)
- {
- System.out.println("GLFunc implementation "+gl_Name+" not created");
- }
- if( (glu=GLContext.createGLUFunc(glu_Name)) ==null)
- {
- System.out.println("GLUFunc implementation "+glu_Name+" not created");
- }
-
- size = new Dimension(width, height);
-
- setSize(size);
-
- }
-
- /**
- *
- * Constructor (JDK 1.2 or later)
- *
- * Uses the default GLFunc and GLUFunc implementation !
- *
- * @param config the GraphicsConfiguration for this canvas (>= JDK 1.2)
- *
- * @param width the canvas initial-prefered width
- * @param height the canvas initial-prefered height
- *
- */
- public GLCanvas( GraphicsConfiguration config,
- GLCapabilities capabilities,
- int width, int height )
- {
- this(config, capabilities, width, height, null, null);
- }
-
- /* GLCanvas AWT classes */
-
- public Dimension getPreferredSize() {
- return getMinimumSize();
- }
-
- public Dimension getMinimumSize() {
- return size;
- }
-
- /**
- * Used to return the created GLContext
- */
- public final GLContext getGLContext() { return glj; }
-
- /**
- *
- * Overridden update
- * This one only call's the paint method, without clearing
- * the background - thats hopefully done by OpenGL ;-)
- *
- * @param g the Graphics Context
- * @return void
- *
- * @see gl4java.awt.GLCanvas#paint
- */
- public void update(Graphics g)
- {
- /* let's let OpenGL clear the background ... */
- paint(g);
- }
-
- /**
- * Safe the toplevel window
- */
- protected Window topLevelWindow = null;
-
- /**
- *
- * This function returns the found TopLevelWindow,
- * which contains this Canvas ..
- *
- * @return void
- *
- * @see gl4java.awt.GLCanvas#paint
- */
- public final Window getTopLevelWindow()
- { return topLevelWindow; }
-
- /**
- * this function overrides the Canvas paint method !
- *
- * For the first paint,
- * the user function preInit is called, a GLContext is created
- * and the user function init is called !
- *
- * Also, if a GL Context exist, GLCanvas's sDisplay-method will be called
- * to do OpenGL-rendering.
- *
- * The sDisplay method itself calls the display-method !
- * sDisplay is needed to be thread-safe, to manage
- * the resize functionality and to safe the time per frame.
- *
- * To define your rendering, you should overwrite the display-method
- * in your derivation.
- *
- * @see gl4java.GLContext#GLContext
- * @see gl4java.awt.GLCanvas#cvsIsInit
- * @see gl4java.awt.GLCanvas#sDisplay
- * @see gl4java.awt.GLCanvas#display
- * @see gl4java.awt.GLCanvas#preInit
- * @see gl4java.awt.GLCanvas#init
- */
- public synchronized final void paint( Graphics g )
- {
- if(glj == null || ( !glj.gljIsInit() && isGLEnabled() ) )
- {
- if(GLContext.gljClassDebug)
- System.out.println("GLCanvas create GLContext (recreate="+
- (glj != null) +")");
- preInit();
-
- if(glj!=null) glj=null;
-
- if (capabilities != null )
- {
- glj = new GLContext ( this, gl, glu,
- capabilities,
- sharedGLContext );
- } else {
- glj = new GLContext ( this, gl, glu,
- createOwnWindow,
- doubleBuffer, stereoView,
- rgba, stencilBits, accumSize,
- sharedGLContext );
- }
-
- if(glj!=null)
- {
- createOwnWindow = glj.isOwnWindowCreated();
- doubleBuffer = glj.isDoubleBuffer();
- stencilBits = glj.getStencilBitNumber();
- accumSize = glj.getAccumSize();
- stereoView = glj.isStereoView();
- rgba = glj.isRGBA();
- }
-
- Color col = getBackground();
- gl.glClearColor((float)col.getRed()/255.0f,
- (float)col.getGreen()/255.0f,
- (float)col.getBlue()/255.0f, 0.0f);
-
- init();
-
- // fetch the top-level window ,
- // to add us as the windowListener
- //
- Container _c = getParent();
- Container c = null;
-
- while(_c!=null)
- {
- c = _c;
- _c = _c.getParent();
- }
-
- if(c instanceof Window) {
- topLevelWindow = (Window)c;
- topLevelWindow.addComponentListener(this);
- } else {
- topLevelWindow = null;
- System.out.println("toplevel is not a Window: "+c);
- }
-
- if(topLevelWindow!=null)
- {
- topLevelWindow.addWindowListener(this);
- } else {
- System.out.println("no parent found for "+getName());
- System.out.flush();
- }
-
- /* to be able for RESIZE event's */
- addComponentListener(this);
- addMouseListener(this);
-
- /* force a reshape, to be sure .. */
- mustResize = true;
- }
-
- sDisplay();
- }
-
- /**
- *
- * This is your pre-init method.
- * preInit is called just BEFORE the GL-Context is created.
- * You should override preInit, to initialize your visual-stuff,
- * like the protected vars: doubleBuffer and stereoView
- *
- * @return void
- *
- * @see gl4java.awt.GLCanvas#paint
- * @see gl4java.awt.GLCanvas#doubleBuffer
- * @see gl4java.awt.GLCanvas#stereoView
- * @see gl4java.awt.GLCanvas#rgba
- * @see gl4java.awt.GLCanvas#stencilBits
- * @see gl4java.awt.GLCanvas#accumSize
- */
- public void preInit()
- {
- }
-
- /**
- *
- * init is called right after the GL-Context is initialized.
- * The default implementation calls init() on all of this
- * component's GLEventListeners.
- *
- * <p>
- * If using the subclassing model, you can override this to
- * perform one-time OpenGL initializations such as setting up
- * lights and display lists.
- *
- * @return void
- *
- * @see gl4java.awt.GLCanvas#paint
- * @see gl4java.drawable.GLEventListener#init
- */
- public void init()
- {
- listeners.sendInitEvent(this);
- }
-
- /**
- * This method is used to clean up any OpenGL stuff (delete textures
- * or whatever) prior to actually deleting the OpenGL context.
- * You should override this with your own version, if you need to do
- * any cleanup work at this phase.
- * This functions is called within cvsDispose
- *
- * @return void
- *
- * @see gl4java.awt.GLCanvas#cvsDispose
- * @see gl4java.drawable.GLEventListener#cleanup
- */
- public void doCleanup()
- {
- listeners.sendCleanupEvent(this);
- }
-
- /**
- * This function returns, if everything is init: the GLContext,
- * the and the users init function
- * This value is set in the paint method!
- *
- * @return boolean
- *
- * @see gl4java.awt.GLCanvas#paint
- * @see gl4java.awt.GLCanvas#init
- */
- public boolean cvsIsInit()
- {
- if(glj!=null)
- return glj.gljIsInit();
- return false;
- }
-
- /**
- * This function enables, disables the GL-Context !
- * If false is given, the openGL renderer/context is
- * disabled and disconected (gljFree is called, if initialized) !
- *
- * If disabled, all GL Functions are disabled but the
- * Destroy & Free are not !
- *
- * @return boolean
- *
- * @see gl4java.awt.GLCanvas#cvsDispose
- * @see gl4java.GLContext#setEnabled
- * @see gl4java.GLContext#gljMakeCurrent
- * @see gl4java.GLContext#gljDestroy
- * @see gl4java.GLContext#gljFree
- */
- public void setGLEnabled(boolean b)
- {
- if(glj!=null)
- glj.setEnabled(b);
- }
-
- /**
- * This function enables, disables the GL-Context !
- * If false is given, the openGL renderer/context is
- * disabled and disconected (gljFree is called, if initialized) !
- *
- * If disabled, all GL Functions are disabled but the
- * Destroy & Free are not !
- *
- * The Visible-Flag of this AWT Component is also set to the given value !
- * The setVisible(boolean) method of Component is called !
- *
- * @return boolean
- *
- * @see gl4java.awt.GLCanvas#cvsDispose
- * @see gl4java.GLContext#setEnabled
- * @see gl4java.GLContext#gljMakeCurrent
- * @see gl4java.GLContext#gljDestroy
- * @see gl4java.GLContext#gljFree
- */
- public void setVisible(boolean b)
- {
- if(glj!=null)
- glj.setEnabled(b);
- super.setVisible(b);
- }
-
- /**
- * This function queries, if the GL-Context is enabled !
- *
- * @return boolean
- *
- * @see gl4java.GLContext#isEnabled
- * @see gl4java.GLContext#gljMakeCurrent
- */
- public boolean isGLEnabled()
- {
- if(glj!=null)
- return glj.isEnabled();
- return false;
- }
-
- protected long _f_dur = 0;
-
- /**
- *
- * This is the thread save rendering-method called by paint.
- * The actual thread will be set to highes priority befor calling
- * 'display'. After 'display' the priority will be reset !
- *
- * 'gljFree' will be NOT called after 'display'.
- *
- * We tested the above to use multi-threading and
- * for the demonstration 'glDemos' it works ;-)) !
- *
- * BE SURE, if you want to call 'display' by yourself
- * (e.g. in the run method for animation)
- * YOU HAVE TO CALL sDisplay -- OR YOU MUST KNOW WHAT YOU ARE DOING THEN !
- *
- * @return void
- *
- * @see gl4java.awt.GLCanvas#paint
- * @see gl4java.awt.GLCanvas#display
- */
- public synchronized final void sDisplay()
- {
- boolean ok = true;
-
- if(!cvsIsInit())
- {
- return;
- }
-
- if( mustResize )
- {
- if( glj.gljMakeCurrent() == true )
- {
- size = getSize();
- glj.gljResize( size.width, size.height ) ;
- reshape(size.width, size.height);
- mustResize = false;
- invalidate();
- repaint(100);
- glj.gljFree();
- }
- }
-
- long _s = System.currentTimeMillis();
-
- if(ok)
- {
- display();
- }
-
- _f_dur = System.currentTimeMillis()-_s;
- }
-
- /**
- *
- * This is the rendering-method called by sDisplay
- * (and sDisplay is called by paint !).
- *
- * <p>
- * The default implementation of display() sends
- * preDisplay, display and postDisplay events to
- * all {@link gl4java.GLEventListener}s associated with this
- * GLCanvas in the above order.
- *
- * <p>
- * <pre>
- reset timer for frame duration (done by sDisplay)
-
- for_all(gl4java.GLEventListener)
- SEND preDisplay
-
- if( gljMakeCurrent() )
- {
- for_all(gl4java.GLEventListener)
- SEND display
- gljFree()
- gljSwap()
-
- for_all(gl4java.GLEventListener)
- SEND postDisplay
- }
-
- stop timer for frame duration (done by sDisplay)
- * </pre>
- *
- * <p>
- * If you use the subclassing model (as opposed to the
- * GLEventListener model), your subclass will redefine this to
- * perform its OpenGL drawing. In this case you MUST encapsulate
- * your OpenGL calls within:
- * <pre>
- - glj.gljMakeCurrent()
- YOUR OpenGL commands here !
- - glj.gljFree()
- * </pre>
- *
- * BE SURE, if you want to call 'display' by yourself
- * (e.g. in the run method for animation)
- * YOU HAVE TO CALL sDisplay !
- *
- * 'sDisplay' manages a semaphore to avoid reentrance of
- * the display function !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- *
- * @return void
- *
- * @see gl4java.awt.GLCanvas#sDisplay
- * @see gl4java.awt.GLCanvas#paint
- * @see gl4java.GLContext#gljMakeCurrent
- * @see gl4java.GLContext#gljSwap
- * @see gl4java.drawable.GLEventListener#preDisplay
- * @see gl4java.drawable.GLEventListener#display
- * @see gl4java.drawable.GLEventListener#postDisplay
- */
- public void display()
- {
- listeners.sendPreDisplayEvent(this);
-
- if (glj.gljMakeCurrent()) {
- listeners.sendDisplayEvent(this);
-
- glj.gljSwap();
- glj.gljCheckGL();
- glj.gljFree();
-
- listeners.sendPostDisplayEvent(this);
- }
-
- }
-
- /**
- *
- * This �reshape� method will be invoked after the first paint command
- * after GLCanvas.componentResize is called AND only if �gljMakeCurrent� was
- * successful (so a call of gljMakeCurrent is redundant).
- * �reshape� is not an overloading of java.awt.Component.reshape,
- * �reshape� is more like �glut�-reshape.
- *
- * <p>
- * GLCanvas.reshape already has a simple default implementation,
- * which calls �gljResize� and �glViewport�. It also sends the
- * reshape() event to all GLEventListeners. If using the
- * GLEventListener model, it may not be necessary to do anything
- * in your event listener's reshape() method; if using the
- * subclassing model, it may not be necessary to override this.
- *
- * <p>
- * The needed call to �gljResize� is done by the invoker paint !
- *
- * @param width the new width
- * @param height the new height
- * @return void
- *
- * @see gl4java.awt.GLCanvas#paint
- * @see gl4java.awt.GLCanvas#sDisplay
- * @see gl4java.drawable.GLEventListener#reshape
- */
- public void reshape( int width, int height )
- {
- gl.glViewport(0,0, width, height);
- listeners.sendReshapeEvent(this, width, height);
- }
-
- /**
- *
- * �componentResized� is the componentListeners event handler.
- *
- * This method sets the variable �mustResize� to true,
- * so the upcoming �paint� method-call will invoke �reshape� !
- *
- * This little look-alike complicating thing is done,
- * to avoid an Exception by using the glContext from more than
- * one concurrent thread�s !
- *
- * You cannot override this implementation, it is final
- * - override �reshape' instead !
- *
- * @param e the element, which is resized
- * @return void
- *
- * @see gl4java.awt.GLCanvas#paint
- * @see gl4java.awt.GLCanvas#reshape
- */
- public void componentResized(ComponentEvent e)
- {
- if(glj!=null && glj.gljIsInit() && e.getComponent()==this )
- {
- mustResize = true;
- repaint();
- }
- }
-
- public void componentMoved(ComponentEvent e)
- {
- if(glj!=null && glj.gljIsInit())
- {
- repaint(100);
- }
- }
-
- public void componentShown(ComponentEvent e)
- {
- }
-
- public void componentHidden(ComponentEvent e)
- { }
-
- public void mouseClicked(MouseEvent e)
- {
- if(glj!=null && glj.gljIsInit())
- {
- repaint();
- }
- }
-
- public void mouseEntered(MouseEvent e)
- { }
- public void mouseExited(MouseEvent e)
- {}
- public void mousePressed(MouseEvent e)
- {
- }
- public void mouseReleased(MouseEvent e)
- {
- }
-
- public void windowOpened(WindowEvent e)
- {
- }
-
- /**
- *
- * �windowClosing� is the windowListeners event handler
- * for the topLevelWindow of this Canvas !
- *
- * This methods free�s AND destroy�s
- * the GL Context with �glj.gljDestroy� !
- *
- * @return void
- *
- */
- public void windowClosing(WindowEvent e)
- {
- if(e.getComponent().equals(topLevelWindow))
- {
- cvsDispose();
- }
- }
-
- /**
- *
- * �windowClosed� is the windowListeners event handler.
- *
- * @return void
- *
- */
- public void windowClosed(WindowEvent e)
- {
- if (needCvsDispose) cvsDispose();
- }
-
- public void windowIconified(WindowEvent e)
- {
- }
-
- public void windowDeiconified(WindowEvent e)
- {
- }
-
- public void windowActivated(WindowEvent e)
- {
- if(glj!=null && glj.gljIsInit())
- {
- repaint(100);
- }
- }
-
- public void windowDeactivated(WindowEvent e)
- {
- }
-
- /**
- * You should call this before releasing/dispose this Window !
- * Also you can overwrite this class,
- * to dispose your own elements, e.g. a Frame etc. -
- * but be shure that you call
- * cvsDispose implementation call this one !
- *
- * This function calls gljDestroy of GLContext !
- * The Visibility is set to false !
- * The Enabled is set to false either !
- *
- * To bring this component back to live,
- * you need call setVisible(true) !
- *
- * @see gl4java.GLContext#gljDestroy
- * @see gl4java.awt.GLCanvas#doCleanup
- */
- public void cvsDispose()
- {
- if(GLContext.gljClassDebug)
- System.out.println("GLCanvas cvsDispose (doit="+
- ( (glj != null) && glj.gljIsInit() ) +")");
-
- removeComponentListener(this);
- removeMouseListener(this);
-
- if (glj != null)
- {
- if (glj.gljIsInit())
- {
- /* Sometimes the Microsoft VM calls the
- Applet.stop() method but doesn't have
- permissions to do J/Direct calls, so
- this whole block of code will throw a
- security exception. If this happens,
- however, windowClosing() will still
- call us again later and we will have
- another opportunity to shut down the
- context, so it all works out fine. */
- try
- {
- setVisible(false);
- doCleanup();
-
- glj.gljDestroy();
- needCvsDispose = false;
- }
- catch (Exception ex)
- {
- needCvsDispose = true;
- }
- }
- }
-
- // Setting glj to null will simply cause paint() to re-initialize.
- // We don't want that to happen, so we will leave glj non-null.
- }
-
- /**
- * does nothing than:
- *
- * @see gl4java.awt.GLCanvas#cvsDispose
- */
- protected void finalize()
- throws Throwable
- {
- if(GLContext.gljClassDebug)
- System.out.println("GLCanvas finalize ..");
-
- cvsDispose();
- super.finalize();
- }
-
- /**
- * does nothing than:
- *
- * @see gl4java.awt.GLCanvas#cvsDispose
- *
- * @deprecated Use cvsDispose instead, well finalize is also implemented
- */
- public void destroy()
- {
- if(GLContext.gljClassDebug)
- System.out.println("GLCanvas destroy ..");
-
- cvsDispose();
- }
-
- /**
- * get methods
- */
- public final int cvsGetWidth() {
- return getSize().width;
- }
- public final int cvsGetHeight() {
- return getSize().height;
- }
-
- //----------------------------------------------------------------------
- // Implementation of GLDrawable
- //
-
- public void addGLEventListener(GLEventListener listener) {
- listeners.add(listener);
- }
-
- public void removeGLEventListener(GLEventListener listener) {
- listeners.remove(listener);
- }
-
- public EventListener[] getListeners(Class listenerType)
- throws ClassCastException
- {
- EventListener[] evtlst=null;
- Class _GLEventListener = null;
-
- try {
- _GLEventListener = Class.forName("gl4java.drawable.GLEventListener");
- } catch (Exception ex) {
- System.out.println(ex);
- }
-
- if (_GLEventListener!=null &&
- listenerType.isAssignableFrom(_GLEventListener) )
- evtlst = listeners.getListeners();
-
- EventListener[] t_evtlst = super.getListeners(listenerType);
-
- if(t_evtlst==null || t_evtlst.length==0)
- return evtlst;
-
- if(evtlst==null || evtlst.length==0)
- return t_evtlst;
-
- EventListener[] n_evtlst =
- new EventListener[t_evtlst.length+evtlst.length];
-
- try {
- System.arraycopy(evtlst, 0, n_evtlst, 0, evtlst.length);
- System.arraycopy(t_evtlst, 0, n_evtlst, evtlst.length, t_evtlst.length);
- } catch (Exception ex)
- { System.out.println(ex); }
-
- evtlst = null;
- t_evtlst = null;
-
- return n_evtlst;
- }
-
- public GLFunc getGL() {
- return gl;
- }
-
- public GLUFunc getGLU() {
- return glu;
- }
-}
+/**
+ * @(#) GLCanvas.java
+ */
+
+
+package gl4java.awt;
+
+import gl4java.*;
+import gl4java.drawable.*;
+import gl4java.drawable.utils.*;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.EventListener;
+
+/**
+ * This is meant as an base class writing
+ * easy render functions. A clean usage of multi-threading compatible
+ * with JAVA2 is implemented in GLAnimCanvas !
+ *
+ * <p>
+ *
+ * If you are interessting in further Documentation and/or
+ * the history of GL4Java follow the following link.
+ *
+ * <pre>
+ <a href="../../GL4Java.html">The GL4Java Documentation</a>
+ * </pre>
+ * <p>
+ *
+ * There are two ways of using a GLCanvas: the {@link
+ * gl4java.drawable.GLEventListener} model or the subclassing model. Earlier
+ * versions of OpenGL for Java only supported the subclassing model.
+ * The default implementations of {@link #init}, {@link #display},
+ * {@link #reshape} and {@link #doCleanup}
+ * now send events to GLEventListeners; they can
+ * still be overridden as before to support the subclassing model.
+ *
+ * <p>
+ * If using the subclassing model, you should override the following
+ * methods for your needs:
+ * <pre>
+ <a href="GLCanvas.html#init()">preInit - initialisation before creating GLContext</a>
+ <a href="GLCanvas.html#init()">init - 1st initialisation after creating GLContext</a>
+ <a href="GLCanvas.html#doCleanup()">doCleanup - OGL cleanup prior to context deletion</a>
+ <a href="GLCanvas.html#display()">display - render your frame</a>
+ <a href="GLCanvas.html#reshape(int, int)">reshape - to reshape (window resize), gljResize() is allready invoked !</a>
+ * </pre>
+ *
+ * To check if you can use the GLContext and GL and GLU methods,
+ * use the function
+ * <pre>
+ <a href="GLCanvas.html#cvsIsInit()">cvsIsInit</a>
+ * </pre>
+ * <p>
+ * IF you remove/release a GLCanvas,
+ * e.g. you want to close/dispose it�s Window (which contains this GLCanvas),
+ * you HAVE TO call:
+ *
+ * <pre>
+ <a href="GLCanvas.html#cvsDispose()">cvsDispose</a>
+ * </pre>
+ * You should call this before releasing/dispose this Window !
+ * Also you can overwrite this class,
+ * to dispose your own elements, e.g. a Frame etc. -
+ * but be shure that you call
+ * cvsDispose implementation call this one !
+ *
+ * <p>
+ * We do override the following Canvas methods.
+ *
+ * <pre>
+ <a href="GLCanvas.html#update(java.awt.Graphics)">update</a>
+ <a href="GLCanvas.html#paint(java.awt.Graphics)">paint</a>
+ * </pre>
+ * <p>
+ *
+ * @see gl4java.awt.GLAnimCanvas
+ * @version 2.0, 21. April 1999
+ * @author Sven Goethel
+ * */
+public class GLCanvas extends Canvas
+ implements GLEnum, GLUEnum,
+ ComponentListener, WindowListener, MouseListener,
+ GLDrawable
+{
+ protected GLContext glj = null;
+ public GLFunc gl = null;
+ public GLUFunc glu = null;
+
+ protected Dimension size = null;
+ protected boolean mustResize = false;
+
+ protected boolean needCvsDispose = false;
+
+ /**
+ * Visual pre-set for doubleBuffer, default: true
+ * This value is updated after a GLContext is created with the
+ * original updated value of GLContext !
+ *
+ * @see gl4java.awt.GLCanvas#preInit
+ * @see gl4java.awt.GLCanvas#paint
+ */
+ protected boolean doubleBuffer = true;
+
+ /**
+ * Visual pre-set for stencil-bit number, default: 0
+ * This value is updated after a GLContext is created with the
+ * original updated value of GLContext !
+ *
+ * @see gl4java.awt.GLCanvas#preInit
+ * @see gl4java.awt.GLCanvas#paint
+ */
+ protected int stencilBits = 0;
+
+ /**
+ * Visual pre-set for accumulator buffer size, default: 0
+ * This value is updated after a GLContext is created with the
+ * original updated value of GLContext !
+ *
+ * This value has a special behavior.
+ * For input - within the contructor,
+ * it is the value for each component !
+ *
+ * The output value, after the constructor returns,
+ * it is the summary of all accumulation bits of all components !
+ *
+ * @see gl4java.awt.GLCanvas#preInit
+ * @see gl4java.awt.GLCanvas#paint
+ */
+ protected int accumSize = 0;
+
+ /**
+ * Visual pre-set for stereoView, default: false
+ * This value is updated after a GLContext is created with the
+ * original updated value of GLContext !
+ *
+ * @see gl4java.awt.GLCanvas#preInit
+ * @see gl4java.awt.GLCanvas#paint
+ */
+ protected boolean stereoView = false;
+
+ /**
+ * Visual pre-set for RGBA usage, default: true - of course ;-)
+ * This value is updated after a GLContext is created with the
+ * original updated value of GLContext !
+ *
+ * @see gl4java.awt.GLCanvas#preInit
+ * @see gl4java.awt.GLCanvas#paint
+ */
+ protected boolean rgba = true;
+
+ protected GLCapabilities capabilities = null;
+
+ /**
+ * Visual pre-set for RGBA usage, default: true - of course ;-)
+ * This value is updated after a GLContext is created with the
+ * original updated value of GLContext !
+ *
+ * @see gl4java.awt.GLCanvas#preInit
+ * @see gl4java.awt.GLCanvas#paint
+ */
+ protected boolean createOwnWindow = false;
+
+ /**
+ * The context with wich display lists and textures will be shared.
+ *
+ * @see gl4java.awt.GLCanvas#preInit
+ * @see gl4java.awt.GLCanvas#paint
+ */
+ protected GLContext sharedGLContext;
+
+ // The list of GLEventListeners
+ private GLEventListenerList listeners = new GLEventListenerList();
+
+ // Indicates whether init() has been called yet.
+ private volatile boolean initCalled = false;
+
+ // Indicates whether the canvas will permit any calls to init() or
+ // display() from within the paint() method; defaults to true for
+ // backward compatibility.
+ private boolean enableAWTThreadRendering = true;
+
+ // Indicates whether display() automatically makes the canvas's
+ // GLContext current and frees it each call; defaults to true for
+ // backward compatibility. On higher-end graphics cards it is
+ // important to minimize the number of "make current" calls even
+ // across frames; a GLAnimCanvas running in its own thread, and
+ // with AWT thread rendering disabled, will only make its
+ // associated context current once, at the beginning of its
+ // rendering loop.
+ private boolean autoMakeContextCurrent = true;
+
+ static {
+ if(GLContext.doLoadNativeLibraries(null, null, null)==false)
+ System.out.println("GLCanvas could not load def. native libs.");
+ }
+
+ /**
+ *
+ * Constructor
+ *
+ * @param width the canvas initial-prefered width
+ * @param height the canvas initial-prefered height
+ *
+ * @param gl_Name The name of the GLFunc implementation
+ * If gl_Name==null, the default class will be used !
+ *
+ * @param glu_Name The name of the GLUFunc implementation
+ * If gl_LibName==null, the default class will be used !
+ *
+ */
+ public GLCanvas( GLCapabilities capabilities,
+ int width, int height,
+ String gl_Name,
+ String glu_Name
+ )
+ {
+ super( );
+
+ this.capabilities=capabilities;
+
+ if( (gl=GLContext.createGLFunc(gl_Name)) ==null)
+ {
+ System.out.println("GLFunc implementation "+gl_Name+" not created");
+ }
+ if( (glu=GLContext.createGLUFunc(glu_Name)) ==null)
+ {
+ System.out.println("GLUFunc implementation "+glu_Name+" not created");
+ }
+
+ size = new Dimension(width, height);
+
+ setSize(size);
+
+ }
+
+ /**
+ *
+ * Constructor
+ *
+ * @param width the canvas initial-prefered width
+ * @param height the canvas initial-prefered height
+ *
+ * @param gl_Name The name of the GLFunc implementation
+ * If gl_Name==null, the default class will be used !
+ *
+ * @param glu_Name The name of the GLUFunc implementation
+ * If gl_LibName==null, the default class will be used !
+ *
+ */
+ public GLCanvas( GLCapabilities capabilities,
+ int width, int height
+ )
+ {
+ this(capabilities, width, height, null, null);
+ }
+
+ /**
+ *
+ * Constructor
+ *
+ * @param width the canvas initial-prefered width
+ * @param height the canvas initial-prefered height
+ *
+ * @param gl_Name The name of the GLFunc implementation
+ * If gl_Name==null, the default class will be used !
+ *
+ * @param glu_Name The name of the GLUFunc implementation
+ * If gl_LibName==null, the default class will be used !
+ *
+ */
+ public GLCanvas( int width, int height,
+ String gl_Name,
+ String glu_Name
+ )
+ {
+ this(null, width, height, gl_Name, glu_Name);
+ }
+
+ /**
+ *
+ * Constructor
+ *
+ * Uses the default GLFunc and GLUFunc implementation !
+ *
+ * @param width the canvas initial-prefered width
+ * @param height the canvas initial-prefered height
+ *
+ */
+ public GLCanvas( int width, int height )
+ {
+ this(width, height, null, null);
+ }
+
+ /**
+ *
+ * Constructor (JDK 1.2 or later)
+ *
+ * @param config the GraphicsConfiguration for this canvas (>= JDK 1.2)
+ *
+ * @param width the canvas initial-prefered width
+ * @param height the canvas initial-prefered height
+ *
+ * @param gl_Name The name of the GLFunc implementation
+ * If gl_Name==null, the default class will be used !
+ *
+ * @param glu_Name The name of the GLUFunc implementation
+ * If gl_LibName==null, the default class will be used !
+ *
+ */
+ public GLCanvas( GraphicsConfiguration config,
+ GLCapabilities capabilities,
+ int width, int height,
+ String gl_Name,
+ String glu_Name
+ )
+ {
+ super( config );
+
+ this.capabilities=capabilities;
+
+ if( (gl=GLContext.createGLFunc(gl_Name)) ==null)
+ {
+ System.out.println("GLFunc implementation "+gl_Name+" not created");
+ }
+ if( (glu=GLContext.createGLUFunc(glu_Name)) ==null)
+ {
+ System.out.println("GLUFunc implementation "+glu_Name+" not created");
+ }
+
+ size = new Dimension(width, height);
+
+ setSize(size);
+
+ }
+
+ /**
+ *
+ * Constructor (JDK 1.2 or later)
+ *
+ * Uses the default GLFunc and GLUFunc implementation !
+ *
+ * @param config the GraphicsConfiguration for this canvas (>= JDK 1.2)
+ *
+ * @param width the canvas initial-prefered width
+ * @param height the canvas initial-prefered height
+ *
+ */
+ public GLCanvas( GraphicsConfiguration config,
+ GLCapabilities capabilities,
+ int width, int height )
+ {
+ this(config, capabilities, width, height, null, null);
+ }
+
+ /* GLCanvas AWT classes */
+
+ public Dimension getPreferredSize() {
+ return getMinimumSize();
+ }
+
+ public Dimension getMinimumSize() {
+ return size;
+ }
+
+ /**
+ * Used to return the created GLContext
+ */
+ public final GLContext getGLContext() { return glj; }
+
+ /**
+ *
+ * Overridden update
+ * This one only call's the paint method, without clearing
+ * the background - thats hopefully done by OpenGL ;-)
+ *
+ * @param g the Graphics Context
+ * @return void
+ *
+ * @see gl4java.awt.GLCanvas#paint
+ */
+ public void update(Graphics g)
+ {
+ /* let's let OpenGL clear the background ... */
+ paint(g);
+ }
+
+ /**
+ * Safe the toplevel window
+ */
+ protected Window topLevelWindow = null;
+
+ /**
+ *
+ * This function returns the found TopLevelWindow,
+ * which contains this Canvas ..
+ *
+ * @return void
+ *
+ * @see gl4java.awt.GLCanvas#paint
+ */
+ public final Window getTopLevelWindow()
+ { return topLevelWindow; }
+
+ /** Enables/disables calls to init() and display() from within the
+ AWT thread. If this is enabled (the default, for backward
+ compatibility with earlier releases), the first call to
+ paint() from within the AWT thread (typically prompted by a
+ repaint()) will cause the canvas to be initialized, and
+ subsequent calls to paint() will cause display() to be called.
+ If AWT thread rendering is disabled, the AWT thread will not
+ cause init() or display() to be called if repaint() is called,
+ and the first call to display() will cause the canvas to be
+ initialized. This function is present both to work around bugs
+ in certain vendors' drivers which do not function properly in
+ multithreaded settings, and to allow improved performance of
+ GLAnimCanvas. */
+ public void setAWTThreadRenderingEnabled(boolean val) {
+ enableAWTThreadRendering = val;
+ }
+
+ /** Indicates whether AWT thread rendering is enabled; see {@link
+ #setAWTThreadRenderingEnabled}. */
+ public boolean getAWTThreadRenderingEnabled() {
+ return enableAWTThreadRendering;
+ }
+
+ /** Indicates whether the canvas automatically makes its
+ underlying GLContext current and frees it during each call to
+ display(); defaults to true for backward compatibility. On
+ higher-end graphics cards it is important to minimize the
+ number of "make current" calls even across frames; a
+ GLAnimCanvas running in its own thread and with AWT thread
+ rendering disabled will only make its associated context
+ current once, at the beginning of its rendering loop. */
+ public void setAutoMakeContextCurrent(boolean val) {
+ autoMakeContextCurrent = val;
+ }
+
+ /** Indicates whether the canvas automatically makes its
+ underlying GLContext current and frees it during each call to
+ display(); see {@link #setAutoMakeContextCurrent}. */
+ public boolean getAutoMakeContextCurrent() {
+ return autoMakeContextCurrent;
+ }
+
+ /** Convenience routine which Enables or disables optimized
+ context handling by calling {@link
+ #setAWTThreadRenderingEnabled} and {@link
+ #setAutoMakeContextCurrent} with the given boolean. */
+ public void optimizeContextHandling(boolean yesOrNo) {
+ setAWTThreadRenderingEnabled(yesOrNo);
+ setAutoMakeContextCurrent(yesOrNo);
+ }
+
+ /**
+ * this function overrides the Canvas paint method !
+ *
+ * For the first paint,
+ * the user function preInit is called, a GLContext is created
+ * and the user function init is called !
+ *
+ * Also, if a GL Context exist, GLCanvas's sDisplay-method will be called
+ * to do OpenGL-rendering.
+ *
+ * The sDisplay method itself calls the display-method !
+ * sDisplay is needed to be thread-safe, to manage
+ * the resize functionality and to safe the time per frame.
+ *
+ * To define your rendering, you should overwrite the display-method
+ * in your derivation.
+ *
+ * @see gl4java.GLContext#GLContext
+ * @see gl4java.awt.GLCanvas#cvsIsInit
+ * @see gl4java.awt.GLCanvas#sDisplay
+ * @see gl4java.awt.GLCanvas#display
+ * @see gl4java.awt.GLCanvas#preInit
+ * @see gl4java.awt.GLCanvas#init
+ */
+ public synchronized final void paint( Graphics g )
+ {
+ if(glj == null || ( !glj.gljIsInit() && isGLEnabled() ) )
+ {
+ if(GLContext.gljClassDebug)
+ System.out.println("GLCanvas create GLContext (recreate="+
+ (glj != null) +")");
+ preInit();
+
+ if(glj!=null) glj=null;
+
+ if (capabilities != null )
+ {
+ glj = new GLContext ( this, gl, glu,
+ capabilities,
+ sharedGLContext );
+ } else {
+ glj = new GLContext ( this, gl, glu,
+ createOwnWindow,
+ doubleBuffer, stereoView,
+ rgba, stencilBits, accumSize,
+ sharedGLContext );
+ }
+
+ if(glj!=null)
+ {
+ createOwnWindow = glj.isOwnWindowCreated();
+ doubleBuffer = glj.isDoubleBuffer();
+ stencilBits = glj.getStencilBitNumber();
+ accumSize = glj.getAccumSize();
+ stereoView = glj.isStereoView();
+ rgba = glj.isRGBA();
+ }
+
+ Color col = getBackground();
+ gl.glClearColor((float)col.getRed()/255.0f,
+ (float)col.getGreen()/255.0f,
+ (float)col.getBlue()/255.0f, 0.0f);
+
+ if (getAWTThreadRenderingEnabled()) {
+ init();
+ initCalled = true;
+ }
+
+ // fetch the top-level window ,
+ // to add us as the windowListener
+ //
+ Container _c = getParent();
+ Container c = null;
+
+ while(_c!=null)
+ {
+ c = _c;
+ _c = _c.getParent();
+ }
+
+ if(c instanceof Window) {
+ topLevelWindow = (Window)c;
+ topLevelWindow.addComponentListener(this);
+ } else {
+ topLevelWindow = null;
+ System.out.println("toplevel is not a Window: "+c);
+ }
+
+ if(topLevelWindow!=null)
+ {
+ topLevelWindow.addWindowListener(this);
+ } else {
+ System.out.println("no parent found for "+getName());
+ System.out.flush();
+ }
+
+ /* to be able for RESIZE event's */
+ addComponentListener(this);
+ addMouseListener(this);
+
+ /* force a reshape, to be sure .. */
+ mustResize = true;
+
+ // Free up the OpenGL context for another thread to use
+ glj.gljFree();
+ }
+
+ if (getAWTThreadRenderingEnabled()) {
+ sDisplay();
+ }
+ }
+
+ /**
+ *
+ * This is your pre-init method.
+ * preInit is called just BEFORE the GL-Context is created.
+ * You should override preInit, to initialize your visual-stuff,
+ * like the protected vars: doubleBuffer and stereoView
+ *
+ * @return void
+ *
+ * @see gl4java.awt.GLCanvas#paint
+ * @see gl4java.awt.GLCanvas#doubleBuffer
+ * @see gl4java.awt.GLCanvas#stereoView
+ * @see gl4java.awt.GLCanvas#rgba
+ * @see gl4java.awt.GLCanvas#stencilBits
+ * @see gl4java.awt.GLCanvas#accumSize
+ */
+ public void preInit()
+ {
+ }
+
+ /**
+ *
+ * init is called right after the GL-Context is initialized.
+ * The default implementation calls init() on all of this
+ * component's GLEventListeners.
+ *
+ * <p>
+ * If using the subclassing model, you can override this to
+ * perform one-time OpenGL initializations such as setting up
+ * lights and display lists.
+ *
+ * @return void
+ *
+ * @see gl4java.awt.GLCanvas#paint
+ * @see gl4java.drawable.GLEventListener#init
+ */
+ public void init()
+ {
+ listeners.sendInitEvent(this);
+ }
+
+ /**
+ * This method is used to clean up any OpenGL stuff (delete textures
+ * or whatever) prior to actually deleting the OpenGL context.
+ * You should override this with your own version, if you need to do
+ * any cleanup work at this phase.
+ * This functions is called within cvsDispose
+ *
+ * @return void
+ *
+ * @see gl4java.awt.GLCanvas#cvsDispose
+ * @see gl4java.drawable.GLEventListener#cleanup
+ */
+ public void doCleanup()
+ {
+ listeners.sendCleanupEvent(this);
+ }
+
+ /**
+ * This function returns, if everything is init: the GLContext,
+ * the and the users init function
+ * This value is set in the paint method!
+ *
+ * @return boolean
+ *
+ * @see gl4java.awt.GLCanvas#paint
+ * @see gl4java.awt.GLCanvas#init
+ */
+ public boolean cvsIsInit()
+ {
+ if(glj!=null)
+ return glj.gljIsInit();
+ return false;
+ }
+
+ /**
+ * This function enables, disables the GL-Context !
+ * If false is given, the openGL renderer/context is
+ * disabled and disconected (gljFree is called, if initialized) !
+ *
+ * If disabled, all GL Functions are disabled but the
+ * Destroy & Free are not !
+ *
+ * @return boolean
+ *
+ * @see gl4java.awt.GLCanvas#cvsDispose
+ * @see gl4java.GLContext#setEnabled
+ * @see gl4java.GLContext#gljMakeCurrent
+ * @see gl4java.GLContext#gljDestroy
+ * @see gl4java.GLContext#gljFree
+ */
+ public void setGLEnabled(boolean b)
+ {
+ if(glj!=null)
+ glj.setEnabled(b);
+ }
+
+ /**
+ * This function enables, disables the GL-Context !
+ * If false is given, the openGL renderer/context is
+ * disabled and disconected (gljFree is called, if initialized) !
+ *
+ * If disabled, all GL Functions are disabled but the
+ * Destroy & Free are not !
+ *
+ * The Visible-Flag of this AWT Component is also set to the given value !
+ * The setVisible(boolean) method of Component is called !
+ *
+ * @return boolean
+ *
+ * @see gl4java.awt.GLCanvas#cvsDispose
+ * @see gl4java.GLContext#setEnabled
+ * @see gl4java.GLContext#gljMakeCurrent
+ * @see gl4java.GLContext#gljDestroy
+ * @see gl4java.GLContext#gljFree
+ */
+ public void setVisible(boolean b)
+ {
+ if(glj!=null)
+ glj.setEnabled(b);
+ super.setVisible(b);
+ }
+
+ /**
+ * This function queries, if the GL-Context is enabled !
+ *
+ * @return boolean
+ *
+ * @see gl4java.GLContext#isEnabled
+ * @see gl4java.GLContext#gljMakeCurrent
+ */
+ public boolean isGLEnabled()
+ {
+ if(glj!=null)
+ return glj.isEnabled();
+ return false;
+ }
+
+ protected long _f_dur = 0;
+
+ /**
+ *
+ * This is the thread save rendering-method called by paint.
+ * The actual thread will be set to highes priority befor calling
+ * 'display'. After 'display' the priority will be reset !
+ *
+ * 'gljFree' will be NOT called after 'display'.
+ *
+ * We tested the above to use multi-threading and
+ * for the demonstration 'glDemos' it works ;-)) !
+ *
+ * BE SURE, if you want to call 'display' by yourself
+ * (e.g. in the run method for animation)
+ * YOU HAVE TO CALL sDisplay -- OR YOU MUST KNOW WHAT YOU ARE DOING THEN !
+ *
+ * @return void
+ *
+ * @see gl4java.awt.GLCanvas#paint
+ * @see gl4java.awt.GLCanvas#display
+ */
+ public synchronized final void sDisplay()
+ {
+ long _s = System.currentTimeMillis();
+
+ display();
+
+ _f_dur = System.currentTimeMillis()-_s;
+ }
+
+ /**
+ *
+ * This is the rendering-method called by sDisplay
+ * (and sDisplay is called by paint !).
+ *
+ * <p>
+ * The default implementation of display() sends
+ * preDisplay, display and postDisplay events to
+ * all {@link gl4java.GLEventListener}s associated with this
+ * GLCanvas in the above order.
+ *
+ * <p>
+ * <pre>
+ reset timer for frame duration (done by sDisplay)
+
+ for_all(gl4java.GLEventListener)
+ SEND preDisplay
+
+ if( gljMakeCurrent() )
+ {
+ for_all(gl4java.GLEventListener)
+ SEND display
+ gljFree()
+ gljSwap()
+
+ for_all(gl4java.GLEventListener)
+ SEND postDisplay
+ }
+
+ stop timer for frame duration (done by sDisplay)
+ * </pre>
+ *
+ * <p>
+ * If you use the subclassing model (as opposed to the
+ * GLEventListener model), your subclass will redefine this to
+ * perform its OpenGL drawing. In this case you MUST encapsulate
+ * your OpenGL calls within:
+ * <pre>
+ - glj.gljMakeCurrent()
+ YOUR OpenGL commands here !
+ - glj.gljFree()
+ * </pre>
+ *
+ * BE SURE, if you want to call 'display' by yourself
+ * (e.g. in the run method for animation)
+ * YOU HAVE TO CALL sDisplay !
+ *
+ * 'sDisplay' manages a semaphore to avoid reentrance of
+ * the display function !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ *
+ * @return void
+ *
+ * @see gl4java.awt.GLCanvas#sDisplay
+ * @see gl4java.awt.GLCanvas#paint
+ * @see gl4java.GLContext#gljMakeCurrent
+ * @see gl4java.GLContext#gljSwap
+ * @see gl4java.drawable.GLEventListener#preDisplay
+ * @see gl4java.drawable.GLEventListener#display
+ * @see gl4java.drawable.GLEventListener#postDisplay
+ */
+ public void display()
+ {
+ if(!cvsIsInit())
+ {
+ return;
+ }
+
+ if( mustResize )
+ {
+ if (getAutoMakeContextCurrent() && getAWTThreadRenderingEnabled()) {
+ if( glj.gljMakeCurrent() == true )
+ {
+ size = getSize();
+ glj.gljResize( size.width, size.height ) ;
+ reshape(size.width, size.height);
+ mustResize = false;
+ invalidate();
+ repaint(100);
+ glj.gljFree();
+ }
+ } else if (getAutoMakeContextCurrent()) {
+ if( glj.gljMakeCurrent() == true )
+ {
+ size = getSize();
+ glj.gljResize( size.width, size.height ) ;
+ reshape(size.width, size.height);
+ mustResize = false;
+ invalidate();
+ repaint(100);
+ glj.gljFree();
+ }
+ } else if (getAWTThreadRenderingEnabled()) {
+ size = getSize();
+ glj.gljResize( size.width, size.height ) ;
+ reshape(size.width, size.height);
+ mustResize = false;
+ invalidate();
+ repaint(100);
+ } else {
+ size = getSize();
+ glj.gljResize( size.width, size.height ) ;
+ mustResize = false;
+ }
+ }
+
+ if (!getAWTThreadRenderingEnabled()) {
+ if (!initCalled) {
+ init();
+ initCalled = true;
+ }
+ }
+
+ listeners.sendPreDisplayEvent(this);
+
+ if (getAutoMakeContextCurrent()) {
+ if (glj.gljMakeCurrent()) {
+ listeners.sendDisplayEvent(this);
+
+ glj.gljSwap();
+ glj.gljCheckGL();
+ glj.gljFree();
+
+ listeners.sendPostDisplayEvent(this);
+ }
+ } else {
+ listeners.sendDisplayEvent(this);
+ glj.gljSwap();
+ glj.gljCheckGL();
+ listeners.sendPostDisplayEvent(this);
+ }
+ }
+
+ /**
+ *
+ * This �reshape� method will be invoked after the first paint command
+ * after GLCanvas.componentResize is called AND only if �gljMakeCurrent� was
+ * successful (so a call of gljMakeCurrent is redundant).
+ * �reshape� is not an overloading of java.awt.Component.reshape,
+ * �reshape� is more like �glut�-reshape.
+ *
+ * <p>
+ * GLCanvas.reshape already has a simple default implementation,
+ * which calls �gljResize� and �glViewport�. It also sends the
+ * reshape() event to all GLEventListeners. If using the
+ * GLEventListener model, it may not be necessary to do anything
+ * in your event listener's reshape() method; if using the
+ * subclassing model, it may not be necessary to override this.
+ *
+ * <p>
+ * The needed call to �gljResize� is done by the invoker paint !
+ *
+ * @param width the new width
+ * @param height the new height
+ * @return void
+ *
+ * @see gl4java.awt.GLCanvas#paint
+ * @see gl4java.awt.GLCanvas#sDisplay
+ * @see gl4java.drawable.GLEventListener#reshape
+ */
+ public void reshape( int width, int height )
+ {
+ gl.glViewport(0,0, width, height);
+ listeners.sendReshapeEvent(this, width, height);
+ }
+
+ /**
+ *
+ * �componentResized� is the componentListeners event handler.
+ *
+ * This method sets the variable �mustResize� to true,
+ * so the upcoming �paint� method-call will invoke �reshape� !
+ *
+ * This little look-alike complicating thing is done,
+ * to avoid an Exception by using the glContext from more than
+ * one concurrent thread�s !
+ *
+ * You cannot override this implementation, it is final
+ * - override �reshape' instead !
+ *
+ * @param e the element, which is resized
+ * @return void
+ *
+ * @see gl4java.awt.GLCanvas#paint
+ * @see gl4java.awt.GLCanvas#reshape
+ */
+ public void componentResized(ComponentEvent e)
+ {
+ if(glj!=null && glj.gljIsInit() && e.getComponent()==this )
+ {
+ mustResize = true;
+ repaint();
+ }
+ }
+
+ public void componentMoved(ComponentEvent e)
+ {
+ if(glj!=null && glj.gljIsInit())
+ {
+ repaint(100);
+ }
+ }
+
+ public void componentShown(ComponentEvent e)
+ {
+ }
+
+ public void componentHidden(ComponentEvent e)
+ { }
+
+ public void mouseClicked(MouseEvent e)
+ {
+ if(glj!=null && glj.gljIsInit())
+ {
+ repaint();
+ }
+ }
+
+ public void mouseEntered(MouseEvent e)
+ { }
+ public void mouseExited(MouseEvent e)
+ {}
+ public void mousePressed(MouseEvent e)
+ {
+ }
+ public void mouseReleased(MouseEvent e)
+ {
+ }
+
+ public void windowOpened(WindowEvent e)
+ {
+ }
+
+ /**
+ *
+ * �windowClosing� is the windowListeners event handler
+ * for the topLevelWindow of this Canvas !
+ *
+ * This methods free�s AND destroy�s
+ * the GL Context with �glj.gljDestroy� !
+ *
+ * @return void
+ *
+ */
+ public void windowClosing(WindowEvent e)
+ {
+ if(e.getComponent().equals(topLevelWindow))
+ {
+ cvsDispose();
+ }
+ }
+
+ /**
+ *
+ * �windowClosed� is the windowListeners event handler.
+ *
+ * @return void
+ *
+ */
+ public void windowClosed(WindowEvent e)
+ {
+ if (needCvsDispose) cvsDispose();
+ }
+
+ public void windowIconified(WindowEvent e)
+ {
+ }
+
+ public void windowDeiconified(WindowEvent e)
+ {
+ }
+
+ public void windowActivated(WindowEvent e)
+ {
+ if(glj!=null && glj.gljIsInit())
+ {
+ repaint(100);
+ }
+ }
+
+ public void windowDeactivated(WindowEvent e)
+ {
+ }
+
+ /**
+ * You should call this before releasing/dispose this Window !
+ * Also you can overwrite this class,
+ * to dispose your own elements, e.g. a Frame etc. -
+ * but be shure that you call
+ * cvsDispose implementation call this one !
+ *
+ * This function calls gljDestroy of GLContext !
+ * The Visibility is set to false !
+ * The Enabled is set to false either !
+ *
+ * To bring this component back to live,
+ * you need call setVisible(true) !
+ *
+ * @see gl4java.GLContext#gljDestroy
+ * @see gl4java.awt.GLCanvas#doCleanup
+ */
+ public void cvsDispose()
+ {
+ if(GLContext.gljClassDebug)
+ System.out.println("GLCanvas cvsDispose (doit="+
+ ( (glj != null) && glj.gljIsInit() ) +")");
+
+ removeComponentListener(this);
+ removeMouseListener(this);
+
+ if (glj != null)
+ {
+ if (glj.gljIsInit())
+ {
+ /* Sometimes the Microsoft VM calls the
+ Applet.stop() method but doesn't have
+ permissions to do J/Direct calls, so
+ this whole block of code will throw a
+ security exception. If this happens,
+ however, windowClosing() will still
+ call us again later and we will have
+ another opportunity to shut down the
+ context, so it all works out fine. */
+ try
+ {
+ setVisible(false);
+ doCleanup();
+
+ glj.gljDestroy();
+ needCvsDispose = false;
+ }
+ catch (Exception ex)
+ {
+ needCvsDispose = true;
+ }
+ }
+ }
+
+ // Setting glj to null will simply cause paint() to re-initialize.
+ // We don't want that to happen, so we will leave glj non-null.
+ }
+
+ /**
+ * does nothing than:
+ *
+ * @see gl4java.awt.GLCanvas#cvsDispose
+ */
+ protected void finalize()
+ throws Throwable
+ {
+ if(GLContext.gljClassDebug)
+ System.out.println("GLCanvas finalize ..");
+
+ cvsDispose();
+ super.finalize();
+ }
+
+ /**
+ * does nothing than:
+ *
+ * @see gl4java.awt.GLCanvas#cvsDispose
+ *
+ * @deprecated Use cvsDispose instead, well finalize is also implemented
+ */
+ public void destroy()
+ {
+ if(GLContext.gljClassDebug)
+ System.out.println("GLCanvas destroy ..");
+
+ cvsDispose();
+ }
+
+ /**
+ * get methods
+ */
+ public final int cvsGetWidth() {
+ return getSize().width;
+ }
+ public final int cvsGetHeight() {
+ return getSize().height;
+ }
+
+ //----------------------------------------------------------------------
+ // Implementation of GLDrawable
+ //
+
+ public void addGLEventListener(GLEventListener listener) {
+ listeners.add(listener);
+ }
+
+ public void removeGLEventListener(GLEventListener listener) {
+ listeners.remove(listener);
+ }
+
+ public EventListener[] getListeners(Class listenerType)
+ throws ClassCastException
+ {
+ EventListener[] evtlst=null;
+ Class _GLEventListener = null;
+
+ try {
+ _GLEventListener = Class.forName("gl4java.drawable.GLEventListener");
+ } catch (Exception ex) {
+ System.out.println(ex);
+ }
+
+ if (_GLEventListener!=null &&
+ listenerType.isAssignableFrom(_GLEventListener) )
+ evtlst = listeners.getListeners();
+
+ EventListener[] t_evtlst = super.getListeners(listenerType);
+
+ if(t_evtlst==null || t_evtlst.length==0)
+ return evtlst;
+
+ if(evtlst==null || evtlst.length==0)
+ return t_evtlst;
+
+ EventListener[] n_evtlst =
+ new EventListener[t_evtlst.length+evtlst.length];
+
+ try {
+ System.arraycopy(evtlst, 0, n_evtlst, 0, evtlst.length);
+ System.arraycopy(t_evtlst, 0, n_evtlst, evtlst.length, t_evtlst.length);
+ } catch (Exception ex)
+ { System.out.println(ex); }
+
+ evtlst = null;
+ t_evtlst = null;
+
+ return n_evtlst;
+ }
+
+ public GLFunc getGL() {
+ return gl;
+ }
+
+ public GLUFunc getGLU() {
+ return glu;
+ }
+}