aboutsummaryrefslogtreecommitdiffstats
path: root/gl4java
diff options
context:
space:
mode:
Diffstat (limited to 'gl4java')
-rw-r--r--gl4java/GLContext.java.skel237
-rw-r--r--gl4java/GLRunnable.java129
-rw-r--r--gl4java/applet/SimpleGLAnimApplet1.java41
-rw-r--r--gl4java/awt/GLAnimCanvas.java149
-rw-r--r--gl4java/awt/GLCanvas.java180
-rw-r--r--gl4java/drawable/GLDrawable.java55
6 files changed, 524 insertions, 267 deletions
diff --git a/gl4java/GLContext.java.skel b/gl4java/GLContext.java.skel
index f5518a1..eac6bc5 100644
--- a/gl4java/GLContext.java.skel
+++ b/gl4java/GLContext.java.skel
@@ -249,7 +249,7 @@ public class GLContext extends Object
*
* Each <Value> is dezimal !
*/
- public final static String version = __SED_CLASS_VERSION__ ;
+ public final static String version = __SED_CLASS_VERSION__ ;
/**
* Flag's to enable/disable verbose Information.
@@ -393,6 +393,8 @@ public class GLContext extends Object
*/
protected Component _compHeavy = null;
+ protected Thread awtThread = null;
+
/**
* Variable to tell is where windows or not (X11)
* Usally X11 ;-))
@@ -1143,6 +1145,11 @@ public class GLContext extends Object
} else
System.out.println("got empty Component");
+ awtThread = Thread.currentThread();
+
+ if(gljThreadDebug)
+ System.out.println("GLContext: locked awt-Thread: "+awtThread);
+
if(_comp!=null && _gr!=null)
{
int i = 0;
@@ -1169,6 +1176,7 @@ public class GLContext extends Object
System.out.println("GLContext GLContext() failed");
}
}
+
/**
*
* Constructor
@@ -2187,11 +2195,75 @@ public class GLContext extends Object
/**
*
+ * gljIsCurrent checks
+ * if the current Thread holds the GL context of this
+ * GLContext instance !
+ *
+ * @return boolean
+ *
+ * @see gl4java.GLContext#gljIsRequested
+ * @see gl4java.GLContext#gljMakeCurrent
+ * @see gl4java.GLContext#getNativeGLContext
+ * @see gl4java.GLContext#gljGetCurrentContext
+ */
+ public synchronized final boolean gljIsCurrent()
+ {
+ if ( ! isInitialized || !glEnabled )
+ return false;
+
+ Thread thisThread = Thread.currentThread();
+
+ if (ctxThread!=null && ctxThread==thisThread && glContext==gljGetCurrentContext())
+ return true;
+
+ return false;
+ }
+
+ /**
+ *
+ * gljIsRequested checks
+ * if the this GLContext instance's native context
+ * is requested by another thread !
+ *
+ * @return boolean
+ *
+ * @see gl4java.GLContext#gljIsCurrent
+ * @see gl4java.GLContext#gljMakeCurrent
+ * @see gl4java.GLContext#getNativeGLContext
+ * @see gl4java.GLContext#gljGetCurrentContext
+ */
+ public synchronized final boolean gljIsRequested()
+ {
+ if ( ! isInitialized || !glEnabled )
+ return false;
+
+ Thread thisThread = Thread.currentThread();
+
+ if (nextThread!=null && nextThread!=thisThread)
+ return true;
+
+ return false;
+ }
+
+ /**
+ *
* gljMakeCurrent checks whether GL4Java is initializes
* AND makes the GL-Context current for this thread.
*
* <p>
*
+ * This functions now optimizes the context-switch !
+ *
+ * The context is changed, only if :
+ * <pre>
+ - another thread has requested this context -> release it
+ this gives the other thread a chance to get it ..
+
+ - this thread does not own the current context
+ * </pre>
+ *
+ * <p>
+ *
* You MUST encapsulate your OpenGL call's within:
* <pre>
- gljMakeCurrent()
@@ -2234,8 +2306,12 @@ public class GLContext extends Object
* that the same thread enters this point twice,
* before calling gljFree !
*/
- if (ctxThread!=null && ctxThread==thisThread)
- gljFree();
+ if(gljThreadDebug && !dbgPrinted)
+ {
+ System.out.println("wait-current: "+thisThread+" for earmarked: "+nextThread);
+ System.out.println("\tfreeing context force .. ctxThread="+ctxThread);
+ }
+ gljFree(true); // force freeing the context
try {
// wait till earmarked nextThread has its chance ..
@@ -2262,6 +2338,19 @@ public class GLContext extends Object
System.out.println("\tctxThread="+ctxThread+", next="+nextThread);
dbgPrinted=true;
}
+ if( _comp instanceof GLRunnable )
+ {
+ if ( ((GLRunnable)_comp).ownsThread(ctxThread) )
+ {
+ synchronized (_comp) {
+ ((GLRunnable)_comp).freeGLContext();
+ ((GLRunnable)_comp).notifyAll();
+ }
+ notifyAll();
+ if(gljThreadDebug)
+ System.out.println("\tfreeGLContext -> "+ctxThread);
+ }
+ }
try {
// wait for gljFree to release the GLXContext
@@ -2269,16 +2358,27 @@ public class GLContext extends Object
} catch (InterruptedException e) { }
}
+ boolean result = false;
+
+ /* is this thread allready owning the context ? */
+ if ( ctxThread==thisThread )
+ {
+ result = lockJAWT(_comp, windowHandle, gljThreadDebug);
+ if(gljThreadDebug)
+ System.out.println("MakeCurrent: "+thisThread+" no CTX change, allready own, lockJAWT: "+result);
+ return result;
+ }
+
ctxThread = thisThread ; // blocking asap ..
if(gljThreadDebug)
{
if(nextThread==thisThread)
{
- System.out.println(thisThread+" <EarMarked Run>");
+ System.out.println("MakeCurrent: "+thisThread+" <EarMarked Run>");
System.out.println("\tctxThread="+ctxThread+", next:=NULL");
} else {
- System.out.println(thisThread);
+ System.out.println("MakeCurrent: "+thisThread);
System.out.println("\tctxThread="+ctxThread+", next="+nextThread);
}
}
@@ -2289,8 +2389,8 @@ public class GLContext extends Object
if(nextThread==thisThread)
nextThread = null;
- boolean result = gljMakeCurrentNative( _comp, displayHandle,
- windowHandle, glContext);
+ result = gljMakeCurrentNative( _comp, displayHandle,
+ windowHandle, glContext);
/**
* If glXMakeCurrent failed, nobody holds this GLXContext ..
@@ -2346,17 +2446,24 @@ public class GLContext extends Object
*
* @deprecated The argument freeContextFirst is obsolete !
*/
- public synchronized final boolean gljMakeCurrent(boolean freeContextFirst)
+ public final boolean gljMakeCurrent(boolean freeContextFirst)
{
return gljMakeCurrent();
}
+ /**
+ * if using JAWT, this function handles the JAWT lock also
+ */
private final static native boolean gljMakeCurrentNative(
Component canvas,
long disp,
long thisWin,
long glContext);
+ private final static native boolean lockJAWT(
+ Component canvas,
+ long thisWin, boolean verbose);
+
/**
*
* gljGetCurrentContext fetches the current native
@@ -2364,7 +2471,7 @@ public class GLContext extends Object
*
* @return int
*/
- public final static native int gljGetCurrentContext();
+ public final static native long gljGetCurrentContext();
/**
*
@@ -2421,64 +2528,106 @@ public class GLContext extends Object
*
* This MUST be called at last in your display function !
*
- * @return void
+ * <p>
+ *
+ * This functions now optimizes the context-switch !
+ *
+ * The context is changed, only if :
+ * <pre>
+ - another thread has requested this context -> release it
+ * </pre>
+ *
+ * <p>
+ *
+ * @return boolean
*
+ * @see gl4java.GLContext#gljFree
+ * @see gl4java.GLContext#gljIsCurrent
+ * @see gl4java.GLContext#gljIsRequested
* @see gl4java.GLContext#gljMakeCurrent
* @see gl4java.GLContext#gljSwap
* @see gl4java.awt.GLCanvas#display
* @see gl4java.awt.GLCanvas#sDisplay
*/
- public synchronized final boolean gljFree()
+ public final boolean gljFree()
+ {
+ return gljFree(false);
+ }
+
+ /**
+ *
+ * gljFree free�s the GL Context
+ *
+ * This MUST be called at last in your display function !
+ *
+ * <p>
+ *
+ * This functions now optimizes the context-switch !
+ *
+ * The context is changed, only if one of the following is true:
+ * <pre>
+ - another thread has requested this context
+ - the force flag is true
+ - this thread is the AWT thread
+ - the component of this context does _not_ implement GLRunnable
+ * </pre>
+ *
+ * <p>
+ *
+ * @return boolean
+ *
+ * @see gl4java.GLContext#gljIsCurrent
+ * @see gl4java.GLContext#gljIsRequested
+ * @see gl4java.GLContext#gljMakeCurrent
+ * @see gl4java.GLContext#gljSwap
+ * @see gl4java.GLRunnable#run
+ */
+ public synchronized final boolean gljFree(boolean force)
{
if ( ! isInitialized ) return false;
+ boolean result = true;
Thread thisThread = Thread.currentThread();
- boolean dbgPrinted = false;
- /**
- * I do skip a lock for the gljFree semantics,
- * because:
- * - to minimize a deadlock
- * - believing that gljFree is semantically the last call ;-)
- * - see above -> redundant
- while (ctxThread!=null && ctxThread!=thisThread)
- {
- if(gljThreadDebug && !dbgPrinted)
- {
- System.out.println("* wait: "+thisThread);
- System.out.println("\tctxThread="+ctxThread+", next="+nextThread);
- dbgPrinted=true;
- }
-
- try {
- // wait for gljMakeCurrent to lock the GLXContext
- wait();
- } catch (InterruptedException e) { }
- }
+ if( thisThread == awtThread || (_comp instanceof GLRunnable) == false)
+ force=true;
- if(gljThreadDebug)
- {
- System.out.println("*: "+thisThread);
- System.out.println("\tctxThread="+ctxThread+", next="+nextThread);
- }
+ /**
+ * only free the context, if another thread does
+ * request this context ...
+ * or the force-flag is true
*/
-
-
- boolean result =
- gljFreeNative ( _comp, displayHandle,
+ if ( force==true ||
+ ( nextThread!=null && nextThread!=thisThread && ctxThread==thisThread )
+ )
+ {
+ result = gljFreeNative ( _comp, displayHandle,
windowHandle,
glContext);
- ctxThread = null ;
- notifyAll();
+ ctxThread = null ;
+ notifyAll();
+ if(gljThreadDebug)
+ System.out.println("gljFree: "+thisThread+" gljFreeNative result: "+result);
+ } else {
+ result = unlockJAWT(windowHandle, false);
+ notifyAll();
+ if(gljThreadDebug)
+ System.out.println("gljFree: "+thisThread+" no CTX change, no requests, unlockJAWT: "+result);
+ }
return result;
}
- private final static native boolean gljFreeNative( Component canvas,
+ /**
+ * if using JAWT, this function handles the JAWT unlock also
+ */
+ private final static native boolean gljFreeNative( Component canvas,
long disp,
long thisWin,
long glContext );
+ private final static native boolean unlockJAWT(long thisWin, boolean verbose);
+
/**
* swap method are for double buffering
*/
diff --git a/gl4java/GLRunnable.java b/gl4java/GLRunnable.java
new file mode 100644
index 0000000..ca66af5
--- /dev/null
+++ b/gl4java/GLRunnable.java
@@ -0,0 +1,129 @@
+/**
+ * @(#) GLRunnable.java
+ */
+package gl4java;
+
+import java.lang.*;
+
+/**
+ * This is the interface for a threaded renderer (animator thread).
+ *
+ * If an animation class, e.g. {@link gl4java.awt.GLAnimCanvas},
+ * implements {@link gl4java.drawable.GLDrawable} and this interface,
+ * you will benefit from the new context handling {@link gl4java.GLContext#gljFree}.
+ *
+ * @see gl4java.GLContext
+ * @see gl4java.drawable.GLDrawable
+ * @see gl4java.awt.GLAnimCanvas
+ */
+public interface GLRunnable extends Runnable
+{
+ /**
+ * This creates and start one singleton unique thread !
+ */
+ public void start();
+
+ /**
+ * This stops and destroys (deferred) our singleton unique thread !
+ */
+ public void stop();
+
+ /**
+ * Identifies this object with the given thread ..
+ * If this object owns this thread, it must return true !
+ */
+ public boolean ownsThread(Thread thread);
+
+ /**
+ * The running loop for animations
+ * which initiates the call of display
+ *
+ * Be sure to force freeing the GL context
+ * with {@link gl4java.GLContext#gljFree}(true), if:
+ * <pre>
+ - you exit this run loop
+ - you suspend your thread -> wait
+ - you kill your thread ..
+ * </pre>
+ *
+ * Also be sure, to implement this Runnable as Java2 does recomends !
+ * Look at the example implementation {@link gl4java.awt.GLAnimCanvas#run} !
+ *
+ * @see gl4java.awt.GLAnimCanvas#run
+ * @see #setSuspended
+ */
+ public void run();
+
+ /**
+ * 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 #isAlive
+ * @see #start
+ */
+ public void setSuspended(boolean suspend);
+
+ /**
+ * 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 #ReInit
+ * @see #isAlive
+ * @see #start
+ * @see #run
+ */
+ public void setSuspended(boolean suspend, boolean reInit);
+
+ /**
+ * is the thread alive, means is started and not died ?
+ *
+ * @see #run
+ * @see #setSuspended
+ * @see #start
+ * @see #stop
+ */
+ public boolean isAlive();
+
+ /**
+ * is the thread suspended, means is started but waiting,
+ * or not alive (ok :-| - but it is practical)
+ *
+ * @see #run
+ * @see #setSuspended
+ * @see #start
+ * @see #stop
+ */
+ public boolean isSuspended();
+
+ /**
+ * ReInit should be overwritten by you,
+ * to enter your re-initialisation within setSuspended(false)
+ *
+ * @see #setSuspended
+ */
+ public void ReInit();
+
+ /**
+ * Forces this thread to release it's GLContext !
+ *
+ * To ensure this, this thread enables itself,
+ * and calls gljFree(true) to force the release !
+ *
+ * @see #setSuspended
+ * @see #run
+ */
+ public void freeGLContext();
+}
diff --git a/gl4java/applet/SimpleGLAnimApplet1.java b/gl4java/applet/SimpleGLAnimApplet1.java
index 84ef869..08b85d5 100644
--- a/gl4java/applet/SimpleGLAnimApplet1.java
+++ b/gl4java/applet/SimpleGLAnimApplet1.java
@@ -26,6 +26,7 @@ public class SimpleGLAnimApplet1 extends Applet
public TextField textFps = null;
public Checkbox checkUseRepaint = null;
public Checkbox checkUseFpsSleep = null;
+ public Checkbox checkUseYield = null;
public Button buttonReStart = null;
@@ -38,17 +39,11 @@ public class SimpleGLAnimApplet1 extends Applet
setLayout(new BorderLayout());
Panel pan = new Panel();
- pan.setLayout(new GridLayout(2,3));
+ pan.setLayout(new GridLayout(2,4));
buttonInfo = new Button("GL4Java");
pan.add(buttonInfo);
- checkUseRepaint = new Checkbox("repaint", true);
- pan.add(checkUseRepaint);
-
- checkUseFpsSleep = new Checkbox("fps-sleep", true);
- pan.add(checkUseFpsSleep);
-
buttonReStart = new Button("start/stop");
pan.add(buttonReStart);
@@ -58,20 +53,37 @@ public class SimpleGLAnimApplet1 extends Applet
textFps=new TextField("0000000000");
pan.add(textFps);
+ checkUseRepaint = new Checkbox("repaint", true);
+ pan.add(checkUseRepaint);
+
+ checkUseFpsSleep = new Checkbox("fps-sleep", true);
+ pan.add(checkUseFpsSleep);
+
+ checkUseYield = new Checkbox("yield", true);
+ pan.add(checkUseYield);
+
add("South",pan);
}
+ public void setCheckButtons()
+ {
+ checkUseFpsSleep.setState(canvas.getUseFpsSleep());
+ checkUseRepaint.setState(canvas.getUseRepaint());
+ checkUseYield.setState(canvas.getUseYield());
+ }
+
public void start()
{
if(GLContext.gljClassDebug)
System.out.println("SGLApplet start ..");
- checkUseFpsSleep.setState(canvas.getUseFpsSleep());
- checkUseRepaint.setState(canvas.getUseRepaint());
+ setCheckButtons();
+
buttonInfo.addMouseListener(this);
checkUseRepaint.addItemListener(this);
checkUseFpsSleep.addItemListener(this);
+ checkUseYield.addItemListener(this);
buttonReStart.addMouseListener(this);
buttonFps.addMouseListener(this);
canvas.addMouseListener(this);
@@ -90,6 +102,7 @@ public class SimpleGLAnimApplet1 extends Applet
buttonInfo.removeMouseListener(this);
checkUseRepaint.removeItemListener(this);
checkUseFpsSleep.removeItemListener(this);
+ checkUseYield.removeItemListener(this);
buttonReStart.removeMouseListener(this);
buttonFps.removeMouseListener(this);
canvas.removeMouseListener(this);
@@ -237,6 +250,16 @@ public class SimpleGLAnimApplet1 extends Applet
checkUseFpsSleep.getState());
}
}
+ if( comp.equals(checkUseYield ) )
+ {
+ if(canvas!=null)
+ {
+ canvas.setUseYield(checkUseYield.getState());
+ System.out.println("canvas uses Yield "+
+ checkUseYield.getState());
+ }
+ }
+ setCheckButtons();
}
public void actionPerformed(ActionEvent event)
diff --git a/gl4java/awt/GLAnimCanvas.java b/gl4java/awt/GLAnimCanvas.java
index b16206c..9268db8 100644
--- a/gl4java/awt/GLAnimCanvas.java
+++ b/gl4java/awt/GLAnimCanvas.java
@@ -131,7 +131,7 @@ import java.lang.Math;
*
*/
public class GLAnimCanvas extends GLCanvas
- implements Runnable
+ implements GLRunnable
{
/**
* To support frames per scounds,
@@ -173,7 +173,7 @@ public class GLAnimCanvas extends GLCanvas
protected boolean threadSuspended = false;
static {
- if(GLContext.loadNativeLibraries(null, null, null)==false)
+ if(GLContext.doLoadNativeLibraries(null, null, null)==false)
System.out.println("GLAnimCanvas could not load def. native libs.");
}
@@ -286,14 +286,12 @@ public class GLAnimCanvas extends GLCanvas
{
}
- protected boolean useRepaint = true;
+ protected boolean useRepaint = false;
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.
@@ -310,7 +308,7 @@ public class GLAnimCanvas extends GLCanvas
* @see gl4java.awt.GLCanvas#sDisplay
* @see gl4java.awt.GLAnimCanvas#setUseFpsSleep
*/
- public void setUseRepaint(boolean b)
+ public synchronized void setUseRepaint(boolean b)
{
useRepaint = b;
}
@@ -327,7 +325,7 @@ public class GLAnimCanvas extends GLCanvas
* @see gl4java.awt.GLCanvas#sDisplay
* @see gl4java.awt.GLAnimCanvas#setUseRepaint
*/
- public void setUseFpsSleep(boolean b)
+ public synchronized void setUseFpsSleep(boolean b)
{
useFpsSleep = b;
}
@@ -338,13 +336,6 @@ public class GLAnimCanvas extends GLCanvas
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;
@@ -360,15 +351,19 @@ public class GLAnimCanvas extends GLCanvas
return useYield;
}
- public boolean getUseSDisplay()
- {
- return useSDisplay;
- }
+ /**
+ * Identifies this object with the given thread ..
+ * If this object owns this thread, it must return true !
+ */
+ public boolean ownsThread(Thread thread)
+ {
+ return killme!=null && killme==thread ;
+ }
- /**
- * HERE WE DO HAVE OUR RUNNING THREAD !
- * WE NEED STUFF LIKE THAT FOR ANIMATION ;-)
- */
+ /**
+ * HERE WE DO HAVE OUR RUNNING THREAD !
+ * WE NEED STUFF LIKE THAT FOR ANIMATION ;-)
+ */
public void start()
{
if(killme == null)
@@ -409,6 +404,7 @@ public class GLAnimCanvas extends GLCanvas
protected boolean shallWeRender = true;
protected boolean isRunning = false;
+ protected boolean forceGLFree = false;
private long _fDelay = 0;
private long _fDelay_Frames = 10;
@@ -416,6 +412,20 @@ public class GLAnimCanvas extends GLCanvas
private boolean _fDelayRun=false;
/**
+ * Forcec this thread to release it's GLContext !
+ *
+ * To ensure this, this thread enables itself,
+ * and calls gljFree(true) to force the release !
+ *
+ * @see gl4java.awt.GLAnimCanvas#run
+ * @see gl4java.GLContext#gljMakeCurrent
+ */
+ public void freeGLContext()
+ {
+ forceGLFree=true;
+ }
+
+ /**
* The running loop for animations
* which initiates the call of display
*
@@ -428,10 +438,7 @@ public class GLAnimCanvas extends GLCanvas
isRunning = true;
- boolean firstRender = true;
-
int numInitRetries = 1;
- int numMakeCurrentRetries = 1;
synchronized (this) {
globalThreadNumber++;
@@ -441,56 +448,54 @@ public class GLAnimCanvas extends GLCanvas
{
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++;
+ // if another thread want's to do use do ..
+ if(forceGLFree)
+ {
+ glj.gljFree(true);
+ forceGLFree=false;
+ if(GLContext.gljThreadDebug)
+ System.out.println("GLAnimCanvas: forceGLFree(1) - gljFree");
+ }
+ else if (shallWeRender)
+ {
+ /* DRAW THE TINGS .. */
+ if(useRepaint)
+ repaint();
+ else
+ sDisplay();
+
+ if(fps_isCounting)
+ fps_frames++;
+
+ } else {
+ synchronized (this) {
+ glj.gljFree(true);
+ threadSuspended=true;
+ }
+ }
} else {
- System.err.println("Waiting for canvas to initialize (" +
- numInitRetries + ")...");
- ++numInitRetries;
+ if(GLContext.gljThreadDebug)
+ {
+ System.err.println("Waiting for canvas to initialize (" +
+ numInitRetries + ")...");
+ }
+ ++numInitRetries;
try {
Thread.currentThread().sleep(100);
} catch (Exception e) {
}
}
+ // if another thread want's to do use do ..
+ if(forceGLFree)
+ {
+ glj.gljFree(true);
+ forceGLFree=false;
+ if(GLContext.gljThreadDebug)
+ System.out.println("GLAnimCanvas: forceGLFree(2) - gljFree");
+ }
+
try {
if(useFpsSleep)
{
@@ -516,6 +521,7 @@ public class GLAnimCanvas extends GLCanvas
}
if (threadSuspended) {
+ glj.gljFree(true);
stopFpsCounter();
synchronized (this) {
while (threadSuspended)
@@ -526,10 +532,8 @@ public class GLAnimCanvas extends GLCanvas
{}
}
- if (getAutoMakeContextCurrent()) {
- if(glj!=null)
- glj.gljFree(); // just to be sure ..
- }
+ if(glj!=null)
+ glj.gljFree(true); // just to be sure .. force freeing the context
synchronized (this) {
globalThreadNumber--;
@@ -550,7 +554,7 @@ public class GLAnimCanvas extends GLCanvas
* @see gl4java.awt.GLAnimCanvas#isAlive
* @see gl4java.awt.GLAnimCanvas#start
*/
- public void setSuspended(boolean suspend)
+ public synchronized void setSuspended(boolean suspend)
{
setSuspended(suspend, false);
}
@@ -567,6 +571,7 @@ public class GLAnimCanvas extends GLCanvas
* @param reInit if true the ReInit will be called additionally,
* where the user can set additional initialisations
*
+ * @see gl4java.awt.GLAnimCanvas#ReInit
* @see gl4java.awt.GLAnimCanvas#isAlive
* @see gl4java.awt.GLAnimCanvas#start
* @see gl4java.awt.GLAnimCanvas#run
diff --git a/gl4java/awt/GLCanvas.java b/gl4java/awt/GLCanvas.java
index a7ade2a..041fabb 100644
--- a/gl4java/awt/GLCanvas.java
+++ b/gl4java/awt/GLCanvas.java
@@ -173,24 +173,6 @@ public class GLCanvas extends Canvas
// 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.");
@@ -403,61 +385,6 @@ public class GLCanvas extends Canvas
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 setOptimizeContextHandling(boolean yesOrNo) {
- setAWTThreadRenderingEnabled(yesOrNo);
- setAutoMakeContextCurrent(yesOrNo);
- }
-
- public boolean getOptimizeContextHandling() {
- return getAWTThreadRenderingEnabled() || getAutoMakeContextCurrent();
- }
-
/**
* this function overrides the Canvas paint method !
*
@@ -482,7 +409,7 @@ public class GLCanvas extends Canvas
* @see gl4java.awt.GLCanvas#preInit
* @see gl4java.awt.GLCanvas#init
*/
- public synchronized final void paint( Graphics g )
+ public final void paint( Graphics g )
{
if(glj == null || ( !glj.gljIsInit() && isGLEnabled() ) )
{
@@ -521,10 +448,7 @@ public class GLCanvas extends Canvas
(float)col.getGreen()/255.0f,
(float)col.getBlue()/255.0f, 0.0f);
- if (getAWTThreadRenderingEnabled()) {
- init();
- initCalled = true;
- }
+ init();
// fetch the top-level window ,
// to add us as the windowListener
@@ -560,14 +484,9 @@ public class GLCanvas extends Canvas
/* force a reshape, to be sure .. */
mustResize = true;
-
- // Free up the OpenGL context for another thread to use
- glj.gljFree();
}
- if (getAWTThreadRenderingEnabled()) {
- sDisplay();
- }
+ sDisplay();
}
/**
@@ -711,15 +630,14 @@ public class GLCanvas extends Canvas
protected long _f_dur = 0;
/**
+ * Return the uses milli secounds of the last frame
+ */
+ public long getLastFrameMillis()
+ { return _f_dur; }
+
+ /**
*
* 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)
@@ -730,11 +648,35 @@ public class GLCanvas extends Canvas
* @see gl4java.awt.GLCanvas#paint
* @see gl4java.awt.GLCanvas#display
*/
- public synchronized final void sDisplay()
+ public 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(true); /* force freeing the context here .. */
+ }
+ }
+
long _s = System.currentTimeMillis();
- display();
+ if(ok)
+ {
+ display();
+ }
_f_dur = System.currentTimeMillis()-_s;
}
@@ -747,7 +689,7 @@ public class GLCanvas extends Canvas
* <p>
* The default implementation of display() sends
* preDisplay, display and postDisplay events to
- * all {@link gl4java.GLEventListener}s associated with this
+ * all {@link gl4java.drawable.GLEventListener}s associated with this
* GLCanvas in the above order.
*
* <p>
@@ -761,8 +703,8 @@ public class GLCanvas extends Canvas
{
for_all(gl4java.GLEventListener)
SEND display
- gljFree()
gljSwap()
+ gljFree()
for_all(gl4java.GLEventListener)
SEND postDisplay
@@ -801,49 +743,9 @@ public class GLCanvas extends Canvas
*/
public void display()
{
- if(!cvsIsInit())
- {
- return;
- }
-
- if( mustResize )
- {
- 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 {
- size = getSize();
- glj.gljResize( size.width, size.height ) ;
- if (getAWTThreadRenderingEnabled()) {
- reshape(size.width, size.height);
- }
- mustResize = false;
- if (getAWTThreadRenderingEnabled()) {
- invalidate();
- repaint(100);
- }
- }
- }
-
- if (!getAWTThreadRenderingEnabled()) {
- if (!initCalled) {
- init();
- initCalled = true;
- }
- }
-
listeners.sendPreDisplayEvent(this);
- if (getAutoMakeContextCurrent()) {
- if (glj.gljMakeCurrent()) {
+ if (glj.gljMakeCurrent()) {
listeners.sendDisplayEvent(this);
glj.gljSwap();
@@ -851,12 +753,6 @@ public class GLCanvas extends Canvas
glj.gljFree();
listeners.sendPostDisplayEvent(this);
- }
- } else {
- listeners.sendDisplayEvent(this);
- glj.gljSwap();
- glj.gljCheckGL();
- listeners.sendPostDisplayEvent(this);
}
}
diff --git a/gl4java/drawable/GLDrawable.java b/gl4java/drawable/GLDrawable.java
index a0818c0..55c1311 100644
--- a/gl4java/drawable/GLDrawable.java
+++ b/gl4java/drawable/GLDrawable.java
@@ -31,6 +31,61 @@ public interface GLDrawable
public GLContext getGLContext();
/**
+ *
+ * This is the rendering-method called by
+ * e.g.: {@link gl4java.awt.GLCanvas#display} or by
+ * {@link gl4java.GLThread#run}.
+ *
+ * <p>
+ * The default implementation of display() sends
+ * preDisplay, display and postDisplay events to
+ * all {@link gl4java.drawable.GLEventListener}s associated with this
+ * GLDrawable in the above order.
+ *
+ * <p>
+ * <pre>
+ reset timer for frame duration
+
+ for_all(gl4java.drawable.GLEventListener)
+ SEND preDisplay
+
+ if( gljMakeCurrent() )
+ {
+ for_all(gl4java.drawable.GLEventListener)
+ SEND display
+ gljSwap()
+ gljFree()
+
+ for_all(gl4java.drawable.GLEventListener)
+ SEND postDisplay
+ }
+
+ stop timer for frame duration
+ * </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>
+ *
+ * @return void
+ *
+ * @see gl4java.GLContext#gljMakeCurrent
+ * @see gl4java.GLContext#gljFree
+ * @see gl4java.GLContext#gljSwap
+ * @see gl4java.drawable.GLEventListener#preDisplay
+ * @see gl4java.drawable.GLEventListener#display
+ * @see gl4java.drawable.GLEventListener#postDisplay
+ */
+ public void display();
+
+ /**
* the components listener's should be implemented also !
* since JDK 1.1
*/