From a9289ce0fde4d4d344e4ab895790642383226cb4 Mon Sep 17 00:00:00 2001
From: Sven Gothel <sgothel@jausoft.com>
Date: Thu, 8 Sep 2011 03:53:33 +0200
Subject: NEWT/ScreenMode: X11 fixes ; Ensure Screen's size is set if
 screenMode changed ; Enhanced tests; Catch NV/XRANDR/GL bug

X11 fixes
 - X11Screen properly uses it's display's connection
   decorated in lock/unlock (for ScreenMode etc)

Ensure Screen's size is set if screenMode changed
 - ScreenImpl's ScreenModeListener updates it's screen size
   so 'external' changes will be detected.

Enhanced tests
 - Verify more data rel. ScreenMode

Catch NV/XRANDR/GL bug
  - Read TestScreenMode01NEWT/TestScreenMode01bNEWT comments
---
 src/newt/classes/jogamp/newt/DisplayImpl.java      |  19 ++
 src/newt/classes/jogamp/newt/ScreenImpl.java       |  18 +-
 .../classes/jogamp/newt/driver/x11/X11Screen.java  | 342 +++++++++++----------
 src/newt/native/X11Window.c                        |   9 +-
 .../test/junit/newt/TestScreenMode00NEWT.java      |  10 +-
 .../test/junit/newt/TestScreenMode00bNEWT.java     | 124 ++++++++
 .../test/junit/newt/TestScreenMode01NEWT.java      |  59 +++-
 .../test/junit/newt/TestScreenMode01bNEWT.java     | 190 ++++++++++++
 .../test/junit/newt/TestScreenMode02NEWT.java      |   3 +-
 9 files changed, 593 insertions(+), 181 deletions(-)
 create mode 100644 src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode00bNEWT.java
 create mode 100644 src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01bNEWT.java

(limited to 'src')

diff --git a/src/newt/classes/jogamp/newt/DisplayImpl.java b/src/newt/classes/jogamp/newt/DisplayImpl.java
index ddb409338..92add6a4e 100644
--- a/src/newt/classes/jogamp/newt/DisplayImpl.java
+++ b/src/newt/classes/jogamp/newt/DisplayImpl.java
@@ -38,6 +38,7 @@ import com.jogamp.newt.Display;
 import com.jogamp.newt.NewtFactory;
 import com.jogamp.newt.event.NEWTEvent;
 import com.jogamp.newt.event.NEWTEventConsumer;
+
 import jogamp.newt.event.NEWTEventTask;
 import com.jogamp.newt.util.EDTUtil;
 import com.jogamp.newt.util.MainThread;
@@ -445,6 +446,24 @@ public abstract class DisplayImpl extends Display {
         }
     }
 
+    public interface DisplayRunnable {
+        Object run(long dpy);
+    }    
+    public final Object runWithLockedDisplayHandle(DisplayRunnable action) {
+        final AbstractGraphicsDevice aDevice = getGraphicsDevice();
+        if(null == aDevice) {
+            throw new RuntimeException("null device - not initialized: "+this);
+        }
+        Object res;
+        aDevice.lock();
+        try {
+            res = action.run(aDevice.getHandle());
+        } finally {
+            aDevice.unlock();
+        }
+        return res;
+    }
+    
     protected EDTUtil edtUtil = null;
     protected int id;
     protected String name;
diff --git a/src/newt/classes/jogamp/newt/ScreenImpl.java b/src/newt/classes/jogamp/newt/ScreenImpl.java
index c83a82a7c..749bba114 100644
--- a/src/newt/classes/jogamp/newt/ScreenImpl.java
+++ b/src/newt/classes/jogamp/newt/ScreenImpl.java
@@ -169,16 +169,12 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
                 System.err.println("Screen.createNative() START ("+DisplayImpl.getThreadName()+", "+this+")");
             }
             t0 = System.currentTimeMillis();
-            display.createNative(); // 1st display: trigger creation w/o incr ref count (hold native dispatching) 
-            try {
-                createNativeImpl();
-                if(null == aScreen) {
-                    throw new NativeWindowException("Screen.createNative() failed to instanciate an AbstractGraphicsScreen");
-                }
-                initScreenModeStatus();
-            } finally {
-                display.addReference(); // 1st display: allow native dispatching
+            display.addReference();
+            createNativeImpl();
+            if(null == aScreen) {
+                throw new NativeWindowException("Screen.createNative() failed to instanciate an AbstractGraphicsScreen");
             }
+            initScreenModeStatus();
             if(DEBUG) {
                 System.err.println("Screen.createNative() END ("+DisplayImpl.getThreadName()+", "+this+")");
             }
@@ -322,7 +318,6 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
 
                 // if mode has changed somehow, update it ..
                 if( sms.getCurrentScreenMode().hashCode() != smU.hashCode() ) {
-                    setScreenSize(smU.getRotatedWidth(), smU.getRotatedHeight());
                     sms.fireScreenModeChanged(smU, true);
                 }
             } finally {
@@ -391,6 +386,9 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
     }
 
     public void screenModeChanged(ScreenMode sm, boolean success) {
+        if(success) {
+            setScreenSize(sm.getRotatedWidth(), sm.getRotatedHeight());
+        }
         for(int i=0; i<referencedScreenModeListener.size(); i++) {
             ((ScreenModeListener)referencedScreenModeListener.get(i)).screenModeChanged(sm, success);
         }
diff --git a/src/newt/classes/jogamp/newt/driver/x11/X11Screen.java b/src/newt/classes/jogamp/newt/driver/x11/X11Screen.java
index 8dd5bba83..a67352138 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/X11Screen.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/X11Screen.java
@@ -32,12 +32,14 @@
  */
 package jogamp.newt.driver.x11;
 
+import jogamp.newt.DisplayImpl;
 import jogamp.newt.ScreenImpl;
+import jogamp.newt.DisplayImpl.DisplayRunnable;
+
 import com.jogamp.newt.ScreenMode;
 import com.jogamp.newt.util.ScreenModeUtil;
 import java.util.List;
 
-import javax.media.nativewindow.AbstractGraphicsDevice;
 import javax.media.nativewindow.x11.*;
 
 public class X11Screen extends ScreenImpl {
@@ -50,13 +52,19 @@ public class X11Screen extends ScreenImpl {
     }
 
     protected void createNativeImpl() {
-        long handle = GetScreen0(getDisplayEDTHandle(), screen_idx);
-        if (handle == 0) {
+        // validate screen index
+        Long handle = (Long) display.runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable() {
+            public Object run(long dpy) {        
+                long handle = GetScreen0(dpy, screen_idx);
+                if(0 != handle) {
+                    setScreenSize(getWidth0(dpy, screen_idx), getHeight0(dpy, screen_idx));
+                }
+                return new Long(handle);
+            } } );        
+        if (handle.longValue() == 0) {
             throw new RuntimeException("Error creating screen: " + screen_idx);
-        }
+        }        
         aScreen = new X11GraphicsScreen((X11GraphicsDevice) getDisplay().getGraphicsDevice(), screen_idx);
-        setScreenSize(getWidth0(getDisplayEDTHandle(), screen_idx),
-                getHeight0(getDisplayEDTHandle(), screen_idx));
     }
 
     protected void closeNativeImpl() {
@@ -71,184 +79,202 @@ public class X11Screen extends ScreenImpl {
     private int nmode_number;
 
     protected int[] getScreenModeFirstImpl() {
-        // initialize iterators and static data
-        nrotations = getAvailableScreenModeRotations0(getDisplayEDTHandle(), screen_idx);
-        if(null==nrotations || 0==nrotations.length) {
-            return null;
-        }
-        nrotation_index = 0;
-
-        nres_number = getNumScreenModeResolutions0(getDisplayEDTHandle(), screen_idx);
-        if(0==nres_number) {
-            return null;
-        }
-        nres_index = 0;
-
-        nrates = getScreenModeRates0(getDisplayEDTHandle(), screen_idx, nres_index);
-        if(null==nrates || 0==nrates.length) {
-            return null;
-        }
-        nrate_index = 0;
-
-        nmode_number = 0;
-
-        return getScreenModeNextImpl();
-    }
-
-    protected int[] getScreenModeNextImpl() {
-        // assemble: w x h x bpp x f x r        
-
-        /**
-        System.err.println("******** mode: "+nmode_number);
-        System.err.println("rot  "+nrotation_index);
-        System.err.println("rate "+nrate_index);
-        System.err.println("res  "+nres_index); */
-
-        int[] res = getScreenModeResolution0(getDisplayEDTHandle(), screen_idx, nres_index);
-        if(null==res || 0==res.length) {
-            return null;
-        }
-        if(0>=res[0] || 0>=res[1]) {
-            throw new InternalError("invalid resolution: "+res[0]+"x"+res[1]+" for res idx "+nres_index+"/"+nres_number);
-        }
-        int bpp = 32; // FIXME
-        int rate = nrates[nrate_index];
-        if(0>=rate) {
-            throw new InternalError("invalid rate: "+rate+" at index "+nrate_index+"/"+nrates.length);
-        }
-        int rotation = nrotations[nrotation_index];
-
-        int[] props = new int[ 1 + ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL ];
-        int i = 0;
-        props[i++] = nres_index; // use resolution index, not unique for native -> ScreenMode
-        props[i++] = 0; // set later for verification of iterator
-        props[i++] = res[0]; // width
-        props[i++] = res[1]; // height
-        props[i++] = bpp;    // bpp
-        props[i++] = res[2]; // widthmm
-        props[i++] = res[3]; // heightmm
-        props[i++] = rate;   // rate
-        props[i++] = rotation;
-        props[i - ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL] = i - 1; // count without extra element
-
-        nmode_number++;
-
-        // iteration: r -> f -> bpp -> [w x h]
-        nrotation_index++;
-        if(nrotation_index == nrotations.length) {
-            nrotation_index=0;
-            nrate_index++;
-            if(null == nrates || nrate_index == nrates.length){
-                nres_index++;
-                if(nres_index == nres_number) {
-                    // done
-                    nrates=null;
-                    nrotations=null;
+        return (int[]) runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable() {
+            public Object run(long dpy) {
+                // initialize iterators and static data
+                nrotations = getAvailableScreenModeRotations0(dpy, screen_idx);
+                if(null==nrotations || 0==nrotations.length) {
                     return null;
                 }
-
-                nrates = getScreenModeRates0(getDisplayEDTHandle(), screen_idx, nres_index);
+                nrotation_index = 0;
+        
+                nres_number = getNumScreenModeResolutions0(dpy, screen_idx);
+                if(0==nres_number) {
+                    return null;
+                }
+                nres_index = 0;
+        
+                nrates = getScreenModeRates0(dpy, screen_idx, nres_index);
                 if(null==nrates || 0==nrates.length) {
                     return null;
                 }
                 nrate_index = 0;
-            }
-        }
+        
+                nmode_number = 0;
+        
+                return getScreenModeNextImpl();
+            } } );
+    }
 
-        return props;
+    protected int[] getScreenModeNextImpl() {
+        // assemble: w x h x bpp x f x r        
+        return (int[]) runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable() {
+            public Object run(long dpy) {
+                /**
+                System.err.println("******** mode: "+nmode_number);
+                System.err.println("rot  "+nrotation_index);
+                System.err.println("rate "+nrate_index);
+                System.err.println("res  "+nres_index); */
+        
+                int[] res = getScreenModeResolution0(dpy, screen_idx, nres_index);
+                if(null==res || 0==res.length) {
+                    return null;
+                }
+                if(0>=res[0] || 0>=res[1]) {
+                    throw new InternalError("invalid resolution: "+res[0]+"x"+res[1]+" for res idx "+nres_index+"/"+nres_number);
+                }
+                int bpp = 32; // FIXME
+                int rate = nrates[nrate_index];
+                if(0>=rate) {
+                    throw new InternalError("invalid rate: "+rate+" at index "+nrate_index+"/"+nrates.length);
+                }
+                int rotation = nrotations[nrotation_index];
+        
+                int[] props = new int[ 1 + ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL ];
+                int i = 0;
+                props[i++] = nres_index; // use resolution index, not unique for native -> ScreenMode
+                props[i++] = 0; // set later for verification of iterator
+                props[i++] = res[0]; // width
+                props[i++] = res[1]; // height
+                props[i++] = bpp;    // bpp
+                props[i++] = res[2]; // widthmm
+                props[i++] = res[3]; // heightmm
+                props[i++] = rate;   // rate
+                props[i++] = rotation;
+                props[i - ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL] = i - 1; // count without extra element
+        
+                nmode_number++;
+        
+                // iteration: r -> f -> bpp -> [w x h]
+                nrotation_index++;
+                if(nrotation_index == nrotations.length) {
+                    nrotation_index=0;
+                    nrate_index++;
+                    if(null == nrates || nrate_index == nrates.length){
+                        nres_index++;
+                        if(nres_index == nres_number) {
+                            // done
+                            nrates=null;
+                            nrotations=null;
+                            return null;
+                        }
+        
+                        nrates = getScreenModeRates0(dpy, screen_idx, nres_index);
+                        if(null==nrates || 0==nrates.length) {
+                            return null;
+                        }
+                        nrate_index = 0;
+                    }
+                }
+        
+                return props;
+            } } );
     }
 
     protected ScreenMode getCurrentScreenModeImpl() {
-        int resNumber = getNumScreenModeResolutions0(getDisplayEDTHandle(), screen_idx);
-        if(0==resNumber) {
-            return null;
-        }
-        int resIdx = getCurrentScreenResolutionIndex0(getDisplayEDTHandle(), screen_idx);
-        if(0>resIdx) {
-            return null;
-        }
-        if(resIdx>=resNumber) {
-            throw new RuntimeException("Invalid resolution index: ! "+resIdx+" < "+resNumber);
-        }
-        int[] res = getScreenModeResolution0(getDisplayEDTHandle(), screen_idx, resIdx);
-        if(null==res || 0==res.length) {
-            return null;
-        }
-        if(0>=res[0] || 0>=res[1]) {
-            throw new InternalError("invalid resolution: "+res[0]+"x"+res[1]+" for res idx "+resIdx+"/"+resNumber);
-        }
-        int rate = getCurrentScreenRate0(getDisplayEDTHandle(), screen_idx);
-        if(0>rate) {
-            return null;
-        }
-        int rot = getCurrentScreenRotation0(getDisplayEDTHandle(), screen_idx);
-        if(0>rot) {
-            return null;
-        }
-
-        int[] props = new int[ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL];
-        int i = 0;
-        props[i++] = 0; // set later for verification of iterator
-        props[i++] = res[0]; // width
-        props[i++] = res[1]; // height
-        props[i++] = 32;     // FIXME: bpp
-        props[i++] = res[2]; // widthmm
-        props[i++] = res[3]; // heightmm
-        props[i++] = rate;   // rate
-        props[i++] = rot;
-        props[i - ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL] = i; // count
-        return ScreenModeUtil.streamIn(props, 0);
+        return (ScreenMode) runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable() {
+            public Object run(long dpy) {
+                int resNumber = getNumScreenModeResolutions0(dpy, screen_idx);
+                if(0==resNumber) {
+                    return null;
+                }
+                int resIdx = getCurrentScreenResolutionIndex0(dpy, screen_idx);
+                if(0>resIdx) {
+                    return null;
+                }
+                if(resIdx>=resNumber) {
+                    throw new RuntimeException("Invalid resolution index: ! "+resIdx+" < "+resNumber);
+                }
+                int[] res = getScreenModeResolution0(dpy, screen_idx, resIdx);
+                if(null==res || 0==res.length) {
+                    return null;
+                }
+                if(0>=res[0] || 0>=res[1]) {
+                    throw new InternalError("invalid resolution: "+res[0]+"x"+res[1]+" for res idx "+resIdx+"/"+resNumber);
+                }
+                int rate = getCurrentScreenRate0(dpy, screen_idx);
+                if(0>rate) {
+                    return null;
+                }
+                int rot = getCurrentScreenRotation0(dpy, screen_idx);
+                if(0>rot) {
+                    return null;
+                }
+                int[] props = new int[ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL];
+                int i = 0;
+                props[i++] = 0; // set later for verification of iterator
+                props[i++] = res[0]; // width
+                props[i++] = res[1]; // height
+                props[i++] = 32;     // FIXME: bpp
+                props[i++] = res[2]; // widthmm
+                props[i++] = res[3]; // heightmm
+                props[i++] = rate;   // rate
+                props[i++] = rot;
+                props[i - ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL] = i; // count
+                return ScreenModeUtil.streamIn(props, 0);
+            } } );
     }
 
-    protected boolean setCurrentScreenModeImpl(ScreenMode screenMode) {
-        List<ScreenMode> screenModes = this.getScreenModesOrig();
-        int screenModeIdx = screenModes.indexOf(screenMode);
+    protected boolean setCurrentScreenModeImpl(final ScreenMode screenMode) {
+        final List<ScreenMode> screenModes = this.getScreenModesOrig();
+        final int screenModeIdx = screenModes.indexOf(screenMode);
         if(0>screenModeIdx) {
             throw new RuntimeException("ScreenMode not element of ScreenMode list: "+screenMode);
         }
-        int resNumber = getNumScreenModeResolutions0(getDisplayEDTHandle(), screen_idx);
-        int resIdx = getScreenModesIdx2NativeIdx().get(screenModeIdx);
-        if(0>resIdx || resIdx>=resNumber) {
-            throw new RuntimeException("Invalid resolution index: ! 0 < "+resIdx+" < "+resNumber+", screenMode["+screenModeIdx+"] "+screenMode);
-        }
-
-        final AbstractGraphicsDevice aDevice = display.getGraphicsDevice();
-        if(null == aDevice) {
-            throw new RuntimeException("null device - not initialized: "+display);
-        }
-        aDevice.lock();
-        boolean done = false;
-        long t0 = System.currentTimeMillis();
-        try {
-            long dpy = aDevice.getHandle();
-            int f = screenMode.getMonitorMode().getRefreshRate();
-            int r = screenMode.getRotation();
-            if( setCurrentScreenModeStart0(dpy, screen_idx, resIdx, f, r) ) {
-                while(!done && System.currentTimeMillis()-t0 < SCREEN_MODE_CHANGE_TIMEOUT) {
-                    done = setCurrentScreenModePollEnd0(dpy, screen_idx, resIdx, f, r);
-                    if(!done) {
-                        try { Thread.sleep(10); } catch (InterruptedException e) { }
+        final long t0 = System.currentTimeMillis();
+        Boolean done = (Boolean) runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable() {
+            public Object run(long dpy) {
+                boolean done = false;
+                int resNumber = getNumScreenModeResolutions0(dpy, screen_idx);
+                int resIdx = getScreenModesIdx2NativeIdx().get(screenModeIdx);
+                if(0>resIdx || resIdx>=resNumber) {
+                    throw new RuntimeException("Invalid resolution index: ! 0 < "+resIdx+" < "+resNumber+", screenMode["+screenModeIdx+"] "+screenMode);
+                }
+        
+                final int f = screenMode.getMonitorMode().getRefreshRate();
+                final int r = screenMode.getRotation();
+                if( setCurrentScreenModeStart0(dpy, screen_idx, resIdx, f, r) ) {
+                    while(!done && System.currentTimeMillis()-t0 < SCREEN_MODE_CHANGE_TIMEOUT) {
+                        done = setCurrentScreenModePollEnd0(dpy, screen_idx, resIdx, f, r);
+                        if(!done) {
+                            try { Thread.sleep(10); } catch (InterruptedException e) { }
+                        }
                     }
                 }
-            }
-        } finally {
-            aDevice.unlock();
-        }
-
-        if(!done) {
+                return Boolean.valueOf(done);
+            }            
+        });
+        
+        if(!done.booleanValue()) {
             System.err.println("X11Screen.setCurrentScreenModeImpl: TO ("+SCREEN_MODE_CHANGE_TIMEOUT+") reached: "+
                                (System.currentTimeMillis()-t0)+"ms");
         }
-        return done;
+        return done.booleanValue();
     }
 
     //----------------------------------------------------------------------
     // Internals only
-    //
-    private final long getDisplayEDTHandle() {
-        return ((X11Display) display).getEDTHandle();
+    //    
+    private final Object runWithLockedDisplayHandle(DisplayRunnable action) {
+        return display.runWithLockedDisplayHandle(action);
+        // return runWithTempDisplayHandle(action);
     }
     
+    /** just here for testing some X11 RANDR bugs .. etc ..
+    private final Object runWithTempDisplayHandle(DisplayRunnable action) {
+        long dpy = X11Util.openDisplay(null);
+        if(0 == dpy) {
+            throw new RuntimeException("null device");
+        }
+        Object res;
+        try {
+            res = action.run(dpy);
+        } finally {
+            X11Util.closeDisplay(dpy);
+        }
+        return res;
+    } */
+    
     private static native long GetScreen0(long dpy, int scrn_idx);
 
     private static native int getWidth0(long display, int scrn_idx);
diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c
index 8d47f544a..092f3f7d3 100644
--- a/src/newt/native/X11Window.c
+++ b/src/newt/native/X11Window.c
@@ -910,14 +910,11 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Screen_GetScreen0
         NewtCommon_FatalError(env, "invalid display connection..");
     }
 
-    scrn = ScreenOfDisplay(dpy,screen_index);
+    scrn = ScreenOfDisplay(dpy, screen_index);
     if(scrn==NULL) {
-        scrn=DefaultScreenOfDisplay(dpy);
+        fprintf(stderr, "couldn't get screen idx %d\n", screen_index);
     }
-    if(scrn==NULL) {
-        fprintf(stderr, "couldn't get screen ..\n");
-    }
-    DBG_PRINT("X11: X11Screen_GetScreen0 scrn %p DONE\n", scrn);
+    DBG_PRINT("X11: X11Screen_GetScreen0 idx %d -> scrn %p DONE\n", screen_index, scrn);
     return (jlong) (intptr_t) scrn;
 }
 
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode00NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode00NEWT.java
index 4abf41f66..cfb8c7715 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode00NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode00NEWT.java
@@ -111,10 +111,14 @@ public class TestScreenMode00NEWT extends UITestCase {
             }
             ScreenMode sm_o = screen.getOriginalScreenMode();
             Assert.assertNotNull(sm_o);            
-            ScreenMode sm_c = screen.getOriginalScreenMode();
+            ScreenMode sm_c = screen.getCurrentScreenMode();
             Assert.assertNotNull(sm_c);
-            System.err.println("orig: "+sm_o);
-            System.err.println("curr: "+sm_c);
+            System.err.println("orig SM: "+sm_o);
+            System.err.println("curr SM: "+sm_c);
+            System.err.println("curr sz: "+screen.getWidth()+"x"+screen.getHeight());
+            Assert.assertEquals(sm_o, sm_c);
+            Assert.assertEquals(sm_c.getRotatedWidth(), screen.getWidth());
+            Assert.assertEquals(sm_c.getRotatedHeight(), screen.getHeight());
         } else {
             // no support ..
             System.err.println("Your platform has no ScreenMode change support, sorry");
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode00bNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode00bNEWT.java
new file mode 100644
index 000000000..a2d7d09bb
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode00bNEWT.java
@@ -0,0 +1,124 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ * 
+ *    1. Redistributions of source code must retain the above copyright notice, this list of
+ *       conditions and the following disclaimer.
+ * 
+ *    2. Redistributions in binary form must reproduce the above copyright notice, this list
+ *       of conditions and the following disclaimer in the documentation and/or other materials
+ *       provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+ 
+package com.jogamp.opengl.test.junit.newt;
+
+import java.io.IOException;
+import javax.media.nativewindow.NativeWindowFactory;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.jogamp.newt.Display;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.Screen;
+import com.jogamp.newt.ScreenMode;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+
+import java.util.Iterator;
+import java.util.List;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+
+public class TestScreenMode00bNEWT extends UITestCase {
+    static int width, height;
+    
+    static int waitTimeShort = 4; //1 sec
+    static int waitTimeLong = 6; //6 sec
+        
+    @BeforeClass
+    public static void initClass() {
+        NativeWindowFactory.initSingleton(true);
+        width  = 640;
+        height = 480;
+    }
+
+    @Test
+    public void testScreenModeInfo01() throws InterruptedException {
+        Display display = NewtFactory.createDisplay(null);
+        Screen screen = NewtFactory.createScreen(display, 0);
+        // screen.addReference();
+        
+        // put some load on the screen/display context ..
+        GLCapabilitiesImmutable caps = new GLCapabilities(null); 
+        GLWindow window = GLWindow.create(screen, caps);
+        window.addGLEventListener(new GearsES2());
+        window.setSize(256, 256);
+        window.setVisible(true);
+        Animator anim = new Animator(window);
+        anim.start();
+
+        Assert.assertEquals(true,window.isNativeValid());
+        Assert.assertEquals(true,screen.isNativeValid());
+        Assert.assertEquals(true,display.isNativeValid());
+        
+        List<ScreenMode> screenModes = screen.getScreenModes();
+        if(null != screenModes) {
+            Assert.assertTrue(screenModes.size()>0);
+            int i=0;
+            for(Iterator<ScreenMode> iter=screenModes.iterator(); iter.hasNext(); i++) {
+                System.err.println(i+": "+iter.next());
+            }
+            ScreenMode sm_o = screen.getOriginalScreenMode();
+            
+            Assert.assertNotNull(sm_o);            
+            ScreenMode sm_c = screen.getCurrentScreenMode();
+            Assert.assertNotNull(sm_c);
+            System.err.println("orig: "+sm_o);
+            System.err.println("curr: "+sm_c);
+            
+            for(i=0; i<1000; i++) {
+                sm_c = screen.getCurrentScreenMode();
+                Assert.assertNotNull(sm_c);
+                System.err.print(".");
+            }
+            System.err.println("!");
+        } else {
+            // no support ..
+            System.err.println("Your platform has no ScreenMode change support, sorry");
+        }
+        
+        // screen.removeReference();
+        anim.stop();
+        window.destroy();
+
+        Assert.assertEquals(false,window.isVisible());
+        Assert.assertEquals(false,window.isNativeValid());
+        Assert.assertEquals(false,screen.isNativeValid());
+        Assert.assertEquals(false,display.isNativeValid());
+    }
+
+    public static void main(String args[]) throws IOException {
+        String tstname = TestScreenMode00bNEWT.class.getName();
+        org.junit.runner.JUnitCore.main(tstname);
+    }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01NEWT.java
index a874d5fe1..c53c9a1de 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01NEWT.java
@@ -29,12 +29,12 @@
 package com.jogamp.opengl.test.junit.newt;
 
 import java.io.IOException;
-import javax.media.nativewindow.NativeWindowFactory;
 import javax.media.opengl.GLCapabilities;
 import javax.media.opengl.GLProfile;
 
 import com.jogamp.opengl.util.Animator;
 
+import org.junit.After;
 import org.junit.AfterClass;
 import org.junit.Assert;
 import org.junit.BeforeClass;
@@ -53,6 +53,12 @@ import com.jogamp.opengl.test.junit.util.UITestCase;
 import java.util.List;
 import javax.media.nativewindow.util.Dimension;
 
+/**
+ * Demonstrates fullscreen with and without ScreenMode change.
+ * 
+ * <p>
+ * Also documents NV RANDR/GL bug, see {@link TestScreenMode01NEWT#cleanupGL()}.</p> 
+ */
 public class TestScreenMode01NEWT extends UITestCase {
     static GLProfile glp;
     static int width, height;
@@ -62,7 +68,7 @@ public class TestScreenMode01NEWT extends UITestCase {
 
     @BeforeClass
     public static void initClass() {
-        NativeWindowFactory.initSingleton(true);
+        GLProfile.initSingleton(true);
         width  = 640;
         height = 480;
         glp = GLProfile.getDefault();
@@ -73,6 +79,43 @@ public class TestScreenMode01NEWT extends UITestCase {
         Thread.sleep(waitTimeShort);
     }
     
+    /**
+     * Following configurations results in a SIGSEGV:
+     * <pre>
+     *   Ubuntu 11.04 (natty), NV GTX 460, driver [280.10* - 285.03]
+     * </pre>
+     * 
+     * Situation:
+     * <pre>
+     *   1 - Create Screen, GLWindow (w/ context)
+     *   2 - ScreenMode change
+     *   3 - Destroy GLWindow (w/ context), Screen
+     *   4 - Create  Screen, GLWindow (w/ context) (*)
+     * </pre>
+     *   
+     * Step 4 causes the exception within 1st 'glXMakeContextCurrent(..)' call
+     * on the the created GL context.
+     * 
+     * Remedy:
+     * <pre>
+     *   A) Releasing all resources before step 4 .. works.
+     *   B) Holding the native Display/Screen in NEWT also works (ie screen.addReference()).
+     * </pre>
+     * 
+     * Hence there must be some correlations with the screen randr mode
+     * and some of the glcontext/gldrawables.
+     * 
+     * <pre>
+     * Remedy A) is demonstrated here
+     * Remedy B) is shown in {@link TestScreenMode01bNEWT}
+     * </pre>
+     */
+    @After
+    public void cleanupGL() throws InterruptedException {
+        GLProfile.shutdown();
+        GLProfile.initSingleton(true);
+    }
+    
     static GLWindow createWindow(Screen screen, GLCapabilities caps, int width, int height, boolean onscreen, boolean undecorated) {
         Assert.assertNotNull(caps);
         caps.setOnscreen(onscreen);
@@ -158,6 +201,8 @@ public class TestScreenMode01NEWT extends UITestCase {
         Assert.assertNotNull(smOrig);
         Assert.assertEquals(smCurrent, smOrig);
         System.err.println("[0] current/orig: "+smCurrent);
+        Assert.assertEquals(smCurrent.getRotatedWidth(), screen.getWidth());
+        Assert.assertEquals(smCurrent.getRotatedHeight(), screen.getHeight());
 
         screenModes = ScreenModeUtil.filterByRate(screenModes, smOrig.getMonitorMode().getRefreshRate());
         Assert.assertNotNull(screenModes);
@@ -178,6 +223,8 @@ public class TestScreenMode01NEWT extends UITestCase {
         screen.setCurrentScreenMode(sm);
         Assert.assertEquals(sm, screen.getCurrentScreenMode());
         Assert.assertNotSame(smOrig, screen.getCurrentScreenMode());
+        Assert.assertEquals(sm.getRotatedWidth(), screen.getWidth());
+        Assert.assertEquals(sm.getRotatedHeight(), screen.getHeight());
 
         Thread.sleep(waitTimeLong);
 
@@ -207,6 +254,8 @@ public class TestScreenMode01NEWT extends UITestCase {
 
         Assert.assertNotNull(smCurrent);
         Assert.assertEquals(smCurrent, smOrig);
+        Assert.assertEquals(smCurrent.getRotatedWidth(), screen.getWidth());
+        Assert.assertEquals(smCurrent.getRotatedHeight(), screen.getHeight());
 
         screen.destroy();
 
@@ -240,6 +289,8 @@ public class TestScreenMode01NEWT extends UITestCase {
         Assert.assertNotNull(smOrig);
         Assert.assertEquals(smCurrent, smOrig);
         System.err.println("[0] current/orig: "+smCurrent);
+        Assert.assertEquals(smCurrent.getRotatedWidth(), screen.getWidth());
+        Assert.assertEquals(smCurrent.getRotatedHeight(), screen.getHeight());
         
         List<ScreenMode> screenModes = screen.getScreenModes();
         if(null==screenModes) {
@@ -266,6 +317,8 @@ public class TestScreenMode01NEWT extends UITestCase {
 
         System.err.println("[0] set current: "+screenMode);
         screen.setCurrentScreenMode(screenMode);
+        Assert.assertEquals(screenMode.getRotatedWidth(), screen.getWidth());
+        Assert.assertEquals(screenMode.getRotatedHeight(), screen.getHeight());
         
         if(!preFS) {
             System.err.println("[0] set FS post 0: "+window.isFullscreen());
@@ -302,6 +355,8 @@ public class TestScreenMode01NEWT extends UITestCase {
 
         Assert.assertNotNull(smCurrent);
         Assert.assertEquals(smCurrent, smOrig);
+        Assert.assertEquals(smCurrent.getRotatedWidth(), screen.getWidth());
+        Assert.assertEquals(smCurrent.getRotatedHeight(), screen.getHeight());
 
         screen.destroy();
     }
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01bNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01bNEWT.java
new file mode 100644
index 000000000..6c505d58a
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01bNEWT.java
@@ -0,0 +1,190 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ * 
+ *    1. Redistributions of source code must retain the above copyright notice, this list of
+ *       conditions and the following disclaimer.
+ * 
+ *    2. Redistributions in binary form must reproduce the above copyright notice, this list
+ *       of conditions and the following disclaimer in the documentation and/or other materials
+ *       provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+ 
+package com.jogamp.opengl.test.junit.newt;
+
+import java.io.IOException;
+import javax.media.nativewindow.NativeWindowFactory;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.jogamp.newt.Display;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.Screen;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.ScreenMode;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.newt.util.ScreenModeUtil;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+import java.util.List;
+import javax.media.nativewindow.util.Dimension;
+
+/**
+ * Documents remedy B) for NV RANDR/GL bug
+ * 
+ * @see TestScreenMode01NEWT#cleanupGL()
+ */
+public class TestScreenMode01bNEWT extends UITestCase {
+    static GLProfile glp;
+    static int width, height;
+    
+    static int waitTimeShort = 2000;
+    static int waitTimeLong = 2000;
+
+    @BeforeClass
+    public static void initClass() {
+        GLProfile.initSingleton(true);
+        width  = 100;
+        height = 100;
+        glp = GLProfile.getDefault();
+    }
+
+    @AfterClass
+    public static void releaseClass() throws InterruptedException {
+        Thread.sleep(waitTimeShort);
+    }
+    
+    static Window createWindow(Screen screen, GLCapabilities caps, String name, int x, int y, int width, int height) {
+        Assert.assertNotNull(caps);
+
+        GLWindow window = GLWindow.create(screen, caps);
+        // Window window = NewtFactory.createWindow(screen, caps);
+        window.setTitle(name);
+        window.setPosition(x, y);
+        window.setSize(width, height);
+        window.addGLEventListener(new GearsES2());
+        Assert.assertNotNull(window);
+        window.setVisible(true);
+        return window;
+    }
+
+    static void destroyWindow(Window window) {
+        if(null!=window) {
+            window.destroy();
+        }
+    }
+    
+    @Test
+    public void testScreenModeChange01() throws InterruptedException {
+        Thread.sleep(waitTimeShort);
+
+        GLCapabilities caps = new GLCapabilities(glp);
+        Assert.assertNotNull(caps);
+        Display display = NewtFactory.createDisplay(null); // local display
+        Assert.assertNotNull(display);
+        Screen screen  = NewtFactory.createScreen(display, 0); // screen 0
+        Assert.assertNotNull(screen);
+        Window window0 = createWindow(screen, caps, "win0", 0, 0, width, height);
+        Assert.assertNotNull(window0);        
+
+        List<ScreenMode> screenModes = screen.getScreenModes();
+        if(null==screenModes) {
+            // no support ..
+            System.err.println("Your platform has no ScreenMode change support, sorry");
+            destroyWindow(window0);
+            return;
+        }
+        Assert.assertTrue(screenModes.size()>0);
+
+        ScreenMode smCurrent = screen.getCurrentScreenMode();
+        Assert.assertNotNull(smCurrent);
+        ScreenMode smOrig = screen.getOriginalScreenMode();
+        Assert.assertNotNull(smOrig);
+        Assert.assertEquals(smCurrent, smOrig);
+        System.err.println("[0] current/orig: "+smCurrent);
+
+        screenModes = ScreenModeUtil.filterByRate(screenModes, smOrig.getMonitorMode().getRefreshRate());
+        Assert.assertNotNull(screenModes);
+        Assert.assertTrue(screenModes.size()>0);
+        screenModes = ScreenModeUtil.filterByRotation(screenModes, 0);
+        Assert.assertNotNull(screenModes);
+        Assert.assertTrue(screenModes.size()>0);
+        screenModes = ScreenModeUtil.filterByResolution(screenModes, new Dimension(801, 601));
+        Assert.assertNotNull(screenModes);
+        Assert.assertTrue(screenModes.size()>0);
+        
+        screenModes = ScreenModeUtil.getHighestAvailableBpp(screenModes);
+        Assert.assertNotNull(screenModes);
+        Assert.assertTrue(screenModes.size()>0);
+
+        ScreenMode sm = (ScreenMode) screenModes.get(0);
+        System.err.println("[0] set current: "+sm);
+        screen.setCurrentScreenMode(sm);
+        Assert.assertEquals(sm, screen.getCurrentScreenMode());
+        Assert.assertNotSame(smOrig, screen.getCurrentScreenMode());
+
+        Thread.sleep(waitTimeShort);
+
+        // check reset ..
+
+        Assert.assertEquals(true,display.isNativeValid());
+        Assert.assertEquals(true,screen.isNativeValid());
+        Assert.assertEquals(true,window0.isNativeValid());
+        Assert.assertEquals(true,window0.isVisible());
+
+        screen.addReference(); // keep it alive !
+        screen.setCurrentScreenMode(smOrig);
+        
+        destroyWindow(window0);
+        Assert.assertEquals(false,window0.isVisible());
+        Assert.assertEquals(false,window0.isNativeValid());
+        Assert.assertEquals(true,screen.isNativeValid()); // alive !
+        Assert.assertEquals(true,display.isNativeValid());
+                
+        Thread.sleep(waitTimeShort);
+
+        Window window1 = createWindow(screen, caps, "win1", 
+                                      width+window0.getInsets().getTotalWidth(), 0, 
+                                      width, height);
+        Assert.assertNotNull(window1);
+        Assert.assertEquals(true,window1.isNativeValid());
+        Assert.assertEquals(true,window1.isVisible());
+        
+        Thread.sleep(waitTimeShort);
+        
+        destroyWindow(window1);
+        Assert.assertEquals(false,window1.isNativeValid());
+        Assert.assertEquals(false,window1.isVisible());
+        
+        screen.removeReference();
+        Assert.assertEquals(false,screen.isNativeValid());
+        Assert.assertEquals(false,display.isNativeValid());                
+    }
+
+    public static void main(String args[]) throws IOException {
+        String tstname = TestScreenMode01bNEWT.class.getName();
+        org.junit.runner.JUnitCore.main(tstname);
+    }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode02NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode02NEWT.java
index 896b02263..c5c11682c 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode02NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode02NEWT.java
@@ -29,7 +29,6 @@
 package com.jogamp.opengl.test.junit.newt;
 
 import java.io.IOException;
-import javax.media.nativewindow.NativeWindowFactory;
 import javax.media.opengl.GLCapabilities;
 import javax.media.opengl.GLProfile;
 
@@ -61,7 +60,7 @@ public class TestScreenMode02NEWT extends UITestCase {
 
     @BeforeClass
     public static void initClass() {
-        NativeWindowFactory.initSingleton(true);
+        GLProfile.initSingleton(true);
         width  = 640;
         height = 480;
         glp = GLProfile.getDefault();
-- 
cgit v1.2.3