From 9d522e77a9ac1f85c57236f00d5432e671f9169c Mon Sep 17 00:00:00 2001
From: Sven Gothel <sgothel@jausoft.com>
Date: Sun, 22 Apr 2012 05:12:16 +0200
Subject: Completing swap-interval implementation for OSX's CALayer usage.
 Closing Bug 555

- Based on Andres Colubri's initiative and commit 218d67fc0222d7709b21c45792d44501351939c4.

- Reading real screen refresh rate ('stolen' from NEWT)

- Properly handling swap-interval and vsync-to in native code

- Increasing accuracy vsync-to to microseconds

Tested manually w/ TestGearsES2AWT.
---
 make/scripts/tests.sh                              |  7 +-
 make/stub_includes/opengl/macosx-window-system.h   |  5 +-
 .../jogamp/opengl/macosx/cgl/MacOSXCGLContext.java | 25 +++---
 .../macosx/MacOSXWindowSystemInterface-pbuffer.m   | 88 ++++++++++++----------
 .../native/macosx/MacOSXWindowSystemInterface.m    | 36 +++++++++
 src/jogl/native/timespec.c                         | 14 ++++
 src/jogl/native/timespec.h                         |  1 +
 .../junit/jogl/demos/es2/awt/TestGearsES2AWT.java  | 32 +++++++-
 .../jogl/demos/es2/newt/TestGearsES2NEWT.java      | 13 ++--
 9 files changed, 157 insertions(+), 64 deletions(-)

diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh
index 4426d2c4e..485552a00 100755
--- a/make/scripts/tests.sh
+++ b/make/scripts/tests.sh
@@ -63,8 +63,7 @@ function jrun() {
     #D_ARGS="-Djogl.debug.GLDebugMessageHandler -Djogl.debug.TraceGL -Djogl.debug.DebugGL -Djogl.debug.GLSLCode -Djogl.debug.GLSLState"
     #D_ARGS="-Djogl.debug.GLDebugMessageHandler -Djogl.debug.DebugGL -Djogl.debug.TraceGL"
     #D_ARGS="-Djogl.debug.TraceGL -Djogl.debug.DebugGL -Djogl.debug.GLSLCode"
-    #D_ARGS="-Djogamp.debug.IOUtil -Djogl.debug.GLSLCode -Djogl.debug.GLMediaPlayer -Djogamp.gluegen.UseTempJarCache=false"
-    D_ARGS="-Djogamp.debug.IOUtil -Djogl.debug.GLSLCode -Djogl.debug.GLMediaPlayer"
+    #D_ARGS="-Djogamp.debug.IOUtil -Djogl.debug.GLSLCode -Djogl.debug.GLMediaPlayer"
     #D_ARGS="-Djogl.debug.GLArrayData"
     #D_ARGS="-Djogl.debug.EGL -Dnativewindow.debug.GraphicsConfiguration -Djogl.debug.GLDrawable"
     #D_ARGS="-Dnewt.test.Screen.disableScreenMode -Dnewt.debug.Screen"
@@ -245,7 +244,7 @@ function testawtswt() {
 #testnoawt com.jogamp.opengl.test.junit.jogl.util.TestGLReadBufferUtilTextureIOWrite02NEWT $*
 #testnoawt com.jogamp.opengl.test.junit.jogl.util.TestPNGImage01NEWT $*
 #testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSimple $*
-testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieCube $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieCube $*
 #testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.TexCubeES2 $*
 
 #
@@ -268,7 +267,7 @@ testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieCube $*
 #testawt com.jogamp.opengl.test.junit.jogl.awt.TestAWT02WindowClosing
 #testawt com.jogamp.opengl.test.junit.jogl.awt.text.TestAWTTextRendererUseVertexArrayBug464
 #testawt com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsAWT $*
-#testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2AWT $*
+testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2AWT $*
 #testawt com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsAWTAnalyzeBug455 $*
 #testawt com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsGLJPanelAWT $*
 #testawt com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsGLJPanelAWTBug450 $*
diff --git a/make/stub_includes/opengl/macosx-window-system.h b/make/stub_includes/opengl/macosx-window-system.h
index 347de6299..e7fe13553 100644
--- a/make/stub_includes/opengl/macosx-window-system.h
+++ b/make/stub_includes/opengl/macosx-window-system.h
@@ -55,7 +55,7 @@ void setContextTextureImageToPBuffer(NSOpenGLContext* ctx, NSOpenGLPixelBuffer*
 // NSOpenGLLayer* createNSOpenGLLayer(NSOpenGLContext* ctx, NSOpenGLPixelFormat* fmt, NSView* view, Bool opaque);
 NSOpenGLLayer* createNSOpenGLLayer(NSOpenGLContext* ctx, NSOpenGLPixelFormat* fmt, NSOpenGLPixelBuffer* pbuffer, Bool opaque, int texWidth, int texHeight);
 void setNSOpenGLLayerSwapInterval(NSOpenGLLayer* layer, int interval);
-void waitUntilNSOpenGLLayerIsReady(NSOpenGLLayer* layer, long to_ms);
+void waitUntilNSOpenGLLayerIsReady(NSOpenGLLayer* layer, long to_micros);
 void setNSOpenGLLayerNeedsDisplay(NSOpenGLLayer* glLayer);
 void releaseNSOpenGLLayer(NSOpenGLLayer *glLayer);
 
@@ -67,3 +67,6 @@ void setSwapInterval(NSOpenGLContext* ctx, int interval);
 Bool setGammaRamp(int tableSize, float* redRamp, float* greenRamp, float* blueRamp);
 void resetGammaRamp();
 
+/* returns the screen refresh rate in Hz */
+int getScreenRefreshRate(int scrn_idx);
+
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
index 7d7dae950..3cd4b340c 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
@@ -396,11 +396,12 @@ public abstract class MacOSXCGLContext extends GLContextImpl
   class NSOpenGLImpl implements GLBackendImpl {
     long nsOpenGLLayer = 0;
     long nsOpenGLLayerPFmt = 0;
-    int vsyncTimeout = 16;
+    float screenVSyncTimeout; // microSec
+    int vsyncTimeout;    // microSec - for nsOpenGLLayer mode
     
     public boolean isNSContext() { return true; }
 
-    public long create(long share, int ctp, int major, int minor) {
+    public long create(long share, int ctp, int major, int minor) {        
         long ctx = 0;
         final MacOSXCGLDrawable drawable = (MacOSXCGLDrawable) MacOSXCGLContext.this.drawable;
         final NativeSurface surface = drawable.getNativeSurface();
@@ -415,6 +416,8 @@ public abstract class MacOSXCGLContext extends GLContextImpl
           return 0;
         }
         config.setChosenPixelFormat(pixelFormat);
+        int sRefreshRate = CGL.getScreenRefreshRate(drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getIndex());
+        screenVSyncTimeout = 1000000f / (float)sRefreshRate;
         if(DEBUG) {
             System.err.println("NS create OSX>=lion "+isLionOrLater);
             System.err.println("NS create backendType: "+drawable.getOpenGLMode());
@@ -424,6 +427,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl
             System.err.println("NS create pixelFormat: "+toHexString(pixelFormat));
             System.err.println("NS create drawable native-handle: "+toHexString(drawable.getHandle()));
             System.err.println("NS create drawable NSView-handle: "+toHexString(drawable.getNSViewHandle()));
+            System.err.println("NS create screen refresh-rate: "+sRefreshRate+" hz, "+screenVSyncTimeout+" micros");
             // Thread.dumpStack();
         }
         try {
@@ -483,6 +487,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl
                   System.err.println("NS create nsOpenGLLayer "+toHexString(nsOpenGLLayer)+", texSize "+texWidth+"x"+texHeight+", "+drawable);
               }
               backingLayerHost.attachSurfaceLayer(nsOpenGLLayer);
+              setSwapInterval(1); // enabled per default in layered surface
           }
         } finally {
           if(0!=pixelFormat) {
@@ -554,23 +559,17 @@ public abstract class MacOSXCGLContext extends GLContextImpl
     public boolean setSwapInterval(int interval) {
       if(0 != nsOpenGLLayer) {
         CGL.setNSOpenGLLayerSwapInterval(nsOpenGLLayer, interval);
+        vsyncTimeout = interval * (int)screenVSyncTimeout;
+        if(DEBUG) { System.err.println("NS setSwapInterval: "+vsyncTimeout+" micros"); }
       }
       CGL.setSwapInterval(contextHandle, interval);
-      if (interval == 0) {
-        // v-sync is disabled, frames were drawn as quickly as possible without adding any
-        // timeout delay.
-        vsyncTimeout = 0;
-      } else {
-        // v-sync is enabled. Swaping interval of 1 means a
-        // timeout of 16ms -> 60Hz, 60fps
-        vsyncTimeout = interval * 16;
-      }
       return true;
     }
     
     public boolean swapBuffers() {
-      if(0 != nsOpenGLLayer && 0 < vsyncTimeout) {
-        // sync w/ CALayer renderer - wait until next frame is required (v-sync)
+      if( 0 != nsOpenGLLayer ) {
+        // If v-sync is disabled, frames will be drawn as quickly as possible 
+        // w/o delay but in sync w/ CALayer. Otherwise wait until next swap interval (v-sync).        
         CGL.waitUntilNSOpenGLLayerIsReady(nsOpenGLLayer, vsyncTimeout);
       }
       if(CGL.flushBuffer(contextHandle)) {
diff --git a/src/jogl/native/macosx/MacOSXWindowSystemInterface-pbuffer.m b/src/jogl/native/macosx/MacOSXWindowSystemInterface-pbuffer.m
index 6071f9610..66bd10f89 100644
--- a/src/jogl/native/macosx/MacOSXWindowSystemInterface-pbuffer.m
+++ b/src/jogl/native/macosx/MacOSXWindowSystemInterface-pbuffer.m
@@ -33,6 +33,8 @@
     int texHeight;
     GLuint textureID;
     GLint swapInterval;
+    GLint swapIntervalCounter;
+    struct timespec lastWaitTime;
 #ifdef HAS_CADisplayLink
     CADisplayLink* displayLink;
 #else
@@ -78,8 +80,14 @@ static CVReturn renderMyNSOpenGLLayer(CVDisplayLinkRef displayLink,
     #ifdef DBG_PERF
         [l tick];
     #endif
-    pthread_cond_signal(&l->renderSignal);
-    SYNC_PRINT("-*-");
+    if(0 < l->swapInterval) {
+        l->swapIntervalCounter++;
+        if(l->swapIntervalCounter>=l->swapInterval) {
+            l->swapIntervalCounter = 0;
+            pthread_cond_signal(&l->renderSignal);
+            SYNC_PRINT("S");
+        }
+    }
     pthread_mutex_unlock(&l->renderLock);
     [pool release];
     return kCVReturnSuccess;
@@ -103,7 +111,9 @@ static CVReturn renderMyNSOpenGLLayer(CVDisplayLinkRef displayLink,
     pthread_cond_init(&renderSignal, NULL); // no attribute
 
     textureID = 0;
-    swapInterval = -1;
+    swapInterval = 1; // defaults to on (as w/ new GL profiles)
+    swapIntervalCounter = 0;
+    timespec_now(&lastWaitTime);
     shallDraw = NO;
     texWidth = _texWidth;
     texHeight = _texHeight;
@@ -244,10 +254,10 @@ static CVReturn renderMyNSOpenGLLayer(CVDisplayLinkRef displayLink,
     pthread_mutex_lock(&renderLock);
     Bool res = NULL != pbuffer && YES == shallDraw;
     if(!res) {
-        SYNC_PRINT("<0>");
+        SYNC_PRINT("0");
         pthread_mutex_unlock(&renderLock);
     } else {
-        SYNC_PRINT("<");
+        SYNC_PRINT("1");
     }
     return res;
 }
@@ -336,10 +346,10 @@ static CVReturn renderMyNSOpenGLLayer(CVDisplayLinkRef displayLink,
     [super drawInOpenGLContext: context pixelFormat: pixelFormat forLayerTime: timeInterval displayTime: timeStamp];
     shallDraw = NO;
     if(0 >= swapInterval) {
-        pthread_cond_signal(&renderSignal);
-        SYNC_PRINT("*");
+        pthread_cond_signal(&renderSignal); // just to wake up
+        SYNC_PRINT("s");
     }
-    SYNC_PRINT("1>");
+    SYNC_PRINT("$");
     pthread_mutex_unlock(&renderLock);
 }
 
@@ -352,6 +362,7 @@ static CVReturn renderMyNSOpenGLLayer(CVDisplayLinkRef displayLink,
 {
     DBG_PRINT("MyNSOpenGLLayer::setSwapInterval: %d\n", interval);
     swapInterval = interval;
+    swapIntervalCounter = 0;
     if(0 < swapInterval) {
         tc = 0;
         timespec_now(&t0);
@@ -409,7 +420,7 @@ void setNSOpenGLLayerSwapInterval(NSOpenGLLayer* layer, int interval) {
   pthread_mutex_unlock(&l->renderLock);
 }
 
-void waitUntilNSOpenGLLayerIsReady(NSOpenGLLayer* layer, long to_ms) {
+void waitUntilNSOpenGLLayerIsReady(NSOpenGLLayer* layer, long to_micros) {
     MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
     BOOL ready = NO;
     int wr = 0;
@@ -420,17 +431,23 @@ void waitUntilNSOpenGLLayerIsReady(NSOpenGLLayer* layer, long to_ms) {
             ready = !l->shallDraw;
         }
         if(NO == ready) {
-            if(0 < to_ms) {
-                struct timespec to_abs;
-                timespec_now(&to_abs);
-                timespec_addms(&to_abs, to_ms);
+            if(0 < to_micros) {
+                #ifdef DBG_SYNC
+                    struct timespec t0, t1, td, td2;
+                    timespec_now(&t0);
+                #endif
+                struct timespec to_abs = l->lastWaitTime;
+                timespec_addmicros(&to_abs, to_micros);
+                #ifdef DBG_SYNC
+                    timespec_subtract(&td, &to_abs, &t0);
+                    fprintf(stderr, "(%ld) / ", timespec_milliseconds(&td));
+                #endif
                 wr = pthread_cond_timedwait(&l->renderSignal, &l->renderLock, &to_abs);
                 #ifdef DBG_SYNC
-                    struct timespec t1, td;
                     timespec_now(&t1);
-                    timespec_subtract(&td, &t1, &to_abs);
-                    long td_ms = timespec_milliseconds(&td);
-                    fprintf(stderr, "%ld ms", td_ms);
+                    timespec_subtract(&td, &t1, &t0);
+                    timespec_subtract(&td2, &t1, &l->lastWaitTime);
+                    fprintf(stderr, "(%ld) / (%ld) ms", timespec_milliseconds(&td), timespec_milliseconds(&td2));
                 #endif
             } else {
                 pthread_cond_wait (&l->renderSignal, &l->renderLock);
@@ -439,32 +456,25 @@ void waitUntilNSOpenGLLayerIsReady(NSOpenGLLayer* layer, long to_ms) {
         }
     } while (NO == ready && 0 == wr) ;
     SYNC_PRINT("-%d}", ready);
+    timespec_now(&l->lastWaitTime);
     pthread_mutex_unlock(&l->renderLock);
 }
 
 void setNSOpenGLLayerNeedsDisplay(NSOpenGLLayer* layer) {
-  MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
-  @synchronized(l) {
-      NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
-      pthread_mutex_lock(&l->renderLock);
-      SYNC_PRINT("[");
-      l->shallDraw = YES;
-      if([l getSwapInterval] > 0) {
-          // only trigger update if async mode is off (swapInterval>0)
-          if ( [NSThread isMainThread] == YES ) {
-              [l setNeedsDisplay];
-          } else {
-              // can't wait, otherwise we may deadlock AWT
-              [l performSelectorOnMainThread:@selector(setNeedsDisplay) withObject:nil waitUntilDone:NO];
-          }
-          SYNC_PRINT("1]");
-      } else {
-          SYNC_PRINT("0]");
-      }
-      pthread_mutex_unlock(&l->renderLock);
-      // DBG_PRINT("MyNSOpenGLLayer::setNSOpenGLLayerNeedsDisplay %p\n", l);
-      [pool release];
-  }
+    MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
+    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+    pthread_mutex_lock(&l->renderLock);
+    l->shallDraw = YES;
+    if ( [NSThread isMainThread] == YES ) {
+      [l setNeedsDisplay];
+    } else {
+      // can't wait, otherwise we may deadlock AWT
+      [l performSelectorOnMainThread:@selector(setNeedsDisplay) withObject:nil waitUntilDone:NO];
+    }
+    SYNC_PRINT(".");
+    pthread_mutex_unlock(&l->renderLock);
+    // DBG_PRINT("MyNSOpenGLLayer::setNSOpenGLLayerNeedsDisplay %p\n", l);
+    [pool release];
 }
 
 void releaseNSOpenGLLayer(NSOpenGLLayer* layer) {
diff --git a/src/jogl/native/macosx/MacOSXWindowSystemInterface.m b/src/jogl/native/macosx/MacOSXWindowSystemInterface.m
index 979e57aee..8ac9f4700 100644
--- a/src/jogl/native/macosx/MacOSXWindowSystemInterface.m
+++ b/src/jogl/native/macosx/MacOSXWindowSystemInterface.m
@@ -745,3 +745,39 @@ Bool setGammaRamp(int tableSize, float* redRamp, float* greenRamp, float* blueRa
 void resetGammaRamp() {
   CGDisplayRestoreColorSyncSettings();
 }
+
+/***
+ * The following static functions are copied out of NEWT's OSX impl. <src/newt/native/MacWindow.m>
+ * May need to push code to NativeWindow, to remove duplication.
+ */
+static NSScreen * NewtScreen_getNSScreenByIndex(int screen_idx) {
+    NSArray *screens = [NSScreen screens];
+    if(screen_idx<0) screen_idx=0;
+    if(screen_idx>=[screens count]) screen_idx=0;
+    return (NSScreen *) [screens objectAtIndex: screen_idx];
+}
+static CGDirectDisplayID NewtScreen_getCGDirectDisplayIDByNSScreen(NSScreen *screen) {
+    // Mind: typedef uint32_t CGDirectDisplayID; - however, we assume it's 64bit on 64bit ?!
+    NSDictionary * dict = [screen deviceDescription];
+    NSNumber * val = (NSNumber *) [dict objectForKey: @"NSScreenNumber"];
+    // [NSNumber integerValue] returns NSInteger which is 32 or 64 bit native size
+    return (CGDirectDisplayID) [val integerValue];
+}
+static long GetDictionaryLong(CFDictionaryRef theDict, const void* key) 
+{
+    long value = 0;
+    CFNumberRef numRef;
+    numRef = (CFNumberRef)CFDictionaryGetValue(theDict, key); 
+    if (numRef != NULL)
+        CFNumberGetValue(numRef, kCFNumberLongType, &value);    
+    return value;
+}
+#define CGDDGetModeRefreshRate(mode) GetDictionaryLong((mode), kCGDisplayRefreshRate)
+
+int getScreenRefreshRate(int scrn_idx) {
+    NSScreen *screen = NewtScreen_getNSScreenByIndex(scrn_idx);
+    CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen);
+    CFDictionaryRef mode = CGDisplayCurrentMode(display);
+    return CGDDGetModeRefreshRate(mode);
+}
+
diff --git a/src/jogl/native/timespec.c b/src/jogl/native/timespec.c
index 74c1a6901..50f0ca8c5 100644
--- a/src/jogl/native/timespec.c
+++ b/src/jogl/native/timespec.c
@@ -24,6 +24,20 @@ void timespec_addms(struct timespec *ts, long ms)
     ts->tv_nsec=ts->tv_nsec%1000000000;
 }
 
+void timespec_addmicros(struct timespec *ts, long micro)
+{
+    int sec=micro/1000000;
+    micro=micro - sec*1000000;
+
+    // perform the addition
+    ts->tv_nsec+=micro*1000;
+
+    // adjust the time
+    ts->tv_sec+=ts->tv_nsec/1000000000 + sec;
+    ts->tv_nsec=ts->tv_nsec%1000000000;
+
+}
+
 void timespec_addns(struct timespec *ts, long ns)
 {
     int sec=ns/1000000000;
diff --git a/src/jogl/native/timespec.h b/src/jogl/native/timespec.h
index 671eb4716..f900bfa16 100644
--- a/src/jogl/native/timespec.h
+++ b/src/jogl/native/timespec.h
@@ -5,6 +5,7 @@
 
 void timespec_now(struct timespec *ts);
 void timespec_addms(struct timespec *ts, long ms);
+void timespec_addmicros(struct timespec *ts, long micro);
 void timespec_addns(struct timespec *ts, long ns);
 
 /** returns 0: a==b, >0: a>b, <0: a<b */
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2AWT.java
index 5bf341388..c6e224548 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2AWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2AWT.java
@@ -38,9 +38,13 @@ import com.jogamp.newt.event.TraceKeyAdapter;
 import com.jogamp.newt.event.TraceWindowAdapter;
 
 import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
 import com.jogamp.opengl.test.junit.util.UITestCase;
 import com.jogamp.opengl.test.junit.util.QuitAdapter;
 import java.awt.Frame;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
 import java.lang.reflect.InvocationTargetException;
 
 import org.junit.Assert;
@@ -52,6 +56,9 @@ public class TestGearsES2AWT extends UITestCase {
     static int width, height;
     static boolean firstUIActionOnProcess = false;
     static boolean forceES2 = false;
+    static boolean shallUseOffscreenLayer = false;
+    static int swapInterval = 1;
+    static boolean showFPS = false;    
 
     @BeforeClass
     public static void initClass() {
@@ -69,10 +76,12 @@ public class TestGearsES2AWT extends UITestCase {
 
         final GLCanvas glCanvas = new GLCanvas(caps);
         Assert.assertNotNull(glCanvas);
+        glCanvas.setShallUseOffscreenLayer(shallUseOffscreenLayer);
         frame.add(glCanvas);
         frame.setSize(512, 512);
+        frame.setTitle("Gears AWT Test (translucent "+!caps.isBackgroundOpaque()+"), swapInterval "+swapInterval);
 
-        glCanvas.addGLEventListener(new GearsES2(1));
+        glCanvas.addGLEventListener(new GearsES2(swapInterval));
 
         Animator animator = new Animator(glCanvas);
         QuitAdapter quitAdapter = new QuitAdapter();
@@ -115,6 +124,8 @@ public class TestGearsES2AWT extends UITestCase {
     static long duration = 500; // ms
 
     public static void main(String args[]) {
+        boolean waitForKey = false;
+        
         for(int i=0; i<args.length; i++) {
             if(args[i].equals("-time")) {
                 i++;
@@ -123,11 +134,30 @@ public class TestGearsES2AWT extends UITestCase {
                 } catch (Exception ex) { ex.printStackTrace(); }
             } else if(args[i].equals("-es2")) {
                 forceES2 = true;
+            } else if(args[i].equals("-vsync")) {
+                i++;
+                swapInterval = MiscUtils.atoi(args[i], swapInterval);
+            } else if(args[i].equals("-layered")) {
+                shallUseOffscreenLayer = true;
+            } else if(args[i].equals("-showFPS")) {
+                showFPS = true;
             } else if(args[i].equals("-firstUIAction")) {
                 firstUIActionOnProcess = true;
+            } else if(args[i].equals("-wait")) {
+                waitForKey = true;
             }
         }
         System.err.println("forceES2 "+forceES2);
+        System.err.println("swapInterval "+swapInterval);
+        System.err.println("shallUseOffscreenLayer "+shallUseOffscreenLayer);
+        
+        if(waitForKey) {
+            BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+            System.err.println("Press enter to continue");
+            try {
+                System.err.println(stdin.readLine());
+            } catch (IOException e) { }
+        }
         org.junit.runner.JUnitCore.main(TestGearsES2AWT.class.getName());
     }
 }
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java
index cab46b475..264b62fec 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java
@@ -77,7 +77,7 @@ public class TestGearsES2NEWT extends UITestCase {
     static boolean alwaysOnTop = false;
     static boolean fullscreen = false;
     static boolean pmvUseBackingArray = true;
-    static boolean vsync = false;
+    static int swapInterval = 1;
     static boolean waitForKey = false;
     static boolean mouseVisible = true;
     static boolean mouseConfined = false;
@@ -98,12 +98,12 @@ public class TestGearsES2NEWT extends UITestCase {
     }
 
     protected void runTestGL(GLCapabilitiesImmutable caps, boolean undecorated) throws InterruptedException {
-        System.err.println("requested: vsync "+vsync+", "+caps);
+        System.err.println("requested: vsync "+swapInterval+", "+caps);
         Display dpy = NewtFactory.createDisplay(null);
         Screen screen = NewtFactory.createScreen(dpy, screenIdx);
         final GLWindow glWindow = GLWindow.create(screen, caps);
         Assert.assertNotNull(glWindow);
-        glWindow.setTitle("Gears NEWT Test (translucent "+!caps.isBackgroundOpaque()+"), vsync "+vsync+", size "+wsize+", pos "+wpos);
+        glWindow.setTitle("Gears NEWT Test (translucent "+!caps.isBackgroundOpaque()+"), swapInterval "+swapInterval+", size "+wsize+", pos "+wpos);
         glWindow.setSize(wsize.getWidth(), wsize.getHeight());
         if(null != wpos) {
             glWindow.setPosition(wpos.getX(), wpos.getY());
@@ -114,7 +114,7 @@ public class TestGearsES2NEWT extends UITestCase {
         glWindow.setPointerVisible(mouseVisible);
         glWindow.confinePointer(mouseConfined);
 
-        final GearsES2 demo = new GearsES2(vsync ? 1 : -1);
+        final GearsES2 demo = new GearsES2(swapInterval);
         demo.setPMVUseBackingArray(pmvUseBackingArray);
         glWindow.addGLEventListener(demo);
         if(waitForKey) {
@@ -276,7 +276,8 @@ public class TestGearsES2NEWT extends UITestCase {
             } else if(args[i].equals("-pmvDirect")) {
                 pmvUseBackingArray = false;
             } else if(args[i].equals("-vsync")) {
-                vsync = true;
+                i++;
+                swapInterval = MiscUtils.atoi(args[i], swapInterval);
             } else if(args[i].equals("-es2")) {
                 forceES2 = true;
             } else if(args[i].equals("-wait")) {
@@ -332,7 +333,7 @@ public class TestGearsES2NEWT extends UITestCase {
         System.err.println("atop "+alwaysOnTop);
         System.err.println("fullscreen "+fullscreen);
         System.err.println("pmvDirect "+(!pmvUseBackingArray));
-        System.err.println("vsync "+vsync);
+        System.err.println("swapInterval "+swapInterval);
         System.err.println("mouseVisible "+mouseVisible);
         System.err.println("mouseConfined "+mouseConfined);
         System.err.println("loops "+loops);
-- 
cgit v1.2.3