diff options
author | Sven Gothel <[email protected]> | 2014-10-08 08:16:10 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2014-10-08 22:30:48 +0200 |
commit | c7ac21e7d25e5271f600806c93e3bd870d45bce3 (patch) | |
tree | ff4c930c68c507c44ce0ef6bae413c96c344c26b | |
parent | 054de091f39a9d4e32a559e476247d7f8512d904 (diff) |
Bug 1088: Add GLRendererQuirks.NeedSharedObjectSync; Tests: Synchronize GL objects if GLRendererQuirks.NeedSharedObjectSync is set.
GLSharedContextSetter#synchronization GL Object Synchronization
Usually synchronization of shared GL objects should not be required,
if the shared GL objects are created and immutable before concurrent usage.
However, using drivers exposing GLRendererQuirks.NeedSharedObjectSync
always require the user to synchronize access of shared GL objects.
Synchronization can be avoided if accessing the shared GL objects
exclusively via a queue or com.jogamp.common.util.Ringbuffer,
see GLMediaPlayerImpl as an example.
+++
GLRendererQuirks.NeedSharedObjectSync is set for all OSX versions
+++
Handle GLRendererQuirks.NeedSharedObjectSync in user code!
+++
All shared context tests passed on OSX 10.9.5,
and GNU/Linux w/ Nvidia + Mesa/AMD driver.
Conflicts:
src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java
9 files changed, 154 insertions, 36 deletions
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh index 2d05c2110..0d8fe8d4f 100644 --- a/make/scripts/tests.sh +++ b/make/scripts/tests.sh @@ -88,7 +88,7 @@ function jrun() { swton=$1 shift - #D_ARGS="-Djogl.debug.DebugGL" + D_ARGS="-Djogl.debug.DebugGL" #D_ARGS="-Djogl.debug.TraceGL" #D_ARGS="-Djogl.debug.DebugGL -Djogl.debug.TraceGL" #D_ARGS="-Djogl.debug.DebugGL -Djogl.debug.TraceGL -Dnativewindow.debug=all -Djogl.debug=all -Dnewt.debug=all" @@ -96,6 +96,7 @@ function jrun() { #D_ARGS="-Djogamp.debug=all" #D_ARGS="-Dnativewindow.debug=all" #D_ARGS="-Djogl.debug=all" + #D_ARGS="-Djogl.debug=all -Dnewt.debug=all -Djogl.debug.DebugGL" #D_ARGS="-Dnewt.debug=all" #D_ARGS="-Djogl.debug=all -Dnewt.debug=all" #D_ARGS="-Djogl.debug=all -Dnativewindow.debug=all" @@ -381,7 +382,7 @@ function testawtswt() { #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestMainVersionGLWindowNEWT $* #testawt com.jogamp.opengl.test.junit.jogl.acore.TestMainVersionGLCanvasAWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile00NEWT $* -testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile01NEWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile01NEWT $* #testawt com.jogamp.opengl.test.junit.jogl.acore.TestVersionSemanticsNOUI $* # @@ -502,8 +503,11 @@ testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile01NEWT $* #testawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2AWT3 $* #testawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2AWT3b $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT0 $* -#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT1 $* +testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT1 $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT2 $* + +#testnoawt com.jogamp.opengl.test.junit.graph.demos.GPUUISceneNewtDemo $* + #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT3 $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT4 $* #testswt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2SWT3 $* diff --git a/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java b/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java index 828aca78c..a7749e100 100644 --- a/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java +++ b/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java @@ -363,11 +363,43 @@ public class GLRendererQuirks { */ public static final int NoPBufferWithAccum = 19; + /** + * Need GL objects (VBO, ..) to be synchronized when utilized + * concurrently from multiple threads via a shared GL context, + * otherwise driver crashes the VM. + * <p> + * Usually synchronization should not be required, if the shared GL objects + * are created and immutable before concurrent usage.<br> + * However, using drivers exposing this issue always require the user to + * synchronize access of shared GL objects. + * </p> + * <p> + * Synchronization can be avoided if accessing the shared GL objects + * exclusively via a queue or {@link com.jogamp.common.util.Ringbuffer Ringbuffer}, see GLMediaPlayerImpl as an example. + * </p> + * <p> + * Appears on: + * <ul> + * <li>Platform OSX + * <ul> + * <li>detected on OSX 10.9.5 first</li> + * <li>any driver</li> + * <li>enabled for all OSX versions</li> + * </ul> + * </li> + * </ul> + * </p> + * <p> + * See Bug 1088 - https://jogamp.org/bugzilla/show_bug.cgi?id=1088 + * </p> + */ + public static final int NeedSharedObjectSync = 20; + /** @deprecated Use {@link #getCount()}, this value is no more valid! */ public static final int COUNT = 18; /** Return the number of known quirks. */ - public static final int getCount() { return 20; } + public static final int getCount() { return 21; } private static final String[] _names = new String[] { "NoDoubleBufferedPBuffer", "NoDoubleBufferedBitmap", "NoSetSwapInterval", "NoOffscreenBitmap", "NoSetSwapIntervalPostRetarget", "GLSLBuggyDiscard", @@ -375,7 +407,8 @@ public class GLRendererQuirks { "NeedCurrCtx4ARBPixFmtQueries", "NeedCurrCtx4ARBCreateContext", "NoFullFBOSupport", "GLSLNonCompliant", "GL4NeedsGL3Request", "GLSharedContextBuggy", "GLES3ViaEGLES2Config", "SingletonEGLDisplayOnly", - "NoMultiSamplingBuffers", "BuggyColorRenderbuffer", "NoPBufferWithAccum" + "NoMultiSamplingBuffers", "BuggyColorRenderbuffer", "NoPBufferWithAccum", + "NeedSharedObjectSync" }; private static final IdentityHashMap<String, GLRendererQuirks> stickyDeviceQuirks = new IdentityHashMap<String, GLRendererQuirks>(); diff --git a/src/jogl/classes/javax/media/opengl/GLSharedContextSetter.java b/src/jogl/classes/javax/media/opengl/GLSharedContextSetter.java index 526967d69..b8aef126b 100644 --- a/src/jogl/classes/javax/media/opengl/GLSharedContextSetter.java +++ b/src/jogl/classes/javax/media/opengl/GLSharedContextSetter.java @@ -28,6 +28,8 @@ package javax.media.opengl; +import com.jogamp.opengl.GLRendererQuirks; + /** * Adds capabilities to set a shared {@link GLContext} directly or via an {@link GLAutoDrawable}. * <p> @@ -88,6 +90,20 @@ package javax.media.opengl; glad.setVisible(true); // GLWindow creation .. * </pre> * </p> + * <h5><a name="synchronization">GL Object Synchronization</a></h5> + * <p> + * Usually synchronization of shared GL objects should not be required, if the shared GL objects + * are created and immutable before concurrent usage. + * </p> + * <p> + * However, using drivers exposing {@link GLRendererQuirks#NeedSharedObjectSync} always + * require the user to synchronize access of shared GL objects. + * </p> + * <p> + * Synchronization can be avoided if accessing the shared GL objects + * exclusively via a queue or {@link com.jogamp.common.util.Ringbuffer Ringbuffer}, see GLMediaPlayerImpl as an example. + * </p> + * </p> * <h5><a name="driverissues">Known Driver Issues</a></h5> * <h7><a name="intelmesa">Intel's Mesa >= 9.1.2 Backend for [Sandybridge/Ivybridge] on GNU/Linux</a></h7> * <p> diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java index bc8d3b7e4..45a4f2426 100644 --- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java @@ -1785,6 +1785,13 @@ public abstract class GLContextImpl extends GLContext { } quirks.addQuirk( quirk ); } + { + final int quirk = GLRendererQuirks.NeedSharedObjectSync; + if(DEBUG) { + System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType()); + } + quirks.addQuirk( quirk ); + } if( Platform.getOSVersionNumber().compareTo(Platform.OSXVersion.Mavericks) >= 0 && 3==reqMajor && 4==major ) { final int quirk = GLRendererQuirks.GL4NeedsGL3Request; if(DEBUG) { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT2.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT2.java index a66aaf9d8..8d040222a 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT2.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT2.java @@ -107,12 +107,13 @@ public class TestSharedContextVBOES2NEWT2 extends UITestCase { animator.start(); final GearsES2 g1 = new GearsES2(0); + g1.setSyncObjects(g1); // this is master, since rendered we must use it as sync final GLWindow f1 = createGLWindow(0, 0, g1); animator.add(f1); final InsetsImmutable insets = f1.getInsets(); final GearsES2 g2 = new GearsES2(0); - g2.setSharedGears(g1); + g2.setSharedGears(g1); // also uses master g1 as sync, if required final GLWindow f2 = createGLWindow(f1.getX()+width+insets.getTotalWidth(), f1.getY()+0, g2); f2.setSharedAutoDrawable(f1); @@ -120,7 +121,7 @@ public class TestSharedContextVBOES2NEWT2 extends UITestCase { f2.setVisible(true); final GearsES2 g3 = new GearsES2(0); - g3.setSharedGears(g1); + g3.setSharedGears(g1); // also uses master g1 as sync, if required final GLWindow f3 = createGLWindow(f1.getX()+0, f1.getY()+height+insets.getTotalHeight(), g3); f3.setSharedAutoDrawable(f1); @@ -222,6 +223,7 @@ public class TestSharedContextVBOES2NEWT2 extends UITestCase { public void asyncEachAnimator(final boolean destroyCleanOrder) throws InterruptedException { final Animator a1 = new Animator(); final GearsES2 g1 = new GearsES2(0); + g1.setSyncObjects(g1); // this is master, since rendered we must use it as sync final GLWindow f1 = createGLWindow(0, 0, g1); a1.add(f1); a1.start(); @@ -230,7 +232,7 @@ public class TestSharedContextVBOES2NEWT2 extends UITestCase { final Animator a2 = new Animator(); final GearsES2 g2 = new GearsES2(0); - g2.setSharedGears(g1); + g2.setSharedGears(g1); // also uses master g1 as sync, if required final GLWindow f2 = createGLWindow(f1.getX()+width+insets.getTotalWidth(), f1.getY()+0, g2); f2.setSharedAutoDrawable(f1); @@ -240,7 +242,7 @@ public class TestSharedContextVBOES2NEWT2 extends UITestCase { final Animator a3 = new Animator(); final GearsES2 g3 = new GearsES2(0); - g3.setSharedGears(g1); + g3.setSharedGears(g1); // also uses master g1 as sync, if required final GLWindow f3 = createGLWindow(f1.getX()+0, f1.getY()+height+insets.getTotalHeight(), g3); f3.setSharedAutoDrawable(f1); @@ -336,8 +338,10 @@ public class TestSharedContextVBOES2NEWT2 extends UITestCase { } static long duration = 1000; // ms + static boolean mainRun = false; public static void main(final String args[]) { + mainRun = true; for(int i=0; i<args.length; i++) { if(args[i].equals("-time")) { i++; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT3.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT3.java index 852b7193e..a0d111c4d 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT3.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT3.java @@ -248,6 +248,7 @@ public class TestSharedContextVBOES2NEWT3 extends UITestCase { public void asyncEachAnimator(final boolean destroyCleanOrder, final boolean useMappedBuffers) throws InterruptedException { final Animator a1 = new Animator(); final GearsES2 g1 = new GearsES2(0); + g1.setSyncObjects(g1); // this is master, since rendered we must use it as sync g1.setUseMappedBuffers(useMappedBuffers); g1.setValidateBuffers(true); final GLWindow f1 = createGLWindow(0, 0, g1); @@ -258,7 +259,7 @@ public class TestSharedContextVBOES2NEWT3 extends UITestCase { final Animator a2 = new Animator(); final GearsES2 g2 = new GearsES2(0); - g2.setSharedGears(g1); + g2.setSharedGears(g1); // also uses master g1 as sync, if required final GLWindow f2 = createGLWindow(f1.getX()+width+insets.getTotalWidth(), f1.getY()+0, g2); f2.setSharedAutoDrawable(f1); @@ -288,7 +289,7 @@ public class TestSharedContextVBOES2NEWT3 extends UITestCase { final Animator a3 = new Animator(); final GearsES2 g3 = new GearsES2(0); - g3.setSharedGears(g1); + g3.setSharedGears(g1); // also uses master g1 as sync, if required final GLWindow f3 = createGLWindow(f1.getX()+0, f1.getY()+height+insets.getTotalHeight(), g3); f3.setSharedAutoDrawable(f1); @@ -374,8 +375,10 @@ public class TestSharedContextVBOES2NEWT3 extends UITestCase { static long duration = 1000; // ms static long durationPostDestroy = 1000; // ms - ~60 frames post destroy + static boolean mainRun = false; public static void main(final String args[]) { + mainRun = true; for(int i=0; i<args.length; i++) { if(args[i].equals("-time")) { i++; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsES1.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsES1.java index 78242944f..9d20495a0 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsES1.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsES1.java @@ -41,6 +41,7 @@ import com.jogamp.newt.event.KeyListener; import com.jogamp.newt.event.MouseAdapter; import com.jogamp.newt.event.MouseEvent; import com.jogamp.newt.event.MouseListener; +import com.jogamp.opengl.GLRendererQuirks; import com.jogamp.opengl.JoglVersion; import com.jogamp.opengl.test.junit.jogl.demos.GearsObject; import com.jogamp.opengl.util.glsl.fixedfunc.FixedFuncUtil; @@ -65,6 +66,7 @@ public class GearsES1 implements GLEventListener { private GearsObject gear1=null, gear2=null, gear3=null; private FloatBuffer gear1Color=GearsObject.red, gear2Color=GearsObject.green, gear3Color=GearsObject.blue; private GearsES1 sharedGears; + private Object syncObjects; private volatile boolean usesSharedGears = false; private boolean useMappedBuffers = false; private boolean validateBuffers = false; @@ -180,6 +182,13 @@ public class GearsES1 implements GLEventListener { System.err.println("gear1 reuse: "+gear1); System.err.println("gear2 reuse: "+gear2); System.err.println("gear3 reuse: "+gear3); + if( gl.getContext().hasRendererQuirk(GLRendererQuirks.NeedSharedObjectSync) ) { + syncObjects = sharedGears; + System.err.println("Shared GearsES1: Synchronized Objects due to quirk "+GLRendererQuirks.toString(GLRendererQuirks.NeedSharedObjectSync)); + } else { + syncObjects = new Object(); + System.err.println("Shared GearsES1: Unsynchronized Objects"); + } } else { gear1 = new GearsObjectES1(gl, useMappedBuffers, gear1Color, 1.0f, 4.0f, 1.0f, 20, 0.7f, validateBuffers); System.err.println("gear1 created: "+gear1); @@ -189,6 +198,8 @@ public class GearsES1 implements GLEventListener { gear3 = new GearsObjectES1(gl, useMappedBuffers, gear3Color, 1.3f, 2.0f, 0.5f, 10, 0.7f, validateBuffers); System.err.println("gear3 created: "+gear3); + + syncObjects = new Object(); } gl.glEnable(GLLightingFunc.GL_NORMALIZE); @@ -249,6 +260,8 @@ public class GearsES1 implements GLEventListener { gear2 = null; gear3.destroy(gl); gear3 = null; + sharedGears = null; + syncObjects = null; System.err.println(Thread.currentThread()+" GearsES1.dispose FIN"); } @@ -294,9 +307,11 @@ public class GearsES1 implements GLEventListener { gl.glRotatef(view_roty, 0.0f, 1.0f, 0.0f); gl.glRotatef(view_rotz, 0.0f, 0.0f, 1.0f); - gear1.draw(gl, -3.0f, -2.0f, angle); - gear2.draw(gl, 3.1f, -2.0f, -2.0f * angle - 9.0f); - gear3.draw(gl, -3.1f, 4.2f, -2.0f * angle - 25.0f); + synchronized ( syncObjects ) { + gear1.draw(gl, -3.0f, -2.0f, angle); + gear2.draw(gl, 3.1f, -2.0f, -2.0f * angle - 9.0f); + gear3.draw(gl, -3.1f, 4.2f, -2.0f * angle - 25.0f); + } // Remember that every push needs a pop; this one is paired with // rotating the entire gear assembly diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java index 0f63566a2..a548d4ccf 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java @@ -30,6 +30,7 @@ import com.jogamp.newt.event.MouseEvent; import com.jogamp.newt.event.MouseListener; import com.jogamp.newt.event.PinchToZoomGesture; import com.jogamp.newt.event.GestureHandler.GestureEvent; +import com.jogamp.opengl.GLRendererQuirks; import com.jogamp.opengl.JoglVersion; import com.jogamp.opengl.math.FloatUtil; import com.jogamp.opengl.math.Quaternion; @@ -75,6 +76,7 @@ public class GearsES2 implements StereoGLEventListener, TileRendererBase.TileRen private float panX = 0.0f, panY = 0.0f, panZ=0.0f; private volatile GearsObjectES2 gear1=null, gear2=null, gear3=null; private GearsES2 sharedGears = null; + private Object syncObjects = null; private boolean useMappedBuffers = false; private boolean validateBuffers = false; private volatile boolean usesSharedGears = false; @@ -146,6 +148,10 @@ public class GearsES2 implements StereoGLEventListener, TileRendererBase.TileRen sharedGears = shared; } + public void setSyncObjects(final Object sync) { + syncObjects = sync; + } + /** * @return gear1 */ @@ -247,6 +253,13 @@ public class GearsES2 implements StereoGLEventListener, TileRendererBase.TileRen System.err.println("gear2 "+sid()+" created w/ share: "+sharedGears.getGear2()+" -> "+gear2); System.err.println("gear3 "+sid()+" created w/ share: "+sharedGears.getGear3()+" -> "+gear3); } + if( gl.getContext().hasRendererQuirk(GLRendererQuirks.NeedSharedObjectSync) ) { + syncObjects = sharedGears; + System.err.println("Shared GearsES2: Synchronized Objects due to quirk "+GLRendererQuirks.toString(GLRendererQuirks.NeedSharedObjectSync)); + } else if( null == syncObjects ) { + syncObjects = new Object(); + System.err.println("Shared GearsES2: Unsynchronized Objects"); + } } else { gear1 = new GearsObjectES2(gl, useMappedBuffers, st, gear1Color, 1.0f, 4.0f, 1.0f, 20, 0.7f, pmvMatrix, pmvMatrixUniform, colorU, validateBuffers); if(verbose) { @@ -262,6 +275,8 @@ public class GearsES2 implements StereoGLEventListener, TileRendererBase.TileRen if(verbose) { System.err.println("gear3 "+sid()+" created: "+gear2); } + if( null == syncObjects ) { + syncObjects = new Object(); } } @@ -461,6 +476,8 @@ public class GearsES2 implements StereoGLEventListener, TileRendererBase.TileRen colorU = null; st.destroy(gl); st = null; + sharedGears = null; + syncObjects = null; if(verbose) { System.err.println(Thread.currentThread()+" GearsES2.dispose "+sid()+" FIN"); @@ -534,9 +551,11 @@ public class GearsES2 implements StereoGLEventListener, TileRendererBase.TileRen pmvMatrix.glRotatef(view_roty, 0.0f, 1.0f, 0.0f); pmvMatrix.glRotatef(view_rotz, 0.0f, 0.0f, 1.0f); - gear1.draw(gl, -3.0f, -2.0f, 1f * angle - 0f); - gear2.draw(gl, 3.1f, -2.0f, -2f * angle - 9.0f); - gear3.draw(gl, -3.1f, 4.2f, -2f * angle - 25.0f); + synchronized ( syncObjects ) { + gear1.draw(gl, -3.0f, -2.0f, 1f * angle - 0f); + gear2.draw(gl, 3.1f, -2.0f, -2f * angle - 9.0f); + gear3.draw(gl, -3.1f, 4.2f, -2f * angle - 25.0f); + } pmvMatrix.glPopMatrix(); st.useProgram(gl, false); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Gears.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Gears.java index 6683f0fbf..28328fcd2 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Gears.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Gears.java @@ -20,6 +20,7 @@ import com.jogamp.newt.event.MouseEvent; import com.jogamp.newt.event.MouseListener; import com.jogamp.newt.event.awt.AWTKeyAdapter; import com.jogamp.newt.event.awt.AWTMouseAdapter; +import com.jogamp.opengl.GLRendererQuirks; import com.jogamp.opengl.JoglVersion; import com.jogamp.opengl.util.TileRendererBase; @@ -33,6 +34,8 @@ public class Gears implements GLEventListener, TileRendererBase.TileRendererList private float view_rotx = 20.0f, view_roty = 30.0f; private final float view_rotz = 0.0f; private int gear1=0, gear2=0, gear3=0; + private Gears sharedGears = null; + private Object syncObjects = null; private float angle = 0.0f; private boolean doRotate = true; private final int swapInterval; @@ -42,6 +45,7 @@ public class Gears implements GLEventListener, TileRendererBase.TileRendererList private boolean doRotateBeforePrinting; private boolean verbose = true; private boolean flipVerticalInGLOrientation = false; + private volatile boolean isInit = false; // private boolean mouseRButtonDown = false; private int prevMouseX, prevMouseY; @@ -182,6 +186,13 @@ public class Gears implements GLEventListener, TileRendererBase.TileRendererList System.err.println("gear1 list reused: "+gear1); System.err.println("gear2 list reused: "+gear2); System.err.println("gear3 list reused: "+gear3); + if( gl.getContext().hasRendererQuirk(GLRendererQuirks.NeedSharedObjectSync) ) { + syncObjects = sharedGears; + System.err.println("Shared Gears: Synchronized Objects due to quirk "+GLRendererQuirks.toString(GLRendererQuirks.NeedSharedObjectSync)); + } else { + syncObjects = new Object(); + System.err.println("Shared Gears: Unsynchronized Objects"); + } } else { gear1 = gl.glGenLists(1); gl.glNewList(gear1, GL2.GL_COMPILE); @@ -203,6 +214,8 @@ public class Gears implements GLEventListener, TileRendererBase.TileRendererList gear(gl, 1.3f, 2.0f, 0.5f, 10, 0.7f); gl.glEndList(); System.err.println("gear3 list created: "+gear3); + + syncObjects = new Object(); } enableStates(gl, false); @@ -295,6 +308,8 @@ public class Gears implements GLEventListener, TileRendererBase.TileRendererList gear1 = 0; gear2 = 0; gear3 = 0; + sharedGears = null; + syncObjects = null; } @Override @@ -355,25 +370,27 @@ public class Gears implements GLEventListener, TileRendererBase.TileRendererList gl.glRotatef(view_rotz, 0.0f, 0.0f, 1.0f); // Place the first gear and call its display list - gl.glPushMatrix(); - gl.glTranslatef(-3.0f, -2.0f, 0.0f); - gl.glRotatef(angle, 0.0f, 0.0f, 1.0f); - gl.glCallList(gear1); - gl.glPopMatrix(); - - // Place the second gear and call its display list - gl.glPushMatrix(); - gl.glTranslatef(3.1f, -2.0f, 0.0f); - gl.glRotatef(-2.0f * angle - 9.0f, 0.0f, 0.0f, 1.0f); - gl.glCallList(gear2); - gl.glPopMatrix(); - - // Place the third gear and call its display list - gl.glPushMatrix(); - gl.glTranslatef(-3.1f, 4.2f, 0.0f); - gl.glRotatef(-2.0f * angle - 25.0f, 0.0f, 0.0f, 1.0f); - gl.glCallList(gear3); - gl.glPopMatrix(); + synchronized ( syncObjects ) { + gl.glPushMatrix(); + gl.glTranslatef(-3.0f, -2.0f, 0.0f); + gl.glRotatef(angle, 0.0f, 0.0f, 1.0f); + gl.glCallList(gear1); + gl.glPopMatrix(); + + // Place the second gear and call its display list + gl.glPushMatrix(); + gl.glTranslatef(3.1f, -2.0f, 0.0f); + gl.glRotatef(-2.0f * angle - 9.0f, 0.0f, 0.0f, 1.0f); + gl.glCallList(gear2); + gl.glPopMatrix(); + + // Place the third gear and call its display list + gl.glPushMatrix(); + gl.glTranslatef(-3.1f, 4.2f, 0.0f); + gl.glRotatef(-2.0f * angle - 25.0f, 0.0f, 0.0f, 1.0f); + gl.glCallList(gear3); + gl.glPopMatrix(); + } // Remember that every push needs a pop; this one is paired with // rotating the entire gear assembly |