diff options
author | Sven Gothel <[email protected]> | 2014-02-23 14:51:06 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2014-02-23 14:51:06 +0100 |
commit | 3352601e0860584509adf2b76f993d03893ded4b (patch) | |
tree | 974fccc8c0eb2f5ad9d4ffd741dfc35869ed67b5 /src/test | |
parent | f51933f0ebe9ae030c26c066e59a728ce08b8559 (diff) | |
parent | c67de337a8aaf52e36104c3f13e273aa19d21f1f (diff) |
Merge branch 'master' into stash_glyphcache
Conflicts:
make/scripts/tests.sh
src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java
src/jogl/classes/com/jogamp/graph/curve/Region.java
src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java
src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java
src/jogl/classes/com/jogamp/graph/curve/opengl/Renderer.java
src/jogl/classes/com/jogamp/graph/curve/opengl/TextRenderer.java
src/jogl/classes/com/jogamp/graph/font/Font.java
src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java
src/jogl/classes/jogamp/graph/curve/text/GlyphShape.java
src/jogl/classes/jogamp/graph/curve/text/GlyphString.java
src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java
src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java
src/jogl/classes/jogamp/graph/font/typecast/TypecastRenderer.java
Diffstat (limited to 'src/test')
466 files changed, 62185 insertions, 5692 deletions
diff --git a/src/test/com/jogamp/opengl/test/android/LauncherUtil.java b/src/test/com/jogamp/opengl/test/android/LauncherUtil.java index 11416cd67..ac69e1e4e 100644 --- a/src/test/com/jogamp/opengl/test/android/LauncherUtil.java +++ b/src/test/com/jogamp/opengl/test/android/LauncherUtil.java @@ -65,11 +65,15 @@ public class LauncherUtil { /** The host <code>jogamp.org</code> */ public static final String HOST = "jogamp.org"; - static final String PKG = "pkg"; + static final String SYS_PKG = "sys"; + + static final String USR_PKG = "pkg"; + + static final String ARG = "arg"; public static abstract class BaseActivityLauncher extends Activity { final OrderedProperties props = new OrderedProperties(); - + final ArrayList<String> args = new ArrayList<String>(); /** * Returns the default {@link LauncherUtil#LAUNCH_ACTIVITY_NORMAL} action. * <p> @@ -86,6 +90,14 @@ public class LauncherUtil { */ public final OrderedProperties getProperties() { return props; } + /** + * Returns the commandline arguments, which are being propagated to the target activity. + * <p> + * Maybe be used to set custom commandline arguments. + * </p> + */ + public final ArrayList<String> getArguments() { return args; } + /** Custom initialization hook which can be overriden to setup data, e.g. fill the properties retrieved by {@link #getProperties()}. */ public void init() { } @@ -95,8 +107,11 @@ public class LauncherUtil { /** Must return the downstream Activity class name */ public abstract String getActivityName(); - /** Must return a list of required packages, at least one. */ - public abstract List<String> getPackages(); + /** Must return a list of required user packages, at least one containing the activity. */ + public abstract List<String> getUsrPackages(); + + /** Return a list of required system packages w/ native libraries, may return null or a zero sized list. */ + public abstract List<String> getSysPackages(); @Override public void onCreate(Bundle savedInstanceState) { @@ -106,8 +121,10 @@ public class LauncherUtil { final DataSet data = new DataSet(); data.setActivityName(getActivityName()); - data.addAllPackages(getPackages()); + data.addAllSysPackages(getSysPackages()); + data.addAllUsrPackages(getUsrPackages()); data.addAllProperties(props); + data.addAllArguments(args); final Intent intent = LauncherUtil.getIntent(getAction(), data); Log.d(getClass().getSimpleName(), "Launching Activity: "+intent); @@ -124,8 +141,14 @@ public class LauncherUtil { ArrayList<String> keyList = new ArrayList<String>(); public final void setProperty(String key, String value) { - if(key.equals(PKG)) { - throw new IllegalArgumentException("Illegal property key, '"+PKG+"' is reserved"); + if(key.equals(SYS_PKG)) { + throw new IllegalArgumentException("Illegal property key, '"+SYS_PKG+"' is reserved"); + } + if(key.equals(USR_PKG)) { + throw new IllegalArgumentException("Illegal property key, '"+USR_PKG+"' is reserved"); + } + if(key.equals(ARG)) { + throw new IllegalArgumentException("Illegal property key, '"+ARG+"' is reserved"); } final String oval = map.put(key, value); if(null != oval) { @@ -164,6 +187,17 @@ public class LauncherUtil { public final List<String> getPropertyKeys() { return keyList; } } + /** + * Data set to transfer from and to launch URI consisting out of: + * <ul> + * <li>system packages w/ native libraries used on Android, which may use a cached ClassLoader, see {@link DataSet#getSysPackages()}.</li> + * <li>user packages w/o native libraries used on Android, which do not use a cached ClassLoader, see {@link DataSet#getUsrPackages()}.</li> + * <li>activity name, used to launch an Android activity, see {@link DataSet#getActivityName()}.</li> + * <li>properties, which will be added to the system properties, see {@link DataSet#getProperties()}.</li> + * <li>arguments, used to launch a class main-entry, see {@link DataSet#getArguments()}.</li> + * </ul> + * {@link DataSet#getUri()} returns a URI representation of all components. + */ public static class DataSet { static final char SLASH = '/'; static final char QMARK = '?'; @@ -173,19 +207,29 @@ public class LauncherUtil { static final String EMPTY = ""; String activityName = null; - ArrayList<String> packages = new ArrayList<String>(); + ArrayList<String> sysPackages = new ArrayList<String>(); + ArrayList<String> usrPackages = new ArrayList<String>(); OrderedProperties properties = new OrderedProperties(); + ArrayList<String> arguments = new ArrayList<String>(); public final void setActivityName(String name) { activityName = name; } public final String getActivityName() { return activityName; } + + public final void addSysPackage(String p) { + sysPackages.add(p); + } + public final void addAllSysPackages(List<String> plist) { + sysPackages.addAll(plist); + } + public final List<String> getSysPackages() { return sysPackages; } - public final void addPackage(String p) { - packages.add(p); + public final void addUsrPackage(String p) { + usrPackages.add(p); } - public final void addAllPackages(List<String> plist) { - packages.addAll(plist); + public final void addAllUsrPackages(List<String> plist) { + usrPackages.addAll(plist); } - public final List<String> getPackages() { return packages; } + public final List<String> getUsrPackages() { return usrPackages; } public final void setProperty(String key, String value) { properties.setProperty(key, value); @@ -201,31 +245,70 @@ public class LauncherUtil { } public final String getProperty(String key) { return properties.getProperty(key); } public final OrderedProperties getProperties() { return properties; } - public final List<String> getPropertyKeys() { return properties.getPropertyKeys(); } + public final List<String> getPropertyKeys() { return properties.getPropertyKeys(); } + + public final void addArgument(String arg) { arguments.add(arg); } + public final void addAllArguments(List<String> args) { + arguments.addAll(args); + } + public final ArrayList<String> getArguments() { return arguments; } public final Uri getUri() { StringBuilder sb = new StringBuilder(); sb.append(SCHEME).append(COLSLASH2).append(HOST).append(SLASH).append(getActivityName()); + boolean needsQMark = true; boolean needsSep = false; - if(packages.size()>0) { - sb.append(QMARK); - for(int i=0; i<packages.size(); i++) { + if(sysPackages.size()>0) { + if( needsQMark ) { + sb.append(QMARK); + needsQMark = false; + } + for(int i=0; i<sysPackages.size(); i++) { if(needsSep) { sb.append(AMPER); } - sb.append(PKG).append(ASSIG).append(packages.get(i)); + sb.append(SYS_PKG).append(ASSIG).append(sysPackages.get(i)); needsSep = true; } } - Iterator<String> argKeys = properties.keyList.iterator(); - while(argKeys.hasNext()) { + if(usrPackages.size()>0) { + if( needsQMark ) { + sb.append(QMARK); + needsQMark = false; + } + for(int i=0; i<usrPackages.size(); i++) { if(needsSep) { sb.append(AMPER); } - final String key = argKeys.next(); - sb.append(key).append(ASSIG).append(properties.map.get(key)); + sb.append(USR_PKG).append(ASSIG).append(usrPackages.get(i)); needsSep = true; + } } + Iterator<String> propKeys = properties.keyList.iterator(); + while(propKeys.hasNext()) { + if( needsQMark ) { + sb.append(QMARK); + needsQMark = false; + } + if(needsSep) { + sb.append(AMPER); + } + final String key = propKeys.next(); + sb.append(key).append(ASSIG).append(properties.map.get(key)); + needsSep = true; + } + Iterator<String> args = arguments.iterator(); + while(args.hasNext()) { + if( needsQMark ) { + sb.append(QMARK); + needsQMark = false; + } + if(needsSep) { + sb.append(AMPER); + } + sb.append(ARG).append(ASSIG).append(args.next()); + needsSep = true; + } return Uri.parse(sb.toString()); } @@ -255,7 +338,7 @@ public class LauncherUtil { int q_b = q_e + 1; // next term q_e = q.indexOf(AMPER, q_b); if(0 == q_e) { - // single seperator + // single separator continue; } if(0 > q_e) { @@ -269,18 +352,28 @@ public class LauncherUtil { // assignment final String k = part.substring(0, assignment); final String v = part.substring(assignment+1); - if(k.equals(PKG)) { + if(k.equals(SYS_PKG)) { if(v.length()==0) { throw new IllegalArgumentException("Empty package name: part <"+part+">, query <"+q+"> of "+uri); } - data.addPackage(v); + data.addSysPackage(v); + } else if(k.equals(USR_PKG)) { + if(v.length()==0) { + throw new IllegalArgumentException("Empty package name: part <"+part+">, query <"+q+"> of "+uri); + } + data.addUsrPackage(v); + } else if(k.equals(ARG)) { + if(v.length()==0) { + throw new IllegalArgumentException("Empty argument name: part <"+part+">, query <"+q+"> of "+uri); + } + data.addArgument(v); } else { data.setProperty(k, v); } } else { // property key only - if(part.equals(PKG)) { - throw new IllegalArgumentException("Empty package name: part <"+part+">, query <"+q+"> of "+uri); + if( part.equals(USR_PKG) || part.equals(ARG) ) { + throw new IllegalArgumentException("Reserved key <"+part+"> in query <"+q+"> of "+uri); } data.setProperty(part, EMPTY); } @@ -304,23 +397,34 @@ public class LauncherUtil { public static void main(String[] args) { if(args.length==0) { args = new String[] { - SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+PKG+"=jogamp.pack1&"+PKG+"=javax.pack2&"+PKG+"=com.jogamp.pack3&jogamp.common.debug=true&com.jogamp.test=false", - SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+PKG+"=jogamp.pack1&jogamp.common.debug=true&com.jogamp.test=false", - SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+PKG+"=jogamp.pack1" + SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+SYS_PKG+"=jogamp.pack1&"+SYS_PKG+"=javax.pack2&"+USR_PKG+"=com.jogamp.pack3&"+USR_PKG+"=com.jogamp.pack4&jogamp.common.debug=true&com.jogamp.test=false", + SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+SYS_PKG+"=jogamp.pack1&jogamp.common.debug=true&com.jogamp.test=false", + SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+USR_PKG+"=jogamp.pack1&jogamp.common.debug=true&com.jogamp.test=false", + SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+USR_PKG+"=jogamp.pack1&"+USR_PKG+"=com.jogamp.pack2", + SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+USR_PKG+"=jogamp.pack1&"+USR_PKG+"=javax.pack2&"+USR_PKG+"=com.jogamp.pack3&jogamp.common.debug=true&com.jogamp.test=false&"+ARG+"=arg1&"+ARG+"=arg2=arg2value&"+ARG+"=arg3", + SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+USR_PKG+"=jogamp.pack1&jogamp.common.debug=true&com.jogamp.test=false&"+ARG+"=arg1&"+ARG+"=arg2=arg2value&"+ARG+"=arg3", + SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+USR_PKG+"=jogamp.pack1&"+ARG+"=arg1&"+ARG+"=arg2=arg2value&"+ARG+"=arg3" }; } + int errors = 0; for(int i=0; i<args.length; i++) { String uri_s = args[i]; Uri uri0 = Uri.parse(uri_s); DataSet data = DataSet.create(uri0); if(null == data) { + errors++; System.err.println("Error: NULL JogAmpLauncherUtil: <"+uri_s+"> -> "+uri0+" -> NULL"); - } - Uri uri1 = data.getUri(); - if(!uri0.equals(uri1)) { - System.err.println("Error: Not equal: <"+uri_s+"> -> "+uri0+" -> "+uri1); + } else { + Uri uri1 = data.getUri(); + if(!uri0.equals(uri1)) { + errors++; + System.err.println("Error: Not equal: <"+uri_s+"> -> "+uri0+" -> "+uri1); + } else { + System.err.println("OK: "+uri1); + } } } + System.err.println("LauncherUtil Self Test: Errors: "+errors); } } diff --git a/src/test/com/jogamp/opengl/test/android/MovieCubeActivity0.java b/src/test/com/jogamp/opengl/test/android/MovieCubeActivity0.java index 59e78936d..1de095161 100644 --- a/src/test/com/jogamp/opengl/test/android/MovieCubeActivity0.java +++ b/src/test/com/jogamp/opengl/test/android/MovieCubeActivity0.java @@ -3,14 +3,14 @@ * * 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 @@ -20,7 +20,7 @@ * 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. @@ -28,13 +28,15 @@ package com.jogamp.opengl.test.android; import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.URISyntaxException; import java.net.URLConnection; import java.util.Arrays; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLProfile; -import jogamp.newt.driver.android.AndroidWindow; import jogamp.newt.driver.android.NewtBaseActivity; import com.jogamp.common.util.IOUtil; @@ -45,38 +47,37 @@ import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieCube; import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.av.GLMediaPlayer; +import com.jogamp.opengl.util.av.GLMediaPlayer.GLMediaEventListener; +import com.jogamp.opengl.util.av.GLMediaPlayer.StreamException; +import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame; -import android.content.Context; import android.os.Bundle; import android.util.Log; -import android.view.inputmethod.InputMethodManager; public class MovieCubeActivity0 extends NewtBaseActivity { static String TAG = "MovieCubeActivity0"; - + MouseAdapter showKeyboardMouseListener = new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { - if(e.getPressure()>2f) { - final AndroidWindow win = (AndroidWindow)e.getSource(); - InputMethodManager mgr = (InputMethodManager) win.getAndroidView().getContext().getSystemService(Context.INPUT_METHOD_SERVICE); - mgr.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); // shows keyboard .. - win.getAndroidView().requestFocus(); + if( e.getPointerCount() == 4 && e.getPressure(0, true) > 0.7f ) { + ((com.jogamp.newt.Window) e.getSource()).setKeyboardVisible(true); } } }; - + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - - String[] urls0 = new String[] { + + String[] streamLocs = new String[] { System.getProperty("jnlp.media0_url2"), System.getProperty("jnlp.media0_url1"), - System.getProperty("jnlp.media0_url0") }; - final URLConnection urlConnection0 = getResource(urls0, 0); - if(null == urlConnection0) { throw new RuntimeException("no media reachable: "+Arrays.asList(urls0)); } - + System.getProperty("jnlp.media0_url0") }; + final URI streamLoc = getURI(streamLocs, 0, false); + if(null == streamLoc) { throw new RuntimeException("no media reachable: "+Arrays.asList(streamLocs)); } + // also initializes JOGL final GLCapabilities capsMain = new GLCapabilities(GLProfile.getGL2ES2()); capsMain.setBackgroundOpaque(false); @@ -85,41 +86,82 @@ public class MovieCubeActivity0 extends NewtBaseActivity { final com.jogamp.newt.Display dpy = NewtFactory.createDisplay(null); final com.jogamp.newt.Screen scrn = NewtFactory.createScreen(dpy, 0); scrn.addReference(); - + try { - final Animator animator = new Animator(); - setAnimator(animator); - - // Main - final MovieCube demoMain = new MovieCube(urlConnection0, -2.3f, 0f, 0f); + final Animator anim = new Animator(); + + // Main final GLWindow glWindowMain = GLWindow.create(scrn, capsMain); glWindowMain.setFullscreen(true); setContentView(getWindow(), glWindowMain); - glWindowMain.addMouseListener(showKeyboardMouseListener); - glWindowMain.addGLEventListener(demoMain); - animator.add(glWindowMain); + anim.add(glWindowMain); glWindowMain.setVisible(true); - - // animator.setUpdateFPSFrames(60, System.err); - animator.setUpdateFPSFrames(-1, null); - animator.resetFPSCounter(); + glWindowMain.addMouseListener(showKeyboardMouseListener); + + final MovieCube demoMain = new MovieCube(MovieCube.zoom_def, 0f, 0f); + final GLMediaPlayer mPlayer = demoMain.getGLMediaPlayer(); + mPlayer.addEventListener(new GLMediaEventListener() { + @Override + public void newFrameAvailable(GLMediaPlayer ts, TextureFrame newFrame, long when) { + } + + @Override + public void attributesChanged(final GLMediaPlayer mp, int event_mask, long when) { + System.err.println("MovieCubeActivity0 AttributesChanges: events_mask 0x"+Integer.toHexString(event_mask)+", when "+when); + System.err.println("MovieCubeActivity0 State: "+mp); + if( 0 != ( GLMediaEventListener.EVENT_CHANGE_INIT & event_mask ) ) { + glWindowMain.addGLEventListener(demoMain); + anim.setUpdateFPSFrames(60, null); + anim.resetFPSCounter(); + } + if( 0 != ( GLMediaEventListener.EVENT_CHANGE_PLAY & event_mask ) ) { + anim.resetFPSCounter(); + } + if( 0 != ( ( GLMediaEventListener.EVENT_CHANGE_ERR | GLMediaEventListener.EVENT_CHANGE_EOS ) & event_mask ) ) { + final StreamException se = mPlayer.getStreamException(); + if( null != se ) { + se.printStackTrace(); + } + getActivity().finish(); + } + } + }); + demoMain.initStream(streamLoc, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, 0); } catch (IOException e) { e.printStackTrace(); } - + scrn.removeReference(); Log.d(TAG, "onCreate - X"); } - - static URLConnection getResource(String path[], int off) { - URLConnection uc = null; - for(int i=off; null==uc && i<path.length; i++) { + + static URI getURI(String path[], int off, boolean checkAvail) { + URI uri = null; + for(int i=off; null==uri && i<path.length; i++) { if(null != path[i] && path[i].length()>0) { - uc = IOUtil.getResource(path[i], null); - Log.d(TAG, "Stream: <"+path[i]+">: "+(null!=uc)); + if( checkAvail ) { + final URLConnection uc = IOUtil.getResource(path[i], null); + if( null != uc ) { + try { + uri = uc.getURL().toURI(); + } catch (URISyntaxException e) { + uri = null; + } + if( uc instanceof HttpURLConnection ) { + ((HttpURLConnection)uc).disconnect(); + } + } + } else { + try { + uri = new URI(path[i]); + } catch (URISyntaxException e) { + uri = null; + } + } + Log.d(TAG, "Stream: <"+path[i]+">: "+(null!=uri)); } } - return uc; + return uri; } } diff --git a/src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher0.java b/src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher0.java index 4f24fc9b8..1e0d6067f 100644 --- a/src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher0.java +++ b/src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher0.java @@ -3,14 +3,14 @@ * * 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 @@ -20,7 +20,7 @@ * 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. @@ -35,12 +35,12 @@ import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties; public class MovieCubeActivityLauncher0 extends LauncherUtil.BaseActivityLauncher { static String demo = "com.jogamp.opengl.test.android.MovieCubeActivity0"; - // static String[] pkgs = new String[] { "com.jogamp.common", "javax.media.opengl", "com.jogamp.opengl.test" }; - static String[] pkgs = new String[] { "com.jogamp.opengl.test" }; - + static String[] sys_pkgs = new String[] { "com.jogamp.common", "javax.media.opengl" }; + static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" }; + @Override public void init() { - final OrderedProperties props = getProperties(); + final OrderedProperties props = getProperties(); // props.setProperty("jnlp.media0_url2", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_640x360.m4v"); props.setProperty("jnlp.media0_url2", ""); props.setProperty("jnlp.media0_url1", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4"); @@ -49,31 +49,40 @@ public class MovieCubeActivityLauncher0 extends LauncherUtil.BaseActivityLaunche // props.setProperty("jogamp.debug.JNILibLoader", "true"); // props.setProperty("jogamp.debug.NativeLibrary", "true"); // props.setProperty("jogamp.debug.NativeLibrary.Lookup", "true"); - // props.setProperty("jogamp.debug.IOUtil", "true"); + // props.setProperty("jogamp.debug.IOUtil", "true"); + // props.setProperty("jogamp.debug.Lock", "true"); + // props.setProperty("jogamp.debug.Lock.TraceLock", "true"); // props.setProperty("nativewindow.debug", "all"); - props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); + // props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); // props.setProperty("jogl.debug", "all"); // props.setProperty("jogl.debug.GLProfile", "true"); - props.setProperty("jogl.debug.GLDrawable", "true"); - props.setProperty("jogl.debug.GLContext", "true"); + // props.setProperty("jogl.debug.GLDrawable", "true"); + // props.setProperty("jogl.debug.GLContext", "true"); + props.setProperty("jogl.debug.GLMediaPlayer", "true"); props.setProperty("jogl.debug.GLSLCode", "true"); - // props.setProperty("jogl.debug.CapabilitiesChooser", "true"); + // props.setProperty("jogl.debug.CapabilitiesChooser", "true"); // props.setProperty("jogl.debug.GLSLState", "true"); // props.setProperty("jogl.debug.DebugGL", "true"); // props.setProperty("jogl.debug.TraceGL", "true"); // props.setProperty("newt.debug", "all"); // props.setProperty("newt.debug.Window", "true"); // props.setProperty("newt.debug.Window.MouseEvent", "true"); - // props.setProperty("newt.debug.Window.KeyEvent", "true"); + // props.setProperty("newt.debug.Window.KeyEvent", "true"); props.setProperty("jogamp.debug.IOUtil", "true"); } - + @Override public String getActivityName() { return demo; } + + @Override + public List<String> getSysPackages() { + return Arrays.asList(sys_pkgs); + } + @Override - public List<String> getPackages() { - return Arrays.asList(pkgs); + public List<String> getUsrPackages() { + return Arrays.asList(usr_pkgs); } } diff --git a/src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher1a.java b/src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher1a.java new file mode 100644 index 000000000..c4eea084a --- /dev/null +++ b/src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher1a.java @@ -0,0 +1,87 @@ +/** + * Copyright 2012 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.android; + +import java.util.Arrays; +import java.util.List; + +import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties; + +public class MovieCubeActivityLauncher1a extends LauncherUtil.BaseActivityLauncher { + + static String demo = "com.jogamp.opengl.test.android.MovieCubeActivity0"; + static String[] sys_pkgs = new String[] { "com.jogamp.common", "javax.media.opengl" }; + static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" }; + + @Override + public void init() { + final OrderedProperties props = getProperties(); + props.setProperty("jnlp.media0_url2", "camera:/0"); + props.setProperty("jnlp.media0_url1", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4"); + props.setProperty("jnlp.media0_url0", "file:///mnt/sdcard/Movies/BigBuckBunny_320x180.mp4"); + props.setProperty("jnlp.media1_url0", "http://archive.org/download/ElephantsDream/ed_1024_512kb.mp4"); + // props.setProperty("jogamp.debug.JNILibLoader", "true"); + // props.setProperty("jogamp.debug.NativeLibrary", "true"); + // props.setProperty("jogamp.debug.NativeLibrary.Lookup", "true"); + // props.setProperty("jogamp.debug.IOUtil", "true"); + // props.setProperty("jogamp.debug.Lock", "true"); + // props.setProperty("jogamp.debug.Lock.TraceLock", "true"); + // props.setProperty("nativewindow.debug", "all"); + // props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); + // props.setProperty("jogl.debug", "all"); + // props.setProperty("jogl.debug.GLProfile", "true"); + // props.setProperty("jogl.debug.GLDrawable", "true"); + // props.setProperty("jogl.debug.GLContext", "true"); + props.setProperty("jogl.debug.GLMediaPlayer", "true"); + props.setProperty("jogl.debug.GLSLCode", "true"); + // props.setProperty("jogl.debug.CapabilitiesChooser", "true"); + // props.setProperty("jogl.debug.GLSLState", "true"); + // props.setProperty("jogl.debug.DebugGL", "true"); + // props.setProperty("jogl.debug.TraceGL", "true"); + // props.setProperty("newt.debug", "all"); + // props.setProperty("newt.debug.Window", "true"); + // props.setProperty("newt.debug.Window.MouseEvent", "true"); + // props.setProperty("newt.debug.Window.KeyEvent", "true"); + // props.setProperty("jogamp.debug.IOUtil", "true"); + } + + @Override + public String getActivityName() { + return demo; + } + + @Override + public List<String> getSysPackages() { + return Arrays.asList(sys_pkgs); + } + + @Override + public List<String> getUsrPackages() { + return Arrays.asList(usr_pkgs); + } +} diff --git a/src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher1b.java b/src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher1b.java new file mode 100644 index 000000000..26b61dd16 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher1b.java @@ -0,0 +1,87 @@ +/** + * Copyright 2012 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.android; + +import java.util.Arrays; +import java.util.List; + +import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties; + +public class MovieCubeActivityLauncher1b extends LauncherUtil.BaseActivityLauncher { + + static String demo = "com.jogamp.opengl.test.android.MovieCubeActivity0"; + static String[] sys_pkgs = new String[] { "com.jogamp.common", "javax.media.opengl" }; + static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" }; + + @Override + public void init() { + final OrderedProperties props = getProperties(); + props.setProperty("jnlp.media0_url2", "camera:/1"); + props.setProperty("jnlp.media0_url1", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4"); + props.setProperty("jnlp.media0_url0", "file:///mnt/sdcard/Movies/BigBuckBunny_320x180.mp4"); + props.setProperty("jnlp.media1_url0", "http://archive.org/download/ElephantsDream/ed_1024_512kb.mp4"); + // props.setProperty("jogamp.debug.JNILibLoader", "true"); + // props.setProperty("jogamp.debug.NativeLibrary", "true"); + // props.setProperty("jogamp.debug.NativeLibrary.Lookup", "true"); + // props.setProperty("jogamp.debug.IOUtil", "true"); + // props.setProperty("jogamp.debug.Lock", "true"); + // props.setProperty("jogamp.debug.Lock.TraceLock", "true"); + // props.setProperty("nativewindow.debug", "all"); + // props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); + // props.setProperty("jogl.debug", "all"); + // props.setProperty("jogl.debug.GLProfile", "true"); + // props.setProperty("jogl.debug.GLDrawable", "true"); + // props.setProperty("jogl.debug.GLContext", "true"); + // props.setProperty("jogl.debug.GLMediaPlayer", "true"); + props.setProperty("jogl.debug.GLSLCode", "true"); + // props.setProperty("jogl.debug.CapabilitiesChooser", "true"); + // props.setProperty("jogl.debug.GLSLState", "true"); + // props.setProperty("jogl.debug.DebugGL", "true"); + // props.setProperty("jogl.debug.TraceGL", "true"); + // props.setProperty("newt.debug", "all"); + // props.setProperty("newt.debug.Window", "true"); + // props.setProperty("newt.debug.Window.MouseEvent", "true"); + // props.setProperty("newt.debug.Window.KeyEvent", "true"); + // props.setProperty("jogamp.debug.IOUtil", "true"); + } + + @Override + public String getActivityName() { + return demo; + } + + @Override + public List<String> getSysPackages() { + return Arrays.asList(sys_pkgs); + } + + @Override + public List<String> getUsrPackages() { + return Arrays.asList(usr_pkgs); + } +} diff --git a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivity0.java b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivity0.java index 11babf187..b5a9ce580 100644 --- a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivity0.java +++ b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivity0.java @@ -27,24 +27,30 @@ */ package com.jogamp.opengl.test.android; -import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.URISyntaxException; import java.net.URLConnection; import java.util.Arrays; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLProfile; -import jogamp.newt.driver.android.AndroidWindow; import jogamp.newt.driver.android.NewtBaseActivity; import com.jogamp.common.util.IOUtil; import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Window; import com.jogamp.newt.event.MouseAdapter; import com.jogamp.newt.event.MouseEvent; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSimple; import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.av.GLMediaPlayer; +import com.jogamp.opengl.util.av.GLMediaPlayer.GLMediaEventListener; +import com.jogamp.opengl.util.av.GLMediaPlayer.StreamException; +import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame; import android.os.Bundle; import android.util.Log; @@ -55,8 +61,8 @@ public class MovieSimpleActivity0 extends NewtBaseActivity { MouseAdapter toFrontMouseListener = new MouseAdapter() { public void mouseClicked(MouseEvent e) { Object src = e.getSource(); - if(src instanceof AndroidWindow) { - ((AndroidWindow)src).requestFocus(false); + if(src instanceof Window) { + ((Window)src).requestFocus(false); } } }; @@ -64,12 +70,12 @@ public class MovieSimpleActivity0 extends NewtBaseActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - String[] urls0 = new String[] { + final String[] streamLocs = new String[] { System.getProperty("jnlp.media0_url2"), System.getProperty("jnlp.media0_url1"), System.getProperty("jnlp.media0_url0") }; - final URLConnection urlConnection0 = getResource(urls0, 0); - if(null == urlConnection0) { throw new RuntimeException("no media reachable: "+Arrays.asList(urls0)); } + final URI streamLoc = getURI(streamLocs, 0, false); + if(null == streamLoc) { throw new RuntimeException("no media reachable: "+Arrays.asList(streamLocs)); } // also initializes JOGL final GLCapabilities capsMain = new GLCapabilities(GLProfile.getGL2ES2()); @@ -80,40 +86,73 @@ public class MovieSimpleActivity0 extends NewtBaseActivity { final com.jogamp.newt.Screen scrn = NewtFactory.createScreen(dpy, 0); scrn.addReference(); - try { - final Animator animator = new Animator(); - setAnimator(animator); - - // Main - final MovieSimple demoMain = new MovieSimple(urlConnection0); - demoMain.setScaleOrig(true); - final GLWindow glWindowMain = GLWindow.create(scrn, capsMain); - glWindowMain.setFullscreen(true); - setContentView(getWindow(), glWindowMain); - glWindowMain.addGLEventListener(demoMain); - animator.add(glWindowMain); - glWindowMain.setVisible(true); - - animator.setUpdateFPSFrames(60, System.err); - // animator.setUpdateFPSFrames(-1, null); - animator.resetFPSCounter(); - } catch (IOException e) { - e.printStackTrace(); - } + final Animator anim = new Animator(); + + // Main + final GLWindow glWindowMain = GLWindow.create(scrn, capsMain); + glWindowMain.setFullscreen(true); + setContentView(getWindow(), glWindowMain); + anim.add(glWindowMain); + glWindowMain.setVisible(true); + + final MovieSimple demoMain = new MovieSimple(null); + demoMain.setScaleOrig(true); + final GLMediaPlayer mPlayer = demoMain.getGLMediaPlayer(); + mPlayer.addEventListener( new GLMediaPlayer.GLMediaEventListener() { + @Override + public void newFrameAvailable(GLMediaPlayer ts, TextureFrame newFrame, long when) { } + + @Override + public void attributesChanged(GLMediaPlayer mp, int event_mask, long when) { + System.err.println("MovieSimpleActivity0 AttributesChanges: events_mask 0x"+Integer.toHexString(event_mask)+", when "+when); + System.err.println("MovieSimpleActivity0 State: "+mp); + if( 0 != ( GLMediaEventListener.EVENT_CHANGE_INIT & event_mask ) ) { + glWindowMain.addGLEventListener(demoMain); + anim.setUpdateFPSFrames(60, System.err); + anim.resetFPSCounter(); + } + if( 0 != ( ( GLMediaEventListener.EVENT_CHANGE_ERR | GLMediaEventListener.EVENT_CHANGE_EOS ) & event_mask ) ) { + final StreamException se = mPlayer.getStreamException(); + if( null != se ) { + se.printStackTrace(); + } + getActivity().finish(); + } + } + }); + demoMain.initStream(streamLoc, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, 0); scrn.removeReference(); Log.d(TAG, "onCreate - X"); } - static URLConnection getResource(String path[], int off) { - URLConnection uc = null; - for(int i=off; null==uc && i<path.length; i++) { + static URI getURI(String path[], int off, boolean checkAvail) { + URI uri = null; + for(int i=off; null==uri && i<path.length; i++) { if(null != path[i] && path[i].length()>0) { - uc = IOUtil.getResource(path[i], null); - Log.d(TAG, "Stream: <"+path[i]+">: "+(null!=uc)); + if( checkAvail ) { + final URLConnection uc = IOUtil.getResource(path[i], null); + if( null != uc ) { + try { + uri = uc.getURL().toURI(); + } catch (URISyntaxException e) { + uri = null; + } + if( uc instanceof HttpURLConnection ) { + ((HttpURLConnection)uc).disconnect(); + } + } + } else { + try { + uri = new URI(path[i]); + } catch (URISyntaxException e) { + uri = null; + } + } + Log.d(TAG, "Stream: <"+path[i]+">: "+(null!=uri)); } } - return uc; + return uri; } } diff --git a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivity1.java b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivity1.java index a5e5f4ccb..e54300de5 100644 --- a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivity1.java +++ b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivity1.java @@ -27,7 +27,9 @@ */ package com.jogamp.opengl.test.android; -import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.URISyntaxException; import java.net.URLConnection; import java.util.Arrays; @@ -36,11 +38,11 @@ import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLProfile; import javax.media.opengl.GLRunnable; -import jogamp.newt.driver.android.AndroidWindow; import jogamp.newt.driver.android.NewtBaseActivity; import com.jogamp.common.util.IOUtil; import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Window; import com.jogamp.newt.event.MouseAdapter; import com.jogamp.newt.event.MouseEvent; import com.jogamp.newt.opengl.GLWindow; @@ -48,6 +50,9 @@ import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSimple; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.util.av.GLMediaPlayer; +import com.jogamp.opengl.util.av.GLMediaPlayer.GLMediaEventListener; +import com.jogamp.opengl.util.av.GLMediaPlayer.StreamException; +import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame; import android.os.Bundle; import android.util.Log; @@ -59,8 +64,8 @@ public class MovieSimpleActivity1 extends NewtBaseActivity { MouseAdapter toFrontMouseListener = new MouseAdapter() { public void mouseClicked(MouseEvent e) { Object src = e.getSource(); - if(src instanceof AndroidWindow) { - ((AndroidWindow)src).requestFocus(false); + if(src instanceof Window) { + ((Window)src).requestFocus(false); } } }; @@ -74,22 +79,22 @@ public class MovieSimpleActivity1 extends NewtBaseActivity { final boolean mPlayerSharedHUD = mPlayerHUD && Boolean.valueOf(System.getProperty("jnlp.mplayer.hud.shared")); Log.d(TAG, "onCreate - 0 - mPlayerLocal "+mPlayerLocal+", mPlayerNoScale "+mPlayerNoZoom+", mPlayerHUD "+mPlayerHUD+", mPlayerSharedHUD "+mPlayerSharedHUD); - String[] urls0 = new String[] { + String[] streamLocs = new String[] { System.getProperty("jnlp.media0_url2"), System.getProperty("jnlp.media0_url1"), System.getProperty("jnlp.media0_url0") }; - final URLConnection urlConnection0 = getResource(urls0, mPlayerLocal ? 2 : 0); - if(null == urlConnection0) { throw new RuntimeException("no media reachable: "+Arrays.asList(urls0)); } + final URI streamLoc0 = getURI(streamLocs, mPlayerLocal ? 2 : 0, false); + if(null == streamLoc0) { throw new RuntimeException("no media reachable: "+Arrays.asList(streamLocs)); } - final URLConnection urlConnection1; + final URI streamLoc1; { - URLConnection _urlConnection1 = null; + URI _streamLoc1 = null; if(mPlayerHUD && !mPlayerSharedHUD) { String[] urls1 = new String[] { System.getProperty("jnlp.media1_url0") }; - _urlConnection1 = getResource(urls1, 0); + _streamLoc1 = getURI(urls1, 0, false); } - if(null == _urlConnection1) { _urlConnection1 = urlConnection0; } - urlConnection1 = _urlConnection1; + if(null == _streamLoc1) { _streamLoc1 = streamLoc0; } + streamLoc1 = _streamLoc1; } setTransparencyTheme(); @@ -107,83 +112,117 @@ public class MovieSimpleActivity1 extends NewtBaseActivity { final com.jogamp.newt.Screen scrn = NewtFactory.createScreen(dpy, 0); scrn.addReference(); - try { - final Animator animator = new Animator(); - setAnimator(animator); - - // Main - final MovieSimple demoMain = new MovieSimple(urlConnection0); - if(mPlayerHUD) { - demoMain.setEffects(MovieSimple.EFFECT_GRADIENT_BOTTOM2TOP); - demoMain.setTransparency(0.9f); - } - demoMain.setScaleOrig(mPlayerNoZoom); - final GLWindow glWindowMain = GLWindow.create(scrn, capsMain); - { - final int padding = mPlayerHUD ? 32 : 0; - final android.view.View androidView = ((AndroidWindow)glWindowMain.getDelegatedWindow()).getAndroidView(); - glWindowMain.setSize(scrn.getWidth()-padding, scrn.getHeight()-padding); - glWindowMain.setUndecorated(true); - // setContentView(getWindow(), glWindowMain); - viewGroup.addView(androidView, new android.widget.FrameLayout.LayoutParams(glWindowMain.getWidth(), glWindowMain.getHeight(), Gravity.BOTTOM|Gravity.RIGHT)); - registerNEWTWindow(glWindowMain); + final Animator anim = new Animator(); + + // Main + final GLWindow glWindowMain = GLWindow.create(scrn, capsMain); + { + final int padding = mPlayerHUD ? 32 : 0; + final android.view.View androidView = ((jogamp.newt.driver.android.WindowDriver)glWindowMain.getDelegatedWindow()).getAndroidView(); + glWindowMain.setSize(scrn.getWidth()-padding, scrn.getHeight()-padding); + glWindowMain.setUndecorated(true); + // setContentView(getWindow(), glWindowMain); + viewGroup.addView(androidView, new android.widget.FrameLayout.LayoutParams(glWindowMain.getWidth(), glWindowMain.getHeight(), Gravity.BOTTOM|Gravity.RIGHT)); + registerNEWTWindow(glWindowMain); + } + anim.add(glWindowMain); + glWindowMain.setVisible(true); + + final MovieSimple demoMain = new MovieSimple(null); + final GLMediaPlayer mPlayerMain = demoMain.getGLMediaPlayer(); + if(mPlayerHUD) { + demoMain.setEffects(MovieSimple.EFFECT_GRADIENT_BOTTOM2TOP); + demoMain.setTransparency(0.9f); + } + demoMain.setScaleOrig(mPlayerNoZoom); + mPlayerMain.addEventListener( new GLMediaPlayer.GLMediaEventListener() { + @Override + public void newFrameAvailable(GLMediaPlayer ts, TextureFrame newFrame, long when) { } + + @Override + public void attributesChanged(GLMediaPlayer mp, int event_mask, long when) { + System.err.println("MovieSimpleActivity1 AttributesChanges: events_mask 0x"+Integer.toHexString(event_mask)+", when "+when); + System.err.println("MovieSimpleActivity1 State: "+mp); + if( 0 != ( GLMediaEventListener.EVENT_CHANGE_INIT & event_mask ) ) { + glWindowMain.addGLEventListener(demoMain); + anim.setUpdateFPSFrames(60, System.err); + anim.resetFPSCounter(); + } + if( 0 != ( ( GLMediaEventListener.EVENT_CHANGE_ERR | GLMediaEventListener.EVENT_CHANGE_EOS ) & event_mask ) ) { + final StreamException se = mPlayerMain.getStreamException(); + if( null != se ) { + se.printStackTrace(); + } + getActivity().finish(); + } } - - glWindowMain.addGLEventListener(demoMain); - animator.add(glWindowMain); - glWindowMain.setVisible(true); - - if(mPlayerHUD) { - final GLMediaPlayer sharedPlayer = mPlayerSharedHUD ? demoMain.getGLMediaPlayer() : null; - final GLCapabilities capsHUD = new GLCapabilities(GLProfile.getGL2ES2()); - capsHUD.setBackgroundOpaque(false); - final GLWindow glWindowHUD = GLWindow.create(scrn, capsHUD); - glWindowMain.invoke(false, new GLRunnable() { - @Override - public boolean run(GLAutoDrawable drawable) { - int x2 = scrn.getX(); - int y2 = scrn.getY(); - int w2 = scrn.getWidth()/3; - int h2 = scrn.getHeight()/3; - if(null != sharedPlayer) { - if(0 < sharedPlayer.getWidth() && sharedPlayer.getWidth()<scrn.getWidth()/2 && - 0 < sharedPlayer.getHeight() && sharedPlayer.getHeight()<scrn.getHeight()/2) { - w2 = sharedPlayer.getWidth(); - h2 = sharedPlayer.getHeight(); - } - glWindowHUD.setSharedContext(glWindowMain.getContext()); - glWindowHUD.addGLEventListener(new MovieSimple(sharedPlayer)); - } else { - try { - glWindowHUD.addGLEventListener(new MovieSimple(urlConnection1)); - } catch (IOException e) { - e.printStackTrace(); + }); + demoMain.initStream(streamLoc0, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, 0); + + if(mPlayerHUD) { + final GLMediaPlayer mPlayerShared = mPlayerSharedHUD ? mPlayerMain : null; + final GLCapabilities capsHUD = new GLCapabilities(GLProfile.getGL2ES2()); + capsHUD.setBackgroundOpaque(false); + final GLWindow glWindowHUD = GLWindow.create(scrn, capsHUD); + glWindowMain.invoke(false, new GLRunnable() { + @Override + public boolean run(GLAutoDrawable drawable) { + final GLMediaPlayer mPlayerSub; + final MovieSimple demoHUD; + int x2 = scrn.getX(); + int y2 = scrn.getY(); + int w2 = scrn.getWidth()/3; + int h2 = scrn.getHeight()/3; + if(null != mPlayerShared) { + if(0 < mPlayerShared.getWidth() && mPlayerShared.getWidth()<scrn.getWidth()/2 && + 0 < mPlayerShared.getHeight() && mPlayerShared.getHeight()<scrn.getHeight()/2) { + w2 = mPlayerShared.getWidth(); + h2 = mPlayerShared.getHeight(); + } + glWindowHUD.setSharedContext(glWindowMain.getContext()); + demoHUD = new MovieSimple(mPlayerShared); + mPlayerSub = mPlayerShared; + } else { + demoHUD = new MovieSimple(null); + mPlayerSub = demoHUD.getGLMediaPlayer(); + } + mPlayerSub.addEventListener( new GLMediaPlayer.GLMediaEventListener() { + @Override + public void newFrameAvailable(GLMediaPlayer ts, TextureFrame newFrame, long when) { } + + @Override + public void attributesChanged(GLMediaPlayer mp, int event_mask, long when) { + if( 0 != ( GLMediaEventListener.EVENT_CHANGE_INIT & event_mask ) ) { + glWindowHUD.addGLEventListener(demoHUD); + } + if( 0 != ( ( GLMediaEventListener.EVENT_CHANGE_ERR | GLMediaEventListener.EVENT_CHANGE_EOS ) & event_mask ) ) { + final StreamException se = mPlayerMain.getStreamException(); + if( null != se ) { + se.printStackTrace(); + } + getActivity().finish(); } - } - glWindowHUD.setPosition(x2, y2); - glWindowHUD.setSize(w2, h2); - System.err.println("HUD: "+mPlayerHUD); - System.err.println("HUD: "+w2+"x"+h2); - glWindowHUD.addMouseListener(toFrontMouseListener); + } + }); + demoHUD.initStream(streamLoc1, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, 0); + + glWindowHUD.setPosition(x2, y2); + glWindowHUD.setSize(w2, h2); + System.err.println("HUD: "+mPlayerHUD); + System.err.println("HUD: "+w2+"x"+h2); + glWindowHUD.addMouseListener(toFrontMouseListener); - viewGroup.post(new Runnable() { - public void run() { - final android.view.View androidView = ((AndroidWindow)glWindowHUD.getDelegatedWindow()).getAndroidView(); - // addContentView(getWindow(), glWindowHUD, new android.view.ViewGroup.LayoutParams(glWindowHUD.getWidth(), glWindowHUD.getHeight())); - viewGroup.addView(androidView, new android.widget.FrameLayout.LayoutParams(glWindowHUD.getWidth(), glWindowHUD.getHeight(), Gravity.TOP|Gravity.LEFT)); - registerNEWTWindow(glWindowHUD); - animator.add(glWindowHUD); - glWindowHUD.setVisible(true); - } } ); - return true; - } } ); - } - - animator.setUpdateFPSFrames(60, System.err); - // animator.setUpdateFPSFrames(-1, null); - animator.resetFPSCounter(); - } catch (IOException e) { - e.printStackTrace(); + viewGroup.post(new Runnable() { + public void run() { + final android.view.View androidView = ((jogamp.newt.driver.android.WindowDriver)glWindowHUD.getDelegatedWindow()).getAndroidView(); + // addContentView(getWindow(), glWindowHUD, new android.view.ViewGroup.LayoutParams(glWindowHUD.getWidth(), glWindowHUD.getHeight())); + viewGroup.addView(androidView, new android.widget.FrameLayout.LayoutParams(glWindowHUD.getWidth(), glWindowHUD.getHeight(), Gravity.TOP|Gravity.LEFT)); + registerNEWTWindow(glWindowHUD); + anim.add(glWindowHUD); + glWindowHUD.setVisible(true); + } } ); + return true; + } } ); } scrn.removeReference(); @@ -191,14 +230,32 @@ public class MovieSimpleActivity1 extends NewtBaseActivity { Log.d(TAG, "onCreate - X"); } - static URLConnection getResource(String path[], int off) { - URLConnection uc = null; - for(int i=off; null==uc && i<path.length; i++) { + static URI getURI(String path[], int off, boolean checkAvail) { + URI uri = null; + for(int i=off; null==uri && i<path.length; i++) { if(null != path[i] && path[i].length()>0) { - uc = IOUtil.getResource(path[i], null); - Log.d(TAG, "Stream: <"+path[i]+">: "+(null!=uc)); + if( checkAvail ) { + final URLConnection uc = IOUtil.getResource(path[i], null); + if( null != uc ) { + try { + uri = uc.getURL().toURI(); + } catch (URISyntaxException e) { + uri = null; + } + if( uc instanceof HttpURLConnection ) { + ((HttpURLConnection)uc).disconnect(); + } + } + } else { + try { + uri = new URI(path[i]); + } catch (URISyntaxException e) { + uri = null; + } + } + Log.d(TAG, "Stream: <"+path[i]+">: "+(null!=uri)); } } - return uc; + return uri; } } diff --git a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher00b.java b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher00b.java index 8c08e987f..00c9fb9eb 100644 --- a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher00b.java +++ b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher00b.java @@ -3,14 +3,14 @@ * * 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 @@ -20,7 +20,7 @@ * 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. @@ -35,32 +35,33 @@ import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties; public class MovieSimpleActivityLauncher00b extends LauncherUtil.BaseActivityLauncher { static String demo = "com.jogamp.opengl.test.android.MovieSimpleActivity1"; - // static String[] pkgs = new String[] { "com.jogamp.common", "javax.media.opengl", "com.jogamp.opengl.test" }; - static String[] pkgs = new String[] { "com.jogamp.opengl.test" }; - + static String[] sys_pkgs = new String[] { "com.jogamp.common", "javax.media.opengl" }; + static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" }; + @Override public void init() { - final OrderedProperties props = getProperties(); + final OrderedProperties props = getProperties(); props.setProperty("jnlp.mplayer.nozoom", "false"); props.setProperty("jnlp.mplayer.hud", "false"); props.setProperty("jnlp.mplayer.hud.shared", "false"); // props.setProperty("jnlp.media0_url2", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_640x360.m4v"); - props.setProperty("jnlp.media0_url2", ""); - props.setProperty("jnlp.media0_url1", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4"); + props.setProperty("jnlp.media0_url2", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4"); + props.setProperty("jnlp.media0_url1", "http://video.webmfiles.org/big-buck-bunny_trailer.webm"); props.setProperty("jnlp.media0_url0", "file:///mnt/sdcard/Movies/BigBuckBunny_320x180.mp4"); props.setProperty("jnlp.media1_url0", "http://archive.org/download/ElephantsDream/ed_1024_512kb.mp4"); // props.setProperty("jogamp.debug.JNILibLoader", "true"); // props.setProperty("jogamp.debug.NativeLibrary", "true"); // props.setProperty("jogamp.debug.NativeLibrary.Lookup", "true"); - // props.setProperty("jogamp.debug.IOUtil", "true"); + // props.setProperty("jogamp.debug.IOUtil", "true"); // props.setProperty("nativewindow.debug", "all"); - props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); + // props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); // props.setProperty("jogl.debug", "all"); // props.setProperty("jogl.debug.GLProfile", "true"); - props.setProperty("jogl.debug.GLDrawable", "true"); + // props.setProperty("jogl.debug.GLDrawable", "true"); props.setProperty("jogl.debug.GLContext", "true"); + props.setProperty("jogl.debug.GLMediaPlayer", "true"); props.setProperty("jogl.debug.GLSLCode", "true"); - // props.setProperty("jogl.debug.CapabilitiesChooser", "true"); + // props.setProperty("jogl.debug.CapabilitiesChooser", "true"); // props.setProperty("jogl.debug.GLSLState", "true"); // props.setProperty("jogl.debug.DebugGL", "true"); // props.setProperty("jogl.debug.TraceGL", "true"); @@ -70,13 +71,18 @@ public class MovieSimpleActivityLauncher00b extends LauncherUtil.BaseActivityLau // props.setProperty("newt.debug.Window.KeyEvent", "true"); props.setProperty("jogamp.debug.IOUtil", "true"); } - + @Override public String getActivityName() { return demo; } @Override - public List<String> getPackages() { - return Arrays.asList(pkgs); + public List<String> getSysPackages() { + return Arrays.asList(sys_pkgs); + } + + @Override + public List<String> getUsrPackages() { + return Arrays.asList(usr_pkgs); } } diff --git a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher00a.java b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher00c.java index fbb0223f8..6e37cb8ad 100644 --- a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher00a.java +++ b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher00c.java @@ -3,14 +3,14 @@ * * 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 @@ -20,7 +20,7 @@ * 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. @@ -32,35 +32,34 @@ import java.util.List; import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties; -public class MovieSimpleActivityLauncher00a extends LauncherUtil.BaseActivityLauncher { +public class MovieSimpleActivityLauncher00c extends LauncherUtil.BaseActivityLauncher { + + static String demo = "com.jogamp.opengl.test.android.MovieSimpleActivity1"; + static String[] sys_pkgs = new String[] { "com.jogamp.common", "javax.media.opengl" }; + static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" }; - static String demo = "com.jogamp.opengl.test.android.MovieSimpleActivity0"; - // static String[] pkgs = new String[] { "com.jogamp.common", "javax.media.opengl", "com.jogamp.opengl.test" }; - static String[] pkgs = new String[] { "com.jogamp.opengl.test" }; - @Override public void init() { - final OrderedProperties props = getProperties(); - props.setProperty("jnlp.mplayer.nozoom", "true"); + final OrderedProperties props = getProperties(); + props.setProperty("jnlp.mplayer.nozoom", "false"); props.setProperty("jnlp.mplayer.hud", "false"); props.setProperty("jnlp.mplayer.hud.shared", "false"); - // props.setProperty("jnlp.media0_url2", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_640x360.m4v"); - props.setProperty("jnlp.media0_url2", ""); + props.setProperty("jnlp.media0_url2", "camera:/0"); props.setProperty("jnlp.media0_url1", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4"); props.setProperty("jnlp.media0_url0", "file:///mnt/sdcard/Movies/BigBuckBunny_320x180.mp4"); - props.setProperty("jnlp.media1_url0", "http://archive.org/download/ElephantsDream/ed_1024_512kb.mp4"); // props.setProperty("jogamp.debug.JNILibLoader", "true"); // props.setProperty("jogamp.debug.NativeLibrary", "true"); // props.setProperty("jogamp.debug.NativeLibrary.Lookup", "true"); - // props.setProperty("jogamp.debug.IOUtil", "true"); + // props.setProperty("jogamp.debug.IOUtil", "true"); // props.setProperty("nativewindow.debug", "all"); - props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); + // props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); // props.setProperty("jogl.debug", "all"); // props.setProperty("jogl.debug.GLProfile", "true"); - props.setProperty("jogl.debug.GLDrawable", "true"); + // props.setProperty("jogl.debug.GLDrawable", "true"); props.setProperty("jogl.debug.GLContext", "true"); + props.setProperty("jogl.debug.GLMediaPlayer", "true"); props.setProperty("jogl.debug.GLSLCode", "true"); - // props.setProperty("jogl.debug.CapabilitiesChooser", "true"); + // props.setProperty("jogl.debug.CapabilitiesChooser", "true"); // props.setProperty("jogl.debug.GLSLState", "true"); // props.setProperty("jogl.debug.DebugGL", "true"); // props.setProperty("jogl.debug.TraceGL", "true"); @@ -68,15 +67,20 @@ public class MovieSimpleActivityLauncher00a extends LauncherUtil.BaseActivityLau // props.setProperty("newt.debug.Window", "true"); // props.setProperty("newt.debug.Window.MouseEvent", "true"); // props.setProperty("newt.debug.Window.KeyEvent", "true"); - props.setProperty("jogamp.debug.IOUtil", "true"); + // props.setProperty("jogamp.debug.IOUtil", "true"); } - + @Override public String getActivityName() { return demo; } @Override - public List<String> getPackages() { - return Arrays.asList(pkgs); + public List<String> getSysPackages() { + return Arrays.asList(sys_pkgs); + } + + @Override + public List<String> getUsrPackages() { + return Arrays.asList(usr_pkgs); } } diff --git a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher01a.java b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher01a.java index b2a3facbd..7f4b911d3 100644 --- a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher01a.java +++ b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher01a.java @@ -3,14 +3,14 @@ * * 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 @@ -20,7 +20,7 @@ * 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. @@ -35,12 +35,12 @@ import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties; public class MovieSimpleActivityLauncher01a extends LauncherUtil.BaseActivityLauncher { static String demo = "com.jogamp.opengl.test.android.MovieSimpleActivity1"; - // static String[] pkgs = new String[] { "com.jogamp.common", "javax.media.opengl", "com.jogamp.opengl.test" }; - static String[] pkgs = new String[] { "com.jogamp.opengl.test" }; - + static String[] sys_pkgs = new String[] { "com.jogamp.common", "javax.media.opengl" }; + static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" }; + @Override public void init() { - final OrderedProperties props = getProperties(); + final OrderedProperties props = getProperties(); props.setProperty("jnlp.mplayer.nozoom", "true"); props.setProperty("jnlp.mplayer.hud", "true"); props.setProperty("jnlp.mplayer.hud.shared", "true"); @@ -52,15 +52,16 @@ public class MovieSimpleActivityLauncher01a extends LauncherUtil.BaseActivityLau // props.setProperty("jogamp.debug.JNILibLoader", "true"); // props.setProperty("jogamp.debug.NativeLibrary", "true"); // props.setProperty("jogamp.debug.NativeLibrary.Lookup", "true"); - // props.setProperty("jogamp.debug.IOUtil", "true"); + // props.setProperty("jogamp.debug.IOUtil", "true"); // props.setProperty("nativewindow.debug", "all"); - props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); + // props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); // props.setProperty("jogl.debug", "all"); // props.setProperty("jogl.debug.GLProfile", "true"); - props.setProperty("jogl.debug.GLDrawable", "true"); - props.setProperty("jogl.debug.GLContext", "true"); + // props.setProperty("jogl.debug.GLDrawable", "true"); + // props.setProperty("jogl.debug.GLContext", "true"); + // props.setProperty("jogl.debug.GLMediaPlayer", "true"); props.setProperty("jogl.debug.GLSLCode", "true"); - // props.setProperty("jogl.debug.CapabilitiesChooser", "true"); + // props.setProperty("jogl.debug.CapabilitiesChooser", "true"); // props.setProperty("jogl.debug.GLSLState", "true"); // props.setProperty("jogl.debug.DebugGL", "true"); // props.setProperty("jogl.debug.TraceGL", "true"); @@ -70,13 +71,18 @@ public class MovieSimpleActivityLauncher01a extends LauncherUtil.BaseActivityLau // props.setProperty("newt.debug.Window.KeyEvent", "true"); props.setProperty("jogamp.debug.IOUtil", "true"); } - + @Override public String getActivityName() { return demo; } @Override - public List<String> getPackages() { - return Arrays.asList(pkgs); + public List<String> getSysPackages() { + return Arrays.asList(sys_pkgs); + } + + @Override + public List<String> getUsrPackages() { + return Arrays.asList(usr_pkgs); } } diff --git a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher01b.java b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher01b.java index 905e2628d..2a76d0843 100644 --- a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher01b.java +++ b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher01b.java @@ -3,14 +3,14 @@ * * 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 @@ -20,7 +20,7 @@ * 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. @@ -35,12 +35,12 @@ import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties; public class MovieSimpleActivityLauncher01b extends LauncherUtil.BaseActivityLauncher { static String demo = "com.jogamp.opengl.test.android.MovieSimpleActivity1"; - // static String[] pkgs = new String[] { "com.jogamp.common", "javax.media.opengl", "com.jogamp.opengl.test" }; - static String[] pkgs = new String[] { "com.jogamp.opengl.test" }; - + static String[] sys_pkgs = new String[] { "com.jogamp.common", "javax.media.opengl" }; + static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" }; + @Override public void init() { - final OrderedProperties props = getProperties(); + final OrderedProperties props = getProperties(); props.setProperty("jnlp.mplayer.nozoom", "false"); props.setProperty("jnlp.mplayer.hud", "true"); props.setProperty("jnlp.mplayer.hud.shared", "true"); @@ -52,15 +52,16 @@ public class MovieSimpleActivityLauncher01b extends LauncherUtil.BaseActivityLau // props.setProperty("jogamp.debug.JNILibLoader", "true"); // props.setProperty("jogamp.debug.NativeLibrary", "true"); // props.setProperty("jogamp.debug.NativeLibrary.Lookup", "true"); - // props.setProperty("jogamp.debug.IOUtil", "true"); + // props.setProperty("jogamp.debug.IOUtil", "true"); // props.setProperty("nativewindow.debug", "all"); - props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); + // props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); // props.setProperty("jogl.debug", "all"); // props.setProperty("jogl.debug.GLProfile", "true"); - props.setProperty("jogl.debug.GLDrawable", "true"); - props.setProperty("jogl.debug.GLContext", "true"); + // props.setProperty("jogl.debug.GLDrawable", "true"); + // props.setProperty("jogl.debug.GLContext", "true"); + // props.setProperty("jogl.debug.GLMediaPlayer", "true"); props.setProperty("jogl.debug.GLSLCode", "true"); - // props.setProperty("jogl.debug.CapabilitiesChooser", "true"); + // props.setProperty("jogl.debug.CapabilitiesChooser", "true"); // props.setProperty("jogl.debug.GLSLState", "true"); // props.setProperty("jogl.debug.DebugGL", "true"); // props.setProperty("jogl.debug.TraceGL", "true"); @@ -70,13 +71,18 @@ public class MovieSimpleActivityLauncher01b extends LauncherUtil.BaseActivityLau // props.setProperty("newt.debug.Window.KeyEvent", "true"); props.setProperty("jogamp.debug.IOUtil", "true"); } - + @Override public String getActivityName() { return demo; } @Override - public List<String> getPackages() { - return Arrays.asList(pkgs); + public List<String> getSysPackages() { + return Arrays.asList(sys_pkgs); + } + + @Override + public List<String> getUsrPackages() { + return Arrays.asList(usr_pkgs); } } diff --git a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher02.java b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher02.java index 369457946..b649de296 100644 --- a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher02.java +++ b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher02.java @@ -3,14 +3,14 @@ * * 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 @@ -20,7 +20,7 @@ * 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. @@ -35,12 +35,12 @@ import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties; public class MovieSimpleActivityLauncher02 extends LauncherUtil.BaseActivityLauncher { static String demo = "com.jogamp.opengl.test.android.MovieSimpleActivity1"; - // static String[] pkgs = new String[] { "com.jogamp.common", "javax.media.opengl", "com.jogamp.opengl.test" }; - static String[] pkgs = new String[] { "com.jogamp.opengl.test" }; - + static String[] sys_pkgs = new String[] { "com.jogamp.common", "javax.media.opengl" }; + static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" }; + @Override public void init() { - final OrderedProperties props = getProperties(); + final OrderedProperties props = getProperties(); props.setProperty("jnlp.mplayer.nozoom", "false"); props.setProperty("jnlp.mplayer.hud", "true"); props.setProperty("jnlp.mplayer.hud.shared", "false"); @@ -52,15 +52,16 @@ public class MovieSimpleActivityLauncher02 extends LauncherUtil.BaseActivityLaun // props.setProperty("jogamp.debug.JNILibLoader", "true"); // props.setProperty("jogamp.debug.NativeLibrary", "true"); // props.setProperty("jogamp.debug.NativeLibrary.Lookup", "true"); - // props.setProperty("jogamp.debug.IOUtil", "true"); + // props.setProperty("jogamp.debug.IOUtil", "true"); // props.setProperty("nativewindow.debug", "all"); - props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); + // props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); // props.setProperty("jogl.debug", "all"); // props.setProperty("jogl.debug.GLProfile", "true"); - props.setProperty("jogl.debug.GLDrawable", "true"); - props.setProperty("jogl.debug.GLContext", "true"); + // props.setProperty("jogl.debug.GLDrawable", "true"); + // props.setProperty("jogl.debug.GLContext", "true"); + // props.setProperty("jogl.debug.GLMediaPlayer", "true"); props.setProperty("jogl.debug.GLSLCode", "true"); - // props.setProperty("jogl.debug.CapabilitiesChooser", "true"); + // props.setProperty("jogl.debug.CapabilitiesChooser", "true"); // props.setProperty("jogl.debug.GLSLState", "true"); // props.setProperty("jogl.debug.DebugGL", "true"); // props.setProperty("jogl.debug.TraceGL", "true"); @@ -70,13 +71,18 @@ public class MovieSimpleActivityLauncher02 extends LauncherUtil.BaseActivityLaun // props.setProperty("newt.debug.Window.KeyEvent", "true"); props.setProperty("jogamp.debug.IOUtil", "true"); } - + @Override public String getActivityName() { return demo; } @Override - public List<String> getPackages() { - return Arrays.asList(pkgs); + public List<String> getSysPackages() { + return Arrays.asList(sys_pkgs); + } + + @Override + public List<String> getUsrPackages() { + return Arrays.asList(usr_pkgs); } } diff --git a/src/test/com/jogamp/opengl/test/android/NEWTElektronActivity.java b/src/test/com/jogamp/opengl/test/android/NEWTElektronActivity.java index d1c8f2743..596c2c84e 100644 --- a/src/test/com/jogamp/opengl/test/android/NEWTElektronActivity.java +++ b/src/test/com/jogamp/opengl/test/android/NEWTElektronActivity.java @@ -32,8 +32,8 @@ import javax.media.opengl.GLProfile; import jogamp.newt.driver.android.NewtBaseActivity; -import com.jogamp.newt.ScreenMode; -import com.jogamp.newt.event.ScreenModeListener; +import com.jogamp.newt.event.MonitorEvent; +import com.jogamp.newt.event.MonitorModeListener; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.jogl.demos.es2.ElektronenMultiplizierer; @@ -51,22 +51,23 @@ public class NEWTElektronActivity extends NewtBaseActivity { super.onCreate(savedInstanceState); // create GLWindow (-> incl. underlying NEWT Display, Screen & Window) - GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); + GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL2ES2)); Log.d(TAG, "req caps: "+caps); GLWindow glWindow = GLWindow.create(caps); glWindow.setFullscreen(true); setContentView(getWindow(), glWindow); glWindow.addGLEventListener(new ElektronenMultiplizierer()); - glWindow.getScreen().addScreenModeListener(new ScreenModeListener() { - public void screenModeChangeNotify(ScreenMode sm) { } - public void screenModeChanged(ScreenMode sm, boolean success) { - System.err.println("ScreenMode Changed: "+sm); - } + glWindow.getScreen().addMonitorModeListener(new MonitorModeListener() { + @Override + public void monitorModeChangeNotify(MonitorEvent me) { } + @Override + public void monitorModeChanged(MonitorEvent me, boolean success) { + System.err.println("MonitorMode Changed (success "+success+"): "+me); + } }); glWindow.setVisible(true); Animator animator = new Animator(glWindow); - setAnimator(animator); animator.setUpdateFPSFrames(60, System.err); animator.resetFPSCounter(); diff --git a/src/test/com/jogamp/opengl/test/android/NEWTElektronActivityLauncher.java b/src/test/com/jogamp/opengl/test/android/NEWTElektronActivityLauncher.java index 33e05de8d..527d66108 100644 --- a/src/test/com/jogamp/opengl/test/android/NEWTElektronActivityLauncher.java +++ b/src/test/com/jogamp/opengl/test/android/NEWTElektronActivityLauncher.java @@ -8,7 +8,8 @@ import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties; public class NEWTElektronActivityLauncher extends LauncherUtil.BaseActivityLauncher { static String demo = "com.jogamp.opengl.test.android.NEWTElektronActivity"; - static String[] pkgs = new String[] { "com.jogamp.opengl.test" }; + static String[] sys_pkgs = new String[] { "com.jogamp.common", "javax.media.opengl" }; + static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" }; @Override public void init() { @@ -39,7 +40,12 @@ public class NEWTElektronActivityLauncher extends LauncherUtil.BaseActivityLaunc return demo; } @Override - public List<String> getPackages() { - return Arrays.asList(pkgs); + public List<String> getSysPackages() { + return Arrays.asList(sys_pkgs); + } + + @Override + public List<String> getUsrPackages() { + return Arrays.asList(usr_pkgs); } } diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGearsES1Activity.java b/src/test/com/jogamp/opengl/test/android/NEWTGearsES1Activity.java index c24c3af28..f10cfc11f 100644 --- a/src/test/com/jogamp/opengl/test/android/NEWTGearsES1Activity.java +++ b/src/test/com/jogamp/opengl/test/android/NEWTGearsES1Activity.java @@ -32,8 +32,8 @@ import javax.media.opengl.GLProfile; import jogamp.newt.driver.android.NewtBaseActivity; -import com.jogamp.newt.ScreenMode; -import com.jogamp.newt.event.ScreenModeListener; +import com.jogamp.newt.event.MonitorEvent; +import com.jogamp.newt.event.MonitorModeListener; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.jogl.demos.es1.GearsES1; @@ -63,15 +63,16 @@ public class NEWTGearsES1Activity extends NewtBaseActivity { setContentView(getWindow(), glWindow); glWindow.addGLEventListener(new GearsES1(-1)); - glWindow.getScreen().addScreenModeListener(new ScreenModeListener() { - public void screenModeChangeNotify(ScreenMode sm) { } - public void screenModeChanged(ScreenMode sm, boolean success) { - System.err.println("ScreenMode Changed: "+sm); - } + glWindow.getScreen().addMonitorModeListener(new MonitorModeListener() { + @Override + public void monitorModeChangeNotify(MonitorEvent me) { } + @Override + public void monitorModeChanged(MonitorEvent me, boolean success) { + System.err.println("MonitorMode Changed (success "+success+"): "+me); + } }); glWindow.setVisible(true); Animator animator = new Animator(glWindow); - setAnimator(animator); animator.setUpdateFPSFrames(60, System.err); animator.resetFPSCounter(); diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGearsES1ActivityLauncher.java b/src/test/com/jogamp/opengl/test/android/NEWTGearsES1ActivityLauncher.java index d0f6263f3..dca453126 100644 --- a/src/test/com/jogamp/opengl/test/android/NEWTGearsES1ActivityLauncher.java +++ b/src/test/com/jogamp/opengl/test/android/NEWTGearsES1ActivityLauncher.java @@ -7,7 +7,8 @@ import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties; public class NEWTGearsES1ActivityLauncher extends LauncherUtil.BaseActivityLauncher { static String demo = "com.jogamp.opengl.test.android.NEWTGearsES1Activity"; - static String[] pkgs = new String[] { "com.jogamp.opengl.test" }; + static String[] sys_pkgs = new String[] { "com.jogamp.common", "javax.media.opengl" }; + static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" }; @Override public void init() { @@ -38,7 +39,12 @@ public class NEWTGearsES1ActivityLauncher extends LauncherUtil.BaseActivityLaunc return demo; } @Override - public List<String> getPackages() { - return Arrays.asList(pkgs); + public List<String> getSysPackages() { + return Arrays.asList(sys_pkgs); + } + + @Override + public List<String> getUsrPackages() { + return Arrays.asList(usr_pkgs); } } diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2Activity.java b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2Activity.java index 592ecf5d6..9572ef6de 100644 --- a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2Activity.java +++ b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2Activity.java @@ -3,14 +3,14 @@ * * 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 @@ -20,79 +20,113 @@ * 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.android; +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.util.ArrayList; + import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLProfile; -import jogamp.newt.driver.android.AndroidWindow; import jogamp.newt.driver.android.NewtBaseActivity; -import com.jogamp.newt.ScreenMode; +import com.jogamp.newt.event.MonitorEvent; import com.jogamp.newt.event.MouseAdapter; import com.jogamp.newt.event.MouseEvent; -import com.jogamp.newt.event.ScreenModeListener; +import com.jogamp.newt.event.MonitorModeListener; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.util.Animator; -import android.content.Context; import android.os.Bundle; import android.util.Log; -import android.view.inputmethod.InputMethodManager; public class NEWTGearsES2Activity extends NewtBaseActivity { static String TAG = "NEWTGearsES2Activity"; - + + static final String forceRGBA5650 = "demo.force.rgba5650"; + static final String forceECT = "demo.force.ect"; + static final String forceKillProcessTest = "demo.force.killProcessTest"; + @Override public void onCreate(Bundle savedInstanceState) { Log.d(TAG, "onCreate - 0"); super.onCreate(savedInstanceState); - + // create GLWindow (-> incl. underlying NEWT Display, Screen & Window) - GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); + GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL2ES2)); + if( null != System.getProperty(forceRGBA5650) ) { + Log.d(TAG, "forceRGBA5650"); + caps.setRedBits(5); caps.setGreenBits(6); caps.setBlueBits(5); + } + Log.d(TAG, "req caps: "+caps); GLWindow glWindow = GLWindow.create(caps); glWindow.setFullscreen(true); setContentView(getWindow(), glWindow); - glWindow.addMouseListener(new MouseAdapter() { - @Override - public void mousePressed(MouseEvent e) { - if(e.getPressure()>2f) { // show Keyboard - final AndroidWindow win = (AndroidWindow)e.getSource(); - InputMethodManager mgr = (InputMethodManager) win.getAndroidView().getContext().getSystemService(Context.INPUT_METHOD_SERVICE); - mgr.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); // shows keyboard .. - win.getAndroidView().requestFocus(); - } - } - }); - + GearsES2 demo = new GearsES2(-1); // demo.enableAndroidTrace(true); glWindow.addGLEventListener(demo); - glWindow.getScreen().addScreenModeListener(new ScreenModeListener() { - public void screenModeChangeNotify(ScreenMode sm) { } - public void screenModeChanged(ScreenMode sm, boolean success) { - System.err.println("ScreenMode Changed: "+sm); - } + glWindow.getScreen().addMonitorModeListener(new MonitorModeListener() { + @Override + public void monitorModeChangeNotify(MonitorEvent me) { } + @Override + public void monitorModeChanged(MonitorEvent me, boolean success) { + System.err.println("MonitorMode Changed (success "+success+"): "+me); + } }); + if( null != System.getProperty(forceKillProcessTest) ) { + Log.d(TAG, "forceKillProcessTest"); + glWindow.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + if( e.getPointerCount() == 3 ) { + Log.d(TAG, "MemoryHog"); + new Thread(new Runnable() { + public void run() { + ArrayList<Buffer> buffers = new ArrayList<Buffer>(); + while(true) { + final int halfMB = 512 * 1024; + final float osizeMB = buffers.size() * 0.5f; + final float nsizeMB = osizeMB + 0.5f; + System.err.println("MemoryHog: ****** +4k: "+osizeMB+" MB +"+nsizeMB+" MB - Try"); + buffers.add(ByteBuffer.allocateDirect(halfMB)); // 0.5 MB each + System.err.println("MemoryHog: ****** +4k: "+osizeMB+" MB +"+nsizeMB+" MB - Done"); + try { + Thread.sleep(500); + } catch (Exception e) {}; + } + } }, "MemoryHog").start(); + } else if( e.getPointerCount() == 4 ) { + Log.d(TAG, "ForceKill"); + android.os.Process.killProcess( android.os.Process.myPid() ); + } + } + }); + } Animator animator = new Animator(glWindow); // animator.setRunAsFastAsPossible(true); - setAnimator(animator); // glWindow.setSkipContextReleaseThread(animator.getThread()); - + + if( null != System.getProperty(forceECT) ) { + Log.d(TAG, "forceECT"); + animator.setExclusiveContext(true); + } + glWindow.setVisible(true); - + animator.setUpdateFPSFrames(60, System.err); animator.resetFPSCounter(); glWindow.resetFPSCounter(); Log.d(TAG, "onCreate - X"); - } + } } diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2ActivityLauncher.java b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2ActivityLauncher.java index 0454d543c..c87e66189 100644 --- a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2ActivityLauncher.java +++ b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2ActivityLauncher.java @@ -35,8 +35,8 @@ import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties; public class NEWTGearsES2ActivityLauncher extends LauncherUtil.BaseActivityLauncher { static String demo = "com.jogamp.opengl.test.android.NEWTGearsES2Activity"; - // static String[] pkgs = new String[] { "com.jogamp.common", "javax.media.opengl", "com.jogamp.opengl.test" }; - static String[] pkgs = new String[] { "com.jogamp.opengl.test" }; + static String[] sys_pkgs = new String[] { "com.jogamp.common", "javax.media.opengl" }; + static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" }; @Override public void init() { @@ -49,25 +49,35 @@ public class NEWTGearsES2ActivityLauncher extends LauncherUtil.BaseActivityLaunc props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); // props.setProperty("jogl.debug", "all"); // properties.setProperty("jogl.debug.GLProfile", "true"); - props.setProperty("jogl.debug.GLDrawable", "true"); + // props.setProperty("jogl.debug.GLDrawable", "true"); props.setProperty("jogl.debug.GLContext", "true"); props.setProperty("jogl.debug.GLSLCode", "true"); // props.setProperty("jogl.debug.CapabilitiesChooser", "true"); - // properties.setProperty("jogl.debug.GLSLState", "true"); - // properties.setProperty("jogl.debug.DebugGL", "true"); - // properties.setProperty("jogl.debug.TraceGL", "true"); - // properties.setProperty("newt.debug", "all"); - // props.setProperty("newt.debug.Window", "true"); - // props.setProperty("newt.debug.Window.MouseEvent", "true"); - // props.setProperty("newt.debug.Window.KeyEvent", "true"); + // props.setProperty("jogl.debug.GLSLState", "true"); + // props.setProperty("jogl.debug.DebugGL", "true"); + // props.setProperty("jogl.debug.TraceGL", "true"); + // props.setProperty("newt.debug", "all"); + props.setProperty("newt.debug.Screen", "true"); + props.setProperty("newt.debug.Window", "true"); + props.setProperty("newt.debug.Window.MouseEvent", "true"); + props.setProperty("newt.debug.Window.KeyEvent", "true"); + // props.setProperty("newt.debug.Android.MouseEvent", "true"); + + // props.setProperty("demo.force.killProcessTest", "true"); } @Override public String getActivityName() { return demo; } + + @Override + public List<String> getSysPackages() { + return Arrays.asList(sys_pkgs); + } + @Override - public List<String> getPackages() { - return Arrays.asList(pkgs); + public List<String> getUsrPackages() { + return Arrays.asList(usr_pkgs); } } diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2ECTActivityLauncher.java b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2ECTActivityLauncher.java new file mode 100644 index 000000000..fb00ecbad --- /dev/null +++ b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2ECTActivityLauncher.java @@ -0,0 +1,80 @@ +/** + * Copyright 2012 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.android; + +import java.util.Arrays; +import java.util.List; + +import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties; + +public class NEWTGearsES2ECTActivityLauncher extends LauncherUtil.BaseActivityLauncher { + + static String demo = "com.jogamp.opengl.test.android.NEWTGearsES2Activity"; + static String[] sys_pkgs = new String[] { "com.jogamp.common", "javax.media.opengl" }; + static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" }; + + @Override + public void init() { + final OrderedProperties props = getProperties(); + // props.setProperty("jogamp.debug.JNILibLoader", "true"); + // props.setProperty("jogamp.debug.NativeLibrary", "true"); + // props.setProperty("jogamp.debug.IOUtil", "true"); + // properties.setProperty("jogamp.debug.NativeLibrary.Lookup", "true"); + // props.setProperty("nativewindow.debug", "all"); + props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); + // props.setProperty("jogl.debug", "all"); + // properties.setProperty("jogl.debug.GLProfile", "true"); + // props.setProperty("jogl.debug.GLDrawable", "true"); + props.setProperty("jogl.debug.GLContext", "true"); + props.setProperty("jogl.debug.GLSLCode", "true"); + // props.setProperty("jogl.debug.CapabilitiesChooser", "true"); + // props.setProperty("jogl.debug.GLSLState", "true"); + // props.setProperty("jogl.debug.DebugGL", "true"); + // props.setProperty("jogl.debug.TraceGL", "true"); + // props.setProperty("newt.debug", "all"); + props.setProperty("newt.debug.Window", "true"); + props.setProperty("newt.debug.Window.MouseEvent", "true"); + props.setProperty("newt.debug.Window.KeyEvent", "true"); + + props.setProperty("demo.force.ect", "true"); + } + + @Override + public String getActivityName() { + return demo; + } + @Override + public List<String> getSysPackages() { + return Arrays.asList(sys_pkgs); + } + + @Override + public List<String> getUsrPackages() { + return Arrays.asList(usr_pkgs); + } +} diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2RGB565ActivityLauncher.java b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2RGB565ActivityLauncher.java new file mode 100644 index 000000000..8acd2c05a --- /dev/null +++ b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2RGB565ActivityLauncher.java @@ -0,0 +1,80 @@ +/** + * Copyright 2012 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.android; + +import java.util.Arrays; +import java.util.List; + +import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties; + +public class NEWTGearsES2RGB565ActivityLauncher extends LauncherUtil.BaseActivityLauncher { + + static String demo = "com.jogamp.opengl.test.android.NEWTGearsES2Activity"; + static String[] sys_pkgs = new String[] { "com.jogamp.common", "javax.media.opengl" }; + static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" }; + + @Override + public void init() { + final OrderedProperties props = getProperties(); + // props.setProperty("jogamp.debug.JNILibLoader", "true"); + // props.setProperty("jogamp.debug.NativeLibrary", "true"); + // props.setProperty("jogamp.debug.IOUtil", "true"); + // properties.setProperty("jogamp.debug.NativeLibrary.Lookup", "true"); + // props.setProperty("nativewindow.debug", "all"); + props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); + // props.setProperty("jogl.debug", "all"); + // properties.setProperty("jogl.debug.GLProfile", "true"); + // props.setProperty("jogl.debug.GLDrawable", "true"); + props.setProperty("jogl.debug.GLContext", "true"); + props.setProperty("jogl.debug.GLSLCode", "true"); + // props.setProperty("jogl.debug.CapabilitiesChooser", "true"); + // props.setProperty("jogl.debug.GLSLState", "true"); + // props.setProperty("jogl.debug.DebugGL", "true"); + // props.setProperty("jogl.debug.TraceGL", "true"); + // props.setProperty("newt.debug", "all"); + props.setProperty("newt.debug.Window", "true"); + props.setProperty("newt.debug.Window.MouseEvent", "true"); + props.setProperty("newt.debug.Window.KeyEvent", "true"); + + props.setProperty("demo.force.rgba5650", "true"); + } + + @Override + public String getActivityName() { + return demo; + } + @Override + public List<String> getSysPackages() { + return Arrays.asList(sys_pkgs); + } + + @Override + public List<String> getUsrPackages() { + return Arrays.asList(usr_pkgs); + } +} diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2TransActivity.java b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2TransActivity.java index 9e50a1be1..beaf60460 100644 --- a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2TransActivity.java +++ b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2TransActivity.java @@ -34,8 +34,8 @@ import jogamp.newt.driver.android.NewtBaseActivity; import com.jogamp.newt.NewtFactory; import com.jogamp.newt.Screen; -import com.jogamp.newt.ScreenMode; -import com.jogamp.newt.event.ScreenModeListener; +import com.jogamp.newt.event.MonitorEvent; +import com.jogamp.newt.event.MonitorModeListener; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; @@ -53,7 +53,7 @@ public class NEWTGearsES2TransActivity extends NewtBaseActivity { super.onCreate(savedInstanceState); // create GLWindow (-> incl. underlying NEWT Display, Screen & Window) - GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); + GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL2ES2)); caps.setBackgroundOpaque(false); Log.d(TAG, "req caps: "+caps); @@ -65,14 +65,15 @@ public class NEWTGearsES2TransActivity extends NewtBaseActivity { setContentView(getWindow(), glWindow); glWindow.addGLEventListener(new GearsES2(-1)); - glWindow.getScreen().addScreenModeListener(new ScreenModeListener() { - public void screenModeChangeNotify(ScreenMode sm) { } - public void screenModeChanged(ScreenMode sm, boolean success) { - System.err.println("ScreenMode Changed: "+sm); - } + glWindow.getScreen().addMonitorModeListener(new MonitorModeListener() { + @Override + public void monitorModeChangeNotify(MonitorEvent me) { } + @Override + public void monitorModeChanged(MonitorEvent me, boolean success) { + System.err.println("MonitorMode Changed (success "+success+"): "+me); + } }); Animator animator = new Animator(glWindow); - setAnimator(animator); // glWindow.setSkipContextReleaseThread(animator.getThread()); glWindow.setVisible(true); diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2TransActivityLauncher.java b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2TransActivityLauncher.java index c29c0c5db..e6fe2a23f 100644 --- a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2TransActivityLauncher.java +++ b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2TransActivityLauncher.java @@ -7,7 +7,8 @@ import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties; public class NEWTGearsES2TransActivityLauncher extends LauncherUtil.BaseActivityLauncher { static String demo = "com.jogamp.opengl.test.android.NEWTGearsES2TransActivity"; - static String[] pkgs = new String[] { "com.jogamp.opengl.test" }; + static String[] sys_pkgs = new String[] { "com.jogamp.common", "javax.media.opengl" }; + static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" }; @Override public void init() { @@ -39,10 +40,17 @@ public class NEWTGearsES2TransActivityLauncher extends LauncherUtil.BaseActivity public String getActivityName() { return demo; } + @Override - public List<String> getPackages() { - return Arrays.asList(pkgs); + public List<String> getSysPackages() { + return Arrays.asList(sys_pkgs); } + + @Override + public List<String> getUsrPackages() { + return Arrays.asList(usr_pkgs); + } + @Override public String getAction() { return LauncherUtil.LAUNCH_ACTIVITY_TRANSPARENT; diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGraphUI1pActivity.java b/src/test/com/jogamp/opengl/test/android/NEWTGraphUI1pActivity.java index b8bf285c6..26adf0c4b 100644 --- a/src/test/com/jogamp/opengl/test/android/NEWTGraphUI1pActivity.java +++ b/src/test/com/jogamp/opengl/test/android/NEWTGraphUI1pActivity.java @@ -32,8 +32,8 @@ import javax.media.opengl.GLProfile; import jogamp.newt.driver.android.NewtBaseActivity; -import com.jogamp.newt.ScreenMode; -import com.jogamp.newt.event.ScreenModeListener; +import com.jogamp.newt.event.MonitorEvent; +import com.jogamp.newt.event.MonitorModeListener; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.graph.demos.GPUUISceneGLListener0A; @@ -51,7 +51,7 @@ public class NEWTGraphUI1pActivity extends NewtBaseActivity { super.onCreate(savedInstanceState); // create GLWindow (-> incl. underlying NEWT Display, Screen & Window) - GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); + GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL2ES2)); caps.setAlphaBits(4); caps.setNumSamples(4); caps.setSampleBuffers(true); @@ -61,15 +61,16 @@ public class NEWTGraphUI1pActivity extends NewtBaseActivity { setContentView(getWindow(), glWindow); glWindow.addGLEventListener(new GPUUISceneGLListener0A(0)); - glWindow.getScreen().addScreenModeListener(new ScreenModeListener() { - public void screenModeChangeNotify(ScreenMode sm) { } - public void screenModeChanged(ScreenMode sm, boolean success) { - System.err.println("ScreenMode Changed: "+sm); - } + glWindow.getScreen().addMonitorModeListener(new MonitorModeListener() { + @Override + public void monitorModeChangeNotify(MonitorEvent me) { } + @Override + public void monitorModeChanged(MonitorEvent me, boolean success) { + System.err.println("MonitorMode Changed (success "+success+"): "+me); + } }); glWindow.setVisible(true); Animator animator = new Animator(glWindow); - setAnimator(animator); animator.setUpdateFPSFrames(60, System.err); animator.resetFPSCounter(); diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGraphUI1pActivityLauncher.java b/src/test/com/jogamp/opengl/test/android/NEWTGraphUI1pActivityLauncher.java index c75c229a8..c18cf1611 100644 --- a/src/test/com/jogamp/opengl/test/android/NEWTGraphUI1pActivityLauncher.java +++ b/src/test/com/jogamp/opengl/test/android/NEWTGraphUI1pActivityLauncher.java @@ -7,38 +7,45 @@ import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties; public class NEWTGraphUI1pActivityLauncher extends LauncherUtil.BaseActivityLauncher { static String demo = "com.jogamp.opengl.test.android.NEWTGraphUI1pActivity"; - static String[] pkgs = new String[] { "com.jogamp.opengl.test" }; + static String[] sys_pkgs = new String[] { "com.jogamp.common", "javax.media.opengl" }; + static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" }; @Override public void init() { final OrderedProperties props = getProperties(); // props.setProperty("jogamp.debug.JNILibLoader", "true"); // props.setProperty("jogamp.debug.NativeLibrary", "true"); - // properties.setProperty("jogamp.debug.NativeLibrary.Lookup", "true"); - // properties.setProperty("jogamp.debug.IOUtil", "true"); - // properties.setProperty("nativewindow.debug", "all"); + // props.setProperty("jogamp.debug.NativeLibrary.Lookup", "true"); + // props.setProperty("jogamp.debug.IOUtil", "true"); + // props.setProperty("nativewindow.debug", "all"); props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); - // properties.setProperty("jogl.debug", "all"); - // properties.setProperty("jogl.debug.GLProfile", "true"); + // props.setProperty("jogl.debug", "all"); + // props.setProperty("jogl.debug.GLProfile", "true"); props.setProperty("jogl.debug.GLDrawable", "true"); props.setProperty("jogl.debug.GLContext", "true"); props.setProperty("jogl.debug.GLSLCode", "true"); props.setProperty("jogl.debug.CapabilitiesChooser", "true"); - // properties.setProperty("jogl.debug.GLSLState", "true"); - // properties.setProperty("jogl.debug.DebugGL", "true"); - // properties.setProperty("jogl.debug.TraceGL", "true"); - // properties.setProperty("newt.debug", "all"); + // props.setProperty("jogl.debug.GLSLState", "true"); + // props.setProperty("jogl.debug.DebugGL", "true"); + // props.setProperty("jogl.debug.TraceGL", "true"); + // props.setProperty("newt.debug", "all"); props.setProperty("newt.debug.Window", "true"); - // properties.setProperty("newt.debug.Window.MouseEvent", "true"); - // properties.setProperty("newt.debug.Window.KeyEvent", "true"); + // props.setProperty("newt.debug.Window.MouseEvent", "true"); + // props.setProperty("newt.debug.Window.KeyEvent", "true"); } @Override public String getActivityName() { return demo; } + + @Override + public List<String> getSysPackages() { + return Arrays.asList(sys_pkgs); + } + @Override - public List<String> getPackages() { - return Arrays.asList(pkgs); + public List<String> getUsrPackages() { + return Arrays.asList(usr_pkgs); } } diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGraphUI2pActivity.java b/src/test/com/jogamp/opengl/test/android/NEWTGraphUI2pActivity.java index 103af1aab..ebabfb01b 100644 --- a/src/test/com/jogamp/opengl/test/android/NEWTGraphUI2pActivity.java +++ b/src/test/com/jogamp/opengl/test/android/NEWTGraphUI2pActivity.java @@ -33,8 +33,8 @@ import javax.media.opengl.GLProfile; import jogamp.newt.driver.android.NewtBaseActivity; import com.jogamp.graph.curve.Region; -import com.jogamp.newt.ScreenMode; -import com.jogamp.newt.event.ScreenModeListener; +import com.jogamp.newt.event.MonitorEvent; +import com.jogamp.newt.event.MonitorModeListener; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.graph.demos.GPUUISceneGLListener0A; @@ -52,7 +52,7 @@ public class NEWTGraphUI2pActivity extends NewtBaseActivity { super.onCreate(savedInstanceState); // create GLWindow (-> incl. underlying NEWT Display, Screen & Window) - GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); + GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL2ES2)); caps.setAlphaBits(4); caps.setNumSamples(4); caps.setSampleBuffers(true); @@ -62,15 +62,16 @@ public class NEWTGraphUI2pActivity extends NewtBaseActivity { setContentView(getWindow(), glWindow); glWindow.addGLEventListener(new GPUUISceneGLListener0A(Region.VBAA_RENDERING_BIT)); - glWindow.getScreen().addScreenModeListener(new ScreenModeListener() { - public void screenModeChangeNotify(ScreenMode sm) { } - public void screenModeChanged(ScreenMode sm, boolean success) { - System.err.println("ScreenMode Changed: "+sm); - } + glWindow.getScreen().addMonitorModeListener(new MonitorModeListener() { + @Override + public void monitorModeChangeNotify(MonitorEvent me) { } + @Override + public void monitorModeChanged(MonitorEvent me, boolean success) { + System.err.println("MonitorMode Changed (success "+success+"): "+me); + } }); glWindow.setVisible(true); Animator animator = new Animator(glWindow); - setAnimator(animator); animator.setUpdateFPSFrames(60, System.err); animator.resetFPSCounter(); diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGraphUI2pActivityLauncher.java b/src/test/com/jogamp/opengl/test/android/NEWTGraphUI2pActivityLauncher.java index 8f6b51484..501d42566 100644 --- a/src/test/com/jogamp/opengl/test/android/NEWTGraphUI2pActivityLauncher.java +++ b/src/test/com/jogamp/opengl/test/android/NEWTGraphUI2pActivityLauncher.java @@ -7,7 +7,8 @@ import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties; public class NEWTGraphUI2pActivityLauncher extends LauncherUtil.BaseActivityLauncher { static String demo = "com.jogamp.opengl.test.android.NEWTGraphUI2pActivity"; - static String[] pkgs = new String[] { "com.jogamp.opengl.test" }; + static String[] sys_pkgs = new String[] { "com.jogamp.common", "javax.media.opengl" }; + static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" }; @Override public void init() { @@ -37,8 +38,14 @@ public class NEWTGraphUI2pActivityLauncher extends LauncherUtil.BaseActivityLaun public String getActivityName() { return demo; } + + @Override + public List<String> getSysPackages() { + return Arrays.asList(sys_pkgs); + } + @Override - public List<String> getPackages() { - return Arrays.asList(pkgs); + public List<String> getUsrPackages() { + return Arrays.asList(usr_pkgs); } } diff --git a/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES1Activity.java b/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES1Activity.java index a394482fc..08fbf643d 100644 --- a/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES1Activity.java +++ b/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES1Activity.java @@ -32,8 +32,8 @@ import javax.media.opengl.GLProfile; import jogamp.newt.driver.android.NewtBaseActivity; -import com.jogamp.newt.ScreenMode; -import com.jogamp.newt.event.ScreenModeListener; +import com.jogamp.newt.event.MonitorEvent; +import com.jogamp.newt.event.MonitorModeListener; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.jogl.demos.es1.RedSquareES1; @@ -57,15 +57,16 @@ public class NEWTRedSquareES1Activity extends NewtBaseActivity { setContentView(getWindow(), glWindow); glWindow.addGLEventListener(new RedSquareES1(-1)); - glWindow.getScreen().addScreenModeListener(new ScreenModeListener() { - public void screenModeChangeNotify(ScreenMode sm) { } - public void screenModeChanged(ScreenMode sm, boolean success) { - System.err.println("ScreenMode Changed: "+sm); - } + glWindow.getScreen().addMonitorModeListener(new MonitorModeListener() { + @Override + public void monitorModeChangeNotify(MonitorEvent me) { } + @Override + public void monitorModeChanged(MonitorEvent me, boolean success) { + System.err.println("MonitorMode Changed (success "+success+"): "+me); + } }); glWindow.setVisible(true); Animator animator = new Animator(glWindow); - setAnimator(animator); animator.setUpdateFPSFrames(60, System.err); animator.resetFPSCounter(); diff --git a/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES1ActivityLauncher.java b/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES1ActivityLauncher.java index 478fe65b7..59bf5ceee 100644 --- a/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES1ActivityLauncher.java +++ b/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES1ActivityLauncher.java @@ -7,7 +7,8 @@ import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties; public class NEWTRedSquareES1ActivityLauncher extends LauncherUtil.BaseActivityLauncher { static String demo = "com.jogamp.opengl.test.android.NEWTRedSquareES1Activity"; - static String[] pkgs = new String[] { "com.jogamp.opengl.test" }; + static String[] sys_pkgs = new String[] { "com.jogamp.common", "javax.media.opengl" }; + static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" }; @Override public void init() { @@ -37,8 +38,14 @@ public class NEWTRedSquareES1ActivityLauncher extends LauncherUtil.BaseActivityL public String getActivityName() { return demo; } + + @Override + public List<String> getSysPackages() { + return Arrays.asList(sys_pkgs); + } + @Override - public List<String> getPackages() { - return Arrays.asList(pkgs); + public List<String> getUsrPackages() { + return Arrays.asList(usr_pkgs); } } diff --git a/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES2Activity.java b/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES2Activity.java index 889e0944e..75ae94e89 100644 --- a/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES2Activity.java +++ b/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES2Activity.java @@ -32,8 +32,8 @@ import javax.media.opengl.GLProfile; import jogamp.newt.driver.android.NewtBaseActivity; -import com.jogamp.newt.ScreenMode; -import com.jogamp.newt.event.ScreenModeListener; +import com.jogamp.newt.event.MonitorEvent; +import com.jogamp.newt.event.MonitorModeListener; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; @@ -51,7 +51,7 @@ public class NEWTRedSquareES2Activity extends NewtBaseActivity { super.onCreate(savedInstanceState); // create GLWindow (-> incl. underlying NEWT Display, Screen & Window) - GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); + GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL2ES2)); Log.d(TAG, "req caps: "+caps); GLWindow glWindow = GLWindow.create(caps); // glWindow.setSize(200, 200); @@ -62,15 +62,16 @@ public class NEWTRedSquareES2Activity extends NewtBaseActivity { final RedSquareES2 demo = new RedSquareES2(-1); // demo.enableAndroidTrace(true); glWindow.addGLEventListener(demo); - glWindow.getScreen().addScreenModeListener(new ScreenModeListener() { - public void screenModeChangeNotify(ScreenMode sm) { } - public void screenModeChanged(ScreenMode sm, boolean success) { - System.err.println("ScreenMode Changed: "+sm); - } + glWindow.getScreen().addMonitorModeListener(new MonitorModeListener() { + @Override + public void monitorModeChangeNotify(MonitorEvent me) { } + @Override + public void monitorModeChanged(MonitorEvent me, boolean success) { + System.err.println("MonitorMode Changed (success "+success+"): "+me); + } }); Animator animator = new Animator(glWindow); // animator.setRunAsFastAsPossible(true); - setAnimator(animator); // glWindow.setSkipContextReleaseThread(animator.getThread()); glWindow.setVisible(true); @@ -79,5 +80,20 @@ public class NEWTRedSquareES2Activity extends NewtBaseActivity { glWindow.resetFPSCounter(); Log.d(TAG, "onCreate - X"); - } + } + + @Override + public void onResume() { + // android.os.Debug.startMethodTracing("GearsES2.trace"); + // android.os.Debug.startAllocCounting(); + super.onResume(); + } + + @Override + public void onPause() { + // android.os.Debug.stopAllocCounting(); + // android.os.Debug.stopMethodTracing(); + super.onPause(); + } + } diff --git a/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES2ActivityLauncher.java b/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES2ActivityLauncher.java index 96299e873..a631eab8e 100644 --- a/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES2ActivityLauncher.java +++ b/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES2ActivityLauncher.java @@ -11,7 +11,7 @@ public class NEWTRedSquareES2ActivityLauncher extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - final Uri uri = Uri.parse("launch://jogamp.org/com.jogamp.opengl.test.android.NEWTRedSquareES2Activity?pkg=com.jogamp.opengl.test"); + final Uri uri = Uri.parse("launch://jogamp.org/com.jogamp.opengl.test.android.NEWTRedSquareES2Activity?sys=com.jogamp.common&sys=javax.media.opengl&pkg=com.jogamp.opengl.test"); final Intent intent = new Intent("org.jogamp.launcher.action.LAUNCH_ACTIVITY_NORMAL", uri); Log.d(getClass().getSimpleName(), "Launching Activity: "+intent); startActivity (intent); diff --git a/src/test/com/jogamp/opengl/test/bugs/Bug427GLJPanelTest1.java b/src/test/com/jogamp/opengl/test/bugs/Bug427GLJPanelTest1.java index 9bf492e0f..66889e9ed 100644 --- a/src/test/com/jogamp/opengl/test/bugs/Bug427GLJPanelTest1.java +++ b/src/test/com/jogamp/opengl/test/bugs/Bug427GLJPanelTest1.java @@ -13,9 +13,16 @@ public class Bug427GLJPanelTest1 extends JFrame implements GLEventListener { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLayout(new BorderLayout()); - setSize(600, 600); - setLocation(40, 40); - setVisible(true); + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + setSize(600, 600); + setLocation(40, 40); + setVisible(true); + } } ); + } catch(Exception ex) { + throw new RuntimeException(ex); + } GLProfile glp = GLProfile.get(GLProfile.GL2); GLCapabilities caps = new GLCapabilities(glp); @@ -29,8 +36,15 @@ public class Bug427GLJPanelTest1 extends JFrame implements GLEventListener { } public static void main(String[] args) { - Bug427GLJPanelTest1 demo = new Bug427GLJPanelTest1(); - demo.setVisible(true); + final Bug427GLJPanelTest1 demo = new Bug427GLJPanelTest1(); + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + demo.setVisible(true); + } } ); + } catch(Exception ex) { + throw new RuntimeException(ex); + } } public void display(GLAutoDrawable drawable) { diff --git a/src/test/com/jogamp/opengl/test/bugs/Bug735.OSX.CALayer.Perf.logs/aaaa-m1-sync0-flush-wait-finish.log b/src/test/com/jogamp/opengl/test/bugs/Bug735.OSX.CALayer.Perf.logs/aaaa-m1-sync0-flush-wait-finish.log new file mode 100644 index 000000000..2261a3caa --- /dev/null +++ b/src/test/com/jogamp/opengl/test/bugs/Bug735.OSX.CALayer.Perf.logs/aaaa-m1-sync0-flush-wait-finish.log @@ -0,0 +1,751 @@ +NSZombieEnabled +NSTraceEvents YES +OBJC_PRINT_EXCEPTIONS +/usr/bin/java +java version "1.6.0_37" +Java(TM) SE Runtime Environment (build 1.6.0_37-b06-434-11M3909) +Java HotSpot(TM) 64-Bit Server VM (build 20.12-b01-434, mixed mode) +LD_LIBRARY_PATH :../../gluegen/make/../build-macosx/obj:../build-macosx/lib +LIBXCB_ALLOW_SLOPPY_LOCK: +LIBGL_DRIVERS_PATH: +LIBGL_DEBUG: +LIBGL_ALWAYS_INDIRECT: +LIBGL_ALWAYS_SOFTWARE: +SWT_CLASSPATH: ../build-macosx/../make/lib/swt/cocoa-macosx-x86_64/swt-debug.jar +/usr/bin/java -d64 -time 100000 -vsync 0 +CLASSPATH .:../../gluegen/make/../build-macosx/gluegen-rt.jar:../build-macosx/jar/jogl-all.jar:../build-macosx/jar/jogl-test.jar:../build-macosx/../make/lib/swt/cocoa-macosx-x86_64/swt-debug.jar:../../gluegen/make/../make/lib/junit.jar:/opt-share/apache-ant/lib/ant.jar:/opt-share/apache-ant/lib/ant-junit.jar +CLASSPATH .:../../gluegen/make/../build-macosx/gluegen-rt.jar:../build-macosx/jar/jogl-all.jar:../build-macosx/jar/jogl-test.jar:../build-macosx/../make/lib/swt/cocoa-macosx-x86_64/swt-debug.jar:../../gluegen/make/../make/lib/junit.jar:/opt-share/apache-ant/lib/ant.jar:/opt-share/apache-ant/lib/ant-junit.jar + +Test Start: com.jogamp.opengl.test.bugs.Bug735Inv3AppletAWT -time 100000 -vsync 0 + +/usr/bin/java -d64 -Djava.awt.headless=false -Djogl.debug.calayer.SwapM1 com.jogamp.opengl.test.bugs.Bug735Inv3AppletAWT -time 100000 -vsync 0 +swapInterval 0 +exclusiveContext false +SWAP_M1 true +SWAP_M2 false +NewtCanvasAWT.attachNewtChild.2: size 500x268 +Thread[main-Display-.macosx_nil-1-EDT-1,5,main] LandscapeES2.init ... +LandscapeES2 init on Thread[main-Display-.macosx_nil-1-EDT-1,5,main] +Chosen GLCapabilities: GLCaps[rgba 8/8/8/0, opaque, accum-rgba 0/0/0/0, dp/st/ms 24/0/0, dbl, mono , hw, GLProfile[GL2/GL2.hw], offscr[fbo]] +INIT GL IS: jogamp.opengl.gl4.GL4bcImpl +GL_VENDOR: NVIDIA Corporation +GL_RENDERER: NVIDIA GeForce 320M OpenGL Engine +GL_VERSION: 2.1 NVIDIA-7.32.12 +GL GLSL: true, has-compiler-func: true, version 1.20, 1.20.0 +GL FBO: basic true, full true +GL Profile: GLProfile[GL2/GL2.hw] +GL Renderer Quirks:[NoOffscreenBitmap] +GL:jogamp.opengl.gl4.GL4bcImpl@6a6779e6, 2.1 (hardware) - 2.1 NVIDIA-7.32.12 +Thread[main-Display-.macosx_nil-1-EDT-1,5,main] LandscapeES2.init FIN +Thread[main-Display-.macosx_nil-1-EDT-1,5,main] LandscapeES2.reshape 0/0 500x268, swapInterval 0, drawable 0x7ff0e40a7db0 +Thread[AWT-EventQueue-0,6,main] LandscapeES2.reshape 0/0 500x268, swapInterval 0, drawable 0x7ff0e40a7db0 +XXX[1] TO 17 ms, lFrame0 119 ms, lFrameX 858 / 858 ~858.987 ms, flushGL 1 / 1 ~1.135 ms, waitGL 1 / 1 ~1.056 ms, finishGL 737 / 737 ~737.152 ms +XXX[2] TO 17 ms, lFrame0 104 ms, lFrameX 194 / 1053 ~526.583 ms, flushGL 0 / 1 ~0.57 ms, waitGL 0 / 1 ~0.531 ms, finishGL 89 / 826 ~413.413 ms +XXX[3] TO 17 ms, lFrame0 2 ms, lFrameX 83 / 1136 ~378.802 ms, flushGL 0 / 1 ~0.383 ms, waitGL 0 / 1 ~0.355 ms, finishGL 81 / 908 ~302.677 ms +XXX[4] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 1219 ~304.958 ms, flushGL 0 / 1 ~0.289 ms, waitGL 0 / 1 ~0.268 ms, finishGL 81 / 989 ~247.438 ms +XXX[5] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 1302 ~260.583 ms, flushGL 0 / 1 ~0.232 ms, waitGL 0 / 1 ~0.215 ms, finishGL 82 / 1071 ~214.354 ms +XXX[6] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 1385 ~230.882 ms, flushGL 0 / 1 ~0.194 ms, waitGL 0 / 1 ~0.18 ms, finishGL 81 / 1153 ~192.227 ms +XXX[7] TO 17 ms, lFrame0 1 ms, lFrameX 82 / 1467 ~209.645 ms, flushGL 0 / 1 ~0.169 ms, waitGL 0 / 1 ~0.155 ms, finishGL 80 / 1233 ~176.248 ms +XXX[8] TO 17 ms, lFrame0 1 ms, lFrameX 82 / 1550 ~193.788 ms, flushGL 0 / 1 ~0.149 ms, waitGL 0 / 1 ~0.136 ms, finishGL 81 / 1314 ~164.348 ms +XXX[9] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 1632 ~181.44 ms, flushGL 0 / 1 ~0.133 ms, waitGL 0 / 1 ~0.121 ms, finishGL 81 / 1396 ~155.19 ms +XXX[10] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 1715 ~171.594 ms, flushGL 0 / 1 ~0.12 ms, waitGL 0 / 1 ~0.109 ms, finishGL 82 / 1478 ~147.892 ms +XXX[11] TO 17 ms, lFrame0 0 ms, lFrameX 98 / 1814 ~164.944 ms, flushGL 0 / 1 ~0.109 ms, waitGL 0 / 1 ~0.099 ms, finishGL 97 / 1576 ~143.33 ms +XXX[12] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 1897 ~158.103 ms, flushGL 0 / 1 ~0.1 ms, waitGL 0 / 1 ~0.092 ms, finishGL 82 / 1658 ~138.232 ms +XXX[13] TO 17 ms, lFrame0 0 ms, lFrameX 77 / 1974 ~151.875 ms, flushGL 0 / 1 ~0.093 ms, waitGL 0 / 1 ~0.085 ms, finishGL 76 / 1735 ~133.461 ms +XXX[14] TO 17 ms, lFrame0 0 ms, lFrameX 104 / 2078 ~148.498 ms, flushGL 0 / 1 ~0.086 ms, waitGL 0 / 1 ~0.079 ms, finishGL 104 / 1839 ~131.357 ms +XXX[15] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 2161 ~144.112 ms, flushGL 0 / 1 ~0.081 ms, waitGL 0 / 1 ~0.074 ms, finishGL 82 / 1921 ~128.079 ms +XXX[16] TO 17 ms, lFrame0 0 ms, lFrameX 75 / 2237 ~139.828 ms, flushGL 0 / 1 ~0.076 ms, waitGL 0 / 1 ~0.069 ms, finishGL 74 / 1995 ~124.741 ms +XXX[17] TO 17 ms, lFrame0 0 ms, lFrameX 90 / 2327 ~136.929 ms, flushGL 0 / 1 ~0.071 ms, waitGL 0 / 1 ~0.065 ms, finishGL 90 / 2086 ~122.706 ms +XXX[18] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 2427 ~134.845 ms, flushGL 0 / 1 ~0.068 ms, waitGL 0 / 1 ~0.062 ms, finishGL 98 / 2184 ~121.372 ms +XXX[19] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 2510 ~132.139 ms, flushGL 0 / 1 ~0.064 ms, waitGL 0 / 1 ~0.059 ms, finishGL 82 / 2267 ~119.34 ms +XXX[20] TO 17 ms, lFrame0 0 ms, lFrameX 75 / 2586 ~129.322 ms, flushGL 0 / 1 ~0.061 ms, waitGL 0 / 1 ~0.056 ms, finishGL 75 / 2342 ~117.125 ms +XXX[21] TO 17 ms, lFrame0 0 ms, lFrameX 107 / 2693 ~128.273 ms, flushGL 0 / 1 ~0.058 ms, waitGL 0 / 1 ~0.053 ms, finishGL 106 / 2449 ~116.638 ms +XXX[22] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 2776 ~126.226 ms, flushGL 0 / 1 ~0.056 ms, waitGL 0 / 1 ~0.051 ms, finishGL 82 / 2532 ~115.096 ms +XXX[23] TO 17 ms, lFrame0 0 ms, lFrameX 74 / 2851 ~123.993 ms, flushGL 0 / 1 ~0.054 ms, waitGL 0 / 1 ~0.049 ms, finishGL 74 / 2606 ~113.316 ms +XXX[24] TO 17 ms, lFrame0 0 ms, lFrameX 105 / 2957 ~123.214 ms, flushGL 0 / 1 ~0.051 ms, waitGL 0 / 1 ~0.047 ms, finishGL 104 / 2711 ~112.961 ms +XXX[25] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 3037 ~121.514 ms, flushGL 0 / 1 ~0.049 ms, waitGL 0 / 1 ~0.045 ms, finishGL 80 / 2791 ~111.652 ms +XXX[26] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 3108 ~119.541 ms, flushGL 0 / 1 ~0.048 ms, waitGL 0 / 1 ~0.044 ms, finishGL 69 / 2860 ~110.026 ms +XXX[27] TO 17 ms, lFrame0 0 ms, lFrameX 94 / 3202 ~118.618 ms, flushGL 0 / 1 ~0.046 ms, waitGL 0 / 1 ~0.042 ms, finishGL 93 / 2954 ~109.423 ms +XXX[28] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 3285 ~117.322 ms, flushGL 0 / 1 ~0.044 ms, waitGL 0 / 1 ~0.041 ms, finishGL 81 / 3036 ~108.439 ms +XXX[29] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 3352 ~115.598 ms, flushGL 0 / 1 ~0.043 ms, waitGL 0 / 1 ~0.039 ms, finishGL 66 / 3102 ~106.999 ms +XXX[30] TO 17 ms, lFrame0 1 ms, lFrameX 97 / 3449 ~114.992 ms, flushGL 0 / 1 ~0.042 ms, waitGL 0 / 1 ~0.038 ms, finishGL 96 / 3199 ~106.644 ms +XXX[31] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 3531 ~113.92 ms, flushGL 0 / 1 ~0.04 ms, waitGL 0 / 1 ~0.037 ms, finishGL 81 / 3280 ~105.828 ms +XXX[32] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 3596 ~112.392 ms, flushGL 0 / 1 ~0.039 ms, waitGL 0 / 1 ~0.036 ms, finishGL 64 / 3345 ~104.535 ms +XXX[33] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 3680 ~111.53 ms, flushGL 0 / 1 ~0.038 ms, waitGL 0 / 1 ~0.035 ms, finishGL 83 / 3428 ~103.889 ms +XXX[34] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 3746 ~110.179 ms, flushGL 0 / 1 ~0.037 ms, waitGL 0 / 1 ~0.034 ms, finishGL 65 / 3493 ~102.75 ms +XXX[35] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 3810 ~108.86 ms, flushGL 0 / 1 ~0.036 ms, waitGL 0 / 1 ~0.034 ms, finishGL 63 / 3556 ~101.622 ms +XXX[36] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 3894 ~108.192 ms, flushGL 0 / 1 ~0.035 ms, waitGL 0 / 1 ~0.033 ms, finishGL 84 / 3641 ~101.141 ms +XXX[37] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 3962 ~107.095 ms, flushGL 0 / 1 ~0.034 ms, waitGL 0 / 1 ~0.032 ms, finishGL 67 / 3708 ~100.222 ms +XXX[38] TO 17 ms, lFrame0 0 ms, lFrameX 62 / 4025 ~105.924 ms, flushGL 0 / 1 ~0.033 ms, waitGL 0 / 1 ~0.031 ms, finishGL 61 / 3770 ~99.213 ms +XXX[39] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 4111 ~105.414 ms, flushGL 0 / 1 ~0.033 ms, waitGL 0 / 1 ~0.03 ms, finishGL 85 / 3855 ~98.863 ms +XXX[40] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 4176 ~104.413 ms, flushGL 0 / 1 ~0.032 ms, waitGL 0 / 1 ~0.03 ms, finishGL 64 / 3920 ~98.012 ms +XXX[41] TO 17 ms, lFrame0 0 ms, lFrameX 60 / 4237 ~103.353 ms, flushGL 0 / 1 ~0.031 ms, waitGL 0 / 1 ~0.029 ms, finishGL 60 / 3980 ~97.094 ms +XXX[42] TO 17 ms, lFrame0 0 ms, lFrameX 88 / 4325 ~102.99 ms, flushGL 0 / 1 ~0.03 ms, waitGL 0 / 1 ~0.028 ms, finishGL 87 / 4068 ~96.868 ms +XXX[43] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4391 ~102.13 ms, flushGL 0 / 1 ~0.03 ms, waitGL 0 / 1 ~0.028 ms, finishGL 65 / 4134 ~96.14 ms +XXX[44] TO 17 ms, lFrame0 0 ms, lFrameX 60 / 4451 ~101.179 ms, flushGL 0 / 1 ~0.029 ms, waitGL 0 / 1 ~0.027 ms, finishGL 59 / 4193 ~95.31 ms +XXX[45] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 4541 ~100.92 ms, flushGL 0 / 1 ~0.029 ms, waitGL 0 / 1 ~0.027 ms, finishGL 88 / 4282 ~95.166 ms +XXX[46] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 4607 ~100.161 ms, flushGL 0 / 1 ~0.028 ms, waitGL 0 / 1 ~0.026 ms, finishGL 65 / 4348 ~94.521 ms +XXX[47] TO 17 ms, lFrame0 0 ms, lFrameX 59 / 4667 ~99.304 ms, flushGL 0 / 1 ~0.027 ms, waitGL 0 / 1 ~0.026 ms, finishGL 59 / 4407 ~93.768 ms +XXX[48] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 4756 ~99.098 ms, flushGL 0 / 1 ~0.027 ms, waitGL 0 / 1 ~0.025 ms, finishGL 88 / 4496 ~93.666 ms +XXX[49] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4823 ~98.431 ms, flushGL 0 / 1 ~0.026 ms, waitGL 0 / 1 ~0.025 ms, finishGL 65 / 4561 ~93.099 ms +XXX[50] TO 17 ms, lFrame0 1 ms, lFrameX 59 / 4883 ~97.662 ms, flushGL 0 / 1 ~0.026 ms, waitGL 0 / 1 ~0.024 ms, finishGL 58 / 4620 ~92.415 ms +XXX[51] TO 17 ms, lFrame0 0 ms, lFrameX 88 / 4972 ~97.49 ms, flushGL 0 / 1 ~0.025 ms, waitGL 0 / 1 ~0.024 ms, finishGL 88 / 4709 ~92.336 ms +XXX[52] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5038 ~96.903 ms, flushGL 0 / 1 ~0.025 ms, waitGL 0 / 1 ~0.023 ms, finishGL 66 / 4775 ~91.84 ms +XXX[53] TO 17 ms, lFrame0 0 ms, lFrameX 58 / 5097 ~96.188 ms, flushGL 0 / 1 ~0.025 ms, waitGL 0 / 1 ~0.023 ms, finishGL 58 / 4834 ~91.211 ms +XXX[54] TO 17 ms, lFrame0 0 ms, lFrameX 90 / 5188 ~96.089 ms, flushGL 0 / 1 ~0.024 ms, waitGL 0 / 1 ~0.022 ms, finishGL 90 / 4924 ~91.197 ms +XXX[55] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 5254 ~95.534 ms, flushGL 0 / 1 ~0.024 ms, waitGL 0 / 1 ~0.022 ms, finishGL 65 / 4989 ~90.723 ms +XXX[56] TO 17 ms, lFrame0 0 ms, lFrameX 59 / 5313 ~94.892 ms, flushGL 0 / 1 ~0.023 ms, waitGL 0 / 1 ~0.022 ms, finishGL 58 / 5048 ~90.152 ms +XXX[57] TO 17 ms, lFrame0 0 ms, lFrameX 90 / 5404 ~94.815 ms, flushGL 0 / 1 ~0.023 ms, waitGL 0 / 1 ~0.021 ms, finishGL 89 / 5138 ~90.148 ms +XXX[58] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5471 ~94.336 ms, flushGL 0 / 1 ~0.023 ms, waitGL 0 / 1 ~0.021 ms, finishGL 66 / 5204 ~89.74 ms +XXX[59] TO 17 ms, lFrame0 0 ms, lFrameX 60 / 5531 ~93.755 ms, flushGL 0 / 1 ~0.022 ms, waitGL 0 / 1 ~0.021 ms, finishGL 59 / 5264 ~89.227 ms +XXX[60] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 5620 ~93.682 ms, flushGL 0 / 1 ~0.022 ms, waitGL 0 / 1 ~0.02 ms, finishGL 88 / 5353 ~89.222 ms +XXX[61] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5687 ~93.244 ms, flushGL 0 / 1 ~0.022 ms, waitGL 0 / 1 ~0.02 ms, finishGL 66 / 5419 ~88.848 ms +XXX[62] TO 17 ms, lFrame0 0 ms, lFrameX 59 / 5747 ~92.707 ms, flushGL 0 / 1 ~0.021 ms, waitGL 0 / 1 ~0.02 ms, finishGL 59 / 5479 ~88.371 ms +XXX[63] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 5837 ~92.662 ms, flushGL 0 / 1 ~0.021 ms, waitGL 0 / 1 ~0.02 ms, finishGL 88 / 5568 ~88.381 ms +XXX[64] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5905 ~92.267 ms, flushGL 0 / 1 ~0.021 ms, waitGL 0 / 1 ~0.019 ms, finishGL 66 / 5634 ~88.042 ms +XXX[65] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 5967 ~91.8 ms, flushGL 0 / 1 ~0.021 ms, waitGL 0 / 1 ~0.019 ms, finishGL 61 / 5695 ~87.629 ms +XXX[66] TO 17 ms, lFrame0 0 ms, lFrameX 88 / 6055 ~91.744 ms, flushGL 0 / 1 ~0.02 ms, waitGL 0 / 1 ~0.019 ms, finishGL 87 / 5783 ~87.626 ms +XXX[67] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6122 ~91.376 ms, flushGL 0 / 1 ~0.02 ms, waitGL 0 / 1 ~0.019 ms, finishGL 66 / 5849 ~87.312 ms +XXX[68] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 6185 ~90.96 ms, flushGL 0 / 1 ~0.02 ms, waitGL 0 / 1 ~0.018 ms, finishGL 62 / 5912 ~86.945 ms +XXX[69] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 6272 ~90.899 ms, flushGL 0 / 1 ~0.019 ms, waitGL 0 / 1 ~0.018 ms, finishGL 86 / 5998 ~86.932 ms +XXX[70] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6338 ~90.547 ms, flushGL 0 / 1 ~0.019 ms, waitGL 0 / 1 ~0.018 ms, finishGL 65 / 6064 ~86.631 ms +XXX[71] TO 17 ms, lFrame0 0 ms, lFrameX 62 / 6400 ~90.149 ms, flushGL 0 / 1 ~0.019 ms, waitGL 0 / 1 ~0.018 ms, finishGL 61 / 6125 ~86.276 ms +XXX[72] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 6486 ~90.094 ms, flushGL 0 / 1 ~0.019 ms, waitGL 0 / 1 ~0.017 ms, finishGL 85 / 6211 ~86.268 ms +XXX[73] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 6552 ~89.761 ms, flushGL 0 / 1 ~0.019 ms, waitGL 0 / 1 ~0.017 ms, finishGL 65 / 6276 ~85.98 ms +XXX[74] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 6613 ~89.376 ms, flushGL 0 / 1 ~0.018 ms, waitGL 0 / 1 ~0.017 ms, finishGL 60 / 6337 ~85.639 ms +XXX[75] TO 17 ms, lFrame0 0 ms, lFrameX 88 / 6702 ~89.368 ms, flushGL 0 / 1 ~0.018 ms, waitGL 0 / 1 ~0.017 ms, finishGL 88 / 6425 ~85.675 ms +XXX[76] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6769 ~89.071 ms, flushGL 0 / 1 ~0.018 ms, waitGL 0 / 1 ~0.017 ms, finishGL 66 / 6491 ~85.42 ms +XXX[77] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 6830 ~88.709 ms, flushGL 0 / 1 ~0.018 ms, waitGL 0 / 1 ~0.016 ms, finishGL 60 / 6552 ~85.097 ms +XXX[78] TO 17 ms, lFrame0 0 ms, lFrameX 88 / 6919 ~88.707 ms, flushGL 0 / 1 ~0.018 ms, waitGL 0 / 1 ~0.016 ms, finishGL 88 / 6640 ~85.135 ms +XXX[79] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6986 ~88.437 ms, flushGL 0 / 1 ~0.017 ms, waitGL 0 / 1 ~0.016 ms, finishGL 66 / 6707 ~84.904 ms +XXX[80] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 7049 ~88.124 ms, flushGL 0 / 1 ~0.017 ms, waitGL 0 / 1 ~0.016 ms, finishGL 62 / 6769 ~84.624 ms +XXX[81] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 7136 ~88.109 ms, flushGL 0 / 1 ~0.017 ms, waitGL 0 / 1 ~0.016 ms, finishGL 86 / 6856 ~84.647 ms +XXX[82] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7203 ~87.846 ms, flushGL 0 / 1 ~0.017 ms, waitGL 0 / 1 ~0.016 ms, finishGL 65 / 6922 ~84.42 ms +XXX[83] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 7267 ~87.556 ms, flushGL 0 / 1 ~0.017 ms, waitGL 0 / 1 ~0.015 ms, finishGL 63 / 6985 ~84.164 ms +XXX[84] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 7353 ~87.538 ms, flushGL 0 / 1 ~0.016 ms, waitGL 0 / 1 ~0.015 ms, finishGL 85 / 7071 ~84.181 ms +XXX[85] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 7419 ~87.287 ms, flushGL 0 / 1 ~0.016 ms, waitGL 0 / 1 ~0.015 ms, finishGL 65 / 7136 ~83.956 ms +XXX[86] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 7482 ~87.011 ms, flushGL 0 / 1 ~0.016 ms, waitGL 0 / 1 ~0.015 ms, finishGL 62 / 7199 ~83.711 ms +XXX[87] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 7569 ~87.002 ms, flushGL 0 / 1 ~0.016 ms, waitGL 0 / 1 ~0.015 ms, finishGL 85 / 7284 ~83.732 ms +XXX[88] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7635 ~86.767 ms, flushGL 0 / 1 ~0.016 ms, waitGL 0 / 1 ~0.015 ms, finishGL 65 / 7350 ~83.529 ms +XXX[89] TO 17 ms, lFrame0 0 ms, lFrameX 62 / 7698 ~86.495 ms, flushGL 0 / 1 ~0.016 ms, waitGL 0 / 1 ~0.015 ms, finishGL 61 / 7412 ~83.287 ms +XXX[90] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 7784 ~86.498 ms, flushGL 0 / 1 ~0.016 ms, waitGL 0 / 1 ~0.014 ms, finishGL 86 / 7498 ~83.321 ms +XXX[91] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7851 ~86.278 ms, flushGL 0 / 1 ~0.015 ms, waitGL 0 / 1 ~0.014 ms, finishGL 65 / 7564 ~83.131 ms +XXX[92] TO 17 ms, lFrame0 0 ms, lFrameX 62 / 7914 ~86.024 ms, flushGL 0 / 1 ~0.015 ms, waitGL 0 / 1 ~0.014 ms, finishGL 62 / 7627 ~82.903 ms +XXX[93] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 8000 ~86.024 ms, flushGL 0 / 1 ~0.015 ms, waitGL 0 / 1 ~0.014 ms, finishGL 85 / 7712 ~82.931 ms +XXX[94] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8066 ~85.812 ms, flushGL 0 / 1 ~0.015 ms, waitGL 0 / 1 ~0.014 ms, finishGL 65 / 7778 ~82.748 ms +XXX[95] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 8127 ~85.556 ms, flushGL 0 / 1 ~0.015 ms, waitGL 0 / 1 ~0.014 ms, finishGL 60 / 7839 ~82.516 ms +XXX[96] TO 17 ms, lFrame0 0 ms, lFrameX 87 / 8215 ~85.577 ms, flushGL 0 / 1 ~0.015 ms, waitGL 0 / 1 ~0.014 ms, finishGL 87 / 7926 ~82.563 ms +XXX[97] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8281 ~85.376 ms, flushGL 0 / 1 ~0.015 ms, waitGL 0 / 1 ~0.014 ms, finishGL 65 / 7991 ~82.388 ms +XXX[98] TO 17 ms, lFrame0 0 ms, lFrameX 60 / 8342 ~85.123 ms, flushGL 0 / 1 ~0.014 ms, waitGL 0 / 1 ~0.013 ms, finishGL 59 / 8051 ~82.158 ms +XXX[99] TO 17 ms, lFrame0 0 ms, lFrameX 88 / 8431 ~85.161 ms, flushGL 0 / 1 ~0.014 ms, waitGL 0 / 1 ~0.013 ms, finishGL 88 / 8139 ~82.22 ms +XXX[1] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 66 ~66.288 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 65 / 65 ~65.79 ms +XXX[2] TO 17 ms, lFrame0 0 ms, lFrameX 59 / 126 ~63.1 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 59 / 125 ~62.55 ms +XXX[3] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 216 ~72.024 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 89 / 214 ~71.495 ms +XXX[4] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 282 ~70.719 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 66 / 280 ~70.203 ms +XXX[5] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 344 ~68.97 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 61 / 342 ~68.43 ms +XXX[6] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 434 ~72.357 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 88 / 430 ~71.813 ms +XXX[7] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 499 ~71.382 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 65 / 495 ~70.842 ms +XXX[8] TO 17 ms, lFrame0 0 ms, lFrameX 60 / 560 ~70.03 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 59 / 555 ~69.454 ms +XXX[9] TO 17 ms, lFrame0 0 ms, lFrameX 88 / 648 ~72.085 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 88 / 643 ~71.521 ms +XXX[10] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 714 ~71.489 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 65 / 709 ~70.934 ms +XXX[11] TO 17 ms, lFrame0 0 ms, lFrameX 59 / 774 ~70.434 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 59 / 768 ~69.865 ms +XXX[12] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 864 ~72.036 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 88 / 857 ~71.454 ms +XXX[13] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 931 ~71.665 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 66 / 924 ~71.094 ms +XXX[14] TO 17 ms, lFrame0 0 ms, lFrameX 60 / 992 ~70.887 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 60 / 984 ~70.309 ms +XXX[15] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 1081 ~72.122 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 88 / 1073 ~71.554 ms +XXX[16] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 1149 ~71.826 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 66 / 1140 ~71.265 ms +XXX[17] TO 17 ms, lFrame0 0 ms, lFrameX 62 / 1211 ~71.277 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 62 / 1202 ~70.724 ms +XXX[18] TO 17 ms, lFrame0 0 ms, lFrameX 88 / 1300 ~72.24 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 88 / 1290 ~71.689 ms +XXX[19] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1366 ~71.934 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 65 / 1356 ~71.388 ms +FrameCount: 120 - FrameRate: 15.0 +XXX[20] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 1430 ~71.539 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 63 / 1419 ~70.979 ms +XXX[21] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 1516 ~72.228 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 85 / 1505 ~71.674 ms +XXX[22] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 1582 ~71.935 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 65 / 1570 ~71.383 ms +XXX[23] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 1647 ~71.614 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 63 / 1634 ~71.055 ms +XXX[24] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 1732 ~72.202 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 85 / 1719 ~71.646 ms +XXX[25] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 1798 ~71.927 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 64 / 1784 ~71.376 ms +XXX[26] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 1862 ~71.624 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 63 / 1847 ~71.063 ms +XXX[27] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 1948 ~72.167 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 85 / 1933 ~71.601 ms +XXX[28] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2015 ~71.976 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 66 / 1999 ~71.412 ms +XXX[29] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 2079 ~71.695 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 63 / 2062 ~71.129 ms +XXX[30] TO 17 ms, lFrame0 0 ms, lFrameX 69 / 2148 ~71.624 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 69 / 2131 ~71.061 ms +XXX[31] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 2213 ~71.415 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 64 / 2196 ~70.855 ms +XXX[32] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 2281 ~71.295 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 67 / 2263 ~70.736 ms +XXX[33] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 2346 ~71.114 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 64 / 2328 ~70.558 ms +XXX[34] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 2414 ~71.014 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 67 / 2395 ~70.461 ms +XXX[35] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 2479 ~70.84 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 64 / 2460 ~70.289 ms +XXX[36] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 2547 ~70.758 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 67 / 2527 ~70.209 ms +XXX[37] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 2612 ~70.595 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 64 / 2591 ~70.048 ms +XXX[38] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2678 ~70.489 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 66 / 2657 ~69.944 ms +XXX[39] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 2743 ~70.352 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 64 / 2722 ~69.808 ms +XXX[40] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 2807 ~70.197 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 63 / 2786 ~69.656 ms +XXX[41] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 2871 ~70.035 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 63 / 2849 ~69.496 ms +XXX[42] TO 17 ms, lFrame0 0 ms, lFrameX 62 / 2934 ~69.863 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 62 / 2911 ~69.326 ms +XXX[43] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 2995 ~69.661 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 60 / 2972 ~69.126 ms +XXX[44] TO 17 ms, lFrame0 0 ms, lFrameX 46 / 3042 ~69.141 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 46 / 3018 ~68.607 ms +XXX[45] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3091 ~68.708 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 49 / 3067 ~68.175 ms +XXX[46] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3140 ~68.274 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 48 / 3116 ~67.743 ms +XXX[47] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3189 ~67.865 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 48 / 3164 ~67.334 ms +XXX[48] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3238 ~67.473 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 48 / 3213 ~66.944 ms +XXX[49] TO 17 ms, lFrame0 1 ms, lFrameX 41 / 3279 ~66.937 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 40 / 3253 ~66.396 ms +XXX[50] TO 17 ms, lFrame0 0 ms, lFrameX 74 / 3354 ~67.082 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 73 / 3327 ~66.541 ms +XXX[51] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3403 ~66.729 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 48 / 3375 ~66.189 ms +XXX[52] TO 17 ms, lFrame0 0 ms, lFrameX 39 / 3442 ~66.203 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 38 / 3414 ~65.658 ms +XXX[53] TO 17 ms, lFrame0 0 ms, lFrameX 59 / 3501 ~66.074 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 58 / 3473 ~65.529 ms +XXX[54] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3550 ~65.758 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 48 / 3521 ~65.213 ms +XXX[55] TO 17 ms, lFrame0 1 ms, lFrameX 37 / 3588 ~65.249 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 36 / 3558 ~64.693 ms +XXX[56] TO 17 ms, lFrame0 0 ms, lFrameX 43 / 3632 ~64.869 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 43 / 3601 ~64.315 ms +XXX[57] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 3697 ~64.87 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 64 / 3666 ~64.319 ms +XXX[58] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3745 ~64.586 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 47 / 3714 ~64.036 ms +XXX[59] TO 17 ms, lFrame0 0 ms, lFrameX 33 / 3779 ~64.054 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 32 / 3746 ~63.502 ms +XXX[60] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 3843 ~64.065 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 64 / 3810 ~63.515 ms +XXX[61] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3892 ~63.804 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 47 / 3858 ~63.254 ms +XXX[62] TO 17 ms, lFrame0 0 ms, lFrameX 29 / 3921 ~63.257 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 29 / 3887 ~62.703 ms +XXX[63] TO 17 ms, lFrame0 0 ms, lFrameX 51 / 3973 ~63.067 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 50 / 3938 ~62.512 ms +XXX[64] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4005 ~62.586 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 31 / 3970 ~62.032 ms +XXX[65] TO 17 ms, lFrame0 0 ms, lFrameX 27 / 4033 ~62.049 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 27 / 3997 ~61.494 ms +XXX[66] TO 17 ms, lFrame0 0 ms, lFrameX 54 / 4087 ~61.93 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 53 / 4050 ~61.376 ms +XXX[67] TO 17 ms, lFrame0 0 ms, lFrameX 31 / 4119 ~61.482 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 31 / 4082 ~60.93 ms +XXX[68] TO 17 ms, lFrame0 1 ms, lFrameX 25 / 4144 ~60.955 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 24 / 4106 ~60.396 ms +XXX[69] TO 17 ms, lFrame0 1 ms, lFrameX 39 / 4184 ~60.646 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 38 / 4145 ~60.074 ms +XXX[70] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 4233 ~60.475 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 48 / 4193 ~59.904 ms +XXX[71] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4265 ~60.081 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 32 / 4225 ~59.512 ms +XXX[72] TO 17 ms, lFrame0 0 ms, lFrameX 23 / 4289 ~59.578 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 23 / 4248 ~59.008 ms +XXX[73] TO 17 ms, lFrame0 0 ms, lFrameX 26 / 4316 ~59.127 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 25 / 4274 ~58.555 ms +XXX[74] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 4365 ~58.995 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 48 / 4323 ~58.422 ms +XXX[75] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4398 ~58.646 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 32 / 4355 ~58.072 ms +XXX[76] TO 17 ms, lFrame0 0 ms, lFrameX 23 / 4422 ~58.189 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0020 ms, finishGL 23 / 4378 ~57.612 ms +XXX[77] TO 17 ms, lFrame0 0 ms, lFrameX 26 / 4448 ~57.777 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 25 / 4404 ~57.201 ms +XXX[78] TO 17 ms, lFrame0 0 ms, lFrameX 53 / 4501 ~57.717 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 52 / 4457 ~57.142 ms +XXX[79] TO 17 ms, lFrame0 0 ms, lFrameX 38 / 4540 ~57.476 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 38 / 4495 ~56.903 ms +XXX[80] TO 17 ms, lFrame0 0 ms, lFrameX 37 / 4578 ~57.226 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 36 / 4532 ~56.651 ms +XXX[81] TO 17 ms, lFrame0 0 ms, lFrameX 69 / 4647 ~57.373 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 68 / 4600 ~56.8 ms +XXX[82] TO 17 ms, lFrame0 0 ms, lFrameX 51 / 4698 ~57.303 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 51 / 4651 ~56.73 ms +XXX[83] TO 17 ms, lFrame0 0 ms, lFrameX 43 / 4742 ~57.134 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 42 / 4694 ~56.559 ms +XXX[84] TO 17 ms, lFrame0 0 ms, lFrameX 74 / 4816 ~57.335 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 73 / 4767 ~56.761 ms +XXX[85] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 4865 ~57.246 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 49 / 4817 ~56.674 ms +XXX[86] TO 17 ms, lFrame0 0 ms, lFrameX 43 / 4909 ~57.083 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 42 / 4859 ~56.51 ms +XXX[87] TO 17 ms, lFrame0 0 ms, lFrameX 73 / 4982 ~57.269 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 72 / 4932 ~56.696 ms +XXX[88] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 5032 ~57.19 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 49 / 4982 ~56.618 ms +XXX[89] TO 17 ms, lFrame0 0 ms, lFrameX 43 / 5076 ~57.041 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 43 / 5025 ~56.469 ms +XXX[90] TO 17 ms, lFrame0 0 ms, lFrameX 72 / 5149 ~57.214 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 71 / 5097 ~56.64 ms +XXX[91] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 5199 ~57.141 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 50 / 5147 ~56.569 ms +XXX[92] TO 17 ms, lFrame0 0 ms, lFrameX 44 / 5244 ~57.002 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 43 / 5191 ~56.429 ms +XXX[93] TO 17 ms, lFrame0 0 ms, lFrameX 73 / 5317 ~57.174 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 72 / 5264 ~56.602 ms +XXX[94] TO 17 ms, lFrame0 0 ms, lFrameX 51 / 5368 ~57.111 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 50 / 5314 ~56.54 ms +XXX[95] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 5416 ~57.02 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 47 / 5362 ~56.449 ms +XXX[96] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 5487 ~57.157 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 69 / 5432 ~56.586 ms +XXX[97] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5554 ~57.266 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 67 / 5499 ~56.696 ms +XXX[98] TO 17 ms, lFrame0 0 ms, lFrameX 52 / 5607 ~57.216 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 51 / 5551 ~56.645 ms +XXX[99] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 5690 ~57.484 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 83 / 5634 ~56.913 ms +XXX[100] TO 17 ms, lFrame0 0 ms, lFrameX 71 / 5762 ~57.624 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 70 / 5705 ~57.053 ms +XXX[101] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 5823 ~57.661 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 60 / 5765 ~57.088 ms +XXX[102] TO 17 ms, lFrame0 0 ms, lFrameX 91 / 5914 ~57.989 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 90 / 5856 ~57.415 ms +XXX[103] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5982 ~58.082 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 67 / 5923 ~57.509 ms +XXX[104] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 6045 ~58.13 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 62 / 5985 ~57.555 ms +XXX[105] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 6131 ~58.396 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 85 / 6071 ~57.82 ms +XXX[106] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6199 ~58.482 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 67 / 6138 ~57.907 ms +XXX[107] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 6264 ~58.543 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 64 / 6202 ~57.966 ms +XXX[108] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 6351 ~58.805 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 86 / 6288 ~58.228 ms +XXX[109] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 6434 ~59.034 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 83 / 6372 ~58.459 ms +XXX[110] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6501 ~59.1 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 65 / 6437 ~58.523 ms +XXX[111] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 6600 ~59.465 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 99 / 6536 ~58.888 ms +XXX[112] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 6684 ~59.681 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 83 / 6619 ~59.105 ms +XXX[113] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6751 ~59.748 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 66 / 6686 ~59.172 ms +XXX[114] TO 17 ms, lFrame0 0 ms, lFrameX 100 / 6851 ~60.104 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 99 / 6786 ~59.528 ms +XXX[115] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 6937 ~60.326 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 85 / 6871 ~59.75 ms +XXX[116] TO 17 ms, lFrame0 0 ms, lFrameX 72 / 7010 ~60.433 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 71 / 6943 ~59.854 ms +XXX[117] TO 17 ms, lFrame0 0 ms, lFrameX 96 / 7107 ~60.744 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 96 / 7039 ~60.167 ms +XXX[118] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 7192 ~60.949 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 84 / 7123 ~60.372 ms +XXX[119] TO 17 ms, lFrame0 0 ms, lFrameX 77 / 7269 ~61.085 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 76 / 7200 ~60.506 ms +XXX[120] TO 17 ms, lFrame0 0 ms, lFrameX 106 / 7376 ~61.467 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 106 / 7306 ~60.888 ms +XXX[121] TO 17 ms, lFrame0 0 ms, lFrameX 79 / 7455 ~61.614 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 78 / 7385 ~61.036 ms +2013-06-17 03:02:44.695 java[63324:5f03] Persistent UI failed to open file file://localhost/Users/jogamp/Library/Saved%20Application%20State/com.apple.javajdk16.cmd.savedState/window_1.data: Operation not permitted (1) +XXX[122] TO 17 ms, lFrame0 0 ms, lFrameX 69 / 7525 ~61.68 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 69 / 7454 ~61.102 ms +XXX[123] TO 17 ms, lFrame0 0 ms, lFrameX 93 / 7618 ~61.941 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 93 / 7547 ~61.363 ms +XXX[124] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 7699 ~62.095 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 80 / 7628 ~61.517 ms +XXX[125] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 7765 ~62.124 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 64 / 7693 ~61.544 ms +XXX[126] TO 17 ms, lFrame0 0 ms, lFrameX 98 / 7864 ~62.413 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 98 / 7791 ~61.834 ms +XXX[127] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 7946 ~62.573 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 7873 ~61.995 ms +XXX[128] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 8010 ~62.584 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 63 / 7936 ~62.005 ms +XXX[129] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 8096 ~62.76 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 84 / 8021 ~62.181 ms +XXX[130] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 8178 ~62.913 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 8103 ~62.333 ms +XXX[131] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 8243 ~62.924 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 63 / 8167 ~62.343 ms +XXX[132] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 8328 ~63.093 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 84 / 8251 ~62.511 ms +XXX[133] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8394 ~63.115 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 65 / 8317 ~62.534 ms +XXX[134] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 8457 ~63.117 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 62 / 8379 ~62.534 ms +XXX[135] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 8543 ~63.287 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 85 / 8465 ~62.703 ms +XXX[136] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 8609 ~63.306 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 65 / 8530 ~62.723 ms +XXX[137] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 8671 ~63.293 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 60 / 8591 ~62.709 ms +XXX[138] TO 17 ms, lFrame0 0 ms, lFrameX 87 / 8758 ~63.466 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 86 / 8677 ~62.882 ms +XXX[139] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8825 ~63.489 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 66 / 8743 ~62.906 ms +FrameCount: 240 - FrameRate: 13.0 +XXX[140] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 8886 ~63.474 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 60 / 8804 ~62.889 ms +XXX[141] TO 17 ms, lFrame0 0 ms, lFrameX 88 / 8974 ~63.649 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 87 / 8892 ~63.065 ms +XXX[142] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9040 ~63.667 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 65 / 8957 ~63.082 ms +XXX[143] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 9102 ~63.652 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 60 / 9018 ~63.066 ms +XXX[144] TO 17 ms, lFrame0 0 ms, lFrameX 88 / 9190 ~63.824 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 87 / 9106 ~63.238 ms +XXX[145] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9257 ~63.841 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 65 / 9172 ~63.257 ms +XXX[146] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 9318 ~63.823 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 60 / 9232 ~63.238 ms +XXX[147] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 9407 ~63.995 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 88 / 9321 ~63.411 ms +XXX[148] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 9473 ~64.008 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 65 / 9386 ~63.424 ms +XXX[149] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 9534 ~63.992 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 61 / 9447 ~63.408 ms +XXX[150] TO 17 ms, lFrame0 0 ms, lFrameX 87 / 9622 ~64.151 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 87 / 9535 ~63.568 ms +XXX[151] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 9688 ~64.161 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 65 / 9600 ~63.578 ms +XXX[152] TO 17 ms, lFrame0 0 ms, lFrameX 59 / 9748 ~64.132 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 59 / 9659 ~63.548 ms +XXX[153] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 9837 ~64.297 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 88 / 9747 ~63.712 ms +XXX[154] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 9903 ~64.306 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 65 / 9813 ~63.721 ms +XXX[155] TO 17 ms, lFrame0 0 ms, lFrameX 59 / 9962 ~64.272 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 58 / 9871 ~63.687 ms +XXX[156] TO 17 ms, lFrame0 0 ms, lFrameX 90 / 10052 ~64.439 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 89 / 9961 ~63.854 ms +XXX[157] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10118 ~64.451 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 65 / 10027 ~63.867 ms +XXX[158] TO 17 ms, lFrame0 0 ms, lFrameX 59 / 10177 ~64.417 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 58 / 10085 ~63.832 ms +XXX[159] TO 17 ms, lFrame0 0 ms, lFrameX 90 / 10268 ~64.583 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 90 / 10175 ~63.999 ms +XXX[160] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10335 ~64.597 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 66 / 10242 ~64.014 ms +XXX[161] TO 17 ms, lFrame0 0 ms, lFrameX 59 / 10394 ~64.565 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 58 / 10300 ~63.981 ms +XXX[162] TO 17 ms, lFrame0 0 ms, lFrameX 90 / 10485 ~64.727 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 90 / 10391 ~64.144 ms +XXX[163] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10552 ~64.741 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 66 / 10457 ~64.158 ms +XXX[164] TO 17 ms, lFrame0 0 ms, lFrameX 60 / 10613 ~64.714 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 59 / 10517 ~64.131 ms +XXX[165] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 10702 ~64.862 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 88 / 10605 ~64.277 ms +XXX[166] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10768 ~64.873 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 66 / 10671 ~64.288 ms +XXX[167] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 10830 ~64.852 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 60 / 10732 ~64.266 ms +XXX[168] TO 17 ms, lFrame0 0 ms, lFrameX 90 / 10920 ~65.003 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 89 / 10822 ~64.418 ms +XXX[169] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 10988 ~65.021 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 67 / 10889 ~64.436 ms +XXX[170] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 11052 ~65.014 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 63 / 10952 ~64.428 ms +XXX[171] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 11138 ~65.136 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 85 / 11038 ~64.55 ms +XXX[172] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11205 ~65.148 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 66 / 11104 ~64.562 ms +XXX[173] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11273 ~65.165 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 67 / 11172 ~64.578 ms +XXX[174] TO 17 ms, lFrame0 0 ms, lFrameX 101 / 11375 ~65.376 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 101 / 11273 ~64.789 ms +XXX[175] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 11460 ~65.49 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 85 / 11358 ~64.904 ms +XXX[176] TO 17 ms, lFrame0 0 ms, lFrameX 74 / 11535 ~65.542 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 73 / 11432 ~64.955 ms +XXX[177] TO 17 ms, lFrame0 0 ms, lFrameX 97 / 11632 ~65.722 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 96 / 11528 ~65.134 ms +XXX[178] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 11717 ~65.827 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 83 / 11612 ~65.239 ms +XXX[179] TO 17 ms, lFrame0 0 ms, lFrameX 79 / 11796 ~65.904 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 78 / 11691 ~65.315 ms +XXX[180] TO 17 ms, lFrame0 0 ms, lFrameX 105 / 11901 ~66.121 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 104 / 11795 ~65.532 ms +XXX[181] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 11985 ~66.216 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 11878 ~65.627 ms +XXX[182] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 12066 ~66.298 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 80 / 11958 ~65.708 ms +XXX[183] TO 17 ms, lFrame0 0 ms, lFrameX 103 / 12170 ~66.502 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 103 / 12062 ~65.912 ms +XXX[184] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 12253 ~66.594 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 12144 ~66.004 ms +XXX[185] TO 17 ms, lFrame0 0 ms, lFrameX 79 / 12332 ~66.662 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 78 / 12223 ~66.071 ms +XXX[186] TO 17 ms, lFrame0 0 ms, lFrameX 100 / 12433 ~66.846 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 100 / 12323 ~66.254 ms +XXX[187] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 12515 ~66.929 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 81 / 12405 ~66.338 ms +XXX[188] TO 17 ms, lFrame0 0 ms, lFrameX 77 / 12592 ~66.983 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 76 / 12481 ~66.391 ms +XXX[189] TO 17 ms, lFrame0 0 ms, lFrameX 104 / 12696 ~67.179 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 103 / 12585 ~66.588 ms +XXX[190] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 12780 ~67.264 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 12667 ~66.673 ms +XXX[191] TO 17 ms, lFrame0 0 ms, lFrameX 77 / 12857 ~67.316 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 76 / 12744 ~66.724 ms +XXX[192] TO 17 ms, lFrame0 1 ms, lFrameX 105 / 12963 ~67.517 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 104 / 12849 ~66.922 ms +XXX[193] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 13047 ~67.602 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 83 / 12932 ~67.008 ms +XXX[194] TO 17 ms, lFrame0 0 ms, lFrameX 74 / 13122 ~67.64 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 74 / 13006 ~67.045 ms +XXX[195] TO 17 ms, lFrame0 0 ms, lFrameX 106 / 13228 ~67.837 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 105 / 13112 ~67.242 ms +XXX[196] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 13309 ~67.908 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 81 / 13193 ~67.313 ms +XXX[197] TO 17 ms, lFrame0 0 ms, lFrameX 71 / 13381 ~67.928 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 71 / 13264 ~67.332 ms +XXX[198] TO 17 ms, lFrame0 0 ms, lFrameX 91 / 13473 ~68.046 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 90 / 13355 ~67.451 ms +XXX[199] TO 17 ms, lFrame0 1 ms, lFrameX 81 / 13554 ~68.114 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 79 / 13435 ~67.514 ms +XXX[200] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 13621 ~68.109 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 66 / 13501 ~67.508 ms +XXX[201] TO 17 ms, lFrame0 0 ms, lFrameX 96 / 13718 ~68.251 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 95 / 13597 ~67.649 ms +XXX[202] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 13800 ~68.317 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 81 / 13678 ~67.716 ms +XXX[203] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 13864 ~68.296 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 63 / 13742 ~67.695 ms +XXX[204] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 13949 ~68.381 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 85 / 13827 ~67.781 ms +XXX[205] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 14015 ~68.369 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 65 / 13892 ~67.769 ms +XXX[206] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 14081 ~68.358 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 65 / 13958 ~67.757 ms +XXX[207] TO 17 ms, lFrame0 0 ms, lFrameX 88 / 14170 ~68.455 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 88 / 14046 ~67.855 ms +XXX[208] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 14255 ~68.537 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 85 / 14131 ~67.938 ms +XXX[209] TO 17 ms, lFrame0 0 ms, lFrameX 73 / 14329 ~68.56 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 72 / 14203 ~67.961 ms +XXX[210] TO 17 ms, lFrame0 0 ms, lFrameX 97 / 14426 ~68.699 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 96 / 14300 ~68.099 ms +XXX[211] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 14511 ~68.774 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 83 / 14384 ~68.174 ms +XXX[212] TO 17 ms, lFrame0 0 ms, lFrameX 77 / 14588 ~68.814 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 76 / 14461 ~68.214 ms +XXX[213] TO 17 ms, lFrame0 0 ms, lFrameX 105 / 14694 ~68.986 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 105 / 14566 ~68.387 ms +XXX[214] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 14777 ~69.051 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 14648 ~68.452 ms +XXX[215] TO 17 ms, lFrame0 0 ms, lFrameX 75 / 14852 ~69.081 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 74 / 14723 ~68.482 ms +XXX[216] TO 17 ms, lFrame0 1 ms, lFrameX 106 / 14959 ~69.256 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 105 / 14829 ~68.653 ms +XXX[217] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15041 ~69.314 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 81 / 14910 ~68.712 ms +XXX[218] TO 17 ms, lFrame0 0 ms, lFrameX 73 / 15114 ~69.333 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 72 / 14983 ~68.73 ms +XXX[219] TO 17 ms, lFrame0 0 ms, lFrameX 91 / 15206 ~69.435 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 91 / 15074 ~68.833 ms +XXX[220] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 15287 ~69.489 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 80 / 15155 ~68.888 ms +XXX[221] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 15356 ~69.486 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 68 / 15223 ~68.885 ms +XXX[222] TO 17 ms, lFrame0 0 ms, lFrameX 94 / 15451 ~69.599 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 94 / 15317 ~68.998 ms +XXX[223] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 15532 ~69.652 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 80 / 15398 ~69.051 ms +XXX[224] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 15597 ~69.63 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 63 / 15462 ~69.028 ms +XXX[225] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 15677 ~69.678 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 79 / 15542 ~69.077 ms +XXX[226] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 15744 ~69.664 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 65 / 15608 ~69.062 ms +XXX[227] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 15807 ~69.637 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 62 / 15671 ~69.035 ms +XXX[228] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 15893 ~69.709 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 85 / 15756 ~69.107 ms +XXX[229] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 15960 ~69.696 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 66 / 15822 ~69.095 ms +XXX[230] TO 17 ms, lFrame0 0 ms, lFrameX 62 / 16023 ~69.667 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 62 / 15884 ~69.064 ms +XXX[231] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 16109 ~69.738 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 85 / 15970 ~69.134 ms +XXX[232] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 16175 ~69.721 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 65 / 16035 ~69.119 ms +XXX[233] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 16237 ~69.687 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 61 / 16096 ~69.085 ms +XXX[234] TO 17 ms, lFrame0 0 ms, lFrameX 87 / 16324 ~69.764 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 87 / 16184 ~69.162 ms +XXX[235] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 16392 ~69.754 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 66 / 16250 ~69.152 ms +XXX[236] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 16456 ~69.729 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 63 / 16314 ~69.127 ms +XXX[237] TO 17 ms, lFrame0 0 ms, lFrameX 87 / 16543 ~69.804 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 87 / 16401 ~69.203 ms +XXX[238] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 16611 ~69.796 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 67 / 16468 ~69.196 ms +XXX[239] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 16679 ~69.788 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 67 / 16535 ~69.187 ms +XXX[240] TO 17 ms, lFrame0 0 ms, lFrameX 103 / 16782 ~69.926 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 102 / 16638 ~69.326 ms +XXX[241] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 16868 ~69.993 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 85 / 16723 ~69.393 ms +XXX[242] TO 17 ms, lFrame0 0 ms, lFrameX 73 / 16942 ~70.009 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 73 / 16796 ~69.408 ms +XXX[243] TO 17 ms, lFrame0 0 ms, lFrameX 95 / 17037 ~70.113 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 94 / 16891 ~69.512 ms +XXX[244] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 17122 ~70.173 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 84 / 16975 ~69.573 ms +XXX[245] TO 17 ms, lFrame0 0 ms, lFrameX 77 / 17200 ~70.204 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 77 / 17053 ~69.604 ms +XXX[246] TO 17 ms, lFrame0 0 ms, lFrameX 107 / 17307 ~70.356 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 107 / 17160 ~69.756 ms +XXX[247] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 17391 ~70.411 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 83 / 17243 ~69.811 ms +XXX[248] TO 17 ms, lFrame0 0 ms, lFrameX 78 / 17470 ~70.445 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 78 / 17321 ~69.845 ms +XXX[249] TO 17 ms, lFrame0 0 ms, lFrameX 104 / 17574 ~70.58 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 103 / 17424 ~69.979 ms +XXX[250] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 17657 ~70.629 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 17507 ~70.029 ms +XXX[251] TO 17 ms, lFrame0 0 ms, lFrameX 77 / 17735 ~70.658 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 77 / 17584 ~70.058 ms +XXX[252] TO 17 ms, lFrame0 0 ms, lFrameX 103 / 17839 ~70.789 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 103 / 17687 ~70.189 ms +XXX[253] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 17921 ~70.836 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 17769 ~70.236 ms +XXX[254] TO 17 ms, lFrame0 0 ms, lFrameX 76 / 17997 ~70.856 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 75 / 17845 ~70.256 ms +XXX[255] TO 17 ms, lFrame0 0 ms, lFrameX 104 / 18102 ~70.988 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 103 / 17949 ~70.388 ms +XXX[256] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18184 ~71.032 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 81 / 18030 ~70.432 ms +XXX[257] TO 17 ms, lFrame0 0 ms, lFrameX 73 / 18257 ~71.04 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 72 / 18103 ~70.44 ms +XXX[258] TO 17 ms, lFrame0 0 ms, lFrameX 90 / 18347 ~71.114 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 89 / 18192 ~70.514 ms +XXX[259] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18429 ~71.157 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 81 / 18274 ~70.557 ms +FrameCount: 360 - FrameRate: 12.0 +XXX[260] TO 17 ms, lFrame0 0 ms, lFrameX 69 / 18499 ~71.152 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 69 / 18343 ~70.551 ms +XXX[261] TO 17 ms, lFrame0 0 ms, lFrameX 94 / 18594 ~71.241 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 94 / 18437 ~70.641 ms +XXX[262] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18676 ~71.285 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 18519 ~70.684 ms +XXX[263] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 18744 ~71.27 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 66 / 18586 ~70.67 ms +XXX[264] TO 17 ms, lFrame0 0 ms, lFrameX 97 / 18841 ~71.37 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 97 / 18683 ~70.77 ms +XXX[265] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 18923 ~71.409 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 81 / 18764 ~70.809 ms +XXX[266] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 18988 ~71.386 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 64 / 18829 ~70.786 ms +XXX[267] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 19071 ~71.43 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 18911 ~70.83 ms +XXX[268] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 19137 ~71.409 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 65 / 18977 ~70.809 ms +XXX[269] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 19201 ~71.38 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 62 / 19039 ~70.78 ms +XXX[270] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 19286 ~71.431 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 84 / 19124 ~70.831 ms +XXX[271] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 19351 ~71.407 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 64 / 19188 ~70.807 ms +XXX[272] TO 17 ms, lFrame0 0 ms, lFrameX 60 / 19411 ~71.366 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 59 / 19248 ~70.765 ms +XXX[273] TO 17 ms, lFrame0 0 ms, lFrameX 87 / 19499 ~71.426 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 87 / 19335 ~70.827 ms +XXX[274] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19564 ~71.404 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 64 / 19400 ~70.805 ms +XXX[275] TO 17 ms, lFrame0 0 ms, lFrameX 57 / 19622 ~71.353 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 56 / 19457 ~70.753 ms +XXX[276] TO 17 ms, lFrame0 0 ms, lFrameX 72 / 19694 ~71.358 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 72 / 19529 ~70.759 ms +XXX[277] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19760 ~71.335 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 64 / 19594 ~70.737 ms +XXX[278] TO 17 ms, lFrame0 0 ms, lFrameX 53 / 19813 ~71.271 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 52 / 19647 ~70.672 ms +XXX[279] TO 17 ms, lFrame0 0 ms, lFrameX 77 / 19891 ~71.294 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 77 / 19724 ~70.695 ms +XXX[280] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 19957 ~71.276 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 65 / 19789 ~70.677 ms +XXX[281] TO 17 ms, lFrame0 0 ms, lFrameX 51 / 20008 ~71.205 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 50 / 19840 ~70.605 ms +XXX[282] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 20089 ~71.237 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 79 / 19920 ~70.638 ms +XXX[283] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 20154 ~71.218 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 65 / 19985 ~70.62 ms +XXX[284] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 20204 ~71.141 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 48 / 20034 ~70.542 ms +XXX[285] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 20287 ~71.184 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 20117 ~70.585 ms +XXX[286] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20354 ~71.167 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 65 / 20182 ~70.569 ms +XXX[287] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 20404 ~71.095 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 49 / 20232 ~70.496 ms +XXX[288] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 20488 ~71.139 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 83 / 20315 ~70.541 ms +XXX[289] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 20556 ~71.129 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 67 / 20383 ~70.532 ms +XXX[290] TO 17 ms, lFrame0 0 ms, lFrameX 55 / 20611 ~71.074 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 54 / 20438 ~70.476 ms +XXX[291] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 20693 ~71.111 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 81 / 20519 ~70.513 ms +XXX[292] TO 17 ms, lFrame0 0 ms, lFrameX 69 / 20762 ~71.105 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 68 / 20588 ~70.507 ms +XXX[293] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 20826 ~71.08 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 63 / 20651 ~70.483 ms +XXX[294] TO 17 ms, lFrame0 0 ms, lFrameX 94 / 20921 ~71.16 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 93 / 20745 ~70.562 ms +XXX[295] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 21010 ~71.221 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 88 / 20834 ~70.624 ms +XXX[296] TO 17 ms, lFrame0 0 ms, lFrameX 76 / 21086 ~71.239 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 75 / 20909 ~70.64 ms +XXX[297] TO 17 ms, lFrame0 0 ms, lFrameX 110 / 21197 ~71.372 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 110 / 21019 ~70.773 ms +XXX[298] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 21281 ~71.415 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 83 / 21103 ~70.816 ms +XXX[299] TO 17 ms, lFrame0 0 ms, lFrameX 79 / 21360 ~71.441 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 78 / 21181 ~70.842 ms +XXX[300] TO 17 ms, lFrame0 0 ms, lFrameX 104 / 21465 ~71.55 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 103 / 21285 ~70.951 ms +XXX[301] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 21549 ~71.592 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 83 / 21369 ~70.993 ms +XXX[302] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 21630 ~71.622 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 80 / 21449 ~71.023 ms +XXX[303] TO 17 ms, lFrame0 0 ms, lFrameX 104 / 21734 ~71.731 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 104 / 21553 ~71.132 ms +XXX[304] TO 17 ms, lFrame0 0 ms, lFrameX 100 / 21835 ~71.825 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 99 / 21653 ~71.227 ms +XXX[305] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 21915 ~71.855 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 80 / 21733 ~71.256 ms +XXX[306] TO 17 ms, lFrame0 0 ms, lFrameX 100 / 22016 ~71.948 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 99 / 21832 ~71.349 ms +XXX[307] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 22098 ~71.982 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 81 / 21914 ~71.383 ms +XXX[308] TO 17 ms, lFrame0 0 ms, lFrameX 79 / 22178 ~72.006 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 79 / 21993 ~71.408 ms +XXX[309] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 22264 ~72.053 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 86 / 22079 ~71.455 ms +XXX[310] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 22347 ~72.088 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 22162 ~71.49 ms +XXX[311] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22430 ~72.124 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 22245 ~71.527 ms +XXX[312] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 22513 ~72.159 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 22327 ~71.562 ms +XXX[313] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 22597 ~72.195 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 22410 ~71.597 ms +XXX[314] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22680 ~72.23 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 22492 ~71.633 ms +XXX[315] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22763 ~72.265 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 22575 ~71.668 ms +XXX[316] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 22863 ~72.351 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 98 / 22674 ~71.754 ms +XXX[317] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 22947 ~72.39 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 84 / 22758 ~71.793 ms +XXX[318] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23031 ~72.425 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 83 / 22841 ~71.829 ms +XXX[319] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 23112 ~72.453 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 80 / 22922 ~71.857 ms +XXX[320] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 23196 ~72.49 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 83 / 23006 ~71.894 ms +XXX[321] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23279 ~72.522 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 23088 ~71.926 ms +XXX[322] TO 17 ms, lFrame0 5 ms, lFrameX 84 / 23363 ~72.557 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 78 / 23167 ~71.947 ms +XXX[323] TO 17 ms, lFrame0 0 ms, lFrameX 96 / 23460 ~72.632 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 96 / 23263 ~72.022 ms +XXX[324] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23542 ~72.662 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 81 / 23345 ~72.052 ms +XXX[325] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23625 ~72.694 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 23427 ~72.085 ms +XXX[326] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23708 ~72.726 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 0 ~0.0030 ms, finishGL 82 / 23510 ~72.117 ms +XXX[327] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23791 ~72.758 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 23592 ~72.149 ms +XXX[328] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23874 ~72.789 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 23675 ~72.18 ms +XXX[329] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23957 ~72.819 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 23757 ~72.21 ms +XXX[330] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24040 ~72.85 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 23840 ~72.243 ms +XXX[331] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24123 ~72.88 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 23922 ~72.273 ms +XXX[332] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24206 ~72.911 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 24005 ~72.304 ms +XXX[333] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24289 ~72.942 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 24087 ~72.335 ms +XXX[334] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24372 ~72.972 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 24170 ~72.365 ms +XXX[335] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24456 ~73.004 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 24253 ~72.398 ms +XXX[336] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24539 ~73.034 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 24335 ~72.428 ms +XXX[337] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24622 ~73.063 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 24418 ~72.457 ms +XXX[338] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24705 ~73.094 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 24501 ~72.488 ms +XXX[339] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24788 ~73.123 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 24583 ~72.518 ms +XXX[340] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24872 ~73.153 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 24666 ~72.548 ms +XXX[341] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24955 ~73.184 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 24749 ~72.579 ms +XXX[342] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 25038 ~73.211 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 24831 ~72.606 ms +XXX[343] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 25121 ~73.24 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 24913 ~72.634 ms +XXX[344] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 25204 ~73.268 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 24996 ~72.663 ms +XXX[345] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25288 ~73.299 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 25079 ~72.694 ms +XXX[346] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25371 ~73.328 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 25162 ~72.723 ms +XXX[347] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 25454 ~73.355 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 25244 ~72.75 ms +XXX[348] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25537 ~73.384 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 25327 ~72.78 ms +XXX[349] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25621 ~73.414 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 25410 ~72.81 ms +XXX[350] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25704 ~73.442 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 25493 ~72.838 ms +XXX[351] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25788 ~73.472 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 25577 ~72.869 ms +XXX[352] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 25871 ~73.499 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 25659 ~72.895 ms +XXX[353] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25955 ~73.527 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 25742 ~72.924 ms +XXX[354] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26037 ~73.553 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 25824 ~72.95 ms +XXX[355] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26121 ~73.582 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 25908 ~72.98 ms +XXX[356] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26204 ~73.608 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 25990 ~73.006 ms +XXX[357] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26287 ~73.634 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 26072 ~73.033 ms +XXX[358] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 26369 ~73.657 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 26154 ~73.056 ms +XXX[359] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26452 ~73.683 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 26236 ~73.083 ms +XXX[360] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26534 ~73.708 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 26318 ~73.107 ms +XXX[361] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26618 ~73.734 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 26401 ~73.134 ms +XXX[362] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26700 ~73.758 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 26483 ~73.159 ms +XXX[363] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26783 ~73.785 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 26566 ~73.185 ms +XXX[364] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26866 ~73.809 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 26648 ~73.21 ms +XXX[365] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26949 ~73.833 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 26730 ~73.235 ms +XXX[366] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27031 ~73.857 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 26812 ~73.259 ms +XXX[367] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27114 ~73.882 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 26895 ~73.284 ms +XXX[368] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27197 ~73.906 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 26977 ~73.308 ms +XXX[369] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27279 ~73.928 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 27059 ~73.331 ms +XXX[370] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27362 ~73.954 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 27142 ~73.357 ms +XXX[371] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 27447 ~73.983 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 84 / 27226 ~73.387 ms +XXX[372] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 27532 ~74.01 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 27310 ~73.414 ms +XXX[373] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27615 ~74.035 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 27393 ~73.439 ms +XXX[374] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27698 ~74.06 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 27475 ~73.464 ms +XXX[375] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 27782 ~74.087 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 27559 ~73.492 ms +XXX[376] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 27868 ~74.117 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 84 / 27644 ~73.522 ms +XXX[377] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 27952 ~74.144 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 27728 ~73.549 ms +XXX[378] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28035 ~74.168 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 27811 ~73.574 ms +XXX[379] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28118 ~74.191 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 27893 ~73.597 ms +FrameCount: 480 - FrameRate: 12.0 +XXX[380] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28201 ~74.215 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 27976 ~73.621 ms +XXX[381] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28284 ~74.238 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 28058 ~73.645 ms +XXX[382] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28367 ~74.261 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 28141 ~73.667 ms +XXX[383] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28450 ~74.284 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 28223 ~73.691 ms +XXX[384] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28533 ~74.306 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 28306 ~73.714 ms +XXX[385] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28616 ~74.327 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 28388 ~73.735 ms +XXX[386] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28699 ~74.35 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 28470 ~73.758 ms +XXX[387] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28781 ~74.371 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 28552 ~73.779 ms +XXX[388] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 28863 ~74.39 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 28634 ~73.799 ms +XXX[389] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 28945 ~74.41 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 28715 ~73.818 ms +XXX[390] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29028 ~74.432 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 28797 ~73.84 ms +XXX[391] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29111 ~74.453 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 82 / 28880 ~73.862 ms +XXX[392] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29194 ~74.475 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 82 / 28962 ~73.884 ms +XXX[393] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29277 ~74.497 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 82 / 29045 ~73.906 ms +XXX[394] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29359 ~74.516 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 81 / 29127 ~73.926 ms +XXX[395] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29442 ~74.537 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 82 / 29209 ~73.947 ms +XXX[396] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29525 ~74.559 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 82 / 29291 ~73.969 ms +XXX[397] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29608 ~74.579 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 82 / 29373 ~73.989 ms +XXX[398] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29691 ~74.601 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 82 / 29456 ~74.011 ms +XXX[399] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29775 ~74.624 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 83 / 29539 ~74.034 ms +XXX[400] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29857 ~74.643 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 81 / 29621 ~74.054 ms +XXX[401] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29940 ~74.663 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 82 / 29704 ~74.074 ms +XXX[402] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 30022 ~74.683 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 82 / 29786 ~74.095 ms +XXX[403] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 30105 ~74.703 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 82 / 29868 ~74.115 ms +XXX[404] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30188 ~74.724 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 82 / 29951 ~74.136 ms +XXX[405] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30272 ~74.745 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 82 / 30034 ~74.158 ms +XXX[406] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30355 ~74.768 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 83 / 30117 ~74.18 ms +XXX[407] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 30439 ~74.79 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 83 / 30200 ~74.203 ms +XXX[408] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 30524 ~74.814 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 83 / 30284 ~74.227 ms +XXX[409] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 30606 ~74.833 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 81 / 30366 ~74.246 ms +XXX[410] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 30686 ~74.846 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 79 / 30446 ~74.259 ms +XXX[411] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 30767 ~74.859 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 79 / 30526 ~74.273 ms +XXX[412] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 30847 ~74.872 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 79 / 30606 ~74.286 ms +XXX[413] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 30911 ~74.846 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 63 / 30669 ~74.26 ms +XXX[414] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 30977 ~74.825 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 30735 ~74.239 ms +XXX[415] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31043 ~74.802 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 65 / 30800 ~74.217 ms +XXX[416] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31108 ~74.78 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 65 / 30865 ~74.195 ms +XXX[417] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31174 ~74.759 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 65 / 30930 ~74.174 ms +XXX[418] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31240 ~74.738 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 65 / 30996 ~74.154 ms +XXX[419] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31306 ~74.718 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 65 / 31062 ~74.134 ms +XXX[420] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31373 ~74.697 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 65 / 31127 ~74.113 ms +XXX[421] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31438 ~74.675 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 64 / 31192 ~74.092 ms +XXX[422] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31504 ~74.656 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 65 / 31258 ~74.072 ms +XXX[423] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31570 ~74.635 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 65 / 31324 ~74.052 ms +XXX[424] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31637 ~74.617 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0020 ms, finishGL 66 / 31390 ~74.034 ms +XXX[425] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 31704 ~74.599 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 66 / 31457 ~74.016 ms +XXX[426] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31771 ~74.58 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 66 / 31523 ~73.997 ms +XXX[427] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31837 ~74.561 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 31588 ~73.978 ms +XXX[428] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 31905 ~74.544 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 67 / 31656 ~73.962 ms +XXX[429] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31971 ~74.526 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 66 / 31722 ~73.944 ms +XXX[430] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32038 ~74.508 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 66 / 31788 ~73.927 ms +XXX[431] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32105 ~74.49 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 66 / 31854 ~73.909 ms +XXX[432] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 32172 ~74.473 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 66 / 31921 ~73.892 ms +XXX[433] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32238 ~74.453 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 31987 ~73.873 ms +XXX[434] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32305 ~74.435 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 66 / 32053 ~73.855 ms +XXX[435] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32371 ~74.416 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 32118 ~73.836 ms +XXX[436] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32438 ~74.399 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 66 / 32185 ~73.819 ms +XXX[437] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32504 ~74.381 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 66 / 32251 ~73.801 ms +XXX[438] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 32570 ~74.362 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 32316 ~73.782 ms +XXX[439] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 32636 ~74.342 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 32381 ~73.763 ms +XXX[440] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32702 ~74.323 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 32447 ~73.744 ms +XXX[441] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 32768 ~74.303 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 32512 ~73.724 ms +XXX[442] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 32833 ~74.284 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 32577 ~73.705 ms +XXX[443] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 32898 ~74.263 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 64 / 32642 ~73.685 ms +XXX[444] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 32964 ~74.244 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 32707 ~73.665 ms +XXX[445] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33030 ~74.224 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 32772 ~73.646 ms +XXX[446] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33096 ~74.206 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 32838 ~73.628 ms +XXX[447] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33161 ~74.186 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 64 / 32903 ~73.609 ms +XXX[448] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33226 ~74.167 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 64 / 32968 ~73.589 ms +XXX[449] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33292 ~74.148 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 33033 ~73.571 ms +XXX[450] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33358 ~74.129 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 33098 ~73.552 ms +XXX[451] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33423 ~74.11 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 64 / 33163 ~73.533 ms +XXX[452] TO 17 ms, lFrame0 0 ms, lFrameX 47 / 33471 ~74.052 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 47 / 33210 ~73.474 ms +XXX[453] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 33521 ~73.999 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 49 / 33260 ~73.422 ms +XXX[454] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 33570 ~73.944 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 33308 ~73.367 ms +XXX[455] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 33619 ~73.888 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 47 / 33356 ~73.311 ms +XXX[456] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 33669 ~73.836 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 49 / 33406 ~73.259 ms +XXX[457] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 33718 ~73.781 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 33454 ~73.205 ms +XXX[458] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 33767 ~73.728 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 33503 ~73.152 ms +XXX[459] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 33816 ~73.674 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 33552 ~73.099 ms +XXX[460] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 33866 ~73.622 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 49 / 33601 ~73.046 ms +XXX[461] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 33915 ~73.569 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 33650 ~72.993 ms +XXX[462] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 33964 ~73.515 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 33698 ~72.94 ms +XXX[463] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34013 ~73.462 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 33747 ~72.887 ms +XXX[464] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34062 ~73.41 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 33795 ~72.835 ms +XXX[465] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34111 ~73.357 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 33844 ~72.783 ms +XXX[466] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34160 ~73.305 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 33892 ~72.731 ms +XXX[467] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34209 ~73.253 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 33941 ~72.679 ms +XXX[468] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34258 ~73.202 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 33989 ~72.628 ms +XXX[469] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34307 ~73.15 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 34038 ~72.576 ms +XXX[470] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34356 ~73.099 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 34087 ~72.525 ms +XXX[471] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34405 ~73.048 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 34135 ~72.474 ms +XXX[472] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34455 ~72.998 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 34184 ~72.424 ms +XXX[473] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34503 ~72.945 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 47 / 34232 ~72.372 ms +XXX[474] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 34553 ~72.897 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 49 / 34281 ~72.324 ms +XXX[475] TO 17 ms, lFrame0 2 ms, lFrameX 34 / 34588 ~72.816 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 31 / 34313 ~72.239 ms +XXX[476] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 34653 ~72.8 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 64 / 34378 ~72.223 ms +XXX[477] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 34703 ~72.754 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 50 / 34428 ~72.177 ms +XXX[478] TO 17 ms, lFrame0 1 ms, lFrameX 33 / 34737 ~72.672 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 32 / 34461 ~72.094 ms +XXX[479] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 34803 ~72.658 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 34526 ~72.08 ms +XXX[480] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34852 ~72.61 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 34575 ~72.031 ms +XXX[481] TO 17 ms, lFrame0 0 ms, lFrameX 34 / 34887 ~72.53 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 33 / 34608 ~71.951 ms +XXX[482] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 34954 ~72.519 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 66 / 34675 ~71.94 ms +XXX[483] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35004 ~72.473 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 49 / 34725 ~71.894 ms +XXX[484] TO 17 ms, lFrame0 0 ms, lFrameX 35 / 35040 ~72.396 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 34 / 34760 ~71.818 ms +XXX[485] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 35105 ~72.381 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 64 / 34824 ~71.803 ms +XXX[486] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35155 ~72.336 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 49 / 34874 ~71.757 ms +XXX[487] TO 17 ms, lFrame0 0 ms, lFrameX 37 / 35192 ~72.264 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 36 / 34911 ~71.685 ms +XXX[488] TO 17 ms, lFrame0 1 ms, lFrameX 46 / 35238 ~72.21 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 44 / 34955 ~71.629 ms +XXX[489] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35289 ~72.167 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 50 / 35005 ~71.585 ms +XXX[490] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 35356 ~72.156 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 66 / 35071 ~71.574 ms +XXX[491] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35406 ~72.111 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 49 / 35121 ~71.529 ms +XXX[492] TO 17 ms, lFrame0 0 ms, lFrameX 38 / 35445 ~72.043 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 37 / 35159 ~71.461 ms +XXX[493] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 35506 ~72.021 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 60 / 35220 ~71.44 ms +XXX[494] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35557 ~71.978 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 49 / 35269 ~71.396 ms +XXX[495] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 35607 ~71.933 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 48 / 35318 ~71.35 ms +XXX[496] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35657 ~71.89 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 49 / 35368 ~71.307 ms +XXX[497] TO 17 ms, lFrame0 0 ms, lFrameX 41 / 35698 ~71.828 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 40 / 35408 ~71.244 ms +XXX[498] TO 17 ms, lFrame0 0 ms, lFrameX 76 / 35775 ~71.837 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 75 / 35484 ~71.254 ms +XXX[499] TO 17 ms, lFrame0 0 ms, lFrameX 53 / 35828 ~71.799 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 52 / 35537 ~71.216 ms +FrameCount: 600 - FrameRate: 20.0 +XXX[500] TO 17 ms, lFrame0 0 ms, lFrameX 47 / 35875 ~71.75 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 46 / 35583 ~71.167 ms +XXX[501] TO 17 ms, lFrame0 0 ms, lFrameX 74 / 35950 ~71.756 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 73 / 35657 ~71.172 ms +XXX[502] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 36020 ~71.753 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 69 / 35727 ~71.169 ms +XXX[503] TO 17 ms, lFrame0 0 ms, lFrameX 60 / 36080 ~71.73 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 59 / 35787 ~71.147 ms +XXX[504] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 36151 ~71.728 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 70 / 35857 ~71.145 ms +XXX[505] TO 17 ms, lFrame0 0 ms, lFrameX 90 / 36241 ~71.766 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 90 / 35947 ~71.183 ms +XXX[506] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36325 ~71.789 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 36030 ~71.207 ms +XXX[507] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 36408 ~71.811 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 36113 ~71.229 ms +XXX[508] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 36491 ~71.833 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 36195 ~71.251 ms +XXX[509] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36575 ~71.856 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 36278 ~71.274 ms +XXX[510] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 36658 ~71.878 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 36361 ~71.296 ms +XXX[511] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 36740 ~71.899 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 36443 ~71.317 ms +XXX[512] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36823 ~71.921 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 36525 ~71.339 ms +XXX[513] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36906 ~71.942 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 36608 ~71.361 ms +XXX[514] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36990 ~71.965 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 36691 ~71.384 ms +XXX[515] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37073 ~71.987 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 36774 ~71.406 ms +XXX[516] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37156 ~72.009 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 36857 ~71.428 ms +XXX[517] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37240 ~72.031 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 36940 ~71.451 ms +XXX[518] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37323 ~72.053 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 37023 ~71.473 ms +XXX[519] TO 17 ms, lFrame0 6 ms, lFrameX 82 / 37406 ~72.073 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 76 / 37099 ~71.482 ms +XXX[520] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 37488 ~72.092 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 37181 ~71.501 ms +XXX[521] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37571 ~72.113 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 37263 ~71.523 ms +XXX[522] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 37654 ~72.134 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 37345 ~71.543 ms +XXX[523] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 37736 ~72.154 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 37427 ~71.563 ms +XXX[524] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37819 ~72.174 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 37510 ~71.584 ms +XXX[525] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 37902 ~72.195 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 37592 ~71.605 ms +XXX[526] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 37985 ~72.215 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 37675 ~71.625 ms +XXX[527] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38068 ~72.237 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 37758 ~71.647 ms +XXX[528] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38152 ~72.258 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 37841 ~71.668 ms +XXX[529] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38235 ~72.278 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 37923 ~71.689 ms +XXX[530] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38319 ~72.3 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 38007 ~71.711 ms +XXX[531] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 38403 ~72.323 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 84 / 38091 ~71.734 ms +XXX[532] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38486 ~72.343 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 38173 ~71.755 ms +XXX[533] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 38571 ~72.366 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 38257 ~71.777 ms +XXX[534] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38654 ~72.387 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 38340 ~71.799 ms +XXX[535] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38738 ~72.408 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 38423 ~71.82 ms +XXX[536] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38822 ~72.429 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 38507 ~71.841 ms +XXX[537] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 38906 ~72.45 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 38590 ~71.862 ms +XXX[538] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 38988 ~72.469 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 38672 ~71.881 ms +XXX[539] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39070 ~72.487 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 38754 ~71.9 ms +XXX[540] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39153 ~72.506 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 38836 ~71.919 ms +XXX[541] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39236 ~72.525 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 38918 ~71.938 ms +XXX[542] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39318 ~72.543 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 39000 ~71.956 ms +XXX[543] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 39398 ~72.557 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 80 / 39080 ~71.971 ms +XXX[544] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39481 ~72.575 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 39162 ~71.989 ms +XXX[545] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39564 ~72.594 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 39244 ~72.008 ms +XXX[546] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 39645 ~72.611 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 39325 ~72.025 ms +XXX[547] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 39727 ~72.627 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 39406 ~72.041 ms +XXX[548] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 39808 ~72.643 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 80 / 39487 ~72.057 ms +XXX[549] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 39889 ~72.659 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 80 / 39568 ~72.073 ms +XXX[550] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39971 ~72.676 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 39649 ~72.09 ms +XXX[551] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 40036 ~72.661 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 64 / 39714 ~72.076 ms +XXX[552] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40101 ~72.648 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 64 / 39778 ~72.063 ms +XXX[553] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40166 ~72.634 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 64 / 39843 ~72.049 ms +XXX[554] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40232 ~72.622 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 39908 ~72.037 ms +XXX[555] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40298 ~72.609 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 39973 ~72.024 ms +XXX[556] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40364 ~72.597 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 40039 ~72.012 ms +XXX[557] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 40431 ~72.588 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 66 / 40106 ~72.003 ms +XXX[558] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40497 ~72.576 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 40171 ~71.991 ms +XXX[559] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 40563 ~72.565 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 66 / 40237 ~71.981 ms +XXX[560] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 40630 ~72.554 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 66 / 40303 ~71.971 ms +XXX[561] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 40697 ~72.544 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 66 / 40369 ~71.96 ms +XXX[562] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40763 ~72.532 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 65 / 40435 ~71.948 ms +XXX[563] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 40831 ~72.525 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 68 / 40503 ~71.942 ms +XXX[564] TO 17 ms, lFrame0 0 ms, lFrameX 69 / 40901 ~72.52 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 69 / 40572 ~71.936 ms +XXX[565] TO 17 ms, lFrame0 0 ms, lFrameX 71 / 40973 ~72.518 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 71 / 40643 ~71.935 ms +XXX[566] TO 17 ms, lFrame0 0 ms, lFrameX 88 / 41061 ~72.546 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 87 / 40731 ~71.963 ms +XXX[567] TO 17 ms, lFrame0 0 ms, lFrameX 87 / 41148 ~72.571 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 86 / 40817 ~71.989 ms +XXX[568] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 41233 ~72.594 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 85 / 40903 ~72.012 ms +XXX[569] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 41317 ~72.614 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 40986 ~72.032 ms +XXX[570] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 41398 ~72.629 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 80 / 41066 ~72.047 ms +XXX[571] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 41480 ~72.644 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 80 / 41147 ~72.062 ms +XXX[572] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 41562 ~72.661 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 41229 ~72.08 ms +XXX[573] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 41645 ~72.679 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 41312 ~72.098 ms +XXX[574] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 41728 ~72.697 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 41394 ~72.115 ms +XXX[575] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 41810 ~72.713 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 41476 ~72.132 ms +XXX[576] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 41893 ~72.731 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 41558 ~72.15 ms +XXX[577] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 41976 ~72.749 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 41641 ~72.169 ms +XXX[578] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42059 ~72.767 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 41724 ~72.187 ms +XXX[579] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42143 ~72.787 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 41807 ~72.206 ms +XXX[580] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42227 ~72.805 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 41890 ~72.225 ms +XXX[581] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42310 ~72.823 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 41973 ~72.243 ms +XXX[582] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 42395 ~72.844 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 84 / 42057 ~72.264 ms +XXX[583] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42478 ~72.862 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 42140 ~72.282 ms +XXX[584] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42562 ~72.88 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 42223 ~72.301 ms +XXX[585] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 42644 ~72.896 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 42305 ~72.317 ms +XXX[586] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 42726 ~72.911 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 42386 ~72.332 ms +XXX[587] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 42808 ~72.926 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 42468 ~72.347 ms +XXX[588] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 42890 ~72.942 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 42549 ~72.363 ms +XXX[589] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 42973 ~72.959 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 42632 ~72.38 ms +XXX[590] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 43056 ~72.977 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 42715 ~72.398 ms +XXX[591] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 43138 ~72.992 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 42796 ~72.413 ms +XXX[592] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 43221 ~73.01 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 42879 ~72.431 ms +XXX[593] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 43304 ~73.026 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 42961 ~72.448 ms +XXX[594] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 43387 ~73.042 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 43043 ~72.464 ms +XXX[595] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 43470 ~73.059 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 43126 ~72.48 ms +XXX[596] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 43553 ~73.075 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 43208 ~72.497 ms +XXX[597] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 43636 ~73.092 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 43290 ~72.514 ms +XXX[598] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 43718 ~73.108 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 43373 ~72.53 ms +XXX[599] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 43802 ~73.126 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 43456 ~72.549 ms +XXX[600] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 43885 ~73.142 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 81 / 43538 ~72.564 ms +XXX[601] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 43968 ~73.158 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 43621 ~72.581 ms +XXX[602] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 44051 ~73.175 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 43704 ~72.598 ms +XXX[603] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 44135 ~73.193 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 43787 ~72.616 ms +XXX[604] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 44219 ~73.21 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 83 / 43870 ~72.633 ms +XXX[605] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 44302 ~73.227 ms, flushGL 0 / 2 ~0.0030 ms, waitGL 0 / 1 ~0.0030 ms, finishGL 82 / 43953 ~72.65 ms diff --git a/src/test/com/jogamp/opengl/test/bugs/Bug735.OSX.CALayer.Perf.logs/aaaa-m1-sync1-flush-wait-finish.log b/src/test/com/jogamp/opengl/test/bugs/Bug735.OSX.CALayer.Perf.logs/aaaa-m1-sync1-flush-wait-finish.log new file mode 100644 index 000000000..fe90a4ede --- /dev/null +++ b/src/test/com/jogamp/opengl/test/bugs/Bug735.OSX.CALayer.Perf.logs/aaaa-m1-sync1-flush-wait-finish.log @@ -0,0 +1,745 @@ +NSZombieEnabled +NSTraceEvents YES +OBJC_PRINT_EXCEPTIONS +/usr/bin/java +java version "1.6.0_37" +Java(TM) SE Runtime Environment (build 1.6.0_37-b06-434-11M3909) +Java HotSpot(TM) 64-Bit Server VM (build 20.12-b01-434, mixed mode) +LD_LIBRARY_PATH :../../gluegen/make/../build-macosx/obj:../build-macosx/lib +LIBXCB_ALLOW_SLOPPY_LOCK: +LIBGL_DRIVERS_PATH: +LIBGL_DEBUG: +LIBGL_ALWAYS_INDIRECT: +LIBGL_ALWAYS_SOFTWARE: +SWT_CLASSPATH: ../build-macosx/../make/lib/swt/cocoa-macosx-x86_64/swt-debug.jar +/usr/bin/java -d64 -time 100000 -vsyncN 0 +CLASSPATH .:../../gluegen/make/../build-macosx/gluegen-rt.jar:../build-macosx/jar/jogl-all.jar:../build-macosx/jar/jogl-test.jar:../build-macosx/../make/lib/swt/cocoa-macosx-x86_64/swt-debug.jar:../../gluegen/make/../make/lib/junit.jar:/opt-share/apache-ant/lib/ant.jar:/opt-share/apache-ant/lib/ant-junit.jar +CLASSPATH .:../../gluegen/make/../build-macosx/gluegen-rt.jar:../build-macosx/jar/jogl-all.jar:../build-macosx/jar/jogl-test.jar:../build-macosx/../make/lib/swt/cocoa-macosx-x86_64/swt-debug.jar:../../gluegen/make/../make/lib/junit.jar:/opt-share/apache-ant/lib/ant.jar:/opt-share/apache-ant/lib/ant-junit.jar + +Test Start: com.jogamp.opengl.test.bugs.Bug735Inv3AppletAWT -time 100000 -vsyncN 0 + +/usr/bin/java -d64 -Djava.awt.headless=false -Djogl.debug.calayer.SwapM1 com.jogamp.opengl.test.bugs.Bug735Inv3AppletAWT -time 100000 -vsyncN 0 +swapInterval 1 +exclusiveContext false +SWAP_M1 true +SWAP_M2 false +NewtCanvasAWT.attachNewtChild.2: size 500x268 +Thread[main-Display-.macosx_nil-1-EDT-1,5,main] LandscapeES2.init ... +LandscapeES2 init on Thread[main-Display-.macosx_nil-1-EDT-1,5,main] +Chosen GLCapabilities: GLCaps[rgba 8/8/8/0, opaque, accum-rgba 0/0/0/0, dp/st/ms 24/0/0, dbl, mono , hw, GLProfile[GL2/GL2.hw], offscr[fbo]] +INIT GL IS: jogamp.opengl.gl4.GL4bcImpl +GL_VENDOR: NVIDIA Corporation +GL_RENDERER: NVIDIA GeForce 320M OpenGL Engine +GL_VERSION: 2.1 NVIDIA-7.32.12 +GL GLSL: true, has-compiler-func: true, version 1.20, 1.20.0 +GL FBO: basic true, full true +GL Profile: GLProfile[GL2/GL2.hw] +GL Renderer Quirks:[NoOffscreenBitmap] +GL:jogamp.opengl.gl4.GL4bcImpl@57ac3379, 2.1 (hardware) - 2.1 NVIDIA-7.32.12 +Thread[main-Display-.macosx_nil-1-EDT-1,5,main] LandscapeES2.init FIN +Thread[main-Display-.macosx_nil-1-EDT-1,5,main] LandscapeES2.reshape 0/0 500x268, swapInterval 1, drawable 0x7ffd218cbca0 +Thread[AWT-EventQueue-0,6,main] LandscapeES2.reshape 0/0 500x268, swapInterval 1, drawable 0x7ffd218cbca0 +XXX[1] TO 17 ms, lFrame0 112 ms, lFrameX 850 / 850 ~850.044 ms, flushGL 1 / 1 ~1.124 ms, waitGL 5 / 5 ~5.544 ms, finishGL 731 / 731 ~731.319 ms +XXX[2] TO 17 ms, lFrame0 91 ms, lFrameX 179 / 1029 ~514.913 ms, flushGL 0 / 1 ~0.564 ms, waitGL 30 / 36 ~18.01 ms, finishGL 57 / 788 ~394.472 ms +XXX[3] TO 17 ms, lFrame0 2 ms, lFrameX 82 / 1112 ~370.819 ms, flushGL 0 / 1 ~0.379 ms, waitGL 0 / 36 ~12.319 ms, finishGL 79 / 868 ~289.378 ms +XXX[4] TO 17 ms, lFrame0 1 ms, lFrameX 85 / 1197 ~299.411 ms, flushGL 0 / 1 ~0.285 ms, waitGL 2 / 39 ~9.817 ms, finishGL 81 / 949 ~237.342 ms +XXX[5] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 1279 ~255.977 ms, flushGL 0 / 1 ~0.229 ms, waitGL 1 / 40 ~8.166 ms, finishGL 79 / 1029 ~205.818 ms +XXX[6] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 1362 ~227.166 ms, flushGL 0 / 1 ~0.191 ms, waitGL 1 / 42 ~7.095 ms, finishGL 80 / 1109 ~184.917 ms +XXX[7] TO 17 ms, lFrame0 1 ms, lFrameX 81 / 1444 ~206.414 ms, flushGL 0 / 1 ~0.165 ms, waitGL 1 / 44 ~6.362 ms, finishGL 78 / 1187 ~169.699 ms +XXX[8] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 1527 ~190.994 ms, flushGL 0 / 1 ~0.145 ms, waitGL 3 / 48 ~6.0 ms, finishGL 79 / 1266 ~158.37 ms +XXX[9] TO 17 ms, lFrame0 0 ms, lFrameX 98 / 1626 ~180.729 ms, flushGL 0 / 1 ~0.131 ms, waitGL 3 / 51 ~5.692 ms, finishGL 94 / 1361 ~151.302 ms +XXX[10] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 1709 ~170.991 ms, flushGL 0 / 1 ~0.118 ms, waitGL 4 / 56 ~5.623 ms, finishGL 77 / 1439 ~143.949 ms +XXX[11] TO 17 ms, lFrame0 0 ms, lFrameX 78 / 1788 ~162.557 ms, flushGL 0 / 1 ~0.108 ms, waitGL 4 / 60 ~5.514 ms, finishGL 72 / 1512 ~137.495 ms +XXX[12] TO 17 ms, lFrame0 0 ms, lFrameX 104 / 1892 ~157.681 ms, flushGL 0 / 1 ~0.099 ms, waitGL 8 / 69 ~5.801 ms, finishGL 94 / 1606 ~133.9 ms +XXX[13] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 1974 ~151.887 ms, flushGL 0 / 1 ~0.092 ms, waitGL 5 / 74 ~5.764 ms, finishGL 76 / 1683 ~129.467 ms +XXX[14] TO 17 ms, lFrame0 0 ms, lFrameX 76 / 2051 ~146.508 ms, flushGL 0 / 1 ~0.086 ms, waitGL 6 / 80 ~5.784 ms, finishGL 69 / 1752 ~125.199 ms +XXX[15] TO 17 ms, lFrame0 0 ms, lFrameX 104 / 2155 ~143.713 ms, flushGL 0 / 1 ~0.08 ms, waitGL 11 / 92 ~6.191 ms, finishGL 91 / 1844 ~122.975 ms +XXX[16] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 2238 ~139.928 ms, flushGL 0 / 1 ~0.076 ms, waitGL 8 / 101 ~6.326 ms, finishGL 74 / 1918 ~119.93 ms +XXX[17] TO 17 ms, lFrame0 1 ms, lFrameX 75 / 2314 ~136.122 ms, flushGL 0 / 1 ~0.071 ms, waitGL 7 / 108 ~6.397 ms, finishGL 66 / 1985 ~116.79 ms +XXX[18] TO 17 ms, lFrame0 0 ms, lFrameX 107 / 2421 ~134.528 ms, flushGL 0 / 1 ~0.068 ms, waitGL 14 / 123 ~6.866 ms, finishGL 91 / 2077 ~115.4 ms +XXX[19] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 2504 ~131.823 ms, flushGL 0 / 1 ~0.064 ms, waitGL 8 / 132 ~6.949 ms, finishGL 74 / 2151 ~113.231 ms +XXX[20] TO 17 ms, lFrame0 0 ms, lFrameX 75 / 2580 ~129.009 ms, flushGL 0 / 1 ~0.061 ms, waitGL 7 / 139 ~6.994 ms, finishGL 66 / 2218 ~110.919 ms +XXX[21] TO 17 ms, lFrame0 0 ms, lFrameX 107 / 2687 ~127.962 ms, flushGL 0 / 1 ~0.058 ms, waitGL 14 / 154 ~7.365 ms, finishGL 91 / 2310 ~110.007 ms +XXX[22] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 2770 ~125.93 ms, flushGL 0 / 1 ~0.056 ms, waitGL 8 / 163 ~7.414 ms, finishGL 74 / 2384 ~108.382 ms +XXX[23] TO 17 ms, lFrame0 0 ms, lFrameX 74 / 2845 ~123.71 ms, flushGL 0 / 1 ~0.054 ms, waitGL 8 / 171 ~7.442 ms, finishGL 66 / 2450 ~106.547 ms +XXX[24] TO 17 ms, lFrame0 0 ms, lFrameX 105 / 2951 ~122.963 ms, flushGL 0 / 1 ~0.051 ms, waitGL 15 / 186 ~7.773 ms, finishGL 89 / 2540 ~105.845 ms +XXX[25] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 3031 ~121.259 ms, flushGL 0 / 1 ~0.05 ms, waitGL 10 / 197 ~7.885 ms, finishGL 69 / 2609 ~104.382 ms +XXX[26] TO 17 ms, lFrame0 1 ms, lFrameX 70 / 3101 ~119.303 ms, flushGL 0 / 1 ~0.048 ms, waitGL 12 / 209 ~8.07 ms, finishGL 56 / 2666 ~102.545 ms +XXX[27] TO 17 ms, lFrame0 0 ms, lFrameX 94 / 3196 ~118.373 ms, flushGL 0 / 1 ~0.046 ms, waitGL 8 / 218 ~8.075 ms, finishGL 85 / 2751 ~101.909 ms +XXX[28] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 3278 ~117.099 ms, flushGL 0 / 1 ~0.045 ms, waitGL 13 / 231 ~8.283 ms, finishGL 67 / 2819 ~100.691 ms +XXX[29] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 3346 ~115.386 ms, flushGL 0 / 1 ~0.043 ms, waitGL 14 / 246 ~8.511 ms, finishGL 51 / 2871 ~99.0 ms +XXX[30] TO 17 ms, lFrame0 0 ms, lFrameX 97 / 3443 ~114.777 ms, flushGL 0 / 1 ~0.042 ms, waitGL 13 / 260 ~8.668 ms, finishGL 83 / 2954 ~98.477 ms +XXX[31] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 3525 ~113.715 ms, flushGL 0 / 1 ~0.041 ms, waitGL 16 / 276 ~8.926 ms, finishGL 64 / 3019 ~97.389 ms +XXX[32] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 3589 ~112.176 ms, flushGL 0 / 1 ~0.041 ms, waitGL 1 / 278 ~8.689 ms, finishGL 62 / 3081 ~96.295 ms +XXX[33] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 3673 ~111.319 ms, flushGL 0 / 1 ~0.04 ms, waitGL 2 / 280 ~8.499 ms, finishGL 80 / 3162 ~95.828 ms +XXX[34] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 3739 ~109.987 ms, flushGL 0 / 1 ~0.039 ms, waitGL 1 / 282 ~8.304 ms, finishGL 63 / 3225 ~94.878 ms +XXX[35] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 3802 ~108.655 ms, flushGL 0 / 1 ~0.038 ms, waitGL 2 / 284 ~8.131 ms, finishGL 60 / 3286 ~93.897 ms +XXX[36] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 3888 ~108.004 ms, flushGL 0 / 1 ~0.037 ms, waitGL 5 / 289 ~8.052 ms, finishGL 79 / 3365 ~93.496 ms +XXX[37] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 3955 ~106.916 ms, flushGL 0 / 1 ~0.036 ms, waitGL 3 / 293 ~7.931 ms, finishGL 63 / 3429 ~92.691 ms +XXX[38] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 4018 ~105.762 ms, flushGL 0 / 1 ~0.035 ms, waitGL 2 / 296 ~7.795 ms, finishGL 59 / 3489 ~91.822 ms +XXX[39] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 4104 ~105.241 ms, flushGL 0 / 1 ~0.034 ms, waitGL 5 / 301 ~7.731 ms, finishGL 79 / 3568 ~91.509 ms +XXX[40] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 4170 ~104.255 ms, flushGL 0 / 1 ~0.033 ms, waitGL 3 / 304 ~7.622 ms, finishGL 61 / 3630 ~90.771 ms +XXX[41] TO 17 ms, lFrame0 0 ms, lFrameX 60 / 4230 ~103.185 ms, flushGL 0 / 1 ~0.033 ms, waitGL 4 / 308 ~7.535 ms, finishGL 55 / 3686 ~89.918 ms +XXX[42] TO 17 ms, lFrame0 0 ms, lFrameX 88 / 4318 ~102.829 ms, flushGL 0 / 1 ~0.032 ms, waitGL 9 / 318 ~7.588 ms, finishGL 78 / 3764 ~89.635 ms +XXX[43] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4385 ~101.979 ms, flushGL 0 / 1 ~0.031 ms, waitGL 5 / 323 ~7.534 ms, finishGL 60 / 3825 ~88.959 ms +XXX[44] TO 17 ms, lFrame0 0 ms, lFrameX 59 / 4444 ~101.014 ms, flushGL 0 / 1 ~0.031 ms, waitGL 5 / 329 ~7.486 ms, finishGL 53 / 3879 ~88.159 ms +XXX[45] TO 17 ms, lFrame0 0 ms, lFrameX 90 / 4534 ~100.772 ms, flushGL 0 / 1 ~0.03 ms, waitGL 11 / 340 ~7.577 ms, finishGL 78 / 3957 ~87.933 ms +XXX[46] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4600 ~100.017 ms, flushGL 0 / 1 ~0.029 ms, waitGL 5 / 346 ~7.526 ms, finishGL 60 / 4017 ~87.333 ms +XXX[47] TO 17 ms, lFrame0 0 ms, lFrameX 60 / 4661 ~99.171 ms, flushGL 0 / 1 ~0.029 ms, waitGL 5 / 351 ~7.484 ms, finishGL 53 / 4071 ~86.623 ms +XXX[48] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 4750 ~98.961 ms, flushGL 0 / 1 ~0.028 ms, waitGL 11 / 363 ~7.565 ms, finishGL 77 / 4148 ~86.428 ms +XXX[49] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4816 ~98.297 ms, flushGL 0 / 1 ~0.028 ms, waitGL 6 / 369 ~7.534 ms, finishGL 59 / 4208 ~85.887 ms +XXX[50] TO 17 ms, lFrame0 0 ms, lFrameX 59 / 4876 ~97.524 ms, flushGL 0 / 1 ~0.027 ms, waitGL 5 / 375 ~7.502 ms, finishGL 53 / 4261 ~85.231 ms +XXX[51] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 4965 ~97.36 ms, flushGL 0 / 1 ~0.027 ms, waitGL 12 / 387 ~7.595 ms, finishGL 76 / 4338 ~85.059 ms +XXX[52] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5032 ~96.78 ms, flushGL 0 / 1 ~0.026 ms, waitGL 7 / 394 ~7.586 ms, finishGL 59 / 4397 ~84.57 ms +XXX[53] TO 17 ms, lFrame0 0 ms, lFrameX 59 / 5091 ~96.069 ms, flushGL 0 / 1 ~0.026 ms, waitGL 5 / 400 ~7.554 ms, finishGL 52 / 4450 ~83.966 ms +XXX[54] TO 17 ms, lFrame0 0 ms, lFrameX 90 / 5182 ~95.967 ms, flushGL 0 / 1 ~0.025 ms, waitGL 12 / 413 ~7.649 ms, finishGL 77 / 4527 ~83.843 ms +XXX[55] TO 17 ms, lFrame0 1 ms, lFrameX 65 / 5247 ~95.414 ms, flushGL 0 / 1 ~0.025 ms, waitGL 6 / 419 ~7.626 ms, finishGL 58 / 4585 ~83.374 ms +XXX[56] TO 17 ms, lFrame0 0 ms, lFrameX 58 / 5306 ~94.761 ms, flushGL 0 / 1 ~0.025 ms, waitGL 6 / 426 ~7.609 ms, finishGL 51 / 4637 ~82.806 ms +XXX[57] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 5396 ~94.675 ms, flushGL 0 / 1 ~0.024 ms, waitGL 13 / 439 ~7.717 ms, finishGL 75 / 4712 ~82.679 ms +XXX[58] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5463 ~94.203 ms, flushGL 0 / 1 ~0.024 ms, waitGL 8 / 447 ~7.722 ms, finishGL 58 / 4771 ~82.269 ms +XXX[59] TO 17 ms, lFrame0 0 ms, lFrameX 60 / 5523 ~93.626 ms, flushGL 0 / 1 ~0.023 ms, waitGL 6 / 454 ~7.709 ms, finishGL 52 / 4824 ~81.765 ms +XXX[60] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 5613 ~93.551 ms, flushGL 0 / 1 ~0.023 ms, waitGL 12 / 467 ~7.785 ms, finishGL 76 / 4900 ~81.672 ms +XXX[61] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5679 ~93.106 ms, flushGL 0 / 1 ~0.023 ms, waitGL 7 / 474 ~7.773 ms, finishGL 58 / 4959 ~81.297 ms +XXX[62] TO 17 ms, lFrame0 0 ms, lFrameX 60 / 5739 ~92.578 ms, flushGL 0 / 1 ~0.022 ms, waitGL 6 / 480 ~7.757 ms, finishGL 52 / 5011 ~80.836 ms +XXX[63] TO 17 ms, lFrame0 0 ms, lFrameX 73 / 5813 ~92.276 ms, flushGL 0 / 1 ~0.022 ms, waitGL 12 / 493 ~7.833 ms, finishGL 60 / 5072 ~80.515 ms +XXX[64] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5880 ~91.883 ms, flushGL 0 / 1 ~0.022 ms, waitGL 5 / 499 ~7.8 ms, finishGL 60 / 5133 ~80.208 ms +XXX[65] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5947 ~91.498 ms, flushGL 0 / 1 ~0.022 ms, waitGL 5 / 504 ~7.759 ms, finishGL 61 / 5194 ~79.917 ms +XXX[66] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6013 ~91.121 ms, flushGL 0 / 1 ~0.021 ms, waitGL 4 / 508 ~7.711 ms, finishGL 61 / 5256 ~79.638 ms +XXX[67] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6080 ~90.758 ms, flushGL 0 / 1 ~0.021 ms, waitGL 4 / 513 ~7.666 ms, finishGL 61 / 5317 ~79.37 ms +XXX[68] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6148 ~90.413 ms, flushGL 0 / 1 ~0.021 ms, waitGL 4 / 517 ~7.617 ms, finishGL 62 / 5380 ~79.122 ms +XXX[69] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6214 ~90.065 ms, flushGL 0 / 1 ~0.021 ms, waitGL 3 / 521 ~7.552 ms, finishGL 62 / 5443 ~78.886 ms +XXX[70] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6280 ~89.725 ms, flushGL 0 / 1 ~0.02 ms, waitGL 3 / 524 ~7.492 ms, finishGL 62 / 5505 ~78.649 ms +XXX[71] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6347 ~89.396 ms, flushGL 0 / 1 ~0.02 ms, waitGL 3 / 528 ~7.439 ms, finishGL 62 / 5567 ~78.417 ms +XXX[72] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6413 ~89.073 ms, flushGL 0 / 1 ~0.02 ms, waitGL 3 / 531 ~7.385 ms, finishGL 62 / 5629 ~78.19 ms +XXX[73] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 6479 ~88.753 ms, flushGL 0 / 1 ~0.02 ms, waitGL 4 / 536 ~7.343 ms, finishGL 60 / 5690 ~77.954 ms +XXX[74] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 6544 ~88.442 ms, flushGL 0 / 1 ~0.019 ms, waitGL 4 / 540 ~7.307 ms, finishGL 60 / 5751 ~77.719 ms +XXX[75] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6611 ~88.153 ms, flushGL 0 / 1 ~0.019 ms, waitGL 6 / 547 ~7.294 ms, finishGL 59 / 5811 ~77.483 ms +XXX[76] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6677 ~87.867 ms, flushGL 0 / 1 ~0.019 ms, waitGL 5 / 552 ~7.265 ms, finishGL 60 / 5872 ~77.264 ms +XXX[77] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6744 ~87.595 ms, flushGL 0 / 1 ~0.019 ms, waitGL 5 / 557 ~7.24 ms, finishGL 61 / 5933 ~77.055 ms +XXX[78] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6812 ~87.341 ms, flushGL 0 / 1 ~0.018 ms, waitGL 5 / 562 ~7.217 ms, finishGL 61 / 5994 ~76.857 ms +XXX[79] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6879 ~87.081 ms, flushGL 0 / 1 ~0.018 ms, waitGL 3 / 566 ~7.169 ms, finishGL 62 / 6057 ~76.68 ms +XXX[80] TO 17 ms, lFrame0 4 ms, lFrameX 66 / 6945 ~86.819 ms, flushGL 0 / 1 ~0.018 ms, waitGL 16 / 582 ~7.283 ms, finishGL 44 / 6102 ~76.282 ms +XXX[81] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 7012 ~86.575 ms, flushGL 0 / 1 ~0.018 ms, waitGL 3 / 586 ~7.239 ms, finishGL 62 / 6165 ~76.118 ms +XXX[82] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7078 ~86.325 ms, flushGL 0 / 1 ~0.018 ms, waitGL 3 / 589 ~7.188 ms, finishGL 62 / 6228 ~75.952 ms +XXX[83] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7145 ~86.089 ms, flushGL 0 / 1 ~0.018 ms, waitGL 3 / 593 ~7.145 ms, finishGL 62 / 6290 ~75.792 ms +XXX[84] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7212 ~85.859 ms, flushGL 0 / 1 ~0.017 ms, waitGL 3 / 596 ~7.1 ms, finishGL 62 / 6353 ~75.638 ms +XXX[85] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7279 ~85.637 ms, flushGL 0 / 1 ~0.017 ms, waitGL 2 / 599 ~7.052 ms, finishGL 63 / 6417 ~75.496 ms +XXX[86] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7345 ~85.409 ms, flushGL 0 / 1 ~0.017 ms, waitGL 2 / 602 ~7.002 ms, finishGL 62 / 6480 ~75.349 ms +XXX[87] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7411 ~85.188 ms, flushGL 0 / 1 ~0.017 ms, waitGL 3 / 605 ~6.958 ms, finishGL 62 / 6542 ~75.202 ms +XXX[88] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7477 ~84.976 ms, flushGL 0 / 1 ~0.017 ms, waitGL 3 / 608 ~6.917 ms, finishGL 62 / 6605 ~75.059 ms +XXX[89] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7544 ~84.766 ms, flushGL 0 / 1 ~0.017 ms, waitGL 3 / 611 ~6.873 ms, finishGL 62 / 6668 ~74.922 ms +XXX[90] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7610 ~84.566 ms, flushGL 0 / 1 ~0.016 ms, waitGL 3 / 615 ~6.835 ms, finishGL 62 / 6730 ~74.788 ms +XXX[91] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 7676 ~84.361 ms, flushGL 0 / 1 ~0.016 ms, waitGL 3 / 618 ~6.796 ms, finishGL 62 / 6793 ~74.649 ms +XXX[92] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7743 ~84.166 ms, flushGL 0 / 1 ~0.016 ms, waitGL 3 / 621 ~6.759 ms, finishGL 62 / 6855 ~74.518 ms +XXX[93] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7810 ~83.979 ms, flushGL 0 / 1 ~0.016 ms, waitGL 3 / 625 ~6.728 ms, finishGL 62 / 6918 ~74.388 ms +XXX[94] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7876 ~83.792 ms, flushGL 0 / 1 ~0.016 ms, waitGL 3 / 629 ~6.693 ms, finishGL 62 / 6980 ~74.261 ms +XXX[95] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 7942 ~83.603 ms, flushGL 0 / 1 ~0.016 ms, waitGL 3 / 632 ~6.657 ms, finishGL 62 / 7042 ~74.133 ms +XXX[96] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 8008 ~83.42 ms, flushGL 0 / 1 ~0.016 ms, waitGL 4 / 636 ~6.631 ms, finishGL 61 / 7104 ~74.0 ms +XXX[97] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8074 ~83.245 ms, flushGL 0 / 1 ~0.015 ms, waitGL 4 / 641 ~6.609 ms, finishGL 61 / 7165 ~73.871 ms +XXX[98] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8140 ~83.07 ms, flushGL 0 / 1 ~0.015 ms, waitGL 4 / 645 ~6.588 ms, finishGL 61 / 7226 ~73.741 ms +XXX[99] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8207 ~82.9 ms, flushGL 0 / 1 ~0.015 ms, waitGL 4 / 650 ~6.57 ms, finishGL 60 / 7287 ~73.612 ms +XXX[1] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 66 ~66.068 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 5 ~5.429 ms, finishGL 60 / 60 ~60.167 ms +XXX[2] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 132 ~66.192 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 5 / 10 ~5.453 ms, finishGL 60 / 120 ~60.277 ms +XXX[3] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 198 ~66.248 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 5 / 16 ~5.506 ms, finishGL 60 / 180 ~60.269 ms +XXX[4] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 264 ~66.104 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 5 / 22 ~5.581 ms, finishGL 59 / 240 ~60.061 ms +XXX[5] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 330 ~66.144 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 6 / 28 ~5.786 ms, finishGL 59 / 299 ~59.896 ms +XXX[6] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 397 ~66.292 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 6 / 35 ~5.943 ms, finishGL 59 / 359 ~59.883 ms +XXX[7] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 464 ~66.376 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 6 / 41 ~5.974 ms, finishGL 60 / 419 ~59.933 ms +XXX[8] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 531 ~66.462 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 5 / 47 ~5.941 ms, finishGL 60 / 480 ~60.052 ms +XXX[9] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 599 ~66.638 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 5 / 53 ~5.912 ms, finishGL 61 / 542 ~60.257 ms +XXX[10] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 665 ~66.544 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 3 / 56 ~5.684 ms, finishGL 61 / 603 ~60.392 ms +XXX[11] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 731 ~66.491 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 4 / 61 ~5.563 ms, finishGL 61 / 665 ~60.459 ms +XXX[12] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 797 ~66.436 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 4 / 66 ~5.511 ms, finishGL 60 / 725 ~60.457 ms +XXX[13] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 863 ~66.445 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 5 / 71 ~5.515 ms, finishGL 60 / 786 ~60.463 ms +XXX[14] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 929 ~66.392 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 5 / 77 ~5.523 ms, finishGL 59 / 845 ~60.402 ms +XXX[15] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 996 ~66.401 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 6 / 83 ~5.572 ms, finishGL 59 / 905 ~60.36 ms +XXX[16] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1062 ~66.427 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 6 / 90 ~5.64 ms, finishGL 59 / 965 ~60.319 ms +XXX[17] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 1130 ~66.474 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 5 / 96 ~5.66 ms, finishGL 60 / 1025 ~60.347 ms +XXX[18] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1196 ~66.479 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 5 / 101 ~5.642 ms, finishGL 60 / 1086 ~60.369 ms +XXX[19] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1263 ~66.504 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 5 / 106 ~5.618 ms, finishGL 61 / 1147 ~60.418 ms +FrameCount: 120 - FrameRate: 15.0 +XXX[20] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1330 ~66.516 ms, flushGL 0 / 0 ~0.0020 ms, waitGL 4 / 111 ~5.581 ms, finishGL 61 / 1209 ~60.461 ms +XXX[21] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 1397 ~66.566 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 115 ~5.523 ms, finishGL 62 / 1271 ~60.569 ms +XXX[22] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 1464 ~66.586 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 119 ~5.418 ms, finishGL 63 / 1335 ~60.694 ms +XXX[23] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1531 ~66.586 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 122 ~5.318 ms, finishGL 63 / 1398 ~60.795 ms +XXX[24] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1598 ~66.601 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 125 ~5.226 ms, finishGL 63 / 1461 ~60.903 ms +XXX[25] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1665 ~66.609 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 128 ~5.14 ms, finishGL 63 / 1524 ~60.998 ms +XXX[26] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1731 ~66.586 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 130 ~5.009 ms, finishGL 63 / 1588 ~61.105 ms +XXX[27] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 1798 ~66.602 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 132 ~4.92 ms, finishGL 63 / 1652 ~61.21 ms +XXX[28] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1864 ~66.603 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 135 ~4.839 ms, finishGL 63 / 1716 ~61.292 ms +XXX[29] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 1930 ~66.575 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 137 ~4.738 ms, finishGL 63 / 1779 ~61.365 ms +XXX[30] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1997 ~66.575 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 139 ~4.666 ms, finishGL 63 / 1843 ~61.438 ms +XXX[31] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2063 ~66.569 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 142 ~4.596 ms, finishGL 63 / 1906 ~61.502 ms +XXX[32] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2129 ~66.557 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 144 ~4.531 ms, finishGL 63 / 1969 ~61.556 ms +XXX[33] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 2197 ~66.575 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 147 ~4.479 ms, finishGL 63 / 2033 ~61.626 ms +XXX[34] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2263 ~66.574 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 150 ~4.414 ms, finishGL 63 / 2097 ~61.689 ms +XXX[35] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 2329 ~66.556 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 152 ~4.352 ms, finishGL 63 / 2160 ~61.734 ms +XXX[36] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2396 ~66.559 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 155 ~4.306 ms, finishGL 63 / 2224 ~61.783 ms +XXX[37] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2462 ~66.558 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 157 ~4.257 ms, finishGL 63 / 2287 ~61.831 ms +XXX[38] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2528 ~66.548 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 160 ~4.223 ms, finishGL 62 / 2350 ~61.856 ms +XXX[39] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2595 ~66.55 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 162 ~4.178 ms, finishGL 63 / 2414 ~61.903 ms +XXX[40] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2662 ~66.55 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 165 ~4.142 ms, finishGL 63 / 2477 ~61.939 ms +XXX[41] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2728 ~66.548 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 168 ~4.116 ms, finishGL 62 / 2540 ~61.962 ms +XXX[42] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2794 ~66.536 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 171 ~4.077 ms, finishGL 63 / 2603 ~61.987 ms +XXX[43] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 2860 ~66.521 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 173 ~4.044 ms, finishGL 62 / 2666 ~62.005 ms +XXX[44] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 2925 ~66.49 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 177 ~4.027 ms, finishGL 61 / 2727 ~61.987 ms +XXX[45] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 2990 ~66.456 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 181 ~4.043 ms, finishGL 59 / 2787 ~61.933 ms +XXX[46] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 3054 ~66.404 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 6 / 188 ~4.094 ms, finishGL 57 / 2844 ~61.83 ms +XXX[47] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 3117 ~66.333 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 8 / 196 ~4.189 ms, finishGL 54 / 2898 ~61.665 ms +XXX[48] TO 17 ms, lFrame0 0 ms, lFrameX 62 / 3180 ~66.252 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 11 / 208 ~4.349 ms, finishGL 50 / 2948 ~61.424 ms +XXX[49] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 3242 ~66.165 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 16 / 224 ~4.587 ms, finishGL 45 / 2993 ~61.099 ms +XXX[50] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3290 ~65.805 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 228 ~4.571 ms, finishGL 43 / 3037 ~60.756 ms +XXX[51] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3339 ~65.474 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 234 ~4.595 ms, finishGL 42 / 3080 ~60.401 ms +XXX[52] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3388 ~65.155 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 6 / 240 ~4.634 ms, finishGL 41 / 3122 ~60.044 ms +XXX[53] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3437 ~64.853 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 7 / 248 ~4.682 ms, finishGL 41 / 3163 ~59.693 ms +XXX[54] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3486 ~64.56 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 8 / 256 ~4.745 ms, finishGL 40 / 3204 ~59.336 ms +XXX[55] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3535 ~64.285 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 8 / 264 ~4.816 ms, finishGL 40 / 3244 ~58.991 ms +XXX[56] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3585 ~64.022 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 9 / 273 ~4.891 ms, finishGL 40 / 3284 ~58.653 ms +XXX[57] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3634 ~63.762 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 9 / 283 ~4.966 ms, finishGL 39 / 3324 ~58.317 ms +XXX[58] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3683 ~63.514 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 9 / 292 ~5.051 ms, finishGL 39 / 3363 ~57.986 ms +XXX[59] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3733 ~63.271 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 10 / 303 ~5.139 ms, finishGL 38 / 3401 ~57.654 ms +XXX[60] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3782 ~63.034 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 10 / 314 ~5.236 ms, finishGL 37 / 3439 ~57.32 ms +XXX[61] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3831 ~62.805 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 11 / 325 ~5.341 ms, finishGL 36 / 3476 ~56.986 ms +XXX[62] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3879 ~62.576 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 12 / 338 ~5.456 ms, finishGL 35 / 3511 ~56.642 ms +XXX[63] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3928 ~62.356 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 13 / 351 ~5.585 ms, finishGL 34 / 3546 ~56.294 ms +XXX[64] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3977 ~62.142 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 14 / 366 ~5.727 ms, finishGL 33 / 3580 ~55.938 ms +XXX[65] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 4025 ~61.937 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 15 / 382 ~5.881 ms, finishGL 32 / 3612 ~55.579 ms +XXX[66] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 4074 ~61.731 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 382 ~5.794 ms, finishGL 47 / 3660 ~55.461 ms +XXX[67] TO 17 ms, lFrame0 0 ms, lFrameX 30 / 4104 ~61.265 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 384 ~5.736 ms, finishGL 27 / 3688 ~55.045 ms +XXX[68] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 4155 ~61.106 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 388 ~5.711 ms, finishGL 45 / 3733 ~54.911 ms +XXX[69] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4187 ~60.689 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 392 ~5.684 ms, finishGL 28 / 3761 ~54.521 ms +XXX[70] TO 17 ms, lFrame0 0 ms, lFrameX 28 / 4216 ~60.231 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 397 ~5.677 ms, finishGL 22 / 3784 ~54.069 ms +XXX[71] TO 17 ms, lFrame0 0 ms, lFrameX 53 / 4269 ~60.13 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 8 / 406 ~5.721 ms, finishGL 43 / 3828 ~53.925 ms +XXX[72] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4301 ~59.745 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 6 / 412 ~5.727 ms, finishGL 25 / 3854 ~53.535 ms +XXX[73] TO 17 ms, lFrame0 0 ms, lFrameX 25 / 4327 ~59.278 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 6 / 418 ~5.739 ms, finishGL 18 / 3872 ~53.052 ms +XXX[74] TO 17 ms, lFrame0 0 ms, lFrameX 39 / 4366 ~59.011 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 13 / 432 ~5.845 ms, finishGL 25 / 3898 ~52.678 ms +XXX[75] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 4415 ~58.868 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 7 / 439 ~5.862 ms, finishGL 40 / 3938 ~52.519 ms +XXX[76] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4447 ~58.52 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 9 / 449 ~5.913 ms, finishGL 22 / 3961 ~52.12 ms +XXX[77] TO 17 ms, lFrame0 0 ms, lFrameX 23 / 4471 ~58.069 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 10 / 459 ~5.968 ms, finishGL 12 / 3974 ~51.61 ms +XXX[78] TO 17 ms, lFrame0 0 ms, lFrameX 42 / 4513 ~57.866 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 462 ~5.932 ms, finishGL 38 / 4012 ~51.443 ms +XXX[79] TO 17 ms, lFrame0 0 ms, lFrameX 33 / 4547 ~57.557 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 10 / 473 ~5.991 ms, finishGL 22 / 4034 ~51.074 ms +XXX[80] TO 17 ms, lFrame0 0 ms, lFrameX 23 / 4570 ~57.135 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 9 / 483 ~6.039 ms, finishGL 13 / 4047 ~50.599 ms +XXX[81] TO 17 ms, lFrame0 0 ms, lFrameX 42 / 4613 ~56.951 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 485 ~5.999 ms, finishGL 38 / 4086 ~50.453 ms +XXX[82] TO 17 ms, lFrame0 0 ms, lFrameX 33 / 4646 ~56.659 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 10 / 496 ~6.053 ms, finishGL 22 / 4108 ~50.107 ms +XXX[83] TO 17 ms, lFrame0 1 ms, lFrameX 25 / 4671 ~56.288 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 9 / 505 ~6.094 ms, finishGL 15 / 4123 ~49.685 ms +XXX[84] TO 17 ms, lFrame0 0 ms, lFrameX 46 / 4718 ~56.169 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 505 ~6.023 ms, finishGL 45 / 4169 ~49.637 ms +XXX[85] TO 17 ms, lFrame0 0 ms, lFrameX 38 / 4756 ~55.957 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 510 ~6.002 ms, finishGL 33 / 4203 ~49.447 ms +XXX[86] TO 17 ms, lFrame0 0 ms, lFrameX 36 / 4793 ~55.733 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 15 / 525 ~6.11 ms, finishGL 20 / 4223 ~49.114 ms +XXX[87] TO 17 ms, lFrame0 0 ms, lFrameX 69 / 4862 ~55.889 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 11 / 537 ~6.174 ms, finishGL 57 / 4280 ~49.206 ms +XXX[88] TO 17 ms, lFrame0 0 ms, lFrameX 52 / 4914 ~55.849 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 10 / 547 ~6.218 ms, finishGL 41 / 4322 ~49.122 ms +XXX[89] TO 17 ms, lFrame0 0 ms, lFrameX 42 / 4957 ~55.703 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 6 / 554 ~6.226 ms, finishGL 35 / 4358 ~48.967 ms +XXX[90] TO 17 ms, lFrame0 0 ms, lFrameX 74 / 5031 ~55.911 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 13 / 567 ~6.304 ms, finishGL 60 / 4418 ~49.096 ms +XXX[91] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 5082 ~55.846 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 573 ~6.297 ms, finishGL 43 / 4462 ~49.039 ms +XXX[92] TO 17 ms, lFrame0 0 ms, lFrameX 43 / 5125 ~55.711 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 578 ~6.289 ms, finishGL 37 / 4499 ~48.91 ms +XXX[93] TO 17 ms, lFrame0 0 ms, lFrameX 72 / 5198 ~55.892 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 11 / 590 ~6.344 ms, finishGL 60 / 4560 ~49.036 ms +XXX[94] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 5248 ~55.834 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 6 / 596 ~6.343 ms, finishGL 43 / 4604 ~48.979 ms +XXX[95] TO 17 ms, lFrame0 0 ms, lFrameX 44 / 5292 ~55.709 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 601 ~6.327 ms, finishGL 38 / 4642 ~48.87 ms +XXX[96] TO 17 ms, lFrame0 0 ms, lFrameX 72 / 5365 ~55.885 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 10 / 611 ~6.371 ms, finishGL 61 / 4704 ~49.002 ms +XXX[97] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 5415 ~55.831 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 617 ~6.36 ms, finishGL 44 / 4749 ~48.959 ms +XXX[98] TO 17 ms, lFrame0 0 ms, lFrameX 44 / 5460 ~55.717 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 620 ~6.335 ms, finishGL 40 / 4789 ~48.869 ms +XXX[99] TO 17 ms, lFrame0 0 ms, lFrameX 72 / 5532 ~55.886 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 8 / 629 ~6.358 ms, finishGL 63 / 4852 ~49.014 ms +XXX[100] TO 17 ms, lFrame0 0 ms, lFrameX 51 / 5584 ~55.843 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 632 ~6.327 ms, finishGL 47 / 4900 ~49.001 ms +XXX[101] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 5632 ~55.771 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 634 ~6.282 ms, finishGL 46 / 4946 ~48.973 ms +XXX[102] TO 17 ms, lFrame0 0 ms, lFrameX 69 / 5702 ~55.909 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 636 ~6.244 ms, finishGL 66 / 5013 ~49.147 ms +XXX[103] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5770 ~56.024 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 16 / 653 ~6.344 ms, finishGL 50 / 5063 ~49.161 ms +XXX[104] TO 17 ms, lFrame0 0 ms, lFrameX 52 / 5823 ~55.992 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 15 / 668 ~6.428 ms, finishGL 36 / 5100 ~49.043 ms +XXX[105] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 5906 ~56.252 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 11 / 679 ~6.472 ms, finishGL 71 / 5171 ~49.256 ms +XXX[106] TO 17 ms, lFrame0 0 ms, lFrameX 71 / 5977 ~56.391 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 12 / 691 ~6.527 ms, finishGL 58 / 5230 ~49.341 ms +XXX[107] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 6038 ~56.436 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 7 / 699 ~6.533 ms, finishGL 53 / 5283 ~49.381 ms +XXX[108] TO 17 ms, lFrame0 0 ms, lFrameX 75 / 6114 ~56.613 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 11 / 710 ~6.582 ms, finishGL 63 / 5346 ~49.508 ms +XXX[109] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6181 ~56.713 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 713 ~6.549 ms, finishGL 64 / 5410 ~49.641 ms +XXX[110] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6248 ~56.803 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 715 ~6.507 ms, finishGL 64 / 5475 ~49.774 ms +XXX[111] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 6314 ~56.885 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 717 ~6.464 ms, finishGL 63 / 5538 ~49.9 ms +XXX[112] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6381 ~56.976 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 719 ~6.427 ms, finishGL 64 / 5603 ~50.028 ms +XXX[113] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6448 ~57.067 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 721 ~6.386 ms, finishGL 65 / 5668 ~50.161 ms +XXX[114] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6514 ~57.146 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 722 ~6.341 ms, finishGL 64 / 5732 ~50.285 ms +XXX[115] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6582 ~57.239 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 724 ~6.298 ms, finishGL 66 / 5798 ~50.422 ms +XXX[116] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 6667 ~57.476 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 16 / 740 ~6.387 ms, finishGL 67 / 5866 ~50.57 ms +XXX[117] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 6749 ~57.69 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 15 / 756 ~6.462 ms, finishGL 66 / 5933 ~50.71 ms +XXX[118] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 6833 ~57.911 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 15 / 771 ~6.54 ms, finishGL 67 / 6000 ~50.852 ms +XXX[119] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 6917 ~58.13 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 15 / 786 ~6.613 ms, finishGL 68 / 6069 ~51.0 ms +XXX[120] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 7001 ~58.341 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 14 / 801 ~6.677 ms, finishGL 68 / 6137 ~51.147 ms +XXX[121] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 7084 ~58.552 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 14 / 815 ~6.738 ms, finishGL 69 / 6206 ~51.297 ms +XXX[122] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 7170 ~58.774 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 13 / 828 ~6.792 ms, finishGL 71 / 6278 ~51.465 ms +XXX[123] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 7255 ~58.988 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 10 / 839 ~6.825 ms, finishGL 73 / 6352 ~51.647 ms +XXX[124] TO 17 ms, lFrame0 1 ms, lFrameX 75 / 7331 ~59.122 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 7 / 847 ~6.832 ms, finishGL 66 / 6418 ~51.763 ms +XXX[125] TO 17 ms, lFrame0 0 ms, lFrameX 93 / 7424 ~59.396 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 16 / 864 ~6.912 ms, finishGL 76 / 6494 ~51.958 ms +XXX[126] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 7508 ~59.588 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 6 / 870 ~6.907 ms, finishGL 76 / 6571 ~52.154 ms +XXX[127] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 7591 ~59.773 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 6 / 876 ~6.9 ms, finishGL 76 / 6648 ~52.347 ms +2013-06-17 02:51:40.860 java[62528:5f07] Persistent UI failed to open file file://localhost/Users/jogamp/Library/Saved%20Application%20State/com.apple.javajdk16.cmd.savedState/window_1.data: Operation not permitted (1) +XXX[128] TO 17 ms, lFrame0 0 ms, lFrameX 79 / 7671 ~59.93 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 882 ~6.892 ms, finishGL 73 / 6721 ~52.512 ms +XXX[129] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 7751 ~60.091 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 9 / 891 ~6.911 ms, finishGL 70 / 6792 ~52.655 ms +XXX[130] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 7834 ~60.261 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 11 / 903 ~6.948 ms, finishGL 70 / 6862 ~52.788 ms +XXX[131] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 7915 ~60.424 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 12 / 916 ~6.993 ms, finishGL 68 / 6930 ~52.907 ms +XXX[132] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 7997 ~60.583 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 14 / 930 ~7.048 ms, finishGL 66 / 6997 ~53.011 ms +XXX[133] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 8079 ~60.751 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 16 / 946 ~7.116 ms, finishGL 66 / 7063 ~53.112 ms +XXX[134] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 8162 ~60.912 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 16 / 963 ~7.187 ms, finishGL 65 / 7129 ~53.202 ms +XXX[135] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 8245 ~61.075 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 963 ~7.137 ms, finishGL 82 / 7211 ~53.415 ms +XXX[136] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 8328 ~61.236 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 965 ~7.096 ms, finishGL 80 / 7292 ~53.618 ms +XXX[137] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 8393 ~61.266 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 966 ~7.051 ms, finishGL 63 / 7355 ~53.693 ms +XXX[138] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 8460 ~61.31 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 968 ~7.015 ms, finishGL 64 / 7420 ~53.774 ms +XXX[139] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8526 ~61.345 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 969 ~6.972 ms, finishGL 64 / 7485 ~53.851 ms +FrameCount: 240 - FrameRate: 13.0 +XXX[140] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8593 ~61.38 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 970 ~6.932 ms, finishGL 64 / 7549 ~53.926 ms +XXX[141] TO 17 ms, lFrame0 4 ms, lFrameX 69 / 8662 ~61.435 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 14 / 985 ~6.989 ms, finishGL 49 / 7599 ~53.894 ms +XXX[142] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 8742 ~61.566 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 15 / 1001 ~7.05 ms, finishGL 63 / 7663 ~53.965 ms +XXX[143] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8808 ~61.599 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1003 ~7.015 ms, finishGL 63 / 7726 ~54.032 ms +XXX[144] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 8874 ~61.628 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1005 ~6.983 ms, finishGL 62 / 7789 ~54.094 ms +XXX[145] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8940 ~61.659 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1008 ~6.955 ms, finishGL 62 / 7852 ~54.153 ms +XXX[146] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9006 ~61.69 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1011 ~6.931 ms, finishGL 62 / 7914 ~54.209 ms +XXX[147] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9073 ~61.726 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1015 ~6.909 ms, finishGL 62 / 7977 ~54.267 ms +XXX[148] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9139 ~61.755 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1019 ~6.89 ms, finishGL 61 / 8038 ~54.316 ms +XXX[149] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9206 ~61.787 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1024 ~6.874 ms, finishGL 61 / 8100 ~54.364 ms +XXX[150] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9272 ~61.818 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1027 ~6.852 ms, finishGL 62 / 8162 ~54.416 ms +XXX[151] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9339 ~61.85 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1031 ~6.831 ms, finishGL 62 / 8225 ~54.47 ms +XXX[152] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9405 ~61.878 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1035 ~6.81 ms, finishGL 62 / 8287 ~54.52 ms +XXX[153] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 9472 ~61.912 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1039 ~6.791 ms, finishGL 62 / 8349 ~54.573 ms +XXX[154] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9538 ~61.939 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1042 ~6.769 ms, finishGL 62 / 8412 ~54.623 ms +XXX[155] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 9606 ~61.974 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1046 ~6.748 ms, finishGL 63 / 8475 ~54.679 ms +XXX[156] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9672 ~62.0 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1048 ~6.723 ms, finishGL 62 / 8538 ~54.731 ms +XXX[157] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9738 ~62.028 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1052 ~6.701 ms, finishGL 62 / 8600 ~54.782 ms +XXX[158] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9804 ~62.054 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1055 ~6.679 ms, finishGL 62 / 8663 ~54.83 ms +XXX[159] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9870 ~62.08 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1058 ~6.66 ms, finishGL 62 / 8725 ~54.875 ms +XXX[160] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 9936 ~62.103 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1062 ~6.643 ms, finishGL 61 / 8786 ~54.915 ms +XXX[161] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10002 ~62.127 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1067 ~6.63 ms, finishGL 60 / 8847 ~54.952 ms +XXX[162] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10068 ~62.152 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 1072 ~6.622 ms, finishGL 60 / 8907 ~54.985 ms +XXX[163] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10135 ~62.178 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 1078 ~6.616 ms, finishGL 60 / 8968 ~55.018 ms +XXX[164] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 10200 ~62.2 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 1084 ~6.61 ms, finishGL 59 / 9027 ~55.047 ms +XXX[165] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10267 ~62.228 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 6 / 1090 ~6.61 ms, finishGL 59 / 9087 ~55.076 ms +XXX[166] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10334 ~62.253 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 1096 ~6.606 ms, finishGL 59 / 9147 ~55.105 ms +XXX[167] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 10402 ~62.287 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 6 / 1102 ~6.603 ms, finishGL 61 / 9208 ~55.143 ms +XXX[168] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 10467 ~62.303 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1106 ~6.588 ms, finishGL 60 / 9268 ~55.172 ms +XXX[169] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 10534 ~62.331 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 1112 ~6.584 ms, finishGL 60 / 9329 ~55.204 ms +XXX[170] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10600 ~62.354 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 1118 ~6.577 ms, finishGL 60 / 9389 ~55.234 ms +XXX[171] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 10667 ~62.382 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 1123 ~6.572 ms, finishGL 60 / 9450 ~55.267 ms +XXX[172] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10734 ~62.408 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 1129 ~6.564 ms, finishGL 61 / 9511 ~55.301 ms +XXX[173] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 10801 ~62.435 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1133 ~6.554 ms, finishGL 61 / 9573 ~55.339 ms +XXX[174] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 10867 ~62.455 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1138 ~6.541 ms, finishGL 61 / 9634 ~55.373 ms +XXX[175] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10934 ~62.48 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1143 ~6.531 ms, finishGL 61 / 9696 ~55.407 ms +XXX[176] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 11000 ~62.501 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1147 ~6.519 ms, finishGL 61 / 9757 ~55.44 ms +XXX[177] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11067 ~62.529 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1152 ~6.509 ms, finishGL 62 / 9819 ~55.479 ms +XXX[178] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11135 ~62.559 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1155 ~6.494 ms, finishGL 63 / 9883 ~55.525 ms +XXX[179] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11203 ~62.588 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1158 ~6.471 ms, finishGL 64 / 9948 ~55.577 ms +XXX[180] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11270 ~62.613 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 1159 ~6.44 ms, finishGL 65 / 10014 ~55.633 ms +XXX[181] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 11354 ~62.732 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 1159 ~6.408 ms, finishGL 82 / 10097 ~55.784 ms +XXX[182] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 11438 ~62.849 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 16 / 1176 ~6.462 ms, finishGL 67 / 10164 ~55.848 ms +XXX[183] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 11523 ~62.97 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 15 / 1191 ~6.511 ms, finishGL 69 / 10233 ~55.92 ms +XXX[184] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 11607 ~63.082 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 13 / 1204 ~6.548 ms, finishGL 69 / 10302 ~55.994 ms +XXX[185] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 11694 ~63.211 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 13 / 1218 ~6.583 ms, finishGL 73 / 10376 ~56.088 ms +XXX[186] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 11780 ~63.334 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 9 / 1227 ~6.598 ms, finishGL 76 / 10452 ~56.197 ms +XXX[187] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 11865 ~63.452 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 6 / 1233 ~6.598 ms, finishGL 78 / 10530 ~56.315 ms +XXX[188] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 11950 ~63.565 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1238 ~6.585 ms, finishGL 80 / 10611 ~56.441 ms +XXX[189] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 12034 ~63.673 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1240 ~6.564 ms, finishGL 80 / 10691 ~56.57 ms +XXX[190] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 12118 ~63.782 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 1242 ~6.539 ms, finishGL 82 / 10774 ~56.705 ms +XXX[191] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 12217 ~63.968 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 1242 ~6.507 ms, finishGL 98 / 10872 ~56.922 ms +XXX[192] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 12301 ~64.07 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 1244 ~6.48 ms, finishGL 81 / 10953 ~57.051 ms +XXX[193] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 12383 ~64.163 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 1245 ~6.451 ms, finishGL 80 / 11034 ~57.174 ms +XXX[194] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 12468 ~64.271 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 1247 ~6.428 ms, finishGL 82 / 11117 ~57.305 ms +XXX[195] TO 17 ms, lFrame0 0 ms, lFrameX 97 / 12566 ~64.441 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 17 / 1264 ~6.482 ms, finishGL 80 / 11197 ~57.422 ms +XXX[196] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 12647 ~64.529 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1266 ~6.461 ms, finishGL 78 / 11276 ~57.531 ms +XXX[197] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 12730 ~64.619 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1270 ~6.446 ms, finishGL 77 / 11354 ~57.634 ms +XXX[198] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 12813 ~64.715 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1274 ~6.438 ms, finishGL 78 / 11432 ~57.738 ms +XXX[199] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 12896 ~64.806 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1279 ~6.428 ms, finishGL 77 / 11510 ~57.84 ms +XXX[200] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 12979 ~64.899 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1284 ~6.42 ms, finishGL 78 / 11588 ~57.942 ms +XXX[201] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 13063 ~64.99 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1288 ~6.411 ms, finishGL 78 / 11666 ~58.043 ms +XXX[202] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 13145 ~65.079 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1293 ~6.401 ms, finishGL 78 / 11744 ~58.141 ms +XXX[203] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 13229 ~65.167 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1297 ~6.392 ms, finishGL 77 / 11822 ~58.239 ms +XXX[204] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 13311 ~65.251 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1302 ~6.384 ms, finishGL 77 / 11899 ~58.331 ms +XXX[205] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 13393 ~65.332 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 1308 ~6.381 ms, finishGL 75 / 11975 ~58.416 ms +XXX[206] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 13475 ~65.414 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 7 / 1315 ~6.384 ms, finishGL 74 / 12050 ~58.495 ms +XXX[207] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 13557 ~65.494 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 7 / 1323 ~6.392 ms, finishGL 73 / 12123 ~58.567 ms +XXX[208] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 13639 ~65.572 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 9 / 1332 ~6.405 ms, finishGL 72 / 12195 ~58.633 ms +XXX[209] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 13720 ~65.647 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 10 / 1343 ~6.426 ms, finishGL 69 / 12265 ~58.687 ms +XXX[210] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 13802 ~65.725 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 12 / 1355 ~6.455 ms, finishGL 69 / 12334 ~58.736 ms +XXX[211] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 13884 ~65.801 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 13 / 1369 ~6.489 ms, finishGL 67 / 12402 ~58.779 ms +XXX[212] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 13965 ~65.875 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 14 / 1384 ~6.529 ms, finishGL 65 / 12468 ~58.812 ms +XXX[213] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 14047 ~65.952 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 16 / 1400 ~6.577 ms, finishGL 65 / 12533 ~58.842 ms +XXX[214] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 14113 ~65.949 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 1401 ~6.55 ms, finishGL 63 / 12597 ~58.866 ms +XXX[215] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 14180 ~65.957 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1403 ~6.529 ms, finishGL 65 / 12662 ~58.896 ms +XXX[216] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 14248 ~65.965 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 1404 ~6.503 ms, finishGL 66 / 12729 ~58.93 ms +XXX[217] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 14333 ~66.05 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 16 / 1421 ~6.548 ms, finishGL 67 / 12796 ~58.97 ms +XXX[218] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 14418 ~66.142 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 15 / 1436 ~6.587 ms, finishGL 70 / 12867 ~59.023 ms +XXX[219] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 14504 ~66.23 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 12 / 1448 ~6.613 ms, finishGL 72 / 12939 ~59.086 ms +XXX[220] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 14590 ~66.319 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 9 / 1458 ~6.628 ms, finishGL 75 / 13015 ~59.159 ms +XXX[221] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 14675 ~66.405 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 7 / 1465 ~6.631 ms, finishGL 77 / 13092 ~59.243 ms +XXX[222] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 14759 ~66.484 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 1471 ~6.626 ms, finishGL 77 / 13170 ~59.328 ms +XXX[223] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 14842 ~66.559 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1475 ~6.616 ms, finishGL 78 / 13249 ~59.413 ms +XXX[224] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 14925 ~66.63 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1479 ~6.605 ms, finishGL 77 / 13326 ~59.494 ms +XXX[225] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15008 ~66.702 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1484 ~6.598 ms, finishGL 77 / 13404 ~59.574 ms +XXX[226] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15090 ~66.773 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 1489 ~6.592 ms, finishGL 76 / 13481 ~59.651 ms +XXX[227] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15173 ~66.843 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 1495 ~6.589 ms, finishGL 76 / 13557 ~59.724 ms +XXX[228] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15255 ~66.911 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 6 / 1502 ~6.587 ms, finishGL 75 / 13633 ~59.794 ms +XXX[229] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15338 ~66.978 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 7 / 1509 ~6.59 ms, finishGL 74 / 13707 ~59.859 ms +XXX[230] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15420 ~67.045 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 8 / 1517 ~6.596 ms, finishGL 73 / 13781 ~59.92 ms +XXX[231] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 15501 ~67.107 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 8 / 1526 ~6.606 ms, finishGL 72 / 13853 ~59.972 ms +XXX[232] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 15583 ~67.17 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 10 / 1536 ~6.624 ms, finishGL 70 / 13924 ~60.018 ms +XXX[233] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 15665 ~67.233 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 12 / 1548 ~6.647 ms, finishGL 69 / 13993 ~60.058 ms +XXX[234] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 15746 ~67.294 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 13 / 1562 ~6.676 ms, finishGL 67 / 14061 ~60.09 ms +XXX[235] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15828 ~67.357 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 15 / 1577 ~6.713 ms, finishGL 66 / 14127 ~60.116 ms +XXX[236] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 15910 ~67.415 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 16 / 1593 ~6.753 ms, finishGL 64 / 14191 ~60.134 ms +XXX[237] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 15976 ~67.411 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 1595 ~6.731 ms, finishGL 64 / 14256 ~60.152 ms +XXX[238] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 16043 ~67.409 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 1597 ~6.71 ms, finishGL 64 / 14321 ~60.172 ms +XXX[239] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 16109 ~67.402 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 1598 ~6.686 ms, finishGL 64 / 14385 ~60.189 ms +XXX[240] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 16176 ~67.4 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 1599 ~6.666 ms, finishGL 64 / 14450 ~60.208 ms +XXX[241] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 16241 ~67.394 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 1601 ~6.643 ms, finishGL 64 / 14514 ~60.224 ms +XXX[242] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 16308 ~67.389 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1603 ~6.624 ms, finishGL 63 / 14577 ~60.239 ms +XXX[243] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 16374 ~67.384 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1605 ~6.606 ms, finishGL 63 / 14641 ~60.252 ms +XXX[244] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 16440 ~67.377 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1607 ~6.589 ms, finishGL 62 / 14704 ~60.262 ms +XXX[245] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 16507 ~67.376 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1611 ~6.575 ms, finishGL 63 / 14767 ~60.275 ms +XXX[246] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 16573 ~67.372 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1613 ~6.559 ms, finishGL 63 / 14830 ~60.287 ms +XXX[247] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 16640 ~67.371 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1616 ~6.543 ms, finishGL 63 / 14894 ~60.302 ms +XXX[248] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 16708 ~67.372 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 1618 ~6.525 ms, finishGL 65 / 14959 ~60.321 ms +XXX[249] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 16776 ~67.373 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 1619 ~6.502 ms, finishGL 66 / 15026 ~60.345 ms +XXX[250] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 16860 ~67.442 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 16 / 1635 ~6.542 ms, finishGL 67 / 15093 ~60.374 ms +XXX[251] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 16945 ~67.513 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 15 / 1650 ~6.576 ms, finishGL 69 / 15163 ~60.411 ms +XXX[252] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 17030 ~67.582 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 13 / 1663 ~6.602 ms, finishGL 71 / 15234 ~60.455 ms +XXX[253] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 17116 ~67.652 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 11 / 1675 ~6.621 ms, finishGL 73 / 15308 ~60.507 ms +XXX[254] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 17200 ~67.719 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 9 / 1684 ~6.63 ms, finishGL 74 / 15383 ~60.563 ms +XXX[255] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 17285 ~67.785 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 7 / 1691 ~6.635 ms, finishGL 76 / 15459 ~60.625 ms +XXX[256] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 17369 ~67.85 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 6 / 1698 ~6.634 ms, finishGL 77 / 15537 ~60.692 ms +XXX[257] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 17454 ~67.916 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 1703 ~6.629 ms, finishGL 79 / 15616 ~60.763 ms +XXX[258] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 17538 ~67.977 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1706 ~6.615 ms, finishGL 79 / 15696 ~60.837 ms +XXX[259] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 17621 ~68.038 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1709 ~6.6 ms, finishGL 80 / 15776 ~60.913 ms +FrameCount: 360 - FrameRate: 15.0 +XXX[260] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 17704 ~68.095 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1712 ~6.587 ms, finishGL 79 / 15855 ~60.984 ms +XXX[261] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 17787 ~68.153 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1715 ~6.571 ms, finishGL 80 / 15936 ~61.057 ms +XXX[262] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 17871 ~68.21 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1717 ~6.556 ms, finishGL 79 / 16016 ~61.129 ms +XXX[263] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 17953 ~68.264 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1720 ~6.541 ms, finishGL 79 / 16095 ~61.199 ms +XXX[264] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18035 ~68.318 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1723 ~6.528 ms, finishGL 78 / 16174 ~61.265 ms +XXX[265] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18118 ~68.371 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1727 ~6.519 ms, finishGL 78 / 16252 ~61.329 ms +XXX[266] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18201 ~68.425 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 4 / 1732 ~6.512 ms, finishGL 77 / 16329 ~61.39 ms +XXX[267] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18283 ~68.478 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 1737 ~6.507 ms, finishGL 77 / 16406 ~61.448 ms +XXX[268] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18366 ~68.53 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 1743 ~6.504 ms, finishGL 75 / 16482 ~61.502 ms +XXX[269] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18448 ~68.582 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 6 / 1750 ~6.505 ms, finishGL 75 / 16558 ~61.554 ms +XXX[270] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 18529 ~68.627 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 7 / 1757 ~6.508 ms, finishGL 73 / 16631 ~61.597 ms +XXX[271] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18611 ~68.677 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 9 / 1766 ~6.519 ms, finishGL 71 / 16703 ~61.635 ms +XXX[272] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18694 ~68.728 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 10 / 1777 ~6.534 ms, finishGL 71 / 16774 ~61.672 ms +XXX[273] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 18775 ~68.775 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 11 / 1788 ~6.551 ms, finishGL 69 / 16844 ~61.701 ms +XXX[274] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18858 ~68.826 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 13 / 1801 ~6.575 ms, finishGL 69 / 16913 ~61.729 ms +XXX[275] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18940 ~68.875 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 13 / 1814 ~6.599 ms, finishGL 68 / 16982 ~61.755 ms +XXX[276] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 19023 ~68.924 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 13 / 1828 ~6.626 ms, finishGL 68 / 17050 ~61.777 ms +XXX[277] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 19105 ~68.973 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 14 / 1843 ~6.655 ms, finishGL 67 / 17117 ~61.797 ms +XXX[278] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 19187 ~69.021 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 15 / 1858 ~6.686 ms, finishGL 66 / 17184 ~61.814 ms +XXX[279] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 19270 ~69.069 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 16 / 1875 ~6.721 ms, finishGL 65 / 17249 ~61.827 ms +XXX[280] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 19352 ~69.116 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 1875 ~6.699 ms, finishGL 81 / 17331 ~61.896 ms +XXX[281] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 19418 ~69.106 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 0 / 1876 ~6.679 ms, finishGL 64 / 17395 ~61.906 ms +XXX[282] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19484 ~69.094 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 1 / 1878 ~6.66 ms, finishGL 63 / 17459 ~61.913 ms +XXX[283] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19549 ~69.08 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 2 / 1880 ~6.645 ms, finishGL 62 / 17522 ~61.915 ms +XXX[284] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19615 ~69.067 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 3 / 1883 ~6.633 ms, finishGL 61 / 17583 ~61.914 ms +XXX[285] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19680 ~69.055 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 1889 ~6.629 ms, finishGL 59 / 17643 ~61.906 ms +XXX[286] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19746 ~69.042 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 5 / 1894 ~6.625 ms, finishGL 59 / 17702 ~61.897 ms +XXX[287] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19811 ~69.03 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 6 / 1901 ~6.625 ms, finishGL 58 / 17761 ~61.886 ms +XXX[288] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19877 ~69.018 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 7 / 1908 ~6.627 ms, finishGL 57 / 17819 ~61.872 ms +XXX[289] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 19942 ~69.003 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 8 / 1917 ~6.634 ms, finishGL 55 / 17874 ~61.85 ms +XXX[290] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 20007 ~68.992 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 10 / 1927 ~6.646 ms, finishGL 55 / 17929 ~61.827 ms +XXX[291] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 20073 ~68.979 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 10 / 1938 ~6.661 ms, finishGL 53 / 17983 ~61.8 ms +XXX[292] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 20138 ~68.968 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 12 / 1950 ~6.679 ms, finishGL 53 / 18037 ~61.771 ms +XXX[293] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 20204 ~68.958 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 12 / 1962 ~6.699 ms, finishGL 52 / 18090 ~61.741 ms +XXX[294] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 20270 ~68.946 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 13 / 1975 ~6.72 ms, finishGL 51 / 18142 ~61.707 ms +XXX[295] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20336 ~68.936 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 14 / 1990 ~6.746 ms, finishGL 51 / 18193 ~61.672 ms +XXX[296] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20402 ~68.926 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 14 / 2004 ~6.773 ms, finishGL 50 / 18244 ~61.636 ms +XXX[297] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 20468 ~68.916 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 14 / 2019 ~6.8 ms, finishGL 50 / 18294 ~61.599 ms +XXX[298] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20534 ~68.909 ms, flushGL 0 / 0 ~0.0030 ms, waitGL 15 / 2035 ~6.829 ms, finishGL 50 / 18345 ~61.562 ms +XXX[299] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 20602 ~68.903 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 15 / 2050 ~6.859 ms, finishGL 51 / 18396 ~61.527 ms +XXX[300] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20669 ~68.896 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 14 / 2065 ~6.885 ms, finishGL 51 / 18448 ~61.495 ms +XXX[301] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 20736 ~68.892 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 14 / 2079 ~6.909 ms, finishGL 53 / 18501 ~61.466 ms +XXX[302] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 20804 ~68.889 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 12 / 2092 ~6.929 ms, finishGL 54 / 18556 ~61.444 ms +XXX[303] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 20873 ~68.889 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 11 / 2104 ~6.944 ms, finishGL 56 / 18612 ~61.428 ms +XXX[304] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 20942 ~68.888 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 10 / 2114 ~6.957 ms, finishGL 57 / 18670 ~61.415 ms +XXX[305] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 21012 ~68.892 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2121 ~6.957 ms, finishGL 62 / 18733 ~61.419 ms +XXX[306] TO 17 ms, lFrame0 0 ms, lFrameX 71 / 21083 ~68.9 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 3 / 2125 ~6.944 ms, finishGL 67 / 18800 ~61.439 ms +XXX[307] TO 17 ms, lFrame0 0 ms, lFrameX 88 / 21171 ~68.963 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 15 / 2140 ~6.971 ms, finishGL 72 / 18873 ~61.475 ms +XXX[308] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 21258 ~69.02 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 10 / 2150 ~6.981 ms, finishGL 76 / 18949 ~61.523 ms +XXX[309] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 21343 ~69.073 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2157 ~6.98 ms, finishGL 78 / 19027 ~61.577 ms +XXX[310] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 21428 ~69.125 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 2161 ~6.972 ms, finishGL 80 / 19107 ~61.637 ms +XXX[311] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 21512 ~69.17 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2163 ~6.957 ms, finishGL 80 / 19187 ~61.697 ms +XXX[312] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 21594 ~69.214 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2166 ~6.943 ms, finishGL 79 / 19267 ~61.755 ms +XXX[313] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 21678 ~69.259 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2169 ~6.93 ms, finishGL 80 / 19347 ~61.814 ms +XXX[314] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 21762 ~69.305 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2171 ~6.914 ms, finishGL 80 / 19428 ~61.874 ms +XXX[315] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 21846 ~69.353 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2173 ~6.899 ms, finishGL 81 / 19510 ~61.937 ms +XXX[316] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 21930 ~69.4 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 2174 ~6.879 ms, finishGL 82 / 19593 ~62.003 ms +XXX[317] TO 17 ms, lFrame0 0 ms, lFrameX 100 / 22030 ~69.497 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 16 / 2190 ~6.91 ms, finishGL 83 / 19676 ~62.07 ms +XXX[318] TO 17 ms, lFrame0 0 ms, lFrameX 98 / 22129 ~69.589 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 16 / 2206 ~6.939 ms, finishGL 81 / 19758 ~62.133 ms +XXX[319] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 22228 ~69.682 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 2207 ~6.92 ms, finishGL 98 / 19856 ~62.245 ms +XXX[320] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 22311 ~69.722 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 2208 ~6.902 ms, finishGL 81 / 19937 ~62.304 ms +XXX[321] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 22394 ~69.764 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 1 / 2210 ~6.885 ms, finishGL 80 / 20018 ~62.362 ms +XXX[322] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 22476 ~69.803 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 1 / 2212 ~6.87 ms, finishGL 80 / 20098 ~62.417 ms +XXX[323] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22559 ~69.844 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2214 ~6.857 ms, finishGL 80 / 20178 ~62.472 ms +XXX[324] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 22642 ~69.885 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2217 ~6.844 ms, finishGL 79 / 20258 ~62.525 ms +XXX[325] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22726 ~69.926 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2220 ~6.831 ms, finishGL 79 / 20338 ~62.579 ms +XXX[326] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22809 ~69.968 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2223 ~6.819 ms, finishGL 80 / 20418 ~62.633 ms +XXX[327] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22892 ~70.008 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2225 ~6.805 ms, finishGL 80 / 20498 ~62.687 ms +XXX[328] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22976 ~70.049 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2227 ~6.791 ms, finishGL 80 / 20579 ~62.742 ms +XXX[329] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 23057 ~70.084 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2229 ~6.778 ms, finishGL 78 / 20658 ~62.791 ms +XXX[330] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 23142 ~70.129 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 3 / 2233 ~6.768 ms, finishGL 80 / 20739 ~62.846 ms +XXX[331] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 23226 ~70.171 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 1 / 2235 ~6.753 ms, finishGL 81 / 20821 ~62.903 ms +XXX[332] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 23308 ~70.207 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 2236 ~6.735 ms, finishGL 80 / 20901 ~62.957 ms +XXX[333] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23392 ~70.248 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2238 ~6.721 ms, finishGL 81 / 20983 ~63.012 ms +XXX[334] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23475 ~70.285 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 1 / 2239 ~6.705 ms, finishGL 80 / 21063 ~63.065 ms +XXX[335] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23558 ~70.323 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 1 / 2241 ~6.69 ms, finishGL 80 / 21144 ~63.117 ms +XXX[336] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23640 ~70.359 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2243 ~6.676 ms, finishGL 79 / 21224 ~63.167 ms +XXX[337] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 23721 ~70.391 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 3 / 2246 ~6.665 ms, finishGL 77 / 21301 ~63.21 ms +XXX[338] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23804 ~70.427 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 2251 ~6.66 ms, finishGL 77 / 21379 ~63.251 ms +XXX[339] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23887 ~70.465 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 2257 ~6.658 ms, finishGL 76 / 21456 ~63.292 ms +XXX[340] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23971 ~70.503 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 2262 ~6.654 ms, finishGL 77 / 21533 ~63.333 ms +XXX[341] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24053 ~70.538 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 2267 ~6.648 ms, finishGL 77 / 21610 ~63.374 ms +XXX[342] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24136 ~70.574 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 2272 ~6.646 ms, finishGL 76 / 21687 ~63.412 ms +XXX[343] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24219 ~70.611 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2279 ~6.644 ms, finishGL 76 / 21763 ~63.451 ms +XXX[344] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24302 ~70.646 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 2284 ~6.642 ms, finishGL 76 / 21840 ~63.488 ms +XXX[345] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24385 ~70.683 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2291 ~6.641 ms, finishGL 76 / 21916 ~63.526 ms +XXX[346] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24468 ~70.718 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2297 ~6.64 ms, finishGL 76 / 21992 ~63.562 ms +XXX[347] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24551 ~70.754 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2304 ~6.641 ms, finishGL 75 / 22068 ~63.598 ms +XXX[348] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24635 ~70.791 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2311 ~6.641 ms, finishGL 76 / 22145 ~63.635 ms +XXX[349] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24718 ~70.826 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2317 ~6.64 ms, finishGL 76 / 22221 ~63.67 ms +XXX[350] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24801 ~70.861 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2323 ~6.639 ms, finishGL 76 / 22297 ~63.706 ms +XXX[351] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24884 ~70.896 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2330 ~6.639 ms, finishGL 76 / 22373 ~63.743 ms +XXX[352] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24967 ~70.931 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2336 ~6.637 ms, finishGL 76 / 22450 ~63.779 ms +XXX[353] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25051 ~70.967 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2342 ~6.636 ms, finishGL 76 / 22527 ~63.815 ms +XXX[354] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25134 ~71.001 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 2348 ~6.634 ms, finishGL 76 / 22603 ~63.852 ms +XXX[355] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 25217 ~71.035 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 2354 ~6.633 ms, finishGL 76 / 22680 ~63.887 ms +XXX[356] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 25300 ~71.068 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2360 ~6.631 ms, finishGL 76 / 22756 ~63.922 ms +XXX[357] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25383 ~71.102 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2367 ~6.631 ms, finishGL 76 / 22832 ~63.957 ms +XXX[358] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25466 ~71.136 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2373 ~6.63 ms, finishGL 76 / 22909 ~63.992 ms +XXX[359] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 25550 ~71.171 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2380 ~6.629 ms, finishGL 77 / 22986 ~64.028 ms +XXX[360] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25633 ~71.205 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 2385 ~6.627 ms, finishGL 76 / 23063 ~64.064 ms +XXX[361] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 25716 ~71.236 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 2391 ~6.624 ms, finishGL 76 / 23139 ~64.099 ms +XXX[362] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 25800 ~71.271 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2397 ~6.622 ms, finishGL 77 / 23217 ~64.136 ms +XXX[363] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25884 ~71.306 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 2402 ~6.618 ms, finishGL 78 / 23295 ~64.175 ms +XXX[364] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25967 ~71.339 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 2406 ~6.612 ms, finishGL 78 / 23374 ~64.214 ms +XXX[365] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26051 ~71.372 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 2411 ~6.606 ms, finishGL 78 / 23452 ~64.253 ms +XXX[366] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26133 ~71.404 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 2415 ~6.599 ms, finishGL 77 / 23530 ~64.291 ms +XXX[367] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26217 ~71.436 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 2420 ~6.595 ms, finishGL 78 / 23608 ~64.329 ms +XXX[368] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26300 ~71.468 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 2424 ~6.588 ms, finishGL 78 / 23687 ~64.367 ms +XXX[369] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26383 ~71.499 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 2429 ~6.582 ms, finishGL 77 / 23765 ~64.404 ms +XXX[370] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26467 ~71.532 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 2433 ~6.577 ms, finishGL 78 / 23843 ~64.442 ms +XXX[371] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26549 ~71.561 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 2438 ~6.571 ms, finishGL 77 / 23921 ~64.478 ms +XXX[372] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26631 ~71.59 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 2442 ~6.566 ms, finishGL 76 / 23998 ~64.511 ms +XXX[373] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26714 ~71.62 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 2448 ~6.563 ms, finishGL 76 / 24074 ~64.544 ms +XXX[374] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26797 ~71.651 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2454 ~6.562 ms, finishGL 76 / 24151 ~64.576 ms +XXX[375] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 26896 ~71.724 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 2460 ~6.561 ms, finishGL 92 / 24244 ~64.651 ms +XXX[376] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26979 ~71.755 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 2467 ~6.562 ms, finishGL 75 / 24320 ~64.681 ms +XXX[377] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27062 ~71.783 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2474 ~6.562 ms, finishGL 75 / 24395 ~64.709 ms +XXX[378] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27145 ~71.813 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 2481 ~6.564 ms, finishGL 75 / 24470 ~64.737 ms +XXX[379] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27227 ~71.841 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 2488 ~6.566 ms, finishGL 74 / 24545 ~64.763 ms +FrameCount: 480 - FrameRate: 12.0 +XXX[380] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27310 ~71.869 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 2496 ~6.57 ms, finishGL 74 / 24619 ~64.787 ms +XXX[381] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27393 ~71.898 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 2505 ~6.575 ms, finishGL 73 / 24692 ~64.81 ms +XXX[382] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27475 ~71.926 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 9 / 2514 ~6.582 ms, finishGL 73 / 24765 ~64.832 ms +XXX[383] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27558 ~71.955 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 9 / 2524 ~6.59 ms, finishGL 72 / 24838 ~64.853 ms +XXX[384] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27642 ~71.985 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 9 / 2533 ~6.598 ms, finishGL 73 / 24911 ~64.874 ms +XXX[385] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 27727 ~72.019 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 9 / 2543 ~6.606 ms, finishGL 75 / 24986 ~64.901 ms +XXX[386] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27811 ~72.049 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 2551 ~6.609 ms, finishGL 75 / 25062 ~64.929 ms +XXX[387] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27894 ~72.078 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2558 ~6.61 ms, finishGL 75 / 25138 ~64.957 ms +XXX[388] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27978 ~72.108 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2564 ~6.609 ms, finishGL 76 / 25215 ~64.987 ms +XXX[389] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 28063 ~72.142 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2570 ~6.608 ms, finishGL 78 / 25293 ~65.022 ms +XXX[390] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 28147 ~72.172 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 2574 ~6.602 ms, finishGL 78 / 25372 ~65.056 ms +XXX[391] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28231 ~72.202 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 3 / 2578 ~6.594 ms, finishGL 79 / 25451 ~65.094 ms +XXX[392] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28314 ~72.23 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2581 ~6.584 ms, finishGL 80 / 25531 ~65.132 ms +XXX[393] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28397 ~72.258 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2583 ~6.574 ms, finishGL 79 / 25611 ~65.17 ms +XXX[394] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28480 ~72.285 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2586 ~6.565 ms, finishGL 79 / 25691 ~65.206 ms +XXX[395] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28563 ~72.313 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2589 ~6.556 ms, finishGL 79 / 25771 ~65.243 ms +XXX[396] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28646 ~72.339 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 2592 ~6.547 ms, finishGL 79 / 25850 ~65.279 ms +XXX[397] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28729 ~72.366 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 3 / 2596 ~6.539 ms, finishGL 79 / 25929 ~65.314 ms +XXX[398] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28812 ~72.393 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 3 / 2599 ~6.531 ms, finishGL 79 / 26008 ~65.348 ms +XXX[399] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28895 ~72.418 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 3 / 2603 ~6.524 ms, finishGL 78 / 26087 ~65.381 ms +XXX[400] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28977 ~72.444 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 2607 ~6.518 ms, finishGL 78 / 26165 ~65.413 ms +XXX[401] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29059 ~72.468 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 2612 ~6.514 ms, finishGL 76 / 26242 ~65.442 ms +XXX[402] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 29141 ~72.491 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 2617 ~6.512 ms, finishGL 75 / 26317 ~65.467 ms +XXX[403] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29224 ~72.517 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 2625 ~6.513 ms, finishGL 75 / 26393 ~65.491 ms +XXX[404] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29307 ~72.542 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 2632 ~6.516 ms, finishGL 74 / 26467 ~65.514 ms +XXX[405] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29390 ~72.568 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 2640 ~6.519 ms, finishGL 74 / 26542 ~65.537 ms +XXX[406] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29473 ~72.594 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 2648 ~6.522 ms, finishGL 74 / 26617 ~65.559 ms +XXX[407] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29555 ~72.618 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 2656 ~6.527 ms, finishGL 73 / 26690 ~65.578 ms +XXX[408] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29638 ~72.644 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 9 / 2665 ~6.533 ms, finishGL 73 / 26764 ~65.598 ms +XXX[409] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29721 ~72.669 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 2674 ~6.539 ms, finishGL 73 / 26837 ~65.618 ms +XXX[410] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29804 ~72.693 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 9 / 2683 ~6.546 ms, finishGL 72 / 26910 ~65.635 ms +XXX[411] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29887 ~72.719 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 10 / 2694 ~6.554 ms, finishGL 72 / 26983 ~65.653 ms +XXX[412] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29970 ~72.744 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 9 / 2703 ~6.561 ms, finishGL 73 / 27056 ~65.671 ms +XXX[413] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 30052 ~72.767 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 9 / 2713 ~6.569 ms, finishGL 72 / 27128 ~65.686 ms +XXX[414] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30136 ~72.792 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 10 / 2723 ~6.578 ms, finishGL 72 / 27200 ~65.702 ms +XXX[415] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30219 ~72.817 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 10 / 2734 ~6.588 ms, finishGL 71 / 27272 ~65.717 ms +XXX[416] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 30301 ~72.84 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 11 / 2745 ~6.599 ms, finishGL 71 / 27343 ~65.73 ms +XXX[417] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30384 ~72.865 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 11 / 2756 ~6.61 ms, finishGL 71 / 27415 ~65.743 ms +XXX[418] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30468 ~72.89 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 11 / 2767 ~6.621 ms, finishGL 71 / 27486 ~65.757 ms +XXX[419] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30551 ~72.914 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 11 / 2779 ~6.633 ms, finishGL 71 / 27557 ~65.77 ms +XXX[420] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 30635 ~72.941 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 11 / 2790 ~6.644 ms, finishGL 72 / 27630 ~65.786 ms +XXX[421] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 30720 ~72.969 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 10 / 2801 ~6.653 ms, finishGL 73 / 27703 ~65.805 ms +XXX[422] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30803 ~72.993 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 2809 ~6.658 ms, finishGL 73 / 27777 ~65.824 ms +XXX[423] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 30883 ~73.011 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 2818 ~6.663 ms, finishGL 71 / 27848 ~65.836 ms +XXX[424] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 30964 ~73.028 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 11 / 2830 ~6.675 ms, finishGL 68 / 27917 ~65.842 ms +XXX[425] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 31044 ~73.046 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 14 / 2844 ~6.693 ms, finishGL 65 / 27982 ~65.842 ms +XXX[426] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 31124 ~73.063 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 2844 ~6.678 ms, finishGL 79 / 28062 ~65.874 ms +XXX[427] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31189 ~73.044 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 3 / 2848 ~6.67 ms, finishGL 61 / 28123 ~65.863 ms +XXX[428] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31256 ~73.028 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 2852 ~6.665 ms, finishGL 61 / 28185 ~65.852 ms +XXX[429] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31321 ~73.01 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 2857 ~6.66 ms, finishGL 59 / 28244 ~65.839 ms +XXX[430] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31387 ~72.994 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2863 ~6.659 ms, finishGL 59 / 28304 ~65.824 ms +XXX[431] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31454 ~72.979 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2869 ~6.658 ms, finishGL 59 / 28364 ~65.809 ms +XXX[432] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31519 ~72.962 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2876 ~6.658 ms, finishGL 58 / 28422 ~65.793 ms +XXX[433] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31586 ~72.947 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 2883 ~6.659 ms, finishGL 58 / 28481 ~65.777 ms +XXX[434] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31651 ~72.93 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 2890 ~6.661 ms, finishGL 57 / 28539 ~65.759 ms +XXX[435] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31718 ~72.915 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 2899 ~6.664 ms, finishGL 57 / 28597 ~65.74 ms +XXX[436] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31784 ~72.899 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 2907 ~6.668 ms, finishGL 57 / 28654 ~65.72 ms +XXX[437] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31850 ~72.884 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 2916 ~6.673 ms, finishGL 57 / 28711 ~65.701 ms +XXX[438] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31917 ~72.871 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 2925 ~6.678 ms, finishGL 57 / 28769 ~65.682 ms +XXX[439] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31984 ~72.857 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 2934 ~6.683 ms, finishGL 57 / 28826 ~65.664 ms +XXX[440] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32050 ~72.843 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 2942 ~6.686 ms, finishGL 57 / 28884 ~65.646 ms +XXX[441] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32117 ~72.829 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 2950 ~6.689 ms, finishGL 58 / 28942 ~65.63 ms +XXX[442] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 32185 ~72.817 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 2957 ~6.692 ms, finishGL 59 / 29002 ~65.615 ms +XXX[443] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32251 ~72.803 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2964 ~6.692 ms, finishGL 59 / 29061 ~65.601 ms +XXX[444] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32318 ~72.788 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2971 ~6.692 ms, finishGL 59 / 29120 ~65.586 ms +XXX[445] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 32385 ~72.776 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2978 ~6.692 ms, finishGL 60 / 29180 ~65.574 ms +XXX[446] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32451 ~72.761 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2984 ~6.691 ms, finishGL 59 / 29240 ~65.561 ms +XXX[447] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32518 ~72.747 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2990 ~6.69 ms, finishGL 59 / 29299 ~65.547 ms +XXX[448] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32585 ~72.734 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 2997 ~6.689 ms, finishGL 60 / 29359 ~65.535 ms +XXX[449] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32651 ~72.72 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3002 ~6.688 ms, finishGL 59 / 29419 ~65.523 ms +XXX[450] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 32718 ~72.707 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 3009 ~6.686 ms, finishGL 60 / 29480 ~65.511 ms +XXX[451] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 32784 ~72.692 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3014 ~6.684 ms, finishGL 59 / 29540 ~65.499 ms +XXX[452] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 32850 ~72.677 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 3021 ~6.683 ms, finishGL 59 / 29599 ~65.484 ms +XXX[453] TO 17 ms, lFrame0 1 ms, lFrameX 65 / 32915 ~72.662 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 3027 ~6.682 ms, finishGL 58 / 29657 ~65.469 ms +XXX[454] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 32981 ~72.645 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 3034 ~6.684 ms, finishGL 57 / 29714 ~65.451 ms +XXX[455] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33047 ~72.63 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 3043 ~6.689 ms, finishGL 56 / 29771 ~65.431 ms +XXX[456] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33112 ~72.614 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 9 / 3053 ~6.695 ms, finishGL 55 / 29826 ~65.409 ms +XXX[457] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 33178 ~72.6 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 10 / 3063 ~6.704 ms, finishGL 54 / 29881 ~65.386 ms +XXX[458] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33243 ~72.584 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 11 / 3074 ~6.713 ms, finishGL 53 / 29935 ~65.361 ms +XXX[459] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33309 ~72.569 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 12 / 3087 ~6.725 ms, finishGL 53 / 29988 ~65.334 ms +XXX[460] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33375 ~72.554 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 13 / 3100 ~6.739 ms, finishGL 52 / 30040 ~65.306 ms +XXX[461] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33440 ~72.539 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 13 / 3113 ~6.754 ms, finishGL 51 / 30092 ~65.275 ms +XXX[462] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33506 ~72.524 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 14 / 3128 ~6.771 ms, finishGL 50 / 30142 ~65.244 ms +XXX[463] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33571 ~72.509 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 15 / 3143 ~6.79 ms, finishGL 49 / 30192 ~65.21 ms +XXX[464] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33637 ~72.494 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 16 / 3160 ~6.81 ms, finishGL 48 / 30241 ~65.174 ms +XXX[465] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33702 ~72.479 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 0 / 3161 ~6.798 ms, finishGL 64 / 30305 ~65.172 ms +XXX[466] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 33751 ~72.428 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 1 / 3162 ~6.786 ms, finishGL 46 / 30352 ~65.133 ms +XXX[467] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 33801 ~72.379 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 3165 ~6.778 ms, finishGL 46 / 30398 ~65.092 ms +XXX[468] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 33850 ~72.329 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 3168 ~6.77 ms, finishGL 45 / 30443 ~65.05 ms +XXX[469] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 33899 ~72.28 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 3 / 3172 ~6.763 ms, finishGL 45 / 30488 ~65.008 ms +XXX[470] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 33948 ~72.231 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 3176 ~6.758 ms, finishGL 44 / 30533 ~64.963 ms +XXX[471] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 33998 ~72.182 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3181 ~6.755 ms, finishGL 43 / 30576 ~64.919 ms +XXX[472] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34047 ~72.134 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3187 ~6.752 ms, finishGL 43 / 30620 ~64.874 ms +XXX[473] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34096 ~72.086 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3192 ~6.75 ms, finishGL 43 / 30663 ~64.827 ms +XXX[474] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34145 ~72.036 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 3199 ~6.749 ms, finishGL 41 / 30705 ~64.779 ms +XXX[475] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34194 ~71.988 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 3206 ~6.75 ms, finishGL 41 / 30746 ~64.729 ms +XXX[476] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34243 ~71.94 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 3214 ~6.753 ms, finishGL 40 / 30787 ~64.678 ms +XXX[477] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34292 ~71.892 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 3223 ~6.758 ms, finishGL 39 / 30826 ~64.626 ms +XXX[478] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34341 ~71.845 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 9 / 3233 ~6.763 ms, finishGL 39 / 30866 ~64.573 ms +XXX[479] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34390 ~71.797 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 10 / 3243 ~6.77 ms, finishGL 38 / 30904 ~64.518 ms +XXX[480] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34439 ~71.749 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 11 / 3254 ~6.779 ms, finishGL 37 / 30941 ~64.461 ms +XXX[481] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34488 ~71.702 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 11 / 3266 ~6.79 ms, finishGL 36 / 30978 ~64.404 ms +XXX[482] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34537 ~71.655 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 12 / 3278 ~6.802 ms, finishGL 36 / 31014 ~64.345 ms +XXX[483] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34586 ~71.608 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 13 / 3292 ~6.815 ms, finishGL 35 / 31049 ~64.285 ms +XXX[484] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34635 ~71.561 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 14 / 3306 ~6.831 ms, finishGL 34 / 31084 ~64.223 ms +XXX[485] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34685 ~71.516 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 15 / 3321 ~6.848 ms, finishGL 33 / 31117 ~64.16 ms +XXX[486] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34735 ~71.471 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 16 / 3337 ~6.867 ms, finishGL 33 / 31150 ~64.096 ms +XXX[487] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34784 ~71.426 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 15 / 3352 ~6.884 ms, finishGL 33 / 31184 ~64.033 ms +XXX[488] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34834 ~71.381 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 15 / 3368 ~6.902 ms, finishGL 33 / 31218 ~63.971 ms +XXX[489] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 34884 ~71.338 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 17 / 3385 ~6.924 ms, finishGL 32 / 31250 ~63.906 ms +XXX[490] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 34934 ~71.295 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 15 / 3401 ~6.941 ms, finishGL 34 / 31284 ~63.846 ms +XXX[491] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34984 ~71.251 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 15 / 3416 ~6.958 ms, finishGL 34 / 31318 ~63.785 ms +XXX[492] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35034 ~71.207 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 15 / 3431 ~6.974 ms, finishGL 34 / 31352 ~63.725 ms +XXX[493] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35083 ~71.163 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 15 / 3446 ~6.991 ms, finishGL 33 / 31386 ~63.664 ms +XXX[494] TO 17 ms, lFrame0 0 ms, lFrameX 51 / 35134 ~71.123 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 15 / 3462 ~7.008 ms, finishGL 35 / 31422 ~63.607 ms +XXX[495] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35185 ~71.081 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 14 / 3476 ~7.023 ms, finishGL 35 / 31457 ~63.55 ms +XXX[496] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35235 ~71.039 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 13 / 3489 ~7.036 ms, finishGL 36 / 31494 ~63.496 ms +XXX[497] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35285 ~70.997 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 13 / 3503 ~7.048 ms, finishGL 36 / 31530 ~63.442 ms +XXX[498] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35336 ~70.956 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 12 / 3515 ~7.059 ms, finishGL 37 / 31568 ~63.389 ms +XXX[499] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35386 ~70.914 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 12 / 3527 ~7.069 ms, finishGL 37 / 31605 ~63.338 ms +FrameCount: 600 - FrameRate: 19.0 +XXX[500] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35436 ~70.873 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 11 / 3538 ~7.077 ms, finishGL 38 / 31644 ~63.288 ms +XXX[501] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35486 ~70.831 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 10 / 3549 ~7.085 ms, finishGL 38 / 31683 ~63.239 ms +XXX[502] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35537 ~70.791 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 10 / 3560 ~7.092 ms, finishGL 39 / 31722 ~63.191 ms +XXX[503] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35587 ~70.749 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 10 / 3570 ~7.098 ms, finishGL 39 / 31761 ~63.144 ms +XXX[504] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35637 ~70.709 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 9 / 3580 ~7.104 ms, finishGL 39 / 31801 ~63.098 ms +XXX[505] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35687 ~70.667 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 9 / 3589 ~7.108 ms, finishGL 39 / 31841 ~63.052 ms +XXX[506] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35737 ~70.627 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 9 / 3599 ~7.113 ms, finishGL 40 / 31881 ~63.007 ms +XXX[507] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35788 ~70.588 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 3608 ~7.117 ms, finishGL 41 / 31923 ~62.964 ms +XXX[508] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35837 ~70.547 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 3616 ~7.119 ms, finishGL 40 / 31964 ~62.921 ms +XXX[509] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35888 ~70.507 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 3625 ~7.122 ms, finishGL 41 / 32005 ~62.878 ms +XXX[510] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35938 ~70.467 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 3633 ~7.123 ms, finishGL 41 / 32047 ~62.837 ms +XXX[511] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35989 ~70.429 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 3640 ~7.124 ms, finishGL 43 / 32090 ~62.799 ms +XXX[512] TO 17 ms, lFrame0 0 ms, lFrameX 52 / 36042 ~70.394 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 3646 ~7.121 ms, finishGL 45 / 32136 ~62.766 ms +XXX[513] TO 17 ms, lFrame0 0 ms, lFrameX 51 / 36093 ~70.358 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 3 / 3649 ~7.114 ms, finishGL 47 / 32184 ~62.737 ms +XXX[514] TO 17 ms, lFrame0 0 ms, lFrameX 53 / 36147 ~70.325 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 1 / 3651 ~7.103 ms, finishGL 51 / 32236 ~62.716 ms +XXX[515] TO 17 ms, lFrame0 0 ms, lFrameX 69 / 36217 ~70.324 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 14 / 3665 ~7.117 ms, finishGL 54 / 32290 ~62.7 ms +XXX[516] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 36287 ~70.325 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 11 / 3676 ~7.125 ms, finishGL 59 / 32349 ~62.693 ms +XXX[517] TO 17 ms, lFrame0 0 ms, lFrameX 76 / 36363 ~70.336 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 3683 ~7.124 ms, finishGL 68 / 32418 ~62.705 ms +XXX[518] TO 17 ms, lFrame0 0 ms, lFrameX 91 / 36455 ~70.376 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 13 / 3697 ~7.138 ms, finishGL 77 / 32495 ~62.732 ms +XXX[519] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36539 ~70.402 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3703 ~7.135 ms, finishGL 77 / 32573 ~62.761 ms +XXX[520] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36622 ~70.427 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 3708 ~7.131 ms, finishGL 77 / 32650 ~62.79 ms +XXX[521] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 36705 ~70.451 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3713 ~7.127 ms, finishGL 77 / 32728 ~62.818 ms +XXX[522] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36788 ~70.476 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3718 ~7.123 ms, finishGL 77 / 32806 ~62.847 ms +XXX[523] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 36871 ~70.5 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 3723 ~7.118 ms, finishGL 77 / 32883 ~62.875 ms +XXX[524] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 36954 ~70.523 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3728 ~7.115 ms, finishGL 76 / 32960 ~62.902 ms +XXX[525] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37037 ~70.547 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3733 ~7.112 ms, finishGL 77 / 33037 ~62.929 ms +XXX[526] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 37120 ~70.57 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3739 ~7.109 ms, finishGL 76 / 33114 ~62.955 ms +XXX[527] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37204 ~70.595 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3745 ~7.107 ms, finishGL 77 / 33191 ~62.982 ms +XXX[528] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37287 ~70.619 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3750 ~7.103 ms, finishGL 77 / 33269 ~63.01 ms +XXX[529] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37370 ~70.643 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3755 ~7.1 ms, finishGL 77 / 33346 ~63.037 ms +XXX[530] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37454 ~70.668 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3761 ~7.096 ms, finishGL 77 / 33424 ~63.065 ms +XXX[531] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37537 ~70.692 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 3765 ~7.091 ms, finishGL 78 / 33502 ~63.094 ms +XXX[532] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 37620 ~70.714 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3771 ~7.088 ms, finishGL 76 / 33579 ~63.119 ms +XXX[533] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37703 ~70.738 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 3776 ~7.084 ms, finishGL 77 / 33657 ~63.146 ms +XXX[534] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 37786 ~70.761 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 3 / 3779 ~7.078 ms, finishGL 77 / 33735 ~63.174 ms +XXX[535] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 37868 ~70.782 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 3784 ~7.074 ms, finishGL 76 / 33811 ~63.199 ms +XXX[536] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 37951 ~70.805 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3790 ~7.072 ms, finishGL 76 / 33888 ~63.224 ms +XXX[537] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38035 ~70.828 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 3796 ~7.07 ms, finishGL 76 / 33964 ~63.249 ms +XXX[538] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 38117 ~70.85 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 3802 ~7.068 ms, finishGL 76 / 34041 ~63.273 ms +XXX[539] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 38200 ~70.872 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 3809 ~7.068 ms, finishGL 75 / 34116 ~63.295 ms +XXX[540] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38284 ~70.896 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 3817 ~7.068 ms, finishGL 76 / 34192 ~63.319 ms +XXX[541] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38367 ~70.919 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 3823 ~7.067 ms, finishGL 76 / 34268 ~63.343 ms +XXX[542] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38450 ~70.942 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 3830 ~7.066 ms, finishGL 76 / 34345 ~63.367 ms +XXX[543] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38534 ~70.965 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 3836 ~7.064 ms, finishGL 76 / 34422 ~63.392 ms +XXX[544] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38617 ~70.988 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3842 ~7.062 ms, finishGL 76 / 34499 ~63.417 ms +XXX[545] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38700 ~71.01 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3847 ~7.06 ms, finishGL 77 / 34576 ~63.442 ms +XXX[546] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 38785 ~71.035 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3853 ~7.057 ms, finishGL 77 / 34654 ~63.469 ms +XXX[547] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38868 ~71.058 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3858 ~7.054 ms, finishGL 77 / 34731 ~63.495 ms +XXX[548] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38952 ~71.081 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 3863 ~7.049 ms, finishGL 79 / 34811 ~63.523 ms +XXX[549] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 39036 ~71.104 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 3 / 3866 ~7.042 ms, finishGL 79 / 34890 ~63.553 ms +XXX[550] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 39120 ~71.128 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 3 / 3869 ~7.035 ms, finishGL 80 / 34971 ~63.584 ms +XXX[551] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39203 ~71.149 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 3871 ~7.026 ms, finishGL 79 / 35051 ~63.614 ms +XXX[552] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39285 ~71.168 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 3874 ~7.018 ms, finishGL 79 / 35130 ~63.641 ms +XXX[553] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39367 ~71.189 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 3 / 3877 ~7.012 ms, finishGL 78 / 35208 ~63.668 ms +XXX[554] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39450 ~71.21 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 3881 ~7.007 ms, finishGL 77 / 35286 ~63.694 ms +XXX[555] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39532 ~71.23 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 3886 ~7.002 ms, finishGL 77 / 35363 ~63.718 ms +XXX[556] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39615 ~71.25 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3892 ~7.0 ms, finishGL 76 / 35440 ~63.741 ms +XXX[557] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 39695 ~71.266 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 3898 ~6.999 ms, finishGL 73 / 35513 ~63.758 ms +XXX[558] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39778 ~71.287 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 9 / 3907 ~7.003 ms, finishGL 73 / 35586 ~63.775 ms +XXX[559] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 39860 ~71.306 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 9 / 3917 ~7.008 ms, finishGL 71 / 35658 ~63.789 ms +XXX[560] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 39941 ~71.324 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 10 / 3928 ~7.015 ms, finishGL 70 / 35728 ~63.801 ms +XXX[561] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 40023 ~71.342 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 12 / 3941 ~7.025 ms, finishGL 68 / 35796 ~63.808 ms +XXX[562] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 40104 ~71.36 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 14 / 3955 ~7.038 ms, finishGL 66 / 35863 ~63.813 ms +XXX[563] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 40186 ~71.379 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 16 / 3972 ~7.055 ms, finishGL 65 / 35928 ~63.815 ms +XXX[564] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40251 ~71.368 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 1 / 3973 ~7.045 ms, finishGL 63 / 35991 ~63.815 ms +XXX[565] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40316 ~71.356 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 3976 ~7.037 ms, finishGL 61 / 36053 ~63.811 ms +XXX[566] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40382 ~71.346 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 3980 ~7.032 ms, finishGL 60 / 36113 ~63.805 ms +XXX[567] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40447 ~71.335 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 3985 ~7.028 ms, finishGL 60 / 36174 ~63.798 ms +XXX[568] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 40513 ~71.326 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 3991 ~7.026 ms, finishGL 59 / 36233 ~63.791 ms +XXX[569] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40579 ~71.316 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 3997 ~7.025 ms, finishGL 58 / 36292 ~63.782 ms +XXX[570] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 40646 ~71.309 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 4005 ~7.026 ms, finishGL 59 / 36351 ~63.774 ms +XXX[571] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40712 ~71.299 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 4011 ~7.025 ms, finishGL 58 / 36410 ~63.765 ms +XXX[572] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 40778 ~71.291 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 4018 ~7.025 ms, finishGL 58 / 36469 ~63.757 ms +XXX[573] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 40845 ~71.283 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 4025 ~7.025 ms, finishGL 59 / 36528 ~63.749 ms +XXX[574] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 40912 ~71.275 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 4032 ~7.026 ms, finishGL 59 / 36587 ~63.741 ms +XXX[575] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40977 ~71.265 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 4039 ~7.026 ms, finishGL 58 / 36645 ~63.731 ms +XXX[576] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 41046 ~71.261 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 4047 ~7.027 ms, finishGL 60 / 36706 ~63.725 ms +XXX[577] TO 17 ms, lFrame0 0 ms, lFrameX 69 / 41116 ~71.259 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 4053 ~7.024 ms, finishGL 63 / 36770 ~63.726 ms +XXX[578] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 41187 ~71.258 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 4055 ~7.016 ms, finishGL 68 / 36838 ~63.734 ms +XXX[579] TO 17 ms, lFrame0 0 ms, lFrameX 88 / 41276 ~71.288 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 14 / 4069 ~7.028 ms, finishGL 73 / 36912 ~63.751 ms +XXX[580] TO 17 ms, lFrame0 0 ms, lFrameX 87 / 41363 ~71.316 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 9 / 4078 ~7.032 ms, finishGL 77 / 36989 ~63.775 ms +XXX[581] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 41449 ~71.34 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 4083 ~7.028 ms, finishGL 80 / 37070 ~63.804 ms +XXX[582] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 41533 ~71.362 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 2 / 4086 ~7.02 ms, finishGL 81 / 37151 ~63.834 ms +XXX[583] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 41613 ~71.378 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 1 / 4087 ~7.011 ms, finishGL 78 / 37230 ~63.859 ms +XXX[584] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 41695 ~71.396 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 3 / 4091 ~7.005 ms, finishGL 77 / 37307 ~63.883 ms +XXX[585] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 41778 ~71.415 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 4096 ~7.002 ms, finishGL 76 / 37384 ~63.905 ms +XXX[586] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 41860 ~71.434 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 4102 ~7.0 ms, finishGL 76 / 37460 ~63.925 ms +XXX[587] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 41943 ~71.453 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 4109 ~7.0 ms, finishGL 75 / 37536 ~63.946 ms +XXX[588] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 42026 ~71.473 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 4116 ~7.0 ms, finishGL 75 / 37611 ~63.965 ms +XXX[589] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42109 ~71.492 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 4123 ~7.0 ms, finishGL 75 / 37686 ~63.984 ms +XXX[590] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 42192 ~71.512 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 4131 ~7.002 ms, finishGL 74 / 37761 ~64.002 ms +XXX[591] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42275 ~71.532 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 8 / 4140 ~7.005 ms, finishGL 74 / 37835 ~64.019 ms +XXX[592] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42358 ~71.551 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 4147 ~7.006 ms, finishGL 74 / 37910 ~64.037 ms +XXX[593] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 42442 ~71.572 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 7 / 4155 ~7.007 ms, finishGL 75 / 37986 ~64.057 ms +XXX[594] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42526 ~71.592 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 4162 ~7.007 ms, finishGL 76 / 38062 ~64.078 ms +XXX[595] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 42610 ~71.614 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 6 / 4168 ~7.006 ms, finishGL 77 / 38139 ~64.1 ms +XXX[596] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42694 ~71.634 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 4 / 4173 ~7.003 ms, finishGL 77 / 38217 ~64.123 ms +XXX[597] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42778 ~71.655 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 4178 ~6.999 ms, finishGL 78 / 38296 ~64.147 ms +XXX[598] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 42860 ~71.672 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 4184 ~6.996 ms, finishGL 76 / 38372 ~64.168 ms +XXX[599] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 42942 ~71.689 ms, flushGL 0 / 1 ~0.0030 ms, waitGL 5 / 4189 ~6.993 ms, finishGL 76 / 38448 ~64.188 ms diff --git a/src/test/com/jogamp/opengl/test/bugs/Bug735.OSX.CALayer.Perf.logs/aaaa-m2-sync0-finish-wait-exclctx.log b/src/test/com/jogamp/opengl/test/bugs/Bug735.OSX.CALayer.Perf.logs/aaaa-m2-sync0-finish-wait-exclctx.log new file mode 100644 index 000000000..cf5bd39f5 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/bugs/Bug735.OSX.CALayer.Perf.logs/aaaa-m2-sync0-finish-wait-exclctx.log @@ -0,0 +1,751 @@ +NSZombieEnabled +NSTraceEvents YES +OBJC_PRINT_EXCEPTIONS +/usr/bin/java +java version "1.6.0_37" +Java(TM) SE Runtime Environment (build 1.6.0_37-b06-434-11M3909) +Java HotSpot(TM) 64-Bit Server VM (build 20.12-b01-434, mixed mode) +LD_LIBRARY_PATH :../../gluegen/make/../build-macosx/obj:../build-macosx/lib +LIBXCB_ALLOW_SLOPPY_LOCK: +LIBGL_DRIVERS_PATH: +LIBGL_DEBUG: +LIBGL_ALWAYS_INDIRECT: +LIBGL_ALWAYS_SOFTWARE: +SWT_CLASSPATH: ../build-macosx/../make/lib/swt/cocoa-macosx-x86_64/swt-debug.jar +/usr/bin/java -d64 -time 100000 -vsync 0 -exclctx +CLASSPATH .:../../gluegen/make/../build-macosx/gluegen-rt.jar:../build-macosx/jar/jogl-all.jar:../build-macosx/jar/jogl-test.jar:../build-macosx/../make/lib/swt/cocoa-macosx-x86_64/swt-debug.jar:../../gluegen/make/../make/lib/junit.jar:/opt-share/apache-ant/lib/ant.jar:/opt-share/apache-ant/lib/ant-junit.jar +CLASSPATH .:../../gluegen/make/../build-macosx/gluegen-rt.jar:../build-macosx/jar/jogl-all.jar:../build-macosx/jar/jogl-test.jar:../build-macosx/../make/lib/swt/cocoa-macosx-x86_64/swt-debug.jar:../../gluegen/make/../make/lib/junit.jar:/opt-share/apache-ant/lib/ant.jar:/opt-share/apache-ant/lib/ant-junit.jar + +Test Start: com.jogamp.opengl.test.bugs.Bug735Inv3AppletAWT -time 100000 -vsync 0 -exclctx + +/usr/bin/java -d64 -Djava.awt.headless=false -Djogl.debug.calayer.SwapM2 com.jogamp.opengl.test.bugs.Bug735Inv3AppletAWT -time 100000 -vsync 0 -exclctx +swapInterval 0 +exclusiveContext true +SWAP_M1 false +SWAP_M2 true +NewtCanvasAWT.attachNewtChild.2: size 500x268 +Thread[main-Display-.macosx_nil-1-EDT-1,5,main] LandscapeES2.init ... +LandscapeES2 init on Thread[main-Display-.macosx_nil-1-EDT-1,5,main] +Chosen GLCapabilities: GLCaps[rgba 8/8/8/0, opaque, accum-rgba 0/0/0/0, dp/st/ms 24/0/0, dbl, mono , hw, GLProfile[GL2/GL2.hw], offscr[fbo]] +INIT GL IS: jogamp.opengl.gl4.GL4bcImpl +GL_VENDOR: NVIDIA Corporation +GL_RENDERER: NVIDIA GeForce 320M OpenGL Engine +GL_VERSION: 2.1 NVIDIA-7.32.12 +GL GLSL: true, has-compiler-func: true, version 1.20, 1.20.0 +GL FBO: basic true, full true +GL Profile: GLProfile[GL2/GL2.hw] +GL Renderer Quirks:[NoOffscreenBitmap] +GL:jogamp.opengl.gl4.GL4bcImpl@57ac3379, 2.1 (hardware) - 2.1 NVIDIA-7.32.12 +Thread[main-Display-.macosx_nil-1-EDT-1,5,main] LandscapeES2.init FIN +Thread[main-Display-.macosx_nil-1-EDT-1,5,main] LandscapeES2.reshape 0/0 500x268, swapInterval 0, drawable 0x7f98910ac7d0 +Thread[AWT-EventQueue-0,6,main] LandscapeES2.reshape 0/0 500x268, swapInterval 0, drawable 0x7f98910ac7d0 +XXX[1] TO 17 ms, lFrame0 110 ms, lFrameX 848 / 848 ~848.189 ms, finishGL 736 / 736 ~736.724 ms, waitGL 1 / 1 ~1.131 ms +XXX[2] TO 17 ms, lFrame0 122 ms, lFrameX 211 / 1059 ~529.747 ms, finishGL 88 / 825 ~412.707 ms, waitGL 0 / 1 ~0.572 ms +XXX[3] TO 17 ms, lFrame0 2 ms, lFrameX 100 / 1159 ~386.566 ms, finishGL 97 / 923 ~307.754 ms, waitGL 0 / 1 ~0.395 ms +XXX[4] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 1259 ~314.909 ms, finishGL 99 / 1022 ~255.589 ms, waitGL 0 / 1 ~0.299 ms +XXX[5] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 1359 ~271.82 ms, finishGL 98 / 1121 ~224.2 ms, waitGL 0 / 1 ~0.242 ms +XXX[6] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 1440 ~240.077 ms, finishGL 80 / 1201 ~200.259 ms, waitGL 0 / 1 ~0.203 ms +XXX[7] TO 17 ms, lFrame0 2 ms, lFrameX 83 / 1524 ~217.736 ms, finishGL 81 / 1283 ~183.315 ms, waitGL 0 / 1 ~0.176 ms +XXX[8] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 1606 ~200.869 ms, finishGL 82 / 1365 ~170.676 ms, waitGL 0 / 1 ~0.156 ms +XXX[9] TO 17 ms, lFrame0 0 ms, lFrameX 98 / 1705 ~189.545 ms, finishGL 98 / 1463 ~162.626 ms, waitGL 0 / 1 ~0.14 ms +XXX[10] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 1788 ~178.844 ms, finishGL 81 / 1545 ~154.52 ms, waitGL 0 / 1 ~0.128 ms +XXX[11] TO 17 ms, lFrame0 1 ms, lFrameX 78 / 1866 ~169.691 ms, finishGL 77 / 1622 ~147.48 ms, waitGL 0 / 1 ~0.118 ms +XXX[12] TO 17 ms, lFrame0 0 ms, lFrameX 104 / 1970 ~164.238 ms, finishGL 103 / 1725 ~143.819 ms, waitGL 0 / 1 ~0.109 ms +XXX[13] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 2052 ~157.921 ms, finishGL 81 / 1807 ~139.019 ms, waitGL 0 / 1 ~0.102 ms +XXX[14] TO 17 ms, lFrame0 1 ms, lFrameX 77 / 2130 ~152.18 ms, finishGL 76 / 1883 ~134.53 ms, waitGL 0 / 1 ~0.096 ms +XXX[15] TO 17 ms, lFrame0 0 ms, lFrameX 104 / 2235 ~149.003 ms, finishGL 104 / 1987 ~132.499 ms, waitGL 0 / 1 ~0.09 ms +XXX[16] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 2317 ~144.869 ms, finishGL 82 / 2069 ~129.364 ms, waitGL 0 / 1 ~0.086 ms +XXX[17] TO 17 ms, lFrame0 0 ms, lFrameX 75 / 2393 ~140.812 ms, finishGL 74 / 2144 ~126.164 ms, waitGL 0 / 1 ~0.081 ms +XXX[18] TO 17 ms, lFrame0 0 ms, lFrameX 107 / 2501 ~138.947 ms, finishGL 106 / 2251 ~125.084 ms, waitGL 0 / 1 ~0.078 ms +XXX[19] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 2584 ~136.019 ms, finishGL 82 / 2334 ~122.861 ms, waitGL 0 / 1 ~0.074 ms +XXX[20] TO 17 ms, lFrame0 0 ms, lFrameX 75 / 2659 ~132.991 ms, finishGL 74 / 2409 ~120.458 ms, waitGL 0 / 1 ~0.071 ms +XXX[21] TO 17 ms, lFrame0 0 ms, lFrameX 107 / 2767 ~131.792 ms, finishGL 107 / 2516 ~119.829 ms, waitGL 0 / 1 ~0.068 ms +XXX[22] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 2850 ~129.57 ms, finishGL 82 / 2598 ~118.129 ms, waitGL 0 / 1 ~0.066 ms +XXX[23] TO 17 ms, lFrame0 0 ms, lFrameX 73 / 2923 ~127.112 ms, finishGL 72 / 2671 ~116.144 ms, waitGL 0 / 1 ~0.064 ms +XXX[24] TO 17 ms, lFrame0 0 ms, lFrameX 104 / 3028 ~126.189 ms, finishGL 104 / 2775 ~115.653 ms, waitGL 0 / 1 ~0.062 ms +XXX[25] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 3111 ~124.449 ms, finishGL 82 / 2857 ~114.316 ms, waitGL 0 / 1 ~0.06 ms +XXX[26] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 3179 ~122.303 ms, finishGL 68 / 2925 ~112.537 ms, waitGL 0 / 1 ~0.058 ms +XXX[27] TO 17 ms, lFrame0 0 ms, lFrameX 96 / 3276 ~121.334 ms, finishGL 95 / 3021 ~111.912 ms, waitGL 0 / 1 ~0.056 ms +XXX[28] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 3358 ~119.931 ms, finishGL 81 / 3103 ~110.824 ms, waitGL 0 / 1 ~0.055 ms +XXX[29] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 3425 ~118.108 ms, finishGL 66 / 3169 ~109.29 ms, waitGL 0 / 1 ~0.053 ms +XXX[30] TO 17 ms, lFrame0 0 ms, lFrameX 97 / 3522 ~117.427 ms, finishGL 97 / 3266 ~108.885 ms, waitGL 0 / 1 ~0.052 ms +XXX[31] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 3605 ~116.298 ms, finishGL 81 / 3348 ~108.018 ms, waitGL 0 / 1 ~0.051 ms +XXX[32] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 3670 ~114.699 ms, finishGL 64 / 3413 ~106.659 ms, waitGL 0 / 1 ~0.05 ms +XXX[33] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 3753 ~113.755 ms, finishGL 83 / 3496 ~105.943 ms, waitGL 0 / 1 ~0.049 ms +XXX[34] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 3819 ~112.326 ms, finishGL 64 / 3560 ~104.731 ms, waitGL 0 / 1 ~0.047 ms +XXX[35] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 3882 ~110.923 ms, finishGL 62 / 3623 ~103.536 ms, waitGL 0 / 1 ~0.046 ms +XXX[36] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 3952 ~109.795 ms, finishGL 69 / 3693 ~102.601 ms, waitGL 0 / 1 ~0.046 ms +XXX[37] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4018 ~108.616 ms, finishGL 65 / 3759 ~101.602 ms, waitGL 0 / 1 ~0.045 ms +XXX[38] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 4084 ~107.492 ms, finishGL 65 / 3824 ~100.649 ms, waitGL 0 / 1 ~0.044 ms +XXX[39] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 4150 ~106.426 ms, finishGL 65 / 3890 ~99.745 ms, waitGL 0 / 1 ~0.043 ms +XXX[40] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 4216 ~105.406 ms, finishGL 65 / 3955 ~98.88 ms, waitGL 0 / 1 ~0.042 ms +XXX[41] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4282 ~104.446 ms, finishGL 65 / 4020 ~98.069 ms, waitGL 0 / 1 ~0.042 ms +XXX[42] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4348 ~103.54 ms, finishGL 65 / 4086 ~97.305 ms, waitGL 0 / 1 ~0.041 ms +XXX[43] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4415 ~102.674 ms, finishGL 65 / 4152 ~96.568 ms, waitGL 0 / 1 ~0.04 ms +XXX[44] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4481 ~101.854 ms, finishGL 66 / 4218 ~95.875 ms, waitGL 0 / 1 ~0.04 ms +XXX[45] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4547 ~101.064 ms, finishGL 65 / 4284 ~95.207 ms, waitGL 0 / 1 ~0.039 ms +XXX[46] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4614 ~100.307 ms, finishGL 65 / 4349 ~94.563 ms, waitGL 0 / 1 ~0.039 ms +XXX[47] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4680 ~99.591 ms, finishGL 66 / 4416 ~93.958 ms, waitGL 0 / 1 ~0.038 ms +XXX[48] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 4746 ~98.887 ms, finishGL 65 / 4481 ~93.363 ms, waitGL 0 / 1 ~0.038 ms +XXX[49] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4813 ~98.226 ms, finishGL 66 / 4547 ~92.806 ms, waitGL 0 / 1 ~0.037 ms +XXX[50] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4879 ~97.587 ms, finishGL 65 / 4613 ~92.262 ms, waitGL 0 / 1 ~0.037 ms +XXX[51] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 4945 ~96.967 ms, finishGL 65 / 4678 ~91.737 ms, waitGL 0 / 1 ~0.037 ms +XXX[52] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5011 ~96.381 ms, finishGL 66 / 4744 ~91.244 ms, waitGL 0 / 1 ~0.036 ms +XXX[53] TO 17 ms, lFrame0 9 ms, lFrameX 68 / 5080 ~95.852 ms, finishGL 58 / 4803 ~90.633 ms, waitGL 0 / 1 ~0.036 ms +XXX[54] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 5145 ~95.284 ms, finishGL 64 / 4868 ~90.153 ms, waitGL 0 / 1 ~0.035 ms +XXX[55] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5211 ~94.762 ms, finishGL 65 / 4934 ~89.712 ms, waitGL 0 / 1 ~0.035 ms +XXX[56] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 5276 ~94.225 ms, finishGL 64 / 4998 ~89.255 ms, waitGL 0 / 1 ~0.035 ms +XXX[57] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5342 ~93.732 ms, finishGL 65 / 5063 ~88.841 ms, waitGL 0 / 1 ~0.034 ms +XXX[58] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5410 ~93.277 ms, finishGL 66 / 5130 ~88.463 ms, waitGL 0 / 1 ~0.034 ms +XXX[59] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5477 ~92.831 ms, finishGL 66 / 5197 ~88.09 ms, waitGL 0 / 2 ~0.034 ms +XXX[60] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5543 ~92.388 ms, finishGL 65 / 5263 ~87.717 ms, waitGL 0 / 2 ~0.033 ms +XXX[61] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5609 ~91.963 ms, finishGL 65 / 5329 ~87.36 ms, waitGL 0 / 2 ~0.033 ms +XXX[62] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5676 ~91.562 ms, finishGL 66 / 5395 ~87.026 ms, waitGL 0 / 2 ~0.033 ms +XXX[63] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5743 ~91.161 ms, finishGL 65 / 5461 ~86.688 ms, waitGL 0 / 2 ~0.032 ms +XXX[64] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5809 ~90.78 ms, finishGL 66 / 5527 ~86.37 ms, waitGL 0 / 2 ~0.032 ms +XXX[65] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5877 ~90.417 ms, finishGL 66 / 5594 ~86.067 ms, waitGL 0 / 2 ~0.032 ms +XXX[66] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5944 ~90.064 ms, finishGL 66 / 5660 ~85.771 ms, waitGL 0 / 2 ~0.032 ms +XXX[67] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6010 ~89.705 ms, finishGL 65 / 5726 ~85.47 ms, waitGL 0 / 2 ~0.031 ms +XXX[68] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6077 ~89.37 ms, finishGL 66 / 5792 ~85.189 ms, waitGL 0 / 2 ~0.031 ms +XXX[69] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6144 ~89.049 ms, finishGL 66 / 5859 ~84.922 ms, waitGL 0 / 2 ~0.031 ms +XXX[70] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6210 ~88.723 ms, finishGL 65 / 5925 ~84.65 ms, waitGL 0 / 2 ~0.031 ms +XXX[71] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6277 ~88.41 ms, finishGL 65 / 5991 ~84.387 ms, waitGL 0 / 2 ~0.031 ms +XXX[72] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6343 ~88.105 ms, finishGL 65 / 6057 ~84.13 ms, waitGL 0 / 2 ~0.03 ms +XXX[73] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 6409 ~87.8 ms, finishGL 65 / 6122 ~83.873 ms, waitGL 0 / 2 ~0.03 ms +XXX[74] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 6475 ~87.502 ms, finishGL 65 / 6188 ~83.622 ms, waitGL 0 / 2 ~0.03 ms +XXX[75] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 6540 ~87.209 ms, finishGL 64 / 6252 ~83.371 ms, waitGL 0 / 2 ~0.03 ms +XXX[76] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6606 ~86.932 ms, finishGL 65 / 6318 ~83.14 ms, waitGL 0 / 2 ~0.03 ms +XXX[77] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6674 ~86.678 ms, finishGL 66 / 6385 ~82.928 ms, waitGL 0 / 2 ~0.029 ms +XXX[78] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6740 ~86.422 ms, finishGL 66 / 6451 ~82.714 ms, waitGL 0 / 2 ~0.029 ms +XXX[79] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6807 ~86.17 ms, finishGL 65 / 6517 ~82.502 ms, waitGL 0 / 2 ~0.029 ms +XXX[80] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6874 ~85.928 ms, finishGL 66 / 6584 ~82.3 ms, waitGL 0 / 2 ~0.029 ms +XXX[81] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6941 ~85.692 ms, finishGL 66 / 6650 ~82.104 ms, waitGL 0 / 2 ~0.029 ms +XXX[82] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 7008 ~85.471 ms, finishGL 67 / 6717 ~81.92 ms, waitGL 0 / 2 ~0.029 ms +XXX[83] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7075 ~85.242 ms, finishGL 65 / 6783 ~81.728 ms, waitGL 0 / 2 ~0.028 ms +XXX[84] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7141 ~85.019 ms, finishGL 66 / 6849 ~81.54 ms, waitGL 0 / 2 ~0.028 ms +XXX[85] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7208 ~84.805 ms, finishGL 66 / 6915 ~81.361 ms, waitGL 0 / 2 ~0.028 ms +XXX[86] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7275 ~84.596 ms, finishGL 66 / 6982 ~81.187 ms, waitGL 0 / 2 ~0.028 ms +XXX[87] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7341 ~84.384 ms, finishGL 65 / 7047 ~81.009 ms, waitGL 0 / 2 ~0.028 ms +XXX[88] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7407 ~84.179 ms, finishGL 65 / 7113 ~80.836 ms, waitGL 0 / 2 ~0.028 ms +XXX[89] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7474 ~83.98 ms, finishGL 65 / 7179 ~80.669 ms, waitGL 0 / 2 ~0.028 ms +XXX[90] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7540 ~83.784 ms, finishGL 65 / 7245 ~80.504 ms, waitGL 0 / 2 ~0.028 ms +XXX[91] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 7607 ~83.599 ms, finishGL 66 / 7311 ~80.348 ms, waitGL 0 / 2 ~0.027 ms +XXX[92] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 7673 ~83.407 ms, finishGL 65 / 7377 ~80.186 ms, waitGL 0 / 2 ~0.027 ms +XXX[93] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7740 ~83.226 ms, finishGL 66 / 7443 ~80.035 ms, waitGL 0 / 2 ~0.027 ms +XXX[94] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7806 ~83.051 ms, finishGL 66 / 7509 ~79.888 ms, waitGL 0 / 2 ~0.027 ms +XXX[95] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7872 ~82.873 ms, finishGL 65 / 7575 ~79.738 ms, waitGL 0 / 2 ~0.027 ms +XXX[96] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 7938 ~82.695 ms, finishGL 65 / 7640 ~79.588 ms, waitGL 0 / 2 ~0.027 ms +XXX[97] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8005 ~82.526 ms, finishGL 65 / 7706 ~79.446 ms, waitGL 0 / 2 ~0.027 ms +XXX[98] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8071 ~82.359 ms, finishGL 65 / 7771 ~79.305 ms, waitGL 0 / 2 ~0.027 ms +XXX[99] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8137 ~82.197 ms, finishGL 65 / 7837 ~79.169 ms, waitGL 0 / 2 ~0.026 ms +XXX[1] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 66 ~66.612 ms, finishGL 66 / 66 ~66.069 ms, waitGL 0 / 0 ~0.017 ms +XXX[2] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 131 ~65.969 ms, finishGL 64 / 130 ~65.483 ms, waitGL 0 / 0 ~0.018 ms +XXX[3] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 198 ~66.176 ms, finishGL 66 / 197 ~65.684 ms, waitGL 0 / 0 ~0.017 ms +XXX[4] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 265 ~66.274 ms, finishGL 66 / 263 ~65.784 ms, waitGL 0 / 0 ~0.016 ms +XXX[5] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 331 ~66.257 ms, finishGL 65 / 328 ~65.765 ms, waitGL 0 / 0 ~0.016 ms +XXX[6] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 397 ~66.228 ms, finishGL 65 / 394 ~65.727 ms, waitGL 0 / 0 ~0.016 ms +XXX[7] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 464 ~66.289 ms, finishGL 66 / 460 ~65.791 ms, waitGL 0 / 0 ~0.015 ms +XXX[8] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 531 ~66.42 ms, finishGL 66 / 527 ~65.919 ms, waitGL 0 / 0 ~0.015 ms +XXX[9] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 598 ~66.459 ms, finishGL 66 / 593 ~65.961 ms, waitGL 0 / 0 ~0.016 ms +XXX[10] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 666 ~66.638 ms, finishGL 67 / 661 ~66.141 ms, waitGL 0 / 0 ~0.016 ms +XXX[11] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 732 ~66.562 ms, finishGL 65 / 726 ~66.062 ms, waitGL 0 / 0 ~0.016 ms +XXX[12] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 798 ~66.515 ms, finishGL 65 / 792 ~66.004 ms, waitGL 0 / 0 ~0.016 ms +XXX[13] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 863 ~66.433 ms, finishGL 64 / 856 ~65.919 ms, waitGL 0 / 0 ~0.016 ms +XXX[14] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 930 ~66.441 ms, finishGL 66 / 923 ~65.929 ms, waitGL 0 / 0 ~0.016 ms +XXX[15] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 996 ~66.432 ms, finishGL 65 / 988 ~65.92 ms, waitGL 0 / 0 ~0.016 ms +XXX[16] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1062 ~66.436 ms, finishGL 66 / 1054 ~65.926 ms, waitGL 0 / 0 ~0.015 ms +XXX[17] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1129 ~66.447 ms, finishGL 66 / 1120 ~65.94 ms, waitGL 0 / 0 ~0.015 ms +XXX[18] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 1196 ~66.495 ms, finishGL 66 / 1187 ~65.989 ms, waitGL 0 / 0 ~0.015 ms +XXX[19] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1263 ~66.485 ms, finishGL 65 / 1253 ~65.979 ms, waitGL 0 / 0 ~0.015 ms +FrameCount: 120 - FrameRate: 15.0 +XXX[20] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 1330 ~66.512 ms, finishGL 66 / 1320 ~66.002 ms, waitGL 0 / 0 ~0.015 ms +XXX[21] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1397 ~66.528 ms, finishGL 66 / 1386 ~66.019 ms, waitGL 0 / 0 ~0.015 ms +XXX[22] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 1464 ~66.577 ms, finishGL 67 / 1453 ~66.069 ms, waitGL 0 / 0 ~0.015 ms +XXX[23] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1531 ~66.581 ms, finishGL 66 / 1519 ~66.074 ms, waitGL 0 / 0 ~0.015 ms +XXX[24] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1598 ~66.589 ms, finishGL 66 / 1585 ~66.082 ms, waitGL 0 / 0 ~0.015 ms +XXX[25] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1665 ~66.601 ms, finishGL 66 / 1652 ~66.095 ms, waitGL 0 / 0 ~0.015 ms +XXX[26] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 1732 ~66.617 ms, finishGL 66 / 1718 ~66.112 ms, waitGL 0 / 0 ~0.015 ms +XXX[27] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1798 ~66.607 ms, finishGL 65 / 1784 ~66.103 ms, waitGL 0 / 0 ~0.016 ms +XXX[28] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1864 ~66.599 ms, finishGL 65 / 1850 ~66.095 ms, waitGL 0 / 0 ~0.016 ms +XXX[29] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1931 ~66.611 ms, finishGL 66 / 1917 ~66.107 ms, waitGL 0 / 0 ~0.016 ms +XXX[30] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 1997 ~66.589 ms, finishGL 65 / 1982 ~66.088 ms, waitGL 0 / 0 ~0.016 ms +XXX[31] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2063 ~66.572 ms, finishGL 65 / 2048 ~66.074 ms, waitGL 0 / 0 ~0.015 ms +XXX[32] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2130 ~66.576 ms, finishGL 66 / 2114 ~66.077 ms, waitGL 0 / 0 ~0.015 ms +XXX[33] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2196 ~66.568 ms, finishGL 65 / 2180 ~66.069 ms, waitGL 0 / 0 ~0.016 ms +XXX[34] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 2263 ~66.587 ms, finishGL 66 / 2247 ~66.089 ms, waitGL 0 / 0 ~0.015 ms +XXX[35] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2330 ~66.58 ms, finishGL 65 / 2312 ~66.082 ms, waitGL 0 / 0 ~0.015 ms +XXX[36] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2396 ~66.574 ms, finishGL 65 / 2378 ~66.077 ms, waitGL 0 / 0 ~0.015 ms +XXX[37] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2463 ~66.57 ms, finishGL 65 / 2444 ~66.07 ms, waitGL 0 / 0 ~0.015 ms +XXX[38] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2530 ~66.579 ms, finishGL 66 / 2510 ~66.078 ms, waitGL 0 / 0 ~0.015 ms +XXX[39] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2596 ~66.572 ms, finishGL 65 / 2576 ~66.072 ms, waitGL 0 / 0 ~0.015 ms +XXX[40] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2662 ~66.566 ms, finishGL 65 / 2642 ~66.062 ms, waitGL 0 / 0 ~0.016 ms +XXX[41] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2728 ~66.555 ms, finishGL 65 / 2708 ~66.052 ms, waitGL 0 / 0 ~0.016 ms +XXX[42] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2795 ~66.566 ms, finishGL 66 / 2774 ~66.063 ms, waitGL 0 / 0 ~0.016 ms +XXX[43] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2861 ~66.554 ms, finishGL 65 / 2840 ~66.052 ms, waitGL 0 / 0 ~0.016 ms +XXX[44] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 2927 ~66.536 ms, finishGL 65 / 2905 ~66.035 ms, waitGL 0 / 0 ~0.015 ms +XXX[45] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 2992 ~66.506 ms, finishGL 64 / 2970 ~66.001 ms, waitGL 0 / 0 ~0.016 ms +XXX[46] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 3057 ~66.473 ms, finishGL 64 / 3034 ~65.966 ms, waitGL 0 / 0 ~0.016 ms +XXX[47] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 3122 ~66.425 ms, finishGL 63 / 3098 ~65.918 ms, waitGL 0 / 0 ~0.016 ms +XXX[48] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 3185 ~66.364 ms, finishGL 63 / 3161 ~65.858 ms, waitGL 0 / 0 ~0.016 ms +XXX[49] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 3247 ~66.267 ms, finishGL 61 / 3222 ~65.763 ms, waitGL 0 / 0 ~0.016 ms +XXX[50] TO 17 ms, lFrame0 0 ms, lFrameX 62 / 3309 ~66.196 ms, finishGL 62 / 3284 ~65.693 ms, waitGL 0 / 0 ~0.016 ms +XXX[51] TO 17 ms, lFrame0 0 ms, lFrameX 47 / 3357 ~65.831 ms, finishGL 47 / 3331 ~65.329 ms, waitGL 0 / 0 ~0.016 ms +XXX[52] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3406 ~65.512 ms, finishGL 48 / 3380 ~65.011 ms, waitGL 0 / 0 ~0.016 ms +XXX[53] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3455 ~65.197 ms, finishGL 48 / 3428 ~64.697 ms, waitGL 0 / 0 ~0.016 ms +XXX[54] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3504 ~64.902 ms, finishGL 48 / 3477 ~64.403 ms, waitGL 0 / 0 ~0.016 ms +XXX[55] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3553 ~64.612 ms, finishGL 48 / 3526 ~64.112 ms, waitGL 0 / 0 ~0.016 ms +XXX[56] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3602 ~64.335 ms, finishGL 48 / 3574 ~63.837 ms, waitGL 0 / 0 ~0.016 ms +XXX[57] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3652 ~64.083 ms, finishGL 49 / 3624 ~63.583 ms, waitGL 0 / 0 ~0.016 ms +XXX[58] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3701 ~63.821 ms, finishGL 48 / 3672 ~63.322 ms, waitGL 0 / 0 ~0.016 ms +XXX[59] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3751 ~63.583 ms, finishGL 49 / 3722 ~63.084 ms, waitGL 0 / 0 ~0.016 ms +XXX[60] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3800 ~63.342 ms, finishGL 48 / 3770 ~62.842 ms, waitGL 0 / 0 ~0.016 ms +XXX[61] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3849 ~63.111 ms, finishGL 48 / 3819 ~62.611 ms, waitGL 0 / 1 ~0.016 ms +XXX[62] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3898 ~62.875 ms, finishGL 48 / 3867 ~62.375 ms, waitGL 0 / 1 ~0.016 ms +XXX[63] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3947 ~62.657 ms, finishGL 48 / 3915 ~62.158 ms, waitGL 0 / 1 ~0.016 ms +XXX[64] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3996 ~62.439 ms, finishGL 48 / 3964 ~61.94 ms, waitGL 0 / 1 ~0.016 ms +XXX[65] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 4044 ~62.229 ms, finishGL 48 / 4012 ~61.729 ms, waitGL 0 / 1 ~0.016 ms +XXX[66] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 4093 ~62.018 ms, finishGL 47 / 4060 ~61.519 ms, waitGL 0 / 1 ~0.016 ms +XXX[67] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 4141 ~61.82 ms, finishGL 48 / 4108 ~61.319 ms, waitGL 0 / 1 ~0.016 ms +XXX[68] TO 17 ms, lFrame0 0 ms, lFrameX 29 / 4171 ~61.351 ms, finishGL 29 / 4137 ~60.851 ms, waitGL 0 / 1 ~0.016 ms +XXX[69] TO 17 ms, lFrame0 0 ms, lFrameX 51 / 4223 ~61.207 ms, finishGL 50 / 4188 ~60.706 ms, waitGL 0 / 1 ~0.016 ms +XXX[70] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4255 ~60.791 ms, finishGL 31 / 4220 ~60.289 ms, waitGL 0 / 1 ~0.016 ms +XXX[71] TO 17 ms, lFrame0 0 ms, lFrameX 28 / 4283 ~60.33 ms, finishGL 27 / 4247 ~59.828 ms, waitGL 0 / 1 ~0.016 ms +XXX[72] TO 17 ms, lFrame0 0 ms, lFrameX 53 / 4337 ~60.239 ms, finishGL 53 / 4301 ~59.736 ms, waitGL 0 / 1 ~0.016 ms +XXX[73] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4369 ~59.853 ms, finishGL 31 / 4332 ~59.35 ms, waitGL 0 / 1 ~0.016 ms +XXX[74] TO 17 ms, lFrame0 0 ms, lFrameX 26 / 4395 ~59.4 ms, finishGL 25 / 4358 ~58.895 ms, waitGL 0 / 1 ~0.016 ms +XXX[75] TO 17 ms, lFrame0 0 ms, lFrameX 39 / 4434 ~59.13 ms, finishGL 38 / 4396 ~58.625 ms, waitGL 0 / 1 ~0.016 ms +XXX[76] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 4483 ~58.99 ms, finishGL 47 / 4444 ~58.481 ms, waitGL 0 / 1 ~0.016 ms +XXX[77] TO 17 ms, lFrame0 0 ms, lFrameX 31 / 4515 ~58.637 ms, finishGL 31 / 4476 ~58.129 ms, waitGL 0 / 1 ~0.016 ms +XXX[78] TO 17 ms, lFrame0 0 ms, lFrameX 22 / 4538 ~58.18 ms, finishGL 22 / 4498 ~57.673 ms, waitGL 0 / 1 ~0.016 ms +XXX[79] TO 17 ms, lFrame0 0 ms, lFrameX 26 / 4564 ~57.78 ms, finishGL 26 / 4524 ~57.273 ms, waitGL 0 / 1 ~0.016 ms +XXX[80] TO 17 ms, lFrame0 0 ms, lFrameX 22 / 4587 ~57.343 ms, finishGL 22 / 4547 ~56.84 ms, waitGL 0 / 1 ~0.016 ms +XXX[81] TO 17 ms, lFrame0 0 ms, lFrameX 43 / 4631 ~57.178 ms, finishGL 43 / 4590 ~56.675 ms, waitGL 0 / 1 ~0.016 ms +XXX[82] TO 17 ms, lFrame0 0 ms, lFrameX 33 / 4664 ~56.885 ms, finishGL 32 / 4623 ~56.382 ms, waitGL 0 / 1 ~0.016 ms +XXX[83] TO 17 ms, lFrame0 0 ms, lFrameX 23 / 4688 ~56.487 ms, finishGL 23 / 4646 ~55.982 ms, waitGL 0 / 1 ~0.016 ms +XXX[84] TO 17 ms, lFrame0 0 ms, lFrameX 42 / 4730 ~56.317 ms, finishGL 41 / 4688 ~55.812 ms, waitGL 0 / 1 ~0.016 ms +XXX[85] TO 17 ms, lFrame0 0 ms, lFrameX 36 / 4766 ~56.079 ms, finishGL 35 / 4723 ~55.575 ms, waitGL 0 / 1 ~0.016 ms +XXX[86] TO 17 ms, lFrame0 0 ms, lFrameX 30 / 4797 ~55.783 ms, finishGL 29 / 4753 ~55.275 ms, waitGL 0 / 1 ~0.016 ms +XXX[87] TO 17 ms, lFrame0 0 ms, lFrameX 59 / 4856 ~55.824 ms, finishGL 58 / 4812 ~55.316 ms, waitGL 0 / 1 ~0.016 ms +XXX[88] TO 17 ms, lFrame0 0 ms, lFrameX 55 / 4912 ~55.82 ms, finishGL 55 / 4867 ~55.313 ms, waitGL 0 / 1 ~0.016 ms +XXX[89] TO 17 ms, lFrame0 0 ms, lFrameX 41 / 4953 ~55.662 ms, finishGL 41 / 4908 ~55.153 ms, waitGL 0 / 1 ~0.016 ms +XXX[90] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 5015 ~55.723 ms, finishGL 60 / 4969 ~55.211 ms, waitGL 0 / 1 ~0.016 ms +XXX[91] TO 17 ms, lFrame0 0 ms, lFrameX 51 / 5066 ~55.677 ms, finishGL 51 / 5020 ~55.166 ms, waitGL 0 / 1 ~0.016 ms +XXX[92] TO 17 ms, lFrame0 0 ms, lFrameX 42 / 5109 ~55.532 ms, finishGL 41 / 5061 ~55.021 ms, waitGL 0 / 1 ~0.016 ms +XXX[93] TO 17 ms, lFrame0 0 ms, lFrameX 74 / 5183 ~55.732 ms, finishGL 73 / 5135 ~55.222 ms, waitGL 0 / 1 ~0.016 ms +XXX[94] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 5233 ~55.671 ms, finishGL 49 / 5185 ~55.161 ms, waitGL 0 / 1 ~0.016 ms +XXX[95] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 5283 ~55.613 ms, finishGL 49 / 5234 ~55.103 ms, waitGL 0 / 1 ~0.016 ms +XXX[96] TO 17 ms, lFrame0 0 ms, lFrameX 43 / 5326 ~55.486 ms, finishGL 42 / 5277 ~54.974 ms, waitGL 0 / 1 ~0.016 ms +XXX[97] TO 17 ms, lFrame0 0 ms, lFrameX 72 / 5399 ~55.667 ms, finishGL 72 / 5350 ~55.155 ms, waitGL 0 / 1 ~0.016 ms +XXX[98] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 5449 ~55.61 ms, finishGL 49 / 5399 ~55.1 ms, waitGL 0 / 1 ~0.016 ms +XXX[99] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 5500 ~55.56 ms, finishGL 50 / 5450 ~55.051 ms, waitGL 0 / 1 ~0.016 ms +XXX[100] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 5550 ~55.5 ms, finishGL 49 / 5499 ~54.991 ms, waitGL 0 / 1 ~0.016 ms +XXX[101] TO 17 ms, lFrame0 0 ms, lFrameX 45 / 5595 ~55.402 ms, finishGL 45 / 5544 ~54.895 ms, waitGL 0 / 1 ~0.016 ms +XXX[102] TO 17 ms, lFrame0 0 ms, lFrameX 56 / 5652 ~55.411 ms, finishGL 55 / 5600 ~54.905 ms, waitGL 0 / 1 ~0.016 ms +XXX[103] TO 17 ms, lFrame0 0 ms, lFrameX 52 / 5704 ~55.379 ms, finishGL 51 / 5651 ~54.873 ms, waitGL 0 / 1 ~0.016 ms +XXX[104] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5771 ~55.496 ms, finishGL 67 / 5719 ~54.99 ms, waitGL 0 / 1 ~0.016 ms +XXX[105] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5838 ~55.609 ms, finishGL 66 / 5785 ~55.103 ms, waitGL 0 / 1 ~0.016 ms +XXX[106] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 5907 ~55.727 ms, finishGL 67 / 5853 ~55.221 ms, waitGL 0 / 1 ~0.016 ms +XXX[107] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 5975 ~55.846 ms, finishGL 67 / 5921 ~55.34 ms, waitGL 0 / 1 ~0.016 ms +XXX[108] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 6046 ~55.983 ms, finishGL 70 / 5991 ~55.478 ms, waitGL 0 / 1 ~0.016 ms +XXX[109] TO 17 ms, lFrame0 0 ms, lFrameX 69 / 6115 ~56.107 ms, finishGL 69 / 6060 ~55.602 ms, waitGL 0 / 1 ~0.016 ms +XXX[110] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6182 ~56.207 ms, finishGL 66 / 6127 ~55.703 ms, waitGL 0 / 1 ~0.016 ms +XXX[111] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6249 ~56.303 ms, finishGL 66 / 6193 ~55.8 ms, waitGL 0 / 1 ~0.016 ms +XXX[112] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6317 ~56.405 ms, finishGL 67 / 6260 ~55.901 ms, waitGL 0 / 1 ~0.016 ms +XXX[113] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6383 ~56.49 ms, finishGL 65 / 6326 ~55.986 ms, waitGL 0 / 1 ~0.016 ms +XXX[114] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6450 ~56.579 ms, finishGL 66 / 6392 ~56.075 ms, waitGL 0 / 1 ~0.016 ms +XXX[115] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6517 ~56.673 ms, finishGL 66 / 6459 ~56.169 ms, waitGL 0 / 1 ~0.016 ms +XXX[116] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6584 ~56.761 ms, finishGL 66 / 6525 ~56.257 ms, waitGL 0 / 1 ~0.016 ms +XXX[117] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6651 ~56.848 ms, finishGL 66 / 6592 ~56.344 ms, waitGL 0 / 1 ~0.016 ms +XXX[118] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 6736 ~57.085 ms, finishGL 84 / 6676 ~56.581 ms, waitGL 0 / 1 ~0.016 ms +XXX[119] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 6818 ~57.298 ms, finishGL 81 / 6758 ~56.794 ms, waitGL 0 / 1 ~0.016 ms +XXX[120] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 6884 ~57.372 ms, finishGL 65 / 6823 ~56.863 ms, waitGL 0 / 1 ~0.015 ms +XXX[121] TO 17 ms, lFrame0 0 ms, lFrameX 100 / 6985 ~57.731 ms, finishGL 100 / 6923 ~57.222 ms, waitGL 0 / 1 ~0.015 ms +XXX[122] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 7068 ~57.939 ms, finishGL 82 / 7006 ~57.431 ms, waitGL 0 / 1 ~0.015 ms +XXX[123] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 7136 ~58.021 ms, finishGL 67 / 7074 ~57.513 ms, waitGL 0 / 1 ~0.015 ms +XXX[124] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 7221 ~58.24 ms, finishGL 84 / 7158 ~57.732 ms, waitGL 0 / 1 ~0.015 ms +XXX[125] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 7307 ~58.46 ms, finishGL 85 / 7244 ~57.952 ms, waitGL 0 / 1 ~0.015 ms +XXX[126] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 7391 ~58.666 ms, finishGL 83 / 7327 ~58.155 ms, waitGL 0 / 2 ~0.015 ms +XXX[127] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 7476 ~58.872 ms, finishGL 84 / 7411 ~58.361 ms, waitGL 0 / 2 ~0.015 ms +XXX[128] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 7561 ~59.076 ms, finishGL 84 / 7496 ~58.565 ms, waitGL 0 / 2 ~0.015 ms +XXX[129] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 7644 ~59.26 ms, finishGL 82 / 7578 ~58.749 ms, waitGL 0 / 2 ~0.016 ms +XXX[130] TO 17 ms, lFrame0 0 ms, lFrameX 79 / 7724 ~59.419 ms, finishGL 79 / 7658 ~58.909 ms, waitGL 0 / 2 ~0.016 ms +2013-06-17 03:36:23.407 java[65080:5f07] Persistent UI failed to open file file://localhost/Users/jogamp/Library/Saved%20Application%20State/com.apple.javajdk16.cmd.savedState/window_1.data: Operation not permitted (1) +XXX[131] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 7805 ~59.58 ms, finishGL 80 / 7738 ~59.071 ms, waitGL 0 / 2 ~0.016 ms +XXX[132] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 7886 ~59.749 ms, finishGL 81 / 7819 ~59.239 ms, waitGL 0 / 2 ~0.016 ms +XXX[133] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 7968 ~59.913 ms, finishGL 81 / 7900 ~59.404 ms, waitGL 0 / 2 ~0.016 ms +XXX[134] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 8049 ~60.074 ms, finishGL 80 / 7981 ~59.565 ms, waitGL 0 / 2 ~0.016 ms +XXX[135] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 8132 ~60.24 ms, finishGL 82 / 8063 ~59.731 ms, waitGL 0 / 2 ~0.016 ms +XXX[136] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 8214 ~60.404 ms, finishGL 82 / 8145 ~59.895 ms, waitGL 0 / 2 ~0.016 ms +XXX[137] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 8298 ~60.57 ms, finishGL 82 / 8228 ~60.061 ms, waitGL 0 / 2 ~0.016 ms +XXX[138] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 8364 ~60.612 ms, finishGL 64 / 8293 ~60.097 ms, waitGL 0 / 2 ~0.016 ms +XXX[139] TO 17 ms, lFrame0 0 ms, lFrameX 98 / 8463 ~60.888 ms, finishGL 98 / 8391 ~60.373 ms, waitGL 0 / 2 ~0.016 ms +FrameCount: 240 - FrameRate: 13.0 +XXX[140] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8529 ~60.926 ms, finishGL 65 / 8457 ~60.41 ms, waitGL 0 / 2 ~0.015 ms +XXX[141] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 8593 ~60.949 ms, finishGL 63 / 8520 ~60.43 ms, waitGL 0 / 2 ~0.015 ms +XXX[142] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 8679 ~61.12 ms, finishGL 84 / 8605 ~60.601 ms, waitGL 0 / 2 ~0.015 ms +XXX[143] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8745 ~61.156 ms, finishGL 65 / 8671 ~60.638 ms, waitGL 0 / 2 ~0.015 ms +XXX[144] TO 17 ms, lFrame0 0 ms, lFrameX 62 / 8807 ~61.166 ms, finishGL 62 / 8733 ~60.648 ms, waitGL 0 / 2 ~0.015 ms +XXX[145] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 8878 ~61.23 ms, finishGL 69 / 8803 ~60.712 ms, waitGL 0 / 2 ~0.015 ms +XXX[146] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8944 ~61.263 ms, finishGL 65 / 8868 ~60.745 ms, waitGL 0 / 2 ~0.015 ms +XXX[147] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 9010 ~61.293 ms, finishGL 65 / 8934 ~60.776 ms, waitGL 0 / 2 ~0.015 ms +XXX[148] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9076 ~61.329 ms, finishGL 65 / 9000 ~60.811 ms, waitGL 0 / 2 ~0.015 ms +XXX[149] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9143 ~61.365 ms, finishGL 66 / 9066 ~60.847 ms, waitGL 0 / 2 ~0.015 ms +XXX[150] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 9208 ~61.393 ms, finishGL 65 / 9131 ~60.875 ms, waitGL 0 / 2 ~0.015 ms +XXX[151] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 9276 ~61.43 ms, finishGL 66 / 9197 ~60.913 ms, waitGL 0 / 2 ~0.015 ms +XXX[152] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 9341 ~61.46 ms, finishGL 65 / 9263 ~60.943 ms, waitGL 0 / 2 ~0.015 ms +XXX[153] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 9409 ~61.497 ms, finishGL 66 / 9330 ~60.981 ms, waitGL 0 / 2 ~0.015 ms +XXX[154] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9475 ~61.529 ms, finishGL 65 / 9396 ~61.013 ms, waitGL 0 / 2 ~0.015 ms +XXX[155] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 9541 ~61.555 ms, finishGL 65 / 9461 ~61.039 ms, waitGL 0 / 2 ~0.015 ms +XXX[156] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 9608 ~61.595 ms, finishGL 67 / 9528 ~61.08 ms, waitGL 0 / 2 ~0.015 ms +XXX[157] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9674 ~61.623 ms, finishGL 65 / 9594 ~61.109 ms, waitGL 0 / 2 ~0.015 ms +XXX[158] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 9742 ~61.659 ms, finishGL 66 / 9660 ~61.144 ms, waitGL 0 / 2 ~0.015 ms +XXX[159] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9808 ~61.691 ms, finishGL 66 / 9727 ~61.176 ms, waitGL 0 / 2 ~0.015 ms +XXX[160] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9874 ~61.718 ms, finishGL 65 / 9792 ~61.204 ms, waitGL 0 / 2 ~0.015 ms +XXX[161] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 9940 ~61.743 ms, finishGL 65 / 9858 ~61.229 ms, waitGL 0 / 2 ~0.015 ms +XXX[162] TO 17 ms, lFrame0 7 ms, lFrameX 68 / 10009 ~61.788 ms, finishGL 61 / 9919 ~61.228 ms, waitGL 0 / 2 ~0.015 ms +XXX[163] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 10071 ~61.788 ms, finishGL 61 / 9980 ~61.229 ms, waitGL 0 / 2 ~0.015 ms +XXX[164] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10137 ~61.813 ms, finishGL 65 / 10045 ~61.255 ms, waitGL 0 / 2 ~0.015 ms +XXX[165] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10203 ~61.841 ms, finishGL 65 / 10111 ~61.283 ms, waitGL 0 / 2 ~0.015 ms +XXX[166] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 10269 ~61.866 ms, finishGL 65 / 10177 ~61.308 ms, waitGL 0 / 2 ~0.015 ms +XXX[167] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10336 ~61.893 ms, finishGL 65 / 10243 ~61.336 ms, waitGL 0 / 2 ~0.015 ms +XXX[168] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10402 ~61.918 ms, finishGL 65 / 10308 ~61.362 ms, waitGL 0 / 2 ~0.015 ms +XXX[169] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 10469 ~61.949 ms, finishGL 66 / 10375 ~61.394 ms, waitGL 0 / 2 ~0.015 ms +XXX[170] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10535 ~61.974 ms, finishGL 65 / 10441 ~61.419 ms, waitGL 0 / 2 ~0.015 ms +XXX[171] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 10602 ~62.005 ms, finishGL 66 / 10508 ~61.45 ms, waitGL 0 / 2 ~0.015 ms +XXX[172] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 10668 ~62.027 ms, finishGL 65 / 10573 ~61.473 ms, waitGL 0 / 2 ~0.015 ms +XXX[173] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 10736 ~62.058 ms, finishGL 66 / 10640 ~61.505 ms, waitGL 0 / 2 ~0.015 ms +XXX[174] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 10803 ~62.087 ms, finishGL 66 / 10706 ~61.534 ms, waitGL 0 / 2 ~0.015 ms +XXX[175] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10869 ~62.114 ms, finishGL 66 / 10773 ~61.561 ms, waitGL 0 / 2 ~0.015 ms +XXX[176] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 10935 ~62.135 ms, finishGL 65 / 10838 ~61.583 ms, waitGL 0 / 2 ~0.015 ms +XXX[177] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11002 ~62.163 ms, finishGL 66 / 10905 ~61.611 ms, waitGL 0 / 2 ~0.016 ms +XXX[178] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11070 ~62.193 ms, finishGL 66 / 10972 ~61.641 ms, waitGL 0 / 2 ~0.016 ms +XXX[179] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11137 ~62.222 ms, finishGL 66 / 11038 ~61.67 ms, waitGL 0 / 2 ~0.016 ms +XXX[180] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11205 ~62.254 ms, finishGL 67 / 11106 ~61.701 ms, waitGL 0 / 2 ~0.016 ms +XXX[181] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11273 ~62.284 ms, finishGL 67 / 11173 ~61.732 ms, waitGL 0 / 2 ~0.016 ms +XXX[182] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11340 ~62.31 ms, finishGL 66 / 11240 ~61.758 ms, waitGL 0 / 2 ~0.016 ms +XXX[183] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 11407 ~62.334 ms, finishGL 66 / 11306 ~61.783 ms, waitGL 0 / 2 ~0.016 ms +XXX[184] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 11490 ~62.446 ms, finishGL 82 / 11388 ~61.895 ms, waitGL 0 / 2 ~0.016 ms +XXX[185] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 11558 ~62.479 ms, finishGL 67 / 11456 ~61.928 ms, waitGL 0 / 2 ~0.016 ms +XXX[186] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 11644 ~62.607 ms, finishGL 85 / 11542 ~62.056 ms, waitGL 0 / 2 ~0.016 ms +XXX[187] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 11730 ~62.727 ms, finishGL 84 / 11627 ~62.177 ms, waitGL 0 / 2 ~0.016 ms +XXX[188] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 11815 ~62.849 ms, finishGL 85 / 11712 ~62.299 ms, waitGL 0 / 3 ~0.016 ms +XXX[189] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 11901 ~62.97 ms, finishGL 85 / 11797 ~62.421 ms, waitGL 0 / 3 ~0.016 ms +XXX[190] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 11986 ~63.085 ms, finishGL 84 / 11881 ~62.535 ms, waitGL 0 / 3 ~0.016 ms +XXX[191] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 12070 ~63.197 ms, finishGL 84 / 11965 ~62.648 ms, waitGL 0 / 3 ~0.016 ms +XXX[192] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 12154 ~63.303 ms, finishGL 83 / 12048 ~62.755 ms, waitGL 0 / 3 ~0.016 ms +XXX[193] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 12238 ~63.411 ms, finishGL 83 / 12132 ~62.863 ms, waitGL 0 / 3 ~0.016 ms +XXX[194] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 12320 ~63.509 ms, finishGL 81 / 12214 ~62.961 ms, waitGL 0 / 3 ~0.016 ms +XXX[195] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 12405 ~63.617 ms, finishGL 84 / 12298 ~63.07 ms, waitGL 0 / 3 ~0.016 ms +XXX[196] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 12505 ~63.801 ms, finishGL 99 / 12397 ~63.254 ms, waitGL 0 / 3 ~0.016 ms +XXX[197] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 12604 ~63.981 ms, finishGL 98 / 12496 ~63.434 ms, waitGL 0 / 3 ~0.016 ms +XXX[198] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 12685 ~64.067 ms, finishGL 80 / 12576 ~63.52 ms, waitGL 0 / 3 ~0.016 ms +XXX[199] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 12767 ~64.16 ms, finishGL 82 / 12659 ~63.613 ms, waitGL 0 / 3 ~0.016 ms +XXX[200] TO 17 ms, lFrame0 3 ms, lFrameX 80 / 12848 ~64.243 ms, finishGL 77 / 12736 ~63.682 ms, waitGL 0 / 3 ~0.016 ms +XXX[201] TO 17 ms, lFrame0 0 ms, lFrameX 79 / 12927 ~64.317 ms, finishGL 78 / 12814 ~63.754 ms, waitGL 0 / 3 ~0.016 ms +XXX[202] TO 17 ms, lFrame0 0 ms, lFrameX 105 / 13033 ~64.52 ms, finishGL 104 / 12919 ~63.958 ms, waitGL 0 / 3 ~0.016 ms +XXX[203] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 13115 ~64.608 ms, finishGL 81 / 13001 ~64.046 ms, waitGL 0 / 3 ~0.016 ms +XXX[204] TO 17 ms, lFrame0 0 ms, lFrameX 77 / 13192 ~64.67 ms, finishGL 76 / 13077 ~64.107 ms, waitGL 0 / 3 ~0.016 ms +XXX[205] TO 17 ms, lFrame0 0 ms, lFrameX 105 / 13298 ~64.869 ms, finishGL 104 / 13182 ~64.306 ms, waitGL 0 / 3 ~0.016 ms +XXX[206] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 13380 ~64.952 ms, finishGL 81 / 13264 ~64.39 ms, waitGL 0 / 3 ~0.016 ms +XXX[207] TO 17 ms, lFrame0 0 ms, lFrameX 74 / 13455 ~65.0 ms, finishGL 74 / 13338 ~64.437 ms, waitGL 0 / 3 ~0.016 ms +XXX[208] TO 17 ms, lFrame0 0 ms, lFrameX 106 / 13561 ~65.198 ms, finishGL 105 / 13444 ~64.634 ms, waitGL 0 / 3 ~0.016 ms +XXX[209] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 13642 ~65.276 ms, finishGL 81 / 13525 ~64.713 ms, waitGL 0 / 3 ~0.016 ms +XXX[210] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 13713 ~65.303 ms, finishGL 70 / 13595 ~64.74 ms, waitGL 0 / 3 ~0.016 ms +XXX[211] TO 17 ms, lFrame0 0 ms, lFrameX 92 / 13806 ~65.434 ms, finishGL 92 / 13687 ~64.87 ms, waitGL 0 / 3 ~0.015 ms +XXX[212] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 13888 ~65.509 ms, finishGL 81 / 13768 ~64.947 ms, waitGL 0 / 3 ~0.015 ms +XXX[213] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 13954 ~65.514 ms, finishGL 65 / 13834 ~64.95 ms, waitGL 0 / 3 ~0.016 ms +XXX[214] TO 17 ms, lFrame0 0 ms, lFrameX 98 / 14053 ~65.668 ms, finishGL 97 / 13932 ~65.104 ms, waitGL 0 / 3 ~0.016 ms +XXX[215] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 14134 ~65.744 ms, finishGL 81 / 14013 ~65.18 ms, waitGL 0 / 3 ~0.015 ms +XXX[216] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 14198 ~65.731 ms, finishGL 62 / 14076 ~65.167 ms, waitGL 0 / 3 ~0.015 ms +XXX[217] TO 17 ms, lFrame0 0 ms, lFrameX 87 / 14285 ~65.83 ms, finishGL 86 / 14162 ~65.266 ms, waitGL 0 / 3 ~0.015 ms +XXX[218] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 14351 ~65.833 ms, finishGL 65 / 14228 ~65.269 ms, waitGL 0 / 3 ~0.016 ms +XXX[219] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 14418 ~65.839 ms, finishGL 66 / 14295 ~65.274 ms, waitGL 0 / 3 ~0.016 ms +XXX[220] TO 17 ms, lFrame0 0 ms, lFrameX 87 / 14506 ~65.938 ms, finishGL 86 / 14382 ~65.373 ms, waitGL 0 / 3 ~0.015 ms +XXX[221] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 14592 ~66.028 ms, finishGL 85 / 14467 ~65.463 ms, waitGL 0 / 3 ~0.015 ms +XXX[222] TO 17 ms, lFrame0 0 ms, lFrameX 75 / 14667 ~66.069 ms, finishGL 74 / 14541 ~65.503 ms, waitGL 0 / 3 ~0.015 ms +XXX[223] TO 17 ms, lFrame0 0 ms, lFrameX 95 / 14763 ~66.203 ms, finishGL 95 / 14636 ~65.636 ms, waitGL 0 / 3 ~0.015 ms +XXX[224] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 14847 ~66.282 ms, finishGL 83 / 14719 ~65.714 ms, waitGL 0 / 3 ~0.015 ms +XXX[225] TO 17 ms, lFrame0 0 ms, lFrameX 77 / 14924 ~66.331 ms, finishGL 76 / 14796 ~65.762 ms, waitGL 0 / 3 ~0.015 ms +XXX[226] TO 17 ms, lFrame0 0 ms, lFrameX 105 / 15029 ~66.503 ms, finishGL 104 / 14901 ~65.934 ms, waitGL 0 / 3 ~0.015 ms +XXX[227] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15112 ~66.574 ms, finishGL 82 / 14983 ~66.006 ms, waitGL 0 / 3 ~0.015 ms +XXX[228] TO 17 ms, lFrame0 0 ms, lFrameX 75 / 15187 ~66.613 ms, finishGL 74 / 15058 ~66.044 ms, waitGL 0 / 3 ~0.015 ms +XXX[229] TO 17 ms, lFrame0 0 ms, lFrameX 106 / 15294 ~66.787 ms, finishGL 106 / 15164 ~66.218 ms, waitGL 0 / 3 ~0.015 ms +XXX[230] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15376 ~66.853 ms, finishGL 81 / 15245 ~66.285 ms, waitGL 0 / 3 ~0.015 ms +XXX[231] TO 17 ms, lFrame0 0 ms, lFrameX 72 / 15449 ~66.88 ms, finishGL 72 / 15317 ~66.311 ms, waitGL 0 / 3 ~0.015 ms +XXX[232] TO 17 ms, lFrame0 0 ms, lFrameX 91 / 15540 ~66.985 ms, finishGL 90 / 15408 ~66.416 ms, waitGL 0 / 3 ~0.015 ms +XXX[233] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 15622 ~67.047 ms, finishGL 80 / 15489 ~66.478 ms, waitGL 0 / 3 ~0.015 ms +XXX[234] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 15690 ~67.053 ms, finishGL 67 / 15556 ~66.482 ms, waitGL 0 / 3 ~0.015 ms +XXX[235] TO 17 ms, lFrame0 0 ms, lFrameX 95 / 15786 ~67.174 ms, finishGL 95 / 15652 ~66.605 ms, waitGL 0 / 3 ~0.015 ms +XXX[236] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 15867 ~67.236 ms, finishGL 81 / 15733 ~66.666 ms, waitGL 0 / 3 ~0.015 ms +XXX[237] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 15932 ~67.225 ms, finishGL 63 / 15797 ~66.654 ms, waitGL 0 / 3 ~0.015 ms +XXX[238] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 16014 ~67.289 ms, finishGL 82 / 15879 ~66.719 ms, waitGL 0 / 3 ~0.015 ms +XXX[239] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 16081 ~67.286 ms, finishGL 66 / 15945 ~66.716 ms, waitGL 0 / 3 ~0.015 ms +XXX[240] TO 17 ms, lFrame0 0 ms, lFrameX 62 / 16144 ~67.268 ms, finishGL 62 / 16007 ~66.699 ms, waitGL 0 / 3 ~0.015 ms +XXX[241] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 16230 ~67.346 ms, finishGL 85 / 16093 ~66.778 ms, waitGL 0 / 3 ~0.015 ms +XXX[242] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 16297 ~67.344 ms, finishGL 66 / 16159 ~66.776 ms, waitGL 0 / 3 ~0.015 ms +XXX[243] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 16360 ~67.327 ms, finishGL 62 / 16222 ~66.759 ms, waitGL 0 / 3 ~0.015 ms +XXX[244] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 16446 ~67.403 ms, finishGL 85 / 16307 ~66.834 ms, waitGL 0 / 3 ~0.015 ms +XXX[245] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 16512 ~67.397 ms, finishGL 65 / 16373 ~66.829 ms, waitGL 0 / 3 ~0.015 ms +XXX[246] TO 17 ms, lFrame0 0 ms, lFrameX 62 / 16574 ~67.376 ms, finishGL 61 / 16434 ~66.807 ms, waitGL 0 / 3 ~0.015 ms +XXX[247] TO 17 ms, lFrame0 0 ms, lFrameX 87 / 16662 ~67.458 ms, finishGL 86 / 16521 ~66.888 ms, waitGL 0 / 3 ~0.015 ms +XXX[248] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 16730 ~67.46 ms, finishGL 67 / 16588 ~66.89 ms, waitGL 0 / 3 ~0.015 ms +XXX[249] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 16794 ~67.446 ms, finishGL 63 / 16652 ~66.877 ms, waitGL 0 / 3 ~0.015 ms +XXX[250] TO 17 ms, lFrame0 0 ms, lFrameX 87 / 16881 ~67.525 ms, finishGL 86 / 16739 ~66.956 ms, waitGL 0 / 3 ~0.015 ms +XXX[251] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 16966 ~67.594 ms, finishGL 84 / 16823 ~67.025 ms, waitGL 0 / 3 ~0.015 ms +XXX[252] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 17035 ~67.599 ms, finishGL 68 / 16891 ~67.031 ms, waitGL 0 / 3 ~0.015 ms +XXX[253] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 17120 ~67.668 ms, finishGL 84 / 16976 ~67.1 ms, waitGL 0 / 3 ~0.015 ms +XXX[254] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 17205 ~67.736 ms, finishGL 84 / 17060 ~67.168 ms, waitGL 0 / 3 ~0.015 ms +XXX[255] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 17290 ~67.804 ms, finishGL 84 / 17145 ~67.236 ms, waitGL 0 / 4 ~0.015 ms +XXX[256] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 17374 ~67.868 ms, finishGL 83 / 17229 ~67.301 ms, waitGL 0 / 4 ~0.015 ms +XXX[257] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 17459 ~67.935 ms, finishGL 84 / 17313 ~67.367 ms, waitGL 0 / 4 ~0.015 ms +XXX[258] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 17543 ~67.999 ms, finishGL 83 / 17397 ~67.432 ms, waitGL 0 / 4 ~0.015 ms +XXX[259] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 17627 ~68.058 ms, finishGL 82 / 17480 ~67.492 ms, waitGL 0 / 4 ~0.015 ms +FrameCount: 360 - FrameRate: 14.0 +XXX[260] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 17710 ~68.119 ms, finishGL 83 / 17563 ~67.553 ms, waitGL 0 / 4 ~0.015 ms +XXX[261] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 17793 ~68.176 ms, finishGL 82 / 17646 ~67.61 ms, waitGL 0 / 4 ~0.015 ms +XXX[262] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 17877 ~68.234 ms, finishGL 82 / 17729 ~67.668 ms, waitGL 0 / 4 ~0.015 ms +XXX[263] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 17960 ~68.29 ms, finishGL 82 / 17811 ~67.725 ms, waitGL 0 / 4 ~0.015 ms +XXX[264] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 18042 ~68.342 ms, finishGL 81 / 17893 ~67.777 ms, waitGL 0 / 4 ~0.015 ms +XXX[265] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18125 ~68.396 ms, finishGL 82 / 17975 ~67.832 ms, waitGL 0 / 4 ~0.015 ms +XXX[266] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18207 ~68.451 ms, finishGL 82 / 18058 ~67.887 ms, waitGL 0 / 4 ~0.015 ms +XXX[267] TO 17 ms, lFrame0 8 ms, lFrameX 85 / 18293 ~68.514 ms, finishGL 76 / 18135 ~67.921 ms, waitGL 0 / 4 ~0.015 ms +XXX[268] TO 17 ms, lFrame0 0 ms, lFrameX 79 / 18373 ~68.556 ms, finishGL 79 / 18214 ~67.964 ms, waitGL 0 / 4 ~0.015 ms +XXX[269] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18455 ~68.608 ms, finishGL 82 / 18296 ~68.016 ms, waitGL 0 / 4 ~0.015 ms +XXX[270] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 18537 ~68.656 ms, finishGL 80 / 18377 ~68.064 ms, waitGL 0 / 4 ~0.015 ms +XXX[271] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 18618 ~68.704 ms, finishGL 81 / 18458 ~68.112 ms, waitGL 0 / 4 ~0.015 ms +XXX[272] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18701 ~68.754 ms, finishGL 82 / 18540 ~68.163 ms, waitGL 0 / 4 ~0.015 ms +XXX[273] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18783 ~68.804 ms, finishGL 81 / 18622 ~68.212 ms, waitGL 0 / 4 ~0.015 ms +XXX[274] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 18865 ~68.851 ms, finishGL 81 / 18703 ~68.261 ms, waitGL 0 / 4 ~0.015 ms +XXX[275] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18947 ~68.901 ms, finishGL 82 / 18785 ~68.311 ms, waitGL 0 / 4 ~0.015 ms +XXX[276] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 19029 ~68.948 ms, finishGL 81 / 18867 ~68.359 ms, waitGL 0 / 4 ~0.015 ms +XXX[277] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 19112 ~68.998 ms, finishGL 82 / 18949 ~68.408 ms, waitGL 0 / 4 ~0.015 ms +XXX[278] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 19195 ~69.047 ms, finishGL 82 / 19031 ~68.459 ms, waitGL 0 / 4 ~0.015 ms +XXX[279] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 19277 ~69.095 ms, finishGL 81 / 19113 ~68.507 ms, waitGL 0 / 4 ~0.015 ms +XXX[280] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 19360 ~69.143 ms, finishGL 81 / 19195 ~68.555 ms, waitGL 0 / 4 ~0.015 ms +XXX[281] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 19442 ~69.19 ms, finishGL 81 / 19277 ~68.602 ms, waitGL 0 / 4 ~0.015 ms +XXX[282] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 19508 ~69.179 ms, finishGL 65 / 19343 ~68.592 ms, waitGL 0 / 4 ~0.015 ms +XXX[283] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19574 ~69.166 ms, finishGL 65 / 19408 ~68.579 ms, waitGL 0 / 4 ~0.015 ms +XXX[284] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19639 ~69.152 ms, finishGL 64 / 19472 ~68.565 ms, waitGL 0 / 4 ~0.015 ms +XXX[285] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19704 ~69.139 ms, finishGL 65 / 19537 ~68.553 ms, waitGL 0 / 4 ~0.015 ms +XXX[286] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19770 ~69.128 ms, finishGL 65 / 19602 ~68.541 ms, waitGL 0 / 4 ~0.015 ms +XXX[287] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19836 ~69.116 ms, finishGL 65 / 19668 ~68.53 ms, waitGL 0 / 4 ~0.015 ms +XXX[288] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19901 ~69.103 ms, finishGL 64 / 19732 ~68.516 ms, waitGL 0 / 4 ~0.015 ms +XXX[289] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19966 ~69.089 ms, finishGL 64 / 19797 ~68.503 ms, waitGL 0 / 4 ~0.015 ms +XXX[290] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 20031 ~69.073 ms, finishGL 64 / 19861 ~68.488 ms, waitGL 0 / 4 ~0.015 ms +XXX[291] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20097 ~69.063 ms, finishGL 65 / 19927 ~68.478 ms, waitGL 0 / 4 ~0.015 ms +XXX[292] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 20163 ~69.051 ms, finishGL 65 / 19992 ~68.466 ms, waitGL 0 / 4 ~0.015 ms +XXX[293] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 20228 ~69.038 ms, finishGL 64 / 20057 ~68.454 ms, waitGL 0 / 4 ~0.015 ms +XXX[294] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20294 ~69.029 ms, finishGL 65 / 20123 ~68.446 ms, waitGL 0 / 4 ~0.015 ms +XXX[295] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 20360 ~69.017 ms, finishGL 64 / 20188 ~68.434 ms, waitGL 0 / 4 ~0.015 ms +XXX[296] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20426 ~69.007 ms, finishGL 65 / 20253 ~68.424 ms, waitGL 0 / 4 ~0.015 ms +XXX[297] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20492 ~68.998 ms, finishGL 65 / 20319 ~68.415 ms, waitGL 0 / 4 ~0.015 ms +XXX[298] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 20558 ~68.988 ms, finishGL 65 / 20384 ~68.405 ms, waitGL 0 / 4 ~0.015 ms +XXX[299] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20625 ~68.98 ms, finishGL 66 / 20451 ~68.399 ms, waitGL 0 / 4 ~0.015 ms +XXX[300] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 20692 ~68.975 ms, finishGL 66 / 20518 ~68.393 ms, waitGL 0 / 4 ~0.015 ms +XXX[301] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 20759 ~68.969 ms, finishGL 66 / 20585 ~68.388 ms, waitGL 0 / 4 ~0.015 ms +XXX[302] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 20827 ~68.965 ms, finishGL 67 / 20652 ~68.385 ms, waitGL 0 / 4 ~0.015 ms +XXX[303] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 20894 ~68.96 ms, finishGL 66 / 20719 ~68.38 ms, waitGL 0 / 4 ~0.015 ms +XXX[304] TO 17 ms, lFrame0 0 ms, lFrameX 69 / 20964 ~68.962 ms, finishGL 69 / 20788 ~68.383 ms, waitGL 0 / 4 ~0.015 ms +XXX[305] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 21033 ~68.96 ms, finishGL 67 / 20856 ~68.381 ms, waitGL 0 / 4 ~0.015 ms +XXX[306] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 21103 ~68.966 ms, finishGL 70 / 20926 ~68.388 ms, waitGL 0 / 4 ~0.015 ms +XXX[307] TO 17 ms, lFrame0 0 ms, lFrameX 71 / 21175 ~68.974 ms, finishGL 70 / 20997 ~68.395 ms, waitGL 0 / 4 ~0.015 ms +XXX[308] TO 17 ms, lFrame0 0 ms, lFrameX 88 / 21263 ~69.036 ms, finishGL 87 / 21085 ~68.457 ms, waitGL 0 / 4 ~0.015 ms +XXX[309] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 21349 ~69.092 ms, finishGL 85 / 21170 ~68.513 ms, waitGL 0 / 4 ~0.015 ms +XXX[310] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 21434 ~69.143 ms, finishGL 84 / 21255 ~68.565 ms, waitGL 0 / 4 ~0.015 ms +XXX[311] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 21520 ~69.197 ms, finishGL 85 / 21340 ~68.618 ms, waitGL 0 / 4 ~0.015 ms +XXX[312] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 21603 ~69.24 ms, finishGL 82 / 21422 ~68.662 ms, waitGL 0 / 4 ~0.015 ms +XXX[313] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 21685 ~69.283 ms, finishGL 82 / 21504 ~68.705 ms, waitGL 0 / 4 ~0.015 ms +XXX[314] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 21768 ~69.326 ms, finishGL 82 / 21587 ~68.748 ms, waitGL 0 / 4 ~0.015 ms +XXX[315] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 21853 ~69.374 ms, finishGL 84 / 21671 ~68.797 ms, waitGL 0 / 5 ~0.015 ms +XXX[316] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 21937 ~69.421 ms, finishGL 83 / 21755 ~68.845 ms, waitGL 0 / 5 ~0.015 ms +XXX[317] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 22021 ~69.469 ms, finishGL 83 / 21838 ~68.892 ms, waitGL 0 / 5 ~0.015 ms +XXX[318] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 22121 ~69.564 ms, finishGL 99 / 21938 ~68.987 ms, waitGL 0 / 5 ~0.015 ms +XXX[319] TO 17 ms, lFrame0 0 ms, lFrameX 98 / 22220 ~69.655 ms, finishGL 98 / 22036 ~69.079 ms, waitGL 0 / 5 ~0.015 ms +XXX[320] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22303 ~69.697 ms, finishGL 82 / 22118 ~69.121 ms, waitGL 0 / 5 ~0.015 ms +XXX[321] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 22384 ~69.733 ms, finishGL 80 / 22199 ~69.158 ms, waitGL 0 / 5 ~0.015 ms +XXX[322] TO 17 ms, lFrame0 1 ms, lFrameX 84 / 22468 ~69.778 ms, finishGL 83 / 22282 ~69.201 ms, waitGL 0 / 5 ~0.015 ms +XXX[323] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 22551 ~69.818 ms, finishGL 82 / 22365 ~69.241 ms, waitGL 0 / 5 ~0.015 ms +XXX[324] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 22634 ~69.859 ms, finishGL 82 / 22447 ~69.282 ms, waitGL 0 / 5 ~0.015 ms +XXX[325] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22717 ~69.899 ms, finishGL 82 / 22530 ~69.323 ms, waitGL 0 / 5 ~0.015 ms +XXX[326] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22800 ~69.941 ms, finishGL 82 / 22613 ~69.365 ms, waitGL 0 / 5 ~0.015 ms +XXX[327] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 22883 ~69.98 ms, finishGL 82 / 22695 ~69.404 ms, waitGL 0 / 5 ~0.015 ms +XXX[328] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22967 ~70.022 ms, finishGL 83 / 22778 ~69.447 ms, waitGL 0 / 5 ~0.015 ms +XXX[329] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 23049 ~70.058 ms, finishGL 81 / 22860 ~69.483 ms, waitGL 0 / 5 ~0.015 ms +XXX[330] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 23134 ~70.103 ms, finishGL 84 / 22944 ~69.528 ms, waitGL 0 / 5 ~0.015 ms +XXX[331] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23217 ~70.143 ms, finishGL 83 / 23027 ~69.569 ms, waitGL 0 / 5 ~0.015 ms +XXX[332] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 23301 ~70.186 ms, finishGL 83 / 23111 ~69.612 ms, waitGL 0 / 5 ~0.015 ms +XXX[333] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23384 ~70.222 ms, finishGL 81 / 23192 ~69.648 ms, waitGL 0 / 5 ~0.015 ms +XXX[334] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23467 ~70.262 ms, finishGL 83 / 23275 ~69.688 ms, waitGL 0 / 5 ~0.015 ms +XXX[335] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23550 ~70.299 ms, finishGL 82 / 23357 ~69.725 ms, waitGL 0 / 5 ~0.015 ms +XXX[336] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23633 ~70.336 ms, finishGL 82 / 23440 ~69.762 ms, waitGL 0 / 5 ~0.015 ms +XXX[337] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23715 ~70.373 ms, finishGL 82 / 23522 ~69.799 ms, waitGL 0 / 5 ~0.015 ms +XXX[338] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23798 ~70.409 ms, finishGL 81 / 23604 ~69.835 ms, waitGL 0 / 5 ~0.015 ms +XXX[339] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23881 ~70.445 ms, finishGL 82 / 23686 ~69.872 ms, waitGL 0 / 5 ~0.015 ms +XXX[340] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23964 ~70.483 ms, finishGL 82 / 23769 ~69.909 ms, waitGL 0 / 5 ~0.015 ms +XXX[341] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 24046 ~70.516 ms, finishGL 81 / 23850 ~69.943 ms, waitGL 0 / 5 ~0.015 ms +XXX[342] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24129 ~70.552 ms, finishGL 82 / 23933 ~69.979 ms, waitGL 0 / 5 ~0.015 ms +XXX[343] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24211 ~70.587 ms, finishGL 82 / 24015 ~70.014 ms, waitGL 0 / 5 ~0.015 ms +XXX[344] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24294 ~70.624 ms, finishGL 82 / 24097 ~70.052 ms, waitGL 0 / 5 ~0.015 ms +XXX[345] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24377 ~70.658 ms, finishGL 81 / 24179 ~70.085 ms, waitGL 0 / 5 ~0.015 ms +XXX[346] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24460 ~70.696 ms, finishGL 83 / 24262 ~70.122 ms, waitGL 0 / 5 ~0.015 ms +XXX[347] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24543 ~70.731 ms, finishGL 82 / 24345 ~70.158 ms, waitGL 0 / 5 ~0.015 ms +XXX[348] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24627 ~70.768 ms, finishGL 82 / 24427 ~70.195 ms, waitGL 0 / 5 ~0.015 ms +XXX[349] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24710 ~70.805 ms, finishGL 83 / 24511 ~70.232 ms, waitGL 0 / 5 ~0.015 ms +XXX[350] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24793 ~70.839 ms, finishGL 82 / 24593 ~70.266 ms, waitGL 0 / 5 ~0.015 ms +XXX[351] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24876 ~70.874 ms, finishGL 82 / 24675 ~70.301 ms, waitGL 0 / 5 ~0.015 ms +XXX[352] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24960 ~70.909 ms, finishGL 82 / 24758 ~70.337 ms, waitGL 0 / 5 ~0.015 ms +XXX[353] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25043 ~70.944 ms, finishGL 82 / 24841 ~70.372 ms, waitGL 0 / 5 ~0.015 ms +XXX[354] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25126 ~70.979 ms, finishGL 82 / 24924 ~70.407 ms, waitGL 0 / 5 ~0.015 ms +XXX[355] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25210 ~71.014 ms, finishGL 82 / 25007 ~70.442 ms, waitGL 0 / 5 ~0.015 ms +XXX[356] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 25292 ~71.047 ms, finishGL 82 / 25089 ~70.475 ms, waitGL 0 / 5 ~0.015 ms +XXX[357] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 25375 ~71.079 ms, finishGL 82 / 25171 ~70.508 ms, waitGL 0 / 5 ~0.015 ms +XXX[358] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25459 ~71.115 ms, finishGL 83 / 25254 ~70.544 ms, waitGL 0 / 5 ~0.015 ms +XXX[359] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25542 ~71.148 ms, finishGL 82 / 25337 ~70.578 ms, waitGL 0 / 5 ~0.015 ms +XXX[360] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25626 ~71.184 ms, finishGL 83 / 25421 ~70.614 ms, waitGL 0 / 5 ~0.015 ms +XXX[361] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25709 ~71.217 ms, finishGL 82 / 25503 ~70.647 ms, waitGL 0 / 5 ~0.015 ms +XXX[362] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 25792 ~71.249 ms, finishGL 82 / 25586 ~70.679 ms, waitGL 0 / 5 ~0.015 ms +XXX[363] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25876 ~71.284 ms, finishGL 83 / 25669 ~70.714 ms, waitGL 0 / 5 ~0.015 ms +XXX[364] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 25960 ~71.319 ms, finishGL 83 / 25753 ~70.75 ms, waitGL 0 / 5 ~0.015 ms +XXX[365] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26043 ~71.352 ms, finishGL 82 / 25835 ~70.783 ms, waitGL 0 / 5 ~0.015 ms +XXX[366] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26126 ~71.384 ms, finishGL 82 / 25918 ~70.815 ms, waitGL 0 / 5 ~0.015 ms +XXX[367] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26209 ~71.415 ms, finishGL 82 / 26000 ~70.847 ms, waitGL 0 / 5 ~0.015 ms +XXX[368] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26293 ~71.448 ms, finishGL 83 / 26083 ~70.88 ms, waitGL 0 / 5 ~0.015 ms +XXX[369] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26376 ~71.481 ms, finishGL 82 / 26166 ~70.912 ms, waitGL 0 / 5 ~0.015 ms +XXX[370] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26459 ~71.511 ms, finishGL 82 / 26248 ~70.943 ms, waitGL 0 / 5 ~0.015 ms +XXX[371] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26542 ~71.542 ms, finishGL 82 / 26331 ~70.973 ms, waitGL 0 / 5 ~0.015 ms +XXX[372] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26625 ~71.574 ms, finishGL 82 / 26414 ~71.006 ms, waitGL 0 / 5 ~0.015 ms +XXX[373] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26707 ~71.603 ms, finishGL 81 / 26495 ~71.034 ms, waitGL 0 / 5 ~0.015 ms +XXX[374] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26790 ~71.633 ms, finishGL 82 / 26578 ~71.065 ms, waitGL 0 / 5 ~0.015 ms +XXX[375] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26873 ~71.663 ms, finishGL 82 / 26660 ~71.095 ms, waitGL 0 / 5 ~0.015 ms +XXX[376] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26956 ~71.694 ms, finishGL 82 / 26743 ~71.126 ms, waitGL 0 / 5 ~0.015 ms +XXX[377] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27039 ~71.723 ms, finishGL 82 / 26825 ~71.155 ms, waitGL 0 / 5 ~0.015 ms +XXX[378] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27122 ~71.751 ms, finishGL 81 / 26907 ~71.184 ms, waitGL 0 / 6 ~0.015 ms +XXX[379] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27205 ~71.781 ms, finishGL 82 / 26990 ~71.214 ms, waitGL 0 / 6 ~0.015 ms +FrameCount: 480 - FrameRate: 12.0 +XXX[380] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27287 ~71.81 ms, finishGL 82 / 27072 ~71.243 ms, waitGL 0 / 6 ~0.015 ms +XXX[381] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27370 ~71.838 ms, finishGL 82 / 27154 ~71.271 ms, waitGL 0 / 6 ~0.015 ms +XXX[382] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27453 ~71.867 ms, finishGL 82 / 27236 ~71.3 ms, waitGL 0 / 6 ~0.015 ms +XXX[383] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27535 ~71.894 ms, finishGL 81 / 27318 ~71.328 ms, waitGL 0 / 6 ~0.015 ms +XXX[384] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27618 ~71.922 ms, finishGL 82 / 27400 ~71.356 ms, waitGL 0 / 6 ~0.015 ms +XXX[385] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 27702 ~71.953 ms, finishGL 83 / 27484 ~71.387 ms, waitGL 0 / 6 ~0.015 ms +XXX[386] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27785 ~71.983 ms, finishGL 82 / 27567 ~71.417 ms, waitGL 0 / 6 ~0.015 ms +XXX[387] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27869 ~72.013 ms, finishGL 83 / 27650 ~71.447 ms, waitGL 0 / 6 ~0.015 ms +XXX[388] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27952 ~72.043 ms, finishGL 83 / 27733 ~71.478 ms, waitGL 0 / 6 ~0.015 ms +XXX[389] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 28038 ~72.077 ms, finishGL 84 / 27818 ~71.512 ms, waitGL 0 / 6 ~0.015 ms +XXX[390] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 28123 ~72.11 ms, finishGL 84 / 27902 ~71.545 ms, waitGL 0 / 6 ~0.015 ms +XXX[391] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 28207 ~72.141 ms, finishGL 83 / 27986 ~71.576 ms, waitGL 0 / 6 ~0.015 ms +XXX[392] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28290 ~72.17 ms, finishGL 83 / 28069 ~71.606 ms, waitGL 0 / 6 ~0.015 ms +XXX[393] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28374 ~72.198 ms, finishGL 82 / 28152 ~71.634 ms, waitGL 0 / 6 ~0.015 ms +XXX[394] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28457 ~72.227 ms, finishGL 82 / 28235 ~71.663 ms, waitGL 0 / 6 ~0.015 ms +XXX[395] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28540 ~72.254 ms, finishGL 82 / 28317 ~71.69 ms, waitGL 0 / 6 ~0.015 ms +XXX[396] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28623 ~72.281 ms, finishGL 82 / 28400 ~71.718 ms, waitGL 0 / 6 ~0.015 ms +XXX[397] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28706 ~72.309 ms, finishGL 83 / 28483 ~71.746 ms, waitGL 0 / 6 ~0.015 ms +XXX[398] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28789 ~72.336 ms, finishGL 82 / 28565 ~71.773 ms, waitGL 0 / 6 ~0.015 ms +XXX[399] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28872 ~72.362 ms, finishGL 82 / 28648 ~71.8 ms, waitGL 0 / 6 ~0.015 ms +XXX[400] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28955 ~72.388 ms, finishGL 82 / 28730 ~71.826 ms, waitGL 0 / 6 ~0.015 ms +XXX[401] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 29036 ~72.409 ms, finishGL 80 / 28810 ~71.847 ms, waitGL 0 / 6 ~0.015 ms +XXX[402] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29118 ~72.434 ms, finishGL 82 / 28893 ~71.873 ms, waitGL 0 / 6 ~0.015 ms +XXX[403] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29200 ~72.458 ms, finishGL 81 / 28974 ~71.897 ms, waitGL 0 / 6 ~0.015 ms +XXX[404] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29283 ~72.483 ms, finishGL 82 / 29056 ~71.922 ms, waitGL 0 / 6 ~0.015 ms +XXX[405] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29366 ~72.509 ms, finishGL 82 / 29139 ~71.948 ms, waitGL 0 / 6 ~0.015 ms +XXX[406] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29449 ~72.534 ms, finishGL 82 / 29221 ~71.973 ms, waitGL 0 / 6 ~0.015 ms +XXX[407] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29531 ~72.559 ms, finishGL 82 / 29303 ~71.998 ms, waitGL 0 / 6 ~0.015 ms +XXX[408] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29614 ~72.585 ms, finishGL 82 / 29385 ~72.024 ms, waitGL 0 / 6 ~0.015 ms +XXX[409] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29697 ~72.61 ms, finishGL 82 / 29468 ~72.049 ms, waitGL 0 / 6 ~0.015 ms +XXX[410] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29780 ~72.634 ms, finishGL 81 / 29550 ~72.073 ms, waitGL 0 / 6 ~0.015 ms +XXX[411] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29863 ~72.659 ms, finishGL 82 / 29632 ~72.099 ms, waitGL 0 / 6 ~0.015 ms +XXX[412] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29946 ~72.685 ms, finishGL 82 / 29715 ~72.125 ms, waitGL 0 / 6 ~0.015 ms +XXX[413] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 30030 ~72.713 ms, finishGL 83 / 29799 ~72.153 ms, waitGL 0 / 6 ~0.015 ms +XXX[414] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 30113 ~72.738 ms, finishGL 82 / 29881 ~72.178 ms, waitGL 0 / 6 ~0.015 ms +XXX[415] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 30196 ~72.762 ms, finishGL 82 / 29964 ~72.202 ms, waitGL 0 / 6 ~0.015 ms +XXX[416] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30279 ~72.787 ms, finishGL 82 / 30046 ~72.228 ms, waitGL 0 / 6 ~0.015 ms +XXX[417] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 30361 ~72.809 ms, finishGL 81 / 30128 ~72.25 ms, waitGL 0 / 6 ~0.015 ms +XXX[418] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30445 ~72.835 ms, finishGL 82 / 30211 ~72.275 ms, waitGL 0 / 6 ~0.015 ms +XXX[419] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 30527 ~72.857 ms, finishGL 81 / 30292 ~72.297 ms, waitGL 0 / 6 ~0.015 ms +XXX[420] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 30611 ~72.884 ms, finishGL 83 / 30376 ~72.325 ms, waitGL 0 / 6 ~0.015 ms +XXX[421] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30695 ~72.911 ms, finishGL 83 / 30460 ~72.351 ms, waitGL 0 / 6 ~0.015 ms +XXX[422] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 30779 ~72.937 ms, finishGL 83 / 30543 ~72.378 ms, waitGL 0 / 6 ~0.015 ms +XXX[423] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30863 ~72.963 ms, finishGL 83 / 30627 ~72.404 ms, waitGL 0 / 6 ~0.015 ms +XXX[424] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 30945 ~72.984 ms, finishGL 81 / 30708 ~72.425 ms, waitGL 0 / 6 ~0.015 ms +XXX[425] TO 17 ms, lFrame0 0 ms, lFrameX 79 / 31025 ~73.0 ms, finishGL 79 / 30787 ~72.441 ms, waitGL 0 / 6 ~0.015 ms +XXX[426] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 31105 ~73.017 ms, finishGL 79 / 30867 ~72.458 ms, waitGL 0 / 6 ~0.015 ms +XXX[427] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 31185 ~73.034 ms, finishGL 80 / 30947 ~72.476 ms, waitGL 0 / 6 ~0.015 ms +XXX[428] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 31250 ~73.015 ms, finishGL 64 / 31011 ~72.456 ms, waitGL 0 / 6 ~0.015 ms +XXX[429] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31316 ~72.999 ms, finishGL 65 / 31077 ~72.441 ms, waitGL 0 / 6 ~0.015 ms +XXX[430] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31382 ~72.982 ms, finishGL 65 / 31142 ~72.424 ms, waitGL 0 / 6 ~0.015 ms +XXX[431] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31448 ~72.966 ms, finishGL 65 / 31208 ~72.408 ms, waitGL 0 / 6 ~0.015 ms +XXX[432] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31514 ~72.95 ms, finishGL 65 / 31273 ~72.392 ms, waitGL 0 / 6 ~0.015 ms +XXX[433] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31580 ~72.933 ms, finishGL 65 / 31338 ~72.376 ms, waitGL 0 / 6 ~0.015 ms +XXX[434] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31646 ~72.918 ms, finishGL 65 / 31404 ~72.361 ms, waitGL 0 / 6 ~0.015 ms +XXX[435] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31712 ~72.901 ms, finishGL 64 / 31469 ~72.344 ms, waitGL 0 / 6 ~0.015 ms +XXX[436] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31778 ~72.886 ms, finishGL 66 / 31535 ~72.329 ms, waitGL 0 / 6 ~0.015 ms +XXX[437] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31844 ~72.871 ms, finishGL 65 / 31601 ~72.314 ms, waitGL 0 / 6 ~0.015 ms +XXX[438] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31911 ~72.856 ms, finishGL 65 / 31667 ~72.299 ms, waitGL 0 / 6 ~0.015 ms +XXX[439] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31977 ~72.842 ms, finishGL 66 / 31733 ~72.285 ms, waitGL 0 / 7 ~0.015 ms +XXX[440] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32044 ~72.827 ms, finishGL 65 / 31799 ~72.271 ms, waitGL 0 / 7 ~0.015 ms +XXX[441] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 32111 ~72.815 ms, finishGL 66 / 31866 ~72.258 ms, waitGL 0 / 7 ~0.015 ms +XXX[442] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32178 ~72.801 ms, finishGL 66 / 31932 ~72.245 ms, waitGL 0 / 7 ~0.015 ms +XXX[443] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 32245 ~72.788 ms, finishGL 66 / 31999 ~72.233 ms, waitGL 0 / 7 ~0.015 ms +XXX[444] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32312 ~72.775 ms, finishGL 66 / 32065 ~72.22 ms, waitGL 0 / 7 ~0.015 ms +XXX[445] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32378 ~72.761 ms, finishGL 65 / 32131 ~72.205 ms, waitGL 0 / 7 ~0.015 ms +XXX[446] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 32446 ~72.749 ms, finishGL 66 / 32198 ~72.193 ms, waitGL 0 / 7 ~0.015 ms +XXX[447] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32512 ~72.734 ms, finishGL 66 / 32264 ~72.179 ms, waitGL 0 / 7 ~0.015 ms +XXX[448] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32578 ~72.72 ms, finishGL 65 / 32330 ~72.165 ms, waitGL 0 / 7 ~0.015 ms +XXX[449] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32645 ~72.707 ms, finishGL 66 / 32396 ~72.152 ms, waitGL 0 / 7 ~0.015 ms +XXX[450] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32711 ~72.692 ms, finishGL 65 / 32462 ~72.138 ms, waitGL 0 / 7 ~0.015 ms +XXX[451] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32777 ~72.678 ms, finishGL 65 / 32528 ~72.124 ms, waitGL 0 / 7 ~0.015 ms +XXX[452] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32844 ~72.665 ms, finishGL 66 / 32594 ~72.111 ms, waitGL 0 / 7 ~0.015 ms +XXX[453] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 32910 ~72.65 ms, finishGL 65 / 32659 ~72.096 ms, waitGL 0 / 7 ~0.015 ms +XXX[454] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 32976 ~72.635 ms, finishGL 65 / 32725 ~72.081 ms, waitGL 0 / 7 ~0.015 ms +XXX[455] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33042 ~72.621 ms, finishGL 65 / 32790 ~72.067 ms, waitGL 0 / 7 ~0.015 ms +XXX[456] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 33107 ~72.604 ms, finishGL 64 / 32855 ~72.05 ms, waitGL 0 / 7 ~0.015 ms +XXX[457] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33173 ~72.589 ms, finishGL 65 / 32920 ~72.036 ms, waitGL 0 / 7 ~0.015 ms +XXX[458] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33239 ~72.574 ms, finishGL 65 / 32985 ~72.021 ms, waitGL 0 / 7 ~0.015 ms +XXX[459] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33304 ~72.558 ms, finishGL 64 / 33050 ~72.005 ms, waitGL 0 / 7 ~0.015 ms +XXX[460] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33370 ~72.544 ms, finishGL 65 / 33115 ~71.991 ms, waitGL 0 / 7 ~0.015 ms +XXX[461] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33435 ~72.529 ms, finishGL 65 / 33181 ~71.976 ms, waitGL 0 / 7 ~0.015 ms +XXX[462] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33500 ~72.512 ms, finishGL 64 / 33245 ~71.96 ms, waitGL 0 / 7 ~0.015 ms +XXX[463] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 33567 ~72.499 ms, finishGL 65 / 33311 ~71.947 ms, waitGL 0 / 7 ~0.015 ms +XXX[464] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33632 ~72.484 ms, finishGL 64 / 33376 ~71.932 ms, waitGL 0 / 7 ~0.016 ms +XXX[465] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33698 ~72.469 ms, finishGL 65 / 33441 ~71.917 ms, waitGL 0 / 7 ~0.016 ms +XXX[466] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33764 ~72.455 ms, finishGL 65 / 33507 ~71.903 ms, waitGL 0 / 7 ~0.016 ms +XXX[467] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 33813 ~72.404 ms, finishGL 48 / 33555 ~71.853 ms, waitGL 0 / 7 ~0.016 ms +XXX[468] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 33862 ~72.355 ms, finishGL 48 / 33604 ~71.803 ms, waitGL 0 / 7 ~0.016 ms +XXX[469] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 33911 ~72.305 ms, finishGL 48 / 33652 ~71.754 ms, waitGL 0 / 7 ~0.016 ms +XXX[470] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 33960 ~72.256 ms, finishGL 48 / 33701 ~71.704 ms, waitGL 0 / 7 ~0.016 ms +XXX[471] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34009 ~72.207 ms, finishGL 48 / 33749 ~71.655 ms, waitGL 0 / 7 ~0.016 ms +XXX[472] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34058 ~72.158 ms, finishGL 48 / 33798 ~71.606 ms, waitGL 0 / 7 ~0.016 ms +XXX[473] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34108 ~72.11 ms, finishGL 49 / 33847 ~71.559 ms, waitGL 0 / 7 ~0.016 ms +XXX[474] TO 17 ms, lFrame0 0 ms, lFrameX 47 / 34155 ~72.058 ms, finishGL 47 / 33894 ~71.507 ms, waitGL 0 / 7 ~0.016 ms +XXX[475] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 34206 ~72.014 ms, finishGL 50 / 33945 ~71.463 ms, waitGL 0 / 7 ~0.016 ms +XXX[476] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34255 ~71.965 ms, finishGL 48 / 33993 ~71.415 ms, waitGL 0 / 7 ~0.016 ms +XXX[477] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34305 ~71.918 ms, finishGL 48 / 34042 ~71.367 ms, waitGL 0 / 7 ~0.016 ms +XXX[478] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34353 ~71.869 ms, finishGL 48 / 34090 ~71.319 ms, waitGL 0 / 7 ~0.016 ms +XXX[479] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34403 ~71.822 ms, finishGL 48 / 34139 ~71.271 ms, waitGL 0 / 7 ~0.016 ms +XXX[480] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34452 ~71.775 ms, finishGL 48 / 34187 ~71.224 ms, waitGL 0 / 7 ~0.016 ms +XXX[481] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34500 ~71.727 ms, finishGL 48 / 34236 ~71.176 ms, waitGL 0 / 7 ~0.016 ms +XXX[482] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34550 ~71.681 ms, finishGL 48 / 34285 ~71.13 ms, waitGL 0 / 7 ~0.016 ms +XXX[483] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34599 ~71.634 ms, finishGL 48 / 34333 ~71.083 ms, waitGL 0 / 7 ~0.016 ms +XXX[484] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34648 ~71.587 ms, finishGL 48 / 34382 ~71.037 ms, waitGL 0 / 7 ~0.016 ms +XXX[485] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34697 ~71.54 ms, finishGL 48 / 34430 ~70.99 ms, waitGL 0 / 7 ~0.016 ms +XXX[486] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34746 ~71.495 ms, finishGL 48 / 34479 ~70.944 ms, waitGL 0 / 7 ~0.016 ms +XXX[487] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34796 ~71.45 ms, finishGL 49 / 34528 ~70.9 ms, waitGL 0 / 7 ~0.016 ms +XXX[488] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34845 ~71.405 ms, finishGL 49 / 34577 ~70.855 ms, waitGL 0 / 7 ~0.016 ms +XXX[489] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34895 ~71.36 ms, finishGL 48 / 34626 ~70.81 ms, waitGL 0 / 7 ~0.016 ms +XXX[490] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 34945 ~71.317 ms, finishGL 49 / 34675 ~70.767 ms, waitGL 0 / 7 ~0.016 ms +XXX[491] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34995 ~71.274 ms, finishGL 49 / 34725 ~70.723 ms, waitGL 0 / 7 ~0.016 ms +XXX[492] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35045 ~71.231 ms, finishGL 49 / 34775 ~70.68 ms, waitGL 0 / 7 ~0.016 ms +XXX[493] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35095 ~71.187 ms, finishGL 49 / 34824 ~70.637 ms, waitGL 0 / 7 ~0.016 ms +XXX[494] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35144 ~71.143 ms, finishGL 49 / 34873 ~70.593 ms, waitGL 0 / 7 ~0.016 ms +XXX[495] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35195 ~71.101 ms, finishGL 49 / 34922 ~70.551 ms, waitGL 0 / 7 ~0.016 ms +XXX[496] TO 17 ms, lFrame0 0 ms, lFrameX 51 / 35246 ~71.06 ms, finishGL 50 / 34973 ~70.511 ms, waitGL 0 / 7 ~0.016 ms +XXX[497] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35296 ~71.019 ms, finishGL 49 / 35023 ~70.469 ms, waitGL 0 / 8 ~0.016 ms +XXX[498] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35346 ~70.976 ms, finishGL 49 / 35072 ~70.427 ms, waitGL 0 / 8 ~0.016 ms +XXX[499] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35396 ~70.935 ms, finishGL 49 / 35122 ~70.386 ms, waitGL 0 / 8 ~0.016 ms +FrameCount: 600 - FrameRate: 19.0 +XXX[500] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35447 ~70.894 ms, finishGL 49 / 35172 ~70.345 ms, waitGL 0 / 8 ~0.016 ms +XXX[501] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35497 ~70.853 ms, finishGL 49 / 35222 ~70.304 ms, waitGL 0 / 8 ~0.016 ms +XXX[502] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35547 ~70.812 ms, finishGL 50 / 35272 ~70.263 ms, waitGL 0 / 8 ~0.016 ms +XXX[503] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35598 ~70.771 ms, finishGL 49 / 35322 ~70.223 ms, waitGL 0 / 8 ~0.016 ms +XXX[504] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35648 ~70.73 ms, finishGL 49 / 35371 ~70.181 ms, waitGL 0 / 8 ~0.016 ms +XXX[505] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35698 ~70.69 ms, finishGL 49 / 35421 ~70.141 ms, waitGL 0 / 8 ~0.016 ms +XXX[506] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35748 ~70.649 ms, finishGL 49 / 35470 ~70.1 ms, waitGL 0 / 8 ~0.016 ms +XXX[507] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35798 ~70.609 ms, finishGL 49 / 35520 ~70.06 ms, waitGL 0 / 8 ~0.016 ms +XXX[508] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35849 ~70.568 ms, finishGL 49 / 35570 ~70.02 ms, waitGL 0 / 8 ~0.016 ms +XXX[509] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35899 ~70.528 ms, finishGL 49 / 35620 ~69.98 ms, waitGL 0 / 8 ~0.016 ms +XXX[510] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35949 ~70.488 ms, finishGL 49 / 35669 ~69.94 ms, waitGL 0 / 8 ~0.016 ms +XXX[511] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35999 ~70.449 ms, finishGL 49 / 35719 ~69.9 ms, waitGL 0 / 8 ~0.016 ms +XXX[512] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 36050 ~70.41 ms, finishGL 50 / 35769 ~69.862 ms, waitGL 0 / 8 ~0.016 ms +XXX[513] TO 17 ms, lFrame0 0 ms, lFrameX 52 / 36102 ~70.375 ms, finishGL 51 / 35821 ~69.827 ms, waitGL 0 / 8 ~0.016 ms +XXX[514] TO 17 ms, lFrame0 0 ms, lFrameX 51 / 36153 ~70.338 ms, finishGL 50 / 35872 ~69.79 ms, waitGL 0 / 8 ~0.016 ms +XXX[515] TO 17 ms, lFrame0 0 ms, lFrameX 53 / 36207 ~70.306 ms, finishGL 53 / 35925 ~69.758 ms, waitGL 0 / 8 ~0.016 ms +XXX[516] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 36276 ~70.302 ms, finishGL 67 / 35993 ~69.755 ms, waitGL 0 / 8 ~0.016 ms +XXX[517] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 36346 ~70.302 ms, finishGL 69 / 36063 ~69.755 ms, waitGL 0 / 8 ~0.016 ms +XXX[518] TO 17 ms, lFrame0 0 ms, lFrameX 75 / 36421 ~70.311 ms, finishGL 74 / 36137 ~69.764 ms, waitGL 0 / 8 ~0.016 ms +XXX[519] TO 17 ms, lFrame0 0 ms, lFrameX 75 / 36497 ~70.322 ms, finishGL 75 / 36213 ~69.775 ms, waitGL 0 / 8 ~0.016 ms +XXX[520] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 36583 ~70.353 ms, finishGL 85 / 36299 ~69.806 ms, waitGL 0 / 8 ~0.016 ms +XXX[521] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 36666 ~70.377 ms, finishGL 82 / 36381 ~69.83 ms, waitGL 0 / 8 ~0.016 ms +XXX[522] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36749 ~70.401 ms, finishGL 82 / 36464 ~69.855 ms, waitGL 0 / 8 ~0.016 ms +XXX[523] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36833 ~70.426 ms, finishGL 82 / 36547 ~69.879 ms, waitGL 0 / 8 ~0.016 ms +XXX[524] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 36915 ~70.449 ms, finishGL 82 / 36629 ~69.903 ms, waitGL 0 / 8 ~0.016 ms +XXX[525] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36998 ~70.473 ms, finishGL 82 / 36711 ~69.927 ms, waitGL 0 / 8 ~0.016 ms +XXX[526] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37081 ~70.497 ms, finishGL 82 / 36794 ~69.951 ms, waitGL 0 / 8 ~0.016 ms +XXX[527] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37165 ~70.522 ms, finishGL 82 / 36877 ~69.976 ms, waitGL 0 / 8 ~0.016 ms +XXX[528] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37248 ~70.547 ms, finishGL 83 / 36960 ~70.001 ms, waitGL 0 / 8 ~0.016 ms +XXX[529] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37332 ~70.572 ms, finishGL 83 / 37043 ~70.026 ms, waitGL 0 / 8 ~0.016 ms +XXX[530] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37415 ~70.595 ms, finishGL 82 / 37126 ~70.049 ms, waitGL 0 / 8 ~0.016 ms +XXX[531] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37498 ~70.619 ms, finishGL 82 / 37209 ~70.073 ms, waitGL 0 / 8 ~0.016 ms +XXX[532] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37582 ~70.643 ms, finishGL 82 / 37291 ~70.097 ms, waitGL 0 / 8 ~0.016 ms +XXX[533] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37665 ~70.667 ms, finishGL 82 / 37374 ~70.121 ms, waitGL 0 / 8 ~0.016 ms +XXX[534] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37749 ~70.691 ms, finishGL 82 / 37457 ~70.145 ms, waitGL 0 / 8 ~0.016 ms +XXX[535] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37832 ~70.714 ms, finishGL 82 / 37540 ~70.168 ms, waitGL 0 / 8 ~0.016 ms +XXX[536] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 37914 ~70.735 ms, finishGL 81 / 37621 ~70.19 ms, waitGL 0 / 8 ~0.016 ms +XXX[537] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 37997 ~70.757 ms, finishGL 82 / 37704 ~70.212 ms, waitGL 0 / 8 ~0.016 ms +XXX[538] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38080 ~70.78 ms, finishGL 82 / 37786 ~70.235 ms, waitGL 0 / 8 ~0.016 ms +XXX[539] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 38162 ~70.802 ms, finishGL 82 / 37868 ~70.257 ms, waitGL 0 / 8 ~0.016 ms +XXX[540] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 38245 ~70.825 ms, finishGL 82 / 37951 ~70.279 ms, waitGL 0 / 8 ~0.016 ms +XXX[541] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38329 ~70.848 ms, finishGL 82 / 38034 ~70.303 ms, waitGL 0 / 8 ~0.016 ms +XXX[542] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38412 ~70.871 ms, finishGL 82 / 38116 ~70.325 ms, waitGL 0 / 8 ~0.016 ms +XXX[543] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38495 ~70.894 ms, finishGL 83 / 38199 ~70.349 ms, waitGL 0 / 8 ~0.016 ms +XXX[544] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38579 ~70.917 ms, finishGL 82 / 38282 ~70.372 ms, waitGL 0 / 8 ~0.016 ms +XXX[545] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38662 ~70.94 ms, finishGL 82 / 38365 ~70.395 ms, waitGL 0 / 8 ~0.016 ms +XXX[546] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38745 ~70.962 ms, finishGL 82 / 38447 ~70.417 ms, waitGL 0 / 8 ~0.016 ms +XXX[547] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 38829 ~70.986 ms, finishGL 83 / 38531 ~70.441 ms, waitGL 0 / 8 ~0.016 ms +XXX[548] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38913 ~71.01 ms, finishGL 83 / 38614 ~70.465 ms, waitGL 0 / 8 ~0.016 ms +XXX[549] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 38997 ~71.034 ms, finishGL 83 / 38698 ~70.488 ms, waitGL 0 / 8 ~0.016 ms +XXX[550] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 39081 ~71.057 ms, finishGL 83 / 38781 ~70.512 ms, waitGL 0 / 8 ~0.016 ms +XXX[551] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 39165 ~71.08 ms, finishGL 83 / 38864 ~70.535 ms, waitGL 0 / 8 ~0.016 ms +XXX[552] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39248 ~71.101 ms, finishGL 82 / 38947 ~70.556 ms, waitGL 0 / 8 ~0.016 ms +XXX[553] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 39331 ~71.123 ms, finishGL 82 / 39029 ~70.578 ms, waitGL 0 / 8 ~0.016 ms +XXX[554] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39413 ~71.143 ms, finishGL 81 / 39111 ~70.598 ms, waitGL 0 / 8 ~0.016 ms +XXX[555] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39495 ~71.163 ms, finishGL 82 / 39193 ~70.619 ms, waitGL 0 / 8 ~0.016 ms +XXX[556] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39578 ~71.183 ms, finishGL 81 / 39275 ~70.639 ms, waitGL 0 / 8 ~0.016 ms +XXX[557] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39660 ~71.203 ms, finishGL 81 / 39357 ~70.659 ms, waitGL 0 / 8 ~0.016 ms +XXX[558] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39742 ~71.223 ms, finishGL 81 / 39438 ~70.678 ms, waitGL 0 / 9 ~0.016 ms +XXX[559] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39824 ~71.243 ms, finishGL 81 / 39520 ~70.698 ms, waitGL 0 / 9 ~0.016 ms +XXX[560] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39907 ~71.263 ms, finishGL 82 / 39603 ~70.719 ms, waitGL 0 / 9 ~0.016 ms +XXX[561] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 39987 ~71.279 ms, finishGL 79 / 39682 ~70.735 ms, waitGL 0 / 9 ~0.016 ms +XXX[562] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 40069 ~71.297 ms, finishGL 80 / 39763 ~70.753 ms, waitGL 0 / 9 ~0.016 ms +XXX[563] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 40150 ~71.315 ms, finishGL 80 / 39844 ~70.771 ms, waitGL 0 / 9 ~0.016 ms +XXX[564] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 40231 ~71.332 ms, finishGL 80 / 39925 ~70.789 ms, waitGL 0 / 9 ~0.016 ms +XXX[565] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 40314 ~71.352 ms, finishGL 82 / 40007 ~70.809 ms, waitGL 0 / 9 ~0.016 ms +XXX[566] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 40378 ~71.339 ms, finishGL 63 / 40070 ~70.796 ms, waitGL 0 / 9 ~0.016 ms +XXX[567] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40444 ~71.329 ms, finishGL 65 / 40135 ~70.786 ms, waitGL 0 / 9 ~0.016 ms +XXX[568] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40509 ~71.319 ms, finishGL 64 / 40200 ~70.776 ms, waitGL 0 / 9 ~0.016 ms +XXX[569] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40575 ~71.309 ms, finishGL 65 / 40266 ~70.766 ms, waitGL 0 / 9 ~0.016 ms +XXX[570] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40640 ~71.299 ms, finishGL 65 / 40331 ~70.756 ms, waitGL 0 / 9 ~0.016 ms +XXX[571] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 40707 ~71.291 ms, finishGL 65 / 40397 ~70.748 ms, waitGL 0 / 9 ~0.016 ms +XXX[572] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40773 ~71.281 ms, finishGL 65 / 40462 ~70.738 ms, waitGL 0 / 9 ~0.016 ms +XXX[573] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40838 ~71.271 ms, finishGL 65 / 40527 ~70.728 ms, waitGL 0 / 9 ~0.016 ms +XXX[574] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 40905 ~71.264 ms, finishGL 66 / 40594 ~70.721 ms, waitGL 0 / 9 ~0.016 ms +XXX[575] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 40973 ~71.257 ms, finishGL 66 / 40660 ~70.714 ms, waitGL 0 / 9 ~0.016 ms +XXX[576] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 41039 ~71.249 ms, finishGL 66 / 40727 ~70.706 ms, waitGL 0 / 9 ~0.016 ms +XXX[577] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 41107 ~71.243 ms, finishGL 66 / 40794 ~70.7 ms, waitGL 0 / 9 ~0.016 ms +XXX[578] TO 17 ms, lFrame0 0 ms, lFrameX 69 / 41176 ~71.24 ms, finishGL 69 / 40863 ~70.697 ms, waitGL 0 / 9 ~0.016 ms +XXX[579] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 41246 ~71.238 ms, finishGL 69 / 40932 ~70.695 ms, waitGL 0 / 9 ~0.016 ms +XXX[580] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 41336 ~71.269 ms, finishGL 88 / 41021 ~70.726 ms, waitGL 0 / 9 ~0.016 ms +XXX[581] TO 17 ms, lFrame0 0 ms, lFrameX 87 / 41424 ~71.298 ms, finishGL 87 / 41109 ~70.755 ms, waitGL 0 / 9 ~0.016 ms +XXX[582] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 41510 ~71.323 ms, finishGL 85 / 41194 ~70.78 ms, waitGL 0 / 9 ~0.016 ms +XXX[583] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 41594 ~71.345 ms, finishGL 83 / 41278 ~70.803 ms, waitGL 0 / 9 ~0.016 ms +XXX[584] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 41676 ~71.364 ms, finishGL 81 / 41360 ~70.822 ms, waitGL 0 / 9 ~0.016 ms +XXX[585] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 41757 ~71.38 ms, finishGL 80 / 41440 ~70.838 ms, waitGL 0 / 9 ~0.016 ms +XXX[586] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 41839 ~71.398 ms, finishGL 81 / 41521 ~70.856 ms, waitGL 0 / 9 ~0.016 ms +XXX[587] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 41922 ~71.417 ms, finishGL 82 / 41604 ~70.875 ms, waitGL 0 / 9 ~0.016 ms +XXX[588] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 42004 ~71.436 ms, finishGL 81 / 41686 ~70.894 ms, waitGL 0 / 9 ~0.016 ms +XXX[589] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42088 ~71.456 ms, finishGL 82 / 41769 ~70.915 ms, waitGL 0 / 9 ~0.016 ms +XXX[590] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 42170 ~71.475 ms, finishGL 81 / 41851 ~70.934 ms, waitGL 0 / 9 ~0.016 ms +XXX[591] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42253 ~71.495 ms, finishGL 82 / 41933 ~70.953 ms, waitGL 0 / 9 ~0.016 ms +XXX[592] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42336 ~71.514 ms, finishGL 82 / 42016 ~70.973 ms, waitGL 0 / 9 ~0.016 ms +XXX[593] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42420 ~71.535 ms, finishGL 83 / 42099 ~70.994 ms, waitGL 0 / 9 ~0.016 ms +XXX[594] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42503 ~71.555 ms, finishGL 82 / 42182 ~71.013 ms, waitGL 0 / 9 ~0.016 ms +XXX[595] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 42588 ~71.577 ms, finishGL 84 / 42266 ~71.035 ms, waitGL 0 / 9 ~0.016 ms +XXX[596] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 42672 ~71.597 ms, finishGL 83 / 42349 ~71.056 ms, waitGL 0 / 9 ~0.016 ms +XXX[597] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42755 ~71.617 ms, finishGL 82 / 42432 ~71.076 ms, waitGL 0 / 9 ~0.016 ms +XXX[598] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42839 ~71.638 ms, finishGL 83 / 42516 ~71.097 ms, waitGL 0 / 9 ~0.016 ms +XXX[599] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42922 ~71.657 ms, finishGL 82 / 42598 ~71.116 ms, waitGL 0 / 9 ~0.016 ms +XXX[600] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 43004 ~71.673 ms, finishGL 80 / 42679 ~71.132 ms, waitGL 0 / 9 ~0.016 ms +XXX[601] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 43085 ~71.689 ms, finishGL 81 / 42760 ~71.149 ms, waitGL 0 / 9 ~0.016 ms +XXX[602] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 43167 ~71.707 ms, finishGL 81 / 42842 ~71.166 ms, waitGL 0 / 9 ~0.016 ms +XXX[603] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 43250 ~71.725 ms, finishGL 82 / 42924 ~71.185 ms, waitGL 0 / 9 ~0.016 ms +XXX[604] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 43333 ~71.743 ms, finishGL 82 / 43006 ~71.203 ms, waitGL 0 / 9 ~0.016 ms +XXX[605] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 43416 ~71.762 ms, finishGL 82 / 43089 ~71.222 ms, waitGL 0 / 9 ~0.016 ms diff --git a/src/test/com/jogamp/opengl/test/bugs/Bug735.OSX.CALayer.Perf.logs/aaaa-m2-sync0-finish-wait.log b/src/test/com/jogamp/opengl/test/bugs/Bug735.OSX.CALayer.Perf.logs/aaaa-m2-sync0-finish-wait.log new file mode 100644 index 000000000..3f9bb251d --- /dev/null +++ b/src/test/com/jogamp/opengl/test/bugs/Bug735.OSX.CALayer.Perf.logs/aaaa-m2-sync0-finish-wait.log @@ -0,0 +1,751 @@ +NSZombieEnabled +NSTraceEvents YES +OBJC_PRINT_EXCEPTIONS +/usr/bin/java +java version "1.6.0_37" +Java(TM) SE Runtime Environment (build 1.6.0_37-b06-434-11M3909) +Java HotSpot(TM) 64-Bit Server VM (build 20.12-b01-434, mixed mode) +LD_LIBRARY_PATH :../../gluegen/make/../build-macosx/obj:../build-macosx/lib +LIBXCB_ALLOW_SLOPPY_LOCK: +LIBGL_DRIVERS_PATH: +LIBGL_DEBUG: +LIBGL_ALWAYS_INDIRECT: +LIBGL_ALWAYS_SOFTWARE: +SWT_CLASSPATH: ../build-macosx/../make/lib/swt/cocoa-macosx-x86_64/swt-debug.jar +/usr/bin/java -d64 -time 100000 -vsync 0 +CLASSPATH .:../../gluegen/make/../build-macosx/gluegen-rt.jar:../build-macosx/jar/jogl-all.jar:../build-macosx/jar/jogl-test.jar:../build-macosx/../make/lib/swt/cocoa-macosx-x86_64/swt-debug.jar:../../gluegen/make/../make/lib/junit.jar:/opt-share/apache-ant/lib/ant.jar:/opt-share/apache-ant/lib/ant-junit.jar +CLASSPATH .:../../gluegen/make/../build-macosx/gluegen-rt.jar:../build-macosx/jar/jogl-all.jar:../build-macosx/jar/jogl-test.jar:../build-macosx/../make/lib/swt/cocoa-macosx-x86_64/swt-debug.jar:../../gluegen/make/../make/lib/junit.jar:/opt-share/apache-ant/lib/ant.jar:/opt-share/apache-ant/lib/ant-junit.jar + +Test Start: com.jogamp.opengl.test.bugs.Bug735Inv3AppletAWT -time 100000 -vsync 0 + +/usr/bin/java -d64 -Djava.awt.headless=false -Djogl.debug.calayer.SwapM2 com.jogamp.opengl.test.bugs.Bug735Inv3AppletAWT -time 100000 -vsync 0 +swapInterval 0 +exclusiveContext false +SWAP_M1 false +SWAP_M2 true +NewtCanvasAWT.attachNewtChild.2: size 500x268 +Thread[main-Display-.macosx_nil-1-EDT-1,5,main] LandscapeES2.init ... +LandscapeES2 init on Thread[main-Display-.macosx_nil-1-EDT-1,5,main] +Chosen GLCapabilities: GLCaps[rgba 8/8/8/0, opaque, accum-rgba 0/0/0/0, dp/st/ms 24/0/0, dbl, mono , hw, GLProfile[GL2/GL2.hw], offscr[fbo]] +INIT GL IS: jogamp.opengl.gl4.GL4bcImpl +GL_VENDOR: NVIDIA Corporation +GL_RENDERER: NVIDIA GeForce 320M OpenGL Engine +GL_VERSION: 2.1 NVIDIA-7.32.12 +GL GLSL: true, has-compiler-func: true, version 1.20, 1.20.0 +GL FBO: basic true, full true +GL Profile: GLProfile[GL2/GL2.hw] +GL Renderer Quirks:[NoOffscreenBitmap] +GL:jogamp.opengl.gl4.GL4bcImpl@3e018c74, 2.1 (hardware) - 2.1 NVIDIA-7.32.12 +Thread[main-Display-.macosx_nil-1-EDT-1,5,main] LandscapeES2.init FIN +Thread[main-Display-.macosx_nil-1-EDT-1,5,main] LandscapeES2.reshape 0/0 500x268, swapInterval 0, drawable 0x7fc3498bf2c0 +Thread[AWT-EventQueue-0,6,main] LandscapeES2.reshape 0/0 500x268, swapInterval 0, drawable 0x7fc3498bf2c0 +XXX[1] TO 17 ms, lFrame0 110 ms, lFrameX 848 / 848 ~848.637 ms, finishGL 736 / 736 ~736.829 ms, waitGL 1 / 1 ~1.296 ms +XXX[2] TO 17 ms, lFrame0 81 ms, lFrameX 169 / 1017 ~508.969 ms, finishGL 87 / 824 ~412.402 ms, waitGL 0 / 1 ~0.654 ms +XXX[3] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 1099 ~366.547 ms, finishGL 80 / 905 ~301.882 ms, waitGL 0 / 1 ~0.441 ms +XXX[4] TO 17 ms, lFrame0 1 ms, lFrameX 86 / 1185 ~296.444 ms, finishGL 84 / 990 ~247.652 ms, waitGL 0 / 1 ~0.334 ms +XXX[5] TO 17 ms, lFrame0 2 ms, lFrameX 83 / 1269 ~253.857 ms, finishGL 81 / 1071 ~214.388 ms, waitGL 0 / 1 ~0.27 ms +XXX[6] TO 17 ms, lFrame0 2 ms, lFrameX 82 / 1351 ~225.33 ms, finishGL 80 / 1152 ~192.095 ms, waitGL 0 / 1 ~0.227 ms +XXX[7] TO 17 ms, lFrame0 2 ms, lFrameX 83 / 1435 ~205.021 ms, finishGL 80 / 1233 ~176.15 ms, waitGL 0 / 1 ~0.196 ms +XXX[8] TO 17 ms, lFrame0 0 ms, lFrameX 97 / 1532 ~191.621 ms, finishGL 97 / 1330 ~166.297 ms, waitGL 0 / 1 ~0.174 ms +XXX[9] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 1615 ~179.507 ms, finishGL 81 / 1412 ~156.923 ms, waitGL 0 / 1 ~0.156 ms +XXX[10] TO 17 ms, lFrame0 1 ms, lFrameX 79 / 1694 ~169.458 ms, finishGL 77 / 1490 ~149.019 ms, waitGL 0 / 1 ~0.141 ms +XXX[11] TO 17 ms, lFrame0 0 ms, lFrameX 103 / 1798 ~163.463 ms, finishGL 102 / 1592 ~144.812 ms, waitGL 0 / 1 ~0.129 ms +XXX[12] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 1881 ~156.761 ms, finishGL 82 / 1675 ~139.611 ms, waitGL 0 / 1 ~0.12 ms +XXX[13] TO 17 ms, lFrame0 0 ms, lFrameX 77 / 1958 ~150.688 ms, finishGL 76 / 1752 ~134.783 ms, waitGL 0 / 1 ~0.111 ms +XXX[14] TO 17 ms, lFrame0 0 ms, lFrameX 87 / 2046 ~146.155 ms, finishGL 86 / 1838 ~131.346 ms, waitGL 0 / 1 ~0.104 ms +XXX[15] TO 17 ms, lFrame0 0 ms, lFrameX 98 / 2144 ~142.991 ms, finishGL 98 / 1936 ~129.13 ms, waitGL 0 / 1 ~0.098 ms +XXX[16] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 2227 ~139.237 ms, finishGL 81 / 2018 ~126.184 ms, waitGL 0 / 1 ~0.093 ms +XXX[17] TO 17 ms, lFrame0 1 ms, lFrameX 75 / 2302 ~135.468 ms, finishGL 74 / 2093 ~123.12 ms, waitGL 0 / 1 ~0.089 ms +XXX[18] TO 17 ms, lFrame0 0 ms, lFrameX 107 / 2410 ~133.895 ms, finishGL 106 / 2199 ~122.184 ms, waitGL 0 / 1 ~0.085 ms +XXX[19] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 2493 ~131.251 ms, finishGL 82 / 2282 ~120.108 ms, waitGL 0 / 1 ~0.081 ms +XXX[20] TO 17 ms, lFrame0 0 ms, lFrameX 75 / 2569 ~128.458 ms, finishGL 74 / 2356 ~117.844 ms, waitGL 0 / 1 ~0.077 ms +XXX[21] TO 17 ms, lFrame0 0 ms, lFrameX 107 / 2676 ~127.46 ms, finishGL 107 / 2463 ~117.328 ms, waitGL 0 / 1 ~0.074 ms +XXX[22] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 2760 ~125.462 ms, finishGL 83 / 2546 ~115.768 ms, waitGL 0 / 1 ~0.072 ms +XXX[23] TO 17 ms, lFrame0 0 ms, lFrameX 75 / 2836 ~123.307 ms, finishGL 75 / 2622 ~114.004 ms, waitGL 0 / 1 ~0.069 ms +XXX[24] TO 17 ms, lFrame0 0 ms, lFrameX 105 / 2941 ~122.558 ms, finishGL 104 / 2726 ~113.619 ms, waitGL 0 / 1 ~0.067 ms +XXX[25] TO 17 ms, lFrame0 0 ms, lFrameX 79 / 3020 ~120.817 ms, finishGL 78 / 2805 ~112.217 ms, waitGL 0 / 1 ~0.065 ms +XXX[26] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 3090 ~118.863 ms, finishGL 69 / 2875 ~110.579 ms, waitGL 0 / 1 ~0.063 ms +XXX[27] TO 17 ms, lFrame0 0 ms, lFrameX 79 / 3169 ~117.398 ms, finishGL 78 / 2953 ~109.402 ms, waitGL 0 / 1 ~0.061 ms +XXX[28] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 3251 ~116.14 ms, finishGL 81 / 3035 ~108.413 ms, waitGL 0 / 1 ~0.06 ms +XXX[29] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 3334 ~114.972 ms, finishGL 81 / 3117 ~107.495 ms, waitGL 0 / 1 ~0.058 ms +XXX[30] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 3416 ~113.876 ms, finishGL 81 / 3199 ~106.633 ms, waitGL 0 / 1 ~0.057 ms +XXX[31] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 3498 ~112.869 ms, finishGL 82 / 3281 ~105.845 ms, waitGL 0 / 1 ~0.055 ms +XXX[32] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 3581 ~111.907 ms, finishGL 81 / 3362 ~105.085 ms, waitGL 0 / 1 ~0.054 ms +XXX[33] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 3646 ~110.507 ms, finishGL 64 / 3427 ~103.87 ms, waitGL 0 / 1 ~0.053 ms +XXX[34] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 3713 ~109.219 ms, finishGL 66 / 3493 ~102.763 ms, waitGL 0 / 1 ~0.052 ms +XXX[35] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 3779 ~107.986 ms, finishGL 65 / 3559 ~101.701 ms, waitGL 0 / 1 ~0.051 ms +XXX[36] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 3845 ~106.813 ms, finishGL 65 / 3624 ~100.684 ms, waitGL 0 / 1 ~0.05 ms +XXX[37] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 3911 ~105.716 ms, finishGL 65 / 3690 ~99.739 ms, waitGL 0 / 1 ~0.049 ms +XXX[38] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 3977 ~104.665 ms, finishGL 65 / 3755 ~98.825 ms, waitGL 0 / 1 ~0.048 ms +XXX[39] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 4044 ~103.71 ms, finishGL 66 / 3822 ~98.008 ms, waitGL 0 / 1 ~0.047 ms +XXX[40] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4111 ~102.777 ms, finishGL 65 / 3888 ~97.206 ms, waitGL 0 / 1 ~0.047 ms +XXX[41] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 4176 ~101.867 ms, finishGL 65 / 3953 ~96.42 ms, waitGL 0 / 1 ~0.046 ms +XXX[42] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4242 ~101.018 ms, finishGL 65 / 4018 ~95.689 ms, waitGL 0 / 1 ~0.045 ms +XXX[43] TO 17 ms, lFrame0 7 ms, lFrameX 68 / 4311 ~100.267 ms, finishGL 61 / 4080 ~94.884 ms, waitGL 0 / 1 ~0.044 ms +XXX[44] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 4375 ~99.44 ms, finishGL 63 / 4143 ~94.168 ms, waitGL 0 / 1 ~0.044 ms +XXX[45] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 4441 ~98.703 ms, finishGL 64 / 4208 ~93.516 ms, waitGL 0 / 1 ~0.043 ms +XXX[46] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4508 ~98.0 ms, finishGL 65 / 4274 ~92.914 ms, waitGL 0 / 1 ~0.042 ms +XXX[47] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4574 ~97.329 ms, finishGL 65 / 4340 ~92.341 ms, waitGL 0 / 1 ~0.042 ms +XXX[48] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4640 ~96.682 ms, finishGL 65 / 4405 ~91.788 ms, waitGL 0 / 2 ~0.041 ms +XXX[49] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4707 ~96.066 ms, finishGL 66 / 4471 ~91.262 ms, waitGL 0 / 2 ~0.041 ms +XXX[50] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4773 ~95.471 ms, finishGL 65 / 4537 ~90.753 ms, waitGL 0 / 2 ~0.04 ms +XXX[51] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4839 ~94.895 ms, finishGL 65 / 4603 ~90.259 ms, waitGL 0 / 2 ~0.04 ms +XXX[52] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4905 ~94.343 ms, finishGL 65 / 4668 ~89.787 ms, waitGL 0 / 2 ~0.039 ms +XXX[53] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 4970 ~93.788 ms, finishGL 64 / 4733 ~89.308 ms, waitGL 0 / 2 ~0.039 ms +XXX[54] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5037 ~93.294 ms, finishGL 66 / 4799 ~88.885 ms, waitGL 0 / 2 ~0.038 ms +XXX[55] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5104 ~92.8 ms, finishGL 65 / 4865 ~88.462 ms, waitGL 0 / 2 ~0.038 ms +XXX[56] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5170 ~92.332 ms, finishGL 66 / 4931 ~88.063 ms, waitGL 0 / 2 ~0.037 ms +XXX[57] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5236 ~91.871 ms, finishGL 65 / 4997 ~87.668 ms, waitGL 0 / 2 ~0.037 ms +XXX[58] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5303 ~91.442 ms, finishGL 66 / 5063 ~87.303 ms, waitGL 0 / 2 ~0.037 ms +XXX[59] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5369 ~91.015 ms, finishGL 65 / 5129 ~86.938 ms, waitGL 0 / 2 ~0.036 ms +XXX[60] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5436 ~90.614 ms, finishGL 66 / 5195 ~86.598 ms, waitGL 0 / 2 ~0.036 ms +XXX[61] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5503 ~90.224 ms, finishGL 66 / 5262 ~86.266 ms, waitGL 0 / 2 ~0.036 ms +XXX[62] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5570 ~89.839 ms, finishGL 65 / 5327 ~85.933 ms, waitGL 0 / 2 ~0.035 ms +XXX[63] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5637 ~89.477 ms, finishGL 66 / 5394 ~85.625 ms, waitGL 0 / 2 ~0.035 ms +XXX[64] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5703 ~89.118 ms, finishGL 66 / 5460 ~85.319 ms, waitGL 0 / 2 ~0.035 ms +XXX[65] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5770 ~88.771 ms, finishGL 65 / 5526 ~85.02 ms, waitGL 0 / 2 ~0.035 ms +XXX[66] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5836 ~88.435 ms, finishGL 66 / 5592 ~84.734 ms, waitGL 0 / 2 ~0.034 ms +XXX[67] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5904 ~88.122 ms, finishGL 66 / 5659 ~84.469 ms, waitGL 0 / 2 ~0.034 ms +XXX[68] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5970 ~87.805 ms, finishGL 66 / 5725 ~84.199 ms, waitGL 0 / 2 ~0.034 ms +XXX[69] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6037 ~87.498 ms, finishGL 66 / 5791 ~83.937 ms, waitGL 0 / 2 ~0.033 ms +XXX[70] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6104 ~87.206 ms, finishGL 66 / 5858 ~83.689 ms, waitGL 0 / 2 ~0.033 ms +XXX[71] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6171 ~86.919 ms, finishGL 66 / 5924 ~83.445 ms, waitGL 0 / 2 ~0.033 ms +XXX[72] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6237 ~86.636 ms, finishGL 65 / 5990 ~83.201 ms, waitGL 0 / 2 ~0.033 ms +XXX[73] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6303 ~86.354 ms, finishGL 65 / 6056 ~82.96 ms, waitGL 0 / 2 ~0.032 ms +XXX[74] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6370 ~86.081 ms, finishGL 65 / 6121 ~82.725 ms, waitGL 0 / 2 ~0.032 ms +XXX[75] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 6435 ~85.806 ms, finishGL 64 / 6186 ~82.485 ms, waitGL 0 / 2 ~0.032 ms +XXX[76] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6501 ~85.551 ms, finishGL 65 / 6251 ~82.261 ms, waitGL 0 / 2 ~0.032 ms +XXX[77] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6567 ~85.298 ms, finishGL 65 / 6317 ~82.044 ms, waitGL 0 / 2 ~0.032 ms +XXX[78] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6634 ~85.057 ms, finishGL 66 / 6383 ~81.839 ms, waitGL 0 / 2 ~0.031 ms +XXX[79] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6701 ~84.826 ms, finishGL 66 / 6449 ~81.642 ms, waitGL 0 / 2 ~0.031 ms +XXX[80] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6768 ~84.601 ms, finishGL 66 / 6516 ~81.452 ms, waitGL 0 / 2 ~0.031 ms +XXX[81] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6834 ~84.376 ms, finishGL 65 / 6582 ~81.259 ms, waitGL 0 / 2 ~0.031 ms +XXX[82] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6901 ~84.162 ms, finishGL 66 / 6648 ~81.077 ms, waitGL 0 / 2 ~0.031 ms +XXX[83] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6968 ~83.956 ms, finishGL 66 / 6714 ~80.903 ms, waitGL 0 / 2 ~0.031 ms +XXX[84] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 7035 ~83.759 ms, finishGL 66 / 6781 ~80.737 ms, waitGL 0 / 2 ~0.03 ms +XXX[85] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7102 ~83.556 ms, finishGL 65 / 6847 ~80.563 ms, waitGL 0 / 2 ~0.03 ms +XXX[86] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7168 ~83.355 ms, finishGL 65 / 6913 ~80.391 ms, waitGL 0 / 2 ~0.03 ms +XXX[87] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 7235 ~83.167 ms, finishGL 66 / 6980 ~80.23 ms, waitGL 0 / 2 ~0.03 ms +XXX[88] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7302 ~82.979 ms, finishGL 66 / 7046 ~80.07 ms, waitGL 0 / 2 ~0.03 ms +XXX[89] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7368 ~82.791 ms, finishGL 65 / 7111 ~79.909 ms, waitGL 0 / 2 ~0.029 ms +XXX[90] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 7435 ~82.616 ms, finishGL 66 / 7178 ~79.761 ms, waitGL 0 / 2 ~0.029 ms +XXX[91] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 7501 ~82.432 ms, finishGL 65 / 7243 ~79.603 ms, waitGL 0 / 2 ~0.029 ms +XXX[92] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7567 ~82.258 ms, finishGL 65 / 7309 ~79.454 ms, waitGL 0 / 2 ~0.029 ms +XXX[93] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7634 ~82.088 ms, finishGL 65 / 7375 ~79.309 ms, waitGL 0 / 2 ~0.029 ms +XXX[94] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7700 ~81.921 ms, finishGL 65 / 7441 ~79.167 ms, waitGL 0 / 2 ~0.029 ms +XXX[95] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7767 ~81.758 ms, finishGL 65 / 7507 ~79.028 ms, waitGL 0 / 2 ~0.029 ms +XXX[96] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7833 ~81.601 ms, finishGL 66 / 7573 ~78.893 ms, waitGL 0 / 2 ~0.028 ms +XXX[97] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7899 ~81.443 ms, finishGL 65 / 7639 ~78.758 ms, waitGL 0 / 2 ~0.028 ms +XXX[98] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 7965 ~81.282 ms, finishGL 65 / 7704 ~78.62 ms, waitGL 0 / 2 ~0.028 ms +XXX[99] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8031 ~81.129 ms, finishGL 65 / 7770 ~78.486 ms, waitGL 0 / 2 ~0.028 ms +XXX[1] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 66 ~66.634 ms, finishGL 66 / 66 ~66.169 ms, waitGL 0 / 0 ~0.015 ms +XXX[2] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 132 ~66.347 ms, finishGL 65 / 131 ~65.882 ms, waitGL 0 / 0 ~0.018 ms +XXX[3] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 198 ~66.312 ms, finishGL 65 / 197 ~65.839 ms, waitGL 0 / 0 ~0.017 ms +XXX[4] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 265 ~66.27 ms, finishGL 65 / 263 ~65.792 ms, waitGL 0 / 0 ~0.016 ms +XXX[5] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 331 ~66.372 ms, finishGL 66 / 329 ~65.865 ms, waitGL 0 / 0 ~0.016 ms +XXX[6] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 397 ~66.297 ms, finishGL 65 / 394 ~65.793 ms, waitGL 0 / 0 ~0.015 ms +XXX[7] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 464 ~66.324 ms, finishGL 65 / 460 ~65.82 ms, waitGL 0 / 0 ~0.015 ms +XXX[8] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 530 ~66.269 ms, finishGL 65 / 526 ~65.77 ms, waitGL 0 / 0 ~0.016 ms +XXX[9] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 597 ~66.378 ms, finishGL 66 / 592 ~65.88 ms, waitGL 0 / 0 ~0.016 ms +XXX[10] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 663 ~66.399 ms, finishGL 66 / 659 ~65.904 ms, waitGL 0 / 0 ~0.015 ms +XXX[11] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 732 ~66.55 ms, finishGL 67 / 726 ~66.051 ms, waitGL 0 / 0 ~0.015 ms +XXX[12] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 798 ~66.573 ms, finishGL 66 / 792 ~66.075 ms, waitGL 0 / 0 ~0.015 ms +XXX[13] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 864 ~66.529 ms, finishGL 65 / 858 ~66.03 ms, waitGL 0 / 0 ~0.015 ms +XXX[14] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 930 ~66.465 ms, finishGL 65 / 923 ~65.966 ms, waitGL 0 / 0 ~0.015 ms +XXX[15] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 996 ~66.452 ms, finishGL 65 / 989 ~65.954 ms, waitGL 0 / 0 ~0.015 ms +XXX[16] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1063 ~66.44 ms, finishGL 65 / 1055 ~65.943 ms, waitGL 0 / 0 ~0.015 ms +XXX[17] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1129 ~66.447 ms, finishGL 66 / 1121 ~65.95 ms, waitGL 0 / 0 ~0.016 ms +XXX[18] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 1195 ~66.422 ms, finishGL 65 / 1186 ~65.925 ms, waitGL 0 / 0 ~0.015 ms +XXX[19] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1262 ~66.442 ms, finishGL 66 / 1252 ~65.946 ms, waitGL 0 / 0 ~0.015 ms +FrameCount: 120 - FrameRate: 16.0 +XXX[20] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 1329 ~66.479 ms, finishGL 66 / 1319 ~65.976 ms, waitGL 0 / 0 ~0.015 ms +XXX[21] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1396 ~66.484 ms, finishGL 66 / 1385 ~65.981 ms, waitGL 0 / 0 ~0.015 ms +XXX[22] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 1463 ~66.515 ms, finishGL 66 / 1452 ~66.013 ms, waitGL 0 / 0 ~0.015 ms +XXX[23] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1530 ~66.53 ms, finishGL 66 / 1518 ~66.028 ms, waitGL 0 / 0 ~0.015 ms +XXX[24] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 1597 ~66.567 ms, finishGL 66 / 1585 ~66.065 ms, waitGL 0 / 0 ~0.015 ms +XXX[25] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 1664 ~66.589 ms, finishGL 66 / 1652 ~66.087 ms, waitGL 0 / 0 ~0.015 ms +XXX[26] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1731 ~66.587 ms, finishGL 66 / 1718 ~66.086 ms, waitGL 0 / 0 ~0.015 ms +XXX[27] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1798 ~66.595 ms, finishGL 66 / 1784 ~66.095 ms, waitGL 0 / 0 ~0.015 ms +XXX[28] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 1865 ~66.624 ms, finishGL 66 / 1851 ~66.124 ms, waitGL 0 / 0 ~0.015 ms +XXX[29] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 1930 ~66.58 ms, finishGL 64 / 1916 ~66.081 ms, waitGL 0 / 0 ~0.015 ms +XXX[30] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 1998 ~66.6 ms, finishGL 66 / 1983 ~66.101 ms, waitGL 0 / 0 ~0.015 ms +XXX[31] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2064 ~66.593 ms, finishGL 65 / 2048 ~66.095 ms, waitGL 0 / 0 ~0.015 ms +XXX[32] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2130 ~66.585 ms, finishGL 65 / 2114 ~66.085 ms, waitGL 0 / 0 ~0.015 ms +XXX[33] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2197 ~66.581 ms, finishGL 65 / 2180 ~66.082 ms, waitGL 0 / 0 ~0.015 ms +XXX[34] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2263 ~66.576 ms, finishGL 65 / 2246 ~66.078 ms, waitGL 0 / 0 ~0.015 ms +XXX[35] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2330 ~66.571 ms, finishGL 65 / 2312 ~66.073 ms, waitGL 0 / 0 ~0.015 ms +XXX[36] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2396 ~66.576 ms, finishGL 66 / 2378 ~66.077 ms, waitGL 0 / 0 ~0.015 ms +XXX[37] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 2462 ~66.558 ms, finishGL 65 / 2444 ~66.058 ms, waitGL 0 / 0 ~0.015 ms +XXX[38] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2529 ~66.564 ms, finishGL 66 / 2510 ~66.066 ms, waitGL 0 / 0 ~0.015 ms +XXX[39] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2596 ~66.572 ms, finishGL 66 / 2576 ~66.074 ms, waitGL 0 / 0 ~0.015 ms +XXX[40] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2662 ~66.564 ms, finishGL 65 / 2642 ~66.067 ms, waitGL 0 / 0 ~0.015 ms +XXX[41] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2728 ~66.551 ms, finishGL 65 / 2708 ~66.054 ms, waitGL 0 / 0 ~0.015 ms +XXX[42] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 2795 ~66.567 ms, finishGL 66 / 2774 ~66.07 ms, waitGL 0 / 0 ~0.015 ms +XXX[43] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2861 ~66.558 ms, finishGL 65 / 2840 ~66.061 ms, waitGL 0 / 0 ~0.015 ms +XXX[44] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2928 ~66.556 ms, finishGL 65 / 2906 ~66.059 ms, waitGL 0 / 0 ~0.015 ms +XXX[45] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2994 ~66.547 ms, finishGL 65 / 2972 ~66.05 ms, waitGL 0 / 0 ~0.015 ms +XXX[46] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 3060 ~66.525 ms, finishGL 65 / 3037 ~66.028 ms, waitGL 0 / 0 ~0.015 ms +XXX[47] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 3125 ~66.498 ms, finishGL 64 / 3101 ~65.999 ms, waitGL 0 / 0 ~0.015 ms +XXX[48] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 3190 ~66.461 ms, finishGL 64 / 3166 ~65.962 ms, waitGL 0 / 0 ~0.015 ms +XXX[49] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 3254 ~66.41 ms, finishGL 63 / 3229 ~65.912 ms, waitGL 0 / 0 ~0.015 ms +XXX[50] TO 17 ms, lFrame0 0 ms, lFrameX 62 / 3316 ~66.338 ms, finishGL 62 / 3291 ~65.839 ms, waitGL 0 / 0 ~0.015 ms +XXX[51] TO 17 ms, lFrame0 0 ms, lFrameX 61 / 3378 ~66.251 ms, finishGL 61 / 3353 ~65.755 ms, waitGL 0 / 0 ~0.015 ms +XXX[52] TO 17 ms, lFrame0 0 ms, lFrameX 46 / 3425 ~65.874 ms, finishGL 46 / 3399 ~65.378 ms, waitGL 0 / 0 ~0.015 ms +XXX[53] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3474 ~65.548 ms, finishGL 48 / 3447 ~65.053 ms, waitGL 0 / 0 ~0.015 ms +XXX[54] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3522 ~65.238 ms, finishGL 48 / 3496 ~64.743 ms, waitGL 0 / 0 ~0.015 ms +XXX[55] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3571 ~64.941 ms, finishGL 48 / 3544 ~64.444 ms, waitGL 0 / 0 ~0.015 ms +XXX[56] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3621 ~64.662 ms, finishGL 48 / 3593 ~64.166 ms, waitGL 0 / 0 ~0.015 ms +XXX[57] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3670 ~64.387 ms, finishGL 48 / 3641 ~63.891 ms, waitGL 0 / 0 ~0.015 ms +XXX[58] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3719 ~64.131 ms, finishGL 48 / 3690 ~63.634 ms, waitGL 0 / 0 ~0.015 ms +XXX[59] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3768 ~63.879 ms, finishGL 48 / 3739 ~63.382 ms, waitGL 0 / 0 ~0.016 ms +XXX[60] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3818 ~63.639 ms, finishGL 48 / 3788 ~63.142 ms, waitGL 0 / 0 ~0.016 ms +XXX[61] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3867 ~63.404 ms, finishGL 48 / 3837 ~62.907 ms, waitGL 0 / 0 ~0.016 ms +XXX[62] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3916 ~63.174 ms, finishGL 48 / 3886 ~62.677 ms, waitGL 0 / 0 ~0.016 ms +XXX[63] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3966 ~62.952 ms, finishGL 48 / 3934 ~62.455 ms, waitGL 0 / 1 ~0.016 ms +XXX[64] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 4014 ~62.732 ms, finishGL 48 / 3983 ~62.236 ms, waitGL 0 / 1 ~0.016 ms +XXX[65] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 4063 ~62.517 ms, finishGL 48 / 4031 ~62.021 ms, waitGL 0 / 1 ~0.016 ms +XXX[66] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 4112 ~62.307 ms, finishGL 48 / 4079 ~61.811 ms, waitGL 0 / 1 ~0.016 ms +XXX[67] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 4161 ~62.107 ms, finishGL 48 / 4127 ~61.611 ms, waitGL 0 / 1 ~0.016 ms +XXX[68] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 4209 ~61.911 ms, finishGL 48 / 4175 ~61.411 ms, waitGL 0 / 1 ~0.016 ms +XXX[69] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 4258 ~61.713 ms, finishGL 47 / 4223 ~61.211 ms, waitGL 0 / 1 ~0.016 ms +XXX[70] TO 17 ms, lFrame0 1 ms, lFrameX 30 / 4289 ~61.272 ms, finishGL 29 / 4253 ~60.762 ms, waitGL 0 / 1 ~0.016 ms +XXX[71] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 4339 ~61.117 ms, finishGL 49 / 4303 ~60.607 ms, waitGL 0 / 1 ~0.016 ms +XXX[72] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4371 ~60.714 ms, finishGL 31 / 4334 ~60.203 ms, waitGL 0 / 1 ~0.016 ms +XXX[73] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4404 ~60.329 ms, finishGL 32 / 4366 ~59.819 ms, waitGL 0 / 1 ~0.016 ms +XXX[74] TO 17 ms, lFrame0 0 ms, lFrameX 27 / 4431 ~59.881 ms, finishGL 26 / 4393 ~59.369 ms, waitGL 0 / 1 ~0.016 ms +XXX[75] TO 17 ms, lFrame0 0 ms, lFrameX 54 / 4485 ~59.812 ms, finishGL 53 / 4447 ~59.297 ms, waitGL 0 / 1 ~0.016 ms +XXX[76] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4518 ~59.447 ms, finishGL 31 / 4478 ~58.932 ms, waitGL 0 / 1 ~0.016 ms +XXX[77] TO 17 ms, lFrame0 0 ms, lFrameX 25 / 4543 ~59.002 ms, finishGL 24 / 4503 ~58.485 ms, waitGL 0 / 1 ~0.016 ms +XXX[78] TO 17 ms, lFrame0 0 ms, lFrameX 40 / 4583 ~58.762 ms, finishGL 39 / 4543 ~58.245 ms, waitGL 0 / 1 ~0.016 ms +XXX[79] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 4632 ~58.633 ms, finishGL 47 / 4590 ~58.113 ms, waitGL 0 / 1 ~0.016 ms +XXX[80] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4664 ~58.309 ms, finishGL 32 / 4623 ~57.79 ms, waitGL 0 / 1 ~0.016 ms +XXX[81] TO 17 ms, lFrame0 0 ms, lFrameX 23 / 4688 ~57.883 ms, finishGL 22 / 4646 ~57.36 ms, waitGL 0 / 1 ~0.016 ms +XXX[82] TO 17 ms, lFrame0 0 ms, lFrameX 26 / 4715 ~57.503 ms, finishGL 26 / 4672 ~56.981 ms, waitGL 0 / 1 ~0.016 ms +XXX[83] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 4764 ~57.404 ms, finishGL 48 / 4721 ~56.882 ms, waitGL 0 / 1 ~0.016 ms +XXX[84] TO 17 ms, lFrame0 0 ms, lFrameX 33 / 4797 ~57.113 ms, finishGL 32 / 4753 ~56.59 ms, waitGL 0 / 1 ~0.016 ms +XXX[85] TO 17 ms, lFrame0 0 ms, lFrameX 23 / 4821 ~56.72 ms, finishGL 22 / 4776 ~56.195 ms, waitGL 0 / 1 ~0.016 ms +XXX[86] TO 17 ms, lFrame0 0 ms, lFrameX 45 / 4866 ~56.59 ms, finishGL 45 / 4821 ~56.066 ms, waitGL 0 / 1 ~0.016 ms +XXX[87] TO 17 ms, lFrame0 0 ms, lFrameX 37 / 4904 ~56.373 ms, finishGL 37 / 4858 ~55.849 ms, waitGL 0 / 1 ~0.016 ms +XXX[88] TO 17 ms, lFrame0 0 ms, lFrameX 33 / 4937 ~56.111 ms, finishGL 32 / 4891 ~55.585 ms, waitGL 0 / 1 ~0.016 ms +XXX[89] TO 17 ms, lFrame0 0 ms, lFrameX 57 / 4994 ~56.123 ms, finishGL 56 / 4948 ~55.597 ms, waitGL 0 / 1 ~0.016 ms +XXX[90] TO 17 ms, lFrame0 0 ms, lFrameX 53 / 5048 ~56.092 ms, finishGL 52 / 5001 ~55.567 ms, waitGL 0 / 1 ~0.016 ms +XXX[91] TO 17 ms, lFrame0 0 ms, lFrameX 41 / 5089 ~55.932 ms, finishGL 40 / 5041 ~55.405 ms, waitGL 0 / 1 ~0.016 ms +XXX[92] TO 17 ms, lFrame0 0 ms, lFrameX 76 / 5166 ~56.159 ms, finishGL 76 / 5118 ~55.633 ms, waitGL 0 / 1 ~0.016 ms +XXX[93] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 5216 ~56.093 ms, finishGL 49 / 5167 ~55.567 ms, waitGL 0 / 1 ~0.016 ms +XXX[94] TO 17 ms, lFrame0 0 ms, lFrameX 43 / 5259 ~55.956 ms, finishGL 42 / 5210 ~55.427 ms, waitGL 0 / 1 ~0.016 ms +XXX[95] TO 17 ms, lFrame0 0 ms, lFrameX 73 / 5333 ~56.137 ms, finishGL 72 / 5282 ~55.606 ms, waitGL 0 / 1 ~0.016 ms +XXX[96] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 5383 ~56.075 ms, finishGL 49 / 5332 ~55.545 ms, waitGL 0 / 1 ~0.016 ms +XXX[97] TO 17 ms, lFrame0 0 ms, lFrameX 43 / 5427 ~55.949 ms, finishGL 43 / 5375 ~55.416 ms, waitGL 0 / 1 ~0.016 ms +XXX[98] TO 17 ms, lFrame0 0 ms, lFrameX 72 / 5499 ~56.116 ms, finishGL 71 / 5447 ~55.582 ms, waitGL 0 / 1 ~0.016 ms +XXX[99] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 5549 ~56.06 ms, finishGL 50 / 5497 ~55.526 ms, waitGL 0 / 1 ~0.016 ms +XXX[100] TO 17 ms, lFrame0 0 ms, lFrameX 44 / 5594 ~55.946 ms, finishGL 43 / 5541 ~55.41 ms, waitGL 0 / 1 ~0.016 ms +XXX[101] TO 17 ms, lFrame0 0 ms, lFrameX 72 / 5667 ~56.112 ms, finishGL 72 / 5613 ~55.576 ms, waitGL 0 / 1 ~0.016 ms +XXX[102] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 5718 ~56.06 ms, finishGL 50 / 5663 ~55.525 ms, waitGL 0 / 1 ~0.016 ms +XXX[103] TO 17 ms, lFrame0 0 ms, lFrameX 46 / 5764 ~55.97 ms, finishGL 46 / 5709 ~55.433 ms, waitGL 0 / 1 ~0.016 ms +XXX[104] TO 17 ms, lFrame0 0 ms, lFrameX 72 / 5836 ~56.124 ms, finishGL 71 / 5781 ~55.588 ms, waitGL 0 / 1 ~0.016 ms +XXX[105] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 5905 ~56.239 ms, finishGL 67 / 5848 ~55.704 ms, waitGL 0 / 1 ~0.016 ms +XXX[106] TO 17 ms, lFrame0 0 ms, lFrameX 51 / 5956 ~56.191 ms, finishGL 50 / 5899 ~55.653 ms, waitGL 0 / 1 ~0.016 ms +XXX[107] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 6040 ~56.453 ms, finishGL 83 / 5983 ~55.916 ms, waitGL 0 / 1 ~0.016 ms +XXX[108] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 6110 ~56.579 ms, finishGL 69 / 6052 ~56.041 ms, waitGL 0 / 1 ~0.016 ms +XXX[109] TO 17 ms, lFrame0 0 ms, lFrameX 60 / 6170 ~56.614 ms, finishGL 59 / 6112 ~56.075 ms, waitGL 0 / 1 ~0.016 ms +XXX[110] TO 17 ms, lFrame0 0 ms, lFrameX 94 / 6265 ~56.956 ms, finishGL 93 / 6206 ~56.418 ms, waitGL 0 / 1 ~0.016 ms +XXX[111] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 6333 ~57.058 ms, finishGL 67 / 6273 ~56.518 ms, waitGL 0 / 1 ~0.016 ms +XXX[112] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 6396 ~57.114 ms, finishGL 62 / 6336 ~56.571 ms, waitGL 0 / 1 ~0.016 ms +XXX[113] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 6483 ~57.373 ms, finishGL 85 / 6421 ~56.829 ms, waitGL 0 / 1 ~0.016 ms +XXX[114] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6549 ~57.455 ms, finishGL 66 / 6487 ~56.91 ms, waitGL 0 / 1 ~0.016 ms +XXX[115] TO 17 ms, lFrame0 0 ms, lFrameX 63 / 6613 ~57.507 ms, finishGL 62 / 6550 ~56.961 ms, waitGL 0 / 1 ~0.016 ms +XXX[116] TO 17 ms, lFrame0 0 ms, lFrameX 88 / 6702 ~57.775 ms, finishGL 88 / 6638 ~57.229 ms, waitGL 0 / 1 ~0.015 ms +XXX[117] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 6786 ~58.001 ms, finishGL 83 / 6722 ~57.453 ms, waitGL 0 / 1 ~0.015 ms +XXX[118] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6852 ~58.072 ms, finishGL 65 / 6787 ~57.522 ms, waitGL 0 / 1 ~0.015 ms +XXX[119] TO 17 ms, lFrame0 0 ms, lFrameX 100 / 6952 ~58.425 ms, finishGL 99 / 6887 ~57.876 ms, waitGL 0 / 1 ~0.016 ms +XXX[120] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 7035 ~58.629 ms, finishGL 82 / 6969 ~58.081 ms, waitGL 0 / 1 ~0.015 ms +XXX[121] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 7102 ~58.699 ms, finishGL 66 / 7036 ~58.148 ms, waitGL 0 / 1 ~0.016 ms +XXX[122] TO 17 ms, lFrame0 0 ms, lFrameX 100 / 7203 ~59.044 ms, finishGL 100 / 7136 ~58.494 ms, waitGL 0 / 1 ~0.016 ms +XXX[123] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 7287 ~59.249 ms, finishGL 83 / 7220 ~58.701 ms, waitGL 0 / 1 ~0.015 ms +XXX[124] TO 17 ms, lFrame0 0 ms, lFrameX 71 / 7359 ~59.349 ms, finishGL 70 / 7291 ~58.8 ms, waitGL 0 / 1 ~0.015 ms +XXX[125] TO 17 ms, lFrame0 0 ms, lFrameX 98 / 7458 ~59.665 ms, finishGL 98 / 7389 ~59.114 ms, waitGL 0 / 1 ~0.015 ms +XXX[126] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 7542 ~59.86 ms, finishGL 83 / 7472 ~59.308 ms, waitGL 0 / 2 ~0.016 ms +XXX[127] TO 17 ms, lFrame0 0 ms, lFrameX 76 / 7618 ~59.989 ms, finishGL 75 / 7548 ~59.437 ms, waitGL 0 / 2 ~0.015 ms +XXX[128] TO 17 ms, lFrame0 0 ms, lFrameX 93 / 7712 ~60.252 ms, finishGL 93 / 7641 ~59.701 ms, waitGL 0 / 2 ~0.015 ms +XXX[129] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 7793 ~60.415 ms, finishGL 80 / 7722 ~59.865 ms, waitGL 0 / 2 ~0.015 ms +2013-06-17 03:01:17.725 java[63231:5f07] Persistent UI failed to open file file://localhost/Users/jogamp/Library/Saved%20Application%20State/com.apple.javajdk16.cmd.savedState/window_1.data: Operation not permitted (1) +XXX[130] TO 17 ms, lFrame0 0 ms, lFrameX 79 / 7873 ~60.562 ms, finishGL 79 / 7801 ~60.012 ms, waitGL 0 / 2 ~0.015 ms +XXX[131] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 7954 ~60.719 ms, finishGL 80 / 7882 ~60.168 ms, waitGL 0 / 2 ~0.015 ms +XXX[132] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 8036 ~60.885 ms, finishGL 82 / 7964 ~60.335 ms, waitGL 0 / 2 ~0.015 ms +XXX[133] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 8118 ~61.038 ms, finishGL 80 / 8045 ~60.489 ms, waitGL 0 / 2 ~0.015 ms +XXX[134] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 8200 ~61.195 ms, finishGL 81 / 8126 ~60.646 ms, waitGL 0 / 2 ~0.015 ms +XXX[135] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 8282 ~61.353 ms, finishGL 81 / 8208 ~60.804 ms, waitGL 0 / 2 ~0.016 ms +XXX[136] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 8365 ~61.51 ms, finishGL 82 / 8290 ~60.962 ms, waitGL 0 / 2 ~0.016 ms +XXX[137] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 8448 ~61.666 ms, finishGL 82 / 8373 ~61.118 ms, waitGL 0 / 2 ~0.016 ms +XXX[138] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 8531 ~61.822 ms, finishGL 82 / 8456 ~61.275 ms, waitGL 0 / 2 ~0.016 ms +XXX[139] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 8614 ~61.973 ms, finishGL 82 / 8538 ~61.425 ms, waitGL 0 / 2 ~0.016 ms +FrameCount: 240 - FrameRate: 13.0 +XXX[140] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 8679 ~61.996 ms, finishGL 64 / 8602 ~61.448 ms, waitGL 0 / 2 ~0.016 ms +XXX[141] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 8746 ~62.032 ms, finishGL 66 / 8669 ~61.485 ms, waitGL 0 / 2 ~0.016 ms +XXX[142] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8812 ~62.063 ms, finishGL 65 / 8735 ~61.516 ms, waitGL 0 / 2 ~0.016 ms +XXX[143] TO 17 ms, lFrame0 5 ms, lFrameX 69 / 8882 ~62.114 ms, finishGL 64 / 8799 ~61.534 ms, waitGL 0 / 2 ~0.016 ms +XXX[144] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 8962 ~62.24 ms, finishGL 79 / 8879 ~61.661 ms, waitGL 0 / 2 ~0.016 ms +XXX[145] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 9028 ~62.262 ms, finishGL 65 / 8944 ~61.684 ms, waitGL 0 / 2 ~0.016 ms +XXX[146] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 9093 ~62.287 ms, finishGL 65 / 9009 ~61.709 ms, waitGL 0 / 2 ~0.016 ms +XXX[147] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9160 ~62.315 ms, finishGL 65 / 9075 ~61.737 ms, waitGL 0 / 2 ~0.016 ms +XXX[148] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9226 ~62.342 ms, finishGL 65 / 9141 ~61.766 ms, waitGL 0 / 2 ~0.016 ms +XXX[149] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9293 ~62.372 ms, finishGL 66 / 9207 ~61.794 ms, waitGL 0 / 2 ~0.016 ms +XXX[150] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 9361 ~62.406 ms, finishGL 67 / 9274 ~61.829 ms, waitGL 0 / 2 ~0.016 ms +XXX[151] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 9426 ~62.427 ms, finishGL 64 / 9339 ~61.849 ms, waitGL 0 / 2 ~0.016 ms +XXX[152] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9493 ~62.453 ms, finishGL 66 / 9405 ~61.876 ms, waitGL 0 / 2 ~0.016 ms +XXX[153] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9559 ~62.479 ms, finishGL 65 / 9471 ~61.902 ms, waitGL 0 / 2 ~0.016 ms +XXX[154] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 9625 ~62.501 ms, finishGL 65 / 9536 ~61.925 ms, waitGL 0 / 2 ~0.016 ms +XXX[155] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 9692 ~62.532 ms, finishGL 66 / 9603 ~61.956 ms, waitGL 0 / 2 ~0.016 ms +XXX[156] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9759 ~62.559 ms, finishGL 66 / 9669 ~61.983 ms, waitGL 0 / 2 ~0.016 ms +XXX[157] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9825 ~62.583 ms, finishGL 65 / 9735 ~62.008 ms, waitGL 0 / 2 ~0.016 ms +XXX[158] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 9890 ~62.599 ms, finishGL 64 / 9799 ~62.024 ms, waitGL 0 / 2 ~0.015 ms +XXX[159] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9957 ~62.624 ms, finishGL 66 / 9866 ~62.051 ms, waitGL 0 / 2 ~0.015 ms +XXX[160] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10023 ~62.646 ms, finishGL 65 / 9931 ~62.072 ms, waitGL 0 / 2 ~0.015 ms +XXX[161] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 10089 ~62.665 ms, finishGL 65 / 9996 ~62.092 ms, waitGL 0 / 2 ~0.015 ms +XXX[162] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10155 ~62.687 ms, finishGL 65 / 10062 ~62.115 ms, waitGL 0 / 2 ~0.015 ms +XXX[163] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10221 ~62.709 ms, finishGL 65 / 10128 ~62.138 ms, waitGL 0 / 2 ~0.015 ms +XXX[164] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 10287 ~62.729 ms, finishGL 64 / 10193 ~62.155 ms, waitGL 0 / 2 ~0.015 ms +XXX[165] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10354 ~62.754 ms, finishGL 66 / 10259 ~62.179 ms, waitGL 0 / 2 ~0.015 ms +XXX[166] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 10420 ~62.772 ms, finishGL 65 / 10324 ~62.197 ms, waitGL 0 / 2 ~0.015 ms +XXX[167] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10486 ~62.793 ms, finishGL 65 / 10390 ~62.22 ms, waitGL 0 / 2 ~0.015 ms +XXX[168] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10553 ~62.816 ms, finishGL 66 / 10456 ~62.243 ms, waitGL 0 / 2 ~0.015 ms +XXX[169] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10619 ~62.839 ms, finishGL 66 / 10523 ~62.266 ms, waitGL 0 / 2 ~0.015 ms +XXX[170] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10686 ~62.861 ms, finishGL 66 / 10589 ~62.289 ms, waitGL 0 / 2 ~0.015 ms +XXX[171] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10753 ~62.884 ms, finishGL 66 / 10655 ~62.312 ms, waitGL 0 / 2 ~0.015 ms +XXX[172] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10819 ~62.906 ms, finishGL 66 / 10721 ~62.335 ms, waitGL 0 / 2 ~0.015 ms +XXX[173] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 10887 ~62.931 ms, finishGL 66 / 10788 ~62.36 ms, waitGL 0 / 2 ~0.015 ms +XXX[174] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10953 ~62.951 ms, finishGL 65 / 10854 ~62.38 ms, waitGL 0 / 2 ~0.016 ms +XXX[175] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 11020 ~62.972 ms, finishGL 66 / 10920 ~62.402 ms, waitGL 0 / 2 ~0.015 ms +XXX[176] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 11086 ~62.99 ms, finishGL 65 / 10986 ~62.421 ms, waitGL 0 / 2 ~0.015 ms +XXX[177] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 11153 ~63.012 ms, finishGL 66 / 11052 ~62.443 ms, waitGL 0 / 2 ~0.016 ms +XXX[178] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11220 ~63.035 ms, finishGL 66 / 11118 ~62.466 ms, waitGL 0 / 2 ~0.015 ms +XXX[179] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11288 ~63.061 ms, finishGL 67 / 11186 ~62.493 ms, waitGL 0 / 2 ~0.016 ms +XXX[180] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11355 ~63.088 ms, finishGL 67 / 11253 ~62.52 ms, waitGL 0 / 2 ~0.015 ms +XXX[181] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 11422 ~63.107 ms, finishGL 65 / 11319 ~62.539 ms, waitGL 0 / 2 ~0.015 ms +XXX[182] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11490 ~63.132 ms, finishGL 67 / 11386 ~62.565 ms, waitGL 0 / 2 ~0.015 ms +XXX[183] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11557 ~63.154 ms, finishGL 66 / 11453 ~62.587 ms, waitGL 0 / 2 ~0.016 ms +XXX[184] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11624 ~63.177 ms, finishGL 66 / 11520 ~62.611 ms, waitGL 0 / 2 ~0.016 ms +XXX[185] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 11709 ~63.294 ms, finishGL 84 / 11604 ~62.728 ms, waitGL 0 / 2 ~0.016 ms +XXX[186] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 11794 ~63.412 ms, finishGL 84 / 11689 ~62.847 ms, waitGL 0 / 2 ~0.016 ms +XXX[187] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 11881 ~63.536 ms, finishGL 86 / 11775 ~62.971 ms, waitGL 0 / 2 ~0.016 ms +XXX[188] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 11967 ~63.657 ms, finishGL 85 / 11861 ~63.092 ms, waitGL 0 / 3 ~0.016 ms +XXX[189] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 12052 ~63.771 ms, finishGL 84 / 11946 ~63.206 ms, waitGL 0 / 3 ~0.016 ms +XXX[190] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 12137 ~63.882 ms, finishGL 84 / 12030 ~63.318 ms, waitGL 0 / 3 ~0.016 ms +XXX[191] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 12221 ~63.986 ms, finishGL 83 / 12113 ~63.422 ms, waitGL 0 / 3 ~0.016 ms +XXX[192] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 12306 ~64.094 ms, finishGL 84 / 12197 ~63.53 ms, waitGL 0 / 3 ~0.016 ms +XXX[193] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 12405 ~64.276 ms, finishGL 98 / 12296 ~63.712 ms, waitGL 0 / 3 ~0.016 ms +XXX[194] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 12489 ~64.376 ms, finishGL 83 / 12379 ~63.812 ms, waitGL 0 / 3 ~0.016 ms +XXX[195] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 12588 ~64.557 ms, finishGL 99 / 12478 ~63.994 ms, waitGL 0 / 3 ~0.016 ms +XXX[196] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 12671 ~64.648 ms, finishGL 81 / 12560 ~64.085 ms, waitGL 0 / 3 ~0.016 ms +XXX[197] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 12752 ~64.735 ms, finishGL 81 / 12642 ~64.173 ms, waitGL 0 / 3 ~0.016 ms +XXX[198] TO 17 ms, lFrame0 1 ms, lFrameX 82 / 12835 ~64.823 ms, finishGL 81 / 12723 ~64.259 ms, waitGL 0 / 3 ~0.016 ms +XXX[199] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 12918 ~64.914 ms, finishGL 82 / 12805 ~64.35 ms, waitGL 0 / 3 ~0.016 ms +XXX[200] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 13001 ~65.005 ms, finishGL 82 / 12888 ~64.441 ms, waitGL 0 / 3 ~0.016 ms +XXX[201] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 13084 ~65.094 ms, finishGL 82 / 12970 ~64.531 ms, waitGL 0 / 3 ~0.016 ms +XXX[202] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 13167 ~65.185 ms, finishGL 82 / 13053 ~64.622 ms, waitGL 0 / 3 ~0.016 ms +XXX[203] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 13250 ~65.274 ms, finishGL 82 / 13136 ~64.711 ms, waitGL 0 / 3 ~0.016 ms +XXX[204] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 13333 ~65.36 ms, finishGL 82 / 13218 ~64.798 ms, waitGL 0 / 3 ~0.016 ms +XXX[205] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 13416 ~65.447 ms, finishGL 82 / 13301 ~64.885 ms, waitGL 0 / 3 ~0.016 ms +XXX[206] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 13498 ~65.527 ms, finishGL 81 / 13383 ~64.966 ms, waitGL 0 / 3 ~0.016 ms +XXX[207] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 13580 ~65.608 ms, finishGL 81 / 13464 ~65.047 ms, waitGL 0 / 3 ~0.016 ms +XXX[208] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 13663 ~65.687 ms, finishGL 81 / 13546 ~65.126 ms, waitGL 0 / 3 ~0.016 ms +XXX[209] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 13744 ~65.764 ms, finishGL 81 / 13627 ~65.204 ms, waitGL 0 / 3 ~0.016 ms +XXX[210] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 13826 ~65.84 ms, finishGL 81 / 13708 ~65.279 ms, waitGL 0 / 3 ~0.016 ms +XXX[211] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 13908 ~65.915 ms, finishGL 81 / 13789 ~65.354 ms, waitGL 0 / 3 ~0.016 ms +XXX[212] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 13989 ~65.99 ms, finishGL 81 / 13871 ~65.43 ms, waitGL 0 / 3 ~0.016 ms +XXX[213] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 14071 ~66.064 ms, finishGL 81 / 13952 ~65.504 ms, waitGL 0 / 3 ~0.016 ms +XXX[214] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 14153 ~66.137 ms, finishGL 81 / 14033 ~65.577 ms, waitGL 0 / 3 ~0.016 ms +XXX[215] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 14235 ~66.211 ms, finishGL 81 / 14115 ~65.652 ms, waitGL 0 / 3 ~0.016 ms +XXX[216] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 14301 ~66.212 ms, finishGL 65 / 14181 ~65.653 ms, waitGL 0 / 3 ~0.016 ms +XXX[217] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 14369 ~66.216 ms, finishGL 66 / 14247 ~65.658 ms, waitGL 0 / 3 ~0.016 ms +XXX[218] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 14452 ~66.296 ms, finishGL 83 / 14330 ~65.738 ms, waitGL 0 / 3 ~0.016 ms +XXX[219] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 14538 ~66.385 ms, finishGL 85 / 14416 ~65.827 ms, waitGL 0 / 3 ~0.016 ms +XXX[220] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 14624 ~66.473 ms, finishGL 85 / 14501 ~65.915 ms, waitGL 0 / 3 ~0.016 ms +XXX[221] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 14709 ~66.56 ms, finishGL 85 / 14586 ~66.003 ms, waitGL 0 / 3 ~0.016 ms +XXX[222] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 14795 ~66.648 ms, finishGL 85 / 14672 ~66.091 ms, waitGL 0 / 3 ~0.016 ms +XXX[223] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 14880 ~66.73 ms, finishGL 84 / 14756 ~66.173 ms, waitGL 0 / 3 ~0.016 ms +XXX[224] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 14964 ~66.804 ms, finishGL 82 / 14839 ~66.247 ms, waitGL 0 / 3 ~0.016 ms +XXX[225] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 15047 ~66.876 ms, finishGL 82 / 14921 ~66.319 ms, waitGL 0 / 3 ~0.016 ms +XXX[226] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15129 ~66.946 ms, finishGL 82 / 15004 ~66.389 ms, waitGL 0 / 3 ~0.016 ms +XXX[227] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15212 ~67.017 ms, finishGL 82 / 15086 ~66.46 ms, waitGL 0 / 3 ~0.016 ms +XXX[228] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15295 ~67.085 ms, finishGL 82 / 15168 ~66.529 ms, waitGL 0 / 3 ~0.016 ms +XXX[229] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15377 ~67.152 ms, finishGL 81 / 15250 ~66.596 ms, waitGL 0 / 3 ~0.016 ms +XXX[230] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15460 ~67.219 ms, finishGL 82 / 15332 ~66.663 ms, waitGL 0 / 3 ~0.016 ms +XXX[231] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 15542 ~67.283 ms, finishGL 81 / 15414 ~66.727 ms, waitGL 0 / 3 ~0.016 ms +XXX[232] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15624 ~67.346 ms, finishGL 81 / 15495 ~66.791 ms, waitGL 0 / 3 ~0.016 ms +XXX[233] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15706 ~67.411 ms, finishGL 81 / 15577 ~66.856 ms, waitGL 0 / 3 ~0.016 ms +XXX[234] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 15787 ~67.469 ms, finishGL 80 / 15658 ~66.915 ms, waitGL 0 / 3 ~0.016 ms +XXX[235] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 15869 ~67.529 ms, finishGL 81 / 15739 ~66.975 ms, waitGL 0 / 3 ~0.016 ms +XXX[236] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15951 ~67.591 ms, finishGL 81 / 15820 ~67.037 ms, waitGL 0 / 3 ~0.016 ms +XXX[237] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 16033 ~67.651 ms, finishGL 81 / 15902 ~67.097 ms, waitGL 0 / 3 ~0.016 ms +XXX[238] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 16115 ~67.711 ms, finishGL 81 / 15983 ~67.157 ms, waitGL 0 / 3 ~0.016 ms +XXX[239] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 16181 ~67.705 ms, finishGL 65 / 16049 ~67.152 ms, waitGL 0 / 3 ~0.016 ms +XXX[240] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 16248 ~67.7 ms, finishGL 66 / 16115 ~67.148 ms, waitGL 0 / 3 ~0.016 ms +XXX[241] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 16314 ~67.694 ms, finishGL 65 / 16181 ~67.141 ms, waitGL 0 / 3 ~0.016 ms +XXX[242] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 16381 ~67.69 ms, finishGL 66 / 16247 ~67.138 ms, waitGL 0 / 3 ~0.016 ms +XXX[243] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 16446 ~67.681 ms, finishGL 64 / 16312 ~67.129 ms, waitGL 0 / 3 ~0.016 ms +XXX[244] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 16513 ~67.677 ms, finishGL 66 / 16378 ~67.125 ms, waitGL 0 / 3 ~0.016 ms +XXX[245] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 16579 ~67.671 ms, finishGL 65 / 16444 ~67.119 ms, waitGL 0 / 3 ~0.016 ms +XXX[246] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 16645 ~67.664 ms, finishGL 65 / 16509 ~67.112 ms, waitGL 0 / 3 ~0.016 ms +XXX[247] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 16712 ~67.661 ms, finishGL 66 / 16576 ~67.11 ms, waitGL 0 / 3 ~0.016 ms +XXX[248] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 16779 ~67.657 ms, finishGL 66 / 16642 ~67.106 ms, waitGL 0 / 3 ~0.016 ms +XXX[249] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 16846 ~67.656 ms, finishGL 66 / 16709 ~67.104 ms, waitGL 0 / 4 ~0.016 ms +XXX[250] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 16913 ~67.655 ms, finishGL 67 / 16776 ~67.105 ms, waitGL 0 / 4 ~0.016 ms +XXX[251] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 16998 ~67.723 ms, finishGL 84 / 16860 ~67.172 ms, waitGL 0 / 4 ~0.016 ms +XXX[252] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 17083 ~67.79 ms, finishGL 84 / 16944 ~67.239 ms, waitGL 0 / 4 ~0.016 ms +XXX[253] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 17168 ~67.859 ms, finishGL 84 / 17029 ~67.309 ms, waitGL 0 / 4 ~0.016 ms +XXX[254] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 17253 ~67.928 ms, finishGL 84 / 17114 ~67.378 ms, waitGL 0 / 4 ~0.016 ms +XXX[255] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 17338 ~67.994 ms, finishGL 84 / 17198 ~67.444 ms, waitGL 0 / 4 ~0.016 ms +XXX[256] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 17423 ~68.06 ms, finishGL 84 / 17282 ~67.51 ms, waitGL 0 / 4 ~0.016 ms +XXX[257] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 17507 ~68.123 ms, finishGL 83 / 17366 ~67.574 ms, waitGL 0 / 4 ~0.016 ms +XXX[258] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 17592 ~68.188 ms, finishGL 84 / 17451 ~67.64 ms, waitGL 0 / 4 ~0.016 ms +XXX[259] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 17676 ~68.25 ms, finishGL 83 / 17534 ~67.702 ms, waitGL 0 / 4 ~0.016 ms +FrameCount: 360 - FrameRate: 15.0 +XXX[260] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 17760 ~68.309 ms, finishGL 82 / 17617 ~67.76 ms, waitGL 0 / 4 ~0.016 ms +XXX[261] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 17843 ~68.367 ms, finishGL 82 / 17700 ~67.818 ms, waitGL 0 / 4 ~0.016 ms +XXX[262] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 17926 ~68.423 ms, finishGL 82 / 17783 ~67.875 ms, waitGL 0 / 4 ~0.016 ms +XXX[263] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18009 ~68.478 ms, finishGL 82 / 17865 ~67.93 ms, waitGL 0 / 4 ~0.016 ms +XXX[264] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18092 ~68.532 ms, finishGL 82 / 17947 ~67.984 ms, waitGL 0 / 4 ~0.016 ms +XXX[265] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18175 ~68.586 ms, finishGL 82 / 18030 ~68.038 ms, waitGL 0 / 4 ~0.016 ms +XXX[266] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18257 ~68.638 ms, finishGL 81 / 18111 ~68.089 ms, waitGL 0 / 4 ~0.016 ms +XXX[267] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18340 ~68.691 ms, finishGL 82 / 18194 ~68.143 ms, waitGL 0 / 4 ~0.016 ms +XXX[268] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18423 ~68.743 ms, finishGL 81 / 18276 ~68.194 ms, waitGL 0 / 4 ~0.016 ms +XXX[269] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18505 ~68.794 ms, finishGL 82 / 18358 ~68.246 ms, waitGL 0 / 4 ~0.016 ms +XXX[270] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18588 ~68.844 ms, finishGL 81 / 18440 ~68.296 ms, waitGL 0 / 4 ~0.016 ms +XXX[271] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 18669 ~68.892 ms, finishGL 81 / 18521 ~68.344 ms, waitGL 0 / 4 ~0.016 ms +XXX[272] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 18751 ~68.939 ms, finishGL 81 / 18602 ~68.391 ms, waitGL 0 / 4 ~0.016 ms +XXX[273] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18833 ~68.987 ms, finishGL 81 / 18684 ~68.44 ms, waitGL 0 / 4 ~0.016 ms +XXX[274] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18915 ~69.036 ms, finishGL 81 / 18766 ~68.489 ms, waitGL 0 / 4 ~0.016 ms +XXX[275] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18998 ~69.084 ms, finishGL 81 / 18847 ~68.537 ms, waitGL 0 / 4 ~0.016 ms +XXX[276] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 19080 ~69.132 ms, finishGL 81 / 18929 ~68.585 ms, waitGL 0 / 4 ~0.016 ms +XXX[277] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 19162 ~69.179 ms, finishGL 81 / 19011 ~68.633 ms, waitGL 0 / 4 ~0.016 ms +XXX[278] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 19245 ~69.228 ms, finishGL 82 / 19093 ~68.682 ms, waitGL 0 / 4 ~0.016 ms +XXX[279] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 19327 ~69.274 ms, finishGL 81 / 19175 ~68.728 ms, waitGL 0 / 4 ~0.016 ms +XXX[280] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 19410 ~69.322 ms, finishGL 82 / 19257 ~68.777 ms, waitGL 0 / 4 ~0.016 ms +XXX[281] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 19492 ~69.368 ms, finishGL 81 / 19339 ~68.823 ms, waitGL 0 / 4 ~0.016 ms +XXX[282] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 19575 ~69.415 ms, finishGL 82 / 19421 ~68.87 ms, waitGL 0 / 4 ~0.016 ms +XXX[283] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19640 ~69.402 ms, finishGL 65 / 19486 ~68.857 ms, waitGL 0 / 4 ~0.016 ms +XXX[284] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19706 ~69.389 ms, finishGL 65 / 19552 ~68.845 ms, waitGL 0 / 4 ~0.016 ms +XXX[285] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19772 ~69.375 ms, finishGL 64 / 19616 ~68.83 ms, waitGL 0 / 4 ~0.016 ms +XXX[286] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19837 ~69.362 ms, finishGL 65 / 19681 ~68.817 ms, waitGL 0 / 4 ~0.016 ms +XXX[287] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19902 ~69.348 ms, finishGL 64 / 19746 ~68.804 ms, waitGL 0 / 4 ~0.016 ms +XXX[288] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 19968 ~69.336 ms, finishGL 65 / 19812 ~68.792 ms, waitGL 0 / 4 ~0.016 ms +XXX[289] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 20034 ~69.322 ms, finishGL 64 / 19877 ~68.778 ms, waitGL 0 / 4 ~0.016 ms +XXX[290] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 20098 ~69.306 ms, finishGL 64 / 19941 ~68.762 ms, waitGL 0 / 4 ~0.016 ms +XXX[291] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 20163 ~69.292 ms, finishGL 64 / 20005 ~68.748 ms, waitGL 0 / 4 ~0.016 ms +XXX[292] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20230 ~69.281 ms, finishGL 65 / 20071 ~68.738 ms, waitGL 0 / 4 ~0.016 ms +XXX[293] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 20295 ~69.267 ms, finishGL 64 / 20136 ~68.724 ms, waitGL 0 / 4 ~0.016 ms +XXX[294] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20361 ~69.257 ms, finishGL 65 / 20202 ~68.714 ms, waitGL 0 / 4 ~0.016 ms +XXX[295] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 20427 ~69.244 ms, finishGL 65 / 20267 ~68.702 ms, waitGL 0 / 4 ~0.016 ms +XXX[296] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 20493 ~69.233 ms, finishGL 65 / 20332 ~68.691 ms, waitGL 0 / 4 ~0.016 ms +XXX[297] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20559 ~69.222 ms, finishGL 65 / 20398 ~68.68 ms, waitGL 0 / 4 ~0.016 ms +XXX[298] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20625 ~69.212 ms, finishGL 65 / 20463 ~68.67 ms, waitGL 0 / 4 ~0.016 ms +XXX[299] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20691 ~69.202 ms, finishGL 65 / 20529 ~68.66 ms, waitGL 0 / 4 ~0.016 ms +XXX[300] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20758 ~69.193 ms, finishGL 66 / 20595 ~68.652 ms, waitGL 0 / 4 ~0.016 ms +XXX[301] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 20825 ~69.187 ms, finishGL 66 / 20662 ~68.645 ms, waitGL 0 / 4 ~0.016 ms +XXX[302] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 20892 ~69.181 ms, finishGL 66 / 20729 ~68.64 ms, waitGL 0 / 4 ~0.016 ms +XXX[303] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 20960 ~69.177 ms, finishGL 67 / 20796 ~68.635 ms, waitGL 0 / 4 ~0.016 ms +XXX[304] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 21029 ~69.175 ms, finishGL 68 / 20864 ~68.634 ms, waitGL 0 / 4 ~0.016 ms +XXX[305] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 21097 ~69.172 ms, finishGL 67 / 20932 ~68.631 ms, waitGL 0 / 4 ~0.016 ms +XXX[306] TO 17 ms, lFrame0 0 ms, lFrameX 69 / 21166 ~69.173 ms, finishGL 68 / 21001 ~68.632 ms, waitGL 0 / 4 ~0.016 ms +XXX[307] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 21237 ~69.178 ms, finishGL 70 / 21072 ~68.638 ms, waitGL 0 / 4 ~0.016 ms +XXX[308] TO 17 ms, lFrame0 0 ms, lFrameX 71 / 21309 ~69.185 ms, finishGL 70 / 21142 ~68.645 ms, waitGL 0 / 4 ~0.016 ms +XXX[309] TO 17 ms, lFrame0 0 ms, lFrameX 87 / 21397 ~69.246 ms, finishGL 87 / 21230 ~68.706 ms, waitGL 0 / 4 ~0.016 ms +XXX[310] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 21482 ~69.298 ms, finishGL 85 / 21315 ~68.759 ms, waitGL 0 / 4 ~0.016 ms +XXX[311] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 21568 ~69.351 ms, finishGL 85 / 21400 ~68.811 ms, waitGL 0 / 5 ~0.016 ms +XXX[312] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 21652 ~69.398 ms, finishGL 83 / 21484 ~68.859 ms, waitGL 0 / 5 ~0.016 ms +XXX[313] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 21735 ~69.442 ms, finishGL 82 / 21566 ~68.903 ms, waitGL 0 / 5 ~0.016 ms +XXX[314] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 21818 ~69.485 ms, finishGL 82 / 21649 ~68.946 ms, waitGL 0 / 5 ~0.016 ms +XXX[315] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 21901 ~69.529 ms, finishGL 82 / 21731 ~68.99 ms, waitGL 0 / 5 ~0.016 ms +XXX[316] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 21985 ~69.575 ms, finishGL 83 / 21815 ~69.036 ms, waitGL 0 / 5 ~0.016 ms +XXX[317] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 22070 ~69.622 ms, finishGL 83 / 21899 ~69.083 ms, waitGL 0 / 5 ~0.016 ms +XXX[318] TO 17 ms, lFrame0 0 ms, lFrameX 100 / 22171 ~69.72 ms, finishGL 100 / 21999 ~69.182 ms, waitGL 0 / 5 ~0.016 ms +XXX[319] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 22270 ~69.814 ms, finishGL 98 / 22098 ~69.274 ms, waitGL 0 / 5 ~0.016 ms +XXX[320] TO 17 ms, lFrame0 0 ms, lFrameX 98 / 22369 ~69.904 ms, finishGL 98 / 22197 ~69.365 ms, waitGL 0 / 5 ~0.016 ms +XXX[321] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 22451 ~69.942 ms, finishGL 81 / 22278 ~69.403 ms, waitGL 0 / 5 ~0.016 ms +XXX[322] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 22534 ~69.982 ms, finishGL 82 / 22360 ~69.443 ms, waitGL 0 / 5 ~0.016 ms +XXX[323] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 22617 ~70.022 ms, finishGL 82 / 22443 ~69.483 ms, waitGL 0 / 5 ~0.016 ms +XXX[324] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22700 ~70.063 ms, finishGL 82 / 22526 ~69.525 ms, waitGL 0 / 5 ~0.016 ms +XXX[325] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 22783 ~70.102 ms, finishGL 82 / 22608 ~69.564 ms, waitGL 0 / 5 ~0.016 ms +XXX[326] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22866 ~70.143 ms, finishGL 83 / 22691 ~69.605 ms, waitGL 0 / 5 ~0.016 ms +XXX[327] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22950 ~70.183 ms, finishGL 82 / 22774 ~69.645 ms, waitGL 0 / 5 ~0.016 ms +XXX[328] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23033 ~70.223 ms, finishGL 82 / 22856 ~69.685 ms, waitGL 0 / 5 ~0.016 ms +XXX[329] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23116 ~70.263 ms, finishGL 83 / 22939 ~69.725 ms, waitGL 0 / 5 ~0.016 ms +XXX[330] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 23198 ~70.298 ms, finishGL 81 / 23021 ~69.761 ms, waitGL 0 / 5 ~0.016 ms +XXX[331] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 23283 ~70.343 ms, finishGL 84 / 23105 ~69.806 ms, waitGL 0 / 5 ~0.016 ms +XXX[332] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23367 ~70.383 ms, finishGL 83 / 23189 ~69.846 ms, waitGL 0 / 5 ~0.016 ms +XXX[333] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23450 ~70.422 ms, finishGL 82 / 23271 ~69.885 ms, waitGL 0 / 5 ~0.016 ms +XXX[334] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23533 ~70.459 ms, finishGL 82 / 23354 ~69.922 ms, waitGL 0 / 5 ~0.016 ms +XXX[335] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23616 ~70.495 ms, finishGL 82 / 23436 ~69.958 ms, waitGL 0 / 5 ~0.016 ms +XXX[336] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23699 ~70.534 ms, finishGL 82 / 23518 ~69.996 ms, waitGL 0 / 5 ~0.016 ms +XXX[337] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23782 ~70.569 ms, finishGL 82 / 23600 ~70.032 ms, waitGL 0 / 5 ~0.016 ms +XXX[338] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 23863 ~70.602 ms, finishGL 80 / 23681 ~70.064 ms, waitGL 0 / 5 ~0.016 ms +XXX[339] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23945 ~70.636 ms, finishGL 81 / 23763 ~70.098 ms, waitGL 0 / 5 ~0.016 ms +XXX[340] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24028 ~70.673 ms, finishGL 82 / 23846 ~70.135 ms, waitGL 0 / 5 ~0.016 ms +XXX[341] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24112 ~70.71 ms, finishGL 82 / 23928 ~70.172 ms, waitGL 0 / 5 ~0.016 ms +XXX[342] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24195 ~70.746 ms, finishGL 82 / 24011 ~70.208 ms, waitGL 0 / 5 ~0.016 ms +XXX[343] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24278 ~70.782 ms, finishGL 82 / 24093 ~70.243 ms, waitGL 0 / 5 ~0.016 ms +XXX[344] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24360 ~70.816 ms, finishGL 82 / 24175 ~70.278 ms, waitGL 0 / 5 ~0.016 ms +XXX[345] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24444 ~70.852 ms, finishGL 82 / 24258 ~70.314 ms, waitGL 0 / 5 ~0.016 ms +XXX[346] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24527 ~70.887 ms, finishGL 82 / 24340 ~70.349 ms, waitGL 0 / 5 ~0.016 ms +XXX[347] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24610 ~70.922 ms, finishGL 82 / 24423 ~70.384 ms, waitGL 0 / 5 ~0.016 ms +XXX[348] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24693 ~70.958 ms, finishGL 82 / 24506 ~70.42 ms, waitGL 0 / 5 ~0.016 ms +XXX[349] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24776 ~70.992 ms, finishGL 82 / 24588 ~70.454 ms, waitGL 0 / 5 ~0.016 ms +XXX[350] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24860 ~71.028 ms, finishGL 83 / 24671 ~70.491 ms, waitGL 0 / 5 ~0.016 ms +XXX[351] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24943 ~71.063 ms, finishGL 82 / 24754 ~70.525 ms, waitGL 0 / 5 ~0.016 ms +XXX[352] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 25025 ~71.096 ms, finishGL 82 / 24836 ~70.559 ms, waitGL 0 / 5 ~0.016 ms +XXX[353] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25109 ~71.131 ms, finishGL 83 / 24919 ~70.594 ms, waitGL 0 / 5 ~0.016 ms +XXX[354] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25192 ~71.165 ms, finishGL 82 / 25002 ~70.629 ms, waitGL 0 / 5 ~0.016 ms +XXX[355] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25275 ~71.199 ms, finishGL 82 / 25085 ~70.662 ms, waitGL 0 / 5 ~0.016 ms +XXX[356] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25359 ~71.234 ms, finishGL 83 / 25168 ~70.698 ms, waitGL 0 / 5 ~0.016 ms +XXX[357] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 25442 ~71.266 ms, finishGL 82 / 25250 ~70.73 ms, waitGL 0 / 5 ~0.016 ms +XXX[358] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25525 ~71.3 ms, finishGL 82 / 25333 ~70.764 ms, waitGL 0 / 5 ~0.016 ms +XXX[359] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 25608 ~71.332 ms, finishGL 82 / 25416 ~70.796 ms, waitGL 0 / 5 ~0.016 ms +XXX[360] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25692 ~71.367 ms, finishGL 83 / 25499 ~70.831 ms, waitGL 0 / 5 ~0.016 ms +XXX[361] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25775 ~71.4 ms, finishGL 83 / 25582 ~70.865 ms, waitGL 0 / 5 ~0.016 ms +XXX[362] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 25858 ~71.432 ms, finishGL 82 / 25664 ~70.896 ms, waitGL 0 / 5 ~0.016 ms +XXX[363] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25941 ~71.465 ms, finishGL 82 / 25747 ~70.929 ms, waitGL 0 / 5 ~0.016 ms +XXX[364] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26025 ~71.499 ms, finishGL 83 / 25830 ~70.963 ms, waitGL 0 / 5 ~0.016 ms +XXX[365] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26108 ~71.531 ms, finishGL 82 / 25913 ~70.996 ms, waitGL 0 / 5 ~0.016 ms +XXX[366] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 26192 ~71.565 ms, finishGL 83 / 25997 ~71.03 ms, waitGL 0 / 5 ~0.016 ms +XXX[367] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26275 ~71.596 ms, finishGL 82 / 26079 ~71.061 ms, waitGL 0 / 5 ~0.016 ms +XXX[368] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26359 ~71.628 ms, finishGL 82 / 26162 ~71.093 ms, waitGL 0 / 5 ~0.016 ms +XXX[369] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26442 ~71.658 ms, finishGL 82 / 26244 ~71.123 ms, waitGL 0 / 5 ~0.016 ms +XXX[370] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26526 ~71.691 ms, finishGL 83 / 26328 ~71.157 ms, waitGL 0 / 5 ~0.016 ms +XXX[371] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26608 ~71.722 ms, finishGL 82 / 26410 ~71.187 ms, waitGL 0 / 5 ~0.016 ms +XXX[372] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26691 ~71.752 ms, finishGL 82 / 26492 ~71.217 ms, waitGL 0 / 5 ~0.016 ms +XXX[373] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 26773 ~71.779 ms, finishGL 81 / 26574 ~71.245 ms, waitGL 0 / 5 ~0.016 ms +XXX[374] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26856 ~71.809 ms, finishGL 82 / 26656 ~71.274 ms, waitGL 0 / 6 ~0.016 ms +XXX[375] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26939 ~71.838 ms, finishGL 82 / 26738 ~71.303 ms, waitGL 0 / 6 ~0.016 ms +XXX[376] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27022 ~71.869 ms, finishGL 82 / 26821 ~71.334 ms, waitGL 0 / 6 ~0.016 ms +XXX[377] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27105 ~71.897 ms, finishGL 81 / 26903 ~71.362 ms, waitGL 0 / 6 ~0.016 ms +XXX[378] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27188 ~71.927 ms, finishGL 82 / 26986 ~71.393 ms, waitGL 0 / 6 ~0.016 ms +XXX[379] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27271 ~71.955 ms, finishGL 82 / 27068 ~71.421 ms, waitGL 0 / 6 ~0.016 ms +FrameCount: 480 - FrameRate: 12.0 +XXX[380] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27353 ~71.983 ms, finishGL 82 / 27150 ~71.449 ms, waitGL 0 / 6 ~0.016 ms +XXX[381] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27436 ~72.011 ms, finishGL 82 / 27232 ~71.477 ms, waitGL 0 / 6 ~0.016 ms +XXX[382] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27519 ~72.04 ms, finishGL 82 / 27315 ~71.506 ms, waitGL 0 / 6 ~0.016 ms +XXX[383] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27602 ~72.068 ms, finishGL 82 / 27397 ~71.534 ms, waitGL 0 / 6 ~0.016 ms +XXX[384] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27684 ~72.094 ms, finishGL 81 / 27479 ~71.56 ms, waitGL 0 / 6 ~0.016 ms +XXX[385] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27767 ~72.123 ms, finishGL 82 / 27562 ~71.59 ms, waitGL 0 / 6 ~0.016 ms +XXX[386] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 27852 ~72.157 ms, finishGL 84 / 27646 ~71.623 ms, waitGL 0 / 6 ~0.016 ms +XXX[387] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27936 ~72.187 ms, finishGL 83 / 27730 ~71.653 ms, waitGL 0 / 6 ~0.016 ms +XXX[388] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28020 ~72.216 ms, finishGL 83 / 27813 ~71.683 ms, waitGL 0 / 6 ~0.016 ms +XXX[389] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28103 ~72.244 ms, finishGL 82 / 27895 ~71.711 ms, waitGL 0 / 6 ~0.016 ms +XXX[390] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 28187 ~72.276 ms, finishGL 84 / 27979 ~71.743 ms, waitGL 0 / 6 ~0.016 ms +XXX[391] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 28272 ~72.309 ms, finishGL 84 / 28064 ~71.776 ms, waitGL 0 / 6 ~0.016 ms +XXX[392] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 28357 ~72.34 ms, finishGL 83 / 28148 ~71.807 ms, waitGL 0 / 6 ~0.016 ms +XXX[393] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 28440 ~72.368 ms, finishGL 82 / 28230 ~71.833 ms, waitGL 0 / 6 ~0.016 ms +XXX[394] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28523 ~72.395 ms, finishGL 82 / 28312 ~71.86 ms, waitGL 0 / 6 ~0.016 ms +XXX[395] TO 17 ms, lFrame0 1 ms, lFrameX 82 / 28606 ~72.421 ms, finishGL 81 / 28394 ~71.885 ms, waitGL 0 / 6 ~0.016 ms +XXX[396] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28689 ~72.448 ms, finishGL 82 / 28477 ~71.912 ms, waitGL 0 / 6 ~0.016 ms +XXX[397] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28772 ~72.475 ms, finishGL 82 / 28559 ~71.939 ms, waitGL 0 / 6 ~0.016 ms +XXX[398] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28855 ~72.502 ms, finishGL 82 / 28642 ~71.966 ms, waitGL 0 / 6 ~0.016 ms +XXX[399] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28938 ~72.528 ms, finishGL 82 / 28725 ~71.992 ms, waitGL 0 / 6 ~0.016 ms +XXX[400] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29021 ~72.553 ms, finishGL 82 / 28807 ~72.017 ms, waitGL 0 / 6 ~0.016 ms +XXX[401] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29104 ~72.58 ms, finishGL 82 / 28889 ~72.044 ms, waitGL 0 / 6 ~0.016 ms +XXX[402] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29187 ~72.605 ms, finishGL 82 / 28971 ~72.069 ms, waitGL 0 / 6 ~0.016 ms +XXX[403] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 29269 ~72.627 ms, finishGL 81 / 29053 ~72.092 ms, waitGL 0 / 6 ~0.016 ms +XXX[404] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 29350 ~72.65 ms, finishGL 81 / 29134 ~72.115 ms, waitGL 0 / 6 ~0.016 ms +XXX[405] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29433 ~72.675 ms, finishGL 82 / 29216 ~72.14 ms, waitGL 0 / 6 ~0.016 ms +XXX[406] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29516 ~72.7 ms, finishGL 82 / 29299 ~72.165 ms, waitGL 0 / 6 ~0.016 ms +XXX[407] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29599 ~72.726 ms, finishGL 82 / 29381 ~72.191 ms, waitGL 0 / 6 ~0.016 ms +XXX[408] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29682 ~72.751 ms, finishGL 82 / 29464 ~72.216 ms, waitGL 0 / 6 ~0.016 ms +XXX[409] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29765 ~72.775 ms, finishGL 81 / 29546 ~72.239 ms, waitGL 0 / 6 ~0.016 ms +XXX[410] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29847 ~72.799 ms, finishGL 82 / 29628 ~72.264 ms, waitGL 0 / 6 ~0.016 ms +XXX[411] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29930 ~72.824 ms, finishGL 82 / 29710 ~72.289 ms, waitGL 0 / 6 ~0.016 ms +XXX[412] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 30013 ~72.848 ms, finishGL 82 / 29793 ~72.313 ms, waitGL 0 / 6 ~0.016 ms +XXX[413] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30096 ~72.873 ms, finishGL 82 / 29875 ~72.338 ms, waitGL 0 / 6 ~0.016 ms +XXX[414] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30180 ~72.899 ms, finishGL 83 / 29959 ~72.365 ms, waitGL 0 / 6 ~0.016 ms +XXX[415] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 30262 ~72.922 ms, finishGL 81 / 30040 ~72.387 ms, waitGL 0 / 6 ~0.016 ms +XXX[416] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 30345 ~72.946 ms, finishGL 82 / 30123 ~72.411 ms, waitGL 0 / 6 ~0.016 ms +XXX[417] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 30428 ~72.969 ms, finishGL 82 / 30205 ~72.434 ms, waitGL 0 / 6 ~0.016 ms +XXX[418] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 30511 ~72.992 ms, finishGL 82 / 30287 ~72.458 ms, waitGL 0 / 6 ~0.016 ms +XXX[419] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30594 ~73.017 ms, finishGL 82 / 30370 ~72.482 ms, waitGL 0 / 6 ~0.016 ms +XXX[420] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30677 ~73.041 ms, finishGL 82 / 30452 ~72.506 ms, waitGL 0 / 6 ~0.016 ms +XXX[421] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30761 ~73.067 ms, finishGL 83 / 30536 ~72.532 ms, waitGL 0 / 6 ~0.016 ms +XXX[422] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 30845 ~73.093 ms, finishGL 83 / 30619 ~72.558 ms, waitGL 0 / 6 ~0.016 ms +XXX[423] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 30929 ~73.12 ms, finishGL 83 / 30703 ~72.585 ms, waitGL 0 / 6 ~0.016 ms +XXX[424] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 31012 ~73.142 ms, finishGL 81 / 30785 ~72.607 ms, waitGL 0 / 6 ~0.016 ms +XXX[425] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 31092 ~73.159 ms, finishGL 79 / 30865 ~72.624 ms, waitGL 0 / 6 ~0.016 ms +XXX[426] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 31173 ~73.176 ms, finishGL 79 / 30945 ~72.641 ms, waitGL 0 / 6 ~0.016 ms +XXX[427] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 31253 ~73.192 ms, finishGL 79 / 31024 ~72.657 ms, waitGL 0 / 6 ~0.016 ms +XXX[428] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 31317 ~73.171 ms, finishGL 63 / 31088 ~72.636 ms, waitGL 0 / 6 ~0.016 ms +XXX[429] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31382 ~73.153 ms, finishGL 64 / 31153 ~72.618 ms, waitGL 0 / 6 ~0.016 ms +XXX[430] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31449 ~73.137 ms, finishGL 65 / 31218 ~72.602 ms, waitGL 0 / 6 ~0.016 ms +XXX[431] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31514 ~73.12 ms, finishGL 65 / 31284 ~72.585 ms, waitGL 0 / 6 ~0.016 ms +XXX[432] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31580 ~73.103 ms, finishGL 65 / 31349 ~72.568 ms, waitGL 0 / 6 ~0.016 ms +XXX[433] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31646 ~73.087 ms, finishGL 65 / 31415 ~72.552 ms, waitGL 0 / 6 ~0.016 ms +XXX[434] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31713 ~73.071 ms, finishGL 65 / 31480 ~72.536 ms, waitGL 0 / 7 ~0.016 ms +XXX[435] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31779 ~73.055 ms, finishGL 65 / 31546 ~72.521 ms, waitGL 0 / 7 ~0.016 ms +XXX[436] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 31844 ~73.038 ms, finishGL 64 / 31611 ~72.503 ms, waitGL 0 / 7 ~0.016 ms +XXX[437] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31911 ~73.023 ms, finishGL 65 / 31677 ~72.488 ms, waitGL 0 / 7 ~0.016 ms +XXX[438] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31977 ~73.007 ms, finishGL 65 / 31743 ~72.472 ms, waitGL 0 / 7 ~0.016 ms +XXX[439] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32043 ~72.992 ms, finishGL 66 / 31809 ~72.458 ms, waitGL 0 / 7 ~0.016 ms +XXX[440] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 32110 ~72.979 ms, finishGL 66 / 31875 ~72.444 ms, waitGL 0 / 7 ~0.016 ms +XXX[441] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32177 ~72.964 ms, finishGL 66 / 31941 ~72.43 ms, waitGL 0 / 7 ~0.016 ms +XXX[442] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32243 ~72.95 ms, finishGL 66 / 32007 ~72.415 ms, waitGL 0 / 7 ~0.016 ms +XXX[443] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 32311 ~72.937 ms, finishGL 66 / 32074 ~72.402 ms, waitGL 0 / 7 ~0.016 ms +XXX[444] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32378 ~72.923 ms, finishGL 66 / 32140 ~72.389 ms, waitGL 0 / 7 ~0.016 ms +XXX[445] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32444 ~72.909 ms, finishGL 66 / 32207 ~72.375 ms, waitGL 0 / 7 ~0.016 ms +XXX[446] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32511 ~72.895 ms, finishGL 66 / 32273 ~72.361 ms, waitGL 0 / 7 ~0.016 ms +XXX[447] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 32578 ~72.882 ms, finishGL 66 / 32339 ~72.348 ms, waitGL 0 / 7 ~0.016 ms +XXX[448] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32644 ~72.867 ms, finishGL 65 / 32405 ~72.333 ms, waitGL 0 / 7 ~0.016 ms +XXX[449] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32711 ~72.853 ms, finishGL 66 / 32471 ~72.32 ms, waitGL 0 / 7 ~0.016 ms +XXX[450] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32778 ~72.84 ms, finishGL 66 / 32537 ~72.306 ms, waitGL 0 / 7 ~0.016 ms +XXX[451] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32844 ~72.826 ms, finishGL 66 / 32604 ~72.292 ms, waitGL 0 / 7 ~0.016 ms +XXX[452] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32911 ~72.812 ms, finishGL 66 / 32670 ~72.279 ms, waitGL 0 / 7 ~0.016 ms +XXX[453] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32977 ~72.797 ms, finishGL 65 / 32735 ~72.264 ms, waitGL 0 / 7 ~0.016 ms +XXX[454] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33042 ~72.781 ms, finishGL 65 / 32800 ~72.248 ms, waitGL 0 / 7 ~0.016 ms +XXX[455] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33108 ~72.765 ms, finishGL 65 / 32865 ~72.232 ms, waitGL 0 / 7 ~0.016 ms +XXX[456] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 33174 ~72.751 ms, finishGL 65 / 32931 ~72.219 ms, waitGL 0 / 7 ~0.016 ms +XXX[457] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33240 ~72.735 ms, finishGL 64 / 32996 ~72.202 ms, waitGL 0 / 7 ~0.016 ms +XXX[458] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33305 ~72.719 ms, finishGL 64 / 33061 ~72.186 ms, waitGL 0 / 7 ~0.016 ms +XXX[459] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33371 ~72.704 ms, finishGL 65 / 33126 ~72.171 ms, waitGL 0 / 7 ~0.016 ms +XXX[460] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33436 ~72.688 ms, finishGL 65 / 33191 ~72.156 ms, waitGL 0 / 7 ~0.016 ms +XXX[461] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33502 ~72.674 ms, finishGL 65 / 33257 ~72.142 ms, waitGL 0 / 7 ~0.016 ms +XXX[462] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33568 ~72.658 ms, finishGL 64 / 33322 ~72.126 ms, waitGL 0 / 7 ~0.016 ms +XXX[463] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33633 ~72.643 ms, finishGL 64 / 33387 ~72.11 ms, waitGL 0 / 7 ~0.016 ms +XXX[464] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33699 ~72.628 ms, finishGL 65 / 33452 ~72.096 ms, waitGL 0 / 7 ~0.016 ms +XXX[465] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33765 ~72.613 ms, finishGL 65 / 33517 ~72.081 ms, waitGL 0 / 7 ~0.016 ms +XXX[466] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 33830 ~72.597 ms, finishGL 64 / 33582 ~72.065 ms, waitGL 0 / 7 ~0.016 ms +XXX[467] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 33878 ~72.545 ms, finishGL 47 / 33630 ~72.013 ms, waitGL 0 / 7 ~0.016 ms +XXX[468] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 33928 ~72.497 ms, finishGL 49 / 33680 ~71.965 ms, waitGL 0 / 7 ~0.016 ms +XXX[469] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 33977 ~72.447 ms, finishGL 48 / 33728 ~71.915 ms, waitGL 0 / 7 ~0.016 ms +XXX[470] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34026 ~72.397 ms, finishGL 48 / 33776 ~71.865 ms, waitGL 0 / 7 ~0.016 ms +XXX[471] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34076 ~72.349 ms, finishGL 49 / 33825 ~71.817 ms, waitGL 0 / 7 ~0.016 ms +XXX[472] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34125 ~72.299 ms, finishGL 48 / 33874 ~71.767 ms, waitGL 0 / 7 ~0.016 ms +XXX[473] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34174 ~72.251 ms, finishGL 48 / 33923 ~71.719 ms, waitGL 0 / 7 ~0.016 ms +XXX[474] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34223 ~72.202 ms, finishGL 48 / 33971 ~71.67 ms, waitGL 0 / 7 ~0.016 ms +XXX[475] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34272 ~72.151 ms, finishGL 47 / 34019 ~71.62 ms, waitGL 0 / 7 ~0.016 ms +XXX[476] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 34322 ~72.106 ms, finishGL 50 / 34069 ~71.574 ms, waitGL 0 / 7 ~0.016 ms +XXX[477] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34371 ~72.057 ms, finishGL 48 / 34117 ~71.525 ms, waitGL 0 / 7 ~0.016 ms +XXX[478] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34420 ~72.009 ms, finishGL 48 / 34166 ~71.478 ms, waitGL 0 / 7 ~0.016 ms +XXX[479] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34469 ~71.961 ms, finishGL 48 / 34215 ~71.43 ms, waitGL 0 / 7 ~0.016 ms +XXX[480] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34518 ~71.914 ms, finishGL 48 / 34263 ~71.383 ms, waitGL 0 / 7 ~0.016 ms +XXX[481] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34567 ~71.865 ms, finishGL 47 / 34311 ~71.334 ms, waitGL 0 / 7 ~0.016 ms +XXX[482] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34616 ~71.818 ms, finishGL 48 / 34360 ~71.288 ms, waitGL 0 / 7 ~0.016 ms +XXX[483] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34665 ~71.772 ms, finishGL 48 / 34409 ~71.241 ms, waitGL 0 / 7 ~0.016 ms +XXX[484] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34714 ~71.725 ms, finishGL 48 / 34458 ~71.194 ms, waitGL 0 / 7 ~0.016 ms +XXX[485] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34764 ~71.678 ms, finishGL 48 / 34506 ~71.148 ms, waitGL 0 / 7 ~0.016 ms +XXX[486] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 34813 ~71.631 ms, finishGL 48 / 34554 ~71.1 ms, waitGL 0 / 7 ~0.016 ms +XXX[487] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34862 ~71.586 ms, finishGL 48 / 34603 ~71.054 ms, waitGL 0 / 7 ~0.016 ms +XXX[488] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34912 ~71.541 ms, finishGL 49 / 34653 ~71.01 ms, waitGL 0 / 7 ~0.016 ms +XXX[489] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34961 ~71.495 ms, finishGL 48 / 34701 ~70.964 ms, waitGL 0 / 7 ~0.016 ms +XXX[490] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35011 ~71.451 ms, finishGL 49 / 34750 ~70.92 ms, waitGL 0 / 7 ~0.016 ms +XXX[491] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35061 ~71.408 ms, finishGL 49 / 34800 ~70.877 ms, waitGL 0 / 7 ~0.016 ms +XXX[492] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35111 ~71.365 ms, finishGL 49 / 34850 ~70.834 ms, waitGL 0 / 8 ~0.016 ms +XXX[493] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35161 ~71.321 ms, finishGL 49 / 34899 ~70.79 ms, waitGL 0 / 8 ~0.016 ms +XXX[494] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35211 ~71.277 ms, finishGL 48 / 34948 ~70.746 ms, waitGL 0 / 8 ~0.016 ms +XXX[495] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35260 ~71.234 ms, finishGL 49 / 34997 ~70.703 ms, waitGL 0 / 8 ~0.016 ms +XXX[496] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35311 ~71.193 ms, finishGL 50 / 35048 ~70.662 ms, waitGL 0 / 8 ~0.016 ms +XXX[497] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35362 ~71.151 ms, finishGL 50 / 35098 ~70.62 ms, waitGL 0 / 8 ~0.016 ms +XXX[498] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35412 ~71.109 ms, finishGL 49 / 35148 ~70.578 ms, waitGL 0 / 8 ~0.016 ms +XXX[499] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35462 ~71.067 ms, finishGL 49 / 35197 ~70.536 ms, waitGL 0 / 8 ~0.016 ms +FrameCount: 600 - FrameRate: 20.0 +XXX[500] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35513 ~71.026 ms, finishGL 49 / 35247 ~70.495 ms, waitGL 0 / 8 ~0.016 ms +XXX[501] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35563 ~70.984 ms, finishGL 49 / 35297 ~70.454 ms, waitGL 0 / 8 ~0.016 ms +XXX[502] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35613 ~70.944 ms, finishGL 50 / 35347 ~70.413 ms, waitGL 0 / 8 ~0.016 ms +XXX[503] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35664 ~70.903 ms, finishGL 49 / 35397 ~70.372 ms, waitGL 0 / 8 ~0.016 ms +XXX[504] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35714 ~70.861 ms, finishGL 49 / 35446 ~70.331 ms, waitGL 0 / 8 ~0.016 ms +XXX[505] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35764 ~70.82 ms, finishGL 49 / 35496 ~70.29 ms, waitGL 0 / 8 ~0.016 ms +XXX[506] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35814 ~70.78 ms, finishGL 49 / 35546 ~70.249 ms, waitGL 0 / 8 ~0.016 ms +XXX[507] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35864 ~70.738 ms, finishGL 48 / 35595 ~70.207 ms, waitGL 0 / 8 ~0.016 ms +XXX[508] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35914 ~70.698 ms, finishGL 50 / 35645 ~70.168 ms, waitGL 0 / 8 ~0.016 ms +XXX[509] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35965 ~70.658 ms, finishGL 49 / 35695 ~70.128 ms, waitGL 0 / 8 ~0.016 ms +XXX[510] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 36015 ~70.618 ms, finishGL 49 / 35744 ~70.088 ms, waitGL 0 / 8 ~0.016 ms +XXX[511] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 36065 ~70.578 ms, finishGL 49 / 35794 ~70.048 ms, waitGL 0 / 8 ~0.016 ms +XXX[512] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 36115 ~70.538 ms, finishGL 49 / 35844 ~70.008 ms, waitGL 0 / 8 ~0.016 ms +XXX[513] TO 17 ms, lFrame0 0 ms, lFrameX 51 / 36166 ~70.5 ms, finishGL 50 / 35895 ~69.971 ms, waitGL 0 / 8 ~0.016 ms +XXX[514] TO 17 ms, lFrame0 0 ms, lFrameX 51 / 36218 ~70.464 ms, finishGL 51 / 35946 ~69.934 ms, waitGL 0 / 8 ~0.016 ms +XXX[515] TO 17 ms, lFrame0 0 ms, lFrameX 52 / 36270 ~70.429 ms, finishGL 51 / 35998 ~69.899 ms, waitGL 0 / 8 ~0.016 ms +XXX[516] TO 17 ms, lFrame0 0 ms, lFrameX 53 / 36324 ~70.396 ms, finishGL 53 / 36051 ~69.866 ms, waitGL 0 / 8 ~0.016 ms +XXX[517] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 36393 ~70.392 ms, finishGL 68 / 36119 ~69.863 ms, waitGL 0 / 8 ~0.016 ms +XXX[518] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 36463 ~70.392 ms, finishGL 69 / 36189 ~69.863 ms, waitGL 0 / 8 ~0.016 ms +XXX[519] TO 17 ms, lFrame0 0 ms, lFrameX 75 / 36539 ~70.402 ms, finishGL 75 / 36264 ~69.873 ms, waitGL 0 / 8 ~0.016 ms +XXX[520] TO 17 ms, lFrame0 0 ms, lFrameX 92 / 36631 ~70.444 ms, finishGL 91 / 36355 ~69.915 ms, waitGL 0 / 8 ~0.016 ms +XXX[521] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 36716 ~70.473 ms, finishGL 85 / 36441 ~69.944 ms, waitGL 0 / 8 ~0.016 ms +XXX[522] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 36799 ~70.496 ms, finishGL 81 / 36522 ~69.967 ms, waitGL 0 / 8 ~0.016 ms +XXX[523] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36882 ~70.521 ms, finishGL 83 / 36606 ~69.992 ms, waitGL 0 / 8 ~0.016 ms +XXX[524] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36965 ~70.545 ms, finishGL 82 / 36688 ~70.016 ms, waitGL 0 / 8 ~0.016 ms +XXX[525] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 37048 ~70.569 ms, finishGL 82 / 36771 ~70.04 ms, waitGL 0 / 8 ~0.016 ms +XXX[526] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 37131 ~70.592 ms, finishGL 82 / 36853 ~70.063 ms, waitGL 0 / 8 ~0.016 ms +XXX[527] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37215 ~70.616 ms, finishGL 82 / 36936 ~70.087 ms, waitGL 0 / 8 ~0.016 ms +XXX[528] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37298 ~70.64 ms, finishGL 82 / 37019 ~70.111 ms, waitGL 0 / 8 ~0.016 ms +XXX[529] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37381 ~70.665 ms, finishGL 82 / 37101 ~70.136 ms, waitGL 0 / 8 ~0.016 ms +XXX[530] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37465 ~70.688 ms, finishGL 82 / 37184 ~70.159 ms, waitGL 0 / 8 ~0.016 ms +XXX[531] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37548 ~70.712 ms, finishGL 82 / 37267 ~70.183 ms, waitGL 0 / 8 ~0.016 ms +XXX[532] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37632 ~70.737 ms, finishGL 83 / 37350 ~70.208 ms, waitGL 0 / 8 ~0.016 ms +XXX[533] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 37714 ~70.759 ms, finishGL 82 / 37432 ~70.23 ms, waitGL 0 / 8 ~0.016 ms +XXX[534] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37798 ~70.782 ms, finishGL 82 / 37515 ~70.253 ms, waitGL 0 / 8 ~0.016 ms +XXX[535] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 37879 ~70.803 ms, finishGL 81 / 37596 ~70.274 ms, waitGL 0 / 8 ~0.016 ms +XXX[536] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37962 ~70.826 ms, finishGL 82 / 37679 ~70.296 ms, waitGL 0 / 8 ~0.016 ms +XXX[537] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 38045 ~70.848 ms, finishGL 82 / 37761 ~70.319 ms, waitGL 0 / 8 ~0.016 ms +XXX[538] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 38128 ~70.87 ms, finishGL 82 / 37843 ~70.341 ms, waitGL 0 / 8 ~0.016 ms +XXX[539] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 38211 ~70.892 ms, finishGL 81 / 37925 ~70.362 ms, waitGL 0 / 8 ~0.016 ms +XXX[540] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38294 ~70.915 ms, finishGL 82 / 38007 ~70.385 ms, waitGL 0 / 8 ~0.016 ms +XXX[541] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 38376 ~70.937 ms, finishGL 82 / 38090 ~70.406 ms, waitGL 0 / 8 ~0.016 ms +XXX[542] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38460 ~70.961 ms, finishGL 83 / 38173 ~70.43 ms, waitGL 0 / 8 ~0.016 ms +XXX[543] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38543 ~70.983 ms, finishGL 82 / 38255 ~70.452 ms, waitGL 0 / 8 ~0.016 ms +XXX[544] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38627 ~71.006 ms, finishGL 82 / 38338 ~70.475 ms, waitGL 0 / 8 ~0.016 ms +XXX[545] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38710 ~71.029 ms, finishGL 82 / 38421 ~70.498 ms, waitGL 0 / 8 ~0.016 ms +XXX[546] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38794 ~71.051 ms, finishGL 82 / 38504 ~70.521 ms, waitGL 0 / 8 ~0.016 ms +XXX[547] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 38878 ~71.076 ms, finishGL 83 / 38588 ~70.545 ms, waitGL 0 / 8 ~0.016 ms +XXX[548] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 38963 ~71.1 ms, finishGL 84 / 38672 ~70.57 ms, waitGL 0 / 8 ~0.016 ms +XXX[549] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 39046 ~71.122 ms, finishGL 82 / 38755 ~70.592 ms, waitGL 0 / 8 ~0.016 ms +XXX[550] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 39130 ~71.147 ms, finishGL 83 / 38839 ~70.616 ms, waitGL 0 / 8 ~0.016 ms +XXX[551] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 39214 ~71.169 ms, finishGL 83 / 38922 ~70.639 ms, waitGL 0 / 8 ~0.016 ms +XXX[552] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 39299 ~71.194 ms, finishGL 84 / 39006 ~70.664 ms, waitGL 0 / 8 ~0.016 ms +XXX[553] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39381 ~71.214 ms, finishGL 82 / 39088 ~70.684 ms, waitGL 0 / 9 ~0.016 ms +XXX[554] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 39463 ~71.233 ms, finishGL 80 / 39169 ~70.703 ms, waitGL 0 / 9 ~0.016 ms +XXX[555] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39545 ~71.253 ms, finishGL 82 / 39251 ~70.724 ms, waitGL 0 / 9 ~0.016 ms +XXX[556] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39628 ~71.274 ms, finishGL 82 / 39334 ~70.744 ms, waitGL 0 / 9 ~0.016 ms +XXX[557] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39710 ~71.293 ms, finishGL 81 / 39415 ~70.763 ms, waitGL 0 / 9 ~0.016 ms +XXX[558] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39793 ~71.313 ms, finishGL 81 / 39497 ~70.783 ms, waitGL 0 / 9 ~0.016 ms +XXX[559] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 39873 ~71.33 ms, finishGL 80 / 39577 ~70.8 ms, waitGL 0 / 9 ~0.016 ms +XXX[560] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39956 ~71.35 ms, finishGL 82 / 39659 ~70.82 ms, waitGL 0 / 9 ~0.016 ms +XXX[561] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 40038 ~71.369 ms, finishGL 81 / 39741 ~70.839 ms, waitGL 0 / 9 ~0.016 ms +XXX[562] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 40120 ~71.388 ms, finishGL 81 / 39822 ~70.858 ms, waitGL 0 / 9 ~0.016 ms +XXX[563] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 40201 ~71.406 ms, finishGL 80 / 39903 ~70.876 ms, waitGL 0 / 9 ~0.016 ms +XXX[564] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 40282 ~71.423 ms, finishGL 80 / 39983 ~70.893 ms, waitGL 0 / 9 ~0.016 ms +XXX[565] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 40364 ~71.441 ms, finishGL 81 / 40065 ~70.911 ms, waitGL 0 / 9 ~0.016 ms +XXX[566] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40429 ~71.43 ms, finishGL 64 / 40130 ~70.901 ms, waitGL 0 / 9 ~0.016 ms +XXX[567] TO 17 ms, lFrame0 0 ms, lFrameX 64 / 40494 ~71.419 ms, finishGL 64 / 40194 ~70.889 ms, waitGL 0 / 9 ~0.016 ms +XXX[568] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40560 ~71.408 ms, finishGL 64 / 40258 ~70.878 ms, waitGL 0 / 9 ~0.016 ms +XXX[569] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40625 ~71.398 ms, finishGL 65 / 40324 ~70.868 ms, waitGL 0 / 9 ~0.016 ms +XXX[570] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40691 ~71.388 ms, finishGL 65 / 40389 ~70.858 ms, waitGL 0 / 9 ~0.016 ms +XXX[571] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40756 ~71.378 ms, finishGL 64 / 40454 ~70.847 ms, waitGL 0 / 9 ~0.016 ms +XXX[572] TO 17 ms, lFrame0 0 ms, lFrameX 68 / 40825 ~71.372 ms, finishGL 67 / 40521 ~70.842 ms, waitGL 0 / 9 ~0.016 ms +XXX[573] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40890 ~71.362 ms, finishGL 64 / 40586 ~70.831 ms, waitGL 0 / 9 ~0.016 ms +XXX[574] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 40956 ~71.353 ms, finishGL 65 / 40651 ~70.822 ms, waitGL 0 / 9 ~0.016 ms +XXX[575] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 41023 ~71.345 ms, finishGL 66 / 40718 ~70.814 ms, waitGL 0 / 9 ~0.016 ms +XXX[576] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 41089 ~71.336 ms, finishGL 65 / 40783 ~70.804 ms, waitGL 0 / 9 ~0.016 ms +XXX[577] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 41155 ~71.327 ms, finishGL 65 / 40848 ~70.795 ms, waitGL 0 / 9 ~0.016 ms +XXX[578] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 41223 ~71.321 ms, finishGL 67 / 40916 ~70.789 ms, waitGL 0 / 9 ~0.016 ms +XXX[579] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 41293 ~71.319 ms, finishGL 69 / 40985 ~70.787 ms, waitGL 0 / 9 ~0.016 ms +XXX[580] TO 17 ms, lFrame0 0 ms, lFrameX 70 / 41364 ~71.318 ms, finishGL 70 / 41056 ~70.786 ms, waitGL 0 / 9 ~0.016 ms +XXX[581] TO 17 ms, lFrame0 0 ms, lFrameX 89 / 41454 ~71.349 ms, finishGL 89 / 41145 ~70.818 ms, waitGL 0 / 9 ~0.016 ms +XXX[582] TO 17 ms, lFrame0 0 ms, lFrameX 86 / 41540 ~71.376 ms, finishGL 86 / 41231 ~70.844 ms, waitGL 0 / 9 ~0.016 ms +XXX[583] TO 17 ms, lFrame0 0 ms, lFrameX 85 / 41626 ~71.401 ms, finishGL 85 / 41317 ~70.869 ms, waitGL 0 / 9 ~0.016 ms +XXX[584] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 41710 ~71.422 ms, finishGL 83 / 41400 ~70.891 ms, waitGL 0 / 9 ~0.016 ms +XXX[585] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 41792 ~71.44 ms, finishGL 81 / 41481 ~70.909 ms, waitGL 0 / 9 ~0.016 ms +XXX[586] TO 17 ms, lFrame0 0 ms, lFrameX 80 / 41873 ~71.456 ms, finishGL 80 / 41562 ~70.925 ms, waitGL 0 / 9 ~0.016 ms +XXX[587] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 41955 ~71.474 ms, finishGL 81 / 41644 ~70.943 ms, waitGL 0 / 9 ~0.016 ms +XXX[588] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 42038 ~71.494 ms, finishGL 82 / 41726 ~70.963 ms, waitGL 0 / 9 ~0.016 ms +XXX[589] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 42121 ~71.513 ms, finishGL 82 / 41808 ~70.982 ms, waitGL 0 / 9 ~0.016 ms +XXX[590] TO 17 ms, lFrame0 1 ms, lFrameX 82 / 42203 ~71.532 ms, finishGL 81 / 41890 ~71.0 ms, waitGL 0 / 9 ~0.016 ms +XXX[591] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42286 ~71.551 ms, finishGL 82 / 41972 ~71.019 ms, waitGL 0 / 9 ~0.016 ms +XXX[592] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 42369 ~71.57 ms, finishGL 82 / 42054 ~71.038 ms, waitGL 0 / 9 ~0.016 ms +XXX[593] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 42453 ~71.591 ms, finishGL 83 / 42138 ~71.059 ms, waitGL 0 / 9 ~0.016 ms +XXX[594] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 42536 ~71.609 ms, finishGL 81 / 42220 ~71.078 ms, waitGL 0 / 9 ~0.016 ms +XXX[595] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42620 ~71.63 ms, finishGL 83 / 42303 ~71.099 ms, waitGL 0 / 9 ~0.016 ms +XXX[596] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42703 ~71.65 ms, finishGL 83 / 42387 ~71.119 ms, waitGL 0 / 9 ~0.016 ms +XXX[597] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 42788 ~71.672 ms, finishGL 84 / 42471 ~71.141 ms, waitGL 0 / 9 ~0.016 ms +XXX[598] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42871 ~71.692 ms, finishGL 82 / 42554 ~71.16 ms, waitGL 0 / 9 ~0.016 ms +XXX[599] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 42956 ~71.713 ms, finishGL 83 / 42637 ~71.181 ms, waitGL 0 / 9 ~0.016 ms +XXX[600] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 43038 ~71.73 ms, finishGL 81 / 42719 ~71.199 ms, waitGL 0 / 9 ~0.016 ms +XXX[601] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 43120 ~71.747 ms, finishGL 81 / 42800 ~71.216 ms, waitGL 0 / 9 ~0.016 ms +XXX[602] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 43202 ~71.764 ms, finishGL 81 / 42881 ~71.232 ms, waitGL 0 / 9 ~0.016 ms +XXX[603] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 43284 ~71.781 ms, finishGL 81 / 42963 ~71.248 ms, waitGL 0 / 9 ~0.016 ms +XXX[604] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 43366 ~71.799 ms, finishGL 82 / 43045 ~71.267 ms, waitGL 0 / 9 ~0.016 ms +XXX[605] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 43449 ~71.818 ms, finishGL 82 / 43128 ~71.285 ms, waitGL 0 / 9 ~0.016 ms diff --git a/src/test/com/jogamp/opengl/test/bugs/Bug735.OSX.CALayer.Perf.logs/aaaa-m2-sync1-finish-wait.log b/src/test/com/jogamp/opengl/test/bugs/Bug735.OSX.CALayer.Perf.logs/aaaa-m2-sync1-finish-wait.log new file mode 100644 index 000000000..940cad603 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/bugs/Bug735.OSX.CALayer.Perf.logs/aaaa-m2-sync1-finish-wait.log @@ -0,0 +1,745 @@ +NSZombieEnabled +NSTraceEvents YES +OBJC_PRINT_EXCEPTIONS +/usr/bin/java +java version "1.6.0_37" +Java(TM) SE Runtime Environment (build 1.6.0_37-b06-434-11M3909) +Java HotSpot(TM) 64-Bit Server VM (build 20.12-b01-434, mixed mode) +LD_LIBRARY_PATH :../../gluegen/make/../build-macosx/obj:../build-macosx/lib +LIBXCB_ALLOW_SLOPPY_LOCK: +LIBGL_DRIVERS_PATH: +LIBGL_DEBUG: +LIBGL_ALWAYS_INDIRECT: +LIBGL_ALWAYS_SOFTWARE: +SWT_CLASSPATH: ../build-macosx/../make/lib/swt/cocoa-macosx-x86_64/swt-debug.jar +/usr/bin/java -d64 -time 100000 -vsyncN 0 +CLASSPATH .:../../gluegen/make/../build-macosx/gluegen-rt.jar:../build-macosx/jar/jogl-all.jar:../build-macosx/jar/jogl-test.jar:../build-macosx/../make/lib/swt/cocoa-macosx-x86_64/swt-debug.jar:../../gluegen/make/../make/lib/junit.jar:/opt-share/apache-ant/lib/ant.jar:/opt-share/apache-ant/lib/ant-junit.jar +CLASSPATH .:../../gluegen/make/../build-macosx/gluegen-rt.jar:../build-macosx/jar/jogl-all.jar:../build-macosx/jar/jogl-test.jar:../build-macosx/../make/lib/swt/cocoa-macosx-x86_64/swt-debug.jar:../../gluegen/make/../make/lib/junit.jar:/opt-share/apache-ant/lib/ant.jar:/opt-share/apache-ant/lib/ant-junit.jar + +Test Start: com.jogamp.opengl.test.bugs.Bug735Inv3AppletAWT -time 100000 -vsyncN 0 + +/usr/bin/java -d64 -Djava.awt.headless=false -Djogl.debug.calayer.SwapM2 com.jogamp.opengl.test.bugs.Bug735Inv3AppletAWT -time 100000 -vsyncN 0 +swapInterval 1 +exclusiveContext false +SWAP_M1 false +SWAP_M2 true +NewtCanvasAWT.attachNewtChild.2: size 500x268 +Thread[main-Display-.macosx_nil-1-EDT-1,5,main] LandscapeES2.init ... +LandscapeES2 init on Thread[main-Display-.macosx_nil-1-EDT-1,5,main] +Chosen GLCapabilities: GLCaps[rgba 8/8/8/0, opaque, accum-rgba 0/0/0/0, dp/st/ms 24/0/0, dbl, mono , hw, GLProfile[GL2/GL2.hw], offscr[fbo]] +INIT GL IS: jogamp.opengl.gl4.GL4bcImpl +GL_VENDOR: NVIDIA Corporation +GL_RENDERER: NVIDIA GeForce 320M OpenGL Engine +GL_VERSION: 2.1 NVIDIA-7.32.12 +GL GLSL: true, has-compiler-func: true, version 1.20, 1.20.0 +GL FBO: basic true, full true +GL Profile: GLProfile[GL2/GL2.hw] +GL Renderer Quirks:[NoOffscreenBitmap] +GL:jogamp.opengl.gl4.GL4bcImpl@7b7a4989, 2.1 (hardware) - 2.1 NVIDIA-7.32.12 +Thread[main-Display-.macosx_nil-1-EDT-1,5,main] LandscapeES2.init FIN +Thread[main-Display-.macosx_nil-1-EDT-1,5,main] LandscapeES2.reshape 0/0 500x268, swapInterval 1, drawable 0x7fd1cbcd7ed0 +Thread[AWT-EventQueue-0,6,main] LandscapeES2.reshape 0/0 500x268, swapInterval 1, drawable 0x7fd1cbcd7ed0 +XXX[1] TO 17 ms, lFrame0 110 ms, lFrameX 849 / 849 ~849.6 ms, finishGL 736 / 736 ~736.509 ms, waitGL 2 / 2 ~2.611 ms +XXX[2] TO 17 ms, lFrame0 89 ms, lFrameX 182 / 1031 ~515.996 ms, finishGL 88 / 825 ~412.638 ms, waitGL 3 / 6 ~3.222 ms +XXX[3] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 1115 ~371.971 ms, finishGL 80 / 905 ~301.799 ms, waitGL 2 / 8 ~2.84 ms +XXX[4] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 1214 ~303.748 ms, finishGL 95 / 1001 ~250.348 ms, waitGL 2 / 11 ~2.756 ms +XXX[5] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 1298 ~259.668 ms, finishGL 80 / 1081 ~216.348 ms, waitGL 2 / 13 ~2.67 ms +XXX[6] TO 17 ms, lFrame0 1 ms, lFrameX 82 / 1381 ~230.176 ms, finishGL 79 / 1161 ~193.531 ms, waitGL 1 / 15 ~2.523 ms +XXX[7] TO 17 ms, lFrame0 1 ms, lFrameX 100 / 1481 ~211.599 ms, finishGL 93 / 1255 ~179.308 ms, waitGL 4 / 19 ~2.805 ms +XXX[8] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 1564 ~195.509 ms, finishGL 78 / 1333 ~166.666 ms, waitGL 4 / 23 ~2.965 ms +XXX[9] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 1647 ~183.082 ms, finishGL 78 / 1411 ~156.839 ms, waitGL 4 / 28 ~3.128 ms +XXX[10] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 1730 ~173.057 ms, finishGL 77 / 1489 ~148.941 ms, waitGL 4 / 32 ~3.258 ms +XXX[11] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 1813 ~164.847 ms, finishGL 77 / 1566 ~142.424 ms, waitGL 4 / 37 ~3.391 ms +XXX[12] TO 17 ms, lFrame0 0 ms, lFrameX 100 / 1913 ~159.477 ms, finishGL 93 / 1659 ~138.306 ms, waitGL 6 / 44 ~3.681 ms +XXX[13] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 1996 ~153.553 ms, finishGL 75 / 1735 ~133.48 ms, waitGL 5 / 50 ~3.853 ms +XXX[14] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 2079 ~148.52 ms, finishGL 75 / 1810 ~129.351 ms, waitGL 6 / 56 ~4.045 ms +XXX[15] TO 17 ms, lFrame0 0 ms, lFrameX 100 / 2180 ~145.336 ms, finishGL 90 / 1901 ~126.785 ms, waitGL 9 / 65 ~4.378 ms +XXX[16] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 2262 ~141.415 ms, finishGL 74 / 1976 ~123.506 ms, waitGL 7 / 73 ~4.576 ms +XXX[17] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 2345 ~137.958 ms, finishGL 74 / 2050 ~120.613 ms, waitGL 7 / 80 ~4.751 ms +XXX[18] TO 17 ms, lFrame0 0 ms, lFrameX 100 / 2446 ~135.894 ms, finishGL 90 / 2141 ~118.948 ms, waitGL 9 / 90 ~5.025 ms +XXX[19] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 2528 ~133.085 ms, finishGL 74 / 2215 ~116.618 ms, waitGL 7 / 97 ~5.149 ms +XXX[20] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 2611 ~130.572 ms, finishGL 74 / 2290 ~114.523 ms, waitGL 7 / 105 ~5.273 ms +XXX[21] TO 17 ms, lFrame0 0 ms, lFrameX 100 / 2712 ~129.145 ms, finishGL 91 / 2381 ~113.407 ms, waitGL 9 / 114 ~5.456 ms +XXX[22] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 2794 ~127.016 ms, finishGL 75 / 2456 ~111.662 ms, waitGL 6 / 121 ~5.517 ms +XXX[23] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 2877 ~125.106 ms, finishGL 74 / 2531 ~110.048 ms, waitGL 7 / 129 ~5.619 ms +XXX[24] TO 17 ms, lFrame0 0 ms, lFrameX 100 / 2978 ~124.095 ms, finishGL 86 / 2617 ~109.073 ms, waitGL 13 / 142 ~5.948 ms +XXX[25] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 3061 ~122.451 ms, finishGL 69 / 2687 ~107.499 ms, waitGL 12 / 155 ~6.224 ms +XXX[26] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 3143 ~120.916 ms, finishGL 69 / 2756 ~106.024 ms, waitGL 12 / 168 ~6.469 ms +XXX[27] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 3227 ~119.539 ms, finishGL 68 / 2824 ~104.617 ms, waitGL 15 / 183 ~6.797 ms +XXX[28] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 3310 ~118.236 ms, finishGL 67 / 2891 ~103.284 ms, waitGL 15 / 198 ~7.097 ms +XXX[29] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 3393 ~117.023 ms, finishGL 66 / 2958 ~102.005 ms, waitGL 16 / 214 ~7.411 ms +XXX[30] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 3476 ~115.89 ms, finishGL 65 / 3023 ~100.789 ms, waitGL 16 / 231 ~7.715 ms +XXX[31] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 3543 ~114.294 ms, finishGL 64 / 3088 ~99.614 ms, waitGL 1 / 233 ~7.516 ms +XXX[32] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 3608 ~112.769 ms, finishGL 63 / 3151 ~98.498 ms, waitGL 0 / 233 ~7.311 ms +XXX[33] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 3692 ~111.899 ms, finishGL 79 / 3231 ~97.929 ms, waitGL 3 / 237 ~7.203 ms +XXX[34] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 3758 ~110.539 ms, finishGL 63 / 3295 ~96.913 ms, waitGL 1 / 239 ~7.047 ms +XXX[35] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 3824 ~109.274 ms, finishGL 63 / 3358 ~95.955 ms, waitGL 2 / 241 ~6.908 ms +XXX[36] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 3908 ~108.567 ms, finishGL 78 / 3437 ~95.474 ms, waitGL 4 / 246 ~6.847 ms +XXX[37] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 3974 ~107.41 ms, finishGL 63 / 3500 ~94.603 ms, waitGL 2 / 248 ~6.72 ms +XXX[38] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4040 ~106.341 ms, finishGL 62 / 3562 ~93.755 ms, waitGL 3 / 252 ~6.638 ms +XXX[39] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 4107 ~105.31 ms, finishGL 61 / 3624 ~92.927 ms, waitGL 3 / 255 ~6.558 ms +XXX[40] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 4173 ~104.339 ms, finishGL 61 / 3685 ~92.135 ms, waitGL 4 / 259 ~6.498 ms +XXX[41] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 4240 ~103.417 ms, finishGL 60 / 3746 ~91.37 ms, waitGL 4 / 264 ~6.454 ms +XXX[42] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 4306 ~102.536 ms, finishGL 60 / 3806 ~90.628 ms, waitGL 5 / 269 ~6.424 ms +XXX[43] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 4372 ~101.696 ms, finishGL 60 / 3866 ~89.923 ms, waitGL 5 / 274 ~6.391 ms +XXX[44] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 4439 ~100.895 ms, finishGL 60 / 3926 ~89.245 ms, waitGL 5 / 280 ~6.365 ms +XXX[45] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 4506 ~100.135 ms, finishGL 60 / 3986 ~88.596 ms, waitGL 5 / 285 ~6.349 ms +XXX[46] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 4572 ~99.399 ms, finishGL 59 / 4046 ~87.965 ms, waitGL 5 / 291 ~6.331 ms +XXX[47] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 4639 ~98.711 ms, finishGL 59 / 4106 ~87.361 ms, waitGL 6 / 298 ~6.341 ms +XXX[48] TO 17 ms, lFrame0 1 ms, lFrameX 65 / 4705 ~98.027 ms, finishGL 59 / 4165 ~86.771 ms, waitGL 5 / 303 ~6.329 ms +XXX[49] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4771 ~97.382 ms, finishGL 59 / 4224 ~86.213 ms, waitGL 6 / 310 ~6.329 ms +XXX[50] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 4838 ~96.763 ms, finishGL 59 / 4283 ~85.67 ms, waitGL 6 / 316 ~6.336 ms +XXX[51] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 4904 ~96.166 ms, finishGL 58 / 4342 ~85.145 ms, waitGL 6 / 323 ~6.336 ms +XXX[52] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 4971 ~95.613 ms, finishGL 58 / 4400 ~84.625 ms, waitGL 8 / 331 ~6.383 ms +XXX[53] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5037 ~95.056 ms, finishGL 58 / 4459 ~84.139 ms, waitGL 6 / 338 ~6.389 ms +XXX[54] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5104 ~94.527 ms, finishGL 58 / 4518 ~83.667 ms, waitGL 7 / 345 ~6.407 ms +XXX[55] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 5170 ~94.001 ms, finishGL 58 / 4576 ~83.211 ms, waitGL 6 / 352 ~6.407 ms +XXX[56] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 5236 ~93.515 ms, finishGL 58 / 4635 ~82.77 ms, waitGL 7 / 359 ~6.42 ms +XXX[57] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5303 ~93.048 ms, finishGL 58 / 4693 ~82.348 ms, waitGL 7 / 367 ~6.443 ms +XXX[58] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5370 ~92.591 ms, finishGL 58 / 4752 ~81.938 ms, waitGL 7 / 374 ~6.463 ms +XXX[59] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5436 ~92.142 ms, finishGL 58 / 4811 ~81.548 ms, waitGL 6 / 381 ~6.464 ms +XXX[60] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5502 ~91.713 ms, finishGL 59 / 4870 ~81.18 ms, waitGL 6 / 387 ~6.463 ms +XXX[61] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5569 ~91.299 ms, finishGL 59 / 4930 ~80.821 ms, waitGL 6 / 394 ~6.467 ms +XXX[62] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 5635 ~90.89 ms, finishGL 59 / 4989 ~80.482 ms, waitGL 5 / 400 ~6.453 ms +XXX[63] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5701 ~90.504 ms, finishGL 59 / 5049 ~80.152 ms, waitGL 6 / 406 ~6.449 ms +XXX[64] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5768 ~90.129 ms, finishGL 59 / 5109 ~79.837 ms, waitGL 6 / 412 ~6.444 ms +XXX[65] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5834 ~89.765 ms, finishGL 60 / 5169 ~79.537 ms, waitGL 5 / 417 ~6.429 ms +XXX[66] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5901 ~89.412 ms, finishGL 60 / 5230 ~79.256 ms, waitGL 5 / 422 ~6.408 ms +XXX[67] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5967 ~89.07 ms, finishGL 61 / 5292 ~78.986 ms, waitGL 4 / 427 ~6.386 ms +XXX[68] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6033 ~88.733 ms, finishGL 61 / 5353 ~78.728 ms, waitGL 4 / 432 ~6.353 ms +XXX[69] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6100 ~88.413 ms, finishGL 61 / 5415 ~78.484 ms, waitGL 4 / 436 ~6.323 ms +XXX[70] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 6166 ~88.092 ms, finishGL 62 / 5477 ~78.254 ms, waitGL 3 / 439 ~6.279 ms +XXX[71] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6233 ~87.802 ms, finishGL 62 / 5540 ~78.028 ms, waitGL 4 / 444 ~6.257 ms +XXX[72] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 6299 ~87.495 ms, finishGL 61 / 5602 ~77.805 ms, waitGL 3 / 447 ~6.216 ms +XXX[73] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6366 ~87.213 ms, finishGL 61 / 5663 ~77.582 ms, waitGL 4 / 452 ~6.199 ms +XXX[74] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 6432 ~86.931 ms, finishGL 60 / 5724 ~77.354 ms, waitGL 4 / 457 ~6.177 ms +XXX[75] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6499 ~86.656 ms, finishGL 60 / 5784 ~77.128 ms, waitGL 5 / 462 ~6.166 ms +XXX[76] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6565 ~86.393 ms, finishGL 59 / 5844 ~76.902 ms, waitGL 6 / 468 ~6.164 ms +XXX[77] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6632 ~86.135 ms, finishGL 60 / 5904 ~76.685 ms, waitGL 5 / 474 ~6.16 ms +XXX[78] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6698 ~85.878 ms, finishGL 60 / 5965 ~76.476 ms, waitGL 5 / 479 ~6.148 ms +XXX[79] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6765 ~85.634 ms, finishGL 60 / 6025 ~76.277 ms, waitGL 5 / 484 ~6.138 ms +XXX[80] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 6831 ~85.388 ms, finishGL 60 / 6086 ~76.083 ms, waitGL 4 / 489 ~6.12 ms +XXX[81] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6898 ~85.162 ms, finishGL 60 / 6147 ~75.896 ms, waitGL 5 / 495 ~6.115 ms +XXX[82] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6964 ~84.932 ms, finishGL 61 / 6209 ~75.721 ms, waitGL 4 / 499 ~6.093 ms +XXX[83] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7030 ~84.709 ms, finishGL 62 / 6271 ~75.56 ms, waitGL 3 / 503 ~6.062 ms +XXX[84] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7097 ~84.491 ms, finishGL 62 / 6333 ~75.399 ms, waitGL 3 / 506 ~6.032 ms +XXX[85] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7163 ~84.28 ms, finishGL 61 / 6395 ~75.241 ms, waitGL 3 / 510 ~6.007 ms +XXX[86] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7230 ~84.076 ms, finishGL 62 / 6458 ~75.095 ms, waitGL 3 / 514 ~5.977 ms +XXX[87] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7296 ~83.87 ms, finishGL 63 / 6521 ~74.958 ms, waitGL 2 / 516 ~5.938 ms +XXX[88] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7363 ~83.676 ms, finishGL 62 / 6584 ~74.819 ms, waitGL 3 / 520 ~5.913 ms +XXX[89] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7430 ~83.483 ms, finishGL 62 / 6646 ~74.684 ms, waitGL 3 / 523 ~5.881 ms +XXX[90] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7496 ~83.293 ms, finishGL 62 / 6709 ~74.544 ms, waitGL 3 / 527 ~5.859 ms +XXX[91] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7562 ~83.108 ms, finishGL 62 / 6771 ~74.411 ms, waitGL 3 / 531 ~5.835 ms +XXX[92] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7629 ~82.927 ms, finishGL 62 / 6833 ~74.281 ms, waitGL 3 / 534 ~5.811 ms +XXX[93] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7695 ~82.751 ms, finishGL 61 / 6895 ~74.146 ms, waitGL 4 / 538 ~5.792 ms +XXX[94] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7762 ~82.579 ms, finishGL 61 / 6957 ~74.016 ms, waitGL 4 / 542 ~5.775 ms +XXX[95] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7828 ~82.408 ms, finishGL 62 / 7019 ~73.893 ms, waitGL 3 / 546 ~5.753 ms +XXX[96] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7895 ~82.243 ms, finishGL 62 / 7081 ~73.769 ms, waitGL 4 / 550 ~5.736 ms +XXX[97] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 7962 ~82.082 ms, finishGL 61 / 7143 ~73.641 ms, waitGL 4 / 555 ~5.727 ms +XXX[98] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8028 ~81.924 ms, finishGL 60 / 7204 ~73.511 ms, waitGL 5 / 560 ~5.721 ms +XXX[99] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8095 ~81.77 ms, finishGL 60 / 7265 ~73.385 ms, waitGL 5 / 566 ~5.717 ms +XXX[1] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 66 ~66.52 ms, finishGL 60 / 60 ~60.267 ms, waitGL 5 / 5 ~5.535 ms +XXX[2] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 132 ~66.402 ms, finishGL 59 / 120 ~60.116 ms, waitGL 5 / 11 ~5.576 ms +XXX[3] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 198 ~66.297 ms, finishGL 59 / 180 ~60.016 ms, waitGL 5 / 16 ~5.646 ms +XXX[4] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 265 ~66.437 ms, finishGL 60 / 240 ~60.014 ms, waitGL 6 / 23 ~5.809 ms +XXX[5] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 332 ~66.458 ms, finishGL 59 / 299 ~59.909 ms, waitGL 6 / 29 ~5.929 ms +XXX[6] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 398 ~66.452 ms, finishGL 59 / 358 ~59.831 ms, waitGL 6 / 36 ~6.026 ms +XXX[7] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 465 ~66.461 ms, finishGL 58 / 417 ~59.693 ms, waitGL 7 / 43 ~6.184 ms +XXX[8] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 531 ~66.442 ms, finishGL 59 / 477 ~59.686 ms, waitGL 6 / 49 ~6.182 ms +XXX[9] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 597 ~66.442 ms, finishGL 59 / 537 ~59.686 ms, waitGL 6 / 55 ~6.196 ms +XXX[10] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 664 ~66.417 ms, finishGL 61 / 598 ~59.828 ms, waitGL 4 / 60 ~6.038 ms +XXX[11] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 730 ~66.425 ms, finishGL 61 / 659 ~59.986 ms, waitGL 4 / 64 ~5.896 ms +XXX[12] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 797 ~66.433 ms, finishGL 60 / 720 ~60.066 ms, waitGL 5 / 69 ~5.826 ms +XXX[13] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 863 ~66.411 ms, finishGL 60 / 780 ~60.063 ms, waitGL 5 / 75 ~5.792 ms +XXX[14] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 930 ~66.443 ms, finishGL 59 / 840 ~60.054 ms, waitGL 6 / 81 ~5.835 ms +XXX[15] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 996 ~66.419 ms, finishGL 59 / 900 ~60.025 ms, waitGL 5 / 87 ~5.845 ms +XXX[16] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1063 ~66.45 ms, finishGL 59 / 959 ~59.969 ms, waitGL 7 / 94 ~5.918 ms +XXX[17] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1129 ~66.444 ms, finishGL 59 / 1018 ~59.933 ms, waitGL 6 / 101 ~5.952 ms +XXX[18] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1195 ~66.444 ms, finishGL 59 / 1078 ~59.91 ms, waitGL 6 / 107 ~5.973 ms +XXX[19] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1262 ~66.438 ms, finishGL 60 / 1138 ~59.931 ms, waitGL 5 / 113 ~5.949 ms +FrameCount: 120 - FrameRate: 15.0 +XXX[20] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1328 ~66.439 ms, finishGL 60 / 1199 ~59.954 ms, waitGL 5 / 118 ~5.924 ms +XXX[21] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1395 ~66.459 ms, finishGL 61 / 1260 ~60.005 ms, waitGL 5 / 123 ~5.898 ms +XXX[22] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 1461 ~66.436 ms, finishGL 61 / 1321 ~60.064 ms, waitGL 3 / 127 ~5.802 ms +XXX[23] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1528 ~66.437 ms, finishGL 62 / 1383 ~60.164 ms, waitGL 3 / 131 ~5.71 ms +XXX[24] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1594 ~66.428 ms, finishGL 62 / 1446 ~60.279 ms, waitGL 2 / 134 ~5.592 ms +XXX[25] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1661 ~66.449 ms, finishGL 62 / 1509 ~60.379 ms, waitGL 3 / 137 ~5.519 ms +XXX[26] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1727 ~66.438 ms, finishGL 63 / 1572 ~60.495 ms, waitGL 2 / 140 ~5.397 ms +XXX[27] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 1794 ~66.47 ms, finishGL 63 / 1636 ~60.62 ms, waitGL 3 / 143 ~5.309 ms +XXX[28] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1860 ~66.46 ms, finishGL 63 / 1699 ~60.705 ms, waitGL 2 / 146 ~5.219 ms +XXX[29] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 1926 ~66.444 ms, finishGL 63 / 1763 ~60.801 ms, waitGL 1 / 148 ~5.106 ms +XXX[30] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 1993 ~66.448 ms, finishGL 63 / 1827 ~60.905 ms, waitGL 2 / 150 ~5.01 ms +XXX[31] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2060 ~66.46 ms, finishGL 63 / 1890 ~60.984 ms, waitGL 3 / 153 ~4.947 ms +XXX[32] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2126 ~66.45 ms, finishGL 63 / 1953 ~61.047 ms, waitGL 2 / 155 ~4.866 ms +XXX[33] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2193 ~66.463 ms, finishGL 62 / 2016 ~61.095 ms, waitGL 3 / 159 ~4.835 ms +XXX[34] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2259 ~66.454 ms, finishGL 62 / 2078 ~61.142 ms, waitGL 2 / 162 ~4.778 ms +XXX[35] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 2326 ~66.477 ms, finishGL 63 / 2142 ~61.22 ms, waitGL 3 / 165 ~4.727 ms +XXX[36] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 2392 ~66.457 ms, finishGL 63 / 2205 ~61.272 ms, waitGL 2 / 167 ~4.658 ms +XXX[37] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2458 ~66.459 ms, finishGL 63 / 2268 ~61.323 ms, waitGL 2 / 170 ~4.611 ms +XXX[38] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2525 ~66.457 ms, finishGL 63 / 2332 ~61.38 ms, waitGL 2 / 173 ~4.556 ms +XXX[39] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2591 ~66.459 ms, finishGL 63 / 2395 ~61.43 ms, waitGL 2 / 175 ~4.508 ms +XXX[40] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2658 ~66.458 ms, finishGL 63 / 2458 ~61.472 ms, waitGL 2 / 178 ~4.467 ms +XXX[41] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2725 ~66.47 ms, finishGL 63 / 2522 ~61.516 ms, waitGL 3 / 181 ~4.438 ms +XXX[42] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2791 ~66.471 ms, finishGL 63 / 2585 ~61.552 ms, waitGL 3 / 185 ~4.405 ms +XXX[43] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2857 ~66.464 ms, finishGL 63 / 2648 ~61.589 ms, waitGL 2 / 187 ~4.364 ms +XXX[44] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2924 ~66.466 ms, finishGL 62 / 2710 ~61.611 ms, waitGL 3 / 191 ~4.346 ms +XXX[45] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 2991 ~66.47 ms, finishGL 61 / 2772 ~61.615 ms, waitGL 4 / 195 ~4.347 ms +XXX[46] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 3058 ~66.48 ms, finishGL 60 / 2833 ~61.592 ms, waitGL 5 / 201 ~4.383 ms +XXX[47] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 3124 ~66.479 ms, finishGL 58 / 2891 ~61.531 ms, waitGL 7 / 208 ~4.444 ms +XXX[48] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 3191 ~66.483 ms, finishGL 56 / 2948 ~61.417 ms, waitGL 10 / 219 ~4.563 ms +XXX[49] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 3257 ~66.482 ms, finishGL 52 / 3000 ~61.228 ms, waitGL 13 / 232 ~4.751 ms +XXX[50] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3307 ~66.146 ms, finishGL 47 / 3047 ~60.945 ms, waitGL 2 / 234 ~4.698 ms +XXX[51] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 3373 ~66.144 ms, finishGL 59 / 3106 ~60.92 ms, waitGL 5 / 240 ~4.721 ms +XXX[52] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3422 ~65.821 ms, finishGL 42 / 3149 ~60.571 ms, waitGL 5 / 246 ~4.737 ms +XXX[53] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 3472 ~65.521 ms, finishGL 41 / 3191 ~60.216 ms, waitGL 7 / 253 ~4.782 ms +XXX[54] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 3539 ~65.552 ms, finishGL 57 / 3248 ~60.158 ms, waitGL 9 / 263 ~4.872 ms +XXX[55] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 3588 ~65.246 ms, finishGL 40 / 3288 ~59.799 ms, waitGL 7 / 270 ~4.925 ms +XXX[56] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 3638 ~64.97 ms, finishGL 40 / 3328 ~59.446 ms, waitGL 8 / 279 ~4.993 ms +XXX[57] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 3705 ~65.014 ms, finishGL 55 / 3384 ~59.376 ms, waitGL 11 / 290 ~5.104 ms +XXX[58] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3755 ~64.75 ms, finishGL 38 / 3423 ~59.018 ms, waitGL 10 / 301 ~5.193 ms +XXX[59] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3805 ~64.497 ms, finishGL 38 / 3461 ~58.667 ms, waitGL 10 / 311 ~5.285 ms +XXX[60] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3855 ~64.251 ms, finishGL 37 / 3499 ~58.319 ms, waitGL 11 / 323 ~5.386 ms +XXX[61] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3904 ~64.014 ms, finishGL 37 / 3536 ~57.97 ms, waitGL 11 / 334 ~5.491 ms +XXX[62] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 3954 ~63.784 ms, finishGL 36 / 3572 ~57.617 ms, waitGL 13 / 348 ~5.613 ms +XXX[63] TO 17 ms, lFrame0 0 ms, lFrameX 48 / 4003 ~63.545 ms, finishGL 34 / 3607 ~57.256 ms, waitGL 13 / 361 ~5.732 ms +XXX[64] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 4053 ~63.336 ms, finishGL 33 / 3640 ~56.886 ms, waitGL 15 / 376 ~5.889 ms +XXX[65] TO 17 ms, lFrame0 1 ms, lFrameX 50 / 4103 ~63.138 ms, finishGL 32 / 3673 ~56.51 ms, waitGL 16 / 393 ~6.059 ms +XXX[66] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 4153 ~62.935 ms, finishGL 31 / 3704 ~56.132 ms, waitGL 17 / 411 ~6.229 ms +XXX[67] TO 17 ms, lFrame0 0 ms, lFrameX 33 / 4186 ~62.489 ms, finishGL 30 / 3735 ~55.75 ms, waitGL 1 / 413 ~6.164 ms +XXX[68] TO 17 ms, lFrame0 0 ms, lFrameX 33 / 4219 ~62.058 ms, finishGL 29 / 3764 ~55.366 ms, waitGL 2 / 415 ~6.117 ms +XXX[69] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 4269 ~61.872 ms, finishGL 44 / 3808 ~55.202 ms, waitGL 4 / 420 ~6.093 ms +XXX[70] TO 17 ms, lFrame0 0 ms, lFrameX 33 / 4302 ~61.462 ms, finishGL 27 / 3836 ~54.811 ms, waitGL 4 / 425 ~6.075 ms +XXX[71] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4335 ~61.06 ms, finishGL 27 / 3864 ~54.424 ms, waitGL 4 / 430 ~6.06 ms +XXX[72] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 4385 ~60.91 ms, finishGL 42 / 3907 ~54.264 ms, waitGL 6 / 437 ~6.071 ms +XXX[73] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4418 ~60.527 ms, finishGL 25 / 3932 ~53.871 ms, waitGL 6 / 443 ~6.078 ms +XXX[74] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4451 ~60.15 ms, finishGL 25 / 3957 ~53.482 ms, waitGL 6 / 450 ~6.088 ms +XXX[75] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 4501 ~60.016 ms, finishGL 40 / 3998 ~53.31 ms, waitGL 9 / 459 ~6.128 ms +XXX[76] TO 17 ms, lFrame0 0 ms, lFrameX 33 / 4534 ~59.662 ms, finishGL 23 / 4021 ~52.916 ms, waitGL 9 / 468 ~6.169 ms +XXX[77] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4567 ~59.314 ms, finishGL 22 / 4044 ~52.527 ms, waitGL 9 / 478 ~6.209 ms +XXX[78] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 4617 ~59.204 ms, finishGL 38 / 4083 ~52.35 ms, waitGL 11 / 489 ~6.278 ms +XXX[79] TO 17 ms, lFrame0 0 ms, lFrameX 33 / 4651 ~58.873 ms, finishGL 23 / 4106 ~51.979 ms, waitGL 9 / 499 ~6.317 ms +XXX[80] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4683 ~58.54 ms, finishGL 23 / 4129 ~51.619 ms, waitGL 8 / 507 ~6.344 ms +XXX[81] TO 17 ms, lFrame0 0 ms, lFrameX 33 / 4716 ~58.226 ms, finishGL 23 / 4152 ~51.269 ms, waitGL 9 / 516 ~6.379 ms +XXX[82] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 4767 ~58.135 ms, finishGL 38 / 4191 ~51.116 ms, waitGL 11 / 528 ~6.439 ms +XXX[83] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4799 ~57.826 ms, finishGL 26 / 4218 ~50.823 ms, waitGL 4 / 532 ~6.421 ms +XXX[84] TO 17 ms, lFrame0 0 ms, lFrameX 32 / 4832 ~57.528 ms, finishGL 30 / 4248 ~50.576 ms, waitGL 2 / 534 ~6.368 ms +XXX[85] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 4882 ~57.437 ms, finishGL 33 / 4281 ~50.375 ms, waitGL 15 / 550 ~6.477 ms +XXX[86] TO 17 ms, lFrame0 1 ms, lFrameX 50 / 4932 ~57.351 ms, finishGL 38 / 4320 ~50.233 ms, waitGL 10 / 561 ~6.527 ms +XXX[87] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 4981 ~57.262 ms, finishGL 40 / 4360 ~50.122 ms, waitGL 7 / 569 ~6.542 ms +XXX[88] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 5031 ~57.177 ms, finishGL 41 / 4402 ~50.023 ms, waitGL 7 / 576 ~6.55 ms +XXX[89] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 5081 ~57.094 ms, finishGL 43 / 4445 ~49.945 ms, waitGL 5 / 582 ~6.539 ms +XXX[90] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 5131 ~57.013 ms, finishGL 42 / 4487 ~49.862 ms, waitGL 6 / 588 ~6.535 ms +XXX[91] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 5181 ~56.934 ms, finishGL 42 / 4530 ~49.786 ms, waitGL 5 / 593 ~6.526 ms +XXX[92] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 5230 ~56.857 ms, finishGL 43 / 4573 ~49.715 ms, waitGL 6 / 600 ~6.522 ms +XXX[93] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 5280 ~56.781 ms, finishGL 42 / 4616 ~49.641 ms, waitGL 6 / 606 ~6.522 ms +XXX[94] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 5330 ~56.708 ms, finishGL 43 / 4660 ~49.575 ms, waitGL 5 / 612 ~6.516 ms +XXX[95] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 5380 ~56.635 ms, finishGL 43 / 4703 ~49.508 ms, waitGL 5 / 617 ~6.505 ms +XXX[96] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 5430 ~56.563 ms, finishGL 43 / 4746 ~49.442 ms, waitGL 5 / 623 ~6.495 ms +XXX[97] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 5480 ~56.494 ms, finishGL 43 / 4790 ~49.383 ms, waitGL 5 / 628 ~6.481 ms +XXX[98] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 5529 ~56.426 ms, finishGL 44 / 4834 ~49.332 ms, waitGL 4 / 633 ~6.459 ms +XXX[99] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 5579 ~56.358 ms, finishGL 44 / 4879 ~49.288 ms, waitGL 4 / 637 ~6.438 ms +XXX[100] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 5629 ~56.293 ms, finishGL 45 / 4925 ~49.253 ms, waitGL 3 / 641 ~6.41 ms +XXX[101] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 5679 ~56.228 ms, finishGL 46 / 4971 ~49.225 ms, waitGL 2 / 643 ~6.369 ms +XXX[102] TO 17 ms, lFrame0 1 ms, lFrameX 50 / 5729 ~56.174 ms, finishGL 47 / 5019 ~49.211 ms, waitGL 1 / 645 ~6.324 ms +XXX[103] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 5812 ~56.428 ms, finishGL 64 / 5084 ~49.365 ms, waitGL 16 / 661 ~6.423 ms +XXX[104] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 5879 ~56.533 ms, finishGL 49 / 5134 ~49.369 ms, waitGL 17 / 678 ~6.526 ms +XXX[105] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 5945 ~56.628 ms, finishGL 51 / 5185 ~49.388 ms, waitGL 14 / 693 ~6.6 ms +XXX[106] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 6011 ~56.711 ms, finishGL 53 / 5239 ~49.428 ms, waitGL 11 / 704 ~6.645 ms +XXX[107] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 6078 ~56.805 ms, finishGL 57 / 5296 ~49.503 ms, waitGL 8 / 712 ~6.659 ms +XXX[108] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6145 ~56.898 ms, finishGL 60 / 5356 ~49.601 ms, waitGL 6 / 718 ~6.656 ms +XXX[109] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6211 ~56.983 ms, finishGL 61 / 5417 ~49.705 ms, waitGL 4 / 723 ~6.638 ms +XXX[110] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6277 ~57.069 ms, finishGL 61 / 5479 ~49.817 ms, waitGL 3 / 727 ~6.613 ms +XXX[111] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6344 ~57.153 ms, finishGL 61 / 5541 ~49.926 ms, waitGL 3 / 731 ~6.589 ms +XXX[112] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6410 ~57.237 ms, finishGL 61 / 5603 ~50.032 ms, waitGL 3 / 735 ~6.565 ms +XXX[113] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6477 ~57.319 ms, finishGL 61 / 5665 ~50.136 ms, waitGL 4 / 739 ~6.543 ms +XXX[114] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 6543 ~57.398 ms, finishGL 63 / 5728 ~50.251 ms, waitGL 2 / 742 ~6.51 ms +XXX[115] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 6610 ~57.483 ms, finishGL 64 / 5793 ~50.374 ms, waitGL 2 / 744 ~6.474 ms +XXX[116] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 6693 ~57.705 ms, finishGL 65 / 5858 ~50.503 ms, waitGL 17 / 762 ~6.569 ms +XXX[117] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 6776 ~57.922 ms, finishGL 65 / 5923 ~50.632 ms, waitGL 16 / 778 ~6.658 ms +XXX[118] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 6859 ~58.133 ms, finishGL 65 / 5989 ~50.755 ms, waitGL 17 / 796 ~6.747 ms +XXX[119] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 6943 ~58.345 ms, finishGL 65 / 6054 ~50.877 ms, waitGL 17 / 813 ~6.838 ms +XXX[120] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 7026 ~58.552 ms, finishGL 66 / 6120 ~51.006 ms, waitGL 16 / 830 ~6.916 ms +XXX[121] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 7109 ~58.754 ms, finishGL 66 / 6187 ~51.135 ms, waitGL 15 / 845 ~6.988 ms +XXX[122] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 7191 ~58.948 ms, finishGL 67 / 6254 ~51.267 ms, waitGL 14 / 860 ~7.051 ms +XXX[123] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 7275 ~59.149 ms, finishGL 69 / 6324 ~51.416 ms, waitGL 13 / 873 ~7.103 ms +XXX[124] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 7357 ~59.338 ms, finishGL 71 / 6395 ~51.578 ms, waitGL 10 / 884 ~7.131 ms +XXX[125] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 7441 ~59.532 ms, finishGL 72 / 6468 ~51.748 ms, waitGL 10 / 894 ~7.157 ms +XXX[126] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 7524 ~59.718 ms, finishGL 74 / 6542 ~51.925 ms, waitGL 8 / 902 ~7.164 ms +XXX[127] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 7607 ~59.901 ms, finishGL 76 / 6618 ~52.116 ms, waitGL 6 / 909 ~7.158 ms +XXX[128] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 7690 ~60.084 ms, finishGL 74 / 6693 ~52.293 ms, waitGL 8 / 917 ~7.164 ms +XXX[129] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 7774 ~60.264 ms, finishGL 72 / 6765 ~52.449 ms, waitGL 10 / 927 ~7.189 ms +2013-06-17 02:52:55.855 java[62619:cc07] Persistent UI failed to open file file://localhost/Users/jogamp/Library/Saved%20Application%20State/com.apple.javajdk16.cmd.savedState/window_1.data: Operation not permitted (1) +XXX[130] TO 17 ms, lFrame0 0 ms, lFrameX 81 / 7855 ~60.427 ms, finishGL 68 / 6834 ~52.574 ms, waitGL 12 / 939 ~7.228 ms +XXX[131] TO 17 ms, lFrame0 1 ms, lFrameX 82 / 7937 ~60.593 ms, finishGL 68 / 6903 ~52.696 ms, waitGL 12 / 952 ~7.267 ms +XXX[132] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 8020 ~60.763 ms, finishGL 67 / 6970 ~52.805 ms, waitGL 14 / 966 ~7.325 ms +XXX[133] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 8104 ~60.932 ms, finishGL 65 / 7035 ~52.899 ms, waitGL 16 / 983 ~7.396 ms +XXX[134] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8170 ~60.973 ms, finishGL 64 / 7100 ~52.987 ms, waitGL 1 / 984 ~7.348 ms +XXX[135] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 8254 ~61.144 ms, finishGL 81 / 7181 ~53.199 ms, waitGL 2 / 986 ~7.309 ms +XXX[136] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 8337 ~61.305 ms, finishGL 80 / 7262 ~53.397 ms, waitGL 2 / 989 ~7.274 ms +XXX[137] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8404 ~61.343 ms, finishGL 63 / 7325 ~53.474 ms, waitGL 1 / 990 ~7.232 ms +XXX[138] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 8487 ~61.501 ms, finishGL 79 / 7405 ~53.662 ms, waitGL 3 / 994 ~7.203 ms +XXX[139] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 8553 ~61.532 ms, finishGL 63 / 7469 ~53.737 ms, waitGL 1 / 995 ~7.16 ms +FrameCount: 240 - FrameRate: 13.0 +XXX[140] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8619 ~61.565 ms, finishGL 62 / 7532 ~53.8 ms, waitGL 2 / 997 ~7.127 ms +XXX[141] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 8702 ~61.722 ms, finishGL 79 / 7611 ~53.984 ms, waitGL 3 / 1001 ~7.1 ms +XXX[142] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 8769 ~61.753 ms, finishGL 63 / 7674 ~54.047 ms, waitGL 2 / 1003 ~7.066 ms +XXX[143] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 8835 ~61.786 ms, finishGL 62 / 7737 ~54.106 ms, waitGL 2 / 1006 ~7.036 ms +XXX[144] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 8902 ~61.819 ms, finishGL 62 / 7799 ~54.164 ms, waitGL 2 / 1009 ~7.008 ms +XXX[145] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 8968 ~61.851 ms, finishGL 61 / 7861 ~54.215 ms, waitGL 3 / 1012 ~6.986 ms +XXX[146] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9034 ~61.883 ms, finishGL 61 / 7922 ~54.264 ms, waitGL 4 / 1017 ~6.97 ms +XXX[147] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9101 ~61.914 ms, finishGL 61 / 7983 ~54.312 ms, waitGL 4 / 1022 ~6.952 ms +XXX[148] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 9168 ~61.946 ms, finishGL 61 / 8045 ~54.359 ms, waitGL 4 / 1026 ~6.933 ms +XXX[149] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9234 ~61.976 ms, finishGL 61 / 8106 ~54.406 ms, waitGL 4 / 1030 ~6.918 ms +XXX[150] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9301 ~62.007 ms, finishGL 61 / 8167 ~54.451 ms, waitGL 5 / 1035 ~6.905 ms +XXX[151] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9367 ~62.036 ms, finishGL 60 / 8228 ~54.492 ms, waitGL 5 / 1040 ~6.893 ms +XXX[152] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 9433 ~62.065 ms, finishGL 61 / 8289 ~54.535 ms, waitGL 4 / 1045 ~6.876 ms +XXX[153] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 9500 ~62.093 ms, finishGL 61 / 8350 ~54.579 ms, waitGL 4 / 1049 ~6.857 ms +XXX[154] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 9566 ~62.122 ms, finishGL 60 / 8411 ~54.618 ms, waitGL 4 / 1054 ~6.844 ms +XXX[155] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9633 ~62.15 ms, finishGL 61 / 8472 ~54.66 ms, waitGL 4 / 1058 ~6.829 ms +XXX[156] TO 17 ms, lFrame0 1 ms, lFrameX 67 / 9700 ~62.184 ms, finishGL 61 / 8533 ~54.702 ms, waitGL 5 / 1063 ~6.818 ms +XXX[157] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 9766 ~62.208 ms, finishGL 60 / 8594 ~54.741 ms, waitGL 4 / 1068 ~6.805 ms +XXX[158] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9833 ~62.235 ms, finishGL 60 / 8654 ~54.777 ms, waitGL 5 / 1073 ~6.797 ms +XXX[159] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9899 ~62.259 ms, finishGL 60 / 8715 ~54.814 ms, waitGL 4 / 1078 ~6.783 ms +XXX[160] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 9965 ~62.286 ms, finishGL 60 / 8775 ~54.848 ms, waitGL 5 / 1084 ~6.777 ms +XXX[161] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 10032 ~62.316 ms, finishGL 59 / 8835 ~54.88 ms, waitGL 6 / 1091 ~6.777 ms +XXX[162] TO 17 ms, lFrame0 1 ms, lFrameX 65 / 10098 ~62.338 ms, finishGL 58 / 8894 ~54.904 ms, waitGL 6 / 1097 ~6.772 ms +XXX[163] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 10165 ~62.367 ms, finishGL 58 / 8952 ~54.926 ms, waitGL 8 / 1105 ~6.78 ms +XXX[164] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10232 ~62.392 ms, finishGL 58 / 9011 ~54.946 ms, waitGL 7 / 1112 ~6.785 ms +XXX[165] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10298 ~62.416 ms, finishGL 58 / 9069 ~54.966 ms, waitGL 7 / 1120 ~6.791 ms +XXX[166] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10365 ~62.441 ms, finishGL 58 / 9127 ~54.985 ms, waitGL 7 / 1128 ~6.797 ms +XXX[167] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10431 ~62.465 ms, finishGL 57 / 9185 ~55.003 ms, waitGL 8 / 1136 ~6.805 ms +XXX[168] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10498 ~62.488 ms, finishGL 57 / 9243 ~55.02 ms, waitGL 7 / 1144 ~6.811 ms +XXX[169] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10564 ~62.511 ms, finishGL 58 / 9301 ~55.039 ms, waitGL 7 / 1151 ~6.815 ms +XXX[170] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10630 ~62.534 ms, finishGL 58 / 9360 ~55.059 ms, waitGL 7 / 1159 ~6.819 ms +XXX[171] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10697 ~62.557 ms, finishGL 58 / 9418 ~55.079 ms, waitGL 7 / 1166 ~6.822 ms +XXX[172] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10763 ~62.579 ms, finishGL 58 / 9477 ~55.1 ms, waitGL 7 / 1173 ~6.824 ms +XXX[173] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10829 ~62.6 ms, finishGL 59 / 9536 ~55.125 ms, waitGL 6 / 1180 ~6.82 ms +XXX[174] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10896 ~62.622 ms, finishGL 59 / 9596 ~55.151 ms, waitGL 6 / 1186 ~6.818 ms +XXX[175] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 10963 ~62.646 ms, finishGL 59 / 9655 ~55.174 ms, waitGL 6 / 1193 ~6.817 ms +XXX[176] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 11028 ~62.664 ms, finishGL 59 / 9715 ~55.199 ms, waitGL 5 / 1198 ~6.811 ms +XXX[177] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 11095 ~62.689 ms, finishGL 59 / 9774 ~55.222 ms, waitGL 7 / 1206 ~6.813 ms +XXX[178] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 11162 ~62.708 ms, finishGL 60 / 9834 ~55.252 ms, waitGL 4 / 1211 ~6.803 ms +XXX[179] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 11228 ~62.73 ms, finishGL 61 / 9896 ~55.287 ms, waitGL 4 / 1215 ~6.791 ms +XXX[180] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 11294 ~62.749 ms, finishGL 62 / 9958 ~55.327 ms, waitGL 3 / 1218 ~6.77 ms +XXX[181] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 11361 ~62.77 ms, finishGL 63 / 10022 ~55.37 ms, waitGL 3 / 1221 ~6.75 ms +XXX[182] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 11428 ~62.793 ms, finishGL 64 / 10086 ~55.418 ms, waitGL 2 / 1224 ~6.725 ms +XXX[183] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 11510 ~62.899 ms, finishGL 64 / 10150 ~55.469 ms, waitGL 16 / 1240 ~6.779 ms +XXX[184] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 11593 ~63.01 ms, finishGL 82 / 10233 ~55.615 ms, waitGL 0 / 1240 ~6.744 ms +XXX[185] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 11677 ~63.119 ms, finishGL 68 / 10301 ~55.685 ms, waitGL 14 / 1255 ~6.784 ms +XXX[186] TO 17 ms, lFrame0 0 ms, lFrameX 100 / 11777 ~63.322 ms, finishGL 86 / 10388 ~55.85 ms, waitGL 13 / 1268 ~6.821 ms +XXX[187] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 11860 ~63.427 ms, finishGL 74 / 10462 ~55.951 ms, waitGL 7 / 1276 ~6.827 ms +XXX[188] TO 17 ms, lFrame0 1 ms, lFrameX 82 / 11943 ~63.527 ms, finishGL 77 / 10540 ~56.066 ms, waitGL 3 / 1280 ~6.811 ms +XXX[189] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 12043 ~63.72 ms, finishGL 94 / 10635 ~56.269 ms, waitGL 4 / 1285 ~6.799 ms +XXX[190] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 12126 ~63.823 ms, finishGL 79 / 10714 ~56.39 ms, waitGL 2 / 1287 ~6.778 ms +XXX[191] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 12209 ~63.924 ms, finishGL 80 / 10794 ~56.515 ms, waitGL 2 / 1290 ~6.756 ms +XXX[192] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 12293 ~64.027 ms, finishGL 79 / 10873 ~56.633 ms, waitGL 3 / 1293 ~6.739 ms +XXX[193] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 12376 ~64.128 ms, finishGL 80 / 10954 ~56.759 ms, waitGL 2 / 1295 ~6.714 ms +XXX[194] TO 17 ms, lFrame0 0 ms, lFrameX 98 / 12475 ~64.308 ms, finishGL 97 / 11051 ~56.968 ms, waitGL 1 / 1296 ~6.685 ms +XXX[195] TO 17 ms, lFrame0 0 ms, lFrameX 100 / 12576 ~64.495 ms, finishGL 97 / 11149 ~57.177 ms, waitGL 2 / 1299 ~6.664 ms +XXX[196] TO 17 ms, lFrame0 0 ms, lFrameX 98 / 12675 ~64.67 ms, finishGL 95 / 11244 ~57.372 ms, waitGL 3 / 1302 ~6.645 ms +XXX[197] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 12758 ~64.764 ms, finishGL 77 / 11322 ~57.474 ms, waitGL 4 / 1307 ~6.635 ms +XXX[198] TO 17 ms, lFrame0 1 ms, lFrameX 84 / 12842 ~64.862 ms, finishGL 77 / 11399 ~57.573 ms, waitGL 5 / 1313 ~6.632 ms +XXX[199] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 12925 ~64.952 ms, finishGL 76 / 11475 ~57.667 ms, waitGL 5 / 1319 ~6.628 ms +XXX[200] TO 17 ms, lFrame0 1 ms, lFrameX 82 / 13008 ~65.04 ms, finishGL 76 / 11552 ~57.762 ms, waitGL 4 / 1324 ~6.62 ms +XXX[201] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 13091 ~65.131 ms, finishGL 77 / 11629 ~57.859 ms, waitGL 5 / 1329 ~6.613 ms +XXX[202] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 13174 ~65.22 ms, finishGL 77 / 11706 ~57.954 ms, waitGL 5 / 1334 ~6.608 ms +XXX[203] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 13257 ~65.309 ms, finishGL 76 / 11783 ~58.046 ms, waitGL 5 / 1340 ~6.602 ms +XXX[204] TO 17 ms, lFrame0 2 ms, lFrameX 83 / 13341 ~65.397 ms, finishGL 76 / 11859 ~58.135 ms, waitGL 4 / 1345 ~6.593 ms +XXX[205] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 13424 ~65.483 ms, finishGL 75 / 11934 ~58.219 ms, waitGL 6 / 1351 ~6.594 ms +XXX[206] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 13507 ~65.569 ms, finishGL 74 / 12009 ~58.299 ms, waitGL 8 / 1359 ~6.601 ms +XXX[207] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 13590 ~65.654 ms, finishGL 73 / 12083 ~58.373 ms, waitGL 9 / 1368 ~6.613 ms +XXX[208] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 13673 ~65.738 ms, finishGL 71 / 12155 ~58.439 ms, waitGL 10 / 1379 ~6.632 ms +XXX[209] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 13756 ~65.822 ms, finishGL 70 / 12225 ~58.497 ms, waitGL 11 / 1391 ~6.655 ms +XXX[210] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 13839 ~65.904 ms, finishGL 68 / 12294 ~58.546 ms, waitGL 13 / 1404 ~6.688 ms +XXX[211] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 13923 ~65.986 ms, finishGL 67 / 12362 ~58.588 ms, waitGL 14 / 1419 ~6.726 ms +XXX[212] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 14006 ~66.067 ms, finishGL 65 / 12428 ~58.623 ms, waitGL 16 / 1435 ~6.772 ms +XXX[213] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 14073 ~66.073 ms, finishGL 64 / 12492 ~58.65 ms, waitGL 2 / 1437 ~6.75 ms +XXX[214] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 14155 ~66.148 ms, finishGL 80 / 12572 ~58.75 ms, waitGL 1 / 1439 ~6.726 ms +XXX[215] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 14222 ~66.15 ms, finishGL 63 / 12636 ~58.772 ms, waitGL 2 / 1441 ~6.705 ms +XXX[216] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 14289 ~66.152 ms, finishGL 63 / 12699 ~58.795 ms, waitGL 2 / 1443 ~6.684 ms +XXX[217] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 14356 ~66.158 ms, finishGL 63 / 12763 ~58.819 ms, waitGL 2 / 1446 ~6.667 ms +XXX[218] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 14439 ~66.236 ms, finishGL 65 / 12829 ~58.85 ms, waitGL 16 / 1463 ~6.715 ms +XXX[219] TO 17 ms, lFrame0 1 ms, lFrameX 82 / 14521 ~66.308 ms, finishGL 68 / 12898 ~58.896 ms, waitGL 12 / 1475 ~6.739 ms +XXX[220] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 14604 ~66.384 ms, finishGL 71 / 12969 ~58.951 ms, waitGL 11 / 1486 ~6.758 ms +XXX[221] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 14687 ~66.46 ms, finishGL 73 / 13042 ~59.017 ms, waitGL 8 / 1495 ~6.766 ms +XXX[222] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 14770 ~66.535 ms, finishGL 76 / 13118 ~59.094 ms, waitGL 5 / 1501 ~6.763 ms +XXX[223] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 14854 ~66.61 ms, finishGL 76 / 13195 ~59.173 ms, waitGL 5 / 1506 ~6.755 ms +XXX[224] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 14937 ~66.683 ms, finishGL 76 / 13272 ~59.252 ms, waitGL 5 / 1512 ~6.751 ms +XXX[225] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 15021 ~66.761 ms, finishGL 76 / 13349 ~59.33 ms, waitGL 6 / 1518 ~6.75 ms +XXX[226] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 15104 ~66.834 ms, finishGL 75 / 13424 ~59.401 ms, waitGL 7 / 1526 ~6.753 ms +XXX[227] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 15186 ~66.902 ms, finishGL 75 / 13499 ~59.47 ms, waitGL 6 / 1532 ~6.751 ms +XXX[228] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 15270 ~66.973 ms, finishGL 74 / 13574 ~59.537 ms, waitGL 7 / 1539 ~6.753 ms +XXX[229] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 15353 ~67.044 ms, finishGL 73 / 13648 ~59.6 ms, waitGL 8 / 1547 ~6.759 ms +XXX[230] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 15436 ~67.114 ms, finishGL 73 / 13721 ~59.658 ms, waitGL 9 / 1556 ~6.769 ms +XXX[231] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 15519 ~67.183 ms, finishGL 72 / 13793 ~59.714 ms, waitGL 9 / 1566 ~6.781 ms +XXX[232] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 15602 ~67.253 ms, finishGL 70 / 13864 ~59.761 ms, waitGL 11 / 1578 ~6.802 ms +XXX[233] TO 17 ms, lFrame0 1 ms, lFrameX 82 / 15685 ~67.32 ms, finishGL 69 / 13933 ~59.801 ms, waitGL 12 / 1590 ~6.827 ms +XXX[234] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 15768 ~67.388 ms, finishGL 67 / 14001 ~59.836 ms, waitGL 14 / 1605 ~6.86 ms +XXX[235] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 15852 ~67.456 ms, finishGL 66 / 14067 ~59.863 ms, waitGL 15 / 1621 ~6.899 ms +XXX[236] TO 17 ms, lFrame0 1 ms, lFrameX 67 / 15919 ~67.455 ms, finishGL 65 / 14133 ~59.885 ms, waitGL 1 / 1622 ~6.874 ms +XXX[237] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 16001 ~67.518 ms, finishGL 79 / 14212 ~59.967 ms, waitGL 2 / 1624 ~6.854 ms +XXX[238] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 16068 ~67.513 ms, finishGL 63 / 14275 ~59.98 ms, waitGL 2 / 1627 ~6.836 ms +XXX[239] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 16134 ~67.509 ms, finishGL 63 / 14338 ~59.994 ms, waitGL 2 / 1629 ~6.817 ms +XXX[240] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 16201 ~67.505 ms, finishGL 62 / 14401 ~60.006 ms, waitGL 2 / 1631 ~6.799 ms +XXX[241] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 16267 ~67.5 ms, finishGL 63 / 14464 ~60.019 ms, waitGL 2 / 1633 ~6.779 ms +XXX[242] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 16334 ~67.497 ms, finishGL 62 / 14527 ~60.03 ms, waitGL 2 / 1636 ~6.762 ms +XXX[243] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 16400 ~67.492 ms, finishGL 62 / 14590 ~60.042 ms, waitGL 2 / 1639 ~6.745 ms +XXX[244] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 16467 ~67.488 ms, finishGL 62 / 14652 ~60.05 ms, waitGL 3 / 1642 ~6.73 ms +XXX[245] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 16533 ~67.484 ms, finishGL 61 / 14713 ~60.056 ms, waitGL 4 / 1646 ~6.721 ms +XXX[246] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 16600 ~67.48 ms, finishGL 61 / 14775 ~60.063 ms, waitGL 3 / 1650 ~6.708 ms +XXX[247] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 16666 ~67.476 ms, finishGL 61 / 14837 ~60.07 ms, waitGL 3 / 1653 ~6.695 ms +XXX[248] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 16733 ~67.472 ms, finishGL 62 / 14899 ~60.08 ms, waitGL 2 / 1656 ~6.68 ms +XXX[249] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 16799 ~67.468 ms, finishGL 63 / 14963 ~60.093 ms, waitGL 1 / 1658 ~6.661 ms +XXX[250] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 16866 ~67.464 ms, finishGL 64 / 15027 ~60.11 ms, waitGL 1 / 1660 ~6.64 ms +XXX[251] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 16966 ~67.593 ms, finishGL 82 / 15110 ~60.201 ms, waitGL 16 / 1676 ~6.679 ms +XXX[252] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 17049 ~67.655 ms, finishGL 68 / 15178 ~60.233 ms, waitGL 14 / 1690 ~6.709 ms +XXX[253] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 17132 ~67.717 ms, finishGL 69 / 15248 ~60.271 ms, waitGL 12 / 1703 ~6.731 ms +XXX[254] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 17215 ~67.779 ms, finishGL 72 / 15320 ~60.317 ms, waitGL 10 / 1713 ~6.746 ms +XXX[255] TO 17 ms, lFrame0 1 ms, lFrameX 82 / 17298 ~67.838 ms, finishGL 73 / 15393 ~60.367 ms, waitGL 8 / 1722 ~6.753 ms +XXX[256] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 17381 ~67.898 ms, finishGL 75 / 15468 ~60.425 ms, waitGL 7 / 1729 ~6.756 ms +XXX[257] TO 17 ms, lFrame0 1 ms, lFrameX 84 / 17466 ~67.961 ms, finishGL 76 / 15545 ~60.487 ms, waitGL 6 / 1736 ~6.755 ms +XXX[258] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 17548 ~68.018 ms, finishGL 76 / 15622 ~60.55 ms, waitGL 5 / 1741 ~6.75 ms +XXX[259] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 17632 ~68.078 ms, finishGL 78 / 15700 ~60.619 ms, waitGL 4 / 1745 ~6.74 ms +FrameCount: 360 - FrameRate: 13.0 +XXX[260] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 17714 ~68.134 ms, finishGL 78 / 15778 ~60.687 ms, waitGL 3 / 1749 ~6.729 ms +XXX[261] TO 17 ms, lFrame0 1 ms, lFrameX 82 / 17797 ~68.19 ms, finishGL 78 / 15857 ~60.756 ms, waitGL 3 / 1752 ~6.715 ms +XXX[262] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 17881 ~68.248 ms, finishGL 78 / 15936 ~60.825 ms, waitGL 3 / 1756 ~6.704 ms +XXX[263] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 17964 ~68.304 ms, finishGL 78 / 16015 ~60.894 ms, waitGL 3 / 1760 ~6.693 ms +XXX[264] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 18047 ~68.36 ms, finishGL 77 / 16093 ~60.958 ms, waitGL 4 / 1764 ~6.685 ms +XXX[265] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 18130 ~68.417 ms, finishGL 77 / 16170 ~61.02 ms, waitGL 5 / 1770 ~6.679 ms +XXX[266] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 18214 ~68.475 ms, finishGL 76 / 16247 ~61.08 ms, waitGL 6 / 1776 ~6.679 ms +XXX[267] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 18296 ~68.527 ms, finishGL 75 / 16323 ~61.136 ms, waitGL 5 / 1782 ~6.675 ms +XXX[268] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 18380 ~68.582 ms, finishGL 75 / 16399 ~61.19 ms, waitGL 6 / 1788 ~6.674 ms +XXX[269] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 18463 ~68.636 ms, finishGL 74 / 16473 ~61.241 ms, waitGL 7 / 1796 ~6.678 ms +XXX[270] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 18546 ~68.692 ms, finishGL 74 / 16548 ~61.289 ms, waitGL 8 / 1805 ~6.685 ms +XXX[271] TO 17 ms, lFrame0 1 ms, lFrameX 82 / 18629 ~68.744 ms, finishGL 71 / 16619 ~61.327 ms, waitGL 10 / 1815 ~6.697 ms +XXX[272] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 18712 ~68.797 ms, finishGL 70 / 16690 ~61.362 ms, waitGL 11 / 1826 ~6.715 ms +XXX[273] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 18796 ~68.849 ms, finishGL 70 / 16760 ~61.394 ms, waitGL 12 / 1838 ~6.735 ms +XXX[274] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 18879 ~68.902 ms, finishGL 68 / 16829 ~61.42 ms, waitGL 13 / 1852 ~6.76 ms +XXX[275] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 18962 ~68.954 ms, finishGL 68 / 16897 ~61.444 ms, waitGL 14 / 1866 ~6.787 ms +XXX[276] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 19045 ~69.006 ms, finishGL 67 / 16964 ~61.465 ms, waitGL 14 / 1881 ~6.816 ms +XXX[277] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 19128 ~69.056 ms, finishGL 66 / 17030 ~61.483 ms, waitGL 15 / 1897 ~6.849 ms +XXX[278] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 19211 ~69.107 ms, finishGL 66 / 17096 ~61.499 ms, waitGL 16 / 1913 ~6.884 ms +XXX[279] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 19278 ~69.098 ms, finishGL 64 / 17161 ~61.512 ms, waitGL 0 / 1914 ~6.86 ms +XXX[280] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 19361 ~69.148 ms, finishGL 81 / 17243 ~61.584 ms, waitGL 1 / 1915 ~6.839 ms +XXX[281] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 19444 ~69.197 ms, finishGL 80 / 17324 ~61.652 ms, waitGL 1 / 1916 ~6.821 ms +XXX[282] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 19511 ~69.188 ms, finishGL 63 / 17387 ~61.659 ms, waitGL 2 / 1919 ~6.805 ms +XXX[283] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 19577 ~69.178 ms, finishGL 62 / 17450 ~61.662 ms, waitGL 3 / 1922 ~6.792 ms +XXX[284] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 19644 ~69.169 ms, finishGL 61 / 17512 ~61.662 ms, waitGL 4 / 1926 ~6.784 ms +XXX[285] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 19710 ~69.16 ms, finishGL 60 / 17573 ~61.659 ms, waitGL 5 / 1932 ~6.779 ms +XXX[286] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 19777 ~69.15 ms, finishGL 59 / 17632 ~61.651 ms, waitGL 5 / 1938 ~6.776 ms +XXX[287] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 19843 ~69.142 ms, finishGL 58 / 17690 ~61.639 ms, waitGL 7 / 1945 ~6.777 ms +XXX[288] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 19910 ~69.132 ms, finishGL 57 / 17748 ~61.625 ms, waitGL 7 / 1952 ~6.78 ms +XXX[289] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 19976 ~69.122 ms, finishGL 56 / 17804 ~61.607 ms, waitGL 8 / 1961 ~6.787 ms +XXX[290] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20043 ~69.115 ms, finishGL 54 / 17859 ~61.583 ms, waitGL 11 / 1973 ~6.804 ms +XXX[291] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 20109 ~69.105 ms, finishGL 53 / 17912 ~61.555 ms, waitGL 11 / 1984 ~6.821 ms +XXX[292] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20176 ~69.096 ms, finishGL 52 / 17965 ~61.525 ms, waitGL 13 / 1997 ~6.842 ms +XXX[293] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 20242 ~69.087 ms, finishGL 51 / 18017 ~61.492 ms, waitGL 13 / 2011 ~6.864 ms +XXX[294] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 20308 ~69.078 ms, finishGL 51 / 18068 ~61.457 ms, waitGL 13 / 2025 ~6.888 ms +XXX[295] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 20375 ~69.069 ms, finishGL 50 / 18119 ~61.42 ms, waitGL 14 / 2040 ~6.915 ms +XXX[296] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 20442 ~69.061 ms, finishGL 49 / 18169 ~61.381 ms, waitGL 15 / 2055 ~6.945 ms +XXX[297] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 20508 ~69.052 ms, finishGL 49 / 18218 ~61.341 ms, waitGL 15 / 2071 ~6.975 ms +XXX[298] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 20575 ~69.043 ms, finishGL 49 / 18267 ~61.3 ms, waitGL 16 / 2087 ~7.006 ms +XXX[299] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 20641 ~69.035 ms, finishGL 49 / 18316 ~61.26 ms, waitGL 15 / 2103 ~7.036 ms +XXX[300] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 20707 ~69.026 ms, finishGL 49 / 18366 ~61.222 ms, waitGL 15 / 2119 ~7.064 ms +XXX[301] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 20774 ~69.018 ms, finishGL 51 / 18417 ~61.188 ms, waitGL 14 / 2133 ~7.088 ms +XXX[302] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 20840 ~69.009 ms, finishGL 51 / 18469 ~61.156 ms, waitGL 13 / 2147 ~7.111 ms +XXX[303] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 20907 ~69.001 ms, finishGL 52 / 18522 ~61.129 ms, waitGL 12 / 2160 ~7.128 ms +XXX[304] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 20973 ~68.993 ms, finishGL 55 / 18577 ~61.109 ms, waitGL 10 / 2170 ~7.139 ms +XXX[305] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 21040 ~68.985 ms, finishGL 57 / 18634 ~61.097 ms, waitGL 8 / 2178 ~7.143 ms +XXX[306] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 21106 ~68.977 ms, finishGL 60 / 18694 ~61.094 ms, waitGL 5 / 2183 ~7.136 ms +XXX[307] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 21173 ~68.968 ms, finishGL 65 / 18760 ~61.107 ms, waitGL 0 / 2184 ~7.114 ms +XXX[308] TO 17 ms, lFrame0 0 ms, lFrameX 99 / 21273 ~69.069 ms, finishGL 87 / 18847 ~61.192 ms, waitGL 12 / 2196 ~7.13 ms +XXX[309] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 21356 ~69.114 ms, finishGL 74 / 18922 ~61.236 ms, waitGL 7 / 2203 ~7.131 ms +XXX[310] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 21439 ~69.16 ms, finishGL 76 / 18998 ~61.286 ms, waitGL 5 / 2208 ~7.125 ms +XXX[311] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 21522 ~69.205 ms, finishGL 78 / 19077 ~61.341 ms, waitGL 3 / 2212 ~7.113 ms +XXX[312] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 21606 ~69.25 ms, finishGL 79 / 19156 ~61.398 ms, waitGL 3 / 2215 ~7.101 ms +XXX[313] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 21689 ~69.294 ms, finishGL 78 / 19235 ~61.454 ms, waitGL 3 / 2218 ~7.088 ms +XXX[314] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 21772 ~69.338 ms, finishGL 78 / 19313 ~61.509 ms, waitGL 3 / 2222 ~7.076 ms +XXX[315] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 21855 ~69.382 ms, finishGL 79 / 19393 ~61.565 ms, waitGL 3 / 2225 ~7.064 ms +XXX[316] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 21938 ~69.426 ms, finishGL 80 / 19473 ~61.624 ms, waitGL 1 / 2226 ~7.046 ms +XXX[317] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 22022 ~69.471 ms, finishGL 81 / 19554 ~61.687 ms, waitGL 1 / 2228 ~7.029 ms +XXX[318] TO 17 ms, lFrame0 0 ms, lFrameX 115 / 22138 ~69.617 ms, finishGL 98 / 19653 ~61.802 ms, waitGL 16 / 2245 ~7.059 ms +XXX[319] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22221 ~69.659 ms, finishGL 80 / 19734 ~61.862 ms, waitGL 1 / 2246 ~7.042 ms +XXX[320] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 22304 ~69.702 ms, finishGL 79 / 19814 ~61.919 ms, waitGL 2 / 2248 ~7.027 ms +XXX[321] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22387 ~69.744 ms, finishGL 79 / 19893 ~61.973 ms, waitGL 3 / 2251 ~7.015 ms +XXX[322] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22471 ~69.786 ms, finishGL 79 / 19972 ~62.026 ms, waitGL 3 / 2255 ~7.005 ms +XXX[323] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 22554 ~69.827 ms, finishGL 78 / 20050 ~62.077 ms, waitGL 3 / 2259 ~6.994 ms +XXX[324] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 22637 ~69.868 ms, finishGL 78 / 20129 ~62.128 ms, waitGL 3 / 2262 ~6.982 ms +XXX[325] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 22720 ~69.909 ms, finishGL 78 / 20207 ~62.178 ms, waitGL 3 / 2266 ~6.972 ms +XXX[326] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 22803 ~69.95 ms, finishGL 78 / 20286 ~62.227 ms, waitGL 3 / 2269 ~6.962 ms +XXX[327] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 22887 ~69.991 ms, finishGL 78 / 20365 ~62.278 ms, waitGL 4 / 2274 ~6.954 ms +XXX[328] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 22970 ~70.031 ms, finishGL 79 / 20444 ~62.33 ms, waitGL 3 / 2277 ~6.942 ms +XXX[329] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 23053 ~70.07 ms, finishGL 78 / 20522 ~62.379 ms, waitGL 3 / 2280 ~6.931 ms +XXX[330] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 23136 ~70.11 ms, finishGL 79 / 20602 ~62.432 ms, waitGL 2 / 2282 ~6.917 ms +XXX[331] TO 17 ms, lFrame0 1 ms, lFrameX 84 / 23220 ~70.152 ms, finishGL 79 / 20681 ~62.483 ms, waitGL 3 / 2286 ~6.907 ms +XXX[332] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23302 ~70.189 ms, finishGL 79 / 20761 ~62.535 ms, waitGL 2 / 2288 ~6.893 ms +XXX[333] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23386 ~70.229 ms, finishGL 80 / 20842 ~62.589 ms, waitGL 2 / 2290 ~6.879 ms +XXX[334] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 23469 ~70.267 ms, finishGL 80 / 20922 ~62.641 ms, waitGL 2 / 2293 ~6.866 ms +XXX[335] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 23552 ~70.305 ms, finishGL 79 / 21002 ~62.693 ms, waitGL 2 / 2295 ~6.852 ms +XXX[336] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 23635 ~70.344 ms, finishGL 79 / 21081 ~62.742 ms, waitGL 2 / 2298 ~6.841 ms +XXX[337] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 23718 ~70.382 ms, finishGL 78 / 21160 ~62.79 ms, waitGL 3 / 2301 ~6.83 ms +XXX[338] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23802 ~70.421 ms, finishGL 77 / 21238 ~62.834 ms, waitGL 5 / 2307 ~6.826 ms +XXX[339] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23885 ~70.459 ms, finishGL 76 / 21314 ~62.875 ms, waitGL 5 / 2313 ~6.823 ms +XXX[340] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 23969 ~70.497 ms, finishGL 77 / 21391 ~62.917 ms, waitGL 5 / 2319 ~6.82 ms +XXX[341] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24052 ~70.533 ms, finishGL 77 / 21468 ~62.958 ms, waitGL 5 / 2324 ~6.816 ms +XXX[342] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24135 ~70.57 ms, finishGL 76 / 21545 ~62.998 ms, waitGL 6 / 2330 ~6.814 ms +XXX[343] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24218 ~70.607 ms, finishGL 76 / 21621 ~63.037 ms, waitGL 6 / 2336 ~6.813 ms +XXX[344] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24301 ~70.644 ms, finishGL 76 / 21697 ~63.075 ms, waitGL 6 / 2343 ~6.812 ms +XXX[345] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24384 ~70.68 ms, finishGL 75 / 21773 ~63.112 ms, waitGL 6 / 2350 ~6.812 ms +XXX[346] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24467 ~70.715 ms, finishGL 76 / 21849 ~63.15 ms, waitGL 6 / 2356 ~6.811 ms +XXX[347] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24551 ~70.752 ms, finishGL 75 / 21925 ~63.186 ms, waitGL 7 / 2363 ~6.812 ms +XXX[348] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 24633 ~70.787 ms, finishGL 75 / 22001 ~63.222 ms, waitGL 6 / 2370 ~6.811 ms +XXX[349] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24717 ~70.822 ms, finishGL 75 / 22077 ~63.258 ms, waitGL 6 / 2377 ~6.811 ms +XXX[350] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24800 ~70.857 ms, finishGL 75 / 22153 ~63.295 ms, waitGL 6 / 2383 ~6.811 ms +XXX[351] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24883 ~70.892 ms, finishGL 75 / 22228 ~63.329 ms, waitGL 7 / 2391 ~6.812 ms +XXX[352] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 24966 ~70.927 ms, finishGL 75 / 22304 ~63.365 ms, waitGL 6 / 2397 ~6.812 ms +XXX[353] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25049 ~70.961 ms, finishGL 75 / 22380 ~63.399 ms, waitGL 6 / 2404 ~6.812 ms +XXX[354] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 25131 ~70.993 ms, finishGL 75 / 22456 ~63.435 ms, waitGL 5 / 2410 ~6.809 ms +XXX[355] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25215 ~71.03 ms, finishGL 76 / 22532 ~63.471 ms, waitGL 7 / 2417 ~6.81 ms +XXX[356] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 25298 ~71.062 ms, finishGL 76 / 22608 ~63.507 ms, waitGL 5 / 2423 ~6.807 ms +XXX[357] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25382 ~71.098 ms, finishGL 75 / 22684 ~63.541 ms, waitGL 7 / 2430 ~6.808 ms +XXX[358] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25465 ~71.131 ms, finishGL 76 / 22760 ~63.576 ms, waitGL 6 / 2437 ~6.807 ms +XXX[359] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25548 ~71.164 ms, finishGL 75 / 22836 ~63.61 ms, waitGL 6 / 2443 ~6.807 ms +XXX[360] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25631 ~71.198 ms, finishGL 76 / 22912 ~63.645 ms, waitGL 6 / 2450 ~6.806 ms +XXX[361] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25714 ~71.23 ms, finishGL 76 / 22988 ~63.681 ms, waitGL 5 / 2456 ~6.803 ms +XXX[362] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25797 ~71.263 ms, finishGL 76 / 23065 ~63.715 ms, waitGL 6 / 2462 ~6.803 ms +XXX[363] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 25880 ~71.297 ms, finishGL 76 / 23141 ~63.751 ms, waitGL 6 / 2468 ~6.801 ms +XXX[364] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 25963 ~71.327 ms, finishGL 77 / 23219 ~63.788 ms, waitGL 4 / 2473 ~6.794 ms +XXX[365] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26046 ~71.361 ms, finishGL 78 / 23297 ~63.827 ms, waitGL 5 / 2478 ~6.789 ms +XXX[366] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26129 ~71.393 ms, finishGL 77 / 23374 ~63.865 ms, waitGL 4 / 2483 ~6.784 ms +XXX[367] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26213 ~71.425 ms, finishGL 77 / 23451 ~63.901 ms, waitGL 5 / 2488 ~6.781 ms +XXX[368] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26296 ~71.457 ms, finishGL 77 / 23529 ~63.939 ms, waitGL 4 / 2493 ~6.775 ms +XXX[369] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26379 ~71.489 ms, finishGL 77 / 23607 ~63.977 ms, waitGL 4 / 2498 ~6.77 ms +XXX[370] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26462 ~71.52 ms, finishGL 78 / 23685 ~64.015 ms, waitGL 4 / 2502 ~6.763 ms +XXX[371] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26545 ~71.551 ms, finishGL 77 / 23763 ~64.052 ms, waitGL 4 / 2507 ~6.757 ms +XXX[372] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26628 ~71.583 ms, finishGL 77 / 23841 ~64.089 ms, waitGL 4 / 2512 ~6.753 ms +XXX[373] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26711 ~71.613 ms, finishGL 76 / 23918 ~64.123 ms, waitGL 5 / 2517 ~6.75 ms +XXX[374] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26795 ~71.645 ms, finishGL 76 / 23994 ~64.156 ms, waitGL 6 / 2524 ~6.75 ms +XXX[375] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 26878 ~71.675 ms, finishGL 75 / 24070 ~64.187 ms, waitGL 6 / 2531 ~6.75 ms +XXX[376] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 26961 ~71.706 ms, finishGL 75 / 24145 ~64.217 ms, waitGL 6 / 2538 ~6.75 ms +XXX[377] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27044 ~71.737 ms, finishGL 75 / 24220 ~64.246 ms, waitGL 7 / 2545 ~6.753 ms +XXX[378] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27128 ~71.767 ms, finishGL 75 / 24296 ~64.275 ms, waitGL 7 / 2553 ~6.754 ms +XXX[379] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27211 ~71.797 ms, finishGL 75 / 24371 ~64.303 ms, waitGL 7 / 2560 ~6.757 ms +FrameCount: 480 - FrameRate: 12.0 +XXX[380] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27294 ~71.827 ms, finishGL 74 / 24445 ~64.329 ms, waitGL 8 / 2569 ~6.761 ms +XXX[381] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27377 ~71.856 ms, finishGL 73 / 24518 ~64.353 ms, waitGL 9 / 2578 ~6.767 ms +XXX[382] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27460 ~71.885 ms, finishGL 73 / 24591 ~64.376 ms, waitGL 8 / 2587 ~6.773 ms +XXX[383] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27543 ~71.916 ms, finishGL 73 / 24664 ~64.399 ms, waitGL 9 / 2597 ~6.781 ms +XXX[384] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27626 ~71.945 ms, finishGL 72 / 24737 ~64.419 ms, waitGL 10 / 2607 ~6.79 ms +XXX[385] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27710 ~71.974 ms, finishGL 72 / 24809 ~64.441 ms, waitGL 9 / 2617 ~6.798 ms +XXX[386] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27793 ~72.002 ms, finishGL 73 / 24882 ~64.463 ms, waitGL 9 / 2626 ~6.805 ms +XXX[387] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 27876 ~72.031 ms, finishGL 73 / 24956 ~64.486 ms, waitGL 9 / 2636 ~6.812 ms +XXX[388] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 27959 ~72.059 ms, finishGL 73 / 25029 ~64.51 ms, waitGL 8 / 2644 ~6.816 ms +XXX[389] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28042 ~72.088 ms, finishGL 74 / 25104 ~64.535 ms, waitGL 8 / 2653 ~6.82 ms +XXX[390] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28125 ~72.115 ms, finishGL 75 / 25179 ~64.563 ms, waitGL 6 / 2660 ~6.82 ms +XXX[391] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28208 ~72.143 ms, finishGL 76 / 25256 ~64.594 ms, waitGL 5 / 2665 ~6.817 ms +XXX[392] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 28291 ~72.171 ms, finishGL 77 / 25334 ~64.628 ms, waitGL 4 / 2670 ~6.811 ms +XXX[393] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28374 ~72.199 ms, finishGL 78 / 25412 ~64.662 ms, waitGL 4 / 2674 ~6.805 ms +XXX[394] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 28457 ~72.226 ms, finishGL 78 / 25490 ~64.697 ms, waitGL 4 / 2678 ~6.798 ms +XXX[395] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28540 ~72.254 ms, finishGL 77 / 25568 ~64.73 ms, waitGL 5 / 2683 ~6.794 ms +XXX[396] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28623 ~72.282 ms, finishGL 77 / 25646 ~64.763 ms, waitGL 4 / 2688 ~6.789 ms +XXX[397] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28707 ~72.309 ms, finishGL 77 / 25724 ~64.795 ms, waitGL 4 / 2693 ~6.785 ms +XXX[398] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28790 ~72.337 ms, finishGL 77 / 25801 ~64.828 ms, waitGL 5 / 2698 ~6.781 ms +XXX[399] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28873 ~72.364 ms, finishGL 77 / 25879 ~64.86 ms, waitGL 4 / 2703 ~6.776 ms +XXX[400] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 28957 ~72.392 ms, finishGL 76 / 25956 ~64.89 ms, waitGL 6 / 2709 ~6.774 ms +XXX[401] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29039 ~72.418 ms, finishGL 76 / 26032 ~64.919 ms, waitGL 5 / 2715 ~6.771 ms +XXX[402] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29123 ~72.445 ms, finishGL 75 / 26108 ~64.945 ms, waitGL 7 / 2722 ~6.772 ms +XXX[403] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29206 ~72.472 ms, finishGL 74 / 26182 ~64.969 ms, waitGL 8 / 2730 ~6.776 ms +XXX[404] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29289 ~72.498 ms, finishGL 73 / 26256 ~64.99 ms, waitGL 9 / 2740 ~6.782 ms +XXX[405] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29372 ~72.524 ms, finishGL 73 / 26329 ~65.012 ms, waitGL 8 / 2748 ~6.786 ms +XXX[406] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29455 ~72.551 ms, finishGL 72 / 26402 ~65.03 ms, waitGL 10 / 2758 ~6.794 ms +XXX[407] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 29538 ~72.575 ms, finishGL 72 / 26475 ~65.049 ms, waitGL 9 / 2768 ~6.801 ms +XXX[408] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29621 ~72.602 ms, finishGL 72 / 26547 ~65.067 ms, waitGL 11 / 2779 ~6.811 ms +XXX[409] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 29705 ~72.628 ms, finishGL 71 / 26619 ~65.083 ms, waitGL 10 / 2789 ~6.821 ms +XXX[410] TO 17 ms, lFrame0 1 ms, lFrameX 82 / 29787 ~72.651 ms, finishGL 71 / 26691 ~65.1 ms, waitGL 8 / 2798 ~6.826 ms +XXX[411] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 29870 ~72.677 ms, finishGL 72 / 26763 ~65.117 ms, waitGL 10 / 2808 ~6.834 ms +XXX[412] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 29953 ~72.702 ms, finishGL 71 / 26834 ~65.133 ms, waitGL 10 / 2819 ~6.842 ms +XXX[413] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 30036 ~72.728 ms, finishGL 72 / 26907 ~65.15 ms, waitGL 10 / 2829 ~6.851 ms +XXX[414] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 30119 ~72.753 ms, finishGL 71 / 26978 ~65.165 ms, waitGL 10 / 2840 ~6.86 ms +XXX[415] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 30203 ~72.778 ms, finishGL 70 / 27049 ~65.179 ms, waitGL 11 / 2851 ~6.87 ms +XXX[416] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 30286 ~72.803 ms, finishGL 71 / 27120 ~65.193 ms, waitGL 10 / 2862 ~6.88 ms +XXX[417] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 30369 ~72.828 ms, finishGL 70 / 27190 ~65.205 ms, waitGL 11 / 2874 ~6.892 ms +XXX[418] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 30452 ~72.853 ms, finishGL 69 / 27260 ~65.216 ms, waitGL 12 / 2886 ~6.905 ms +XXX[419] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 30535 ~72.877 ms, finishGL 69 / 27329 ~65.226 ms, waitGL 12 / 2898 ~6.918 ms +XXX[420] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 30619 ~72.902 ms, finishGL 70 / 27400 ~65.239 ms, waitGL 11 / 2910 ~6.93 ms +XXX[421] TO 17 ms, lFrame0 1 ms, lFrameX 82 / 30702 ~72.926 ms, finishGL 70 / 27470 ~65.251 ms, waitGL 11 / 2922 ~6.941 ms +XXX[422] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 30785 ~72.95 ms, finishGL 71 / 27542 ~65.266 ms, waitGL 10 / 2932 ~6.949 ms +XXX[423] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 30868 ~72.974 ms, finishGL 72 / 27614 ~65.283 ms, waitGL 9 / 2942 ~6.955 ms +XXX[424] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 30951 ~72.998 ms, finishGL 71 / 27686 ~65.298 ms, waitGL 10 / 2952 ~6.963 ms +XXX[425] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 31034 ~73.023 ms, finishGL 68 / 27755 ~65.307 ms, waitGL 13 / 2965 ~6.978 ms +XXX[426] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 31117 ~73.046 ms, finishGL 65 / 27820 ~65.307 ms, waitGL 16 / 2982 ~7.0 ms +XXX[427] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 31184 ~73.031 ms, finishGL 62 / 27883 ~65.3 ms, waitGL 3 / 2985 ~6.991 ms +XXX[428] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 31250 ~73.016 ms, finishGL 60 / 27944 ~65.289 ms, waitGL 4 / 2990 ~6.986 ms +XXX[429] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 31317 ~73.0 ms, finishGL 59 / 28003 ~65.277 ms, waitGL 5 / 2995 ~6.982 ms +XXX[430] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 31383 ~72.985 ms, finishGL 59 / 28063 ~65.263 ms, waitGL 6 / 3001 ~6.98 ms +XXX[431] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 31450 ~72.97 ms, finishGL 58 / 28121 ~65.248 ms, waitGL 6 / 3008 ~6.979 ms +XXX[432] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 31516 ~72.955 ms, finishGL 58 / 28179 ~65.231 ms, waitGL 7 / 3015 ~6.98 ms +XXX[433] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 31583 ~72.94 ms, finishGL 57 / 28237 ~65.214 ms, waitGL 7 / 3023 ~6.981 ms +XXX[434] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 31649 ~72.926 ms, finishGL 57 / 28295 ~65.197 ms, waitGL 7 / 3030 ~6.983 ms +XXX[435] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 31716 ~72.911 ms, finishGL 56 / 28352 ~65.178 ms, waitGL 8 / 3039 ~6.986 ms +XXX[436] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 31782 ~72.896 ms, finishGL 56 / 28409 ~65.158 ms, waitGL 8 / 3048 ~6.99 ms +XXX[437] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 31849 ~72.882 ms, finishGL 56 / 28465 ~65.137 ms, waitGL 9 / 3057 ~6.996 ms +XXX[438] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 31915 ~72.867 ms, finishGL 55 / 28520 ~65.116 ms, waitGL 9 / 3066 ~7.002 ms +XXX[439] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 31982 ~72.853 ms, finishGL 55 / 28576 ~65.093 ms, waitGL 10 / 3077 ~7.01 ms +XXX[440] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 32047 ~72.836 ms, finishGL 56 / 28632 ~65.073 ms, waitGL 8 / 3086 ~7.014 ms +XXX[441] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32114 ~72.822 ms, finishGL 56 / 28689 ~65.055 ms, waitGL 8 / 3095 ~7.018 ms +XXX[442] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 32180 ~72.807 ms, finishGL 56 / 28746 ~65.036 ms, waitGL 8 / 3103 ~7.021 ms +XXX[443] TO 17 ms, lFrame0 1 ms, lFrameX 67 / 32248 ~72.795 ms, finishGL 57 / 28803 ~65.02 ms, waitGL 8 / 3112 ~7.025 ms +XXX[444] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 32313 ~72.779 ms, finishGL 57 / 28861 ~65.002 ms, waitGL 8 / 3120 ~7.027 ms +XXX[445] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32380 ~72.765 ms, finishGL 58 / 28919 ~64.987 ms, waitGL 7 / 3127 ~7.029 ms +XXX[446] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 32446 ~72.751 ms, finishGL 58 / 28977 ~64.972 ms, waitGL 7 / 3135 ~7.029 ms +XXX[447] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32513 ~72.737 ms, finishGL 59 / 29036 ~64.959 ms, waitGL 6 / 3141 ~7.027 ms +XXX[448] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 32579 ~72.722 ms, finishGL 58 / 29095 ~64.944 ms, waitGL 6 / 3148 ~7.027 ms +XXX[449] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32646 ~72.709 ms, finishGL 58 / 29154 ~64.931 ms, waitGL 7 / 3155 ~7.027 ms +XXX[450] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 32712 ~72.695 ms, finishGL 58 / 29212 ~64.917 ms, waitGL 6 / 3161 ~7.026 ms +XXX[451] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 32779 ~72.681 ms, finishGL 58 / 29271 ~64.903 ms, waitGL 6 / 3168 ~7.026 ms +XXX[452] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 32845 ~72.667 ms, finishGL 58 / 29330 ~64.889 ms, waitGL 6 / 3175 ~7.025 ms +XXX[453] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32912 ~72.654 ms, finishGL 58 / 29388 ~64.876 ms, waitGL 7 / 3182 ~7.026 ms +XXX[454] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 32978 ~72.64 ms, finishGL 57 / 29446 ~64.859 ms, waitGL 8 / 3190 ~7.028 ms +XXX[455] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 33045 ~72.627 ms, finishGL 56 / 29503 ~64.841 ms, waitGL 8 / 3199 ~7.032 ms +XXX[456] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 33111 ~72.613 ms, finishGL 55 / 29558 ~64.821 ms, waitGL 9 / 3209 ~7.037 ms +XXX[457] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 33178 ~72.6 ms, finishGL 55 / 29613 ~64.8 ms, waitGL 10 / 3219 ~7.045 ms +XXX[458] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 33244 ~72.586 ms, finishGL 53 / 29667 ~64.776 ms, waitGL 11 / 3230 ~7.054 ms +XXX[459] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 33311 ~72.573 ms, finishGL 53 / 29721 ~64.751 ms, waitGL 12 / 3243 ~7.066 ms +XXX[460] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 33377 ~72.56 ms, finishGL 52 / 29773 ~64.724 ms, waitGL 12 / 3256 ~7.079 ms +XXX[461] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 33444 ~72.547 ms, finishGL 51 / 29824 ~64.695 ms, waitGL 14 / 3270 ~7.094 ms +XXX[462] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 33510 ~72.533 ms, finishGL 50 / 29874 ~64.664 ms, waitGL 14 / 3285 ~7.111 ms +XXX[463] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 33577 ~72.52 ms, finishGL 49 / 29924 ~64.631 ms, waitGL 15 / 3301 ~7.13 ms +XXX[464] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 33627 ~72.473 ms, finishGL 48 / 29973 ~64.597 ms, waitGL 1 / 3302 ~7.117 ms +XXX[465] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 33693 ~72.46 ms, finishGL 63 / 30036 ~64.595 ms, waitGL 1 / 3304 ~7.105 ms +XXX[466] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 33760 ~72.448 ms, finishGL 63 / 30100 ~64.593 ms, waitGL 2 / 3306 ~7.096 ms +XXX[467] TO 17 ms, lFrame0 1 ms, lFrameX 48 / 33809 ~72.397 ms, finishGL 46 / 30146 ~64.554 ms, waitGL 1 / 3308 ~7.084 ms +XXX[468] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 33859 ~72.349 ms, finishGL 45 / 30192 ~64.513 ms, waitGL 3 / 3311 ~7.076 ms +XXX[469] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 33909 ~72.301 ms, finishGL 44 / 30237 ~64.472 ms, waitGL 3 / 3315 ~7.068 ms +XXX[470] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 33959 ~72.253 ms, finishGL 44 / 30281 ~64.428 ms, waitGL 4 / 3319 ~7.063 ms +XXX[471] TO 17 ms, lFrame0 1 ms, lFrameX 48 / 34007 ~72.202 ms, finishGL 43 / 30325 ~64.385 ms, waitGL 2 / 3322 ~7.054 ms +XXX[472] TO 17 ms, lFrame0 1 ms, lFrameX 50 / 34057 ~72.155 ms, finishGL 42 / 30368 ~64.339 ms, waitGL 6 / 3328 ~7.052 ms +XXX[473] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 34107 ~72.109 ms, finishGL 41 / 30409 ~64.291 ms, waitGL 8 / 3336 ~7.054 ms +XXX[474] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34157 ~72.061 ms, finishGL 41 / 30451 ~64.243 ms, waitGL 6 / 3343 ~7.054 ms +XXX[475] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 34206 ~72.014 ms, finishGL 41 / 30492 ~64.194 ms, waitGL 7 / 3351 ~7.055 ms +XXX[476] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 34256 ~71.967 ms, finishGL 40 / 30532 ~64.144 ms, waitGL 8 / 3359 ~7.057 ms +XXX[477] TO 17 ms, lFrame0 1 ms, lFrameX 50 / 34307 ~71.922 ms, finishGL 39 / 30572 ~64.093 ms, waitGL 9 / 3369 ~7.063 ms +XXX[478] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34356 ~71.874 ms, finishGL 38 / 30611 ~64.039 ms, waitGL 10 / 3379 ~7.069 ms +XXX[479] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34406 ~71.828 ms, finishGL 38 / 30649 ~63.987 ms, waitGL 10 / 3389 ~7.076 ms +XXX[480] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34455 ~71.782 ms, finishGL 38 / 30688 ~63.933 ms, waitGL 10 / 3400 ~7.084 ms +XXX[481] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34505 ~71.737 ms, finishGL 37 / 30725 ~63.878 ms, waitGL 11 / 3412 ~7.094 ms +XXX[482] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34555 ~71.691 ms, finishGL 35 / 30761 ~63.82 ms, waitGL 13 / 3425 ~7.107 ms +XXX[483] TO 17 ms, lFrame0 1 ms, lFrameX 50 / 34605 ~71.646 ms, finishGL 35 / 30796 ~63.761 ms, waitGL 13 / 3439 ~7.12 ms +XXX[484] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34655 ~71.601 ms, finishGL 34 / 30831 ~63.701 ms, waitGL 14 / 3453 ~7.135 ms +XXX[485] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 34704 ~71.556 ms, finishGL 33 / 30864 ~63.638 ms, waitGL 15 / 3468 ~7.151 ms +XXX[486] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34754 ~71.511 ms, finishGL 33 / 30898 ~63.576 ms, waitGL 16 / 3484 ~7.17 ms +XXX[487] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 34804 ~71.466 ms, finishGL 33 / 30931 ~63.513 ms, waitGL 15 / 3500 ~7.187 ms +XXX[488] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 34854 ~71.422 ms, finishGL 32 / 30963 ~63.45 ms, waitGL 16 / 3516 ~7.206 ms +XXX[489] TO 17 ms, lFrame0 1 ms, lFrameX 34 / 34888 ~71.346 ms, finishGL 32 / 30996 ~63.387 ms, waitGL 0 / 3517 ~7.192 ms +XXX[490] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 34953 ~71.334 ms, finishGL 48 / 31044 ~63.356 ms, waitGL 16 / 3533 ~7.211 ms +XXX[491] TO 17 ms, lFrame0 0 ms, lFrameX 33 / 34987 ~71.258 ms, finishGL 33 / 31077 ~63.294 ms, waitGL 0 / 3533 ~7.197 ms +XXX[492] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 35053 ~71.246 ms, finishGL 49 / 31127 ~63.266 ms, waitGL 15 / 3549 ~7.214 ms +XXX[493] TO 17 ms, lFrame0 0 ms, lFrameX 50 / 35104 ~71.204 ms, finishGL 33 / 31160 ~63.205 ms, waitGL 16 / 3566 ~7.234 ms +XXX[494] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 35153 ~71.16 ms, finishGL 32 / 31192 ~63.142 ms, waitGL 15 / 3582 ~7.252 ms +XXX[495] TO 17 ms, lFrame0 1 ms, lFrameX 33 / 35187 ~71.085 ms, finishGL 32 / 31224 ~63.08 ms, waitGL 0 / 3582 ~7.238 ms +XXX[496] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 35252 ~71.074 ms, finishGL 50 / 31275 ~63.054 ms, waitGL 14 / 3597 ~7.253 ms +XXX[497] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35302 ~71.031 ms, finishGL 35 / 31310 ~62.998 ms, waitGL 13 / 3611 ~7.266 ms +XXX[498] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 35352 ~70.988 ms, finishGL 34 / 31344 ~62.941 ms, waitGL 13 / 3625 ~7.279 ms +XXX[499] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35402 ~70.946 ms, finishGL 35 / 31380 ~62.887 ms, waitGL 13 / 3638 ~7.291 ms +FrameCount: 600 - FrameRate: 21.0 +XXX[500] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 35452 ~70.904 ms, finishGL 37 / 31417 ~62.835 ms, waitGL 11 / 3649 ~7.299 ms +XXX[501] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35501 ~70.861 ms, finishGL 36 / 31454 ~62.783 ms, waitGL 12 / 3662 ~7.309 ms +XXX[502] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 35551 ~70.82 ms, finishGL 37 / 31492 ~62.733 ms, waitGL 11 / 3673 ~7.317 ms +XXX[503] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35601 ~70.778 ms, finishGL 37 / 31529 ~62.683 ms, waitGL 11 / 3684 ~7.325 ms +XXX[504] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 35651 ~70.736 ms, finishGL 38 / 31567 ~62.634 ms, waitGL 10 / 3695 ~7.331 ms +XXX[505] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 35701 ~70.695 ms, finishGL 38 / 31606 ~62.586 ms, waitGL 10 / 3705 ~7.338 ms +XXX[506] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 35750 ~70.653 ms, finishGL 38 / 31644 ~62.538 ms, waitGL 10 / 3716 ~7.345 ms +XXX[507] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 35800 ~70.612 ms, finishGL 38 / 31683 ~62.491 ms, waitGL 9 / 3726 ~7.35 ms +XXX[508] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 35850 ~70.571 ms, finishGL 39 / 31722 ~62.445 ms, waitGL 9 / 3736 ~7.354 ms +XXX[509] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 35900 ~70.53 ms, finishGL 40 / 31762 ~62.401 ms, waitGL 8 / 3744 ~7.356 ms +XXX[510] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 35950 ~70.49 ms, finishGL 39 / 31802 ~62.357 ms, waitGL 8 / 3753 ~7.359 ms +XXX[511] TO 17 ms, lFrame0 2 ms, lFrameX 48 / 35998 ~70.447 ms, finishGL 39 / 31841 ~62.313 ms, waitGL 6 / 3759 ~7.357 ms +XXX[512] TO 17 ms, lFrame0 1 ms, lFrameX 49 / 36048 ~70.406 ms, finishGL 41 / 31883 ~62.272 ms, waitGL 6 / 3766 ~7.356 ms +XXX[513] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 36098 ~70.366 ms, finishGL 42 / 31926 ~62.234 ms, waitGL 6 / 3772 ~7.353 ms +XXX[514] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 36147 ~70.326 ms, finishGL 44 / 31971 ~62.2 ms, waitGL 4 / 3776 ~7.347 ms +XXX[515] TO 17 ms, lFrame0 0 ms, lFrameX 49 / 36197 ~70.286 ms, finishGL 47 / 32018 ~62.172 ms, waitGL 1 / 3778 ~7.336 ms +XXX[516] TO 17 ms, lFrame0 0 ms, lFrameX 67 / 36265 ~70.281 ms, finishGL 49 / 32068 ~62.147 ms, waitGL 17 / 3795 ~7.355 ms +XXX[517] TO 17 ms, lFrame0 1 ms, lFrameX 65 / 36330 ~70.272 ms, finishGL 52 / 32120 ~62.129 ms, waitGL 11 / 3807 ~7.363 ms +XXX[518] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 36396 ~70.264 ms, finishGL 58 / 32179 ~62.122 ms, waitGL 6 / 3813 ~7.362 ms +XXX[519] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36480 ~70.289 ms, finishGL 68 / 32248 ~62.135 ms, waitGL 14 / 3827 ~7.375 ms +XXX[520] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36563 ~70.313 ms, finishGL 76 / 32324 ~62.161 ms, waitGL 6 / 3834 ~7.373 ms +XXX[521] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36646 ~70.338 ms, finishGL 76 / 32401 ~62.19 ms, waitGL 5 / 3839 ~7.37 ms +XXX[522] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36729 ~70.363 ms, finishGL 76 / 32477 ~62.217 ms, waitGL 6 / 3846 ~7.368 ms +XXX[523] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 36812 ~70.387 ms, finishGL 76 / 32553 ~62.244 ms, waitGL 6 / 3852 ~7.366 ms +XXX[524] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 36895 ~70.412 ms, finishGL 76 / 32630 ~62.271 ms, waitGL 5 / 3858 ~7.362 ms +XXX[525] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 36979 ~70.436 ms, finishGL 76 / 32706 ~62.297 ms, waitGL 5 / 3864 ~7.36 ms +XXX[526] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 37062 ~70.46 ms, finishGL 75 / 32782 ~62.323 ms, waitGL 6 / 3870 ~7.358 ms +XXX[527] TO 17 ms, lFrame0 1 ms, lFrameX 84 / 37146 ~70.486 ms, finishGL 75 / 32857 ~62.348 ms, waitGL 7 / 3877 ~7.358 ms +XXX[528] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 37228 ~70.508 ms, finishGL 74 / 32932 ~62.372 ms, waitGL 7 / 3884 ~7.357 ms +XXX[529] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 37311 ~70.532 ms, finishGL 75 / 33008 ~62.397 ms, waitGL 6 / 3890 ~7.355 ms +XXX[530] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37395 ~70.556 ms, finishGL 76 / 33084 ~62.423 ms, waitGL 6 / 3897 ~7.353 ms +XXX[531] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 37478 ~70.58 ms, finishGL 76 / 33160 ~62.449 ms, waitGL 6 / 3903 ~7.351 ms +XXX[532] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 37561 ~70.603 ms, finishGL 76 / 33237 ~62.476 ms, waitGL 5 / 3909 ~7.348 ms +XXX[533] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 37644 ~70.627 ms, finishGL 76 / 33313 ~62.502 ms, waitGL 5 / 3914 ~7.344 ms +XXX[534] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 37727 ~70.651 ms, finishGL 76 / 33390 ~62.528 ms, waitGL 5 / 3920 ~7.341 ms +XXX[535] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 37810 ~70.674 ms, finishGL 76 / 33466 ~62.554 ms, waitGL 5 / 3926 ~7.338 ms +XXX[536] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 37893 ~70.697 ms, finishGL 76 / 33542 ~62.579 ms, waitGL 5 / 3931 ~7.335 ms +XXX[537] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 37977 ~70.721 ms, finishGL 75 / 33618 ~62.604 ms, waitGL 6 / 3938 ~7.333 ms +XXX[538] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 38060 ~70.744 ms, finishGL 75 / 33694 ~62.628 ms, waitGL 6 / 3944 ~7.332 ms +XXX[539] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 38143 ~70.767 ms, finishGL 75 / 33769 ~62.651 ms, waitGL 6 / 3951 ~7.331 ms +XXX[540] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 38226 ~70.79 ms, finishGL 74 / 33843 ~62.673 ms, waitGL 7 / 3958 ~7.331 ms +XXX[541] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 38309 ~70.813 ms, finishGL 74 / 33918 ~62.695 ms, waitGL 7 / 3966 ~7.332 ms +XXX[542] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 38393 ~70.835 ms, finishGL 74 / 33992 ~62.717 ms, waitGL 7 / 3974 ~7.332 ms +XXX[543] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 38476 ~70.858 ms, finishGL 75 / 34067 ~62.74 ms, waitGL 6 / 3981 ~7.331 ms +XXX[544] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 38559 ~70.881 ms, finishGL 74 / 34142 ~62.762 ms, waitGL 7 / 3988 ~7.331 ms +XXX[545] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 38642 ~70.903 ms, finishGL 75 / 34218 ~62.786 ms, waitGL 6 / 3994 ~7.329 ms +XXX[546] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38725 ~70.926 ms, finishGL 75 / 34294 ~62.809 ms, waitGL 7 / 4001 ~7.329 ms +XXX[547] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 38809 ~70.95 ms, finishGL 75 / 34369 ~62.833 ms, waitGL 7 / 4009 ~7.329 ms +XXX[548] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 38892 ~70.97 ms, finishGL 76 / 34446 ~62.857 ms, waitGL 5 / 4014 ~7.326 ms +XXX[549] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 38975 ~70.993 ms, finishGL 77 / 34523 ~62.884 ms, waitGL 4 / 4019 ~7.321 ms +XXX[550] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 39058 ~71.015 ms, finishGL 77 / 34601 ~62.912 ms, waitGL 3 / 4023 ~7.315 ms +XXX[551] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 39141 ~71.037 ms, finishGL 78 / 34680 ~62.94 ms, waitGL 4 / 4027 ~7.31 ms +XXX[552] TO 17 ms, lFrame0 0 ms, lFrameX 84 / 39225 ~71.06 ms, finishGL 79 / 34759 ~62.97 ms, waitGL 4 / 4031 ~7.304 ms +XXX[553] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39307 ~71.081 ms, finishGL 78 / 34837 ~62.997 ms, waitGL 3 / 4035 ~7.296 ms +XXX[554] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 39391 ~71.103 ms, finishGL 77 / 34915 ~63.024 ms, waitGL 4 / 4040 ~7.292 ms +XXX[555] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 39474 ~71.124 ms, finishGL 77 / 34992 ~63.05 ms, waitGL 5 / 4045 ~7.289 ms +XXX[556] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 39557 ~71.146 ms, finishGL 76 / 35069 ~63.074 ms, waitGL 5 / 4051 ~7.286 ms +XXX[557] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 39640 ~71.168 ms, finishGL 75 / 35145 ~63.097 ms, waitGL 6 / 4057 ~7.284 ms +XXX[558] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 39724 ~71.19 ms, finishGL 73 / 35219 ~63.116 ms, waitGL 9 / 4066 ~7.287 ms +XXX[559] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 39807 ~71.212 ms, finishGL 73 / 35292 ~63.134 ms, waitGL 9 / 4076 ~7.292 ms +XXX[560] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 39890 ~71.233 ms, finishGL 72 / 35364 ~63.15 ms, waitGL 10 / 4086 ~7.297 ms +XXX[561] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 39974 ~71.255 ms, finishGL 71 / 35435 ~63.164 ms, waitGL 11 / 4098 ~7.305 ms +XXX[562] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 40057 ~71.276 ms, finishGL 69 / 35504 ~63.175 ms, waitGL 13 / 4112 ~7.316 ms +XXX[563] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 40140 ~71.297 ms, finishGL 67 / 35572 ~63.183 ms, waitGL 15 / 4127 ~7.33 ms +XXX[564] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 40223 ~71.318 ms, finishGL 65 / 35637 ~63.187 ms, waitGL 16 / 4144 ~7.347 ms +XXX[565] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 40289 ~71.308 ms, finishGL 64 / 35702 ~63.189 ms, waitGL 0 / 4145 ~7.336 ms +XXX[566] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 40372 ~71.329 ms, finishGL 78 / 35780 ~63.217 ms, waitGL 3 / 4148 ~7.329 ms +XXX[567] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 40438 ~71.32 ms, finishGL 61 / 35842 ~63.213 ms, waitGL 4 / 4153 ~7.324 ms +XXX[568] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 40504 ~71.311 ms, finishGL 60 / 35902 ~63.208 ms, waitGL 4 / 4157 ~7.32 ms +XXX[569] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 40588 ~71.333 ms, finishGL 74 / 35977 ~63.229 ms, waitGL 8 / 4166 ~7.322 ms +XXX[570] TO 17 ms, lFrame0 0 ms, lFrameX 65 / 40654 ~71.323 ms, finishGL 58 / 36035 ~63.22 ms, waitGL 6 / 4173 ~7.321 ms +XXX[571] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 40720 ~71.315 ms, finishGL 58 / 36094 ~63.212 ms, waitGL 6 / 4179 ~7.319 ms +XXX[572] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 40787 ~71.306 ms, finishGL 58 / 36152 ~63.204 ms, waitGL 7 / 4186 ~7.319 ms +XXX[573] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 40853 ~71.298 ms, finishGL 57 / 36210 ~63.193 ms, waitGL 8 / 4194 ~7.32 ms +XXX[574] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 40920 ~71.289 ms, finishGL 57 / 36267 ~63.184 ms, waitGL 7 / 4202 ~7.321 ms +XXX[575] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 40986 ~71.281 ms, finishGL 57 / 36325 ~63.174 ms, waitGL 8 / 4210 ~7.322 ms +XXX[576] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 41053 ~71.273 ms, finishGL 57 / 36382 ~63.164 ms, waitGL 8 / 4218 ~7.324 ms +XXX[577] TO 17 ms, lFrame0 0 ms, lFrameX 66 / 41120 ~71.265 ms, finishGL 57 / 36440 ~63.154 ms, waitGL 8 / 4227 ~7.325 ms +XXX[578] TO 17 ms, lFrame0 1 ms, lFrameX 66 / 41186 ~71.256 ms, finishGL 61 / 36501 ~63.151 ms, waitGL 3 / 4231 ~7.32 ms +XXX[579] TO 17 ms, lFrame0 1 ms, lFrameX 67 / 41253 ~71.25 ms, finishGL 64 / 36565 ~63.153 ms, waitGL 1 / 4232 ~7.31 ms +XXX[580] TO 17 ms, lFrame0 0 ms, lFrameX 98 / 41352 ~71.298 ms, finishGL 86 / 36652 ~63.194 ms, waitGL 11 / 4244 ~7.318 ms +XXX[581] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 41436 ~71.318 ms, finishGL 75 / 36728 ~63.215 ms, waitGL 6 / 4251 ~7.317 ms +XXX[582] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 41519 ~71.338 ms, finishGL 78 / 36807 ~63.242 ms, waitGL 4 / 4255 ~7.311 ms +XXX[583] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 41602 ~71.359 ms, finishGL 79 / 36886 ~63.269 ms, waitGL 2 / 4258 ~7.303 ms +XXX[584] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 41685 ~71.379 ms, finishGL 79 / 36965 ~63.297 ms, waitGL 2 / 4260 ~7.296 ms +XXX[585] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 41768 ~71.399 ms, finishGL 76 / 37042 ~63.319 ms, waitGL 5 / 4266 ~7.293 ms +XXX[586] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 41851 ~71.419 ms, finishGL 75 / 37117 ~63.339 ms, waitGL 6 / 4273 ~7.293 ms +XXX[587] TO 17 ms, lFrame0 1 ms, lFrameX 84 / 41935 ~71.441 ms, finishGL 74 / 37191 ~63.359 ms, waitGL 8 / 4282 ~7.294 ms +XXX[588] TO 17 ms, lFrame0 2 ms, lFrameX 83 / 42019 ~71.461 ms, finishGL 74 / 37266 ~63.379 ms, waitGL 5 / 4287 ~7.292 ms +XXX[589] TO 17 ms, lFrame0 0 ms, lFrameX 82 / 42101 ~71.479 ms, finishGL 73 / 37340 ~63.396 ms, waitGL 8 / 4296 ~7.294 ms +XXX[590] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42184 ~71.499 ms, finishGL 73 / 37414 ~63.414 ms, waitGL 8 / 4304 ~7.296 ms +XXX[591] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42267 ~71.519 ms, finishGL 73 / 37487 ~63.431 ms, waitGL 9 / 4313 ~7.299 ms +XXX[592] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 42351 ~71.538 ms, finishGL 73 / 37561 ~63.448 ms, waitGL 8 / 4322 ~7.301 ms +XXX[593] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 42434 ~71.558 ms, finishGL 73 / 37635 ~63.465 ms, waitGL 8 / 4330 ~7.302 ms +XXX[594] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 42517 ~71.578 ms, finishGL 73 / 37709 ~63.483 ms, waitGL 8 / 4338 ~7.303 ms +XXX[595] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 42600 ~71.597 ms, finishGL 74 / 37784 ~63.502 ms, waitGL 7 / 4345 ~7.303 ms +XXX[596] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 42683 ~71.616 ms, finishGL 75 / 37859 ~63.522 ms, waitGL 6 / 4352 ~7.302 ms +XXX[597] TO 17 ms, lFrame0 1 ms, lFrameX 83 / 42766 ~71.636 ms, finishGL 76 / 37935 ~63.544 ms, waitGL 5 / 4358 ~7.3 ms +XXX[598] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42850 ~71.655 ms, finishGL 76 / 38012 ~63.566 ms, waitGL 5 / 4363 ~7.297 ms +XXX[599] TO 17 ms, lFrame0 0 ms, lFrameX 83 / 42933 ~71.674 ms, finishGL 77 / 38090 ~63.589 ms, waitGL 5 / 4369 ~7.294 ms diff --git a/src/test/com/jogamp/opengl/test/bugs/Bug735Inv0AppletAWT.java b/src/test/com/jogamp/opengl/test/bugs/Bug735Inv0AppletAWT.java new file mode 100644 index 000000000..f443459c3 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/bugs/Bug735Inv0AppletAWT.java @@ -0,0 +1,430 @@ +package com.jogamp.opengl.test.bugs; + +import java.applet.Applet; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.nio.FloatBuffer; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLException; +import javax.media.opengl.GLProfile; +import javax.media.opengl.GLRunnable; +import javax.media.opengl.GLUniformData; +import javax.media.opengl.awt.GLCanvas; +import javax.media.opengl.glu.GLU; + +import com.jogamp.newt.awt.NewtCanvasAWT; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.jogl.demos.es2.LandscapeES2; +import com.jogamp.opengl.util.GLArrayDataServer; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; +import com.jogamp.opengl.util.glsl.ShaderState; + +/** + * Original test case. + * <br/> + * OSX Results: + * <pre> + * - Visible content + * - Fluent animation + * </pre> + */ +@SuppressWarnings("serial") +public class Bug735Inv0AppletAWT extends Applet implements Runnable { + static public int AWT = 0; + static public int NEWT = 1; + + static public int APPLET_WIDTH = 500; + static public int APPLET_HEIGHT = 290; + static public int TARGET_FPS = 120; + static public int TOOLKIT = NEWT; + static public boolean MANUAL_FRAME_HANDLING = true; + + ////////////////////////////////////////////////////////////////////////////// + + static private Frame frame; + static private Bug735Inv0AppletAWT applet; + private GLCanvas awtCanvas; + private GLWindow newtWindow; + private NewtCanvasAWT newtCanvas; + private DrawRunnable drawRunnable; + private GLContext context; + private GLU glu; + + private int width; + private int height; + private Thread thread; + + private boolean doneInit = false; + private boolean doneSetup = false; + + private long frameRatePeriod = 1000000000L / TARGET_FPS; + private long millisOffset; + private int frameCount; + private float frameRate; + + private ShaderCode vertShader; + private ShaderCode fragShader; + private ShaderProgram shaderProg; + private ShaderState shaderState; + private GLUniformData resolution; + private GLUniformData time; + private GLArrayDataServer vertices; + + private int fcount = 0, lastm = 0; + private int fint = 1; + + public void init() { + setSize(APPLET_WIDTH, APPLET_HEIGHT); + setPreferredSize(new Dimension(APPLET_WIDTH, APPLET_HEIGHT)); + width = APPLET_WIDTH; + height = APPLET_HEIGHT; + } + + public void start() { + thread = new Thread(this, "Animation Thread"); + thread.start(); + } + + public void run() { + int noDelays = 0; + // Number of frames with a delay of 0 ms before the + // animation thread yields to other running threads. + final int NO_DELAYS_PER_YIELD = 15; + final int TIMEOUT_SECONDS = 2; + + long beforeTime = System.nanoTime(); + long overSleepTime = 0L; + + millisOffset = System.currentTimeMillis(); + frameCount = 1; + while (Thread.currentThread() == thread) { + final CountDownLatch latch = new CountDownLatch(1); + requestDraw(latch); + try { + latch.await(TIMEOUT_SECONDS, TimeUnit.SECONDS); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + if (frameCount == 1) { + EventQueue.invokeLater(new Runnable() { + public void run() { + requestFocusInWindow(); + } + }); + } + + long afterTime = System.nanoTime(); + long timeDiff = afterTime - beforeTime; + long sleepTime = (frameRatePeriod - timeDiff) - overSleepTime; + if (sleepTime > 0) { // some time left in this cycle + try { + Thread.sleep(sleepTime / 1000000L, (int) (sleepTime % 1000000L)); + noDelays = 0; // Got some sleep, not delaying anymore + } catch (InterruptedException ex) { } + overSleepTime = (System.nanoTime() - afterTime) - sleepTime; + } else { // sleepTime <= 0; the frame took longer than the period + overSleepTime = 0L; + noDelays++; + if (noDelays > NO_DELAYS_PER_YIELD) { + Thread.yield(); // give another thread a chance to run + noDelays = 0; + } + } + beforeTime = System.nanoTime(); + } + } + + public void requestDraw(CountDownLatch latch) { + if (!doneInit) { + initDraw(); + } + + if (TOOLKIT == AWT) { + awtCanvas.invoke(true, drawRunnable); + } else if (TOOLKIT == NEWT) { + newtWindow.invoke(true, drawRunnable); + } + + if (latch != null) { + latch.countDown(); + } + } + + private class DrawRunnable implements GLRunnable { + private boolean notCurrent; + + @Override + public boolean run(GLAutoDrawable drawable) { + if (MANUAL_FRAME_HANDLING) { + makeContextCurrent(); + } + + if (doneSetup) { + draw(drawable.getGL().getGL2ES2()); + } else { + setup(drawable.getGL().getGL2ES2()); + } + checkGLErrors(drawable.getGL()); + + if (MANUAL_FRAME_HANDLING) { + swapBuffers(); + releaseCurrentContext(); + } + + return true; + } + + private void makeContextCurrent() { + int MAX_CONTEXT_GRAB_ATTEMPTS = 10; + + if (context.isCurrent()) { + notCurrent = false; + } else { + notCurrent = true; + int value = GLContext.CONTEXT_NOT_CURRENT; + int attempt = 0; + do { + try { + value = context.makeCurrent(); + System.out.println("Made context current"); + } catch (final GLException gle) { + gle.printStackTrace(); + } finally { + attempt++; + if (attempt == MAX_CONTEXT_GRAB_ATTEMPTS) { + throw new RuntimeException("Failed to claim OpenGL context."); + } + } + try { + Thread.sleep(5); + } catch (final InterruptedException e) { + e.printStackTrace(); + } + + } while (value == GLContext.CONTEXT_NOT_CURRENT); + } + } + + private void swapBuffers() { + final GL gl = GLContext.getCurrentGL(); + gl.glFlush(); + GLContext.getCurrent().getGLDrawable().swapBuffers(); + } + + private void releaseCurrentContext() { + if (notCurrent) { + try { + context.release(); + System.out.println("Released context"); + } catch (final GLException gle) { + gle.printStackTrace(); + } + } + } + } + + private void initGL() { + GLProfile profile = GLProfile.getDefault(); + GLCapabilities caps = new GLCapabilities(profile); + caps.setBackgroundOpaque(true); + caps.setOnscreen(true); + caps.setSampleBuffers(false); + + if (TOOLKIT == AWT) { + awtCanvas = new GLCanvas(caps); + awtCanvas.setBounds(0, 0, applet.width, applet.height); + awtCanvas.setBackground(new Color(0xFFCCCCCC, true)); + awtCanvas.setFocusable(true); + + applet.setLayout(new BorderLayout()); + applet.add(awtCanvas, BorderLayout.CENTER); + + if (MANUAL_FRAME_HANDLING) { + awtCanvas.setIgnoreRepaint(true); + awtCanvas.setAutoSwapBufferMode(false); + } + } else if (TOOLKIT == NEWT) { + newtWindow = GLWindow.create(caps); + newtCanvas = new NewtCanvasAWT(newtWindow); + newtCanvas.setBounds(0, 0, applet.width, applet.height); + newtCanvas.setBackground(new Color(0xFFCCCCCC, true)); + newtCanvas.setFocusable(true); + + applet.setLayout(new BorderLayout()); + applet.add(newtCanvas, BorderLayout.CENTER); + + if (MANUAL_FRAME_HANDLING) { + newtCanvas.setIgnoreRepaint(true); + newtWindow.setAutoSwapBufferMode(false); + } + } + } + + private void initDraw() { + if (TOOLKIT == AWT) { + awtCanvas.setVisible(true); + // Force the realization + awtCanvas.display(); + if (awtCanvas.getDelegatedDrawable().isRealized()) { + // Request the focus here as it cannot work when the window is not visible + awtCanvas.requestFocus(); + context = awtCanvas.getContext(); + } + } else if (TOOLKIT == NEWT) { + newtCanvas.setVisible(true); + // Force the realization + newtWindow.display(); + if (newtWindow.isRealized()) { + // Request the focus here as it cannot work when the window is not visible + newtCanvas.requestFocus(); + context = newtWindow.getContext(); + } + } + + drawRunnable = new DrawRunnable(); + + doneInit = true; + } + + private void setup(GL2ES2 gl) { + if (60 < TARGET_FPS) { + // Disables vsync + gl.setSwapInterval(0); + } + glu = new GLU(); + + vertShader = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, LandscapeES2.class, "shader", "shader/bin", "landscape", true); + fragShader = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, LandscapeES2.class, "shader", "shader/bin", "landscape", true); + vertShader.defaultShaderCustomization(gl, true, true); + fragShader.defaultShaderCustomization(gl, true, true); + shaderProg = new ShaderProgram(); + shaderProg.add(gl, vertShader, System.err); + shaderProg.add(gl, fragShader, System.err); + + shaderState = new ShaderState(); + shaderState.attachShaderProgram(gl, shaderProg, true); + + resolution = new GLUniformData("iResolution", 3, FloatBuffer.wrap(new float[] {width, height, 0})); + shaderState.ownUniform(resolution); + shaderState.uniform(gl, resolution); + + time = new GLUniformData("iGlobalTime", 0.0f); + shaderState.ownUniform(time); + + vertices = GLArrayDataServer.createGLSL("inVertex", 2, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW); + vertices.putf(-1.0f); vertices.putf(-1.0f); + vertices.putf(+1.0f); vertices.putf(-1.0f); + vertices.putf(-1.0f); vertices.putf(+1.0f); + vertices.putf(+1.0f); vertices.putf(+1.0f); + vertices.seal(gl, true); + shaderState.ownAttribute(vertices, true); + shaderState.useProgram(gl, false); + + doneSetup = true; + } + + private void draw(GL2ES2 gl) { + // gl.glClearColor(0.5f, 0.1f, 0.1f, 1); + // gl.glClear(GL2ES2.GL_COLOR_BUFFER_BIT); + + shaderState.useProgram(gl, true); + + time.setData((System.currentTimeMillis() - millisOffset) / 1000.0f); + shaderState.uniform(gl, time); + vertices.enableBuffer(gl, true); + gl.glDrawArrays(GL2ES2.GL_TRIANGLE_STRIP, 0, 4); + vertices.enableBuffer(gl, false); + + shaderState.useProgram(gl, false); + + // Compute current framerate and printout. + frameCount++; + fcount += 1; + int m = (int) (System.currentTimeMillis() - millisOffset); + if (m - lastm > 1000 * fint) { + frameRate = (float)(fcount) / fint; + fcount = 0; + lastm = m; + } + if (frameCount % TARGET_FPS == 0) { + System.out.println("FrameCount: " + frameCount + " - " + + "FrameRate: " + frameRate); + } + } + + private void checkGLErrors(GL gl) { + int err = gl.glGetError(); + if (err != 0) { + String errString = glu.gluErrorString(err); + System.out.println(errString); + } + } + + static public void main(String[] args) { + GraphicsEnvironment environment = + GraphicsEnvironment.getLocalGraphicsEnvironment(); + GraphicsDevice displayDevice = environment.getDefaultScreenDevice(); + + frame = new Frame(displayDevice.getDefaultConfiguration()); + frame.setBackground(new Color(0xCC, 0xCC, 0xCC)); + frame.setTitle("TestBug735Inv0AppletAWT"); + + try { + Class<?> c = Thread.currentThread().getContextClassLoader(). + loadClass(Bug735Inv0AppletAWT.class.getName()); + applet = (Bug735Inv0AppletAWT) c.newInstance(); + } catch (Exception e) { + throw new RuntimeException(e); + } + + frame.setLayout(null); + frame.add(applet); + frame.pack(); + frame.setResizable(false); + + applet.init(); + + Insets insets = frame.getInsets(); + int windowW = applet.width + insets.left + insets.right; + int windowH = applet.height + insets.top + insets.bottom; + frame.setSize(windowW, windowH); + + Rectangle screenRect = displayDevice.getDefaultConfiguration().getBounds(); + frame.setLocation(screenRect.x + (screenRect.width - applet.width) / 2, + screenRect.y + (screenRect.height - applet.height) / 2); + + int usableWindowH = windowH - insets.top - insets.bottom; + applet.setBounds((windowW - applet.width)/2, + insets.top + (usableWindowH - applet.height)/2, + applet.width, applet.height); + + // This allows to close the frame. + frame.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }); + + applet.initGL(); + frame.setVisible(true); + applet.start(); + } +} diff --git a/src/test/com/jogamp/opengl/test/bugs/Bug735Inv1AppletAWT.java b/src/test/com/jogamp/opengl/test/bugs/Bug735Inv1AppletAWT.java new file mode 100644 index 000000000..e8cef5e16 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/bugs/Bug735Inv1AppletAWT.java @@ -0,0 +1,429 @@ +package com.jogamp.opengl.test.bugs; + +import java.applet.Applet; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.nio.FloatBuffer; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLException; +import javax.media.opengl.GLProfile; +import javax.media.opengl.GLRunnable; +import javax.media.opengl.GLUniformData; +import javax.media.opengl.awt.GLCanvas; +import javax.media.opengl.glu.GLU; + +import com.jogamp.newt.awt.NewtCanvasAWT; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.jogl.demos.es2.LandscapeES2; +import com.jogamp.opengl.util.GLArrayDataServer; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; +import com.jogamp.opengl.util.glsl.ShaderState; + +/** + * Difference to orig. Bug735Inv0AppletAWT: + * <pre> + * - MANUAL_FRAME_HANDLING: impl using pass through GLContext instead of static + * </pre> + * OSX Results: + * <pre> + * - Visible content + * - Fluent animation + * </pre> + */ +@SuppressWarnings("serial") +public class Bug735Inv1AppletAWT extends Applet implements Runnable { + static public int AWT = 0; + static public int NEWT = 1; + + static public int APPLET_WIDTH = 500; + static public int APPLET_HEIGHT = 290; + static public int TARGET_FPS = 120; + static public int TOOLKIT = NEWT; + static public boolean MANUAL_FRAME_HANDLING = true; + + ////////////////////////////////////////////////////////////////////////////// + + static private Frame frame; + static private Bug735Inv1AppletAWT applet; + private GLCanvas awtCanvas; + private GLWindow newtWindow; + private NewtCanvasAWT newtCanvas; + private DrawRunnable drawRunnable; + // JAU private GLContext context; + private GLU glu; + + private int width; + private int height; + private Thread thread; + + private boolean doneInit = false; + private boolean doneSetup = false; + + private long frameRatePeriod = 1000000000L / TARGET_FPS; + private long millisOffset; + private int frameCount; + private float frameRate; + + private ShaderCode vertShader; + private ShaderCode fragShader; + private ShaderProgram shaderProg; + private ShaderState shaderState; + private GLUniformData resolution; + private GLUniformData time; + private GLArrayDataServer vertices; + + private int fcount = 0, lastm = 0; + private int fint = 1; + + public void init() { + setSize(APPLET_WIDTH, APPLET_HEIGHT); + setPreferredSize(new Dimension(APPLET_WIDTH, APPLET_HEIGHT)); + width = APPLET_WIDTH; + height = APPLET_HEIGHT; + } + + public void start() { + thread = new Thread(this, "Animation Thread"); + thread.start(); + } + + public void run() { + int noDelays = 0; + // Number of frames with a delay of 0 ms before the + // animation thread yields to other running threads. + final int NO_DELAYS_PER_YIELD = 15; + final int TIMEOUT_SECONDS = 2; + + long beforeTime = System.nanoTime(); + long overSleepTime = 0L; + + millisOffset = System.currentTimeMillis(); + frameCount = 1; + while (Thread.currentThread() == thread) { + final CountDownLatch latch = new CountDownLatch(1); + requestDraw(latch); + try { + latch.await(TIMEOUT_SECONDS, TimeUnit.SECONDS); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + if (frameCount == 1) { + EventQueue.invokeLater(new Runnable() { + public void run() { + requestFocusInWindow(); + } + }); + } + + long afterTime = System.nanoTime(); + long timeDiff = afterTime - beforeTime; + long sleepTime = (frameRatePeriod - timeDiff) - overSleepTime; + if (sleepTime > 0) { // some time left in this cycle + try { + Thread.sleep(sleepTime / 1000000L, (int) (sleepTime % 1000000L)); + noDelays = 0; // Got some sleep, not delaying anymore + } catch (InterruptedException ex) { } + overSleepTime = (System.nanoTime() - afterTime) - sleepTime; + } else { // sleepTime <= 0; the frame took longer than the period + overSleepTime = 0L; + noDelays++; + if (noDelays > NO_DELAYS_PER_YIELD) { + Thread.yield(); // give another thread a chance to run + noDelays = 0; + } + } + beforeTime = System.nanoTime(); + } + } + + public void requestDraw(CountDownLatch latch) { + if (!doneInit) { + initDraw(); + } + + if (TOOLKIT == AWT) { + awtCanvas.invoke(true, drawRunnable); + } else if (TOOLKIT == NEWT) { + newtWindow.invoke(true, drawRunnable); + } + + if (latch != null) { + latch.countDown(); + } + } + + private class DrawRunnable implements GLRunnable { + private boolean notCurrent; + + @Override + public boolean run(GLAutoDrawable drawable) { + if (MANUAL_FRAME_HANDLING) { + makeContextCurrent(drawable.getContext()); + } + + if (!doneSetup) { + setup(drawable.getGL().getGL2ES2()); + } + draw(drawable.getGL().getGL2ES2()); + checkGLErrors(drawable.getGL()); + + if (MANUAL_FRAME_HANDLING) { + swapBuffers(drawable.getContext()); + releaseCurrentContext(drawable.getContext()); + } + + return true; + } + + private void makeContextCurrent(GLContext context) { + int MAX_CONTEXT_GRAB_ATTEMPTS = 10; + + if (context.isCurrent()) { + notCurrent = false; + } else { + notCurrent = true; + int value = GLContext.CONTEXT_NOT_CURRENT; + int attempt = 0; + do { + try { + value = context.makeCurrent(); + System.out.println("Made context current"); + } catch (final GLException gle) { + gle.printStackTrace(); + } finally { + attempt++; + if (attempt == MAX_CONTEXT_GRAB_ATTEMPTS) { + throw new RuntimeException("Failed to claim OpenGL context."); + } + } + try { + Thread.sleep(5); + } catch (final InterruptedException e) { + e.printStackTrace(); + } + + } while (value == GLContext.CONTEXT_NOT_CURRENT); + } + } + + private void swapBuffers(GLContext context) { + final GL gl = context.getGL(); + gl.glFlush(); + context.getGLDrawable().swapBuffers(); + } + + private void releaseCurrentContext(GLContext context) { + if (notCurrent) { + try { + context.release(); + System.out.println("Released context"); + } catch (final GLException gle) { + gle.printStackTrace(); + } + } + } + } + + private void initGL() { + GLProfile profile = GLProfile.getDefault(); + GLCapabilities caps = new GLCapabilities(profile); + caps.setBackgroundOpaque(true); + caps.setOnscreen(true); + caps.setSampleBuffers(false); + + if (TOOLKIT == AWT) { + awtCanvas = new GLCanvas(caps); + awtCanvas.setBounds(0, 0, applet.width, applet.height); + awtCanvas.setBackground(new Color(0xFFCCCCCC, true)); + awtCanvas.setFocusable(true); + + applet.setLayout(new BorderLayout()); + applet.add(awtCanvas, BorderLayout.CENTER); + + if (MANUAL_FRAME_HANDLING) { + awtCanvas.setIgnoreRepaint(true); + awtCanvas.setAutoSwapBufferMode(false); + } + } else if (TOOLKIT == NEWT) { + newtWindow = GLWindow.create(caps); + newtCanvas = new NewtCanvasAWT(newtWindow); + newtCanvas.setBounds(0, 0, applet.width, applet.height); + newtCanvas.setBackground(new Color(0xFFCCCCCC, true)); + newtCanvas.setFocusable(true); + + applet.setLayout(new BorderLayout()); + applet.add(newtCanvas, BorderLayout.CENTER); + + if (MANUAL_FRAME_HANDLING) { + newtCanvas.setIgnoreRepaint(true); + newtWindow.setAutoSwapBufferMode(false); + } + } + } + + private void initDraw() { + if (TOOLKIT == AWT) { + awtCanvas.setVisible(true); + // Force the realization + awtCanvas.display(); + if (awtCanvas.getDelegatedDrawable().isRealized()) { + // Request the focus here as it cannot work when the window is not visible + awtCanvas.requestFocus(); + } + } else if (TOOLKIT == NEWT) { + newtCanvas.setVisible(true); + // Force the realization + newtWindow.display(); + if (newtWindow.isRealized()) { + // Request the focus here as it cannot work when the window is not visible + newtCanvas.requestFocus(); + } + } + + drawRunnable = new DrawRunnable(); + + doneInit = true; + } + + private void setup(GL2ES2 gl) { + if (60 < TARGET_FPS) { + // Disables vsync + gl.setSwapInterval(0); + } + glu = new GLU(); + + vertShader = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, LandscapeES2.class, "shader", "shader/bin", "landscape", true); + fragShader = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, LandscapeES2.class, "shader", "shader/bin", "landscape", true); + vertShader.defaultShaderCustomization(gl, true, true); + fragShader.defaultShaderCustomization(gl, true, true); + shaderProg = new ShaderProgram(); + shaderProg.add(gl, vertShader, System.err); + shaderProg.add(gl, fragShader, System.err); + + shaderState = new ShaderState(); + shaderState.attachShaderProgram(gl, shaderProg, true); + + resolution = new GLUniformData("iResolution", 3, FloatBuffer.wrap(new float[] {width, height, 0})); + shaderState.ownUniform(resolution); + shaderState.uniform(gl, resolution); + + time = new GLUniformData("iGlobalTime", 0.0f); + shaderState.ownUniform(time); + + vertices = GLArrayDataServer.createGLSL("inVertex", 2, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW); + vertices.putf(-1.0f); vertices.putf(-1.0f); + vertices.putf(+1.0f); vertices.putf(-1.0f); + vertices.putf(-1.0f); vertices.putf(+1.0f); + vertices.putf(+1.0f); vertices.putf(+1.0f); + vertices.seal(gl, true); + shaderState.ownAttribute(vertices, true); + shaderState.useProgram(gl, false); + + doneSetup = true; + } + + private void draw(GL2ES2 gl) { + // gl.glClearColor(0.5f, 0.1f, 0.1f, 1); + // gl.glClear(GL2ES2.GL_COLOR_BUFFER_BIT); + + shaderState.useProgram(gl, true); + + time.setData((System.currentTimeMillis() - millisOffset) / 1000.0f); + shaderState.uniform(gl, time); + vertices.enableBuffer(gl, true); + gl.glDrawArrays(GL2ES2.GL_TRIANGLE_STRIP, 0, 4); + vertices.enableBuffer(gl, false); + + shaderState.useProgram(gl, false); + + // Compute current framerate and printout. + frameCount++; + fcount += 1; + int m = (int) (System.currentTimeMillis() - millisOffset); + if (m - lastm > 1000 * fint) { + frameRate = (float)(fcount) / fint; + fcount = 0; + lastm = m; + } + if (frameCount % TARGET_FPS == 0) { + System.out.println("FrameCount: " + frameCount + " - " + + "FrameRate: " + frameRate); + } + } + + private void checkGLErrors(GL gl) { + int err = gl.glGetError(); + if (err != 0) { + String errString = glu.gluErrorString(err); + System.out.println(errString); + } + } + + static public void main(String[] args) { + GraphicsEnvironment environment = + GraphicsEnvironment.getLocalGraphicsEnvironment(); + GraphicsDevice displayDevice = environment.getDefaultScreenDevice(); + + frame = new Frame(displayDevice.getDefaultConfiguration()); + frame.setBackground(new Color(0xCC, 0xCC, 0xCC)); + frame.setTitle("TestBug735Inv1AppletAWT"); + + try { + Class<?> c = Thread.currentThread().getContextClassLoader(). + loadClass(Bug735Inv1AppletAWT.class.getName()); + applet = (Bug735Inv1AppletAWT) c.newInstance(); + } catch (Exception e) { + throw new RuntimeException(e); + } + + frame.setLayout(null); + frame.add(applet); + frame.pack(); + frame.setResizable(false); + + applet.init(); + + Insets insets = frame.getInsets(); + int windowW = applet.width + insets.left + insets.right; + int windowH = applet.height + insets.top + insets.bottom; + frame.setSize(windowW, windowH); + + Rectangle screenRect = displayDevice.getDefaultConfiguration().getBounds(); + frame.setLocation(screenRect.x + (screenRect.width - applet.width) / 2, + screenRect.y + (screenRect.height - applet.height) / 2); + + int usableWindowH = windowH - insets.top - insets.bottom; + applet.setBounds((windowW - applet.width)/2, + insets.top + (usableWindowH - applet.height)/2, + applet.width, applet.height); + + // This allows to close the frame. + frame.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }); + + applet.initGL(); + frame.setVisible(true); + applet.start(); + } +} diff --git a/src/test/com/jogamp/opengl/test/bugs/Bug735Inv2AppletAWT.java b/src/test/com/jogamp/opengl/test/bugs/Bug735Inv2AppletAWT.java new file mode 100644 index 000000000..6340d2b64 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/bugs/Bug735Inv2AppletAWT.java @@ -0,0 +1,272 @@ +package com.jogamp.opengl.test.bugs; + +import java.applet.Applet; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; + +import com.jogamp.newt.awt.NewtCanvasAWT; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.jogl.demos.es2.LandscapeES2; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Difference to orig. Bug735Inv0AppletAWT: + * <pre> + * - Use GLEventListener + * - Add GLEventListener to GLAutoDrawable + * - Use GLAutoDrawable.display() instead of GLAutoDrawable.invoke(true, GLRunnable { init / render }) + * - Removed MANUAL_FRAME_HANDLING, obsolete due to GLAutoDrawable/GLEventListener + * </pre> + * OSX Results: + * <pre> + * - Visible content + * - Fluent animation + * </pre> + */ +@SuppressWarnings("serial") +public class Bug735Inv2AppletAWT extends Applet implements Runnable { + static public int AWT = 0; + static public int NEWT = 1; + + static public int APPLET_WIDTH = 500; + static public int APPLET_HEIGHT = 290; + static public int TARGET_FPS = 120; + static public int TOOLKIT = NEWT; + static public boolean IGNORE_AWT_REPAINT = false; + static public boolean USE_ECT = false; + static public int SWAP_INTERVAL = 1; + + ////////////////////////////////////////////////////////////////////////////// + + static boolean waitForKey = false; + static private Frame frame; + static private Bug735Inv2AppletAWT applet; + private GLCanvas awtCanvas; + private GLWindow newtWindow; + private GLAutoDrawable glad; + private NewtCanvasAWT newtCanvas; + private GLEventListener demo; + + private int width; + private int height; + private Thread thread; + + private long frameRatePeriod = 1000000000L / TARGET_FPS; + private int frameCount; + + public void init() { + setSize(APPLET_WIDTH, APPLET_HEIGHT); + setPreferredSize(new Dimension(APPLET_WIDTH, APPLET_HEIGHT)); + width = APPLET_WIDTH; + height = APPLET_HEIGHT; + initGL(); + } + + public void start() { + initDraw(); + thread = new Thread(this, "Animation Thread"); + thread.start(); + } + + public void run() { + int noDelays = 0; + // Number of frames with a delay of 0 ms before the + // animation thread yields to other running threads. + final int NO_DELAYS_PER_YIELD = 15; + final int TIMEOUT_SECONDS = 2; + + long beforeTime = System.nanoTime(); + long overSleepTime = 0L; + + frameCount = 1; + while (Thread.currentThread() == thread) { + if (frameCount == 1) { + EventQueue.invokeLater(new Runnable() { + public void run() { + requestFocusInWindow(); + } + }); + if( USE_ECT ) { + glad.setExclusiveContextThread(thread); + } + } + final CountDownLatch latch = new CountDownLatch(1); + requestDraw(latch); + try { + latch.await(TIMEOUT_SECONDS, TimeUnit.SECONDS); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + long afterTime = System.nanoTime(); + long timeDiff = afterTime - beforeTime; + long sleepTime = (frameRatePeriod - timeDiff) - overSleepTime; + if (sleepTime > 0) { // some time left in this cycle + try { + Thread.sleep(sleepTime / 1000000L, (int) (sleepTime % 1000000L)); + noDelays = 0; // Got some sleep, not delaying anymore + } catch (InterruptedException ex) { } + overSleepTime = (System.nanoTime() - afterTime) - sleepTime; + } else { // sleepTime <= 0; the frame took longer than the period + overSleepTime = 0L; + noDelays++; + if (noDelays > NO_DELAYS_PER_YIELD) { + Thread.yield(); // give another thread a chance to run + noDelays = 0; + } + } + beforeTime = System.nanoTime(); + } + } + + public void requestDraw(CountDownLatch latch) { + glad.display(); + + if (latch != null) { + latch.countDown(); + } + } + + private void initGL() { + GLProfile profile = GLProfile.getDefault(); + GLCapabilities caps = new GLCapabilities(profile); + caps.setBackgroundOpaque(true); + caps.setOnscreen(true); + caps.setSampleBuffers(false); + + if (TOOLKIT == AWT) { + awtCanvas = new GLCanvas(caps); + awtCanvas.setBounds(0, 0, applet.width, applet.height); + awtCanvas.setBackground(new Color(0xFFCCCCCC, true)); + awtCanvas.setFocusable(true); + + applet.setLayout(new BorderLayout()); + applet.add(awtCanvas, BorderLayout.CENTER); + + if (IGNORE_AWT_REPAINT) { + awtCanvas.setIgnoreRepaint(true); + } + glad = awtCanvas; + } else if (TOOLKIT == NEWT) { + newtWindow = GLWindow.create(caps); + newtCanvas = new NewtCanvasAWT(newtWindow); + newtCanvas.setBounds(0, 0, applet.width, applet.height); + newtCanvas.setBackground(new Color(0xFFCCCCCC, true)); + newtCanvas.setFocusable(true); + + applet.setLayout(new BorderLayout()); + applet.add(newtCanvas, BorderLayout.CENTER); + + if (IGNORE_AWT_REPAINT) { + newtCanvas.setIgnoreRepaint(true); + } + glad = newtWindow; + } + + demo = new LandscapeES2(SWAP_INTERVAL); + glad.addGLEventListener(demo); + } + + private void initDraw() { + if (TOOLKIT == AWT) { + awtCanvas.setVisible(true); + // Force the realization + awtCanvas.display(); + if (awtCanvas.getDelegatedDrawable().isRealized()) { + // Request the focus here as it cannot work when the window is not visible + awtCanvas.requestFocus(); + } + } else if (TOOLKIT == NEWT) { + newtCanvas.setVisible(true); + // Force the realization + newtWindow.display(); + if (newtWindow.isRealized()) { + // Request the focus here as it cannot work when the window is not visible + newtCanvas.requestFocus(); + } + } + } + + static public void main(String[] args) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-vsync")) { + i++; + SWAP_INTERVAL = MiscUtils.atoi(args[i], SWAP_INTERVAL); + } else if(args[i].equals("-exclctx")) { + USE_ECT = true; + } else if(args[i].equals("-wait")) { + waitForKey = true; + } + } + System.err.println("swapInterval "+SWAP_INTERVAL); + System.err.println("exclusiveContext "+USE_ECT); + if(waitForKey) { + UITestCase.waitForKey("Start"); + } + + GraphicsEnvironment environment = + GraphicsEnvironment.getLocalGraphicsEnvironment(); + GraphicsDevice displayDevice = environment.getDefaultScreenDevice(); + + frame = new Frame(displayDevice.getDefaultConfiguration()); + frame.setBackground(new Color(0xCC, 0xCC, 0xCC)); + frame.setTitle("TestBug735Inv2AppletAWT"); + + try { + Class<?> c = Thread.currentThread().getContextClassLoader(). + loadClass(Bug735Inv2AppletAWT.class.getName()); + applet = (Bug735Inv2AppletAWT) c.newInstance(); + } catch (Exception e) { + throw new RuntimeException(e); + } + + frame.setLayout(null); + frame.add(applet); + frame.pack(); + frame.setResizable(false); + + applet.init(); + + Insets insets = frame.getInsets(); + int windowW = applet.width + insets.left + insets.right; + int windowH = applet.height + insets.top + insets.bottom; + frame.setSize(windowW, windowH); + + Rectangle screenRect = displayDevice.getDefaultConfiguration().getBounds(); + frame.setLocation(screenRect.x + (screenRect.width - applet.width) / 2, + screenRect.y + (screenRect.height - applet.height) / 2); + + int usableWindowH = windowH - insets.top - insets.bottom; + applet.setBounds((windowW - applet.width)/2, + insets.top + (usableWindowH - applet.height)/2, + applet.width, applet.height); + + // This allows to close the frame. + frame.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }); + + frame.setVisible(true); + applet.start(); + } +} diff --git a/src/test/com/jogamp/opengl/test/bugs/Bug735Inv3AppletAWT.java b/src/test/com/jogamp/opengl/test/bugs/Bug735Inv3AppletAWT.java new file mode 100644 index 000000000..0a4c54046 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/bugs/Bug735Inv3AppletAWT.java @@ -0,0 +1,218 @@ +package com.jogamp.opengl.test.bugs; + +import java.applet.Applet; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Frame; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; +import javax.swing.SwingUtilities; + +import com.jogamp.newt.awt.NewtCanvasAWT; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.jogl.demos.es2.LandscapeES2; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.AnimatorBase; + +/** + * Difference to orig. Bug735Inv0AppletAWT: + * <pre> + * - Use GLEventListener + * - Add GLEventListener to GLAutoDrawable + * - Use GLAutoDrawable.display() instead of GLAutoDrawable.invoke(true, GLRunnable { init / render }) + * - Removed MANUAL_FRAME_HANDLING, obsolete due to GLAutoDrawable/GLEventListener + * - Use Animator + * - Remove applet, component sizes, use frame based size via validate + * - Run frame validation/visibility on AWT-EDT + * - Add Wait-For-Key after init (perf-test) + * </pre> + * OSX Results: + * <pre> + * - Visible content + * - Fluent animation + * </pre> + */ +@SuppressWarnings("serial") +public class Bug735Inv3AppletAWT extends Applet { + static public int AWT = 0; + static public int NEWT = 1; + + static public int APPLET_WIDTH = 500; + static public int APPLET_HEIGHT = 290; + static public int TOOLKIT = NEWT; + static public boolean IGNORE_AWT_REPAINT = false; + static public boolean USE_ECT = false; + static public int SWAP_INTERVAL = 1; + + ////////////////////////////////////////////////////////////////////////////// + + static boolean waitForKey = false; + static private Frame frame; + static private Bug735Inv3AppletAWT applet; + private GLCanvas awtCanvas; + private GLWindow newtWindow; + private GLAutoDrawable glad; + private NewtCanvasAWT newtCanvas; + private GLEventListener demo; + private AnimatorBase animator; + + private int width; + private int height; + + public void init() { + setSize(APPLET_WIDTH, APPLET_HEIGHT); + // JAU setPreferredSize(new Dimension(APPLET_WIDTH, APPLET_HEIGHT)); + width = APPLET_WIDTH; + height = APPLET_HEIGHT; + initGL(); + } + + public void start() { + initDraw(); + animator.start(); + animator.setUpdateFPSFrames(60, System.err); + } + + private void initGL() { + GLProfile profile = GLProfile.getDefault(); + GLCapabilities caps = new GLCapabilities(profile); + caps.setBackgroundOpaque(true); + caps.setOnscreen(true); + caps.setSampleBuffers(false); + + if (TOOLKIT == AWT) { + awtCanvas = new GLCanvas(caps); + // JAU awtCanvas.setBounds(0, 0, applet.width, applet.height); + awtCanvas.setBackground(new Color(0xFFCCCCCC, true)); + awtCanvas.setFocusable(true); + + applet.setLayout(new BorderLayout()); + applet.add(awtCanvas, BorderLayout.CENTER); + + if (IGNORE_AWT_REPAINT) { + awtCanvas.setIgnoreRepaint(true); + } + glad = awtCanvas; + } else if (TOOLKIT == NEWT) { + newtWindow = GLWindow.create(caps); + newtCanvas = new NewtCanvasAWT(newtWindow); + // JAU newtCanvas.setBounds(0, 0, applet.width, applet.height); + newtCanvas.setBackground(new Color(0xFFCCCCCC, true)); + newtCanvas.setFocusable(true); + + applet.setLayout(new BorderLayout()); + applet.add(newtCanvas, BorderLayout.CENTER); + + if (IGNORE_AWT_REPAINT) { + newtCanvas.setIgnoreRepaint(true); + } + glad = newtWindow; + } + + demo = new LandscapeES2(SWAP_INTERVAL); + // demo = new GearsES2(SWAP_INTERVAL); + glad.addGLEventListener(demo); + animator = new Animator(glad); + animator.setExclusiveContext(USE_ECT); + } + + private void initDraw() { + if (TOOLKIT == AWT) { + // JAU awtCanvas.setVisible(true); + if (awtCanvas.getDelegatedDrawable().isRealized()) { + // Request the focus here as it cannot work when the window is not visible + awtCanvas.requestFocus(); + } + } else if (TOOLKIT == NEWT) { + // JAU newtCanvas.setVisible(true); + // Force the realization + // JAU newtWindow.display(); + if (newtWindow.isRealized()) { + // Request the focus here as it cannot work when the window is not visible + newtCanvas.requestFocus(); + } + } + } + + static public void main(String[] args) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-vsync")) { + i++; + SWAP_INTERVAL = MiscUtils.atoi(args[i], SWAP_INTERVAL); + } else if(args[i].equals("-exclctx")) { + USE_ECT = true; + } else if(args[i].equals("-wait")) { + waitForKey = true; + } + } + System.err.println("swapInterval "+SWAP_INTERVAL); + System.err.println("exclusiveContext "+USE_ECT); + if(waitForKey) { + UITestCase.waitForKey("Start"); + } + + final GraphicsEnvironment environment = + GraphicsEnvironment.getLocalGraphicsEnvironment(); + final GraphicsDevice displayDevice = environment.getDefaultScreenDevice(); + + frame = new Frame(displayDevice.getDefaultConfiguration()); + frame.setBackground(new Color(0xCC, 0xCC, 0xCC)); + frame.setTitle("TestBug735Inv3AppletAWT"); + + // This allows to close the frame. + frame.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }); + + try { + Class<?> c = Thread.currentThread().getContextClassLoader(). + loadClass(Bug735Inv3AppletAWT.class.getName()); + applet = (Bug735Inv3AppletAWT) c.newInstance(); + } catch (Exception e) { + throw new RuntimeException(e); + } + + // JAU frame.setLayout(null); + frame.add(applet); + + applet.init(); + + Insets insets = frame.getInsets(); + final int windowW = applet.width + insets.left + insets.right; + final int windowH = applet.height + insets.top + insets.bottom; + + try { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setSize(windowW, windowH); + frame.validate(); + // JAU frame.pack(); + Rectangle screenRect = displayDevice.getDefaultConfiguration().getBounds(); + frame.setLocation(screenRect.x + (screenRect.width - applet.width) / 2, + screenRect.y + (screenRect.height - applet.height) / 2); + + frame.setResizable(false); + frame.setVisible(true); + } + }); + } catch (Exception e) { + e.printStackTrace(); + } + + applet.start(); + } +} diff --git a/src/test/com/jogamp/opengl/test/bugs/Bug735Inv4AWT.java b/src/test/com/jogamp/opengl/test/bugs/Bug735Inv4AWT.java new file mode 100644 index 000000000..f0be22b65 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/bugs/Bug735Inv4AWT.java @@ -0,0 +1,202 @@ +package com.jogamp.opengl.test.bugs; + +import java.awt.Color; +import java.awt.Frame; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; +import javax.swing.SwingUtilities; + +import com.jogamp.newt.awt.NewtCanvasAWT; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.jogl.demos.es2.LandscapeES2; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.AnimatorBase; + +/** + * Difference to orig. Bug735Inv0AppletAWT: + * <pre> + * - Use GLEventListener + * - Add GLEventListener to GLAutoDrawable + * - Use GLAutoDrawable.display() instead of GLAutoDrawable.invoke(true, GLRunnable { init / render }) + * - Removed MANUAL_FRAME_HANDLING, obsolete due to GLAutoDrawable/GLEventListener + * - Use Animator + * - Remove component sizes, use frame based size via validate + * - Run frame validation/visibility on AWT-EDT + * - Add Wait-For-Key after init (perf-test) + * - Remove intermediate applet! + * </pre> + * OSX Results: + * <pre> + * - Visible content + * - Fluent animation + * </pre> + */ +public class Bug735Inv4AWT { + static public int AWT = 0; + static public int NEWT = 1; + + static public int APPLET_WIDTH = 500; + static public int APPLET_HEIGHT = 290; + static public int TOOLKIT = NEWT; + static public boolean IGNORE_AWT_REPAINT = false; + static public boolean USE_ECT = false; + static public int SWAP_INTERVAL = 1; + + ////////////////////////////////////////////////////////////////////////////// + + static boolean waitForKey = false; + static private Frame frame; + static private Bug735Inv4AWT applet; + private GLCanvas awtCanvas; + private GLWindow newtWindow; + private GLAutoDrawable glad; + private NewtCanvasAWT newtCanvas; + private GLEventListener demo; + private AnimatorBase animator; + + private int width; + private int height; + + public void init() { + width = APPLET_WIDTH; + height = APPLET_HEIGHT; + initGL(); + } + + public void start() { + initDraw(); + animator.start(); + animator.setUpdateFPSFrames(60, System.err); + } + + private void initGL() { + GLProfile profile = GLProfile.getDefault(); + GLCapabilities caps = new GLCapabilities(profile); + caps.setBackgroundOpaque(true); + caps.setOnscreen(true); + caps.setSampleBuffers(false); + + if (TOOLKIT == AWT) { + awtCanvas = new GLCanvas(caps); + awtCanvas.setBackground(new Color(0xFFCCCCCC, true)); + awtCanvas.setFocusable(true); + + if (IGNORE_AWT_REPAINT) { + awtCanvas.setIgnoreRepaint(true); + } + glad = awtCanvas; + } else if (TOOLKIT == NEWT) { + newtWindow = GLWindow.create(caps); + newtCanvas = new NewtCanvasAWT(newtWindow); + newtCanvas.setBackground(new Color(0xFFCCCCCC, true)); + newtCanvas.setFocusable(true); + + if (IGNORE_AWT_REPAINT) { + newtCanvas.setIgnoreRepaint(true); + } + glad = newtWindow; + } + + demo = new LandscapeES2(SWAP_INTERVAL); + // demo = new GearsES2(SWAP_INTERVAL); + glad.addGLEventListener(demo); + animator = new Animator(glad); + animator.setExclusiveContext(USE_ECT); + } + + private void initDraw() { + if (TOOLKIT == AWT) { + if (awtCanvas.getDelegatedDrawable().isRealized()) { + // Request the focus here as it cannot work when the window is not visible + awtCanvas.requestFocus(); + } + } else if (TOOLKIT == NEWT) { + // newtCanvas.repaint(); + // Force the realization + // newtWindow.display(); + if (newtWindow.isRealized()) { + // Request the focus here as it cannot work when the window is not visible + newtCanvas.requestFocus(); + } + } + } + + static public void main(String[] args) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-vsync")) { + i++; + SWAP_INTERVAL = MiscUtils.atoi(args[i], SWAP_INTERVAL); + } else if(args[i].equals("-exclctx")) { + USE_ECT = true; + } else if(args[i].equals("-wait")) { + waitForKey = true; + } + } + System.err.println("swapInterval "+SWAP_INTERVAL); + System.err.println("exclusiveContext "+USE_ECT); + if(waitForKey) { + UITestCase.waitForKey("Start"); + } + + final GraphicsEnvironment environment = + GraphicsEnvironment.getLocalGraphicsEnvironment(); + final GraphicsDevice displayDevice = environment.getDefaultScreenDevice(); + + frame = new Frame(displayDevice.getDefaultConfiguration()); + // JAU frame.setBackground(new Color(0xCC, 0xCC, 0xCC)); + frame.setTitle("TestBug735Inv4AWT"); + + // This allows to close the frame. + frame.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }); + + applet = new Bug735Inv4AWT(); + applet.init(); + + if (TOOLKIT == AWT) { + frame.add(applet.awtCanvas); + } else if (TOOLKIT == NEWT) { + frame.add(applet.newtCanvas); + } + // frame.pack(); + // frame.setResizable(false); + + Insets insets = frame.getInsets(); + final int windowW = applet.width + insets.left + insets.right; + final int windowH = applet.height + insets.top + insets.bottom; + + try { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setSize(windowW, windowH); + frame.validate(); + // frame.pack(); + Rectangle screenRect = displayDevice.getDefaultConfiguration().getBounds(); + frame.setLocation(screenRect.x + (screenRect.width - applet.width) / 2, + screenRect.y + (screenRect.height - applet.height) / 2); + + frame.setVisible(true); + } + }); + } catch (Exception e) { + e.printStackTrace(); + } + + applet.start(); + } +} diff --git a/src/test/com/jogamp/opengl/test/bugs/DemoBug910ExtendedAWTAppletLifecycleCheck.java b/src/test/com/jogamp/opengl/test/bugs/DemoBug910ExtendedAWTAppletLifecycleCheck.java new file mode 100644 index 000000000..1d7f6e78c --- /dev/null +++ b/src/test/com/jogamp/opengl/test/bugs/DemoBug910ExtendedAWTAppletLifecycleCheck.java @@ -0,0 +1,234 @@ +/** + * Copyright 2013 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.bugs; + +import java.applet.Applet; +import java.awt.BorderLayout; +import java.awt.Canvas; +import java.awt.Color; +import java.awt.Component; +import java.awt.EventQueue; +import java.awt.Graphics; +import java.lang.reflect.InvocationTargetException; + +@SuppressWarnings("serial") +public class DemoBug910ExtendedAWTAppletLifecycleCheck extends Applet { + + private static String currentThreadName() { return "["+Thread.currentThread().getName()+", isAWT-EDT "+EventQueue.isDispatchThread()+"]"; } + + private static void invoke(boolean wait, Runnable r) { + if(EventQueue.isDispatchThread()) { + r.run(); + } else { + try { + if(wait) { + EventQueue.invokeAndWait(r); + } else { + EventQueue.invokeLater(r); + } + } catch (InvocationTargetException e) { + throw new RuntimeException(e.getTargetException()); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + } + + private static final String comp2Str(Component c) { + return c.getClass().getSimpleName()+"[visible "+c.isVisible()+", showing "+c.isShowing()+", valid "+c.isValid()+ + ", displayable "+c.isDisplayable()+", "+c.getX()+"/"+c.getY()+" "+c.getWidth()+"x"+c.getHeight()+"]"; + } + + private void println(String msg) { + System.err.println(msg); + } + + private final void checkComponentState(String msg, boolean expIsContained, int expAddNotifyCount, int expRemoveNotifyCount) { + final int compCount = getComponentCount(); + final Component c = 1 <= compCount ? getComponent(0) : null; + final String clazzName = null != c ? c.getName() : "n/a"; + final boolean isContained = c == myCanvas; + final String okS = ( expIsContained == isContained && + expAddNotifyCount == myCanvas.addNotifyCount && + expRemoveNotifyCount == myCanvas.removeNotifyCount ) ? "OK" : "ERROR"; + println("Component-State @ "+msg+": "+okS+ + ", contained[exp "+expIsContained+", has "+isContained+"]"+(expIsContained!=isContained?"*":"")+ + ", addNotify[exp "+expAddNotifyCount+", has "+myCanvas.addNotifyCount+"]"+(expAddNotifyCount!=myCanvas.addNotifyCount?"*":"")+ + ", removeNotify[exp "+expRemoveNotifyCount+", has "+myCanvas.removeNotifyCount+"]"+(expRemoveNotifyCount!=myCanvas.removeNotifyCount?"*":"")+ + ", compCount "+compCount+", compClazz "+clazzName); + } + + volatile int initCount = 0; + volatile int startCount = 0; + volatile int stopCount = 0; + volatile int destroyCount = 0; + + private final void checkAppletState(String msg, boolean expIsActive, + int expInitCount, int expStartCount, int expStopCount, boolean startStopCountEquals, int expDestroyCount) { + final boolean isActive = this.isActive(); + final String okS = ( expInitCount == initCount && + expIsActive == isActive && + expStartCount == startCount && + expStopCount == stopCount && + expDestroyCount == destroyCount && + ( !startStopCountEquals || startCount == stopCount ) ) ? "OK" : "ERROR"; + println("Applet-State @ "+msg+": "+okS+ + ", active[exp "+expIsActive+", has "+isActive+"]"+(expIsActive!=isActive?"*":"")+ + ", init[exp "+expInitCount+", has "+initCount+"]"+(expInitCount!=initCount?"*":"")+ + ", start[exp "+expStartCount+", has "+startCount+"]"+(expStartCount!=startCount?"*":"")+ + ", stop[exp "+expStopCount+", has "+stopCount+"]"+(expStopCount!=stopCount?"*":"")+ + ", start==stop[exp "+startStopCountEquals+", start "+startCount+", stop "+stopCount+"]"+(( startStopCountEquals && startCount != stopCount )?"*":"")+ + ", destroy[exp "+expDestroyCount+", has "+destroyCount+"]"+(expDestroyCount!=destroyCount?"*":"")); + } + + private class MyCanvas extends Canvas { + int addNotifyCount = 0; + int removeNotifyCount = 0; + int paintCount = 0; + + MyCanvas() { + setBackground( new Color( 200, 200, 255 ) ); + } + + public String toString() { + return comp2Str(this)+", add/remove[addNotify "+addNotifyCount+", removeCount "+removeNotifyCount+"]"; + } + + @Override + public void addNotify() { + addNotifyCount++; + println("Applet.Canvas.addNotify() - "+currentThreadName()); + if( !EventQueue.isDispatchThread() ) { + println("Applet.Canvas.addNotify() ERROR: Not on AWT-EDT"); + } + // Thread.dumpStack(); + super.addNotify(); + println("Applet.Canvas.addNotify(): "+this); + } + + @Override + public void removeNotify() { + removeNotifyCount++; + println("Applet.Canvas.removeNotify() - "+currentThreadName()); + println("Applet.Canvas.removeNotify(): "+this); + if( !EventQueue.isDispatchThread() ) { + println("Applet.Canvas.removeNotify() ERROR: Not on AWT-EDT"); + } + // Thread.dumpStack(); + super.removeNotify(); + } + + @Override + public void paint(Graphics g) { + super.paint(g); + paintCount++; + final int width = getWidth(); + final int height = getHeight(); + final String msg = "The payload Canvas. Paint "+width+"x"+height+" #"+paintCount; + g.setColor(Color.black); + g.drawString(msg, 64, 64); + } + } + MyCanvas myCanvas = null; + + @Override + public void init() { + final java.awt.Dimension aSize = getSize(); + println("Applet.init() START - applet.size "+aSize+" - "+currentThreadName()); + initCount++; + checkAppletState("init", false /* expIsActive */, 1 /* expInitCount */, + 0 /* expStartCount */, 0 /* expStopCount */, true /* startStopCountEquals */, + 0 /* expDestroyCount */); + invoke(true, new Runnable() { + public void run() { + setLayout(new BorderLayout()); + myCanvas = new MyCanvas(); + println("Applet.init(): self "+comp2Str(DemoBug910ExtendedAWTAppletLifecycleCheck.this)); + println("Applet.init(): canvas "+comp2Str(myCanvas)); + checkComponentState("init-add.pre", false, 0, 0); + add(myCanvas, BorderLayout.CENTER); + validate(); + checkComponentState("init-add.post", true, 1, 0); + println("Applet.init(): canvas "+comp2Str(myCanvas)); + } } ); + println("Applet.init() END - "+currentThreadName()); + } + + @Override + public void start() { + println("Applet.start() START (isVisible "+isVisible()+", isDisplayable "+isDisplayable()+") - "+currentThreadName()); + startCount++; + checkAppletState("start", true /* expIsActive */, 1 /* expInitCount */, + startCount /* expStartCount */, startCount-1 /* expStopCount */, false /* startStopCountEquals */, + 0 /* expDestroyCount */); + invoke(true, new Runnable() { + public void run() { + checkComponentState("start-visible.pre", true, 1, 0); + if( null != myCanvas ) { + myCanvas.setFocusable(true); + myCanvas.requestFocus(); + } + checkComponentState("start-visible.post", true, 1, 0); + println("Applet.start(): self "+comp2Str(DemoBug910ExtendedAWTAppletLifecycleCheck.this)); + println("Applet.start(): canvas "+comp2Str(myCanvas)); + } + }); + println("Applet.start() END - "+currentThreadName()); + } + + @Override + public void stop() { + println("Applet.stop() START - "+currentThreadName()); + stopCount++; + checkAppletState("stop", false /* expIsActive */, 1 /* expInitCount */, + stopCount /* expStartCount */, stopCount /* expStopCount */, true /* startStopCountEquals */, + 0 /* expDestroyCount */); + invoke(true, new Runnable() { + public void run() { + checkComponentState("stop", true, 1, 0); + } } ); + println("Applet.stop() END - "+currentThreadName()); + } + + @Override + public void destroy() { + println("Applet.destroy() START - "+currentThreadName()); + destroyCount++; + checkAppletState("destroy", false /* expIsActive */, 1 /* expInitCount */, + startCount /* expStartCount */, stopCount /* expStopCount */, true /* startStopCountEquals */, + 1 /* expDestroyCount */); + invoke(true, new Runnable() { + public void run() { + checkComponentState("destroy-remove.pre", true, 1, 0); + remove(myCanvas); + checkComponentState("destroy-remove.post", false, 1, 1); + } } ); + println("Applet.destroy() END - "+currentThreadName()); + } +} + diff --git a/src/test/com/jogamp/opengl/test/bugs/Issue344Base.java b/src/test/com/jogamp/opengl/test/bugs/Issue344Base.java index 9b0a4c6a0..2a7afabff 100644 --- a/src/test/com/jogamp/opengl/test/bugs/Issue344Base.java +++ b/src/test/com/jogamp/opengl/test/bugs/Issue344Base.java @@ -36,7 +36,7 @@ public abstract class Issue344Base implements GLEventListener protected abstract String getText(); protected void run(String[] args) { - Frame frame = new Frame(getClass().getName()); + final Frame frame = new Frame(getClass().getName()); frame.setLayout(new BorderLayout()); GLCanvas canvas = new GLCanvas(); @@ -53,7 +53,14 @@ public abstract class Issue344Base implements GLEventListener }).start(); } }); - frame.setVisible(true); + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(true); + } } ); + } catch(Exception ex) { + throw new RuntimeException(ex); + } } public void init(GLAutoDrawable drawable) diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestRegionRendererNEWT01.java b/src/test/com/jogamp/opengl/test/junit/graph/TestRegionRendererNEWT01.java index a6616945d..e9609ca9c 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/TestRegionRendererNEWT01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/TestRegionRendererNEWT01.java @@ -38,6 +38,8 @@ import javax.media.opengl.GLProfile; import org.junit.Assert; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import com.jogamp.common.os.Platform; import com.jogamp.graph.curve.Region; @@ -51,6 +53,7 @@ import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.util.glsl.ShaderState; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestRegionRendererNEWT01 extends UITestCase { public static void main(String args[]) throws IOException { diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java index 738d40971..826c08ed4 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java @@ -45,19 +45,22 @@ import javax.media.opengl.GLRunnable; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import com.jogamp.graph.curve.opengl.RenderState; import com.jogamp.graph.curve.opengl.TextRenderer; import com.jogamp.graph.font.Font; import com.jogamp.graph.font.FontFactory; -import com.jogamp.graph.geom.AABBox; import com.jogamp.graph.geom.opengl.SVertex; import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.math.geom.AABBox; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.util.GLReadBufferUtil; import com.jogamp.opengl.util.glsl.ShaderState; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestTextRendererNEWT00 extends UITestCase { static final boolean DEBUG = false; static final boolean TRACE = false; @@ -193,7 +196,7 @@ public class TestTextRendererNEWT00 extends UITestCase { pw.printf("%s-%03dx%03d-T%04d", objName, drawable.getWidth(), drawable.getHeight(), texSize[0]); final String filename = dir + sw +".png"; - if(screenshot.readPixels(drawable.getGL(), drawable, false)) { + if(screenshot.readPixels(drawable.getGL(), false)) { screenshot.write(new File(filename)); } } diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT01.java b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT01.java index ea02e930c..75a672a5b 100755..100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT01.java @@ -39,6 +39,8 @@ import javax.media.opengl.GLProfile; import org.junit.Assert; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import com.jogamp.common.os.Platform; import com.jogamp.graph.curve.Region; @@ -52,6 +54,7 @@ import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.util.glsl.ShaderState; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestTextRendererNEWT01 extends UITestCase { static final boolean DEBUG = false; static final boolean TRACE = false; diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT10.java b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT10.java index c9f28309c..77f562dda 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT10.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT10.java @@ -38,22 +38,28 @@ import javax.media.opengl.GLProfile; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import com.jogamp.graph.curve.opengl.RenderState; import com.jogamp.graph.curve.opengl.TextRenderer; import com.jogamp.graph.font.Font; import com.jogamp.graph.font.FontFactory; -import com.jogamp.graph.geom.AABBox; import com.jogamp.graph.geom.opengl.SVertex; +import com.jogamp.opengl.math.geom.AABBox; import com.jogamp.opengl.test.junit.util.NEWTGLContext; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.util.glsl.ShaderState; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestTextRendererNEWT10 extends UITestCase { static final boolean DEBUG = false; static final boolean TRACE = false; static long duration = 100; // ms + static boolean forceES2 = false; + static boolean forceGL3 = false; + static boolean mainRun = false; static final int[] texSize = new int[] { 0 }; static final int fontSize = 24; @@ -71,10 +77,15 @@ public class TestTextRendererNEWT10 extends UITestCase { } public static void main(String args[]) throws IOException { + mainRun = true; for(int i=0; i<args.length; i++) { if(args[i].equals("-time")) { i++; duration = atoi(args[i]); + } else if(args[i].equals("-es2")) { + forceES2 = true; + } else if(args[i].equals("-gl3")) { + forceGL3 = true; } } String tstname = TestTextRendererNEWT10.class.getName(); @@ -90,8 +101,15 @@ public class TestTextRendererNEWT10 extends UITestCase { @Test public void testTextRendererMSAA01() throws InterruptedException { - GLProfile glp = GLProfile.get(GLProfile.GL2ES2); - GLCapabilities caps = new GLCapabilities(glp); + final GLProfile glp; + if(forceGL3) { + glp = GLProfile.get(GLProfile.GL3); + } else if(forceES2) { + glp = GLProfile.get(GLProfile.GLES2); + } else { + glp = GLProfile.getGL2ES2(); + } + final GLCapabilities caps = new GLCapabilities( glp ); caps.setAlphaBits(4); caps.setSampleBuffers(true); caps.setNumSamples(4); diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TextRendererGLELBase.java b/src/test/com/jogamp/opengl/test/junit/graph/TextRendererGLELBase.java new file mode 100644 index 000000000..1282d5d97 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/graph/TextRendererGLELBase.java @@ -0,0 +1,195 @@ +/** + * Copyright 2014 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.graph; + +import java.io.IOException; + +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.fixedfunc.GLMatrixFunc; + +import com.jogamp.graph.curve.opengl.RenderState; +import com.jogamp.graph.curve.opengl.TextRenderer; +import com.jogamp.graph.font.Font; +import com.jogamp.graph.font.FontFactory; +import com.jogamp.graph.geom.opengl.SVertex; +import com.jogamp.opengl.math.geom.AABBox; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderState; + +public abstract class TextRendererGLELBase implements GLEventListener { + protected final float[] textPosition = new float[] {0,0,0}; + protected final int[] texSize = new int[] { 0 }; + protected final float[] staticRGBAColor = new float[] { 1f, 1f, 1f, 1f }; + + protected final Font font; + protected final int usrRenderModes; + + /** + * In exclusive mode, impl. uses a pixelScale of 1f and orthogonal PMV on window dimensions + * and renderString uses 'height' for '1'. + * <p> + * In non-exclusive mode, i.e. shared w/ custom PMV (within another 3d scene), + * it uses the custom pixelScale and renderString uses normalized 'height', i.e. '1'. + * </p> + */ + protected boolean exclusivePMVMatrix = true; + protected PMVMatrix usrPMVMatrix = null; + protected RenderState rs = null; + protected TextRenderer renderer = null; + + /** font size in pixels, default is 24 */ + protected int fontSize = 24; + /** scale pixel, default is 1f */ + protected float pixelScale = 1.0f; + protected int texSizeScale = 2; + + boolean flipVerticalInGLOrientation = false; + + public TextRendererGLELBase(final int renderModes) { + usrRenderModes = renderModes; + { + Font _font = null; + try { + _font = FontFactory.get(FontFactory.UBUNTU).getDefault(); + } catch (IOException e) { + e.printStackTrace(); + } + this.font = _font; + } + } + + public void setFlipVerticalInGLOrientation(boolean v) { flipVerticalInGLOrientation=v; } + public final TextRenderer getRenderer() { return renderer; } + + @Override + public void init(GLAutoDrawable drawable) { + if( null != font ) { + exclusivePMVMatrix = null == usrPMVMatrix; + this.rs = RenderState.createRenderState(new ShaderState(), SVertex.factory(), usrPMVMatrix); + this.renderer = TextRenderer.create(rs, usrRenderModes); + if( 0 == usrRenderModes ) { + texSizeScale = 0; + } + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + renderer.init(gl); + renderer.setAlpha(gl, staticRGBAColor[3]); + renderer.setColorStatic(gl, staticRGBAColor[0], staticRGBAColor[1], staticRGBAColor[2]); + final ShaderState st = rs.getShaderState(); + st.useProgram(gl, false); + } else { + this.rs = null; + this.renderer = null; + } + } + + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + if( null != renderer ) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + final ShaderState st = rs.getShaderState(); + st.useProgram(gl, true); + if( exclusivePMVMatrix ) { + // renderer.reshapePerspective(gl, 45.0f, width, height, 0.1f, 1000.0f); + renderer.reshapeOrtho(gl, width, height, 0.1f, 1000.0f); + pixelScale = 1.0f; + } else { + renderer.reshapeNotify(gl, width, height); + } + st.useProgram(gl, false); + texSize[0] = width * texSizeScale; + } + } + + @Override + public abstract void display(GLAutoDrawable drawable); + + @Override + public void dispose(GLAutoDrawable drawable) { + if( null != renderer ) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + renderer.destroy(gl); + } + } + + int lastRow = -1; + + public void renderString(GLAutoDrawable drawable, String text, int column, float tx, float ty, float tz) { + final int row = lastRow + 1; + renderString(drawable, text, column, row, tx, ty, tz); + lastRow = row; + } + + public void renderString(GLAutoDrawable drawable, String text, int column, int row, float tx, float ty, float tz) { + if( null != renderer ) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + + float dx = tx; + float dy; + + if( !exclusivePMVMatrix ) { + dy = 1f-ty; + } else { + final int height = drawable.getHeight(); + dy = height-ty; + } + + final AABBox textBox = font.getStringBounds(text, fontSize); + dx += pixelScale * font.getAdvanceWidth('X', fontSize) * column; + dy -= pixelScale * (int)textBox.getHeight() * ( row + 1 ); + + final ShaderState st = rs.getShaderState(); + final PMVMatrix pmvMatrix = rs.pmvMatrix(); + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + if( !exclusivePMVMatrix ) { + pmvMatrix.glPushMatrix(); + } else { + pmvMatrix.glLoadIdentity(); + } + + st.useProgram(gl, true); + gl.glEnable(GL2ES2.GL_BLEND); + pmvMatrix.glTranslatef(dx, dy, tz); + if( flipVerticalInGLOrientation && drawable.isGLOriented() ) { + pmvMatrix.glScalef(pixelScale, -1f*pixelScale, 1f); + } else if( 1f != pixelScale ) { + pmvMatrix.glScalef(pixelScale, pixelScale, 1f); + } + renderer.updateMatrix(gl); + renderer.drawString3D(gl, font, text, textPosition, fontSize, texSize); + st.useProgram(gl, false); + gl.glDisable(GL2ES2.GL_BLEND); + + if( !exclusivePMVMatrix ) { + pmvMatrix.glPopMatrix(); + } + lastRow = -1; + } + } +}
\ No newline at end of file diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionNewtDemo01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionNewtDemo01.java index 160dc0ffe..160dc0ffe 100755..100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionNewtDemo01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionNewtDemo01.java diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java index a3182a30f..4ebb937a0 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java @@ -194,7 +194,7 @@ public abstract class GPURendererListenerBase01 implements GLEventListener { pw.printf("-%03dx%03d-Z%04d-T%04d-%s", drawable.getWidth(), drawable.getHeight(), (int)Math.abs(zoom), texSize[0], objName); final String filename = dir + tech + sw +".png"; - if(screenshot.readPixels(drawable.getGL(), drawable, false)) { + if(screenshot.readPixels(drawable.getGL(), false)) { screenshot.write(new File(filename)); } } @@ -293,7 +293,6 @@ public abstract class GPURendererListenerBase01 implements GLEventListener { } } } - public void keyTyped(KeyEvent arg0) {} public void keyReleased(KeyEvent arg0) {} } } diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java index 9c18b741a..2ab0632d3 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java @@ -39,10 +39,10 @@ import com.jogamp.graph.curve.opengl.RenderState; import com.jogamp.graph.curve.opengl.TextRenderer; import com.jogamp.graph.font.Font; import com.jogamp.graph.font.FontFactory; -import com.jogamp.graph.geom.AABBox; import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.event.KeyListener; import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.math.geom.AABBox; /** * @@ -269,46 +269,50 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB } public class KeyAction implements KeyListener { - public void keyPressed(KeyEvent arg0) { + public void keyPressed(KeyEvent e) { if(userInput) { return; } - - if(arg0.getKeyCode() == KeyEvent.VK_3) { + final short s = e.getKeySymbol(); + if(s == KeyEvent.VK_3) { fontIncr(10); } - else if(arg0.getKeyCode() == KeyEvent.VK_4) { + else if(s == KeyEvent.VK_4) { fontIncr(-10); } - else if(arg0.getKeyCode() == KeyEvent.VK_H) { + else if(s == KeyEvent.VK_H) { switchHeadBox(); } - else if(arg0.getKeyCode() == KeyEvent.VK_F) { + else if(s == KeyEvent.VK_F) { drawFPS = !drawFPS; } - else if(arg0.getKeyCode() == KeyEvent.VK_SPACE) { + else if(s == KeyEvent.VK_SPACE) { nextFontSet(); } - else if(arg0.getKeyCode() == KeyEvent.VK_I) { + else if(s == KeyEvent.VK_I) { userInput = true; setIgnoreInput(true); } } - public void keyTyped(KeyEvent arg0) { + public void keyReleased(KeyEvent e) { + if( !e.isPrintableKey() || e.isAutoRepeat() ) { + return; + } if(userInput) { - char c = arg0.getKeyChar(); - - if(c == 0x0d) { + final short k = e.getKeySymbol(); + if( KeyEvent.VK_ENTER == k ) { userInput = false; setIgnoreInput(false); - } else if(c == 0x08 && userString.length()>0) { + } else if( KeyEvent.VK_BACK_SPACE == k && userString.length()>0) { userString.deleteCharAt(userString.length()-1); - } else if( font.isPrintableChar( c ) ) { - userString.append(c); + } else { + final char c = e.getKeyChar(); + if( font.isPrintableChar( c ) ) { + userString.append(c); + } } } } - public void keyReleased(KeyEvent arg0) {} } } diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener0A.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener0A.java index b68b24a7a..c9a3f5542 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener0A.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener0A.java @@ -267,9 +267,8 @@ public class GPUUISceneGLListener0A implements GLEventListener { } else { System.err.println("GPUUISceneGLListener0A: dispose (0)"); } - - drawable.removeGLEventListener(sceneUIController); - sceneUIController.dispose(drawable); + + // sceneUIController will remove itself from the drawable! GL2ES2 gl = drawable.getGL().getGL2ES2(); regionRenderer.destroy(gl); @@ -429,7 +428,9 @@ public class GPUUISceneGLListener0A implements GLEventListener { @Override public void mouseWheelMoved(MouseEvent e) { - zoom += 2f*e.getWheelRotation(); + if( !e.isShiftDown() ) { + zoom += 2f*e.getRotation()[1]; // vertical: wheel + } } } }
\ No newline at end of file diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/RIButton.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/RIButton.java index 150082200..3060c5657 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/RIButton.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/RIButton.java @@ -32,9 +32,9 @@ import javax.media.opengl.GL2ES2; import com.jogamp.graph.curve.opengl.RegionRenderer; import com.jogamp.graph.curve.opengl.RenderState; import com.jogamp.graph.font.Font; -import com.jogamp.graph.geom.AABBox; import com.jogamp.graph.geom.Vertex; import com.jogamp.graph.geom.Vertex.Factory; +import com.jogamp.opengl.math.geom.AABBox; import com.jogamp.opengl.test.junit.graph.demos.ui.opengl.UIRegion; /** GPU based resolution independent Button impl diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/SceneUIController.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/SceneUIController.java index c6d43480a..616dd9b98 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/SceneUIController.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/SceneUIController.java @@ -100,6 +100,7 @@ public class SceneUIController implements GLEventListener{ public void dispose(GLAutoDrawable drawable) { System.err.println("SceneUIController: dispose"); cDrawable = null; + drawable.removeGLEventListener(this); } public void reshape(GLAutoDrawable drawable, int x, int y, int width, diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java index d0093ad0c..c94b63494 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java @@ -180,7 +180,7 @@ public abstract class UIListenerBase01 implements GLEventListener { pw.printf("-%03dx%03d-Z%04d-T%04d-%s", drawable.getWidth(), drawable.getHeight(), (int)Math.abs(zoom), 0, objName); final String filename = dir + tech + sw +".png"; - if(screenshot.readPixels(drawable.getGL(), drawable, false)) { + if(screenshot.readPixels(drawable.getGL(), false)) { screenshot.write(new File(filename)); } } @@ -317,7 +317,6 @@ public abstract class UIListenerBase01 implements GLEventListener { } } } - public void keyTyped(KeyEvent arg0) {} public void keyReleased(KeyEvent arg0) {} } } diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIShape.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIShape.java index 2f87fab66..c38f8f75c 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIShape.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIShape.java @@ -32,9 +32,9 @@ import javax.media.opengl.GL2ES2; import com.jogamp.graph.curve.OutlineShape; import com.jogamp.graph.curve.opengl.RegionRenderer; import com.jogamp.graph.curve.opengl.RenderState; -import com.jogamp.graph.geom.AABBox; import com.jogamp.graph.geom.Vertex; import com.jogamp.graph.geom.Vertex.Factory; +import com.jogamp.opengl.math.geom.AABBox; public abstract class UIShape { private final Factory<? extends Vertex> vertexFactory; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00Base.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00Base.java new file mode 100644 index 000000000..43f8b89bd --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00Base.java @@ -0,0 +1,117 @@ +/** + * Copyright 2014 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.jogl.acore; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLProfile; + +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import com.jogamp.graph.curve.Region; +import com.jogamp.opengl.test.junit.graph.TextRendererGLELBase; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Multiple GLJPanels in a JFrame + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public abstract class GLReadBuffer00Base extends UITestCase { + + public static class TextRendererGLEL extends TextRendererGLELBase { + public int frameNo = 0; + public int userCounter = 0; + + public TextRendererGLEL() { + // FIXME: Graph TextRenderer does not AA well w/o MSAA and FBO + super(Region.VBAA_RENDERING_BIT); + texSizeScale = 2; + + fontSize = 24; + + staticRGBAColor[0] = 1.0f; + staticRGBAColor[1] = 1.0f; + staticRGBAColor[2] = 1.0f; + staticRGBAColor[3] = 0.99f; + } + + @Override + public void display(GLAutoDrawable drawable) { + final String text = String.format("Frame %04d (%03d): %04dx%04d", frameNo, userCounter, drawable.getWidth(), drawable.getHeight()); + System.err.println("TextRendererGLEL.display: "+text); + if( null != renderer ) { + renderString(drawable, text, 0 /* col */, 0 /* row */, 0, 0, -1); + } else { + System.err.println(text); + } + frameNo++; + } + } + + @BeforeClass + public static void initClass() throws IOException { + GLProfile.initSingleton(); + } + + protected abstract void test(final GLCapabilitiesImmutable caps, final boolean useSwingDoubleBuffer, final boolean skipGLOrientationVerticalFlip); + + @Test + public void test00_MSAA0_DefFlip() throws InterruptedException, InvocationTargetException { + test(new GLCapabilities(null), false /*useSwingDoubleBuffer*/, false /* skipGLOrientationVerticalFlip */); + } + + @Test + public void test01_MSAA0_UsrFlip() throws InterruptedException, InvocationTargetException { + test(new GLCapabilities(null), false /*useSwingDoubleBuffer*/, true /* skipGLOrientationVerticalFlip */); + } + + @Test + public void test10_MSAA8_DefFlip() throws InterruptedException, InvocationTargetException { + final GLCapabilities caps = new GLCapabilities(null); + caps.setNumSamples(8); + caps.setSampleBuffers(true); + test(caps, false /*useSwingDoubleBuffer*/, false /* skipGLOrientationVerticalFlip */); + } + + @Test + public void test11_MSAA8_UsrFlip() throws InterruptedException, InvocationTargetException { + final GLCapabilities caps = new GLCapabilities(null); + caps.setNumSamples(8); + caps.setSampleBuffers(true); + test(caps, false /*useSwingDoubleBuffer*/, true /* skipGLOrientationVerticalFlip */); + } + + static long duration = 500; // ms +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrentNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/InitConcurrentBaseNEWT.java index 8c0213e8e..f1bc0ab7a 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrentNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/InitConcurrentBaseNEWT.java @@ -28,8 +28,6 @@ package com.jogamp.opengl.test.junit.jogl.acore; -import java.io.IOException; - import javax.media.nativewindow.Capabilities; import javax.media.nativewindow.util.InsetsImmutable; import javax.media.opengl.GLCapabilities; @@ -37,17 +35,25 @@ import javax.media.opengl.GLProfile; import org.junit.Assert; import org.junit.BeforeClass; -import org.junit.Test; -import com.jogamp.common.os.Platform; +import com.jogamp.newt.Display; import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Screen; import com.jogamp.newt.Window; 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.test.junit.util.ValidateLockListener; import com.jogamp.opengl.util.Animator; -public class TestInitConcurrentNEWT extends UITestCase { +/** + * Concurrent and lock-free initialization and rendering using exclusive NEWT Display EDT instances, or + * concurrent locked initialization and lock-free rendering using a shared NEWT Display EDT instances. + * <p> + * Rendering is always lock-free and independent of the EDT. + * </p> + */ +public abstract class InitConcurrentBaseNEWT extends UITestCase { static final int demoSize = 128; @@ -73,31 +79,39 @@ public class TestInitConcurrentNEWT extends UITestCase { } public class JOGLTask implements Runnable { - private int id; - private Object postSync; + private final int id; + private final Object postSync; + private final boolean reuse; private boolean done = false; - public JOGLTask(Object postSync, int id) { + public JOGLTask(Object postSync, int id, boolean reuse) { this.postSync = postSync; this.id = id; + this.reuse = reuse; } public void run() { int x = ( id % num_x ) * ( demoSize + insets.getTotalHeight() ); int y = ( (id / num_x) % num_y ) * ( demoSize + insets.getTotalHeight() ); - System.err.println("JOGLTask "+id+": START: "+x+"/"+y+" - "+Thread.currentThread().getName()); - GLWindow glWindow = GLWindow.create(new GLCapabilities(GLProfile.getDefault())); + System.err.println("JOGLTask "+id+": START: "+x+"/"+y+", reuse "+reuse+" - "+Thread.currentThread().getName()); + final Display display = NewtFactory.createDisplay(null, reuse); + final Screen screen = NewtFactory.createScreen(display, 0); + final GLWindow glWindow = GLWindow.create(screen, new GLCapabilities(GLProfile.getDefault())); Assert.assertNotNull(glWindow); glWindow.setTitle("Task "+id); glWindow.setPosition(x + insets.getLeftWidth(), y + insets.getTopHeight() ); - glWindow.addGLEventListener(new GearsES2(1)); + glWindow.addGLEventListener(new ValidateLockListener()); + glWindow.addGLEventListener(new GearsES2(0)); Animator animator = new Animator(glWindow); glWindow.setSize(demoSize, demoSize); glWindow.setVisible(true); animator.setUpdateFPSFrames(60, null); + + System.err.println("JOGLTask "+id+": INITIALIZED: "+", "+display+" - "+Thread.currentThread().getName()); + animator.start(); Assert.assertEquals(true, animator.isAnimating()); Assert.assertEquals(true, glWindow.isVisible()); @@ -169,67 +183,43 @@ public class TestInitConcurrentNEWT extends UITestCase { return sb.toString(); } - protected void runJOGLTasks(int num) throws InterruptedException { + protected void runJOGLTasks(int num, boolean reuse) throws InterruptedException { + System.err.println("InitConcurrentBaseNEWT "+num+" threads, reuse display: "+reuse); final String currentThreadName = Thread.currentThread().getName(); - final Object sync = new Object(); + final Object syncDone = new Object(); final JOGLTask[] tasks = new JOGLTask[num]; final Thread[] threads = new Thread[num]; int i; for(i=0; i<num; i++) { - tasks[i] = new JOGLTask(sync, i); + tasks[i] = new JOGLTask(syncDone, i, reuse); threads[i] = new Thread(tasks[i], currentThreadName+"-jt"+i); } + final long t0 = System.currentTimeMillis(); + for(i=0; i<num; i++) { threads[i].start(); } - synchronized (sync) { + i=0; + synchronized (syncDone) { while(!done(tasks)) { try { - sync.wait(); + syncDone.wait(500); } catch (InterruptedException e) { throw new RuntimeException(e); } + System.err.println(i+": "+doneDump(tasks)); + i++; } } + final long t1 = System.currentTimeMillis(); + System.err.println("total: "+(t1-t0)/1000.0+"s"); + Assert.assertTrue("Tasks are incomplete. Complete: "+doneDump(tasks), done(tasks)); i=0; while(i<30 && !isDead(threads)) { Thread.sleep(100); i++; } - Assert.assertTrue("Threads are still alive after 3s. Alive: "+isAliveDump(threads), isDead(threads)); - } - - @Test - public void test01OneThread() throws InterruptedException { - runJOGLTasks(1); - } - - @Test - public void test02TwoThreads() throws InterruptedException { - runJOGLTasks(2); - } - - @Test - public void test16SixteenThreads() throws InterruptedException { - if( Platform.getCPUFamily() == Platform.CPUFamily.ARM ) { - runJOGLTasks(8); - } else { - runJOGLTasks(16); - } - } - - public static void main(String args[]) throws IOException { - for(int i=0; i<args.length; i++) { - if(args[i].equals("-time")) { - i++; - try { - duration = Integer.parseInt(args[i]); - } catch (Exception ex) { ex.printStackTrace(); } - } - } - String tstname = TestInitConcurrentNEWT.class.getName(); - org.junit.runner.JUnitCore.main(tstname); - } - + Assert.assertTrue("Threads are still alive after 3s. Alive: "+isAliveDump(threads), isDead(threads)); + } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAWTCloseX11DisplayBug565.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAWTCloseX11DisplayBug565.java index 8df54988f..d8506a0d6 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAWTCloseX11DisplayBug565.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAWTCloseX11DisplayBug565.java @@ -3,6 +3,8 @@ package com.jogamp.opengl.test.junit.jogl.acore; import jogamp.nativewindow.x11.X11Util; import org.junit.Assert; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import javax.media.nativewindow.NativeWindowFactory; import javax.media.opengl.GLCapabilities; @@ -14,6 +16,7 @@ import java.awt.Frame; /** * Tests the closing the device of GLCanvas in JOGL */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestAWTCloseX11DisplayBug565 { @Test @@ -29,19 +32,16 @@ public class TestAWTCloseX11DisplayBug565 { } GLCapabilitiesImmutable caps = new GLCapabilities( GLProfile.getDefault( ) ); - Frame frame = new Frame( "AWT Resource X11 Leak - #" + j ); + final Frame frame = new Frame( "AWT Resource X11 Leak - #" + j ); - GLCanvas glCanvas = new GLCanvas( caps ); + final GLCanvas glCanvas = new GLCanvas( caps ); frame.add( glCanvas ); - frame.setSize( 128, 128 ); - - final Frame _frame = frame; - final GLCanvas _glCanvas = glCanvas; try { javax.swing.SwingUtilities.invokeAndWait( new Runnable() { public void run() { - _frame.setVisible( true ); + frame.setSize( 128, 128 ); + frame.setVisible( true ); } } ); } @@ -53,9 +53,9 @@ public class TestAWTCloseX11DisplayBug565 { try { javax.swing.SwingUtilities.invokeAndWait( new Runnable() { public void run() { - _frame.setVisible( false ); - _frame.remove( _glCanvas ); - _frame.dispose(); + frame.setVisible( false ); + frame.remove( glCanvas ); + frame.dispose(); } } ); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAddRemove01GLCanvasSwingAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAddRemove01GLCanvasSwingAWT.java new file mode 100644 index 000000000..3e54bcd60 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAddRemove01GLCanvasSwingAWT.java @@ -0,0 +1,292 @@ +/** + * Copyright 2013 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.jogl.acore; + +import java.awt.AWTException; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +import jogamp.nativewindow.jawt.JAWTUtil; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +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; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestAddRemove01GLCanvasSwingAWT extends UITestCase { + static long durationPerTest = 100; + static int addRemoveCount = 15; + static int pauseEach = 0; + static int pauseDuration = 500; + static boolean noOnscreenTest = false; + static boolean noOffscreenTest = false; + static boolean offscreenPBufferOnly = false; + static boolean offscreenFBOOnly = false; + static GLProfile glpGL2, glpGL2ES2; + static int width, height; + static boolean waitForKey = false; + static boolean waitForKeyPost = false; + + @BeforeClass + public static void initClass() { + width = 640; + height = 480; + if(GLProfile.isAvailable(GLProfile.GL2ES2)) { + glpGL2ES2 = GLProfile.get(GLProfile.GL2ES2); + Assert.assertNotNull(glpGL2ES2); + } + if(GLProfile.isAvailable(GLProfile.GL2)) { + glpGL2 = GLProfile.get(GLProfile.GL2); + Assert.assertNotNull(glpGL2); + } + } + + @AfterClass + public static void releaseClass() { + } + + protected JPanel create(final JFrame[] top, final int width, final int height, final int num) + throws InterruptedException, InvocationTargetException + { + final JPanel[] jPanel = new JPanel[] { null }; + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + jPanel[0] = new JPanel(); + jPanel[0].setLayout(new BorderLayout()); + + final JFrame jFrame1 = new JFrame("JFrame #"+num); + // jFrame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + jFrame1.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // equivalent to Frame, use windowClosing event! + jFrame1.getContentPane().add(jPanel[0]); + jFrame1.setSize(width, height); + + top[0] = jFrame1; + } } ); + return jPanel[0]; + } + + protected void add(final Container cont, final Component comp) + throws InterruptedException, InvocationTargetException + { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + cont.add(comp, BorderLayout.CENTER); + } } ); + } + + protected void dispose(final GLCanvas glc) + throws InterruptedException, InvocationTargetException + { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + glc.destroy(); + } } ); + } + + protected void setVisible(final JFrame jFrame, final boolean visible) throws InterruptedException, InvocationTargetException { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + if( visible ) { + jFrame.pack(); + jFrame.validate(); + } + jFrame.setVisible(visible); + } } ) ; + } + + protected void dispose(final JFrame jFrame) throws InterruptedException, InvocationTargetException { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + jFrame.dispose(); + } } ) ; + } + + protected void runTestGL(boolean onscreen, GLCapabilities caps, int addRemoveOpCount) + throws AWTException, InterruptedException, InvocationTargetException + { + + if(waitForKey) { + UITestCase.waitForKey("Start"); + } + for(int i=0; i<addRemoveOpCount; i++) { + System.err.println("Loop # "+i+" / "+addRemoveCount); + final GLCanvas glc = new GLCanvas(caps); + Assert.assertNotNull(glc); + if( !onscreen ) { + glc.setShallUseOffscreenLayer(true); + } + Dimension glc_sz = new Dimension(width, height); + glc.setMinimumSize(glc_sz); + glc.setPreferredSize(glc_sz); + glc.setSize(glc_sz); + final GearsES2 gears = new GearsES2(1); + gears.setVerbose(false); + glc.addGLEventListener(gears); + + final JFrame[] top = new JFrame[] { null }; + final Container glcCont = create(top, width, height, i); + add(glcCont, glc); + + setVisible(top[0], true); + + final long t0 = System.currentTimeMillis(); + do { + glc.display(); + Thread.sleep(10); + } while ( ( System.currentTimeMillis() - t0 ) < durationPerTest ) ; + + System.err.println("GLCanvas isOffscreenLayerSurfaceEnabled: "+glc.isOffscreenLayerSurfaceEnabled()+": "+glc.getChosenGLCapabilities()); + + dispose(top[0]); + + if( 0 < pauseEach && 0 == i % pauseEach ) { + System.err.println("******* P A U S E - Start ********"); + // OSXUtil.WaitUntilFinish(); + Thread.sleep(pauseDuration); + System.err.println("******* P A U S E - End ********"); + } + } + if(waitForKeyPost) { + UITestCase.waitForKey("End"); + } + } + + @Test + public void test01Onscreen() + throws AWTException, InterruptedException, InvocationTargetException + { + if( noOnscreenTest || JAWTUtil.isOffscreenLayerRequired() ) { + System.err.println("No onscreen test requested or platform doesn't support onscreen rendering."); + return; + } + GLCapabilities caps = new GLCapabilities(glpGL2ES2); + runTestGL(true, caps, addRemoveCount); + } + + @Test + public void test02OffscreenFBO() + throws AWTException, InterruptedException, InvocationTargetException + { + if( noOffscreenTest || !JAWTUtil.isOffscreenLayerSupported() ) { + System.err.println("No offscreen test requested or platform doesn't support offscreen rendering."); + return; + } + if( offscreenPBufferOnly ) { + System.err.println("Only PBuffer test is requested."); + return; + } + GLCapabilities caps = new GLCapabilities(glpGL2ES2); + if(offscreenPBufferOnly) { + caps.setPBuffer(true); + caps.setOnscreen(true); // simulate normal behavior .. + } + runTestGL(false, caps, addRemoveCount); + } + + @Test + public void test03OffscreenPBuffer() + throws AWTException, InterruptedException, InvocationTargetException + { + if( noOffscreenTest || !JAWTUtil.isOffscreenLayerSupported() ) { + System.err.println("No offscreen test requested or platform doesn't support offscreen rendering."); + return; + } + if( offscreenFBOOnly ) { + System.err.println("Only FBO test is requested."); + return; + } + GLCapabilities caps = new GLCapabilities(glpGL2); + caps.setPBuffer(true); + caps.setOnscreen(true); // simulate normal behavior .. + runTestGL(false, caps, addRemoveCount); + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + try { + durationPerTest = Long.parseLong(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } else if(args[i].equals("-loops")) { + i++; + addRemoveCount = MiscUtils.atoi(args[i], addRemoveCount); + } else if(args[i].equals("-pauseEach")) { + i++; + pauseEach = MiscUtils.atoi(args[i], pauseEach); + } else if(args[i].equals("-pauseDuration")) { + i++; + pauseDuration = MiscUtils.atoi(args[i], pauseDuration); + } else if(args[i].equals("-noOnscreen")) { + noOnscreenTest = true; + } else if(args[i].equals("-noOffscreen")) { + noOffscreenTest = true; + } else if(args[i].equals("-layeredFBO")) { + offscreenFBOOnly = true; + } else if(args[i].equals("-layeredPBuffer")) { + offscreenPBufferOnly = true; + } else if(args[i].equals("-wait")) { + waitForKey = true; + } else if(args[i].equals("-waitPost")) { + waitForKeyPost = true; + } + } + System.err.println("waitForKey "+waitForKey); + System.err.println("waitForKeyPost "+waitForKeyPost); + + System.err.println("addRemoveCount "+addRemoveCount); + System.err.println("pauseEach "+pauseEach); + System.err.println("pauseDuration "+pauseDuration); + + System.err.println("noOnscreenTest "+noOnscreenTest); + System.err.println("noOffscreenTest "+noOffscreenTest); + System.err.println("offscreenPBufferOnly "+offscreenPBufferOnly); + System.err.println("offscreenFBOOnly "+offscreenFBOOnly); + + org.junit.runner.JUnitCore.main(TestAddRemove01GLCanvasSwingAWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAddRemove02GLWindowNewtCanvasAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAddRemove02GLWindowNewtCanvasAWT.java new file mode 100644 index 000000000..be8dd3d46 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAddRemove02GLWindowNewtCanvasAWT.java @@ -0,0 +1,288 @@ +/** + * Copyright 2013 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.jogl.acore; + +import java.awt.AWTException; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +import jogamp.nativewindow.jawt.JAWTUtil; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.awt.NewtCanvasAWT; +import com.jogamp.newt.opengl.GLWindow; +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; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestAddRemove02GLWindowNewtCanvasAWT extends UITestCase { + static long durationPerTest = 50; + static int addRemoveCount = 15; + static int pauseEach = 0; + static int pauseDuration = 500; + static boolean noOnscreenTest = false; + static boolean noOffscreenTest = false; + static boolean offscreenPBufferOnly = false; + static boolean offscreenFBOOnly = false; + static GLProfile glp; + static int width, height; + static boolean waitForKey = false; + static boolean waitForKeyPost = false; + + @BeforeClass + public static void initClass() { + if(GLProfile.isAvailable(GLProfile.GL2ES2)) { + glp = GLProfile.get(GLProfile.GL2ES2); + Assert.assertNotNull(glp); + width = 640; + height = 480; + } else { + setTestSupported(false); + } + } + + @AfterClass + public static void releaseClass() { + } + + protected JPanel create(final JFrame[] top, final int width, final int height, final int num) + throws InterruptedException, InvocationTargetException + { + final JPanel[] jPanel = new JPanel[] { null }; + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + jPanel[0] = new JPanel(); + jPanel[0].setLayout(new BorderLayout()); + + final JFrame jFrame1 = new JFrame("JFrame #"+num); + // jFrame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + jFrame1.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // equivalent to Frame, use windowClosing event! + jFrame1.getContentPane().add(jPanel[0]); + jFrame1.setSize(width, height); + + top[0] = jFrame1; + } } ); + return jPanel[0]; + } + + protected void add(final Container cont, final Component comp) + throws InterruptedException, InvocationTargetException + { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + cont.add(comp, BorderLayout.CENTER); + } } ); + } + + protected void dispose(final GLCanvas glc) + throws InterruptedException, InvocationTargetException + { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + glc.destroy(); + } } ); + } + + protected void setVisible(final JFrame jFrame, final boolean visible) throws InterruptedException, InvocationTargetException { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + if( visible ) { + jFrame.pack(); + jFrame.validate(); + } + jFrame.setVisible(visible); + } } ) ; + } + + protected void dispose(final JFrame jFrame) throws InterruptedException, InvocationTargetException { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + jFrame.dispose(); + } } ) ; + } + + protected void runTestGL(boolean onscreen, GLCapabilities caps, int addRemoveOpCount) + throws AWTException, InterruptedException, InvocationTargetException + { + + for(int i=0; i<addRemoveOpCount; i++) { + System.err.println("Loop # "+i+" / "+addRemoveCount); + final GLWindow glw = GLWindow.create(caps); + Assert.assertNotNull(glw); + final NewtCanvasAWT glc = new NewtCanvasAWT(glw); + Assert.assertNotNull(glc); + if( !onscreen ) { + glc.setShallUseOffscreenLayer(true); + } + Dimension glc_sz = new Dimension(width, height); + glc.setMinimumSize(glc_sz); + glc.setPreferredSize(glc_sz); + glc.setSize(glc_sz); + final GearsES2 gears = new GearsES2(1); + gears.setVerbose(false); + glw.addGLEventListener(gears); + + final JFrame[] top = new JFrame[] { null }; + final Container glcCont = create(top, width, height, i); + add(glcCont, glc); + + setVisible(top[0], true); + + final long t0 = System.currentTimeMillis(); + do { + glw.display(); + Thread.sleep(10); + } while ( ( System.currentTimeMillis() - t0 ) < durationPerTest ) ; + + System.err.println("GLCanvas isOffscreenLayerSurfaceEnabled: "+glc.isOffscreenLayerSurfaceEnabled()+": "+glw.getChosenGLCapabilities()); + + dispose(top[0]); + glw.destroy(); + + if( 0 < pauseEach && 0 == i % pauseEach ) { + System.err.println("******* P A U S E ********"); + Thread.sleep(pauseDuration); + } + } + if(waitForKeyPost) { + UITestCase.waitForKey("End"); + } + } + + @Test + public void test01Onscreen() + throws AWTException, InterruptedException, InvocationTargetException + { + if( noOnscreenTest || JAWTUtil.isOffscreenLayerRequired() ) { + System.err.println("No onscreen test requested or platform doesn't support onscreen rendering."); + return; + } + GLCapabilities caps = new GLCapabilities(glp); + runTestGL(true, caps, addRemoveCount); + } + + @Test + public void test02OffscreenFBO() + throws AWTException, InterruptedException, InvocationTargetException + { + if( noOffscreenTest || !JAWTUtil.isOffscreenLayerSupported() ) { + System.err.println("No offscreen test requested or platform doesn't support offscreen rendering."); + return; + } + if( offscreenPBufferOnly ) { + System.err.println("Only PBuffer test is requested."); + return; + } + GLCapabilities caps = new GLCapabilities(glp); + runTestGL(false, caps, addRemoveCount); + } + + @Test + public void test03OffscreenPBuffer() + throws AWTException, InterruptedException, InvocationTargetException + { + if( noOffscreenTest || !JAWTUtil.isOffscreenLayerSupported() ) { + System.err.println("No offscreen test requested or platform doesn't support offscreen rendering."); + return; + } + if( offscreenFBOOnly ) { + System.err.println("Only FBO test is requested."); + return; + } + GLCapabilities caps = new GLCapabilities(glp); + caps.setPBuffer(true); + caps.setOnscreen(true); // simulate normal behavior .. + runTestGL(false, caps, addRemoveCount); + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + try { + durationPerTest = Long.parseLong(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } else if(args[i].equals("-loops")) { + i++; + addRemoveCount = MiscUtils.atoi(args[i], addRemoveCount); + } else if(args[i].equals("-pauseEach")) { + i++; + pauseEach = MiscUtils.atoi(args[i], pauseEach); + } else if(args[i].equals("-pauseDuration")) { + i++; + pauseDuration = MiscUtils.atoi(args[i], pauseDuration); + } else if(args[i].equals("-noOnscreen")) { + noOnscreenTest = true; + } else if(args[i].equals("-noOffscreen")) { + noOffscreenTest = true; + } else if(args[i].equals("-layeredFBO")) { + offscreenFBOOnly = true; + } else if(args[i].equals("-layeredPBuffer")) { + offscreenPBufferOnly = true; + } else if(args[i].equals("-wait")) { + waitForKey = true; + } else if(args[i].equals("-waitPost")) { + waitForKeyPost = true; + } + } + System.err.println("waitForKey "+waitForKey); + System.err.println("waitForKeyPost "+waitForKeyPost); + + System.err.println("addRemoveCount "+addRemoveCount); + System.err.println("pauseEach "+pauseEach); + System.err.println("pauseDuration "+pauseDuration); + + System.err.println("noOnscreenTest "+noOnscreenTest); + System.err.println("noOffscreenTest "+noOffscreenTest); + System.err.println("offscreenPBufferOnly "+offscreenPBufferOnly); + System.err.println("offscreenFBOOnly "+offscreenFBOOnly); + if(waitForKey) { + UITestCase.waitForKey("Start"); + } + org.junit.runner.JUnitCore.main(TestAddRemove02GLWindowNewtCanvasAWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAddRemove03GLWindowNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAddRemove03GLWindowNEWT.java new file mode 100644 index 000000000..d99475442 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAddRemove03GLWindowNEWT.java @@ -0,0 +1,147 @@ +/** + * Copyright 2013 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.jogl.acore; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +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 org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.opengl.GLWindow; +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; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestAddRemove03GLWindowNEWT extends UITestCase { + static long durationPerTest = 50; + static int addRemoveCount = 15; + static int pauseEach = 0; + static int pauseDuration = 500; + static GLProfile glp; + static int width, height; + static boolean waitForKey = false; + + @BeforeClass + public static void initClass() { + if(GLProfile.isAvailable(GLProfile.GL2ES2)) { + glp = GLProfile.get(GLProfile.GL2ES2); + Assert.assertNotNull(glp); + width = 640; + height = 480; + } else { + setTestSupported(false); + } + } + + @AfterClass + public static void releaseClass() { + } + + protected void runTestGL(GLCapabilities caps, int addRemoveOpCount) + throws InterruptedException, InvocationTargetException + { + + for(int i=0; i<addRemoveOpCount; i++) { + System.err.println("Loop # "+i+" / "+addRemoveCount); + final GLWindow glw = GLWindow.create(caps); + Assert.assertNotNull(glw); + glw.setTitle("GLWindow #"+i); + glw.setSize(width, height); + final GearsES2 gears = new GearsES2(1); + gears.setVerbose(false); + glw.addGLEventListener(gears); + + glw.setVisible(true); + + final long t0 = System.currentTimeMillis(); + do { + glw.display(); + Thread.sleep(10); + } while ( ( System.currentTimeMillis() - t0 ) < durationPerTest ) ; + + System.err.println("GLWindow: "+glw.getChosenGLCapabilities()); + + glw.destroy(); + + if( 0 < pauseEach && 0 == i % pauseEach ) { + System.err.println("******* P A U S E ********"); + Thread.sleep(pauseDuration); + } + } + } + + @Test + public void test01Onscreen() + throws InterruptedException, InvocationTargetException + { + GLCapabilities caps = new GLCapabilities(glp); + runTestGL(caps, addRemoveCount); + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + try { + durationPerTest = Long.parseLong(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } else if(args[i].equals("-loops")) { + i++; + addRemoveCount = MiscUtils.atoi(args[i], addRemoveCount); + } else if(args[i].equals("-pauseEach")) { + i++; + pauseEach = MiscUtils.atoi(args[i], pauseEach); + } else if(args[i].equals("-pauseDuration")) { + i++; + pauseDuration = MiscUtils.atoi(args[i], pauseDuration); + } else if(args[i].equals("-wait")) { + waitForKey = true; + } + } + System.err.println("waitForKey "+waitForKey); + + System.err.println("addRemoveCount "+addRemoveCount); + System.err.println("pauseEach "+pauseEach); + System.err.println("pauseDuration "+pauseDuration); + + if(waitForKey) { + UITestCase.waitForKey("Start"); + } + org.junit.runner.JUnitCore.main(TestAddRemove03GLWindowNEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestBug669RecursiveGLContext01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestBug669RecursiveGLContext01NEWT.java new file mode 100644 index 000000000..d61ac9ab3 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestBug669RecursiveGLContext01NEWT.java @@ -0,0 +1,138 @@ +/** + * Copyright 2013 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.jogl.acore; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import jogamp.opengl.GLContextImpl; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +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; + +/** + * Tests simple recursive GLContext behavior. + * + * <p> + * Issues {@link GLContext#makeCurrent()} and {@link GLContext#release()} + * from within {@link GLEventListener#display(GLAutoDrawable)}. + * </p> + * + * <https://jogamp.org/bugzilla/show_bug.cgi?id=669> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestBug669RecursiveGLContext01NEWT extends UITestCase { + + @Test(timeout=5000) + public void test01_Plain() { + test01Impl(false); + } + + @Test(timeout=5000) + public void test01_Anim() { + test01Impl(true); + } + + private void test01Impl(boolean anim) { + final String profile = GLProfile.GL2ES2; + if(!GLProfile.isAvailable(profile)) { System.err.println(profile+" n/a"); return; } + + final GLProfile pro = GLProfile.get(profile); + final GLCapabilities caps = new GLCapabilities(pro); + final GLWindow window = GLWindow.create(caps); + + final Animator animator = new Animator(); + if(anim) { + animator.add(window); + } + animator.start(); + + window.setSize(640, 480); + window.addGLEventListener(new GLEventListener() { + private void makeCurrentRecursive(GLContextImpl context, int lockCount) { + Assert.assertEquals(true, context.isOwner(Thread.currentThread())); + Assert.assertEquals(lockCount, context.getLockCount()); + Assert.assertEquals(true, context.isCurrent()); + + Assert.assertEquals(GLContext.CONTEXT_CURRENT, context.makeCurrent()); // recursive: lock +1 + + Assert.assertEquals(true, context.isOwner(Thread.currentThread())); + Assert.assertEquals(lockCount+1, context.getLockCount()); + Assert.assertEquals(true, context.isCurrent()); + } + private void releaseRecursive(GLContextImpl context, int lockCount) { + Assert.assertEquals(true, context.isOwner(Thread.currentThread())); + Assert.assertEquals(lockCount, context.getLockCount()); + Assert.assertEquals(true, context.isCurrent()); // still current + + context.release(); // recursive: lock -1 + + Assert.assertEquals(true, context.isOwner(Thread.currentThread())); + Assert.assertEquals(lockCount-1, context.getLockCount()); + Assert.assertEquals(true, context.isCurrent()); // still current + } + + public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { } + + public void init(final GLAutoDrawable drawable) { } + + public void dispose(final GLAutoDrawable drawable) { } + + public void display(final GLAutoDrawable drawable) { + final GLContextImpl context = (GLContextImpl)drawable.getContext(); + makeCurrentRecursive(context, 1); + releaseRecursive(context, 2); + } + }); + window.addGLEventListener(new GearsES2()); + + try { + window.setVisible(true); + window.display(); + } finally { + animator.stop(); + window.destroy(); + } + } + + public static void main(String args[]) { + org.junit.runner.JUnitCore.main(TestBug669RecursiveGLContext01NEWT.class.getName()); + } + +} + diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestBug669RecursiveGLContext02NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestBug669RecursiveGLContext02NEWT.java new file mode 100644 index 000000000..d83101659 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestBug669RecursiveGLContext02NEWT.java @@ -0,0 +1,135 @@ +/** + * Copyright 2013 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.jogl.acore; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; + +/** + * Tests recursive GLContext behavior. + * + * <p> + * Issues {@link GLAutoDrawable#display()} of another {@link GLAutoDrawable} + * from within {@link GLEventListener#display(GLAutoDrawable)}. + * </p> + * + * <https://jogamp.org/bugzilla/show_bug.cgi?id=669> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestBug669RecursiveGLContext02NEWT extends UITestCase { + + @Test(timeout=5000) + public void test01_Plain() { + test01Impl(false); + } + + @Test(timeout=5000) + public void test01_Anim() { + test01Impl(true); + } + + private void test01Impl(boolean anim) { + final String profile = GLProfile.GL2ES2; + if(!GLProfile.isAvailable(profile)) { System.err.println(profile+" n/a"); return; } + + final GLProfile pro = GLProfile.get(profile); + final GLCapabilities caps = new GLCapabilities(pro); + + final GLWindow window2 = GLWindow.create(caps); // display() triggered by window's GLEventListener! + window2.setPosition(0, 0); + window2.setSize(200, 200); + window2.addGLEventListener(new RedSquareES2()); + + final GLWindow window1 = GLWindow.create(caps); + + final Animator animator1 = new Animator(); + final Animator animator2 = new Animator(); + if(anim) { + animator1.add(window1); + animator2.add(window2); + } + animator1.start(); + animator2.start(); + + window1.setPosition(250, 0); + window1.setSize(200, 200); + window1.addGLEventListener(new GLEventListener() { + public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { } + + public void init(final GLAutoDrawable drawable) { } + + public void dispose(final GLAutoDrawable drawable) { } + + public void display(final GLAutoDrawable drawable) { + window2.display(); + } + }); + window1.addGLEventListener(new GearsES2()); + + try { + window2.setVisible(true); + window1.setVisible(true); + window1.display(); + window2.display(); + if(anim) { + try { + Thread.sleep(500); + } catch(InterruptedException ie) {} + } + } finally { + animator1.stop(); + + final int win1Frames = window1.getTotalFPSFrames(); + final int win2Frames = window2.getTotalFPSFrames(); + System.err.println("Window1: frames "+win1Frames); + System.err.println("Window2: frames "+win2Frames); + Assert.assertTrue("Win2 frames not double the amount of Win1 frames", 2*win2Frames >= win1Frames); + window1.destroy(); + window2.destroy(); + } + } + + public static void main(String args[]) { + org.junit.runner.JUnitCore.main(TestBug669RecursiveGLContext02NEWT.class.getName()); + } + +} + diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestBug692GL3VAONEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestBug692GL3VAONEWT.java new file mode 100644 index 000000000..5337b64a0 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestBug692GL3VAONEWT.java @@ -0,0 +1,442 @@ +/**
+ * Copyright 2013 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.jogl.acore;
+
+import java.io.IOException;
+import java.nio.FloatBuffer;
+import java.nio.ShortBuffer;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.media.opengl.GL3;
+import javax.media.opengl.GL3bc;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Assert;
+import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.GLBuffers;
+
+/**
+ * Test Vertex Array Object (VAO) Usage and BufferStateTracker
+ * <p>
+ * All combinations of CPU_SRC, VBO_ONLY and VBO_VAO are tested
+ * and validate the fix for Bug 692, i.e. <https://jogamp.org/bugzilla/show_bug.cgi?id=692>.
+ * </p>
+ * <p>
+ * Test order is important!
+ * </p>
+ * <p>
+ * Note that VAO initialization does unbind the VBO .. since otherwise they are still bound
+ * and the CPU_SRC test will fail!<br/>
+ * The OpenGL spec does not mention that unbinding a VAO will also unbind the bound VBOs
+ * during their setup.<br/>
+ * Local tests here on NV and AMD proprietary driver resulted in <i>no ourput image</i>
+ * when not unbinding said VBOs before the CPU_SRC tests.<br/>
+ * Hence Bug 692 Comment 5 is invalid, i.e. <https://jogamp.org/bugzilla/show_bug.cgi?id=692#c5>,
+ * and we should throw an exception to give users a hint!
+ * </p>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestBug692GL3VAONEWT extends UITestCase {
+ static long duration = 500; // ms
+
+ static class GL3VAODemo implements GLEventListener {
+ /** Different modes of displaying the geometry */
+ public enum Mode {
+ CPU_SRC {
+ @Override
+ void display(GL3VAODemo t, GL3bc gl) {
+ t.displayCPUSourcing(gl);
+ }
+ },
+
+ /** Traditional one without using VAO */
+ VBO_ONLY {
+ @Override
+ void display(GL3VAODemo t, GL3bc gl) {
+ t.displayVBOOnly(gl);
+ }
+ },
+
+ /** Using VAOs throws [incorrectly as of JOGL 2.0rc11] a GLException */
+ VBO_VAO {
+ @Override
+ void display(GL3VAODemo t, GL3bc gl) {
+ t.displayVBOVAO(gl);
+ }
+ };
+
+ abstract void display(GL3VAODemo t, GL3bc gl);
+ }
+
+ private final Mode[] allModes;
+ private Mode currentMode;
+ private int currentModeIdx;
+
+ public GL3VAODemo(Mode[] modes) {
+ allModes = modes;
+ currentMode = allModes[0];
+ currentModeIdx = 0;
+ }
+
+ private final static float[] vertexColorData = new float[]{
+ 0.0f, 0.75f, 0.0f, 1,0,0,
+ -0.5f, -0.75f, 0.0f, 0,1,0,
+ 0.9f, -0.75f, 0.0f, 0,0,1
+ };
+ private final FloatBuffer vertexColorDataBuffer = GLBuffers.newDirectFloatBuffer(vertexColorData);
+
+ private final short[] indices = new short[]{0, 1, 2};
+ private final ShortBuffer indicesBuffer = GLBuffers.newDirectShortBuffer(indices);
+
+
+ private int ibo = -1;
+ private int vbo = -1;
+ private int vertID = -1;
+ private int fragID = -1;
+ private int progID = -1;
+
+ private int vao = -1;
+
+ private static int createShader(final GL3 gl, int type,
+ final String[] srcLines){
+ int shaderID = gl.glCreateShader(type);
+ assert shaderID > 0;
+ int[] lengths = new int[srcLines.length];
+ for (int i = 0; i < srcLines.length; i++) {
+ lengths[i] = srcLines[i].length();
+ }
+ gl.glShaderSource(shaderID, srcLines.length, srcLines, lengths, 0);
+ gl.glCompileShader(shaderID);
+ return shaderID;
+ }
+
+ private void initBuffers(GL3 gl) {
+ // IDs for 2 buffers
+ int[] buffArray = new int[2];
+ gl.glGenBuffers(buffArray.length, buffArray, 0);
+ vbo = buffArray[0];
+ assert vbo > 0;
+
+ // Bind buffer and upload data
+ gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, vbo);
+ gl.glBufferData(GL3.GL_ARRAY_BUFFER, vertexColorData.length * Buffers.SIZEOF_FLOAT,
+ vertexColorDataBuffer, GL3.GL_STATIC_DRAW);
+ gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, 0);
+
+ // Buffer with the 3 indices required for one triangle
+ ibo = buffArray[1];
+ assert ibo > 0;
+ gl.glBindBuffer(GL3.GL_ELEMENT_ARRAY_BUFFER, ibo);
+ gl.glBufferData(GL3.GL_ELEMENT_ARRAY_BUFFER,indices.length*Buffers.SIZEOF_SHORT,
+ indicesBuffer, GL3.GL_STATIC_DRAW);
+ gl.glBindBuffer(GL3.GL_ELEMENT_ARRAY_BUFFER, 0);
+ }
+ private void initShaders(GL3 gl) {
+ final String[] vertSrc = new String[]{
+ "#version 150\n",
+ "in vec4 vPosition;\n",
+ "in vec4 vColor;\n",
+ "out vec4 pColor;\n",
+ "void main() {\n",
+ " pColor = vColor;\n",
+ " gl_Position = vPosition;\n",
+ "}\n"
+ };
+ vertID = createShader(gl, GL3.GL_VERTEX_SHADER, vertSrc);
+
+ final String[] fragSrc = new String[]{
+ "#version 150\n",
+ "in vec4 pColor;\n",
+ "void main() {\n",
+ " gl_FragColor = pColor;\n",
+ "}\n"
+ };
+ fragID = createShader(gl, GL3.GL_FRAGMENT_SHADER, fragSrc);
+
+ // We're done with the compiler
+ gl.glReleaseShaderCompiler();
+
+ progID = gl.glCreateProgram();
+ assert progID > 0;
+ gl.glAttachShader(progID, vertID);
+ gl.glAttachShader(progID, fragID);
+ gl.glLinkProgram(progID);
+ gl.glValidateProgram(progID);
+ }
+
+ private int initVAO(GL3 gl) {
+ int[] buff = new int[1];
+ gl.glGenVertexArrays(1, buff, 0);
+ int vao = buff[0];
+ Assert.assertTrue("Invalid VAO: "+vao, vao > 0);
+
+
+ gl.glUseProgram(progID);
+ final int posLoc = gl.glGetAttribLocation(progID, "vPosition");
+ final int colorLoc = gl.glGetAttribLocation(progID, "vColor");
+ gl.glUseProgram(0);
+
+ gl.glBindVertexArray(vao);
+ gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, vbo);
+ gl.glBindBuffer(GL3.GL_ELEMENT_ARRAY_BUFFER, ibo);
+
+ gl.glEnableVertexAttribArray(posLoc);
+ gl.glEnableVertexAttribArray(colorLoc);
+
+ final int stride = 6 * Buffers.SIZEOF_FLOAT;
+ final int cOff = 3 * Buffers.SIZEOF_FLOAT;
+ gl.glVertexAttribPointer(posLoc, 3, GL3.GL_FLOAT, false, stride, 0L);
+ gl.glVertexAttribPointer(colorLoc,3, GL3.GL_FLOAT, false, stride, cOff);
+
+ gl.glBindVertexArray(0);
+ // See class documentation above!
+ gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, 0);
+ gl.glBindBuffer(GL3.GL_ELEMENT_ARRAY_BUFFER, 0);
+ return vao;
+ }
+
+ @Override
+ public void init(GLAutoDrawable drawable) {
+ final GL3 gl = drawable.getGL().getGL3();
+ gl.glEnable(GL3.GL_DEPTH_TEST);
+ gl.glDisable(GL3.GL_CULL_FACE);
+ initBuffers(gl);
+ initShaders(gl);
+
+ vao = initVAO(gl);
+
+ gl.setSwapInterval(1);
+ }
+
+ @Override
+ public void dispose(GLAutoDrawable drawable) {
+ final GL3 gl = drawable.getGL().getGL3();
+ gl.glDeleteBuffers(2, new int[]{vbo, ibo}, 0);
+ gl.glDetachShader(progID, fragID);
+ gl.glDetachShader(progID, vertID);
+ gl.glDeleteProgram(progID);
+ gl.glDeleteShader(fragID);
+ gl.glDeleteShader(vertID);
+ }
+
+ private void displayCPUSourcing(final GL3bc gl) {
+ final int posLoc = gl.glGetAttribLocation(progID, "vPosition");
+ final int colorLoc = gl.glGetAttribLocation(progID, "vColor");
+ gl.glEnableVertexAttribArray(posLoc);
+ gl.glEnableVertexAttribArray(colorLoc);
+
+ final int stride = 6 * Buffers.SIZEOF_FLOAT;
+ // final int cOff = 3 * Buffers.SIZEOF_FLOAT;
+ gl.glVertexAttribPointer(posLoc, 3, GL3.GL_FLOAT, false, stride, vertexColorDataBuffer);
+ vertexColorDataBuffer.position(3); // move to cOff
+ gl.glVertexAttribPointer(colorLoc,3, GL3.GL_FLOAT, false, stride, vertexColorDataBuffer);
+ vertexColorDataBuffer.position(0); // rewind cOff
+
+ gl.glDrawElements(GL3.GL_TRIANGLES, 3, GL3.GL_UNSIGNED_SHORT, indicesBuffer);
+
+ gl.glDisableVertexAttribArray(posLoc);
+ gl.glDisableVertexAttribArray(colorLoc);
+ }
+
+ private void displayVBOOnly(final GL3 gl) {
+ final int posLoc = gl.glGetAttribLocation(progID, "vPosition");
+ final int colorLoc = gl.glGetAttribLocation(progID, "vColor");
+ gl.glEnableVertexAttribArray(posLoc);
+ gl.glEnableVertexAttribArray(colorLoc);
+
+ gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, vbo);
+ final int stride = 6 * Buffers.SIZEOF_FLOAT;
+ final int cOff = 3 * Buffers.SIZEOF_FLOAT;
+ gl.glVertexAttribPointer(posLoc, 3, GL3.GL_FLOAT, false, stride, 0L);
+ gl.glVertexAttribPointer(colorLoc,3, GL3.GL_FLOAT, false, stride, cOff);
+ gl.glBindBuffer(GL3.GL_ELEMENT_ARRAY_BUFFER, ibo);
+ gl.glDrawElements(GL3.GL_TRIANGLES, 3, GL3.GL_UNSIGNED_SHORT, 0L);
+
+ gl.glDisableVertexAttribArray(posLoc);
+ gl.glDisableVertexAttribArray(colorLoc);
+ gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, 0);
+ gl.glBindBuffer(GL3.GL_ELEMENT_ARRAY_BUFFER, 0);
+ }
+
+ private void displayVBOVAO(final GL3 gl) {
+ try {
+ gl.glBindVertexArray(vao);
+ gl.glDrawElements(GL3.GL_TRIANGLES, 3, GL3.GL_UNSIGNED_SHORT, 0L);
+ gl.glBindVertexArray(0);
+ } catch (GLException ex) {
+ Logger.getLogger(TestBug692GL3VAONEWT.class.getName()).log(Level.SEVERE,null,ex);
+ }
+ }
+
+ @Override
+ public void display(GLAutoDrawable drawable) {
+ final GL3bc gl = drawable.getGL().getGL3bc();
+ float color = ((float) currentMode.ordinal() + 1) / (Mode.values().length + 2);
+ gl.glClearColor(color, color, color, 0);
+ gl.glClear(GL3.GL_COLOR_BUFFER_BIT | GL3.GL_DEPTH_BUFFER_BIT);
+ gl.glUseProgram(progID);
+ final Mode newMode;
+ {
+ currentModeIdx = ( currentModeIdx + 1 ) % allModes.length;
+ newMode = allModes[ currentModeIdx ];
+ }
+ if (newMode != currentMode) {
+ currentMode = newMode;
+ System.out.println("Display mode: " + currentMode);
+ }
+ currentMode.display(this, gl);
+ gl.glUseProgram(0);
+ }
+
+ @Override
+ public void reshape(GLAutoDrawable drawable, int x, int y, int w, int h) {
+ }
+ }
+
+ private void testImpl(GLProfile profile, GL3VAODemo.Mode[] modes) throws InterruptedException {
+ final GLCapabilities capabilities = new GLCapabilities(profile);
+ final GLWindow glWindow = GLWindow.create(capabilities);
+ glWindow.setSize(512, 512);
+
+ Animator anim = new Animator(glWindow);
+
+ QuitAdapter quitAdapter = new QuitAdapter();
+ glWindow.addKeyListener(quitAdapter);
+ glWindow.addWindowListener(quitAdapter);
+
+ final GL3VAODemo vaoTest = new GL3VAODemo(modes);
+ glWindow.addGLEventListener(vaoTest);
+ glWindow.setVisible(true);
+ anim.start();
+
+ final long t0 = System.currentTimeMillis();
+ long t1 = t0;
+ while(!quitAdapter.shouldQuit() && t1-t0<duration) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ anim.stop();
+ glWindow.destroy();
+ }
+
+ @Test
+ public void test01CPUSource() throws GLException, InterruptedException {
+ if( ! GLProfile.isAvailable(GLProfile.GL3bc) ) {
+ System.err.println("GL3bc n/a");
+ return;
+ }
+ GL3VAODemo.Mode[] modes = new GL3VAODemo.Mode[] { GL3VAODemo.Mode.CPU_SRC };
+ testImpl(GLProfile.get(GLProfile.GL3bc), modes);
+ }
+
+ @Test
+ public void test02VBOOnly() throws GLException, InterruptedException {
+ if( ! GLProfile.isAvailable(GLProfile.GL3bc) ) {
+ System.err.println("GL3bc n/a");
+ return;
+ }
+ GL3VAODemo.Mode[] modes = new GL3VAODemo.Mode[] { GL3VAODemo.Mode.VBO_ONLY };
+ testImpl(GLProfile.get(GLProfile.GL3bc), modes);
+ }
+
+ @Test
+ public void test03VBOVAO() throws GLException, InterruptedException {
+ if( ! GLProfile.isAvailable(GLProfile.GL3bc) ) {
+ System.err.println("GL3bc n/a");
+ return;
+ }
+ GL3VAODemo.Mode[] modes = new GL3VAODemo.Mode[] { GL3VAODemo.Mode.VBO_VAO };
+ testImpl(GLProfile.get(GLProfile.GL3bc), modes);
+ }
+
+ @Test
+ public void test12CPUSourceAndVBOOnly() throws GLException, InterruptedException {
+ if( ! GLProfile.isAvailable(GLProfile.GL3bc) ) {
+ System.err.println("GL3bc n/a");
+ return;
+ }
+ GL3VAODemo.Mode[] modes = new GL3VAODemo.Mode[] { GL3VAODemo.Mode.CPU_SRC, GL3VAODemo.Mode.VBO_ONLY };
+ testImpl(GLProfile.get(GLProfile.GL3bc), modes);
+ }
+
+ @Test
+ public void test13CPUSourceAndVBOVAO() throws GLException, InterruptedException {
+ if( ! GLProfile.isAvailable(GLProfile.GL3bc) ) {
+ System.err.println("GL3bc n/a");
+ return;
+ }
+ GL3VAODemo.Mode[] modes = new GL3VAODemo.Mode[] { GL3VAODemo.Mode.CPU_SRC, GL3VAODemo.Mode.VBO_VAO };
+ testImpl(GLProfile.get(GLProfile.GL3bc), modes);
+ }
+
+ @Test
+ public void test23VBOOnlyAndVBOVAO() throws GLException, InterruptedException {
+ if( ! GLProfile.isAvailable(GLProfile.GL3bc) ) {
+ System.err.println("GL3bc n/a");
+ return;
+ }
+ GL3VAODemo.Mode[] modes = new GL3VAODemo.Mode[] { GL3VAODemo.Mode.VBO_ONLY, GL3VAODemo.Mode.VBO_VAO };
+ testImpl(GLProfile.get(GLProfile.GL3bc), modes);
+ }
+
+ @Test
+ public void test88AllModes() throws GLException, InterruptedException {
+ if( ! GLProfile.isAvailable(GLProfile.GL3bc) ) {
+ System.err.println("GL3bc n/a");
+ return;
+ }
+ GL3VAODemo.Mode[] modes = new GL3VAODemo.Mode[] { GL3VAODemo.Mode.CPU_SRC, GL3VAODemo.Mode.VBO_ONLY, GL3VAODemo.Mode.VBO_VAO };
+ testImpl(GLProfile.get(GLProfile.GL3bc), modes);
+ }
+
+ public static void main(String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ duration = MiscUtils.atoi(args[++i], (int)duration);
+ }
+ }
+ String tstname = TestBug692GL3VAONEWT.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestCPUSourcingAPINEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestCPUSourcingAPINEWT.java new file mode 100644 index 000000000..388c57904 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestCPUSourcingAPINEWT.java @@ -0,0 +1,225 @@ +/** + * Copyright 2013 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.jogl.acore; + +import java.nio.FloatBuffer; +import java.nio.ShortBuffer; + +import com.jogamp.common.nio.Buffers; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.GLBuffers; + +import javax.media.opengl.GL2; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLException; +import javax.media.opengl.GLOffscreenAutoDrawable; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestCPUSourcingAPINEWT extends UITestCase { + static long duration = 500; // ms + + static class Demo implements GLEventListener { + private final static float[] vertexColorData = new float[]{ + 0.0f, 0.75f, 0.0f, 1,0,0, + -0.5f, -0.75f, 0.0f, 0,1,0, + 0.9f, -0.75f, 0.0f, 0,0,1 + }; + private final FloatBuffer vertexColorDataBuffer = GLBuffers.newDirectFloatBuffer(vertexColorData); + + private final short[] indices = new short[]{0, 1, 2}; + private final ShortBuffer indicesBuffer = GLBuffers.newDirectShortBuffer(indices); + + + private int vertID = -1; + private int fragID = -1; + private int progID = -1; + + private static int createShader(final GL2ES2 gl, int type, + final String[] srcLines){ + int shaderID = gl.glCreateShader(type); + assert shaderID > 0; + int[] lengths = new int[srcLines.length]; + for (int i = 0; i < srcLines.length; i++) { + lengths[i] = srcLines[i].length(); + } + gl.glShaderSource(shaderID, srcLines.length, srcLines, lengths, 0); + gl.glCompileShader(shaderID); + return shaderID; + } + + private void initShaders(GL2ES2 gl) { + final String[] vertSrc = new String[]{ + "#version 150\n", + "in vec4 vPosition;\n", + "in vec4 vColor;\n", + "out vec4 pColor;\n", + "void main() {\n", + " pColor = vColor;\n", + " gl_Position = vPosition;\n", + "}\n" + }; + vertID = createShader(gl, GL2ES2.GL_VERTEX_SHADER, vertSrc); + + final String[] fragSrc = new String[]{ + "#version 150\n", + "in vec4 pColor;\n", + "void main() {\n", + " gl_FragColor = pColor;\n", + "}\n" + }; + fragID = createShader(gl, GL2ES2.GL_FRAGMENT_SHADER, fragSrc); + + // We're done with the compiler + gl.glReleaseShaderCompiler(); + + progID = gl.glCreateProgram(); + assert progID > 0; + gl.glAttachShader(progID, vertID); + gl.glAttachShader(progID, fragID); + gl.glLinkProgram(progID); + gl.glValidateProgram(progID); + } + + @Override + public void init(GLAutoDrawable drawable) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + gl.glEnable(GL2ES2.GL_DEPTH_TEST); + gl.glDisable(GL2ES2.GL_CULL_FACE); + initShaders(gl); + + gl.setSwapInterval(1); + } + + @Override + public void dispose(GLAutoDrawable drawable) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + gl.glDetachShader(progID, fragID); + gl.glDetachShader(progID, vertID); + gl.glDeleteProgram(progID); + gl.glDeleteShader(fragID); + gl.glDeleteShader(vertID); + } + + private void displayCPUSourcing(final GL2 gl) { + final int posLoc = gl.glGetAttribLocation(progID, "vPosition"); + final int colorLoc = gl.glGetAttribLocation(progID, "vColor"); + gl.glEnableVertexAttribArray(posLoc); + gl.glEnableVertexAttribArray(colorLoc); + + final int stride = 6 * Buffers.SIZEOF_FLOAT; + // final int cOff = 3 * Buffers.SIZEOF_FLOAT; + gl.glVertexAttribPointer(posLoc, 3, GL2ES2.GL_FLOAT, false, stride, vertexColorDataBuffer); + vertexColorDataBuffer.position(3); // move to cOff + gl.glVertexAttribPointer(colorLoc,3, GL2ES2.GL_FLOAT, false, stride, vertexColorDataBuffer); + vertexColorDataBuffer.position(0); // rewind cOff + + gl.glDrawElements(GL2ES2.GL_TRIANGLES, 3, GL2ES2.GL_UNSIGNED_SHORT, indicesBuffer); + + gl.glDisableVertexAttribArray(posLoc); + gl.glDisableVertexAttribArray(colorLoc); + } + + @Override + public void display(GLAutoDrawable drawable) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + gl.glClearColor(0x44, 0x44, 0x44, 0); + gl.glClear(GL2ES2.GL_COLOR_BUFFER_BIT | GL2ES2.GL_DEPTH_BUFFER_BIT); + gl.glUseProgram(progID); + + // Hard casting is of course invalid! + // But we need to 'fake' compatibility mode to trigger CPU-sourcing w/ GL3 core + displayCPUSourcing((GL2) gl); + + gl.glUseProgram(0); + } + + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int w, int h) { + } + } + + private void testImpl(GLProfile profile) throws InterruptedException { + final GLCapabilities capabilities = new GLCapabilities(profile); + GLDrawableFactory factory = GLDrawableFactory.getFactory(profile); + GLOffscreenAutoDrawable glad = factory.createOffscreenAutoDrawable(null, capabilities, null, 512, 512); + + final Demo vaoTest = new Demo(); + glad.addGLEventListener(vaoTest); + glad.display(); + + glad.destroy(); + } + + @Test + public void test01GL2CPUSource() throws GLException, InterruptedException { + if( ! GLProfile.isAvailable(GLProfile.GL2) ) { + System.err.println("GL2 n/a"); + return; + } + testImpl(GLProfile.get(GLProfile.GL2)); + } + + @Test + public void test02GL3CPUSource() throws GLException, InterruptedException { + final GLProfile glp = GLProfile.getMaxProgrammableCore(true); + if( !glp.isGL3ES3() && !glp.isGL2ES2() ) { + System.err.println("No GL core profile available, got "+glp); + return; + } + GLException exp = null; + try { + testImpl(glp); + } catch(GLException gle) { + exp = gle; + System.err.println("Expected Exception: "+exp.getMessage()); + } + Assert.assertNotNull("Excpected GLException missing due to CPU Sourcing w/ GL3 core context", exp); + } + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } + } + org.junit.runner.JUnitCore.main(TestCPUSourcingAPINEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableDeadlockAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableDeadlockAWT.java new file mode 100644 index 000000000..1548c08b5 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableDeadlockAWT.java @@ -0,0 +1,127 @@ +/** + * Copyright 2011 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.jogl.acore; + +import java.awt.EventQueue; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.DefaultGLCapabilitiesChooser; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLOffscreenAutoDrawable; +import javax.media.opengl.GLProfile; + +import jogamp.nativewindow.jawt.JAWTUtil; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.common.util.RunnableTask; +import com.jogamp.opengl.test.junit.util.UITestCase; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestFBOAutoDrawableDeadlockAWT extends UITestCase { + static GLProfile glp; + static int width, height; + + @BeforeClass + public static void initClass() { + glp = GLProfile.getGL2ES2(); + Assert.assertNotNull( glp ); + width = 512; + height = 512; + } + + protected void runTestGL( GLCapabilities caps ) throws InterruptedException, InvocationTargetException { + final GLOffscreenAutoDrawable fbod = GLDrawableFactory.getFactory(caps.getGLProfile()).createOffscreenAutoDrawable( + null, caps, new DefaultGLCapabilitiesChooser(), 512, 512); + + final boolean[] done = {false}; + final Runnable pbufferCreationAction = new Runnable() { + public void run() { + System.err.println("AA.1"); + fbod.display(); + done[ 0 ] = true; + System.err.println("AA.X"); + } + }; + + EventQueue.invokeAndWait(new Runnable() { + public void run() { + Assert.assertTrue(EventQueue.isDispatchThread()); + JAWTUtil.lockToolkit(); + try { + final RunnableTask rTask = new RunnableTask(pbufferCreationAction, new Object(), false, null); + System.err.println("BB.0: "+rTask.getSyncObject()); + synchronized (rTask.getSyncObject()) { + System.err.println("BB.1: "+rTask.getSyncObject()); + new Thread(rTask, Thread.currentThread().getName()+"-Pbuffer_Creation").start(); + try { + System.err.println("BB.2"); + rTask.getSyncObject().wait(); + System.err.println("BB.3"); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + System.err.println("BB.X"); + } + } finally { + JAWTUtil.unlockToolkit(); + } + } + }); + Assert.assertTrue(done[0]); + fbod.destroy(); + } + + @Test(timeout = 2000) // 2s timeout + public void testDeadlock() throws InterruptedException, InvocationTargetException { + GLCapabilities caps = new GLCapabilities( glp ); + runTestGL( caps ); + } + + static long duration = 500; // ms + + public static void main( String args[] ) { + for ( int i = 0; i < args.length; i++ ) { + if ( args[ i ].equals( "-time" ) ) { + i++; + try { + duration = Integer.parseInt( args[ i ] ); + } + catch ( Exception ex ) { + ex.printStackTrace(); + } + } + } + org.junit.runner.JUnitCore.main( TestFBOAutoDrawableDeadlockAWT.class.getName() ); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableFactoryNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableFactoryNEWT.java new file mode 100644 index 000000000..cc06136d6 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableFactoryNEWT.java @@ -0,0 +1,378 @@ +/** + * Copyright 2012 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.jogl.acore; + +import java.io.IOException; + +import javax.media.opengl.GL; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLOffscreenAutoDrawable; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.opengl.FBObject; +import com.jogamp.opengl.test.junit.jogl.demos.es2.FBOMix2DemosES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.MultisampleDemoES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Toolkit agnostic {@link GLOffscreenAutoDrawable.FBO} tests using the + * {@link GLDrawableFactory#createOffscreenAutoDrawable(javax.media.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, int, int, GLContext) factory model}. + * <p> + * The created {@link GLOffscreenAutoDrawable.FBO} is being used to run the {@link GLEventListener}. + * </p> + * <p> + * Extensive FBO reconfiguration (size and sample buffer count) and validation are performed. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestFBOAutoDrawableFactoryNEWT extends UITestCase { + + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + interface MyGLEventListener extends GLEventListener { + void setMakeSnapshot(); + } + + @Test + public void testGL2ES2_Demo1_SingleBuffer_Normal() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setDoubleBuffered(false); + testGLFBODrawableImpl(caps, new GearsES2(0)); + } + + @Test + public void testGL2ES2_Demo1_DoubleBuffer_Normal() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setDoubleBuffered(true); // default + testGLFBODrawableImpl(caps, new GearsES2(0)); + } + + @Test + public void testGL2ES2_Demo2MSAA4() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + testGLFBODrawableImpl(caps, new MultisampleDemoES2(true)); + } + + @Test + public void testGL2ES2_FBODemoMSAA4() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final FBOMix2DemosES2 demo = new FBOMix2DemosES2(0); + demo.setDoRotation(false); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + testGLFBODrawableImpl(caps, demo); + } + + @Test + public void testEGLES2_Demo0Normal() throws InterruptedException { + if( GLProfile.isAvailable(GLProfile.GLES2) ) { + final GLProfile glp = GLProfile.get(GLProfile.GLES2); + final GLCapabilities caps = new GLCapabilities(glp); + testGLFBODrawableImpl(caps, new GearsES2(0)); + } else { + System.err.println("EGL ES2 n/a"); + } + } + + @Test + public void testEGLES2_Demo0MSAA4() throws InterruptedException { + if( GLProfile.isAvailable(GLProfile.GLES2) ) { + final GLProfile glp = GLProfile.get(GLProfile.GLES2); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + testGLFBODrawableImpl(caps, new GearsES2(0)); + } else { + System.err.println("EGL ES2 n/a"); + } + } + + void testGLFBODrawableImpl(GLCapabilities caps, GLEventListener demo) throws InterruptedException { + caps.setFBO(true); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); + final GLOffscreenAutoDrawable.FBO glad = (GLOffscreenAutoDrawable.FBO) + factory.createOffscreenAutoDrawable(null, caps, null, widthStep*szStep, heightStep*szStep); + Assert.assertNotNull(glad); + + System.out.println("Realized GLAD: "+glad); + System.out.println("Realized GLAD: "+glad.getChosenGLCapabilities()); + Assert.assertTrue("FBO drawable is initialized before ctx creation", !glad.isInitialized()); + + glad.display(); // initial display incl. init! + { + final GLContext context = glad.getContext(); + Assert.assertNotNull(context); + Assert.assertTrue(context.isCreated()); + } + Assert.assertTrue("FBO drawable is not initialized after ctx creation", glad.isInitialized()); + + // + // FBO incl. MSAA is fully initialized now + // + + final GLCapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities(); + System.out.println("Init GLAD: "+glad); + System.out.println("Init GLAD: "+chosenCaps); + + final FBObject fboFront = glad.getFBObject(GL.GL_FRONT); + final FBObject fboBack = glad.getFBObject(GL.GL_BACK); + + System.out.println("Init front FBO: "+fboFront); + System.out.println("Init back FBO: "+fboBack); + + Assert.assertTrue("FBO drawable is not initialized before ctx creation", glad.isInitialized()); + Assert.assertTrue("FBO Front is not initialized before ctx creation", fboFront.isInitialized()); + Assert.assertTrue("FBO Back is not initialized before ctx creation", fboBack.isInitialized()); + + if( chosenCaps.getDoubleBuffered() ) { + Assert.assertTrue("FBO are equal: "+fboFront+" == "+fboBack, !fboFront.equals(fboBack)); + Assert.assertNotSame(fboFront, fboBack); + } else { + Assert.assertTrue("FBO are not equal: "+fboFront+" != "+fboBack, fboFront.equals(fboBack)); + Assert.assertSame(fboFront, fboBack); + } + + final FBObject.TextureAttachment texAttachA, texAttachB; + + texAttachA = glad.getTextureBuffer(GL.GL_FRONT); + if(0==glad.getNumSamples()) { + texAttachB = glad.getTextureBuffer(GL.GL_BACK); + } else { + texAttachB = null; + } + + final FBObject.Colorbuffer colorA, colorB; + final FBObject.RenderAttachment depthA, depthB; + + colorA = fboFront.getColorbuffer(0); + Assert.assertNotNull(colorA); + colorB = fboBack.getColorbuffer(0); + Assert.assertNotNull(colorB); + + depthA = fboFront.getDepthAttachment(); + Assert.assertNotNull(depthA); + depthB = fboBack.getDepthAttachment(); + Assert.assertNotNull(depthB); + + glad.display(); // SWAP_ODD + + if( chosenCaps.getDoubleBuffered() ) { + // double buffer or MSAA + Assert.assertTrue("Color attachments are equal: "+colorB+" == "+colorA, !colorB.equals(colorA)); + Assert.assertNotSame(colorB, colorA); + Assert.assertTrue("Depth attachments are equal: "+depthB+" == "+depthA, !depthB.equals(depthA)); + Assert.assertNotSame(depthB, depthA); + } else { + // single buffer + Assert.assertEquals(colorA, colorB); + Assert.assertSame(colorA, colorB); + Assert.assertEquals(depthA, depthB); + Assert.assertSame(depthA, depthB); + } + + Assert.assertEquals(texAttachA, colorA); + Assert.assertSame(texAttachA, colorA); + if(0==glad.getNumSamples()) { + Assert.assertEquals(texAttachB, colorB); + Assert.assertSame(texAttachB, colorB); + } + + if( chosenCaps.getNumSamples() > 0 ) { + // MSAA + FBObject _fboFront = glad.getFBObject(GL.GL_FRONT); + FBObject _fboBack = glad.getFBObject(GL.GL_BACK); + Assert.assertTrue("FBO are not equal: "+fboFront+" != "+_fboFront, fboFront.equals(_fboFront)); + Assert.assertSame(fboFront, _fboFront); + Assert.assertTrue("FBO are not equal: "+fboBack+" != "+_fboBack, fboBack.equals(_fboBack)); + Assert.assertSame(fboBack, _fboBack); + } else if( chosenCaps.getDoubleBuffered() ) { + // real double buffer + FBObject _fboFront = glad.getFBObject(GL.GL_FRONT); + FBObject _fboBack = glad.getFBObject(GL.GL_BACK); + Assert.assertTrue("FBO are not equal: "+fboBack+" != "+_fboFront, fboBack.equals(_fboFront)); + Assert.assertSame(fboBack, _fboFront); + Assert.assertTrue("FBO are not equal: "+fboFront+" != "+_fboBack, fboFront.equals(_fboBack)); + Assert.assertSame(fboFront, _fboBack); + } else { + // single buffer + FBObject _fboFront = glad.getFBObject(GL.GL_FRONT); + FBObject _fboBack = glad.getFBObject(GL.GL_BACK); + Assert.assertTrue("FBO are not equal: "+fboFront+" != "+_fboFront, fboFront.equals(_fboFront)); + Assert.assertSame(fboFront, _fboFront); + Assert.assertTrue("FBO are not equal: "+fboBack+" != "+_fboFront, fboBack.equals(_fboFront)); + Assert.assertSame(fboBack, _fboFront); + Assert.assertTrue("FBO are not equal: "+fboBack+" != "+_fboBack, fboBack.equals(_fboBack)); + Assert.assertSame(fboBack, _fboBack); + Assert.assertTrue("FBO are not equal: "+fboFront+" != "+_fboBack, fboFront.equals(_fboBack)); + Assert.assertSame(fboFront, _fboBack); + } + + glad.addGLEventListener(demo); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + glad.addGLEventListener(snapshotGLEventListener); + + glad.display(); // - SWAP_EVEN + + // 1 - szStep = 2 + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); // - SWAP_ODD + + // 2, 3 (resize + display) + szStep = 1; + glad.setSize(widthStep*szStep, heightStep*szStep); // SWAP_EVEN + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); // - SWAP_ODD + glad.display(); // - SWAP_EVEN + { + // Check whether the attachment reference are still valid! + final FBObject _fboFront = glad.getFBObject(GL.GL_FRONT); + final FBObject _fboBack = glad.getFBObject(GL.GL_BACK); + System.out.println("Resize1.oldFront: "+fboFront); + System.out.println("Resize1.nowFront: "+_fboFront); + System.out.println("Resize1.oldBack : "+fboBack); + System.out.println("Resize1.nowBack : "+_fboBack); + Assert.assertEquals(fboFront, _fboFront); + Assert.assertSame(fboFront, _fboFront); + Assert.assertEquals(fboBack, _fboBack); + Assert.assertSame(fboBack, _fboBack); + + FBObject.Colorbuffer _color = _fboFront.getColorbuffer(0); + Assert.assertNotNull(_color); + Assert.assertEquals(colorA, _color); + Assert.assertSame(colorA, _color); + + FBObject.RenderAttachment _depth = _fboFront.getDepthAttachment(); + System.err.println("Resize1.oldDepth "+depthA); + System.err.println("Resize1.newDepth "+_depth); + Assert.assertNotNull(_depth); + + Assert.assertEquals(depthA, _depth); + Assert.assertSame(depthA, _depth); + _depth = _fboBack.getDepthAttachment(); + Assert.assertNotNull(_depth); + Assert.assertEquals(depthB, _depth); + Assert.assertSame(depthB, _depth); + + _color = _fboFront.getColorbuffer(colorA); + Assert.assertNotNull(_color); + Assert.assertEquals(colorA, _color); + Assert.assertSame(colorA, _color); + } + + // 4, 5 (resize + display) + szStep = 4; + glad.setSize(widthStep*szStep, heightStep*szStep); // SWAP_ODD + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); // - SWAP_EVEN + glad.display(); // - SWAP_ODD + { + // Check whether the attachment reference are still valid! + final FBObject _fboFront = glad.getFBObject(GL.GL_FRONT); + final FBObject _fboBack = glad.getFBObject(GL.GL_BACK); + System.out.println("Resize2.oldFront: "+fboFront); + System.out.println("Resize2.nowFront: "+_fboFront); + System.out.println("Resize2.oldBack : "+fboBack); + System.out.println("Resize2.nowBack : "+_fboBack); + if(chosenCaps.getDoubleBuffered() && 0==chosenCaps.getNumSamples()) { + // real double buffer + Assert.assertEquals(fboBack, _fboFront); + Assert.assertEquals(fboFront, _fboBack); + } else { + // single or MSAA + Assert.assertEquals(fboFront, _fboFront); + Assert.assertEquals(fboBack, _fboBack); + } + + FBObject.Colorbuffer _color = fboBack.getColorbuffer(0); + Assert.assertNotNull(_color); + Assert.assertEquals(colorB, _color); + Assert.assertSame(colorB, _color); + + FBObject.RenderAttachment _depth = fboBack.getDepthAttachment(); + Assert.assertNotNull(_depth); // MSAA back w/ depth + Assert.assertEquals(depthB, _depth); + Assert.assertSame(depthB, _depth); + + _depth = fboFront.getDepthAttachment(); + Assert.assertNotNull(_depth); + Assert.assertEquals(depthA, _depth); + Assert.assertSame(depthA, _depth); + + _color = fboBack.getColorbuffer(colorB); + Assert.assertNotNull(_color); + Assert.assertEquals(colorB, _color); + Assert.assertSame(colorB, _color); + } + + // 6 + 7 (samples + display) + glad.setNumSamples(glad.getGL(), chosenCaps.getNumSamples() > 0 ? 0 : 4); // triggers repaint + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); // actual screenshot + + // 8, 9 (resize + samples + display) + szStep = 3; + glad.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + glad.destroy(); + System.out.println("Fin: "+glad); + } + + public static void main(String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestFBOAutoDrawableFactoryNEWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestFBOMRTNEWT01.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java index 1b33866d7..7ec8715a4 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestFBOMRTNEWT01.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java @@ -25,14 +25,18 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of JogAmp Community. */ -package com.jogamp.opengl.test.junit.jogl.glsl; +package com.jogamp.opengl.test.junit.jogl.acore; -import com.jogamp.opengl.util.FBObject; +import com.jogamp.opengl.FBObject; +import com.jogamp.opengl.FBObject.TextureAttachment; import com.jogamp.opengl.util.GLArrayDataServer; +import com.jogamp.opengl.util.GLReadBufferUtil; import com.jogamp.opengl.util.PMVMatrix; import com.jogamp.opengl.util.glsl.ShaderCode; import com.jogamp.opengl.util.glsl.ShaderProgram; import com.jogamp.opengl.util.glsl.ShaderState; +import com.jogamp.opengl.util.texture.TextureIO; +import com.jogamp.opengl.FBObject.Attachment.Type; import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; import com.jogamp.opengl.test.junit.util.MiscUtils; import com.jogamp.opengl.test.junit.util.NEWTGLContext; @@ -40,33 +44,39 @@ import com.jogamp.opengl.test.junit.util.UITestCase; import java.io.IOException; +import javax.media.nativewindow.NativeSurface; import javax.media.opengl.GL; import javax.media.opengl.GL2ES2; import javax.media.opengl.GL2GL3; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLDrawable; -import javax.media.opengl.GLPipelineFactory; import javax.media.opengl.GLProfile; import javax.media.opengl.GLUniformData; import org.junit.Assert; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestFBOMRTNEWT01 extends UITestCase { - static long durationPerTest = 10; // ms + static long durationPerTest = 10*40*2; // ms @Test public void test01() throws InterruptedException { + final int step = 4; + final int width = 800; + final int height = 600; // preset .. if(!GLProfile.isAvailable(GLProfile.GL2GL3)) { System.err.println("Test requires GL2/GL3 profile."); return; } final NEWTGLContext.WindowContext winctx = NEWTGLContext.createOnscreenWindow( - new GLCapabilities(GLProfile.getGL2GL3()), 640, 480, true); + new GLCapabilities(GLProfile.getGL2GL3()), width/step, height/step, true); final GLDrawable drawable = winctx.context.getGLDrawable(); GL2GL3 gl = winctx.context.getGL().getGL2GL3(); - gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", null, gl, null) ).getGL2GL3(); + // gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", null, gl, null) ).getGL2GL3(); System.err.println(winctx.context); Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); @@ -75,26 +85,30 @@ public class TestFBOMRTNEWT01 extends UITestCase { // st.setVerbose(true); final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, RedSquareES2.class, "shader", - "shader/bin", "fbo-mrt-1", false); + "shader/bin", "fbo-mrt-1", true); final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, "shader", - "shader/bin", "fbo-mrt-1", false); + "shader/bin", "fbo-mrt-1", true); + vp0.defaultShaderCustomization(gl, true, true); + fp0.defaultShaderCustomization(gl, true, true); final ShaderProgram sp0 = new ShaderProgram(); sp0.add(gl, vp0, System.err); - sp0.add(gl, fp0, System.err); - Assert.assertTrue(0<=sp0.program()); + sp0.add(gl, fp0, System.err); + Assert.assertTrue(0 != sp0.program()); Assert.assertTrue(!sp0.inUse()); Assert.assertTrue(!sp0.linked()); Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); st.attachShaderProgram(gl, sp0, false); final ShaderCode vp1 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, RedSquareES2.class, "shader", - "shader/bin", "fbo-mrt-2", false); + "shader/bin", "fbo-mrt-2", true); final ShaderCode fp1 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, "shader", - "shader/bin", "fbo-mrt-2", false); + "shader/bin", "fbo-mrt-2", true); + vp1.defaultShaderCustomization(gl, true, true); + fp1.defaultShaderCustomization(gl, true, true); final ShaderProgram sp1 = new ShaderProgram(); sp1.add(gl, vp1, System.err); sp1.add(gl, fp1, System.err); - Assert.assertTrue(0<=sp1.program()); + Assert.assertTrue(0 != sp1.program()); Assert.assertTrue(!sp1.inUse()); Assert.assertTrue(!sp1.linked()); Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); @@ -147,12 +161,21 @@ public class TestFBOMRTNEWT01 extends UITestCase { texCoords0.enableBuffer(gl, false); Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + final int texA0Point = 0; // attachment point for texA0 + final int texA1Point = 1; // attachment point for texA1 + // FBO w/ 2 texture2D color buffers - final FBObject fbo_mrt = new FBObject(drawable.getWidth(), drawable.getHeight()); - fbo_mrt.init(gl); - Assert.assertTrue( 0 == fbo_mrt.attachTexture2D(gl, texUnit0.intValue(), GL.GL_NEAREST, GL.GL_NEAREST, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE) ); - Assert.assertTrue( 1 == fbo_mrt.attachTexture2D(gl, texUnit1.intValue(), GL.GL_NEAREST, GL.GL_NEAREST, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE) ); - Assert.assertTrue( fbo_mrt.attachDepthBuffer(gl, GL.GL_DEPTH_COMPONENT16) ); + final FBObject fbo_mrt = new FBObject(); + fbo_mrt.reset(gl, drawable.getWidth(), drawable.getHeight()); + final TextureAttachment texA0 = fbo_mrt.attachTexture2D(gl, texA0Point, true, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE); + final TextureAttachment texA1; + if(fbo_mrt.getMaxColorAttachments() > 1) { + texA1 = fbo_mrt.attachTexture2D(gl, texA1Point, true, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE); + } else { + texA1 = null; + System.err.println("FBO supports only one attachment, no MRT available!"); + } + fbo_mrt.attachRenderbuffer(gl, Type.DEPTH, 24); Assert.assertTrue( fbo_mrt.isStatusValid() ) ; fbo_mrt.unbind(gl); @@ -170,9 +193,13 @@ public class TestFBOMRTNEWT01 extends UITestCase { st.uniform(gl, pmvMatrixUniform); Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); - final int[] two_buffers = new int[] { GL.GL_COLOR_ATTACHMENT0, GL.GL_COLOR_ATTACHMENT0+1 }; + final int[] two_buffers = new int[] { GL.GL_COLOR_ATTACHMENT0+texA0Point, GL.GL_COLOR_ATTACHMENT0+texA1Point }; final int[] bck_buffers = new int[] { GL2GL3.GL_BACK_LEFT }; + final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); + int step_i = 0; + int[] last_snap_size = new int[] { 0, 0 }; + for(int i=0; i<durationPerTest; i+=50) { // pass 1 - MRT: Red -> buffer0, Green -> buffer1 st.attachShaderProgram(gl, sp0, true); @@ -198,8 +225,13 @@ public class TestFBOMRTNEWT01 extends UITestCase { gl.glDrawBuffers(1, bck_buffers, 0); gl.glViewport(0, 0, drawable.getWidth(), drawable.getHeight()); - fbo_mrt.use(gl, 0); - fbo_mrt.use(gl, 1); + + gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit0.intValue()); + fbo_mrt.use(gl, texA0); + if(null != texA1) { + gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit1.intValue()); + fbo_mrt.use(gl, texA1); + } gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4); fbo_mrt.unuse(gl); @@ -207,8 +239,27 @@ public class TestFBOMRTNEWT01 extends UITestCase { colors0.enableBuffer(gl, false); texCoords0.enableBuffer(gl, false); + { + final NativeSurface ns = gl.getContext().getGLReadDrawable().getNativeSurface(); + if(last_snap_size[0] != ns.getWidth() && last_snap_size[1] != ns.getHeight()) { + gl.glFinish(); // sync .. no swap buffers yet! + snapshot(step_i, null, gl, screenshot, TextureIO.PNG, null); // overwrite ok + last_snap_size[0] = ns.getWidth(); + last_snap_size[1] = ns.getHeight(); + } + } + drawable.swapBuffers(); Thread.sleep(50); + int j = (int) ( (long)i / (durationPerTest/(long)step) ) + 1; + if(j>step_i) { + int w = width/step * j; + int h = height/step * j; + System.err.println("resize: "+step_i+" -> "+j+" - "+w+"x"+h); + fbo_mrt.reset(gl, w, h); + winctx.window.setSize(w, h); + step_i = j; + } } NEWTGLContext.destroyWindow(winctx); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java new file mode 100644 index 000000000..42f7ba652 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java @@ -0,0 +1,264 @@ +/** + * Copyright 2012 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.jogl.acore; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +import com.jogamp.newt.event.KeyAdapter; +import com.jogamp.newt.event.KeyEvent; +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +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 com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; + +import com.jogamp.opengl.test.junit.jogl.demos.es2.FBOMix2DemosES2; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.AfterClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestFBOMix2DemosES2NEWT extends UITestCase { + static long duration = 500; // ms + static int swapInterval = 1; + static boolean showFPS = false; + static boolean forceES2 = false; + static boolean doRotate = true; + static boolean demo0Only = false; + static int globalNumSamples = 0; + static boolean mainRun = false; + + @AfterClass + public static void releaseClass() { + } + + protected void runTestGL(GLCapabilitiesImmutable caps, int numSamples) throws InterruptedException { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); + System.err.println("requested: vsync "+swapInterval+", "+caps); + final GLWindow glWindow = GLWindow.create(caps); + Assert.assertNotNull(glWindow); + glWindow.setTitle("Gears NEWT Test (translucent "+!caps.isBackgroundOpaque()+"), swapInterval "+swapInterval); + if(mainRun) { + glWindow.setSize(512, 512); + } else { + glWindow.setSize(128, 128); + } + + final FBOMix2DemosES2 demo = new FBOMix2DemosES2(swapInterval); + demo.setMSAA(numSamples); + demo.setDoRotation(doRotate); + demo.setDemo0Only(demo0Only); + glWindow.addGLEventListener(demo); + glWindow.addGLEventListener(new GLEventListener() { + int i=0, c=0; + int origS; + public void init(GLAutoDrawable drawable) { + origS = demo.getMSAA(); + } + public void dispose(GLAutoDrawable drawable) {} + public void display(GLAutoDrawable drawable) { + if(mainRun) return; + + final int dw = drawable.getWidth(); + final int dh = drawable.getHeight(); + c++; + + if(dw<800) { + System.err.println("XXX: "+dw+"x"+dh+", c "+c); + if(0 == c%3) { + snapshot(i++, "msaa"+demo.getMSAA(), drawable.getGL(), screenshot, TextureIO.PNG, null); + } + if( 3 == c ) { + new Thread() { + @Override + public void run() { + demo.setMSAA(4); + } }.start(); + } else if( 6 == c ) { + new Thread() { + @Override + public void run() { + demo.setMSAA(8); + } }.start(); + } else if(9 == c) { + c=0; + new Thread() { + @Override + public void run() { + glWindow.setSize(dw+256, dh+256); + demo.setMSAA(origS); + } }.start(); + } + } + } + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } + }); + + Animator animator = new Animator(glWindow); + QuitAdapter quitAdapter = new QuitAdapter(); + + //glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter)); + //glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter)); + glWindow.addKeyListener(quitAdapter); + glWindow.addWindowListener(quitAdapter); + + glWindow.addWindowListener(new WindowAdapter() { + public void windowResized(WindowEvent e) { + System.err.println("window resized: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()); + } + public void windowMoved(WindowEvent e) { + System.err.println("window moved: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()); + } + }); + + glWindow.addKeyListener(new KeyAdapter() { + public void keyReleased(KeyEvent e) { + if( !e.isPrintableKey() || e.isAutoRepeat() ) { + return; + } + System.err.println("*** "+e); + if(e.getKeyChar()=='f') { + new Thread() { + public void run() { + System.err.println("[set fullscreen pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets()); + glWindow.setFullscreen(!glWindow.isFullscreen()); + System.err.println("[set fullscreen post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets()); + } }.start(); + } else if(e.getKeyChar()=='d') { + demo.setDemo0Only(!demo.getDemo0Only()); + } else { + int num = e.getKeyChar() - '0'; + System.err.println("*** "+num); + if(0 <= num && num <= 8) { + System.err.println("MSAA: "+demo.getMSAA()+" -> "+num); + demo.setMSAA(num); + } + } + } + }); + + animator.start(); + // glWindow.setSkipContextReleaseThread(animator.getThread()); + + glWindow.setVisible(true); + + System.err.println("NW chosen: "+glWindow.getDelegatedWindow().getChosenCapabilities()); + System.err.println("GL chosen: "+glWindow.getChosenCapabilities()); + System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", "+glWindow.getInsets()); + + animator.setUpdateFPSFrames(60, showFPS ? System.err : null); + + while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) { + Thread.sleep(100); + } + + animator.stop(); + Assert.assertFalse(animator.isAnimating()); + Assert.assertFalse(animator.isStarted()); + glWindow.destroy(); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false)); + } + + @Test + public void test01_Main() throws InterruptedException { + if( mainRun ) { + GLCapabilities caps = new GLCapabilities(forceES2 ? GLProfile.get(GLProfile.GLES2) : GLProfile.getGL2ES2()); + caps.setAlphaBits(1); + runTestGL(caps, globalNumSamples); + } + } + + @Test + public void test01() throws InterruptedException { + if( mainRun ) return ; + GLCapabilities caps = new GLCapabilities(forceES2 ? GLProfile.get(GLProfile.GLES2) : GLProfile.getGL2ES2()); + caps.setAlphaBits(1); + runTestGL(caps, 0); + } + + public static void main(String args[]) throws IOException { + boolean waitForKey = false; + + mainRun = true; + + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-vsync")) { + i++; + swapInterval = MiscUtils.atoi(args[i], swapInterval); + } else if(args[i].equals("-es2")) { + forceES2 = true; + } else if(args[i].equals("-showFPS")) { + showFPS = true; + } else if(args[i].equals("-samples")) { + i++; + globalNumSamples = MiscUtils.atoi(args[i], globalNumSamples); + } else if(args[i].equals("-norotate")) { + doRotate = false; + } else if(args[i].equals("-demo0Only")) { + demo0Only = true; + } else if(args[i].equals("-wait")) { + waitForKey = true; + } else if(args[i].equals("-nomain")) { + mainRun = false; + } + } + + System.err.println("swapInterval "+swapInterval); + System.err.println("forceES2 "+forceES2); + + 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(TestFBOMix2DemosES2NEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOffThreadSharedContextMix2DemosES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOffThreadSharedContextMix2DemosES2NEWT.java new file mode 100644 index 000000000..51dd9df37 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOffThreadSharedContextMix2DemosES2NEWT.java @@ -0,0 +1,306 @@ +/** + * Copyright 2012 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.jogl.acore; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +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 com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.FPSAnimator; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; +import com.jogamp.opengl.test.junit.jogl.demos.GLFinishOnDisplay; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.Mix2TexturesES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; + +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.SurfaceUpdatedListener; +import javax.media.opengl.GL; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLOffscreenAutoDrawable; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.AfterClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +/** + * Toolkit agnostic {@link GLOffscreenAutoDrawable.FBO} tests using the + * {@link GLDrawableFactory#createOffscreenAutoDrawable(javax.media.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, int, int, GLContext) factory model}. + * <p> + * The created {@link GLOffscreenAutoDrawable.FBO} is being used to run the {@link GLEventListener}. + * </p> + * <p> + * This test simulates shared off-thread GL context / texture usage, + * where the producer use FBOs and delivers shared textures. + * The receiver blends the shared textures onscreen. + * In detail the test consist of: + * <ul> + * <li>2 {@link GLOffscreenAutoDrawable.FBO} double buffered + * <ul> + * <li>each with their own {@link GLContext}, which is shares the {@link GLWindow} one (see below)</li> + * <li>both run within one {@link FPSAnimator} @ 30fps</li> + * <li>produce a texture</li> + * <li>notify the onscreen renderer about new textureID (swapping double buffer)</li> + * </ul></li> + * <li>1 onscreen {@link GLWindow} + * <ul> + * <li>shares it's {@link GLContext} w/ above FBOs</li> + * <li>running within one {@link Animator} at v-sync</li> + * <li>uses the shared FBO textures and blends them onscreen</li> + * </ul></li> + * </ul> + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestFBOOffThreadSharedContextMix2DemosES2NEWT extends UITestCase { + static long duration = 500; // ms + static int swapInterval = 1; + static boolean showFPS = false; + static boolean forceES2 = false; + static boolean mainRun = false; + + @AfterClass + public static void releaseClass() { + } + + protected void runTestGL(GLCapabilitiesImmutable caps) throws InterruptedException { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false); + System.err.println("requested: vsync "+swapInterval+", "+caps); + + final GLWindow glWindow = GLWindow.create(caps); + Assert.assertNotNull(glWindow); + glWindow.setTitle("Gears NEWT Test (translucent "+!caps.isBackgroundOpaque()+"), swapInterval "+swapInterval); + if(mainRun) { + glWindow.setSize(512, 512); + } else { + glWindow.setSize(256, 256); + } + // eager initialization of context + glWindow.setVisible(true); + glWindow.display(); + + final int fbod1_texUnit = 0; + final int fbod2_texUnit = 1; + + final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); + GLCapabilities fbodCaps = (GLCapabilities) caps.cloneMutable(); + // fbodCaps.setDoubleBuffered(false); + + final Mix2TexturesES2 mixerDemo = new Mix2TexturesES2(1, fbod1_texUnit, fbod2_texUnit); + + // FBOD1 + final GLOffscreenAutoDrawable.FBO fbod1 = (GLOffscreenAutoDrawable.FBO) + factory.createOffscreenAutoDrawable(null, fbodCaps, null, glWindow.getWidth(), glWindow.getHeight()); + fbod1.setSharedAutoDrawable(glWindow); + fbod1.setUpstreamWidget(glWindow); // connect the real GLWindow (mouse/key) to offscreen! + fbod1.setTextureUnit(fbod1_texUnit); + { + GearsES2 demo0 = new GearsES2(-1); + fbod1.addGLEventListener(demo0); + fbod1.addGLEventListener(new GLFinishOnDisplay()); + demo0.setIgnoreFocus(true); + } + fbod1.getNativeSurface().addSurfaceUpdatedListener(new SurfaceUpdatedListener() { + @Override + public void surfaceUpdated(Object updater, NativeSurface ns, long when) { + mixerDemo.setTexID0(fbod1.getTextureBuffer(GL.GL_FRONT).getName()); + } }); + fbod1.display(); // init + System.err.println("FBOD1 "+fbod1); + Assert.assertTrue(fbod1.isInitialized()); + + // FBOD2 + final GLOffscreenAutoDrawable.FBO fbod2 = (GLOffscreenAutoDrawable.FBO) + factory.createOffscreenAutoDrawable(null, fbodCaps, null, glWindow.getWidth(), glWindow.getHeight()); + fbod2.setSharedAutoDrawable(glWindow); + fbod2.setTextureUnit(fbod2_texUnit); + fbod2.addGLEventListener(new RedSquareES2(-1)); + fbod2.addGLEventListener(new GLFinishOnDisplay()); + fbod2.getNativeSurface().addSurfaceUpdatedListener(new SurfaceUpdatedListener() { + @Override + public void surfaceUpdated(Object updater, NativeSurface ns, long when) { + mixerDemo.setTexID1(fbod2.getTextureBuffer(GL.GL_FRONT).getName()); + } }); + fbod2.display(); // init + System.err.println("FBOD2 "+fbod2); + Assert.assertTrue(fbod2.isInitialized()); + + // preinit texIDs + mixerDemo.setTexID0(fbod1.getTextureBuffer(GL.GL_FRONT).getName()); + mixerDemo.setTexID1(fbod2.getTextureBuffer(GL.GL_FRONT).getName()); + + glWindow.addGLEventListener(mixerDemo); + glWindow.addGLEventListener(new GLEventListener() { + int i=0, c=0; + public void init(GLAutoDrawable drawable) {} + public void dispose(GLAutoDrawable drawable) {} + public void display(GLAutoDrawable drawable) { + if(mainRun) return; + + final int dw = drawable.getWidth(); + final int dh = drawable.getHeight(); + c++; + + if(dw<800) { + System.err.println("XXX: "+dw+"x"+dh+", c "+c); + if(8 == c) { + snapshot(i++, "msaa"+fbod1.getNumSamples(), drawable.getGL(), screenshot, TextureIO.PNG, null); + } + if(9 == c) { + c=0; + new Thread() { + @Override + public void run() { + glWindow.setSize(dw+256, dh+256); + } }.start(); + } + } + } + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + fbod1.setSize(width, height); + fbod2.setSize(width, height); + } + }); + + final FPSAnimator animator0 = new FPSAnimator(30); + animator0.add(fbod1); + animator0.add(fbod2); + + final Animator animator1 = new Animator(); + animator1.add(glWindow); + + QuitAdapter quitAdapter = new QuitAdapter(); + + //glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter)); + //glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter)); + glWindow.addKeyListener(quitAdapter); + glWindow.addWindowListener(quitAdapter); + + glWindow.addWindowListener(new WindowAdapter() { + public void windowResized(WindowEvent e) { + System.err.println("window resized: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()); + } + public void windowMoved(WindowEvent e) { + System.err.println("window moved: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()); + } + }); + + animator0.start(); + animator1.start(); + // glWindow.setSkipContextReleaseThread(animator.getThread()); + + glWindow.setVisible(true); + + System.err.println("NW chosen: "+glWindow.getDelegatedWindow().getChosenCapabilities()); + System.err.println("GL chosen: "+glWindow.getChosenCapabilities()); + System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", "+glWindow.getInsets()); + + animator0.setUpdateFPSFrames(30, showFPS ? System.err : null); + animator1.setUpdateFPSFrames(60, showFPS ? System.err : null); + + while(!quitAdapter.shouldQuit() && animator1.isAnimating() && animator1.getTotalFPSDuration()<duration) { + Thread.sleep(100); + } + + animator0.stop(); + Assert.assertFalse(animator0.isAnimating()); + Assert.assertFalse(animator0.isStarted()); + + animator1.stop(); + Assert.assertFalse(animator1.isAnimating()); + Assert.assertFalse(animator1.isStarted()); + + fbod1.destroy(); + fbod2.destroy(); + + glWindow.destroy(); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false)); + } + + @Test + public void test01() throws InterruptedException { + GLCapabilities caps = new GLCapabilities(forceES2 ? GLProfile.get(GLProfile.GLES2) : GLProfile.getGL2ES2()); + caps.setAlphaBits(1); + runTestGL(caps); + } + + public static void main(String args[]) throws IOException { + boolean waitForKey = false; + + mainRun = true; + + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-vsync")) { + i++; + swapInterval = MiscUtils.atoi(args[i], swapInterval); + } else if(args[i].equals("-es2")) { + forceES2 = true; + } else if(args[i].equals("-showFPS")) { + showFPS = true; + } else if(args[i].equals("-wait")) { + waitForKey = true; + } else if(args[i].equals("-nomain")) { + mainRun = false; + } + } + + System.err.println("swapInterval "+swapInterval); + System.err.println("forceES2 "+forceES2); + + 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(TestFBOOffThreadSharedContextMix2DemosES2NEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOnThreadSharedContext1DemoES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOnThreadSharedContext1DemoES2NEWT.java new file mode 100644 index 000000000..3c6c61f80 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOnThreadSharedContext1DemoES2NEWT.java @@ -0,0 +1,279 @@ +/** + * Copyright 2012 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.jogl.acore; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +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 com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; +import com.jogamp.opengl.test.junit.jogl.demos.GLFinishOnDisplay; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.Mix2TexturesES2; + +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.SurfaceUpdatedListener; +import javax.media.opengl.GL; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLOffscreenAutoDrawable; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.AfterClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +/** + * Toolkit agnostic {@link GLOffscreenAutoDrawable.FBO} tests using the + * {@link GLDrawableFactory#createOffscreenAutoDrawable(javax.media.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, int, int, GLContext) factory model}. + * <p> + * The created {@link GLOffscreenAutoDrawable.FBO} is being used to run the {@link GLEventListener}. + * </p> + * <p> + * This test simulates shared on-thread GL context / texture usage, + * where the producer uses an FBO and delivers a shared texture. + * The receiver draws the shared texture onscreen. + * In detail the test consist of: + * <ul> + * <li>1 {@link GLOffscreenAutoDrawable.FBO} double buffered + * <ul> + * <liwith its own {@link GLContext}, which is shares the {@link GLWindow} one (see below)</li> + * <li>running within common {@link Animator} @ 60fps</li> + * <li>produce a texture</li> + * <li>notify the onscreen renderer about new textureID (swapping double buffer)</li> + * </ul></li> + * <li>1 onscreen {@link GLWindow} + * <ul> + * <li>shares it's {@link GLContext} w/ above FBO</li> + * <li>running within common {@link Animator} @ 60fps</li> + * <li>uses the shared FBO texture and draws it onscreen</li> + * </ul></li> + * </ul> + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestFBOOnThreadSharedContext1DemoES2NEWT extends UITestCase { + static long duration = 500; // ms + static int swapInterval = 1; + static boolean showFPS = false; + static boolean forceES2 = false; + static boolean mainRun = false; + + @AfterClass + public static void releaseClass() { + } + + protected void runTestGL(GLCapabilitiesImmutable caps) throws InterruptedException { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false); + System.err.println("requested: vsync "+swapInterval+", "+caps); + + final GLWindow glWindow = GLWindow.create(caps); + Assert.assertNotNull(glWindow); + glWindow.setTitle("Gears NEWT Test (translucent "+!caps.isBackgroundOpaque()+"), swapInterval "+swapInterval); + if(mainRun) { + glWindow.setSize(512, 512); + } else { + glWindow.setSize(256, 256); + } + // eager initialization of context + glWindow.setVisible(true); + glWindow.display(); + + final int fbod1_texUnit = 0; + + final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); + GLCapabilities fbodCaps = (GLCapabilities) caps.cloneMutable(); + // fbodCaps.setDoubleBuffered(false); + + final Mix2TexturesES2 mixerDemo = new Mix2TexturesES2(1, fbod1_texUnit, 0); + + // FBOD1 + final GLOffscreenAutoDrawable.FBO fbod1 = (GLOffscreenAutoDrawable.FBO) + factory.createOffscreenAutoDrawable(null, fbodCaps, null, glWindow.getWidth(), glWindow.getHeight()); + fbod1.setSharedAutoDrawable(glWindow); + fbod1.setUpstreamWidget(glWindow); // connect the real GLWindow (mouse/key) to offscreen! + fbod1.setTextureUnit(fbod1_texUnit); + { + GearsES2 demo0 = new GearsES2(-1); + fbod1.addGLEventListener(demo0); + fbod1.addGLEventListener(new GLFinishOnDisplay()); + demo0.setIgnoreFocus(true); + } + fbod1.getNativeSurface().addSurfaceUpdatedListener(new SurfaceUpdatedListener() { + @Override + public void surfaceUpdated(Object updater, NativeSurface ns, long when) { + mixerDemo.setTexID0(fbod1.getTextureBuffer(GL.GL_FRONT).getName()); + } }); + fbod1.display(); // init + System.err.println("FBOD1 "+fbod1); + Assert.assertTrue(fbod1.isInitialized()); + + // preinit texIDs + mixerDemo.setTexID0(fbod1.getTextureBuffer(GL.GL_FRONT).getName()); + + glWindow.addWindowListener(new WindowAdapter() { + @Override + public void windowResized(WindowEvent e) { + fbod1.setSize(glWindow.getWidth(), glWindow.getHeight()); + } + }); + glWindow.addGLEventListener(mixerDemo); + glWindow.addGLEventListener(new GLEventListener() { + int i=0, c=0; + public void init(GLAutoDrawable drawable) {} + public void dispose(GLAutoDrawable drawable) {} + public void display(GLAutoDrawable drawable) { + if(mainRun) return; + + final int dw = drawable.getWidth(); + final int dh = drawable.getHeight(); + c++; + + if(dw<800) { + System.err.println("XXX: "+dw+"x"+dh+", c "+c); + if(8 == c) { + snapshot(i++, "msaa"+fbod1.getNumSamples(), drawable.getGL(), screenshot, TextureIO.PNG, null); + } + if(9 == c) { + c=0; + new Thread() { + @Override + public void run() { + glWindow.setSize(dw+256, dh+256); + } }.start(); + } + } + } + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } + }); + + final Animator animator1 = new Animator(); + animator1.add(fbod1); + animator1.add(glWindow); + + QuitAdapter quitAdapter = new QuitAdapter(); + + //glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter)); + //glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter)); + glWindow.addKeyListener(quitAdapter); + glWindow.addWindowListener(quitAdapter); + + glWindow.addWindowListener(new WindowAdapter() { + public void windowResized(WindowEvent e) { + System.err.println("window resized: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()); + } + public void windowMoved(WindowEvent e) { + System.err.println("window moved: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()); + } + }); + + animator1.start(); + // glWindow.setSkipContextReleaseThread(animator.getThread()); + + glWindow.setVisible(true); + + System.err.println("NW chosen: "+glWindow.getDelegatedWindow().getChosenCapabilities()); + System.err.println("GL chosen: "+glWindow.getChosenCapabilities()); + System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", "+glWindow.getInsets()); + + animator1.setUpdateFPSFrames(60, showFPS ? System.err : null); + + while(!quitAdapter.shouldQuit() && animator1.isAnimating() && animator1.getTotalFPSDuration()<duration) { + Thread.sleep(100); + } + + animator1.stop(); + Assert.assertFalse(animator1.isAnimating()); + Assert.assertFalse(animator1.isStarted()); + + fbod1.destroy(); + + glWindow.destroy(); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false)); + } + + @Test + public void test01() throws InterruptedException { + GLCapabilities caps = new GLCapabilities(forceES2 ? GLProfile.get(GLProfile.GLES2) : GLProfile.getGL2ES2()); + caps.setAlphaBits(1); + runTestGL(caps); + } + + public static void main(String args[]) throws IOException { + boolean waitForKey = false; + + mainRun = true; + + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-vsync")) { + i++; + swapInterval = MiscUtils.atoi(args[i], swapInterval); + } else if(args[i].equals("-es2")) { + forceES2 = true; + } else if(args[i].equals("-showFPS")) { + showFPS = true; + } else if(args[i].equals("-wait")) { + waitForKey = true; + } else if(args[i].equals("-nomain")) { + mainRun = false; + } + } + + System.err.println("swapInterval "+swapInterval); + System.err.println("forceES2 "+forceES2); + + 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(TestFBOOnThreadSharedContext1DemoES2NEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateNEWT.java new file mode 100644 index 000000000..91bae16d7 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateNEWT.java @@ -0,0 +1,163 @@ +/** + * Copyright 2013 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.jogl.acore; + +import java.io.IOException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Window; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.event.WindowUpdateEvent; +import com.jogamp.opengl.GLAutoDrawableDelegate; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; + +/** + * Test using a NEWT {@link Window} for onscreen case. + * <p> + * Creates a {@link GLDrawable} using the + * {@link GLDrawableFactory#createGLDrawable(javax.media.nativewindow.NativeSurface) factory model}. + * The {@link GLContext} is derived {@link GLDrawable#createContext(GLContext) from the drawable}. + * </p> + * <p> + * Finally a {@link GLAutoDrawableDelegate} is created with the just created {@link GLDrawable} and {@link GLContext}. + * It is being used to run the {@link GLEventListener}. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLAutoDrawableDelegateNEWT extends UITestCase { + static long duration = 500; // ms + + void doTest(GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException { + final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); + + // + // Create native windowing resources .. X11/Win/OSX + // + final Window window = NewtFactory.createWindow(reqGLCaps); + Assert.assertNotNull(window); + window.setSize(640, 400); + window.setVisible(true); + Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true)); + System.out.println("Window: "+window.getClass().getName()); + + final GLDrawable drawable = factory.createGLDrawable(window); + Assert.assertNotNull(drawable); + drawable.setRealized(true); + + final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, null, window, false, null) { + @Override + protected void destroyImplInLock() { + super.destroyImplInLock(); // destroys drawable/context + window.destroy(); // destroys the actual window, incl. the device + } + }; + + window.setWindowDestroyNotifyAction( new Runnable() { + public void run() { + glad.windowDestroyNotifyOp(); + } } ); + + window.addWindowListener(new WindowAdapter() { + @Override + public void windowRepaint(WindowUpdateEvent e) { + glad.windowRepaintOp(); + } + + @Override + public void windowResized(WindowEvent e) { + glad.windowResizedOp(window.getWidth(), window.getHeight()); + } + }); + + glad.addGLEventListener(demo); + + QuitAdapter quitAdapter = new QuitAdapter(); + //glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter)); + //glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter)); + window.addKeyListener(quitAdapter); + window.addWindowListener(quitAdapter); + + Animator animator = new Animator(); + animator.setUpdateFPSFrames(60, System.err); + animator.setModeBits(false, Animator.MODE_EXPECT_AWT_RENDERING_THREAD); + animator.add(glad); + animator.start(); + Assert.assertTrue(animator.isStarted()); + Assert.assertTrue(animator.isAnimating()); + + while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) { + Thread.sleep(100); + } + System.out.println("Fin start ..."); + + animator.stop(); + Assert.assertFalse(animator.isAnimating()); + Assert.assertFalse(animator.isStarted()); + glad.destroy(); + System.out.println("Fin Drawable: "+drawable); + System.out.println("Fin Window: "+window); + } + + @Test + public void testOnScreenDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = new GLCapabilities( GLProfile.getGL2ES2() ); + doTest(reqGLCaps, new GearsES2(1)); + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } + } + org.junit.runner.JUnitCore.main(TestGLAutoDrawableDelegateNEWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateOnOffscrnCapsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateOnOffscrnCapsNEWT.java new file mode 100644 index 000000000..3d49a0dce --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateOnOffscrnCapsNEWT.java @@ -0,0 +1,388 @@ +/** + * 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.jogl.acore; + +import java.io.IOException; + +import javax.media.nativewindow.CapabilitiesImmutable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import jogamp.opengl.GLGraphicsConfigurationUtil; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Window; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.event.WindowUpdateEvent; +import com.jogamp.opengl.GLAutoDrawableDelegate; +import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Tests using a NEWT {@link Window} for on- and offscreen cases. + * <p> + * Each test creates a {@link GLDrawable} using the + * {@link GLDrawableFactory#createGLDrawable(javax.media.nativewindow.NativeSurface) factory model}. + * The {@link GLContext} is derived {@link GLDrawable#createContext(GLContext) from the drawable}. + * </p> + * <p> + * Finally a {@link GLAutoDrawableDelegate} is created with the just created {@link GLDrawable} and {@link GLContext}. + * It is being used to run the {@link GLEventListener}. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLAutoDrawableDelegateOnOffscrnCapsNEWT extends UITestCase { + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + static GLCapabilities getCaps(String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return new GLCapabilities(GLProfile.get(profile)); + } + + void doTest(GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException { + System.out.println("Requested GL Caps: "+reqGLCaps); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); + final GLCapabilitiesImmutable expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, factory, null); + System.out.println("Expected GL Caps: "+expGLCaps); + // + // Create native windowing resources .. X11/Win/OSX + // + final Window window = NewtFactory.createWindow(reqGLCaps); + Assert.assertNotNull(window); + window.setSize(widthStep*szStep, heightStep*szStep); + window.setVisible(true); + Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true)); + System.out.println("Window: "+window.getClass().getName()); + + // Check caps of NativeWindow config w/o GL + final CapabilitiesImmutable chosenCaps = window.getGraphicsConfiguration().getChosenCapabilities(); + System.out.println("Window Caps Pre_GL: "+chosenCaps); + Assert.assertNotNull(chosenCaps); + Assert.assertTrue(chosenCaps.getGreenBits()>5); + Assert.assertTrue(chosenCaps.getBlueBits()>5); + Assert.assertTrue(chosenCaps.getRedBits()>5); + + // + // Create native OpenGL resources .. XGL/WGL/CGL .. + // equivalent to GLAutoDrawable methods: setVisible(true) + // + final GLDrawable drawable = factory.createGLDrawable(window); + Assert.assertNotNull(drawable); + System.out.println("Drawable Pre-GL(0): "+drawable.getClass().getName()+", "+drawable.getNativeSurface().getClass().getName()); + + // + drawable.setRealized(true); + Assert.assertTrue(drawable.isRealized()); + + System.out.println("Window Caps PostGL : "+window.getGraphicsConfiguration().getChosenCapabilities()); + System.out.println("Drawable Post-GL(1): "+drawable.getClass().getName()+", "+drawable.getNativeSurface().getClass().getName()); + + // Note: FBO Drawable realization happens at 1st context.makeCurrent(), + // and hence only then it's caps can _fully_ reflect expectations, + // i.e. depth, stencil and MSAA will be valid only after makeCurrent(), + // where on-/offscreen state after setRealized(true) + // See GLFBODrawable API doc in this regard! + + + final GLCapabilitiesImmutable chosenGLCaps01 = drawable.getChosenGLCapabilities(); + System.out.println("Chosen GL Caps(1): "+chosenGLCaps01); + Assert.assertNotNull(chosenGLCaps01); + Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps01.isOnscreen()); + Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps01.isFBO()); + Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps01.isPBuffer()); + Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps01.isBitmap()); + + final GLContext context = drawable.createContext(null); + Assert.assertNotNull(context); + int res = context.makeCurrent(); + Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res); + context.release(); + + // Check caps of GLDrawable after realization + final GLCapabilitiesImmutable chosenGLCaps02 = drawable.getChosenGLCapabilities(); + System.out.println("Chosen GL Caps(2): "+chosenGLCaps02); + System.out.println("Chosen GL CTX (2): "+context.getGLVersion()); + System.out.println("Drawable Post-GL(2): "+drawable.getClass().getName()+", "+drawable.getNativeSurface().getClass().getName()); + Assert.assertNotNull(chosenGLCaps02); + Assert.assertTrue(chosenGLCaps02.getGreenBits()>5); + Assert.assertTrue(chosenGLCaps02.getBlueBits()>5); + Assert.assertTrue(chosenGLCaps02.getRedBits()>5); + Assert.assertTrue(chosenGLCaps02.getDepthBits()>4); + Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps02.isOnscreen()); + Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps02.isFBO()); + Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps02.isPBuffer()); + Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps02.isBitmap()); + /** Single/Double buffer cannot be checked since result may vary .. + if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) { + // dbl buffer may be disabled w/ offscreen pbuffer and bitmap + Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered()); + } */ + + final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, context, window, false, null) { + @Override + protected void destroyImplInLock() { + super.destroyImplInLock(); // destroys drawable/context + window.destroy(); // destroys the actual window, incl. the device + } + }; + + window.setWindowDestroyNotifyAction( new Runnable() { + public void run() { + glad.windowDestroyNotifyOp(); + } } ); + + window.addWindowListener(new WindowAdapter() { + @Override + public void windowRepaint(WindowUpdateEvent e) { + glad.windowRepaintOp(); + } + + @Override + public void windowResized(WindowEvent e) { + glad.windowResizedOp(window.getWidth(), window.getHeight()); + } + }); + + glad.addGLEventListener(demo); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + glad.addGLEventListener(snapshotGLEventListener); + + glad.display(); // initial resize/display + + // 1 - szStep = 2 + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 2, 3 (resize + display) + szStep = 1; + window.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 4, 5 (resize + display) + szStep = 4; + window.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + Thread.sleep(50); + + glad.destroy(); + System.out.println("Fin Drawable: "+drawable); + System.out.println("Fin Window: "+window); + } + + @Test + public void testAvailableInfo() { + GLDrawableFactory f = GLDrawableFactory.getDesktopFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + f = GLDrawableFactory.getEGLFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + } + + @Test + public void testGL2OnScreenSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OnScreenDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenAutoDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBOSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBODblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbufferDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbufferSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenBitmapSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testES2OnScreenSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OnScreenDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenAutoDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBOSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBODblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenPbufferDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenPbufferSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + /** Not implemented ! + @Test + public void testES2OffScreenBitmapDblBuf() throws InterruptedException { + if(!checkProfile(GLProfile.GLES2)) { + return; + } + final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + doTest(reqGLCaps, new GearsES2(1)); + } */ + + public static void main(String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestGLAutoDrawableDelegateOnOffscrnCapsNEWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryES2OffscrnCapsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryES2OffscrnCapsNEWT.java new file mode 100644 index 000000000..a5799a6cb --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryES2OffscrnCapsNEWT.java @@ -0,0 +1,345 @@ +/** + * 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.jogl.acore; + +import java.io.IOException; + +import javax.media.nativewindow.CapabilitiesImmutable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLOffscreenAutoDrawable; +import javax.media.opengl.GLProfile; + +import jogamp.opengl.GLGraphicsConfigurationUtil; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Toolkit agnostic {@link GLOffscreenAutoDrawable} tests using the + * {@link GLDrawableFactory#createOffscreenAutoDrawable(javax.media.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, int, int, GLContext) factory model}. + * <p> + * The created {@link GLOffscreenAutoDrawable} is being used to run the {@link GLEventListener}. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLAutoDrawableFactoryES2OffscrnCapsNEWT extends UITestCase { + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + static GLCapabilities getCaps(String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return new GLCapabilities(GLProfile.get(profile)); + } + + void doTest(GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException { + System.out.println("Requested GL Caps: "+reqGLCaps); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); + final GLCapabilitiesImmutable expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, factory, null); + System.out.println("Expected GL Caps: "+expGLCaps); + + // + // Create native OpenGL resources .. XGL/WGL/CGL .. + // equivalent to GLAutoDrawable methods: setVisible(true) + // + final GLOffscreenAutoDrawable glad = factory.createOffscreenAutoDrawable(null, reqGLCaps, null, widthStep*szStep, heightStep*szStep); + + Assert.assertNotNull(glad); + System.out.println("Drawable Pre-GL(0): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + Assert.assertTrue(glad.isRealized()); + + // Check caps of NativeWindow config w/o GL + final CapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities(); + System.out.println("Drawable Caps Pre_GL : "+chosenCaps); + Assert.assertNotNull(chosenCaps); + Assert.assertTrue(chosenCaps.getGreenBits()>4); + Assert.assertTrue(chosenCaps.getBlueBits()>4); + Assert.assertTrue(chosenCaps.getRedBits()>4); + + glad.display(); // force native context creation + + // Check caps of GLDrawable after realization + final GLCapabilitiesImmutable chosenGLCaps = glad.getChosenGLCapabilities(); + System.out.println("Chosen GL CTX (1): "+glad.getContext().getGLVersion()); + System.out.println("Chosen GL Caps(1): "+chosenGLCaps); + System.out.println("Chosen GL Caps(2): "+glad.getNativeSurface().getGraphicsConfiguration().getChosenCapabilities()); + + Assert.assertNotNull(chosenGLCaps); + Assert.assertTrue(chosenGLCaps.getGreenBits()>4); + Assert.assertTrue(chosenGLCaps.getBlueBits()>4); + Assert.assertTrue(chosenGLCaps.getRedBits()>4); + Assert.assertTrue(chosenGLCaps.getDepthBits()>4); + Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps.isOnscreen()); + Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO()); + Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer()); + Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap()); + /** Single/Double buffer cannot be checked since result may vary .. + if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) { + // dbl buffer may be disabled w/ offscreen pbuffer and bitmap + Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered()); + } */ + + glad.addGLEventListener(demo); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + glad.addGLEventListener(snapshotGLEventListener); + + glad.display(); // initial resize/display + + // 1 - szStep = 2 + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 2, 3 (resize + display) + szStep = 1; + glad.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 4, 5 (resize + display) + szStep = 4; + glad.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + Thread.sleep(50); + + glad.destroy(); + System.out.println("Fin Drawable: "+glad); + } + + @Test + public void testAvailableInfo() { + GLDrawableFactory f = GLDrawableFactory.getDesktopFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + f = GLDrawableFactory.getEGLFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + } + + @Test + public void testES2OffScreenAutoDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBODblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBOSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBODblBufStencil() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setStencilBits(1); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBODblBufMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBODblBufStencilMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setStencilBits(1); + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenPbufferDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenPbufferSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + // Might be reduced to !stencil + @Test + public void testES2OffScreenPbufferDblBufStencil() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setStencilBits(1); + doTest(reqGLCaps, new GearsES2(1)); + } + + // Might be reduced to !MSAA + @Test + public void testES2OffScreenPbufferDblBufMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(reqGLCaps, new GearsES2(1)); + } + + // Might be reduced to !stencil && !MSAA + @Test + public void testES2OffScreenPbufferDblBufStencilMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setStencilBits(1); + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(reqGLCaps, new GearsES2(1)); + } + + /** NOT Implemented: + // Might be reduced to !double-buff + @Test + public void testES2OffScreenBitmapDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testES2OffScreenBitmapSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new Gears(1)); + } + + // Might be reduced to !stencil + @Test + public void testES2OffScreenBitmapDblBufStencil() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + reqGLCaps.setStencilBits(1); + doTest(reqGLCaps, new GearsES2(1)); + } + + // Might be reduced to !MSAA + @Test + public void testES2OffScreenBitmapDblBufMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(reqGLCaps, new GearsES2(1)); + } + + // Might be reduced to !stencil && !MSAA + @Test + public void testES2OffScreenBitmapDblBufStencilMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + reqGLCaps.setStencilBits(1); + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(reqGLCaps, new GearsES2(1)); + } */ + + public static void main(String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestGLAutoDrawableFactoryES2OffscrnCapsNEWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGL2OffscrnCapsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGL2OffscrnCapsNEWT.java new file mode 100644 index 000000000..09e211332 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGL2OffscrnCapsNEWT.java @@ -0,0 +1,384 @@ +/** + * 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.jogl.acore; + +import java.io.IOException; + +import javax.media.nativewindow.CapabilitiesImmutable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLOffscreenAutoDrawable; +import javax.media.opengl.GLProfile; + +import jogamp.opengl.GLGraphicsConfigurationUtil; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Toolkit agnostic {@link GLOffscreenAutoDrawable} tests using the + * {@link GLDrawableFactory#createOffscreenAutoDrawable(javax.media.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, int, int, GLContext) factory model}. + * <p> + * The created {@link GLOffscreenAutoDrawable} is being used to run the {@link GLEventListener}. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLAutoDrawableFactoryGL2OffscrnCapsNEWT extends UITestCase { + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + static GLCapabilities getCaps(String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return new GLCapabilities(GLProfile.get(profile)); + } + + void doTest(GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException { + System.out.println("Requested GL Caps: "+reqGLCaps); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); + final GLCapabilitiesImmutable expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, factory, null); + System.out.println("Expected GL Caps: "+expGLCaps); + + // + // Create native OpenGL resources .. XGL/WGL/CGL .. + // equivalent to GLAutoDrawable methods: setVisible(true) + // + final GLOffscreenAutoDrawable glad = factory.createOffscreenAutoDrawable(null, reqGLCaps, null, widthStep*szStep, heightStep*szStep); + + Assert.assertNotNull(glad); + System.out.println("Drawable Pre-GL(0): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + Assert.assertTrue(glad.isRealized()); + + // Check caps of NativeWindow config w/o GL + final CapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities(); + System.out.println("Drawable Caps Pre_GL : "+chosenCaps); + Assert.assertNotNull(chosenCaps); + Assert.assertTrue(chosenCaps.getGreenBits()>4); + Assert.assertTrue(chosenCaps.getBlueBits()>4); + Assert.assertTrue(chosenCaps.getRedBits()>4); + + glad.display(); // force native context creation + + // Check caps of GLDrawable after realization + final GLCapabilitiesImmutable chosenGLCaps = glad.getChosenGLCapabilities(); + System.out.println("Chosen GL CTX (1): "+glad.getContext().getGLVersion()); + System.out.println("Chosen GL Caps(1): "+chosenGLCaps); + System.out.println("Chosen GL Caps(2): "+glad.getNativeSurface().getGraphicsConfiguration().getChosenCapabilities()); + + Assert.assertNotNull(chosenGLCaps); + Assert.assertTrue(chosenGLCaps.getGreenBits()>4); + Assert.assertTrue(chosenGLCaps.getBlueBits()>4); + Assert.assertTrue(chosenGLCaps.getRedBits()>4); + Assert.assertTrue(chosenGLCaps.getDepthBits()>4); + Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps.isOnscreen()); + Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO()); + Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer()); + Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap()); + /** Single/Double buffer cannot be checked since result may vary .. + if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) { + // dbl buffer may be disabled w/ offscreen pbuffer and bitmap + Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered()); + } */ + + glad.addGLEventListener(demo); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + glad.addGLEventListener(snapshotGLEventListener); + + glad.display(); // initial resize/display + + // 1 - szStep = 2 + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 2, 3 (resize + display) + szStep = 1; + glad.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 4, 5 (resize + display) + szStep = 4; + glad.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + Thread.sleep(50); + + glad.destroy(); + System.out.println("Fin Drawable: "+glad); + } + + @Test + public void testAvailableInfo() { + GLDrawableFactory f = GLDrawableFactory.getDesktopFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + f = GLDrawableFactory.getEGLFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + } + + @Test + public void testGL2OffScreenAutoDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testGL2OffScreenFBODblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testGL2OffScreenFBOSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testGL2OffScreenFBODblBufStencil() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setStencilBits(1); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testGL2OffScreenFBODblBufMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testGL2OffScreenFBODblBufStencilMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setStencilBits(1); + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testGL2OffScreenPbufferDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testGL2OffScreenPbufferSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new Gears(1)); + } + + // Might be reduced to !stencil + @Test + public void testGL2OffScreenPbufferDblBufStencil() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setStencilBits(1); + doTest(reqGLCaps, new Gears(1)); + } + + // Might be reduced to !MSAA + @Test + public void testGL2OffScreenPbufferDblBufMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(reqGLCaps, new Gears(1)); + } + + // Might be reduced to !stencil && !MSAA + @Test + public void testGL2OffScreenPbufferDblBufStencilMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setStencilBits(1); + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(reqGLCaps, new Gears(1)); + } + + + // Might be reduced to !double-buff + @Test + public void testGL2OffScreenBitmapDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testGL2OffScreenBitmapDblBufRGBA8881() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setRedBits(8); + reqGLCaps.setGreenBits(8); + reqGLCaps.setBlueBits(8); + reqGLCaps.setAlphaBits(1); + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testGL2OffScreenBitmapDblBufRGB555() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setRedBits(5); + reqGLCaps.setGreenBits(5); + reqGLCaps.setBlueBits(5); + reqGLCaps.setAlphaBits(0); + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testGL2OffScreenBitmapDblBufRGBA5551() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setRedBits(5); + reqGLCaps.setGreenBits(5); + reqGLCaps.setBlueBits(5); + reqGLCaps.setAlphaBits(1); + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testGL2OffScreenBitmapSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new Gears(1)); + } + + // Might be reduced to !stencil + @Test + public void testGL2OffScreenBitmapDblBufStencil() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + reqGLCaps.setStencilBits(1); + doTest(reqGLCaps, new Gears(1)); + } + + // Might be reduced to !MSAA + @Test + public void testGL2OffScreenBitmapDblBufMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(reqGLCaps, new Gears(1)); + } + + // Might be reduced to !stencil && !MSAA + @Test + public void testGL2OffScreenBitmapDblBufStencilMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + reqGLCaps.setStencilBits(1); + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(reqGLCaps, new Gears(1)); + } + + public static void main(String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestGLAutoDrawableFactoryGL2OffscrnCapsNEWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGLnBitmapCapsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGLnBitmapCapsNEWT.java new file mode 100644 index 000000000..f35f8c8b0 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGLnBitmapCapsNEWT.java @@ -0,0 +1,185 @@ +/** + * 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.jogl.acore; + +import java.io.IOException; + +import javax.media.nativewindow.CapabilitiesImmutable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLOffscreenAutoDrawable; +import javax.media.opengl.GLProfile; + +import jogamp.opengl.GLGraphicsConfigurationUtil; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Toolkit agnostic {@link GLOffscreenAutoDrawable} tests using the + * {@link GLDrawableFactory#createOffscreenAutoDrawable(javax.media.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, int, int, GLContext) factory model}. + * <p> + * The created {@link GLOffscreenAutoDrawable} is being used to run the {@link GLEventListener}. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLAutoDrawableFactoryGLnBitmapCapsNEWT extends UITestCase { + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + void doTest(GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException { + System.out.println("Requested GL Caps: "+reqGLCaps); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); + final GLCapabilitiesImmutable expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, factory, null); + System.out.println("Expected GL Caps: "+expGLCaps); + + // + // Create native OpenGL resources .. XGL/WGL/CGL .. + // equivalent to GLAutoDrawable methods: setVisible(true) + // + final GLOffscreenAutoDrawable glad = factory.createOffscreenAutoDrawable(null, reqGLCaps, null, widthStep*szStep, heightStep*szStep); + + Assert.assertNotNull(glad); + System.out.println("Drawable Pre-GL(0): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + Assert.assertTrue(glad.isRealized()); + + // Check caps of NativeWindow config w/o GL + final CapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities(); + System.out.println("Drawable Caps Pre_GL : "+chosenCaps); + Assert.assertNotNull(chosenCaps); + Assert.assertTrue(chosenCaps.getGreenBits()>4); + Assert.assertTrue(chosenCaps.getBlueBits()>4); + Assert.assertTrue(chosenCaps.getRedBits()>4); + + glad.display(); // force native context creation + + // Check caps of GLDrawable after realization + final GLCapabilitiesImmutable chosenGLCaps = glad.getChosenGLCapabilities(); + System.out.println("Chosen GL CTX (1): "+glad.getContext().getGLVersion()); + System.out.println("Chosen GL Caps(1): "+chosenGLCaps); + System.out.println("Chosen GL Caps(2): "+glad.getNativeSurface().getGraphicsConfiguration().getChosenCapabilities()); + + Assert.assertNotNull(chosenGLCaps); + Assert.assertTrue(chosenGLCaps.getGreenBits()>4); + Assert.assertTrue(chosenGLCaps.getBlueBits()>4); + Assert.assertTrue(chosenGLCaps.getRedBits()>4); + Assert.assertTrue(chosenGLCaps.getDepthBits()>4); + Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps.isOnscreen()); + Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO()); + Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer()); + Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap()); + /** Single/Double buffer cannot be checked since result may vary .. + if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) { + // dbl buffer may be disabled w/ offscreen pbuffer and bitmap + Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered()); + } */ + + glad.addGLEventListener(demo); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + glad.addGLEventListener(snapshotGLEventListener); + + glad.display(); // initial resize/display + + // 1 - szStep = 2 + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 2, 3 (resize + display) + szStep = 1; + glad.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 4, 5 (resize + display) + szStep = 4; + glad.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + Thread.sleep(50); + + glad.destroy(); + System.out.println("Fin Drawable: "+glad); + } + + @Test + public void testAvailableInfo() { + GLDrawableFactory f = GLDrawableFactory.getDesktopFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + f = GLDrawableFactory.getEGLFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + } + + // Might be reduced to !double-buff + @Test + public void testGL2OffScreenBitmapDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.getDefault()); + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + doTest(reqGLCaps, new Gears(1)); + } + + // Might be reduced to !MSAA + @Test + public void testGL2OffScreenBitmapDblBufMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.getDefault()); + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(reqGLCaps, new Gears(1)); + } + + public static void main(String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestGLAutoDrawableFactoryGLnBitmapCapsNEWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.java new file mode 100644 index 000000000..ab64b5def --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.java @@ -0,0 +1,346 @@ +/** + * 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.jogl.acore; + +import java.awt.Dimension; +import java.awt.Frame; +import java.io.IOException; + +import javax.media.nativewindow.CapabilitiesImmutable; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; + +import jogamp.nativewindow.jawt.JAWTUtil; +import jogamp.opengl.GLGraphicsConfigurationUtil; + +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Tests using an AWT {@link GLCanvas} {@link GLAutoDrawable auto drawable} for on- and offscreen cases. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT extends UITestCase { + static final int widthStep = 800/4; + static final int heightStep = 600/4; + static boolean waitForKey = false; + volatile int szStep = 2; + + static GLCapabilities getCaps(String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return new GLCapabilities(GLProfile.get(profile)); + } + + static void setGLCanvasSize(final Frame frame, final GLCanvas glc, final int width, final int height) { + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + final Dimension new_sz = new Dimension(width, height); + glc.setMinimumSize(new_sz); + glc.setPreferredSize(new_sz); + glc.setSize(new_sz); + frame.pack(); + frame.validate(); + } } ); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + } + + static interface MyGLEventListener extends GLEventListener { + void setMakeSnapshot(); + } + + void doTest(GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException { + if(reqGLCaps.isOnscreen() && JAWTUtil.isOffscreenLayerRequired()) { + System.err.println("onscreen layer n/a"); + return; + } + if(!reqGLCaps.isOnscreen() && !JAWTUtil.isOffscreenLayerSupported()) { + System.err.println("offscreen layer n/a"); + return; + } + System.out.println("Requested GL Caps: "+reqGLCaps); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); + final GLCapabilitiesImmutable expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, factory, null); + System.out.println("Expected GL Caps: "+expGLCaps); + // + // Create native windowing resources .. X11/Win/OSX + // + final GLCanvas glad = new GLCanvas(reqGLCaps); // will implicit trigger offscreen layer - if !onscreen && supported + Assert.assertNotNull(glad); + Dimension glc_sz = new Dimension(widthStep*szStep, heightStep*szStep); + glad.setMinimumSize(glc_sz); + glad.setPreferredSize(glc_sz); + glad.setSize(glc_sz); + final Frame frame = new Frame(getSimpleTestName(".")); + Assert.assertNotNull(frame); + frame.add(glad); + + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.pack(); + frame.setVisible(true); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + + Assert.assertTrue(AWTRobotUtil.waitForVisible(glad, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(glad, true)); + System.out.println("Window: "+glad.getClass().getName()); + + // Check caps of NativeWindow config w/o GL + final CapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities(); + System.out.println("Window Caps Pre_GL: "+chosenCaps); + Assert.assertNotNull(chosenCaps); + Assert.assertTrue(chosenCaps.getGreenBits()>5); + Assert.assertTrue(chosenCaps.getBlueBits()>5); + Assert.assertTrue(chosenCaps.getRedBits()>5); + + glad.display(); // force native context creation + + // + // Create native OpenGL resources .. XGL/WGL/CGL .. + // equivalent to GLAutoDrawable methods: setVisible(true) + // + { + final GLDrawable actualDrawable = glad.getDelegatedDrawable(); + Assert.assertNotNull(actualDrawable); + System.out.println("Drawable Pre-GL(0): "+actualDrawable.getClass().getName()+", "+actualDrawable.getNativeSurface().getClass().getName()); + } + + System.out.println("Window Caps PostGL : "+glad.getChosenGLCapabilities()); + System.out.println("Drawable Post-GL(1): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + + // Check caps of GLDrawable after realization + final GLCapabilitiesImmutable chosenGLCaps = glad.getChosenGLCapabilities(); + System.out.println("Chosen GL Caps(1): "+chosenGLCaps); + Assert.assertNotNull(chosenGLCaps); + Assert.assertTrue(chosenGLCaps.getGreenBits()>5); + Assert.assertTrue(chosenGLCaps.getBlueBits()>5); + Assert.assertTrue(chosenGLCaps.getRedBits()>5); + Assert.assertTrue(chosenGLCaps.getDepthBits()>4); + Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps.isOnscreen()); + Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO()); + Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer()); + Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap()); + /** Single/Double buffer cannot be checked since result may vary .. + if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) { + // dbl buffer may be disabled w/ offscreen pbuffer and bitmap + Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered()); + } */ + + { + GLContext context = glad.getContext(); + System.out.println("Chosen GL CTX (2): "+context.getGLVersion()); + Assert.assertNotNull(context); + Assert.assertTrue(context.isCreated()); + } + + System.out.println("Chosen GL Caps(2): "+glad.getChosenGLCapabilities()); + System.out.println("Drawable Post-GL(2): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + + glad.addGLEventListener(demo); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + glad.addGLEventListener(snapshotGLEventListener); + + glad.display(); // initial resize/display + + // 1 - szStep = 2 + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 2, 3 (resize + display) + szStep = 1; + setGLCanvasSize(frame, glad, widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + glad.display(); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 4, 5 (resize + display) + szStep = 4; + setGLCanvasSize(frame, glad, widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + glad.display(); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + Thread.sleep(50); + + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + frame.remove(glad); + frame.dispose(); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + System.out.println("Fin: "+glad); + } + + @Test + public void testAvailableInfo() { + GLDrawableFactory f = GLDrawableFactory.getDesktopFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + f = GLDrawableFactory.getEGLFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + } + + @Test + public void testGL2OnScreenDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OnScreenDblBufStencil() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setStencilBits(1); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OnScreenDblBufMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OnScreenDblBufStencilMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setStencilBits(1); + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenAutoDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBODblBufStencil() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setStencilBits(1); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBODblBufMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBODblBufStencilMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setStencilBits(1); + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbuffer() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-wait")) { + waitForKey = true; + } + } + if(waitForKey) { + UITestCase.waitForKey("Start"); + } + org.junit.runner.JUnitCore.main(TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.java new file mode 100644 index 000000000..9332b0f2e --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.java @@ -0,0 +1,462 @@ +/** + * 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.jogl.acore; + +import java.io.IOException; + +import javax.media.nativewindow.CapabilitiesImmutable; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import jogamp.opengl.GLGraphicsConfigurationUtil; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Tests using a NEWT {@link GLWindow} {@link GLAutoDrawable auto drawable} for on- and offscreen cases. + * <p> + * The NEWT {@link GLAutoDrawable} is being used to run the {@link GLEventListener}. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT extends UITestCase { + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + static interface MyGLEventListener extends GLEventListener { + void setMakeSnapshot(); + } + + static GLCapabilities getCaps(String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return new GLCapabilities(GLProfile.get(profile)); + } + + void doTest(GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException { + System.out.println("Requested GL Caps: "+reqGLCaps); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); + final GLCapabilitiesImmutable expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, factory, null); + System.out.println("Expected GL Caps: "+expGLCaps); + // + // Create native windowing resources .. X11/Win/OSX + // + final GLWindow glad = GLWindow.create(reqGLCaps); + Assert.assertNotNull(glad); + glad.setSize(widthStep*szStep, heightStep*szStep); + glad.setVisible(true); + Assert.assertTrue(AWTRobotUtil.waitForVisible(glad, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(glad, true)); + System.out.println("Window: "+glad.getClass().getName()); + + // Check caps of NativeWindow config w/o GL + final CapabilitiesImmutable chosenCaps = glad.getGraphicsConfiguration().getChosenCapabilities(); + System.out.println("Window Caps Pre_GL: "+chosenCaps); + Assert.assertNotNull(chosenCaps); + Assert.assertTrue(chosenCaps.getGreenBits()>5); + Assert.assertTrue(chosenCaps.getBlueBits()>5); + Assert.assertTrue(chosenCaps.getRedBits()>5); + + // + // Create native OpenGL resources .. XGL/WGL/CGL .. + // equivalent to GLAutoDrawable methods: setVisible(true) + // + { + final GLDrawable actualDrawable = glad.getDelegatedDrawable(); + Assert.assertNotNull(actualDrawable); + System.out.println("Drawable Pre-GL(0): "+actualDrawable.getClass().getName()+", "+actualDrawable.getNativeSurface().getClass().getName()); + } + + System.out.println("Window Caps PostGL : "+glad.getGraphicsConfiguration().getChosenCapabilities()); + System.out.println("Drawable Post-GL(1): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + + // Check caps of GLDrawable after realization + final GLCapabilitiesImmutable chosenGLCaps = glad.getChosenGLCapabilities(); + System.out.println("Chosen GL Caps(1): "+chosenGLCaps); + Assert.assertNotNull(chosenGLCaps); + Assert.assertTrue(chosenGLCaps.getGreenBits()>5); + Assert.assertTrue(chosenGLCaps.getBlueBits()>5); + Assert.assertTrue(chosenGLCaps.getRedBits()>5); + Assert.assertTrue(chosenGLCaps.getDepthBits()>4); + Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps.isOnscreen()); + Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO()); + Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer()); + Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap()); + /** Single/Double buffer cannot be checked since result may vary .. + if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) { + // dbl buffer may be disabled w/ offscreen pbuffer and bitmap + Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered()); + } */ + + glad.display(); + { + GLContext context = glad.getContext(); + System.out.println("Chosen GL CTX (2): "+context.getGLVersion()); + Assert.assertNotNull(context); + Assert.assertTrue(context.isCreated()); + } + + System.out.println("Chosen GL Caps(2): "+glad.getChosenGLCapabilities()); + System.out.println("Drawable Post-GL(2): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + + glad.addGLEventListener(demo); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + glad.addGLEventListener(snapshotGLEventListener); + + glad.display(); // initial resize/display + + // 1 - szStep = 2 + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 2, 3 (resize + display) + szStep = 1; + glad.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 4, 5 (resize + display) + szStep = 4; + glad.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + Thread.sleep(50); + + glad.destroy(); + System.out.println("Fin: "+glad); + } + + @Test + public void testAvailableInfo() { + GLDrawableFactory f = GLDrawableFactory.getDesktopFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + f = GLDrawableFactory.getEGLFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + } + + @Test + public void testGL2OnScreenSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OnScreenDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OnScreenDblBufStencil() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setStencilBits(1); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OnScreenDblBufMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OnScreenDblBufStencilMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setStencilBits(1); + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenAutoDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBOSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBODblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBODblBufStencil() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setStencilBits(1); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBODblBufMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBODblBufStencilMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setStencilBits(1); + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbufferDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbufferSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenBitmapSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testES2OnScreenSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OnScreenDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OnScreenDblBufStencil() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setStencilBits(1); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OnScreenDblBufMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OnScreenDblBufStencilMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setStencilBits(1); + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenAutoDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBOSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBODblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBODblBufStencil() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setStencilBits(1); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBODblBufMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBODblBufStencilMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setStencilBits(1); + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenPbufferDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenPbufferSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + /** Not implemented ! + @Test + public void testES2OffScreenBitmapDblBuf() throws InterruptedException { + if(!checkProfile(GLProfile.GLES2)) { + return; + } + final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + doTest(reqGLCaps, new GearsES2(1)); + } */ + + public static void main(String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.java new file mode 100644 index 000000000..ae5dc614b --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.java @@ -0,0 +1,351 @@ +/** + * 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.jogl.acore; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Frame; +import java.io.IOException; + +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.CapabilitiesImmutable; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import jogamp.nativewindow.jawt.JAWTUtil; +import jogamp.opengl.GLGraphicsConfigurationUtil; + +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.awt.NewtCanvasAWT; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Tests using a NEWT {@link GLWindow} {@link GLAutoDrawable auto drawable} for on- and offscreen cases. + * <p> + * The NEWT {@link GLAutoDrawable} is being used to run the {@link GLEventListener}. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT extends UITestCase { + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + static GLCapabilities getCaps(String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return new GLCapabilities(GLProfile.get(profile)); + } + + static void setComponentSize(final Frame frame, final Component comp, final int width, final int height) { + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + final Dimension new_sz = new Dimension(width, height); + comp.setMinimumSize(new_sz); + comp.setPreferredSize(new_sz); + comp.setSize(new_sz); + frame.pack(); + frame.validate(); + } } ); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + } + + static interface MyGLEventListener extends GLEventListener { + void setMakeSnapshot(); + } + + void doTest(boolean offscreenLayer, GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException { + if(!offscreenLayer && JAWTUtil.isOffscreenLayerRequired()) { + System.err.println("onscreen layer n/a"); + return; + } + if(offscreenLayer && !JAWTUtil.isOffscreenLayerSupported()) { + System.err.println("offscreen layer n/a"); + return; + } + System.out.println("Requested GL Caps: "+reqGLCaps); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); + final AbstractGraphicsDevice device = factory.getDefaultDevice(); + final GLCapabilitiesImmutable expGLCaps = offscreenLayer ? + GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(reqGLCaps, factory, device) : + GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, factory, device); + System.out.println("Expected GL Caps: "+expGLCaps); + + final GLWindow glad = GLWindow.create(reqGLCaps); + Assert.assertNotNull(glad); + + + final NewtCanvasAWT nca = new NewtCanvasAWT(glad); + Assert.assertNotNull(nca); + Dimension size0 = new Dimension(widthStep*szStep, heightStep*szStep); + nca.setShallUseOffscreenLayer(offscreenLayer); // trigger offscreen layer - if supported + nca.setPreferredSize(size0); + nca.setMinimumSize(size0); + nca.setSize(size0); + + final Frame frame = new Frame(getSimpleTestName(".")); + Assert.assertNotNull(frame); + frame.add(nca); + + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.pack(); + frame.setVisible(true); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + + Assert.assertTrue(AWTRobotUtil.waitForVisible(glad, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(glad, true)); + System.out.println("Window: "+glad.getClass().getName()); + + // Check caps of NativeWindow config w/o GL + final CapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities(); + System.out.println("Window Caps Pre_GL: "+chosenCaps); + Assert.assertNotNull(chosenCaps); + Assert.assertTrue(chosenCaps.getGreenBits()>5); + Assert.assertTrue(chosenCaps.getBlueBits()>5); + Assert.assertTrue(chosenCaps.getRedBits()>5); + + glad.display(); // force native context creation + + // + // Create native OpenGL resources .. XGL/WGL/CGL .. + // equivalent to GLAutoDrawable methods: setVisible(true) + // + { + final GLDrawable actualDrawable = glad.getDelegatedDrawable(); + Assert.assertNotNull(actualDrawable); + System.out.println("Drawable Pre-GL(0): "+actualDrawable.getClass().getName()+", "+actualDrawable.getNativeSurface().getClass().getName()); + } + + System.out.println("Window Caps PostGL : "+glad.getChosenGLCapabilities()); + System.out.println("Drawable Post-GL(1): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + + // Check caps of GLDrawable after realization + final GLCapabilitiesImmutable chosenGLCaps = glad.getChosenGLCapabilities(); + System.out.println("Chosen GL Caps(1): "+chosenGLCaps); + Assert.assertNotNull(chosenGLCaps); + Assert.assertTrue(chosenGLCaps.getGreenBits()>5); + Assert.assertTrue(chosenGLCaps.getBlueBits()>5); + Assert.assertTrue(chosenGLCaps.getRedBits()>5); + Assert.assertTrue(chosenGLCaps.getDepthBits()>4); + Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps.isOnscreen()); + Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO()); + Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer()); + Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap()); + /** Single/Double buffer cannot be checked since result may vary .. + if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) { + // dbl buffer may be disabled w/ offscreen pbuffer and bitmap + Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered()); + } */ + + { + GLContext context = glad.getContext(); + System.out.println("Chosen GL CTX (2): "+context.getGLVersion()); + Assert.assertNotNull(context); + Assert.assertTrue(context.isCreated()); + } + + System.out.println("Chosen GL Caps(2): "+glad.getChosenGLCapabilities()); + System.out.println("Drawable Post-GL(2): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + + glad.addGLEventListener(demo); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + glad.addGLEventListener(snapshotGLEventListener); + + glad.display(); // initial resize/display + + // 1 - szStep = 2 + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 2, 3 (resize + display) + szStep = 1; + setComponentSize(frame, nca, widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + glad.display(); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 4, 5 (resize + display) + szStep = 4; + setComponentSize(frame, nca, widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + glad.display(); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + Thread.sleep(50); + + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + frame.remove(nca); + frame.dispose(); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + glad.destroy(); + System.out.println("Fin: "+nca); + System.out.println("Fin: "+glad); + } + + @Test + public void testAvailableInfo() { + GLDrawableFactory f = GLDrawableFactory.getDesktopFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + f = GLDrawableFactory.getEGLFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + } + + @Test + public void testGL2OnScreenDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + doTest(false, reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OnScreenDblBufStencil() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setStencilBits(1); + doTest(false, reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OnScreenDblBufMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(false, reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OnScreenDblBufStencilMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setStencilBits(1); + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(false, reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenLayerAutoDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + doTest(true, reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBODblBufStencil() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setFBO(true); + reqGLCaps.setOnscreen(true); // get native NEWT Window, not OffscreenWindow + reqGLCaps.setStencilBits(1); + doTest(true, reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBODblBufMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setFBO(true); + reqGLCaps.setOnscreen(true); // get native NEWT Window, not OffscreenWindow + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(true, reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBODblBufStencilMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setFBO(true); + reqGLCaps.setOnscreen(true); // get native NEWT Window, not OffscreenWindow + reqGLCaps.setStencilBits(1); + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(true, reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbuffer() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setPBuffer(true); + reqGLCaps.setOnscreen(true); // get native NEWT Window, not OffscreenWindow + doTest(true, reqGLCaps, new GearsES2(1)); + } + + public static void main(String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextSurfaceLockNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextSurfaceLockNEWT.java index 78988c0e5..c64bb3854 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextSurfaceLockNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextSurfaceLockNEWT.java @@ -33,15 +33,18 @@ import java.io.IOException; import javax.media.nativewindow.NativeSurface; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; -import org.junit.Assert; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.util.UITestCase; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestGLContextSurfaceLockNEWT extends UITestCase { static final int demoSize = 64; @@ -69,7 +72,7 @@ public class TestGLContextSurfaceLockNEWT extends UITestCase { } public void run() { - System.err.println("Animatr "+id+": PRE: "+Thread.currentThread().getName()); + System.err.println("Animatr "+id+", count "+frameCount+": PRE: "+Thread.currentThread().getName()); for(int c=0; c<frameCount; c++) { glad.display(); @@ -99,10 +102,10 @@ public class TestGLContextSurfaceLockNEWT extends UITestCase { } public void run() { - System.err.println("Resizer "+id+": PRE: "+Thread.currentThread().getName()); + System.err.println("Resizer "+id+", count "+actionCount+": PRE: "+Thread.currentThread().getName()); for(int c=0; c<actionCount; c++) { - win.runOnEDTIfAvail(false, new Runnable() { + win.runOnEDTIfAvail(true, new Runnable() { public void run() { // Normal resize, may trigger immediate display within lock win.setSize(win.getWidth()+1, win.getHeight()+1); @@ -148,41 +151,80 @@ public class TestGLContextSurfaceLockNEWT extends UITestCase { return true; } + protected class MyEventCounter implements GLEventListener { + volatile int reshapeCount = 0; + volatile int displayCount = 0; + + @Override + public void init(GLAutoDrawable drawable) { + } + + @Override + public void dispose(GLAutoDrawable drawable) { + System.err.println("*** reshapes: "+reshapeCount+", displays "+displayCount); + } + + @Override + public void display(GLAutoDrawable drawable) { + displayCount++; + } + + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + reshapeCount++; + } + + public void reset() { + reshapeCount = 0; + displayCount = 0; + } + } + protected void runJOGLTasks(int animThreadCount, int frameCount, int reszThreadCount, int resizeCount) throws InterruptedException { - GLWindow glWindow = GLWindow.create(new GLCapabilities(GLProfile.getDefault())); - Assert.assertNotNull(glWindow); + final GLWindow glWindow = GLWindow.create(new GLCapabilities(GLProfile.getDefault())); + final MyEventCounter myEventCounter = new MyEventCounter(); glWindow.addGLEventListener(new GearsES2(0)); + glWindow.addGLEventListener(myEventCounter); glWindow.setSize(demoSize, demoSize); glWindow.setVisible(true); final String currentThreadName = Thread.currentThread().getName(); final Object sync = new Object(); - final MyRunnable[] tasks = new MyRunnable[animThreadCount+reszThreadCount]; - final Thread[] threads = new Thread[animThreadCount+reszThreadCount]; - int i=0; + final MyRunnable[] animTasks = new MyRunnable[animThreadCount]; + final MyRunnable[] resizeTasks = new MyRunnable[animThreadCount]; + final Thread[] animThreads = new Thread[reszThreadCount]; + final Thread[] resizeThreads = new Thread[reszThreadCount]; System.err.println("animThreadCount "+animThreadCount+", frameCount "+frameCount); System.err.println("reszThreadCount "+reszThreadCount+", resizeCount "+resizeCount); - System.err.println("tasks "+tasks.length+", threads "+threads.length); + System.err.println("tasks "+(animTasks.length+resizeTasks.length)+", threads "+(animThreads.length+resizeThreads.length)); - for(; i<animThreadCount; i++) { + for(int i=0; i<animThreadCount; i++) { System.err.println("create anim task/thread "+i); - tasks[i] = new RudeAnimator(glWindow, frameCount, sync, i); - threads[i] = new Thread(tasks[i], currentThreadName+"-anim"+i); + animTasks[i] = new RudeAnimator(glWindow, frameCount, sync, i); + animThreads[i] = new Thread(animTasks[i], currentThreadName+"-anim"+i); } - for(; i<animThreadCount+reszThreadCount; i++) { + for(int i=0; i<reszThreadCount; i++) { System.err.println("create resz task/thread "+i); - tasks[i] = new RudeResizer(glWindow, resizeCount, sync, i); - threads[i] = new Thread(tasks[i], currentThreadName+"-resz"+i); + resizeTasks[i] = new RudeResizer(glWindow, resizeCount, sync, i); + resizeThreads[i] = new Thread(resizeTasks[i], currentThreadName+"-resz"+i); } - for(i=0; i<animThreadCount+reszThreadCount; i++) { - System.err.println("start thread "+i); - threads[i].start(); + myEventCounter.reset(); + + int j=0, k=0; + for(int i=0; i<reszThreadCount+animThreadCount; i++) { + if(0==i%2) { + System.err.println("start resize thread "+j); + resizeThreads[j++].start(); + } else { + System.err.println("start anim thread "+k); + animThreads[k++].start(); + } } synchronized (sync) { - while(!done(tasks)) { + while(!done(resizeTasks) || !done(animTasks)) { try { sync.wait(); } catch (InterruptedException e) { @@ -190,8 +232,8 @@ public class TestGLContextSurfaceLockNEWT extends UITestCase { } } } - i=0; - while(i<30 && !isDead(threads)) { + int i=0; + while(i<30 && !isDead(animThreads) && !isDead(resizeThreads)) { Thread.sleep(100); i++; } @@ -200,8 +242,13 @@ public class TestGLContextSurfaceLockNEWT extends UITestCase { } @Test - public void test01_1AThreads_600Frames() throws InterruptedException { - runJOGLTasks(1, 600, 1, 600); + public void test01_1A1RThreads_100Resizes() throws InterruptedException { + runJOGLTasks(1, 200, 1, 100); + } + + @Test + public void test01_3A3RThreads_50Resizes() throws InterruptedException { + runJOGLTasks(3, 100, 3, 50); } public static void main(String args[]) throws IOException { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDebug00NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDebug00NEWT.java index 62e74466f..f0950fba8 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDebug00NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDebug00NEWT.java @@ -42,7 +42,8 @@ import javax.media.opengl.GLProfile; import org.junit.Assert; import org.junit.Test; -import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import com.jogamp.newt.Display; import com.jogamp.newt.NewtFactory; @@ -50,6 +51,7 @@ import com.jogamp.newt.Screen; import com.jogamp.newt.Window; import com.jogamp.opengl.test.junit.util.UITestCase; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestGLDebug00NEWT extends UITestCase { static String dbgTstMsg0 = "Hello World"; @@ -144,9 +146,9 @@ public class TestGLDebug00NEWT extends UITestCase { WindowContext winctx = createWindow(glp, true); MyGLDebugListener myGLDebugListener = new MyGLDebugListener( - GL2GL3.GL_DEBUG_SOURCE_API_ARB, - GL2GL3.GL_DEBUG_TYPE_ERROR_ARB, - GL2GL3.GL_DEBUG_SEVERITY_HIGH_ARB); + GL2GL3.GL_DEBUG_SOURCE_API, + GL2GL3.GL_DEBUG_TYPE_ERROR, + GL2GL3.GL_DEBUG_SEVERITY_HIGH); winctx.context.addGLDebugListener(myGLDebugListener); GL gl = winctx.context.getGL(); @@ -171,10 +173,10 @@ public class TestGLDebug00NEWT extends UITestCase { Assert.assertEquals((null == glDebugExt) ? false : true, winctx.context.isGLDebugMessageEnabled()); if( winctx.context.isGLDebugMessageEnabled() ) { - winctx.context.glDebugMessageInsert(GL2GL3.GL_DEBUG_SOURCE_APPLICATION_ARB, - GL2GL3.GL_DEBUG_TYPE_OTHER_ARB, + winctx.context.glDebugMessageInsert(GL2GL3.GL_DEBUG_SOURCE_APPLICATION, + GL2GL3.GL_DEBUG_TYPE_OTHER, dbgTstId0, - GL2GL3.GL_DEBUG_SEVERITY_MEDIUM_ARB, dbgTstMsg0); + GL2GL3.GL_DEBUG_SEVERITY_MEDIUM, dbgTstMsg0); Assert.assertEquals(true, myGLDebugListener.received()); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDebug01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDebug01NEWT.java index f9b566c25..76bf33044 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDebug01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDebug01NEWT.java @@ -41,10 +41,13 @@ import javax.media.opengl.GLRunnable; import org.junit.Assert; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.util.UITestCase; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestGLDebug01NEWT extends UITestCase { static String dbgTstMsg0 = "Hello World"; @@ -91,10 +94,10 @@ public class TestGLDebug01NEWT extends UITestCase { if(ctx.isGLDebugMessageEnabled() && null != dbgTstMsg && 0 <= dbgTstId) { window.invoke(true, new GLRunnable() { public boolean run(GLAutoDrawable drawable) { - drawable.getContext().glDebugMessageInsert(GL2GL3.GL_DEBUG_SOURCE_APPLICATION_ARB, - GL2GL3.GL_DEBUG_TYPE_OTHER_ARB, + drawable.getContext().glDebugMessageInsert(GL2GL3.GL_DEBUG_SOURCE_APPLICATION, + GL2GL3.GL_DEBUG_TYPE_OTHER, dbgTstId, - GL2GL3.GL_DEBUG_SEVERITY_MEDIUM_ARB, dbgTstMsg); + GL2GL3.GL_DEBUG_SEVERITY_MEDIUM, dbgTstMsg); return true; } }); @@ -121,9 +124,9 @@ public class TestGLDebug01NEWT extends UITestCase { GLWindow window = createWindow(glp, true); MyGLDebugListener myGLDebugListener = new MyGLDebugListener( - GL2GL3.GL_DEBUG_SOURCE_API_ARB, - GL2GL3.GL_DEBUG_TYPE_ERROR_ARB, - GL2GL3.GL_DEBUG_SEVERITY_HIGH_ARB); + GL2GL3.GL_DEBUG_SOURCE_API, + GL2GL3.GL_DEBUG_TYPE_ERROR, + GL2GL3.GL_DEBUG_SEVERITY_HIGH); window.getContext().addGLDebugListener(myGLDebugListener); window.invoke(true, new GLRunnable() { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLExtensionQueryOffscreen.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLExtensionQueryOffscreen.java index e4245ef11..4bc8e7ee3 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLExtensionQueryOffscreen.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLExtensionQueryOffscreen.java @@ -3,14 +3,14 @@ * * 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 @@ -20,41 +20,41 @@ * 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.jogl.acore; import java.util.Collections; import java.util.SortedSet; import java.util.TreeSet; -import javax.media.nativewindow.AbstractGraphicsDevice; -import javax.media.opengl.DefaultGLCapabilitiesChooser; import javax.media.opengl.GL; -import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLCapabilitiesChooser; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLOffscreenAutoDrawable; import javax.media.opengl.GLProfile; import jogamp.opengl.GLDrawableFactoryImpl; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestGLExtensionQueryOffscreen { - + public static void main(String[] args) { TestGLExtensionQueryOffscreen instance = new TestGLExtensionQueryOffscreen(); instance.testJogl2ExtensionCheck1(); instance.testJogl2ExtensionCheck2(); } - /** + /** * @deprecated This test uses a non public API in jogamp.opengl.* and hence is not recommended */ @Test @@ -74,16 +74,14 @@ public class TestGLExtensionQueryOffscreen { System.out.println("SharedContext: "+sharedContext); System.out.println("SharedContext: "+setExtensions); } - + @Test public void testJogl2ExtensionCheck2() { - GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); - GLDrawableFactory factory = GLDrawableFactory.getDesktopFactory(); - GLCapabilitiesChooser glCapsChooser = new DefaultGLCapabilitiesChooser(); - AbstractGraphicsDevice agd = factory.getDefaultDevice(); - - GLAutoDrawable drawable = factory.createGLPbuffer(agd, caps, glCapsChooser, 256, 256, null); - GLContext context = drawable.getContext(); + final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); + final GLOffscreenAutoDrawable drawable = factory.createOffscreenAutoDrawable(null, caps, null, 256, 256); + drawable.display(); // trigger context creation .. + final GLContext context = drawable.getContext(); context.makeCurrent(); String extensions; try { @@ -94,8 +92,8 @@ public class TestGLExtensionQueryOffscreen { String[] tabExtensions = extensions.split(" "); SortedSet<String> setExtensions = new TreeSet<String>(); Collections.addAll(setExtensions, tabExtensions); - System.out.println("DefaulContext: "+context); - System.out.println("DefaulContext: "+setExtensions); + System.out.println("DefaultContext: "+context); + System.out.println("DefaultContext: "+setExtensions); } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLMesaBug651NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLMesaBug651NEWT.java new file mode 100644 index 000000000..5efe21e16 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLMesaBug651NEWT.java @@ -0,0 +1,225 @@ +/** + * Copyright 2012 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.jogl.acore; + +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.GLExtensions; +import com.jogamp.opengl.test.junit.util.UITestCase; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GL2GL3; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.AfterClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +/** + * Some GL state values are broken w/ Mesa 9.0 w/ multiple different context. + * <p> + * This bug lies within Mesa3D (any renderer) and is fixed in + * commit 8dc79ae7d73cf6711c2182ff9a5d37ef6c989d23. + * </p> + * <p> + * Mesa3D Version 9.0 still exposes this bug, + * where 9.0.1 has it fixed w/ above commit. + * </p> + * <https://jogamp.org/bugzilla/show_bug.cgi?id=651> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLMesaBug651NEWT extends UITestCase { + static int width, height; + + @BeforeClass + public static void initClass() { + width = 512; + height = 512; + } + + @AfterClass + public static void releaseClass() { + } + + class UnitTester implements GLEventListener { + @Override + public void init(GLAutoDrawable drawable) { + final GL gl = drawable.getGL(); + System.err.println("GL UnitTester"); + System.err.println(" GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR)); + System.err.println(" GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER)); + System.err.println(" GL_VERSION: " + gl.glGetString(GL.GL_VERSION)); + System.err.println(" GL GLSL: "+gl.hasGLSL()+", has-compiler-func: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none")+", "+gl.getContext().getGLSLVersionNumber()); + System.err.println(" GL FBO: basic "+ gl.hasBasicFBOSupport()+", full "+gl.hasFullFBOSupport()); + System.err.println(" GL Profile: "+gl.getGLProfile()); + System.err.println(" GL Renderer Quirks:" + gl.getContext().getRendererQuirks().toString()); + System.err.println(" GL:" + gl + ", " + gl.getContext().getGLVersion()); + + final int _glerr = gl.glGetError(); // clear pre-error + System.err.println(" - pre GL-Error 0x"+Integer.toHexString(_glerr)); + + final int[] val = new int[1]; + final int[] glerr = new int[] { GL.GL_NO_ERROR, GL.GL_NO_ERROR, GL.GL_NO_ERROR, GL.GL_NO_ERROR, GL.GL_NO_ERROR }; + int i=0; + + val[0]=0; + gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, val, 0); + System.out.println(" - GL_MAX_TEXTURE_SIZE: " + val[0]); + glerr[i] = gl.glGetError(); // clear pre-error + System.err.println(" - GL-Error 0x"+Integer.toHexString(glerr[i])); + i++; + + val[0]=0; + gl.glGetIntegerv(GL2ES2.GL_ACTIVE_TEXTURE, val, 0); + System.out.println(" - GL_ACTIVE_TEXTURE: " + val[0]); + glerr[i] = gl.glGetError(); // clear pre-error + System.err.println(" - GL-Error 0x"+Integer.toHexString(glerr[i])); + i++; + + if(gl.isGL2ES2()) { + val[0]=0; + gl.glGetIntegerv(GL2ES2.GL_MAX_TEXTURE_IMAGE_UNITS, val, 0); + System.out.println(" - GL_MAX_TEXTURE_IMAGE_UNITS: " + val[0]); + glerr[i] = gl.glGetError(); // clear pre-error + System.err.println(" - GL-Error 0x"+Integer.toHexString(glerr[i])); + } + i++; + + if( gl.hasFullFBOSupport() || gl.isExtensionAvailable(GLExtensions.NV_fbo_color_attachments) ) { + val[0]=0; + gl.glGetIntegerv(GL2ES2.GL_MAX_COLOR_ATTACHMENTS, val, 0); + System.out.println(" - GL_MAX_COLOR_ATTACHMENTS: " + val[0]); + glerr[i] = gl.glGetError(); // clear pre-error + System.err.println(" - GL-Error 0x"+Integer.toHexString(glerr[i])); + } + i++; + + if( gl.hasFullFBOSupport() ) { + val[0]=0; + gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, val, 0); + System.out.println(" - GL_MAX_SAMPLES: " + val[0]); + glerr[i] = gl.glGetError(); // clear pre-error + System.err.println(" - GL-Error 0x"+Integer.toHexString(glerr[i])); + } + i++; + + boolean ok = true; + String res=""; + for(int j=0; j<i; j++) { + switch(j) { + case 0: res += "GL_MAX_TEXTURE_SIZE"; break; + case 1: res += "GL_ACTIVE_TEXTURE"; break; + case 2: res += "GL_MAX_TEXTURE_IMAGE_UNITS"; break; + case 3: res += "GL_MAX_COLOR_ATTACHMENTS"; break; + case 4: res += "GL_MAX_SAMPLES"; break; + } + if(GL.GL_NO_ERROR == glerr[j]) { + res += " OK, "; + } else { + res += " ERROR, "; + ok = false; + } + } + Assert.assertTrue(res, ok); + } + + @Override + public void dispose(GLAutoDrawable drawable) { + } + + @Override + public void display(GLAutoDrawable drawable) { + } + + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + } + } + + protected void runTestGL(GLCapabilities caps) throws InterruptedException { + GLWindow glWindow = GLWindow.create(caps); + Assert.assertNotNull(glWindow); + glWindow.setTitle(getSimpleTestName(".")); + + UnitTester demo = new UnitTester(); + + glWindow.addGLEventListener(demo); + + glWindow.setSize(width, height); + glWindow.setVisible(true); + glWindow.display(); + + glWindow.destroy(); + } + + @Test + public void test01_ES1() throws InterruptedException { + if(!GLProfile.isAvailable(GLProfile.GLES1)) { System.err.println("GLES1 n/a"); return; } + GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GLES1)); + runTestGL(caps); + } + + @Test + public void test02__ES2() throws InterruptedException { + if(!GLProfile.isAvailable(GLProfile.GLES2)) { System.err.println("GLES2 n/a"); return; } + GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); + runTestGL(caps); + } + + @Test + public void test03_GL2() throws InterruptedException { + if(!GLProfile.isAvailable(GLProfile.GL2)) { System.err.println("GL2 n/a"); return; } + GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL2)); + runTestGL(caps); + } + + @Test + public void test04_GL3() throws InterruptedException { + if(!GLProfile.isAvailable(GLProfile.GL3)) { System.err.println("GL3 n/a"); return; } + GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL3)); + runTestGL(caps); + } + + @Test + public void test05_GL4() throws InterruptedException { + if(!GLProfile.isAvailable(GLProfile.GL4)) { System.err.println("GL4 n/a"); return; } + GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL4)); + runTestGL(caps); + } + + public static void main(String args[]) { + org.junit.runner.JUnitCore.main(TestGLMesaBug651NEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLMesaBug658NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLMesaBug658NEWT.java new file mode 100644 index 000000000..cb225b96f --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLMesaBug658NEWT.java @@ -0,0 +1,203 @@ +package com.jogamp.opengl.test.junit.jogl.acore; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2GL3; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * The 3.1 compatibility context on Mesa >= 9.0 seems to be broken. + * <p> + * This bug lies within Mesa3D (any renderer) and is fixed in + * commit ??? (not yet). + * </p> + * <p> + * Mesa3D Version 9.0 still exposes this bug, + * where 9.?.? has it fixed w/ above commit. + * </p> + * <https://jogamp.org/bugzilla/show_bug.cgi?id=658> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLMesaBug658NEWT extends UITestCase { + + @Test + public void test00ShowAvailProfiles() { + System.err.println(JoglVersion.getDefaultOpenGLInfo(null, null, false).toString()); + } + + @Test + public void test10GL2PolygonModeFailure() { + testGLNPolygonModeFailureImpl(GLProfile.GL2); + } + + @Test + public void test11GL3bcPolygonModeFailure() { + testGLNPolygonModeFailureImpl(GLProfile.GL3bc); + } + + @Test + public void test12GL3PolygonModeFailure() { + testGLNPolygonModeFailureImpl(GLProfile.GL3); + } + + private void testGLNPolygonModeFailureImpl(String profile) { + if(!GLProfile.isAvailable(profile)) { System.err.println(profile+" n/a"); return; } + + final GLProfile pro = GLProfile.get(profile); + final GLCapabilities caps = new GLCapabilities(pro); + final GLWindow window = GLWindow.create(caps); + + window.setSize(640, 480); + window.addGLEventListener(new GLEventListener() { + public void reshape( + final GLAutoDrawable drawable, + final int x, + final int y, + final int width, + final int height) + { + // Nothing. + } + + public void init( + final GLAutoDrawable drawable) + { + final GLContext context = drawable.getContext(); + System.err.println("CTX: "+context.getGLVersion()); + + final GL2GL3 gl = drawable.getGL().getGL2GL3(); + System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR)); + System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER)); + System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION)); + System.err.println("GL Renderer Quirks:" + gl.getContext().getRendererQuirks().toString()); + + if( gl.isGL2() || gl.isGLES2() ) { // compatibility profile || ES2 + gl.glPolygonMode(GL.GL_FRONT, GL2GL3.GL_FILL); + } else { + gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL2GL3.GL_FILL); + } + + final int e = gl.glGetError(); + Assert.assertTrue(e == GL.GL_NO_ERROR); // // FIXME On Mesa 9.0.1 w/ GL 3.1 -> GL.GL_INVALID_OPERATION ? + } + + public void dispose( + final GLAutoDrawable drawable) + { + // Nothing. + } + + public void display( + final GLAutoDrawable drawable) + { + // Nothing. + } + }); + + try { + window.setVisible(true); + } finally { + window.destroy(); + } + } + + @Test + public void test20GL2BindArrayAttributeFails() { + testGLNBindArrayAttributeFailsImpl(GLProfile.GL2); + } + + @Test + public void test21GL3bcBindArrayAttributeFails() { + testGLNBindArrayAttributeFailsImpl(GLProfile.GL3bc); + } + + @Test + public void test22GL3BindArrayAttributeFails() { + testGLNBindArrayAttributeFailsImpl(GLProfile.GL3); + } + + private void testGLNBindArrayAttributeFailsImpl(String profile) { + if(!GLProfile.isAvailable(profile)) { System.err.println(profile+ " n/a"); return; } + + final GLProfile pro = GLProfile.get(profile); + final GLCapabilities caps = new GLCapabilities(pro); + final GLWindow window = GLWindow.create(caps); + + window.setSize(640, 480); + window.addGLEventListener(new GLEventListener() { + public void reshape( + final GLAutoDrawable drawable, + final int x, + final int y, + final int width, + final int height) + { + // Nothing. + } + + public void init( + final GLAutoDrawable drawable) + { + final GLContext context = drawable.getContext(); + System.err.println("CTX: "+context.getGLVersion()); + + final GL2GL3 gl = drawable.getGL().getGL2GL3(); + System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR)); + System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER)); + System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION)); + System.err.println("GL Renderer Quirks:" + gl.getContext().getRendererQuirks().toString()); + + final int[] name = new int[] { 0 }; + gl.glGenBuffers(1, name, 0); + Assert.assertTrue(gl.glGetError() == GL.GL_NO_ERROR); + + gl.glBindBuffer(GL.GL_ARRAY_BUFFER, name[0]); + Assert.assertTrue(gl.glGetError() == 0); + gl.glBufferData(GL.GL_ARRAY_BUFFER, 4 * 32, null, GL.GL_STATIC_DRAW); + Assert.assertTrue(gl.glGetError() == 0); + + Assert.assertTrue(gl.getBoundBuffer(GL.GL_ARRAY_BUFFER) == name[0]); + gl.glEnableVertexAttribArray(1); + Assert.assertTrue(gl.glGetError() == GL.GL_NO_ERROR); + gl.glVertexAttribPointer(1, 4, GL.GL_FLOAT, false, 0, 0L); + Assert.assertTrue(gl.glGetError() == GL.GL_NO_ERROR); // FIXME On Mesa 9.0.1 w/ GL 3.1 -> GL.GL_INVALID_OPERATION ? + } + + public void dispose( + final GLAutoDrawable drawable) + { + // Nothing. + } + + public void display( + final GLAutoDrawable drawable) + { + // Nothing. + } + }); + + try { + window.setVisible(true); + } finally { + window.destroy(); + } + } + + public static void main(String args[]) { + org.junit.runner.JUnitCore.main(TestGLMesaBug658NEWT.class.getName()); + } + +} + diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLPointsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLPointsNEWT.java new file mode 100644 index 000000000..7d3a7b896 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLPointsNEWT.java @@ -0,0 +1,159 @@ +/** + * Copyright 2011 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.jogl.acore; + +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.util.UITestCase; + +import com.jogamp.opengl.test.junit.jogl.demos.PointsDemo; +import com.jogamp.opengl.test.junit.jogl.demos.es1.PointsDemoES1; +import com.jogamp.opengl.test.junit.jogl.demos.es2.PointsDemoES2; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.AfterClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLPointsNEWT extends UITestCase { + static int width, height; + + @BeforeClass + public static void initClass() { + width = 512; + height = 512; + } + + @AfterClass + public static void releaseClass() { + } + + protected void runTestGL0(GLCapabilities caps, PointsDemo demo) throws InterruptedException { + GLWindow glWindow = GLWindow.create(caps); + Assert.assertNotNull(glWindow); + glWindow.setTitle(getSimpleTestName(".")); + + glWindow.addGLEventListener(demo); + final SnapshotGLEventListener snap = new SnapshotGLEventListener(); + snap.setPostSNDetail(demo.getClass().getSimpleName()); + glWindow.addGLEventListener(snap); + + glWindow.setSize(width, height); + glWindow.setVisible(true); + + demo.setSmoothPoints(false); + snap.setMakeSnapshot(); + snap.setPostSNDetail("flat"); + glWindow.display(); + + demo.setSmoothPoints(true); + snap.setMakeSnapshot(); + snap.setPostSNDetail("smooth"); + glWindow.display(); + + demo.setPointParams(2f, 40f, 0.01f, 0.0f, 0.01f, 1f); + snap.setMakeSnapshot(); + snap.setPostSNDetail("attn0"); + glWindow.display(); + + glWindow.removeGLEventListener(demo); + + glWindow.destroy(); + } + + protected void runTestGL(GLCapabilities caps, PointsDemo demo, boolean forceFFPEmu) throws InterruptedException { + // final PointsDemoES2 demo01 = new PointsDemoES2(); + runTestGL0(caps, demo); + } + + @Test + public void test01FFP__GL2() throws InterruptedException { + if(!GLProfile.isAvailable(GLProfile.GL2)) { System.err.println("GL2 n/a"); return; } + GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL2)); + runTestGL(caps, new PointsDemoES1(), false); + } + + @Test + public void test02FFP__ES1() throws InterruptedException { + if(!GLProfile.isAvailable(GLProfile.GLES1)) { System.err.println("GLES1 n/a"); return; } + GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GLES1)); + runTestGL(caps, new PointsDemoES1(), false); + } + + @Test + public void test03FFP__ES2() throws InterruptedException { + if(!GLProfile.isAvailable(GLProfile.GLES2)) { System.err.println("GLES2 n/a"); return; } + GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); + PointsDemoES1 demo = new PointsDemoES1(); + demo.setForceFFPEmu(true, false, false, false); + runTestGL(caps, demo, false); + } + + @Test + public void test04FFP__GL2ES2() throws InterruptedException { + if(!GLProfile.isAvailable(GLProfile.GL2ES2)) { System.err.println("GL2ES2 n/a"); return; } + GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL2ES2)); + PointsDemoES1 demo = new PointsDemoES1(); + demo.setForceFFPEmu(true, false, false, false); + runTestGL(caps, demo, false); + } + + @Test + public void test11GLSL_GL2() throws InterruptedException { + if(!GLProfile.isAvailable(GLProfile.GL2)) { System.err.println("GL2 n/a"); return; } + GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL2)); + runTestGL(caps, new PointsDemoES2(), false); + } + + @Test + public void test12GLSL_ES2() throws InterruptedException { + if(!GLProfile.isAvailable(GLProfile.GLES2)) { System.err.println("GLES2 n/a"); return; } + GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); + runTestGL(caps, new PointsDemoES2(), false); // should be FFPEmu implicit + } + + static long duration = 1000; // ms + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + try { + duration = Integer.parseInt(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } + } + org.junit.runner.JUnitCore.main(TestGLPointsNEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile00NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile00NEWT.java new file mode 100644 index 000000000..df182c5d3 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile00NEWT.java @@ -0,0 +1,72 @@ +/** + * Copyright 2012 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.jogl.acore; + +import java.io.IOException; + +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import javax.media.opengl.*; + +import com.jogamp.common.os.Platform; +import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.test.junit.util.UITestCase; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLProfile00NEWT extends UITestCase { + + @Test + public void testInitSingleton() throws InterruptedException { + GLProfile.initSingleton(); + System.err.println("Desktop"); + GLDrawableFactory desktopFactory = GLDrawableFactory.getDesktopFactory(); + if( null != desktopFactory ) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(desktopFactory.getDefaultDevice(), null, false)); + System.err.println(Platform.getNewline()+Platform.getNewline()+Platform.getNewline()); + } else { + System.err.println("\tNULL"); + } + + System.err.println("EGL"); + GLDrawableFactory eglFactory = GLDrawableFactory.getEGLFactory(); + if( null != eglFactory ) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(eglFactory.getDefaultDevice(), null, false)); + } else { + System.err.println("\tNULL"); + } + } + + public static void main(String args[]) throws IOException { + String tstname = TestGLProfile00NEWT.class.getName(); + org.junit.runner.JUnitCore.main(tstname); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile01NEWT.java index 2c89ec7f6..88d643aa6 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile01NEWT.java @@ -3,14 +3,14 @@ * * 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 @@ -20,161 +20,441 @@ * 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.jogl.acore; import java.io.IOException; +import javax.media.opengl.GL; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + import org.junit.Assert; +import org.junit.FixMethodOrder; import org.junit.Test; - -import javax.media.opengl.*; +import org.junit.runners.MethodSorters; import com.jogamp.common.GlueGenVersion; import com.jogamp.common.util.VersionUtil; import com.jogamp.nativewindow.NativeWindowVersion; -import com.jogamp.opengl.test.junit.util.UITestCase; -import com.jogamp.opengl.test.junit.util.DumpGLInfo; +import com.jogamp.newt.NewtVersion; +import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.JoglVersion; -import com.jogamp.newt.opengl.*; -import com.jogamp.newt.*; +import com.jogamp.opengl.test.junit.util.UITestCase; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestGLProfile01NEWT extends UITestCase { @Test - public void testVersion() throws InterruptedException { + public void test00Version() throws InterruptedException { System.err.println(VersionUtil.getPlatformInfo()); System.err.println(GlueGenVersion.getInstance()); System.err.println(NativeWindowVersion.getInstance()); System.err.println(JoglVersion.getInstance()); System.err.println(NewtVersion.getInstance()); - System.err.println(JoglVersion.getDefaultOpenGLInfo(null).toString()); + final GLDrawableFactory deskFactory = GLDrawableFactory.getDesktopFactory(); + if( null != deskFactory ) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(deskFactory.getDefaultDevice(), null, true).toString()); + } + final GLDrawableFactory eglFactory = GLDrawableFactory.getEGLFactory(); + if( null != eglFactory ) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(eglFactory.getDefaultDevice(), null, true).toString()); + } } - @Test - public void testGLProfileDefault() throws InterruptedException { - System.out.println("GLProfile "+GLProfile.glAvailabilityToString()); - System.out.println("GLProfile.getDefaultDevice(): "+GLProfile.getDefaultDevice()); - GLProfile glp = GLProfile.getDefault(); - System.out.println("GLProfile.getDefault(): "+glp); - if(glp.getName().equals(GLProfile.GL4bc)) { + static void validate(GLProfile glp) { + final boolean gles3CompatAvail = GLContext.isGLES3CompatibleAvailable(GLProfile.getDefaultDevice()); + if( glp.getImplName().equals(GLProfile.GL4bc) ) { Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL4bc)); + Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL4)); Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL3bc)); Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2)); + Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2GL3)); + if( gles3CompatAvail ) { + Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL4ES3)); + } else { + Assert.assertFalse(GLProfile.isAvailable(GLProfile.GL4ES3)); + } Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2ES1)); Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2ES2)); - } else if(glp.getName().equals(GLProfile.GL3bc)) { + } else if(glp.getImplName().equals(GLProfile.GL3bc)) { Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL3bc)); + Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL3)); Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2)); + Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2GL3)); Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2ES1)); Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2ES2)); - } else if(glp.getName().equals(GLProfile.GL2)) { + } else if(glp.getImplName().equals(GLProfile.GL2)) { Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2)); + Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2GL3)); Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2ES1)); Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2ES2)); - } else if(glp.getName().equals(GLProfile.GL2ES1)) { + } else if(glp.getImplName().equals(GLProfile.GL4)) { + Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL4)); + Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL3)); + Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2GL3)); + if( gles3CompatAvail ) { + Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL4ES3)); + } else { + Assert.assertFalse(GLProfile.isAvailable(GLProfile.GL4ES3)); + } + Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2ES2)); + } else if(glp.getImplName().equals(GLProfile.GL3)) { + Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL3)); + Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2GL3)); + Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2ES2)); + } else if(glp.getImplName().equals(GLProfile.GLES3)) { + Assert.assertTrue(GLProfile.isAvailable(GLProfile.GLES3)); + if( gles3CompatAvail ) { + Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL4ES3)); + } else { + Assert.assertFalse(GLProfile.isAvailable(GLProfile.GL4ES3)); + } + Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2ES2)); + } else if(glp.getImplName().equals(GLProfile.GLES2)) { + Assert.assertTrue(GLProfile.isAvailable(GLProfile.GLES2)); + Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2ES2)); + } else if(glp.getImplName().equals(GLProfile.GLES1)) { + Assert.assertTrue(GLProfile.isAvailable(GLProfile.GLES1)); Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2ES1)); } + if( glp.isGL4bc() ) { + Assert.assertTrue(glp.isGL4()); + Assert.assertTrue(glp.isGL3bc()); + Assert.assertTrue(glp.isGL3()); + Assert.assertTrue(glp.isGL2()); + Assert.assertTrue(glp.isGL2GL3()); + Assert.assertTrue(glp.isGL4ES3()); + Assert.assertTrue(glp.isGL3ES3()); + Assert.assertTrue(glp.isGL2ES1()); + Assert.assertTrue(glp.isGL2ES2()); + } else if(glp.isGL3bc()) { + Assert.assertTrue(glp.isGL3()); + Assert.assertTrue(glp.isGL2()); + Assert.assertTrue(glp.isGL2GL3()); + Assert.assertTrue(glp.isGL2ES1()); + Assert.assertTrue(glp.isGL2ES2()); + } else if(glp.isGL2()) { + Assert.assertTrue(glp.isGL2GL3()); + Assert.assertTrue(glp.isGL2ES1()); + Assert.assertTrue(glp.isGL2ES2()); + } else if(glp.isGL4()) { + Assert.assertTrue(glp.isGL3()); + Assert.assertTrue(glp.isGL2GL3()); + Assert.assertTrue(glp.isGL4ES3()); + Assert.assertTrue(glp.isGL3ES3()); + Assert.assertTrue(glp.isGL2ES2()); + } else if(glp.isGL3()) { + Assert.assertTrue(glp.isGL2GL3()); + Assert.assertTrue(glp.isGL3ES3()); + Assert.assertTrue(glp.isGL2ES2()); + } else if(glp.isGLES3()) { + Assert.assertTrue(glp.isGL4ES3()); + Assert.assertTrue(glp.isGL3ES3()); + Assert.assertTrue(glp.isGL2ES2()); + } else if(glp.isGLES2()) { + Assert.assertTrue(glp.isGL2ES2()); + } else if(glp.isGLES1()) { + Assert.assertTrue(glp.isGL2ES1()); + } + } + + static void validate(GL gl) { + final GLContext ctx = gl.getContext(); + final boolean gles3CompatAvail = ctx.isGLES3Compatible(); + + if( gl.isGL4bc() ) { + Assert.assertTrue(gl.isGL4()); + Assert.assertTrue(gl.isGL3bc()); + Assert.assertTrue(gl.isGL3()); + Assert.assertTrue(gl.isGL2()); + Assert.assertTrue(gl.isGL2GL3()); + if( gles3CompatAvail ) { + Assert.assertTrue(gl.isGL4ES3()); + } else { + Assert.assertFalse(gl.isGL4ES3()); + } + Assert.assertTrue(gl.isGL3ES3()); + Assert.assertTrue(gl.isGL2ES1()); + Assert.assertTrue(gl.isGL2ES2()); + } else if(gl.isGL3bc()) { + Assert.assertTrue(gl.isGL3()); + Assert.assertTrue(gl.isGL2()); + Assert.assertTrue(gl.isGL2GL3()); + Assert.assertTrue(gl.isGL2ES1()); + Assert.assertTrue(gl.isGL2ES2()); + } else if(gl.isGL2()) { + Assert.assertTrue(gl.isGL2GL3()); + Assert.assertTrue(gl.isGL2ES1()); + Assert.assertTrue(gl.isGL2ES2()); + } else if(gl.isGL4()) { + Assert.assertTrue(gl.isGL3()); + Assert.assertTrue(gl.isGL2GL3()); + if( gles3CompatAvail ) { + Assert.assertTrue(gl.isGL4ES3()); + } else { + Assert.assertFalse(gl.isGL4ES3()); + } + Assert.assertTrue(gl.isGL3ES3()); + Assert.assertTrue(gl.isGL2ES2()); + } else if(gl.isGL3()) { + Assert.assertTrue(gl.isGL2GL3()); + Assert.assertTrue(gl.isGL3ES3()); + Assert.assertTrue(gl.isGL2ES2()); + } else if(gl.isGLES3()) { + if( gles3CompatAvail ) { + Assert.assertTrue(gl.isGL4ES3()); + } else { + Assert.assertFalse(gl.isGL4ES3()); + } + Assert.assertTrue(gl.isGL3ES3()); + Assert.assertTrue(gl.isGL2ES2()); + } else if(gl.isGLES2()) { + Assert.assertTrue(gl.isGL2ES2()); + } else if(gl.isGLES1()) { + Assert.assertTrue(gl.isGL2ES1()); + } + + if( ctx.isGL4bc() ) { + Assert.assertTrue(ctx.isGL4()); + Assert.assertTrue(ctx.isGL3bc()); + Assert.assertTrue(ctx.isGL3()); + Assert.assertTrue(ctx.isGL2()); + Assert.assertTrue(ctx.isGL2GL3()); + if( gles3CompatAvail ) { + Assert.assertTrue(ctx.isGL4ES3()); + } else { + Assert.assertFalse(ctx.isGL4ES3()); + } + Assert.assertTrue(ctx.isGL3ES3()); + Assert.assertTrue(ctx.isGL2ES1()); + Assert.assertTrue(ctx.isGL2ES2()); + } else if(ctx.isGL3bc()) { + Assert.assertTrue(ctx.isGL3()); + Assert.assertTrue(ctx.isGL2()); + Assert.assertTrue(ctx.isGL2GL3()); + Assert.assertTrue(ctx.isGL2ES1()); + Assert.assertTrue(ctx.isGL2ES2()); + } else if(ctx.isGL2()) { + Assert.assertTrue(ctx.isGL2GL3()); + Assert.assertTrue(ctx.isGL2ES1()); + Assert.assertTrue(ctx.isGL2ES2()); + } else if(ctx.isGL4()) { + Assert.assertTrue(ctx.isGL3()); + Assert.assertTrue(ctx.isGL2GL3()); + if( gles3CompatAvail ) { + Assert.assertTrue(ctx.isGL4ES3()); + } else { + Assert.assertFalse(ctx.isGL4ES3()); + } + Assert.assertTrue(ctx.isGL3ES3()); + Assert.assertTrue(ctx.isGL2ES2()); + } else if(ctx.isGL3()) { + Assert.assertTrue(ctx.isGL2GL3()); + Assert.assertTrue(ctx.isGL3ES3()); + Assert.assertTrue(ctx.isGL2ES2()); + } else if(ctx.isGLES3()) { + if( gles3CompatAvail ) { + Assert.assertTrue(ctx.isGL4ES3()); + } else { + Assert.assertFalse(ctx.isGL4ES3()); + } + Assert.assertTrue(ctx.isGL3ES3()); + Assert.assertTrue(ctx.isGL2ES2()); + } else if(ctx.isGLES2()) { + Assert.assertTrue(ctx.isGL2ES2()); + } else if(ctx.isGLES1()) { + Assert.assertTrue(ctx.isGL2ES1()); + } + } + + @Test + public void test01GLProfileDefault() throws InterruptedException { + System.out.println("GLProfile "+GLProfile.glAvailabilityToString()); + System.out.println("GLProfile.getDefaultDevice(): "+GLProfile.getDefaultDevice()); + GLProfile glp = GLProfile.getDefault(); + System.out.println("GLProfile.getDefault(): "+glp); + validate(glp); dumpVersion(glp); } @Test - public void testGLProfileMaxProgrammable() throws InterruptedException { + public void test02GLProfileMaxProgrammable() throws InterruptedException { // Assuming at least one programmable profile is available GLProfile glp = GLProfile.getMaxProgrammable(true); System.out.println("GLProfile.getMaxProgrammable(): "+glp); - if(glp.getName().equals(GLProfile.GL4)) { - Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL4)); - Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL3)); - Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2ES2)); - } else if(glp.getName().equals(GLProfile.GL3)) { - Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL3)); - Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2ES2)); - } else if(glp.getName().equals(GLProfile.GL2ES2)) { - Assert.assertTrue(GLProfile.isAvailable(GLProfile.GL2ES2)); - } + validate(glp); + dumpVersion(glp); + } + + @Test + public void test03GLProfileMaxFixedFunc() throws InterruptedException { + // Assuming at least one fixed function profile is available + GLProfile glp = GLProfile.getMaxFixedFunc(true); + System.out.println("GLProfile.getMaxFixedFunc(): "+glp); + validate(glp); dumpVersion(glp); } @Test - public void testGLProfileGL2ES1() throws InterruptedException { + public void test04GLProfileGL2ES1() throws InterruptedException { if(!GLProfile.isAvailable(GLProfile.GL2ES1)) { System.out.println("GLProfile GL2ES1 n/a"); return; } GLProfile glp = GLProfile.getGL2ES1(); System.out.println("GLProfile GL2ES1: "+glp); + validate(glp); dumpVersion(glp); } @Test - public void testGLProfileGL2ES2() throws InterruptedException { + public void test05GLProfileGL2ES2() throws InterruptedException { if(!GLProfile.isAvailable(GLProfile.GL2ES2)) { System.out.println("GLProfile GL2ES2 n/a"); return; } GLProfile glp = GLProfile.getGL2ES2(); System.out.println("GLProfile GL2ES2: "+glp); + validate(glp); dumpVersion(glp); } - + + @Test + public void test06GLProfileGL4ES3() throws InterruptedException { + if(!GLProfile.isAvailable(GLProfile.GL4ES3)) { + System.out.println("GLProfile GL4ES3 n/a"); + return; + } + GLProfile glp = GLProfile.getGL4ES3(); + System.out.println("GLProfile GL4ES3: "+glp); + validate(glp); + dumpVersion(glp); + } + void testSpecificProfile(String glps) throws InterruptedException { if(GLProfile.isAvailable(glps)) { GLProfile glp = GLProfile.get(glps); + validate(glp); dumpVersion(glp); } else { System.err.println("Profile "+glps+" n/a"); } } - + @Test - public void testGL4bc() throws InterruptedException { + public void test10_GL4bc() throws InterruptedException { testSpecificProfile(GLProfile.GL4bc); } @Test - public void testGL3bc() throws InterruptedException { + public void test11_GL3bc() throws InterruptedException { testSpecificProfile(GLProfile.GL3bc); } @Test - public void testGL2() throws InterruptedException { + public void test12_GL2() throws InterruptedException { testSpecificProfile(GLProfile.GL2); } - + @Test - public void testGL4() throws InterruptedException { + public void test13_GL4() throws InterruptedException { testSpecificProfile(GLProfile.GL4); } @Test - public void testGL3() throws InterruptedException { + public void test14_GL3() throws InterruptedException { testSpecificProfile(GLProfile.GL3); } @Test - public void testGLES1() throws InterruptedException { + public void test15_GLES1() throws InterruptedException { testSpecificProfile(GLProfile.GLES1); } @Test - public void testGLES2() throws InterruptedException { + public void test16_GLES2() throws InterruptedException { testSpecificProfile(GLProfile.GLES2); } - + + @Test + public void test17_GLES3() throws InterruptedException { + testSpecificProfile(GLProfile.GLES3); + } + protected void dumpVersion(GLProfile glp) throws InterruptedException { - GLCapabilities caps = new GLCapabilities(glp); + GLCapabilities caps = new GLCapabilities(glp); GLWindow glWindow = GLWindow.create(caps); Assert.assertNotNull(glWindow); glWindow.setTitle("TestGLProfile01NEWT"); - glWindow.addGLEventListener(new DumpGLInfo()); + glWindow.addGLEventListener(new GLEventListener() { + + public void init(GLAutoDrawable drawable) { + final GL gl = drawable.getGL(); + System.err.println(JoglVersion.getGLStrings(gl, null, true)); + + validate(gl); + + final GLProfile glp = gl.getGLProfile(); + System.err.println("GL impl. class "+gl.getClass().getName()); + if( gl.isGL4() ) { + Assert.assertNotNull( gl.getGL4() ); + System.err.println("GL Mapping "+glp+" -> GL4"); + } + if( gl.isGL4bc() ) { + Assert.assertNotNull( gl.getGL4bc() ); + System.err.println("GL Mapping "+glp+" -> GL4bc"); + } + if( gl.isGL3() ) { + Assert.assertNotNull( gl.getGL3() ); + System.err.println("GL Mapping "+glp+" -> GL3"); + } + if( gl.isGL3bc() ) { + Assert.assertNotNull( gl.getGL3bc() ); + System.err.println("GL Mapping "+glp+" -> GL3bc"); + } + if( gl.isGLES3() ) { + Assert.assertNotNull( gl.getGLES3() ); + System.err.println("GL Mapping "+glp+" -> GLES3"); + } + if( gl.isGLES2() ) { + Assert.assertNotNull( gl.getGLES2() ); + System.err.println("GL Mapping "+glp+" -> GLES2"); + } + if( gl.isGL4ES3() ) { + Assert.assertNotNull( gl.getGL4ES3() ); + System.err.println("GL Mapping "+glp+" -> GL4ES3"); + } + if( gl.isGL2ES2() ) { + Assert.assertNotNull( gl.getGL2ES2() ); + System.err.println("GL Mapping "+glp+" -> GL2ES2"); + } + if( gl.isGL2ES1() ) { + Assert.assertNotNull( gl.getGL2ES1() ); + System.err.println("GL Mapping "+glp+" -> GL2ES1"); + } + } + + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + } + + public void display(GLAutoDrawable drawable) { + } + + public void dispose(GLAutoDrawable drawable) { + } + }); glWindow.setSize(128, 128); glWindow.setVisible(true); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLJPanelAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLJPanelAWT.java new file mode 100644 index 000000000..f3b5e42de --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLJPanelAWT.java @@ -0,0 +1,253 @@ +/** + * Copyright 2014 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.jogl.acore; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; + +import javax.imageio.ImageIO; +import javax.media.opengl.GL; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLJPanel; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +import org.junit.Assume; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.GLDrawableUtil; +import com.jogamp.opengl.util.awt.AWTGLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; + +/** + * Multiple GLJPanels in a JFrame + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLReadBuffer01GLJPanelAWT extends GLReadBuffer00Base { + + @BeforeClass + public static void initClass() { + GLProfile.initSingleton(); + } + + public void test(final GLCapabilitiesImmutable caps, final boolean useSwingDoubleBuffer, final boolean skipGLOrientationVerticalFlip) { + final AWTGLReadBufferUtil awtGLReadBufferUtil = new AWTGLReadBufferUtil(caps.getGLProfile(), false); + final JFrame frame = new JFrame(); + final Dimension d = new Dimension(320, 240); + final GLJPanel glad = createGLJPanel(skipGLOrientationVerticalFlip, useSwingDoubleBuffer, caps, d); + final TextRendererGLEL textRendererGLEL = new TextRendererGLEL(); + final SnapshotGLELAWT snapshotGLEL = doSnapshot ? new SnapshotGLELAWT(textRendererGLEL, awtGLReadBufferUtil, skipGLOrientationVerticalFlip) : null; + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setLocation(64, 64); + final JPanel panel = new JPanel(); + panel.setLayout(new BorderLayout()); + panel.setDoubleBuffered(useSwingDoubleBuffer); + frame.getContentPane().add(panel); + + final GearsES2 gears = new GearsES2(1); + gears.setFlipVerticalInGLOrientation(skipGLOrientationVerticalFlip); + gears.setVerbose(false); + glad.addGLEventListener(gears); + textRendererGLEL.setFlipVerticalInGLOrientation(skipGLOrientationVerticalFlip); + glad.addGLEventListener(textRendererGLEL); + if( doSnapshot ) { + glad.addGLEventListener(snapshotGLEL); + } + panel.add(glad); + frame.pack(); + frame.setVisible(true); + } } ); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + glad.display(); // trigger initialization to get chosen-caps! + final Dimension size0 = frame.getSize(); + final Dimension size1 = new Dimension(size0.width+100, size0.height+100); + final Dimension size2 = new Dimension(size0.width-100, size0.height-100); + try { + for(int i=0; i<3; i++) { + final String str = "Frame# "+textRendererGLEL.frameNo+", user #"+(i+1); + System.err.println(str); + if( keyFrame ) { + waitForKey(str); + } + textRendererGLEL.userCounter = i + 1; + glad.display(); + } + try { Thread.sleep(duration); } catch (InterruptedException e) { } + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setSize(size1); + frame.validate(); + } } ); + try { Thread.sleep(duration); } catch (InterruptedException e) { } + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setSize(size2); + frame.validate(); + } } ); + try { Thread.sleep(duration); } catch (InterruptedException e) { } + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setSize(size0); + frame.validate(); + } } ); + try { Thread.sleep(duration); } catch (InterruptedException e) { } + + if( doSnapshot ) { + glad.disposeGLEventListener(snapshotGLEL, true /* remove */); + } + final Animator anim = new Animator(glad); + anim.start(); + try { Thread.sleep(2*duration); } catch (InterruptedException e) { } + anim.stop(); + } catch (Exception e1) { + e1.printStackTrace(); + } + try { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.dispose(); + } } ); + } catch (Exception e1) { + e1.printStackTrace(); + } + } + + private GLJPanel createGLJPanel(final boolean skipGLOrientationVerticalFlip, final boolean useSwingDoubleBuffer, final GLCapabilitiesImmutable caps, final Dimension size) { + final GLJPanel canvas = new GLJPanel(caps); + canvas.setSize(size); + canvas.setPreferredSize(size); + canvas.setMinimumSize(size); + canvas.setDoubleBuffered(useSwingDoubleBuffer); + canvas.setSkipGLOrientationVerticalFlip(skipGLOrientationVerticalFlip); + return canvas; + } + + private class SnapshotGLELAWT implements GLEventListener { + final TextRendererGLEL textRendererGLEL; + final AWTGLReadBufferUtil glReadBufferUtil; + final boolean skipGLOrientationVerticalFlip; + boolean defAutoSwapMode; + boolean swapBuffersBeforeRead; + int i; + + SnapshotGLELAWT(final TextRendererGLEL textRendererGLEL, final AWTGLReadBufferUtil glReadBufferUtil, final boolean skipGLOrientationVerticalFlip) { + this.textRendererGLEL = textRendererGLEL; + this.glReadBufferUtil = glReadBufferUtil; + this.skipGLOrientationVerticalFlip = skipGLOrientationVerticalFlip; + this.defAutoSwapMode = true; + this.swapBuffersBeforeRead = false; + i = 0; + } + + @Override + public void init(GLAutoDrawable drawable) { + defAutoSwapMode = drawable.getAutoSwapBufferMode(); + swapBuffersBeforeRead = GLDrawableUtil.swapBuffersBeforeRead(drawable.getChosenGLCapabilities()); + drawable.setAutoSwapBufferMode( !swapBuffersBeforeRead ); + } + @Override + public void dispose(GLAutoDrawable drawable) { + drawable.setAutoSwapBufferMode( defAutoSwapMode ); + } + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } + @Override + public void display(GLAutoDrawable drawable) { + snapshot(i++, drawable.getGL(), TextureIO.PNG, null); + } + public void snapshot(int sn, GL gl, String fileSuffix, String destPath) { + final GLDrawable drawable = gl.getContext().getGLReadDrawable(); + final String postSNDetail = String.format("awt-usr%03d", textRendererGLEL.userCounter); + final String filenameAWT = getSnapshotFilename(sn, postSNDetail, + drawable.getChosenGLCapabilities(), drawable.getWidth(), drawable.getHeight(), + glReadBufferUtil.hasAlpha(), fileSuffix, destPath); + if( swapBuffersBeforeRead ) { + drawable.swapBuffers(); + // Just to test whether we use the right buffer, + // i.e. back-buffer shall no more be required .. + gl.glClear(GL.GL_COLOR_BUFFER_BIT); + } else { + gl.glFinish(); // just make sure rendering finished .. + } + + final boolean awtOrientation = !( drawable.isGLOriented() && skipGLOrientationVerticalFlip ); + System.err.println(Thread.currentThread().getName()+": ** screenshot: awtOrient/v-flip "+awtOrientation+", swapBuffersBeforeRead "+swapBuffersBeforeRead+", "+filenameAWT); + + final BufferedImage image = glReadBufferUtil.readPixelsToBufferedImage(gl, awtOrientation); + final File fout = new File(filenameAWT); + try { + ImageIO.write(image, "png", fout); + } catch (IOException e) { + e.printStackTrace(); + } + /** + final String filenameJGL = getSnapshotFilename(sn, "jgl", + drawable.getChosenGLCapabilities(), drawable.getWidth(), drawable.getHeight(), + glReadBufferUtil.hasAlpha(), fileSuffix, destPath); + glReadBufferUtil.write(new File(filenameJGL)); + */ + } + }; + + static GLCapabilitiesImmutable caps = null; + static boolean doSnapshot = true; + static boolean keyFrame = false; + + public static void main(String[] args) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-keyFrame")) { + keyFrame = true; + } else if(args[i].equals("-noSnapshot")) { + doSnapshot = false; + } + } + org.junit.runner.JUnitCore.main(TestGLReadBuffer01GLJPanelAWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLWindowNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLWindowNEWT.java new file mode 100644 index 000000000..9bc47f9e0 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLWindowNEWT.java @@ -0,0 +1,194 @@ +/** + * Copyright 2014 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.jogl.acore; + +import java.io.File; + +import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.DimensionImmutable; +import javax.media.opengl.GL; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import org.junit.Assume; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.GLDrawableUtil; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; + +/** + * Multiple GLJPanels in a JFrame + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLReadBuffer01GLWindowNEWT extends GLReadBuffer00Base { + + @BeforeClass + public static void initClass() { + GLProfile.initSingleton(); + } + + public void test(final GLCapabilitiesImmutable caps, final boolean useSwingDoubleBuffer, final boolean skipGLOrientationVerticalFlip) { + if( skipGLOrientationVerticalFlip || useSwingDoubleBuffer ) { + return; // NOP + } + final GLReadBufferUtil glReadBufferUtil = new GLReadBufferUtil(false, false); + final GLWindow glad= GLWindow.create(caps); + final TextRendererGLEL textRendererGLEL = new TextRendererGLEL(); + final SnapshotGLEL snapshotGLEL = doSnapshot ? new SnapshotGLEL(textRendererGLEL, glReadBufferUtil) : null; + try { + glad.setPosition(64, 64); + glad.setSize(320, 240); + final GearsES2 gears = new GearsES2(1); + gears.setVerbose(false); + glad.addGLEventListener(gears); + textRendererGLEL.setFlipVerticalInGLOrientation(skipGLOrientationVerticalFlip); + glad.addGLEventListener(textRendererGLEL); + if( doSnapshot ) { + glad.addGLEventListener(snapshotGLEL); + } + glad.setVisible(true); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + final DimensionImmutable size0 = new Dimension(glad.getWidth(), glad.getHeight()); + final DimensionImmutable size1 = new Dimension(size0.getWidth()+100, size0.getHeight()+100); + final DimensionImmutable size2 = new Dimension(size0.getWidth()-100, size0.getHeight()-100); + try { + for(int i=0; i<3; i++) { + final String str = "Frame# "+textRendererGLEL.frameNo+", user #"+(i+1); + System.err.println(str); + if( keyFrame ) { + waitForKey(str); + } + textRendererGLEL.userCounter = i + 1; + glad.display(); + } + try { Thread.sleep(duration); } catch (InterruptedException e) { } + glad.setSize(size1.getWidth(), size1.getHeight()); + try { Thread.sleep(duration); } catch (InterruptedException e) { } + glad.setSize(size2.getWidth(), size2.getHeight()); + try { Thread.sleep(duration); } catch (InterruptedException e) { } + glad.setSize(size0.getWidth(), size0.getHeight()); + try { Thread.sleep(duration); } catch (InterruptedException e) { } + + if( doSnapshot ) { + glad.disposeGLEventListener(snapshotGLEL, true /* remove */); + } + final Animator anim = new Animator(glad); + anim.start(); + try { Thread.sleep(2*duration); } catch (InterruptedException e) { } + anim.stop(); + } catch (Exception e1) { + e1.printStackTrace(); + } + glad.destroy(); + } + + private class SnapshotGLEL implements GLEventListener { + final TextRendererGLEL textRendererGLEL; + final GLReadBufferUtil glReadBufferUtil; + boolean defAutoSwapMode; + boolean swapBuffersBeforeRead; + int i; + + SnapshotGLEL(final TextRendererGLEL textRendererGLEL, final GLReadBufferUtil glReadBufferUtil) { + this.textRendererGLEL = textRendererGLEL; + this.glReadBufferUtil = glReadBufferUtil; + this.defAutoSwapMode = true; + this.swapBuffersBeforeRead = false; + i = 0; + } + + @Override + public void init(GLAutoDrawable drawable) { + defAutoSwapMode = drawable.getAutoSwapBufferMode(); + swapBuffersBeforeRead = GLDrawableUtil.swapBuffersBeforeRead(drawable.getChosenGLCapabilities()); + drawable.setAutoSwapBufferMode( !swapBuffersBeforeRead ); + } + @Override + public void dispose(GLAutoDrawable drawable) { + drawable.setAutoSwapBufferMode( defAutoSwapMode ); + } + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } + @Override + public void display(GLAutoDrawable drawable) { + snapshot(i++, drawable, TextureIO.PNG, null); + } + public void snapshot(int sn, GLAutoDrawable drawable, String fileSuffix, String destPath) { + final GL gl = drawable.getGL(); + final String postSNDetail = String.format("jgl-usr%03d", textRendererGLEL.userCounter); + final String filenameJGL = getSnapshotFilename(sn, postSNDetail, + drawable.getChosenGLCapabilities(), drawable.getWidth(), drawable.getHeight(), + glReadBufferUtil.hasAlpha(), fileSuffix, destPath); + if( swapBuffersBeforeRead ) { + drawable.swapBuffers(); + // Just to test whether we use the right buffer, + // i.e. back-buffer shall no more be required .. + gl.glClear(GL.GL_COLOR_BUFFER_BIT); + } else { + gl.glFinish(); // just make sure rendering finished .. + } + final boolean mustFlipVertically = !drawable.isGLOriented(); + System.err.println(Thread.currentThread().getName()+": ** screenshot: v-flip "+mustFlipVertically+", swapBuffersBeforeRead "+swapBuffersBeforeRead+", "+filenameJGL); + + if(glReadBufferUtil.readPixels(gl, mustFlipVertically)) { + glReadBufferUtil.write(new File(filenameJGL)); + } + } + }; + + static GLCapabilitiesImmutable caps = null; + static boolean doSnapshot = true; + static boolean keyFrame = false; + + public static void main(String[] args) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-keyFrame")) { + keyFrame = true; + } else if(args[i].equals("-noSnapshot")) { + doSnapshot = false; + } + } + org.junit.runner.JUnitCore.main(TestGLReadBuffer01GLWindowNEWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLVersionParsing00NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLVersionParsing00NEWT.java new file mode 100644 index 000000000..7ae49fe54 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLVersionParsing00NEWT.java @@ -0,0 +1,204 @@ +/** + * Copyright 2013 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.jogl.acore; + +import java.io.IOException; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import jogamp.opengl.GLVersionNumber; + +import com.jogamp.common.util.VersionNumberString; +import com.jogamp.opengl.test.junit.util.UITestCase; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLVersionParsing00NEWT extends UITestCase { + + public static final String[] glVersionStrings00 = new String[] { + "GL_VERSION_2_1 DummyTool 1.2.3", // 0 + "2.1 Mesa 7.0.3-rc2", + "4.2.12171 Compatibility Profile Context 9.01.8", + "4.2.12198 Compatibility Profile Context 12.102.3.0", + "2.1 Mesa 7.0.3-rc2 post odd", + "4.2.12171 Compatibility Profile Context 9.01.8 post odd", + "4.2.12198 Compatibility Profile Context 12.102.3.0 post odd", + "OpenGL ES 2.0 Mesa 9.1.1", // 7 + "OpenGL ES 2.0 14.10.1", + "OpenGL ES GLSL ES 2.0 14.10.1", // 9 + "OpenGL ES 2.0 3Com L3 11.33.44" // 10 + }; + public static final String[] glVersionStrings01 = new String[] { + "GL_VERSION_2_1 Dummy Tool 1.2", // 0 + "2.1 Mesa 7.12", + "2.1 Mesa 7.12-devel", + "2.1 Mesa 7.12-devel (git-d6c318e)", + "2.1 Mesa 7.12-devel la1 la2 li3", + "4.3.0 NVIDIA 310.32", + "OpenGL ES 2.0 Mesa 9.1", // 6 + "OpenGL ES 2.0 14.10", + "OpenGL ES GLSL ES 2.0 14.10", // 8 + "OpenGL ES 2.0 3Com L3 11.33" // 9 + }; + public static final String[] glVersionStrings02 = new String[] { + "GL_VERSION_2_1", // 0 + "OpenGL ES 2.0", // 1 + "OpenGL ES GLSL ES 2.0", // 2 + "OpenGL 2.1 LaLa", // 3 + "4.2.11762 Compatibility Profile Context" // 4 + }; + + public static final VersionNumberString[] glVersionNumbers = new VersionNumberString[] { + new VersionNumberString(2, 1, 0, glVersionStrings00[0]), + new VersionNumberString(2, 1, 0, glVersionStrings00[1]), + new VersionNumberString(4, 2, 0, glVersionStrings00[2]), + new VersionNumberString(4, 2, 0, glVersionStrings00[3]), + new VersionNumberString(2, 1, 0, glVersionStrings00[4]), + new VersionNumberString(4, 2, 0, glVersionStrings00[5]), + new VersionNumberString(4, 2, 0, glVersionStrings00[6]), + new VersionNumberString(2, 0, 0, glVersionStrings00[7]), + new VersionNumberString(2, 0, 0, glVersionStrings00[8]), + new VersionNumberString(2, 0, 0, glVersionStrings00[9]), + new VersionNumberString(2, 0, 0, glVersionStrings00[10]), + + new VersionNumberString(2, 1, 0, glVersionStrings01[0]), + new VersionNumberString(2, 1, 0, glVersionStrings01[1]), + new VersionNumberString(2, 1, 0, glVersionStrings01[2]), + new VersionNumberString(2, 1, 0, glVersionStrings01[3]), + new VersionNumberString(2, 1, 0, glVersionStrings01[4]), + new VersionNumberString(4, 3, 0, glVersionStrings01[5]), + new VersionNumberString(2, 0, 0, glVersionStrings01[6]), + new VersionNumberString(2, 0, 0, glVersionStrings01[7]), + new VersionNumberString(2, 0, 0, glVersionStrings01[8]), + new VersionNumberString(2, 0, 0, glVersionStrings01[9]), + + new VersionNumberString(2, 1, 0, glVersionStrings02[0]), + new VersionNumberString(2, 0, 0, glVersionStrings02[1]), + new VersionNumberString(2, 0, 0, glVersionStrings02[2]), + new VersionNumberString(2, 1, 0, glVersionStrings02[3]), + new VersionNumberString(4, 2, 0, glVersionStrings02[4]) + }; + public static final VersionNumberString[] glVendorVersionNumbersWithSub = new VersionNumberString[] { + new VersionNumberString(1, 2, 3, glVersionStrings00[0]), + new VersionNumberString(7, 0, 3, glVersionStrings00[1]), + new VersionNumberString(9, 1, 8, glVersionStrings00[2]), + new VersionNumberString(12, 102, 3, glVersionStrings00[3]), + new VersionNumberString(7, 0, 3, glVersionStrings00[4]), + new VersionNumberString(9, 1, 8, glVersionStrings00[5]), + new VersionNumberString(12, 102, 3, glVersionStrings00[6]), + new VersionNumberString(9, 1, 1, glVersionStrings00[7]), + new VersionNumberString(14, 10, 1, glVersionStrings00[8]), + new VersionNumberString(14, 10, 1, glVersionStrings00[9]), + new VersionNumberString(11, 33, 44, glVersionStrings00[10]) + }; + public static final VersionNumberString[] glVendorVersionNumbersNoSub = new VersionNumberString[] { + new VersionNumberString(1, 2, 0, glVersionStrings01[0]), + new VersionNumberString(7, 12, 0, glVersionStrings01[1]), + new VersionNumberString(7, 12, 0, glVersionStrings01[2]), + new VersionNumberString(7, 12, 0, glVersionStrings01[3]), + new VersionNumberString(7, 12, 0, glVersionStrings01[4]), + new VersionNumberString(310, 32, 0, glVersionStrings01[5]), + new VersionNumberString(9, 1, 0, glVersionStrings01[6]), + new VersionNumberString(14, 10, 0, glVersionStrings01[7]), + new VersionNumberString(14, 10, 0, glVersionStrings01[8]), + new VersionNumberString(11, 33, 0, glVersionStrings01[9]) + }; + public static final VersionNumberString[] glVendorVersionNumbersNone = new VersionNumberString[] { + new VersionNumberString(0, 0, 0, glVersionStrings02[0]), + new VersionNumberString(0, 0, 0, glVersionStrings02[1]), + new VersionNumberString(0, 0, 0, glVersionStrings02[2]), + new VersionNumberString(0, 0, 0, glVersionStrings02[3]), + new VersionNumberString(0, 0, 0, glVersionStrings02[4]) + }; + + @Test + public void test01GLVersion() throws InterruptedException { + for(int i=0; i<glVersionNumbers.length; i++) { + final VersionNumberString exp = glVersionNumbers[i]; + final GLVersionNumber has = GLVersionNumber.create(exp.getVersionString()); + System.err.println("Test["+i+"]: "+exp+" -> "+has+", valid "+has.isValid()+", define ["+has.hasMajor()+":"+has.hasMinor()+":"+has.hasSub()+"]"); + Assert.assertTrue(has.hasMajor()); + Assert.assertTrue(has.hasMinor()); + Assert.assertTrue(!has.hasSub()); + Assert.assertTrue(has.isValid()); + Assert.assertEquals(exp, has); + } + { + final GLVersionNumber has = GLVersionNumber.create("GL_VERSION_2"); + System.err.println("Test-X1: "+has+", valid "+has.isValid()+", define ["+has.hasMajor()+":"+has.hasMinor()+":"+has.hasSub()+"]"); + Assert.assertTrue(has.hasMajor()); + Assert.assertTrue(!has.hasMinor()); + Assert.assertTrue(!has.hasSub()); + Assert.assertTrue(!has.isValid()); + } + { + final GLVersionNumber has = GLVersionNumber.create("GL2 Buggy L3"); + System.err.println("Test-X2: "+has+", valid "+has.isValid()+", define ["+has.hasMajor()+":"+has.hasMinor()+":"+has.hasSub()+"]"); + Assert.assertTrue(has.hasMajor()); + Assert.assertTrue(!has.hasMinor()); + Assert.assertTrue(!has.hasSub()); + Assert.assertTrue(!has.isValid()); + } + { + final GLVersionNumber has = GLVersionNumber.create("GL Nope"); + System.err.println("Test-X3: "+has+", valid "+has.isValid()+", define ["+has.hasMajor()+":"+has.hasMinor()+":"+has.hasSub()+"]"); + Assert.assertTrue(!has.hasMajor()); + Assert.assertTrue(!has.hasMinor()); + Assert.assertTrue(!has.hasSub()); + Assert.assertTrue(!has.isValid()); + } + } + + private void testGLVendorVersionImpl(VersionNumberString[] versionNumberString, boolean withMajor, boolean withMinor, boolean withSub) throws InterruptedException { + for(int i=0; i<versionNumberString.length; i++) { + final VersionNumberString exp = versionNumberString[i]; + final VersionNumberString has = GLVersionNumber.createVendorVersion(exp.getVersionString()); + System.err.println("Test["+withMajor+":"+withMinor+":"+withSub+"]["+i+"]: "+exp+" -> "+has+", define ["+has.hasMajor()+":"+has.hasMinor()+":"+has.hasSub()+"]"); + Assert.assertEquals(withMajor, has.hasMajor()); + Assert.assertEquals(withMinor, has.hasMinor()); + Assert.assertEquals(withSub, has.hasSub()); + Assert.assertEquals(exp, has); + } + } + + @Test + public void test02GLVendorVersion() throws InterruptedException { + testGLVendorVersionImpl(glVendorVersionNumbersWithSub, true, true, true); + testGLVendorVersionImpl(glVendorVersionNumbersNoSub, true, true, false); + testGLVendorVersionImpl(glVendorVersionNumbersNone, false, false, false); + } + + public static void main(String args[]) throws IOException { + String tstname = TestGLVersionParsing00NEWT.class.getName(); + org.junit.runner.JUnitCore.main(tstname); + } + +}
\ No newline at end of file diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGPUMemSec01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGPUMemSec01NEWT.java index bebe3531e..93713c783 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGPUMemSec01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGPUMemSec01NEWT.java @@ -36,6 +36,7 @@ import java.io.IOException; import java.nio.ByteBuffer; import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; import javax.media.opengl.GL2GL3; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLDrawable; @@ -44,7 +45,10 @@ import javax.media.opengl.GLProfile; import org.junit.Assert; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestGPUMemSec01NEWT extends UITestCase { static String hexString(int i) { return "0x"+Integer.toHexString(i); @@ -61,6 +65,8 @@ public class TestGPUMemSec01NEWT extends UITestCase { new GLCapabilities(glp), width, height, true); final GL gl = winctx.context.getGL(); + // System.err.println("Pre GL Error: 0x"+Integer.toHexString(gl.glGetError())); + // System.err.println(winctx.drawable); Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); // misc GL setup @@ -249,7 +255,7 @@ public class TestGPUMemSec01NEWT extends UITestCase { NEWTGLContext.destroyWindow(winctx); } - + @Test public void testReadPixelsGL_99x100xRGBxUB() throws InterruptedException { GLProfile glp = GLProfile.getGL2ES2(); @@ -275,8 +281,8 @@ public class TestGPUMemSec01NEWT extends UITestCase { @Test public void testReadPixelsGL2GL3_640x480xRGBxUB() throws InterruptedException { GLProfile glp = GLProfile.getGL2ES2(); - if(!glp.isGL2GL3()) { - System.err.println("GL2GL3 n/a skip test"); + if(!glp.isGL2ES3()) { + System.err.println("GL2ES3 n/a skip test"); return; } final int width = 640; @@ -299,8 +305,8 @@ public class TestGPUMemSec01NEWT extends UITestCase { @Test public void testReadPixelsGL2GL3_99x100xRGBxUB() throws InterruptedException { GLProfile glp = GLProfile.getGL2ES2(); - if(!glp.isGL2GL3()) { - System.err.println("GL2GL3 n/a skip test"); + if(!glp.isGL2ES3()) { + System.err.println("GL2ES3 n/a skip test"); return; } final int wwidth = 640; @@ -325,8 +331,8 @@ public class TestGPUMemSec01NEWT extends UITestCase { @Test public void testReadPixelsGL2GL3_640x480xREDxUB() throws InterruptedException { GLProfile glp = GLProfile.getGL2ES2(); - if(!glp.isGL2GL3()) { - System.err.println("GL2GL3 n/a skip test"); + if(!glp.isGL2ES3()) { + System.err.println("GL2ES3 n/a skip test"); return; } final int width = 640; @@ -338,7 +344,7 @@ public class TestGPUMemSec01NEWT extends UITestCase { final GL2GL3 gl = winctx.context.getGL().getGL2GL3(); // 2 x too small - 0 x alignment - Assert.assertEquals(2, readPixelsCheck(gl, GL2GL3.GL_RED, GL.GL_UNSIGNED_BYTE, 1, width, height)); + Assert.assertEquals(2, readPixelsCheck(gl, GL2ES2.GL_RED, GL.GL_UNSIGNED_BYTE, 1, width, height)); drawable.swapBuffers(); Thread.sleep(50); @@ -349,8 +355,8 @@ public class TestGPUMemSec01NEWT extends UITestCase { @Test public void testReadPixelsGL2GL3_102x100xREDxUB() throws InterruptedException { GLProfile glp = GLProfile.getGL2ES2(); - if(!glp.isGL2GL3()) { - System.err.println("GL2GL3 n/a skip test"); + if(!glp.isGL2ES3()) { + System.err.println("GL2ES3 n/a skip test"); return; } int wwidth = 640; @@ -364,7 +370,7 @@ public class TestGPUMemSec01NEWT extends UITestCase { final GL2GL3 gl = winctx.context.getGL().getGL2GL3(); // 2 x too small - 2 x alignment - Assert.assertEquals(4, readPixelsCheck(gl, GL2GL3.GL_RED, GL.GL_UNSIGNED_BYTE, 1, rwidth, rheight)); + Assert.assertEquals(4, readPixelsCheck(gl, GL2ES2.GL_RED, GL.GL_UNSIGNED_BYTE, 1, rwidth, rheight)); drawable.swapBuffers(); Thread.sleep(50); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrent01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrent01NEWT.java new file mode 100644 index 000000000..7aca28006 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrent01NEWT.java @@ -0,0 +1,82 @@ +/** + * 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.jogl.acore; + +import java.io.IOException; + +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.common.os.Platform; + +/** + * Concurrent initialization and lock-free rendering using shared NEWT Display EDT instances. + * <p> + * Rendering is always lock-free and independent of the EDT, however shared NEWT Display instances + * perform lifecycle actions (window creation etc) with locking. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestInitConcurrent01NEWT extends InitConcurrentBaseNEWT { + + @Test(timeout=180000) // TO 3 min + public void test02TwoThreads() throws InterruptedException { + runJOGLTasks(2, true); + } + + @Test(timeout=180000) // TO 3 min + public void test04FourThreads() throws InterruptedException { + runJOGLTasks(4, true); + } + + @Test(timeout=300000) // TO 5 min + public void test16SixteenThreads() throws InterruptedException { + if( Platform.getCPUFamily() != Platform.CPUFamily.ARM && + Platform.getOSType() != Platform.OSType.WINDOWS ) { + runJOGLTasks(16, true); + } else { + runJOGLTasks( 6, true); + } + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + try { + duration = Integer.parseInt(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } + } + String tstname = TestInitConcurrent01NEWT.class.getName(); + org.junit.runner.JUnitCore.main(tstname); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrent02NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrent02NEWT.java new file mode 100644 index 000000000..67b3cef38 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrent02NEWT.java @@ -0,0 +1,98 @@ +/** + * 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.jogl.acore; + +import java.io.IOException; + +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.common.os.Platform; + +/** + * Concurrent and lock-free initialization and rendering using exclusive NEWT Display EDT instances. + * <p> + * Rendering is always lock-free and independent of the EDT, however exclusive NEWT Display instances + * perform lifecycle actions (window creation etc) w/o locking. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestInitConcurrent02NEWT extends InitConcurrentBaseNEWT { + static boolean mainRun = false; + + @Test(timeout=180000) // TO 3 min + public void test02TwoThreads() throws InterruptedException { + if(!mainRun) { + System.err.println("Disabled for auto unit test until further analysis - Windows/ATI driver crash"); + return; + } + runJOGLTasks(2, false); + } + + @Test(timeout=180000) // TO 3 min + public void test02FourThreads() throws InterruptedException { + if(!mainRun) { + System.err.println("Disabled for auto unit test until further analysis - Windows/ATI driver crash"); + return; + } + runJOGLTasks(4, false); + } + + @Test(timeout=180000) // TO 3 min + public void test16SixteenThreads() throws InterruptedException { + if(!mainRun) { + System.err.println("Disabled for auto unit test until further analysis - Windows/ATI driver crash"); + return; + } + if( Platform.getCPUFamily() != Platform.CPUFamily.ARM && + Platform.getOSType() != Platform.OSType.WINDOWS ) { + runJOGLTasks(16, false); + } else { + runJOGLTasks( 6, false); + } + } + + public static void main(String args[]) throws IOException { + mainRun = true; + for(int i=0; i<args.length; i++) { + if(args[i].equals("-normalRun")) { + mainRun = false; + } else if(args[i].equals("-time")) { + i++; + try { + duration = Integer.parseInt(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } + } + String tstname = TestInitConcurrent02NEWT.class.getName(); + org.junit.runner.JUnitCore.main(tstname); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMainVersionGLCanvasAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMainVersionGLCanvasAWT.java index 5523ce5ce..5c60d094f 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMainVersionGLCanvasAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMainVersionGLCanvasAWT.java @@ -33,9 +33,12 @@ import java.io.IOException; import javax.media.opengl.awt.GLCanvas; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import com.jogamp.opengl.test.junit.util.UITestCase; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestMainVersionGLCanvasAWT extends UITestCase { @Test diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMainVersionGLWindowNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMainVersionGLWindowNEWT.java index d178e34f4..85de65e2a 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMainVersionGLWindowNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMainVersionGLWindowNEWT.java @@ -30,19 +30,30 @@ package com.jogamp.opengl.test.junit.jogl.acore; import java.io.IOException; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.JoglVersion; import com.jogamp.opengl.test.junit.util.UITestCase; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestMainVersionGLWindowNEWT extends UITestCase { + private static String[] args = null; @Test public void testMain() throws InterruptedException { - GLWindow.main(null); + JoglVersion j = JoglVersion.getInstance(); + System.out.println("Implementation-Version: "+j.getImplementationVersion()); + System.out.println("Implementation-Build: "+j.getImplementationBuild()); + System.out.println("Implementation-Branch: "+j.getImplementationBranch()); + System.out.println("Implementation-Commit: "+j.getImplementationCommit()); + GLWindow.main(args); } - public static void main(String args[]) throws IOException { + public static void main(String[] args) throws IOException { + TestMainVersionGLWindowNEWT.args = args; String tstname = TestMainVersionGLWindowNEWT.class.getName(); org.junit.runner.JUnitCore.main(tstname); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMapBufferRead01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMapBufferRead01NEWT.java index 158c2aa90..ac82c74ea 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMapBufferRead01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMapBufferRead01NEWT.java @@ -37,19 +37,25 @@ import java.nio.ByteOrder; import javax.media.opengl.GL; import javax.media.opengl.GL2GL3; +import javax.media.opengl.GLBufferStorage; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLProfile; import org.junit.Assert; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; /** + * Verifies content of buffer storage's content + * as well as general buffer- and buffer-storage tracking. * * @author Luz, et.al. */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestMapBufferRead01NEWT extends UITestCase { static final boolean DEBUG = false; - + @Test public void testWriteRead01a() throws InterruptedException { if(!GLProfile.isAvailable(GLProfile.GL2GL3)) { @@ -73,51 +79,64 @@ public class TestMapBufferRead01NEWT extends UITestCase { private void testWriteRead01(ByteBuffer verticiesBB) throws InterruptedException { final NEWTGLContext.WindowContext winctx = NEWTGLContext.createOffscreenWindow( new GLCapabilities(GLProfile.getGL2GL3()), 800, 600, true); - final GL gl = winctx.context.getGL(); - - int[] vertexBuffer = new int[1]; - - verticiesBB.putFloat(0); - verticiesBB.putFloat(0.5f); - verticiesBB.putFloat(0); - - verticiesBB.putFloat(0.5f); - verticiesBB.putFloat(-0.5f); - verticiesBB.putFloat(0); - - verticiesBB.putFloat(-0.5f); - verticiesBB.putFloat(-0.5f); - verticiesBB.putFloat(0); - verticiesBB.rewind(); - if(DEBUG) { - for(int i=0; i < verticiesBB.capacity(); i+=4) { - System.out.println("java "+i+": "+verticiesBB.getFloat(i)); + try { + final GL gl = winctx.context.getGL(); + + int[] vertexBuffer = new int[1]; + + verticiesBB.putFloat(0); + verticiesBB.putFloat(0.5f); + verticiesBB.putFloat(0); + + verticiesBB.putFloat(0.5f); + verticiesBB.putFloat(-0.5f); + verticiesBB.putFloat(0); + + verticiesBB.putFloat(-0.5f); + verticiesBB.putFloat(-0.5f); + verticiesBB.putFloat(0); + verticiesBB.rewind(); + if(DEBUG) { + for(int i=0; i < verticiesBB.capacity(); i+=4) { + System.err.println("java "+i+": "+verticiesBB.getFloat(i)); + } } - } - gl.glGenBuffers(1, vertexBuffer, 0); + gl.glGenBuffers(1, vertexBuffer, 0); - gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vertexBuffer[0]); + gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vertexBuffer[0]); - // gl.glBufferData(GL.GL_ARRAY_BUFFER, verticiesBB.capacity(), verticiesBB, GL.GL_STATIC_READ); - gl.glBufferData(GL.GL_ARRAY_BUFFER, verticiesBB.capacity(), verticiesBB, GL.GL_STATIC_DRAW); - - ByteBuffer bb = gl.glMapBuffer(GL.GL_ARRAY_BUFFER, GL2GL3.GL_READ_ONLY); - Assert.assertNotNull(bb); - - if(DEBUG) { + // gl.glBufferData(GL.GL_ARRAY_BUFFER, verticiesBB.capacity(), verticiesBB, GL.GL_STATIC_READ); + gl.glBufferData(GL.GL_ARRAY_BUFFER, verticiesBB.capacity(), verticiesBB, GL.GL_STATIC_DRAW); + + final int bufferName = gl.getBoundBuffer(GL.GL_ARRAY_BUFFER); + final GLBufferStorage bufferStorage = gl.getBufferStorage(bufferName); + System.err.println("gpu-01 GL_ARRAY_BUFFER -> bufferName "+bufferName+" -> "+bufferStorage); + Assert.assertEquals("Buffer storage's bytes-buffer not null before map", null, bufferStorage.getMappedBuffer()); + + final ByteBuffer bb = gl.glMapBuffer(GL.GL_ARRAY_BUFFER, GL2GL3.GL_READ_ONLY); + Assert.assertNotNull(bb); + System.err.println("gpu-02 mapped GL_ARRAY_BUFFER -> "+bb); + System.err.println("gpu-03 GL_ARRAY_BUFFER -> bufferName "+bufferName+" -> "+bufferStorage); + Assert.assertEquals("Buffer storage size not equals buffer storage size", bufferStorage.getSize(), bb.capacity()); + Assert.assertEquals("Buffer storage's bytes-buffer not equal with mapped bytes-buffer", bufferStorage.getMappedBuffer(), bb); + + if(DEBUG) { + for(int i=0; i < bb.capacity(); i+=4) { + System.err.println("gpu "+i+": "+bb.getFloat(i)); + } + } for(int i=0; i < bb.capacity(); i+=4) { - System.out.println("gpu "+i+": "+bb.getFloat(i)); + Assert.assertEquals(verticiesBB.getFloat(i), bb.getFloat(i), 0.0); } + gl.glUnmapBuffer(GL.GL_ARRAY_BUFFER); + Assert.assertEquals("Buffer storage's bytes-buffer not null after unmap", null, bufferStorage.getMappedBuffer()); + } finally { + NEWTGLContext.destroyWindow(winctx); } - for(int i=0; i < bb.capacity(); i+=4) { - Assert.assertEquals(verticiesBB.getFloat(i), bb.getFloat(i), 0.0); - } - gl.glUnmapBuffer(GL.GL_ARRAY_BUFFER); - NEWTGLContext.destroyWindow(winctx); } public static void main(String args[]) throws IOException { String tstname = TestMapBufferRead01NEWT.class.getName(); org.junit.runner.JUnitCore.main(tstname); - } + } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestNEWTCloseX11DisplayBug565.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestNEWTCloseX11DisplayBug565.java index e14d5b800..83e55b7e0 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestNEWTCloseX11DisplayBug565.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestNEWTCloseX11DisplayBug565.java @@ -3,6 +3,8 @@ package com.jogamp.opengl.test.junit.jogl.acore; import jogamp.nativewindow.x11.X11Util; import org.junit.Assert; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import com.jogamp.newt.opengl.GLWindow; @@ -11,12 +13,15 @@ import javax.media.opengl.DefaultGLCapabilitiesChooser; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLOffscreenAutoDrawable; import javax.media.opengl.GLPbuffer; import javax.media.opengl.GLProfile; /** * Tests the closing the device of GLWindow and GLPBuffer in JOGL */ +@SuppressWarnings("deprecation") +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestNEWTCloseX11DisplayBug565 { @Test @@ -25,16 +30,16 @@ public class TestNEWTCloseX11DisplayBug565 { try { for ( int j = 0; j < 10; j++ ) { final int open0; - if(NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(false)) { + if(NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(false)) { open0 = X11Util.getOpenDisplayConnectionNumber(); } else { open0 = 0; } - + GLCapabilitiesImmutable caps = new GLCapabilities( GLProfile.getDefault( ) ); - + GLWindow window = GLWindow.create(caps); - window.setTitle("NEWT Resource X11 Leak - #" + j ); + window.setTitle("NEWT Resource X11 Leak - #" + j ); window.setSize( 128, 128 ); window.setVisible(true); window.display(); @@ -43,10 +48,10 @@ public class TestNEWTCloseX11DisplayBug565 { if(NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(false)) { final int openD = X11Util.getOpenDisplayConnectionNumber() - open0; - if(openD>1) { + if( openD > 0) { X11Util.dumpOpenDisplayConnections(); X11Util.dumpPendingDisplayConnections(); - Assert.assertTrue("More than 1 new open display connections", false); + Assert.assertEquals("New display connection didn't close", 0, openD); } } } @@ -59,12 +64,12 @@ public class TestNEWTCloseX11DisplayBug565 { @Test - public void testX11WindowMemoryLeakOffscreenWindow() throws Exception { + public void testX11WindowMemoryLeakGLPbuffer() throws Exception { GLProfile.initSingleton(); // ensure shared resource runner is done try { for ( int j = 0; j < 10; j++ ) { final int open0; - if(NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(false)) { + if(NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(false)) { open0 = X11Util.getOpenDisplayConnectionNumber(); } else { open0 = 0; @@ -86,10 +91,46 @@ public class TestNEWTCloseX11DisplayBug565 { if(NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(false)) { final int openD = X11Util.getOpenDisplayConnectionNumber() - open0; - if(openD>1) { + if(openD > 0) { + X11Util.dumpOpenDisplayConnections(); + X11Util.dumpPendingDisplayConnections(); + Assert.assertEquals("New display connection didn't close", 0, openD); + } + } + } + } + catch ( Exception e ) { + e.printStackTrace(); + Assert.fail(e.getMessage()); + } + } + + @Test + public void testX11WindowMemoryLeakFBOAutoDrawable() throws Exception { + GLProfile.initSingleton(); // ensure shared resource runner is done + try { + for ( int j = 0; j < 10; j++ ) { + final int open0; + if(NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(false)) { + open0 = X11Util.getOpenDisplayConnectionNumber(); + } else { + open0 = 0; + } + final GLProfile glp = GLProfile.getDefault( ); + GLCapabilitiesImmutable caps = new GLCapabilities( glp ); + + + GLOffscreenAutoDrawable buffer = GLDrawableFactory.getFactory( glp ).createOffscreenAutoDrawable( + null, caps, new DefaultGLCapabilitiesChooser(), 256, 256); + buffer.display(); + buffer.destroy(); + + if(NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(false)) { + final int openD = X11Util.getOpenDisplayConnectionNumber() - open0; + if(openD > 0) { X11Util.dumpOpenDisplayConnections(); X11Util.dumpPendingDisplayConnections(); - Assert.assertTrue("More than 1 new open display connections", false); + Assert.assertEquals("New display connection didn't close", 0, openD); } } } @@ -103,6 +144,6 @@ public class TestNEWTCloseX11DisplayBug565 { public static void main(String args[]) { org.junit.runner.JUnitCore.main(TestNEWTCloseX11DisplayBug565.class.getName()); } - + } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestNVSwapGroupNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestNVSwapGroupNEWT.java index 54f99433c..e41f22ab0 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestNVSwapGroupNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestNVSwapGroupNEWT.java @@ -44,7 +44,10 @@ import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestNVSwapGroupNEWT extends UITestCase { static GLProfile glp; static GLCapabilities caps; diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParentingOffscreenLayer01GLCanvasAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer01GLCanvasAWT.java index 8ec65bf50..c93e54eb9 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParentingOffscreenLayer01GLCanvasAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer01GLCanvasAWT.java @@ -26,7 +26,7 @@ * or implied, of JogAmp Community. */ -package com.jogamp.opengl.test.junit.newt.parenting; +package com.jogamp.opengl.test.junit.jogl.acore; import java.awt.BorderLayout; import java.awt.Button; @@ -39,6 +39,7 @@ import java.lang.reflect.InvocationTargetException; import javax.media.opengl.GLAnimatorControl; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; import javax.media.opengl.awt.GLCanvas; import jogamp.nativewindow.jawt.JAWTUtil; @@ -46,6 +47,8 @@ import jogamp.nativewindow.jawt.JAWTUtil; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import com.jogamp.common.os.Platform; import com.jogamp.newt.Window; @@ -56,19 +59,25 @@ import com.jogamp.opengl.test.junit.util.MiscUtils; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.util.Animator; -public class TestParentingOffscreenLayer01GLCanvasAWT extends UITestCase { +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestOffscreenLayer01GLCanvasAWT extends UITestCase { + static boolean singleBuffer = false; + static boolean useMSAA = false; + static boolean addComp = true; + static int swapInterval = 1; + static boolean shallUseOffscreenPBufferLayer = false; + static boolean noAnimation = false; static Dimension frameSize0; static Dimension frameSize1; static Dimension preferredGLSize; - static Dimension minGLSize; static long durationPerTest = 1000; + static boolean waitForKey = false; @BeforeClass public static void initClass() { frameSize0 = new Dimension(500,300); frameSize1 = new Dimension(800,600); preferredGLSize = new Dimension(400,200); - minGLSize = new Dimension(200,100); } private void setupFrameAndShow(final Frame f, java.awt.Component comp) throws InterruptedException, InvocationTargetException { @@ -90,10 +99,12 @@ public class TestParentingOffscreenLayer01GLCanvasAWT extends UITestCase { javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { + f.pack(); f.validate(); f.setVisible(true); }}); } + private void end(GLAnimatorControl actrl, final Frame f, Window w) throws InterruptedException, InvocationTargetException { actrl.stop(); javax.swing.SwingUtilities.invokeAndWait(new Runnable() { @@ -114,66 +125,76 @@ public class TestParentingOffscreenLayer01GLCanvasAWT extends UITestCase { } @Test - public void testOnscreenLayerGLCanvas_Onscreen() throws InterruptedException, InvocationTargetException { - if(!JAWTUtil.isOffscreenLayerRequired()) { - testOffscreenLayerGLCanvas_Impl(false, false); - } else { - System.err.println("onscreen layer n/a"); - } + public void test01_GLDefault() throws InterruptedException, InvocationTargetException { + testOffscreenLayerGLCanvas_Impl(null); } - /** We have no GLCanvas OffscreenWindow as we have for NEWT .. test disabled. - @Test - public void testOffscreenLayerGLCanvas_OffscreenLayerWithOffscreenClass() throws InterruptedException, InvocationTargetException { - testOffscreenLayerGLCanvas_Impl(true, true); - } */ - @Test - public void testOffscreenLayerGLCanvas_OffscreenLayerWithOnscreenClass() throws InterruptedException, InvocationTargetException { - if(JAWTUtil.isOffscreenLayerSupported()) { - testOffscreenLayerGLCanvas_Impl(true, false); - } else { - System.err.println("offscreen layer n/a"); + public void test01_GL3() throws InterruptedException, InvocationTargetException { + if( !GLProfile.isAvailable(GLProfile.GL3) ) { + System.err.println("GL3 n/a"); + return; } + testOffscreenLayerGLCanvas_Impl(GLProfile.get(GLProfile.GL3)); } - private void testOffscreenLayerGLCanvas_Impl(boolean offscreenLayer, boolean offscreenClass) throws InterruptedException, InvocationTargetException { + private void testOffscreenLayerGLCanvas_Impl(GLProfile glp) throws InterruptedException, InvocationTargetException { + if(!JAWTUtil.isOffscreenLayerSupported()) { + System.err.println("offscreen layer n/a"); + return; + } final Frame frame1 = new Frame("AWT Parent Frame"); - GLCapabilities glCaps = new GLCapabilities(null); - if(offscreenClass) { - glCaps.setOnscreen(false); - glCaps.setPBuffer(true); + GLCapabilities caps = new GLCapabilities(glp); + if(singleBuffer) { + caps.setDoubleBuffered(false); } - - final GLCanvas glc = new GLCanvas(glCaps); - glc.setShallUseOffscreenLayer(offscreenLayer); // trigger offscreen layer - if supported + if(useMSAA) { + caps.setNumSamples(4); + caps.setSampleBuffers(true); + } + if(shallUseOffscreenPBufferLayer) { + caps.setPBuffer(true); + caps.setOnscreen(true); // simulate normal behavior .. + } + final GLCanvas glc = new GLCanvas(caps); + glc.setShallUseOffscreenLayer(true); // trigger offscreen layer - if supported glc.setPreferredSize(preferredGLSize); - glc.setMinimumSize(minGLSize); + glc.setMinimumSize(preferredGLSize); + glc.setSize(preferredGLSize); - GLEventListener demo1 = new GearsES2(1); + GearsES2 demo1 = new GearsES2(swapInterval); + if(noAnimation) { + demo1.setDoRotation(false); + } glc.addGLEventListener(demo1); frame1.setSize(frameSize0); setupFrameAndShow(frame1, glc); Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glc, true)); Assert.assertEquals(true, AWTRobotUtil.waitForVisible(glc, true)); - Assert.assertEquals(JAWTUtil.isOffscreenLayerSupported() && offscreenLayer, - glc.isOffscreenLayerSurfaceEnabled()); + Assert.assertEquals(true, glc.isOffscreenLayerSurfaceEnabled()); GLAnimatorControl animator1 = new Animator(glc); - animator1.start(); + if(!noAnimation) { + animator1.start(); + } + animator1.setUpdateFPSFrames(60, System.err); Thread.sleep(durationPerTest/2); javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { frame1.setSize(frameSize1); + frame1.pack(); frame1.validate(); }}); Thread.sleep(durationPerTest/2); - end(animator1, frame1, null); + end(animator1, frame1, null); + if( waitForKey ) { + UITestCase.waitForKey("Continue"); + } } public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) { @@ -201,9 +222,25 @@ public class TestParentingOffscreenLayer01GLCanvasAWT extends UITestCase { for(int i=0; i<args.length; i++) { if(args[i].equals("-time")) { durationPerTest = atoi(args[++i]); + } else if(args[i].equals("-vsync")) { + i++; + swapInterval = MiscUtils.atoi(args[i], swapInterval); + } else if(args[i].equals("-layeredPBuffer")) { + shallUseOffscreenPBufferLayer = true; + } else if(args[i].equals("-msaa")) { + useMSAA = true; + } else if(args[i].equals("-single")) { + singleBuffer = true; + } else if(args[i].equals("-still")) { + noAnimation = true; + } else if(args[i].equals("-wait")) { + waitForKey = true; } } - String tstname = TestParentingOffscreenLayer01GLCanvasAWT.class.getName(); + if(waitForKey) { + UITestCase.waitForKey("Start"); + } + String tstname = TestOffscreenLayer01GLCanvasAWT.class.getName(); /* org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] { tstname, diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParentingOffscreenLayer02NewtCanvasAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer02NewtCanvasAWT.java index 6a1980b90..5335d858e 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParentingOffscreenLayer02NewtCanvasAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer02NewtCanvasAWT.java @@ -26,7 +26,7 @@ * or implied, of JogAmp Community. */ -package com.jogamp.opengl.test.junit.newt.parenting; +package com.jogamp.opengl.test.junit.jogl.acore; import java.awt.BorderLayout; import java.awt.Button; @@ -39,39 +39,48 @@ import java.lang.reflect.InvocationTargetException; import javax.media.opengl.GLAnimatorControl; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; import jogamp.nativewindow.jawt.JAWTUtil; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import com.jogamp.newt.Window; import com.jogamp.newt.awt.NewtCanvasAWT; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.newt.parenting.NewtAWTReparentingKeyAdapter; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.MiscUtils; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.util.Animator; -public class TestParentingOffscreenLayer02NewtCanvasAWT extends UITestCase { +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestOffscreenLayer02NewtCanvasAWT extends UITestCase { + static boolean singleBuffer = false; + static boolean useMSAA = false; + static boolean addComp = true; + static int swapInterval = 1; + static boolean shallUseOffscreenPBufferLayer = false; + static boolean noAnimation = false; static Dimension frameSize0; static Dimension frameSize1; static Dimension preferredGLSize; - static Dimension minGLSize; static long durationPerTest = 1000; + static boolean waitForKey = false; @BeforeClass public static void initClass() { frameSize0 = new Dimension(500,300); frameSize1 = new Dimension(800,600); preferredGLSize = new Dimension(400,200); - minGLSize = new Dimension(200,100); } private void setupFrameAndShow(final Frame f, java.awt.Component comp) throws InterruptedException, InvocationTargetException { - Container c = new Container(); c.setLayout(new BorderLayout()); c.add(new Button("north"), BorderLayout.NORTH); @@ -89,10 +98,12 @@ public class TestParentingOffscreenLayer02NewtCanvasAWT extends UITestCase { javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { + f.pack(); f.validate(); f.setVisible(true); }}); } + private void end(GLAnimatorControl actrl, final Frame f, Window w) throws InterruptedException, InvocationTargetException { actrl.stop(); javax.swing.SwingUtilities.invokeAndWait(new Runnable() { @@ -105,74 +116,81 @@ public class TestParentingOffscreenLayer02NewtCanvasAWT extends UITestCase { } @Test - public void testOnscreenLayerNewtCanvas_Onscreen() throws InterruptedException, InvocationTargetException { - if(!JAWTUtil.isOffscreenLayerRequired()) { - testOffscreenLayerNewtCanvas_Impl(false, false); - } else { - System.err.println("onscreen layer n/a"); - } + public void test01_GLDefault() throws InterruptedException, InvocationTargetException { + testOffscreenLayerNewtCanvas_Impl(null); } - // @Test - public void testOffscreenLayerNewtCanvas_OffscreenLayerWithOffscreenClass() throws InterruptedException, InvocationTargetException { - if(JAWTUtil.isOffscreenLayerSupported()) { - testOffscreenLayerNewtCanvas_Impl(true, true); - } else { - System.err.println("offscreen layer n/a"); - } + @Test + public void test02_GL3() throws InterruptedException, InvocationTargetException { + if( !GLProfile.isAvailable(GLProfile.GL3) ) { + System.err.println("GL3 n/a"); + return; + } + testOffscreenLayerNewtCanvas_Impl(GLProfile.get(GLProfile.GL3)); } - @Test - public void testOffscreenLayerNewtCanvas_OffscreenLayerWithOnscreenClass() throws InterruptedException, InvocationTargetException { - if(JAWTUtil.isOffscreenLayerSupported()) { - testOffscreenLayerNewtCanvas_Impl(true, false); - } else { + private void testOffscreenLayerNewtCanvas_Impl(GLProfile glp) throws InterruptedException, InvocationTargetException { + if(!JAWTUtil.isOffscreenLayerSupported()) { System.err.println("offscreen layer n/a"); + return; } - } - - private void testOffscreenLayerNewtCanvas_Impl(boolean offscreenLayer, boolean offscreenClass) throws InterruptedException, InvocationTargetException { final Frame frame1 = new Frame("AWT Parent Frame"); - GLCapabilities glCaps = new GLCapabilities(null); - if(offscreenClass) { - glCaps.setOnscreen(false); - glCaps.setPBuffer(true); + GLCapabilities caps = new GLCapabilities(glp); + if(singleBuffer) { + caps.setDoubleBuffered(false); } - - GLWindow glWindow1 = GLWindow.create(glCaps); + if(useMSAA) { + caps.setNumSamples(4); + caps.setSampleBuffers(true); + } + if(shallUseOffscreenPBufferLayer) { + caps.setPBuffer(true); + caps.setOnscreen(true); // get native NEWT Window, not OffscreenWindow + } + GLWindow glWindow1 = GLWindow.create(caps); final NewtCanvasAWT newtCanvasAWT1 = new NewtCanvasAWT(glWindow1); - newtCanvasAWT1.setShallUseOffscreenLayer(offscreenLayer); // trigger offscreen layer - if supported + newtCanvasAWT1.setShallUseOffscreenLayer(true); // trigger offscreen layer - if supported newtCanvasAWT1.setPreferredSize(preferredGLSize); - newtCanvasAWT1.setMinimumSize(minGLSize); + newtCanvasAWT1.setMinimumSize(preferredGLSize); + newtCanvasAWT1.setSize(preferredGLSize); - GLEventListener demo1 = new GearsES2(1); + GearsES2 demo1 = new GearsES2(swapInterval); + if(noAnimation) { + demo1.setDoRotation(false); + } setDemoFields(demo1, glWindow1, false); glWindow1.addGLEventListener(demo1); - glWindow1.addKeyListener(new NewtAWTReparentingKeyAdapter(frame1, newtCanvasAWT1, glWindow1)); + glWindow1.addKeyListener(new NewtAWTReparentingKeyAdapter(frame1, newtCanvasAWT1, glWindow1, null)); frame1.setSize(frameSize0); setupFrameAndShow(frame1, newtCanvasAWT1); Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow1, true)); Assert.assertEquals(true, AWTRobotUtil.waitForVisible(glWindow1, true)); Assert.assertEquals(newtCanvasAWT1.getNativeWindow(),glWindow1.getParent()); - Assert.assertEquals(JAWTUtil.isOffscreenLayerSupported() && offscreenLayer, - newtCanvasAWT1.isOffscreenLayerSurfaceEnabled()); - + Assert.assertEquals(true, newtCanvasAWT1.isOffscreenLayerSurfaceEnabled()); + GLAnimatorControl animator1 = new Animator(glWindow1); - animator1.start(); + if(!noAnimation) { + animator1.start(); + } + animator1.setUpdateFPSFrames(60, System.err); Thread.sleep(durationPerTest/2); javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { frame1.setSize(frameSize1); + frame1.pack(); frame1.validate(); }}); Thread.sleep(durationPerTest/2); end(animator1, frame1, glWindow1); + if( waitForKey ) { + UITestCase.waitForKey("Continue"); + } } public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) { @@ -200,9 +218,25 @@ public class TestParentingOffscreenLayer02NewtCanvasAWT extends UITestCase { for(int i=0; i<args.length; i++) { if(args[i].equals("-time")) { durationPerTest = atoi(args[++i]); + } else if(args[i].equals("-vsync")) { + i++; + swapInterval = MiscUtils.atoi(args[i], swapInterval); + } else if(args[i].equals("-layeredPBuffer")) { + shallUseOffscreenPBufferLayer = true; + } else if(args[i].equals("-msaa")) { + useMSAA = true; + } else if(args[i].equals("-single")) { + singleBuffer = true; + } else if(args[i].equals("-still")) { + noAnimation = true; + } else if(args[i].equals("-wait")) { + waitForKey = true; } } - String tstname = TestParentingOffscreenLayer02NewtCanvasAWT.class.getName(); + if(waitForKey) { + UITestCase.waitForKey("Start"); + } + String tstname = TestOffscreenLayer02NewtCanvasAWT.class.getName(); /* org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] { tstname, diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestPBufferDeadlockAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestPBufferDeadlockAWT.java index 3a25d1206..a1f0d3330 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestPBufferDeadlockAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestPBufferDeadlockAWT.java @@ -41,17 +41,21 @@ import jogamp.nativewindow.jawt.JAWTUtil; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import com.jogamp.common.util.RunnableTask; import com.jogamp.opengl.test.junit.util.UITestCase; +@SuppressWarnings("deprecation") +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestPBufferDeadlockAWT extends UITestCase { static GLProfile glp; static int width, height; @BeforeClass public static void initClass() { - glp = GLProfile.getGL2ES2(); + glp = GLProfile.getMaxFixedFunc(true); Assert.assertNotNull( glp ); width = 512; height = 512; @@ -80,7 +84,7 @@ public class TestPBufferDeadlockAWT extends UITestCase { Assert.assertTrue(EventQueue.isDispatchThread()); JAWTUtil.lockToolkit(); try { - final RunnableTask rTask = new RunnableTask(pbufferCreationAction, new Object(), false); + final RunnableTask rTask = new RunnableTask(pbufferCreationAction, new Object(), false, null); System.err.println("BB.0: "+rTask.getSyncObject()); synchronized (rTask.getSyncObject()) { System.err.println("BB.1: "+rTask.getSyncObject()); @@ -100,6 +104,7 @@ public class TestPBufferDeadlockAWT extends UITestCase { } }); Assert.assertTrue(done[0]); + pbuffer.destroy(); } @Test(timeout = 2000) // 2s timeout diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListAWT.java index 60502bab1..77657f6f1 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListAWT.java @@ -3,14 +3,14 @@ * * 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 @@ -20,21 +20,20 @@ * 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.jogl.acore; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLDrawableFactory; -import javax.media.opengl.GLPbuffer; +import javax.media.opengl.GLOffscreenAutoDrawable; import javax.media.opengl.GLProfile; import javax.media.opengl.awt.GLCanvas; -import com.jogamp.common.os.Platform; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.test.junit.util.UITestCase; @@ -48,22 +47,19 @@ import org.junit.Assert; import org.junit.Assume; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestSharedContextListAWT extends UITestCase { static GLProfile glp; static GLCapabilities caps; static int width, height; - GLPbuffer sharedDrawable; + GLOffscreenAutoDrawable sharedDrawable; Gears sharedGears; @BeforeClass public static void initClass() { - if(Platform.CPUFamily.X86 != Platform.CPU_ARCH.family) { // FIXME - // FIXME: Turns out on some mobile GL drivers and platforms - // using shared context is instable, Linux ARM (Omap4, Tegra2, Mesa3d, ..) - setTestSupported(false); - return; - } if(GLProfile.isAvailable(GLProfile.GL2)) { glp = GLProfile.get(GLProfile.GL2); Assert.assertNotNull(glp); @@ -77,7 +73,7 @@ public class TestSharedContextListAWT extends UITestCase { } private void initShared() { - sharedDrawable = GLDrawableFactory.getFactory(glp).createGLPbuffer(null, caps, null, width, height, null); + sharedDrawable = GLDrawableFactory.getFactory(glp).createOffscreenAutoDrawable(null, caps, null, width, height); Assert.assertNotNull(sharedDrawable); sharedGears = new Gears(); Assert.assertNotNull(sharedGears); @@ -90,8 +86,8 @@ public class TestSharedContextListAWT extends UITestCase { Assert.assertNotNull(sharedDrawable); sharedDrawable.destroy(); } - - protected void setFrameTitle(final Frame f, final boolean useShared) + + protected void setFrameTitle(final Frame f, final boolean useShared) throws InterruptedException, InvocationTargetException { javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { @@ -103,12 +99,13 @@ public class TestSharedContextListAWT extends UITestCase { protected GLCanvas runTestGL(final Frame frame, final Animator animator, final int x, final int y, final boolean useShared, final boolean vsync) throws InterruptedException, InvocationTargetException { - final GLCanvas glCanvas = new GLCanvas(caps, useShared ? sharedDrawable.getContext() : null); + final GLCanvas glCanvas = new GLCanvas(caps); Assert.assertNotNull(glCanvas); + glCanvas.setSharedAutoDrawable(sharedDrawable); frame.add(glCanvas); frame.setLocation(x, y); frame.setSize(width, height); - + Gears gears = new Gears(vsync ? 1 : 0); if(useShared) { gears.setGears(sharedGears.getGear1(), sharedGears.getGear2(), sharedGears.getGear3()); @@ -137,32 +134,28 @@ public class TestSharedContextListAWT extends UITestCase { final GLCanvas glc1 = runTestGL(f1, animator, 0, 0, true, false); int x0 = f1.getX(); int y0 = f1.getY(); - - final GLCanvas glc2 = runTestGL(f2, animator, + + final GLCanvas glc2 = runTestGL(f2, animator, x0+width, - y0+0, + y0+0, true, false); - - final GLCanvas glc3 = runTestGL(f3, animator, - x0+0, - y0+height, + + final GLCanvas glc3 = runTestGL(f3, animator, + x0+0, + y0+height, false, true); setFrameTitle(f1, true); setFrameTitle(f2, true); setFrameTitle(f3, false); - - animator.setUpdateFPSFrames(1, null); + + animator.setUpdateFPSFrames(1, null); animator.start(); while(animator.isAnimating() && animator.getTotalFPSDuration()<duration) { Thread.sleep(100); } animator.stop(); - // here we go again: On AMD/X11 the create/destroy sequence must be the same - // even though this is agains the chicken/egg logic - releaseShared(); - try { javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { @@ -180,10 +173,9 @@ public class TestSharedContextListAWT extends UITestCase { } catch( Throwable throwable ) { throwable.printStackTrace(); Assume.assumeNoException( throwable ); - } - - // see above .. - //releaseShared(); + } + + releaseShared(); } static long duration = 500; // ms diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListNEWT.java index 39367d1b0..09173fb24 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListNEWT.java @@ -3,14 +3,14 @@ * * 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 @@ -20,23 +20,22 @@ * 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.jogl.acore; import java.io.IOException; -import com.jogamp.common.os.Platform; import com.jogamp.newt.opengl.GLWindow; import javax.media.nativewindow.util.InsetsImmutable; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLDrawableFactory; -import javax.media.opengl.GLPbuffer; +import javax.media.opengl.GLOffscreenAutoDrawable; import javax.media.opengl.GLProfile; import com.jogamp.opengl.util.Animator; @@ -47,22 +46,19 @@ import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestSharedContextListNEWT extends UITestCase { static GLProfile glp; static GLCapabilities caps; static int width, height; - GLPbuffer sharedDrawable; + GLOffscreenAutoDrawable sharedDrawable; Gears sharedGears; @BeforeClass public static void initClass() { - if(Platform.CPUFamily.X86 != Platform.CPU_ARCH.family) { // FIXME - // FIXME: Turns out on some mobile GL drivers and platforms - // using shared context is instable, Linux ARM (Omap4, Tegra2, Mesa3d, ..) - setTestSupported(false); - return; - } if(GLProfile.isAvailable(GLProfile.GL2)) { glp = GLProfile.get(GLProfile.GL2); Assert.assertNotNull(glp); @@ -76,7 +72,7 @@ public class TestSharedContextListNEWT extends UITestCase { } private void initShared() { - sharedDrawable = GLDrawableFactory.getFactory(glp).createGLPbuffer(null, caps, null, width, height, null); + sharedDrawable = GLDrawableFactory.getFactory(glp).createOffscreenAutoDrawable(null, caps, null, width, height); Assert.assertNotNull(sharedDrawable); sharedGears = new Gears(); Assert.assertNotNull(sharedGears); @@ -123,27 +119,22 @@ public class TestSharedContextListNEWT extends UITestCase { Animator animator = new Animator(); GLWindow f1 = runTestGL(animator, 0, 0, true, false); InsetsImmutable insets = f1.getInsets(); - GLWindow f2 = runTestGL(animator, f1.getX()+width+insets.getTotalWidth(), + GLWindow f2 = runTestGL(animator, f1.getX()+width+insets.getTotalWidth(), f1.getY()+0, true, false); - GLWindow f3 = runTestGL(animator, f1.getX()+0, + GLWindow f3 = runTestGL(animator, f1.getX()+0, f1.getY()+height+insets.getTotalHeight(), false, true); - animator.setUpdateFPSFrames(1, null); + animator.setUpdateFPSFrames(1, null); animator.start(); while(animator.isAnimating() && animator.getTotalFPSDuration()<duration) { Thread.sleep(100); } animator.stop(); - // here we go again: On AMD/X11 the create/destroy sequence must be the same - // even though this is against the chicken/egg logic here .. - releaseShared(); - f1.destroy(); f2.destroy(); f3.destroy(); - // see above .. - // releaseShared(); + releaseShared(); } static long duration = 500; // ms @@ -160,7 +151,7 @@ public class TestSharedContextListNEWT extends UITestCase { /** BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); System.err.println("Press enter to continue"); - System.err.println(stdin.readLine()); */ + System.err.println(stdin.readLine()); */ org.junit.runner.JUnitCore.main(TestSharedContextListNEWT.class.getName()); } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListNEWT2.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListNEWT2.java index 7dca314bd..967c94ec6 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListNEWT2.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextListNEWT2.java @@ -30,7 +30,6 @@ package com.jogamp.opengl.test.junit.jogl.acore; import java.io.IOException; -import com.jogamp.common.os.Platform; import com.jogamp.newt.opengl.GLWindow; import javax.media.nativewindow.util.InsetsImmutable; @@ -45,7 +44,10 @@ import com.jogamp.opengl.test.junit.util.UITestCase; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestSharedContextListNEWT2 extends UITestCase { static GLProfile glp; static GLCapabilities caps; @@ -55,12 +57,6 @@ public class TestSharedContextListNEWT2 extends UITestCase { @BeforeClass public static void initClass() { - if(Platform.CPUFamily.X86 != Platform.CPU_ARCH.family) { // FIXME - // FIXME: Turns out on some mobile GL drivers and platforms - // using shared context is instable, Linux ARM (Omap4, Tegra2, Mesa3d, ..) - setTestSupported(false); - return; - } if(GLProfile.isAvailable(GLProfile.GL2)) { glp = GLProfile.get(GLProfile.GL2); Assert.assertNotNull(glp); @@ -122,12 +118,13 @@ public class TestSharedContextListNEWT2 extends UITestCase { @Test(timeout=10000) public void test01() throws InterruptedException { initShared(); - GLWindow f1 = runTestGL(new Animator(), 0, 0, true, false); - InsetsImmutable insets = f1.getInsets(); - GLWindow f2 = runTestGL(new Animator(), f1.getX()+width+insets.getTotalWidth(), - f1.getY()+0, true, false); - GLWindow f3 = runTestGL(new Animator(), f1.getX()+0, - f1.getY()+height+insets.getTotalHeight(), true, false); + + final GLWindow f1 = runTestGL(new Animator(), 0, 0, true, false); + final InsetsImmutable insets = f1.getInsets(); + final GLWindow f2 = runTestGL(new Animator(), f1.getX()+width+insets.getTotalWidth(), + f1.getY()+0, true, false); + final GLWindow f3 = runTestGL(new Animator(), f1.getX()+0, + f1.getY()+height+insets.getTotalHeight(), true, false); try { Thread.sleep(duration); @@ -135,16 +132,15 @@ public class TestSharedContextListNEWT2 extends UITestCase { e.printStackTrace(); } - // here we go again: On AMD/X11 the create/destroy sequence must be the same - // even though this is against the chicken/egg logic here .. - releaseShared(); - f1.destroy(); f2.destroy(); f3.destroy(); + + // f1.getAnimator().stop(); + // f2.getAnimator().stop(); + // f3.getAnimator().stop(); - // see above .. - // releaseShared(); + releaseShared(); } static long duration = 2000; // ms diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextNewtAWTBug523.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextNewtAWTBug523.java index bc2eddb9a..ff98d6f57 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextNewtAWTBug523.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextNewtAWTBug523.java @@ -3,14 +3,14 @@ * * 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 @@ -20,12 +20,12 @@ * 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.jogl.acore; import java.awt.Component; @@ -36,16 +36,19 @@ import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.nio.FloatBuffer; import java.nio.IntBuffer; +import java.util.HashSet; +import java.util.Set; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; +import javax.media.opengl.GL; import javax.media.opengl.GL2; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLEventListener; -import javax.media.opengl.GLPbuffer; +import javax.media.opengl.GLOffscreenAutoDrawable; import javax.media.opengl.GLProfile; import javax.media.opengl.awt.GLCanvas; import javax.media.opengl.glu.GLU; @@ -62,25 +65,29 @@ import javax.swing.event.ChangeListener; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import com.jogamp.common.nio.Buffers; -import com.jogamp.common.os.Platform; import com.jogamp.newt.awt.NewtCanvasAWT; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil.WindowClosingListener; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.util.GLBuffers; /** * TestSharedContextNewtAWTBug523 - * + * * Opens a single JFrame with two OpenGL windows and sliders to adjust the view orientation. * * Each window renders a red triangle and a blue triangle. * The red triangle is rendered using glBegin / glVertex / glEnd. - * The blue triangle is rendered using vertex buffer objects bound to a vertex array object. + * The blue triangle is rendered using vertex buffer objects. + * + * VAO's are not used to allow testing on OSX GL2 context! * * If static useNewt is true, then those windows are GLWindow objects in a NewtCanvasAWT. * If static useNewt is false, then those windows are GLCanvas objects. @@ -89,17 +96,18 @@ import com.jogamp.opengl.util.GLBuffers; * so that they share the vertex buffer and array objects and display lists. * If shareContext is false, then the two OpenGL windows each have their own context, and the blue * triangle fails to render in one of the windows. - * + * * The four test cases run through the four combinations of useNewt and shareContext. - * - * Similar test cases are {@link TestSharedContextListNEWT}, {@link TestSharedContextListAWT}, - * {@link TestSharedContextVBOES2NEWT} and {@link TestSharedContextVBOES1NEWT}. - * + * + * Similar test cases are {@link TestSharedContextListNEWT}, {@link TestSharedContextListAWT}, + * {@link TestSharedContextVBOES2NEWT1} and {@link TestSharedContextVBOES1NEWT}. + * */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestSharedContextNewtAWTBug523 extends UITestCase { static long durationPerTest = 1000; - + // counters for instances of event listener TwoTriangles // private static int instanceCounter; private static int initializationCounter; @@ -108,68 +116,87 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase { // The main thread waits twice on this semaphore to ensure both canvases have finished cleaning up. private static Semaphore disposalCompleteSemaphore = new Semaphore(0); - // Buffer objects can be shared across shared OpenGL context. + // Buffer objects can be shared across shared OpenGL context. // If we run with sharedContext, then the tests will use these shared buffer objects, // otherwise each event listener allocates its own buffer objects. - private static int [] sharedVertexBufferObjects = {0}; - private static int [] sharedIndexBufferObjects = {0}; - private static FloatBuffer sharedVertexBuffer; - private static IntBuffer sharedIndexBuffer; + private static volatile int[] sharedVertexBufferObjects = {0}; + private static volatile int[] sharedIndexBufferObjects = {0}; @BeforeClass public static void initClass() { - if(Platform.CPUFamily.X86 != Platform.CPU_ARCH.family) { // FIXME - // FIXME: Turns out on some mobile GL drivers and platforms - // using shared context is instable, Linux ARM (Omap4, Tegra2, Mesa3d, ..) - setTestSupported(false); - return; - } if(!GLProfile.isAvailable(GLProfile.GL2)) { setTestSupported(false); } } - - static private GLPbuffer initShared(GLCapabilities caps) { - GLPbuffer sharedDrawable = GLDrawableFactory.getFactory(caps.getGLProfile()).createGLPbuffer(null, caps, null, 64, 64, null); + + static private GLOffscreenAutoDrawable initShared(GLCapabilities caps) { + final GLOffscreenAutoDrawable sharedDrawable = GLDrawableFactory.getFactory(caps.getGLProfile()).createOffscreenAutoDrawable(null, caps, null, 64, 64); Assert.assertNotNull(sharedDrawable); // init and render one frame, which will setup the Gears display lists sharedDrawable.display(); + final GLContext ctx = sharedDrawable.getContext(); + Assert.assertNotNull("Shared drawable's ctx is null", ctx); + Assert.assertTrue("Shared drawable's ctx is not created", ctx.isCreated()); return sharedDrawable; } - static private void releaseShared(GLPbuffer sharedDrawable) { + static private void releaseShared(GLOffscreenAutoDrawable sharedDrawable) { if(null != sharedDrawable) { sharedDrawable.destroy(); } } - + // inner class that implements the event listener static class TwoTriangles implements GLEventListener { boolean useShared; int canvasWidth; int canvasHeight; - private float boundsRadius = 2f; + private final float boundsRadius = 2f; private float viewDistance; private float viewDistanceFactor = 1.0f; private float xAxisRotation; private float yAxisRotation; - private float viewFovDegrees = 15f; - - // vertex array objects cannot be shared across open gl canvases; - // - // However, display lists can be shared across GLCanvas instances (if those canvases are initialized with the same GLContext), - // including a display list created in one context that uses a VAO. - private int [] vertexArrayObjects = {0}; + private final float viewFovDegrees = 15f; // Buffer objects can be shared across canvas instances, if those canvases are initialized with the same GLContext. // If we run with sharedBufferObjects true, then the tests will use these shared buffer objects. // If we run with sharedBufferObjects false, then each event listener allocates its own buffer objects. - private int [] privateVertexBufferObjects = {0}; - private int [] privateIndexBufferObjects = {0}; - private FloatBuffer privateVertexBuffer; - private IntBuffer privateIndexBuffer; - + private final int [] privateVertexBufferObjects = {0}; + private final int [] privateIndexBufferObjects = {0}; + + public static int createVertexBuffer(GL2 gl2) { + final FloatBuffer vertexBuffer = GLBuffers.newDirectFloatBuffer(18); + vertexBuffer.put(new float[]{ + 1.0f, -0.5f, 0f, // vertex 1 + 0f, 0f, 1f, // normal 1 + 1.5f, -0.5f, 0f, // vertex 2 + 0f, 0f, 1f, // normal 2 + 1.0f, 0.5f, 0f, // vertex 3 + 0f, 0f, 1f // normal 3 + }); + vertexBuffer.position(0); + + final int[] vbo = { 0 }; + gl2.glGenBuffers(1, vbo, 0); + gl2.glBindBuffer(GL2.GL_ARRAY_BUFFER, vbo[0]); + gl2.glBufferData(GL2.GL_ARRAY_BUFFER, vertexBuffer.capacity() * Buffers.SIZEOF_FLOAT, vertexBuffer, GL2.GL_STATIC_DRAW); + gl2.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0); + return vbo[0]; + } + public static int createVertexIndexBuffer(GL2 gl2) { + final IntBuffer indexBuffer = GLBuffers.newDirectIntBuffer(3); + indexBuffer.put(new int[]{0, 1, 2}); + indexBuffer.position(0); + + final int[] vbo = { 0 }; + gl2.glGenBuffers(1, vbo, 0); + gl2.glBindBuffer(GL2.GL_ELEMENT_ARRAY_BUFFER, vbo[0]); + gl2.glBufferData(GL2.GL_ELEMENT_ARRAY_BUFFER, indexBuffer.capacity() * Buffers.SIZEOF_INT, indexBuffer, GL2.GL_STATIC_DRAW); + gl2.glBindBuffer(GL2.GL_ELEMENT_ARRAY_BUFFER, 0); + return vbo[0]; + } + TwoTriangles (int canvasWidth, int canvasHeight, boolean useShared) { // instanceNum = instanceCounter++; this.canvasWidth = canvasWidth; @@ -202,49 +229,29 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase { gl2.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // the first instance of TwoTriangles initializes the shared buffer objects; - // synchronizing to deal with potential liveness issues if the data is intialized from one thread and used on another + // synchronizing to deal with potential liveness issues if the data is initialized from one thread and used on another synchronized (this) { - gl2.glGenVertexArrays(1, vertexArrayObjects, 0); - - gl2.glBindVertexArray(vertexArrayObjects[0]); - - // use either the shared or private vertex buffers, as + // use either the shared or private vertex buffers, as int [] vertexBufferObjects; int [] indexBufferObjects; - FloatBuffer vertexBuffer; - IntBuffer indexBuffer; // if (useShared) { + System.err.println("Using shared VBOs on slave 0x"+Integer.toHexString(hashCode())); vertexBufferObjects = sharedVertexBufferObjects; indexBufferObjects = sharedIndexBufferObjects; - vertexBuffer = sharedVertexBuffer; - indexBuffer = sharedIndexBuffer; } else { + System.err.println("Using local VBOs on slave 0x"+Integer.toHexString(hashCode())); vertexBufferObjects = privateVertexBufferObjects; indexBufferObjects = privateIndexBufferObjects; - vertexBuffer = privateVertexBuffer; - indexBuffer = privateIndexBuffer; } - + // if buffer sharing is enabled, then the first of the two event listeners to be // initialized will allocate the buffers, and the other will re-use the allocated one if (vertexBufferObjects[0] == 0) { - vertexBuffer = GLBuffers.newDirectFloatBuffer(18); - vertexBuffer.put(new float[]{ - 1.0f, -0.5f, 0f, // vertex 1 - 0f, 0f, 1f, // normal 1 - 1.5f, -0.5f, 0f, // vertex 2 - 0f, 0f, 1f, // normal 2 - 1.0f, 0.5f, 0f, // vertex 3 - 0f, 0f, 1f // normal 3 - }); - vertexBuffer.position(0); - - gl2.glGenBuffers(1, vertexBufferObjects, 0); - gl2.glBindBuffer(GL2.GL_ARRAY_BUFFER, vertexBufferObjects[0]); - gl2.glBufferData(GL2.GL_ARRAY_BUFFER, vertexBuffer.capacity() * Buffers.SIZEOF_FLOAT, vertexBuffer, GL2.GL_STATIC_DRAW); + System.err.println("Creating vertex VBO on slave 0x"+Integer.toHexString(hashCode())); + vertexBufferObjects[0] = createVertexBuffer(gl2); } - + // A check in the case that buffer sharing is enabled but context sharing is not enabled -- in that // case, the buffer objects are not shareable, and the blue triangle cannot be rendereds. // Furthermore, although the calls to bind and draw elements do not cause an error from glGetError @@ -259,24 +266,22 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase { // gl2.glEnableClientState(GL2.GL_NORMAL_ARRAY); gl2.glNormalPointer(GL2.GL_FLOAT, 6 * GLBuffers.SIZEOF_FLOAT, 3 * GLBuffers.SIZEOF_FLOAT); + } else { + System.err.println("Vertex VBO is not a buffer on slave 0x"+Integer.toHexString(hashCode())); } if (indexBufferObjects[0] == 0) { - indexBuffer = GLBuffers.newDirectIntBuffer(3); - indexBuffer.put(new int[]{0, 1, 2}); - indexBuffer.position(0); - - gl2.glGenBuffers(1, indexBufferObjects, 0); - gl2.glBindBuffer(GL2.GL_ELEMENT_ARRAY_BUFFER, indexBufferObjects[0]); - gl2.glBufferData(GL2.GL_ELEMENT_ARRAY_BUFFER, indexBuffer.capacity() * Buffers.SIZEOF_INT, indexBuffer, GL2.GL_STATIC_DRAW); + System.err.println("Creating index VBO on slave 0x"+Integer.toHexString(hashCode())); + indexBufferObjects[0] = createVertexIndexBuffer(gl2); } - // again, a check in the case that buffer sharing is enabled but context sharing is not enabled + // again, a check in the case that buffer sharing is enabled but context sharing is not enabled if (gl2.glIsBuffer(indexBufferObjects[0])) { gl2.glBindBuffer(GL2.GL_ELEMENT_ARRAY_BUFFER, indexBufferObjects[0]); + } else { + System.err.println("Index VBO is not a buffer on slave 0x"+Integer.toHexString(hashCode())); } - gl2.glBindVertexArray(0); gl2.glBindBuffer(GL2.GL_ELEMENT_ARRAY_BUFFER, 0); gl2.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0); gl2.glDisableClientState(GL2.GL_VERTEX_ARRAY); @@ -297,13 +302,9 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase { GL2 gl2 = drawable.getGL().getGL2(); - gl2.glDeleteVertexArrays(1, vertexArrayObjects, 0); - vertexArrayObjects[0] = 0; - logAnyErrorCodes(gl2, "display"); - - // release shared resources + // release shared resources if (initializationCounter == 0 || !useShared) { - // use either the shared or private vertex buffers, as + // use either the shared or private vertex buffers, as int [] vertexBufferObjects; int [] indexBufferObjects; if (useShared) { @@ -315,10 +316,11 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase { } gl2.glDeleteBuffers(1, vertexBufferObjects, 0); + logAnyErrorCodes(this, gl2, "dispose.2"); gl2.glDeleteBuffers(1, indexBufferObjects, 0); + logAnyErrorCodes(this, gl2, "dispose.3"); vertexBufferObjects[0] = 0; indexBufferObjects[0] = 0; - logAnyErrorCodes(gl2, "display"); } // release the main thread once for each disposal @@ -333,7 +335,7 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase { // wait until all instances are initialized before attempting to draw using the // vertex array object, because the buffers are allocated in init and when the - // buffers are shared, we need to ensure that they are allocated before trying to use thems + // buffers are shared, we need to ensure that they are allocated before trying to use them synchronized (this) { if (initializationCounter != 2) { return; @@ -343,6 +345,8 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase { GL2 gl2 = drawable.getGL().getGL2(); GLU glu = new GLU(); + logAnyErrorCodes(this, gl2, "display.0"); + // Clear the drawing area gl2.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT); @@ -367,6 +371,8 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase { gl2.glDisable(GL2.GL_CULL_FACE); gl2.glEnable(GL2.GL_DEPTH_TEST); + logAnyErrorCodes(this, gl2, "display.1"); + // draw the triangles drawTwoTriangles(gl2); @@ -376,7 +382,7 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase { // Flush all drawing operations to the graphics card gl2.glFlush(); - logAnyErrorCodes(gl2, "display"); + logAnyErrorCodes(this, gl2, "display.X"); } public void drawTwoTriangles(GL2 gl2) { @@ -392,13 +398,15 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase { gl2.glNormal3d(0, 0, 1); gl2.glEnd(); + logAnyErrorCodes(this, gl2, "drawTwoTriangles.1"); + // draw the blue triangle using a vertex array object, sharing the vertex and index buffer objects across // contexts; if context sharing is not initialized, then one window will simply have to live without a blue triangle // - // synchronizing to deal with potential liveness issues if the data is intialized from one + // synchronizing to deal with potential liveness issues if the data is initialized from one // thread and used on another - boolean vaoBound = false; - // use either the shared or private vertex buffers, as + boolean vboBound = false; + // use either the shared or private vertex buffers, as int [] vertexBufferObjects; int [] indexBufferObjects; synchronized (this) { @@ -410,44 +418,65 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase { indexBufferObjects = privateIndexBufferObjects; } } // synchronized (this) - + // A check in the case that buffer sharing is enabled but context sharing is not enabled -- in that // case, the buffer objects are not shareable, and the blue triangle cannot be rendereds. // Furthermore, although the calls to bind and draw elements do not cause an error from glGetError // when this check is removed, true blue triangle is not rendered anyways, and more importantly, // I found that with my system glDrawElements causes a runtime exception 50% of the time. Executing the binds // to unshareable buffers sets up glDrawElements for unpredictable crashes -- sometimes it does, sometimes not. - if (gl2.glIsVertexArray(vertexArrayObjects[0]) && - gl2.glIsBuffer(indexBufferObjects[0]) && gl2.glIsBuffer(vertexBufferObjects[0])) { - gl2.glBindVertexArray(vertexArrayObjects[0]); + final boolean isVBO1 = gl2.glIsBuffer(indexBufferObjects[0]); + final boolean isVBO2 = gl2.glIsBuffer(vertexBufferObjects[0]); + final boolean useVBO = isVBO1 && isVBO2; + if ( useVBO ) { + gl2.glBindBuffer(GL2.GL_ARRAY_BUFFER, vertexBufferObjects[0]); gl2.glBindBuffer(GL2.GL_ELEMENT_ARRAY_BUFFER, indexBufferObjects[0]); - vaoBound = true; + + gl2.glEnableClientState(GL2.GL_VERTEX_ARRAY); + // gl2.glVertexPointer(3, GL2.GL_FLOAT, 6 * GLBuffers.SIZEOF_FLOAT, 0); + gl2.glEnableClientState(GL2.GL_NORMAL_ARRAY); + // gl2.glNormalPointer(GL2.GL_FLOAT, 6 * GLBuffers.SIZEOF_FLOAT, 3 * GLBuffers.SIZEOF_FLOAT); + vboBound = true; } - - logAnyErrorCodes(gl2, "drawTwoTriangles"); + // System.err.println("XXX VBO bound "+vboBound+"[ vbo1 "+isVBO1+", vbo2 "+isVBO2+"]"); + + logAnyErrorCodes(this, gl2, "drawTwoTriangles.2"); - if (vaoBound) { + if (vboBound) { gl2.glColor3f(0f, 0f, 1f); gl2.glDrawElements(GL2.GL_TRIANGLES, 3, GL2.GL_UNSIGNED_INT, 0); - gl2.glBindVertexArray(0); + gl2.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0); gl2.glBindBuffer(GL2.GL_ELEMENT_ARRAY_BUFFER, 0); - } + gl2.glDisableClientState(GL2.GL_VERTEX_ARRAY); + gl2.glDisableClientState(GL2.GL_NORMAL_ARRAY); + } + + logAnyErrorCodes(this, gl2, "drawTwoTriangles.3"); } public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) { } - + } // inner class TwoTriangles - public static void logAnyErrorCodes(GL2 gl2, String prefix) { - int glError = gl2.glGetError(); - while (glError != GL2.GL_NO_ERROR) { - System.err.println(prefix + ", OpenGL error: 0x" + Integer.toHexString(glError)); - glError = gl2.glGetError(); + private static final Set<String> errorSet = new HashSet<String>(); + + public static void logAnyErrorCodes(Object obj, GL gl, String prefix) { + final int glError = gl.glGetError(); + if(glError != GL.GL_NO_ERROR) { + final String errStr = "GL-Error: "+prefix + " on obj 0x"+Integer.toHexString(obj.hashCode())+", OpenGL error: 0x" + Integer.toHexString(glError); + if( errorSet.add(errStr) ) { + System.err.println(errStr); + Thread.dumpStack(); + } } - int status = gl2.glCheckFramebufferStatus(GL2.GL_FRAMEBUFFER); - if (status != GL2.GL_FRAMEBUFFER_COMPLETE) { - System.err.println(prefix + ", glCheckFramebufferStatus: 0x" + Integer.toHexString(status)); + final int status = gl.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER); + if (status != GL.GL_FRAMEBUFFER_COMPLETE) { + final String errStr = "GL-Error: "+prefix + " on obj 0x"+Integer.toHexString(obj.hashCode())+", glCheckFramebufferStatus: 0x" + Integer.toHexString(status); + if( errorSet.add(errStr) ) { + System.err.println(errStr); + Thread.dumpStack(); + } } } @@ -489,22 +518,22 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase { } @Test - public void testContextSharingCreateVisibleDestroy1() throws InterruptedException, InvocationTargetException { + public void test01UseAWTNotShared() throws InterruptedException, InvocationTargetException { testContextSharingCreateVisibleDestroy(false, false); } @Test - public void testContextSharingCreateVisibleDestroy2() throws InterruptedException, InvocationTargetException { + public void test02UseAWTSharedContext() throws InterruptedException, InvocationTargetException { testContextSharingCreateVisibleDestroy(false, true); } @Test - public void testContextSharingCreateVisibleDestroy3() throws InterruptedException, InvocationTargetException { + public void test10UseNEWTNotShared() throws InterruptedException, InvocationTargetException { testContextSharingCreateVisibleDestroy(true, false); } @Test - public void testContextSharingCreateVisibleDestroy4() throws InterruptedException, InvocationTargetException { + public void test11UseNEWTSharedContext() throws InterruptedException, InvocationTargetException { testContextSharingCreateVisibleDestroy(true, true); } @@ -514,6 +543,8 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase { */ public void testContextSharingCreateVisibleDestroy(final boolean useNewt, final boolean shareContext) throws InterruptedException, InvocationTargetException { final JFrame frame = new JFrame("Simple JOGL App for testing context sharing"); + final WindowClosingListener awtClosingListener = AWTRobotUtil.addClosingListener(frame); + // // GLDrawableFactory factory = GLDrawableFactory.getFactory(GLProfile.get(GLProfile.GL2)); // GLContext sharedContext = factory.getOrCreateSharedContext(factory.getDefaultDevice()); @@ -522,16 +553,13 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase { glCapabilities.setSampleBuffers(true); glCapabilities.setNumSamples(4); - final GLPbuffer sharedDrawable; - final GLContext sharedContext; + final GLOffscreenAutoDrawable sharedDrawable; if(shareContext) { sharedDrawable = initShared(glCapabilities); - sharedContext = sharedDrawable.getContext(); } else { sharedDrawable = null; - sharedContext = null; } - + final TwoTriangles eventListener1 = new TwoTriangles(640, 480, shareContext); final TwoTriangles eventListener2 = new TwoTriangles(320, 480, shareContext); @@ -542,12 +570,17 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase { if (useNewt) { GLWindow glWindow1 = GLWindow.create(glCapabilities); - glWindow1.setSharedContext(sharedContext); + if(shareContext) { + glWindow1.setSharedAutoDrawable(sharedDrawable); + } NewtCanvasAWT newtCanvasAWT1 = new NewtCanvasAWT(glWindow1); newtCanvasAWT1.setPreferredSize(new Dimension(eventListener1.canvasWidth, eventListener1.canvasHeight)); glWindow1.addGLEventListener(eventListener1); // GLWindow glWindow2 = GLWindow.create(glCapabilities); + if(shareContext) { + glWindow2.setSharedAutoDrawable(sharedDrawable); + } NewtCanvasAWT newtCanvasAWT2 = new NewtCanvasAWT(glWindow2); newtCanvasAWT2.setPreferredSize(new Dimension(eventListener2.canvasWidth, eventListener2.canvasHeight)); glWindow2.addGLEventListener(eventListener2); @@ -564,8 +597,10 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase { final GLCanvas canvas2; if (shareContext) { - canvas1 = new GLCanvas(glCapabilities, sharedContext); - canvas2 = new GLCanvas(glCapabilities, sharedContext); + canvas1 = new GLCanvas(glCapabilities); + canvas1.setSharedAutoDrawable(sharedDrawable); + canvas2 = new GLCanvas(glCapabilities); + canvas2.setSharedAutoDrawable(sharedDrawable); } else { canvas1 = new GLCanvas(glCapabilities); canvas2 = new GLCanvas(glCapabilities); @@ -623,8 +658,8 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase { viewDistanceFactorSlider.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { - eventListener1.setViewDistanceFactor((float) viewDistanceFactorSlider.getValue() / 10.0f); - eventListener2.setViewDistanceFactor((float) viewDistanceFactorSlider.getValue() / 10.0f); + eventListener1.setViewDistanceFactor(viewDistanceFactorSlider.getValue() / 10.0f); + eventListener2.setViewDistanceFactor(viewDistanceFactorSlider.getValue() / 10.0f); } }); JLabel viewDistanceFactorLabel = new JLabel("View Distance Factor"); @@ -706,7 +741,7 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase { while(animator.isAnimating() && animator.getTotalFPSDuration() < durationPerTest) { Thread.sleep(100); } - AWTRobotUtil.closeWindow(frame, true); + AWTRobotUtil.closeWindow(frame, true, awtClosingListener); boolean windowClosed = closingSemaphore.tryAcquire(5000, TimeUnit.MILLISECONDS); Assert.assertEquals(true, windowClosed); } catch (InterruptedException e) { @@ -754,7 +789,7 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase { } Assert.assertEquals(true, disposalSuccesses == 2); - + releaseShared(sharedDrawable); } @@ -772,9 +807,9 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase { if (++i < args.length) { durationPerTest = atoi(args[i]); } - } + } } - + String testname = TestSharedContextNewtAWTBug523.class.getName(); org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] { testname, diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES1NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES1NEWT.java index 707bd5a9b..0f4f8fc34 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES1NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES1NEWT.java @@ -3,14 +3,14 @@ * * 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 @@ -20,47 +20,65 @@ * 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.jogl.acore; -import com.jogamp.common.os.Platform; import com.jogamp.newt.opengl.GLWindow; import javax.media.nativewindow.util.InsetsImmutable; +import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; import javax.media.opengl.GLDrawableFactory; -import javax.media.opengl.GLPbuffer; import javax.media.opengl.GLProfile; -import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.GLAutoDrawableDelegate; +import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.jogl.demos.es1.GearsES1; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +/** + * Sharing the VBO of 3 GearsES1 instances, each in their own GLWindow. + * <p> + * This is achieved by creating a <i>master</i> GLContext to an offscreen invisible GLAutoDrawable, + * which is then shared by the 3 GLContext of the three GLWindow instances. + * </p> + * <p> + * The original VBO is created by attaching a GearsES1 instance to + * the <i>master</i> GLAutoDrawable and initializing it. + * </p> + * <p> + * Above method allows random creation of all GLWindow instances. + * </p> + * <p> + * One animator is being used, hence the GLWindow, GLDrawable and GLContext + * creation of all 3 GLWindows is sequential. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestSharedContextVBOES1NEWT extends UITestCase { static GLProfile glp; static GLCapabilities caps; static int width, height; - GLPbuffer sharedDrawable; + GLAutoDrawable sharedDrawable; GearsES1 sharedGears; @BeforeClass public static void initClass() { - if(Platform.CPUFamily.X86 != Platform.CPU_ARCH.family) { // FIXME - // FIXME: Turns out on some mobile GL drivers and platforms - // using shared context is instable, Linux ARM (Omap4, Tegra2, Mesa3d, ..) - setTestSupported(false); - return; - } if(GLProfile.isAvailable(GLProfile.GL2ES1)) { glp = GLProfile.get(GLProfile.GL2ES1); Assert.assertNotNull(glp); @@ -73,14 +91,22 @@ public class TestSharedContextVBOES1NEWT extends UITestCase { } } - private void initShared() { - sharedDrawable = GLDrawableFactory.getFactory(glp).createGLPbuffer(null, caps, null, width, height, null); + private void initShared() throws InterruptedException { + GLDrawable dummyDrawable = GLDrawableFactory.getFactory(glp).createDummyDrawable(null, true /* createNewDevice */, caps, null); + dummyDrawable.setRealized(true); + sharedDrawable = new GLAutoDrawableDelegate(dummyDrawable, null, null, true /*ownDevice*/, null) { }; Assert.assertNotNull(sharedDrawable); + Assert.assertTrue(AWTRobotUtil.waitForRealized(sharedDrawable, true)); + sharedGears = new GearsES1(); Assert.assertNotNull(sharedGears); sharedDrawable.addGLEventListener(sharedGears); // init and render one frame, which will setup the Gears display lists sharedDrawable.display(); + final GLContext ctxM = sharedDrawable.getContext(); + Assert.assertTrue("Master ctx not created", AWTRobotUtil.waitForContextCreated(sharedDrawable, true)); + Assert.assertTrue("Master Ctx is shared before shared creation", !ctxM.isShared()); + Assert.assertTrue("Master Gears is shared", !sharedGears.usesSharedGears()); } private void releaseShared() { @@ -91,6 +117,7 @@ public class TestSharedContextVBOES1NEWT extends UITestCase { protected GLWindow runTestGL(Animator animator, int x, int y, boolean useShared, boolean vsync) throws InterruptedException { GLWindow glWindow = GLWindow.create(caps); Assert.assertNotNull(glWindow); + glWindow.setPosition(x, y); glWindow.setTitle("Shared Gears NEWT Test: "+x+"/"+y+" shared "+useShared); if(useShared) { glWindow.setSharedContext(sharedDrawable.getContext()); @@ -100,7 +127,7 @@ public class TestSharedContextVBOES1NEWT extends UITestCase { GearsES1 gears = new GearsES1(vsync ? 1 : 0); if(useShared) { - gears.setGears(sharedGears.getGear1(), sharedGears.getGear2(), sharedGears.getGear3()); + gears.setSharedGearsObjects(sharedGears.getGear1(), sharedGears.getGear2(), sharedGears.getGear3()); } glWindow.addGLEventListener(gears); @@ -109,9 +136,17 @@ public class TestSharedContextVBOES1NEWT extends UITestCase { glWindow.setVisible(true); Assert.assertTrue(AWTRobotUtil.waitForRealized(glWindow, true)); Assert.assertTrue(AWTRobotUtil.waitForVisible(glWindow, true)); - - glWindow.setPosition(x, y); - + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(glWindow, true)); + + System.err.println("Master Context: "); + MiscUtils.dumpSharedGLContext(sharedDrawable.getContext()); + System.err.println("New Context: "); + MiscUtils.dumpSharedGLContext(glWindow.getContext()); + if( useShared ) { + Assert.assertEquals("Master Context not shared as expected", true, sharedDrawable.getContext().isShared()); + } + Assert.assertEquals("New Context not shared as expected", useShared, glWindow.getContext().isShared()); + Assert.assertEquals("Gears is not shared as expected", useShared, gears.usesSharedGears()); return glWindow; } @@ -121,27 +156,22 @@ public class TestSharedContextVBOES1NEWT extends UITestCase { Animator animator = new Animator(); GLWindow f1 = runTestGL(animator, 0, 0, true, false); InsetsImmutable insets = f1.getInsets(); - GLWindow f2 = runTestGL(animator, f1.getX()+width+insets.getTotalWidth(), + GLWindow f2 = runTestGL(animator, f1.getX()+width+insets.getTotalWidth(), f1.getY()+0, true, false); - GLWindow f3 = runTestGL(animator, f1.getX()+0, - f1.getY()+height+insets.getTotalHeight(), false, true); - animator.setUpdateFPSFrames(1, null); + GLWindow f3 = runTestGL(animator, f1.getX()+0, + f1.getY()+height+insets.getTotalHeight(), false, true); + animator.setUpdateFPSFrames(1, null); animator.start(); while(animator.isAnimating() && animator.getTotalFPSDuration()<duration) { Thread.sleep(100); } animator.stop(); - // here we go again: On AMD/X11 the create/destroy sequence must be the same - // even though this is agains the chicken/egg logic here .. - releaseShared(); - f1.destroy(); f2.destroy(); f3.destroy(); - // see above .. - // releaseShared(); + releaseShared(); } static long duration = 500; // ms diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2AWT3.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2AWT3.java new file mode 100644 index 000000000..3b576fabd --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2AWT3.java @@ -0,0 +1,413 @@ +/** + * 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.jogl.acore; + +import java.awt.Frame; +import java.lang.reflect.InvocationTargetException; +import java.util.List; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; + +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +/** + * Sharing the VBO of 3 GearsES2 instances, each in their own AWT GLCanvas. + * <p> + * This is achieved by using the 1st GLCanvas as the <i>master</i> + * and using the build-in blocking mechanism to postpone creation + * of the 2nd and 3rd GLCanvas until the 1st GLCanvas's GLContext becomes created. + * </p> + * <p> + * Above method allows random creation of the 1st GLCanvas, which triggers + * creation of the <i>dependent</i> other GLCanvas sharing it's GLContext. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestSharedContextVBOES2AWT3 extends UITestCase { + static GLProfile glp; + static GLCapabilities caps; + static int width, height; + + @BeforeClass + public static void initClass() { + if(GLProfile.isAvailable(GLProfile.GL2ES2)) { + glp = GLProfile.get(GLProfile.GL2ES2); + Assert.assertNotNull(glp); + caps = new GLCapabilities(glp); + Assert.assertNotNull(caps); + width = 256; + height = 256; + } else { + setTestSupported(false); + } + } + + protected GLCanvas createGLCanvas(final Frame frame, int x, int y, GearsES2 gears) throws InterruptedException { + final GLCanvas glCanvas = new GLCanvas(caps); + Assert.assertNotNull(glCanvas); + glCanvas.addGLEventListener(gears); + frame.add(glCanvas); + frame.setLocation(x, y); + frame.setSize(width, height); + frame.setTitle("AWT GLCanvas Shared Gears Test: "+x+"/"+y+" shared true"); + return glCanvas; + } + + @Test + public void test01SyncedOneAnimatorCleanDtorOrder() throws InterruptedException, InvocationTargetException { + syncedOneAnimator(true); + } + + @Test + public void test02SyncedOneAnimatorDirtyDtorOrder() throws InterruptedException, InvocationTargetException { + syncedOneAnimator(false); + } + + public void syncedOneAnimator(final boolean destroyCleanOrder) throws InterruptedException, InvocationTargetException { + final Frame f1 = new Frame(); + final Animator animator = new Animator(); + final GearsES2 g1 = new GearsES2(0); + final GLCanvas c1 = createGLCanvas(f1, 0, 0, g1); + animator.add(c1); + + final Frame f2 = new Frame(); + final GearsES2 g2 = new GearsES2(0); + g2.setSharedGears(g1); + final GLCanvas c2 = createGLCanvas(f2, f1.getX()+width, + f1.getY()+0, g2); + c2.setSharedAutoDrawable(c1); + animator.add(c2); + + final Frame f3 = new Frame(); + final GearsES2 g3 = new GearsES2(0); + g3.setSharedGears(g1); + final GLCanvas c3 = createGLCanvas(f3, f1.getX()+0, + f1.getY()+height, g3); + c3.setSharedAutoDrawable(c1); + animator.add(c3); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + f2.setVisible(true); // shall wait until f1 is ready + f1.setVisible(true); // master .. + f3.setVisible(true); // shall wait until f1 is ready + } } ); + animator.start(); // kicks off GLContext .. and hence gears of f2 + f3 completion + + Thread.sleep(1000/60*10); // wait ~10 frames giving a chance to create (blocking until master share is valid) + + Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c1, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c1, true)); + Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true)); + + Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c2, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c2, true)); + Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true)); + + Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c3, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c3, true)); + Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true)); + + final GLContext ctx1 = c1.getContext(); + final GLContext ctx2 = c2.getContext(); + final GLContext ctx3 = c3.getContext(); + { + final List<GLContext> ctx1Shares = ctx1.getCreatedShares(); + final List<GLContext> ctx2Shares = ctx2.getCreatedShares(); + final List<GLContext> ctx3Shares = ctx3.getCreatedShares(); + System.err.println("XXX-C-3.1:"); + MiscUtils.dumpSharedGLContext(ctx1); + System.err.println("XXX-C-3.2:"); + MiscUtils.dumpSharedGLContext(ctx2); + System.err.println("XXX-C-3.3:"); + MiscUtils.dumpSharedGLContext(ctx3); + + Assert.assertTrue("Ctx1 is not shared", ctx1.isShared()); + Assert.assertTrue("Ctx2 is not shared", ctx2.isShared()); + Assert.assertTrue("Ctx3 is not shared", ctx3.isShared()); + Assert.assertEquals("Ctx1 has unexpected number of created shares", 2, ctx1Shares.size()); + Assert.assertEquals("Ctx2 has unexpected number of created shares", 2, ctx2Shares.size()); + Assert.assertEquals("Ctx3 has unexpected number of created shares", 2, ctx3Shares.size()); + } + + Assert.assertTrue("Gears1 is shared", !g1.usesSharedGears()); + Assert.assertTrue("Gears2 is not shared", g2.usesSharedGears()); + Assert.assertTrue("Gears3 is not shared", g3.usesSharedGears()); + + try { + Thread.sleep(duration); + } catch(Exception e) { + e.printStackTrace(); + } + // Stopped animator allows native windowing system 'repaint' event + // to trigger GLAD 'display' + animator.stop(); + Assert.assertEquals(false, animator.isAnimating()); + + if( destroyCleanOrder ) { + System.err.println("XXX Destroy in clean order NOW"); + } else { + System.err.println("XXX Destroy in creation order NOW - Driver Impl. Ma trigger driver Bug i.e. not postponing GL ctx destruction after releasing all refs."); + } + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + try { + if( destroyCleanOrder ) { + f3.dispose(); + } else { + f1.dispose(); + } + } catch (Throwable t) { + throw new RuntimeException(t); + } + }}); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + try { + if( destroyCleanOrder ) { + f2.dispose(); + } else { + f2.dispose(); + } + } catch (Throwable t) { + throw new RuntimeException(t); + } + }}); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + try { + if( destroyCleanOrder ) { + f1.dispose(); + } else { + f3.dispose(); + } + } catch (Throwable t) { + throw new RuntimeException(t); + } + }}); + + Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, false)); + } + + @Test + public void test11AsyncEachAnimatorCleanDtorOrder() throws InterruptedException, InvocationTargetException { + syncedOneAnimator(true); + } + + @Test + public void test12AsyncEachAnimatorDirtyDtorOrder() throws InterruptedException, InvocationTargetException { + asyncEachOneAnimator(false); + } + + public void asyncEachOneAnimator(final boolean destroyCleanOrder) throws InterruptedException, InvocationTargetException { + final Frame f1 = new Frame(); + final Animator a1 = new Animator(); + final GearsES2 g1 = new GearsES2(0); + final GLCanvas c1 = createGLCanvas(f1, 0, 0, g1); + a1.add(c1); + a1.start(); + // f1.setVisible(true); // we do this post f2 .. to test pending creation! + + final Frame f2 = new Frame(); + final Animator a2 = new Animator(); + final GearsES2 g2 = new GearsES2(0); + g2.setSharedGears(g1); + final GLCanvas c2 = createGLCanvas(f2, f1.getX()+width, f1.getY()+0, g2); + c2.setSharedAutoDrawable(c1); + a2.add(c2); + a2.start(); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + f2.setVisible(true); + } } ); + + Thread.sleep(200); // wait a while .. + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + f1.setVisible(true); // test pending creation of f2 + } } ); + + final Frame f3 = new Frame(); + final Animator a3 = new Animator(); + final GearsES2 g3 = new GearsES2(0); + g3.setSharedGears(g1); + final GLCanvas c3 = createGLCanvas(f3, f1.getX()+0, f1.getY()+height, g3); + c3.setSharedAutoDrawable(c1); + a3.add(c3); + a3.start(); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + f3.setVisible(true); + } } ); + + Thread.sleep(1000/60*10); // wait ~10 frames giving a chance to create (blocking until master share is valid) + + Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c1, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c1, true)); + Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true)); + + Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c2, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c2, true)); + Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true)); + + Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c3, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c3, true)); + Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true)); + + final GLContext ctx1 = c1.getContext(); + final GLContext ctx2 = c2.getContext(); + final GLContext ctx3 = c3.getContext(); + { + final List<GLContext> ctx1Shares = ctx1.getCreatedShares(); + final List<GLContext> ctx2Shares = ctx2.getCreatedShares(); + final List<GLContext> ctx3Shares = ctx3.getCreatedShares(); + System.err.println("XXX-C-3.1:"); + MiscUtils.dumpSharedGLContext(ctx1); + System.err.println("XXX-C-3.2:"); + MiscUtils.dumpSharedGLContext(ctx2); + System.err.println("XXX-C-3.3:"); + MiscUtils.dumpSharedGLContext(ctx3); + + Assert.assertTrue("Ctx1 is not shared", ctx1.isShared()); + Assert.assertTrue("Ctx2 is not shared", ctx2.isShared()); + Assert.assertTrue("Ctx3 is not shared", ctx3.isShared()); + Assert.assertEquals("Ctx1 has unexpected number of created shares", 2, ctx1Shares.size()); + Assert.assertEquals("Ctx2 has unexpected number of created shares", 2, ctx2Shares.size()); + Assert.assertEquals("Ctx3 has unexpected number of created shares", 2, ctx3Shares.size()); + } + + Assert.assertTrue("Gears1 is shared", !g1.usesSharedGears()); + Assert.assertTrue("Gears2 is not shared", g2.usesSharedGears()); + Assert.assertTrue("Gears3 is not shared", g3.usesSharedGears()); + + try { + Thread.sleep(duration); + } catch(Exception e) { + e.printStackTrace(); + } + // Stopped animator allows native windowing system 'repaint' event + // to trigger GLAD 'display' + a1.stop(); + Assert.assertEquals(false, a1.isAnimating()); + a2.stop(); + Assert.assertEquals(false, a2.isAnimating()); + a3.stop(); + Assert.assertEquals(false, a3.isAnimating()); + + if( destroyCleanOrder ) { + System.err.println("XXX Destroy in clean order NOW"); + } else { + System.err.println("XXX Destroy in creation order NOW - Driver Impl. Ma trigger driver Bug i.e. not postponing GL ctx destruction after releasing all refs."); + } + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + try { + if( destroyCleanOrder ) { + f3.dispose(); + } else { + f1.dispose(); + } + } catch (Throwable t) { + throw new RuntimeException(t); + } + }}); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + try { + if( destroyCleanOrder ) { + f2.dispose(); + } else { + f2.dispose(); + } + } catch (Throwable t) { + throw new RuntimeException(t); + } + }}); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + try { + if( destroyCleanOrder ) { + f1.dispose(); + } else { + f3.dispose(); + } + } catch (Throwable t) { + throw new RuntimeException(t); + } + }}); + + Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, false)); + } + + static long duration = 1000; // ms + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + try { + duration = Integer.parseInt(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } + } + /** + BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); + System.err.println("Press enter to continue"); + System.err.println(stdin.readLine()); */ + org.junit.runner.JUnitCore.main(TestSharedContextVBOES2AWT3.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2AWT3b.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2AWT3b.java new file mode 100644 index 000000000..d4079e30c --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2AWT3b.java @@ -0,0 +1,329 @@ +/** + * 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.jogl.acore; + +import java.awt.Frame; +import java.lang.reflect.InvocationTargetException; +import java.util.List; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLJPanel; + +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +/** + * Sharing the VBO of 3 GearsES2 instances, each in their own AWT GLJPanel. + * <p> + * This is achieved by using the 1st GLJPanel as the <i>master</i> + * and using the build-in blocking mechanism to postpone creation + * of the 2nd and 3rd GLJPanel until the 1st GLJPanel 's GLContext becomes created. + * </p> + * <p> + * Above method allows random creation of the 1st GLJPanel, which triggers + * creation of the <i>dependent</i> other GLJPanel sharing it's GLContext. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestSharedContextVBOES2AWT3b extends UITestCase { + static GLProfile glp; + static GLCapabilities caps; + static int width, height; + + @BeforeClass + public static void initClass() { + if(GLProfile.isAvailable(GLProfile.GL2ES2)) { + glp = GLProfile.get(GLProfile.GL2ES2); + Assert.assertNotNull(glp); + caps = new GLCapabilities(glp); + Assert.assertNotNull(caps); + width = 256; + height = 256; + } else { + setTestSupported(false); + } + } + + protected GLJPanel createGLJPanel(final Frame frame, int x, int y, GearsES2 gears) throws InterruptedException { + final GLJPanel glCanvas = new GLJPanel(caps); + Assert.assertNotNull(glCanvas); + glCanvas.addGLEventListener(gears); + frame.add(glCanvas); + frame.setLocation(x, y); + frame.setSize(width, height); + frame.setTitle("AWT GLJPanel Shared Gears Test: "+x+"/"+y+" shared true"); + return glCanvas; + } + + @Test + public void test01SyncedOneAnimator() throws InterruptedException, InvocationTargetException { + final Frame f1 = new Frame(); + final Animator animator = new Animator(); + final GearsES2 g1 = new GearsES2(0); + final GLJPanel c1 = createGLJPanel(f1, 0, 0, g1); + animator.add(c1); + + final Frame f2 = new Frame(); + final GearsES2 g2 = new GearsES2(0); + g2.setSharedGears(g1); + final GLJPanel c2 = createGLJPanel(f2, f1.getX()+width, + f1.getY()+0, g2); + c2.setSharedAutoDrawable(c1); + animator.add(c2); + + final Frame f3 = new Frame(); + final GearsES2 g3 = new GearsES2(0); + g3.setSharedGears(g1); + final GLJPanel c3 = createGLJPanel(f3, f1.getX()+0, + f1.getY()+height, g3); + c3.setSharedAutoDrawable(c1); + animator.add(c3); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + f2.setVisible(true); // shall wait until f1 is ready + f1.setVisible(true); // master .. + f3.setVisible(true); // shall wait until f1 is ready + } } ); + animator.start(); // kicks off GLContext .. and hence gears of f2 + f3 completion + + Thread.sleep(1000/60*10); // wait ~10 frames giving a chance to create (blocking until master share is valid) + + Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c1, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c1, true)); + Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true)); + + Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c2, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c2, true)); + Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true)); + + Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c3, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c3, true)); + Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true)); + + final GLContext ctx1 = c1.getContext(); + final GLContext ctx2 = c2.getContext(); + final GLContext ctx3 = c3.getContext(); + { + final List<GLContext> ctx1Shares = ctx1.getCreatedShares(); + final List<GLContext> ctx2Shares = ctx2.getCreatedShares(); + final List<GLContext> ctx3Shares = ctx3.getCreatedShares(); + System.err.println("XXX-C-3.1:"); + MiscUtils.dumpSharedGLContext(ctx1); + System.err.println("XXX-C-3.2:"); + MiscUtils.dumpSharedGLContext(ctx2); + System.err.println("XXX-C-3.3:"); + MiscUtils.dumpSharedGLContext(ctx3); + + Assert.assertTrue("Ctx1 is not shared", ctx1.isShared()); + Assert.assertTrue("Ctx2 is not shared", ctx2.isShared()); + Assert.assertTrue("Ctx3 is not shared", ctx3.isShared()); + Assert.assertEquals("Ctx1 has unexpected number of created shares", 2, ctx1Shares.size()); + Assert.assertEquals("Ctx2 has unexpected number of created shares", 2, ctx2Shares.size()); + Assert.assertEquals("Ctx3 has unexpected number of created shares", 2, ctx3Shares.size()); + } + + Assert.assertTrue("Gears1 is shared", !g1.usesSharedGears()); + Assert.assertTrue("Gears2 is not shared", g2.usesSharedGears()); + Assert.assertTrue("Gears3 is not shared", g3.usesSharedGears()); + + try { + Thread.sleep(duration); + } catch(Exception e) { + e.printStackTrace(); + } + // Stopped animator allows native windowing system 'repaint' event + // to trigger GLAD 'display' + animator.stop(); + Assert.assertEquals(false, animator.isAnimating()); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + try { + f3.dispose(); + f2.dispose(); + f1.dispose(); + } catch (Throwable t) { + throw new RuntimeException(t); + } + }}); + + Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, false)); + } + + @Test + public void test02AsyncEachAnimator() throws InterruptedException, InvocationTargetException { + final Frame f1 = new Frame(); + final Animator a1 = new Animator(); + final GearsES2 g1 = new GearsES2(0); + final GLJPanel c1 = createGLJPanel(f1, 0, 0, g1); + a1.add(c1); + a1.start(); + // f1.setVisible(true); // we do this post f2 .. to test pending creation! + + final Frame f2 = new Frame(); + final Animator a2 = new Animator(); + final GearsES2 g2 = new GearsES2(0); + g2.setSharedGears(g1); + final GLJPanel c2 = createGLJPanel(f2, f1.getX()+width, f1.getY()+0, g2); + c2.setSharedAutoDrawable(c1); + a2.add(c2); + a2.start(); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + f2.setVisible(true); + } } ); + + Thread.sleep(200); // wait a while .. + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + f1.setVisible(true); // test pending creation of f2 + } } ); + + final Frame f3 = new Frame(); + final Animator a3 = new Animator(); + final GearsES2 g3 = new GearsES2(0); + g3.setSharedGears(g1); + final GLJPanel c3 = createGLJPanel(f3, f1.getX()+0, f1.getY()+height, g3); + c3.setSharedAutoDrawable(c1); + a3.add(c3); + a3.start(); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + f3.setVisible(true); + } } ); + + Thread.sleep(1000/60*10); // wait ~10 frames giving a chance to create (blocking until master share is valid) + + Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c1, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c1, true)); + Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true)); + + Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c2, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c2, true)); + Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true)); + + Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c3, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c3, true)); + Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true)); + + final GLContext ctx1 = c1.getContext(); + final GLContext ctx2 = c2.getContext(); + final GLContext ctx3 = c3.getContext(); + { + final List<GLContext> ctx1Shares = ctx1.getCreatedShares(); + final List<GLContext> ctx2Shares = ctx2.getCreatedShares(); + final List<GLContext> ctx3Shares = ctx3.getCreatedShares(); + System.err.println("XXX-C-3.1:"); + MiscUtils.dumpSharedGLContext(ctx1); + System.err.println("XXX-C-3.2:"); + MiscUtils.dumpSharedGLContext(ctx2); + System.err.println("XXX-C-3.3:"); + MiscUtils.dumpSharedGLContext(ctx3); + + Assert.assertTrue("Ctx1 is not shared", ctx1.isShared()); + Assert.assertTrue("Ctx2 is not shared", ctx2.isShared()); + Assert.assertTrue("Ctx3 is not shared", ctx3.isShared()); + Assert.assertEquals("Ctx1 has unexpected number of created shares", 2, ctx1Shares.size()); + Assert.assertEquals("Ctx2 has unexpected number of created shares", 2, ctx2Shares.size()); + Assert.assertEquals("Ctx3 has unexpected number of created shares", 2, ctx3Shares.size()); + } + + Assert.assertTrue("Gears1 is shared", !g1.usesSharedGears()); + Assert.assertTrue("Gears2 is not shared", g2.usesSharedGears()); + Assert.assertTrue("Gears3 is not shared", g3.usesSharedGears()); + + try { + Thread.sleep(duration); + } catch(Exception e) { + e.printStackTrace(); + } + // Stopped animator allows native windowing system 'repaint' event + // to trigger GLAD 'display' + a1.stop(); + Assert.assertEquals(false, a1.isAnimating()); + a2.stop(); + Assert.assertEquals(false, a2.isAnimating()); + a3.stop(); + Assert.assertEquals(false, a3.isAnimating()); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + try { + f3.dispose(); + f2.dispose(); + f1.dispose(); + } catch (Throwable t) { + throw new RuntimeException(t); + } + }}); + + Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, false)); + } + + static long duration = 1000; // ms + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + try { + duration = Integer.parseInt(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } + } + /** + BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); + System.err.println("Press enter to continue"); + System.err.println(stdin.readLine()); */ + org.junit.runner.JUnitCore.main(TestSharedContextVBOES2AWT3b.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT.java deleted file mode 100644 index ce2bd77e1..000000000 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT.java +++ /dev/null @@ -1,160 +0,0 @@ -/** - * 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.jogl.acore; - -import com.jogamp.common.os.Platform; -import com.jogamp.newt.opengl.GLWindow; - -import javax.media.nativewindow.util.InsetsImmutable; -import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLDrawableFactory; -import javax.media.opengl.GLPbuffer; -import javax.media.opengl.GLProfile; -import com.jogamp.opengl.util.Animator; - -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; -import com.jogamp.opengl.test.junit.util.UITestCase; -import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; - -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; - -public class TestSharedContextVBOES2NEWT extends UITestCase { - static GLProfile glp; - static GLCapabilities caps; - static int width, height; - GLPbuffer sharedDrawable; - GearsES2 sharedGears; - - @BeforeClass - public static void initClass() { - if(Platform.CPUFamily.X86 != Platform.CPU_ARCH.family) { // FIXME - // FIXME: Turns out on some mobile GL drivers and platforms - // using shared context is instable, Linux ARM (Omap4, Tegra2, Mesa3d, ..) - setTestSupported(false); - return; - } - if(GLProfile.isAvailable(GLProfile.GL2ES2)) { - glp = GLProfile.get(GLProfile.GL2ES2); - Assert.assertNotNull(glp); - caps = new GLCapabilities(glp); - Assert.assertNotNull(caps); - width = 256; - height = 256; - } else { - setTestSupported(false); - } - } - - private void initShared() { - sharedDrawable = GLDrawableFactory.getFactory(glp).createGLPbuffer(null, caps, null, width, height, null); - Assert.assertNotNull(sharedDrawable); - sharedGears = new GearsES2(); - Assert.assertNotNull(sharedGears); - sharedDrawable.addGLEventListener(sharedGears); - // init and render one frame, which will setup the Gears display lists - sharedDrawable.display(); - } - - private void releaseShared() { - Assert.assertNotNull(sharedDrawable); - sharedDrawable.destroy(); - } - - protected GLWindow runTestGL(Animator animator, int x, int y, boolean useShared, boolean vsync) throws InterruptedException { - GLWindow glWindow = GLWindow.create(caps); - Assert.assertNotNull(glWindow); - glWindow.setTitle("Shared Gears NEWT Test: "+x+"/"+y+" shared "+useShared); - if(useShared) { - glWindow.setSharedContext(sharedDrawable.getContext()); - } - - glWindow.setSize(width, height); - - GearsES2 gears = new GearsES2(vsync ? 1 : 0); - if(useShared) { - gears.setGears(sharedGears.getGear1(), sharedGears.getGear2(), sharedGears.getGear3()); - } - glWindow.addGLEventListener(gears); - - animator.add(glWindow); - - glWindow.setVisible(true); - Assert.assertTrue(AWTRobotUtil.waitForRealized(glWindow, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(glWindow, true)); - - glWindow.setPosition(x, y); - - return glWindow; - } - - @Test - public void test01() throws InterruptedException { - initShared(); - Animator animator = new Animator(); - GLWindow f1 = runTestGL(animator, 0, 0, true, false); - InsetsImmutable insets = f1.getInsets(); - GLWindow f2 = runTestGL(animator, f1.getX()+width+insets.getTotalWidth(), - f1.getY()+0, true, false); - GLWindow f3 = runTestGL(animator, f1.getX()+0, - f1.getY()+height+insets.getTotalHeight(), false, true); - animator.setUpdateFPSFrames(1, null); - animator.start(); - while(animator.isAnimating() && animator.getTotalFPSDuration()<duration) { - Thread.sleep(100); - } - animator.stop(); - - // here we go again: On AMD/X11 the create/destroy sequence must be the same - // even though this is agains the chicken/egg logic here .. - releaseShared(); - - f1.destroy(); - f2.destroy(); - f3.destroy(); - - // see above .. - // releaseShared(); - } - - static long duration = 500; // ms - - public static void main(String args[]) { - for(int i=0; i<args.length; i++) { - if(args[i].equals("-time")) { - i++; - try { - duration = Integer.parseInt(args[i]); - } catch (Exception ex) { ex.printStackTrace(); } - } - } - org.junit.runner.JUnitCore.main(TestSharedContextVBOES2NEWT.class.getName()); - } -} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT0.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT0.java new file mode 100644 index 000000000..010368b4b --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT0.java @@ -0,0 +1,285 @@ +/** + * 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.jogl.acore; + +import java.util.List; + +import com.jogamp.newt.opengl.GLWindow; + +import javax.media.nativewindow.util.InsetsImmutable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLProfile; + +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +/** + * Sharing the VBO of 3 GearsES2 instances, each in their own GLWindow. + * <p> + * This is achieved by relying on the sequential creation + * of the 3 GLWindows with their GLDrawable and GLContext. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestSharedContextVBOES2NEWT0 extends UITestCase { + static GLProfile glp; + static GLCapabilities caps; + static int width, height; + + @BeforeClass + public static void initClass() { + if(GLProfile.isAvailable(GLProfile.GL2ES2)) { + glp = GLProfile.get(GLProfile.GL2ES2); + Assert.assertNotNull(glp); + caps = new GLCapabilities(glp); + Assert.assertNotNull(caps); + width = 256; + height = 256; + } else { + setTestSupported(false); + } + } + + protected GLWindow runTestGL(Animator animator, int x, int y, GearsES2 gears, GLContext sharedContext) throws InterruptedException { + final boolean useShared = null != sharedContext; + GLWindow glWindow = GLWindow.create(caps); + Assert.assertNotNull(glWindow); + glWindow.setPosition(x, y); + glWindow.setTitle("Shared Gears NEWT Test: "+x+"/"+y+" shared "+useShared); + if(useShared) { + glWindow.setSharedContext(sharedContext); + } + glWindow.setSize(width, height); + glWindow.addGLEventListener(gears); + + animator.add(glWindow); + glWindow.setVisible(true); + Assert.assertTrue(AWTRobotUtil.waitForRealized(glWindow, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(glWindow, true)); + glWindow.display(); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(glWindow, true)); + Assert.assertTrue("Gears not initialized", gears.waitForInit(true)); + + return glWindow; + } + + @Test + public void test01CommonAnimatorSharedCopyBuffer() throws InterruptedException { + testCommonAnimatorSharedImpl(false); + } + @Test + public void test02CommonAnimatorMapBuffer() throws InterruptedException { + testCommonAnimatorSharedImpl(true); + } + private void testCommonAnimatorSharedImpl(boolean useMappedBuffers) throws InterruptedException { + final Animator animator = new Animator(); + + // + // 1st + // + final GearsES2 g1 = new GearsES2(0); + g1.setUseMappedBuffers(useMappedBuffers); + g1.setValidateBuffers(true); + final GLWindow f1 = runTestGL(animator, 0, 0, g1, null); + final GLContext ctx1 = f1.getContext(); + Assert.assertTrue("Ctx is shared before shared creation", !ctx1.isShared()); + final InsetsImmutable insets = f1.getInsets(); + + System.err.println("XXX-C-2.1:"); + MiscUtils.dumpSharedGLContext(ctx1); + + // + // 2nd + // + final GearsES2 g2 = new GearsES2(0); + g2.setSharedGearsObjects(g1.getGear1(), g1.getGear2(), g1.getGear3()); + final GLWindow f2 = runTestGL(animator, f1.getX()+width+insets.getTotalWidth(), + f1.getY()+0, g2, f1.getContext()); + final GLContext ctx2 = f2.getContext(); + Assert.assertTrue("Ctx1 is not shared", ctx1.isShared()); + Assert.assertTrue("Ctx2 is not shared", ctx2.isShared()); + + { + final List<GLContext> ctx1Shares = ctx1.getCreatedShares(); + final List<GLContext> ctx2Shares = ctx2.getCreatedShares(); + System.err.println("XXX-C-2.1:"); + MiscUtils.dumpSharedGLContext(ctx1); + System.err.println("XXX-C-2.2:"); + MiscUtils.dumpSharedGLContext(ctx2); + + Assert.assertEquals("Ctx1 has unexpected number of created shares", 1, ctx1Shares.size()); + Assert.assertEquals("Ctx2 has unexpected number of created shares", 1, ctx2Shares.size()); + } + + // + // 3rd + // + final GearsES2 g3 = new GearsES2(0); + g3.setSharedGearsObjects(g1.getGear1(), g1.getGear2(), g1.getGear3()); + final GLWindow f3 = runTestGL(animator, f1.getX()+0, + f1.getY()+height+insets.getTotalHeight(), g3, f1.getContext()); + + final GLContext ctx3 = f3.getContext(); + Assert.assertTrue("Ctx1 is not shared", ctx1.isShared()); + Assert.assertTrue("Ctx2 is not shared", ctx2.isShared()); + Assert.assertTrue("Ctx3 is not shared", ctx3.isShared()); + + { + final List<GLContext> ctx1Shares = ctx1.getCreatedShares(); + final List<GLContext> ctx2Shares = ctx2.getCreatedShares(); + final List<GLContext> ctx3Shares = ctx3.getCreatedShares(); + System.err.println("XXX-C-3.1:"); + MiscUtils.dumpSharedGLContext(ctx1); + System.err.println("XXX-C-3.2:"); + MiscUtils.dumpSharedGLContext(ctx2); + System.err.println("XXX-C-3.3:"); + MiscUtils.dumpSharedGLContext(ctx3); + + Assert.assertEquals("Ctx1 has unexpected number of created shares", 2, ctx1Shares.size()); + Assert.assertEquals("Ctx2 has unexpected number of created shares", 2, ctx2Shares.size()); + Assert.assertEquals("Ctx3 has unexpected number of created shares", 2, ctx3Shares.size()); + } + + Assert.assertTrue("Gears1 is shared", !g1.usesSharedGears()); + Assert.assertTrue("Gears2 is not shared", g2.usesSharedGears()); + Assert.assertTrue("Gears3 is not shared", g3.usesSharedGears()); + + animator.start(); + + try { + Thread.sleep(duration); + } catch(Exception e) { + e.printStackTrace(); + } + + f3.destroy(); + Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, false)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, false)); + { + final List<GLContext> ctx1Shares = ctx1.getCreatedShares(); + final List<GLContext> ctx2Shares = ctx2.getCreatedShares(); + final List<GLContext> ctx3Shares = ctx3.getCreatedShares(); + System.err.println("XXX-D-0.1:"); + MiscUtils.dumpSharedGLContext(ctx1); + System.err.println("XXX-D-0.2:"); + MiscUtils.dumpSharedGLContext(ctx2); + System.err.println("XXX-D-0.3:"); + MiscUtils.dumpSharedGLContext(ctx3); + + Assert.assertTrue("Ctx1 is shared", ctx1.isShared()); + Assert.assertTrue("Ctx2 is shared", ctx2.isShared()); + Assert.assertTrue("Ctx3 is shared", ctx3.isShared()); + Assert.assertEquals("Ctx1 has unexpected number of created shares", 1, ctx1Shares.size()); + Assert.assertEquals("Ctx2 has unexpected number of created shares", 1, ctx2Shares.size()); + Assert.assertEquals("Ctx3 has unexpected number of created shares", 2, ctx3Shares.size()); + } + try { Thread.sleep(durationPostDestroy); } catch(Exception e) { e.printStackTrace(); } + + f2.destroy(); + Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, false)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, false)); + { + final List<GLContext> ctx1Shares = ctx1.getCreatedShares(); + final List<GLContext> ctx2Shares = ctx2.getCreatedShares(); + final List<GLContext> ctx3Shares = ctx3.getCreatedShares(); + System.err.println("XXX-D-1.1:"); + MiscUtils.dumpSharedGLContext(ctx1); + System.err.println("XXX-D-1.2:"); + MiscUtils.dumpSharedGLContext(ctx2); + System.err.println("XXX-D-1.3:"); + MiscUtils.dumpSharedGLContext(ctx3); + + Assert.assertTrue("Ctx1 is not shared", ctx1.isShared()); + Assert.assertTrue("Ctx2 is not shared", ctx2.isShared()); + Assert.assertTrue("Ctx3 is not shared", ctx3.isShared()); + Assert.assertEquals("Ctx1 has unexpected number of created shares", 0, ctx1Shares.size()); + Assert.assertEquals("Ctx2 has unexpected number of created shares", 1, ctx2Shares.size()); + Assert.assertEquals("Ctx3 has unexpected number of created shares", 1, ctx3Shares.size()); + } + try { Thread.sleep(durationPostDestroy); } catch(Exception e) { e.printStackTrace(); } + + f1.destroy(); + Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, false)); + { + final List<GLContext> ctx1Shares = ctx1.getCreatedShares(); + final List<GLContext> ctx2Shares = ctx2.getCreatedShares(); + final List<GLContext> ctx3Shares = ctx3.getCreatedShares(); + System.err.println("XXX-D-2.1:"); + MiscUtils.dumpSharedGLContext(ctx1); + System.err.println("XXX-D-2.2:"); + MiscUtils.dumpSharedGLContext(ctx2); + System.err.println("XXX-D-2.3:"); + MiscUtils.dumpSharedGLContext(ctx3); + + Assert.assertTrue("Ctx1 is not shared", !ctx1.isShared()); + Assert.assertTrue("Ctx2 is not shared", !ctx2.isShared()); + Assert.assertTrue("Ctx3 is not shared", !ctx3.isShared()); + Assert.assertEquals("Ctx1 has unexpected number of created shares", 0, ctx1Shares.size()); + Assert.assertEquals("Ctx2 has unexpected number of created shares", 0, ctx2Shares.size()); + Assert.assertEquals("Ctx3 has unexpected number of created shares", 0, ctx3Shares.size()); + } + try { Thread.sleep(durationPostDestroy); } catch(Exception e) { e.printStackTrace(); } + + animator.stop(); + Assert.assertEquals(false, animator.isAnimating()); + } + + static long duration = 1000; // ms + static long durationPostDestroy = 1000; // ms - ~60 frames post destroy + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + try { + duration = Integer.parseInt(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } + } + /** + BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); + System.err.println("Press enter to continue"); + System.err.println(stdin.readLine()); */ + org.junit.runner.JUnitCore.main(TestSharedContextVBOES2NEWT0.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT1.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT1.java new file mode 100644 index 000000000..7051bac13 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT1.java @@ -0,0 +1,293 @@ +/** + * 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.jogl.acore; + +import com.jogamp.newt.opengl.GLWindow; + +import javax.media.nativewindow.util.InsetsImmutable; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLProfile; + +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +/** + * Sharing the VBO of 3 GearsES2 instances, each in their own GLWindow. + * <p> + * This is achieved by creating a <i>master</i> GLContext to an offscreen invisible GLAutoDrawable, + * which is then shared by the 3 GLContext of the three GLWindow instances. + * </p> + * <p> + * The original VBO is created by attaching a GearsES2 instance to + * the <i>master</i> GLAutoDrawable and initializing it. + * </p> + * <p> + * Above method allows random creation of all GLWindow instances. + * </p> + * <p> + * One tests uses only one animator, where the GLWindow, GLDrawable and GLContext + * creation of all 3 GLWindows is sequential. + * </p> + * <p> + * Another tests uses 3 animator, one for each GLWindow, + * where the GLWindow, GLDrawable and GLContext creation + * of all 3 GLWindows is <i>random</i>. + * This fact benefits from the <i>master</i> GLContext/GLAutoDrawable, + * since it is guaranteed it exist and is realized at the time of the <i>shared</i> + * GLWindow creation. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestSharedContextVBOES2NEWT1 extends UITestCase { + static GLProfile glp; + static GLCapabilities caps; + static int width, height; + GLAutoDrawable sharedDrawable; + GearsES2 sharedGears; + + @BeforeClass + public static void initClass() { + if(GLProfile.isAvailable(GLProfile.GL2ES2)) { + glp = GLProfile.get(GLProfile.GL2ES2); + Assert.assertNotNull(glp); + caps = new GLCapabilities(glp); + Assert.assertNotNull(caps); + width = 256; + height = 256; + } else { + setTestSupported(false); + } + } + + private void initShared(boolean onscreen) throws InterruptedException { + if(onscreen) { + GLWindow glWindow = GLWindow.create(caps); + Assert.assertNotNull(glWindow); + glWindow.setSize(width, height); + glWindow.setVisible(true); + sharedDrawable = glWindow; + } else { + sharedDrawable = GLDrawableFactory.getFactory(glp).createDummyAutoDrawable(null, true /* createNewDevice */, caps, null); + } + Assert.assertNotNull(sharedDrawable); + Assert.assertTrue(AWTRobotUtil.waitForRealized(sharedDrawable, true)); + + sharedGears = new GearsES2(); + Assert.assertNotNull(sharedGears); + sharedDrawable.addGLEventListener(sharedGears); + // init and render one frame, which will setup the Gears display lists + sharedDrawable.display(); + final GLContext ctxM = sharedDrawable.getContext(); + Assert.assertTrue("Master ctx not created", AWTRobotUtil.waitForContextCreated(sharedDrawable, true)); + Assert.assertTrue("Master Ctx is shared before shared creation", !ctxM.isShared()); + Assert.assertTrue("Master Gears not initialized", sharedGears.waitForInit(true)); + System.err.println("Master Gears Init done: "+sharedGears); + Assert.assertTrue("Master Gears is shared", !sharedGears.usesSharedGears()); + } + + private void releaseShared() { + Assert.assertNotNull(sharedDrawable); + sharedDrawable.destroy(); + sharedDrawable = null; + } + + protected GLWindow runTestGL(Animator animator, int x, int y, boolean useShared, boolean vsync) throws InterruptedException { + GLWindow glWindow = GLWindow.create(caps); + Assert.assertNotNull(glWindow); + glWindow.setPosition(x, y); + glWindow.setTitle("Shared Gears NEWT Test: "+x+"/"+y+" shared "+useShared); + if(useShared) { + glWindow.setSharedContext(sharedDrawable.getContext()); + } + + glWindow.setSize(width, height); + + GearsES2 gears = new GearsES2(vsync ? 1 : 0); + if(useShared) { + gears.setSharedGearsObjects(sharedGears.getGear1(), sharedGears.getGear2(), sharedGears.getGear3()); + } + glWindow.addGLEventListener(gears); + + animator.add(glWindow); + animator.start(); + glWindow.setVisible(true); + Assert.assertTrue(AWTRobotUtil.waitForRealized(glWindow, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(glWindow, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(glWindow, true)); + + System.err.println("Master Context: "); + MiscUtils.dumpSharedGLContext(sharedDrawable.getContext()); + System.err.println("New Context: "); + MiscUtils.dumpSharedGLContext(glWindow.getContext()); + if( useShared ) { + Assert.assertEquals("Master Context not shared as expected", true, sharedDrawable.getContext().isShared()); + } + Assert.assertEquals("New Context not shared as expected", useShared, glWindow.getContext().isShared()); + + Assert.assertTrue("Gears not initialized", gears.waitForInit(true)); + System.err.println("Slave Gears Init done: "+gears); + Assert.assertEquals("Gears is not shared as expected", useShared, gears.usesSharedGears()); + + return glWindow; + } + + @Test + public void test01CommonAnimatorSharedOnscreen() throws InterruptedException { + initShared(true); + Animator animator = new Animator(); + GLWindow f1 = runTestGL(animator, 0, 0, true, false); + InsetsImmutable insets = f1.getInsets(); + GLWindow f2 = runTestGL(animator, f1.getX()+width+insets.getTotalWidth(), + f1.getY()+0, true, false); + GLWindow f3 = runTestGL(animator, f1.getX()+0, + f1.getY()+height+insets.getTotalHeight(), true, false); + try { + Thread.sleep(duration); + } catch(Exception e) { + e.printStackTrace(); + } + animator.stop(); + + f1.destroy(); + f2.destroy(); + f3.destroy(); + Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, false)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, false)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, false)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, false)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, false)); + + releaseShared(); + } + + @Test + public void test02CommonAnimatorSharedOffscreen() throws InterruptedException { + initShared(false); + Animator animator = new Animator(); + GLWindow f1 = runTestGL(animator, 0, 0, true, false); + InsetsImmutable insets = f1.getInsets(); + GLWindow f2 = runTestGL(animator, f1.getX()+width+insets.getTotalWidth(), + f1.getY()+0, true, false); + GLWindow f3 = runTestGL(animator, f1.getX()+0, + f1.getY()+height+insets.getTotalHeight(), true, false); + try { + Thread.sleep(duration); + } catch(Exception e) { + e.printStackTrace(); + } + animator.stop(); + + f1.destroy(); + f2.destroy(); + f3.destroy(); + Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, false)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, false)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, false)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, false)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, false)); + + releaseShared(); + } + + @Test + public void test03EachWithAnimatorSharedOffscreen() throws InterruptedException { + initShared(false); + Animator animator1 = new Animator(); + Animator animator2 = new Animator(); + Animator animator3 = new Animator(); + GLWindow f1 = runTestGL(animator1, 0, 0, true, false); + InsetsImmutable insets = f1.getInsets(); + GLWindow f2 = runTestGL(animator2, f1.getX()+width+insets.getTotalWidth(), + f1.getY()+0, true, false); + GLWindow f3 = runTestGL(animator3, f1.getX()+0, + f1.getY()+height+insets.getTotalHeight(), true, false); + + try { + Thread.sleep(duration); + } catch(Exception e) { + e.printStackTrace(); + } + animator1.stop(); + animator2.stop(); + animator3.stop(); + + f1.destroy(); + f2.destroy(); + f3.destroy(); + Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, false)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, false)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, false)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, false)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, false)); + + releaseShared(); + } + + static long duration = 1000; // ms + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + try { + duration = Integer.parseInt(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } + } + /** + BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); + System.err.println("Press enter to continue"); + System.err.println(stdin.readLine()); */ + org.junit.runner.JUnitCore.main(TestSharedContextVBOES2NEWT1.class.getName()); + } +} 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 8911e73ef..e8e4cc739 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 @@ -3,14 +3,14 @@ * * 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 @@ -20,47 +20,58 @@ * 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.jogl.acore; -import java.io.IOException; +import java.util.List; -import com.jogamp.common.os.Platform; import com.jogamp.newt.opengl.GLWindow; import javax.media.nativewindow.util.InsetsImmutable; +import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLContext; import javax.media.opengl.GLProfile; -import com.jogamp.opengl.util.Animator; +import javax.media.opengl.GLRunnable; +import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +/** + * Sharing the VBO of 3 GearsES2 instances, each in their own GLWindow. + * <p> + * This is achieved by using the 1st GLWindow's GLContext as the <i>master</i> + * and manually triggering creation of the 2nd and 3rd GLWindow when the 1st GLWindow's + * GLContext becomes created. The trigger is performed by simply + * inserting a GLRunnable in the 1st GLWindow, which makes the other visible. + * </p> + * <p> + * Above method allows random creation of the 1st GLWindow, which triggers + * creation of the <i>dependent</i> other GLWindow sharing it's GLContext. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestSharedContextVBOES2NEWT2 extends UITestCase { static GLProfile glp; static GLCapabilities caps; static int width, height; - GLWindow sharedDrawable; - GearsES2 sharedGears; @BeforeClass public static void initClass() { - if(Platform.CPUFamily.X86 != Platform.CPU_ARCH.family) { // FIXME - // FIXME: Turns out on some mobile GL drivers and platforms - // using shared context is instable, Linux ARM (Omap4, Tegra2, Mesa3d, ..) - setTestSupported(false); - return; - } if(GLProfile.isAvailable(GLProfile.GL2ES2)) { glp = GLProfile.get(GLProfile.GL2ES2); Assert.assertNotNull(glp); @@ -73,84 +84,261 @@ public class TestSharedContextVBOES2NEWT2 extends UITestCase { } } - private void initShared() { - sharedDrawable = GLWindow.create(caps); - Assert.assertNotNull(sharedDrawable); - // sharedGears = new Gears(0); - sharedGears = new GearsES2(0); - Assert.assertNotNull(sharedGears); - sharedDrawable.addGLEventListener(sharedGears); - sharedDrawable.setSize(width, height); - sharedDrawable.setVisible(true); - // init and render one frame, which will setup the Gears display lists - sharedDrawable.display(); + protected GLWindow createGLWindow(int x, int y, GearsES2 gears) throws InterruptedException { + GLWindow glWindow = GLWindow.create(caps); + Assert.assertNotNull(glWindow); + glWindow.setPosition(x, y); + glWindow.setTitle("Shared Gears NEWT Test: "+x+"/"+y+" shared true"); + glWindow.setSize(width, height); + glWindow.addGLEventListener(gears); + + return glWindow; } - private void releaseShared() { - Assert.assertNotNull(sharedDrawable); - sharedDrawable.destroy(); - sharedDrawable = null; + @Test + public void test01SyncedOneAnimatorCleanDtorOrder() throws InterruptedException { + syncedOneAnimator(true); } - protected GLWindow runTestGL(Animator animator, int x, int y, boolean useShared, boolean vsync) throws InterruptedException { - GLWindow glWindow = GLWindow.create(caps); - - Assert.assertNotNull(glWindow); - glWindow.setTitle("Shared Gears NEWT Test: "+x+"/"+y+" shared "+useShared); - if(useShared) { - glWindow.setSharedContext(sharedDrawable.getContext()); + @Test + public void test02SyncedOneAnimatorDirtyDtorOrder() throws InterruptedException { + syncedOneAnimator(false); + } + + public void syncedOneAnimator(boolean destroyCleanOrder) throws InterruptedException { + final Animator animator = new Animator(); + final GearsES2 g1 = new GearsES2(0); + final GLWindow f1 = createGLWindow(0, 0, g1); + animator.add(f1); + InsetsImmutable insets = f1.getInsets(); + + final GearsES2 g2 = new GearsES2(0); + g2.setSharedGears(g1); + final GLWindow f2 = createGLWindow(f1.getX()+width+insets.getTotalWidth(), + f1.getY()+0, g2); + animator.add(f2); + + final GearsES2 g3 = new GearsES2(0); + g3.setSharedGears(g1); + final GLWindow f3 = createGLWindow(f1.getX()+0, + f1.getY()+height+insets.getTotalHeight(), g3); + animator.add(f3); + + // f1's shared GLContext is ready ! + f1.invoke(false, new GLRunnable() { + @Override + public boolean run(GLAutoDrawable drawable) { + final GLContext ctx1 = f1.getContext(); + Assert.assertTrue("Ctx is shared before shared creation", !ctx1.isShared()); + f2.setSharedContext(ctx1); + f2.setVisible(true); + f2.display(); // kick off GLContext .. + f3.setSharedContext(ctx1); + f3.setVisible(true); + f3.display(); // kick off GLContext .. + return true; + } + }); + + f1.setVisible(true); + f1.display(); // kick off GLContext .. and hence f2 + f3 creation + + Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, true)); + Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true)); + + Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, true)); + Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true)); + + Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, true)); + Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true)); + + animator.start(); // post start animator, otherwise display will be suppressed + + final GLContext ctx1 = f1.getContext(); + final GLContext ctx2 = f2.getContext(); + final GLContext ctx3 = f3.getContext(); + { + final List<GLContext> ctx1Shares = ctx1.getCreatedShares(); + final List<GLContext> ctx2Shares = ctx2.getCreatedShares(); + final List<GLContext> ctx3Shares = ctx3.getCreatedShares(); + System.err.println("XXX-C-3.1:"); + MiscUtils.dumpSharedGLContext(ctx1); + System.err.println("XXX-C-3.2:"); + MiscUtils.dumpSharedGLContext(ctx2); + System.err.println("XXX-C-3.3:"); + MiscUtils.dumpSharedGLContext(ctx3); + + Assert.assertTrue("Ctx1 is not shared", ctx1.isShared()); + Assert.assertTrue("Ctx2 is not shared", ctx2.isShared()); + Assert.assertTrue("Ctx3 is not shared", ctx3.isShared()); + Assert.assertEquals("Ctx1 has unexpected number of created shares", 2, ctx1Shares.size()); + Assert.assertEquals("Ctx2 has unexpected number of created shares", 2, ctx2Shares.size()); + Assert.assertEquals("Ctx3 has unexpected number of created shares", 2, ctx3Shares.size()); } - glWindow.setSize(width, height); + Assert.assertTrue("Gears1 is shared", !g1.usesSharedGears()); + Assert.assertTrue("Gears2 is not shared", g2.usesSharedGears()); + Assert.assertTrue("Gears3 is not shared", g3.usesSharedGears()); - GearsES2 gears = new GearsES2(vsync ? 1 : 0); - if(useShared) { - gears.setGears(sharedGears.getGear1(), sharedGears.getGear2(), sharedGears.getGear3()); + try { + Thread.sleep(duration); + } catch(Exception e) { + e.printStackTrace(); } - glWindow.addGLEventListener(gears); + animator.stop(); + Assert.assertEquals(false, animator.isAnimating()); - animator.add(glWindow); - animator.start(); - glWindow.setVisible(true); + if( destroyCleanOrder ) { + System.err.println("XXX Destroy in clean order NOW"); + f3.destroy(); + f2.destroy(); + f1.destroy(); + } else { + System.err.println("XXX Destroy in creation order NOW - Driver Impl. May trigger driver Bug i.e. not postponing GL ctx destruction after releasing all refs."); + f1.destroy(); + f2.destroy(); + f3.destroy(); + } + Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, false)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, false)); + } - Assert.assertTrue(AWTRobotUtil.waitForRealized(glWindow, true)); - Assert.assertTrue(AWTRobotUtil.waitForVisible(glWindow, true)); - glWindow.setPosition(x, y); - - return glWindow; + @Test + public void test11AsyncEachAnimatorCleanDtorOrder() throws InterruptedException { + asyncEachAnimator(true); } @Test - public void test01() throws InterruptedException { - initShared(); - GLWindow f1 = runTestGL(new Animator(), 0, 0, true, false); + public void test12AsyncEachAnimatorDirtyDtorOrder() throws InterruptedException { + asyncEachAnimator(false); + } + + public void asyncEachAnimator(boolean destroyCleanOrder) throws InterruptedException { + final Animator a1 = new Animator(); + final GearsES2 g1 = new GearsES2(0); + final GLWindow f1 = createGLWindow(0, 0, g1); + a1.add(f1); + a1.start(); + f1.setVisible(true); + InsetsImmutable insets = f1.getInsets(); - GLWindow f2 = runTestGL(new Animator(), f1.getX()+width+insets.getTotalWidth(), - f1.getY()+0, true, false); - GLWindow f3 = runTestGL(new Animator(), f1.getX()+0, - f1.getY()+height+insets.getTotalHeight(), true, false); - try { - Thread.sleep(duration); - } catch(Exception e) { - e.printStackTrace(); - } + final Animator a2 = new Animator(); + final GearsES2 g2 = new GearsES2(0); + g2.setSharedGears(g1); + final GLWindow f2 = createGLWindow(f1.getX()+width+insets.getTotalWidth(), + f1.getY()+0, g2); + a2.add(f2); + a2.start(); + + final Animator a3 = new Animator(); + final GearsES2 g3 = new GearsES2(0); + g3.setSharedGears(g1); + final GLWindow f3 = createGLWindow(f1.getX()+0, + f1.getY()+height+insets.getTotalHeight(), g3); + a3.add(f3); + a3.start(); - // here we go again: On AMD/X11 the create/destroy sequence must be the same - // even though this is against the chicken/egg logic here .. - releaseShared(); + // f1's shared GLContext is ready ! + f1.invoke(false, new GLRunnable() { + @Override + public boolean run(GLAutoDrawable drawable) { + final GLContext ctx1 = f1.getContext(); + Assert.assertTrue("Ctx is shared before shared creation", !ctx1.isShared()); + f2.setSharedContext(ctx1); + f2.setVisible(true); + f3.setSharedContext(ctx1); + f3.setVisible(true); + return true; + } + }); + + Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, true)); + Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true)); - f1.destroy(); - f2.destroy(); - f3.destroy(); + Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, true)); + Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, true)); + Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true)); - // see above .. - // releaseShared(); + final GLContext ctx1 = f1.getContext(); + final GLContext ctx2 = f2.getContext(); + final GLContext ctx3 = f3.getContext(); + { + final List<GLContext> ctx1Shares = ctx1.getCreatedShares(); + final List<GLContext> ctx2Shares = ctx2.getCreatedShares(); + final List<GLContext> ctx3Shares = ctx3.getCreatedShares(); + System.err.println("XXX-C-3.1:"); + MiscUtils.dumpSharedGLContext(ctx1); + System.err.println("XXX-C-3.2:"); + MiscUtils.dumpSharedGLContext(ctx2); + System.err.println("XXX-C-3.3:"); + MiscUtils.dumpSharedGLContext(ctx3); + + Assert.assertTrue("Ctx1 is not shared", ctx1.isShared()); + Assert.assertTrue("Ctx2 is not shared", ctx2.isShared()); + Assert.assertTrue("Ctx3 is not shared", ctx3.isShared()); + Assert.assertEquals("Ctx1 has unexpected number of created shares", 2, ctx1Shares.size()); + Assert.assertEquals("Ctx2 has unexpected number of created shares", 2, ctx2Shares.size()); + Assert.assertEquals("Ctx3 has unexpected number of created shares", 2, ctx3Shares.size()); + } + + Assert.assertTrue("Gears1 is shared", !g1.usesSharedGears()); + Assert.assertTrue("Gears2 is not shared", g2.usesSharedGears()); + Assert.assertTrue("Gears3 is not shared", g3.usesSharedGears()); + + try { + Thread.sleep(duration); + } catch(Exception e) { + e.printStackTrace(); + } + // Stopped animator allows native windowing system 'repaint' event + // to trigger GLAD 'display' + a1.stop(); + Assert.assertEquals(false, a1.isAnimating()); + a2.stop(); + Assert.assertEquals(false, a2.isAnimating()); + a3.stop(); + Assert.assertEquals(false, a3.isAnimating()); + + if( destroyCleanOrder ) { + System.err.println("XXX Destroy in clean order NOW"); + f3.destroy(); + f2.destroy(); + f1.destroy(); + } else { + System.err.println("XXX Destroy in creation order NOW - Driver Impl. May trigger driver Bug i.e. not postponing GL ctx destruction after releasing all refs."); + f1.destroy(); + f2.destroy(); + f3.destroy(); + } + Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, false)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, false)); } - static long duration = 2000; // ms + static long duration = 1000; // ms - public static void main(String args[]) throws IOException { + public static void main(String args[]) { for(int i=0; i<args.length; i++) { if(args[i].equals("-time")) { i++; @@ -162,7 +350,7 @@ public class TestSharedContextVBOES2NEWT2 extends UITestCase { /** BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); System.err.println("Press enter to continue"); - System.err.println(stdin.readLine()); */ + System.err.println(stdin.readLine()); */ org.junit.runner.JUnitCore.main(TestSharedContextVBOES2NEWT2.class.getName()); } } 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 new file mode 100644 index 000000000..a8684ad4c --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT3.java @@ -0,0 +1,381 @@ +/** + * 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.jogl.acore; + +import java.util.List; + +import com.jogamp.newt.opengl.GLWindow; + +import javax.media.nativewindow.util.InsetsImmutable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLProfile; + +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +/** + * Sharing the VBO of 3 GearsES2 instances, each in their own GLWindow. + * <p> + * This is achieved by using the 1st GLWindow as the <i>master</i> + * and using the build-in blocking mechanism to postpone creation + * of the 2nd and 3rd GLWindow until the 1st GLWindow's GLContext becomes created. + * </p> + * <p> + * Above method allows random creation of the 1st GLWindow, which triggers + * creation of the <i>dependent</i> other GLWindow sharing it's GLContext. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestSharedContextVBOES2NEWT3 extends UITestCase { + static GLProfile glp; + static GLCapabilities caps; + static int width, height; + + @BeforeClass + public static void initClass() { + if(GLProfile.isAvailable(GLProfile.GL2ES2)) { + glp = GLProfile.get(GLProfile.GL2ES2); + Assert.assertNotNull(glp); + caps = new GLCapabilities(glp); + Assert.assertNotNull(caps); + width = 256; + height = 256; + } else { + setTestSupported(false); + } + } + + protected GLWindow createGLWindow(int x, int y, GearsES2 gears) throws InterruptedException { + GLWindow glWindow = GLWindow.create(caps); + Assert.assertNotNull(glWindow); + glWindow.setPosition(x, y); + glWindow.setTitle("Shared Gears NEWT Test: "+x+"/"+y+" shared true"); + glWindow.setSize(width, height); + glWindow.addGLEventListener(gears); + + return glWindow; + } + + @Test + public void test01SyncedOneAnimatorCleanDtorOrderCopyBuffer() throws InterruptedException { + syncedOneAnimator(true, false); + } + @Test + public void test02SyncedOneAnimatorCleanDtorOrderMapBuffer() throws InterruptedException { + syncedOneAnimator(true, true); + } + + @Test + public void test03SyncedOneAnimatorDirtyDtorOrderCopyBuffer() throws InterruptedException { + syncedOneAnimator(false, false); + } + @Test + public void test04SyncedOneAnimatorDirtyDtorOrderMapBuffer() throws InterruptedException { + syncedOneAnimator(false, true); + } + + public void syncedOneAnimator(boolean destroyCleanOrder, boolean useMappedBuffers) throws InterruptedException { + final Animator animator = new Animator(); + final GearsES2 g1 = new GearsES2(0); + g1.setUseMappedBuffers(useMappedBuffers); + g1.setValidateBuffers(true); + final GLWindow f1 = createGLWindow(0, 0, g1); + animator.add(f1); + InsetsImmutable insets = f1.getInsets(); + + final GearsES2 g2 = new GearsES2(0); + g2.setSharedGears(g1); + final GLWindow f2 = createGLWindow(f1.getX()+width+insets.getTotalWidth(), + f1.getY()+0, g2); + f2.setSharedAutoDrawable(f1); + animator.add(f2); + + final GearsES2 g3 = new GearsES2(0); + g3.setSharedGears(g1); + final GLWindow f3 = createGLWindow(f1.getX()+0, + f1.getY()+height+insets.getTotalHeight(), g3); + f3.setSharedAutoDrawable(f1); + animator.add(f3); + + f2.setVisible(true); // shall wait until f1 is ready + f1.setVisible(true); // master .. + f3.setVisible(true); // shall wait until f1 is ready + animator.start(); // kicks off GLContext .. and hence gears of f2 + f3 completion + + Thread.sleep(1000/60*10); // wait ~10 frames giving a chance to create (blocking until master share is valid) + + Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, true)); + Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true)); + + Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, true)); + Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true)); + + Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, true)); + Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true)); + + final GLContext ctx1 = f1.getContext(); + final GLContext ctx2 = f2.getContext(); + final GLContext ctx3 = f3.getContext(); + { + final List<GLContext> ctx1Shares = ctx1.getCreatedShares(); + final List<GLContext> ctx2Shares = ctx2.getCreatedShares(); + final List<GLContext> ctx3Shares = ctx3.getCreatedShares(); + System.err.println("XXX-C-3.1:"); + MiscUtils.dumpSharedGLContext(ctx1); + System.err.println("XXX-C-3.2:"); + MiscUtils.dumpSharedGLContext(ctx2); + System.err.println("XXX-C-3.3:"); + MiscUtils.dumpSharedGLContext(ctx3); + + Assert.assertTrue("Ctx1 is not shared", ctx1.isShared()); + Assert.assertTrue("Ctx2 is not shared", ctx2.isShared()); + Assert.assertTrue("Ctx3 is not shared", ctx3.isShared()); + Assert.assertEquals("Ctx1 has unexpected number of created shares", 2, ctx1Shares.size()); + Assert.assertEquals("Ctx2 has unexpected number of created shares", 2, ctx2Shares.size()); + Assert.assertEquals("Ctx3 has unexpected number of created shares", 2, ctx3Shares.size()); + } + + Assert.assertTrue("Gears1 is shared", !g1.usesSharedGears()); + Assert.assertTrue("Gears2 is not shared", g2.usesSharedGears()); + Assert.assertTrue("Gears3 is not shared", g3.usesSharedGears()); + + try { + Thread.sleep(duration); + } catch(Exception e) { + e.printStackTrace(); + } + + if( destroyCleanOrder ) { + System.err.println("XXX Destroy in clean order NOW"); + f3.destroy(); + try { Thread.sleep(durationPostDestroy); } catch(Exception e) { e.printStackTrace(); } + f2.destroy(); + try { Thread.sleep(durationPostDestroy); } catch(Exception e) { e.printStackTrace(); } + f1.destroy(); + try { Thread.sleep(durationPostDestroy); } catch(Exception e) { e.printStackTrace(); } + } else { + System.err.println("XXX Destroy in creation order NOW - Driver Impl. Ma trigger driver Bug i.e. not postponing GL ctx destruction after releasing all refs."); + animator.pause(); + f1.destroy(); + animator.resume(); + try { Thread.sleep(durationPostDestroy); } catch(Exception e) { e.printStackTrace(); } + + animator.pause(); + f2.destroy(); + animator.resume(); + try { Thread.sleep(durationPostDestroy); } catch(Exception e) { e.printStackTrace(); } + + f3.destroy(); + try { Thread.sleep(durationPostDestroy); } catch(Exception e) { e.printStackTrace(); } + } + Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, false)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, false)); + + animator.stop(); + } + + @Test + public void test11ASyncEachAnimatorCleanDtorOrderCopyBuffer() throws InterruptedException { + asyncEachAnimator(true, false); + } + @Test + public void test12ASyncEachAnimatorCleanDtorOrderMapBuffer() throws InterruptedException { + asyncEachAnimator(true, true); + } + + @Test + public void test13AsyncEachAnimatorDirtyDtorOrderCopyBuffers() throws InterruptedException { + asyncEachAnimator(false, false); + } + @Test + public void test14AsyncEachAnimatorDirtyDtorOrderMapBuffers() throws InterruptedException { + asyncEachAnimator(false, true); + } + + public void asyncEachAnimator(boolean destroyCleanOrder, boolean useMappedBuffers) throws InterruptedException { + final Animator a1 = new Animator(); + final GearsES2 g1 = new GearsES2(0); + g1.setUseMappedBuffers(useMappedBuffers); + g1.setValidateBuffers(true); + final GLWindow f1 = createGLWindow(0, 0, g1); + a1.add(f1); + a1.start(); + // f1.setVisible(true); // we do this post f2 .. to test pending creation! + + InsetsImmutable insets = f1.getInsets(); + + final Animator a2 = new Animator(); + final GearsES2 g2 = new GearsES2(0); + g2.setSharedGears(g1); + final GLWindow f2 = createGLWindow(f1.getX()+width+insets.getTotalWidth(), + f1.getY()+0, g2); + f2.setSharedAutoDrawable(f1); + a2.add(f2); + a2.start(); + f2.setVisible(true); + + f1.setVisible(true); // test pending creation of f2 + + final Animator a3 = new Animator(); + final GearsES2 g3 = new GearsES2(0); + g3.setSharedGears(g1); + final GLWindow f3 = createGLWindow(f1.getX()+0, + f1.getY()+height+insets.getTotalHeight(), g3); + f3.setSharedAutoDrawable(f1); + a3.add(f3); + a3.start(); + f3.setVisible(true); + + Thread.sleep(1000/60*10); // wait ~10 frames giving a chance to create (blocking until master share is valid) + + Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, true)); + Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true)); + + Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f2, true)); + Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true)); + + Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, true)); + Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true)); + + final GLContext ctx1 = f1.getContext(); + final GLContext ctx2 = f2.getContext(); + final GLContext ctx3 = f3.getContext(); + { + final List<GLContext> ctx1Shares = ctx1.getCreatedShares(); + final List<GLContext> ctx2Shares = ctx2.getCreatedShares(); + final List<GLContext> ctx3Shares = ctx3.getCreatedShares(); + System.err.println("XXX-C-3.1:"); + MiscUtils.dumpSharedGLContext(ctx1); + System.err.println("XXX-C-3.2:"); + MiscUtils.dumpSharedGLContext(ctx2); + System.err.println("XXX-C-3.3:"); + MiscUtils.dumpSharedGLContext(ctx3); + + Assert.assertTrue("Ctx1 is not shared", ctx1.isShared()); + Assert.assertTrue("Ctx2 is not shared", ctx2.isShared()); + Assert.assertTrue("Ctx3 is not shared", ctx3.isShared()); + Assert.assertEquals("Ctx1 has unexpected number of created shares", 2, ctx1Shares.size()); + Assert.assertEquals("Ctx2 has unexpected number of created shares", 2, ctx2Shares.size()); + Assert.assertEquals("Ctx3 has unexpected number of created shares", 2, ctx3Shares.size()); + } + + Assert.assertTrue("Gears1 is shared", !g1.usesSharedGears()); + Assert.assertTrue("Gears2 is not shared", g2.usesSharedGears()); + Assert.assertTrue("Gears3 is not shared", g3.usesSharedGears()); + + try { + Thread.sleep(duration); + } catch(Exception e) { + e.printStackTrace(); + } + + if( destroyCleanOrder ) { + System.err.println("XXX Destroy in clean order NOW"); + a3.stop(); + f3.destroy(); + try { Thread.sleep(durationPostDestroy); } catch(Exception e) { e.printStackTrace(); } + a2.stop(); + f2.destroy(); + try { Thread.sleep(durationPostDestroy); } catch(Exception e) { e.printStackTrace(); } + a1.stop(); + f1.destroy(); + try { Thread.sleep(durationPostDestroy); } catch(Exception e) { e.printStackTrace(); } + } else { + System.err.println("XXX Destroy in creation order NOW - Driver Impl. May trigger driver Bug i.e. not postponing GL ctx destruction after releasing all refs."); + a1.stop(); + a2.pause(); + a3.pause(); + f1.destroy(); + a2.resume(); + a3.resume(); + try { Thread.sleep(durationPostDestroy); } catch(Exception e) { e.printStackTrace(); } + + a2.stop(); + a3.pause(); + f2.destroy(); + a3.resume(); + try { Thread.sleep(durationPostDestroy); } catch(Exception e) { e.printStackTrace(); } + + a3.stop(); + f3.destroy(); + try { Thread.sleep(durationPostDestroy); } catch(Exception e) { e.printStackTrace(); } + } + Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, false)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, false)); + } + + static long duration = 1000; // ms + static long durationPostDestroy = 1000; // ms - ~60 frames post destroy + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + try { + duration = Integer.parseInt(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } + } + /** + BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); + System.err.println("Press enter to continue"); + System.err.println(stdin.readLine()); */ + org.junit.runner.JUnitCore.main(TestSharedContextVBOES2NEWT3.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2SWT3.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2SWT3.java new file mode 100644 index 000000000..9ccfd394f --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2SWT3.java @@ -0,0 +1,375 @@ +/** + * 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.jogl.acore; + +import java.util.List; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLProfile; + +import com.jogamp.nativewindow.swt.SWTAccessor; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.swt.GLCanvas; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.junit.After; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +/** + * Sharing the VBO of 3 GearsES2 instances, each in their own SWT GLCanvas. + * <p> + * This is achieved by using the 1st GLCanvas as the <i>master</i> + * and using the build-in blocking mechanism to postpone creation + * of the 2nd and 3rd GLCanvas until the 1st GLCanvas's GLContext becomes created. + * </p> + * <p> + * Above method allows random creation of the 1st GLCanvas <b>in theory</b>, which triggers + * creation of the <i>dependent</i> other GLCanvas sharing it's GLContext.<br> + * However, since this test may perform on the <i>main thread</i> we have + * to initialize all in order, since otherwise the <i>test main thread</i> + * itself blocks SWT GLCanvas creation .. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestSharedContextVBOES2SWT3 extends UITestCase { + static GLProfile glp; + static GLCapabilities caps; + static int width, height; + + @BeforeClass + public static void initClass() { + if(GLProfile.isAvailable(GLProfile.GL2ES2)) { + glp = GLProfile.get(GLProfile.GL2ES2); + Assert.assertNotNull(glp); + caps = new GLCapabilities(glp); + Assert.assertNotNull(caps); + width = 256; + height = 256; + } else { + setTestSupported(false); + } + } + + Display display = null; + Shell shell1 = null; + Composite composite1 = null; + Shell shell2 = null; + Composite composite2 = null; + Shell shell3 = null; + Composite composite3 = null; + + @Before + public void init() { + SWTAccessor.invoke(true, new Runnable() { + public void run() { + display = new Display(); + Assert.assertNotNull( display ); + }}); + display.syncExec(new Runnable() { + public void run() { + shell1 = new Shell( display ); + shell1.setLayout( new FillLayout() ); + composite1 = new Composite( shell1, SWT.NO_BACKGROUND ); + composite1.setLayout( new FillLayout() ); + + shell2 = new Shell( display ); + shell2.setLayout( new FillLayout() ); + composite2 = new Composite( shell2, SWT.NO_BACKGROUND ); + composite2.setLayout( new FillLayout() ); + + shell3 = new Shell( display ); + shell3.setLayout( new FillLayout() ); + composite3 = new Composite( shell3, SWT.NO_BACKGROUND ); + composite3.setLayout( new FillLayout() ); + }}); + } + + @After + public void release() { + Assert.assertNotNull( display ); + Assert.assertNotNull( shell1 ); + Assert.assertNotNull( composite1 ); + Assert.assertNotNull( shell2 ); + Assert.assertNotNull( composite2 ); + Assert.assertNotNull( shell3 ); + Assert.assertNotNull( composite3 ); + try { + display.syncExec(new Runnable() { + public void run() { + composite3.dispose(); + shell3.dispose(); + composite2.dispose(); + shell2.dispose(); + composite1.dispose(); + shell1.dispose(); + }}); + SWTAccessor.invoke(true, new Runnable() { + public void run() { + display.dispose(); + }}); + } + catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + display = null; + shell1 = null; + composite1 = null; + shell2 = null; + composite2 = null; + shell3 = null; + composite3 = null; + } + + protected GLCanvas createGLCanvas(final Shell shell, final Composite composite, final int x, final int y, GearsES2 gears) throws InterruptedException { + final GLCanvas glCanvas = GLCanvas.create( composite, 0, caps, null); + Assert.assertNotNull( glCanvas ); + glCanvas.addGLEventListener(gears); + display.syncExec(new Runnable() { + public void run() { + shell.setText("SWT GLCanvas Shared Gears Test"); + shell.setSize( width, height); + shell.setLocation(x, y); + } } ); + return glCanvas; + } + + @Test + public void test01SyncedOneAnimator() throws InterruptedException { + final Animator animator = new Animator(); + final GearsES2 g1 = new GearsES2(0); + final GLCanvas c1 = createGLCanvas(shell1, composite1, 0, 0, g1); + animator.add(c1); + + final GearsES2 g2 = new GearsES2(0); + g2.setSharedGears(g1); + final GLCanvas c2 = createGLCanvas(shell2, composite2, 0+width, 0+0, g2); + c2.setSharedAutoDrawable(c1); + animator.add(c2); + + final GearsES2 g3 = new GearsES2(0); + g3.setSharedGears(g1); + final GLCanvas c3 = createGLCanvas(shell3, composite3, 0, height, g3); + c3.setSharedAutoDrawable(c1); + animator.add(c3); + + display.syncExec(new Runnable() { + public void run() { + shell1.open(); // master .. + shell2.open(); // shall wait until f1 is ready + shell3.open(); // shall wait until f1 is ready + } } ); + animator.start(); // kicks off GLContext .. and hence gears of f2 + f3 completion + + Thread.sleep(1000/60*10); // wait ~10 frames giving a chance to create (blocking until master share is valid) + + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c1, true)); + Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true)); + + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c2, true)); + Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true)); + + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c3, true)); + Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true)); + + final GLContext ctx1 = c1.getContext(); + final GLContext ctx2 = c2.getContext(); + final GLContext ctx3 = c3.getContext(); + { + final List<GLContext> ctx1Shares = ctx1.getCreatedShares(); + final List<GLContext> ctx2Shares = ctx2.getCreatedShares(); + final List<GLContext> ctx3Shares = ctx3.getCreatedShares(); + System.err.println("XXX-C-3.1:"); + MiscUtils.dumpSharedGLContext(ctx1); + System.err.println("XXX-C-3.2:"); + MiscUtils.dumpSharedGLContext(ctx2); + System.err.println("XXX-C-3.3:"); + MiscUtils.dumpSharedGLContext(ctx3); + + Assert.assertTrue("Ctx1 is not shared", ctx1.isShared()); + Assert.assertTrue("Ctx2 is not shared", ctx2.isShared()); + Assert.assertTrue("Ctx3 is not shared", ctx3.isShared()); + Assert.assertEquals("Ctx1 has unexpected number of created shares", 2, ctx1Shares.size()); + Assert.assertEquals("Ctx2 has unexpected number of created shares", 2, ctx2Shares.size()); + Assert.assertEquals("Ctx3 has unexpected number of created shares", 2, ctx3Shares.size()); + } + + Assert.assertTrue("Gears1 is shared", !g1.usesSharedGears()); + Assert.assertTrue("Gears2 is not shared", g2.usesSharedGears()); + Assert.assertTrue("Gears3 is not shared", g3.usesSharedGears()); + + try { + Thread.sleep(duration); + } catch(Exception e) { + e.printStackTrace(); + } + // Stopped animator allows native windowing system 'repaint' event + // to trigger GLAD 'display' + animator.stop(); + Assert.assertEquals(false, animator.isAnimating()); + + display.syncExec(new Runnable() { + public void run() { + c3.dispose(); + c2.dispose(); + c1.dispose(); + } } ); + } + + @Test + public void test02AsyncEachAnimator() throws InterruptedException { + final Animator a1 = new Animator(); + final GearsES2 g1 = new GearsES2(0); + final GLCanvas c1 = createGLCanvas(shell1, composite1, 0, 0, g1); + a1.add(c1); + display.syncExec(new Runnable() { + public void run() { + shell1.open(); + } } ); + a1.start(); + + + Thread.sleep(1000/60*10); // wait ~10 frames giving a chance to create (blocking until master share is valid) + + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c1, true)); + Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true)); + + final Animator a2 = new Animator(); + final GearsES2 g2 = new GearsES2(0); + g2.setSharedGears(g1); + final GLCanvas c2 = createGLCanvas(shell2, composite2, width, 0, g2); + c2.setSharedAutoDrawable(c1); + a2.add(c2); + display.syncExec(new Runnable() { + public void run() { + shell2.open(); + } } ); + a2.start(); + + Thread.sleep(200); // wait a while .. + + final Animator a3 = new Animator(); + final GearsES2 g3 = new GearsES2(0); + g3.setSharedGears(g1); + final GLCanvas c3 = createGLCanvas(shell3, composite3, 0, height, g3); + c3.setSharedAutoDrawable(c1); + a3.add(c3); + display.syncExec(new Runnable() { + public void run() { + shell3.open(); + } } ); + a3.start(); + + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c2, true)); + Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true)); + + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c3, true)); + Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true)); + + final GLContext ctx1 = c1.getContext(); + final GLContext ctx2 = c2.getContext(); + final GLContext ctx3 = c3.getContext(); + { + final List<GLContext> ctx1Shares = ctx1.getCreatedShares(); + final List<GLContext> ctx2Shares = ctx2.getCreatedShares(); + final List<GLContext> ctx3Shares = ctx3.getCreatedShares(); + System.err.println("XXX-C-3.1:"); + MiscUtils.dumpSharedGLContext(ctx1); + System.err.println("XXX-C-3.2:"); + MiscUtils.dumpSharedGLContext(ctx2); + System.err.println("XXX-C-3.3:"); + MiscUtils.dumpSharedGLContext(ctx3); + + Assert.assertTrue("Ctx1 is not shared", ctx1.isShared()); + Assert.assertTrue("Ctx2 is not shared", ctx2.isShared()); + Assert.assertTrue("Ctx3 is not shared", ctx3.isShared()); + Assert.assertEquals("Ctx1 has unexpected number of created shares", 2, ctx1Shares.size()); + Assert.assertEquals("Ctx2 has unexpected number of created shares", 2, ctx2Shares.size()); + Assert.assertEquals("Ctx3 has unexpected number of created shares", 2, ctx3Shares.size()); + } + + Assert.assertTrue("Gears1 is shared", !g1.usesSharedGears()); + Assert.assertTrue("Gears2 is not shared", g2.usesSharedGears()); + Assert.assertTrue("Gears3 is not shared", g3.usesSharedGears()); + + try { + Thread.sleep(duration); + } catch(Exception e) { + e.printStackTrace(); + } + // Stopped animator allows native windowing system 'repaint' event + // to trigger GLAD 'display' + a1.stop(); + Assert.assertEquals(false, a1.isAnimating()); + a2.stop(); + Assert.assertEquals(false, a2.isAnimating()); + a3.stop(); + Assert.assertEquals(false, a3.isAnimating()); + + display.syncExec(new Runnable() { + public void run() { + c3.dispose(); + c2.dispose(); + c1.dispose(); + } } ); + } + + static long duration = 1000; // ms + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + try { + duration = Integer.parseInt(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } + } + /** + BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); + System.err.println("Press enter to continue"); + System.err.println(stdin.readLine()); */ + org.junit.runner.JUnitCore.main(TestSharedContextVBOES2SWT3.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextWithJTabbedPaneAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextWithJTabbedPaneAWT.java new file mode 100644 index 000000000..d6a6f7bed --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextWithJTabbedPaneAWT.java @@ -0,0 +1,264 @@ +/** + * Copyright (C) 2013 United States Government as represented by the Administrator of the + * National Aeronautics and Space Administration. + * All Rights Reserved. + * + * 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.jogl.acore; + +import java.awt.BorderLayout; +import java.lang.reflect.InvocationTargetException; +import java.nio.FloatBuffer; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTabbedPane; +import javax.swing.SwingUtilities; +import javax.swing.WindowConstants; + +import org.junit.Assert; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import com.jogamp.common.nio.Buffers; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestSharedContextWithJTabbedPaneAWT extends UITestCase { + + static class DemoInstance { + protected static GLCapabilities getCaps() { + GLCapabilities caps = new GLCapabilities(GLProfile.getMaxFixedFunc(true)); + + caps.setAlphaBits(8); + caps.setRedBits(8); + caps.setGreenBits(8); + caps.setBlueBits(8); + caps.setDepthBits(24); + caps.setDoubleBuffered(true); + + return caps; + } + + int[] bufferId; + + @SuppressWarnings("serial") + class SharedGLPanel extends JPanel implements GLEventListener { + final GLCanvas canvas; + final boolean shared; + + public SharedGLPanel(GLCanvas shareWith, int width, int height) { + GLContext sharedCtx = shareWith != null ? shareWith.getContext() : null; + System.err.println("XXX WWPanel: shareWith "+shareWith+", sharedCtx "+sharedCtx); + canvas = new GLCanvas(getCaps()); // same caps for 1st and 2nd shared ctx ! + if( null != shareWith) { + canvas.setSharedAutoDrawable(shareWith); + shared = true; + } else { + shared = false; + } + canvas.setSize(new java.awt.Dimension(width, height)); + + setLayout(new BorderLayout(5, 5)); + add(canvas, BorderLayout.CENTER); + setOpaque(false); + + canvas.addGLEventListener(this); + } + + @Override + public void init(GLAutoDrawable glAutoDrawable) { + if (!shared) { + Assert.assertNull("Buffer is set, but instance is share master", bufferId); + makeVBO(glAutoDrawable); + System.err.println("XXX Create Buffer "+bufferId[0]); + } else { + Assert.assertNotNull("Buffer is not set, but instance is share slave", bufferId); + Assert.assertTrue("Context is not shared", glAutoDrawable.getContext().isShared()); + System.err.println("XXX Reuse Buffer "+bufferId[0]); + } + final GL2 gl = glAutoDrawable.getGL().getGL2(); + if( shared ) { + gl.glColor3f(1, 1, 1); + gl.glClearColor(0.3f, 0.3f, 0.3f, 1f); + } else { + gl.glColor3f(0, 0, 0); + gl.glClearColor(1f, 1f, 1f, 1f); + } + gl.glShadeModel(GL2.GL_FLAT); + } + + @Override + public void dispose(GLAutoDrawable glAutoDrawable) {} + + @Override + public void display(GLAutoDrawable glAutoDrawable) { + final GL2 gl = glAutoDrawable.getGL().getGL2(); + + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + + gl.glEnableClientState(GL2.GL_VERTEX_ARRAY); + gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, bufferId[0]); + gl.glVertexPointer(3, GL2.GL_FLOAT, 0, 0); + gl.glDrawArrays(GL2.GL_LINES, 0, 2); + } + + @Override + public void reshape(GLAutoDrawable glAutoDrawable, int i, int i1, int i2, int i3) { + int w = getWidth(); + int h = getHeight(); + + final GL2 gl = glAutoDrawable.getGL().getGL2(); + + gl.glViewport(0, 0, w, h); + gl.glMatrixMode(GL2.GL_PROJECTION); + gl.glLoadIdentity(); + gl.glOrtho(0, 1, 0, 1, -1, 1); + gl.glMatrixMode(GL2.GL_MODELVIEW); + gl.glLoadIdentity(); + } + } + + protected void makeVBO(GLAutoDrawable drawable) { + GL2 gl = drawable.getGL().getGL2(); + + bufferId = new int[1]; + gl.glGenBuffers(1, bufferId, 0); + gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, bufferId[0]); + + FloatBuffer vertices = Buffers.newDirectFloatBuffer(6); + vertices.put(0).put(0).put(0); + vertices.put(1).put(1).put(0); + gl.glBufferData(GL2.GL_ARRAY_BUFFER, vertices.capacity() * 4, vertices.rewind(), GL2.GL_STATIC_DRAW); + } + + public JTabbedPane tabbedPanel; + + public DemoInstance(JFrame f) { + try + { + GLProfile.initSingleton(); // Lets have init debug messages above below marker + System.err.println("XXX START DEMO XXX"); + + // Create the application frame and the tabbed pane and add the pane to the frame. + tabbedPanel = new JTabbedPane(); + f.add(tabbedPanel, BorderLayout.CENTER); + + // Create two World Windows that share resources. + SharedGLPanel wwpA = new SharedGLPanel(null, 600, 600); + SharedGLPanel wwpB = new SharedGLPanel(wwpA.canvas, wwpA.getWidth(), wwpA.getHeight()); + + tabbedPanel.add(wwpA, "Window A"); + tabbedPanel.add(wwpB, "Window B"); + + // Add the card panel to the frame. + f.add(tabbedPanel, BorderLayout.CENTER); + + // Position and display the frame. + f.setTitle("Multi-Window Tabbed Pane"); + f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + f.pack(); + f.setResizable(true); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + static long durationPerTest = 500*4; // ms + static boolean manual = false; + + @Test + public void test01() throws InterruptedException, InvocationTargetException { + final JFrame f = new JFrame(); + f.setTitle("Shared GLContext AWT GLCanvas JTabbedPane"); + final DemoInstance demo = new DemoInstance(f); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + System.err.println("XXX SetVisible XXX"); + f.setVisible(true); + } }); + + if(manual) { + for(long w=durationPerTest; w>0; w-=100) { + Thread.sleep(100); + } + } else { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + demo.tabbedPanel.setSelectedIndex(0); + }}); + Thread.sleep(durationPerTest/4); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + demo.tabbedPanel.setSelectedIndex(1); + }}); + Thread.sleep(durationPerTest/4); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + demo.tabbedPanel.setSelectedIndex(0); + }}); + Thread.sleep(durationPerTest/4); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + demo.tabbedPanel.setSelectedIndex(1); + }}); + Thread.sleep(durationPerTest/4); + } + + SwingUtilities.invokeLater(new Runnable() { + public void run() { + System.err.println("XXX SetVisible XXX"); + f.dispose(); + } }); + } + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + durationPerTest = MiscUtils.atoi(args[++i], (int)durationPerTest); + } else if(args[i].equals("-manual")) { + manual = true; + } + } + org.junit.runner.JUnitCore.main(TestSharedContextWithJTabbedPaneAWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownCompleteAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownCompleteAWT.java index 9f2820a37..9f367ef0b 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownCompleteAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownCompleteAWT.java @@ -3,14 +3,14 @@ * * 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 @@ -20,12 +20,12 @@ * 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.jogl.acore; import java.awt.Frame; @@ -36,17 +36,23 @@ import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLProfile; import javax.media.opengl.awt.GLCanvas; +import org.junit.AfterClass; import org.junit.Assert; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +import com.jogamp.common.os.Platform; +import com.jogamp.opengl.JoglVersion; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.util.Animator; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestShutdownCompleteAWT extends UITestCase { static long duration = 300; // ms - + protected void runTestGL() throws InterruptedException, InvocationTargetException { final Frame frame = new Frame("Gears AWT Test"); Assert.assertNotNull(frame); @@ -54,7 +60,6 @@ public class TestShutdownCompleteAWT extends UITestCase { final GLCanvas glCanvas = new GLCanvas(new GLCapabilities(GLProfile.getGL2ES2())); Assert.assertNotNull(glCanvas); frame.add(glCanvas); - frame.setSize(256, 256); glCanvas.addGLEventListener(new GearsES2(1)); @@ -62,10 +67,11 @@ public class TestShutdownCompleteAWT extends UITestCase { javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame.setSize(256, 256); frame.setVisible(true); }}); - - animator.setUpdateFPSFrames(60, System.err); + + animator.setUpdateFPSFrames(60, System.err); animator.start(); Assert.assertEquals(true, animator.isAnimating()); Assert.assertEquals(true, glCanvas.isVisible()); @@ -78,7 +84,10 @@ public class TestShutdownCompleteAWT extends UITestCase { animator.stop(); Assert.assertEquals(false, animator.isAnimating()); - frame.setVisible(false); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + }}); Assert.assertEquals(false, frame.isVisible()); javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { @@ -87,37 +96,70 @@ public class TestShutdownCompleteAWT extends UITestCase { }}); } - protected void oneLife() throws InterruptedException, InvocationTargetException { - long t0 = System.nanoTime(); + @AfterClass + public static void afterAll() { + if(waitForKey) { + UITestCase.waitForKey("Exit"); + } + } + + protected void oneLife(boolean glInfo) throws InterruptedException, InvocationTargetException { + final long t0 = Platform.currentTimeMicros(); GLProfile.initSingleton(); - long t1 = System.nanoTime(); - runTestGL(); - long t2 = System.nanoTime(); - GLProfile.shutdown(GLProfile.ShutdownType.COMPLETE); - long t3 = System.nanoTime(); - System.err.println("Total: "+ (t3-t0)/1e6 +"ms"); - System.err.println(" GLProfile.initSingleton(): "+ (t1-t0)/1e6 +"ms"); - System.err.println(" Demo Code: "+ (t2-t1)/1e6 +"ms"); - System.err.println(" GLProfile.shutdown(COMPLETE): "+ (t3-t2)/1e6 +"ms"); + final long t1 = Platform.currentTimeMicros(); + if(!initOnly) { + runTestGL(); + } + final long t2 = Platform.currentTimeMicros(); + if(glInfo) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(null, null, false).toString()); + } + final long t3 = Platform.currentTimeMicros(); + GLProfile.shutdown(); + final long t4 = Platform.currentTimeMicros(); + System.err.println("Total: "+ (t4-t0)/1e3 +"ms"); + System.err.println(" GLProfile.initSingleton(): "+ (t1-t0)/1e3 +"ms"); + System.err.println(" Demo Code: "+ (t2-t1)/1e3 +"ms"); + System.err.println(" GLInfo: "+ (t3-t2)/1e3 +"ms"); + System.err.println(" GLProfile.shutdown(): "+ (t4-t3)/1e3 +"ms"); } - + @Test public void test01OneLife() throws InterruptedException, InvocationTargetException { - oneLife(); + oneLife(false); + } + + @Test + public void test02AnotherLifeWithGLInfo() throws InterruptedException, InvocationTargetException { + oneLife(true); } @Test - public void test01AnotherLife() throws InterruptedException, InvocationTargetException { - oneLife(); + public void test03AnotherLife() throws InterruptedException, InvocationTargetException { + oneLife(true); } - + @Test - public void test01TwoLifes() throws InterruptedException, InvocationTargetException { - oneLife(); - oneLife(); + public void test03TwoLifes() throws InterruptedException, InvocationTargetException { + oneLife(false); + oneLife(false); } - + + static boolean initOnly = false; + static boolean waitForKey = false; + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-wait")) { + waitForKey = true; + } else if(args[i].equals("-initOnly")) { + initOnly = true; + } + } + + if(waitForKey) { + UITestCase.waitForKey("Start"); + } String tstname = TestShutdownCompleteAWT.class.getName(); org.junit.runner.JUnitCore.main(tstname); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownCompleteNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownCompleteNEWT.java index 459284177..e7d1cb8e9 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownCompleteNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownCompleteNEWT.java @@ -3,14 +3,14 @@ * * 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 @@ -20,35 +20,43 @@ * 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.jogl.acore; -import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStreamReader; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLProfile; +import org.junit.AfterClass; import org.junit.Assert; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +import com.jogamp.common.os.Platform; import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.JoglVersion; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.util.Animator; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestShutdownCompleteNEWT extends UITestCase { static long duration = 300; // ms - - protected void runTestGL() throws InterruptedException { - GLWindow glWindow = GLWindow.create(new GLCapabilities(GLProfile.getGL2ES2())); + + protected void runTestGL(boolean onscreen) throws InterruptedException { + GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES2()); + caps.setOnscreen(onscreen); + caps.setPBuffer(!onscreen); + + GLWindow glWindow = GLWindow.create(caps); Assert.assertNotNull(glWindow); glWindow.setTitle("Gears NEWT Test"); @@ -73,55 +81,63 @@ public class TestShutdownCompleteNEWT extends UITestCase { glWindow.destroy(); } - protected void oneLife() throws InterruptedException { + @AfterClass + public static void afterAll() { + if(waitForKey) { + UITestCase.waitForKey("Exit"); + } + } + + protected void oneLife(boolean glInfo) throws InterruptedException { if(waitForEach) { - waitForEnter(); + UITestCase.waitForKey("Start One Life"); } - long t0 = System.nanoTime(); + final long t0 = Platform.currentTimeMicros(); GLProfile.initSingleton(); - long t1 = System.nanoTime(); + final long t1 = Platform.currentTimeMicros(); if(!initOnly) { - runTestGL(); + runTestGL(true); } - long t2 = System.nanoTime(); - GLProfile.shutdown(GLProfile.ShutdownType.COMPLETE); - long t3 = System.nanoTime(); - System.err.println("Total: "+ (t3-t0)/1e6 +"ms"); - System.err.println(" GLProfile.initSingleton(): "+ (t1-t0)/1e6 +"ms"); - System.err.println(" Demo Code: "+ (t2-t1)/1e6 +"ms"); - System.err.println(" GLProfile.shutdown(COMPLETE): "+ (t3-t2)/1e6 +"ms"); + final long t2 = Platform.currentTimeMicros(); + if(glInfo) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(null, null, false).toString()); + } + final long t3 = Platform.currentTimeMicros(); + GLProfile.shutdown(); + final long t4 = Platform.currentTimeMicros(); + System.err.println("Total: "+ (t4-t0)/1e3 +"ms"); + System.err.println(" GLProfile.initSingleton(): "+ (t1-t0)/1e3 +"ms"); + System.err.println(" Demo Code: "+ (t2-t1)/1e3 +"ms"); + System.err.println(" GLInfo: "+ (t3-t2)/1e3 +"ms"); + System.err.println(" GLProfile.shutdown(): "+ (t4-t3)/1e3 +"ms"); } - + @Test public void test01OneLife() throws InterruptedException { - oneLife(); + oneLife(false); + } + + @Test + public void test02AnotherLifeWithGLInfo() throws InterruptedException { + oneLife(true); } @Test - public void test01AnotherLife() throws InterruptedException { - oneLife(); + public void test03AnotherLife() throws InterruptedException { + oneLife(true); } - + @Test - public void test01TwoLifes() throws InterruptedException { - oneLife(); - oneLife(); + public void test03TwoLifes() throws InterruptedException { + oneLife(false); + oneLife(false); } - + static boolean initOnly = false; static boolean waitForEach = false; - - static void waitForEnter() { - BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); - System.err.println("Press enter to continue"); - try { - System.err.println(stdin.readLine()); - } catch (IOException e) { } - } - + static boolean waitForKey = false; + public static void main(String args[]) throws IOException { - boolean waitForKey = false; - for(int i=0; i<args.length; i++) { if(args[i].equals("-wait")) { waitForKey = true; @@ -132,11 +148,11 @@ public class TestShutdownCompleteNEWT extends UITestCase { initOnly = true; } } - + if(waitForKey) { - waitForEnter(); + UITestCase.waitForKey("Start"); } - + String tstname = TestShutdownCompleteNEWT.class.getName(); org.junit.runner.JUnitCore.main(tstname); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownSharedAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownSharedAWT.java deleted file mode 100644 index 3274ea820..000000000 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownSharedAWT.java +++ /dev/null @@ -1,124 +0,0 @@ -/** - * 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.jogl.acore; - -import java.awt.Frame; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; - -import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLProfile; -import javax.media.opengl.awt.GLCanvas; - -import org.junit.Assert; -import org.junit.Test; - -import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; -import com.jogamp.opengl.test.junit.util.UITestCase; -import com.jogamp.opengl.util.Animator; - -public class TestShutdownSharedAWT extends UITestCase { - - static long duration = 300; // ms - - protected void runTestGL() throws InterruptedException, InvocationTargetException { - final Frame frame = new Frame("Gears AWT Test"); - Assert.assertNotNull(frame); - - final GLCanvas glCanvas = new GLCanvas(new GLCapabilities(GLProfile.getGL2ES2())); - Assert.assertNotNull(glCanvas); - frame.add(glCanvas); - frame.setSize(256, 256); - - glCanvas.addGLEventListener(new GearsES2(1)); - - Animator animator = new Animator(glCanvas); - - javax.swing.SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - frame.setVisible(true); - }}); - animator.setUpdateFPSFrames(60, System.err); - animator.start(); - Assert.assertEquals(true, animator.isAnimating()); - Assert.assertEquals(true, glCanvas.isVisible()); - Assert.assertEquals(true, glCanvas.isDisplayable()); - - while(animator.isAnimating() && animator.getTotalFPSDuration()<duration) { - Thread.sleep(100); - } - Assert.assertEquals(true, glCanvas.isRealized()); - - animator.stop(); - Assert.assertEquals(false, animator.isAnimating()); - frame.setVisible(false); - Assert.assertEquals(false, frame.isVisible()); - javax.swing.SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - frame.remove(glCanvas); - frame.dispose(); - }}); - } - - protected void oneLife() throws InterruptedException, InvocationTargetException { - long t0 = System.nanoTime(); - GLProfile.initSingleton(); - long t1 = System.nanoTime(); - runTestGL(); - long t2 = System.nanoTime(); - GLProfile.shutdown(GLProfile.ShutdownType.SHARED_ONLY); - long t3 = System.nanoTime(); - System.err.println("Total: "+ (t3-t0)/1e6 +"ms"); - System.err.println(" GLProfile.initSingleton(): "+ (t1-t0)/1e6 +"ms"); - System.err.println(" Demo Code: "+ (t2-t1)/1e6 +"ms"); - System.err.println(" GLProfile.shutdown(SHARED): "+ (t3-t2)/1e6 +"ms"); - } - - @Test - public void test01OneLife() throws InterruptedException, InvocationTargetException { - oneLife(); - } - - @Test - public void test01AnotherLife() throws InterruptedException, InvocationTargetException { - oneLife(); - } - - @Test - public void test01TwoLifes() throws InterruptedException, InvocationTargetException { - oneLife(); - oneLife(); - } - - public static void main(String args[]) throws IOException { - String tstname = TestShutdownSharedAWT.class.getName(); - org.junit.runner.JUnitCore.main(tstname); - } - -} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownSharedNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownSharedNEWT.java deleted file mode 100644 index 8db7dff9b..000000000 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownSharedNEWT.java +++ /dev/null @@ -1,127 +0,0 @@ -/** - * 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.jogl.acore; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; - -import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLProfile; - -import org.junit.Assert; -import org.junit.Test; - -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; - -public class TestShutdownSharedNEWT extends UITestCase { - - static long duration = 300; // ms - - protected void runTestGL() throws InterruptedException { - GLWindow glWindow = GLWindow.create(new GLCapabilities(GLProfile.getGL2ES2())); - Assert.assertNotNull(glWindow); - glWindow.setTitle("Gears NEWT Test"); - - glWindow.addGLEventListener(new GearsES2()); - - Animator animator = new Animator(glWindow); - - glWindow.setSize(256, 256); - glWindow.setVisible(true); - animator.setUpdateFPSFrames(60, System.err); - animator.start(); - Assert.assertEquals(true, animator.isAnimating()); - Assert.assertEquals(true, glWindow.isVisible()); - Assert.assertEquals(true, glWindow.isNativeValid()); - Assert.assertEquals(true, glWindow.isRealized()); - - while(animator.isAnimating() && animator.getTotalFPSDuration()<duration) { - Thread.sleep(100); - } - - animator.stop(); - glWindow.destroy(); - } - - protected void oneLife() throws InterruptedException { - long t0 = System.nanoTime(); - GLProfile.initSingleton(); - long t1 = System.nanoTime(); - runTestGL(); - long t2 = System.nanoTime(); - GLProfile.shutdown(GLProfile.ShutdownType.SHARED_ONLY); - long t3 = System.nanoTime(); - System.err.println("Total: "+ (t3-t0)/1e6 +"ms"); - System.err.println(" GLProfile.initSingleton(): "+ (t1-t0)/1e6 +"ms"); - System.err.println(" Demo Code: "+ (t2-t1)/1e6 +"ms"); - System.err.println(" GLProfile.shutdown(SHARED): "+ (t3-t2)/1e6 +"ms"); - } - - @Test - public void test01OneLife() throws InterruptedException { - oneLife(); - } - - @Test - public void test01AnotherLife() throws InterruptedException { - oneLife(); - } - - @Test - public void test01TwoLifes() throws InterruptedException { - oneLife(); - oneLife(); - } - - public static void main(String args[]) throws IOException { - boolean waitForKey = false; - - for(int i=0; i<args.length; i++) { - if(args[i].equals("-wait")) { - waitForKey = true; - } - } - - 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) { } - } - - String tstname = TestShutdownSharedNEWT.class.getName(); - org.junit.runner.JUnitCore.main(tstname); - } - -} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestX11DefaultDisplay.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestX11DefaultDisplay.java new file mode 100644 index 000000000..fca2beb73 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestX11DefaultDisplay.java @@ -0,0 +1,147 @@ +/** + * Copyright 2011 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.jogl.acore; + +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.NativeWindowFactory; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.jogl.demos.es1.RedSquareES1; +import com.jogamp.opengl.test.junit.util.DumpGLInfo; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; + +/** + * This is a clone of TestGLPointsNEWT which uses the ability to specify + * the X11 default display programmatically instead of relying on the + * DISPLAY environment variable. + * + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestX11DefaultDisplay extends UITestCase { + static long duration = 500; // ms + static int width = 512, height = 512; + static String x11DefaultDisplay = ":0.0"; + + @BeforeClass + public static void initClass() { + System.setProperty("nativewindow.x11.display.default", x11DefaultDisplay); + } + + protected void runTestGL(GLCapabilities caps) throws InterruptedException { + final GLWindow glWindow = GLWindow.create(caps); + Assert.assertNotNull(glWindow); + glWindow.setTitle(getSimpleTestName(".")); + glWindow.setSize(width, height); + + final RedSquareES1 demo = new RedSquareES1(); + glWindow.addGLEventListener(demo); + + final SnapshotGLEventListener snap = new SnapshotGLEventListener(); + snap.setPostSNDetail(demo.getClass().getSimpleName()); + glWindow.addGLEventListener(snap); + + Animator animator = new Animator(glWindow); + QuitAdapter quitAdapter = new QuitAdapter(); + + glWindow.addKeyListener(quitAdapter); + glWindow.addWindowListener(quitAdapter); + + animator.start(); + + glWindow.setVisible(true); + + System.err.println("NW chosen: "+glWindow.getDelegatedWindow().getChosenCapabilities()); + System.err.println("GL chosen: "+glWindow.getChosenCapabilities()); + System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", "+glWindow.getInsets()); + + animator.setUpdateFPSFrames(60, System.err); + snap.setMakeSnapshot(); + + while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) { + Thread.sleep(100); + } + + animator.stop(); + glWindow.destroy(); + } + + @Test + public void test00_DefaultDevice() { + final AbstractGraphicsDevice defaultDevice = GLProfile.getDefaultDevice(); + System.out.println("GLProfile "+GLProfile.glAvailabilityToString()); + System.out.println("GLProfile.getDefaultDevice(): "+defaultDevice); + GLProfile glp = GLProfile.getDefault(); + System.out.println("GLProfile.getDefault(): "+glp); + + GLCapabilities caps = new GLCapabilities(glp); + GLWindow glWindow = GLWindow.create(caps); + Assert.assertNotNull(glWindow); + + glWindow.addGLEventListener(new DumpGLInfo()); + + glWindow.setSize(128, 128); + glWindow.setVisible(true); + + glWindow.display(); + glWindow.destroy(); + + if( NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(true) ) { + Assert.assertEquals("X11 Default device does not match", defaultDevice.getConnection(), x11DefaultDisplay); + } + } + + @Test + public void test01_GLDefaultRendering() throws InterruptedException { + GLCapabilities caps = new GLCapabilities(null); + runTestGL(caps); + } + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-x11DefaultDisplay")) { + x11DefaultDisplay = args[++i]; + } + } + org.junit.runner.JUnitCore.main(TestX11DefaultDisplay.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/Bug898AnimatorFromEDTAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/Bug898AnimatorFromEDTAWT.java new file mode 100644 index 000000000..55e045d48 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/Bug898AnimatorFromEDTAWT.java @@ -0,0 +1,129 @@ +/** + * Copyright 2013 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.jogl.acore.anim; + +import java.awt.BorderLayout; +import java.awt.Dimension; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; +import javax.swing.SwingUtilities; + +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.util.Animator; + +/** + * Manual test case to validate Animator pause/resume on AWT-EDT. + * <p> + * Even though (AWT) Animator is not able to block until pause/resume is finished + * when issued on AWT-EDT, best effort shall be made to preserve functionality. + * </p> + * Original Author: <i>kosukek</i> from JogAmp forum; Modifier a bit. + */ +@SuppressWarnings("serial") +public class Bug898AnimatorFromEDTAWT extends javax.swing.JFrame { + + public Bug898AnimatorFromEDTAWT() { + setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); + //Layout + setMinimumSize(new Dimension(640, 480)); + getContentPane().setLayout(new BorderLayout()); + GLCanvas panel = new GLCanvas(new GLCapabilities(GLProfile.getMaxProgrammable(true))); + getContentPane().add(panel, BorderLayout.CENTER); + pack(); + //Animator + final Animator animator = new Animator(); + animator.add(panel); + //GLEventListener + panel.addGLEventListener(new GearsES2(1)); + panel.addGLEventListener(new GLEventListener() { + long startTime = 0, lastTime = 0; + long step = 1; + + @Override + public void init(GLAutoDrawable glad) { + startTime = System.currentTimeMillis(); + } + + @Override + public void dispose(GLAutoDrawable glad) { + } + + @Override + public void display(GLAutoDrawable glad) { + long time = System.currentTimeMillis(); + if (animator.isAnimating() && step * 2000 < time - startTime) { + long td = time - lastTime; + lastTime = time; + animator.pause(); + System.out.println(Thread.currentThread().getName()+": #"+step+" "+td+" ms: animator.pause(): paused "+animator); + new Thread() { + public void run() { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + long td = System.currentTimeMillis() - lastTime; + if (animator.isPaused()) { + animator.resume(); //Doesn't work on v2.0.2 or higher + System.out.println(Thread.currentThread().getName()+": #"+step+" "+td+" ms: animator.resume(): animating "+animator); + } else { + System.out.println(Thread.currentThread().getName()+": #"+step+" "+td+" ms: animator.resume(): Ooops - not paused! - animating "+animator); + } + } } ); + } + }.start(); + step++; + } + } + + @Override + public void reshape(GLAutoDrawable glad, int i, int i1, int i2, int i3) { + } + }); + //Start animation + animator.start(); + System.out.println("animator.start()"); + } + + public static void main(String args[]) { + java.awt.EventQueue.invokeLater(new Runnable() { + @Override + public void run() { + new Bug898AnimatorFromEDTAWT().setVisible(true); + } + }); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWTCardLayoutAnimatorStartStopBug532.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/TestAWTCardLayoutAnimatorStartStopBug532.java index 8384e5b61..3790a87f7 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWTCardLayoutAnimatorStartStopBug532.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/TestAWTCardLayoutAnimatorStartStopBug532.java @@ -1,7 +1,8 @@ -package com.jogamp.opengl.test.junit.jogl.awt; +package com.jogamp.opengl.test.junit.jogl.acore.anim; import java.awt.BorderLayout; import java.awt.CardLayout; +import java.awt.Component; import java.awt.Dimension; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; @@ -9,11 +10,8 @@ import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.lang.reflect.InvocationTargetException; -import javax.media.nativewindow.NativeWindow; import javax.media.opengl.GLAnimatorControl; -import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; import javax.media.opengl.awt.GLCanvas; import javax.swing.JComboBox; @@ -21,69 +19,74 @@ import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; -import jogamp.nativewindow.windows.GDI; - import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; -import com.jogamp.common.os.Platform; 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.util.Animator; import com.jogamp.opengl.util.FPSAnimator; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestAWTCardLayoutAnimatorStartStopBug532 extends UITestCase { - static final String LABEL = "Label"; + static final String LABEL = "Label"; static final String CANVAS = "GLCanvas"; - + public enum AnimatorControlBehavior { StartStop, PauseResume, Continue; } - - static long durationPerTest = 200*4; // ms + + static long durationPerTest = 200*4; // ms static boolean manual = false; static volatile boolean shouldStop = false; - + private String selected = LABEL; - + @Test public void testFPSAnimatorStartStop() throws InterruptedException, InvocationTargetException { testImpl(AnimatorControlBehavior.StartStop, true); } - + @Test public void testFPSAnimatorResumePause() throws InterruptedException, InvocationTargetException { testImpl(AnimatorControlBehavior.PauseResume, true); } - + @Test public void testFPSAnimatorContinue() throws InterruptedException, InvocationTargetException { testImpl(AnimatorControlBehavior.Continue, true); } - + @Test public void testAnimatorStartStop() throws InterruptedException, InvocationTargetException { testImpl(AnimatorControlBehavior.StartStop, false); } - + @Test public void testAnimatorResumePause() throws InterruptedException, InvocationTargetException { testImpl(AnimatorControlBehavior.PauseResume, false); } - + @Test public void testAnimatorContinue() throws InterruptedException, InvocationTargetException { testImpl(AnimatorControlBehavior.Continue, false); } - + + private static String id(Object obj) { return "0x" + ( null!=obj ? Integer.toHexString(obj.hashCode()) : "nil" ); } + private static String str(Component c) { + return id(c)+": "+c.getClass().getSimpleName()+"[visible "+c.isVisible()+", showing "+c.isShowing()+", valid "+c.isValid()+ + ", displayable "+c.isDisplayable()+", "+c.getX()+"/"+c.getY()+" "+c.getWidth()+"x"+c.getHeight()+"]"; + } void testImpl(final AnimatorControlBehavior animCtrl, boolean useFPSAnimator) throws InterruptedException, InvocationTargetException { - final GLProfile glp = GLProfile.get(GLProfile.GL2); - final GLCapabilities caps = new GLCapabilities(glp); - final GLCanvas canvas = new GLCanvas(caps); + final GLProfile glp = GLProfile.get(GLProfile.GL2); + final GLCapabilities caps = new GLCapabilities(glp); + final GLCanvas canvas = new GLCanvas(caps); canvas.setPreferredSize(new Dimension(640, 480)); - + final GLAnimatorControl animatorCtrl = useFPSAnimator ? new FPSAnimator(canvas, 60) : new Animator(canvas); - animatorCtrl.setUpdateFPSFrames(60, System.err); + animatorCtrl.setUpdateFPSFrames(60, null);// System.err); switch (animCtrl) { case PauseResume: animatorCtrl.start(); @@ -92,12 +95,13 @@ public class TestAWTCardLayoutAnimatorStartStopBug532 extends UITestCase { case Continue: animatorCtrl.start(); break; + default: } canvas.addGLEventListener(new GearsES2(1)); /* if(Platform.OS_TYPE == Platform.OSType.WINDOWS) { canvas.addGLEventListener(new GLEventListener() { - public void init(GLAutoDrawable drawable) { } + public void init(GLAutoDrawable drawable) { } public void dispose(GLAutoDrawable drawable) { } public void display(GLAutoDrawable drawable) { final NativeWindow win = (NativeWindow) drawable.getNativeSurface(); @@ -114,15 +118,17 @@ public class TestAWTCardLayoutAnimatorStartStopBug532 extends UITestCase { final JFrame frame = new JFrame(); frame.setTitle(getSimpleTestName(" - ")); - frame.addWindowListener(new WindowAdapter() { + frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { animatorCtrl.stop(); shouldStop = true; - } + } }); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); - - final JPanel cards = new JPanel(new CardLayout()); + + final JLabel label = new JLabel("A label to cover the canvas"); + + final JPanel cards = new JPanel(new CardLayout()); final JPanel comboBoxPanel = new JPanel(); // nicer look .. final JComboBox comboBox = new JComboBox(new String[] { LABEL, CANVAS }); comboBox.setEditable(false); @@ -133,7 +139,13 @@ public class TestAWTCardLayoutAnimatorStartStopBug532 extends UITestCase { if(!newSelection.equals(selected)) { final String oldSelected = selected; if(newSelection.equals(CANVAS)) { - cl.show(cards, CANVAS); + System.err.println("XXX Card.SHOW Canvas PRE: "); + System.err.println(" CANVAS "+str(canvas)); + System.err.println(" LABEL "+str(label)); + cl.show(cards, CANVAS); + System.err.println("XXX Card.SHOW Canvas POST: "); + System.err.println(" CANVAS "+str(canvas)); + System.err.println(" LABEL "+str(label)); switch (animCtrl) { case StartStop: animatorCtrl.start(); @@ -141,6 +153,7 @@ public class TestAWTCardLayoutAnimatorStartStopBug532 extends UITestCase { case PauseResume: animatorCtrl.resume(); break; + default: } selected = CANVAS; } else if(newSelection.equals(LABEL)) { @@ -151,33 +164,39 @@ public class TestAWTCardLayoutAnimatorStartStopBug532 extends UITestCase { case PauseResume: animatorCtrl.pause(); break; + default: } - cl.show(cards, LABEL); + System.err.println("XXX Card.SHOW Label PRE: "); + System.err.println(" CANVAS "+str(canvas)); + System.err.println(" LABEL "+str(label)); + cl.show(cards, LABEL); + System.err.println("XXX Card.SHOW Label POST: "); + System.err.println(" CANVAS "+str(canvas)); + System.err.println(" LABEL "+str(label)); selected = LABEL; } else { throw new RuntimeException("oops .. unexpected item: "+evt); } - System.err.println("Item Change: "+oldSelected+" -> "+selected+", "+animatorCtrl); + System.err.println("Item Change: "+oldSelected+" -> "+selected+", "+animatorCtrl); } else { System.err.println("Item Stays: "+selected+", "+animatorCtrl); } } }); - comboBoxPanel.add(comboBox); + comboBoxPanel.add(comboBox); - cards.add(new JLabel("A label to cover the canvas"), LABEL); + cards.add(label, LABEL); cards.add(canvas, CANVAS); - + frame.add(comboBoxPanel, BorderLayout.PAGE_START); frame.add(cards, BorderLayout.CENTER); - - frame.pack(); - + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame.pack(); frame.setVisible(true); }}); - + if(manual) { for(long w=durationPerTest; !shouldStop && w>0; w-=100) { Thread.sleep(100); @@ -188,34 +207,34 @@ public class TestAWTCardLayoutAnimatorStartStopBug532 extends UITestCase { comboBox.setSelectedItem(LABEL); }}); Thread.sleep(durationPerTest/4); - + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { comboBox.setSelectedItem(CANVAS); }}); Thread.sleep(durationPerTest/4); - + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { comboBox.setSelectedItem(LABEL); }}); Thread.sleep(durationPerTest/4); - + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { comboBox.setSelectedItem(CANVAS); }}); Thread.sleep(durationPerTest/4); } - + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { frame.setVisible(false); frame.dispose(); }}); - + } - + public static void main(String args[]) { for(int i=0; i<args.length; i++) { if(args[i].equals("-time")) { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/TestAnimatorGLJPanel01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/TestAnimatorGLJPanel01AWT.java new file mode 100644 index 000000000..42f170a06 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/TestAnimatorGLJPanel01AWT.java @@ -0,0 +1,301 @@ +/** + * 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.jogl.acore.anim; + +import java.awt.Frame; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.awt.GLJPanel; + +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestAnimatorGLJPanel01AWT extends UITestCase { + static final int width = 640; + static final int height = 480; + + protected GLJPanel createGLJPanel(final GLCapabilities caps, final Frame frame, int x, int y, GearsES2 gears) throws InterruptedException { + final GLJPanel glCanvas = new GLJPanel(caps); + Assert.assertNotNull(glCanvas); + glCanvas.addGLEventListener(gears); + frame.add(glCanvas); + frame.setLocation(x, y); + frame.setSize(width, height); + frame.setTitle("GLJPanel: "+x+"/"+y); + return glCanvas; + } + + static void pauseAnimator(Animator animator, boolean pause) { + if(pause) { + animator.pause(); + Assert.assertEquals(true, animator.isStarted()); + Assert.assertEquals(true, animator.isPaused()); + Assert.assertEquals(false, animator.isAnimating()); + } else { + animator.resume(); + Assert.assertEquals(true, animator.isStarted()); + Assert.assertEquals(false, animator.isPaused()); + Assert.assertEquals(true, animator.isAnimating()); + } + } + static void stopAnimator(Animator animator) { + animator.stop(); + Assert.assertEquals(false, animator.isStarted()); + Assert.assertEquals(false, animator.isPaused()); + Assert.assertEquals(false, animator.isAnimating()); + } + + @Test + public void test01SyncedOneAnimator() throws InterruptedException, InvocationTargetException { + final GLCapabilities caps = new GLCapabilities(null); + final Frame f1 = new Frame(); + final Animator animator = new Animator(); + animator.start(); + Assert.assertEquals(true, animator.isStarted()); + Assert.assertEquals(true, animator.isPaused()); + Assert.assertEquals(false, animator.isAnimating()); + + final GearsES2 g1 = new GearsES2(0); + final GLJPanel c1 = createGLJPanel(caps, f1, 0, 0, g1); + animator.add(c1); + Assert.assertEquals(true, animator.isStarted()); + Assert.assertEquals(false, animator.isPaused()); + Assert.assertEquals(true, animator.isAnimating()); + + final Frame f2 = new Frame(); + final GearsES2 g2 = new GearsES2(0); + final GLJPanel c2 = createGLJPanel(caps, f2, f1.getX()+width, + f1.getY()+0, g2); + animator.add(c2); + + final Frame f3 = new Frame(); + final GearsES2 g3 = new GearsES2(0); + final GLJPanel c3 = createGLJPanel(caps, f3, f1.getX()+0, + f1.getY()+height, g3); + animator.add(c3); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + f1.setVisible(true); + f2.setVisible(true); + f3.setVisible(true); + } } ); + + Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c1, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c1, true)); + Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true)); + + Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c2, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c2, true)); + Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true)); + + Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c3, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c3, true)); + Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true)); + + try { + Thread.sleep(duration/3); + } catch(Exception e) { + e.printStackTrace(); + } + + pauseAnimator(animator, true); + + try { + Thread.sleep(duration/3); + } catch(Exception e) { + e.printStackTrace(); + } + + pauseAnimator(animator, false); + + try { + Thread.sleep(duration/3); + } catch(Exception e) { + e.printStackTrace(); + } + + // Stopped animator allows native windowing system 'repaint' event + // to trigger GLAD 'display' + stopAnimator(animator); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + try { + f1.dispose(); + f2.dispose(); + f3.dispose(); + } catch (Throwable t) { + throw new RuntimeException(t); + } + }}); + + Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, false)); + } + + @Test + public void test02AsyncEachAnimator() throws InterruptedException, InvocationTargetException { + final GLCapabilities caps = new GLCapabilities(null); + final Frame f1 = new Frame(); + final Animator a1 = new Animator(); + final GearsES2 g1 = new GearsES2(0); + final GLJPanel c1 = createGLJPanel(caps, f1, 0, 0, g1); + a1.add(c1); + a1.start(); + Assert.assertEquals(true, a1.isStarted()); + Assert.assertEquals(false, a1.isPaused()); + Assert.assertEquals(true, a1.isAnimating()); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + f1.setVisible(true); + } } ); + + final Frame f2 = new Frame(); + final Animator a2 = new Animator(); + final GearsES2 g2 = new GearsES2(0); + final GLJPanel c2 = createGLJPanel(caps, f2, f1.getX()+width, f1.getY()+0, g2); + a2.add(c2); + a2.start(); + Assert.assertEquals(true, a2.isStarted()); + Assert.assertEquals(false, a2.isPaused()); + Assert.assertEquals(true, a2.isAnimating()); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + f2.setVisible(true); + } } ); + + final Frame f3 = new Frame(); + final Animator a3 = new Animator(); + final GearsES2 g3 = new GearsES2(0); + final GLJPanel c3 = createGLJPanel(caps, f3, f1.getX()+0, f1.getY()+height, g3); + a3.add(c3); + a3.start(); + Assert.assertEquals(true, a3.isStarted()); + Assert.assertEquals(false, a3.isPaused()); + Assert.assertEquals(true, a3.isAnimating()); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + f3.setVisible(true); + } } ); + + Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c1, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c1, true)); + Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true)); + + Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c2, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c2, true)); + Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true)); + + Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c3, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c3, true)); + Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true)); + + try { + Thread.sleep(duration/3); + } catch(Exception e) { + e.printStackTrace(); + } + + pauseAnimator(a1, true); + pauseAnimator(a2, true); + pauseAnimator(a3, true); + + try { + Thread.sleep(duration/3); + } catch(Exception e) { + e.printStackTrace(); + } + + pauseAnimator(a1, false); + pauseAnimator(a2, false); + pauseAnimator(a3, false); + + try { + Thread.sleep(duration/3); + } catch(Exception e) { + e.printStackTrace(); + } + + // Stopped animator allows native windowing system 'repaint' event + // to trigger GLAD 'display' + stopAnimator(a1); + stopAnimator(a2); + stopAnimator(a3); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + try { + f1.dispose(); + f2.dispose(); + f3.dispose(); + } catch (Throwable t) { + throw new RuntimeException(t); + } + }}); + + Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, false)); + } + + static long duration = 3*500; // ms + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + try { + duration = Integer.parseInt(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } + } + /** + BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); + System.err.println("Press enter to continue"); + System.err.println(stdin.readLine()); */ + org.junit.runner.JUnitCore.main(TestAnimatorGLJPanel01AWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/TestAnimatorGLWindow01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/TestAnimatorGLWindow01NEWT.java new file mode 100644 index 000000000..7b0fbe9ee --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/anim/TestAnimatorGLWindow01NEWT.java @@ -0,0 +1,267 @@ +/** + * 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.jogl.acore.anim; + +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLCapabilities; + +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestAnimatorGLWindow01NEWT extends UITestCase { + static final int width = 640; + static final int height = 480; + + protected GLWindow createGLWindow(final GLCapabilities caps, int x, int y, GearsES2 gears) throws InterruptedException { + final GLWindow glWindow = GLWindow.create(caps); + Assert.assertNotNull(glWindow); + glWindow.addGLEventListener(gears); + glWindow.setPosition(x, y); + glWindow.setSize(width, height); + glWindow.setTitle("GLWindow: "+x+"/"+y); + return glWindow; + } + + static void pauseAnimator(Animator animator, boolean pause) { + if(pause) { + animator.pause(); + Assert.assertEquals(true, animator.isStarted()); + Assert.assertEquals(true, animator.isPaused()); + Assert.assertEquals(false, animator.isAnimating()); + } else { + animator.resume(); + Assert.assertEquals(true, animator.isStarted()); + Assert.assertEquals(false, animator.isPaused()); + Assert.assertEquals(true, animator.isAnimating()); + } + } + static void stopAnimator(Animator animator) { + animator.stop(); + Assert.assertEquals(false, animator.isStarted()); + Assert.assertEquals(false, animator.isPaused()); + Assert.assertEquals(false, animator.isAnimating()); + } + + @Test + public void test01SyncedOneAnimator() throws InterruptedException, InvocationTargetException { + final GLCapabilities caps = new GLCapabilities(null); + final Animator animator = new Animator(); + animator.start(); + Assert.assertEquals(true, animator.isStarted()); + Assert.assertEquals(true, animator.isPaused()); + Assert.assertEquals(false, animator.isAnimating()); + + final GearsES2 g1 = new GearsES2(0); + final GLWindow c1 = createGLWindow(caps, 0, 0, g1); + animator.add(c1); + Assert.assertEquals(true, animator.isStarted()); + Assert.assertEquals(false, animator.isPaused()); + Assert.assertEquals(true, animator.isAnimating()); + + final GearsES2 g2 = new GearsES2(0); + final GLWindow c2 = createGLWindow(caps, c1.getX()+width, + c1.getY()+0, g2); + animator.add(c2); + + final GearsES2 g3 = new GearsES2(0); + final GLWindow c3 = createGLWindow(caps, c1.getX()+0, + c1.getY()+height, g3); + animator.add(c3); + + c1.setVisible(true); + c2.setVisible(true); + c3.setVisible(true); + + Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c1, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c1, true)); + Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true)); + + Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c2, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c2, true)); + Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true)); + + Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c3, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c3, true)); + Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true)); + + try { + Thread.sleep(duration/3); + } catch(Exception e) { + e.printStackTrace(); + } + + pauseAnimator(animator, true); + + try { + Thread.sleep(duration/3); + } catch(Exception e) { + e.printStackTrace(); + } + + pauseAnimator(animator, false); + + try { + Thread.sleep(duration/3); + } catch(Exception e) { + e.printStackTrace(); + } + + // Stopped animator allows native windowing system 'repaint' event + // to trigger GLAD 'display' + stopAnimator(animator); + + c1.destroy(); + c2.destroy(); + c3.destroy(); + + Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, false)); + } + + @Test + public void test02AsyncEachAnimator() throws InterruptedException, InvocationTargetException { + final GLCapabilities caps = new GLCapabilities(null); + final Animator a1 = new Animator(); + final GearsES2 g1 = new GearsES2(0); + final GLWindow c1 = createGLWindow(caps, 0, 0, g1); + a1.add(c1); + a1.start(); + Assert.assertEquals(true, a1.isStarted()); + Assert.assertEquals(false, a1.isPaused()); + Assert.assertEquals(true, a1.isAnimating()); + c1.setVisible(true); + + final Animator a2 = new Animator(); + final GearsES2 g2 = new GearsES2(0); + final GLWindow c2 = createGLWindow(caps, c1.getX()+width, c1.getY()+0, g2); + a2.add(c2); + a2.start(); + Assert.assertEquals(true, a2.isStarted()); + Assert.assertEquals(false, a2.isPaused()); + Assert.assertEquals(true, a2.isAnimating()); + c2.setVisible(true); + + final Animator a3 = new Animator(); + final GearsES2 g3 = new GearsES2(0); + final GLWindow c3 = createGLWindow(caps, c1.getX()+0, c1.getY()+height, g3); + a3.add(c3); + a3.start(); + Assert.assertEquals(true, a3.isStarted()); + Assert.assertEquals(false, a3.isPaused()); + Assert.assertEquals(true, a3.isAnimating()); + c3.setVisible(true); + + Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c1, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c1, true)); + Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true)); + + Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c2, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c2, true)); + Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true)); + + Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(c3, true)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(c3, true)); + Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true)); + + try { + Thread.sleep(duration/3); + } catch(Exception e) { + e.printStackTrace(); + } + + pauseAnimator(a1, true); + pauseAnimator(a2, true); + pauseAnimator(a3, true); + + try { + Thread.sleep(duration/3); + } catch(Exception e) { + e.printStackTrace(); + } + + pauseAnimator(a1, false); + pauseAnimator(a2, false); + pauseAnimator(a3, false); + + try { + Thread.sleep(duration/3); + } catch(Exception e) { + e.printStackTrace(); + } + + // Stopped animator allows native windowing system 'repaint' event + // to trigger GLAD 'display' + stopAnimator(a1); + stopAnimator(a2); + stopAnimator(a3); + + c1.destroy(); + c2.destroy(); + c3.destroy(); + + Assert.assertTrue(AWTRobotUtil.waitForRealized(c1, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c2, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(c3, false)); + } + + static long duration = 3*500; // ms + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + try { + duration = Integer.parseInt(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } + } + /** + BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); + System.err.println("Press enter to continue"); + System.err.println(stdin.readLine()); */ + org.junit.runner.JUnitCore.main(TestAnimatorGLWindow01NEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase00.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase00.java new file mode 100644 index 000000000..4980e8562 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase00.java @@ -0,0 +1,423 @@ +/** + * Copyright 2013 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.jogl.acore.ect; + +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Window; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; + +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.AnimatorBase; + +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; + +import javax.media.nativewindow.Capabilities; +import javax.media.nativewindow.util.InsetsImmutable; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.AfterClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +/** + * ExclusiveContextThread base implementation to test correctness of the ExclusiveContext feature _and_ AnimatorBase. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public abstract class ExclusiveContextBase00 extends UITestCase { + static boolean testExclusiveWithAWT = false; + static final int durationParts = 9; + static long duration = 320 * durationParts; // ms ~ 20 frames + + static boolean showFPS = false; + static int showFPSRate = 100; + + static final int demoSize = 128; + + static InsetsImmutable insets = null; + static int scrnHeight, scrnWidth; + static int num_x, num_y; + + static int swapInterval = 0; + + @BeforeClass + public static void initClass00() { + Window dummyWindow = NewtFactory.createWindow(new Capabilities()); + dummyWindow.setSize(demoSize, demoSize); + dummyWindow.setVisible(true); + Assert.assertEquals(true, dummyWindow.isVisible()); + Assert.assertEquals(true, dummyWindow.isNativeValid()); + insets = dummyWindow.getInsets(); + scrnHeight = dummyWindow.getScreen().getHeight(); + scrnWidth = dummyWindow.getScreen().getWidth(); + num_x = scrnWidth / ( demoSize + insets.getTotalWidth() ) - 2; + num_y = scrnHeight / ( demoSize + insets.getTotalHeight() ) - 2; + dummyWindow.destroy(); + } + + @AfterClass + public static void releaseClass00() { + } + + protected abstract boolean isAWTTestCase(); + protected abstract Thread getAWTRenderThread(); + protected abstract AnimatorBase createAnimator(); + protected abstract GLAutoDrawable createGLAutoDrawable(String title, int x, int y, int width, int height, GLCapabilitiesImmutable caps); + protected abstract void setGLAutoDrawableVisible(GLAutoDrawable[] glads); + protected abstract void destroyGLAutoDrawableVisible(GLAutoDrawable glad); + + protected void runTestGL(GLCapabilitiesImmutable caps, int drawableCount, boolean exclusive, boolean preAdd, boolean shortenTest) throws InterruptedException { + final boolean useAWTRenderThread = isAWTTestCase(); + if( useAWTRenderThread && exclusive ) { + if( testExclusiveWithAWT ) { + System.err.println("Warning: Testing AWT + Exclusive -> Not advised!"); + } else { + System.err.println("Info: Skip test: AWT + Exclusive!"); + return; + } + } + if( useAWTRenderThread && exclusive && !testExclusiveWithAWT) { + System.err.println("Skip test: AWT + Exclusive -> Not advised!"); + return; + } + final Thread awtRenderThread = getAWTRenderThread(); + final AnimatorBase animator = createAnimator(); + if( !useAWTRenderThread ) { + animator.setModeBits(false, Animator.MODE_EXPECT_AWT_RENDERING_THREAD); + } + final GLAutoDrawable[] drawables = new GLAutoDrawable[drawableCount]; + for(int i=0; i<drawableCount; i++) { + final int x = ( i % num_x ) * ( demoSize + insets.getTotalHeight() ) + insets.getLeftWidth(); + final int y = ( (i / num_x) % num_y ) * ( demoSize + insets.getTotalHeight() ) + insets.getTopHeight(); + + drawables[i] = createGLAutoDrawable("Win #"+i, x, y, demoSize, demoSize, caps); + Assert.assertNotNull(drawables[i]); + final GearsES2 demo = new GearsES2(swapInterval); + demo.setVerbose(false); + drawables[i].addGLEventListener(demo); + } + + if( preAdd ) { + for(int i=0; i<drawableCount; i++) { + animator.add(drawables[i]); + } + if( exclusive ) { + if( useAWTRenderThread ) { + Assert.assertEquals(null, animator.setExclusiveContext(awtRenderThread)); + } else { + Assert.assertEquals(false, animator.setExclusiveContext(true)); + } + } + } + Assert.assertFalse(animator.isAnimating()); + Assert.assertFalse(animator.isStarted()); + + // Animator Start + Assert.assertTrue(animator.start()); + + Assert.assertTrue(animator.isStarted()); + if( preAdd ) { + Assert.assertTrue(animator.isAnimating()); + } else { + Assert.assertFalse(animator.isAnimating()); + if( exclusive ) { + if( useAWTRenderThread ) { + Assert.assertEquals(null, animator.setExclusiveContext(awtRenderThread)); + } else { + Assert.assertEquals(false, animator.setExclusiveContext(true)); + } + } + for(int i=0; i<drawableCount; i++) { + animator.add(drawables[i]); + } + Assert.assertTrue(animator.isAnimating()); + } + Assert.assertEquals(exclusive, animator.isExclusiveContextEnabled()); + + // After start, ExclusiveContextThread is set + { + final Thread ect = animator.getExclusiveContextThread(); + if(exclusive) { + if( useAWTRenderThread ) { + Assert.assertEquals(awtRenderThread, ect); + } else { + Assert.assertEquals(animator.getThread(), ect); + } + } else { + Assert.assertEquals(null, ect); + } + for(int i=0; i<drawableCount; i++) { + Assert.assertEquals(ect, drawables[i].getExclusiveContextThread()); + } + setGLAutoDrawableVisible(drawables); + } + animator.setUpdateFPSFrames(showFPSRate, showFPS ? System.err : null); + + // Normal run .. + Thread.sleep(duration/durationParts); // 1 + + if( !shortenTest ) { + // Disable/Enable exclusive mode manually for all GLAutoDrawable + if(exclusive) { + final Thread ect = animator.getExclusiveContextThread(); + if( useAWTRenderThread ) { + Assert.assertEquals(awtRenderThread, ect); + } else { + Assert.assertEquals(animator.getThread(), ect); + } + for(int i=0; i<drawableCount; i++) { + final Thread t = drawables[i].setExclusiveContextThread(null); + Assert.assertEquals(ect, t); + } + + Thread.sleep(duration/durationParts); // 2 + + for(int i=0; i<drawableCount; i++) { + // poll until clearing drawable ECT is established + { + boolean ok = null == drawables[i].getExclusiveContextThread(); + int c = 0; + while(!ok && c<5*50) { // 5*50*20 = 5s TO + Thread.sleep(20); + ok = null == drawables[i].getExclusiveContextThread(); + c++; + } + if(c>0) { + System.err.println("Clearing drawable ECT was done 'later' @ "+(c*20)+"ms, ok "+ok); + } + Assert.assertEquals(true, ok); + } + final Thread t = drawables[i].setExclusiveContextThread(ect); + Assert.assertEquals(null, t); + } + + Thread.sleep(duration/durationParts); // 3 + } + + // Disable/Enable exclusive mode via Animator for all GLAutoDrawable + if(exclusive) { + final Thread ect = animator.getExclusiveContextThread(); + if( useAWTRenderThread ) { + Assert.assertEquals(awtRenderThread, ect); + } else { + Assert.assertEquals(animator.getThread(), ect); + } + + Assert.assertEquals(true, animator.setExclusiveContext(false)); + Assert.assertFalse(animator.isExclusiveContextEnabled()); + for(int i=0; i<drawableCount; i++) { + Assert.assertEquals(null, drawables[i].getExclusiveContextThread()); + } + + Thread.sleep(duration/durationParts); // 4 + + Assert.assertEquals(null, animator.setExclusiveContext(ect)); + Assert.assertTrue(animator.isExclusiveContextEnabled()); + Assert.assertEquals(ect, animator.getExclusiveContextThread()); + for(int i=0; i<drawableCount; i++) { + Assert.assertEquals(ect, drawables[i].getExclusiveContextThread()); + } + + Thread.sleep(duration/durationParts); // 5 + } + + Assert.assertEquals(exclusive, animator.isExclusiveContextEnabled()); + Assert.assertTrue(animator.isStarted()); + Assert.assertTrue(animator.isAnimating()); + Assert.assertFalse(animator.isPaused()); + + // Animator Pause + Assert.assertTrue(animator.pause()); + Assert.assertTrue(animator.isStarted()); + Assert.assertFalse(animator.isAnimating()); + Assert.assertTrue(animator.isPaused()); + Assert.assertEquals(exclusive, animator.isExclusiveContextEnabled()); + if(exclusive) { + final Thread ect = animator.getExclusiveContextThread(); + if( useAWTRenderThread ) { + Assert.assertEquals(awtRenderThread, ect); + } else { + Assert.assertEquals(animator.getThread(), ect); + } + } else { + Assert.assertEquals(null, animator.getExclusiveContextThread()); + } + for(int i=0; i<drawableCount; i++) { + Assert.assertEquals(null, drawables[i].getExclusiveContextThread()); + } + Thread.sleep(duration/durationParts); // 6 + + // Animator Resume + Assert.assertTrue(animator.resume()); + Assert.assertTrue(animator.isStarted()); + Assert.assertTrue(animator.isAnimating()); + Assert.assertFalse(animator.isPaused()); + Assert.assertEquals(exclusive, animator.isExclusiveContextEnabled()); + if(exclusive) { + final Thread ect = animator.getExclusiveContextThread(); + if( useAWTRenderThread ) { + Assert.assertEquals(awtRenderThread, ect); + } else { + Assert.assertEquals(animator.getThread(), ect); + } + for(int i=0; i<drawableCount; i++) { + Assert.assertEquals(ect, drawables[i].getExclusiveContextThread()); + } + } else { + Assert.assertEquals(null, animator.getExclusiveContextThread()); + for(int i=0; i<drawableCount; i++) { + Assert.assertEquals(null, drawables[i].getExclusiveContextThread()); + } + } + Thread.sleep(duration/durationParts); // 7 + + // Animator Stop #1 + Assert.assertTrue(animator.stop()); + Assert.assertFalse(animator.isAnimating()); + Assert.assertFalse(animator.isStarted()); + Assert.assertFalse(animator.isPaused()); + Assert.assertEquals(exclusive, animator.isExclusiveContextEnabled()); + Assert.assertEquals(null, animator.getExclusiveContextThread()); + for(int i=0; i<drawableCount; i++) { + Assert.assertEquals(null, drawables[i].getExclusiveContextThread()); + } + Thread.sleep(duration/durationParts); // 8 + + // Animator Re-Start + Assert.assertTrue(animator.start()); + Assert.assertTrue(animator.isStarted()); + Assert.assertTrue(animator.isAnimating()); + Assert.assertEquals(exclusive, animator.isExclusiveContextEnabled()); + // After start, ExclusiveContextThread is set + { + final Thread ect = animator.getExclusiveContextThread(); + if(exclusive) { + if( useAWTRenderThread ) { + Assert.assertEquals(awtRenderThread, ect); + } else { + Assert.assertEquals(animator.getThread(), ect); + } + } else { + Assert.assertEquals(null, ect); + } + for(int i=0; i<drawableCount; i++) { + Assert.assertEquals(ect, drawables[i].getExclusiveContextThread()); + } + } + Thread.sleep(duration/durationParts); // 9 + + // Remove all drawables .. while running! + for(int i=0; i<drawableCount; i++) { + final GLAutoDrawable drawable = drawables[i]; + animator.remove(drawable); + Assert.assertEquals(null, drawable.getExclusiveContextThread()); + } + Assert.assertTrue(animator.isStarted()); + Assert.assertFalse(animator.isAnimating()); // no drawables in list! + } // !shortenTest + + // Animator Stop #2 + Assert.assertTrue(animator.stop()); + Assert.assertFalse(animator.isAnimating()); + Assert.assertFalse(animator.isStarted()); + Assert.assertFalse(animator.isPaused()); + Assert.assertEquals(exclusive, animator.isExclusiveContextEnabled()); + Assert.assertEquals(null, animator.getExclusiveContextThread()); + + // Destroy GLWindows + for(int i=0; i<drawableCount; i++) { + destroyGLAutoDrawableVisible(drawables[i]); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(drawables[i], false)); + } + } + + @Test + public void test01NormalPre_1Win() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities( glp ); + runTestGL(caps, 1 /* numWin */, false /* exclusive */, true /* preAdd */, false /* short */); + } + + @Test + public void test02NormalPost_1Win() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities( glp ); + runTestGL(caps, 1 /* numWin */, false /* exclusive */, false /* preAdd */, true /* short */); + } + + @Test + public void test03ExclPre_1Win() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities( glp ); + runTestGL(caps, 1 /* numWin */, true /* exclusive */, true /* preAdd */, false /* short */); + } + + @Test + public void test04ExclPost_1Win() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities( glp ); + runTestGL(caps, 1 /* numWin */, true /* exclusive */, false /* preAdd */, true /* short */); + } + + @Test + public void test05NormalPre_4Win() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities( glp ); + runTestGL(caps, 4 /* numWin */, false /* exclusive */, true /* preAdd */, false /* short */); + } + + @Test + public void test06NormalPost_4Win() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities( glp ); + runTestGL(caps, 4 /* numWin */, false /* exclusive */, false /* preAdd */, true /* short */); + } + + @Test + public void test07ExclPre_4Win() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities( glp ); + runTestGL(caps, 4 /* numWin */, true /* exclusive */, true /* preAdd */, false /* short */); + } + + @Test + public void test08ExclPost_4Win() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities( glp ); + runTestGL(caps, 4 /* numWin */, true /* exclusive */, false /* preAdd */, true /* short */); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase00AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase00AWT.java new file mode 100644 index 000000000..5608fe282 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase00AWT.java @@ -0,0 +1,164 @@ +/** + * Copyright 2013 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.jogl.acore.ect; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.awt.GLCanvas; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.AfterClass; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.common.os.Platform; +import com.jogamp.common.util.VersionNumber; + +/** + * ExclusiveContextThread base implementation to test correctness of the ExclusiveContext feature _and_ AnimatorBase with AWT. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public abstract class ExclusiveContextBase00AWT extends ExclusiveContextBase00 { + + static Thread awtEDT; + static boolean osxCALayerAWTModBug; + + @BeforeClass + public static void initClass00AWT() { + + final VersionNumber version170 = new VersionNumber(1, 7, 0); + osxCALayerAWTModBug = Platform.OSType.MACOS == Platform.getOSType() && + 0 > Platform.getJavaVersionNumber().compareTo(version170); + System.err.println("OSX CALayer AWT-Mod Bug "+osxCALayerAWTModBug); + System.err.println("OSType "+Platform.getOSType()); + System.err.println("Java Version "+Platform.getJavaVersionNumber()); + + try { + EventQueue.invokeAndWait(new Runnable() { + public void run() { + awtEDT = Thread.currentThread(); + } } ); + } catch (Exception e) { + e.printStackTrace(); + Assert.assertNull(e); + } + + } + + @AfterClass + public static void releaseClass00AWT() { + } + + @Override + protected boolean isAWTTestCase() { return true; } + + @Override + protected Thread getAWTRenderThread() { + return awtEDT; + } + + @Override + protected GLAutoDrawable createGLAutoDrawable(final String title, final int x, final int y, final int width, final int height, GLCapabilitiesImmutable caps) { + final GLCanvas glCanvas = new GLCanvas(); + + // FIXME: Below AWT layouts freezes OSX/Java7 @ setVisible: Window.setVisible .. [email protected] + // final Dimension sz = new Dimension(width, height); + // glCanvas.setMinimumSize(sz); + // glCanvas.setPreferredSize(sz); + // glCanvas.setSize(sz); + try { + EventQueue.invokeAndWait(new Runnable() { + public void run() { + final Frame frame = new Frame(); + frame.setLayout(new BorderLayout()); + frame.setMinimumSize(new Dimension(width, height)); + frame.setBounds(x, y, width, height); + frame.add(glCanvas, BorderLayout.CENTER); + // frame.pack(); + frame.validate(); + if( !osxCALayerAWTModBug ) { + frame.setTitle(title); + } + } }); + } catch (Exception e) { + e.printStackTrace(); + Assert.assertNull(e); + } + + return glCanvas; + } + + protected Frame getFrame(GLAutoDrawable glad) { + Container p = ((Component)glad).getParent(); + while( null != p && !( p instanceof Frame ) ) { + p = p.getParent(); + } + return (Frame)p; + } + + @Override + protected void setGLAutoDrawableVisible(final GLAutoDrawable[] glads) { + try { + EventQueue.invokeAndWait(new Runnable() { + public void run() { + final int count = glads.length; + for(int i=0; i<count; i++) { + final GLAutoDrawable glad = glads[i]; + final Frame frame = getFrame(glad); + frame.setVisible(true); + } + } } ); + } catch (Exception e) { + e.printStackTrace(); + Assert.assertNull(e); + } + } + + @Override + protected void destroyGLAutoDrawableVisible(GLAutoDrawable glad) { + final Frame frame = getFrame(glad); + try { + EventQueue.invokeAndWait(new Runnable() { + public void run() { + frame.dispose(); + } } ); + } catch (Exception e) { + e.printStackTrace(); + Assert.assertNull(e); + } + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase00NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase00NEWT.java new file mode 100644 index 000000000..3f2de0156 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase00NEWT.java @@ -0,0 +1,97 @@ +/** + * Copyright 2013 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.jogl.acore.ect; + +import com.jogamp.newt.Display; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Screen; +import com.jogamp.newt.opengl.GLWindow; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilitiesImmutable; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.AfterClass; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +/** + * ExclusiveContextThread base implementation to test correctness of the ExclusiveContext feature _and_ AnimatorBase with NEWT. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public abstract class ExclusiveContextBase00NEWT extends ExclusiveContextBase00 { + + static Display dpy; + static Screen screen; + + @BeforeClass + public static void initClass00NEWT() { + dpy = NewtFactory.createDisplay(null); + screen = NewtFactory.createScreen(dpy, 0); + } + + @AfterClass + public static void releaseClass00NEWT() { + screen = null; + dpy = null; + } + + @Override + protected boolean isAWTTestCase() { return false; } + + @Override + protected Thread getAWTRenderThread() { + return null; + } + + @Override + protected GLAutoDrawable createGLAutoDrawable(String title, int x, int y, int width, int height, GLCapabilitiesImmutable caps) { + GLWindow glWindow = GLWindow.create(screen, caps); + Assert.assertNotNull(glWindow); + glWindow.setTitle(title); + glWindow.setSize(width, height); + glWindow.setPosition(x, y); + return glWindow; + } + + @Override + protected void setGLAutoDrawableVisible(GLAutoDrawable[] glads) { + final int count = glads.length; + for(int i=0; i<count; i++) { + final GLAutoDrawable glad = glads[i]; + ((GLWindow)glad).setVisible(true); + } + } + + @Override + protected void destroyGLAutoDrawableVisible(GLAutoDrawable glad) { + ((GLWindow)glad).destroy(); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase10.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase10.java new file mode 100644 index 000000000..516622796 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase10.java @@ -0,0 +1,216 @@ +/** + * Copyright 2013 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.jogl.acore.ect; + +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Window; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; + +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.AnimatorBase; + +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; + +import javax.media.nativewindow.Capabilities; +import javax.media.nativewindow.util.InsetsImmutable; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.AfterClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +/** + * ExclusiveContextThread base implementation to test performance impact of the ExclusiveContext feature with AnimatorBase. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public abstract class ExclusiveContextBase10 extends UITestCase { + static boolean testExclusiveWithAWT = false; + static long duration = 1400; + + static boolean showFPS = true; + static int showFPSRate = 60; + + static final int demoSize = 128; + + static InsetsImmutable insets = null; + static int scrnHeight, scrnWidth; + static int num_x, num_y; + + static int swapInterval = 0; + + @BeforeClass + public static void initClass00() { + Window dummyWindow = NewtFactory.createWindow(new Capabilities()); + dummyWindow.setSize(demoSize, demoSize); + dummyWindow.setVisible(true); + Assert.assertEquals(true, dummyWindow.isVisible()); + Assert.assertEquals(true, dummyWindow.isNativeValid()); + insets = dummyWindow.getInsets(); + scrnHeight = dummyWindow.getScreen().getHeight(); + scrnWidth = dummyWindow.getScreen().getWidth(); + num_x = scrnWidth / ( demoSize + insets.getTotalWidth() ) - 2; + num_y = scrnHeight / ( demoSize + insets.getTotalHeight() ) - 2; + dummyWindow.destroy(); + } + + @AfterClass + public static void releaseClass00() { + } + + protected abstract boolean isAWTTestCase(); + protected abstract Thread getAWTRenderThread(); + protected abstract AnimatorBase createAnimator(); + protected abstract GLAutoDrawable createGLAutoDrawable(String title, int x, int y, int width, int height, GLCapabilitiesImmutable caps); + protected abstract void setGLAutoDrawableVisible(GLAutoDrawable[] glads); + protected abstract void destroyGLAutoDrawableVisible(GLAutoDrawable glad); + + protected void runTestGL(GLCapabilitiesImmutable caps, int drawableCount, boolean exclusive) throws InterruptedException { + final boolean useAWTRenderThread = isAWTTestCase(); + if( useAWTRenderThread && exclusive ) { + if( testExclusiveWithAWT ) { + System.err.println("Warning: Testing AWT + Exclusive -> Not advised!"); + } else { + System.err.println("Info: Skip test: AWT + Exclusive!"); + return; + } + } + if( useAWTRenderThread && exclusive && !testExclusiveWithAWT) { + System.err.println("Skip test: AWT + Exclusive -> Not advised!"); + return; + } + final Thread awtRenderThread = getAWTRenderThread(); + final AnimatorBase animator = createAnimator(); + if( !useAWTRenderThread ) { + animator.setModeBits(false, Animator.MODE_EXPECT_AWT_RENDERING_THREAD); + } + final GLAutoDrawable[] drawables = new GLAutoDrawable[drawableCount]; + for(int i=0; i<drawableCount; i++) { + final int x = ( i % num_x ) * ( demoSize + insets.getTotalHeight() ) + insets.getLeftWidth(); + final int y = ( (i / num_x) % num_y ) * ( demoSize + insets.getTotalHeight() ) + insets.getTopHeight(); + + drawables[i] = createGLAutoDrawable("Win #"+i, x, y, demoSize, demoSize, caps); + Assert.assertNotNull(drawables[i]); + final GearsES2 demo = new GearsES2(swapInterval); + demo.setVerbose(false); + drawables[i].addGLEventListener(demo); + } + + for(int i=0; i<drawableCount; i++) { + animator.add(drawables[i]); + } + if( exclusive ) { + if( useAWTRenderThread ) { + Assert.assertEquals(null, animator.setExclusiveContext(awtRenderThread)); + } else { + Assert.assertEquals(false, animator.setExclusiveContext(true)); + } + } + Assert.assertFalse(animator.isAnimating()); + Assert.assertFalse(animator.isStarted()); + + // Animator Start + Assert.assertTrue(animator.start()); + + Assert.assertTrue(animator.isStarted()); + Assert.assertTrue(animator.isAnimating()); + Assert.assertEquals(exclusive, animator.isExclusiveContextEnabled()); + + // After start, ExclusiveContextThread is set + { + final Thread ect = animator.getExclusiveContextThread(); + if(exclusive) { + if( useAWTRenderThread ) { + Assert.assertEquals(awtRenderThread, ect); + } else { + Assert.assertEquals(animator.getThread(), ect); + } + } else { + Assert.assertEquals(null, ect); + } + for(int i=0; i<drawableCount; i++) { + Assert.assertEquals(ect, drawables[i].getExclusiveContextThread()); + } + setGLAutoDrawableVisible(drawables); + } + animator.setUpdateFPSFrames(showFPSRate, showFPS ? System.err : null); + + // Normal run .. + Thread.sleep(duration); + + // Animator Stop #2 + Assert.assertTrue(animator.stop()); + Assert.assertFalse(animator.isAnimating()); + Assert.assertFalse(animator.isStarted()); + Assert.assertFalse(animator.isPaused()); + Assert.assertEquals(exclusive, animator.isExclusiveContextEnabled()); + Assert.assertEquals(null, animator.getExclusiveContextThread()); + + // Destroy GLWindows + for(int i=0; i<drawableCount; i++) { + destroyGLAutoDrawableVisible(drawables[i]); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(drawables[i], false)); + } + } + + @Test + public void test01Normal_1Win() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities( glp ); + runTestGL(caps, 1 /* numWin */, false /* exclusive */); + } + + @Test + public void test03Excl_1Win() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities( glp ); + runTestGL(caps, 1 /* numWin */, true /* exclusive */); + } + + @Test + public void test05Normal_4Win() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities( glp ); + runTestGL(caps, 4 /* numWin */, false /* exclusive */); + } + + @Test + public void test07Excl_4Win() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities( glp ); + runTestGL(caps, 4 /* numWin */, true /* exclusive */); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase10AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase10AWT.java new file mode 100644 index 000000000..237479e5a --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase10AWT.java @@ -0,0 +1,164 @@ +/** + * Copyright 2013 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.jogl.acore.ect; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.awt.GLCanvas; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.AfterClass; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.common.os.Platform; +import com.jogamp.common.util.VersionNumber; + +/** + * ExclusiveContextThread base implementation to test performance impact of the ExclusiveContext feature with AnimatorBase and AWT. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public abstract class ExclusiveContextBase10AWT extends ExclusiveContextBase10 { + + static Thread awtEDT; + static boolean osxCALayerAWTModBug; + + @BeforeClass + public static void initClass00AWT() { + + final VersionNumber version170 = new VersionNumber(1, 7, 0); + osxCALayerAWTModBug = Platform.OSType.MACOS == Platform.getOSType() && + 0 > Platform.getJavaVersionNumber().compareTo(version170); + System.err.println("OSX CALayer AWT-Mod Bug "+osxCALayerAWTModBug); + System.err.println("OSType "+Platform.getOSType()); + System.err.println("Java Version "+Platform.getJavaVersionNumber()); + + try { + EventQueue.invokeAndWait(new Runnable() { + public void run() { + awtEDT = Thread.currentThread(); + } } ); + } catch (Exception e) { + e.printStackTrace(); + Assert.assertNull(e); + } + + } + + @AfterClass + public static void releaseClass00AWT() { + } + + @Override + protected boolean isAWTTestCase() { return true; } + + @Override + protected Thread getAWTRenderThread() { + return awtEDT; + } + + @Override + protected GLAutoDrawable createGLAutoDrawable(final String title, final int x, final int y, final int width, final int height, GLCapabilitiesImmutable caps) { + final GLCanvas glCanvas = new GLCanvas(); + + // FIXME: Below AWT layouts freezes OSX/Java7 @ setVisible: Window.setVisible .. [email protected] + // final Dimension sz = new Dimension(width, height); + // glCanvas.setMinimumSize(sz); + // glCanvas.setPreferredSize(sz); + // glCanvas.setSize(sz); + try { + EventQueue.invokeAndWait(new Runnable() { + public void run() { + final Frame frame = new Frame(); + frame.setLayout(new BorderLayout()); + frame.setMinimumSize(new Dimension(width, height)); + frame.setBounds(x, y, width, height); + frame.add(glCanvas, BorderLayout.CENTER); + // frame.pack(); + frame.validate(); + if( !osxCALayerAWTModBug ) { + frame.setTitle(title); + } + } }); + } catch (Exception e) { + e.printStackTrace(); + Assert.assertNull(e); + } + + return glCanvas; + } + + protected Frame getFrame(GLAutoDrawable glad) { + Container p = ((Component)glad).getParent(); + while( null != p && !( p instanceof Frame ) ) { + p = p.getParent(); + } + return (Frame)p; + } + + @Override + protected void setGLAutoDrawableVisible(final GLAutoDrawable[] glads) { + try { + EventQueue.invokeAndWait(new Runnable() { + public void run() { + final int count = glads.length; + for(int i=0; i<count; i++) { + final GLAutoDrawable glad = glads[i]; + final Frame frame = getFrame(glad); + frame.setVisible(true); + } + } } ); + } catch (Exception e) { + e.printStackTrace(); + Assert.assertNull(e); + } + } + + @Override + protected void destroyGLAutoDrawableVisible(GLAutoDrawable glad) { + final Frame frame = getFrame(glad); + try { + EventQueue.invokeAndWait(new Runnable() { + public void run() { + frame.dispose(); + } } ); + } catch (Exception e) { + e.printStackTrace(); + Assert.assertNull(e); + } + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase10NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase10NEWT.java new file mode 100644 index 000000000..fc8cad04c --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase10NEWT.java @@ -0,0 +1,97 @@ +/** + * Copyright 2013 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.jogl.acore.ect; + +import com.jogamp.newt.Display; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Screen; +import com.jogamp.newt.opengl.GLWindow; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilitiesImmutable; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.AfterClass; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +/** + * ExclusiveContextThread base implementation to test performance impact of the ExclusiveContext feature with AnimatorBase and NEWT. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public abstract class ExclusiveContextBase10NEWT extends ExclusiveContextBase10 { + + static Display dpy; + static Screen screen; + + @BeforeClass + public static void initClass00NEWT() { + dpy = NewtFactory.createDisplay(null); + screen = NewtFactory.createScreen(dpy, 0); + } + + @AfterClass + public static void releaseClass00NEWT() { + screen = null; + dpy = null; + } + + @Override + protected boolean isAWTTestCase() { return false; } + + @Override + protected Thread getAWTRenderThread() { + return null; + } + + @Override + protected GLAutoDrawable createGLAutoDrawable(String title, int x, int y, int width, int height, GLCapabilitiesImmutable caps) { + GLWindow glWindow = GLWindow.create(screen, caps); + Assert.assertNotNull(glWindow); + glWindow.setTitle(title); + glWindow.setSize(width, height); + glWindow.setPosition(x, y); + return glWindow; + } + + @Override + protected void setGLAutoDrawableVisible(GLAutoDrawable[] glads) { + final int count = glads.length; + for(int i=0; i<count; i++) { + final GLAutoDrawable glad = glads[i]; + ((GLWindow)glad).setVisible(true); + } + } + + @Override + protected void destroyGLAutoDrawableVisible(GLAutoDrawable glad) { + ((GLWindow)glad).destroy(); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext01VSyncAnimAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext01VSyncAnimAWT.java new file mode 100644 index 000000000..038e0781f --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext01VSyncAnimAWT.java @@ -0,0 +1,74 @@ +/** + * Copyright 2013 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.jogl.acore.ect; + +import java.io.IOException; + +import com.jogamp.opengl.test.junit.util.MiscUtils; + +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.AnimatorBase; + +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +/** + * ExclusiveContextThread VSync Animator to test correctness of the ExclusiveContext feature _and_ Animator with AWT. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestExclusiveContext01VSyncAnimAWT extends ExclusiveContextBase00AWT { + + @Override + protected AnimatorBase createAnimator() { + return new Animator(); + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-vsync")) { + i++; + swapInterval = MiscUtils.atoi(args[i], swapInterval); + } else if(args[i].equals("-showFPS")) { + i++; + showFPS = MiscUtils.atoi(args[i], showFPS ? 1 : 0) == 0 ? false : true ; + } else if(args[i].equals("-forceExclusiveTest")) { + testExclusiveWithAWT = true; + } + } + System.err.println("duration "+duration); + System.err.println("showFPS "+showFPS); + System.err.println("swapInterval "+swapInterval); + System.err.println("testExclusiveWithAWT "+testExclusiveWithAWT); + + org.junit.runner.JUnitCore.main(TestExclusiveContext01VSyncAnimAWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext01VSyncAnimNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext01VSyncAnimNEWT.java new file mode 100644 index 000000000..d52347920 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext01VSyncAnimNEWT.java @@ -0,0 +1,70 @@ +/** + * Copyright 2013 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.jogl.acore.ect; + +import java.io.IOException; + +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.AnimatorBase; + +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +/** + * ExclusiveContextThread VSync Animator to test correctness of the ExclusiveContext feature _and_ Animator with NEWT. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestExclusiveContext01VSyncAnimNEWT extends ExclusiveContextBase00NEWT { + + @Override + protected AnimatorBase createAnimator() { + return new Animator(); + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-vsync")) { + i++; + swapInterval = MiscUtils.atoi(args[i], swapInterval); + } else if(args[i].equals("-showFPS")) { + i++; + showFPS = MiscUtils.atoi(args[i], showFPS ? 1 : 0) == 0 ? false : true ; + } + } + System.err.println("duration "+duration); + System.err.println("showFPS "+showFPS); + System.err.println("swapInterval "+swapInterval); + + org.junit.runner.JUnitCore.main(TestExclusiveContext01VSyncAnimNEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext02FPSAnimAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext02FPSAnimAWT.java new file mode 100644 index 000000000..f6697c608 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext02FPSAnimAWT.java @@ -0,0 +1,73 @@ +/** + * Copyright 2013 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.jogl.acore.ect; + +import java.io.IOException; + +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.util.AnimatorBase; +import com.jogamp.opengl.util.FPSAnimator; + +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +/** + * ExclusiveContextThread FPS Animator to test correctness of the ExclusiveContext feature _and_ FPSAnimator with AWT. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestExclusiveContext02FPSAnimAWT extends ExclusiveContextBase00AWT { + + @Override + protected AnimatorBase createAnimator() { + return new FPSAnimator(0); + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-vsync")) { + i++; + swapInterval = MiscUtils.atoi(args[i], swapInterval); + } else if(args[i].equals("-showFPS")) { + i++; + showFPS = MiscUtils.atoi(args[i], showFPS ? 1 : 0) == 0 ? false : true ; + } else if(args[i].equals("-forceExclusiveTest")) { + testExclusiveWithAWT = true; + } + } + System.err.println("duration "+duration); + System.err.println("showFPS "+showFPS); + System.err.println("swapInterval "+swapInterval); + System.err.println("testExclusiveWithAWT "+testExclusiveWithAWT); + + org.junit.runner.JUnitCore.main(TestExclusiveContext02FPSAnimAWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext02FPSAnimNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext02FPSAnimNEWT.java new file mode 100644 index 000000000..33819c845 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext02FPSAnimNEWT.java @@ -0,0 +1,70 @@ +/** + * Copyright 2013 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.jogl.acore.ect; + +import java.io.IOException; + +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.util.AnimatorBase; +import com.jogamp.opengl.util.FPSAnimator; + +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +/** + * ExclusiveContextThread FPS Animator to test correctness of the ExclusiveContext feature _and_ FPSAnimator with NEWT. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestExclusiveContext02FPSAnimNEWT extends ExclusiveContextBase00NEWT { + + @Override + protected AnimatorBase createAnimator() { + return new FPSAnimator(0); + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-vsync")) { + i++; + swapInterval = MiscUtils.atoi(args[i], swapInterval); + } else if(args[i].equals("-showFPS")) { + i++; + showFPS = MiscUtils.atoi(args[i], showFPS ? 1 : 0) == 0 ? false : true ; + } + } + System.err.println("duration "+duration); + System.err.println("showFPS "+showFPS); + System.err.println("swapInterval "+swapInterval); + + org.junit.runner.JUnitCore.main(TestExclusiveContext02FPSAnimNEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext11VSyncAnimNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext11VSyncAnimNEWT.java new file mode 100644 index 000000000..5067d6c57 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext11VSyncAnimNEWT.java @@ -0,0 +1,70 @@ +/** + * Copyright 2013 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.jogl.acore.ect; + +import java.io.IOException; + +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.AnimatorBase; + +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +/** + * ExclusiveContextThread base implementation to test performance impact of the ExclusiveContext feature with Animator and NEWT. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestExclusiveContext11VSyncAnimNEWT extends ExclusiveContextBase10NEWT { + + @Override + protected AnimatorBase createAnimator() { + return new Animator(); + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-vsync")) { + i++; + swapInterval = MiscUtils.atoi(args[i], swapInterval); + } else if(args[i].equals("-showFPS")) { + i++; + showFPS = MiscUtils.atoi(args[i], showFPS ? 1 : 0) == 0 ? false : true ; + } + } + System.err.println("duration "+duration); + System.err.println("showFPS "+showFPS); + System.err.println("swapInterval "+swapInterval); + + org.junit.runner.JUnitCore.main(TestExclusiveContext11VSyncAnimNEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext12FPSAnimNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext12FPSAnimNEWT.java new file mode 100644 index 000000000..993b67e80 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext12FPSAnimNEWT.java @@ -0,0 +1,70 @@ +/** + * Copyright 2013 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.jogl.acore.ect; + +import java.io.IOException; + +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.util.AnimatorBase; +import com.jogamp.opengl.util.FPSAnimator; + +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +/** + * ExclusiveContextThread base implementation to test performance impact of the ExclusiveContext feature with FPSAnimator and NEWT. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestExclusiveContext12FPSAnimNEWT extends ExclusiveContextBase10NEWT { + + @Override + protected AnimatorBase createAnimator() { + return new FPSAnimator(0); + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-vsync")) { + i++; + swapInterval = MiscUtils.atoi(args[i], swapInterval); + } else if(args[i].equals("-showFPS")) { + i++; + showFPS = MiscUtils.atoi(args[i], showFPS ? 1 : 0) == 0 ? false : true ; + } + } + System.err.println("duration "+duration); + System.err.println("showFPS "+showFPS); + System.err.println("swapInterval "+swapInterval); + + org.junit.runner.JUnitCore.main(TestExclusiveContext12FPSAnimNEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/GLContextDrawableSwitchBase.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/GLContextDrawableSwitchBase.java new file mode 100644 index 000000000..8c9d6c24a --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/GLContextDrawableSwitchBase.java @@ -0,0 +1,291 @@ +/** + * Copyright 2013 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.jogl.acore.glels; + +import java.awt.Dimension; +import java.awt.Frame; + +import javax.media.opengl.GLAnimatorControl; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLOffscreenAutoDrawable; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; + +import jogamp.nativewindow.jawt.JAWTUtil; + +import com.jogamp.newt.Screen; +import com.jogamp.newt.opengl.GLWindow; + +import com.jogamp.opengl.GLEventListenerState; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.GLEventListenerCounter; +import com.jogamp.opengl.test.junit.util.UITestCase; + +import org.junit.Assert; +import org.junit.Assume; +import org.junit.BeforeClass; + +/** + * Test re-association of GLContext/GLDrawables, + * here GLContext's survival of GLDrawable destruction + * and reuse w/ new or recreated GLDrawable. + * <p> + * Test utilizes {@link GLEventListenerState} for preserving the + * GLAutoDrawable state, i.e. GLContext, all GLEventListener + * and the GLAnimatorControl association. + * </p> + * <p> + * See Bug 665 - https://jogamp.org/bugzilla/show_bug.cgi?id=665. + * </p> + */ +public abstract class GLContextDrawableSwitchBase extends UITestCase { + static protected enum GLADType { GLCanvasOnscreen, GLCanvasOffscreen, GLWindow, GLOffscreen }; + + // default period for 1 GLAD cycle + static long duration = 1000; // ms + + static int width, height; + + static GLCapabilities getCaps(String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return new GLCapabilities(GLProfile.get(profile)); + } + + @BeforeClass + public static void initClass() { + width = 256; + height = 256; + } + + static void setGLCanvasSize(final GLCanvas glc, final Dimension new_sz) { + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + glc.setMinimumSize(new_sz); + glc.setPreferredSize(new_sz); + glc.setSize(new_sz); + } } ); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + } + + static void setFrameVisible(final Frame frame) throws InterruptedException { + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.pack(); + frame.setVisible(true); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + } + + static void destroyFrame(final Frame frame) throws InterruptedException { + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.dispose(); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + } + + private GLOffscreenAutoDrawable createGLOffscreenAutoDrawable(GLCapabilities caps, int width, int height) throws InterruptedException { + final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); + return factory.createOffscreenAutoDrawable(null, caps, null, width, height); + } + + protected static boolean validateOnOffscreenLayer(GLADType gladType1, GLADType gladType2) { + final boolean useOffscreenLayer = GLADType.GLCanvasOffscreen == gladType1 || GLADType.GLCanvasOffscreen == gladType2 ; + final boolean useOnscreenLayer = GLADType.GLCanvasOnscreen == gladType1 || GLADType.GLCanvasOnscreen == gladType2 ; + if( useOffscreenLayer ) { + if( !JAWTUtil.isOffscreenLayerSupported() ) { + System.err.println("Platform doesn't support offscreen rendering."); + return false; + } + } else if( useOnscreenLayer ) { + if( JAWTUtil.isOffscreenLayerRequired() ) { + System.err.println("Platform requires offscreen rendering."); + return false; + } + } + return true; + } + + protected void testGLADOneLifecycle(Screen screen, GLCapabilities caps, GLADType gladType, int width, + int height, GLEventListenerCounter glelTracker, + SnapshotGLEventListener snapshotGLEventListener, final GLEventListenerState glelsIn, final GLEventListenerState glelsOut[], GLAnimatorControl animator) + throws InterruptedException { + + System.err.println("GLAD Lifecycle.0 "+gladType+", restoring "+((null!=glelsIn)?true:false)+", preserving "+((null!=glelsOut)?true:false)); + final Frame frame; + final GLAutoDrawable glad; + if( GLADType.GLCanvasOnscreen == gladType ) { + if( jogamp.nativewindow.jawt.JAWTUtil.isOffscreenLayerRequired() ) { + throw new InternalError("Platform requires offscreen rendering, but onscreen requested: "+gladType); + } + frame = new Frame("AWT GLCanvas"); + + glad = new GLCanvas(caps); + setGLCanvasSize((GLCanvas)glad, new Dimension(width, height)); + frame.add((GLCanvas)glad); + } else if( GLADType.GLCanvasOffscreen == gladType ) { + if( !jogamp.nativewindow.jawt.JAWTUtil.isOffscreenLayerSupported() ) { + throw new InternalError("Platform doesn't support offscreen rendering: "+gladType); + } + frame = new Frame("AWT GLCanvas"); + + glad = new GLCanvas(caps); + ((GLCanvas)glad).setShallUseOffscreenLayer(true); + setGLCanvasSize((GLCanvas)glad, new Dimension(width, height)); + frame.add((GLCanvas)glad); + } else if( GLADType.GLWindow == gladType ) { + frame = null; + + if( null != screen ) { + glad = GLWindow.create(screen, caps); + } else { + glad = GLWindow.create(caps); + } + ((GLWindow)glad).setTitle("Newt GLWindow"); + ((GLWindow)glad).setSize(width, height); + } else if( GLADType.GLOffscreen == gladType ) { + frame = null; + + glad = this.createGLOffscreenAutoDrawable(caps, width, height); + } else { + throw new InternalError("Unsupported: "+gladType); + } + + if( null == glelsIn ) { + if( null != animator ) { + animator.add(glad); + } + glad.addGLEventListener(glelTracker); + glad.addGLEventListener(new GearsES2(1)); + glad.addGLEventListener(snapshotGLEventListener); + } + snapshotGLEventListener.setMakeSnapshot(); + + if( GLADType.GLCanvasOnscreen == gladType || GLADType.GLCanvasOffscreen == gladType ) { + setFrameVisible(frame); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); + } else if( GLADType.GLWindow == gladType ) { + ((GLWindow)glad).setVisible(true); + } + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glad, true)); + Assert.assertNotNull(glad.getContext()); + Assert.assertTrue(glad.isRealized()); + + if( null != glelsIn ) { + Assert.assertEquals(0, glad.getGLEventListenerCount()); + System.err.println(".. restoring.0"); + glelsIn.moveTo(glad); + System.err.println(".. restoring.X"); + + Assert.assertEquals(1, glelTracker.initCount); + Assert.assertTrue(1 <= glelTracker.reshapeCount); + Assert.assertTrue(1 <= glelTracker.displayCount); + Assert.assertEquals(0, glelTracker.disposeCount); + Assert.assertEquals(3, glad.getGLEventListenerCount()); + + Assert.assertEquals(glelsIn.context, glad.getContext()); + Assert.assertEquals(glelsIn.listenerCount(), glad.getGLEventListenerCount()); + Assert.assertEquals(glelsIn.context.getGLReadDrawable(), glad.getDelegatedDrawable()); + Assert.assertEquals(glelsIn.context.getGLDrawable(), glad.getDelegatedDrawable()); + Assert.assertEquals(false, glelsIn.isOwner()); + } + + for (int wait=0; wait<AWTRobotUtil.POLL_DIVIDER && + ( 1 > glelTracker.initCount || 1 > glelTracker.reshapeCount || 1 > glelTracker.displayCount ); + wait++) { + Thread.sleep(AWTRobotUtil.TIME_SLICE); + } + + final long t0 = System.currentTimeMillis(); + long t1 = t0; + + while( ( t1 - t0 ) < duration ) { + Thread.sleep(100); + t1 = System.currentTimeMillis(); + } + + Assert.assertEquals(1, glelTracker.initCount); + Assert.assertTrue(1 <= glelTracker.reshapeCount); + Assert.assertTrue(1 <= glelTracker.displayCount); + Assert.assertEquals(0, glelTracker.disposeCount); + + if( null != glelsOut ) { + final GLContext context1 = glad.getContext(); + System.err.println(".. preserving.0"); + glelsOut[0] = GLEventListenerState.moveFrom(glad); + System.err.println(".. preserving.X"); + + Assert.assertEquals(context1, glelsOut[0].context); + Assert.assertNull(context1.getGLReadDrawable()); + Assert.assertNull(context1.getGLDrawable()); + Assert.assertEquals(3, glelsOut[0].listenerCount()); + Assert.assertEquals(true, glelsOut[0].isOwner()); + Assert.assertEquals(null, glad.getContext()); + Assert.assertEquals(0, glad.getGLEventListenerCount()); + } + if( GLADType.GLCanvasOnscreen == gladType || GLADType.GLCanvasOffscreen == gladType ) { + destroyFrame(frame); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, false)); + } else if( GLADType.GLWindow == gladType ) { + glad.destroy(); + } else if( GLADType.GLOffscreen == gladType ) { + glad.destroy(); + } + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glad, false)); + + Assert.assertEquals(1, glelTracker.initCount); + Assert.assertTrue(1 <= glelTracker.reshapeCount); + Assert.assertTrue(1 <= glelTracker.displayCount); + if( null != glelsOut ) { + Assert.assertEquals(0, glelTracker.disposeCount); + } else { + Assert.assertEquals(1, glelTracker.disposeCount); + } + System.err.println("GLAD Lifecycle.X "+gladType); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestBug722GLContextDrawableSwitchNewt2AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestBug722GLContextDrawableSwitchNewt2AWT.java new file mode 100644 index 000000000..24eefe73c --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestBug722GLContextDrawableSwitchNewt2AWT.java @@ -0,0 +1,154 @@ +/** + * Copyright 2013 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.jogl.acore.glels; + +import java.io.IOException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; + + +import com.jogamp.newt.Display; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Screen; +import com.jogamp.opengl.GLEventListenerState; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.GLRendererQuirks; +import com.jogamp.opengl.test.junit.util.GLEventListenerCounter; +import com.jogamp.opengl.test.junit.util.MiscUtils; + +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +/** + * Tests Bug 722 + * <p> + * See Bug 722 - https://jogamp.org/bugzilla/show_bug.cgi?id=722. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestBug722GLContextDrawableSwitchNewt2AWT extends GLContextDrawableSwitchBase { + + static int loops = 10; + static long duration2 = 100; // ms + + /** + * Interesting artifact w/ ATI proprietary driver is that the + * bug causing the quirk {@link GLRendererQuirks#DontCloseX11Display} + * also causes an XCB crash when reusing the X11 display connection + * from AWT -> NEWT. Pre-allocating the X11 Display and keeping it referenced + * to avoid such re-usage worksaround this problem. + */ + public static boolean fixedNewtDisplay = true; + + @Test(timeout=180000) // TO 3 min + public void test11GLWindow2GLCanvasOnScrnGL2ES2() throws InterruptedException { + final GLCapabilities caps = getCaps(GLProfile.GL2ES2); + if(null == caps) { + System.err.println("GL2ES2 n/a, test n/a."); + return; + } + if( jogamp.nativewindow.jawt.JAWTUtil.isOffscreenLayerRequired() ) { + System.err.println("JAWT required offscreen, test n/a."); + return; + } + + + GLADType gladType1 = GLADType.GLWindow; + GLADType gladType2 = GLADType.GLCanvasOnscreen; + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + final Animator animator = new Animator(); + animator.start(); + + final Display dpy; + final Screen screen; + if( fixedNewtDisplay ) { + dpy = NewtFactory.createDisplay(null); + screen = NewtFactory.createScreen(dpy, 0); + screen.addReference(); + } else { + dpy = null; + screen = null; + } + + duration = duration2; + + for(int i=0; i<loops; i++) { + final GLEventListenerState glels[] = new GLEventListenerState[1]; + final GLEventListenerCounter glelTracker = new GLEventListenerCounter(); + + // - create glad1 w/o context + // - create context using glad1 and assign it to glad1 + { + System.err.println("Test "+i+"/"+loops+".1: GLAD-1 "+gladType1+", preserving."); + testGLADOneLifecycle(screen, caps, gladType1, width, height, + glelTracker, snapshotGLEventListener, + null, + glels, animator); + System.err.println("Test "+i+"/"+loops+".1: done"); + } + + // - create glad2 w/ survived context + { + System.err.println("Test "+i+"/"+loops+".2: GLAD-1 "+gladType2+", restoring."); + testGLADOneLifecycle(screen, caps, gladType2, width+100, height+100, + glelTracker, snapshotGLEventListener, + glels[0], + null, null); + System.err.println("Test "+i+"/"+loops+".2: done."); + } + } + animator.stop(); + + if( fixedNewtDisplay ) { + screen.removeReference(); + } + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration2 = MiscUtils.atol(args[i], duration2); + } else if(args[i].equals("-loops")) { + i++; + loops = MiscUtils.atoi(args[i], loops); + } else if(args[i].equals("-noFixedNewtDisplay")) { + fixedNewtDisplay = false; + } + } + /** + BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); + System.err.println("Press enter to continue"); + System.err.println(stdin.readLine()); */ + org.junit.runner.JUnitCore.main(TestBug722GLContextDrawableSwitchNewt2AWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch01NEWT.java new file mode 100644 index 000000000..633d9de3b --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch01NEWT.java @@ -0,0 +1,377 @@ +/** + * 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.jogl.acore.glels; + +import java.io.IOException; + +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Window; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.event.WindowListener; +import com.jogamp.newt.event.WindowUpdateEvent; +import com.jogamp.newt.opengl.GLWindow; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLProfile; + +import com.jogamp.opengl.GLAutoDrawableDelegate; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.GLDrawableUtil; + +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.test.junit.util.UITestCase; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +/** + * Test re-association (switching) of GLContext/GLDrawables, + * i.e. ctx1/draw1, ctx2/draw2 -> ctx1/draw2, ctx2/draw1. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLContextDrawableSwitch01NEWT extends UITestCase { + static int width, height; + + static GLCapabilities getCaps(String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return new GLCapabilities(GLProfile.get(profile)); + } + + @BeforeClass + public static void initClass() { + width = 256; + height = 256; + } + + private GLAutoDrawable createGLAutoDrawable(GLCapabilities caps, int x, int y, int width, int height, WindowListener wl) throws InterruptedException { + final Window window = NewtFactory.createWindow(caps); + Assert.assertNotNull(window); + window.setPosition(x, y); + window.setSize(width, height); + window.setVisible(true); + Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true)); + + final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); + final GLDrawable drawable = factory.createGLDrawable(window); + Assert.assertNotNull(drawable); + + drawable.setRealized(true); + Assert.assertTrue(drawable.isRealized()); + + final GLContext context = drawable.createContext(null); + Assert.assertNotNull(context); + + final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, context, window, false, null) { + @Override + protected void destroyImplInLock() { + super.destroyImplInLock(); + window.destroy(); // destroys the actual window + } + }; + + window.setWindowDestroyNotifyAction( new Runnable() { + public void run() { + glad.windowDestroyNotifyOp(); + } } ); + + // add basic window interaction + window.addWindowListener(new WindowAdapter() { + @Override + public void windowRepaint(WindowUpdateEvent e) { + glad.windowRepaintOp(); + } + @Override + public void windowResized(WindowEvent e) { + glad.windowResizedOp(window.getWidth(), window.getHeight()); + } + }); + window.addWindowListener(wl); + + return glad; + } + + @Test(timeout=30000) + public void testSwitch2WindowSingleContextGL2ES2() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2); + if(null == reqGLCaps) return; + testSwitch2WindowSingleContextImpl(reqGLCaps); + } + + @Test(timeout=30000) + public void testSwitch2WindowSingleContextGLES2() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + testSwitch2WindowSingleContextImpl(reqGLCaps); + } + + private void testSwitch2WindowSingleContextImpl(GLCapabilities caps) throws InterruptedException { + final QuitAdapter quitAdapter = new QuitAdapter(); + + GLAutoDrawable glad1 = createGLAutoDrawable(caps, 64, 64, width, height, quitAdapter); + GLAutoDrawable glad2 = createGLAutoDrawable(caps, 2*64+width, 64, width+100, height+100, quitAdapter); + + // create single context using glad1 and assign it to glad1, + // destroy the prev. context afterwards. + { + final GLContext newCtx = glad1.createContext(null); + Assert.assertNotNull(newCtx); + final GLContext oldCtx = glad1.setContext(newCtx, true); + Assert.assertNotNull(oldCtx); + Assert.assertFalse(oldCtx.isCreated()); + final int res = newCtx.makeCurrent(); + Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res); + newCtx.release(); + } + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + GearsES2 gears = new GearsES2(1); + glad1.addGLEventListener(gears); + glad1.addGLEventListener(snapshotGLEventListener); + snapshotGLEventListener.setMakeSnapshot(); + + Animator animator = new Animator(); + animator.add(glad1); + animator.add(glad2); + animator.start(); + + int s = 0; + long t0 = System.currentTimeMillis(); + long t1 = t0; + + while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) { + if( ( t1 - t0 ) / period > s) { + s++; + System.err.println(s+" - switch - START "+ ( t1 - t0 )); + + // switch context _and_ the demo synchronously + GLDrawableUtil.swapGLContextAndAllGLEventListener(glad1, glad2); + + System.err.println(s+" - switch - END "+ ( t1 - t0 )); + } + Thread.sleep(100); + t1 = System.currentTimeMillis(); + } + + animator.stop(); + glad1.destroy(); + glad2.destroy(); + } + + @Test(timeout=30000) + public void testSwitch2GLWindowOneDemoGL2ES2() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2); + if(null == reqGLCaps) return; + testSwitch2GLWindowOneDemoImpl(reqGLCaps); + } + + @Test(timeout=30000) + public void testSwitch2GLWindowOneDemoGLES2() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + testSwitch2GLWindowOneDemoImpl(reqGLCaps); + } + + private void testSwitch2GLWindowOneDemoImpl(GLCapabilities caps) throws InterruptedException { + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + final GearsES2 gears = new GearsES2(1); + final QuitAdapter quitAdapter = new QuitAdapter(); + + GLWindow glWindow1 = GLWindow.create(caps); + glWindow1.setTitle("win1"); + glWindow1.setSize(width, height); + glWindow1.setPosition(64, 64); + glWindow1.addGLEventListener(0, gears); + glWindow1.addGLEventListener(snapshotGLEventListener); + glWindow1.addWindowListener(quitAdapter); + + GLWindow glWindow2 = GLWindow.create(caps); + glWindow2.setTitle("win2"); + glWindow2.setSize(width+100, height+100); + glWindow2.setPosition(2*64+width, 64); + glWindow2.addWindowListener(quitAdapter); + + Animator animator = new Animator(); + animator.add(glWindow1); + animator.add(glWindow2); + animator.start(); + + glWindow1.setVisible(true); + glWindow2.setVisible(true); + + snapshotGLEventListener.setMakeSnapshot(); + + int s = 0; + long t0 = System.currentTimeMillis(); + long t1 = t0; + + while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) { + if( ( t1 - t0 ) / period > s) { + s++; + System.err.println(s+" - switch - START "+ ( t1 - t0 )); + System.err.println(s+" - A w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle())); + System.err.println(s+" - A w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle())); + + // switch context _and_ the demo synchronously + GLDrawableUtil.swapGLContextAndAllGLEventListener(glWindow1, glWindow2); + + System.err.println(s+" - B w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle())); + System.err.println(s+" - B w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle())); + System.err.println(s+" - switch - END "+ ( t1 - t0 )); + + snapshotGLEventListener.setMakeSnapshot(); + } + Thread.sleep(100); + t1 = System.currentTimeMillis(); + } + + animator.stop(); + glWindow1.destroy(); + glWindow2.destroy(); + + } + + @Test(timeout=30000) + public void testSwitch2GLWindowEachWithOwnDemoGL2ES2() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2); + if(null == reqGLCaps) return; + testSwitch2GLWindowEachWithOwnDemoImpl(reqGLCaps); + } + + @Test(timeout=30000) + public void testSwitch2GLWindowEachWithOwnDemoGLES2() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + testSwitch2GLWindowEachWithOwnDemoImpl(reqGLCaps); + } + + public void testSwitch2GLWindowEachWithOwnDemoImpl(GLCapabilities caps) throws InterruptedException { + final GearsES2 gears = new GearsES2(1); + final RedSquareES2 rsquare = new RedSquareES2(1); + final QuitAdapter quitAdapter = new QuitAdapter(); + final SnapshotGLEventListener snapshotGLEventListener1 = new SnapshotGLEventListener(); + final SnapshotGLEventListener snapshotGLEventListener2 = new SnapshotGLEventListener(); + + GLWindow glWindow1 = GLWindow.create(caps); + glWindow1.setTitle("win1"); + glWindow1.setSize(width, height); + glWindow1.setPosition(64, 64); + glWindow1.addGLEventListener(0, gears); + glWindow1.addGLEventListener(snapshotGLEventListener1); + glWindow1.addWindowListener(quitAdapter); + + GLWindow glWindow2 = GLWindow.create(caps); + glWindow2.setTitle("win2"); + glWindow2.setSize(width+100, height+100); + glWindow2.setPosition(2*64+width, 64); + glWindow2.addGLEventListener(0, rsquare); + glWindow2.addGLEventListener(snapshotGLEventListener2); + glWindow2.addWindowListener(quitAdapter); + + Animator animator = new Animator(); + animator.add(glWindow1); + animator.add(glWindow2); + animator.start(); + + glWindow1.setVisible(true); + glWindow2.setVisible(true); + + snapshotGLEventListener1.setMakeSnapshot(); + snapshotGLEventListener2.setMakeSnapshot(); + + int s = 0; + long t0 = System.currentTimeMillis(); + long t1 = t0; + + while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) { + if( ( t1 - t0 ) / period > s) { + s++; + System.err.println(s+" - switch - START "+ ( t1 - t0 )); + System.err.println(s+" - A w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle())); + System.err.println(s+" - A w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle())); + GLDrawableUtil.swapGLContextAndAllGLEventListener(glWindow1, glWindow2); + System.err.println(s+" - B w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle())); + System.err.println(s+" - B w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle())); + System.err.println(s+" - switch - END "+ ( t1 - t0 )); + snapshotGLEventListener1.setMakeSnapshot(); + snapshotGLEventListener2.setMakeSnapshot(); + } + Thread.sleep(100); + t1 = System.currentTimeMillis(); + } + + animator.stop(); + // System.err.println("pre -del-w1: w1: "+glWindow1); + // System.err.println("pre -del-w1: w2: "+glWindow2); + glWindow1.destroy(); + // System.err.println("post-del-w1: w1: "+glWindow1); + // System.err.println("post-del-w1: w2: "+glWindow2); + glWindow2.destroy(); + + } + + // default timing for 2 switches + static long duration = 2200; // ms + static long period = 1000; // ms + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + try { + duration = Integer.parseInt(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } else if(args[i].equals("-period")) { + i++; + try { + period = Integer.parseInt(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } + } + /** + BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); + System.err.println("Press enter to continue"); + System.err.println(stdin.readLine()); */ + org.junit.runner.JUnitCore.main(TestGLContextDrawableSwitch01NEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch02AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch02AWT.java new file mode 100644 index 000000000..316199d07 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch02AWT.java @@ -0,0 +1,192 @@ +/** + * Copyright 2013 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.jogl.acore.glels; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Frame; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +import com.jogamp.newt.event.TraceWindowAdapter; +import com.jogamp.newt.event.awt.AWTWindowAdapter; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; + +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.GLDrawableUtil; + +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.test.junit.util.UITestCase; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +/** + * Test re-association (switching) of GLContext/GLDrawables, + * from GLCanvas to an GLOffscreenAutoDrawable and back. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLContextDrawableSwitch02AWT extends UITestCase { + static int width, height; + + static GLCapabilities getCaps(String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return new GLCapabilities(GLProfile.get(profile)); + } + + @BeforeClass + public static void initClass() { + width = 256; + height = 256; + } + + private GLAutoDrawable createGLAutoDrawable(final Frame frame, GLCapabilities caps, int width, int height) throws InterruptedException, InvocationTargetException { + final GLAutoDrawable glad; + if( caps.isOnscreen() ) { + GLCanvas glCanvas = new GLCanvas(caps); + Assert.assertNotNull(glCanvas); + Dimension glc_sz = new Dimension(width, height); + glCanvas.setMinimumSize(glc_sz); + glCanvas.setPreferredSize(glc_sz); + glCanvas.setSize(glc_sz); + glad = glCanvas; + + frame.setLayout(new BorderLayout()); + frame.add(glCanvas, BorderLayout.CENTER); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.pack(); + frame.setVisible(true); + }}); + + } else { + final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); + glad = factory.createOffscreenAutoDrawable(null, caps, null, width, height); + Assert.assertNotNull(glad); + } + return glad; + } + + @Test(timeout=30000) + public void testSwitch2AWTGLCanvas2OffscreenGL2ES2() throws InterruptedException, InvocationTargetException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2); + if(null == reqGLCaps) return; + testSwitch2AWTGLCanvas2OffscreenImpl(reqGLCaps); + } + + private void testSwitch2AWTGLCanvas2OffscreenImpl(GLCapabilities capsOnscreen) throws InterruptedException, InvocationTargetException { + final GLCapabilities capsOffscreen = (GLCapabilities) capsOnscreen.clone(); + capsOffscreen.setOnscreen(false); + + final QuitAdapter quitAdapter = new QuitAdapter(); + + final Frame frame = new Frame("Gears AWT Test"); + Assert.assertNotNull(frame); + new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter)).addTo(frame); + + GLAutoDrawable glCanvas = createGLAutoDrawable(frame, capsOnscreen, width, height); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + GearsES2 gears = new GearsES2(1); + glCanvas.addGLEventListener(gears); + glCanvas.addGLEventListener(snapshotGLEventListener); + snapshotGLEventListener.setMakeSnapshot(); + + Animator animator = new Animator(); + animator.add(glCanvas); + animator.start(); + + int s = 0; + long t0 = System.currentTimeMillis(); + long t1 = t0; + + GLAutoDrawable glOffscreen = createGLAutoDrawable(null, capsOffscreen, width, height); + while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) { + if( ( t1 - t0 ) / period > s) { + s++; + System.err.println(s+" - switch - START "+ ( t1 - t0 )); + + // switch context _and_ the demo synchronously + GLDrawableUtil.swapGLContextAndAllGLEventListener(glCanvas, glOffscreen); + snapshotGLEventListener.setMakeSnapshot(); + + System.err.println(s+" - switch - END "+ ( t1 - t0 )); + } + Thread.sleep(100); + t1 = System.currentTimeMillis(); + } + + animator.stop(); + // glCanvas.destroy(); + glOffscreen.destroy(); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + final Frame _frame = frame; + _frame.dispose(); + }}); + } + + // default timing for 2 switches + static long duration = 2900; // ms + static long period = 1000; // ms + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + try { + duration = Integer.parseInt(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } else if(args[i].equals("-period")) { + i++; + try { + period = Integer.parseInt(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } + } + /** + BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); + System.err.println("Press enter to continue"); + System.err.println(stdin.readLine()); */ + org.junit.runner.JUnitCore.main(TestGLContextDrawableSwitch02AWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch10NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch10NEWT.java new file mode 100644 index 000000000..4225cd988 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch10NEWT.java @@ -0,0 +1,277 @@ +/** + * Copyright 2013 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.jogl.acore.glels; + +import java.io.IOException; + +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Window; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.event.WindowListener; +import com.jogamp.newt.event.WindowUpdateEvent; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLProfile; + + +import com.jogamp.opengl.GLAutoDrawableDelegate; +import com.jogamp.opengl.GLEventListenerState; +import com.jogamp.opengl.util.Animator; + +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.GLEventListenerCounter; +import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.test.junit.util.UITestCase; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +/** + * Test re-association of GLContext/GLDrawables, + * here GLContext's survival of GLDrawable destruction + * and reuse w/ new or recreated GLDrawable. + * <p> + * Test utilizes {@link GLEventListenerState} for preserving the + * GLAutoDrawable state, i.e. GLContext, all GLEventListener + * and the GLAnimatorControl association. + * </p> + * <p> + * This test is using NEWT's plain Window w/ GLAutoDrawableDelegate. + * </p> + * <p> + * See Bug 665 - https://jogamp.org/bugzilla/show_bug.cgi?id=665. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLContextDrawableSwitch10NEWT extends UITestCase { + // default period for 1 GLAD cycle + static long duration = 1000; // ms + + static int width, height; + + static GLCapabilities getCaps(String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return new GLCapabilities(GLProfile.get(profile)); + } + + @BeforeClass + public static void initClass() { + width = 256; + height = 256; + } + + private GLAutoDrawable createGLAutoDrawableWithoutContext(GLCapabilities caps, int x, int y, int width, int height, WindowListener wl) throws InterruptedException { + final Window window = NewtFactory.createWindow(caps); + Assert.assertNotNull(window); + window.setPosition(x, y); + window.setSize(width, height); + window.setVisible(true); + Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true)); + + final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); + final GLDrawable drawable = factory.createGLDrawable(window); + Assert.assertNotNull(drawable); + + drawable.setRealized(true); + Assert.assertTrue(drawable.isRealized()); + + final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, null, window, false, null) { + @Override + protected void destroyImplInLock() { + super.destroyImplInLock(); + window.destroy(); // destroys the actual window + } + }; + + window.setWindowDestroyNotifyAction( new Runnable() { + public void run() { + glad.windowDestroyNotifyOp(); + } } ); + + // add basic window interaction + window.addWindowListener(new WindowAdapter() { + @Override + public void windowRepaint(WindowUpdateEvent e) { + glad.windowRepaintOp(); + } + @Override + public void windowResized(WindowEvent e) { + glad.windowResizedOp(window.getWidth(), window.getHeight()); + } + }); + window.addWindowListener(wl); + + return glad; + } + + @Test(timeout=30000) + public void test01GLADDelegateGL2ES2() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2); + if(null == reqGLCaps) return; + testGLADDelegateImpl(reqGLCaps); + } + + @Test(timeout=30000) + public void test02GLADDelegateGLES2() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + testGLADDelegateImpl(reqGLCaps); + } + + private void testGLADDelegateImpl(GLCapabilities caps) throws InterruptedException { + final GLEventListenerCounter glelCounter = new GLEventListenerCounter(); + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + final Animator animator = new Animator(); + animator.start(); + + final GLEventListenerState glls1; + + // - create glad1 w/o context + // - create context using glad1 and assign it to glad1 + { + final QuitAdapter quitAdapter = new QuitAdapter(); + final GLAutoDrawable glad1 = createGLAutoDrawableWithoutContext(caps, 64, 64, width, height, quitAdapter); + final GLContext context1 = glad1.createContext(null); + glad1.setContext(context1, true); + animator.add(glad1); + + glad1.addGLEventListener(glelCounter); + glad1.addGLEventListener(new GearsES2(1)); + glad1.addGLEventListener(snapshotGLEventListener); + snapshotGLEventListener.setMakeSnapshot(); + + final long t0 = System.currentTimeMillis(); + long t1 = t0; + + while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) { + Thread.sleep(100); + t1 = System.currentTimeMillis(); + } + + Assert.assertEquals(1, glelCounter.initCount); + Assert.assertTrue(1 <= glelCounter.reshapeCount); + Assert.assertTrue(1 <= glelCounter.displayCount); + Assert.assertEquals(0, glelCounter.disposeCount); + Assert.assertEquals(context1, glad1.getContext()); + Assert.assertEquals(3, glad1.getGLEventListenerCount()); + Assert.assertEquals(context1.getGLReadDrawable(), glad1.getDelegatedDrawable()); + Assert.assertEquals(context1.getGLDrawable(), glad1.getDelegatedDrawable()); + + // - dis-associate context from glad1 + // - destroy glad1 + glls1 = GLEventListenerState.moveFrom(glad1); + + Assert.assertEquals(1, glelCounter.initCount); + Assert.assertTrue(1 <= glelCounter.reshapeCount); + Assert.assertTrue(1 <= glelCounter.displayCount); + Assert.assertEquals(0, glelCounter.disposeCount); + Assert.assertEquals(context1, glls1.context); + Assert.assertNull(context1.getGLReadDrawable()); + Assert.assertNull(context1.getGLDrawable()); + Assert.assertEquals(3, glls1.listenerCount()); + Assert.assertEquals(true, glls1.isOwner()); + Assert.assertEquals(null, glad1.getContext()); + Assert.assertEquals(0, glad1.getGLEventListenerCount()); + + glad1.destroy(); + Assert.assertEquals(1, glelCounter.initCount); + Assert.assertTrue(1 <= glelCounter.reshapeCount); + Assert.assertTrue(1 <= glelCounter.displayCount); + Assert.assertEquals(0, glelCounter.disposeCount); + } + + // - create glad2 w/ survived context + { + final QuitAdapter quitAdapter = new QuitAdapter(); + final GLAutoDrawable glad2 = createGLAutoDrawableWithoutContext(caps, 2*64+width, 64, width+100, height+100, quitAdapter); + snapshotGLEventListener.setMakeSnapshot(); + + Assert.assertEquals(null, glad2.getContext()); + Assert.assertEquals(0, glad2.getGLEventListenerCount()); + + glls1.moveTo(glad2); + + Assert.assertTrue(glad2.isRealized()); + + Assert.assertEquals(1, glelCounter.initCount); + Assert.assertTrue(1 <= glelCounter.reshapeCount); + Assert.assertTrue(1 <= glelCounter.displayCount); + Assert.assertEquals(0, glelCounter.disposeCount); + Assert.assertEquals(glls1.context, glad2.getContext()); + Assert.assertEquals(3, glad2.getGLEventListenerCount()); + Assert.assertEquals(glls1.context.getGLReadDrawable(), glad2.getDelegatedDrawable()); + Assert.assertEquals(glls1.context.getGLDrawable(), glad2.getDelegatedDrawable()); + Assert.assertEquals(false, glls1.isOwner()); + + final long t0 = System.currentTimeMillis(); + long t1 = t0; + + while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) { + Thread.sleep(100); + t1 = System.currentTimeMillis(); + } + + glad2.destroy(); + Assert.assertEquals(1, glelCounter.initCount); + Assert.assertTrue(1 <= glelCounter.reshapeCount); + Assert.assertTrue(1 <= glelCounter.displayCount); + Assert.assertEquals(1, glelCounter.disposeCount); + } + animator.stop(); + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + try { + duration = Integer.parseInt(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } + } + /** + BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); + System.err.println("Press enter to continue"); + System.err.println(stdin.readLine()); */ + org.junit.runner.JUnitCore.main(TestGLContextDrawableSwitch10NEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch11NewtAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch11NewtAWT.java new file mode 100644 index 000000000..e5f61a4be --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch11NewtAWT.java @@ -0,0 +1,121 @@ +/** + * Copyright 2013 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.jogl.acore.glels; + +import java.io.IOException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; + + +import com.jogamp.opengl.GLEventListenerState; +import com.jogamp.opengl.util.Animator; + +import com.jogamp.opengl.test.junit.util.GLEventListenerCounter; + +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +/** + * Test re-association of GLContext/GLDrawables, + * here GLContext's survival of GLDrawable destruction + * and reuse w/ new or recreated GLDrawable. + * <p> + * Test utilizes {@link GLEventListenerState} for preserving the + * GLAutoDrawable state, i.e. GLContext, all GLEventListener + * and the GLAnimatorControl association. + * </p> + * <p> + * This test is using JOGL's NEWT GLWindow. + * </p> + * <p> + * See Bug 665 - https://jogamp.org/bugzilla/show_bug.cgi?id=665. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLContextDrawableSwitch11NewtAWT extends GLContextDrawableSwitchBase { + + @Test(timeout=30000) + public void test21GLWindowGL2ES2() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2); + if(null == reqGLCaps) return; + testGLWindowImpl(reqGLCaps); + } + + @Test(timeout=30000) + public void test22GLWindowGLES2() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + testGLWindowImpl(reqGLCaps); + } + + private void testGLWindowImpl(GLCapabilities caps) throws InterruptedException { + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + final GLEventListenerCounter glelTracker = new GLEventListenerCounter(); + final Animator animator = new Animator(); + animator.start(); + + final GLEventListenerState glels[] = new GLEventListenerState[1]; + + // - create glad1 w/o context + // - create context using glad1 and assign it to glad1 + { + testGLADOneLifecycle(null, caps, GLADType.GLWindow, width, + height, glelTracker, + snapshotGLEventListener, + null, glels, animator); + } + + // - create glad2 w/ survived context + { + testGLADOneLifecycle(null, caps, GLADType.GLWindow, width+100, + height+100, glelTracker, + snapshotGLEventListener, + glels[0], null, null); + } + animator.stop(); + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + try { + duration = Integer.parseInt(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } + } + /** + BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); + System.err.println("Press enter to continue"); + System.err.println(stdin.readLine()); */ + org.junit.runner.JUnitCore.main(TestGLContextDrawableSwitch11NewtAWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch12AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch12AWT.java new file mode 100644 index 000000000..d17d899b8 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch12AWT.java @@ -0,0 +1,147 @@ +/** + * Copyright 2013 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.jogl.acore.glels; + +import java.io.IOException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; + +import jogamp.nativewindow.jawt.JAWTUtil; + +import com.jogamp.opengl.GLEventListenerState; +import com.jogamp.opengl.util.Animator; + +import com.jogamp.opengl.test.junit.util.GLEventListenerCounter; + +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +/** + * Test re-association of GLContext/GLDrawables, + * here GLContext's survival of GLDrawable destruction + * and reuse w/ new or recreated GLDrawable. + * <p> + * Test utilizes {@link GLEventListenerState} for preserving the + * GLAutoDrawable state, i.e. GLContext, all GLEventListener + * and the GLAnimatorControl association. + * </p> + * <p> + * This test is using JOGL's AWT GLCanvas + * </p> + * <p> + * See Bug 665 - https://jogamp.org/bugzilla/show_bug.cgi?id=665. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLContextDrawableSwitch12AWT extends GLContextDrawableSwitchBase { + + @Test(timeout=30000) + public void test01GLCanvasOnscreenGL2ES2() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2); + if(null == reqGLCaps) return; + testGLCanvasImpl(reqGLCaps, false); + } + + @Test(timeout=30000) + public void test02GLCanvasOnscreenGLES2() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + testGLCanvasImpl(reqGLCaps, false); + } + + @Test(timeout=30000) + public void test11GLCanvasOffscreenGL2ES2() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2); + if(null == reqGLCaps) return; + testGLCanvasImpl(reqGLCaps, true); + } + + @Test(timeout=30000) + public void test12GLCanvasOffscreenGLES2() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + testGLCanvasImpl(reqGLCaps, true); + } + + private void testGLCanvasImpl(GLCapabilities caps, boolean offscreenLayer) throws InterruptedException { + if( offscreenLayer ) { + if( !JAWTUtil.isOffscreenLayerSupported() ) { + System.err.println("Platform doesn't support offscreen rendering."); + return; + } + } else { + if( JAWTUtil.isOffscreenLayerRequired() ) { + System.err.println("Platform requires offscreen rendering."); + return; + } + } + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + final GLEventListenerCounter glelTracker = new GLEventListenerCounter(); + final Animator animator = new Animator(); + animator.start(); + + final GLEventListenerState glels[] = new GLEventListenerState[1]; + + // - create glad1 w/o context + // - create context using glad1 and assign it to glad1 + { + testGLADOneLifecycle(null, caps, offscreenLayer ? GLADType.GLCanvasOffscreen : GLADType.GLCanvasOnscreen, width, + height, glelTracker, + snapshotGLEventListener, + null, glels, animator); + } + + // - create glad2 w/ survived context + { + testGLADOneLifecycle(null, caps, offscreenLayer ? GLADType.GLCanvasOffscreen : GLADType.GLCanvasOnscreen, width+100, + height+100, glelTracker, + snapshotGLEventListener, + glels[0], null, null); + } + animator.stop(); + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + try { + duration = Integer.parseInt(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } + } + /** + BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); + System.err.println("Press enter to continue"); + System.err.println(stdin.readLine()); */ + org.junit.runner.JUnitCore.main(TestGLContextDrawableSwitch12AWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch21Newt2AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch21Newt2AWT.java new file mode 100644 index 000000000..2b0f43d68 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch21Newt2AWT.java @@ -0,0 +1,195 @@ +/** + * Copyright 2013 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.jogl.acore.glels; + +import java.io.IOException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; + + +import com.jogamp.newt.Display; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Screen; +import com.jogamp.opengl.GLEventListenerState; +import com.jogamp.opengl.GLRendererQuirks; +import com.jogamp.opengl.util.Animator; + +import com.jogamp.opengl.test.junit.util.GLEventListenerCounter; + +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +/** + * Test re-association of GLContext/GLDrawables, + * here GLContext's survival of GLDrawable destruction + * and reuse w/ new or recreated GLDrawable. + * <p> + * Test utilizes {@link GLEventListenerState} for preserving the + * GLAutoDrawable state, i.e. GLContext, all GLEventListener + * and the GLAnimatorControl association. + * </p> + * <p> + * This test moves the {@link GLEventListenerState} from a + * NEWT GLWindow before it's destruction to an AWT GLCanvas after it's creation + * and vice versa + * </p> + * <p> + * See Bug 665 - https://jogamp.org/bugzilla/show_bug.cgi?id=665. + * </p> + * <p> + * Interesting artifact w/ ATI proprietary driver is that the + * bug causing the quirk {@link GLRendererQuirks#DontCloseX11Display} + * also causes an XCB crash when reusing the X11 display connection + * from AWT -> NEWT. Pre-allocating the X11 Display and keeping it referenced + * to avoid such re-usage worksaround this problem. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLContextDrawableSwitch21Newt2AWT extends GLContextDrawableSwitchBase { + + @Test(timeout=30000) + public void test01GLCanvasOnScrn2GLWindowGL2ES2() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2); + if(null == reqGLCaps) return; + testGLCanvas2GLWindowImpl(null, reqGLCaps, GLADType.GLCanvasOnscreen, GLADType.GLWindow); + } + + @Test(timeout=30000) + public void test02GLCanvasOnScrn2GLWindowGLES2() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + testGLCanvas2GLWindowImpl(null, reqGLCaps, GLADType.GLCanvasOnscreen, GLADType.GLWindow); + } + + @Test(timeout=30000) + public void test11GLWindow2GLCanvasOnScrnGL2ES2() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2); + if(null == reqGLCaps) return; + final Display dpy = NewtFactory.createDisplay(null); + final Screen screen = NewtFactory.createScreen(dpy, 0); + screen.addReference(); + testGLCanvas2GLWindowImpl(screen, reqGLCaps, GLADType.GLWindow, GLADType.GLCanvasOnscreen); + screen.removeReference(); + } + + @Test(timeout=30000) + public void test12GLWindow2GLCanvasOnScrnGLES2() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + final Display dpy = NewtFactory.createDisplay(null); + final Screen screen = NewtFactory.createScreen(dpy, 0); + screen.addReference(); + testGLCanvas2GLWindowImpl(screen, reqGLCaps, GLADType.GLWindow, GLADType.GLCanvasOnscreen); + screen.removeReference(); + } + + @Test(timeout=30000) + public void test21GLCanvasOffScrn2GLWindowGL2ES2() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2); + if(null == reqGLCaps) return; + testGLCanvas2GLWindowImpl(null, reqGLCaps, GLADType.GLCanvasOffscreen, GLADType.GLWindow); + } + + @Test(timeout=30000) + public void test22GLCanvasOffScrn2GLWindowGLES2() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + testGLCanvas2GLWindowImpl(null, reqGLCaps, GLADType.GLCanvasOffscreen, GLADType.GLWindow); + } + + @Test(timeout=30000) + public void test31GLWindow2GLCanvasOffScrnGL2ES2() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2); + if(null == reqGLCaps) return; + final Display dpy = NewtFactory.createDisplay(null); + final Screen screen = NewtFactory.createScreen(dpy, 0); + screen.addReference(); + testGLCanvas2GLWindowImpl(screen, reqGLCaps, GLADType.GLWindow, GLADType.GLCanvasOffscreen); + screen.removeReference(); + } + + @Test(timeout=30000) + public void test32GLWindow2GLCanvasOffScrnGLES2() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + final Display dpy = NewtFactory.createDisplay(null); + final Screen screen = NewtFactory.createScreen(dpy, 0); + screen.addReference(); + testGLCanvas2GLWindowImpl(screen, reqGLCaps, GLADType.GLWindow, GLADType.GLCanvasOffscreen); + screen.removeReference(); + } + + private void testGLCanvas2GLWindowImpl(Screen screen, GLCapabilities caps, GLADType gladType1, GLADType gladType2) throws InterruptedException { + if( !validateOnOffscreenLayer(gladType1, gladType2) ) { + return; + } + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + final GLEventListenerCounter glelTracker = new GLEventListenerCounter(); + final Animator animator = new Animator(); + animator.start(); + + final GLEventListenerState glels[] = new GLEventListenerState[1]; + + // - create glad1 w/o context + // - create context using glad1 and assign it to glad1 + { + testGLADOneLifecycle(screen, caps, gladType1, width, + height, glelTracker, + snapshotGLEventListener, + null, glels, animator); + } + + // - create glad2 w/ survived context + { + testGLADOneLifecycle(screen, caps, gladType2, width+100, + height+100, glelTracker, + snapshotGLEventListener, + glels[0], null, null); + } + animator.stop(); + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + try { + duration = Integer.parseInt(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } + } + /** + BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); + System.err.println("Press enter to continue"); + System.err.println(stdin.readLine()); */ + org.junit.runner.JUnitCore.main(TestGLContextDrawableSwitch21Newt2AWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT01GLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT01GLn.java index 64a1a0138..6152fb144 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT01GLn.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT01GLn.java @@ -40,61 +40,38 @@ import java.awt.Frame; import org.junit.Assert; import org.junit.Assume; -import org.junit.Before; import org.junit.BeforeClass; -import org.junit.After; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestAWT01GLn extends UITestCase { - Frame frame=null; - GLCanvas glCanvas=null; - @BeforeClass public static void startup() { System.out.println("GLProfile "+GLProfile.glAvailabilityToString()); } - @Before - public void init() { - frame = new Frame("Texture Test"); - Assert.assertNotNull(frame); - } - - @After - public void release() { - Assert.assertNotNull(frame); - Assert.assertNotNull(glCanvas); - try { - javax.swing.SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - frame.setVisible(false); - frame.remove(glCanvas); - frame.dispose(); - }}); - } catch (Throwable t) { - t.printStackTrace(); - Assume.assumeNoException(t); - } - frame=null; - glCanvas=null; - } - protected void runTestGL(GLCapabilities caps) throws InterruptedException { - glCanvas = new GLCanvas(caps); + final Frame frame = new Frame("Texture Test"); + Assert.assertNotNull(frame); + + final GLCanvas glCanvas = new GLCanvas(caps); Assert.assertNotNull(glCanvas); + glCanvas.addGLEventListener(new GearsES2()); frame.add(glCanvas); - // Revalidate size/layout. - // Always validate if component added/removed. - // Ensure 1st paint of GLCanvas will have a valid size, hence drawable gets created. - frame.setSize(512, 512); - frame.validate(); - try { javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { + // Revalidate size/layout. + // Always validate if component added/removed. + // Ensure 1st paint of GLCanvas will have a valid size, hence drawable gets created. + frame.setSize(512, 512); + frame.validate(); + frame.setVisible(true); }}); } catch (Throwable t) { @@ -110,6 +87,18 @@ public class TestAWT01GLn extends UITestCase { Thread.sleep(500); // 500 ms animator.stop(); + + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + frame.remove(glCanvas); + frame.dispose(); + }}); + } catch (Throwable t) { + t.printStackTrace(); + Assume.assumeNoException(t); + } } @Test @@ -136,6 +125,18 @@ public class TestAWT01GLn extends UITestCase { } } + @Test + public void test02ES2() throws InterruptedException { + if(GLProfile.isAvailable(GLProfile.GLES2)) { + GLProfile glprofile = GLProfile.get(GLProfile.GLES2); + System.out.println( "GLProfile GLES2: " + glprofile ); + GLCapabilities caps = new GLCapabilities(glprofile); + runTestGL(caps); + } else { + System.out.println("GLES2 n/a"); + } + } + public static void main(String args[]) { org.junit.runner.JUnitCore.main(TestAWT01GLn.class.getName()); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT02WindowClosing.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT02WindowClosing.java index f83c8c03d..349674eef 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT02WindowClosing.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT02WindowClosing.java @@ -29,33 +29,31 @@ package com.jogamp.opengl.test.junit.jogl.awt; import com.jogamp.opengl.test.junit.util.UITestCase; -import javax.media.opengl.GLProfile; import java.awt.*; import java.awt.event.*; import org.junit.Assert; import org.junit.Assume; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.After; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestAWT02WindowClosing extends UITestCase { static long durationPerTest = 200; // ms @Test public void test01WindowClosing() throws InterruptedException { - Frame frame = new Frame(); - frame.setSize(500, 500); + final Frame frame = new Frame(); ClosingWindowAdapter closingWindowAdapter = new ClosingWindowAdapter(frame); frame.addWindowListener(closingWindowAdapter); - final Frame _frame = frame; try { javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { - _frame.setVisible(true); + frame.setSize(500, 500); + frame.setVisible(true); }}); } catch (Throwable t) { t.printStackTrace(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT03GLCanvasRecreate01.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT03GLCanvasRecreate01.java index aa7b4e06b..7282687e5 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT03GLCanvasRecreate01.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT03GLCanvasRecreate01.java @@ -46,8 +46,11 @@ import org.junit.Before; import org.junit.BeforeClass; import org.junit.After; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestAWT03GLCanvasRecreate01 extends UITestCase { static long durationPerTest = 1000; // ms @@ -139,7 +142,7 @@ public class TestAWT03GLCanvasRecreate01 extends UITestCase { } private void setVisible(final Frame frame, final boolean v) { - try { + try { javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { frame.setVisible(v); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug460GLCanvasNPEAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug460GLCanvasNPEAWT.java index c89ce43f7..00e14b094 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug460GLCanvasNPEAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug460GLCanvasNPEAWT.java @@ -34,7 +34,10 @@ import javax.media.opengl.GLProfile; import javax.media.opengl.awt.GLCanvas; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestBug460GLCanvasNPEAWT { public static void main(String[] args) { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug461FBOSupersamplingSwingAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug461FBOSupersamplingSwingAWT.java new file mode 100644 index 000000000..96ec8ab75 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug461FBOSupersamplingSwingAWT.java @@ -0,0 +1,189 @@ +/** + * Copyright 2011 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.jogl.awt; + +import java.awt.Container; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +import java.awt.image.BufferedImage; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLOffscreenAutoDrawable; +import javax.media.opengl.GLProfile; +import javax.swing.ImageIcon; +import javax.swing.JFrame; +import javax.swing.JLabel; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.awt.AWTGLReadBufferUtil; + +/** + * Tests for bug 461, a failure of GLDrawableFactory.createGLPbuffer() on Windows + * when the stencil buffer is turned on. + * + * @author Wade Walker (from code sample provided by Owen Dimond) + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestBug461FBOSupersamplingSwingAWT extends UITestCase implements GLEventListener { + static long durationPerTest = 500; + JFrame jframe; + GLOffscreenAutoDrawable offScreenBuffer; + AWTGLReadBufferUtil awtGLReadBufferUtil; + + private void render(GLAutoDrawable drawable) { + GL2 gl = drawable.getGL().getGL2(); + Assert.assertNotNull(gl); + gl.glClear(GL.GL_COLOR_BUFFER_BIT); + + // draw a triangle filling the window + gl.glBegin(GL.GL_TRIANGLES); + gl.glColor3f(1, 0, 0); + gl.glVertex2d(-1, -1); + gl.glColor3f(0, 1, 0); + gl.glVertex2d(0, 1); + gl.glColor3f(0, 0, 1); + gl.glVertex2d(1, -1); + gl.glEnd(); + } + + /* @Override */ + public void init(GLAutoDrawable drawable) { + awtGLReadBufferUtil = new AWTGLReadBufferUtil(drawable.getGLProfile(), false); + } + + /* @Override */ + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + } + + /* @Override */ + public void display(GLAutoDrawable drawable) { + render(offScreenBuffer); + // BufferedImage outputImage = com.jogamp.opengl.util.awt.Screenshot.readToBufferedImage(200, 200, false); + BufferedImage outputImage = awtGLReadBufferUtil.readPixelsToBufferedImage(drawable.getGL(), 0, 0, 200, 200, true /* awtOrientation */); + Assert.assertNotNull(outputImage); + ImageIcon imageIcon = new ImageIcon(outputImage); + final JLabel imageLabel = new JLabel(imageIcon); + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + Container cont = jframe.getContentPane(); + cont.removeAll(); + cont.add(imageLabel); + cont.validate(); + }}); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /* @Override */ + public void dispose(GLAutoDrawable drawable) { + try { + awtGLReadBufferUtil.dispose(drawable.getGL()); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + jframe.setVisible(false); + jframe.dispose(); + }}); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void testOffscreenSupersampling() throws InterruptedException, InvocationTargetException { + jframe = new JFrame("Offscreen Supersampling"); + Assert.assertNotNull(jframe); + jframe.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }); + + GLProfile glp = GLProfile.get(GLProfile.GL2); + Assert.assertNotNull(glp); + + GLDrawableFactory fac = GLDrawableFactory.getFactory(glp); + Assert.assertNotNull(fac); + + Assert.assertTrue( fac.canCreateGLPbuffer(GLProfile.getDefaultDevice(), glp) ); + + GLCapabilities glCap = new GLCapabilities(glp); + Assert.assertNotNull(glCap); + + // COMMENTING OUT THIS LINE FIXES THE ISSUE. + // Setting this in JOGL1 works. Thus this is a JOGL2 issue. + glCap.setSampleBuffers(true); + + // Without line below, there is an error on Windows. + // glCap.setDoubleBuffered(false); // implicit double buffer -> MSAA + FBO + + // Needed for drop shadows + glCap.setStencilBits(1); + + //makes a new buffer + offScreenBuffer = fac.createOffscreenAutoDrawable(GLProfile.getDefaultDevice(), glCap, null, 200, 200); + Assert.assertNotNull(offScreenBuffer); + offScreenBuffer.addGLEventListener(this); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + jframe.setSize( 300, 300); + jframe.setVisible(true); + }}); + offScreenBuffer.display(); // read from front buffer due to FBO+MSAA -> double-buffer + offScreenBuffer.display(); // now we have prev. image in front buffer to be read out + + Thread.sleep(durationPerTest); + + offScreenBuffer.destroy(); + } + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + durationPerTest = MiscUtils.atol(args[++i], durationPerTest); + } + } + org.junit.runner.JUnitCore.main(TestBug461FBOSupersamplingSwingAWT.class.getName()); + } +} + diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug461OffscreenSupersamplingSwingAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug461PBufferSupersamplingSwingAWT.java index 6a315c67d..a1abbe2aa 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug461OffscreenSupersamplingSwingAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug461PBufferSupersamplingSwingAWT.java @@ -48,6 +48,8 @@ import javax.swing.JLabel; import org.junit.Assert; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import com.jogamp.opengl.test.junit.util.UITestCase; @@ -57,7 +59,9 @@ import com.jogamp.opengl.test.junit.util.UITestCase; * * @author Wade Walker (from code sample provided by Owen Dimond) */ -public class TestBug461OffscreenSupersamplingSwingAWT extends UITestCase implements GLEventListener { +@SuppressWarnings("deprecation") +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestBug461PBufferSupersamplingSwingAWT extends UITestCase implements GLEventListener { JFrame jframe; GLPbuffer offScreenBuffer; @@ -125,7 +129,7 @@ public class TestBug461OffscreenSupersamplingSwingAWT extends UITestCase impleme GLDrawableFactory fac = GLDrawableFactory.getFactory(glp); Assert.assertNotNull(fac); - Assert.assertTrue( fac.canCreateGLPbuffer(GLProfile.getDefaultDevice()) ); + Assert.assertTrue( fac.canCreateGLPbuffer(GLProfile.getDefaultDevice(), glp) ); GLCapabilities glCap = new GLCapabilities(glp); Assert.assertNotNull(glCap); @@ -148,10 +152,11 @@ public class TestBug461OffscreenSupersamplingSwingAWT extends UITestCase impleme public void run() { jframe.setVisible(true); }}); + offScreenBuffer.destroy(); } public static void main(String args[]) { - org.junit.runner.JUnitCore.main(TestBug461OffscreenSupersamplingSwingAWT.class.getName()); + org.junit.runner.JUnitCore.main(TestBug461PBufferSupersamplingSwingAWT.class.getName()); } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug551AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug551AWT.java index e68ddb4c1..51eb22210 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug551AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug551AWT.java @@ -46,6 +46,8 @@ import java.awt.Window; import javax.swing.JFrame; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import static org.junit.Assume.*; import static javax.swing.SwingUtilities.*; @@ -54,6 +56,7 @@ import static javax.swing.SwingUtilities.*; * Tests context creation + display on various kinds of Window implementations. * @author Michael Bien, et. al. */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestBug551AWT extends UITestCase { static void checkGraphicsEnvironment() { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug572AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug572AWT.java new file mode 100644 index 000000000..234336016 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug572AWT.java @@ -0,0 +1,170 @@ +/** + * Copyright 2012 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.jogl.awt; + +import java.awt.Dimension; +import java.awt.Window; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; + +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Test realize GLCanvas and setVisible(true) AWT-Frames on AWT-EDT and on current thread (non AWT-EDT) + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestBug572AWT extends UITestCase { + static long durationPerTest = 150; // ms + + static class Cleanup implements Runnable { + Window window; + + public Cleanup(Window w) { + window = w; + } + + public void run() { + System.err.println("cleaning up..."); + window.setVisible(false); + try { + window.removeAll(); + } catch (Throwable t) { + Assume.assumeNoException(t); + t.printStackTrace(); + } + window.dispose(); + } + } + + private void testRealizeGLCanvas(final boolean onAWTEDT, final boolean setFrameSize) throws InterruptedException, InvocationTargetException { + final Window window = new JFrame(this.getSimpleTestName(" - ")); + final GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES2()); + final GLCanvas glCanvas = new GLCanvas(caps); + final SnapshotGLEventListener snapshooter = new SnapshotGLEventListener(); + snapshooter.setMakeSnapshotAlways(true); + glCanvas.addGLEventListener(new GearsES2()); + glCanvas.addGLEventListener(snapshooter); + window.add(glCanvas); + + final Runnable realizeAction = new Runnable() { + @Override + public void run() { + // Revalidate size/layout. + // Always validate if component added/removed. + // Ensure 1st paint of GLCanvas will have a valid size, hence drawable gets created. + if( setFrameSize ) { + window.setSize(512, 512); + window.validate(); + } else { + Dimension size = new Dimension(512, 512); + glCanvas.setPreferredSize(size); + glCanvas.setMinimumSize(size); + window.pack(); + } + window.setVisible(true); + } }; + if( onAWTEDT ) { + // trigger realization on AWT-EDT, otherwise it won't immediatly .. + SwingUtilities.invokeAndWait( realizeAction ); + } else { + // trigger realization on non AWT-EDT, realization will happen at a later time .. + realizeAction.run(); + + // Wait until it's displayable after issuing initial setVisible(true) on current thread (non AWT-EDT)! + Assert.assertTrue("GLCanvas didn't become visible", AWTRobotUtil.waitForVisible(glCanvas, true)); + Assert.assertTrue("GLCanvas didn't become realized", AWTRobotUtil.waitForRealized(glCanvas, true)); // implies displayable + } + + System.err.println("XXXX-0 "+glCanvas.getDelegatedDrawable().isRealized()+", "+glCanvas); + + Assert.assertTrue("GLCanvas didn't become displayable", glCanvas.isDisplayable()); + Assert.assertTrue("GLCanvas didn't become realized", glCanvas.isRealized()); + + // The AWT-EDT reshape/repaint events happen offthread later .. + System.err.println("XXXX-1 reshapeCount "+snapshooter.getReshapeCount()); + System.err.println("XXXX-1 displayCount "+snapshooter.getDisplayCount()); + + // Wait unitl AWT-EDT has issued reshape/repaint + for (int wait=0; wait<AWTRobotUtil.POLL_DIVIDER && + ( 0 == snapshooter.getReshapeCount() || 0 == snapshooter.getDisplayCount() ); + wait++) { + Thread.sleep(AWTRobotUtil.TIME_SLICE); + } + System.err.println("XXXX-2 reshapeCount "+snapshooter.getReshapeCount()); + System.err.println("XXXX-2 displayCount "+snapshooter.getDisplayCount()); + + Assert.assertTrue("GLCanvas didn't reshape", snapshooter.getReshapeCount()>0); + Assert.assertTrue("GLCanvas didn't display", snapshooter.getDisplayCount()>0); + + Thread.sleep(durationPerTest); + + // After initial 'setVisible(true)' all AWT manipulation needs to be done + // via the AWT EDT, according to the AWT spec. + + // AWT / Swing on EDT.. + SwingUtilities.invokeAndWait(new Cleanup(window)); + } + + @Test(timeout = 10000) // 10s timeout + public void test01RealizeGLCanvasOnAWTEDTUseFrameSize() throws InterruptedException, InvocationTargetException { + testRealizeGLCanvas(true, true); + } + + @Test(timeout = 10000) // 10s timeout + public void test02RealizeGLCanvasOnAWTEDTUseGLCanvasSize() throws InterruptedException, InvocationTargetException { + testRealizeGLCanvas(true, false); + } + + @Test(timeout = 10000) // 10s timeout + public void test11RealizeGLCanvasOnMainTUseFrameSize() throws InterruptedException, InvocationTargetException { + testRealizeGLCanvas(false, true); + } + + @Test(timeout = 10000) // 10s timeout + public void test12RealizeGLCanvasOnMainTUseGLCanvasSize() throws InterruptedException, InvocationTargetException { + testRealizeGLCanvas(false, false); + } + + public static void main(String args[]) { + org.junit.runner.JUnitCore.main(TestBug572AWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug611AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug611AWT.java new file mode 100644 index 000000000..d8e781d92 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug611AWT.java @@ -0,0 +1,84 @@ + +package com.jogamp.opengl.test.junit.jogl.awt; + +import java.awt.Desktop; +import java.io.File; + +import javax.media.opengl.GLProfile; + +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.common.os.Platform; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * As reported in Bug 611, on Windows XP is a performance issue: + * After JOGL initialization there seems to be a huge time lag + * when trying to open the Desktop folder. + * <p> + * Test disabled since showing the Desktop folder will + * disturb the 'desktop' .. if there is another way to show + * the performance bug, pls do so. + * </p> + * <p> + * Since Windows XP is out of life .. we may not care .. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestBug611AWT extends UITestCase { + + @Test + public void test00() { + // make junit happy + } + + // @Test + public void test01() { + try { + // System.setProperty("jogamp.gluegen.UseTempJarCache", "false"); + GLProfile.initSingleton(); + Desktop desktop; + if (Desktop.isDesktopSupported()) { + desktop = Desktop.getDesktop(); + } else { + desktop = null; + } + if(null != desktop) { + String home = System.getProperty("user.home"); + File homeFolder = null; + if(null != home) { + { + File tst = new File(home + "/Desktop"); + if( tst.canRead() ) { + homeFolder = tst; + } + } + if(null == homeFolder) { + File tst = new File(home); + if( tst.canRead() ) { + homeFolder = tst; + } + } + } + if(null == homeFolder) { + if(Platform.getOSType() == Platform.OSType.WINDOWS) { + homeFolder = new File("c:\\"); + } else { + homeFolder = new File("/"); + } + } + if(null != homeFolder) { + desktop.open(homeFolder); + } + } + } catch(Exception ex) { + ex.printStackTrace(); + } + } + + public static void main(String args[]) { + org.junit.runner.JUnitCore.main(TestBug611AWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug642JSplitPaneMixHwLw01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug642JSplitPaneMixHwLw01AWT.java new file mode 100644 index 000000000..57210a946 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug642JSplitPaneMixHwLw01AWT.java @@ -0,0 +1,199 @@ +package com.jogamp.opengl.test.junit.jogl.awt; + +import java.awt.BorderLayout; +// import java.awt.Canvas; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.GraphicsConfiguration; +import java.awt.Rectangle; +import java.awt.Shape; +import java.io.IOException; + +import javax.media.opengl.GLAnimatorControl; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; +import javax.media.opengl.awt.GLJPanel; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; +import javax.swing.WindowConstants; + +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.common.util.ReflectionUtil; +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.util.Animator; +import com.jogamp.opengl.util.FPSAnimator; + +/** + * Documenting Bug 642 (related to Bug 586) + * + * <p> + * JSplitPane cannot mix hw/lw components, only if setting property '-Dsun.awt.disableMixing=true'. + * </p> + * See Bug 586 + * See git commit '8df12ca151dfc577c90b485d4ebfe491b88e55aa'. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestBug642JSplitPaneMixHwLw01AWT extends UITestCase { + static long durationPerTest = 500; + + static { + // too late: use at cmd-line '-Dsun.awt.disableMixing=true' works + // System.setProperty("sun.awt.disableMixing", "true"); + } + + /** + * Doesn't work either .. + */ + @SuppressWarnings("serial") + public static class TransparentJScrollPane extends JScrollPane { + + public TransparentJScrollPane(Component view) { + super(view); + + setOpaque(false); + + try { + ReflectionUtil.callStaticMethod( + "com.sun.awt.AWTUtilities", "setComponentMixingCutoutShape", + new Class<?>[] { Component.class, Shape.class }, + new Object[] { this, new Rectangle() } , + GraphicsConfiguration.class.getClassLoader()); + System.err.println("com.sun.awt.AWTUtilities.setComponentMixingCutoutShape(..) passed"); + } catch (RuntimeException re) { + System.err.println("com.sun.awt.AWTUtilities.setComponentMixingCutoutShape(..) failed: "+re.getMessage()); + } + } + + @Override + public void setOpaque(boolean isOpaque) { + } + } + + protected void runTestGL(GLCapabilities caps, boolean useGLJPanel, boolean useContainer) throws InterruptedException { + final String typeS = useGLJPanel ? "LW" : "HW"; + final JFrame frame = new JFrame("Mix Hw/Lw Swing - Canvas "+typeS); + Assert.assertNotNull(frame); + + final Dimension f_sz = new Dimension(824,568); + // final Dimension f_sz = new Dimension(600,400); + // final Dimension glc_sz = new Dimension(500,600); + + frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + + final Component glComp; + final GLAutoDrawable glad; + if(useGLJPanel) { + final GLJPanel glJPanel = new GLJPanel(new GLCapabilities(GLProfile.getDefault())); + Assert.assertNotNull(glJPanel); + glJPanel.addGLEventListener(new GearsES2()); + glComp = glJPanel; + glad = glJPanel; + } else { + final GLCanvas glCanvas = new GLCanvas(new GLCapabilities(GLProfile.getDefault())); + Assert.assertNotNull(glCanvas); + glCanvas.addGLEventListener(new GearsES2()); + if( useContainer ) { + final Container cont = new Container(); + cont.setLayout(new BorderLayout()); + cont.add(glCanvas, BorderLayout.CENTER); + glComp = cont; + } else { + glComp = glCanvas; + } + glad = glCanvas; + } + + final Container contentPane = frame.getContentPane(); + + JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); + splitPane.setResizeWeight(0.5d); + splitPane.setLeftComponent(glComp); + // splitPane.setLeftComponent(new JPanel()); + // splitPane.setLeftComponent(new Canvas()); + splitPane.setRightComponent(new JPanel()); + contentPane.add(splitPane, BorderLayout.CENTER); + + final GLAnimatorControl animator = useGLJPanel ? new FPSAnimator(glad, 60) : new Animator(glad); + animator.start(); + + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setPreferredSize(f_sz); + frame.setSize(f_sz.width+1, f_sz.height+1); // trick to force pack() to work! + frame.pack(); + frame.setVisible(true); + // however, Hw/Lw mixing is still a problem .. + }}); + } catch (Throwable t) { + t.printStackTrace(); + Assume.assumeNoException(t); + } + + animator.setUpdateFPSFrames(60, System.err); + Thread.sleep(durationPerTest); + + animator.stop(); + + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + frame.dispose(); + }}); + } catch (Throwable t) { + t.printStackTrace(); + Assume.assumeNoException(t); + } + } + + @Test + public void test01JSplitPaneWithHwGLCanvasPlain() throws InterruptedException { + GLProfile glp = GLProfile.getGL2ES2(); + GLCapabilities caps = new GLCapabilities(glp); + runTestGL(caps, false, false); + } + + @Test + public void test02JSplitPaneWithHwGLCanvasContainer() throws InterruptedException { + GLProfile glp = GLProfile.getGL2ES2(); + GLCapabilities caps = new GLCapabilities(glp); + runTestGL(caps, false, true); + } + + @Test + public void test03JSplitPaneWithLwGLJPanel() throws InterruptedException { + GLProfile glp = GLProfile.getGL2ES2(); + GLCapabilities caps = new GLCapabilities(glp); + runTestGL(caps, true, false); + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + durationPerTest = MiscUtils.atol(args[++i], durationPerTest); + } + } + /** + BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); + System.err.println("Press enter to continue"); + System.err.println(stdin.readLine()); + */ + System.out.println("durationPerTest: "+durationPerTest); + String tstname = TestBug642JSplitPaneMixHwLw01AWT.class.getName(); + org.junit.runner.JUnitCore.main(tstname); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug664GLCanvasSetVisibleSwingAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug664GLCanvasSetVisibleSwingAWT.java new file mode 100644 index 000000000..2a0bbfeb8 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug664GLCanvasSetVisibleSwingAWT.java @@ -0,0 +1,286 @@ +/** + * Copyright 2013 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.jogl.awt; + +import java.awt.AWTException; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +import jogamp.nativewindow.jawt.JAWTUtil; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestBug664GLCanvasSetVisibleSwingAWT extends UITestCase { + static long durationPerTest = 500; + static boolean shallUseOffscreenFBOLayer = false; + static boolean shallUseOffscreenPBufferLayer = false; + static GLProfile glp; + static int width, height; + static boolean waitForKey = false; + + @BeforeClass + public static void initClass() { + if(GLProfile.isAvailable(GLProfile.GL2ES2)) { + glp = GLProfile.get(GLProfile.GL2ES2); + Assert.assertNotNull(glp); + width = 640; + height = 480; + } else { + setTestSupported(false); + } + } + + @AfterClass + public static void releaseClass() { + } + + protected JPanel create(final JFrame[] top, final int width, final int height, final int num) + throws InterruptedException, InvocationTargetException + { + final JPanel[] jPanel = new JPanel[] { null }; + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + jPanel[0] = new JPanel(); + jPanel[0].setLayout(new BorderLayout()); + + final JFrame jFrame1 = new JFrame("JFrame #"+num); + // jFrame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + jFrame1.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // equivalent to Frame, use windowClosing event! + jFrame1.getContentPane().add(jPanel[0]); + jFrame1.setSize(width, height); + + top[0] = jFrame1; + } } ); + return jPanel[0]; + } + + protected void add(final Container cont, final Component comp, final JFrame jFrame) + throws InterruptedException, InvocationTargetException + { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + cont.add(comp, BorderLayout.CENTER); + jFrame.pack(); + jFrame.validate(); + } } ); + } + + protected void dispose(final GLCanvas glc) + throws InterruptedException, InvocationTargetException + { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + glc.destroy(); + } } ); + } + + protected void setFrameVisible(final JFrame jFrame, final boolean visible) throws InterruptedException, InvocationTargetException { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + jFrame.setVisible(visible); + } } ) ; + } + + protected void setComponentVisible(final Component comp, final boolean visible) throws InterruptedException, InvocationTargetException { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + comp.setVisible(visible); + } } ) ; + } + + protected void dispose(final JFrame jFrame) throws InterruptedException, InvocationTargetException { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + jFrame.dispose(); + } } ) ; + } + + private volatile int frameCount = 0; + + protected void runTestGL(boolean onscreen, GLCapabilities caps) + throws AWTException, InterruptedException, InvocationTargetException + { + + for(int i=0; i<1; i++) { + Animator anim = new Animator(); + final GLCanvas glc = new GLCanvas(caps); + Assert.assertNotNull(glc); + anim.add(glc); + if( !onscreen ) { + glc.setShallUseOffscreenLayer(true); + } + Dimension glc_sz = new Dimension(width, height); + glc.setMinimumSize(glc_sz); + glc.setPreferredSize(glc_sz); + glc.setSize(glc_sz); + glc.addGLEventListener(new GLEventListener() { + @Override + public void init(GLAutoDrawable drawable) {} + @Override + public void dispose(GLAutoDrawable drawable) {} + @Override + public void display(GLAutoDrawable drawable) { + frameCount++; + } + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {} + }); + final GearsES2 gears = new GearsES2(1); + gears.setVerbose(false); + glc.addGLEventListener(gears); + + final JFrame[] top = new JFrame[] { null }; + final Container glcCont = create(top, width, height, i); + add(glcCont, glc, top[0]); + + System.err.println("XXXX Visible Part 1/3"); + frameCount = 0; + setFrameVisible(top[0], true); + Assert.assertTrue("Component didn't become visible", AWTRobotUtil.waitForVisible(glc, true)); + Assert.assertTrue("Component didn't become realized", AWTRobotUtil.waitForRealized(glc, true)); + + anim.setUpdateFPSFrames(60, System.err); + anim.start(); + anim.resetFPSCounter(); + + while( anim.getTotalFPSDuration() < durationPerTest ) { + Thread.sleep(60); + } + + System.err.println("XXXXX Invisible Part 2/3"); + setComponentVisible(glc, false); + Assert.assertTrue("Component didn't become invisible", AWTRobotUtil.waitForVisible(glc, false)); + final int frameCountT0 = frameCount; + anim.resetFPSCounter(); + + while( anim.getTotalFPSDuration() < durationPerTest ) { + Thread.sleep(60); + } + + final int frameCountT1 = frameCount; + System.err.println("GLCanvas invisible frame count: Before "+frameCountT0+", after "+frameCountT1); + Assert.assertTrue("GLCanvas rendered more that 4 times while being invisible, before "+frameCountT0+", after "+frameCountT1, + 4 >= frameCountT1 - frameCountT0); + + System.err.println("XXXX Visible Part 3/3"); + setComponentVisible(glc, true); + Assert.assertTrue("Component didn't become visible", AWTRobotUtil.waitForVisible(glc, true)); + anim.resetFPSCounter(); + + while( anim.getTotalFPSDuration() < durationPerTest ) { + Thread.sleep(60); + } + + System.err.println("GLCanvas isOffscreenLayerSurfaceEnabled: "+glc.isOffscreenLayerSurfaceEnabled()+": "+glc.getChosenGLCapabilities()); + + dispose(top[0]); + } + } + + @Test + public void test01Onscreen() + throws AWTException, InterruptedException, InvocationTargetException + { + if( shallUseOffscreenFBOLayer || shallUseOffscreenPBufferLayer || JAWTUtil.isOffscreenLayerRequired() ) { + System.err.println("Offscreen test requested or platform requires it."); + return; + } + GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); + if(shallUseOffscreenPBufferLayer) { + caps.setPBuffer(true); + caps.setOnscreen(true); // simulate normal behavior .. + } + runTestGL(true, caps); + } + + @Test + public void test02Offscreen() + throws AWTException, InterruptedException, InvocationTargetException + { + if( !JAWTUtil.isOffscreenLayerSupported() ) { + System.err.println("Platform doesn't support offscreen test."); + return; + } + GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); + if(shallUseOffscreenPBufferLayer) { + caps.setPBuffer(true); + caps.setOnscreen(true); // simulate normal behavior .. + } + runTestGL(false, caps); + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + try { + durationPerTest = Long.parseLong(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } else if(args[i].equals("-layeredFBO")) { + shallUseOffscreenFBOLayer = true; + } else if(args[i].equals("-layeredPBuffer")) { + shallUseOffscreenPBufferLayer = true; + } else if(args[i].equals("-wait")) { + waitForKey = true; + } + } + System.err.println("waitForKey "+waitForKey); + + System.err.println("shallUseOffscreenFBOLayer "+shallUseOffscreenFBOLayer); + System.err.println("shallUseOffscreenPBufferLayer "+shallUseOffscreenPBufferLayer); + if(waitForKey) { + UITestCase.waitForKey("Start"); + } + org.junit.runner.JUnitCore.main(TestBug664GLCanvasSetVisibleSwingAWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug675BeansInDesignTimeAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug675BeansInDesignTimeAWT.java new file mode 100644 index 000000000..3363fdd52 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug675BeansInDesignTimeAWT.java @@ -0,0 +1,113 @@ +/** + * Copyright 2013 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.jogl.awt; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Window; +import java.beans.Beans; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +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; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestBug675BeansInDesignTimeAWT extends UITestCase { + static boolean waitForKey = false; + static long durationPerTest = 200; + + @Test + public void test01() throws InterruptedException, InvocationTargetException { + Beans.setDesignTime(true); + + final GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES2()); + final GLCanvas glCanvas = new GLCanvas(caps); + final Dimension preferredGLSize = new Dimension(400,200); + glCanvas.setPreferredSize(preferredGLSize); + glCanvas.setMinimumSize(preferredGLSize); + glCanvas.setSize(preferredGLSize); + + glCanvas.addGLEventListener(new GearsES2()); + + final Window window = new JFrame(this.getSimpleTestName(" - ")); + window.setLayout(new BorderLayout()); + window.add(glCanvas, BorderLayout.CENTER); + + // trigger realization on AWT-EDT, otherwise it won't immediatly .. + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + window.pack(); + window.validate(); + window.setVisible(true); + } + } ); + + // Immediately displayable after issuing initial setVisible(true) on AWT-EDT! + Assert.assertTrue("GLCanvas didn't become displayable", glCanvas.isDisplayable()); + if( !Beans.isDesignTime() ) { + Assert.assertTrue("GLCanvas didn't become realized", glCanvas.isRealized()); + } + + Thread.sleep(durationPerTest); + + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + window.dispose(); + } + } ); + } + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + durationPerTest = MiscUtils.atol(args[++i], durationPerTest); + } else if(args[i].equals("-wait")) { + waitForKey = true; + } + } + if(waitForKey) { + UITestCase.waitForKey("Start"); + } + org.junit.runner.JUnitCore.main(TestBug675BeansInDesignTimeAWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816GLCanvasFrameHoppingB849B889AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816GLCanvasFrameHoppingB849B889AWT.java new file mode 100644 index 000000000..51d00a5a1 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816GLCanvasFrameHoppingB849B889AWT.java @@ -0,0 +1,262 @@ +/** + * Copyright 2013 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.jogl.awt; + +import java.awt.BorderLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +import org.junit.Assert; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Moving GLCanvas between 2 AWT JFrame + * <p> + * Validates bugs: + * <ul> + * <li>Bug 816: OSX CALayer Positioning Bug</li> + * <li>Bug 729: OSX CALayer shall honor the Component's visibility state</li> + * <li>Bug 849: AWT GLAutoDrawables (JAWTWindow) shall honor it's parent visibility state</li> + * <li>Bug 878: JAWTWindow's HierarchyListener doesn't set component visible (again) on 'addNotify(..)' - GLCanvas in JtabbedPane disappear</li> + * <li>Bug 889: GLCanvas disappear when moves between two JFrame</li> + * </ul> + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestBug816GLCanvasFrameHoppingB849B889AWT extends UITestCase { + static long durationPerTest = 500*4; // ms + static boolean manual = false; + + @Test + public void test01AllVisible() throws InterruptedException, InvocationTargetException { + test(false); + } + + @Test + public void test02VisibleWithCanvas() throws InterruptedException, InvocationTargetException { + test(true); + } + + private void test(final boolean onlyVisibleWithCanvas) throws InterruptedException, InvocationTargetException { + final JFrame frame1 = new JFrame("Bug889 #1"); + final JPanel panel1 = new javax.swing.JPanel(); + panel1.setLayout(new BorderLayout()); + panel1.setSize(new java.awt.Dimension(640, 480)); + frame1.setContentPane(panel1); + frame1.setSize(640, 480); + frame1.setLocation(64, 64); + + final JFrame frame2 = new JFrame("Bug889 #2"); + final JPanel panel2 = new javax.swing.JPanel(); + panel2.setLayout(new BorderLayout()); + panel2.setSize(new java.awt.Dimension(640, 480)); + frame2.setContentPane(panel2); + frame2.setSize(640, 480); + frame2.setLocation(800, 64); + + GLProfile profile = GLProfile.get(GLProfile.GL2ES2); + GLCapabilities glCapabilities = new GLCapabilities(profile); + final GLCanvas glCanvas = new GLCanvas(glCapabilities); + glCanvas.setSize(new java.awt.Dimension(640, 480)); + glCanvas.addGLEventListener(new GearsES2(1)); + panel1.add(glCanvas, BorderLayout.CENTER); + + JButton bMoveP1toP2 = new JButton("Move to Panel2"); + bMoveP1toP2.addActionListener(new ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent evt) { + System.err.println("XXXX Move P1 -> P2 - START"); + dumpGLCanvasStats(glCanvas); + panel2.add(glCanvas, BorderLayout.CENTER); + if( onlyVisibleWithCanvas ) { + frame1.setVisible(false); + frame2.setVisible(true); + frame2.toFront(); + } else { + frame1.validate(); + frame2.validate(); + } + dumpGLCanvasStats(glCanvas); + System.err.println("XXXX Move P1 -> P2 - END"); + } + }); + panel1.add(bMoveP1toP2, BorderLayout.NORTH); + + JButton bMoveP2toP1 = new JButton("Move to Panel1"); + bMoveP2toP1.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + System.err.println("XXXX Move P2 -> P1 - START"); + dumpGLCanvasStats(glCanvas); + panel1.add(glCanvas, BorderLayout.CENTER); + if( onlyVisibleWithCanvas ) { + frame2.setVisible(false); + frame1.setVisible(true); + frame1.toFront(); + } else { + frame2.validate(); + frame1.validate(); + } + dumpGLCanvasStats(glCanvas); + System.err.println("XXXX Move P2 -> P1 - END"); + } + }); + panel2.add(bMoveP2toP1, BorderLayout.NORTH); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + // frame1.pack(); + System.err.println("XXX SetVisible ON XXX GLCanvas on Panel1("+id(panel1)+")"); + if( onlyVisibleWithCanvas ) { + frame1.setVisible(true); + } else { + frame1.setVisible(true); + frame2.setVisible(true); + } + }}); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame1, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas, true)); + dumpGLCanvasStats(glCanvas); + + if(manual) { + for(long w=durationPerTest; w>0; w-=100) { + Thread.sleep(100); + } + } else { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + System.err.println("XXXX Add GLCanvas Panel1("+id(panel1)+" -> Panel2("+id(panel2)+") START"); + dumpGLCanvasStats(glCanvas); + panel2.add(glCanvas, BorderLayout.CENTER); + if( onlyVisibleWithCanvas ) { + frame1.setVisible(false); + frame2.setVisible(true); + frame2.toFront(); + } else { + frame1.validate(); + frame2.validate(); + } + dumpGLCanvasStats(glCanvas); + }}); + Thread.sleep(durationPerTest/4); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + System.err.println("XXXX Add GLCanvas Panel2("+id(panel2)+") -> Panel1("+id(panel1)+" START"); + dumpGLCanvasStats(glCanvas); + panel1.add(glCanvas, BorderLayout.CENTER); + if( onlyVisibleWithCanvas ) { + frame2.setVisible(false); + frame1.setVisible(true); + frame1.toFront(); + } else { + frame2.validate(); + frame1.validate(); + } + dumpGLCanvasStats(glCanvas); + }}); + Thread.sleep(durationPerTest/4); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + System.err.println("XXXX Add GLCanvas Panel1("+id(panel1)+" -> Panel2("+id(panel2)+") START"); + dumpGLCanvasStats(glCanvas); + panel2.add(glCanvas, BorderLayout.CENTER); + if( onlyVisibleWithCanvas ) { + frame1.setVisible(false); + frame2.setVisible(true); + frame2.toFront(); + } else { + frame1.validate(); + frame2.validate(); + } + dumpGLCanvasStats(glCanvas); + }}); + Thread.sleep(durationPerTest/4); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + System.err.println("XXXX Add GLCanvas Panel2("+id(panel2)+") -> Panel1("+id(panel1)+" START"); + dumpGLCanvasStats(glCanvas); + panel1.add(glCanvas, BorderLayout.CENTER); + if( onlyVisibleWithCanvas ) { + frame2.setVisible(false); + frame1.setVisible(true); + frame1.toFront(); + } else { + frame2.validate(); + frame1.validate(); + } + dumpGLCanvasStats(glCanvas); + }}); + Thread.sleep(durationPerTest/4); + } + + SwingUtilities.invokeLater(new Runnable() { + public void run() { + System.err.println("XXX SetVisible OFF XXX"); + frame1.dispose(); + frame2.dispose(); + } }); + } + + private static String id(Object obj) { return "0x"+Integer.toHexString(obj.hashCode()); } + + static void dumpGLCanvasStats(GLCanvas glCanvas) { + System.err.println("XXXX GLCanvas: comp "+glCanvas+", visible "+glCanvas.isVisible()+", showing "+glCanvas.isShowing()+ + ", displayable "+glCanvas.isDisplayable()+", "+glCanvas.getWidth()+"x"+glCanvas.getHeight()); + } + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + durationPerTest = MiscUtils.atoi(args[++i], (int)durationPerTest); + } else if(args[i].equals("-manual")) { + manual = true; + } + } + org.junit.runner.JUnitCore.main(TestBug816GLCanvasFrameHoppingB849B889AWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816JTabbedPanelVisibilityB849B878AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816JTabbedPanelVisibilityB849B878AWT.java new file mode 100644 index 000000000..84af232d4 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816JTabbedPanelVisibilityB849B878AWT.java @@ -0,0 +1,194 @@ +/** + * Copyright 2013 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.jogl.awt; + +import java.awt.BorderLayout; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTabbedPane; +import javax.swing.SwingUtilities; + +import org.junit.Assert; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * AWT JFrame w/ JTabbedPanel, Moving GLCanvas between it's tabs while selecting. + * <p> + * Validates bugs: + * <ul> + * <li>Bug 816: OSX CALayer Positioning Bug</li> + * <li>Bug 729: OSX CALayer shall honor the Component's visibility state</li> + * <li>Bug 849: AWT GLAutoDrawables (JAWTWindow) shall honor it's parent visibility state</li> + * <li>Bug 878: JAWTWindow's HierarchyListener doesn't set component visible (again) on 'addNotify(..)' - GLCanvas in JtabbedPane disappear</li> + * </ul> + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestBug816JTabbedPanelVisibilityB849B878AWT extends UITestCase { + + static long durationPerTest = 500*6; // ms + static boolean manual = false; + + @Test + public void test() throws InterruptedException, InvocationTargetException { + final JFrame frame = new JFrame("TestBug816OSXCALayerPos03dBug878AWT"); + + final JPanel panel1 = new javax.swing.JPanel(); + final JPanel panel2 = new javax.swing.JPanel(); + final JPanel panel3 = new javax.swing.JPanel(); + + panel1.setLayout(new BorderLayout()); + panel2.setLayout(new BorderLayout()); + + GLProfile profile = GLProfile.get(GLProfile.GL2ES2); + GLCapabilities glCapabilities = new GLCapabilities(profile); + final GLCanvas glCanvas = new GLCanvas(glCapabilities); + glCanvas.setSize(new java.awt.Dimension(640, 480)); + glCanvas.addGLEventListener(new GearsES2(1)); + panel1.add(glCanvas, BorderLayout.CENTER); + panel3.add(new JLabel("A label to cover the canvas"), BorderLayout.CENTER); + + final JTabbedPane tabbedPanel = new JTabbedPane(); + tabbedPanel.addTab("tab1", panel1); // glcanvas + tabbedPanel.addTab("tab2", panel2); // glcanvas + tabbedPanel.addTab("tab3", panel3); // text + + tabbedPanel.addChangeListener(new javax.swing.event.ChangeListener() { + @Override + public void stateChanged(javax.swing.event.ChangeEvent evt) { + if (tabbedPanel.getSelectedIndex() == 0) { + System.err.println("XXXX Add GLCanvas Panel2("+id(panel2)+" -> Panel1("+id(panel1)+") START"); + dumpGLCanvasStats(glCanvas); + panel1.add(glCanvas, BorderLayout.CENTER); + dumpGLCanvasStats(glCanvas); + } else if (tabbedPanel.getSelectedIndex() == 1) { + System.err.println("XXXX Add GLCanvas Panel1("+id(panel1)+" -> Panel2("+id(panel2)+") START"); + dumpGLCanvasStats(glCanvas); + panel2.add(glCanvas, BorderLayout.CENTER); + dumpGLCanvasStats(glCanvas); + } else { + System.err.println("XXXX NOP"); + dumpGLCanvasStats(glCanvas); + } + } + }); + + frame.setContentPane(tabbedPanel); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.pack(); + System.err.println("XXX SetVisible ON XXX GLCanvas on Panel1("+id(panel1)+")"); + frame.setVisible(true); + }}); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas, true)); + dumpGLCanvasStats(glCanvas); + + if(manual) { + for(long w=durationPerTest; w>0; w-=100) { + Thread.sleep(100); + } + } else { + Thread.sleep(durationPerTest/6); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + System.err.println("XXXX Panel1("+id(panel1)+" -> Panel2("+id(panel2)+") START"); + tabbedPanel.setSelectedIndex(1); + }}); + + Thread.sleep(durationPerTest/6); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + System.err.println("XXXX Panel2("+id(panel2)+") -> Panel3("+id(panel3)+" START"); + tabbedPanel.setSelectedIndex(2); + }}); + + Thread.sleep(durationPerTest/6); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + System.err.println("XXXX Panel3("+id(panel3)+") -> Panel1("+id(panel1)+" START"); + tabbedPanel.setSelectedIndex(0); + }}); + + // one loop done + + Thread.sleep(durationPerTest/6); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + System.err.println("XXXX Panel1("+id(panel1)+" -> Panel2("+id(panel2)+") START"); + tabbedPanel.setSelectedIndex(1); + }}); + + Thread.sleep(durationPerTest/6); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + System.err.println("XXXX Panel2("+id(panel2)+") -> Panel1("+id(panel1)+" START"); + tabbedPanel.setSelectedIndex(0); + }}); + + Thread.sleep(durationPerTest/6); + } + + SwingUtilities.invokeLater(new Runnable() { + public void run() { + System.err.println("XXX SetVisible OFF XXX"); + frame.dispose(); + } }); + } + + private static String id(Object obj) { return "0x"+Integer.toHexString(obj.hashCode()); } + + static void dumpGLCanvasStats(GLCanvas glCanvas) { + System.err.println("XXXX GLCanvas: comp "+glCanvas+", visible "+glCanvas.isVisible()+", showing "+glCanvas.isShowing()+ + ", displayable "+glCanvas.isDisplayable()+", "+glCanvas.getWidth()+"x"+glCanvas.getHeight()); + } + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + durationPerTest = MiscUtils.atoi(args[++i], (int)durationPerTest); + } else if(args[i].equals("-manual")) { + manual = true; + } + } + org.junit.runner.JUnitCore.main(TestBug816JTabbedPanelVisibilityB849B878AWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos01AWT.java new file mode 100644 index 000000000..ace578e7a --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos01AWT.java @@ -0,0 +1,476 @@ +/** + * Copyright 2013 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.jogl.awt; + +import javax.media.opengl.*; + +import com.jogamp.opengl.util.Animator; + +import javax.media.opengl.awt.GLCanvas; +import javax.swing.BoundedRangeModel; +import javax.swing.BoxLayout; +import javax.swing.JFrame; +import javax.swing.JScrollBar; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; +import javax.swing.ScrollPaneConstants; + +import com.jogamp.common.util.awt.AWTEDTExecutor; +import com.jogamp.newt.event.awt.AWTWindowAdapter; +import com.jogamp.newt.event.TraceWindowAdapter; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +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.BorderLayout; +import java.awt.Button; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.GridLayout; +import java.lang.reflect.InvocationTargetException; + +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +/** + * Bug 816: OSX CALayer Positioning Bug. + * <p> + * Diff. OSX CALayer positioning w/ java6, [7uxx..7u40[, and >= 7u40 + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestBug816OSXCALayerPos01AWT extends UITestCase { + public enum FrameLayout { None, Flow, DoubleBorderCenterSurrounded, Box, Split }; + + static long duration = 1600; // ms + static final int width = 640, height = 480; + + static boolean forceES2 = false; + static boolean forceGL3 = false; + static int swapInterval = 1; + static java.awt.Dimension rwsize = new Dimension(800, 600); + + static void setComponentSize(final Frame frame, final Component comp1, final java.awt.Dimension new_sz1, final Component comp2, final java.awt.Dimension new_sz2) { + try { + AWTEDTExecutor.singleton.invoke(true /* wait */, new Runnable() { + public void run() { + comp1.setMinimumSize(new_sz1); + comp1.setPreferredSize(new_sz1); + comp1.setSize(new_sz1); + if( null != comp2 ) { + comp2.setMinimumSize(new_sz2); + comp2.setPreferredSize(new_sz2); + comp2.setSize(new_sz2); + } + if( null != frame ) { + frame.pack(); + } + } } ); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + } + static void setFrameSize(final Frame frame, final boolean frameLayout, final java.awt.Dimension new_sz) { + try { + AWTEDTExecutor.singleton.invoke(true /* wait */, new Runnable() { + public void run() { + frame.setSize(new_sz); + if( frameLayout ) { + frame.validate(); + } + } } ); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + } + + protected void runTestGL(GLCapabilities caps, FrameLayout frameLayout, final boolean twoCanvas, final boolean resizeByComp) throws InterruptedException, InvocationTargetException { + final JFrame frame = new JFrame("Bug816: "+this.getTestMethodName()); + Assert.assertNotNull(frame); + final Container framePane = frame.getContentPane(); + + final GLCanvas glCanvas1 = new GLCanvas(caps); + Assert.assertNotNull(glCanvas1); + final GLCanvas glCanvas2; + if( twoCanvas ) { + glCanvas2 = new GLCanvas(caps); + Assert.assertNotNull(glCanvas2); + } else { + glCanvas2 = null; + } + + final Dimension glcDim = new Dimension(width/2, height); + final Dimension frameDim = new Dimension(twoCanvas ? width + 64: width/2 + 64, height + 64); + + setComponentSize(null, glCanvas1, glcDim, glCanvas2, glcDim); + + switch( frameLayout) { + case None: { + framePane.add(glCanvas1); + } + break; + case Flow: { + final Container c = new Container(); + c.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); + c.add(glCanvas1); + if( twoCanvas ) { + c.add(glCanvas2); + } + framePane.add(c); + } + break; + case DoubleBorderCenterSurrounded: { + final Container c = new Container(); + c.setLayout(new BorderLayout()); + c.add(new Button("north"), BorderLayout.NORTH); + c.add(new Button("south"), BorderLayout.SOUTH); + c.add(new Button("east"), BorderLayout.EAST); + c.add(new Button("west"), BorderLayout.WEST); + if( twoCanvas ) { + final Container c2 = new Container(); + c2.setLayout(new GridLayout(1, 2)); + c2.add(glCanvas1); + c2.add(glCanvas2); + c.add(c2, BorderLayout.CENTER); + } else { + c.add(glCanvas1, BorderLayout.CENTER); + } + framePane.setLayout(new BorderLayout()); + framePane.add(new Button("NORTH"), BorderLayout.NORTH); + framePane.add(new Button("SOUTH"), BorderLayout.SOUTH); + framePane.add(new Button("EAST"), BorderLayout.EAST); + framePane.add(new Button("WEST"), BorderLayout.WEST); + framePane.add(c, BorderLayout.CENTER); + } + break; + case Box: { + final Container c = new Container(); + c.setLayout(new BoxLayout(c, BoxLayout.X_AXIS)); + c.add(glCanvas1); + if( twoCanvas ) { + c.add(glCanvas2); + } + framePane.add(c); + } + break; + case Split: { + Dimension sbDim = new Dimension(16, 16); + JScrollPane vsp = new JScrollPane(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + { + JScrollBar vsb = vsp.getVerticalScrollBar(); + vsb.setPreferredSize(sbDim); + BoundedRangeModel model = vsb.getModel(); + model.setMinimum(0); + model.setMaximum(100); + model.setValue(50); + model.setExtent(1); + vsb.setEnabled(true); + } + JScrollPane hsp = new JScrollPane(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); + { + JScrollBar hsb = hsp.getHorizontalScrollBar(); + hsb.setPreferredSize(sbDim); + BoundedRangeModel model = hsb.getModel(); + model.setMinimum(0); + model.setMaximum(100); + model.setValue(50); + model.setExtent(1); + hsb.setEnabled(true); + } + JSplitPane horizontalSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, + twoCanvas ? glCanvas2 : vsp, glCanvas1 ); + horizontalSplitPane.setResizeWeight(0.5); + JSplitPane verticalSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, + true, horizontalSplitPane, hsp); + verticalSplitPane.setResizeWeight(0.5); + framePane.add(verticalSplitPane); + } + break; + } + final GearsES2 demo1 = new GearsES2(swapInterval); + glCanvas1.addGLEventListener(demo1); + if( twoCanvas ) { + final RedSquareES2 demo2 = new RedSquareES2(swapInterval); + glCanvas2.addGLEventListener(demo2); + } + + final Animator animator = new Animator(); + animator.add(glCanvas1); + if( twoCanvas ) { + animator.add(glCanvas2); + } + QuitAdapter quitAdapter = new QuitAdapter(); + + new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter)).addTo(frame); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + if( resizeByComp ) { + frame.pack(); + } else { + setFrameSize(frame, true, frameDim); + } + frame.setVisible(true); + }}); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas1, true)); + if( twoCanvas ) { + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas2, true)); + } + + animator.start(); + Assert.assertTrue(animator.isStarted()); + Assert.assertTrue(animator.isAnimating()); + + System.err.println("canvas1 pos/siz: "+glCanvas1.getX()+"/"+glCanvas1.getY()+" "+glCanvas1.getWidth()+"x"+glCanvas1.getHeight()); + if( twoCanvas ) { + System.err.println("canvas2 pos/siz: "+glCanvas2.getX()+"/"+glCanvas2.getY()+" "+glCanvas2.getWidth()+"x"+glCanvas2.getHeight()); + } + + Thread.sleep(Math.max(1000, duration/2)); + if( null != rwsize ) { + final Dimension compRSizeHalf = new Dimension(rwsize.width/2, rwsize.height); + final Dimension frameRSizeHalf = new Dimension(twoCanvas ? rwsize.width + 64: rwsize.width/2 + 64, rwsize.height + 64); + if( resizeByComp ) { + setComponentSize(frame, glCanvas1, compRSizeHalf, glCanvas2, compRSizeHalf); + } else { + setFrameSize(frame, true, frameRSizeHalf); + } + System.err.println("resize canvas1 pos/siz: "+glCanvas1.getX()+"/"+glCanvas1.getY()+" "+glCanvas1.getWidth()+"x"+glCanvas1.getHeight()); + if( twoCanvas ) { + System.err.println("resize canvas2 pos/siz: "+glCanvas2.getX()+"/"+glCanvas2.getY()+" "+glCanvas2.getWidth()+"x"+glCanvas2.getHeight()); + } + } + + final long t0 = System.currentTimeMillis(); + long t1 = t0; + while(!quitAdapter.shouldQuit() && t1 - t0 < duration) { + Thread.sleep(100); + t1 = System.currentTimeMillis(); + } + + Assert.assertNotNull(frame); + Assert.assertNotNull(glCanvas1); + if( twoCanvas ) { + Assert.assertNotNull(glCanvas2); + } else { + Assert.assertNull(glCanvas2); + } + + Assert.assertNotNull(animator); + animator.stop(); + Assert.assertFalse(animator.isAnimating()); + Assert.assertFalse(animator.isStarted()); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + }}); + Assert.assertEquals(false, frame.isVisible()); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.remove(glCanvas1); + if( twoCanvas ) { + frame.remove(glCanvas2); + } + frame.dispose(); + }}); + } + + static GLProfile getGLP() { + return GLProfile.getMaxProgrammableCore(true); + } + + @Test + public void test00_Compo_None_One() throws InterruptedException, InvocationTargetException { + if( testNum != -1 && testNum != 0 ) { return ; } + final GLCapabilities caps = new GLCapabilities(getGLP()); + runTestGL(caps, FrameLayout.None, false /* twoCanvas */, true /* resizeByComp */); + } + + @Test + public void test01_Compo_Flow_One() throws InterruptedException, InvocationTargetException { + if( testNum != -1 && testNum != 1 ) { return ; } + final GLCapabilities caps = new GLCapabilities(getGLP()); + runTestGL(caps, FrameLayout.Flow, false /* twoCanvas */, true /* resizeByComp */); + } + + @Test + public void test02_Compo_DblBrd_One() throws InterruptedException, InvocationTargetException { + if( testNum != -1 && testNum != 2 ) { return ; } + final GLCapabilities caps = new GLCapabilities(getGLP()); + runTestGL(caps, FrameLayout.DoubleBorderCenterSurrounded, false /* twoCanvas */, true /* resizeByComp */); + } + + @Test + public void test03_Compo_Box_One() throws InterruptedException, InvocationTargetException { + if( testNum != -1 && testNum != 3 ) { return ; } + final GLCapabilities caps = new GLCapabilities(getGLP()); + runTestGL(caps, FrameLayout.Box, false /* twoCanvas */, true /* resizeByComp */); + } + + @Test + public void test04_Compo_Split_One() throws InterruptedException, InvocationTargetException { + if( testNum != -1 && testNum != 4 ) { return ; } + final GLCapabilities caps = new GLCapabilities(getGLP()); + runTestGL(caps, FrameLayout.Split, false /* twoCanvas */, true /* resizeByComp */); + } + + @Test + public void test05_Compo_Flow_Two() throws InterruptedException, InvocationTargetException { + if( testNum != -1 && testNum != 5 ) { return ; } + final GLCapabilities caps = new GLCapabilities(getGLP()); + runTestGL(caps, FrameLayout.Flow, true/* twoCanvas */, true /* resizeByComp */); + } + + @Test + public void test06_Compo_DblBrd_Two() throws InterruptedException, InvocationTargetException { + if( testNum != -1 && testNum != 6 ) { return ; } + final GLCapabilities caps = new GLCapabilities(getGLP()); + runTestGL(caps, FrameLayout.DoubleBorderCenterSurrounded, true/* twoCanvas */, true /* resizeByComp */); + } + + @Test + public void test07_Compo_Box_Two() throws InterruptedException, InvocationTargetException { + if( testNum != -1 && testNum != 7 ) { return ; } + final GLCapabilities caps = new GLCapabilities(getGLP()); + runTestGL(caps, FrameLayout.Box, true/* twoCanvas */, true /* resizeByComp */); + } + + @Test + public void test08_Compo_Split_Two() throws InterruptedException, InvocationTargetException { + if( testNum != -1 && testNum != 8 ) { return ; } + final GLCapabilities caps = new GLCapabilities(getGLP()); + runTestGL(caps, FrameLayout.Split, true/* twoCanvas */, true /* resizeByComp */); + } + + @Test + public void test10_Frame_None_One() throws InterruptedException, InvocationTargetException { + if( testNum != -1 && testNum != 10 ) { return ; } + final GLCapabilities caps = new GLCapabilities(getGLP()); + runTestGL(caps, FrameLayout.None, false /* twoCanvas */, false /* resizeByComp */); + } + + @Test + public void test11_Frame_Flow_One() throws InterruptedException, InvocationTargetException { + if( testNum != -1 && testNum != 11 ) { return ; } + final GLCapabilities caps = new GLCapabilities(getGLP()); + runTestGL(caps, FrameLayout.Flow, false /* twoCanvas */, false /* resizeByComp */); + } + + @Test + public void test12_Frame_DblBrd_One() throws InterruptedException, InvocationTargetException { + if( testNum != -1 && testNum != 12 ) { return ; } + final GLCapabilities caps = new GLCapabilities(getGLP()); + runTestGL(caps, FrameLayout.DoubleBorderCenterSurrounded, false /* twoCanvas */, false /* resizeByComp */); + } + + @Test + public void test13_Frame_Box_One() throws InterruptedException, InvocationTargetException { + if( testNum != -1 && testNum != 13 ) { return ; } + final GLCapabilities caps = new GLCapabilities(getGLP()); + runTestGL(caps, FrameLayout.Box, false /* twoCanvas */, false /* resizeByComp */); + } + + @Test + public void test14_Frame_Split_One() throws InterruptedException, InvocationTargetException { + if( testNum != -1 && testNum != 14) { return ; } + final GLCapabilities caps = new GLCapabilities(getGLP()); + runTestGL(caps, FrameLayout.Split, false /* twoCanvas */, false /* resizeByComp */); + } + + @Test + public void test15_Frame_Flow_Two() throws InterruptedException, InvocationTargetException { + if( testNum != -1 && testNum != 15 ) { return ; } + final GLCapabilities caps = new GLCapabilities(getGLP()); + runTestGL(caps, FrameLayout.Flow, true/* twoCanvas */, false /* resizeByComp */); + } + + @Test + public void test16_Frame_DblBrd_Two() throws InterruptedException, InvocationTargetException { + if( testNum != -1 && testNum != 16 ) { return ; } + final GLCapabilities caps = new GLCapabilities(getGLP()); + runTestGL(caps, FrameLayout.DoubleBorderCenterSurrounded, true/* twoCanvas */, false /* resizeByComp */); + } + + @Test + public void test17_Frame_Box_Two() throws InterruptedException, InvocationTargetException { + if( testNum != -1 && testNum != 17 ) { return ; } + final GLCapabilities caps = new GLCapabilities(getGLP()); + runTestGL(caps, FrameLayout.Box, true/* twoCanvas */, false /* resizeByComp */); + } + + @Test + public void test18_Frame_Split_Two() throws InterruptedException, InvocationTargetException { + if( testNum != -1 && testNum != 18 ) { return ; } + final GLCapabilities caps = new GLCapabilities(getGLP()); + runTestGL(caps, FrameLayout.Split, true/* twoCanvas */, false /* resizeByComp */); + } + + static int testNum = -1; + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-test")) { + i++; + testNum = MiscUtils.atoi(args[i], 0); + } else if(args[i].equals("-noresize")) { + rwsize = null; + } else if(args[i].equals("-es2")) { + forceES2 = true; + } else if(args[i].equals("-gl3")) { + forceGL3 = true; + } else if(args[i].equals("-vsync")) { + i++; + swapInterval = MiscUtils.atoi(args[i], swapInterval); + } + } + + System.err.println("resize "+rwsize); + System.err.println("forceES2 "+forceES2); + System.err.println("forceGL3 "+forceGL3); + System.err.println("swapInterval "+swapInterval); + + org.junit.runner.JUnitCore.main(TestBug816OSXCALayerPos01AWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos02AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos02AWT.java new file mode 100644 index 000000000..df24fc6e0 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos02AWT.java @@ -0,0 +1,152 @@ +/** + * Copyright 2013 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.jogl.awt; + +import javax.media.opengl.*; + +import com.jogamp.opengl.util.Animator; + +import javax.media.opengl.awt.GLCanvas; +import javax.swing.JFrame; +import javax.swing.JRootPane; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; + +import com.jogamp.newt.event.awt.AWTWindowAdapter; +import com.jogamp.newt.event.TraceWindowAdapter; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +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.lang.reflect.InvocationTargetException; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +/** + * Bug 816: OSX CALayer Positioning Bug - Swing JFrame w/ 2 JRootPanes and 2 JSplitPanes + * <p> + * Diff. OSX CALayer positioning w/ java6, [7uxx..7u40[, and >= 7u40 + * </p> + * <p> + * See also {@link com.jogamp.opengl.test.junit.jogl.demos.es2.awt.Bug816AppletOSXCALayerPos03b} + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestBug816OSXCALayerPos02AWT extends UITestCase { + static long duration = 1600; // ms + static int width=640, height=480; + + @Test + public void test() throws InterruptedException, InvocationTargetException { + final GLCapabilities caps = new GLCapabilities(getGLP()); + + final JFrame frame = new JFrame("TestBug816OSXCALayerPos02AWT"); + Assert.assertNotNull(frame); + + final GLCanvas glCanvas1 = new GLCanvas(caps); + Assert.assertNotNull(glCanvas1); + glCanvas1.addGLEventListener(new GearsES2(1)); + + final Animator animator = new Animator(); + animator.add(glCanvas1); + QuitAdapter quitAdapter = new QuitAdapter(); + + new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter)).addTo(frame); + + // Build a GUI where the canvas 3D is located at top right of the frame + // and can be resized with split panes dividers + JSplitPane verticalSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, + true, new JScrollPane(), glCanvas1); + verticalSplitPane.setResizeWeight(0.5); + JSplitPane horizontalSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, + true, new JScrollPane(), verticalSplitPane); + horizontalSplitPane.setResizeWeight(0.5); + JRootPane intermediateRootPane = new JRootPane(); + intermediateRootPane.setContentPane(horizontalSplitPane); + frame.add(intermediateRootPane); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setSize(width, height); + frame.setVisible(true); + }}); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas1, true)); + + animator.start(); + Assert.assertTrue(animator.isStarted()); + Assert.assertTrue(animator.isAnimating()); + + final long t0 = System.currentTimeMillis(); + long t1 = t0; + while(!quitAdapter.shouldQuit() && t1 - t0 < duration) { + Thread.sleep(100); + t1 = System.currentTimeMillis(); + } + + Assert.assertNotNull(frame); + Assert.assertNotNull(glCanvas1); + + Assert.assertNotNull(animator); + animator.stop(); + Assert.assertFalse(animator.isAnimating()); + Assert.assertFalse(animator.isStarted()); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + }}); + Assert.assertEquals(false, frame.isVisible()); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.remove(glCanvas1); + frame.dispose(); + }}); + } + + static GLProfile getGLP() { + return GLProfile.getMaxProgrammableCore(true); + } + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } + } + + org.junit.runner.JUnitCore.main(TestBug816OSXCALayerPos02AWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos03aB729AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos03aB729AWT.java new file mode 100644 index 000000000..29dc9a190 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos03aB729AWT.java @@ -0,0 +1,166 @@ +/** + * Copyright 2013 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.jogl.awt; + +import java.awt.BorderLayout; +import java.awt.Checkbox; +import java.awt.Frame; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; + +import org.junit.Assert; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.event.TraceWindowAdapter; +import com.jogamp.newt.event.awt.AWTWindowAdapter; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; + +/** + * AWT Frame BorderLayout w/ Checkbox North, GLCanvas Center. + * <p> + * Checkbox toggles GLCanvas visibility state. + * </p> + * <p> + * Validates bugs: + * <ul> + * <li>Bug 816: OSX CALayer Positioning Bug</li> + * <li>Bug 729: OSX CALayer shall honor the Component's visibility state</li> + * </ul> + * </p> + * <p> + * Diff. OSX CALayer positioning w/ java6, [7uxx..7u40[, and >= 7u40 + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestBug816OSXCALayerPos03aB729AWT extends UITestCase { + static long duration = 1600; // ms + static int width=640, height=480; + + @Test + public void test() throws InterruptedException, InvocationTargetException { + final GLCapabilities caps = new GLCapabilities(getGLP()); + + final Frame frame = new Frame("TestBug816OSXCALayerPos03aAWT"); + Assert.assertNotNull(frame); + + final GLCanvas glCanvas1 = new GLCanvas(caps); + Assert.assertNotNull(glCanvas1); + glCanvas1.addGLEventListener(new GearsES2(1)); + + final Animator animator = new Animator(); + animator.add(glCanvas1); + QuitAdapter quitAdapter = new QuitAdapter(); + + new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter)).addTo(frame); + + // Create a check box that hides / shows canvas + final Checkbox checkbox = new Checkbox("Visible canvas", true); + checkbox.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent ev) { + final boolean visible = checkbox.getState(); + System.err.println("XXXX Canvas setVisible "+visible); + glCanvas1.setVisible(visible); + System.err.println("XXXX Canvas visible: "+glCanvas1.isVisible()); + if( glCanvas1.isVisible() ) { + frame.validate(); // take care of resized frame while hidden + } + } + }); + + // Build a GUI that displays canvas and check box + frame.setLayout(new BorderLayout()); + frame.add(glCanvas1, BorderLayout.CENTER); + frame.add(checkbox, BorderLayout.NORTH); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setSize(width, height); + frame.setVisible(true); + }}); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas1, true)); + + animator.start(); + Assert.assertTrue(animator.isStarted()); + Assert.assertTrue(animator.isAnimating()); + + final long t0 = System.currentTimeMillis(); + long t1 = t0; + while(!quitAdapter.shouldQuit() && t1 - t0 < duration) { + Thread.sleep(100); + t1 = System.currentTimeMillis(); + } + + Assert.assertNotNull(frame); + Assert.assertNotNull(glCanvas1); + + Assert.assertNotNull(animator); + animator.stop(); + Assert.assertFalse(animator.isAnimating()); + Assert.assertFalse(animator.isStarted()); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + }}); + Assert.assertEquals(false, frame.isVisible()); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.remove(glCanvas1); + frame.dispose(); + }}); + } + + static GLProfile getGLP() { + return GLProfile.getMaxProgrammableCore(true); + } + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } + } + + org.junit.runner.JUnitCore.main(TestBug816OSXCALayerPos03aB729AWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos03bB849AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos03bB849AWT.java new file mode 100644 index 000000000..3e60c8b47 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos03bB849AWT.java @@ -0,0 +1,172 @@ +/** + * Copyright 2013 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.jogl.awt; + +import java.awt.BorderLayout; +import java.awt.Checkbox; +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.Panel; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; + +import org.junit.Assert; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.event.TraceWindowAdapter; +import com.jogamp.newt.event.awt.AWTWindowAdapter; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; + +/** + * AWT Frame BorderLayout w/ Checkbox North, Panel.GLCanvas Center. + * <p> + * Checkbox toggles GLCanvas's parent panel's visibility state. + * </p> + * <p> + * Validates bugs: + * <ul> + * <li>Bug 816: OSX CALayer Positioning Bug</li> + * <li>Bug 729: OSX CALayer shall honor the Component's visibility state</li> + * <li>Bug 849: AWT GLAutoDrawables (JAWTWindow) shall honor it's parent visibility state</li> + * </ul> + * </p> + * <p> + * Diff. OSX CALayer positioning w/ java6, [7uxx..7u40[, and >= 7u40 + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestBug816OSXCALayerPos03bB849AWT extends UITestCase { + static long duration = 1600; // ms + static int width=640, height=480; + + @Test + public void test() throws InterruptedException, InvocationTargetException { + final GLCapabilities caps = new GLCapabilities(getGLP()); + + final Frame frame = new Frame("TestBug816OSXCALayerPos03bAWT"); + Assert.assertNotNull(frame); + + final GLCanvas glCanvas1 = new GLCanvas(caps); + Assert.assertNotNull(glCanvas1); + glCanvas1.addGLEventListener(new GearsES2(1)); + // Put it in a panel + final Panel panel = new Panel(new GridLayout(1, 1)); + panel.add(glCanvas1); + + final Animator animator = new Animator(); + animator.add(glCanvas1); + QuitAdapter quitAdapter = new QuitAdapter(); + + new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter)).addTo(frame); + + // Create a check box that hides / shows canvas + final Checkbox checkbox = new Checkbox("Visible canvas", true); + checkbox.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent ev) { + final boolean visible = checkbox.getState(); + System.err.println("XXXX Panel setVisible "+visible); + panel.setVisible(visible); + System.err.println("XXXX Visible: [panel "+panel.isVisible()+", canvas "+glCanvas1.isVisible()+"]; Displayable: [panel "+panel.isDisplayable()+", canvas "+glCanvas1.isDisplayable()+"]"); + if( panel.isVisible() ) { + frame.validate(); // take care of resized frame while hidden + } + } + }); + + // Build a GUI that displays canvas and check box + frame.setLayout(new BorderLayout()); + frame.add(panel, BorderLayout.CENTER); + frame.add(checkbox, BorderLayout.NORTH); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setSize(width, height); + frame.setVisible(true); + }}); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas1, true)); + + animator.start(); + Assert.assertTrue(animator.isStarted()); + Assert.assertTrue(animator.isAnimating()); + + final long t0 = System.currentTimeMillis(); + long t1 = t0; + while(!quitAdapter.shouldQuit() && t1 - t0 < duration) { + Thread.sleep(100); + t1 = System.currentTimeMillis(); + } + + Assert.assertNotNull(frame); + Assert.assertNotNull(glCanvas1); + + Assert.assertNotNull(animator); + animator.stop(); + Assert.assertFalse(animator.isAnimating()); + Assert.assertFalse(animator.isStarted()); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + }}); + Assert.assertEquals(false, frame.isVisible()); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.remove(panel); + frame.dispose(); + }}); + } + + static GLProfile getGLP() { + return GLProfile.getMaxProgrammableCore(true); + } + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } + } + + org.junit.runner.JUnitCore.main(TestBug816OSXCALayerPos03bB849AWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos03cB849AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos03cB849AWT.java new file mode 100644 index 000000000..24f9de961 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos03cB849AWT.java @@ -0,0 +1,174 @@ +/** + * Copyright 2013 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.jogl.awt; + +import java.awt.BorderLayout; +import java.awt.Container; +import java.awt.GridLayout; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; +import javax.swing.JCheckBox; +import javax.swing.JFrame; +import javax.swing.JPanel; + +import org.junit.Assert; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.event.TraceWindowAdapter; +import com.jogamp.newt.event.awt.AWTWindowAdapter; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; + +/** + * AWT JFrame BorderLayout w/ Checkbox North, JPanel.GLCanvas Center. + * <p> + * Checkbox toggles GLCanvas's parent jpanel's visibility state. + * </p> + * <p> + * Validates bugs: + * <ul> + * <li>Bug 816: OSX CALayer Positioning Bug</li> + * <li>Bug 729: OSX CALayer shall honor the Component's visibility state</li> + * <li>Bug 849: AWT GLAutoDrawables (JAWTWindow) shall honor it's parent visibility state</li> + * </ul> + * </p> + * <p> + * Diff. OSX CALayer positioning w/ java6, [7uxx..7u40[, and >= 7u40 + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestBug816OSXCALayerPos03cB849AWT extends UITestCase { + static long duration = 1600; // ms + static int width=640, height=480; + + @Test + public void test() throws InterruptedException, InvocationTargetException { + final GLCapabilities caps = new GLCapabilities(getGLP()); + + final JFrame frame = new JFrame("TestBug816OSXCALayerPos03cAWT"); + Assert.assertNotNull(frame); + final Container framePane = frame.getContentPane(); + + final GLCanvas glCanvas1 = new GLCanvas(caps); + Assert.assertNotNull(glCanvas1); + glCanvas1.addGLEventListener(new GearsES2(1)); + // Put it in a panel + final JPanel panel = new JPanel(new GridLayout(1, 1)); + panel.add(glCanvas1); + + final Animator animator = new Animator(); + animator.add(glCanvas1); + QuitAdapter quitAdapter = new QuitAdapter(); + + new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter)).addTo(frame); + + // Create a check box that hides / shows canvas + final JCheckBox checkbox = new JCheckBox("Visible canvas", true); + checkbox.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent ev) { + final boolean visible = checkbox.getSelectedObjects()!=null; + System.err.println("XXXX Panel setVisible "+visible); + panel.setVisible(visible); + System.err.println("XXXX Visible: [panel "+panel.isVisible()+", canvas "+glCanvas1.isVisible()+"]; Displayable: [panel "+panel.isDisplayable()+", canvas "+glCanvas1.isDisplayable()+"]"); + if( panel.isVisible() ) { + frame.validate(); // take care of resized frame while hidden + } + } + }); + + // Build a GUI that displays canvas and check box + framePane.setLayout(new BorderLayout()); + framePane.add(panel, BorderLayout.CENTER); + framePane.add(checkbox, BorderLayout.NORTH); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setSize(width, height); + frame.setVisible(true); + }}); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas1, true)); + + animator.start(); + Assert.assertTrue(animator.isStarted()); + Assert.assertTrue(animator.isAnimating()); + + final long t0 = System.currentTimeMillis(); + long t1 = t0; + while(!quitAdapter.shouldQuit() && t1 - t0 < duration) { + Thread.sleep(100); + t1 = System.currentTimeMillis(); + } + + Assert.assertNotNull(frame); + Assert.assertNotNull(glCanvas1); + + Assert.assertNotNull(animator); + animator.stop(); + Assert.assertFalse(animator.isAnimating()); + Assert.assertFalse(animator.isStarted()); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + }}); + Assert.assertEquals(false, frame.isVisible()); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + framePane.remove(panel); + frame.dispose(); + }}); + } + + static GLProfile getGLP() { + return GLProfile.getMaxProgrammableCore(true); + } + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } + } + + org.junit.runner.JUnitCore.main(TestBug816OSXCALayerPos03cB849AWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos04aAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos04aAWT.java new file mode 100644 index 000000000..b558b1680 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos04aAWT.java @@ -0,0 +1,152 @@ +/** + * Copyright 2013 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.jogl.awt; + +import java.awt.BorderLayout; +import java.awt.Dialog; +import java.awt.Frame; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; + +import org.junit.Assert; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.event.TraceWindowAdapter; +import com.jogamp.newt.event.awt.AWTWindowAdapter; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; + +/** + * Bug 816: OSX CALayer Positioning Bug - AWT Frame w/ (top-level) Dialog child containing the GLCanvas + * <p> + * Diff. OSX CALayer positioning w/ java6, [7uxx..7u40[, and >= 7u40 + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestBug816OSXCALayerPos04aAWT extends UITestCase { + static long duration = 1600; // ms + static int width=640, height=480; + + @Test + public void test() throws InterruptedException, InvocationTargetException { + final GLCapabilities caps = new GLCapabilities(getGLP()); + + final Frame frame = new Frame("TestBug816OSXCALayerPos04aAWT"); + Assert.assertNotNull(frame); + + final GLCanvas glCanvas1 = new GLCanvas(caps); + Assert.assertNotNull(glCanvas1); + glCanvas1.addGLEventListener(new GearsES2(1)); + + final Animator animator = new Animator(); + animator.add(glCanvas1); + QuitAdapter quitAdapter = new QuitAdapter(); + + new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter)).addTo(frame); + + // Display the canvas 3D in a dialog child of a frame + frame.setSize(400, 400); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setLocation(100, 100); + frame.setSize(width, height); + frame.setVisible(true); + }}); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); + + final Dialog dialog = new Dialog(frame, "Bug 816 AWT Top-Level Dialog"); + dialog.setLayout(new BorderLayout()); + dialog.add(glCanvas1, BorderLayout.CENTER); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + dialog.setLocation(200, 200); + dialog.setSize(width/2, height/2); + dialog.setVisible(true); + }}); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(dialog, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas1, true)); + + animator.start(); + Assert.assertTrue(animator.isStarted()); + Assert.assertTrue(animator.isAnimating()); + animator.setUpdateFPSFrames(60, System.err); + + final long t0 = System.currentTimeMillis(); + long t1 = t0; + while(!quitAdapter.shouldQuit() && t1 - t0 < duration) { + Thread.sleep(100); + t1 = System.currentTimeMillis(); + } + + Assert.assertNotNull(frame); + Assert.assertNotNull(glCanvas1); + + Assert.assertNotNull(animator); + animator.stop(); + Assert.assertFalse(animator.isAnimating()); + Assert.assertFalse(animator.isStarted()); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + }}); + Assert.assertEquals(false, frame.isVisible()); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.remove(glCanvas1); + frame.dispose(); + }}); + } + + static GLProfile getGLP() { + return GLProfile.getMaxProgrammableCore(true); + } + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } + } + + org.junit.runner.JUnitCore.main(TestBug816OSXCALayerPos04aAWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos04bAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos04bAWT.java new file mode 100644 index 000000000..b502dbdae --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816OSXCALayerPos04bAWT.java @@ -0,0 +1,152 @@ +/** + * Copyright 2013 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.jogl.awt; + +import java.awt.BorderLayout; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; +import javax.swing.JDialog; +import javax.swing.JFrame; + +import org.junit.Assert; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.event.TraceWindowAdapter; +import com.jogamp.newt.event.awt.AWTWindowAdapter; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; + +/** + * Bug 816: OSX CALayer Positioning Bug - AWT JFrame w/ JDialog child containing the GLCanvas + * <p> + * Diff. OSX CALayer positioning w/ java6, [7uxx..7u40[, and >= 7u40 + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestBug816OSXCALayerPos04bAWT extends UITestCase { + static long duration = 1600; // ms + static int width=640, height=480; + + @Test + public void test() throws InterruptedException, InvocationTargetException { + final GLCapabilities caps = new GLCapabilities(getGLP()); + + final JFrame frame = new JFrame("TestBug816OSXCALayerPos04bAWT"); + Assert.assertNotNull(frame); + + final GLCanvas glCanvas1 = new GLCanvas(caps); + Assert.assertNotNull(glCanvas1); + glCanvas1.addGLEventListener(new GearsES2(1)); + + final Animator animator = new Animator(); + animator.add(glCanvas1); + QuitAdapter quitAdapter = new QuitAdapter(); + + new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter)).addTo(frame); + + // Display the canvas 3D in a dialog child of a frame + frame.setSize(400, 400); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setLocation(100, 100); + frame.setSize(width, height); + frame.setVisible(true); + }}); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); + + final JDialog dialog = new JDialog(frame, "Bug 816 AWT Top-Level JDialog"); + dialog.setLayout(new BorderLayout()); + dialog.add(glCanvas1, BorderLayout.CENTER); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + dialog.setLocation(200, 200); + dialog.setSize(width/2, height/2); + dialog.setVisible(true); + }}); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(dialog, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas1, true)); + + animator.start(); + Assert.assertTrue(animator.isStarted()); + Assert.assertTrue(animator.isAnimating()); + animator.setUpdateFPSFrames(60, System.err); + + final long t0 = System.currentTimeMillis(); + long t1 = t0; + while(!quitAdapter.shouldQuit() && t1 - t0 < duration) { + Thread.sleep(100); + t1 = System.currentTimeMillis(); + } + + Assert.assertNotNull(frame); + Assert.assertNotNull(glCanvas1); + + Assert.assertNotNull(animator); + animator.stop(); + Assert.assertFalse(animator.isAnimating()); + Assert.assertFalse(animator.isStarted()); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + }}); + Assert.assertEquals(false, frame.isVisible()); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.remove(glCanvas1); + frame.dispose(); + }}); + } + + static GLProfile getGLP() { + return GLProfile.getMaxProgrammableCore(true); + } + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } + } + + org.junit.runner.JUnitCore.main(TestBug816OSXCALayerPos04bAWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock00AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock00AWT.java new file mode 100644 index 000000000..46230465f --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock00AWT.java @@ -0,0 +1,244 @@ +/** + * Copyright 2012 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.jogl.awt; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.awt.GLCanvas; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.AnimatorBase; +import com.jogamp.opengl.util.FPSAnimator; + +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; + +import com.jogamp.opengl.test.junit.util.MiscUtils; + +import java.awt.BorderLayout; +import java.awt.Frame; +import java.awt.Insets; + +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLCanvasAWTActionDeadlock00AWT extends UITestCase { + static long durationPerTest = 1000; // ms + static final int width = 512; + static final int height = 512; + + GLEventListener gle1 = null; + GLEventListener gle2 = null; + + @Test + public void test01Animator() throws InterruptedException { + testImpl(new Animator(), 0, false); + } + + @Test + public void test02FPSAnimator() throws InterruptedException { + testImpl(new FPSAnimator(30), 0, false); + } + + @Test + public void test02FPSAnimator_RestartOnAWTEDT() throws InterruptedException { + testImpl(new FPSAnimator(30), 100, false); + } + + /** May crash due to invalid thread usage, i.e. non AWT-EDT + @Test + public void test02FPSAnimator_RestartOnCurrentThread() throws InterruptedException { + testImpl(new FPSAnimator(30), 100, true); + } */ + + void testImpl(final AnimatorBase animator, int restartPeriod, boolean restartOnCurrentThread) throws InterruptedException { + final Frame frame1 = new Frame("Frame 1"); + gle1 = new GLEventListener() { + @Override + public void init(GLAutoDrawable drawable) { + } + + @Override + public void dispose(GLAutoDrawable drawable) { + } + + @Override + public void display(GLAutoDrawable drawable) { + frame1.setTitle("f "+frameCount+", fps "+animator.getLastFPS()); + frameCount++; + } + + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + } + }; + gle2 = new GearsES2(); + + Assert.assertNotNull(frame1); + { + Insets insets = frame1.getInsets(); + int w = width + insets.left + insets.right; + int h = height + insets.top + insets.bottom; + frame1.setSize(w, h); + } + frame1.setLocation(0, 0); + frame1.setTitle("Generic Title"); + + GLCanvas glCanvas = createGLCanvas(); + glCanvas.addGLEventListener(gle1); + glCanvas.addGLEventListener(gle2); + + animator.setUpdateFPSFrames(60, System.err); + animator.add(glCanvas); + animator.start(); + + attachGLCanvas(frame1, glCanvas, false); + + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame1.setVisible(true); + }}); + } catch (Throwable t) { + t.printStackTrace(); + Assume.assumeNoException(t); + } + + final long sleep = 0 < restartPeriod ? restartPeriod : 100; + long togo = durationPerTest; + while( 0 < togo ) { + if(0 < restartPeriod) { + glCanvas = restart(frame1, glCanvas, restartOnCurrentThread); + } + + Thread.sleep(sleep); + + togo -= sleep; + } + + dispose(frame1, glCanvas); + animator.stop(); + + gle1 = null; + gle2 = null; + } + + void dispose(final Frame frame, final GLCanvas glCanvas) { + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + glCanvas.destroy(); + frame.dispose(); + }}); + } catch (Throwable t) { + t.printStackTrace(); + Assume.assumeNoException(t); + } + } + + GLCanvas restart(final Frame frame, GLCanvas glCanvas, boolean restartOnCurrentThread) throws InterruptedException { + glCanvas.disposeGLEventListener(gle1, true); + glCanvas.disposeGLEventListener(gle2, true); + detachGLCanvas(frame, glCanvas, restartOnCurrentThread); + + glCanvas = createGLCanvas(); + + attachGLCanvas(frame, glCanvas, restartOnCurrentThread); + glCanvas.addGLEventListener(gle1); + glCanvas.addGLEventListener(gle2); + + return glCanvas; + } + + void attachGLCanvas(final Frame frame, final GLCanvas glCanvas, boolean restartOnCurrentThread) { + System.err.println("*** attachGLCanvas.0 on-current-thread "+restartOnCurrentThread+", currentThread "+Thread.currentThread().getName()); + if( restartOnCurrentThread ) { + frame.setLayout(new BorderLayout()); + frame.add(glCanvas, BorderLayout.CENTER); + frame.validate(); + } else { + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setLayout(new BorderLayout()); + frame.add(glCanvas, BorderLayout.CENTER); + frame.validate(); + }}); + } catch (Throwable t) { + t.printStackTrace(); + Assume.assumeNoException(t); + } + } + System.err.println("*** attachGLCanvas.X"); + } + + void detachGLCanvas(final Frame frame, final GLCanvas glCanvas, boolean restartOnCurrentThread) { + System.err.println("*** detachGLCanvas.0 on-current-thread "+restartOnCurrentThread+", currentThread "+Thread.currentThread().getName()); + if( restartOnCurrentThread ) { + frame.remove(glCanvas); + frame.validate(); + } else { + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.remove(glCanvas); + frame.validate(); + }}); + } catch (Throwable t) { + t.printStackTrace(); + Assume.assumeNoException(t); + } + } + System.err.println("*** detachGLCanvas.X"); + } + + int frameCount = 0; + + GLCanvas createGLCanvas() { + System.err.println("*** createGLCanvas.0"); + final GLCanvas glCanvas = new GLCanvas(); + glCanvas.setBounds(0, 0, width, height); + Assert.assertNotNull(glCanvas); + System.err.println("*** createGLCanvas.X"); + return glCanvas; + } + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + durationPerTest = MiscUtils.atoi(args[++i], (int)durationPerTest); + } + } + org.junit.runner.JUnitCore.main(TestGLCanvasAWTActionDeadlock00AWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock01AWT.java new file mode 100644 index 000000000..ba06f91a3 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock01AWT.java @@ -0,0 +1,351 @@ +/** + * Copyright 2012 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.jogl.awt; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; + +import com.jogamp.common.os.Platform; +import com.jogamp.common.util.VersionNumber; +import com.jogamp.common.util.awt.AWTEDTExecutor; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.AnimatorBase; +import com.jogamp.opengl.util.FPSAnimator; + +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; + +import com.jogamp.opengl.test.junit.util.MiscUtils; + +import java.applet.Applet; +import java.awt.BorderLayout; +import java.awt.Frame; +import java.awt.Insets; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.lang.reflect.InvocationTargetException; + +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +/** + * BUG on OSX/CALayer w/ Java6: + * If frame.setTitle() is issued right after initialization the call hangs in + * <pre> + * at apple.awt.CWindow._setTitle(Native Method) + * at apple.awt.CWindow.setTitle(CWindow.java:765) [1.6.0_37, build 1.6.0_37-b06-434-11M3909] + * </pre> + * <p> + * OSX/CALayer is forced by using an Applet component in this unit test. + * </p> + * <p> + * Similar deadlock has been experienced w/ other mutable operation on an AWT Container owning a GLCanvas child, + * e.g. setResizable*(). + * </p> + * <p> + * Users shall make sure all mutable AWT calls are performed on the EDT, even before 1st setVisible(true) ! + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLCanvasAWTActionDeadlock01AWT extends UITestCase { + static long durationPerTest = 1000; // ms + static final int width = 512; + static final int height = 512; + + GLEventListener gle1 = null; + GLEventListener gle2 = null; + + @Test + public void test00NoAnimator() throws InterruptedException, InvocationTargetException { + testImpl(null, 0, false); + } + + @Test + public void test01Animator() throws InterruptedException, InvocationTargetException { + testImpl(new Animator(), 0, false); + } + + @Test + public void test02FPSAnimator() throws InterruptedException, InvocationTargetException { + testImpl(new FPSAnimator(30), 0, false); + } + + @Test + public void test02FPSAnimator_RestartOnAWTEDT() throws InterruptedException, InvocationTargetException { + testImpl(new FPSAnimator(30), 200, false); + } + + /** May crash due to invalid thread usage, i.e. non AWT-EDT + * @throws InvocationTargetException + * @throws InterruptedException + @Test + public void test02FPSAnimator_RestartOnCurrentThread() throws InterruptedException { + testImpl(new FPSAnimator(30), 200, true); + } */ + + private static void setFrameTitle(final Frame frame, final String msg) { + System.err.println("About to setTitle: <"+msg+"> CT "+Thread.currentThread().getName()+", "+ + frame+", displayable "+frame.isDisplayable()+ + ", valid "+frame.isValid()+", visible "+frame.isVisible()); + // Thread.dumpStack(); + AWTEDTExecutor.singleton.invoke(true, new Runnable() { + public void run() { + frame.setTitle(msg); + } } ); + } + + void testImpl(final AnimatorBase animator, int restartPeriod, boolean restartOnCurrentThread) throws InterruptedException, InvocationTargetException { + final Frame frame1 = new Frame("Frame 1"); + final Applet applet1 = new Applet() { + private static final long serialVersionUID = 1L; + }; + + final VersionNumber version170 = new VersionNumber(1, 7, 0); + final boolean osxCALayerAWTModBug = Platform.OSType.MACOS == Platform.getOSType() && + 0 > Platform.getJavaVersionNumber().compareTo(version170); + System.err.println("OSX CALayer AWT-Mod Bug "+osxCALayerAWTModBug); + System.err.println("OSType "+Platform.getOSType()); + System.err.println("Java Version "+Platform.getJavaVersionNumber()); + + Assert.assertNotNull(frame1); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame1.setLayout(null); + frame1.pack(); + { + Insets insets = frame1.getInsets(); + int w = width + insets.left + insets.right; + int h = height + insets.top + insets.bottom; + frame1.setSize(w, h); + + int usableH = h - insets.top - insets.bottom; + applet1.setBounds((w - width)/2, insets.top + (usableH - height)/2, width, height); + } + frame1.setLocation(0, 0); + frame1.setTitle("Generic Title"); + frame1.add(applet1); + }}); + + frame1.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + dispose(frame1, applet1); + } + }); + + gle1 = new GLEventListener() { + boolean justInitialized = true; + + @Override + public void init(GLAutoDrawable drawable) { + justInitialized = true; + if( !osxCALayerAWTModBug ) { + System.err.println("*Init*: CT "+Thread.currentThread().getName()); + setFrameTitle(frame1, "INIT"); + frame1.setResizable(false); + } + } + + @Override + public void dispose(GLAutoDrawable drawable) { + System.err.println("*Dispose*: CT "+Thread.currentThread().getName()); + setFrameTitle(frame1, "DISPOSE"); + } + + @Override + public void display(GLAutoDrawable drawable) { + if( !osxCALayerAWTModBug || !justInitialized ) { + System.err.println("*Display*: CT "+Thread.currentThread().getName()); + setFrameTitle(frame1, "f "+frameCount+", fps "+( null != animator ? animator.getLastFPS() : 0)); + frame1.setResizable(false); + } + frameCount++; + justInitialized = false; + } + + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + if( !osxCALayerAWTModBug || !justInitialized ) { + System.err.println("*Reshape*: CT "+Thread.currentThread().getName()); + setFrameTitle(frame1, "RESHAPE"); + } + } + }; + gle2 = new GearsES2(); + + GLCanvas glCanvas = createGLCanvas(); + glCanvas.addGLEventListener(gle1); + glCanvas.addGLEventListener(gle2); + + if(null != animator) { + System.err.println("About to start Animator: CT "+Thread.currentThread().getName()); + animator.setUpdateFPSFrames(60, System.err); + animator.add(glCanvas); + animator.start(); + } + + attachGLCanvas(applet1, glCanvas, false); + + System.err.println("About to setVisible.0 CT "+Thread.currentThread().getName()); + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + System.err.println("About to setVisible.1.0 CT "+Thread.currentThread().getName()); + frame1.setVisible(true); + System.err.println("About to setVisible.1.X CT "+Thread.currentThread().getName()); + }}); + } catch (Throwable t) { + t.printStackTrace(); + Assume.assumeNoException(t); + } + System.err.println("About to setVisible.X CT "+Thread.currentThread().getName()); + + final long sleep = 0 < restartPeriod ? restartPeriod : 100; + long togo = durationPerTest; + while( 0 < togo ) { + if(null == animator) { + glCanvas.display(); + } + if(0 < restartPeriod) { + glCanvas = restart(applet1, glCanvas, restartOnCurrentThread); + } + + Thread.sleep(sleep); + + togo -= sleep; + } + + dispose(frame1, applet1); + if(null != animator) { + animator.stop(); + } + + gle1 = null; + gle2 = null; + } + + int frameCount = 0; + + GLCanvas createGLCanvas() { + System.err.println("*** createGLCanvas.0"); + final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); + // Iff using offscreen layer, use pbuffer, hence restore onscreen:=true. + // caps.setPBuffer(true); + // caps.setOnscreen(true); + final GLCanvas glCanvas = new GLCanvas(caps); + glCanvas.setBounds(0, 0, width, height); + Assert.assertNotNull(glCanvas); + System.err.println("*** createGLCanvas.X"); + frameCount = 0; + return glCanvas; + } + + void dispose(final Frame frame, final Applet applet) { + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.remove(applet); + frame.dispose(); + }}); + } catch (Throwable t) { + t.printStackTrace(); + Assume.assumeNoException(t); + } + } + + GLCanvas restart(final Applet applet, GLCanvas glCanvas, boolean restartOnCurrentThread) throws InterruptedException { + glCanvas.disposeGLEventListener(gle1, true); + glCanvas.disposeGLEventListener(gle2, true); + detachGLCanvas(applet, glCanvas, restartOnCurrentThread); + + glCanvas = createGLCanvas(); + + attachGLCanvas(applet, glCanvas, restartOnCurrentThread); + glCanvas.addGLEventListener(gle1); + glCanvas.addGLEventListener(gle2); + + return glCanvas; + } + + void attachGLCanvas(final Applet applet, final GLCanvas glCanvas, boolean restartOnCurrentThread) { + System.err.println("*** attachGLCanvas.0 on-current-thread "+restartOnCurrentThread+", currentThread "+Thread.currentThread().getName()); + if( restartOnCurrentThread ) { + applet.setLayout(new BorderLayout()); + applet.add(glCanvas, BorderLayout.CENTER); + applet.validate(); + } else { + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + applet.setLayout(new BorderLayout()); + applet.add(glCanvas, BorderLayout.CENTER); + applet.validate(); + }}); + } catch (Throwable t) { + t.printStackTrace(); + Assume.assumeNoException(t); + } + } + System.err.println("*** attachGLCanvas.X"); + } + + void detachGLCanvas(final Applet applet, final GLCanvas glCanvas, boolean restartOnCurrentThread) { + System.err.println("*** detachGLCanvas.0 on-current-thread "+restartOnCurrentThread+", currentThread "+Thread.currentThread().getName()); + if( restartOnCurrentThread ) { + applet.remove(glCanvas); + applet.validate(); + } else { + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + applet.remove(glCanvas); + applet.validate(); + }}); + } catch (Throwable t) { + t.printStackTrace(); + Assume.assumeNoException(t); + } + } + System.err.println("*** detachGLCanvas.X"); + } + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + durationPerTest = MiscUtils.atoi(args[++i], (int)durationPerTest); + } + } + org.junit.runner.JUnitCore.main(TestGLCanvasAWTActionDeadlock01AWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock02AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock02AWT.java new file mode 100644 index 000000000..605f97fe3 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock02AWT.java @@ -0,0 +1,670 @@ +/** + * Copyright 2012 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.jogl.awt; + +import java.applet.Applet; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.DisplayMode; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.lang.reflect.InvocationTargetException; +import java.util.Timer; +import java.util.TimerTask; + +import javax.media.opengl.*; +import javax.media.opengl.awt.GLCanvas; + +import org.junit.Assume; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.common.os.Platform; +import com.jogamp.common.util.VersionNumber; +import com.jogamp.common.util.awt.AWTEDTExecutor; +import com.jogamp.opengl.util.AnimatorBase; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Sample program that relies on JOGL's mechanism to handle the OpenGL context + * and rendering loop when using an AWT canvas attached to an Applet. + * <p> + * BUG on OSX/CALayer w/ Java6: + * If frame.setTitle() is issued right after initialization the call hangs in + * <pre> + * at apple.awt.CWindow._setTitle(Native Method) + * at apple.awt.CWindow.setTitle(CWindow.java:765) [1.6.0_37, build 1.6.0_37-b06-434-11M3909] + * </pre> + * </p> + * <p> + * OSX/CALayer is forced by using an Applet component in this unit test. + * </p> + * <p> + * Similar deadlock has been experienced w/ other mutable operation on an AWT Container owning a GLCanvas child, + * e.g. setResizable*(). + * </p> + * <p> + * Users shall make sure all mutable AWT calls are performed on the EDT, even before 1st setVisible(true) ! + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase { + static int framesPerTest = 240; // frames + + static class MiniPApplet extends Applet implements MouseMotionListener, KeyListener { + private static final long serialVersionUID = 1L; + + ///////////////////////////////////////////////////////////// + // + // Test parameters + + public int frameRate = 120; + public int numSamples = 4; + + public boolean fullScreen = false; + public boolean useAnimator = true; + public boolean resizeableFrame = true; + + public boolean restartCanvas = true; + public int restartTimeout = 100; // in number of frames. + + public boolean printThreadInfo = false; + public boolean printEventInfo = false; + + ///////////////////////////////////////////////////////////// + // + // Internal variables + + int width; + int height; + + String OPENGL_VENDOR; + String OPENGL_RENDERER; + String OPENGL_VERSION; + String OPENGL_EXTENSIONS; + + int currentSamples = -1; + + private Frame frame; + private GLProfile profile; + private GLCapabilities capabilities; + private GLCanvas canvas; + + private SimpleListener listener; + private CustomAnimator animator; + + private long beforeTime; + private long overSleepTime; + private final long frameRatePeriod = 1000000000L / frameRate; + + private boolean initialized = false; + private boolean osxCALayerAWTModBug = false; + boolean justInitialized = true; + + private double theta = 0; + private double s = 0; + private double c = 0; + + private long millisOffset; + private int fcount, lastm; + private float frate; + private final int fint = 3; + + private boolean setFramerate = false; + private boolean restarted = false; + + private int frameCount = 0; + + void run() throws InterruptedException, InvocationTargetException { + // Thread loop = new Thread("Animation Thread") { + // public void run() { + frameCount = 0; + while ( frameCount < framesPerTest ) { + if (!initialized) { + setup(); + } + + if (restartCanvas && restartTimeout == frameCount) { + restart(); + } + + if (useAnimator) { + animator.requestRender(); + } else { + canvas.display(); + } + + clock(); + + frameCount++; + if( null == frame ) { + break; + } + } + dispose(); + // } + // }; + // loop.start(); + } + + void setup() throws InterruptedException, InvocationTargetException { + if (printThreadInfo) System.out.println("Current thread at setup(): " + Thread.currentThread()); + + millisOffset = System.currentTimeMillis(); + + final VersionNumber version170 = new VersionNumber(1, 7, 0); + osxCALayerAWTModBug = Platform.OSType.MACOS == Platform.getOSType() && + 0 > Platform.getJavaVersionNumber().compareTo(version170); + System.err.println("OSX CALayer AWT-Mod Bug "+osxCALayerAWTModBug); + System.err.println("OSType "+Platform.getOSType()); + System.err.println("Java Version "+Platform.getJavaVersionNumber()); + + // Frame setup ---------------------------------------------------------- + + width = 300; + height = 300; + final MiniPApplet applet = this; + + GraphicsEnvironment environment = + GraphicsEnvironment.getLocalGraphicsEnvironment(); + GraphicsDevice displayDevice = environment.getDefaultScreenDevice(); + frame = new Frame(displayDevice.getDefaultConfiguration()); + + final Rectangle fullScreenRect; + if (fullScreen) { + DisplayMode mode = displayDevice.getDisplayMode(); + fullScreenRect = new Rectangle(0, 0, mode.getWidth(), mode.getHeight()); + } else { + fullScreenRect = null; + } + // All AWT Mods on AWT-EDT, especially due to the follow-up complicated code! + AWTEDTExecutor.singleton.invoke(true, new Runnable() { + public void run() { + frame.setTitle("MiniPApplet"); + } } ); + if (fullScreen) { + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setUndecorated(true); + frame.setBackground(Color.GRAY); + frame.setBounds(fullScreenRect); + frame.setVisible(true); + }}); + } catch (Throwable t) { + t.printStackTrace(); + Assume.assumeNoException(t); + } + } + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setLayout(null); + frame.add(applet); + if (fullScreen) { + frame.invalidate(); + } else { + frame.pack(); + } + frame.setResizable(resizeableFrame); + if (fullScreen) { + // After the pack(), the screen bounds are gonna be 0s + frame.setBounds(fullScreenRect); + applet.setBounds((fullScreenRect.width - applet.width) / 2, + (fullScreenRect.height - applet.height) / 2, + applet.width, applet.height); + } else { + Insets insets = frame.getInsets(); + + int windowW = applet.width + insets.left + insets.right; + int windowH = applet.height + insets.top + insets.bottom; + int locationX = 100; + int locationY = 100; + + frame.setSize(windowW, windowH); + frame.setLocation(locationX, locationY); + + int usableWindowH = windowH - insets.top - insets.bottom; + applet.setBounds((windowW - width)/2, insets.top + (usableWindowH - height)/2, width, height); + } + }}); + } catch (Throwable t) { + t.printStackTrace(); + Assume.assumeNoException(t); + } + + + frame.add(this); + frame.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + try { + dispose(); + } catch (Exception ex) { + Assume.assumeNoException(ex); + } + } + }); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(true); + } } ); + + // Canvas setup ---------------------------------------------------------- + + profile = GLProfile.getDefault(); + capabilities = new GLCapabilities(profile); + capabilities.setSampleBuffers(true); + capabilities.setNumSamples(numSamples); + capabilities.setDepthBits(24); + // capabilities.setStencilBits(8); // No Stencil on OSX w/ hw-accel ! + capabilities.setAlphaBits(8); + + canvas = new GLCanvas(capabilities); + canvas.setBounds(0, 0, width, height); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + MiniPApplet.this.setLayout(new BorderLayout()); + MiniPApplet.this.add(canvas, BorderLayout.CENTER); + MiniPApplet.this.validate(); + } } ); + canvas.addMouseMotionListener(this); + canvas.addKeyListener(this); + + // Setting up animation + listener = new SimpleListener(); + canvas.addGLEventListener(listener); + if (useAnimator) { + animator = new CustomAnimator(canvas); + animator.start(); + } + initialized = true; + } + + void restart() throws InterruptedException, InvocationTargetException { + System.out.println("Restarting surface..."); + + // Stopping animation, removing current canvas. + if (useAnimator) { + animator.stop(); + animator.remove(canvas); + } + canvas.disposeGLEventListener(listener, true); + this.remove(canvas); + + capabilities = new GLCapabilities(profile); + capabilities.setSampleBuffers(true); + capabilities.setNumSamples(numSamples); + + canvas = new GLCanvas(capabilities); + canvas.setBounds(0, 0, width, height); + + // Setting up animation again + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + MiniPApplet.this.setLayout(new BorderLayout()); + MiniPApplet.this.add(canvas, BorderLayout.CENTER); + MiniPApplet.this.validate(); + } } ); + canvas.addMouseMotionListener(this); + canvas.addKeyListener(this); + + canvas.addGLEventListener(listener); + if (useAnimator) { + animator.add(canvas); + animator.start(); + } + + setFramerate = false; + restarted = true; + + System.out.println("Done"); + } + + void dispose() throws InterruptedException, InvocationTargetException { + if( null == frame ) { + return; + } + + // Stopping animation, removing current canvas. + if (useAnimator) { + animator.stop(); + animator.remove(canvas); + } + canvas.removeGLEventListener(listener); + if( EventQueue.isDispatchThread() ) { + MiniPApplet.this.remove(canvas); + frame.remove(MiniPApplet.this); + frame.validate(); + frame.dispose(); + frame = null; + } else { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + MiniPApplet.this.remove(canvas); + frame.remove(MiniPApplet.this); + frame.validate(); + frame.dispose(); + frame = null; + }}); + } + } + + void draw(GL2 gl) { + if( !osxCALayerAWTModBug || !justInitialized ) { + AWTEDTExecutor.singleton.invoke(true, new Runnable() { + public void run() { + frame.setTitle("frame " + frameCount); + } } ); + } + + if (printThreadInfo) System.out.println("Current thread at draw(): " + Thread.currentThread()); + + if (OPENGL_VENDOR == null) { + OPENGL_VENDOR = gl.glGetString(GL.GL_VENDOR); + OPENGL_RENDERER = gl.glGetString(GL.GL_RENDERER); + OPENGL_VERSION = gl.glGetString(GL.GL_VERSION); + OPENGL_EXTENSIONS = gl.glGetString(GL.GL_EXTENSIONS); + System.out.println(OPENGL_VENDOR); + System.out.println(OPENGL_RENDERER); + System.out.println(OPENGL_VERSION); + System.out.println(OPENGL_EXTENSIONS); + + int[] temp = { 0 }; + gl.glGetIntegerv(GL2.GL_MAX_SAMPLES, temp, 0); + System.out.println("Maximum number of samples supported by the hardware: " + temp[0]); + System.out.println("Frame: "+frame); + System.out.println("Applet: "+MiniPApplet.this); + System.out.println("GLCanvas: "+canvas); + System.out.println("GLDrawable: "+canvas.getDelegatedDrawable()); + } + + if (currentSamples == -1) { + int[] temp = { 0 }; + gl.glGetIntegerv(GL.GL_SAMPLES, temp, 0); + currentSamples = temp[0]; + if (numSamples != currentSamples) { + System.err.println("Requested sampling level " + numSamples + " not supported. Using " + currentSamples + " samples instead."); + } + } + + if (!setFramerate) { + if (60 < frameRate) { + // Disables vsync + gl.setSwapInterval(0); + } else if (30 < frameRate) { + gl.setSwapInterval(1); + } else { + gl.setSwapInterval(2); + } + setFramerate = true; + } + + if (restarted) { + int[] temp = { 0 }; + gl.glGetIntegerv(GL.GL_SAMPLES, temp, 0); + if (numSamples != temp[0]) { + System.err.println("Multisampling level requested " + numSamples + " not supported. Using " + temp[0] + "samples instead."); + } + } + + gl.glClearColor(0, 0, 0, 1); + gl.glClear(GL.GL_COLOR_BUFFER_BIT); + + theta += 0.01; + s = Math.sin(theta); + c = Math.cos(theta); + + gl.glBegin(GL.GL_TRIANGLES); + gl.glColor3f(1, 0, 0); + gl.glVertex2d(-c, -c); + gl.glColor3f(0, 1, 0); + gl.glVertex2d(0, c); + gl.glColor3f(0, 0, 1); + gl.glVertex2d(s, -s); + gl.glEnd(); + + gl.glFlush(); + + fcount += 1; + int m = (int) (System.currentTimeMillis() - millisOffset); + if (m - lastm > 1000 * fint) { + frate = (float)(fcount) / fint; + fcount = 0; + lastm = m; + System.err.println("fps: " + frate); + } + } + + void clock() { + long afterTime = System.nanoTime(); + long timeDiff = afterTime - beforeTime; + long sleepTime = (frameRatePeriod - timeDiff) - overSleepTime; + + if (sleepTime > 0) { // some time left in this cycle + try { + Thread.sleep(sleepTime / 1000000L, (int) (sleepTime % 1000000L)); + } catch (InterruptedException ex) { } + + overSleepTime = (System.nanoTime() - afterTime) - sleepTime; + + } else { // sleepTime <= 0; the frame took longer than the period + overSleepTime = 0L; + } + + beforeTime = System.nanoTime(); + } + + class SimpleListener implements GLEventListener { + @Override + public void display(GLAutoDrawable drawable) { + draw(drawable.getGL().getGL2()); + justInitialized = false; + } + + @Override + public void dispose(GLAutoDrawable drawable) { } + + @Override + public void init(GLAutoDrawable drawable) { + justInitialized = true; + } + + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int w, int h) { } + } + + public void mouseDragged(MouseEvent ev) { + if (printEventInfo) { + System.err.println("Mouse dragged event: " + ev); + } + } + + public void mouseMoved(MouseEvent ev) { + if (printEventInfo) { + System.err.println("Mouse moved event: " + ev); + } + } + + public void keyPressed(KeyEvent ev) { + if (printEventInfo) { + System.err.println("Key pressed event: " + ev); + } + } + + public void keyReleased(KeyEvent ev) { + if (printEventInfo) { + System.err.println("Key released event: " + ev); + } + } + + public void keyTyped(KeyEvent ev) { + if (printEventInfo) { + System.err.println("Key typed event: " + ev); + } + } + + /** An Animator subclass which renders one frame at the time + * upon calls to the requestRender() method. + **/ + public class CustomAnimator extends AnimatorBase { + private Timer timer = null; + private TimerTask task = null; + private volatile boolean shouldRun; + + protected String getBaseName(String prefix) { + return "Custom" + prefix + "Animator" ; + } + + /** Creates an CustomAnimator with an initial drawable to + * animate. */ + public CustomAnimator(GLAutoDrawable drawable) { + if (drawable != null) { + add(drawable); + } + } + + public synchronized void requestRender() { + shouldRun = true; + } + + public final synchronized boolean isStarted() { + return (timer != null); + } + + public final synchronized boolean isAnimating() { + return (timer != null) && (task != null); + } + + private void startTask() { + if(null != task) { + return; + } + + task = new TimerTask() { + private boolean firstRun = true; + public void run() { + if (firstRun) { + Thread.currentThread().setName("OPENGL"); + firstRun = false; + } + if(CustomAnimator.this.shouldRun) { + CustomAnimator.this.animThread = Thread.currentThread(); + // display impl. uses synchronized block on the animator instance + display(); + synchronized (this) { + // done with current frame. + shouldRun = false; + } + } + } + }; + + fpsCounter.resetFPSCounter(); + shouldRun = false; + + timer.schedule(task, 0, 1); + } + + public synchronized boolean start() { + if (timer != null) { + return false; + } + timer = new Timer(); + startTask(); + return true; + } + + /** Stops this CustomAnimator. */ + public synchronized boolean stop() { + if (timer == null) { + return false; + } + shouldRun = false; + if(null != task) { + task.cancel(); + task = null; + } + if(null != timer) { + timer.cancel(); + timer = null; + } + animThread = null; + try { + Thread.sleep(20); // ~ 1/60 hz wait, since we can't ctrl stopped threads + } catch (InterruptedException e) { } + return true; + } + + public final synchronized boolean isPaused() { return false; } + public synchronized boolean resume() { return false; } + public synchronized boolean pause() { return false; } + } + } + + @Test + public void test00() { + TestGLCanvasAWTActionDeadlock02AWT.MiniPApplet mini; + try { + Class<?> c = Thread.currentThread().getContextClassLoader().loadClass(TestGLCanvasAWTActionDeadlock02AWT.MiniPApplet.class.getName()); + mini = (TestGLCanvasAWTActionDeadlock02AWT.MiniPApplet) c.newInstance(); + } catch (Exception e) { + throw new RuntimeException(e); + } + if (mini != null) { + try { + mini.run(); + } catch (Exception ex) { + Assume.assumeNoException(ex); + } + } + } + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-frames")) { + framesPerTest = MiscUtils.atoi(args[++i], framesPerTest); + } + } + org.junit.runner.JUnitCore.main(TestGLCanvasAWTActionDeadlock02AWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLJPanelResize01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLJPanelResize01AWT.java new file mode 100644 index 000000000..2133d62a2 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLJPanelResize01AWT.java @@ -0,0 +1,209 @@ +/** + * Copyright 2013 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.jogl.awt; + +import java.awt.Dimension; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLJPanel; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +import org.junit.Assume; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +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; + +/** + * Multiple GLJPanels in a JFrame + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLJPanelResize01AWT extends UITestCase { + + @BeforeClass + public static void initClass() { + GLProfile.initSingleton(); + } + + static Dimension[] esize00 = { + new Dimension(281, 151), + new Dimension(282, 151), + new Dimension(283, 151), + new Dimension(284, 151), + + new Dimension(284, 152), + new Dimension(283, 152), + new Dimension(282, 152), + new Dimension(281, 152), + + new Dimension(291, 153), + new Dimension(292, 153), + new Dimension(293, 153), + new Dimension(294, 153), + + new Dimension(281, 154), + new Dimension(282, 154), + new Dimension(283, 154), + new Dimension(284, 154) + }; + static Dimension[] esize01 = { + new Dimension(283, 154), // #3: new sub-aligned image in pixelBuffer-1 + new Dimension(291, 154), // #2: new pixelBuffer-1 + new Dimension(282, 154), // #1: new pixelBuffer-0 + }; + static Dimension[] esize02 = { + new Dimension(291, 154), // #2: new pixelBuffer-1 + new Dimension(282, 154), // #1: new pixelBuffer-0 + }; + + public void test(final GLCapabilitiesImmutable caps, final Dimension[] dims, final boolean useSwingDoubleBuffer) { + final int cols = 4; + final int rows = dims.length / cols + ( dims.length % cols > 0 ? 1 : 0 ); + final JFrame[] frame = new JFrame[] { null }; + + System.err.println("Frame size: cols x rows "+cols+"x"+rows); + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame[0] = new JFrame(); + frame[0].setLocation(64, 64); + final JPanel panel = new JPanel(); + panel.setLayout(null); // new BorderLayout()); + panel.setDoubleBuffered(useSwingDoubleBuffer); + frame[0].getContentPane().add(panel); + + final int x0 = 4; + int x = x0, y = 4; + int maxRowWidth = 0; + for(int i=0; i<rows; i++) { + int maxColHeight = 0; + for(int j=0; j<cols; j++) { + final int idx = i*cols+j; + if( idx >= dims.length ) { break; } + final Dimension d = dims[idx]; + if( d.height > maxColHeight ) { + maxColHeight = d.height; + } + final GLJPanel glad = createGLJPanel(useSwingDoubleBuffer, caps, d, "[r "+i+", c "+j+"]"); + panel.add(glad); + glad.setLocation(x, y); + x+=d.width+4; + } + if( x > maxRowWidth ) { + maxRowWidth = x; + } + x = x0; + y += maxColHeight+4; + } + frame[0].setSize(maxRowWidth+4+64, y+4+64); + // frame[0].pack(); + frame[0].setVisible(true); + } } ); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + try { + Thread.sleep(duration); + } catch (InterruptedException e1) { + e1.printStackTrace(); + } + try { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame[0].dispose(); + } } ); + } catch (Exception e1) { + e1.printStackTrace(); + } + } + + private GLJPanel createGLJPanel(final boolean useSwingDoubleBuffer, final GLCapabilitiesImmutable caps, final Dimension size, final String name) { + final GLJPanel canvas = new GLJPanel(caps); + canvas.setName(name); + canvas.setSize(size); + canvas.setPreferredSize(size); + canvas.setMinimumSize(size); + canvas.setDoubleBuffered(useSwingDoubleBuffer); + final GearsES2 g = new GearsES2(0); + g.setVerbose(false); + canvas.addGLEventListener(g); + return canvas; + } + + static GLCapabilitiesImmutable caps = null; + + // @Test + public void test00() throws InterruptedException, InvocationTargetException { + test(new GLCapabilities(null), esize00, false /*useSwingDoubleBuffer*/); + } + + @Test + public void test01() throws InterruptedException, InvocationTargetException { + test(new GLCapabilities(null), esize01, false /*useSwingDoubleBuffer*/); + } + + @Test + public void test02() throws InterruptedException, InvocationTargetException { + test(new GLCapabilities(null), esize02, false /*useSwingDoubleBuffer*/); + } + + static long duration = 600; // ms + + public static void main(String[] args) { + boolean useSwingDoubleBuffer=false, manual=false; + + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-swingDoubleBuffer")) { + useSwingDoubleBuffer = true; + } else if(args[i].equals("-manual")) { + manual = true; + } + } + if( manual ) { + GLProfile.initSingleton(); + TestGLJPanelResize01AWT demo = new TestGLJPanelResize01AWT(); + demo.test(new GLCapabilities(null), esize01, useSwingDoubleBuffer); + } else { + org.junit.runner.JUnitCore.main(TestGLJPanelResize01AWT.class.getName()); + } + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLJPanelTextureStateAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLJPanelTextureStateAWT.java new file mode 100644 index 000000000..2d4c6da4d --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLJPanelTextureStateAWT.java @@ -0,0 +1,282 @@ +/** + * Copyright 2013 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.jogl.awt; + + +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.TextureDraw02ES2ListenerFBO; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.test.junit.util.UITestCase; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.awt.GLJPanel; +import javax.swing.JFrame; + +import com.jogamp.opengl.util.texture.TextureIO; +import com.jogamp.opengl.util.texture.TextureState; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.GLReadBufferUtil; + +import java.awt.Dimension; + +import java.io.IOException; + +import org.junit.Assert; +import org.junit.Assume; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +/** + * Unit test for bug 826, test {@link GLJPanel}'s {@link TextureState} save and restore. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLJPanelTextureStateAWT extends UITestCase { + static boolean showFPS = false; + static long duration = 100; // ms + + @BeforeClass + public static void initClass() { + } + + public void testImpl(final boolean keepTextureBound, final int texUnit) + throws InterruptedException, IOException + { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); + GLProfile glp; + if(GLProfile.isAvailable(GLProfile.GL2ES2)) { + glp = GLProfile.getGL2ES2(); + } else { + System.err.println(getSimpleTestName(".")+": GLProfile n/a"); + return; + } + final GLCapabilities caps = new GLCapabilities(glp); + + final GLJPanel glc = new GLJPanel(caps); + Dimension glc_sz = new Dimension(800, 400); + glc.setMinimumSize(glc_sz); + glc.setPreferredSize(glc_sz); + final JFrame frame = new JFrame("TestGLJPanelTextureStateAWT"); + Assert.assertNotNull(frame); + frame.getContentPane().add(glc); + + final TextureDraw02ES2ListenerFBO gle0; + { + final GearsES2 gle0sub = new GearsES2( 0 ); + // gle1sub.setClearBuffers(false); + gle0 = new TextureDraw02ES2ListenerFBO(gle0sub, 1, texUnit ) ; + } + gle0.setKeepTextureBound(keepTextureBound); + gle0.setClearBuffers(false); + + final RedSquareES2 gle1 = new RedSquareES2( 1 ) ; + gle1.setClearBuffers(false); + + glc.addGLEventListener(new GLEventListener() { + int gle0X, gle0Y, gle0W, gle0H; + int gle1X, gle1Y, gle1W, gle1H; + int tX, tY, tW, tH; + int shot = 0; + + void setupTex(GL gl) { + // Note: FBObject uses diff defaults, i.e.: GL_NEAREST and GL_CLAMP_TO_EDGE + if( keepTextureBound ) { + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT); + } + } + + @Override + public void init(GLAutoDrawable drawable) { + // Initialize w/ arbitrary values ! + GL2ES2 gl = drawable.getGL().getGL2ES2(); + gl.glActiveTexture(GL.GL_TEXTURE0 + 1); + gl.glBindTexture(GL.GL_TEXTURE_2D, 0); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT); + gl.glActiveTexture(GL.GL_TEXTURE0 + 0); + gl.glBindTexture(GL.GL_TEXTURE_2D, 0); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT); + + gle0.init(drawable); + gle1.init(drawable); + setupTex(gl); + } + + @Override + public void dispose(GLAutoDrawable drawable) { + gle0.dispose(drawable); + gle1.dispose(drawable); + } + @Override + public void display(GLAutoDrawable drawable) { + GL2ES2 gl = drawable.getGL().getGL2ES2(); + + gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + + // restore viewport test + final int[] viewport = new int[] { 0, 0, 0, 0 }; + gl.glGetIntegerv(GL.GL_VIEWPORT, viewport, 0); + if( gle0X != viewport[0] || gle0Y != viewport[1] || gle0W != viewport[2] || gle0H != viewport[3] ) { + final String msg = "Expected "+viewport[0]+"/"+viewport[1]+" "+viewport[2]+"x"+viewport[3]+ + ", actual "+gle0X+"/"+gle0Y+" "+gle0W+"x"+gle0H; + Assert.assertTrue("Viewport not restored: "+msg, false); + } + + // gl.glViewport(gle0X, gle0Y, gle0W, gle0H); // restore viewport test + gle0.display(drawable); + + gl.glViewport(gle1X, gle1Y, gle1W, gle1H); + gle1.display(drawable); + + shot++; + if( 4 == shot ) { + gl.glViewport(tX, tY, tW, tH); + snapshot(0, null, drawable.getGL(), screenshot, TextureIO.PNG, null); + } + + gl.glViewport(gle0X, gle0Y, gle0W, gle0H); // restore viewport test + + final TextureState ts = new TextureState(drawable.getGL(), GL.GL_TEXTURE_2D); + // System.err.println("XXX: "+ts); + Assert.assertEquals("Texture unit changed", GL.GL_TEXTURE0+texUnit, ts.getUnit()); + if( keepTextureBound ) { + Assert.assertEquals("Texture mag-filter changed", GL.GL_LINEAR, ts.getMagFilter()); + Assert.assertEquals("Texture mag-filter changed", GL.GL_LINEAR, ts.getMinFilter()); + Assert.assertEquals("Texture wrap-s changed", GL.GL_REPEAT, ts.getWrapS()); + Assert.assertEquals("Texture wrap-t changed", GL.GL_REPEAT, ts.getWrapT()); + } + } + final int border = 5; + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + gle0X = x + border; + gle0Y = y; + gle0W = width/2 - 2*border; + gle0H = height; + + gle1X = gle0X + gle0W + 2*border; + gle1Y = y; + gle1W = width/2 - 2*border; + gle1H = height; + + tX = x; + tY = y; + tW = width; + tH = height; + + GL2ES2 gl = drawable.getGL().getGL2ES2(); + gl.glViewport(gle0X, gle0Y, gle0W, gle0H); + gle0.reshape(drawable, gle0X, gle0Y, gle0W, gle0H); + + gl.glViewport(gle1X, gle1Y, gle1W, gle1H); + gle1.reshape(drawable, gle1X, gle1Y, gle1W, gle1H); + + gl.glViewport(gle0X, gle0Y, gle0W, gle0H); // restore viewport test + + if( keepTextureBound ) { + setupTex(gl); + } + } + }); + + Animator animator = new Animator(glc); + animator.setUpdateFPSFrames(60, showFPS ? System.err : null); + QuitAdapter quitAdapter = new QuitAdapter(); + new com.jogamp.newt.event.awt.AWTKeyAdapter(quitAdapter).addTo(glc); + new com.jogamp.newt.event.awt.AWTWindowAdapter(quitAdapter).addTo(glc); + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.pack(); + frame.setVisible(true); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + animator.start(); + + while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) { + Thread.sleep(100); + } + + animator.stop(); + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + frame.remove(glc); + frame.dispose(); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + } + + @Test + public void test01_texUnit0_keepTex0_ES2() throws InterruptedException, IOException { + testImpl(false /* keepTextureBound */, 0 /* texUnit */); + } + @Test + public void test02_texUnit0_keepTex1_ES2() throws InterruptedException, IOException { + testImpl(true /* keepTextureBound */, 0 /* texUnit */); + } + @Test + public void test03_texUnit1_keepTex1_ES2() throws InterruptedException, IOException { + testImpl(true /* keepTextureBound */, 1 /* texUnit */); + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } + } + org.junit.runner.JUnitCore.main(TestGLJPanelTextureStateAWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestIsRealizedConcurrency01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestIsRealizedConcurrency01AWT.java new file mode 100644 index 000000000..3f8b76a17 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestIsRealizedConcurrency01AWT.java @@ -0,0 +1,104 @@ +/** + * 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.jogl.awt; + +import javax.media.opengl.awt.GLCanvas; +import com.jogamp.opengl.util.Animator; + +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; + +import com.jogamp.opengl.test.junit.util.MiscUtils; + +import java.awt.Dimension; +import java.awt.Frame; +import java.lang.reflect.InvocationTargetException; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestIsRealizedConcurrency01AWT extends UITestCase { + static long durationPerTest = 500; // ms + + @Test + public void testAddRemove() throws InterruptedException, InvocationTargetException { + final Dimension f_sz = new Dimension(512, 512); + + final GLCanvas glCanvas = new GLCanvas(); + Assert.assertNotNull(glCanvas); + glCanvas.addGLEventListener(new GearsES2()); + + final Animator animator = new Animator(glCanvas); + animator.start(); + + final Frame frame = new Frame("Frame"); + Assert.assertNotNull(frame); + frame.add(glCanvas); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setLocation(0, 0); + frame.setPreferredSize(f_sz); + frame.setSize(f_sz); + frame.pack(); + frame.setVisible(true); + }}); + Thread.sleep(durationPerTest/2); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.remove(glCanvas); + frame.validate(); + frame.add(glCanvas); + frame.validate(); + }}); + Thread.sleep(durationPerTest/2); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + glCanvas.destroy(); + frame.dispose(); + }}); + + animator.stop(); + } + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + durationPerTest = MiscUtils.atoi(args[++i], (int)durationPerTest); + } + } + org.junit.runner.JUnitCore.main(TestIsRealizedConcurrency01AWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestJScrollPaneMixHwLw01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestJScrollPaneMixHwLw01AWT.java new file mode 100644 index 000000000..28fb79cea --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestJScrollPaneMixHwLw01AWT.java @@ -0,0 +1,176 @@ +package com.jogamp.opengl.test.junit.jogl.awt; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.GraphicsConfiguration; +import java.awt.Rectangle; +import java.awt.ScrollPane; +import java.awt.Shape; +import java.io.IOException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.WindowConstants; + +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.common.util.ReflectionUtil; +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.util.Animator; + +/** + * Documenting Bug 586 + * + * <p> + * JScrollPane cannot mix hw/lw components, only if setting property '-Dsun.awt.disableMixing=true'. + * </p> + * <p> + * You can use ScrollPane, or maybe a slider and fwd the panning to the GLCanvas, + * which could change it's GL viewport accordingly. + * </p> + * See git commit '8df12ca151dfc577c90b485d4ebfe491b88e55aa'. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestJScrollPaneMixHwLw01AWT extends UITestCase { + static long durationPerTest = 500; + + static { + // too late: use at cmd-line '-Dsun.awt.disableMixing=true' works + // System.setProperty("sun.awt.disableMixing", "true"); + } + + /** + * Doesn't work either .. + */ + @SuppressWarnings("serial") + public static class TransparentJScrollPane extends JScrollPane { + + public TransparentJScrollPane(Component view) { + super(view); + + setOpaque(false); + + try { + ReflectionUtil.callStaticMethod( + "com.sun.awt.AWTUtilities", "setComponentMixingCutoutShape", + new Class<?>[] { Component.class, Shape.class }, + new Object[] { this, new Rectangle() } , + GraphicsConfiguration.class.getClassLoader()); + System.err.println("com.sun.awt.AWTUtilities.setComponentMixingCutoutShape(..) passed"); + } catch (RuntimeException re) { + System.err.println("com.sun.awt.AWTUtilities.setComponentMixingCutoutShape(..) failed: "+re.getMessage()); + } + } + + @Override + public void setOpaque(boolean isOpaque) { + } + } + + protected void runTestGL(GLCapabilities caps, boolean useJScroll) throws InterruptedException { + final String typeS = useJScroll ? "LW" : "HW"; + final JFrame frame = new JFrame("Mix Hw/Lw Swing - ScrollPane "+typeS); + Assert.assertNotNull(frame); + + final Dimension f_sz = new Dimension(600,400); + final Dimension glc_sz = new Dimension(500,600); + + final GLCanvas glCanvas = new GLCanvas(caps); + Assert.assertNotNull(glCanvas); + glCanvas.addGLEventListener(new GearsES2()); + glCanvas.setPreferredSize(glc_sz); + + JPanel panel = new JPanel(new BorderLayout()); + panel.setOpaque(false); + if(useJScroll) { + final JScrollPane scrollPane = new TransparentJScrollPane(glCanvas); + panel.add(scrollPane, BorderLayout.CENTER); + } else { + ScrollPane scrollPane = new ScrollPane(); + scrollPane.add(glCanvas); + panel.add(scrollPane, BorderLayout.CENTER); + } + + JTextArea textArea = new JTextArea(); + textArea.setText("Test\nTest\nTest\nTest\n"); + + panel.add(textArea, BorderLayout.NORTH); + + frame.add(panel); + frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setLocationRelativeTo(null); + frame.setTitle("GLCanvas in JScrollPane example"); + frame.setSize(f_sz); + frame.setVisible(true); + }}); + } catch (Throwable t) { + t.printStackTrace(); + Assume.assumeNoException(t); + } + + Animator animator = new Animator(glCanvas); + animator.start(); + + Thread.sleep(durationPerTest); + + animator.stop(); + + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + frame.dispose(); + }}); + } catch (Throwable t) { + t.printStackTrace(); + Assume.assumeNoException(t); + } + } + + // @Test doesn't work + public void test01JScrollPane() throws InterruptedException { + GLProfile glp = GLProfile.getGL2ES2(); + GLCapabilities caps = new GLCapabilities(glp); + runTestGL(caps, true); + } + + @Test + public void test01ScrollPane() throws InterruptedException { + GLProfile glp = GLProfile.getGL2ES2(); + GLCapabilities caps = new GLCapabilities(glp); + runTestGL(caps, false); + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + durationPerTest = MiscUtils.atol(args[++i], durationPerTest); + } + } + /** + BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); + System.err.println("Press enter to continue"); + System.err.println(stdin.readLine()); + */ + System.out.println("durationPerTest: "+durationPerTest); + String tstname = TestJScrollPaneMixHwLw01AWT.class.getName(); + org.junit.runner.JUnitCore.main(tstname); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestSwingAWT01GLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestSwingAWT01GLn.java index 007df9f49..ccdaf6edc 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestSwingAWT01GLn.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestSwingAWT01GLn.java @@ -45,6 +45,8 @@ import javax.swing.JFrame; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import static org.junit.Assume.*; import static javax.swing.SwingUtilities.*; @@ -53,6 +55,7 @@ import static javax.swing.SwingUtilities.*; * Tests context creation + display on various kinds of Window implementations. * @author Michael Bien, et. al. */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestSwingAWT01GLn extends UITestCase { private Window[] windows; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/text/TestAWTTextRendererUseVertexArrayBug464.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/text/TestAWTTextRendererUseVertexArrayBug464.java index ab369a959..066e5fe0d 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/text/TestAWTTextRendererUseVertexArrayBug464.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/text/TestAWTTextRendererUseVertexArrayBug464.java @@ -37,7 +37,6 @@ import com.jogamp.opengl.test.junit.util.UITestCase; import java.awt.Frame; import java.io.IOException; -import java.lang.reflect.InvocationTargetException; import org.junit.Assert; import org.junit.Assume; @@ -45,6 +44,8 @@ import org.junit.Before; import org.junit.BeforeClass; import org.junit.After; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; /* * Unit tests for Bug464 @@ -62,6 +63,7 @@ import org.junit.Test; * TestTextRendererTraceGL2Mock01 */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestAWTTextRendererUseVertexArrayBug464 extends UITestCase { static GLProfile glp; static GLCapabilities caps; @@ -84,9 +86,16 @@ public class TestAWTTextRendererUseVertexArrayBug464 extends UITestCase { frame = new Frame("TextRenderer Test"); Assert.assertNotNull(frame); frame.add(glCanvas); - frame.setSize(512, 512); - frame.setVisible(true); - + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setSize(512, 512); + frame.setVisible(true); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } } @After diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/caps/MultisampleChooser01.java b/src/test/com/jogamp/opengl/test/junit/jogl/caps/MultisampleChooser01.java index c2182b8b7..efdd2e16d 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/caps/MultisampleChooser01.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/caps/MultisampleChooser01.java @@ -40,12 +40,17 @@ package com.jogamp.opengl.test.junit.jogl.caps; import java.util.List; + +import javax.media.nativewindow.CapabilitiesImmutable; import javax.media.opengl.DefaultGLCapabilitiesChooser; import javax.media.opengl.GLCapabilitiesImmutable; class MultisampleChooser01 extends DefaultGLCapabilitiesChooser { - public int chooseCapabilities(GLCapabilitiesImmutable desired, List/*<GLCapabilitiesImmutable>*/ available, int windowSystemRecommendedChoice) { + @Override + public int chooseCapabilities(final CapabilitiesImmutable desired, + final List<? extends CapabilitiesImmutable> available, + final int windowSystemRecommendedChoice) { boolean anyHaveSampleBuffers = false; for (int i = 0; i < available.size(); i++) { GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) available.get(i); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestBug605FlippedImageAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestBug605FlippedImageAWT.java new file mode 100644 index 000000000..e87c34419 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestBug605FlippedImageAWT.java @@ -0,0 +1,187 @@ +/** + * Copyright 2012 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.jogl.caps; + +import java.io.File; +import java.io.IOException; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLException; +import javax.media.opengl.GLProfile; + +import com.jogamp.opengl.util.awt.Screenshot; +import com.jogamp.opengl.util.texture.TextureIO; + +import java.awt.image.BufferedImage; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.opengl.test.junit.util.UITestCase; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestBug605FlippedImageAWT extends UITestCase { + class FlippedImageTest implements GLEventListener { + public void display(GLAutoDrawable drawable) { + GL2 gl = drawable.getGL().getGL2(); + + gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT | GL.GL_STENCIL_BUFFER_BIT | GL2.GL_ACCUM_BUFFER_BIT ); + + gl.glMatrixMode(GL2.GL_PROJECTION); + gl.glLoadIdentity(); + gl.glMatrixMode(GL2.GL_MODELVIEW); + gl.glLoadIdentity(); + + // red below + gl.glColor3f(1, 0, 0); + gl.glRectf(-1, -1, 1, 0); + + // green above + gl.glColor3f(0, 1, 0); + gl.glRectf(-1, 0, 1, 1); + gl.glFinish(); + + final GLCapabilitiesImmutable caps = drawable.getChosenGLCapabilities(); + if(caps.getAccumGreenBits() > 0) { + gl.glAccum(GL2.GL_ACCUM, 1.0f); + gl.glAccum(GL2.GL_RETURN, 1.0f); + } + gl.glFinish(); + + final int width = drawable.getWidth(); + final int height = drawable.getHeight(); + + final String fname = getSnapshotFilename(0, null, caps, width, height, false, TextureIO.PNG, null); + try { + Screenshot.writeToFile(new File(fname), width, height, false); + } catch (GLException e) { + throw e; + } catch (IOException e) { + throw new GLException(e); + } + testFlipped(width, height); + } + + public void init(GLAutoDrawable drawable) { + final GL gl = drawable.getGL(); + System.err.println("GL_RENDERER: "+gl.glGetString(GL.GL_RENDERER)); + System.err.println("GL_VERSION: "+gl.glGetString(GL.GL_VERSION)); + } + public void reshape(GLAutoDrawable glDrawable, int x, int y, int w, int h) {} + public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {} + public void dispose(GLAutoDrawable drawable) {} + } + + static final int green = 0x0000ff00; // above + static final int red = 0x00ff0000; // below + + private void testFlipped(int width, int height) { + // Default origin 0/0 is lower left corner, so is the memory layout + // However AWT origin 0/0 is upper left corner + final BufferedImage image = Screenshot.readToBufferedImage(width, height); + + final int below = image.getRGB(0, height-1) & 0x00ffffff; + System.err.println("below: 0x"+Integer.toHexString(below)); + + final int above = image.getRGB(0, 0) & 0x00ffffff; + System.err.println("above: 0x"+Integer.toHexString(above)); + + if (above == green && below == red) { + System.out.println("Image right side up"); + } else if (above == red && below == green) { + Assert.assertTrue("Image is flipped", false); + } else { + Assert.assertTrue("Error in test", false); + } + } + + private void test(GLCapabilitiesImmutable caps) { + + final GLDrawableFactory glFactory = GLDrawableFactory.getFactory(caps.getGLProfile()); + final GLAutoDrawable glad = glFactory.createOffscreenAutoDrawable(null, caps, null, 256, 256); + final FlippedImageTest tglel = new FlippedImageTest(); + glad.addGLEventListener(tglel); + + // 1 frame incl. snapshot to memory & file + glad.display(); + System.err.println("XXX "+glad.getChosenGLCapabilities()); + System.err.println("XXX "+glad.getContext().getGLVersion()); + + glad.destroy(); + } + + @Test + public void test01DefaultFBO() { + final GLProfile glp = GLProfile.get(GLProfile.GL2); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setFBO(true); + test(caps); + } + + @Test + public void test01StencilFBO() { + final GLProfile glp = GLProfile.get(GLProfile.GL2); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setStencilBits(8); + caps.setFBO(true); + test(caps); + } + + @Test + public void test01DefaultPBuffer() { + final GLProfile glp = GLProfile.get(GLProfile.GL2); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setPBuffer(true); + test(caps); + } + + @Test + public void test01AccumStencilPBuffer() { + final GLProfile glp = GLProfile.get(GLProfile.GL2); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setAccumRedBits(16); + caps.setAccumGreenBits(16); + caps.setAccumBlueBits(16); + caps.setStencilBits(8); + caps.setPBuffer(true); + test(caps); + } + + public static void main(String[] args) { + org.junit.runner.JUnitCore.main(TestBug605FlippedImageAWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestBug605FlippedImageNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestBug605FlippedImageNEWT.java new file mode 100644 index 000000000..28fcb9885 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestBug605FlippedImageNEWT.java @@ -0,0 +1,178 @@ +/** + * Copyright 2012 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.jogl.caps; + +import java.nio.ByteBuffer; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.GLReadBufferUtil; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestBug605FlippedImageNEWT extends UITestCase { + static class FlippedImageTest implements GLEventListener { + public void display(GLAutoDrawable drawable) { + GL2 gl = drawable.getGL().getGL2(); + + gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT | GL.GL_STENCIL_BUFFER_BIT | GL2.GL_ACCUM_BUFFER_BIT ); + + gl.glMatrixMode(GL2.GL_PROJECTION); + gl.glLoadIdentity(); + gl.glMatrixMode(GL2.GL_MODELVIEW); + gl.glLoadIdentity(); + + // red below + gl.glColor3f(1, 0, 0); + gl.glRectf(-1, -1, 1, 0); + + // green above + gl.glColor3f(0, 1, 0); + gl.glRectf(-1, 0, 1, 1); + gl.glFinish(); + + final GLCapabilitiesImmutable caps = drawable.getChosenGLCapabilities(); + if(caps.getAccumGreenBits() > 0) { + gl.glAccum(GL2.GL_ACCUM, 1.0f); + gl.glAccum(GL2.GL_RETURN, 1.0f); + } + gl.glFinish(); + } + + public void init(GLAutoDrawable drawable) { + final GL gl = drawable.getGL(); + System.err.println("GL_RENDERER: "+gl.glGetString(GL.GL_RENDERER)); + System.err.println("GL_VERSION: "+gl.glGetString(GL.GL_VERSION)); + } + public void reshape(GLAutoDrawable glDrawable, int x, int y, int w, int h) {} + public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {} + public void dispose(GLAutoDrawable drawable) {} + } + + static final int green = 0x0000ff00; // above + static final int red = 0x00ff0000; // below + + private int getRGB(ByteBuffer bb, int o) { + return ( bb.get(o+0) & 0x000000ff ) << 16 | + ( bb.get(o+1) & 0x000000ff ) << 8 | + ( bb.get(o+2) & 0x000000ff ); + } + + private void testFlipped(ByteBuffer bb, int width, int height, int comp) { + // Default origin 0/0 is lower left corner, so is the memory layout + + // x=0, y=0: RGB -> _RGB [high-byte .. low-byte] + final int below = getRGB(bb, 0); + System.err.println("below: 0x"+Integer.toHexString(below)); + + // x=0, y=height-1: RGB -> _RGB [high-byte .. low-byte] + final int above= getRGB(bb, ( height - 1 ) * ( width * comp )); + System.err.println("above: 0x"+Integer.toHexString(above)); + + if (above == green && below == red) { + System.out.println("Image right side up"); + } else if (above == red && below == green) { + Assert.assertTrue("Image is flipped", false); + } else { + Assert.assertTrue("Error in test", false); + } + } + + private void test(GLCapabilitiesImmutable caps) { + final GLReadBufferUtil rbu = new GLReadBufferUtil(false, false); + final GLDrawableFactory glFactory = GLDrawableFactory.getFactory(caps.getGLProfile()); + final GLAutoDrawable glad = glFactory.createOffscreenAutoDrawable(null, caps, null, 256, 256); + final FlippedImageTest tglel = new FlippedImageTest(); + glad.addGLEventListener(tglel); + final SnapshotGLEventListener snap = new SnapshotGLEventListener(rbu); + glad.addGLEventListener(snap); + snap.setMakeSnapshotAlways(true); + + // 1 frame incl. snapshot to memory & file + glad.display(); + System.err.println("XXX "+glad.getChosenGLCapabilities()); + System.err.println("XXX "+glad.getContext().getGLVersion()); + testFlipped((ByteBuffer)rbu.getPixelBuffer().buffer, glad.getWidth(), glad.getHeight(), 3); + + glad.destroy(); + } + + @Test + public void test01DefaultFBO() { + final GLProfile glp = GLProfile.get(GLProfile.GL2); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setFBO(true); + test(caps); + } + + @Test + public void test01StencilFBO() { + final GLProfile glp = GLProfile.get(GLProfile.GL2); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setStencilBits(8); + caps.setFBO(true); + test(caps); + } + + @Test + public void test01DefaultPBuffer() { + final GLProfile glp = GLProfile.get(GLProfile.GL2); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setPBuffer(true); + test(caps); + } + + @Test + public void test01AccumStencilPBuffer() { + final GLProfile glp = GLProfile.get(GLProfile.GL2); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setAccumRedBits(16); + caps.setAccumGreenBits(16); + caps.setAccumBlueBits(16); + caps.setStencilBits(8); + caps.setPBuffer(true); + test(caps); + } + + public static void main(String[] args) { + org.junit.runner.JUnitCore.main(TestBug605FlippedImageNEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1AWT.java index 517d12578..ba93dcdcd 100755..100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1AWT.java @@ -1,22 +1,22 @@ /* * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. * Copyright (c) 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: - * + * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistribution 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. - * + * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. - * + * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A @@ -29,11 +29,11 @@ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * + * * You acknowledge that this software is not designed or intended for use * in the design, construction, operation or maintenance of any nuclear * facility. - * + * * Sun gratefully acknowledges that this software was originally authored * and developed by Kenneth Bradley Russell and Christopher John Kline. */ @@ -44,19 +44,27 @@ import java.lang.reflect.InvocationTargetException; import java.awt.BorderLayout; import java.awt.Frame; +import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesChooser; +import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; import javax.media.opengl.awt.GLCanvas; +import com.jogamp.opengl.test.junit.jogl.demos.es1.MultisampleDemoES1; import com.jogamp.opengl.test.junit.util.MiscUtils; import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestMultisampleES1AWT extends UITestCase { - static long durationPerTest = 250; // ms + static long durationPerTest = 60; // ms private GLCanvas canvas; public static void main(String[] args) { @@ -71,41 +79,52 @@ public class TestMultisampleES1AWT extends UITestCase { } @Test - public void testMultiSampleAA4() throws InterruptedException, InvocationTargetException { + public void testOnscreenMultiSampleAA0() throws InterruptedException, InvocationTargetException { + testMultiSampleAAImpl(0); + } + + @Test + public void testOnscreenMultiSampleAA4() throws InterruptedException, InvocationTargetException { testMultiSampleAAImpl(4); } @Test - public void testMultiSampleNone() throws InterruptedException, InvocationTargetException { - testMultiSampleAAImpl(0); + public void testOnscreenMultiSampleAA8() throws InterruptedException, InvocationTargetException { + testMultiSampleAAImpl(8); } - private void testMultiSampleAAImpl(int samples) throws InterruptedException, InvocationTargetException { + private void testMultiSampleAAImpl(int reqSamples) throws InterruptedException, InvocationTargetException { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); GLProfile glp = GLProfile.getMaxFixedFunc(true); GLCapabilities caps = new GLCapabilities(glp); GLCapabilitiesChooser chooser = new MultisampleChooser01(); - if(samples>0) { + if(reqSamples>0) { caps.setSampleBuffers(true); - caps.setNumSamples(samples); - // turns out we need to have alpha, - // otherwise no AA will be visible. - caps.setAlphaBits(1); + caps.setNumSamples(reqSamples); } - canvas = new GLCanvas(caps, chooser, null, null); - canvas.addGLEventListener(new MultisampleDemoES1(samples>0?true:false)); - - final Frame frame = new Frame("Multi Samples "+samples); + canvas = new GLCanvas(caps, chooser, null); + canvas.addGLEventListener(new MultisampleDemoES1(reqSamples>0?true:false)); + canvas.addGLEventListener(new GLEventListener() { + int displayCount = 0; + public void init(GLAutoDrawable drawable) {} + public void dispose(GLAutoDrawable drawable) {} + public void display(GLAutoDrawable drawable) { + snapshot(displayCount++, null, drawable.getGL(), screenshot, TextureIO.PNG, null); + } + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } + }); + + final Frame frame = new Frame("Multi Samples "+reqSamples); frame.setLayout(new BorderLayout()); canvas.setSize(512, 512); - frame.add(canvas, BorderLayout.CENTER); - frame.pack(); javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame.add(canvas, BorderLayout.CENTER); + frame.pack(); frame.setVisible(true); - frame.setLocation(0, 0); canvas.requestFocus(); canvas.display(); }}); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1NEWT.java index cdfeb2bad..cf30c50bd 100755..100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1NEWT.java @@ -40,17 +40,26 @@ package com.jogamp.opengl.test.junit.jogl.caps; +import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesChooser; +import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.jogl.demos.es1.MultisampleDemoES1; import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; -public class TestMultisampleES1NEWT { - static long durationPerTest = 500; // ms +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestMultisampleES1NEWT extends UITestCase { + static long durationPerTest = 60; // ms private GLWindow window; public static void main(String[] args) { @@ -65,35 +74,74 @@ public class TestMultisampleES1NEWT { } @Test - public void testMultiSampleAA4() throws InterruptedException { - testMultiSampleAAImpl(4); + public void testOnscreenMultiSampleAA0() throws InterruptedException { + testMultiSampleAAImpl(false, false, 0); } - // @Test - public void testMultiSampleNone() throws InterruptedException { - testMultiSampleAAImpl(0); + @Test + public void testOnscreenMultiSampleAA2() throws InterruptedException { + testMultiSampleAAImpl(false, false, 2); + } + + @Test + public void testOnscreenMultiSampleAA4() throws InterruptedException { + testMultiSampleAAImpl(false, false, 4); + } + + @Test + public void testOnscreenMultiSampleAA8() throws InterruptedException { + testMultiSampleAAImpl(false, false, 8); + } + + @Test + public void testOffscreenPBufferMultiSampleAA0() throws InterruptedException { + testMultiSampleAAImpl(false, true, 0); } - private void testMultiSampleAAImpl(int samples) throws InterruptedException { + @Test + public void testOffsreenPBufferMultiSampleAA8() throws InterruptedException { + testMultiSampleAAImpl(false, true, 8); + } + + @Test + public void testOffscreenFBOMultiSampleAA0() throws InterruptedException { + testMultiSampleAAImpl(true, false, 0); + } + + @Test + public void testOffsreenFBOMultiSampleAA8() throws InterruptedException { + testMultiSampleAAImpl(true, false, 8); + } + + private void testMultiSampleAAImpl(boolean useFBO, boolean usePBuffer, int reqSamples) throws InterruptedException { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); GLProfile glp = GLProfile.getMaxFixedFunc(true); GLCapabilities caps = new GLCapabilities(glp); GLCapabilitiesChooser chooser = new MultisampleChooser01(); - if(samples>0) { + caps.setAlphaBits(1); + caps.setFBO(useFBO); + caps.setPBuffer(usePBuffer); + + if(reqSamples>0) { caps.setSampleBuffers(true); - caps.setNumSamples(4); + caps.setNumSamples(reqSamples); } - // turns out we need to have alpha, - // otherwise no AA will be visible. - // This is done implicit now .. - // caps.setAlphaBits(1); window = GLWindow.create(caps); window.setCapabilitiesChooser(chooser); - window.addGLEventListener(new MultisampleDemoES1(samples>0?true:false)); + window.addGLEventListener(new MultisampleDemoES1(reqSamples>0?true:false)); + window.addGLEventListener(new GLEventListener() { + int displayCount = 0; + public void init(GLAutoDrawable drawable) {} + public void dispose(GLAutoDrawable drawable) {} + public void display(GLAutoDrawable drawable) { + snapshot(displayCount++, null, drawable.getGL(), screenshot, TextureIO.PNG, null); + } + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } + }); window.setSize(512, 512); window.setVisible(true); - window.setPosition(0, 0); window.requestFocus(); Thread.sleep(durationPerTest); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES2NEWT.java new file mode 100644 index 000000000..008568f68 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES2NEWT.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 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: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.test.junit.jogl.caps; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesChooser; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.jogl.demos.es2.MultisampleDemoES2; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestMultisampleES2NEWT extends UITestCase { + static long durationPerTest = 60; // ms + + public static void main(String[] args) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + durationPerTest = MiscUtils.atoi(args[++i], 500); + } + } + System.out.println("durationPerTest: "+durationPerTest); + String tstname = TestMultisampleES2NEWT.class.getName(); + org.junit.runner.JUnitCore.main(tstname); + } + + @Test + public void testOnscreenMultiSampleAA0() throws InterruptedException { + testMultiSampleAAImpl(false, false, 0); + } + + @Test + public void testOnscreenMultiSampleAA8() throws InterruptedException { + testMultiSampleAAImpl(false, false, 8); + } + + @Test + public void testOffscreenPBufferMultiSampleAA0() throws InterruptedException { + testMultiSampleAAImpl(false, true, 0); + } + + @Test(timeout = 3000) // 3s timeout + public void testOffsreenPBufferMultiSampleAA8() throws InterruptedException { + testMultiSampleAAImpl(false, true, 8); + } + + @Test(timeout = 3000) // 3s timeout + public void testOffscreenFBOMultiSampleAA0() throws InterruptedException { + testMultiSampleAAImpl(true, false, 0); + } + + @Test(timeout = 3000) // 3s timeout + public void testOffsreenFBOMultiSampleAA8() throws InterruptedException { + testMultiSampleAAImpl(true, false, 8); + } + + private void testMultiSampleAAImpl(boolean useFBO, boolean usePBuffer, int reqSamples) throws InterruptedException { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); + GLProfile glp = GLProfile.getGL2ES2(); + GLCapabilities caps = new GLCapabilities(glp); + GLCapabilitiesChooser chooser = new MultisampleChooser01(); + + caps.setAlphaBits(1); + caps.setFBO(useFBO); + caps.setPBuffer(usePBuffer); + + if(reqSamples>0) { + caps.setSampleBuffers(true); + caps.setNumSamples(reqSamples); + } + + final GLWindow window = GLWindow.create(caps); + window.setCapabilitiesChooser(chooser); + window.addGLEventListener(new MultisampleDemoES2(reqSamples>0?true:false)); + window.addGLEventListener(new GLEventListener() { + int displayCount = 0; + public void init(GLAutoDrawable drawable) {} + public void dispose(GLAutoDrawable drawable) {} + public void display(GLAutoDrawable drawable) { + snapshot(displayCount++, null, drawable.getGL(), screenshot, TextureIO.PNG, null); + } + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } + }); + window.setSize(512, 512); + window.setVisible(true); + window.requestFocus(); + + Thread.sleep(durationPerTest); + + window.destroy(); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestTranslucencyAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestTranslucencyAWT.java index 8e720965c..7ba6b0947 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestTranslucencyAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestTranslucencyAWT.java @@ -50,12 +50,15 @@ import javax.media.opengl.awt.GLCanvas; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import com.jogamp.common.util.ReflectionUtil; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.util.Animator; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestTranslucencyAWT extends UITestCase { static Dimension size; static long durationPerTest = 400; @@ -65,7 +68,6 @@ public class TestTranslucencyAWT extends UITestCase { public static void initClass() { size = new Dimension(400,200); glCaps = new GLCapabilities(null); - glCaps.setAlphaBits(8); glCaps.setBackgroundOpaque(false); } @@ -120,18 +122,21 @@ public class TestTranslucencyAWT extends UITestCase { GLAnimatorControl animator1 = new Animator(glCanvas); animator1.start(); - Container cont1 = new Container(); + final Container cont1 = new Container(); cont1.setLayout(new BorderLayout()); cont1.add(glCanvas, BorderLayout.CENTER); - cont1.setVisible(true); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + cont1.setVisible(true); + }}); frame1.setLayout(new BorderLayout()); frame1.add(cont1, BorderLayout.EAST); frame1.add(new Label("center"), BorderLayout.CENTER); - frame1.setLocation(0, 0); - frame1.setSize((int)size.getWidth(), (int)size.getHeight()); javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame1.setLocation(0, 0); + frame1.setSize((int)size.getWidth(), (int)size.getHeight()); frame1.pack(); frame1.setVisible(true); }}); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestTranslucencyNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestTranslucencyNEWT.java index 67e8524a3..8d65fdef3 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestTranslucencyNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestTranslucencyNEWT.java @@ -45,7 +45,10 @@ import org.junit.Assert; import org.junit.BeforeClass; import org.junit.AfterClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestTranslucencyNEWT extends UITestCase { static GLProfile glp; static int width, height; @@ -85,7 +88,10 @@ public class TestTranslucencyNEWT extends UITestCase { final GLWindow f_glWindow = glWindow; glWindow.addKeyListener(new KeyAdapter() { - public void keyTyped(KeyEvent e) { + public void keyReleased(KeyEvent e) { + if( !e.isPrintableKey() || e.isAutoRepeat() ) { + return; + } if(e.getKeyChar()=='f') { new Thread() { public void run() { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/GLFinishOnDisplay.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/GLFinishOnDisplay.java new file mode 100644 index 000000000..cb76f1057 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/GLFinishOnDisplay.java @@ -0,0 +1,40 @@ +/** + * Copyright (C) 2013 JogAmp Community. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.jogamp.opengl.test.junit.jogl.demos; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; + +public class GLFinishOnDisplay implements GLEventListener { + @Override + public void init(GLAutoDrawable drawable) { } + + @Override + public void dispose(GLAutoDrawable drawable) { } + + @Override + public void display(GLAutoDrawable drawable) { + drawable.getGL().glFinish(); + } + + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/GearsObject.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/GearsObject.java index b098e1de9..00d360f6e 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/GearsObject.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/GearsObject.java @@ -7,10 +7,10 @@ * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL @@ -36,7 +36,8 @@ public abstract class GearsObject { public static final FloatBuffer green = Buffers.newDirectFloatBuffer( new float[] { 0.0f, 0.8f, 0.2f, 0.7f } ); public static final FloatBuffer blue = Buffers.newDirectFloatBuffer( new float[] { 0.2f, 0.2f, 1.0f, 0.7f } ); public static final float M_PI = (float)Math.PI; - + + public final FloatBuffer gearColor; public GLArrayDataServer frontFace; public GLArrayDataServer frontSide; public GLArrayDataServer backFace; @@ -44,11 +45,23 @@ public abstract class GearsObject { public GLArrayDataServer outwardFace; public GLArrayDataServer insideRadiusCyl; public boolean isShared; + protected boolean validateBuffers = false; - public abstract GLArrayDataServer createInterleaved(int comps, int dataType, boolean normalized, int initialSize, int vboUsage); + public abstract GLArrayDataServer createInterleaved(boolean useMappedBuffers, int comps, int dataType, boolean normalized, int initialSize, int vboUsage); public abstract void addInterleavedVertexAndNormalArrays(GLArrayDataServer array, int components); - public abstract void draw(GL gl, float x, float y, float angle, FloatBuffer color); - + public abstract void draw(GL gl, float x, float y, float angle); + + private GLArrayDataServer createInterleavedClone(GLArrayDataServer ads) { + final GLArrayDataServer n = new GLArrayDataServer(ads); + n.setInterleavedOffset(0); + return n; + } + + private void init(GL gl, GLArrayDataServer array) { + array.enableBuffer(gl, true); + array.enableBuffer(gl, false); + } + public void destroy(GL gl) { if(!isShared) { // could be already destroyed by shared configuration @@ -76,28 +89,37 @@ public abstract class GearsObject { backFace=null; backSide=null; outwardFace=null; - insideRadiusCyl=null; + insideRadiusCyl=null; isShared = false; } - + public GearsObject ( GearsObject shared ) { isShared = true; - frontFace = shared.frontFace; - frontSide = shared.frontSide; - backFace = shared.backFace; - backSide = shared.backSide; - outwardFace = shared.outwardFace; - insideRadiusCyl = shared.insideRadiusCyl; + validateBuffers = shared.validateBuffers; + frontFace = createInterleavedClone(shared.frontFace); + addInterleavedVertexAndNormalArrays(frontFace, 3); + backFace = createInterleavedClone(shared.backFace); + addInterleavedVertexAndNormalArrays(backFace, 3); + frontSide = createInterleavedClone(shared.frontSide); + addInterleavedVertexAndNormalArrays(frontSide, 3); + backSide= createInterleavedClone(shared.backSide); + addInterleavedVertexAndNormalArrays(backSide, 3); + outwardFace = createInterleavedClone(shared.outwardFace); + addInterleavedVertexAndNormalArrays(outwardFace, 3); + insideRadiusCyl = createInterleavedClone(shared.insideRadiusCyl); + addInterleavedVertexAndNormalArrays(insideRadiusCyl, 3); + gearColor = shared.gearColor; } - + public GearsObject ( + GL gl, + boolean useMappedBuffers, + FloatBuffer gearColor, float inner_radius, float outer_radius, - float width, - int teeth, - float tooth_depth) + float width, int teeth, float tooth_depth, boolean validateBuffers) { - final float dz = width * 0.5f; + final float dz = width * 0.5f; int i; float r0, r1, r2; float angle, da; @@ -107,8 +129,10 @@ public abstract class GearsObject { float normal[] = new float[3]; // final int tris_per_tooth = 32; - isShared = false; - + this.validateBuffers = validateBuffers; + this.isShared = false; + this.gearColor = gearColor; + r0 = inner_radius; r1 = outer_radius - tooth_depth / 2.0f; r2 = outer_radius + tooth_depth / 2.0f; @@ -118,64 +142,75 @@ public abstract class GearsObject { s[4] = 0; // sin(0f) c[4] = 1; // cos(0f) - frontFace = createInterleaved(6, GL.GL_FLOAT, false, 4*teeth+2, GL.GL_STATIC_DRAW); + final int vboUsage = GL.GL_STATIC_DRAW; + + frontFace = createInterleaved(useMappedBuffers, 6, GL.GL_FLOAT, false, 4*teeth+2, vboUsage); addInterleavedVertexAndNormalArrays(frontFace, 3); - backFace = createInterleaved(6, GL.GL_FLOAT, false, 4*teeth+2, GL.GL_STATIC_DRAW); + backFace = createInterleaved(useMappedBuffers, 6, GL.GL_FLOAT, false, 4*teeth+2, vboUsage); addInterleavedVertexAndNormalArrays(backFace, 3); - frontSide = createInterleaved(6, GL.GL_FLOAT, false, 6*teeth, GL.GL_STATIC_DRAW); + frontSide = createInterleaved(useMappedBuffers, 6, GL.GL_FLOAT, false, 6*teeth, vboUsage); addInterleavedVertexAndNormalArrays(frontSide, 3); - backSide = createInterleaved(6, GL.GL_FLOAT, false, 6*teeth, GL.GL_STATIC_DRAW); + backSide = createInterleaved(useMappedBuffers, 6, GL.GL_FLOAT, false, 6*teeth, vboUsage); addInterleavedVertexAndNormalArrays(backSide, 3); - outwardFace = createInterleaved(6, GL.GL_FLOAT, false, 4*4*teeth+2, GL.GL_STATIC_DRAW); + outwardFace = createInterleaved(useMappedBuffers, 6, GL.GL_FLOAT, false, 4*4*teeth+2, vboUsage); addInterleavedVertexAndNormalArrays(outwardFace, 3); - insideRadiusCyl = createInterleaved(6, GL.GL_FLOAT, false, 2*teeth+2, GL.GL_STATIC_DRAW); + insideRadiusCyl = createInterleaved(useMappedBuffers, 6, GL.GL_FLOAT, false, 2*teeth+2, vboUsage); addInterleavedVertexAndNormalArrays(insideRadiusCyl, 3); + if( useMappedBuffers ) { + frontFace.mapStorage(gl, GL.GL_WRITE_ONLY); + backFace.mapStorage(gl, GL.GL_WRITE_ONLY); + frontSide.mapStorage(gl, GL.GL_WRITE_ONLY); + backSide.mapStorage(gl, GL.GL_WRITE_ONLY); + outwardFace.mapStorage(gl, GL.GL_WRITE_ONLY); + insideRadiusCyl.mapStorage(gl, GL.GL_WRITE_ONLY); + } + for (i = 0; i < teeth; i++) { angle = i * 2.0f * M_PI / teeth; sincos(angle + da * 0f, s, 0, c, 0); sincos(angle + da * 1f, s, 1, c, 1); sincos(angle + da * 2f, s, 2, c, 2); sincos(angle + da * 3f, s, 3, c, 3); - + /* front */ normal[0] = 0.0f; normal[1] = 0.0f; normal[2] = 1.0f; - + /* front face - GL.GL_TRIANGLE_STRIP */ vert(frontFace, r0 * c[0], r0 * s[0], dz, normal); vert(frontFace, r1 * c[0], r1 * s[0], dz, normal); vert(frontFace, r0 * c[0], r0 * s[0], dz, normal); vert(frontFace, r1 * c[3], r1 * s[3], dz, normal); - + /* front sides of teeth - GL.GL_TRIANGLES */ vert(frontSide, r1 * c[0], r1 * s[0], dz, normal); - vert(frontSide, r2 * c[1], r2 * s[1], dz, normal); + vert(frontSide, r2 * c[1], r2 * s[1], dz, normal); vert(frontSide, r2 * c[2], r2 * s[2], dz, normal); vert(frontSide, r1 * c[0], r1 * s[0], dz, normal); - vert(frontSide, r2 * c[2], r2 * s[2], dz, normal); + vert(frontSide, r2 * c[2], r2 * s[2], dz, normal); vert(frontSide, r1 * c[3], r1 * s[3], dz, normal); - + /* back */ normal[0] = 0.0f; normal[1] = 0.0f; normal[2] = -1.0f; - + /* back face - GL.GL_TRIANGLE_STRIP */ vert(backFace, r1 * c[0], r1 * s[0], -dz, normal); vert(backFace, r0 * c[0], r0 * s[0], -dz, normal); vert(backFace, r1 * c[3], r1 * s[3], -dz, normal); vert(backFace, r0 * c[0], r0 * s[0], -dz, normal); - + /* back sides of teeth - GL.GL_TRIANGLES*/ vert(backSide, r1 * c[3], r1 * s[3], -dz, normal); vert(backSide, r2 * c[2], r2 * s[2], -dz, normal); vert(backSide, r2 * c[1], r2 * s[1], -dz, normal); vert(backSide, r1 * c[3], r1 * s[3], -dz, normal); - vert(backSide, r2 * c[1], r2 * s[1], -dz, normal); + vert(backSide, r2 * c[1], r2 * s[1], -dz, normal); vert(backSide, r1 * c[0], r1 * s[0], -dz, normal); - + /* outward faces of teeth */ u = r2 * c[1] - r1 * c[0]; v = r2 * s[1] - r1 * s[0]; @@ -201,7 +236,7 @@ public abstract class GearsObject { normal[0] = ( r1 * s[3] - r2 * s[2] ); normal[1] = ( r1 * c[3] - r2 * c[2] ) * -1.0f ; vert(outwardFace, r2 * c[2], r2 * s[2], dz, normal); - vert(outwardFace, r2 * c[2], r2 * s[2], -dz, normal); + vert(outwardFace, r2 * c[2], r2 * s[2], -dz, normal); vert(outwardFace, r1 * c[3], r1 * s[3], dz, normal); vert(outwardFace, r1 * c[3], r1 * s[3], -dz, normal); @@ -211,7 +246,7 @@ public abstract class GearsObject { vert(outwardFace, r1 * c[3], r1 * s[3], -dz, normal); vert(outwardFace, r1 * c[0], r1 * s[0], dz, normal); vert(outwardFace, r1 * c[0], r1 * s[0], -dz, normal); - + /* inside radius cylinder */ normal[0] = c[0] * -1.0f; normal[1] = s[0] * -1.0f; @@ -226,16 +261,16 @@ public abstract class GearsObject { vert(frontFace, r0 * c[4], r0 * s[4], dz, normal); vert(frontFace, r1 * c[4], r1 * s[4], dz, normal); frontFace.seal(true); - + /* finish back face */ - normal[2] = -1.0f; + normal[2] = -1.0f; vert(backFace, r1 * c[4], r1 * s[4], -dz, normal); vert(backFace, r0 * c[4], r0 * s[4], -dz, normal); backFace.seal(true); - + backSide.seal(true); frontSide.seal(true); - + /* finish outward face */ sincos(da * 1f, s, 1, c, 1); u = r2 * c[1] - r1 * c[4]; @@ -247,7 +282,7 @@ public abstract class GearsObject { normal[1] = -u; normal[2] = 0.0f; vert(outwardFace, r1 * c[4], r1 * s[4], dz, normal); - vert(outwardFace, r1 * c[4], r1 * s[4], -dz, normal); + vert(outwardFace, r1 * c[4], r1 * s[4], -dz, normal); outwardFace.seal(true); /* finish inside radius cylinder */ @@ -257,6 +292,32 @@ public abstract class GearsObject { vert(insideRadiusCyl, r0 * c[4], r0 * s[4], -dz, normal); vert(insideRadiusCyl, r0 * c[4], r0 * s[4], dz, normal); insideRadiusCyl.seal(true); + + if( useMappedBuffers ) { + frontFace.unmapStorage(gl); + backFace.unmapStorage(gl); + frontSide.unmapStorage(gl); + backSide.unmapStorage(gl); + outwardFace.unmapStorage(gl); + insideRadiusCyl.unmapStorage(gl); + } else { + /** Init VBO and data .. */ + init(gl, frontFace); + init(gl, frontSide); + init(gl, backFace); + init(gl, backSide); + init(gl, outwardFace); + init(gl, insideRadiusCyl); + } + } + + @Override + public String toString() { + final int ffVBO = null != frontFace ? frontFace.getVBOName() : 0; + final int fsVBO = null != frontSide ? frontSide.getVBOName() : 0; + final int bfVBO = null != backFace ? backFace.getVBOName() : 0; + final int bsVBO = null != backSide ? backSide.getVBOName() : 0; + return "GearsObj[0x"+Integer.toHexString(hashCode())+", vbo ff "+ffVBO+", fs "+fsVBO+", bf "+bfVBO+", bs "+bsVBO+"]"; } static void vert(GLArrayDataServer array, float x, float y, float z, float n[]) { @@ -267,7 +328,7 @@ public abstract class GearsObject { array.putf(n[1]); array.putf(n[2]); } - + static void sincos(float x, float sin[], int sinIdx, float cos[], int cosIdx) { sin[sinIdx] = (float) Math.sin(x); cos[cosIdx] = (float) Math.cos(x); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/PointsDemo.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/PointsDemo.java new file mode 100644 index 000000000..4f2e4153e --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/PointsDemo.java @@ -0,0 +1,48 @@ +/** + * Copyright 2012 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.jogl.demos; + +import javax.media.opengl.GLEventListener; + +public abstract class PointsDemo implements GLEventListener { + int swapInterval = 0; + final int edge = 8; // 8*8 + + public PointsDemo(int swapInterval) { + this.swapInterval = swapInterval; + } + + public PointsDemo() { + this.swapInterval = 1; + } + + public abstract void setSmoothPoints(boolean v); + + public abstract void setPointParams(float minSize, float maxSize, float distAttenConst, float distAttenLinear, float distAttenQuadratic, float fadeThreshold); + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/TextureDraw01Accessor.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/TextureDraw01Accessor.java new file mode 100644 index 000000000..7283a204e --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/TextureDraw01Accessor.java @@ -0,0 +1,36 @@ +/** + * Copyright 2012 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.jogl.demos; + +import com.jogamp.opengl.util.texture.Texture; + +public interface TextureDraw01Accessor { + public void setKeepTextureBound(boolean v); + public Texture getTexture(); +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/TestTextureSequence.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/TextureSequenceDemo01.java index 6dfb11855..b015aebba 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/TestTextureSequence.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/TextureSequenceDemo01.java @@ -6,30 +6,28 @@ import javax.media.opengl.GL; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; -import jogamp.opengl.util.av.NullGLMediaPlayer; - import com.jogamp.common.util.IOUtil; import com.jogamp.opengl.util.texture.Texture; import com.jogamp.opengl.util.texture.TextureData; import com.jogamp.opengl.util.texture.TextureIO; import com.jogamp.opengl.util.texture.TextureSequence; -public class TestTextureSequence implements TextureSequence { - TextureSequence.TextureFrame frame = null; +public class TextureSequenceDemo01 implements TextureSequence { + TextureSequence.TextureFrame frame = null; int textureUnit = 0; protected int[] texMinMagFilter = { GL.GL_NEAREST, GL.GL_NEAREST }; protected int[] texWrapST = { GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE }; final boolean useBuildInTexLookup; - - public TestTextureSequence(boolean useBuildInTexLookup) { + + public TextureSequenceDemo01(boolean useBuildInTexLookup) { this.useBuildInTexLookup = useBuildInTexLookup; } - + public void initGLResources(GL gl) throws GLException { if(null == frame) { TextureData texData = null; try { - URLConnection urlConn = IOUtil.getResource("jogl/util/data/av/test-ntsc01-160x90.png", NullGLMediaPlayer.class.getClassLoader()); + URLConnection urlConn = IOUtil.getResource("jogl/util/data/av/test-ntsc01-57x32.png", this.getClass().getClassLoader()); if(null != urlConn) { texData = TextureIO.newTextureData(GLProfile.getGL2ES2(), urlConn.getInputStream(), false, TextureIO.PNG); } @@ -40,24 +38,29 @@ public class TestTextureSequence implements TextureSequence { frame = new TextureSequence.TextureFrame(tex); tex.bind(gl); gl.glTexParameteri(tex.getTarget(), GL.GL_TEXTURE_MIN_FILTER, texMinMagFilter[0]); - gl.glTexParameteri(tex.getTarget(), GL.GL_TEXTURE_MAG_FILTER, texMinMagFilter[1]); + gl.glTexParameteri(tex.getTarget(), GL.GL_TEXTURE_MAG_FILTER, texMinMagFilter[1]); gl.glTexParameteri(tex.getTarget(), GL.GL_TEXTURE_WRAP_S, texWrapST[0]); gl.glTexParameteri(tex.getTarget(), GL.GL_TEXTURE_WRAP_T, texWrapST[1]); } } - + public void destroyGLResources(GL gl) { if(null != frame) { frame.getTexture().destroy(gl); frame = null; } } - + public void destroy(GL gl) throws GLException { frame.getTexture().destroy(gl); - frame = null; + frame = null; } - + + @Override + public int getTextureTarget() { + return GL.GL_TEXTURE_2D; + } + @Override public int getTextureUnit() { return textureUnit; @@ -79,22 +82,22 @@ public class TestTextureSequence implements TextureSequence { } @Override - public TextureSequence.TextureFrame getNextTexture(GL gl, boolean blocking) throws IllegalStateException { + public TextureSequence.TextureFrame getNextTexture(GL gl) throws IllegalStateException { return frame; } - + @Override public String getRequiredExtensionsShaderStub() throws IllegalStateException { return "// TextTextureSequence: No extensions required\n"; } - + @Override public String getTextureSampler2DType() throws IllegalStateException { return "sampler2D" ; - } - + } + private String textureLookupFunctionName = "myTexture2D"; - + @Override public String getTextureLookupFunctionName(String desiredFuncName) throws IllegalStateException { if(useBuildInTexLookup) { @@ -105,7 +108,7 @@ public class TestTextureSequence implements TextureSequence { } return textureLookupFunctionName; } - + @Override public String getTextureLookupFragmentShaderImpl() throws IllegalStateException { if(useBuildInTexLookup) { 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 fb2c9c7ea..f4c5e8b2f 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 @@ -7,10 +7,10 @@ * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL @@ -21,11 +21,15 @@ package com.jogamp.opengl.test.junit.jogl.demos.es1; +import java.nio.FloatBuffer; + import javax.media.nativewindow.NativeWindow; import javax.media.opengl.GL; import javax.media.opengl.GL2ES1; +import javax.media.opengl.GL2ES2; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLPipelineFactory; import javax.media.opengl.GLProfile; import com.jogamp.newt.Window; @@ -35,19 +39,37 @@ 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.JoglVersion; import com.jogamp.opengl.test.junit.jogl.demos.GearsObject; +import com.jogamp.opengl.util.glsl.fixedfunc.FixedFuncUtil; +import com.jogamp.opengl.util.glsl.fixedfunc.ShaderSelectionMode; /** * GearsES1.java <BR> * @author Brian Paul (converted to Java by Ron Cemer and Sven Gothel) <P> */ public class GearsES1 implements GLEventListener { + private boolean debugFFPEmu = false; + private boolean verboseFFPEmu = false; + private boolean traceFFPEmu = false; + private boolean forceFFPEmu = false; + private boolean debug = false ; + private boolean trace = false ; + private final float pos[] = { 5.0f, 5.0f, 10.0f, 0.0f }; - private float view_rotx = 20.0f, view_roty = 30.0f, view_rotz = 0.0f; + private float view_rotx = 20.0f, view_roty = 30.0f; + private final float view_rotz = 0.0f; private GearsObject gear1=null, gear2=null, gear3=null; + private FloatBuffer gear1Color=GearsObject.red, gear2Color=GearsObject.green, gear3Color=GearsObject.blue; + private volatile boolean usesSharedGears = false; + private boolean useMappedBuffers = false; + private boolean validateBuffers = false; private float angle = 0.0f; - private int swapInterval; + private final int swapInterval; + private final MouseListener gearsMouse = new GearsMouseAdapter(); + private final KeyListener gearsKeys = new GearsKeyAdapter(); + private int prevMouseX, prevMouseY; @@ -58,8 +80,21 @@ public class GearsES1 implements GLEventListener { public GearsES1() { this.swapInterval = 1; } - - public void setGears(GearsObject g1, GearsObject g2, GearsObject g3) { + + public void setForceFFPEmu(boolean forceFFPEmu, boolean verboseFFPEmu, boolean debugFFPEmu, boolean traceFFPEmu) { + this.forceFFPEmu = forceFFPEmu; + this.verboseFFPEmu = verboseFFPEmu; + this.debugFFPEmu = debugFFPEmu; + this.traceFFPEmu = traceFFPEmu; + } + + public void setGearsColors(FloatBuffer gear1Color, FloatBuffer gear2Color, FloatBuffer gear3Color) { + this.gear1Color = gear1Color; + this.gear2Color = gear2Color; + this.gear3Color = gear3Color; + } + + public void setSharedGearsObjects(GearsObject g1, GearsObject g2, GearsObject g3) { gear1 = g1; gear2 = g2; gear3 = g3; @@ -79,69 +114,96 @@ public class GearsES1 implements GLEventListener { * @return gear3 */ public GearsObject getGear3() { return gear3; } - + + public boolean usesSharedGears() { return usesSharedGears; } + + public void setUseMappedBuffers(boolean v) { useMappedBuffers = v; } + public void setValidateBuffers(boolean v) { validateBuffers = v; } + public void init(GLAutoDrawable drawable) { System.err.println(Thread.currentThread()+" GearsES1.init ..."); - + // Use debug pipeline // drawable.setGL(new DebugGL(drawable.getGL())); GL _gl = drawable.getGL(); - // GL2ES1 gl = FixedFuncUtil.wrapFixedFuncEmul(_gl /*, true*/); - GL2ES1 gl = _gl.getGL2ES1(); - + + if(debugFFPEmu) { + // Debug .. + _gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", GL2ES2.class, _gl, null) ); + debug = false; + } + if(traceFFPEmu) { + // Trace .. + _gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", GL2ES2.class, _gl, new Object[] { System.err } ) ); + trace = false; + } + GL2ES1 gl = FixedFuncUtil.wrapFixedFuncEmul(_gl, ShaderSelectionMode.AUTO, null, forceFFPEmu, verboseFFPEmu); + + if(debug) { + try { + // Debug .. + gl = (GL2ES1) gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", GL2ES1.class, gl, null) ); + } catch (Exception e) {e.printStackTrace();} + } + if(trace) { + try { + // Trace .. + gl = (GL2ES1) gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", GL2ES1.class, gl, new Object[] { System.err } ) ); + } catch (Exception e) {e.printStackTrace();} + } + + System.err.println("GearsES1 init on "+Thread.currentThread()); System.err.println("Chosen GLCapabilities: " + drawable.getChosenGLCapabilities()); System.err.println("INIT GL IS: " + gl.getClass().getName()); - System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR)); - System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER)); - System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION)); + System.err.println(JoglVersion.getGLStrings(gl, null, false).toString()); gl.glLightfv(GL2ES1.GL_LIGHT0, GL2ES1.GL_POSITION, pos, 0); gl.glEnable(GL.GL_CULL_FACE); gl.glEnable(GL2ES1.GL_LIGHTING); gl.glEnable(GL2ES1.GL_LIGHT0); gl.glEnable(GL2ES1.GL_DEPTH_TEST); - + /* make the gears */ if(null == gear1) { - gear1 = new GearsObjectES1(1.0f, 4.0f, 1.0f, 20, 0.7f); + gear1 = new GearsObjectES1(gl, useMappedBuffers, gear1Color, 1.0f, 4.0f, 1.0f, 20, 0.7f, validateBuffers); System.err.println("gear1 created: "+gear1); } else { + usesSharedGears = true; System.err.println("gear1 reused: "+gear1); } - + if(null == gear2) { - gear2 = new GearsObjectES1(0.5f, 2.0f, 2.0f, 10, 0.7f); + gear2 = new GearsObjectES1(gl, useMappedBuffers, gear2Color, 0.5f, 2.0f, 2.0f, 10, 0.7f, validateBuffers); System.err.println("gear2 created: "+gear2); } else { + usesSharedGears = true; System.err.println("gear2 reused: "+gear2); } - + if(null == gear3) { - gear3 = new GearsObjectES1(1.3f, 2.0f, 0.5f, 10, 0.7f); + gear3 = new GearsObjectES1(gl, useMappedBuffers, gear3Color, 1.3f, 2.0f, 0.5f, 10, 0.7f, validateBuffers); System.err.println("gear3 created: "+gear3); } else { + usesSharedGears = true; System.err.println("gear3 reused: "+gear3); } - + gl.glEnable(GL2ES1.GL_NORMALIZE); - - // MouseListener gearsMouse = new TraceMouseAdapter(new GearsMouseAdapter()); - MouseListener gearsMouse = new GearsMouseAdapter(); - KeyListener gearsKeys = new GearsKeyAdapter(); - if (drawable instanceof Window) { - Window window = (Window) drawable; + final Object upstreamWidget = drawable.getUpstreamWidget(); + if (upstreamWidget instanceof Window) { + final Window window = (Window) upstreamWidget; window.addMouseListener(gearsMouse); window.addKeyListener(gearsKeys); - } else if (GLProfile.isAWTAvailable() && drawable instanceof java.awt.Component) { - java.awt.Component comp = (java.awt.Component) drawable; + } else if (GLProfile.isAWTAvailable() && upstreamWidget instanceof java.awt.Component) { + final java.awt.Component comp = (java.awt.Component) upstreamWidget; new com.jogamp.newt.event.awt.AWTMouseAdapter(gearsMouse).addTo(comp); new com.jogamp.newt.event.awt.AWTKeyAdapter(gearsKeys).addTo(comp); } System.err.println(Thread.currentThread()+" GearsES1.init FIN"); } - + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { System.err.println(Thread.currentThread()+" GearsES1.reshape "+x+"/"+y+" "+width+"x"+height+", swapInterval "+swapInterval); GL2ES1 gl = drawable.getGL().getGL2ES1(); @@ -166,6 +228,12 @@ public class GearsES1 implements GLEventListener { public void dispose(GLAutoDrawable drawable) { System.err.println(Thread.currentThread()+" GearsES1.dispose ... "); + final Object upstreamWidget = drawable.getUpstreamWidget(); + if (upstreamWidget instanceof Window) { + final Window window = (Window) upstreamWidget; + window.removeMouseListener(gearsMouse); + window.removeKeyListener(gearsKeys); + } GL gl = drawable.getGL(); gear1.destroy(gl); gear1 = null; @@ -176,7 +244,7 @@ public class GearsES1 implements GLEventListener { System.err.println(Thread.currentThread()+" GearsES1.dispose FIN"); } - public void display(GLAutoDrawable drawable) { + public void display(GLAutoDrawable drawable) { // Turn the gears' teeth angle += 2.0f; @@ -184,8 +252,9 @@ public class GearsES1 implements GLEventListener { GL2ES1 gl = drawable.getGL().getGL2ES1(); final boolean hasFocus; - if(drawable.getNativeSurface() instanceof NativeWindow) { - hasFocus = ((NativeWindow)drawable.getNativeSurface()).hasFocus(); + final Object upstreamWidget = drawable.getUpstreamWidget(); + if(upstreamWidget instanceof NativeWindow) { + hasFocus = ((NativeWindow)upstreamWidget).hasFocus(); } else { hasFocus = true; } @@ -194,10 +263,10 @@ public class GearsES1 implements GLEventListener { } else { gl.glClearColor(0.2f, 0.2f, 0.2f, 0.0f); } - + // Special handling for the case where the GLJPanel is translucent // and wants to be composited with other Java 2D content - if (GLProfile.isAWTAvailable() && + if (GLProfile.isAWTAvailable() && (drawable instanceof javax.media.opengl.awt.GLJPanel) && !((javax.media.opengl.awt.GLJPanel) drawable).isOpaque() && ((javax.media.opengl.awt.GLJPanel) drawable).shouldPreserveColorBufferIfTranslucent()) { @@ -207,25 +276,25 @@ public class GearsES1 implements GLEventListener { } gl.glNormal3f(0.0f, 0.0f, 1.0f); - + // Rotate the entire assembly of gears based on how the user // dragged the mouse around gl.glPushMatrix(); gl.glRotatef(view_rotx, 1.0f, 0.0f, 0.0f); 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, GearsObject.red); - gear2.draw(gl, 3.1f, -2.0f, -2.0f * angle - 9.0f, GearsObject.green); - gear3.draw(gl, -3.1f, 4.2f, -2.0f * angle - 25.0f, GearsObject.blue); - + + 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 gl.glPopMatrix(); } - - class GearsKeyAdapter extends KeyAdapter { + + class GearsKeyAdapter extends KeyAdapter { public void keyPressed(KeyEvent e) { int kc = e.getKeyCode(); if(KeyEvent.VK_LEFT == kc) { @@ -239,16 +308,16 @@ public class GearsES1 implements GLEventListener { } } } - + class GearsMouseAdapter extends MouseAdapter { public void mousePressed(MouseEvent e) { prevMouseX = e.getX(); prevMouseY = e.getY(); } - + public void mouseReleased(MouseEvent e) { } - + public void mouseDragged(MouseEvent e) { int x = e.getX(); int y = e.getY(); @@ -267,7 +336,7 @@ public class GearsES1 implements GLEventListener { } float thetaY = 360.0f * ( (float)(x-prevMouseX)/(float)width); float thetaX = 360.0f * ( (float)(prevMouseY-y)/(float)height); - + prevMouseX = x; prevMouseY = y; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsObjectES1.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsObjectES1.java index 1208dad61..777fb04ae 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsObjectES1.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsObjectES1.java @@ -7,10 +7,10 @@ * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL @@ -24,9 +24,10 @@ import java.nio.FloatBuffer; import javax.media.opengl.GL; import javax.media.opengl.GL2ES1; +import javax.media.opengl.GLBufferStorage; +import javax.media.opengl.GLException; import javax.media.opengl.fixedfunc.GLPointerFunc; - import com.jogamp.opengl.test.junit.jogl.demos.GearsObject; import com.jogamp.opengl.util.GLArrayDataServer; @@ -36,45 +37,64 @@ import com.jogamp.opengl.util.GLArrayDataServer; */ public class GearsObjectES1 extends GearsObject { - public GearsObjectES1(float inner_radius, float outer_radius, float width, - int teeth, float tooth_depth) { - super(inner_radius, outer_radius, width, teeth, tooth_depth); + public GearsObjectES1(GL gl, boolean useMappedBuffers, FloatBuffer gearColor, float inner_radius, + float outer_radius, float width, int teeth, float tooth_depth, boolean validateBuffers) { + super(gl, useMappedBuffers, gearColor, inner_radius, outer_radius, width, teeth, tooth_depth, validateBuffers); } @Override - public GLArrayDataServer createInterleaved(int comps, int dataType, boolean normalized, int initialSize, int vboUsage) { - return GLArrayDataServer.createFixedInterleaved(comps, dataType, normalized, initialSize, vboUsage); + public GLArrayDataServer createInterleaved(boolean useMappedBuffers, int comps, int dataType, boolean normalized, int initialSize, int vboUsage) { + if( useMappedBuffers ) { + return GLArrayDataServer.createFixedInterleavedMapped(comps, dataType, normalized, initialSize, vboUsage); + } else { + return GLArrayDataServer.createFixedInterleaved(comps, dataType, normalized, initialSize, vboUsage); + } } - + @Override - public void addInterleavedVertexAndNormalArrays(GLArrayDataServer array, - int components) { - array.addFixedSubArray(GLPointerFunc.GL_VERTEX_ARRAY, 3, GL.GL_ARRAY_BUFFER); - array.addFixedSubArray(GLPointerFunc.GL_NORMAL_ARRAY, 3, GL.GL_ARRAY_BUFFER); + public void addInterleavedVertexAndNormalArrays(GLArrayDataServer array, int components) { + array.addFixedSubArray(GLPointerFunc.GL_VERTEX_ARRAY, components, GL.GL_ARRAY_BUFFER); + array.addFixedSubArray(GLPointerFunc.GL_NORMAL_ARRAY, components, GL.GL_ARRAY_BUFFER); } private void draw(GL2ES1 gl, GLArrayDataServer array, int mode) { - array.enableBuffer(gl, true); - gl.glDrawArrays(mode, 0, array.getElementCount()); - array.enableBuffer(gl, false); + if( !isShared || gl.glIsBuffer(array.getVBOName()) ) { + array.enableBuffer(gl, true); + if( validateBuffers ) { + final int bufferTarget = array.getVBOTarget(); + final int bufferName = array.getVBOName(); + final long bufferSize = array.getSizeInBytes(); + final int hasBufferName = gl.getBoundBuffer(bufferTarget); + final GLBufferStorage hasStorage = gl.getBufferStorage(hasBufferName); + final boolean ok = bufferName == hasBufferName && + bufferName == hasStorage.getName() && + bufferSize == hasStorage.getSize(); + if( !ok ) { + throw new GLException("GLBufferStorage Validation Error: Target[exp 0x"+Integer.toHexString(bufferTarget)+", has 0x"+Integer.toHexString(bufferTarget)+ + ", Name[exp "+bufferName+", has "+hasBufferName+", Size exp "+bufferSize+", Storage "+hasStorage+"]"); + } + } + gl.glDrawArrays(mode, 0, array.getElementCount()); + array.enableBuffer(gl, false); + } } @Override - public void draw(GL _gl, float x, float y, float angle, FloatBuffer color) { - GL2ES1 gl = _gl.getGL2ES1(); + public void draw(GL _gl, float x, float y, float angle) { + GL2ES1 gl = _gl.getGL2ES1(); gl.glPushMatrix(); gl.glTranslatef(x, y, 0f); gl.glRotatef(angle, 0f, 0f, 1f); - gl.glMaterialfv(GL2ES1.GL_FRONT_AND_BACK, GL2ES1.GL_AMBIENT_AND_DIFFUSE, color); - + gl.glMaterialfv(GL2ES1.GL_FRONT_AND_BACK, GL2ES1.GL_AMBIENT_AND_DIFFUSE, gearColor); + gl.glShadeModel(GL2ES1.GL_FLAT); draw(gl, frontFace, GL.GL_TRIANGLE_STRIP); draw(gl, frontSide, GL.GL_TRIANGLES); draw(gl, backFace, GL.GL_TRIANGLE_STRIP); draw(gl, backSide, GL.GL_TRIANGLES); draw(gl, outwardFace, GL.GL_TRIANGLE_STRIP); - gl.glShadeModel(GL2ES1.GL_SMOOTH); + gl.glShadeModel(GL2ES1.GL_SMOOTH); draw(gl, insideRadiusCyl, GL.GL_TRIANGLE_STRIP); gl.glPopMatrix(); - } + } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/caps/MultisampleDemoES1.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/MultisampleDemoES1.java index 0aaf4b020..4b4c7f2d8 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/caps/MultisampleDemoES1.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/MultisampleDemoES1.java @@ -38,24 +38,16 @@ * and developed by Kenneth Bradley Russell and Christopher John Kline. */ -package com.jogamp.opengl.test.junit.jogl.caps; +package com.jogamp.opengl.test.junit.jogl.demos.es1; -import jogamp.opengl.x11.glx.GLX; -import jogamp.opengl.x11.glx.X11GLXGraphicsConfiguration; -import javax.media.nativewindow.AbstractGraphicsConfiguration; -import javax.media.nativewindow.NativeWindowFactory; import javax.media.opengl.GL; import javax.media.opengl.GL2ES1; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLEventListener; -import javax.media.opengl.GLPipelineFactory; import com.jogamp.opengl.util.ImmModeSink; -class MultisampleDemoES1 implements GLEventListener { - - static boolean glDebug = false; - static boolean glTrace = false; +public class MultisampleDemoES1 implements GLEventListener { boolean multisample; ImmModeSink immModeSink; @@ -70,30 +62,7 @@ class MultisampleDemoES1 implements GLEventListener { System.err.println(); System.err.println("Chosen : " + drawable.getChosenGLCapabilities()); System.err.println(); - if (!drawable.getGL().isGLES() && NativeWindowFactory.TYPE_X11.equals(NativeWindowFactory.getNativeWindowType(false))) { - AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration(); - X11GLXGraphicsConfiguration x11config = (X11GLXGraphicsConfiguration) config; - long display = drawable.getNativeSurface().getDisplayHandle(); - int[] foo = new int[1]; - GLX.glXGetFBConfigAttrib(display, x11config.getFBConfig(), GLX.GLX_SAMPLES, foo, 0); - System.out.println("GLX_SAMPLES " + foo[0]); - GLX.glXGetFBConfigAttrib(display, x11config.getFBConfig(), GLX.GLX_SAMPLE_BUFFERS, foo, 0); - System.out.println("GLX_SAMPLE_BUFFERS " + foo[0]); - } - GL _gl = drawable.getGL(); - if (glDebug) { - try { - // Debug .. - _gl = _gl.getContext().setGL(GLPipelineFactory.create("javax.media.opengl.Debug", GL2ES1.class, _gl, null)); - if (glTrace) { - // Trace .. - _gl = _gl.getContext().setGL(GLPipelineFactory.create("javax.media.opengl.Trace", GL2ES1.class, _gl, new Object[]{System.err})); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - GL2ES1 gl = _gl.getGL2ES1(); + GL2ES1 gl = drawable.getGL().getGL2ES1(); if (multisample) { gl.glEnable(GL.GL_MULTISAMPLE); } @@ -108,11 +77,12 @@ class MultisampleDemoES1 implements GLEventListener { if (multisample) { gl.glDisable(GL.GL_MULTISAMPLE); } - immModeSink = ImmModeSink.createFixed(gl, GL.GL_STATIC_DRAW, 40, - 3, GL.GL_FLOAT, // vertex - 0, GL.GL_FLOAT, // color - 0, GL.GL_FLOAT,// normal - 0, GL.GL_FLOAT); // texture + immModeSink = ImmModeSink.createFixed(40, + 3, GL.GL_FLOAT, // vertex + 0, GL.GL_FLOAT, // color + 0, GL.GL_FLOAT, // normal + 0, GL.GL_FLOAT, // texCoords + GL.GL_STATIC_DRAW); final int numSteps = 20; final double increment = Math.PI / numSteps; final double radius = 1; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/OlympicES1.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/OlympicES1.java new file mode 100644 index 000000000..04fe26420 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/OlympicES1.java @@ -0,0 +1,357 @@ +/** + * OlympicGL2 + */ + +package com.jogamp.opengl.test.junit.jogl.demos.es1; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES1; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLPipelineFactory; +import javax.media.opengl.glu.GLU; +import javax.media.opengl.glu.gl2es1.GLUgl2es1; + +import com.jogamp.opengl.util.ImmModeSink; +import com.jogamp.opengl.util.glsl.fixedfunc.FixedFuncUtil; +import com.jogamp.opengl.util.glsl.fixedfunc.ShaderSelectionMode; + +import java.lang.Math; + +public class OlympicES1 implements GLEventListener +{ + private boolean debugFFPEmu = false; + private boolean verboseFFPEmu = false; + private boolean traceFFPEmu = false; + private boolean forceFFPEmu = false; + private boolean debug = false ; + private boolean trace = false ; + + // private static final double M_PI= 3.141592654; + private static final double M_2PI= 2*3.141592654; + + private static final int + // XSIZE= 100, + // YSIZE= 75, + RINGS= 5, + BLUERING= 0, + BLACKRING= 1, + REDRING= 2, + YELLOWRING =3, + GREENRING =4, + // BACKGROUND =8, + BLACK = 0, + RED=1, + GREEN=2, + YELLOW=3, + BLUE=4 + // ,MAGENTA=5, + // CYAN=6, + // WHITE=7 + ; + + private byte rgb_colors[][]; + private int mapped_colors[]; + private float dests[][]; + private float offsets[][]; + private float angs[]; + private float rotAxis[][]; + private int iters[]; + private ImmModeSink theTorus; + + private float lmodel_ambient[] = {0.0f, 0.0f, 0.0f, 0.0f}; + private float lmodel_twoside[] = {0.0f, 0.0f, 0.0f, 0.0f}; + // private float lmodel_local[] = {0.0f, 0.0f, 0.0f, 0.0f}; + private float light0_ambient[] = {0.1f, 0.1f, 0.1f, 1.0f}; + private float light0_diffuse[] = {1.0f, 1.0f, 1.0f, 0.0f}; + private float light0_position[] = {0.8660254f, 0.5f, 1f, 0f}; + private float light0_specular[] = {1.0f, 1.0f, 1.0f, 0.0f}; + private float bevel_mat_ambient[] = {0.0f, 0.0f, 0.0f, 1.0f}; + private float bevel_mat_shininess[] = {40.0f, 0f, 0f, 0f}; + private float bevel_mat_specular[] = {1.0f, 1.0f, 1.0f, 0.0f}; + private float bevel_mat_diffuse[] = {1.0f, 0.0f, 0.0f, 0.0f}; + private int swapInterval; + private GLU glu; + + public OlympicES1() { + swapInterval = 1; + } + + public OlympicES1(int swapInterval) { + this.swapInterval = swapInterval; + } + + public void setForceFFPEmu(boolean forceFFPEmu, boolean verboseFFPEmu, boolean debugFFPEmu, boolean traceFFPEmu) { + this.forceFFPEmu = forceFFPEmu; + this.verboseFFPEmu = verboseFFPEmu; + this.debugFFPEmu = debugFFPEmu; + this.traceFFPEmu = traceFFPEmu; + } + + public void init(GLAutoDrawable drawable) + { + GL _gl = drawable.getGL(); + + if(debugFFPEmu) { + // Debug .. + _gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", GL2ES2.class, _gl, null) ); + debug = false; + } + if(traceFFPEmu) { + // Trace .. + _gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", GL2ES2.class, _gl, new Object[] { System.err } ) ); + trace = false; + } + GL2ES1 gl = FixedFuncUtil.wrapFixedFuncEmul(_gl, ShaderSelectionMode.AUTO, null, forceFFPEmu, verboseFFPEmu); + + if(debug) { + try { + // Debug .. + gl = (GL2ES1) gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", GL2ES1.class, gl, null) ); + } catch (Exception e) {e.printStackTrace();} + } + if(trace) { + try { + // Trace .. + gl = (GL2ES1) gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", GL2ES1.class, gl, new Object[] { System.err } ) ); + } catch (Exception e) {e.printStackTrace();} + } + + System.err.println("OlympicES1 init on "+Thread.currentThread()); + System.err.println("Chosen GLCapabilities: " + drawable.getChosenGLCapabilities()); + System.err.println("INIT GL IS: " + gl.getClass().getName()); + System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR)); + System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER)); + System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION)); + System.err.println("GL GLSL: "+gl.hasGLSL()+", has-compiler-func: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none")); + System.err.println("GL FBO: basic "+ gl.hasBasicFBOSupport()+", full "+gl.hasFullFBOSupport()); + System.err.println("GL Profile: "+gl.getGLProfile()); + System.err.println("GL:" + gl + ", " + gl.getContext().getGLVersion()); + + glu = GLUgl2es1.createGLU(gl); + + rgb_colors=new byte[RINGS][3]; + mapped_colors=new int [RINGS]; + dests=new float [RINGS][3]; + offsets=new float[RINGS][3]; + angs=new float[RINGS]; + rotAxis=new float[RINGS][3]; + iters=new int[RINGS]; + + int i; + float top_y = 1.0f; + float bottom_y = 0.0f; + float top_z = 0.15f; + float bottom_z = 0.69f; + float spacing = 2.5f; + + for (i = 0; i < RINGS; i++) { + rgb_colors[i][0] = rgb_colors[i][1] = rgb_colors[i][2] = (byte)0; + } + rgb_colors[BLUERING][2] = (byte)255; + rgb_colors[REDRING][0] = (byte)255; + rgb_colors[GREENRING][1] = (byte)255; + rgb_colors[YELLOWRING][0] = (byte)255; + rgb_colors[YELLOWRING][1] = (byte)255; + mapped_colors[BLUERING] = BLUE; + mapped_colors[REDRING] = RED; + mapped_colors[GREENRING] = GREEN; + mapped_colors[YELLOWRING] = YELLOW; + mapped_colors[BLACKRING] = BLACK; + + dests[BLUERING][0] = -spacing; + dests[BLUERING][1] = top_y; + dests[BLUERING][2] = top_z; + + dests[BLACKRING][0] = 0.0f; + dests[BLACKRING][1] = top_y; + dests[BLACKRING][2] = top_z; + + dests[REDRING][0] = spacing; + dests[REDRING][1] = top_y; + dests[REDRING][2] = top_z; + + dests[YELLOWRING][0] = -spacing / 2.0f; + dests[YELLOWRING][1] = bottom_y; + dests[YELLOWRING][2] = bottom_z; + + dests[GREENRING][0] = spacing / 2.0f; + dests[GREENRING][1] = bottom_y; + dests[GREENRING][2] = bottom_z; + + theTorus = ImmModeSink.createFixed(40, + 3, GL.GL_FLOAT, // vertex + 0, GL.GL_FLOAT, // color + 3, GL.GL_FLOAT, // normal + 0, GL.GL_FLOAT, // texCoords + GL.GL_STATIC_DRAW); + FillTorus(gl, theTorus, 0.1f, 8, 1.0f, 25); + + gl.glEnable(GL.GL_CULL_FACE); + gl.glCullFace(GL.GL_BACK); + gl.glEnable(GL.GL_DEPTH_TEST); + gl.glClearDepth(1.0); + + gl.glLightfv(GL2ES1.GL_LIGHT0, GL2ES1.GL_AMBIENT, light0_ambient, 0); + gl.glLightfv(GL2ES1.GL_LIGHT0, GL2ES1.GL_DIFFUSE, light0_diffuse, 0); + gl.glLightfv(GL2ES1.GL_LIGHT0, GL2ES1.GL_SPECULAR, light0_specular, 0); + gl.glLightfv(GL2ES1.GL_LIGHT0, GL2ES1.GL_POSITION, light0_position, 0); + gl.glEnable(GL2ES1.GL_LIGHT0); + + // gl.glLightModelfv(GL2.GL_LIGHT_MODEL_LOCAL_VIEWER, lmodel_local, 0); + gl.glLightModelfv(GL2ES1.GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside, 0); + gl.glLightModelfv(GL2ES1.GL_LIGHT_MODEL_AMBIENT, lmodel_ambient, 0); + gl.glEnable(GL2ES1.GL_LIGHTING); + + gl.glClearColor(0.5f, 0.5f, 0.5f, 0.0f); + + gl.glMaterialfv(GL.GL_FRONT, GL2ES1.GL_AMBIENT, bevel_mat_ambient, 0); + gl.glMaterialfv(GL.GL_FRONT, GL2ES1.GL_SHININESS, bevel_mat_shininess, 0); + gl.glMaterialfv(GL.GL_FRONT, GL2ES1.GL_SPECULAR, bevel_mat_specular, 0); + gl.glMaterialfv(GL.GL_FRONT, GL2ES1.GL_DIFFUSE, bevel_mat_diffuse, 0); + + // gl.glColorMaterial(GL.GL_FRONT_AND_BACK, GL2ES1.GL_DIFFUSE); + gl.glEnable(GL2ES1.GL_COLOR_MATERIAL); + gl.glShadeModel(GL2ES1.GL_SMOOTH); + + ReInit(); + t0 = System.currentTimeMillis(); + tL = t0; + } + + + @Override + public void dispose(GLAutoDrawable glad) { + glu.destroy(); + glu = null; + theTorus.destroy(glad.getGL()); + theTorus = null; + } + + + @Override + public void reshape(GLAutoDrawable glad, int x, int y, int width, int height) { + final GL2ES1 gl = glad.getGL().getGL2ES1(); + gl.setSwapInterval(swapInterval); + + gl.glMatrixMode(GL2ES1.GL_PROJECTION); + gl.glLoadIdentity(); + glu.gluPerspective(45f, (float) width / (float) height, 0.1f, 100.0f); + gl.glMatrixMode(GL2ES1.GL_MODELVIEW); + gl.glLoadIdentity(); + glu.gluLookAt(0, 0, 10, 0, 0, 0, 0, 1, 0); + } + + @Override + public void display(GLAutoDrawable glad) { + final GL2ES1 gl = glad.getGL().getGL2ES1(); + int i; + + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + + gl.glPushMatrix(); + for (i = 0; i < RINGS; i++) { + gl.glColor4ub(rgb_colors[i][0], rgb_colors[i][1], rgb_colors[i][2], (byte)1); + gl.glPushMatrix(); + gl.glTranslatef(dests[i][0] + offsets[i][0], + dests[i][1] + offsets[i][1], + dests[i][2] + offsets[i][2]); + gl.glRotatef(angs[i], rotAxis[i][0], rotAxis[i][1], rotAxis[i][2]); + theTorus.draw(gl, true); + gl.glPopMatrix(); + } + gl.glPopMatrix(); + animationCalc(); + } + + long t0, tL; + + protected void animationCalc() + { + int i, j; + + long t1 = System.currentTimeMillis(); + if( t1 - tL < 50 ) { + return; + } + + for (i = 0; i < RINGS; i++) { + if (iters[i]!=0) { + for (j = 0; j < 3; j++) { + offsets[i][j] = Clamp(iters[i], offsets[i][j]); + } + angs[i] = Clamp(iters[i], angs[i]); + iters[i]--; + } + } + if (iters[0]==0) + { + ReInit(); + } + + tL = t1; + } + + protected void ReInit() { + int i; + float deviation; + + deviation = MyRand() / 2; + deviation = deviation * deviation; + for (i = 0; i < RINGS; i++) { + offsets[i][0] = MyRand(); + offsets[i][1] = MyRand(); + offsets[i][2] = MyRand(); + angs[i] = (float) (260.0 * MyRand()); + rotAxis[i][0] = MyRand(); + rotAxis[i][1] = MyRand(); + rotAxis[i][2] = MyRand(); + iters[i] = ( int ) (deviation * MyRand() + 60.0); + } + } + + protected static void FillTorus(GL gl, ImmModeSink immModeSink, float rc, int numc, float rt, int numt) + { + int i, j, k; + double s, t; + float x, y, z; + + for (i = 0; i < numc; i++) { + immModeSink.glBegin(ImmModeSink.GL_QUAD_STRIP); + for (j = 0; j <= numt; j++) { + for (k = 1; k >= 0; k--) { + s = (i + k) % numc + 0.5; + t = j % numt; + + x = (float) Math.cos(t * M_2PI / numt) * (float) Math.cos(s * M_2PI / numc); + y = (float) Math.sin(t * M_2PI / numt) * (float) Math.cos(s * M_2PI / numc); + z = (float) Math.sin(s * M_2PI / numc); + immModeSink.glNormal3f(x, y, z); + + x = (rt + rc * (float) Math.cos(s * M_2PI / numc)) * (float) Math.cos(t * M_2PI / numt); + y = (rt + rc * (float) Math.cos(s * M_2PI / numc)) * (float) Math.sin(t * M_2PI / numt); + z = rc * (float) Math.sin(s * M_2PI / numc); + immModeSink.glVertex3f(x, y, z); + } + } + immModeSink.glEnd(gl, false); + } + } + + protected float Clamp(int iters_left, float t) + { + if (iters_left < 3) { + return 0.0f; + } + return (iters_left - 2) * t / iters_left; + } + + protected float MyRand() + { + // return 10.0 * (drand48() - 0.5); + return (float) ( 10.0 * (Math.random() - 0.5) ); + } + +} + diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/OneTriangle.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/OneTriangle.java index 8c9f53b82..4b05f1a42 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/OneTriangle.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/OneTriangle.java @@ -61,11 +61,12 @@ public class OneTriangle { // draw a triangle filling the window gl.glLoadIdentity(); - ImmModeSink immModeSink = ImmModeSink.createFixed(gl, GL.GL_STATIC_DRAW, 3, - 3, GL.GL_FLOAT, // vertex - 3, GL.GL_FLOAT, // color - 0, GL.GL_FLOAT,// normal - 0, GL.GL_FLOAT); // texture + ImmModeSink immModeSink = ImmModeSink.createFixed(3*3, + 3, GL.GL_FLOAT, // vertex + 3, GL.GL_FLOAT, // color + 0, GL.GL_FLOAT, // normal + 0, GL.GL_FLOAT, // texCoords + GL.GL_STATIC_DRAW); immModeSink.glBegin(GL.GL_TRIANGLES); immModeSink.glColor3f( 1, 0, 0 ); immModeSink.glVertex2f( 0, 0 ); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/PointsDemoES1.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/PointsDemoES1.java new file mode 100644 index 000000000..5f0c99a3d --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/PointsDemoES1.java @@ -0,0 +1,198 @@ +/** + * Copyright 2012 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.jogl.demos.es1; + +import java.nio.FloatBuffer; + +import com.jogamp.common.nio.Buffers; +import com.jogamp.opengl.test.junit.jogl.demos.PointsDemo; +import com.jogamp.opengl.util.GLArrayDataServer; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.fixedfunc.FixedFuncUtil; +import com.jogamp.opengl.util.glsl.fixedfunc.ShaderSelectionMode; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES1; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLPipelineFactory; +import javax.media.opengl.glu.GLU; +import javax.media.opengl.glu.gl2es1.GLUgl2es1; + +public class PointsDemoES1 extends PointsDemo { + final static GLU glu = new GLUgl2es1(); + private boolean debugFFPEmu = false; + private boolean verboseFFPEmu = false; + private boolean traceFFPEmu = false; + private boolean forceFFPEmu = false; + private boolean debug = false ; + private boolean trace = false ; + GLArrayDataServer vertices ; + float[] pointSizes ; + private int swapInterval = 0; + final int edge = 8; // 8*8 + boolean smooth = false; + + public PointsDemoES1(int swapInterval) { + this.swapInterval = swapInterval; + } + + public PointsDemoES1() { + this.swapInterval = 1; + } + + public void setForceFFPEmu(boolean forceFFPEmu, boolean verboseFFPEmu, boolean debugFFPEmu, boolean traceFFPEmu) { + this.forceFFPEmu = forceFFPEmu; + this.verboseFFPEmu = verboseFFPEmu; + this.debugFFPEmu = debugFFPEmu; + this.traceFFPEmu = traceFFPEmu; + } + + public void setSmoothPoints(boolean v) { smooth = v; } + + public void init(GLAutoDrawable glad) { + GL _gl = glad.getGL(); + + if(debugFFPEmu) { + // Debug .. + _gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", GL2ES2.class, _gl, null) ); + debug = false; + } + if(traceFFPEmu) { + // Trace .. + _gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", GL2ES2.class, _gl, new Object[] { System.err } ) ); + trace = false; + } + GL2ES1 gl = FixedFuncUtil.wrapFixedFuncEmul(_gl, ShaderSelectionMode.AUTO, null, forceFFPEmu, verboseFFPEmu); + + if(debug) { + try { + // Debug .. + gl = (GL2ES1) gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", GL2ES1.class, gl, null) ); + } catch (Exception e) {e.printStackTrace();} + } + if(trace) { + try { + // Trace .. + gl = (GL2ES1) gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", GL2ES1.class, gl, new Object[] { System.err } ) ); + } catch (Exception e) {e.printStackTrace();} + } + + System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR)); + System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER)); + System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION)); + System.err.println("GL Profile: "+gl.getGLProfile()); + + // Allocate Vertex Array + vertices = GLArrayDataServer.createFixed(GL2ES1.GL_VERTEX_ARRAY, 3, GL.GL_FLOAT, false, edge*edge, GL.GL_STATIC_DRAW); + pointSizes = new float[edge*edge]; + for(int i=0; i<edge; i++) { + for(int j=0; j<edge; j++) { + final float x = -3+j*0.7f; + final float y = -3+i*0.7f; + final float p = Math.max(0.000001f, (i*edge+j)*0.5f); // no zero point size! + // System.err.println("["+j+"/"+i+"]: "+x+"/"+y+": "+p); + vertices.putf(x); vertices.putf(y); vertices.putf( 0); + pointSizes[(i*edge+j)] = p; + } + } + vertices.seal(gl, true); + vertices.enableBuffer(gl, false); + + // OpenGL Render Settings + gl.glEnable(GL2ES1.GL_DEPTH_TEST); + } + + public void setPointParams(float minSize, float maxSize, float distAttenConst, float distAttenLinear, float distAttenQuadratic, float fadeThreshold) { + pointMinSize = minSize; + pointMaxSize = maxSize; + pointFadeThreshold = fadeThreshold; + pointDistAtten.put(0, distAttenConst); + pointDistAtten.put(1, distAttenLinear); + pointDistAtten.put(2, distAttenQuadratic); + } + + /** default values */ + private float pointMinSize = 0.0f; + private float pointMaxSize = 4096.0f; + private float pointFadeThreshold = 1.0f; + private final FloatBuffer pointDistAtten = Buffers.newDirectFloatBuffer(new float[] { 1.0f, 0.0f, 0.0f }); + + public void display(GLAutoDrawable glad) { + GL2ES1 gl = glad.getGL().getGL2ES1(); + gl.glClearColor(0f, 0f, 0f, 0f); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + gl.glMatrixMode(GL2ES1.GL_MODELVIEW); + gl.glLoadIdentity(); + gl.glTranslatef(0, 0, -10); + + gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f ); + + vertices.enableBuffer(gl, true); + + gl.glEnable ( GL.GL_BLEND ); + gl.glBlendFunc ( GL.GL_SRC_ALPHA, GL.GL_ONE ); + if(smooth) { + gl.glEnable(GL2ES1.GL_POINT_SMOOTH); + } else { + gl.glDisable(GL2ES1.GL_POINT_SMOOTH); + } + gl.glPointParameterf(GL2ES1.GL_POINT_SIZE_MIN, pointMinSize ); + gl.glPointParameterf(GL2ES1.GL_POINT_SIZE_MAX, pointMaxSize ); + gl.glPointParameterf(GL2ES1.GL_POINT_FADE_THRESHOLD_SIZE, pointFadeThreshold); + gl.glPointParameterfv(GL2ES1.GL_POINT_DISTANCE_ATTENUATION, pointDistAtten ); + + for(int i=edge*edge-1; i>=0; i--) { + gl.glPointSize(pointSizes[i]); + gl.glDrawArrays(GL.GL_POINTS, i, 1); + } + + vertices.enableBuffer(gl, false); + } + + public void reshape(GLAutoDrawable glad, int x, int y, int width, int height) { + // Thread.dumpStack(); + GL2ES1 gl = glad.getGL().getGL2ES1(); + + if(-1 != swapInterval) { + gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there) + } + + // Set location in front of camera + gl.glMatrixMode(PMVMatrix.GL_PROJECTION); + gl.glLoadIdentity(); + glu.gluPerspective(45.0F, ( (float) width / (float) height ) / 1.0f, 1.0F, 100.0F); + //gl.glOrthof(-4.0f, 4.0f, -4.0f, 4.0f, 1.0f, 100.0f); + } + + public void dispose(GLAutoDrawable glad) { + GL2ES1 gl = glad.getGL().getGL2ES1(); + vertices.destroy(gl); + vertices = null; + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/RedSquareES1.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/RedSquareES1.java index 8d1c708af..5891bce0d 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/RedSquareES1.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/RedSquareES1.java @@ -1,21 +1,33 @@ package com.jogamp.opengl.test.junit.jogl.demos.es1; import com.jogamp.common.nio.Buffers; + import java.nio.*; + import javax.media.opengl.*; import javax.media.opengl.fixedfunc.GLMatrixFunc; import javax.media.opengl.fixedfunc.GLPointerFunc; +import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.util.TileRendererBase; import com.jogamp.opengl.util.glsl.fixedfunc.*; -public class RedSquareES1 implements GLEventListener { +public class RedSquareES1 implements GLEventListener, TileRendererBase.TileRendererListener { - public static boolean glDebugEmu = false; - public static boolean glDebug = false ; - public static boolean glTrace = false ; public static boolean oneThread = false; public static boolean useAnimator = false; + private boolean debugFFPEmu = false; + private boolean verboseFFPEmu = false; + private boolean traceFFPEmu = false; + private boolean forceFFPEmu = false; + private boolean debug = false ; + private boolean trace = false ; private int swapInterval = 0; + private final float aspect = 1.0f; + private boolean doRotate = true; + private TileRendererBase tileRendererInUse = null; + private boolean doRotateBeforePrinting; + private boolean flipVerticalInGLOrientation = false; long startTime = 0; long curTime = 0; @@ -27,7 +39,36 @@ public class RedSquareES1 implements GLEventListener { public RedSquareES1() { this.swapInterval = 1; } - + + @Override + public void addTileRendererNotify(TileRendererBase tr) { + tileRendererInUse = tr; + doRotateBeforePrinting = doRotate; + setDoRotation(false); + } + @Override + public void removeTileRendererNotify(TileRendererBase tr) { + tileRendererInUse = null; + setDoRotation(doRotateBeforePrinting); + } + @Override + public void startTileRendering(TileRendererBase tr) { + System.err.println("RedSquareES1.startTileRendering: "+tr); + } + @Override + public void endTileRendering(TileRendererBase tr) { + System.err.println("RedSquareES1.endTileRendering: "+tr); + } + + public void setDoRotation(boolean rotate) { this.doRotate = rotate; } + public void setForceFFPEmu(boolean forceFFPEmu, boolean verboseFFPEmu, boolean debugFFPEmu, boolean traceFFPEmu) { + this.forceFFPEmu = forceFFPEmu; + this.verboseFFPEmu = verboseFFPEmu; + this.debugFFPEmu = debugFFPEmu; + this.traceFFPEmu = traceFFPEmu; + } + public void setFlipVerticalInGLOrientation(boolean v) { flipVerticalInGLOrientation=v; } + // FIXME: we must add storage of the pointers in the GL state to // the GLImpl classes. The need for this can be seen by making // these variables method local instead of instance members. The @@ -38,48 +79,40 @@ public class RedSquareES1 implements GLEventListener { private FloatBuffer colors; private FloatBuffer vertices; + @Override public void init(GLAutoDrawable drawable) { System.err.println(Thread.currentThread()+" RedSquareES1.init ..."); GL _gl = drawable.getGL(); - if(glDebugEmu) { - try { - // Debug .. - _gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", GL2ES2.class, _gl, null) ); - - if(glTrace) { - // Trace .. - _gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", GL2ES2.class, _gl, new Object[] { System.err } ) ); - } - } catch (Exception e) {e.printStackTrace();} - glDebug = false; - glTrace = false; + if(debugFFPEmu) { + // Debug .. + _gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", GL2ES2.class, _gl, null) ); + debug = false; } + if(traceFFPEmu) { + // Trace .. + _gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", GL2ES2.class, _gl, new Object[] { System.err } ) ); + trace = false; + } + GL2ES1 gl = FixedFuncUtil.wrapFixedFuncEmul(_gl, ShaderSelectionMode.AUTO, null, forceFFPEmu, verboseFFPEmu); - GL2ES1 gl = FixedFuncUtil.wrapFixedFuncEmul(_gl); - if(glDebug) { + if(debug) { try { // Debug .. gl = (GL2ES1) gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", GL2ES1.class, gl, null) ); - } catch (Exception e) {e.printStackTrace();} + } catch (Exception e) {e.printStackTrace();} } - - if(glTrace) { + if(trace) { try { // Trace .. gl = (GL2ES1) gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", GL2ES1.class, gl, new Object[] { System.err } ) ); } catch (Exception e) {e.printStackTrace();} } - System.err.println(Thread.currentThread()+"Chosen GLCapabilities: " + drawable.getChosenGLCapabilities()); - System.err.println(Thread.currentThread()+"INIT GL IS: " + gl.getClass().getName()); - System.err.println(Thread.currentThread()+"GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR)); - System.err.println(Thread.currentThread()+"GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER)); - System.err.println(Thread.currentThread()+"GL_VERSION: " + gl.glGetString(GL.GL_VERSION)); - - System.err.println(Thread.currentThread()+" GL Profile: "+gl.getGLProfile()); - System.err.println(Thread.currentThread()+" GL:" + gl); - System.err.println(Thread.currentThread()+" GL_VERSION=" + gl.glGetString(GL.GL_VERSION)); + System.err.println("RedSquareES1 init on "+Thread.currentThread()); + System.err.println("Chosen GLCapabilities: " + drawable.getChosenGLCapabilities()); + System.err.println("INIT GL IS: " + gl.getClass().getName()); + System.err.println(JoglVersion.getGLStrings(gl, null, false).toString()); // Allocate vertex arrays colors = Buffers.newDirectFloatBuffer(16); @@ -98,7 +131,6 @@ public class RedSquareES1 implements GLEventListener { gl.glColorPointer(4, GL.GL_FLOAT, 0, colors); // OpenGL Render Settings - gl.glClearColor(0, 0, 0, 1); gl.glEnable(GL.GL_DEPTH_TEST); startTime = System.currentTimeMillis(); @@ -106,37 +138,79 @@ public class RedSquareES1 implements GLEventListener { System.err.println(Thread.currentThread()+" RedSquareES1.init FIN"); } - public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { - System.err.println(Thread.currentThread()+" RedSquareES1.reshape "+x+"/"+y+" "+width+"x"+height+", swapInterval "+swapInterval); - GL2ES1 gl = drawable.getGL().getGL2ES1(); - gl.setSwapInterval(swapInterval); - + @Override + public void reshape(GLAutoDrawable glad, int x, int y, int width, int height) { + final GL2ES1 gl = glad.getGL().getGL2ES1(); + if(-1 != swapInterval) { + gl.setSwapInterval(swapInterval); + } + reshapeImpl(gl, x, y, width, height, width, height); + } + + @Override + public void reshapeTile(TileRendererBase tr, + int tileX, int tileY, int tileWidth, int tileHeight, + int imageWidth, int imageHeight) { + final GL2ES1 gl = tr.getAttachedDrawable().getGL().getGL2ES1(); + gl.setSwapInterval(0); + reshapeImpl(gl, tileX, tileY, tileWidth, tileHeight, imageWidth, imageHeight); + } + + void reshapeImpl(GL2ES1 gl, int tileX, int tileY, int tileWidth, int tileHeight, int imageWidth, int imageHeight) { + System.err.println(Thread.currentThread()+" RedSquareES1.reshape "+tileX+"/"+tileY+" "+tileWidth+"x"+tileHeight+" of "+imageWidth+"x"+imageHeight+", swapInterval "+swapInterval+", drawable 0x"+Long.toHexString(gl.getContext().getGLDrawable().getHandle())+", tileRendererInUse "+tileRendererInUse); + // Set location in front of camera gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION); gl.glLoadIdentity(); - gluPerspective(gl, 45.0f, (float)width / (float)height, 1.0f, 100.0f); + if( flipVerticalInGLOrientation && gl.getContext().getGLDrawable().isGLOriented() ) { + gl.glScalef(1f, -1f, 1f); + } + + // compute projection parameters 'normal' perspective + final float fovy=45f; + final float aspect2 = ( (float) imageWidth / (float) imageHeight ) / aspect; + final float zNear=1f; + final float zFar=100f; + + // compute projection parameters 'normal' frustum + final float top=(float)Math.tan(fovy*((float)Math.PI)/360.0f)*zNear; + final float bottom=-1.0f*top; + final float left=aspect2*bottom; + final float right=aspect2*top; + final float w = right - left; + final float h = top - bottom; + + // compute projection parameters 'tiled' + final float l = left + tileX * w / imageWidth; + final float r = l + tileWidth * w / imageWidth; + final float b = bottom + tileY * h / imageHeight; + final float t = b + tileHeight * h / imageHeight; + + gl.glFrustumf(l, r, b, t, zNear, zFar); // gl.glOrthof(-4.0f, 4.0f, -4.0f, 4.0f, 1.0f, 100.0f); + + gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + gl.glLoadIdentity(); + System.err.println(Thread.currentThread()+" RedSquareES1.reshape FIN"); } - - void gluPerspective(GL2ES1 gl, final float fovy, final float aspect, final float zNear, final float zFar) { - float top=(float)Math.tan(fovy*((float)Math.PI)/360.0f)*zNear; - float bottom=-1.0f*top; - float left=aspect*bottom; - float right=aspect*top; - gl.glFrustumf(left, right, bottom, top, zNear, zFar); - } + @Override public void display(GLAutoDrawable drawable) { curTime = System.currentTimeMillis(); GL2ES1 gl = drawable.getGL().getGL2ES1(); + if( null != tileRendererInUse ) { + gl.glClearColor(1.0f, 1.0f, 1.0f, 0.0f); + } else { + gl.glClearColor(0, 0, 0, 0); + } gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); // One rotation every four seconds gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); gl.glLoadIdentity(); gl.glTranslatef(0, 0, -10); - float ang = ((float) (curTime - startTime) * 360.0f) / 4000.0f; + float ang = doRotate ? ((curTime - startTime) * 360.0f) / 4000.0f : 1f; gl.glRotatef(ang, 0, 0, 1); gl.glRotatef(ang, 0, 1, 0); @@ -148,6 +222,7 @@ public class RedSquareES1 implements GLEventListener { gl.glDisableClientState(GLPointerFunc.GL_COLOR_ARRAY); } + @Override public void dispose(GLAutoDrawable drawable) { System.err.println(Thread.currentThread()+" RedSquareES1.dispose ... "); GL2ES1 gl = drawable.getGL().getGL2ES1(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestGearsES1NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestGearsES1NEWT.java index dffe61f69..8abb0cc0e 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestGearsES1NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestGearsES1NEWT.java @@ -31,6 +31,7 @@ package com.jogamp.opengl.test.junit.jogl.demos.es1.newt; import com.jogamp.newt.event.KeyAdapter; import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.util.MiscUtils; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.util.QuitAdapter; @@ -45,26 +46,36 @@ import org.junit.Assert; import org.junit.BeforeClass; import org.junit.AfterClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestGearsES1NEWT extends UITestCase { static int width, height; + static boolean forceES2 = false; + static boolean forceFFPEmu = false; + static int swapInterval = 1; @BeforeClass public static void initClass() { - width = 512; - height = 512; + width = 640; + height = 480; } @AfterClass public static void releaseClass() { } - protected void runTestGL(GLCapabilities caps) throws InterruptedException { + protected void runTestGL(GLCapabilities caps, boolean forceFFPEmu) throws InterruptedException { GLWindow glWindow = GLWindow.create(caps); Assert.assertNotNull(glWindow); glWindow.setTitle("Gears NEWT Test"); - glWindow.addGLEventListener(new GearsES1()); + final GearsES1 demo = new GearsES1(swapInterval); + demo.setForceFFPEmu(forceFFPEmu, forceFFPEmu, false, false); + glWindow.addGLEventListener(demo); + final SnapshotGLEventListener snap = new SnapshotGLEventListener(); + glWindow.addGLEventListener(snap); Animator animator = new Animator(glWindow); QuitAdapter quitAdapter = new QuitAdapter(); @@ -76,7 +87,10 @@ public class TestGearsES1NEWT extends UITestCase { final GLWindow f_glWindow = glWindow; glWindow.addKeyListener(new KeyAdapter() { - public void keyTyped(KeyEvent e) { + public void keyReleased(KeyEvent e) { + if( !e.isPrintableKey() || e.isAutoRepeat() ) { + return; + } if(e.getKeyChar()=='f') { new Thread() { public void run() { @@ -95,6 +109,7 @@ public class TestGearsES1NEWT extends UITestCase { glWindow.setVisible(true); animator.setUpdateFPSFrames(1, null); animator.start(); + snap.setMakeSnapshot(); while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) { Thread.sleep(100); @@ -105,13 +120,13 @@ public class TestGearsES1NEWT extends UITestCase { } @Test - public void test01() throws InterruptedException { - GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES1()); - runTestGL(caps); + public void test00() throws InterruptedException { + GLCapabilities caps = new GLCapabilities(forceES2 ? GLProfile.get(GLProfile.GLES2) : GLProfile.getGL2ES1()); + runTestGL(caps, forceFFPEmu); } - + static long duration = 500; // ms - + public static void main(String args[]) { for(int i=0; i<args.length; i++) { if(args[i].equals("-time")) { @@ -119,6 +134,13 @@ public class TestGearsES1NEWT extends UITestCase { try { duration = Integer.parseInt(args[i]); } catch (Exception ex) { ex.printStackTrace(); } + } else if(args[i].equals("-vsync")) { + i++; + swapInterval = MiscUtils.atoi(args[i], swapInterval); + } else if(args[i].equals("-es2")) { + forceES2 = true; + } else if(args[i].equals("-ffpemu")) { + forceFFPEmu = true; } } org.junit.runner.JUnitCore.main(TestGearsES1NEWT.class.getName()); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestOlympicES1NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestOlympicES1NEWT.java new file mode 100644 index 000000000..c12ef9525 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestOlympicES1NEWT.java @@ -0,0 +1,144 @@ +/** + * 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.jogl.demos.es1.newt; + +import com.jogamp.newt.opengl.GLWindow; +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 com.jogamp.opengl.test.junit.jogl.demos.es1.OlympicES1; + +import com.jogamp.opengl.util.Animator; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.AfterClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestOlympicES1NEWT extends UITestCase { + static int width, height; + static boolean forceES2 = false; + static boolean forceFFPEmu = false; + static boolean verboseFFPEmu = false; + static int swapInterval = 1; + static boolean exclusiveContext = false; + + @BeforeClass + public static void initClass() { + width = 640; + height = 480; + } + + @AfterClass + public static void releaseClass() { + } + + protected void runTestGL(GLCapabilities caps) throws InterruptedException { + GLWindow glWindow = GLWindow.create(caps); + Assert.assertNotNull(glWindow); + glWindow.setTitle("Olympic NEWT Test"); + + OlympicES1 demo = new OlympicES1( swapInterval ); + demo.setForceFFPEmu(forceFFPEmu, verboseFFPEmu, false, false); + glWindow.addGLEventListener(demo); + final SnapshotGLEventListener snap = new SnapshotGLEventListener(); + glWindow.addGLEventListener(snap); + + Animator animator = new Animator(); + animator.setModeBits(false, Animator.MODE_EXPECT_AWT_RENDERING_THREAD); + animator.setExclusiveContext(exclusiveContext); + + QuitAdapter quitAdapter = new QuitAdapter(); + glWindow.addKeyListener(quitAdapter); + glWindow.addWindowListener(quitAdapter); + glWindow.setSize(width, height); + glWindow.setVisible(true); + + animator.add(glWindow); + animator.start(); + animator.setUpdateFPSFrames(60, System.err); + Assert.assertTrue(animator.isStarted()); + Assert.assertTrue(animator.isAnimating()); + Assert.assertEquals(exclusiveContext ? animator.getThread() : null, glWindow.getExclusiveContextThread()); + + snap.setMakeSnapshot(); + + while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) { + Thread.sleep(100); + } + + Assert.assertEquals(exclusiveContext ? animator.getThread() : null, glWindow.getExclusiveContextThread()); + animator.stop(); + Assert.assertFalse(animator.isAnimating()); + Assert.assertFalse(animator.isStarted()); + Assert.assertEquals(null, glWindow.getExclusiveContextThread()); + glWindow.destroy(); + } + + @Test + public void test00() throws InterruptedException { + GLCapabilities caps = new GLCapabilities(forceES2 ? GLProfile.get(GLProfile.GLES2) : GLProfile.getGL2ES1()); + runTestGL(caps); + } + + static long duration = 500; // ms + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + try { + duration = Integer.parseInt(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } else if(args[i].equals("-vsync")) { + i++; + swapInterval = MiscUtils.atoi(args[i], swapInterval); + } else if(args[i].equals("-exclctx")) { + exclusiveContext = true; + } else if(args[i].equals("-es2")) { + forceES2 = true; + } else if(args[i].equals("-ffpemu")) { + forceFFPEmu = true; + } else if(args[i].equals("-verbose")) { + verboseFFPEmu = true; + } + } + System.err.println("forceES2 "+forceES2); + System.err.println("forceFFPEmu "+forceFFPEmu); + System.err.println("swapInterval "+swapInterval); + System.err.println("exclusiveContext "+exclusiveContext); + org.junit.runner.JUnitCore.main(TestOlympicES1NEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestRedSquareES1NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestRedSquareES1NEWT.java index c327a3005..200936f34 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestRedSquareES1NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestRedSquareES1NEWT.java @@ -45,9 +45,14 @@ import org.junit.Assert; import org.junit.BeforeClass; import org.junit.AfterClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestRedSquareES1NEWT extends UITestCase { static int width, height; + static boolean forceES2 = false; + static boolean forceFFPEmu = false; @BeforeClass public static void initClass() { @@ -59,12 +64,16 @@ public class TestRedSquareES1NEWT extends UITestCase { public static void releaseClass() { } - protected void runTestGL(GLCapabilities caps) throws InterruptedException { + protected void runTestGL(GLCapabilities caps, boolean forceFFPEmu) throws InterruptedException { GLWindow glWindow = GLWindow.create(caps); Assert.assertNotNull(glWindow); glWindow.setTitle("Gears NEWT Test"); - glWindow.addGLEventListener(new RedSquareES1()); + final RedSquareES1 demo = new RedSquareES1(); + demo.setForceFFPEmu(forceFFPEmu, forceFFPEmu, false, false); + glWindow.addGLEventListener(demo); + final SnapshotGLEventListener snap = new SnapshotGLEventListener(); + glWindow.addGLEventListener(snap); Animator animator = new Animator(glWindow); QuitAdapter quitAdapter = new QuitAdapter(); @@ -76,7 +85,10 @@ public class TestRedSquareES1NEWT extends UITestCase { final GLWindow f_glWindow = glWindow; glWindow.addKeyListener(new KeyAdapter() { - public void keyTyped(KeyEvent e) { + public void keyReleased(KeyEvent e) { + if( !e.isPrintableKey() || e.isAutoRepeat() ) { + return; + } if(e.getKeyChar()=='f') { new Thread() { public void run() { @@ -95,6 +107,7 @@ public class TestRedSquareES1NEWT extends UITestCase { glWindow.setVisible(true); animator.setUpdateFPSFrames(1, null); animator.start(); + snap.setMakeSnapshot(); while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) { Thread.sleep(100); @@ -105,20 +118,24 @@ public class TestRedSquareES1NEWT extends UITestCase { } @Test - public void test01() throws InterruptedException { - GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES1()); - runTestGL(caps); + public void test00() throws InterruptedException { + GLCapabilities caps = new GLCapabilities(forceES2 ? GLProfile.get(GLProfile.GLES2) : GLProfile.getGL2ES1()); + runTestGL(caps, forceFFPEmu); } + + static long duration = 1000; // ms - static long duration = 500; // ms - - public static void main(String args[]) { + public static void main(String args[]) { for(int i=0; i<args.length; i++) { if(args[i].equals("-time")) { i++; try { duration = Integer.parseInt(args[i]); } catch (Exception ex) { ex.printStackTrace(); } + } else if(args[i].equals("-es2")) { + forceES2 = true; + } else if(args[i].equals("-ffpemu")) { + forceFFPEmu = true; } } org.junit.runner.JUnitCore.main(TestRedSquareES1NEWT.class.getName()); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/ElektronenMultiplizierer.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/ElektronenMultiplizierer.java index cb3eb4351..3120a1832 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/ElektronenMultiplizierer.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/ElektronenMultiplizierer.java @@ -232,10 +232,13 @@ public class ElektronenMultiplizierer implements GLEventListener { st = new ShaderState(); final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(), "shader", - "shader/bin", "default", false); + "shader/bin", "default", true); final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(), "shader", - "shader/bin", "elektronenmultiplizierer_development", false); - // "shader", "shader/bin", "elektronenmultiplizierer_port", false); + "shader/bin", "elektronenmultiplizierer_development", true); + // "shader", "shader/bin", "elektronenmultiplizierer_port", true); + vp0.defaultShaderCustomization(gl, true, true); + fp0.defaultShaderCustomization(gl, true, true); + final ShaderProgram sp0 = new ShaderProgram(); sp0.add(gl, vp0, System.err); sp0.add(gl, fp0, System.err); @@ -450,7 +453,9 @@ public class ElektronenMultiplizierer implements GLEventListener { st.uniform(gl, en.setData(mEffectNumber)); st.uniform(gl, et.setData(mEffectTime)); - gl.glEnable(GL_TEXTURE_2D); + if( !gl.isGLcore() ) { + gl.glEnable(GL_TEXTURE_2D); + } gl.glBindTexture(GL_TEXTURE_2D, mFrameBufferTextureID); gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/FBOMix2DemosES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/FBOMix2DemosES2.java new file mode 100644 index 000000000..add11ff8c --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/FBOMix2DemosES2.java @@ -0,0 +1,312 @@ +/** + * Copyright (C) 2011 JogAmp Community. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.jogamp.opengl.test.junit.jogl.demos.es2; + +import java.nio.FloatBuffer; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLUniformData; +import javax.media.opengl.fixedfunc.GLMatrixFunc; + +import com.jogamp.opengl.FBObject; +import com.jogamp.opengl.FBObject.TextureAttachment; +import com.jogamp.opengl.FBObject.Attachment.Type; +import com.jogamp.opengl.util.GLArrayDataServer; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; +import com.jogamp.opengl.util.glsl.ShaderState; + +public class FBOMix2DemosES2 implements GLEventListener { + private final GearsES2 demo0; + private final RedSquareES2 demo1; + private final int swapInterval; + private int numSamples; + private boolean demo0Only; + + + private final ShaderState st; + private final PMVMatrix pmvMatrix; + + private final FBObject fbo0; + private final FBObject fbo1; + + private TextureAttachment fbo0Tex; + private TextureAttachment fbo1Tex; + + private ShaderProgram sp0; + private GLUniformData pmvMatrixUniform; + private GLArrayDataServer interleavedVBO; + private GLUniformData texUnit0; + private GLUniformData texUnit1; + + public FBOMix2DemosES2(int swapInterval) { + demo0 = new GearsES2(-1); + demo0.setIgnoreFocus(true); + demo1 = new RedSquareES2(-1); + this.swapInterval = swapInterval; + + st = new ShaderState(); + // st.setVerbose(true); + pmvMatrix = new PMVMatrix(); + + fbo0 = new FBObject(); + fbo1 = new FBObject(); + + numSamples = 0; + demo0Only = false; + } + + public void setDemo0Only(boolean v) { + this.demo0Only = v; + } + public boolean getDemo0Only() { return demo0Only; } + + public void setMSAA(int numSamples) { + this.numSamples=numSamples; + } + public int getMSAA() { return numSamples; } + + public void setDoRotation(boolean rotate) { demo1.setDoRotation(rotate); } + + @Override + public void init(GLAutoDrawable drawable) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + + demo0.init(drawable); + demo1.init(drawable); + + final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, FBOMix2DemosES2.class, "shader", + "shader/bin", "texture01_xxx", true); + final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, FBOMix2DemosES2.class, "shader", + "shader/bin", "texture02_xxx", true); + vp0.defaultShaderCustomization(gl, true, true); + fp0.defaultShaderCustomization(gl, true, true); + + sp0 = new ShaderProgram(); + sp0.add(gl, vp0, System.err); + sp0.add(gl, fp0, System.err); + st.attachShaderProgram(gl, sp0, true); + + pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); + st.ownUniform(pmvMatrixUniform); + st.uniform(gl, pmvMatrixUniform); + + interleavedVBO = GLArrayDataServer.createGLSLInterleaved(3+4+2, GL.GL_FLOAT, false, 3*4, GL.GL_STATIC_DRAW); + { + interleavedVBO.addGLSLSubArray("mgl_Vertex", 3, GL.GL_ARRAY_BUFFER); + interleavedVBO.addGLSLSubArray("mgl_Color", 4, GL.GL_ARRAY_BUFFER); + //interleavedVBO.addGLSLSubArray("mgl_Normal", 3, GL.GL_ARRAY_BUFFER); + interleavedVBO.addGLSLSubArray("mgl_MultiTexCoord", 2, GL.GL_ARRAY_BUFFER); + + FloatBuffer ib = (FloatBuffer)interleavedVBO.getBuffer(); + + for(int i=0; i<4; i++) { + ib.put(s_quadVertices, i*3, 3); + ib.put(s_quadColors, i*4, 4); + //ib.put(s_cubeNormals, i*3, 3); + ib.put(s_quadTexCoords, i*2, 2); + } + } + interleavedVBO.seal(gl, true); + interleavedVBO.enableBuffer(gl, false); + st.ownAttribute(interleavedVBO, true); + + texUnit0 = new GLUniformData("mgl_Texture0", 0); + st.ownUniform(texUnit0); + st.uniform(gl, texUnit0); + texUnit1 = new GLUniformData("mgl_Texture1", 1); + st.ownUniform(texUnit1); + st.uniform(gl, texUnit1); + + st.useProgram(gl, false); + + System.err.println("**** Init"); + initFBOs(gl, drawable); + + gl.glEnable(GL2ES2.GL_DEPTH_TEST); + } + + private void initFBOs(GL gl, GLAutoDrawable drawable) { + // remove all texture attachments, since MSAA uses just color-render-buffer + // and non-MSAA uses texture2d-buffer + fbo0.detachAllColorbuffer(gl); + fbo1.detachAllColorbuffer(gl); + + fbo0.reset(gl, drawable.getWidth(), drawable.getHeight(), numSamples, false); + fbo1.reset(gl, drawable.getWidth(), drawable.getHeight(), numSamples, false); + if(fbo0.getNumSamples() != fbo1.getNumSamples()) { + throw new InternalError("sample size mismatch: \n\t0: "+fbo0+"\n\t1: "+fbo1); + } + numSamples = fbo0.getNumSamples(); + + if(numSamples>0) { + fbo0.attachColorbuffer(gl, 0, true); + fbo0.resetSamplingSink(gl); + fbo1.attachColorbuffer(gl, 0, true); + fbo1.resetSamplingSink(gl); + fbo0Tex = fbo0.getSamplingSink(); + fbo1Tex = fbo1.getSamplingSink(); + } else { + fbo0Tex = fbo0.attachTexture2D(gl, 0, true); + fbo1Tex = fbo1.attachTexture2D(gl, 0, true); + } + numSamples=fbo0.getNumSamples(); + fbo0.attachRenderbuffer(gl, Type.DEPTH, 24); + fbo0.unbind(gl); + fbo1.attachRenderbuffer(gl, Type.DEPTH, 24); + fbo1.unbind(gl); + } + + private void resetFBOs(GL gl, GLAutoDrawable drawable) { + fbo0.reset(gl, drawable.getWidth(), drawable.getHeight(), numSamples, true); + fbo1.reset(gl, drawable.getWidth(), drawable.getHeight(), numSamples, true); + if(fbo0.getNumSamples() != fbo1.getNumSamples()) { + throw new InternalError("sample size mismatch: \n\t0: "+fbo0+"\n\t1: "+fbo1); + } + numSamples = fbo0.getNumSamples(); + if(numSamples>0) { + fbo0Tex = fbo0.getSamplingSink(); + fbo1Tex = fbo1.getSamplingSink(); + } else { + fbo0Tex = (TextureAttachment) fbo0.getColorbuffer(0); + fbo1Tex = (TextureAttachment) fbo1.getColorbuffer(0); + } + } + + @Override + public void dispose(GLAutoDrawable drawable) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + demo0.dispose(drawable); + demo1.dispose(drawable); + fbo0.destroy(gl); + fbo1.destroy(gl); + st.destroy(gl); + + fbo0Tex = null; + fbo1Tex = null; + sp0 = null; + pmvMatrixUniform = null; + interleavedVBO = null; + } + + @Override + public void display(GLAutoDrawable drawable) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + + if( fbo0.getNumSamples() != numSamples ) { + System.err.println("**** NumSamples: "+fbo0.getNumSamples()+" -> "+numSamples); + resetFBOs(gl, drawable); + } + + if(0 < numSamples) { + gl.glEnable(GL.GL_MULTISAMPLE); + } + + fbo0.bind(gl); + demo0.display(drawable); + fbo0.unbind(gl); + + if(!demo0Only) { + fbo1.bind(gl); + demo1.display(drawable); + fbo1.unbind(gl); + } + + st.useProgram(gl, true); + gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + + gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit0.intValue()); + fbo0.use(gl, fbo0Tex); + if(!demo0Only) { + gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit1.intValue()); + fbo1.use(gl, fbo1Tex); + } + interleavedVBO.enableBuffer(gl, true); + + if( !gl.isGLcore() ) { + gl.glEnable(GL.GL_TEXTURE_2D); + } + + gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4); + + interleavedVBO.enableBuffer(gl, false); + fbo0.unuse(gl); + if(!demo0Only) { + fbo1.unuse(gl); + } + + st.useProgram(gl, false); + } + + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + + if(-1 != swapInterval) { + gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there) + } + + System.err.println("**** Reshape: "+width+"x"+height); + resetFBOs(gl, drawable); + + fbo0.bind(gl); + demo0.reshape(drawable, x, y, width, height); + fbo0.unbind(gl); + fbo1.bind(gl); + demo1.reshape(drawable, x, y, width, height); + fbo1.unbind(gl); + + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glOrthof(-1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 10.0f); + + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + + st.useProgram(gl, true); + st.uniform(gl, pmvMatrixUniform); + st.useProgram(gl, false); + + } + + private static final float[] s_quadVertices = { + -1f, -1f, 0f, // LB + 1f, -1f, 0f, // RB + -1f, 1f, 0f, // LT + 1f, 1f, 0f // RT + }; + private static final float[] s_quadColors = { + 1f, 1f, 1f, 1f, + 1f, 1f, 1f, 1f, + 1f, 1f, 1f, 1f, + 1f, 1f, 1f, 1f }; + private static final float[] s_quadTexCoords = { + 0f, 0f, // LB + 1f, 0f, // RB + 0f, 1f, // LT + 1f, 1f // RT + }; +} 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 21aca0487..653937a7e 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 @@ -7,10 +7,10 @@ * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL @@ -22,22 +22,28 @@ package com.jogamp.opengl.test.junit.jogl.demos.es2; import com.jogamp.common.nio.Buffers; import com.jogamp.newt.Window; +import com.jogamp.newt.event.GestureHandler; import com.jogamp.newt.event.KeyAdapter; import com.jogamp.newt.event.KeyEvent; 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.newt.event.PinchToZoomGesture; +import com.jogamp.newt.event.GestureHandler.GestureEvent; +import com.jogamp.opengl.JoglVersion; import com.jogamp.opengl.test.junit.jogl.demos.GearsObject; import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.TileRendererBase; import com.jogamp.opengl.util.glsl.ShaderCode; import com.jogamp.opengl.util.glsl.ShaderProgram; import com.jogamp.opengl.util.glsl.ShaderState; + import java.nio.FloatBuffer; import javax.media.nativewindow.NativeWindow; import javax.media.opengl.GL; import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAnimatorControl; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; @@ -47,23 +53,42 @@ import javax.media.opengl.GLUniformData; * GearsES2.java <BR> * @author Brian Paul (converted to Java by Ron Cemer and Sven Gothel) <P> */ -public class GearsES2 implements GLEventListener { +public class GearsES2 implements GLEventListener, TileRendererBase.TileRendererListener { private final FloatBuffer lightPos = Buffers.newDirectFloatBuffer( new float[] { 5.0f, 5.0f, 10.0f } ); - + private ShaderState st = null; private PMVMatrix pmvMatrix = null; private GLUniformData pmvMatrixUniform = null; private GLUniformData colorU = null; - private float view_rotx = 20.0f, view_roty = 30.0f, view_rotz = 0.0f; - private GearsObjectES2 gear1=null, gear2=null, gear3=null; + private float view_rotx = 20.0f, view_roty = 30.0f; + private boolean flipVerticalInGLOrientation = false; + + private final float view_rotz = 0.0f; + 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 boolean useMappedBuffers = false; + private boolean validateBuffers = false; + private volatile boolean usesSharedGears = false; + private FloatBuffer gear1Color=GearsObject.red, gear2Color=GearsObject.green, gear3Color=GearsObject.blue; private float angle = 0.0f; private int swapInterval = 0; private boolean pmvUseBackingArray = true; // the default for PMVMatrix now, since it's faster // private MouseListener gearsMouse = new TraceMouseAdapter(new GearsMouseAdapter()); - private MouseListener gearsMouse = new GearsMouseAdapter(); - private KeyListener gearsKeys = new GearsKeyAdapter(); + public MouseListener gearsMouse = new GearsMouseAdapter(); + public KeyListener gearsKeys = new GearsKeyAdapter(); + private TileRendererBase tileRendererInUse = null; + private boolean doRotateBeforePrinting; + + private boolean doRotate = true; + private boolean ignoreFocus = false; + private float[] clearColor = null; + private boolean clearBuffers = true; + private boolean verbose = true; + private volatile boolean isInit = false; + + private PinchToZoomGesture pinchToZoomGesture = null; - private int prevMouseX, prevMouseY; public GearsES2(int swapInterval) { this.swapInterval = swapInterval; @@ -73,16 +98,57 @@ public class GearsES2 implements GLEventListener { this.swapInterval = 1; } + @Override + public void addTileRendererNotify(TileRendererBase tr) { + tileRendererInUse = tr; + doRotateBeforePrinting = doRotate; + setDoRotation(false); + } + @Override + public void removeTileRendererNotify(TileRendererBase tr) { + tileRendererInUse = null; + setDoRotation(doRotateBeforePrinting); + } + @Override + public void startTileRendering(TileRendererBase tr) { + System.err.println("GearsES2.startTileRendering: "+sid()+""+tr); + } + @Override + public void endTileRendering(TileRendererBase tr) { + System.err.println("GearsES2.endTileRendering: "+sid()+""+tr); + } + + public void setIgnoreFocus(boolean v) { ignoreFocus = v; } + public void setDoRotation(boolean rotate) { this.doRotate = rotate; } + public void setClearBuffers(boolean v) { clearBuffers = v; } + public void setVerbose(boolean v) { verbose = v; } + public void setFlipVerticalInGLOrientation(boolean v) { flipVerticalInGLOrientation=v; } + public void setPMVUseBackingArray(boolean pmvUseBackingArray) { this.pmvUseBackingArray = pmvUseBackingArray; } - - public void setGears(GearsObjectES2 g1, GearsObjectES2 g2, GearsObjectES2 g3) { + + /** float[4] */ + public void setClearColor(float[] clearColor) { + this.clearColor = clearColor; + } + + public void setGearsColors(FloatBuffer gear1Color, FloatBuffer gear2Color, FloatBuffer gear3Color) { + this.gear1Color = gear1Color; + this.gear2Color = gear2Color; + this.gear3Color = gear3Color; + } + + public void setSharedGearsObjects(GearsObjectES2 g1, GearsObjectES2 g2, GearsObjectES2 g3) { gear1 = g1; gear2 = g2; gear3 = g3; } + public void setSharedGears(GearsES2 shared) { + sharedGears = shared; + } + /** * @return gear1 */ @@ -98,26 +164,59 @@ public class GearsES2 implements GLEventListener { */ public GearsObjectES2 getGear3() { return gear3; } + public boolean usesSharedGears() { return usesSharedGears; } + + public void setUseMappedBuffers(boolean v) { useMappedBuffers = v; } + public void setValidateBuffers(boolean v) { validateBuffers = v; } + + private static final int TIME_OUT = 2000; // 2s + private static final int POLL_DIVIDER = 20; // TO/20 + private static final int TIME_SLICE = TIME_OUT / POLL_DIVIDER ; + + /** + * @return True if this GLEventListener became initialized within TIME_OUT 2s + */ + public boolean waitForInit(boolean initialized) throws InterruptedException { + int wait; + for (wait=0; wait<POLL_DIVIDER && initialized != isInit ; wait++) { + Thread.sleep(TIME_SLICE); + } + return wait<POLL_DIVIDER; + } + + private final String sid() { return "0x"+Integer.toHexString(hashCode()); } + @Override public void init(GLAutoDrawable drawable) { - System.err.println(Thread.currentThread()+" GearsES2.init ..."); - GL2ES2 gl = drawable.getGL().getGL2ES2(); + if(null != sharedGears && !sharedGears.isInit() ) { + System.err.println(Thread.currentThread()+" GearsES2.init.0 "+sid()+": pending shared Gears .. re-init later XXXXX"); + drawable.setGLEventListenerInitState(this, false); + return; + } - System.err.println("Chosen GLCapabilities: " + drawable.getChosenGLCapabilities()); - System.err.println("INIT GL IS: " + gl.getClass().getName()); - System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR)); - System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER)); - System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION)); + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + if(verbose) { + System.err.println(Thread.currentThread()+" GearsES2.init.0 "+sid()+": tileRendererInUse "+tileRendererInUse+", "+this); + System.err.println("GearsES2 init "+sid()+" on "+Thread.currentThread()); + System.err.println("Chosen GLCapabilities: " + drawable.getChosenGLCapabilities()); + System.err.println("INIT GL IS: " + gl.getClass().getName()); + System.err.println(JoglVersion.getGLStrings(gl, null, false).toString()); + } + if( !gl.hasGLSL() ) { + System.err.println("No GLSL available, no rendering."); + return; + } - gl.glEnable(GL.GL_CULL_FACE); gl.glEnable(GL.GL_DEPTH_TEST); - + st = new ShaderState(); // st.setVerbose(true); final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(), "shader", - "shader/bin", "gears", false); + "shader/bin", "gears", true); final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(), "shader", - "shader/bin", "gears", false); + "shader/bin", "gears", true); + vp0.defaultShaderCustomization(gl, true, true); + fp0.defaultShaderCustomization(gl, true, true); final ShaderProgram sp0 = new ShaderProgram(); sp0.add(gl, vp0, System.err); sp0.add(gl, fp0, System.err); @@ -139,161 +238,296 @@ public class GearsES2 implements GLEventListener { st.ownUniform(colorU); st.uniform(gl, colorU); - if(null == gear1) { - gear1 = new GearsObjectES2(1.0f, 4.0f, 1.0f, 20, 0.7f, pmvMatrix, pmvMatrixUniform, colorU); - System.err.println("gear1 created: "+gear1); + if( null != sharedGears ) { + gear1 = new GearsObjectES2(sharedGears.getGear1(), st, pmvMatrix, pmvMatrixUniform, colorU); + gear2 = new GearsObjectES2(sharedGears.getGear2(), st, pmvMatrix, pmvMatrixUniform, colorU); + gear3 = new GearsObjectES2(sharedGears.getGear3(), st, pmvMatrix, pmvMatrixUniform, colorU); + usesSharedGears = true; + if(verbose) { + System.err.println("gear1 "+sid()+" created w/ share: "+sharedGears.getGear1()+" -> "+gear1); + System.err.println("gear2 "+sid()+" created w/ share: "+sharedGears.getGear2()+" -> "+gear2); + System.err.println("gear3 "+sid()+" created w/ share: "+sharedGears.getGear3()+" -> "+gear3); + } } else { - gear1 = new GearsObjectES2(gear1, pmvMatrix, pmvMatrixUniform, colorU); - System.err.println("gear1 reused: "+gear1); - } - - if(null == gear2) { - gear2 = new GearsObjectES2(0.5f, 2.0f, 2.0f, 10, 0.7f, pmvMatrix, pmvMatrixUniform, colorU); - System.err.println("gear2 created: "+gear2); - } else { - gear2 = new GearsObjectES2(gear2, pmvMatrix, pmvMatrixUniform, colorU); - System.err.println("gear2 reused: "+gear2); + if(null == gear1) { + gear1 = new GearsObjectES2(gl, useMappedBuffers, st, gear1Color, 1.0f, 4.0f, 1.0f, 20, 0.7f, pmvMatrix, pmvMatrixUniform, colorU, validateBuffers); + if(verbose) { + System.err.println("gear1 "+sid()+" created: "+gear1); + } + } else { + final GearsObjectES2 _gear1 = gear1; + gear1 = new GearsObjectES2(_gear1, st, pmvMatrix, pmvMatrixUniform, colorU); + usesSharedGears = true; + if(verbose) { + System.err.println("gear1 "+sid()+" created w/ share: "+_gear1+" -> "+gear1); + } + } + + if(null == gear2) { + gear2 = new GearsObjectES2(gl, useMappedBuffers, st, gear2Color, 0.5f, 2.0f, 2.0f, 10, 0.7f, pmvMatrix, pmvMatrixUniform, colorU, validateBuffers); + if(verbose) { + System.err.println("gear2 "+sid()+" created: "+gear2); + } + } else { + final GearsObjectES2 _gear2 = gear2; + gear2 = new GearsObjectES2(_gear2, st, pmvMatrix, pmvMatrixUniform, colorU); + usesSharedGears = true; + if(verbose) { + System.err.println("gear2 "+sid()+" created w/ share: "+_gear2+" -> "+gear2); + } + } + + if(null == gear3) { + gear3 = new GearsObjectES2(gl, useMappedBuffers, st, gear3Color, 1.3f, 2.0f, 0.5f, 10, 0.7f, pmvMatrix, pmvMatrixUniform, colorU, validateBuffers); + if(verbose) { + System.err.println("gear3 "+sid()+" created: "+gear2); + } + } else { + final GearsObjectES2 _gear3 = gear3; + gear3 = new GearsObjectES2(_gear3, st, pmvMatrix, pmvMatrixUniform, colorU); + usesSharedGears = true; + if(verbose) { + System.err.println("gear3 "+sid()+" created w/ share: "+_gear3+" -> "+gear3); + } + } } - - if(null == gear3) { - gear3 = new GearsObjectES2(1.3f, 2.0f, 0.5f, 10, 0.7f, pmvMatrix, pmvMatrixUniform, colorU); - System.err.println("gear3 created: "+gear3); - } else { - gear3 = new GearsObjectES2(gear3, pmvMatrix, pmvMatrixUniform, colorU); - System.err.println("gear3 reused: "+gear3); - } - - if (drawable instanceof Window) { - Window window = (Window) drawable; + + final Object upstreamWidget = drawable.getUpstreamWidget(); + if (upstreamWidget instanceof Window) { + final Window window = (Window) upstreamWidget; window.addMouseListener(gearsMouse); window.addKeyListener(gearsKeys); - } else if (GLProfile.isAWTAvailable() && drawable instanceof java.awt.Component) { - java.awt.Component comp = (java.awt.Component) drawable; + window.addGestureListener(pinchToZoomListener); + pinchToZoomGesture = new PinchToZoomGesture(drawable.getNativeSurface(), false); + window.addGestureHandler(pinchToZoomGesture); + } else if (GLProfile.isAWTAvailable() && upstreamWidget instanceof java.awt.Component) { + final java.awt.Component comp = (java.awt.Component) upstreamWidget; new com.jogamp.newt.event.awt.AWTMouseAdapter(gearsMouse).addTo(comp); new com.jogamp.newt.event.awt.AWTKeyAdapter(gearsKeys).addTo(comp); } + st.useProgram(gl, false); - - gl.setSwapInterval(swapInterval); - - System.err.println(Thread.currentThread()+" GearsES2.init FIN"); + + gl.glFinish(); // make sure .. for shared context (impacts OSX 10.9) + + isInit = true; + if(verbose) { + System.err.println(Thread.currentThread()+" GearsES2.init.X "+sid()+" FIN "+this); + } } - public void enableAndroidTrace(boolean v) { - useAndroidDebug = v; + public final boolean isInit() { return isInit; } + + private final GestureHandler.GestureListener pinchToZoomListener = new GestureHandler.GestureListener() { + @Override + public void gestureDetected(GestureEvent gh) { + final PinchToZoomGesture.ZoomEvent ze = (PinchToZoomGesture.ZoomEvent) gh; + final float zoom = ze.getZoom(); // * ( ze.getTrigger().getPointerCount() - 1 ); <- too much .. + panZ = zoom * 30f - 30f; // [0 .. 2] -> [-30f .. 30f] + } + }; + + @Override + public void reshape(GLAutoDrawable glad, int x, int y, int width, int height) { + if( !isInit ) { return; } + final GL2ES2 gl = glad.getGL().getGL2ES2(); + if(-1 != swapInterval) { + gl.setSwapInterval(swapInterval); + } + reshapeImpl(gl, x, y, width, height, width, height); } - - public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { - // System.err.println(Thread.currentThread()+" GearsES2.reshape "+x+"/"+y+" "+width+"x"+height+", swapInterval "+swapInterval); - GL2ES2 gl = drawable.getGL().getGL2ES2(); + + @Override + public void reshapeTile(TileRendererBase tr, + int tileX, int tileY, int tileWidth, int tileHeight, + int imageWidth, int imageHeight) { + if( !isInit ) { return; } + final GL2ES2 gl = tr.getAttachedDrawable().getGL().getGL2ES2(); + gl.setSwapInterval(0); + reshapeImpl(gl, tileX, tileY, tileWidth, tileHeight, imageWidth, imageHeight); + } + + void reshapeImpl(GL2ES2 gl, int tileX, int tileY, int tileWidth, int tileHeight, int imageWidth, int imageHeight) { + final boolean msaa = gl.getContext().getGLDrawable().getChosenGLCapabilities().getSampleBuffers(); + if(verbose) { + System.err.println(Thread.currentThread()+" GearsES2.reshape "+sid()+" "+tileX+"/"+tileY+" "+tileWidth+"x"+tileHeight+" of "+imageWidth+"x"+imageHeight+", swapInterval "+swapInterval+", drawable 0x"+Long.toHexString(gl.getContext().getGLDrawable().getHandle())+", msaa "+msaa+", tileRendererInUse "+tileRendererInUse); + } + + if( !gl.hasGLSL() ) { + return; + } st.useProgram(gl, true); + + // compute projection parameters 'normal' + float left, right, bottom, top; + if( imageHeight > imageWidth ) { + float a = (float)imageHeight / (float)imageWidth; + left = -1.0f; + right = 1.0f; + bottom = -a; + top = a; + } else { + float a = (float)imageWidth / (float)imageHeight; + left = -a; + right = a; + bottom = -1.0f; + top = 1.0f; + } + final float w = right - left; + final float h = top - bottom; + + // compute projection parameters 'tiled' + final float l = left + tileX * w / imageWidth; + final float r = l + tileWidth * w / imageWidth; + final float b = bottom + tileY * h / imageHeight; + final float t = b + tileHeight * h / imageHeight; + + final float _w = r - l; + final float _h = t - b; + if(verbose) { + System.err.println(">> GearsES2 "+sid()+", angle "+angle+", [l "+left+", r "+right+", b "+bottom+", t "+top+"] "+w+"x"+h+" -> [l "+l+", r "+r+", b "+b+", t "+t+"] "+_w+"x"+_h+", v-flip "+flipVerticalInGLOrientation); + } + pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION); pmvMatrix.glLoadIdentity(); - - if(height>width) { - float h = (float)height / (float)width; - pmvMatrix.glFrustumf(-1.0f, 1.0f, -h, h, 5.0f, 60.0f); - } else { - float h = (float)width / (float)height; - pmvMatrix.glFrustumf(-h, h, -1.0f, 1.0f, 5.0f, 60.0f); + if( flipVerticalInGLOrientation && gl.getContext().getGLDrawable().isGLOriented() ) { + pmvMatrix.glScalef(1f, -1f, 1f); } + pmvMatrix.glFrustumf(l, r, b, t, 5.0f, 200.0f); pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW); pmvMatrix.glLoadIdentity(); pmvMatrix.glTranslatef(0.0f, 0.0f, -40.0f); st.uniform(gl, pmvMatrixUniform); st.useProgram(gl, false); - - if(useAndroidDebug) { - try { - android.os.Debug.startMethodTracing("GearsES2.trace"); - // android.os.Debug.startAllocCounting(); - useAndroidDebug = true; - } catch (NoClassDefFoundError e) { useAndroidDebug=false; } - } - + // System.err.println(Thread.currentThread()+" GearsES2.reshape FIN"); } - private boolean useAndroidDebug = false; + // private boolean useAndroidDebug = false; + @Override public void dispose(GLAutoDrawable drawable) { - if(useAndroidDebug) { - // android.os.Debug.stopAllocCounting(); - android.os.Debug.stopMethodTracing(); - } - - System.err.println(Thread.currentThread()+" GearsES2.dispose ... "); - if (drawable instanceof Window) { - Window window = (Window) drawable; + if( !isInit ) { return; } + isInit = false; + if(verbose) { + System.err.println(Thread.currentThread()+" GearsES2.dispose "+sid()+": tileRendererInUse "+tileRendererInUse); + } + final Object upstreamWidget = drawable.getUpstreamWidget(); + if (upstreamWidget instanceof Window) { + final Window window = (Window) upstreamWidget; window.removeMouseListener(gearsMouse); window.removeKeyListener(gearsKeys); + window.removeGestureHandler(pinchToZoomGesture); + pinchToZoomGesture = null; + window.removeGestureListener(pinchToZoomListener); + } + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + if( !gl.hasGLSL() ) { + return; } - GL2ES2 gl = drawable.getGL().getGL2ES2(); st.useProgram(gl, false); gear1.destroy(gl); gear1 = null; gear2.destroy(gl); gear2 = null; gear3.destroy(gl); - gear3 = null; + gear3 = null; pmvMatrix = null; - colorU = null; + colorU = null; st.destroy(gl); st = null; - System.err.println(Thread.currentThread()+" GearsES2.dispose FIN"); + + if(verbose) { + System.err.println(Thread.currentThread()+" GearsES2.dispose "+sid()+" FIN"); + } } + @Override public void display(GLAutoDrawable drawable) { + if( !isInit ) { return; } + if(null != sharedGears && !sharedGears.isInit() ) { return; } + GLAnimatorControl anim = drawable.getAnimator(); + if( verbose && ( null == anim || !anim.isAnimating() ) ) { + System.err.println(Thread.currentThread()+" GearsES2.display "+sid()+" "+drawable.getWidth()+"x"+drawable.getHeight()+", swapInterval "+swapInterval+", drawable 0x"+Long.toHexString(drawable.getHandle())); + } // Turn the gears' teeth - angle += 2.0f; + if(doRotate) { + angle += 2.0f; + } // Get the GL corresponding to the drawable we are animating - GL2ES2 gl = drawable.getGL().getGL2ES2(); + final GL2ES2 gl = drawable.getGL().getGL2ES2(); final boolean hasFocus; - if(drawable.getNativeSurface() instanceof NativeWindow) { - hasFocus = ((NativeWindow)drawable.getNativeSurface()).hasFocus(); + final Object upstreamWidget = drawable.getUpstreamWidget(); + if(upstreamWidget instanceof NativeWindow) { + hasFocus = ((NativeWindow)upstreamWidget).hasFocus(); } else { hasFocus = true; } - if(hasFocus) { - gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - } else { - gl.glClearColor(0.2f, 0.2f, 0.2f, 0.0f); - } - - // Special handling for the case where the GLJPanel is translucent - // and wants to be composited with other Java 2D content - if (GLProfile.isAWTAvailable() && - (drawable instanceof javax.media.opengl.awt.GLJPanel) && - !((javax.media.opengl.awt.GLJPanel) drawable).isOpaque() && - ((javax.media.opengl.awt.GLJPanel) drawable).shouldPreserveColorBufferIfTranslucent()) { - gl.glClear(GL.GL_DEPTH_BUFFER_BIT); - } else { - gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + + if( clearBuffers ) { + if( null != clearColor ) { + gl.glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]); + } else if( null != tileRendererInUse ) { + gl.glClearColor(1.0f, 1.0f, 1.0f, 0.0f); + } else if( ignoreFocus || hasFocus ) { + gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + } else { + gl.glClearColor(0.2f, 0.2f, 0.2f, 0.0f); + } + // Special handling for the case where the GLJPanel is translucent + // and wants to be composited with other Java 2D content + if (GLProfile.isAWTAvailable() && + (drawable instanceof javax.media.opengl.awt.GLJPanel) && + !((javax.media.opengl.awt.GLJPanel) drawable).isOpaque() && + ((javax.media.opengl.awt.GLJPanel) drawable).shouldPreserveColorBufferIfTranslucent()) { + gl.glClear(GL.GL_DEPTH_BUFFER_BIT); + } else { + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + } + } + if( !gl.hasGLSL() ) { + return; + } + + // Only possible if we do not flip the projection matrix + final boolean enableCullFace = ! ( flipVerticalInGLOrientation && gl.getContext().getGLDrawable().isGLOriented() ); + if( enableCullFace ) { + gl.glEnable(GL.GL_CULL_FACE); } st.useProgram(gl, true); pmvMatrix.glPushMatrix(); + pmvMatrix.glTranslatef(panX, panY, panZ); pmvMatrix.glRotatef(view_rotx, 1.0f, 0.0f, 0.0f); 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, GearsObject.red); - gear2.draw(gl, 3.1f, -2.0f, -2f * angle - 9.0f, GearsObject.green); - gear3.draw(gl, -3.1f, 4.2f, -2f * angle - 25.0f, GearsObject.blue); + 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); + st.useProgram(gl, false); + + if( enableCullFace ) { + gl.glDisable(GL.GL_CULL_FACE); + } } - + + @Override + public String toString() { + return "GearsES2[obj "+sid()+" isInit "+isInit+", usesShared "+usesSharedGears+", 1 "+gear1+", 2 "+gear2+", 3 "+gear3+", sharedGears "+sharedGears+"]"; + } + boolean confinedFixedCenter = false; - + public void setConfinedFixedCenter(boolean v) { confinedFixedCenter = v; } - - class GearsKeyAdapter extends KeyAdapter { + + class GearsKeyAdapter extends KeyAdapter { public void keyPressed(KeyEvent e) { int kc = e.getKeyCode(); if(KeyEvent.VK_LEFT == kc) { @@ -308,18 +542,54 @@ public class GearsES2 implements GLEventListener { } } - class GearsMouseAdapter extends MouseAdapter { + class GearsMouseAdapter implements MouseListener{ + private int prevMouseX, prevMouseY; + + @Override + public void mouseClicked(MouseEvent e) { + } + + @Override + public void mouseEntered(MouseEvent e) { + } + + @Override + public void mouseExited(MouseEvent e) { + } + + @Override + public void mouseWheelMoved(MouseEvent e) { + float[] rot = e.getRotation(); + if( e.isControlDown() ) { + // alternative zoom + final float incr = e.isShiftDown() ? rot[0] : rot[1] * 0.5f ; + panZ += incr; + System.err.println("panZ.2: incr "+incr+", dblZoom "+e.isShiftDown()+" -> "+panZ); + } else { + // panning + panX -= rot[0]; // positive -> left + panY += rot[1]; // positive -> up + } + } + public void mousePressed(MouseEvent e) { - prevMouseX = e.getX(); - prevMouseY = e.getY(); + if( e.getPointerCount()==1 ) { + prevMouseX = e.getX(); + prevMouseY = e.getY(); + } else if( e.getPointerCount() == 4 ) { + final Object src = e.getSource(); + if( e.getPressure(0, true) > 0.7f && src instanceof Window) { // show Keyboard + ((Window) src).setKeyboardVisible(true); + } + } } public void mouseReleased(MouseEvent e) { } - public void mouseMoved(MouseEvent e) { - if(e.isConfined()) { - navigate(e); + public void mouseMoved(MouseEvent e) { + if( e.isConfined() ) { + navigate(e); } else { // track prev. position so we don't have 'jumps' // in case we move to confined navigation. @@ -327,15 +597,15 @@ public class GearsES2 implements GLEventListener { prevMouseY = e.getY(); } } - + public void mouseDragged(MouseEvent e) { navigate(e); } - + private void navigate(MouseEvent e) { int x = e.getX(); int y = e.getY(); - + int width, height; Object source = e.getSource(); Window window = null; @@ -343,24 +613,29 @@ public class GearsES2 implements GLEventListener { window = (Window) source; width=window.getWidth(); height=window.getHeight(); + } else if (source instanceof GLAutoDrawable) { + GLAutoDrawable glad = (GLAutoDrawable) source; + width = glad.getWidth(); + height = glad.getHeight(); } else if (GLProfile.isAWTAvailable() && source instanceof java.awt.Component) { java.awt.Component comp = (java.awt.Component) source; width=comp.getWidth(); height=comp.getHeight(); } else { throw new RuntimeException("Event source neither Window nor Component: "+source); - } + } final float thetaY = 360.0f * ( (float)(x-prevMouseX)/(float)width); final float thetaX = 360.0f * ( (float)(prevMouseY-y)/(float)height); view_rotx += thetaX; view_roty += thetaY; - if(e.isConfined() && confinedFixedCenter && null!=window) { + if(e.isConfined() && confinedFixedCenter && null!=window) { x=window.getWidth()/2; y=window.getHeight()/2; window.warpPointer(x, y); } prevMouseX = x; prevMouseY = y; + // System.err.println("rotXY.1: "+view_rotx+"/"+view_roty+", source "+e); } } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsObjectES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsObjectES2.java index 82485ea1a..4cef6394e 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsObjectES2.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsObjectES2.java @@ -7,10 +7,10 @@ * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL @@ -24,9 +24,10 @@ import java.nio.FloatBuffer; import javax.media.opengl.GL; import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLBufferStorage; +import javax.media.opengl.GLException; import javax.media.opengl.GLUniformData; - import com.jogamp.opengl.test.junit.jogl.demos.GearsObject; import com.jogamp.opengl.util.GLArrayDataServer; import com.jogamp.opengl.util.PMVMatrix; @@ -37,71 +38,108 @@ import com.jogamp.opengl.util.glsl.ShaderState; * @author Brian Paul (converted to Java by Ron Cemer and Sven Gothel) <P> */ public class GearsObjectES2 extends GearsObject { - PMVMatrix pmvMatrix; - GLUniformData pmvMatrixUniform; - GLUniformData colorUniform; - - public GearsObjectES2(float inner_radius, float outer_radius, float width, - int teeth, float tooth_depth, - PMVMatrix pmvMatrix, - GLUniformData pmvMatrixUniform, - GLUniformData colorUniform) + final PMVMatrix pmvMatrix; + final GLUniformData pmvMatrixUniform; + final GLUniformData colorUniform; + final ShaderState st; + + public GearsObjectES2(GL gl, boolean useMappedBuffers, ShaderState st, FloatBuffer gearColor, + float inner_radius, float outer_radius, + float width, + int teeth, + float tooth_depth, PMVMatrix pmvMatrix, GLUniformData pmvMatrixUniform, GLUniformData colorUniform, boolean validateBuffers) { - super(inner_radius, outer_radius, width, teeth, tooth_depth); + super(gl, useMappedBuffers, gearColor, inner_radius, outer_radius, width, teeth, tooth_depth, validateBuffers); this.pmvMatrix = pmvMatrix; this.pmvMatrixUniform = pmvMatrixUniform; this.colorUniform = colorUniform; + this.st = st; + associate(st); } - public GearsObjectES2(GearsObject shared, - PMVMatrix pmvMatrix, - GLUniformData pmvMatrixUniform, - GLUniformData colorUniform) + public GearsObjectES2(GearsObjectES2 shared, + ShaderState st, + PMVMatrix pmvMatrix, + GLUniformData pmvMatrixUniform, GLUniformData colorUniform) { super(shared); this.pmvMatrix = pmvMatrix; this.pmvMatrixUniform = pmvMatrixUniform; this.colorUniform = colorUniform; + this.st = st; + associate(st); + } + + private void associate(ShaderState st) { + frontFace.associate(st, true); + frontSide.associate(st, true); + backFace.associate(st, true); + backSide.associate(st, true); + outwardFace.associate(st, true); + insideRadiusCyl.associate(st, true); } @Override - public GLArrayDataServer createInterleaved(int comps, int dataType, boolean normalized, int initialSize, int vboUsage) { - return GLArrayDataServer.createGLSLInterleaved(comps, dataType, normalized, initialSize, vboUsage); + public GLArrayDataServer createInterleaved(boolean useMappedBuffers, int comps, int dataType, boolean normalized, int initialSize, int vboUsage) { + if( useMappedBuffers ) { + return GLArrayDataServer.createGLSLInterleavedMapped(comps, dataType, normalized, initialSize, vboUsage); + } else { + return GLArrayDataServer.createGLSLInterleaved(comps, dataType, normalized, initialSize, vboUsage); + } } - + @Override - public void addInterleavedVertexAndNormalArrays(GLArrayDataServer array, - int components) { - array.addGLSLSubArray("vertices", 3, GL.GL_ARRAY_BUFFER); - array.addGLSLSubArray("normals", 3, GL.GL_ARRAY_BUFFER); + public void addInterleavedVertexAndNormalArrays(GLArrayDataServer array, int components) { + array.addGLSLSubArray("vertices", components, GL.GL_ARRAY_BUFFER); + array.addGLSLSubArray("normals", components, GL.GL_ARRAY_BUFFER); } - private void draw(GL2ES2 gl, GLArrayDataServer array, int mode) { - array.enableBuffer(gl, true); - gl.glDrawArrays(mode, 0, array.getElementCount()); - array.enableBuffer(gl, false); + private void draw(GL2ES2 gl, GLArrayDataServer array, int mode, int face) { + if( !isShared || gl.glIsBuffer(array.getVBOName()) ) { + if( validateBuffers ) { + array.bindBuffer(gl, true); + final int bufferTarget = array.getVBOTarget(); + final int bufferName = array.getVBOName(); + final long bufferSize = array.getSizeInBytes(); + final int hasBufferName = gl.getBoundBuffer(bufferTarget); + final GLBufferStorage hasStorage = gl.getBufferStorage(hasBufferName); + final boolean ok = bufferName == hasBufferName && + bufferName == hasStorage.getName() && + bufferSize == hasStorage.getSize(); + if( !ok ) { + throw new GLException("GLBufferStorage Validation Error: Target[exp 0x"+Integer.toHexString(bufferTarget)+", has 0x"+Integer.toHexString(bufferTarget)+ + ", Name[exp "+bufferName+", has "+hasBufferName+", Size exp "+bufferSize+", Storage "+hasStorage+"]"); + } + } + array.enableBuffer(gl, true); + // System.err.println("XXX Draw face "+face+" of "+this); + gl.glDrawArrays(mode, 0, array.getElementCount()); + array.enableBuffer(gl, false); + } } @Override - public void draw(GL _gl, float x, float y, float angle, FloatBuffer color) { + public void draw(GL _gl, float x, float y, float angle) { final GL2ES2 gl = _gl.getGL2ES2(); - final ShaderState st = ShaderState.getShaderState(gl); pmvMatrix.glPushMatrix(); pmvMatrix.glTranslatef(x, y, 0f); pmvMatrix.glRotatef(angle, 0f, 0f, 1f); - pmvMatrix.update(); - st.uniform(gl, pmvMatrixUniform); + if( pmvMatrix.update() ) { + st.uniform(gl, pmvMatrixUniform); + } else { + throw new InternalError("PMVMatrix.update() returns false after mutable operations"); + } - colorUniform.setData(color); + colorUniform.setData(gearColor); st.uniform(gl, colorUniform); - draw(gl, frontFace, GL.GL_TRIANGLE_STRIP); - draw(gl, frontSide, GL.GL_TRIANGLES); - draw(gl, backFace, GL.GL_TRIANGLE_STRIP); - draw(gl, backSide, GL.GL_TRIANGLES); - draw(gl, outwardFace, GL.GL_TRIANGLE_STRIP); - draw(gl, insideRadiusCyl, GL.GL_TRIANGLE_STRIP); - + draw(gl, frontFace, GL.GL_TRIANGLE_STRIP, 0); + draw(gl, frontSide, GL.GL_TRIANGLES, 1); + draw(gl, backFace, GL.GL_TRIANGLE_STRIP, 2); + draw(gl, backSide, GL.GL_TRIANGLES, 3); + draw(gl, outwardFace, GL.GL_TRIANGLE_STRIP, 4); + draw(gl, insideRadiusCyl, GL.GL_TRIANGLE_STRIP, 5); + pmvMatrix.glPopMatrix(); - } + } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/LandscapeES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/LandscapeES2.java new file mode 100644 index 000000000..e7f980ccd --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/LandscapeES2.java @@ -0,0 +1,182 @@ +/** + * Copyright (C) 2013 JogAmp Community. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.jogamp.opengl.test.junit.jogl.demos.es2; + +import com.jogamp.opengl.util.GLArrayDataServer; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; +import com.jogamp.opengl.util.glsl.ShaderState; +import java.nio.FloatBuffer; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLUniformData; + +/** + * LandscapeES2 + */ +public class LandscapeES2 implements GLEventListener { + private int swapInterval = 0; + private boolean verbose = true; + + static public int TARGET_FPS = 120; + private long millisOffset; + private int frameCount; + private float frameRate; + private ShaderCode vertShader; + private ShaderCode fragShader; + private ShaderProgram shaderProg; + private ShaderState shaderState; + private float[] resolution; + private GLUniformData resolutionUni; + private GLUniformData timeUni; + private GLArrayDataServer vertices; + + private int fcount = 0, lastm = 0; + private int fint = 1; + + public LandscapeES2(int swapInterval) { + this.swapInterval = swapInterval; + } + + public LandscapeES2() { + this.swapInterval = 1; + } + + public void setVerbose(boolean v) { verbose = v; } + + public void init(GLAutoDrawable drawable) { + System.err.println(Thread.currentThread()+" LandscapeES2.init ..."); + GL2ES2 gl = drawable.getGL().getGL2ES2(); + + if(verbose) { + System.err.println("LandscapeES2 init on "+Thread.currentThread()); + System.err.println("Chosen GLCapabilities: " + drawable.getChosenGLCapabilities()); + System.err.println("INIT GL IS: " + gl.getClass().getName()); + System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR)); + System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER)); + System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION)); + System.err.println("GL GLSL: "+gl.hasGLSL()+", has-compiler-func: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none")+", "+gl.getContext().getGLSLVersionNumber()); + System.err.println("GL FBO: basic "+ gl.hasBasicFBOSupport()+", full "+gl.hasFullFBOSupport()); + System.err.println("GL Profile: "+gl.getGLProfile()); + System.err.println("GL Renderer Quirks:" + gl.getContext().getRendererQuirks().toString()); + System.err.println("GL:" + gl + ", " + gl.getContext().getGLVersion()); + } + + vertShader = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(), "shader", "shader/bin", "landscape", true); + fragShader = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(), "shader", "shader/bin", "landscape", true); + vertShader.defaultShaderCustomization(gl, true, true); + fragShader.defaultShaderCustomization(gl, true, true); + shaderProg = new ShaderProgram(); + shaderProg.add(gl, vertShader, System.err); + shaderProg.add(gl, fragShader, System.err); + + shaderState = new ShaderState(); + shaderState.attachShaderProgram(gl, shaderProg, true); + + resolution = new float[] { drawable.getWidth(), drawable.getHeight(), 0}; + resolutionUni = new GLUniformData("iResolution", 3, FloatBuffer.wrap(resolution)); + shaderState.ownUniform(resolutionUni); + shaderState.uniform(gl, resolutionUni); + + timeUni = new GLUniformData("iGlobalTime", 0.0f); + shaderState.ownUniform(timeUni); + + vertices = GLArrayDataServer.createGLSL("inVertex", 2, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW); + vertices.putf(-1.0f); vertices.putf(-1.0f); + vertices.putf(+1.0f); vertices.putf(-1.0f); + vertices.putf(-1.0f); vertices.putf(+1.0f); + vertices.putf(+1.0f); vertices.putf(+1.0f); + vertices.seal(gl, true); + shaderState.ownAttribute(vertices, true); + shaderState.useProgram(gl, false); + + millisOffset = System.currentTimeMillis(); + + System.err.println(Thread.currentThread()+" LandscapeES2.init FIN"); + } + + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + System.err.println(Thread.currentThread()+" LandscapeES2.reshape "+x+"/"+y+" "+width+"x"+height+", swapInterval "+swapInterval+", drawable 0x"+Long.toHexString(drawable.getHandle())); + + GL2ES2 gl = drawable.getGL().getGL2ES2(); + + if(-1 != swapInterval) { + gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there) + } + + shaderState.useProgram(gl, true); + + resolution[0] = drawable.getWidth(); + resolution[1] = drawable.getHeight(); + shaderState.uniform(gl, resolutionUni); + + shaderState.useProgram(gl, false); + } + + public void dispose(GLAutoDrawable drawable) { + System.err.println(Thread.currentThread()+" LandscapeES2.dispose ... "); + GL2ES2 gl = drawable.getGL().getGL2ES2(); + shaderState.useProgram(gl, false); + shaderState.destroy(gl); + shaderState = null; + + System.err.println(Thread.currentThread()+" LandscapeES2.dispose FIN"); + } + + public void display(GLAutoDrawable drawable) { + GL2ES2 gl = drawable.getGL().getGL2ES2(); + // Shader fills complete framebuffer regardless of DEPTH, no Clear required. + // gl.glClearColor(0.5f, 0.1f, 0.1f, 1); + // gl.glClear(GL.GL_COLOR_BUFFER_BIT); + + shaderState.useProgram(gl, true); + + timeUni.setData((System.currentTimeMillis() - millisOffset) / 1000.0f); + shaderState.uniform(gl, timeUni); + vertices.enableBuffer(gl, true); + gl.glDrawArrays(GL2ES2.GL_TRIANGLE_STRIP, 0, 4); + vertices.enableBuffer(gl, false); + + shaderState.useProgram(gl, false); + + // Compute current framerate and printout. + frameCount++; + fcount += 1; + int m = (int) (System.currentTimeMillis() - millisOffset); + if (m - lastm > 1000 * fint) { + frameRate = (float)(fcount) / fint; + fcount = 0; + lastm = m; + } + if (frameCount % TARGET_FPS == 0) { + System.out.println("FrameCount: " + frameCount + " - " + "FrameRate: " + frameRate); + } + } + + boolean confinedFixedCenter = false; + + public void setConfinedFixedCenter(boolean v) { + confinedFixedCenter = v; + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/Mix2TexturesES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/Mix2TexturesES2.java new file mode 100644 index 000000000..b69505457 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/Mix2TexturesES2.java @@ -0,0 +1,211 @@ +/** + * Copyright (C) 2011 JogAmp Community. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.jogamp.opengl.test.junit.jogl.demos.es2; + +import java.nio.FloatBuffer; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLUniformData; +import javax.media.opengl.fixedfunc.GLMatrixFunc; + +import com.jogamp.opengl.util.GLArrayDataServer; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; +import com.jogamp.opengl.util.glsl.ShaderState; + +public class Mix2TexturesES2 implements GLEventListener { + private final int swapInterval; + + private final ShaderState st; + private final PMVMatrix pmvMatrix; + private final GLUniformData texUnit0, texUnit1; + + private Object syncTexIDs = new Object(); + private int texID0, texID1; + private ShaderProgram sp0; + private GLUniformData pmvMatrixUniform; + private GLArrayDataServer interleavedVBO; + + public Mix2TexturesES2(int swapInterval, int texUnit0, int texUnit1) { + this.swapInterval = swapInterval; + + st = new ShaderState(); + // st.setVerbose(true); + pmvMatrix = new PMVMatrix(); + + if(0 == texUnit1) { + this.texUnit0 = new GLUniformData("mgl_ActiveTexture", texUnit0); + this.texUnit1 = null; + } else { + this.texUnit0 = new GLUniformData("mgl_Texture0", texUnit0); + this.texUnit1 = new GLUniformData("mgl_Texture1", texUnit1); + } + this.texID0 = 0; + this.texID1 = 0; + } + + public void setTexID0(int texID) { + synchronized( syncTexIDs ) { + this.texID0 = texID; + } + } + public void setTexID1(int texID) { + synchronized( syncTexIDs ) { + this.texID1 = texID; + } + } + + @Override + public void init(GLAutoDrawable drawable) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + + final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, Mix2TexturesES2.class, "shader", + "shader/bin", "texture01_xxx", true); + final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, Mix2TexturesES2.class, "shader", + "shader/bin", null == texUnit1 ? "texture01_xxx" : "texture02_xxx", true); + vp0.defaultShaderCustomization(gl, true, true); + fp0.defaultShaderCustomization(gl, true, true); + + sp0 = new ShaderProgram(); + sp0.add(gl, vp0, System.err); + sp0.add(gl, fp0, System.err); + st.attachShaderProgram(gl, sp0, true); + + pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); + st.ownUniform(pmvMatrixUniform); + st.uniform(gl, pmvMatrixUniform); + + interleavedVBO = GLArrayDataServer.createGLSLInterleaved(3+4+2, GL.GL_FLOAT, false, 3*4, GL.GL_STATIC_DRAW); + { + interleavedVBO.addGLSLSubArray("mgl_Vertex", 3, GL.GL_ARRAY_BUFFER); + interleavedVBO.addGLSLSubArray("mgl_Color", 4, GL.GL_ARRAY_BUFFER); + //interleavedVBO.addGLSLSubArray("mgl_Normal", 3, GL.GL_ARRAY_BUFFER); + interleavedVBO.addGLSLSubArray("mgl_MultiTexCoord", 2, GL.GL_ARRAY_BUFFER); + + FloatBuffer ib = (FloatBuffer)interleavedVBO.getBuffer(); + + for(int i=0; i<4; i++) { + ib.put(s_quadVertices, i*3, 3); + ib.put(s_quadColors, i*4, 4); + //ib.put(s_cubeNormals, i*3, 3); + ib.put(s_quadTexCoords, i*2, 2); + } + } + interleavedVBO.seal(gl, true); + interleavedVBO.enableBuffer(gl, false); + st.ownAttribute(interleavedVBO, true); + + st.ownUniform(texUnit0); + st.uniform(gl, texUnit0); + if(null != texUnit1) { + st.ownUniform(texUnit1); + st.uniform(gl, texUnit1); + } + + st.useProgram(gl, false); + } + + @Override + public void dispose(GLAutoDrawable drawable) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + st.destroy(gl); + + sp0 = null; + pmvMatrixUniform = null; + interleavedVBO = null; + } + + @Override + public void display(GLAutoDrawable drawable) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + + st.useProgram(gl, true); + gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + + interleavedVBO.enableBuffer(gl, true); + + synchronized( syncTexIDs ) { + if(0<texID0) { + gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit0.intValue()); + gl.glBindTexture(GL.GL_TEXTURE_2D, texID0); + } + + if(0<texID1 && null != texUnit1) { + gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit1.intValue()); + gl.glBindTexture(GL.GL_TEXTURE_2D, texID1); + } + + if( !gl.isGLcore() ) { + gl.glEnable(GL.GL_TEXTURE_2D); + } + + gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4); + } + + interleavedVBO.enableBuffer(gl, false); + + st.useProgram(gl, false); + } + + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + + if(-1 != swapInterval) { + gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there) + } + + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glOrthof(-1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 10.0f); + + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + + st.useProgram(gl, true); + st.uniform(gl, pmvMatrixUniform); + st.useProgram(gl, false); + + } + + private static final float[] s_quadVertices = { + -1f, -1f, 0f, // LB + 1f, -1f, 0f, // RB + -1f, 1f, 0f, // LT + 1f, 1f, 0f // RT + }; + private static final float[] s_quadColors = { + 1f, 1f, 1f, 1f, + 1f, 1f, 1f, 1f, + 1f, 1f, 1f, 1f, + 1f, 1f, 1f, 1f }; + private static final float[] s_quadTexCoords = { + 0f, 0f, // LB + 1f, 0f, // RB + 0f, 1f, // LT + 1f, 1f // RT + }; +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/MultisampleDemoES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/MultisampleDemoES2.java new file mode 100644 index 000000000..430ea45c0 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/MultisampleDemoES2.java @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 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: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.test.junit.jogl.demos.es2; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLUniformData; +import javax.media.opengl.fixedfunc.GLMatrixFunc; + +import com.jogamp.opengl.util.ImmModeSink; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; +import com.jogamp.opengl.util.glsl.ShaderState; + +public class MultisampleDemoES2 implements GLEventListener { + + private boolean multisample; + private final ShaderState st; + private final PMVMatrix pmvMatrix; + private ShaderProgram sp0; + private GLUniformData pmvMatrixUniform; + private ImmModeSink immModeSink; + + public MultisampleDemoES2(boolean multisample) { + this.multisample = multisample; + st = new ShaderState(); + st.setVerbose(true); + pmvMatrix = new PMVMatrix(); + } + + public void init(GLAutoDrawable glad) { + final GL2ES2 gl = glad.getGL().getGL2ES2(); + + System.err.println(); + System.err.println("req. msaa: "+multisample); + System.err.println("Requested: " + glad.getNativeSurface().getGraphicsConfiguration().getRequestedCapabilities()); + multisample = multisample & glad.getChosenGLCapabilities().getNumSamples() > 0 ; + System.err.println("Chosen : " + glad.getChosenGLCapabilities()); + System.err.println("has msaa: "+multisample); + System.err.println(); + + final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, MultisampleDemoES2.class, "shader", + "shader/bin", "mgl_default_xxx", true); + final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, MultisampleDemoES2.class, "shader", + "shader/bin", "mgl_default_xxx", true); + vp0.defaultShaderCustomization(gl, true, true); + fp0.defaultShaderCustomization(gl, true, true); + + sp0 = new ShaderProgram(); + sp0.add(gl, vp0, System.err); + sp0.add(gl, fp0, System.err); + st.attachShaderProgram(gl, sp0, true); + + pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); + st.ownUniform(pmvMatrixUniform); + st.uniform(gl, pmvMatrixUniform); + + // Using predef array names, see + // GLPointerFuncUtil.getPredefinedArrayIndexName(glArrayIndex); + immModeSink = ImmModeSink.createGLSL(40, + 3, GL.GL_FLOAT, // vertex + 4, GL.GL_FLOAT, // color + 0, GL.GL_FLOAT, // normal + 0, GL.GL_FLOAT, // texCoords + GL.GL_STATIC_DRAW, st); + final int numSteps = 20; + final double increment = Math.PI / numSteps; + final double radius = 1; + immModeSink.glBegin(GL.GL_LINES); + for (int i = numSteps - 1; i >= 0; i--) { + immModeSink.glVertex3f((float) (radius * Math.cos(i * increment)), + (float) (radius * Math.sin(i * increment)), + 0f); + immModeSink.glColor4f( 1f, 1f, 1f, 1f ); + immModeSink.glVertex3f((float) (-1.0 * radius * Math.cos(i * increment)), + (float) (-1.0 * radius * Math.sin(i * increment)), + 0f); + immModeSink.glColor4f( 1f, 1f, 1f, 1f ); + } + immModeSink.glEnd(gl, false); + + st.useProgram(gl, false); + } + + public void dispose(GLAutoDrawable glad) { + final GL2ES2 gl = glad.getGL().getGL2ES2(); + immModeSink.destroy(gl); + immModeSink = null; + st.destroy(gl); + } + + public void display(GLAutoDrawable glad) { + final GL2ES2 gl = glad.getGL().getGL2ES2(); + if (multisample) { + gl.glEnable(GL.GL_MULTISAMPLE); + } + gl.glClearColor(0, 0, 0, 0); + // gl.glEnable(GL.GL_DEPTH_TEST); + // gl.glDepthFunc(GL.GL_LESS); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + + st.useProgram(gl, true); + + immModeSink.draw(gl, true); + + st.useProgram(gl, false); + } + + // Unused routines + public void reshape(GLAutoDrawable glad, int x, int y, int width, int height) { + System.err.println("reshape .."); + final GL2ES2 gl = glad.getGL().getGL2ES2(); + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + // pmvMatrix.glOrthof(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f); + pmvMatrix.glOrthof(-1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 10.0f); + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + + st.useProgram(gl, true); + st.uniform(gl, pmvMatrixUniform); + st.useProgram(gl, false); + } + + public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) { + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/PointsDemoES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/PointsDemoES2.java new file mode 100644 index 000000000..52af4916c --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/PointsDemoES2.java @@ -0,0 +1,209 @@ +/** + * Copyright 2012 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.jogl.demos.es2; + +import java.nio.FloatBuffer; + +import com.jogamp.common.nio.Buffers; +import com.jogamp.opengl.test.junit.jogl.demos.PointsDemo; +import com.jogamp.opengl.util.GLArrayDataServer; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; +import com.jogamp.opengl.util.glsl.ShaderState; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES1; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GL2GL3; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLUniformData; + +public class PointsDemoES2 extends PointsDemo { + ShaderState st; + PMVMatrix pmvMatrix; + GLUniformData pmvMatrixUniform; + GLArrayDataServer vertices ; + GLArrayDataServer pointSizes ; + private int swapInterval = 0; + final int edge = 8; // 8*8 + /** vec4[2]: { (sz, smooth, attnMinSz, attnMaxSz), (attnCoeff(3), attnFadeTs) } */ + private static final String mgl_PointParams = "mgl_PointParams"; + + /** ( pointSize, pointSmooth, attn. pointMinSize, attn. pointMaxSize ) , ( attenuation coefficients 1f 0f 0f, attenuation fade theshold 1f ) */ + private final FloatBuffer pointParams = Buffers.newDirectFloatBuffer(new float[] { 1.0f, 0.0f, 0.0f, 4096.0f, 1.0f, 0.0f, 0.0f, 1.0f }); + + public PointsDemoES2(int swapInterval) { + this.swapInterval = swapInterval; + } + + public PointsDemoES2() { + this.swapInterval = 1; + } + + public void setSmoothPoints(boolean v) { + pointParams.put(1, v ? 1.0f : 0.0f); + } + + public void setPointParams(float minSize, float maxSize, float distAttenConst, float distAttenLinear, float distAttenQuadratic, float fadeThreshold) { + pointParams.put(2, minSize); + pointParams.put(3, maxSize); + pointParams.put(4+0, distAttenConst); + pointParams.put(4+1, distAttenLinear); + pointParams.put(4+2, distAttenQuadratic); + pointParams.put(4+3, fadeThreshold); + } + + public void init(GLAutoDrawable glad) { + GL2ES2 gl = glad.getGL().getGL2ES2(); + + System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR)); + System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER)); + System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION)); + System.err.println("GL GLSL: "+gl.hasGLSL()+", has-compiler-func: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none")); + System.err.println("GL Profile: "+gl.getGLProfile()); + + st = new ShaderState(); + st.setVerbose(true); + final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(), "shader", + "shader/bin", "PointsShader", true); + final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(), "shader", + "shader/bin", "PointsShader", true); + vp0.defaultShaderCustomization(gl, true, true); + fp0.defaultShaderCustomization(gl, true, true); + final ShaderProgram sp0 = new ShaderProgram(); + sp0.add(gl, vp0, System.err); + sp0.add(gl, fp0, System.err); + st.attachShaderProgram(gl, sp0, true); + + // setup mgl_PMVMatrix + pmvMatrix = new PMVMatrix(); + pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); // P, Mv + st.ownUniform(pmvMatrixUniform); + st.uniform(gl, pmvMatrixUniform); + + st.uniform(gl, new GLUniformData(mgl_PointParams, 4, pointParams)); + + final GLUniformData colorStaticUniform = new GLUniformData("mgl_ColorStatic", 4, Buffers.newDirectFloatBuffer(new float[] { 1.0f, 1.0f, 1.0f, 1.0f }) ); + st.uniform(gl, colorStaticUniform); + st.ownUniform(colorStaticUniform); + + // Allocate Vertex Array + vertices = GLArrayDataServer.createGLSL("mgl_Vertex", 3, GL.GL_FLOAT, false, edge*edge, GL.GL_STATIC_DRAW); + pointSizes = GLArrayDataServer.createGLSL("mgl_PointSize", 1, GL.GL_FLOAT, false, edge*edge, GL.GL_STATIC_DRAW); + for(int i=0; i<edge; i++) { + for(int j=0; j<edge; j++) { + final float x = -3+j*0.7f; + final float y = -3+i*0.7f; + final float p = (i*edge+j)*0.5f; + // System.err.println("["+j+"/"+i+"]: "+x+"/"+y+": "+p); + vertices.putf(x); vertices.putf(y); vertices.putf( 0); + pointSizes.putf(p); + } + } + vertices.seal(gl, true); + st.ownAttribute(vertices, true); + vertices.enableBuffer(gl, false); + pointSizes.seal(gl, true); + st.ownAttribute(pointSizes, true); + pointSizes.enableBuffer(gl, false); + + // OpenGL Render Settings + gl.glEnable(GL2ES2.GL_DEPTH_TEST); + st.useProgram(gl, false); + } + + public void display(GLAutoDrawable glad) { + GL2ES2 gl = glad.getGL().getGL2ES2(); + gl.glClearColor(0f, 0f, 0f, 0f); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + st.useProgram(gl, true); + pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glTranslatef(0, 0, -10); + st.uniform(gl, pmvMatrixUniform); + + GLUniformData ud = st.getUniform(mgl_PointParams); + if(null!=ud) { + // same data object + st.uniform(gl, ud); + } + + vertices.enableBuffer(gl, true); + pointSizes.enableBuffer(gl, true); + + if(gl.isGL2GL3()) { + gl.glEnable(GL2GL3.GL_VERTEX_PROGRAM_POINT_SIZE); + } + if(gl.isGL2ES1()) { + gl.glEnable(GL2ES1.GL_POINT_SPRITE); // otherwise no gl_PointCoord + } + gl.glEnable ( GL.GL_BLEND ); + gl.glBlendFunc ( GL.GL_SRC_ALPHA, GL.GL_ONE ); + + gl.glDrawArrays(GL.GL_POINTS, 0, edge*edge); + + if(gl.isGL2GL3()) { + gl.glDisable(GL2GL3.GL_VERTEX_PROGRAM_POINT_SIZE); + } + + pointSizes.enableBuffer(gl, false); + vertices.enableBuffer(gl, false); + st.useProgram(gl, false); + } + + public void reshape(GLAutoDrawable glad, int x, int y, int width, int height) { + // Thread.dumpStack(); + GL2ES2 gl = glad.getGL().getGL2ES2(); + + if(-1 != swapInterval) { + gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there) + } + + st.useProgram(gl, true); + // Set location in front of camera + pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.gluPerspective(45.0F, ( (float) width / (float) height ) / 1.0f, 1.0F, 100.0F); + //pmvMatrix.glOrthof(-4.0f, 4.0f, -4.0f, 4.0f, 1.0f, 100.0f); + st.uniform(gl, pmvMatrixUniform); + st.useProgram(gl, false); + } + + public void dispose(GLAutoDrawable glad) { + GL2ES2 gl = glad.getGL().getGL2ES2(); + st.destroy(gl); + st = null; + pmvMatrix.destroy(); + pmvMatrix = null; + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java index a24662568..715a97d63 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java @@ -27,32 +27,33 @@ */ package com.jogamp.opengl.test.junit.jogl.demos.es2; -import com.jogamp.newt.event.MouseAdapter; -import com.jogamp.newt.event.MouseEvent; -import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.JoglVersion; import com.jogamp.opengl.util.GLArrayDataServer; import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.TileRendererBase; import com.jogamp.opengl.util.glsl.ShaderCode; import com.jogamp.opengl.util.glsl.ShaderProgram; import com.jogamp.opengl.util.glsl.ShaderState; + import javax.media.opengl.GL; import javax.media.opengl.GL2ES2; -import javax.media.opengl.GLAnimatorControl; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLEventListener; -import javax.media.opengl.GLRunnable; import javax.media.opengl.GLUniformData; -public class RedSquareES2 implements GLEventListener { - ShaderState st; - PMVMatrix pmvMatrix; - GLUniformData pmvMatrixUniform; - GLArrayDataServer vertices ; - GLArrayDataServer colors ; - long t0; +public class RedSquareES2 implements GLEventListener, TileRendererBase.TileRendererListener { + private ShaderState st; + private PMVMatrix pmvMatrix; + private GLUniformData pmvMatrixUniform; + private GLArrayDataServer vertices ; + private GLArrayDataServer colors ; + private long t0; private int swapInterval = 0; - MyMouseAdapter myMouse = new MyMouseAdapter(); - GLWindow glWindow = null; + private float aspect = 1.0f; + private boolean doRotate = true; + private boolean clearBuffers = true; + private TileRendererBase tileRendererInUse = null; + private boolean doRotateBeforePrinting; public RedSquareES2(int swapInterval) { this.swapInterval = swapInterval; @@ -62,26 +63,51 @@ public class RedSquareES2 implements GLEventListener { this.swapInterval = 1; } + @Override + public void addTileRendererNotify(TileRendererBase tr) { + tileRendererInUse = tr; + doRotateBeforePrinting = doRotate; + setDoRotation(false); + } + @Override + public void removeTileRendererNotify(TileRendererBase tr) { + tileRendererInUse = null; + setDoRotation(doRotateBeforePrinting); + } + @Override + public void startTileRendering(TileRendererBase tr) { + System.err.println("RedSquareES2.startTileRendering: "+tr); + } + @Override + public void endTileRendering(TileRendererBase tr) { + System.err.println("RedSquareES2.endTileRendering: "+tr); + } + + public void setAspect(float aspect) { this.aspect = aspect; } + public void setDoRotation(boolean rotate) { this.doRotate = rotate; } + public void setClearBuffers(boolean v) { clearBuffers = v; } + + @Override public void init(GLAutoDrawable glad) { - System.err.println(Thread.currentThread()+" RedSquareES2.init ..."); - GL2ES2 gl = glad.getGL().getGL2ES2(); - - System.err.println(Thread.currentThread()+"Chosen GLCapabilities: " + glad.getChosenGLCapabilities()); - System.err.println(Thread.currentThread()+"INIT GL IS: " + gl.getClass().getName()); - System.err.println(Thread.currentThread()+"GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR)); - System.err.println(Thread.currentThread()+"GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER)); - System.err.println(Thread.currentThread()+"GL_VERSION: " + gl.glGetString(GL.GL_VERSION)); - - System.err.println(Thread.currentThread()+" GL Profile: "+gl.getGLProfile()); - System.err.println(Thread.currentThread()+" GL:" + gl); - System.err.println(Thread.currentThread()+" GL_VERSION=" + gl.glGetString(GL.GL_VERSION)); + System.err.println(Thread.currentThread()+" RedSquareES2.init: tileRendererInUse "+tileRendererInUse); + final GL2ES2 gl = glad.getGL().getGL2ES2(); + System.err.println("RedSquareES2 init on "+Thread.currentThread()); + System.err.println("Chosen GLCapabilities: " + glad.getChosenGLCapabilities()); + System.err.println("INIT GL IS: " + gl.getClass().getName()); + System.err.println(JoglVersion.getGLStrings(gl, null, false).toString()); + if( !gl.hasGLSL() ) { + System.err.println("No GLSL available, no rendering."); + return; + } st = new ShaderState(); st.setVerbose(true); final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(), "shader", - "shader/bin", "RedSquareShader", false); + "shader/bin", "RedSquareShader", true); final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(), "shader", - "shader/bin", "RedSquareShader", false); + "shader/bin", "RedSquareShader", true); + vp0.defaultShaderCustomization(gl, true, true); + fp0.defaultShaderCustomization(gl, true, true); final ShaderProgram sp0 = new ShaderProgram(); sp0.add(gl, vp0, System.err); sp0.add(gl, fp0, System.err); @@ -118,33 +144,39 @@ public class RedSquareES2 implements GLEventListener { colors.enableBuffer(gl, false); // OpenGL Render Settings - gl.glClearColor(0, 0, 0, 1); gl.glEnable(GL2ES2.GL_DEPTH_TEST); st.useProgram(gl, false); - gl.setSwapInterval(swapInterval); - - if (glad instanceof GLWindow) { - glWindow = (GLWindow) glad; - glWindow.addMouseListener(myMouse); - } t0 = System.currentTimeMillis(); System.err.println(Thread.currentThread()+" RedSquareES2.init FIN"); } + @Override public void display(GLAutoDrawable glad) { long t1 = System.currentTimeMillis(); - GL2ES2 gl = glad.getGL().getGL2ES2(); - gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + final GL2ES2 gl = glad.getGL().getGL2ES2(); + if( clearBuffers ) { + if( null != tileRendererInUse ) { + gl.glClearColor(1.0f, 1.0f, 1.0f, 0.0f); + } else { + gl.glClearColor(0, 0, 0, 0); + } + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + } + if( !gl.hasGLSL() ) { + return; + } st.useProgram(gl, true); // One rotation every four seconds pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW); pmvMatrix.glLoadIdentity(); pmvMatrix.glTranslatef(0, 0, -10); - float ang = ((float) (t1 - t0) * 360.0F) / 4000.0F; - pmvMatrix.glRotatef(ang, 0, 0, 1); - pmvMatrix.glRotatef(ang, 0, 1, 0); + if(doRotate) { + float ang = ((float) (t1 - t0) * 360.0F) / 4000.0F; + pmvMatrix.glRotatef(ang, 0, 0, 1); + pmvMatrix.glRotatef(ang, 0, 1, 0); + } st.uniform(gl, pmvMatrixUniform); // Draw a square @@ -156,75 +188,75 @@ public class RedSquareES2 implements GLEventListener { st.useProgram(gl, false); } - public void enableAndroidTrace(boolean v) { - useAndroidDebug = v; + @Override + public void reshape(GLAutoDrawable glad, int x, int y, int width, int height) { + final GL2ES2 gl = glad.getGL().getGL2ES2(); + if(-1 != swapInterval) { + gl.setSwapInterval(swapInterval); + } + reshapeImpl(gl, x, y, width, height, width, height); } - public void reshape(GLAutoDrawable glad, int x, int y, int width, int height) { - System.err.println(Thread.currentThread()+" RedSquareES2.reshape "+x+"/"+y+" "+width+"x"+height+", swapInterval "+swapInterval); - GL2ES2 gl = glad.getGL().getGL2ES2(); + @Override + public void reshapeTile(TileRendererBase tr, + int tileX, int tileY, int tileWidth, int tileHeight, + int imageWidth, int imageHeight) { + final GL2ES2 gl = tr.getAttachedDrawable().getGL().getGL2ES2(); + gl.setSwapInterval(0); + reshapeImpl(gl, tileX, tileY, tileWidth, tileHeight, imageWidth, imageHeight); + } + + void reshapeImpl(GL2ES2 gl, int tileX, int tileY, int tileWidth, int tileHeight, int imageWidth, int imageHeight) { + System.err.println(Thread.currentThread()+" RedSquareES2.reshape "+tileX+"/"+tileY+" "+tileWidth+"x"+tileHeight+" of "+imageWidth+"x"+imageHeight+", swapInterval "+swapInterval+", drawable 0x"+Long.toHexString(gl.getContext().getGLDrawable().getHandle())+", tileRendererInUse "+tileRendererInUse); + // Thread.dumpStack(); + if( !gl.hasGLSL() ) { + return; + } st.useProgram(gl, true); // Set location in front of camera pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION); pmvMatrix.glLoadIdentity(); - pmvMatrix.gluPerspective(45.0F, (float) width / (float) height, 1.0F, 100.0F); + + // compute projection parameters 'normal' perspective + final float fovy=45f; + final float aspect2 = ( (float) imageWidth / (float) imageHeight ) / aspect; + final float zNear=1f; + final float zFar=100f; + + // compute projection parameters 'normal' frustum + final float top=(float)Math.tan(fovy*((float)Math.PI)/360.0f)*zNear; + final float bottom=-1.0f*top; + final float left=aspect2*bottom; + final float right=aspect2*top; + final float w = right - left; + final float h = top - bottom; + + // compute projection parameters 'tiled' + final float l = left + tileX * w / imageWidth; + final float r = l + tileWidth * w / imageWidth; + final float b = bottom + tileY * h / imageHeight; + final float t = b + tileHeight * h / imageHeight; + + pmvMatrix.glFrustumf(l, r, b, t, zNear, zFar); //pmvMatrix.glOrthof(-4.0f, 4.0f, -4.0f, 4.0f, 1.0f, 100.0f); st.uniform(gl, pmvMatrixUniform); st.useProgram(gl, false); - if(useAndroidDebug) { - try { - android.os.Debug.startMethodTracing("RedSquareES2.trace"); - // android.os.Debug.startAllocCounting(); - useAndroidDebug = true; - } catch (NoClassDefFoundError e) { useAndroidDebug=false; } - } - System.err.println(Thread.currentThread()+" RedSquareES2.reshape FIN"); } - private boolean useAndroidDebug = false; + @Override public void dispose(GLAutoDrawable glad) { - if(useAndroidDebug) { - // android.os.Debug.stopAllocCounting(); - android.os.Debug.stopMethodTracing(); - } - System.err.println(Thread.currentThread()+" RedSquareES2.dispose ... "); - if (null != glWindow) { - glWindow.removeMouseListener(myMouse); - glWindow = null; + System.err.println(Thread.currentThread()+" RedSquareES2.dispose: tileRendererInUse "+tileRendererInUse); + final GL2ES2 gl = glad.getGL().getGL2ES2(); + if( !gl.hasGLSL() ) { + return; } - GL2ES2 gl = glad.getGL().getGL2ES2(); st.destroy(gl); st = null; pmvMatrix.destroy(); pmvMatrix = null; System.err.println(Thread.currentThread()+" RedSquareES2.dispose FIN"); - } - - class MyMouseAdapter extends MouseAdapter { - public void mouseClicked(MouseEvent e) { - System.err.println(e); - if(null != glWindow && e.getSource() == glWindow.getDelegatedWindow()) { - if(e.getX() < glWindow.getWidth()/2) { - glWindow.setFullscreen(!glWindow.isFullscreen()); - System.err.println("setFullscreen: "+glWindow.isFullscreen()); - } else { - glWindow.invoke(false, new GLRunnable() { - public boolean run(GLAutoDrawable drawable) { - GL gl = drawable.getGL(); - gl.setSwapInterval(gl.getSwapInterval()<=0?1:0); - System.err.println("setSwapInterval: "+gl.getSwapInterval()); - final GLAnimatorControl a = drawable.getAnimator(); - if( null != a ) { - a.resetFPSCounter(); - } - return true; - } - }); - } - } - } - } + } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareMappedES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareMappedES2.java new file mode 100644 index 000000000..f0c9fc6ed --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareMappedES2.java @@ -0,0 +1,281 @@ +/** + * 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.jogl.demos.es2; + +import java.nio.FloatBuffer; + +import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.util.GLArrayDataServer; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.TileRendererBase; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; +import com.jogamp.opengl.util.glsl.ShaderState; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLBufferStorage; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLUniformData; + +public class RedSquareMappedES2 implements GLEventListener, TileRendererBase.TileRendererListener { + private ShaderState st; + private PMVMatrix pmvMatrix; + private GLUniformData pmvMatrixUniform; + private GLArrayDataServer vertices ; + private GLArrayDataServer colors ; + private long t0; + private int swapInterval = 0; + private float aspect = 1.0f; + private boolean doRotate = true; + private boolean clearBuffers = true; + private TileRendererBase tileRendererInUse = null; + private boolean doRotateBeforePrinting; + + public RedSquareMappedES2(int swapInterval) { + this.swapInterval = swapInterval; + } + + public RedSquareMappedES2() { + this.swapInterval = 1; + } + + @Override + public void addTileRendererNotify(TileRendererBase tr) { + tileRendererInUse = tr; + doRotateBeforePrinting = doRotate; + setDoRotation(false); + } + @Override + public void removeTileRendererNotify(TileRendererBase tr) { + tileRendererInUse = null; + setDoRotation(doRotateBeforePrinting); + } + @Override + public void startTileRendering(TileRendererBase tr) { + System.err.println("RedSquareES2.startTileRendering: "+tr); + } + @Override + public void endTileRendering(TileRendererBase tr) { + System.err.println("RedSquareES2.endTileRendering: "+tr); + } + + public void setAspect(float aspect) { this.aspect = aspect; } + public void setDoRotation(boolean rotate) { this.doRotate = rotate; } + public void setClearBuffers(boolean v) { clearBuffers = v; } + + @Override + public void init(GLAutoDrawable glad) { + System.err.println(Thread.currentThread()+" RedSquareES2.init: tileRendererInUse "+tileRendererInUse); + final GL2ES2 gl = glad.getGL().getGL2ES2(); + + System.err.println("RedSquareES2 init on "+Thread.currentThread()); + System.err.println("Chosen GLCapabilities: " + glad.getChosenGLCapabilities()); + System.err.println("INIT GL IS: " + gl.getClass().getName()); + System.err.println(JoglVersion.getGLStrings(gl, null, false).toString()); + if( !gl.hasGLSL() ) { + System.err.println("No GLSL available, no rendering."); + return; + } + st = new ShaderState(); + st.setVerbose(true); + final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(), "shader", + "shader/bin", "RedSquareShader", true); + final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(), "shader", + "shader/bin", "RedSquareShader", true); + vp0.defaultShaderCustomization(gl, true, true); + fp0.defaultShaderCustomization(gl, true, true); + final ShaderProgram sp0 = new ShaderProgram(); + sp0.add(gl, vp0, System.err); + sp0.add(gl, fp0, System.err); + st.attachShaderProgram(gl, sp0, true); + + // setup mgl_PMVMatrix + pmvMatrix = new PMVMatrix(); + pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); // P, Mv + st.ownUniform(pmvMatrixUniform); + st.uniform(gl, pmvMatrixUniform); + + // Allocate Vertex Array + vertices = GLArrayDataServer.createGLSLMapped("mgl_Vertex", 3, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW); + { + final GLArrayDataServer ad = vertices; + final GLBufferStorage store = ad.mapStorage(gl, GL.GL_WRITE_ONLY); + { + final FloatBuffer fb = store.getMappedBuffer().asFloatBuffer(); + fb.put(-2); fb.put( 2); fb.put( 0); + fb.put( 2); fb.put( 2); fb.put( 0); + fb.put(-2); fb.put(-2); fb.put( 0); + fb.put( 2); fb.put(-2); fb.put( 0); + } + ad.unmapStorage(gl); + } + vertices.seal(gl, true); + st.ownAttribute(vertices, true); + vertices.enableBuffer(gl, false); + + // Allocate Color Array + colors = GLArrayDataServer.createGLSLMapped("mgl_Color", 4, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW); + { + final GLArrayDataServer ad = colors; + final GLBufferStorage store = ad.mapStorage(gl, GL.GL_WRITE_ONLY); + { + final FloatBuffer fb = store.getMappedBuffer().asFloatBuffer(); + fb.put(1); fb.put(0); fb.put(0); fb.put(1); + fb.put(0); fb.put(0); fb.put(1); fb.put(1); + fb.put(1); fb.put(0); fb.put(0); fb.put(1); + fb.put(1); fb.put(0); fb.put(0); fb.put(1); + } + ad.unmapStorage(gl); + } + colors.seal(gl, true); + st.ownAttribute(colors, true); + colors.enableBuffer(gl, false); + + // OpenGL Render Settings + gl.glEnable(GL2ES2.GL_DEPTH_TEST); + st.useProgram(gl, false); + + t0 = System.currentTimeMillis(); + System.err.println(Thread.currentThread()+" RedSquareES2.init FIN"); + } + + @Override + public void display(GLAutoDrawable glad) { + long t1 = System.currentTimeMillis(); + + final GL2ES2 gl = glad.getGL().getGL2ES2(); + if( clearBuffers ) { + if( null != tileRendererInUse ) { + gl.glClearColor(1.0f, 1.0f, 1.0f, 0.0f); + } else { + gl.glClearColor(0, 0, 0, 0); + } + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + } + if( !gl.hasGLSL() ) { + return; + } + st.useProgram(gl, true); + // One rotation every four seconds + pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glTranslatef(0, 0, -10); + if(doRotate) { + float ang = ((t1 - t0) * 360.0F) / 4000.0F; + pmvMatrix.glRotatef(ang, 0, 0, 1); + pmvMatrix.glRotatef(ang, 0, 1, 0); + } + st.uniform(gl, pmvMatrixUniform); + + // Draw a square + vertices.enableBuffer(gl, true); + colors.enableBuffer(gl, true); + gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4); + vertices.enableBuffer(gl, false); + colors.enableBuffer(gl, false); + st.useProgram(gl, false); + } + + @Override + public void reshape(GLAutoDrawable glad, int x, int y, int width, int height) { + final GL2ES2 gl = glad.getGL().getGL2ES2(); + if(-1 != swapInterval) { + gl.setSwapInterval(swapInterval); + } + reshapeImpl(gl, x, y, width, height, width, height); + } + + @Override + public void reshapeTile(TileRendererBase tr, + int tileX, int tileY, int tileWidth, int tileHeight, + int imageWidth, int imageHeight) { + final GL2ES2 gl = tr.getAttachedDrawable().getGL().getGL2ES2(); + gl.setSwapInterval(0); + reshapeImpl(gl, tileX, tileY, tileWidth, tileHeight, imageWidth, imageHeight); + } + + void reshapeImpl(GL2ES2 gl, int tileX, int tileY, int tileWidth, int tileHeight, int imageWidth, int imageHeight) { + System.err.println(Thread.currentThread()+" RedSquareES2.reshape "+tileX+"/"+tileY+" "+tileWidth+"x"+tileHeight+" of "+imageWidth+"x"+imageHeight+", swapInterval "+swapInterval+", drawable 0x"+Long.toHexString(gl.getContext().getGLDrawable().getHandle())+", tileRendererInUse "+tileRendererInUse); + // Thread.dumpStack(); + if( !gl.hasGLSL() ) { + return; + } + + st.useProgram(gl, true); + // Set location in front of camera + pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + + // compute projection parameters 'normal' perspective + final float fovy=45f; + final float aspect2 = ( (float) imageWidth / (float) imageHeight ) / aspect; + final float zNear=1f; + final float zFar=100f; + + // compute projection parameters 'normal' frustum + final float top=(float)Math.tan(fovy*((float)Math.PI)/360.0f)*zNear; + final float bottom=-1.0f*top; + final float left=aspect2*bottom; + final float right=aspect2*top; + final float w = right - left; + final float h = top - bottom; + + // compute projection parameters 'tiled' + final float l = left + tileX * w / imageWidth; + final float r = l + tileWidth * w / imageWidth; + final float b = bottom + tileY * h / imageHeight; + final float t = b + tileHeight * h / imageHeight; + + pmvMatrix.glFrustumf(l, r, b, t, zNear, zFar); + //pmvMatrix.glOrthof(-4.0f, 4.0f, -4.0f, 4.0f, 1.0f, 100.0f); + st.uniform(gl, pmvMatrixUniform); + st.useProgram(gl, false); + + System.err.println(Thread.currentThread()+" RedSquareES2.reshape FIN"); + } + + @Override + public void dispose(GLAutoDrawable glad) { + System.err.println(Thread.currentThread()+" RedSquareES2.dispose: tileRendererInUse "+tileRendererInUse); + final GL2ES2 gl = glad.getGL().getGL2ES2(); + if( !gl.hasGLSL() ) { + return; + } + st.destroy(gl); + st = null; + pmvMatrix.destroy(); + pmvMatrix = null; + System.err.println(Thread.currentThread()+" RedSquareES2.dispose FIN"); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw01ES2Listener.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw01ES2Listener.java new file mode 100644 index 000000000..8aa3a006c --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw01ES2Listener.java @@ -0,0 +1,265 @@ +/** + * Copyright 2012 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.jogl.demos.es2; + +import java.nio.FloatBuffer; + +import com.jogamp.opengl.test.junit.jogl.demos.TextureDraw01Accessor; +import com.jogamp.opengl.util.GLArrayDataServer; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; +import com.jogamp.opengl.util.glsl.ShaderState; +import com.jogamp.opengl.util.texture.Texture; +import com.jogamp.opengl.util.texture.TextureData; +import com.jogamp.opengl.util.texture.TextureIO; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLException; +import javax.media.opengl.GLUniformData; +import javax.media.opengl.fixedfunc.GLMatrixFunc; + +public class TextureDraw01ES2Listener implements GLEventListener, TextureDraw01Accessor { + TextureData textureData; + Texture texture; + int textureUnit; + boolean keepTextureBound; + + ShaderState st; + PMVMatrix pmvMatrix; + GLUniformData pmvMatrixUniform; + GLArrayDataServer interleavedVBO; + float[] clearColor = new float[] { 1.0f, 1.0f, 1.0f, 1.0f }; + + /** + * + * @param td + * @param textureUnit of range [0..] + */ + public TextureDraw01ES2Listener(TextureData td, int textureUnit) { + this.textureData = td; + this.textureUnit = textureUnit; + this.keepTextureBound = false; + } + + public void setClearColor(float[] clearColor) { + this.clearColor = clearColor; + } + + @Override + public void setKeepTextureBound(boolean v) { + this.keepTextureBound = v; + } + @Override + public Texture getTexture( ) { + return this.texture; + } + + /** + public void setTextureData(GL gl, TextureData textureData ) { + if(null!=texture) { + texture.disable(gl); + texture.destroy(gl); + } + if(null!=this.textureData) { + this.textureData.destroy(); + } + this.textureData = textureData; + this.texture = TextureIO.newTexture(this.textureData); + + // fix VBO ! + } */ + + static final String shaderBasename = "texture01_xxx"; + + private void initShader(GL2ES2 gl, boolean use_program) { + // Create & Compile the shader objects + ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(), + "shader", "shader/bin", shaderBasename, true); + ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(), + "shader", "shader/bin", shaderBasename, true); + rsVp.defaultShaderCustomization(gl, true, true); + rsFp.defaultShaderCustomization(gl, true, true); + + // Create & Link the shader program + ShaderProgram sp = new ShaderProgram(); + sp.add(rsVp); + sp.add(rsFp); + if(!sp.link(gl, System.err)) { + throw new GLException("Couldn't link program: "+sp); + } + + // Let's manage all our states using ShaderState. + st = new ShaderState(); + st.attachShaderProgram(gl, sp, use_program); + } + + @Override + public void init(GLAutoDrawable glad) { + if(null!=textureData) { + this.texture = TextureIO.newTexture(glad.getGL(), textureData); + } + GL2ES2 gl = glad.getGL().getGL2ES2(); + + initShader(gl, true); + + // setup mgl_PMVMatrix + pmvMatrix = new PMVMatrix(); + pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); // P, Mv + + st.ownUniform(pmvMatrixUniform); + if(!st.uniform(gl, pmvMatrixUniform)) { + throw new GLException("Error setting PMVMatrix in shader: "+st); + } + if(!st.uniform(gl, new GLUniformData("mgl_ActiveTexture", textureUnit))) { + throw new GLException("Error setting mgl_ActiveTexture in shader: "+st); + } + + // fetch the flipped texture coordinates + texture.getImageTexCoords().getST_LB_RB_LT_RT(s_quadTexCoords, 0, 1f, 1f); + + interleavedVBO = GLArrayDataServer.createGLSLInterleaved(3+4+2, GL.GL_FLOAT, false, 3*4, GL.GL_STATIC_DRAW); + { + interleavedVBO.addGLSLSubArray("mgl_Vertex", 3, GL.GL_ARRAY_BUFFER); + interleavedVBO.addGLSLSubArray("mgl_Color", 4, GL.GL_ARRAY_BUFFER); + //interleavedVBO.addGLSLSubArray("mgl_Normal", 3, GL.GL_ARRAY_BUFFER); + interleavedVBO.addGLSLSubArray("mgl_MultiTexCoord", 2, GL.GL_ARRAY_BUFFER); + + FloatBuffer ib = (FloatBuffer)interleavedVBO.getBuffer(); + + for(int i=0; i<4; i++) { + ib.put(s_quadVertices, i*3, 3); + ib.put(s_quadColors, i*4, 4); + //ib.put(s_cubeNormals, i*3, 3); + ib.put(s_quadTexCoords, i*2, 2); + } + } + interleavedVBO.seal(gl, true); + interleavedVBO.enableBuffer(gl, false); + st.ownAttribute(interleavedVBO, true); + + // OpenGL Render Settings + gl.glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]); + gl.glEnable(GL2ES2.GL_DEPTH_TEST); + + if( keepTextureBound && null != texture ) { + gl.glActiveTexture(GL.GL_TEXTURE0 + textureUnit); + texture.enable(gl); + texture.bind(gl); + } + st.useProgram(gl, false); + } + + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + GL2ES2 gl = drawable.getGL().getGL2ES2(); + + // Clear background to white + gl.glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]); + if(null != st) { + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glOrthof(-1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 10.0f); + + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + + st.useProgram(gl, true); + st.uniform(gl, pmvMatrixUniform); + st.useProgram(gl, false); + } + } + + @Override + public void dispose(GLAutoDrawable drawable) { + GL2ES2 gl = drawable.getGL().getGL2ES2(); + if(null!=texture) { + texture.disable(gl); + texture.destroy(gl); + } + if(null!=textureData) { + textureData.destroy(); + } + + pmvMatrixUniform = null; + pmvMatrix.destroy(); + pmvMatrix=null; + st.destroy(gl); + st=null; + } + + @Override + public void display(GLAutoDrawable drawable) { + GL2ES2 gl = drawable.getGL().getGL2ES2(); + + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + + st.useProgram(gl, true); + interleavedVBO.enableBuffer(gl, true); + if( !keepTextureBound && null != texture ) { + gl.glActiveTexture(GL.GL_TEXTURE0 + textureUnit); + texture.enable(gl); + texture.bind(gl); + } + + gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4); + + if( !keepTextureBound && null != texture ) { + texture.disable(gl); + } + interleavedVBO.enableBuffer(gl, false); + st.useProgram(gl, false); + } + + private static final float[] s_quadVertices = { + -1f, -1f, 0f, // LB + 1f, -1f, 0f, // RB + -1f, 1f, 0f, // LT + 1f, 1f, 0f // RT + }; + private static final float[] s_quadColors = { + 1f, 1f, 1f, 1f, + 1f, 1f, 1f, 1f, + 1f, 1f, 1f, 1f, + 1f, 1f, 1f, 1f }; + private static final float[] s_quadTexCoords = { + 0f, 0f, // LB + 1f, 0f, // RB + 0f, 1f, // LT + 1f, 1f // RT + }; +} + diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw02ES2ListenerFBO.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw02ES2ListenerFBO.java new file mode 100644 index 000000000..aac0080f2 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw02ES2ListenerFBO.java @@ -0,0 +1,285 @@ +/** + * Copyright (C) 2011 JogAmp Community. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.jogamp.opengl.test.junit.jogl.demos.es2; + +import java.nio.FloatBuffer; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLUniformData; +import javax.media.opengl.fixedfunc.GLMatrixFunc; + +import com.jogamp.opengl.FBObject; +import com.jogamp.opengl.FBObject.TextureAttachment; +import com.jogamp.opengl.FBObject.Attachment.Type; +import com.jogamp.opengl.util.GLArrayDataServer; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; +import com.jogamp.opengl.util.glsl.ShaderState; + +public class TextureDraw02ES2ListenerFBO implements GLEventListener { + private final GLEventListener demo; + private final int swapInterval; + private boolean clearBuffers = true; + private int numSamples; + int textureUnit; + boolean keepTextureBound; + + private final ShaderState st; + private final PMVMatrix pmvMatrix; + + private final FBObject fbo0; + + private TextureAttachment fbo0Tex; + + private ShaderProgram sp0; + private GLUniformData pmvMatrixUniform; + private GLArrayDataServer interleavedVBO; + private GLUniformData texUnit0; + + public TextureDraw02ES2ListenerFBO(GLEventListener demo, int swapInterval, int textureUnit) { + this.demo = demo; + this.swapInterval = swapInterval; + this.textureUnit = textureUnit; + this.keepTextureBound = false; + + st = new ShaderState(); + // st.setVerbose(true); + pmvMatrix = new PMVMatrix(); + + fbo0 = new FBObject(); + + numSamples = 0; + } + + public void setClearBuffers(boolean v) { clearBuffers = v; } + + public void setKeepTextureBound(boolean v) { + this.keepTextureBound = v; + } + public void setMSAA(int numSamples) { + this.numSamples=numSamples; + } + public int getMSAA() { return numSamples; } + + @Override + public void init(GLAutoDrawable drawable) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + + demo.init(drawable); + + final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, TextureDraw02ES2ListenerFBO.class, "shader", + "shader/bin", "texture01_xxx", true); + final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, TextureDraw02ES2ListenerFBO.class, "shader", + "shader/bin", "texture02_xxx", true); + vp0.defaultShaderCustomization(gl, true, true); + fp0.defaultShaderCustomization(gl, true, true); + + sp0 = new ShaderProgram(); + sp0.add(gl, vp0, System.err); + sp0.add(gl, fp0, System.err); + st.attachShaderProgram(gl, sp0, true); + + pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); + st.ownUniform(pmvMatrixUniform); + st.uniform(gl, pmvMatrixUniform); + + interleavedVBO = GLArrayDataServer.createGLSLInterleaved(3+4+2, GL.GL_FLOAT, false, 3*4, GL.GL_STATIC_DRAW); + { + interleavedVBO.addGLSLSubArray("mgl_Vertex", 3, GL.GL_ARRAY_BUFFER); + interleavedVBO.addGLSLSubArray("mgl_Color", 4, GL.GL_ARRAY_BUFFER); + //interleavedVBO.addGLSLSubArray("mgl_Normal", 3, GL.GL_ARRAY_BUFFER); + interleavedVBO.addGLSLSubArray("mgl_MultiTexCoord", 2, GL.GL_ARRAY_BUFFER); + + FloatBuffer ib = (FloatBuffer)interleavedVBO.getBuffer(); + + for(int i=0; i<4; i++) { + ib.put(s_quadVertices, i*3, 3); + ib.put(s_quadColors, i*4, 4); + //ib.put(s_cubeNormals, i*3, 3); + ib.put(s_quadTexCoords, i*2, 2); + } + } + interleavedVBO.seal(gl, true); + interleavedVBO.enableBuffer(gl, false); + st.ownAttribute(interleavedVBO, true); + + texUnit0 = new GLUniformData("mgl_Texture0", textureUnit); + st.ownUniform(texUnit0); + st.uniform(gl, texUnit0); + + st.useProgram(gl, false); + + gl.glEnable(GL2ES2.GL_DEPTH_TEST); + } + + private void initFBOs(GL gl, int width, int height) { + // remove all texture attachments, since MSAA uses just color-render-buffer + // and non-MSAA uses texture2d-buffer + fbo0.detachAllColorbuffer(gl); + + fbo0.reset(gl, width, height, numSamples, false); + numSamples = fbo0.getNumSamples(); + + if(numSamples>0) { + fbo0.attachColorbuffer(gl, 0, true); + fbo0.resetSamplingSink(gl); + fbo0Tex = fbo0.getSamplingSink(); + } else { + fbo0Tex = fbo0.attachTexture2D(gl, 0, true); + } + numSamples=fbo0.getNumSamples(); + fbo0.attachRenderbuffer(gl, Type.DEPTH, 24); + fbo0.unbind(gl); + } + + private void resetFBOs(GL gl, int width, int height) { + fbo0.reset(gl, width, height, numSamples, true); + numSamples = fbo0.getNumSamples(); + if(numSamples>0) { + fbo0Tex = fbo0.getSamplingSink(); + } else { + fbo0Tex = (TextureAttachment) fbo0.getColorbuffer(0); + } + } + + @Override + public void dispose(GLAutoDrawable drawable) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + demo.dispose(drawable); + fbo0.destroy(gl); + st.destroy(gl); + + fbo0Tex = null; + sp0 = null; + pmvMatrixUniform = null; + interleavedVBO = null; + } + + @Override + public void display(GLAutoDrawable drawable) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + + if( fbo0.getNumSamples() != numSamples ) { + System.err.println("**** NumSamples: "+fbo0.getNumSamples()+" -> "+numSamples); + resetFBOs(gl, drawable.getWidth(), drawable.getHeight()); + } + + if(0 < numSamples) { + gl.glEnable(GL.GL_MULTISAMPLE); + } + + fbo0.bind(gl); + demo.display(drawable); + fbo0.unbind(gl); + + st.useProgram(gl, true); + if( clearBuffers ) { + gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + } + + if( !keepTextureBound ) { + gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit0.intValue()); + fbo0.use(gl, fbo0Tex); + if( !gl.isGLcore() ) { + gl.glEnable(GL.GL_TEXTURE_2D); + } + } + gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit0.intValue()); + interleavedVBO.enableBuffer(gl, true); + + gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4); + + interleavedVBO.enableBuffer(gl, false); + + if( !keepTextureBound ) { + fbo0.unuse(gl); + } + + st.useProgram(gl, false); + } + + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + + if(-1 != swapInterval) { + gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there) + } + + if( !fbo0.isInitialized() ) { + System.err.println("**** Reshape.Init: "+width+"x"+height); + initFBOs(gl, width, height); + } else { + System.err.println("**** Reshape.Reset: "+width+"x"+height); + if( keepTextureBound ) { + fbo0.unuse(gl); + } + resetFBOs(gl, width, height); + } + + fbo0.bind(gl); + demo.reshape(drawable, x, y, width, height); + fbo0.unbind(gl); + + if( keepTextureBound ) { + gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit0.intValue()); + fbo0.use(gl, fbo0Tex); + if( !gl.isGLcore() ) { + gl.glEnable(GL.GL_TEXTURE_2D); + } + } + + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glOrthof(-1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 10.0f); + + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + + st.useProgram(gl, true); + st.uniform(gl, pmvMatrixUniform); + st.useProgram(gl, false); + + } + + private static final float[] s_quadVertices = { + -1f, -1f, 0f, // LB + 1f, -1f, 0f, // RB + -1f, 1f, 0f, // LT + 1f, 1f, 0f // RT + }; + private static final float[] s_quadColors = { + 1f, 1f, 1f, 1f, + 1f, 1f, 1f, 1f, + 1f, 1f, 1f, 1f, + 1f, 1f, 1f, 1f }; + private static final float[] s_quadTexCoords = { + 0f, 0f, // LB + 1f, 0f, // RB + 0f, 1f, // LT + 1f, 1f // RT + }; +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TexCubeES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureSequenceCubeES2.java index e85468bcb..b02238c2b 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TexCubeES2.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureSequenceCubeES2.java @@ -3,14 +3,14 @@ * * 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 @@ -20,20 +20,18 @@ * 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.jogl.demos.es2; -import java.nio.ByteBuffer; import java.nio.FloatBuffer; import javax.media.opengl.GL; import javax.media.opengl.GL2ES2; import javax.media.opengl.GLAutoDrawable; -import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLES2; import javax.media.opengl.GLEventListener; import javax.media.opengl.GLException; @@ -41,17 +39,13 @@ import javax.media.opengl.GLProfile; import javax.media.opengl.GLUniformData; import javax.media.opengl.fixedfunc.GLMatrixFunc; +import com.jogamp.common.os.Platform; import com.jogamp.newt.Window; import com.jogamp.newt.event.MouseAdapter; import com.jogamp.newt.event.MouseEvent; import com.jogamp.newt.event.MouseListener; -import com.jogamp.newt.event.WindowAdapter; -import com.jogamp.newt.event.WindowEvent; -import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.GLExtensions; import com.jogamp.opengl.JoglVersion; -import com.jogamp.opengl.test.junit.jogl.demos.TestTextureSequence; -import com.jogamp.opengl.test.junit.util.MiscUtils; -import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.util.GLArrayDataServer; import com.jogamp.opengl.util.PMVMatrix; import com.jogamp.opengl.util.glsl.ShaderCode; @@ -60,40 +54,40 @@ import com.jogamp.opengl.util.glsl.ShaderState; import com.jogamp.opengl.util.texture.Texture; import com.jogamp.opengl.util.texture.TextureCoords; import com.jogamp.opengl.util.texture.TextureSequence; +import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame; -public class TexCubeES2 implements GLEventListener { - public TexCubeES2 (TextureSequence texSource, boolean innerCube, float zoom0, float rotx, float roty) { +public class TextureSequenceCubeES2 implements GLEventListener { + public TextureSequenceCubeES2 (TextureSequence texSource, boolean innerCube, float zoom0, float rotx, float roty) { this.texSeq = texSource; this.innerCube = innerCube; - this.zoom0 = zoom0; + this.zoom = zoom0; this.view_rotx = rotx; this.view_roty = roty; } private TextureSequence texSeq; - private ShaderState st; - private PMVMatrix pmvMatrix; + public ShaderState st; + public PMVMatrix pmvMatrix; private GLUniformData pmvMatrixUniform; // private TextureCoords[] textureCoords = null; private float nearPlaneNormalized; // private float zoom0=-5.0f, zoom=zoom0; // private float view_rotx = 20.0f, view_roty = 30.0f, view_rotz = 0.0f; - private float zoom0=-2.3f, zoom=zoom0; - private float view_rotx = 0.0f, view_roty = 0.0f, view_rotz = 0.0f; + public float zoom=-2.3f; + private float view_rotx = 0.0f, view_roty = 0.0f; + private final float view_rotz = 0.0f; int[] vboNames = new int[4]; boolean innerCube; - boolean initialized = false; - private ByteBuffer cubeIndices; - + private final MouseListener mouseAction = new MouseAdapter() { int lx = 0; int ly = 0; boolean first = false; public void mousePressed(MouseEvent e) { - first = true; + first = true; } - public void mouseMoved(MouseEvent e) { + public void mouseMoved(MouseEvent e) { first = false; } public void mouseDragged(MouseEvent e) { @@ -110,7 +104,7 @@ public class TexCubeES2 implements GLEventListener { height=comp.getHeight(); } else { throw new RuntimeException("Event source neither Window nor Component: "+source); - } + } if(e.getPointerCount()==2) { // 2 pointers zoom .. if(first) { @@ -120,9 +114,14 @@ public class TexCubeES2 implements GLEventListener { } int nv = Math.abs(e.getY(0)-e.getY(1)); int dy = nv - lx; - - zoom += 40f*Math.signum(dy)/(float)height; - + + { + final float o = zoom; + final float d = 40f*Math.signum(dy)/height; + zoom += d; + System.err.println("zoom.d: "+o+" + "+d+" -> "+zoom); + } + lx = nv; } else { // 1 pointer rotate @@ -139,47 +138,55 @@ public class TexCubeES2 implements GLEventListener { lx = nx; ly = ny; } - } + } public void mouseWheelMoved(MouseEvent e) { - zoom += e.getWheelRotation()/10f; - System.err.println("zoom: "+zoom); + // System.err.println("XXX "+e); + if( !e.isShiftDown() ) { + final float o = zoom; + final float d = e.getRotation()[1]/10f; // vertical: wheel + zoom += d; + System.err.println("zoom.w: "+o+" + "+d+" -> "+zoom); + } } }; - - static final String[] es2_prelude = { "#version 100\n", "precision mediump float;\n" }; - static final String gl2_prelude = "#version 110\n"; + static final String shaderBasename = "texsequence_xxx"; static final String myTextureLookupName = "myTexture2D"; - + private void initShader(GL2ES2 gl) { // Create & Compile the shader objects - ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, TexCubeES2.class, + ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(), "shader", "shader/bin", shaderBasename, true); - ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, TexCubeES2.class, + ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(), "shader", "shader/bin", shaderBasename, true); - - // Prelude shader code w/ GLSL profile specifics [ 1. pre-proc, 2. other ] - int rsFpPos; - if(gl.isGLES2()) { - rsVp.insertShaderSource(0, 0, es2_prelude[0]); - rsFpPos = rsFp.insertShaderSource(0, 0, es2_prelude[0]); - } else { - rsVp.insertShaderSource(0, 0, gl2_prelude); - rsFpPos = rsFp.insertShaderSource(0, 0, gl2_prelude); + + boolean preludeGLSLVersion = true; + if( GLES2.GL_TEXTURE_EXTERNAL_OES == texSeq.getTextureTarget() ) { + if( !gl.isExtensionAvailable(GLExtensions.OES_EGL_image_external) ) { + throw new GLException(GLExtensions.OES_EGL_image_external+" requested but not available"); + } + if( Platform.OSType.ANDROID == Platform.getOSType() && gl.isGLES3() ) { + // Bug on Nexus 10, ES3 - Android 4.3, where + // GL_OES_EGL_image_external extension directive leads to a failure _with_ '#version 300 es' ! + // P0003: Extension 'GL_OES_EGL_image_external' not supported + preludeGLSLVersion = false; + } } + rsVp.defaultShaderCustomization(gl, preludeGLSLVersion, true); + + int rsFpPos = preludeGLSLVersion ? rsFp.addGLSLVersion(gl) : 0; rsFpPos = rsFp.insertShaderSource(0, rsFpPos, texSeq.getRequiredExtensionsShaderStub()); - if(gl.isGLES2()) { - rsFpPos = rsFp.insertShaderSource(0, rsFpPos, es2_prelude[1]); - } - final String texLookupFuncName = texSeq.getTextureLookupFunctionName(myTextureLookupName); + rsFpPos = rsFp.addDefaultShaderPrecision(gl, rsFpPos); + + final String texLookupFuncName = texSeq.getTextureLookupFunctionName(myTextureLookupName); rsFp.replaceInShaderSource(myTextureLookupName, texLookupFuncName); - + // Inject TextureSequence shader details final StringBuilder sFpIns = new StringBuilder(); sFpIns.append("uniform ").append(texSeq.getTextureSampler2DType()).append(" mgl_ActiveTexture;\n"); sFpIns.append(texSeq.getTextureLookupFragmentShaderImpl()); rsFp.insertShaderSource(0, "TEXTURE-SEQUENCE-CODE-BEGIN", 0, sFpIns); - + // Create & Link the shader program ShaderProgram sp = new ShaderProgram(); sp.add(rsVp); @@ -192,35 +199,36 @@ public class TexCubeES2 implements GLEventListener { st = new ShaderState(); st.attachShaderProgram(gl, sp, false); } - - GLArrayDataServer interleavedVBO; - + + GLArrayDataServer interleavedVBO, cubeIndicesVBO; + public void init(GLAutoDrawable drawable) { GL2ES2 gl = drawable.getGL().getGL2ES2(); System.err.println(JoglVersion.getGLInfo(gl, null)); - final Texture tex= texSeq.getLastTexture().getTexture(); - - final boolean useExternalTexture = GLES2.GL_TEXTURE_EXTERNAL_OES == tex.getTarget(); - if(useExternalTexture && !gl.isExtensionAvailable("GL_OES_EGL_image_external")) { - throw new GLException("GL_OES_EGL_image_external requested but not available"); + final TextureFrame frame = texSeq.getLastTexture(); + if( null == frame ) { + return; } - + final Texture tex= frame.getTexture(); + initShader(gl); - // Push the 1st uniform down the path + // Push the 1st uniform down the path st.useProgram(gl, true); pmvMatrix = new PMVMatrix(); reshapePMV(drawable.getWidth(), drawable.getHeight()); - pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); + pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); // P, Mv if(!st.uniform(gl, pmvMatrixUniform)) { throw new GLException("Error setting PMVMatrix in shader: "+st); } if(!st.uniform(gl, new GLUniformData("mgl_ActiveTexture", texSeq.getTextureUnit()))) { throw new GLException("Error setting mgl_ActiveTexture in shader: "+st); } - - + + + // calculate centered tex coords w/ aspect ratio + float[] fixedCubeTexCoords = new float[s_cubeTexCoords.length]; { final float aspect = tex.getAspectRatio(); final TextureCoords tc = tex.getImageTexCoords(); @@ -235,52 +243,63 @@ public class TexCubeES2 implements GLEventListener { final float tx = s_cubeTexCoords[i+0]; final float ty = s_cubeTexCoords[i+1]; if(tx!=0) { - s_cubeTexCoords[i+0] = tc_x1 * ss; + fixedCubeTexCoords[i+0] = tc_x1 * ss; } if(ty==0 && !tex.getMustFlipVertically() || ty!=0 && tex.getMustFlipVertically()) { - s_cubeTexCoords[i+1] = 0f + dy; + fixedCubeTexCoords[i+1] = 0f + dy; } else { - s_cubeTexCoords[i+1] = tc_y1 * ts + dy; + fixedCubeTexCoords[i+1] = tc_y1 * ts + dy; } } } - - + interleavedVBO = GLArrayDataServer.createGLSLInterleaved(3+4+2, GL.GL_FLOAT, false, 3*6*4, GL.GL_STATIC_DRAW); - { - interleavedVBO.addGLSLSubArray("mgl_Vertex", 3, GL.GL_ARRAY_BUFFER); - interleavedVBO.addGLSLSubArray("mgl_Color", 4, GL.GL_ARRAY_BUFFER); + { + interleavedVBO.addGLSLSubArray("mgl_Vertex", 3, GL.GL_ARRAY_BUFFER); + interleavedVBO.addGLSLSubArray("mgl_Color", 4, GL.GL_ARRAY_BUFFER); //interleavedVBO.addGLSLSubArray("mgl_Normal", 3, GL.GL_ARRAY_BUFFER); interleavedVBO.addGLSLSubArray("mgl_MultiTexCoord", 2, GL.GL_ARRAY_BUFFER); FloatBuffer ib = (FloatBuffer)interleavedVBO.getBuffer(); - + for(int i=0; i<6*4; i++) { ib.put(s_cubeVertices, i*3, 3); - ib.put(s_cubeColors, i*4, 4); + ib.put(s_cubeColors, i*4, 4); //ib.put(s_cubeNormals, i*3, 3); - ib.put(s_cubeTexCoords, i*2, 2); - } + ib.put(fixedCubeTexCoords, i*2, 2); + } } interleavedVBO.seal(gl, true); interleavedVBO.enableBuffer(gl, false); st.ownAttribute(interleavedVBO, true); - cubeIndices = ByteBuffer.wrap(s_cubeIndices); - + + cubeIndicesVBO = GLArrayDataServer.createData(6, GL.GL_UNSIGNED_SHORT, 6, GL.GL_STATIC_DRAW, GL.GL_ELEMENT_ARRAY_BUFFER); + for(int i=0; i<6*6; i++) { + cubeIndicesVBO.puts(s_cubeIndices[i]); + } + cubeIndicesVBO.seal(gl, true); + cubeIndicesVBO.enableBuffer(gl, false); + st.ownAttribute(cubeIndicesVBO, true); + + gl.glEnable(GL2ES2.GL_DEPTH_TEST); st.useProgram(gl, false); - if (drawable instanceof Window) { - Window window = (Window) drawable; + final Object upstreamWidget = drawable.getUpstreamWidget(); + if (upstreamWidget instanceof Window) { + final Window window = (Window) upstreamWidget; window.addMouseListener(mouseAction); + } else if (GLProfile.isAWTAvailable() && upstreamWidget instanceof java.awt.Component) { + final java.awt.Component comp = (java.awt.Component) upstreamWidget; + new com.jogamp.newt.event.awt.AWTMouseAdapter(mouseAction).addTo(comp); } - + // Let's show the completed shader state .. System.out.println("iVBO: "+interleavedVBO); System.out.println(st); } - + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { GL2ES2 gl = drawable.getGL().getGL2ES2(); @@ -309,44 +328,56 @@ public class TexCubeES2 implements GLEventListener { st.useProgram(gl, false); } } - - + + private void reshapePMV(int width, int height) { - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); - pmvMatrix.glLoadIdentity(); - if(!innerCube) { - pmvMatrix.gluPerspective(45.0f, (float)width / (float)height, 1f, 10.0f); - nearPlaneNormalized = 1f/(100f-1f); - } else { - pmvMatrix.glOrthof(-1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 10.0f); - nearPlaneNormalized = 0f; - } - System.err.println("XXX0: Perspective nearPlaneNormalized: "+nearPlaneNormalized); + if(null != pmvMatrix) { + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + if(!innerCube) { + pmvMatrix.gluPerspective(45.0f, (float)width / (float)height, 1f, 10.0f); + nearPlaneNormalized = 1f/(100f-1f); + } else { + pmvMatrix.glOrthof(-1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 10.0f); + nearPlaneNormalized = 0f; + } + System.err.println("XXX0: Perspective nearPlaneNormalized: "+nearPlaneNormalized); - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); - pmvMatrix.glLoadIdentity(); - pmvMatrix.glTranslatef(0, 0, zoom0); + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glTranslatef(0, 0, zoom); + } } + @Override public void dispose(GLAutoDrawable drawable) { GL2ES2 gl = drawable.getGL().getGL2ES2(); - texSeq = null; + texSeq = null; pmvMatrixUniform = null; - pmvMatrix.destroy(); - pmvMatrix=null; - st.destroy(gl); - st=null; + if( null != pmvMatrix ) { + pmvMatrix.destroy(); + pmvMatrix=null; + } + if( null != st ) { + st.destroy(gl); + st=null; + } } + @Override public void display(GLAutoDrawable drawable) { GL2ES2 gl = drawable.getGL().getGL2ES2(); gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + if( null == st ) { + return; + } + st.useProgram(gl, true); - + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); pmvMatrix.glLoadIdentity(); pmvMatrix.glTranslatef(0, 0, zoom); @@ -357,25 +388,25 @@ public class TexCubeES2 implements GLEventListener { interleavedVBO.enableBuffer(gl, true); Texture tex = null; if(null!=texSeq) { - final TextureSequence.TextureFrame texFrame = texSeq.getNextTexture(gl, true); + final TextureSequence.TextureFrame texFrame = texSeq.getNextTexture(gl); if(null != texFrame) { tex = texFrame.getTexture(); gl.glActiveTexture(GL.GL_TEXTURE0+texSeq.getTextureUnit()); tex.enable(gl); - tex.bind(gl); + tex.bind(gl); } } - gl.glDrawElements(GL.GL_TRIANGLES, 6 * 6, GL.GL_UNSIGNED_BYTE, cubeIndices); + cubeIndicesVBO.bindBuffer(gl, true); // keeps VBO binding + gl.glDrawElements(GL2ES2.GL_TRIANGLES, cubeIndicesVBO.getElementCount() * cubeIndicesVBO.getComponentCount(), GL2ES2.GL_UNSIGNED_SHORT, 0); + cubeIndicesVBO.bindBuffer(gl, false); + if(null != tex) { - tex.disable(gl); + tex.disable(gl); } interleavedVBO.enableBuffer(gl, false); - st.useProgram(gl, false); + st.useProgram(gl, false); } - public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) { - } - static final float[] light_position = { -50.f, 50.f, 50.f, 0.f }; static final float[] light_ambient = { 0.125f, 0.125f, 0.125f, 1.f }; static final float[] light_diffuse = { 1.0f, 1.0f, 1.0f, 1.f }; @@ -385,18 +416,18 @@ public class TexCubeES2 implements GLEventListener { private static final float[] s_cubeVertices = /* f b t b r l */ { -1f, 1f, 1f, 1f, -1f, 1f, 1f, 1f, 1f, -1f, -1f, 1f, - + -1f, 1f, -1f, 1f, -1f, -1f, 1f, 1f, -1f, -1f, -1f, -1f, - + -1f, -1f, 1f, 1f, -1f, -1f, 1f, -1f, 1f, -1f, -1f, -1f, - + -1f, 1f, 1f, 1f, 1f, -1f, 1f, 1f, 1f, -1f, 1f, -1f, - + 1f, -1f, 1f, 1f, 1f, -1f, 1f, 1f, 1f, 1f, -1f, -1f, - + -1f, -1f, 1f, -1f, 1f, -1f, -1f, 1f, 1f, -1f, -1f, -1f }; - + private static final float[] s_cubeTexCoords = { // LT RB RT LB 0f, 1f, 1f, 0f, 1f, 1f, 0f, 0f, @@ -415,38 +446,39 @@ public class TexCubeES2 implements GLEventListener { private static final float[] s_cubeColors = { 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, - + 40f/255f, 80f/255f, 160f/255f, 255f/255f, 40f/255f, 80f/255f, 160f/255f, 255f/255f, 40f/255f, 80f/255f, 160f/255f, 255f/255f, 40f/255f, 80f/255f, 160f/255f, 255f/255f, - + 40f/255f, 80f/255f, 160f/255f, 255f/255f, 40f/255f, 80f/255f, 160f/255f, 255f/255f, - 40f/255f, 80f/255f, 160f/255f, 255f/255f, 40f/255f, 80f/255f, 160f/255f, 255f/255f, - + 40f/255f, 80f/255f, 160f/255f, 255f/255f, 40f/255f, 80f/255f, 160f/255f, 255f/255f, + 128f/255f, 128f/255f, 128f/255f, 255f/255f, 128f/255f, 128f/255f, 128f/255f, 255f/255f, 128f/255f, 128f/255f, 128f/255f, 255f/255f, 128f/255f, 128f/255f, 128f/255f, 255f/255f, - + 255f/255f, 110f/255f, 10f/255f, 255f/255f, 255f/255f, 110f/255f, 10f/255f, 255f/255f, 255f/255f, 110f/255f, 10f/255f, 255f/255f, 255f/255f, 110f/255f, 10f/255f, 255f/255f, - + 255f/255f, 70f/255f, 60f/255f, 255f/255f, 255f/255f, 70f/255f, 60f/255f, 255f/255f, 255f/255f, 70f/255f, 60f/255f, 255f/255f, 255f/255f, 70f/255f, 60f/255f, 255f/255f }; - + + /* private static final float[] s_cubeNormals = { 0f, 0f, 1f, 0f, 0f, 1f, 0f, 0f, 1f, 0f, 0f, 1f, - + 0f, 0f, -1f, 0f, 0f, -1f, 0f, 0f, -1f, 0f, 0f, -1f, - + 0f, -1f, 0f, 0f, -1f, 0f, 0f, -1f, 0f, 0f, -1f, 0f, - + 0f, 1f, 0f, 0f, 1f, 0f, 0f, 1f, 0f, 0f, 1f, 0f, - + 1f, 0f, 0f, 1f, 0f, 0f, 1f, 0f, 0f, 1f, 0f, 0f, - + -1f, 0f, 0f, -1f, 0f, 0f, -1f, 0f, 0f, -1f, 0f, 0f - }; - private static final byte[] s_cubeIndices = + };*/ + private static final short[] s_cubeIndices = { 0, 3, 1, 2, 0, 1, /* front */ 6, 5, 4, 5, 7, 4, /* back */ @@ -455,53 +487,5 @@ public class TexCubeES2 implements GLEventListener { 16, 19, 17, 18, 16, 17, /* right */ 23, 20, 21, 20, 22, 21 /* left */ }; - - public static void main(String[] args) { - int width = 510; - int height = 300; - boolean useBuildInTexLookup = false; - System.err.println("TexCubeES2.run()"); - - for(int i=0; i<args.length; i++) { - if(args[i].equals("-width")) { - i++; - width = MiscUtils.atoi(args[i], width); - } else if(args[i].equals("-height")) { - i++; - height = MiscUtils.atoi(args[i], height); - } else if(args[i].equals("-shaderBuildIn")) { - useBuildInTexLookup = true; - } - } - - final GLWindow window = GLWindow.create(new GLCapabilities(GLProfile.getGL2ES2())); - // Size OpenGL to Video Surface - window.setSize(width, height); - window.setFullscreen(false); - window.setSize(width, height); - final TestTextureSequence texSource = new TestTextureSequence(useBuildInTexLookup); - window.addGLEventListener(new GLEventListener() { - @Override - public void init(GLAutoDrawable drawable) { - texSource.initGLResources(drawable.getGL()); - } - @Override - public void dispose(GLAutoDrawable drawable) { } - @Override - public void display(GLAutoDrawable drawable) { } - @Override - public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } - }); - window.addGLEventListener(new TexCubeES2(texSource, false, -2.3f, 0f, 0f)); - window.setVisible(true); - final Animator anim = new Animator(window); - // anim.setUpdateFPSFrames(60, System.err); - anim.start(); - window.addWindowListener(new WindowAdapter() { - public void windowDestroyed(WindowEvent e) { - anim.stop(); - } - }); - } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/CrossFadePlayer.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/CrossFadePlayer.java new file mode 100644 index 000000000..02f62c415 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/CrossFadePlayer.java @@ -0,0 +1,211 @@ +/**
+ * Copyright 2014 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.jogl.demos.es2.av;
+
+import com.jogamp.opengl.util.av.AudioSink;
+import com.jogamp.opengl.util.av.GLMediaPlayer;
+import com.jogamp.opengl.util.av.GLMediaPlayer.GLMediaEventListener;
+import com.jogamp.opengl.util.av.GLMediaPlayer.StreamException;
+import com.jogamp.opengl.util.av.GLMediaPlayerFactory;
+import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame;
+
+import java.io.File;
+import java.net.URI;
+
+/**
+ * Parallel media player that demonstrate CrossFade of audio volume during playback.
+ * This also demonstrate audio only playback of the GLMediaPlayer.
+ */
+public class CrossFadePlayer
+{
+ static GLMediaPlayer[] player;
+ static volatile boolean stop = false;
+
+ public static void main(String[] args)
+ {
+
+ if(args.length==0) {
+ System.out.println("No files! \n" +
+ "pass as many media files you want\n" +
+ "to the CrossFadePlayer arguments \n" +
+ "and i will try CrossFade-play them all in parallel!");
+ }
+
+ GLMediaEventListener mediaEventListener = new GLMediaEventListener()
+ {
+ @Override
+ public void newFrameAvailable(GLMediaPlayer ts, TextureFrame newFrame, long when) { }
+
+ @Override
+ public void attributesChanged(final GLMediaPlayer mp, int event_mask, long when)
+ {
+ System.out.println("\n***\nEvent mask changed: " + event_mask);
+ System.out.println("Timestamp: "+ when);
+ System.out.println("State of player: " + mp.getState().toString() +"\n");
+
+ if ((event_mask & GLMediaEventListener.EVENT_CHANGE_INIT) !=0) {
+ System.out.println("Duration: " + mp.getDuration() + "ms");
+ System.out.println("Volume: " + mp.getAudioVolume());
+ System.out.println("player.initGL()...");
+ new Thread() {
+ public void run() {
+ try {
+ mp.initGL(null);
+ if ( GLMediaPlayer.State.Paused == mp.getState() ) { // init OK
+ mp.play();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }.start();
+ } else if ((event_mask & GLMediaEventListener.EVENT_CHANGE_PAUSE) !=0) {
+ System.out.println("player.paused()...");
+ } else if ((event_mask & GLMediaEventListener.EVENT_CHANGE_PLAY) !=0) {
+ System.out.println("playing...");
+ System.out.println(mp.toString());
+ System.out.println(mp.getAudioSink().toString());
+ } else if( 0 != ( GLMediaEventListener.EVENT_CHANGE_EOS & event_mask ) ) {
+ final StreamException se = mp.getStreamException();
+ if( null != se ) {
+ System.err.println("Player State: EOS + Exception");
+ stop = true;
+ } else {
+ System.err.println("Player State: EOS");
+ new Thread() {
+ public void run() {
+ System.out.println("mp.setPlaySpeed(1f) returned: " + mp.setPlaySpeed(1f));
+ mp.seek(0);
+ mp.play();
+ }
+ }.start();
+ }
+ }
+ if( 0 != ( ( GLMediaEventListener.EVENT_CHANGE_ERR | GLMediaEventListener.EVENT_CHANGE_EOS ) & event_mask ) ) {
+ final StreamException se = mp.getStreamException();
+ if( null != se ) {
+ se.printStackTrace();
+ }
+ new Thread() {
+ public void run() {
+ System.out.println("terminating...");
+ stop = true;
+ }
+ }.start();
+ }
+
+ }
+ };
+
+ // Initialize media players
+ player = new GLMediaPlayer[args.length];
+ int i=0;
+ for( String arg: args ) {
+ player[i] = GLMediaPlayerFactory.createDefault();
+ if(player[i]!=null){
+ System.out.println("Created CrossFade player: "+ i + " " + player[i].getClass().getName());
+ player[i].addEventListener(mediaEventListener);
+ try {
+ final String filename = arg;
+ if(filename.equals("")){
+ System.out.println("No file selected: arg " + i +" = "+ filename);
+ player[i]=null;
+ } else {
+ File file = new File(filename);
+ if(!file.exists()){
+ System.out.println("File do not exist");
+ } else {
+ URI uri = file.toURI();
+ System.out.println("State of player "+ i +": " + player[i].getState().toString());
+ System.out.println("...initializing stream "+ i +"...");
+ player[i].initStream(uri, GLMediaPlayer.STREAM_ID_NONE, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.TEXTURE_COUNT_DEFAULT);
+
+ }
+ }
+ } catch (Exception e1) {
+ e1.printStackTrace();
+ }
+ } else {
+ System.out.println("Failed to create player "+ i +"!");
+ }
+ i++;
+ }
+
+
+ // Main thread CrossFade until playback is done
+ long startTime = com.jogamp.common.os.Platform.currentTimeMillis();
+ double piPlayers = Math.PI*2.0f/args.length;
+ StreamException se = null;
+ while( null == se && stop == false ) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) { }
+
+ // Find out the longest duration...
+ float maxDuration = 1000.0f ;
+ for(GLMediaPlayer p: player) {
+ if(p!=null){
+ if( p.getDuration() > maxDuration) {
+ maxDuration = p.getDuration();
+ }
+ }
+ }
+
+ // tune the volume on players to crossfade!
+ float progress = (com.jogamp.common.os.Platform.currentTimeMillis()-startTime)/maxDuration;
+
+ i = 0;
+ for(GLMediaPlayer p: player){
+ if(p!=null){
+ AudioSink sink = p.getAudioSink();
+ if(sink != null){
+ float volume = (float) (0.5f+(0.5f*(Math.cos(40.0f*progress+(piPlayers*i)))));
+ float playbacktime = com.jogamp.common.os.Platform.currentTimeMillis()-startTime;
+ // System.out.println("player: "+ i +" volume = " + volume +" progress = "+ progress +" time = "+ playbacktime + " / duration = " + maxDuration);
+ sink.setVolume(volume);
+ }
+
+ se = p.getStreamException();
+ if( null != se) {
+ se.printStackTrace();
+ throw new RuntimeException(se);
+ }
+ }
+
+ i++;
+ }
+ }
+
+ for(GLMediaPlayer p: player) {
+ if(p!=null)
+ p.destroy(null);
+ }
+ System.out.println("...main exit...");
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java index bb0d84193..b148ebabd 100755..100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java @@ -1,52 +1,49 @@ -/* - * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution 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. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * +/** + * Copyright 2012 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.jogl.demos.es2.av; -import java.io.BufferedReader; +import java.io.File; import java.io.IOException; -import java.io.InputStreamReader; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLConnection; +import java.net.URI; +import java.net.URISyntaxException; import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAnimatorControl; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLEventListener; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; +import com.jogamp.common.util.IOUtil; +import com.jogamp.graph.curve.Region; +import com.jogamp.graph.font.Font; import com.jogamp.newt.Window; import com.jogamp.newt.event.KeyAdapter; import com.jogamp.newt.event.KeyEvent; @@ -55,183 +52,512 @@ import com.jogamp.newt.event.WindowAdapter; import com.jogamp.newt.event.WindowEvent; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.JoglVersion; -import com.jogamp.opengl.test.junit.jogl.demos.es2.TexCubeES2; +import com.jogamp.opengl.test.junit.graph.TextRendererGLELBase; +import com.jogamp.opengl.test.junit.jogl.demos.es2.TextureSequenceCubeES2; import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.util.av.GLMediaPlayer; import com.jogamp.opengl.util.av.GLMediaPlayer.GLMediaEventListener; +import com.jogamp.opengl.util.av.GLMediaPlayer.StreamException; import com.jogamp.opengl.util.av.GLMediaPlayerFactory; +import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame; -public class MovieCube implements GLEventListener, GLMediaEventListener { - static boolean waitForKey = false; - final URLConnection stream; - final float zoom0, rotx, roty; - TexCubeES2 cube=null; - GLMediaPlayer mPlayer=null; - - public MovieCube() throws IOException { - this(new URL("http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4").openConnection(), - -2.3f, 0f, 0f); +/** + * Simple cube movie player w/ aspect ration true projection on a cube. + */ +public class MovieCube implements GLEventListener { + public static final float zoom_def = -2.77f; + private static boolean waitForKey = false; + private final float zoom0, rotx, roty; + private TextureSequenceCubeES2 cube=null; + private GLMediaPlayer mPlayer=null; + private int swapInterval = 1; + private int swapIntervalSet = -1; + private long lastPerfPos = 0; + private volatile boolean resetGLState = false; + + /** Blender's Big Buck Bunny Trailer: 24f 640p VP8, Vorbis 44100Hz mono, WebM/Matroska Stream. */ + public static final URI defURI; + static { + URI _defURI = null; + try { + _defURI = new URI("http://video.webmfiles.org/big-buck-bunny_trailer.webm"); + } catch (URISyntaxException e) { + e.printStackTrace(); + } + defURI = _defURI; } - - public MovieCube(URLConnection stream, float zoom0, float rotx, float roty) throws IOException { - this.stream = stream; + + /** + * Default constructor which also issues {@link #initStream(URI, int, int, int)} w/ default values + * and polls until the {@link GLMediaPlayer} is {@link GLMediaPlayer.State#Initialized}. + * If {@link GLMediaEventListener#EVENT_CHANGE_EOS} is reached, the stream is started over again. + * <p> + * This default constructor is merely useful for some <i>drop-in</i> test, e.g. using an applet. + * </p> + */ + public MovieCube() throws IOException, URISyntaxException { + this(zoom_def, 0f, 0f); + + mPlayer.addEventListener(new GLMediaEventListener() { + @Override + public void newFrameAvailable(GLMediaPlayer ts, TextureFrame newFrame, long when) { } + + @Override + public void attributesChanged(final GLMediaPlayer mp, int event_mask, long when) { + System.err.println("MovieCube AttributesChanges: events_mask 0x"+Integer.toHexString(event_mask)+", when "+when); + System.err.println("MovieCube State: "+mp); + if( 0 != ( GLMediaEventListener.EVENT_CHANGE_SIZE & event_mask ) ) { + resetGLState(); + } + if( 0 != ( GLMediaEventListener.EVENT_CHANGE_EOS & event_mask ) ) { + new Thread() { + public void run() { + // loop for-ever .. + mPlayer.seek(0); + mPlayer.play(); + } }.start(); + } + } + }); + initStream(defURI, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.TEXTURE_COUNT_DEFAULT); + StreamException se = null; + while( null == se && GLMediaPlayer.State.Initialized != mPlayer.getState() ) { + try { + Thread.sleep(16); + } catch (InterruptedException e) { } + se = mPlayer.getStreamException(); + } + if( null != se ) { + se.printStackTrace(); + throw new RuntimeException(se); + } + } + + /** Custom constructor, user needs to issue {@link #initStream(URI, int, int, int)} afterwards. */ + public MovieCube(float zoom0, float rotx, float roty) throws IOException { this.zoom0 = zoom0; this.rotx = rotx; this.roty = roty; + mPlayer = GLMediaPlayerFactory.createDefault(); + } + + public void initStream(URI streamLoc, int vid, int aid, int textureCount) { + mPlayer.initStream(streamLoc, vid, aid, textureCount); + System.out.println("pC.1b "+mPlayer); + } + + public void setSwapInterval(int v) { this.swapInterval = v; } + + public GLMediaPlayer getGLMediaPlayer() { return mPlayer; } + + public void resetGLState() { + resetGLState = true; } + private final class InfoTextRendererGLELBase extends TextRendererGLELBase { + static final float z_diff = 0.001f; + final float underlineSize; + + InfoTextRendererGLELBase() { + // FIXME: Graph TextRenderer does not AA well w/o MSAA and FBO + super(Region.VBAA_RENDERING_BIT); + texSizeScale = 2; + + fontSize = 1; + pixelScale = 1.0f / ( fontSize * 20f ); + + // underlineSize: 'underline' amount of pixel below 0/0 (Note: lineGap is negative) + final Font.Metrics metrics = font.getMetrics(); + final float lineGap = metrics.getLineGap(fontSize); + final float descent = metrics.getDescent(fontSize); + underlineSize = descent - lineGap; + // System.err.println("XXX: fLG "+lineGap+", fDesc "+descent+", underlineSize "+underlineSize); + + staticRGBAColor[0] = 0.0f; + staticRGBAColor[1] = 0.0f; + staticRGBAColor[2] = 0.0f; + staticRGBAColor[3] = 1.0f; + } + + @Override + public void init(GLAutoDrawable drawable) { + // non-exclusive mode! + this.usrPMVMatrix = cube.pmvMatrix; + super.init(drawable); + } + + @Override + public void display(GLAutoDrawable drawable) { + final GLAnimatorControl anim = drawable.getAnimator(); + final float lfps = null != anim ? anim.getLastFPS() : 0f; + final float tfps = null != anim ? anim.getTotalFPS() : 0f; + final boolean hasVideo = GLMediaPlayer.STREAM_ID_NONE != mPlayer.getVID(); + final float pts = ( hasVideo ? mPlayer.getVideoPTS() : mPlayer.getAudioPTS() ) / 1000f; + + // Note: MODELVIEW is from [ -1 .. 1 ] + + // dy: position right above video rectangle (bottom text line) + final float aspect = (float)mPlayer.getWidth() / (float)mPlayer.getHeight(); + final float aspect_h = 1f/aspect; + final float dy = 1f-aspect_h; + + // yoff1: position right above video rectangle (bottom text line) + // less than underlineSize, so 'underline' pixels are above video. + final float yoff1 = dy-(pixelScale*underlineSize); + + // yoff2: position right below video rectangle (bottom text line) + final float yoff2 = 2f-dy; + + /** + System.err.println("XXX: a "+aspect+", aspect_h "+aspect_h+", dy "+dy+ + "; underlineSize "+underlineSize+" "+(pixelScale*underlineSize)+ + "; yoff "+yoff1+", yoff2 "+yoff2); */ + + // FIXME: Graph TextRenderer does not scale well, i.e. text update per 1/10s cause too much recompute of regions! + // final String text1 = String.format("%03.1f/%03.1f s, %s (%01.2fx, vol %01.2f), a %01.2f, fps %02.1f -> %02.1f / %02.1f, v-sync %d", + final String text1 = String.format("%03.0f/%03.0f s, %s (%01.2fx, vol %01.2f), a %01.2f, fps %02.1f -> %02.1f / %02.1f, v-sync %d", + pts, mPlayer.getDuration() / 1000f, + mPlayer.getState().toString().toLowerCase(), mPlayer.getPlaySpeed(), mPlayer.getAudioVolume(), + aspect, mPlayer.getFramerate(), lfps, tfps, swapIntervalSet); + final String text2 = String.format("audio: id %d, kbps %d, codec %s", + mPlayer.getAID(), mPlayer.getAudioBitrate()/1000, mPlayer.getAudioCodec()); + final String text3 = String.format("video: id %d, kbps %d, codec %s", + mPlayer.getVID(), mPlayer.getVideoBitrate()/1000, mPlayer.getVideoCodec()); + final String text4 = mPlayer.getURI().getRawPath(); + if( displayOSD && null != renderer ) { + renderString(drawable, text1, 1 /* col */, -1 /* row */, -1+z_diff, yoff1, 1f+z_diff); + renderString(drawable, text2, 1 /* col */, 0 /* row */, -1+z_diff, yoff2, 1f+z_diff); + renderString(drawable, text3, 1 /* col */, 1 /* row */, -1+z_diff, yoff2, 1f+z_diff); + renderString(drawable, text4, 1 /* col */, 2 /* row */, -1+z_diff, yoff2, 1f+z_diff); + } + } }; + private final InfoTextRendererGLELBase textRendererGLEL = new InfoTextRendererGLELBase(); + private boolean displayOSD = true; + private final KeyListener keyAction = new KeyAdapter() { - public void keyTyped(KeyEvent e) { + public void keyReleased(KeyEvent e) { + if( e.isAutoRepeat() ) { + return; + } System.err.println("MC "+e); - int pts0 = mPlayer.getCurrentPosition(); + final int pts0 = GLMediaPlayer.STREAM_ID_NONE != mPlayer.getVID() ? mPlayer.getVideoPTS() : mPlayer.getAudioPTS(); int pts1 = 0; - switch(e.getKeyCode()) { - case KeyEvent.VK_3: + switch(e.getKeySymbol()) { + case KeyEvent.VK_V: { + switch(swapIntervalSet) { + case 0: swapInterval = 1; break; + default: swapInterval = 0; break; + } + break; + } + case KeyEvent.VK_O: displayOSD = !displayOSD; break; case KeyEvent.VK_RIGHT: pts1 = pts0 + 1000; break; - case KeyEvent.VK_4: case KeyEvent.VK_UP: pts1 = pts0 + 10000; break; - case KeyEvent.VK_2: + case KeyEvent.VK_PAGE_UP: pts1 = pts0 + 30000; break; case KeyEvent.VK_LEFT: pts1 = pts0 - 1000; break; - case KeyEvent.VK_1: case KeyEvent.VK_DOWN: pts1 = pts0 - 10000; break; + case KeyEvent.VK_PAGE_DOWN: pts1 = pts0 - 30000; break; case KeyEvent.VK_ESCAPE: - case KeyEvent.VK_DELETE: + case KeyEvent.VK_HOME: case KeyEvent.VK_BACK_SPACE: { mPlayer.seek(0); - mPlayer.setPlaySpeed(1.0f); - mPlayer.start(); break; } case KeyEvent.VK_SPACE: { if(GLMediaPlayer.State.Paused == mPlayer.getState()) { - mPlayer.start(); + mPlayer.play(); } else { - mPlayer.pause(); + mPlayer.pause(false); } break; } - case KeyEvent.VK_S: mPlayer.setPlaySpeed(mPlayer.getPlaySpeed()/2.0f); break; - case KeyEvent.VK_F: mPlayer.setPlaySpeed(mPlayer.getPlaySpeed()*2.0f); break; + case KeyEvent.VK_MULTIPLY: + mPlayer.setPlaySpeed(1.0f); + break; + case KeyEvent.VK_SUBTRACT: { + float playSpeed = mPlayer.getPlaySpeed(); + if( e.isShiftDown() ) { + playSpeed /= 2.0f; + } else { + playSpeed -= 0.1f; + } + mPlayer.setPlaySpeed(playSpeed); + } break; + case KeyEvent.VK_ADD: { + float playSpeed = mPlayer.getPlaySpeed(); + if( e.isShiftDown() ) { + playSpeed *= 2.0f; + } else { + playSpeed += 0.1f; + } + mPlayer.setPlaySpeed(playSpeed); + } break; + case KeyEvent.VK_M: { + float audioVolume = mPlayer.getAudioVolume(); + if( audioVolume > 0.5f ) { + audioVolume = 0f; + } else { + audioVolume = 1f; + } + mPlayer.setAudioVolume(audioVolume); + } break; } - + if( 0 != pts1 ) { mPlayer.seek(pts1); } - } + } }; - - @Override - public void attributesChanges(GLMediaPlayer mp, int event_mask, long when) { - System.out.println("attributesChanges: "+mp+", 0x"+Integer.toHexString(event_mask)+", when "+when); - } @Override - public void newFrameAvailable(GLMediaPlayer mp, long when) { - // System.out.println("newFrameAvailable: "+mp+", when "+when); - } - public void init(GLAutoDrawable drawable) { + if(null == mPlayer) { + throw new InternalError("mPlayer null"); + } + if( GLMediaPlayer.State.Uninitialized == mPlayer.getState() ) { + throw new IllegalStateException("mPlayer in uninitialized state: "+mPlayer); + } + if( GLMediaPlayer.STREAM_ID_NONE == mPlayer.getVID() ) { + // throw new IllegalStateException("mPlayer has no VID/stream selected: "+mPlayer); + } + resetGLState = false; + GL2ES2 gl = drawable.getGL().getGL2ES2(); System.err.println(JoglVersion.getGLInfo(gl, null)); - mPlayer = GLMediaPlayerFactory.create(); - mPlayer.addEventListener(this); - cube = new TexCubeES2(mPlayer, false, zoom0, rotx, roty); - + cube = new TextureSequenceCubeES2(mPlayer, false, zoom0, rotx, roty); + 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) { } + UITestCase.waitForKey("Init>"); } - try { - System.out.println("p0 "+mPlayer); - mPlayer.initGLStream(gl, stream); - System.out.println("p1 "+mPlayer); - } catch (Exception e) { - e.printStackTrace(); - if(null != mPlayer) { - mPlayer.destroy(gl); - mPlayer = null; + + if( GLMediaPlayer.State.Initialized == mPlayer.getState() ) { + try { + mPlayer.initGL(gl); + } catch (Exception e) { + e.printStackTrace(); + if(null != mPlayer) { + mPlayer.destroy(gl); + mPlayer = null; + } + throw new GLException(e); } - throw new GLException(e); } - cube.init(drawable); - mPlayer.start(); + mPlayer.play(); + System.out.println("play.0 "+mPlayer); boolean added; - if (drawable instanceof Window) { - Window window = (Window) drawable; + final Object upstreamWidget = drawable.getUpstreamWidget(); + if (upstreamWidget instanceof Window) { + final Window window = (Window) upstreamWidget; window.addKeyListener(keyAction); added = true; - } else { added = false; } + } else { added = false; } System.err.println("MC.init: kl-added "+added+", "+drawable.getClass().getName()); + drawable.addGLEventListener(textRendererGLEL); } + @Override public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { if(null == mPlayer) { return; } cube.reshape(drawable, x, y, width, height); } + @Override public void dispose(GLAutoDrawable drawable) { System.err.println(Thread.currentThread()+" MovieCube.dispose ... "); + drawable.disposeGLEventListener(textRendererGLEL, true); + disposeImpl(drawable, true); + } + + private void disposeImpl(GLAutoDrawable drawable, boolean disposePlayer) { if(null == mPlayer) { return; } - mPlayer.stop(); - GL2ES2 gl = drawable.getGL().getGL2ES2(); - mPlayer.destroy(gl); - mPlayer=null; + final Object upstreamWidget = drawable.getUpstreamWidget(); + if (upstreamWidget instanceof Window) { + final Window window = (Window) upstreamWidget; + window.removeKeyListener(keyAction); + } + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + if( disposePlayer ) { + mPlayer.destroy(gl); + mPlayer=null; + } cube.dispose(drawable); cube=null; } + + @Override public void display(GLAutoDrawable drawable) { + if(-1 != swapInterval) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there) + drawable.getAnimator().resetFPSCounter(); + swapIntervalSet = swapInterval; + swapInterval = -1; + } if(null == mPlayer) { return; } + + if( resetGLState ) { + resetGLState = false; + System.err.println("XXX resetGLState"); + disposeImpl(drawable, false); + init(drawable); + reshape(drawable, 0, 0, drawable.getWidth(), drawable.getHeight()); + } + + final long currentPos = System.currentTimeMillis(); + if( currentPos - lastPerfPos > 2000 ) { + System.err.println( mPlayer.getPerfString() ); + lastPerfPos = currentPos; + } cube.display(drawable); } - public void displayChanged(javax.media.opengl.GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) { - } - - public static void main(String[] args) throws MalformedURLException, IOException, InterruptedException { + public static void main(String[] args) throws IOException, InterruptedException, URISyntaxException { + int swapInterval = 1; int width = 510; int height = 300; - System.err.println("TexCubeES2.run()"); - - String url_s="http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4"; - for(int i=0; i<args.length; i++) { - if(args[i].equals("-width")) { - i++; - width = MiscUtils.atoi(args[i], width); - } else if(args[i].equals("-height")) { - i++; - height = MiscUtils.atoi(args[i], height); - } else if(args[i].equals("-url")) { - i++; - url_s = args[i]; - } else if(args[i].equals("-wait")) { - waitForKey = true; + int textureCount = GLMediaPlayer.TEXTURE_COUNT_DEFAULT; // default - threaded + + boolean forceES2 = false; + boolean forceES3 = false; + boolean forceGL3 = false; + boolean forceGLDef = false; + int vid = GLMediaPlayer.STREAM_ID_AUTO; + int aid = GLMediaPlayer.STREAM_ID_AUTO; + final boolean origSize; + + String url_s=null, file_s=null; + { + boolean _origSize = false; + for(int i=0; i<args.length; i++) { + if(args[i].equals("-vid")) { + i++; + vid = MiscUtils.atoi(args[i], vid); + } else if(args[i].equals("-aid")) { + i++; + aid = MiscUtils.atoi(args[i], aid); + } else if(args[i].equals("-width")) { + i++; + width = MiscUtils.atoi(args[i], width); + } else if(args[i].equals("-height")) { + i++; + height = MiscUtils.atoi(args[i], height); + } else if(args[i].equals("-osize")) { + _origSize = true; + } else if(args[i].equals("-textureCount")) { + i++; + textureCount = MiscUtils.atoi(args[i], textureCount); + } else if(args[i].equals("-url")) { + i++; + url_s = args[i]; + } else if(args[i].equals("-file")) { + i++; + file_s = args[i]; + } else if(args[i].equals("-es2")) { + forceES2 = true; + } else if(args[i].equals("-es3")) { + forceES3 = true; + } else if(args[i].equals("-gl3")) { + forceGL3 = true; + } else if(args[i].equals("-gldef")) { + forceGLDef = true; + } else if(args[i].equals("-vsync")) { + i++; + swapInterval = MiscUtils.atoi(args[i], swapInterval); + } else if(args[i].equals("-wait")) { + waitForKey = true; + } } + origSize = _origSize; } - final MovieCube mc = new MovieCube(new URL(url_s).openConnection(), -2.3f, 0f, 0f); - - final GLWindow window = GLWindow.create(new GLCapabilities(GLProfile.getGL2ES2())); - // Size OpenGL to Video Surface - window.setSize(width, height); - window.setFullscreen(false); - window.setSize(width, height); - window.addGLEventListener(mc); + final URI streamLoc; + if( null != url_s ) { + streamLoc = new URI(url_s); + } else if( null != file_s ) { + streamLoc = IOUtil.toURISimple(new File(file_s)); + } else { + streamLoc = defURI; + } + System.err.println("url_s "+url_s); + System.err.println("file_s "+file_s); + System.err.println("stream "+streamLoc); + System.err.println("vid "+vid+", aid "+aid); + System.err.println("textureCount "+textureCount); + System.err.println("forceES2 "+forceES2); + System.err.println("forceES3 "+forceES3); + System.err.println("forceGL3 "+forceGL3); + System.err.println("forceGLDef "+forceGLDef); + System.err.println("swapInterval "+swapInterval); + + final MovieCube mc = new MovieCube(zoom_def, 0f, 0f); + mc.setSwapInterval(swapInterval); + + final GLProfile glp; + if(forceGLDef) { + glp = GLProfile.getDefault(); + } else if(forceGL3) { + glp = GLProfile.get(GLProfile.GL3); + } else if(forceES3) { + glp = GLProfile.get(GLProfile.GLES3); + } else if(forceES2) { + glp = GLProfile.get(GLProfile.GLES2); + } else { + glp = GLProfile.getGL2ES2(); + } + System.err.println("GLProfile: "+glp); + final GLWindow window = GLWindow.create(new GLCapabilities(glp)); final Animator anim = new Animator(window); window.addWindowListener(new WindowAdapter() { public void windowDestroyed(WindowEvent e) { anim.stop(); - } + } }); - // anim.setUpdateFPSFrames(60, System.err); - anim.start(); + window.setSize(width, height); window.setVisible(true); + anim.start(); + + mc.mPlayer.addEventListener(new GLMediaEventListener() { + @Override + public void newFrameAvailable(GLMediaPlayer ts, TextureFrame newFrame, long when) { + } + + @Override + public void attributesChanged(final GLMediaPlayer mp, int event_mask, long when) { + System.err.println("MovieCube AttributesChanges: events_mask 0x"+Integer.toHexString(event_mask)+", when "+when); + System.err.println("MovieCube State: "+mp); + if( 0 != ( GLMediaEventListener.EVENT_CHANGE_SIZE & event_mask ) ) { + if( origSize ) { + window.setSize(mp.getWidth(), mp.getHeight()); + } + // window.disposeGLEventListener(ms, false /* remove */ ); + mc.resetGLState(); + } + if( 0 != ( GLMediaEventListener.EVENT_CHANGE_INIT & event_mask ) ) { + window.addGLEventListener(mc); + anim.setUpdateFPSFrames(60, null); + anim.resetFPSCounter(); + } + if( 0 != ( GLMediaEventListener.EVENT_CHANGE_PLAY & event_mask ) ) { + anim.resetFPSCounter(); + } + if( 0 != ( ( GLMediaEventListener.EVENT_CHANGE_ERR | GLMediaEventListener.EVENT_CHANGE_EOS ) & event_mask ) ) { + final StreamException se = mc.mPlayer.getStreamException(); + if( null != se ) { + se.printStackTrace(); + } + new Thread() { + public void run() { + window.destroy(); + } }.start(); + } + } + }); + mc.initStream(streamLoc, vid, aid, textureCount); } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java index 8210065ab..787dbab78 100755..100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java @@ -3,14 +3,14 @@ * * 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 @@ -20,7 +20,7 @@ * 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. @@ -28,14 +28,15 @@ package com.jogamp.opengl.test.junit.jogl.demos.es2.av; +import java.io.File; import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLConnection; +import java.net.URI; +import java.net.URISyntaxException; import java.nio.FloatBuffer; import javax.media.opengl.GL; import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAnimatorControl; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLES2; @@ -45,20 +46,30 @@ import javax.media.opengl.GLProfile; import javax.media.opengl.GLUniformData; import javax.media.opengl.fixedfunc.GLMatrixFunc; +import com.jogamp.common.os.Platform; +import com.jogamp.common.util.IOUtil; +import com.jogamp.graph.curve.Region; import com.jogamp.newt.Window; +import com.jogamp.newt.event.KeyAdapter; +import com.jogamp.newt.event.KeyEvent; +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.newt.event.WindowAdapter; import com.jogamp.newt.event.WindowEvent; import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.GLExtensions; import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.test.junit.graph.TextRendererGLELBase; import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.util.GLArrayDataServer; import com.jogamp.opengl.util.PMVMatrix; import com.jogamp.opengl.util.av.GLMediaPlayer; import com.jogamp.opengl.util.av.GLMediaPlayer.GLMediaEventListener; +import com.jogamp.opengl.util.av.GLMediaPlayer.StreamException; import com.jogamp.opengl.util.av.GLMediaPlayerFactory; import com.jogamp.opengl.util.glsl.ShaderCode; import com.jogamp.opengl.util.glsl.ShaderProgram; @@ -66,8 +77,20 @@ import com.jogamp.opengl.util.glsl.ShaderState; import com.jogamp.opengl.util.texture.Texture; import com.jogamp.opengl.util.texture.TextureCoords; import com.jogamp.opengl.util.texture.TextureSequence; +import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame; -public class MovieSimple implements GLEventListener, GLMediaEventListener { +/** + * Simple planar movie player w/ orthogonal 1:1 projection. + */ +public class MovieSimple implements GLEventListener { + public static final int EFFECT_NORMAL = 0; + public static final int EFFECT_GRADIENT_BOTTOM2TOP = 1<<1; + public static final int EFFECT_TRANSPARENT = 1<<3; + + private static final String WINDOW_KEY = "window"; + private static final String PLAYER = "player"; + + private static boolean waitForKey = false; private int winWidth, winHeight; private int prevMouseX; // , prevMouseY; private int rotate = 0; @@ -79,36 +102,90 @@ public class MovieSimple implements GLEventListener, GLMediaEventListener { private long startTime; private int effects = EFFECT_NORMAL; private float alpha = 1.0f; + private int swapInterval = 1; + private int swapIntervalSet = -1; - public static final int EFFECT_NORMAL = 0; - public static final int EFFECT_GRADIENT_BOTTOM2TOP = 1<<1; - public static final int EFFECT_TRANSPARENT = 1<<3; + private GLMediaPlayer mPlayer; + private final boolean mPlayerShared; + private boolean mPlayerScaleOrig; + private float[] verts = null; + private GLArrayDataServer interleavedVBO; + private volatile boolean resetGLState = false; - /** defaults to true */ - public void setOrthoProjection(boolean v) { orthoProjection=v; } - public boolean getOrthoProjection() { return orthoProjection; } - - public boolean hasEffect(int e) { return 0 != ( effects & e ) ; } - public void setEffects(int e) { effects = e; }; - public void setTransparency(float alpha) { - this.effects |= EFFECT_TRANSPARENT; - this.alpha = alpha; - } + private ShaderState st; + private PMVMatrix pmvMatrix; + private GLUniformData pmvMatrixUniform; + private static final String shaderBasename = "texsequence_xxx"; + private static final String myTextureLookupName = "myTexture2D"; + + /** Blender's Big Buck Bunny Trailer: 24f 640p VP8, Vorbis 44100Hz mono, WebM/Matroska Stream. */ + public static final URI defURI; + static { + URI _defURI = null; + try { + _defURI = new URI("http://video.webmfiles.org/big-buck-bunny_trailer.webm"); + } catch (URISyntaxException e) { + e.printStackTrace(); + } + defURI = _defURI; + } + + private final class InfoTextRendererGLELBase extends TextRendererGLELBase { + InfoTextRendererGLELBase() { + // FIXME: Graph TextRenderer does not AA well w/o MSAA and FBO + super(Region.VBAA_RENDERING_BIT); + texSizeScale = 2; + + fontSize = 18; - GLMediaPlayer mPlayer; - URLConnection stream = null; - boolean mPlayerExternal; - boolean mPlayerShared; - boolean mPlayerScaleOrig; - GLArrayDataServer interleavedVBO; + staticRGBAColor[0] = 1.0f; + staticRGBAColor[1] = 1.0f; + staticRGBAColor[2] = 1.0f; + staticRGBAColor[3] = 1.0f; + } + + @Override + public void display(GLAutoDrawable drawable) { + final GLAnimatorControl anim = drawable.getAnimator(); + final float lfps = null != anim ? anim.getLastFPS() : 0f; + final float tfps = null != anim ? anim.getTotalFPS() : 0f; + final boolean hasVideo = GLMediaPlayer.STREAM_ID_NONE != mPlayer.getVID(); + final float pts = ( hasVideo ? mPlayer.getVideoPTS() : mPlayer.getAudioPTS() ) / 1000f; + + // Note: MODELVIEW is from [ 0 .. height ] + + final int height = drawable.getHeight(); + + final float aspect = (float)mPlayer.getWidth() / (float)mPlayer.getHeight(); + + // FIXME: Graph TextRenderer does not scale well, i.e. text update per 1/10s cause too much recompute of regions! + // final String text1 = String.format("%03.1f/%03.1f s, %s (%01.2fx, vol %01.2f), a %01.2f, fps %02.1f -> %02.1f / %02.1f, v-sync %d", + final String text1 = String.format("%03.0f/%03.0f s, %s (%01.2fx, vol %01.2f), a %01.2f, fps %02.1f -> %02.1f / %02.1f, v-sync %d", + pts, mPlayer.getDuration() / 1000f, + mPlayer.getState().toString().toLowerCase(), mPlayer.getPlaySpeed(), mPlayer.getAudioVolume(), + aspect, mPlayer.getFramerate(), lfps, tfps, swapIntervalSet); + final String text2 = String.format("audio: id %d, kbps %d, codec %s", + mPlayer.getAID(), mPlayer.getAudioBitrate()/1000, mPlayer.getAudioCodec()); + final String text3 = String.format("video: id %d, kbps %d, codec %s", + mPlayer.getVID(), mPlayer.getVideoBitrate()/1000, mPlayer.getVideoCodec()); + final String text4 = mPlayer.getURI().getRawPath(); + if( displayOSD && null != renderer ) { + renderString(drawable, text1, 1 /* col */, 1 /* row */, 0, 0, -1); + renderString(drawable, text2, 1 /* col */, -4 /* row */, 0, height, -1); + renderString(drawable, text3, 1 /* col */, -3 /* row */, 0, height, -1); + renderString(drawable, text4, 1 /* col */, -2 /* row */, 0, height, -1); + } + } }; + private final InfoTextRendererGLELBase textRendererGLEL = new InfoTextRendererGLELBase(); + private boolean displayOSD = true; private final MouseListener mouseAction = new MouseAdapter() { public void mousePressed(MouseEvent e) { if(e.getY()<=winHeight/2 && null!=mPlayer && 1 == e.getClickCount()) { if(GLMediaPlayer.State.Playing == mPlayer.getState()) { - mPlayer.pause(); + mPlayer.pause(false); } else { - mPlayer.start(); + mPlayer.play(); } } } @@ -126,106 +203,215 @@ public class MovieSimple implements GLEventListener, GLMediaEventListener { public void mouseDragged(MouseEvent e) { int x = e.getX(); int y = e.getY(); - + if(y>winHeight/2) { final float dp = (float)(x-prevMouseX)/(float)winWidth; - mPlayer.seek(mPlayer.getCurrentPosition() + (int) (mPlayer.getDuration() * dp)); + final int pts0 = GLMediaPlayer.STREAM_ID_NONE != mPlayer.getVID() ? mPlayer.getVideoPTS() : mPlayer.getAudioPTS(); + mPlayer.seek(pts0 + (int) (mPlayer.getDuration() * dp)); } else { - mPlayer.start(); - rotate = 1; + mPlayer.play(); + rotate = 1; zoom = zoom1; } - + prevMouseX = x; // prevMouseY = y; } public void mouseWheelMoved(MouseEvent e) { - zoom += e.getWheelRotation()/10f; - System.err.println("zoom: "+zoom); + if( !e.isShiftDown() ) { + zoom += e.getRotation()[1]/10f; // vertical: wheel + System.err.println("zoom: "+zoom); + } + } }; + + private final KeyListener keyAction = new KeyAdapter() { + public void keyReleased(KeyEvent e) { + if( e.isAutoRepeat() ) { + return; + } + System.err.println("MC "+e); + final int pts0 = GLMediaPlayer.STREAM_ID_NONE != mPlayer.getVID() ? mPlayer.getVideoPTS() : mPlayer.getAudioPTS(); + int pts1 = 0; + switch(e.getKeySymbol()) { + case KeyEvent.VK_V: { + switch(swapIntervalSet) { + case 0: swapInterval = 1; break; + default: swapInterval = 0; break; + } + break; + } + case KeyEvent.VK_O: displayOSD = !displayOSD; break; + case KeyEvent.VK_RIGHT: pts1 = pts0 + 1000; break; + case KeyEvent.VK_UP: pts1 = pts0 + 10000; break; + case KeyEvent.VK_PAGE_UP: pts1 = pts0 + 30000; break; + case KeyEvent.VK_LEFT: pts1 = pts0 - 1000; break; + case KeyEvent.VK_DOWN: pts1 = pts0 - 10000; break; + case KeyEvent.VK_PAGE_DOWN: pts1 = pts0 - 30000; break; + case KeyEvent.VK_ESCAPE: + case KeyEvent.VK_HOME: + case KeyEvent.VK_BACK_SPACE: { + mPlayer.seek(0); + break; + } + case KeyEvent.VK_SPACE: { + if(GLMediaPlayer.State.Paused == mPlayer.getState()) { + mPlayer.play(); + } else { + mPlayer.pause(false); + } + break; + } + case KeyEvent.VK_MULTIPLY: + mPlayer.setPlaySpeed(1.0f); + break; + case KeyEvent.VK_SUBTRACT: { + float playSpeed = mPlayer.getPlaySpeed(); + if( e.isShiftDown() ) { + playSpeed /= 2.0f; + } else { + playSpeed -= 0.1f; + } + mPlayer.setPlaySpeed(playSpeed); + } break; + case KeyEvent.VK_ADD: { + float playSpeed = mPlayer.getPlaySpeed(); + if( e.isShiftDown() ) { + playSpeed *= 2.0f; + } else { + playSpeed += 0.1f; + } + mPlayer.setPlaySpeed(playSpeed); + } break; + case KeyEvent.VK_M: { + float audioVolume = mPlayer.getAudioVolume(); + if( audioVolume > 0.5f ) { + audioVolume = 0f; + } else { + audioVolume = 1f; + } + mPlayer.setAudioVolume(audioVolume); + } break; + } + + if( 0 != pts1 ) { + mPlayer.seek(pts1); + } + } }; + + /** + * Default constructor which also issues {@link #initStream(URI, int, int, int)} w/ default values + * and polls until the {@link GLMediaPlayer} is {@link GLMediaPlayer.State#Initialized}. + * If {@link GLMediaEventListener#EVENT_CHANGE_EOS} is reached, the stream is started over again. + * <p> + * This default constructor is merely useful for some <i>drop-in</i> test, e.g. using an applet. + * </p> + */ + public MovieSimple() { + this(null); + + mPlayer.addEventListener(new GLMediaEventListener() { + @Override + public void newFrameAvailable(GLMediaPlayer ts, TextureFrame newFrame, long when) { } + + @Override + public void attributesChanged(final GLMediaPlayer mp, int event_mask, long when) { + System.err.println("MovieCube AttributesChanges: events_mask 0x"+Integer.toHexString(event_mask)+", when "+when); + System.err.println("MovieCube State: "+mp); + if( 0 != ( GLMediaEventListener.EVENT_CHANGE_SIZE & event_mask ) ) { + resetGLState(); + } + if( 0 != ( GLMediaEventListener.EVENT_CHANGE_EOS & event_mask ) ) { + new Thread() { + public void run() { + // loop for-ever .. + mPlayer.seek(0); + mPlayer.play(); + } }.start(); + } + } + }); + initStream(defURI, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, 3 /* textureCount */); + StreamException se = null; + while( null == se && GLMediaPlayer.State.Initialized != mPlayer.getState() ) { + try { + Thread.sleep(16); + } catch (InterruptedException e) { } + se = mPlayer.getStreamException(); + } + if( null != se ) { + se.printStackTrace(); + throw new RuntimeException(se); } - }; - - public MovieSimple(URLConnection stream) throws IOException { - mPlayerScaleOrig = false; - mPlayerShared = false; - mPlayerExternal = false; - mPlayer = GLMediaPlayerFactory.create(); - mPlayer.addEventListener(this); - this.stream = stream; - System.out.println("pC.1 "+mPlayer); } + /** Custom constructor, user needs to issue {@link #initStream(URI, int, int, int)} afterwards. */ public MovieSimple(GLMediaPlayer sharedMediaPlayer) throws IllegalStateException { - mPlayerScaleOrig = false; - mPlayerShared = true; - mPlayerExternal = true; mPlayer = sharedMediaPlayer; - mPlayer.addEventListener(this); - this.stream = null; - System.out.println("pC.2 shared "+mPlayerShared+", "+mPlayer); + mPlayerScaleOrig = false; + mPlayerShared = null != mPlayer; + if( !mPlayerShared ) { + mPlayer = GLMediaPlayerFactory.createDefault(); + mPlayer.attachObject(PLAYER, this); + } + System.out.println("pC.1a shared "+mPlayerShared+", "+mPlayer); } - + + public void initStream(URI streamLoc, int vid, int aid, int textureCount) { + mPlayer.initStream(streamLoc, vid, aid, textureCount); + System.out.println("pC.1b "+mPlayer); + } + + public void setSwapInterval(int v) { this.swapInterval = v; } + public GLMediaPlayer getGLMediaPlayer() { return mPlayer; } - + public void setScaleOrig(boolean v) { mPlayerScaleOrig = v; } - - @Override - public void attributesChanges(GLMediaPlayer mp, int event_mask, long when) { - System.out.println("attributesChanges: "+mp+", 0x"+Integer.toHexString(event_mask)+", when "+when); - } - @Override - public void newFrameAvailable(GLMediaPlayer mp, long when) { - // System.out.println("newFrameAvailable: "+mp+", when "+when); - } + /** defaults to true */ + public void setOrthoProjection(boolean v) { orthoProjection=v; } + public boolean getOrthoProjection() { return orthoProjection; } - public void start() { - if(null!=mPlayer) { - mPlayer.start(); - System.out.println("pStart "+mPlayer); - } + public boolean hasEffect(int e) { return 0 != ( effects & e ) ; } + public void setEffects(int e) { effects = e; }; + public void setTransparency(float alpha) { + this.effects |= EFFECT_TRANSPARENT; + this.alpha = alpha; } - public void stop() { - if(null!=mPlayer) { - mPlayer.stop(); - System.out.println("pStop "+mPlayer); - } + public void resetGLState() { + resetGLState = true; } - - ShaderState st; - PMVMatrix pmvMatrix; - GLUniformData pmvMatrixUniform; - static final String[] es2_prelude = { "#version 100\n", "precision mediump float;\n" }; - static final String gl2_prelude = "#version 110\n"; - static final String shaderBasename = "texsequence_xxx"; - static final String myTextureLookupName = "myTexture2D"; - + private void initShader(GL2ES2 gl) { // Create & Compile the shader objects - ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, MovieSimple.class, + ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, MovieSimple.class, "../shader", "../shader/bin", shaderBasename, true); - ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, MovieSimple.class, + ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, MovieSimple.class, "../shader", "../shader/bin", shaderBasename, true); - // Prelude shader code w/ GLSL profile specifics [ 1. pre-proc, 2. other ] - int rsFpPos; - if(gl.isGLES2()) { - rsVp.insertShaderSource(0, 0, es2_prelude[0]); - rsFpPos = rsFp.insertShaderSource(0, 0, es2_prelude[0]); - } else { - rsVp.insertShaderSource(0, 0, gl2_prelude); - rsFpPos = rsFp.insertShaderSource(0, 0, gl2_prelude); + boolean preludeGLSLVersion = true; + if( GLES2.GL_TEXTURE_EXTERNAL_OES == mPlayer.getTextureTarget() ) { + if( !gl.isExtensionAvailable(GLExtensions.OES_EGL_image_external) ) { + throw new GLException(GLExtensions.OES_EGL_image_external+" requested but not available"); + } + if( Platform.OSType.ANDROID == Platform.getOSType() && gl.isGLES3() ) { + // Bug on Nexus 10, ES3 - Android 4.3, where + // GL_OES_EGL_image_external extension directive leads to a failure _with_ '#version 300 es' ! + // P0003: Extension 'GL_OES_EGL_image_external' not supported + preludeGLSLVersion = false; + } } + rsVp.defaultShaderCustomization(gl, preludeGLSLVersion, true); + + int rsFpPos = preludeGLSLVersion ? rsFp.addGLSLVersion(gl) : 0; rsFpPos = rsFp.insertShaderSource(0, rsFpPos, mPlayer.getRequiredExtensionsShaderStub()); - if(gl.isGLES2()) { - rsFpPos = rsFp.insertShaderSource(0, rsFpPos, es2_prelude[1]); - } - final String texLookupFuncName = mPlayer.getTextureLookupFunctionName(myTextureLookupName); + rsFpPos = rsFp.addDefaultShaderPrecision(gl, rsFpPos); + + final String texLookupFuncName = mPlayer.getTextureLookupFunctionName(myTextureLookupName); rsFp.replaceInShaderSource(myTextureLookupName, texLookupFuncName); - + // Inject TextureSequence shader details final StringBuilder sFpIns = new StringBuilder(); sFpIns.append("uniform ").append(mPlayer.getTextureSampler2DType()).append(" mgl_ActiveTexture;\n"); @@ -245,105 +431,163 @@ public class MovieSimple implements GLEventListener, GLMediaEventListener { st.attachShaderProgram(gl, sp, false); } + @Override public void init(GLAutoDrawable drawable) { + if(null == mPlayer) { + throw new InternalError("mPlayer null"); + } + if( GLMediaPlayer.State.Uninitialized == mPlayer.getState() ) { + throw new IllegalStateException("mPlayer in uninitialized state: "+mPlayer); + } + final boolean hasVideo = GLMediaPlayer.STREAM_ID_NONE != mPlayer.getVID(); + resetGLState = false; + zoom0 = orthoProjection ? 0f : -2.5f; zoom1 = orthoProjection ? 0f : -5f; - zoom = zoom0; + zoom = zoom0; GL2ES2 gl = drawable.getGL().getGL2ES2(); System.err.println(JoglVersion.getGLInfo(gl, null)); System.err.println("Alpha: "+alpha+", opaque "+drawable.getChosenGLCapabilities().isBackgroundOpaque()+ ", "+drawable.getClass().getName()+", "+drawable); - + + if(waitForKey) { + UITestCase.waitForKey("Init>"); + } final Texture tex; - boolean useExternalTexture = false; try { System.out.println("p0 "+mPlayer+", shared "+mPlayerShared); - if(!mPlayerShared) { - mPlayer.initGLStream(gl, stream); + if(!mPlayerShared && GLMediaPlayer.State.Initialized == mPlayer.getState() ) { + mPlayer.initGL(gl); } - tex = mPlayer.getLastTexture().getTexture(); System.out.println("p1 "+mPlayer+", shared "+mPlayerShared); - useExternalTexture = GLES2.GL_TEXTURE_EXTERNAL_OES == tex.getTarget(); - if(useExternalTexture && !gl.isExtensionAvailable("GL_OES_EGL_image_external")) { - throw new GLException("GL_OES_EGL_image_external requested but not available"); + final TextureFrame frame = mPlayer.getLastTexture(); + if( null != frame ) { + if( !hasVideo ) { + throw new InternalError("XXX: "+mPlayer); + } + tex = frame.getTexture(); + if( null == tex ) { + throw new InternalError("XXX: "+mPlayer); + } + } else { + tex = null; + if( hasVideo ) { + throw new InternalError("XXX: "+mPlayer); + } } if(!mPlayerShared) { mPlayer.setTextureMinMagFilter( new int[] { GL.GL_NEAREST, GL.GL_LINEAR } ); } - } catch (Exception glex) { + } catch (Exception glex) { + glex.printStackTrace(); if(!mPlayerShared && null != mPlayer) { mPlayer.destroy(gl); mPlayer = null; } throw new GLException(glex); } - - initShader(gl); - // Push the 1st uniform down the path - st.useProgram(gl, true); + if( hasVideo ) { + initShader(gl); - int[] viewPort = new int[] { 0, 0, drawable.getWidth(), drawable.getHeight()}; - pmvMatrix = new PMVMatrix(); - reshapePMV(viewPort[2], viewPort[3]); - pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); - if(!st.uniform(gl, pmvMatrixUniform)) { - throw new GLException("Error setting PMVMatrix in shader: "+st); - } - if(!st.uniform(gl, new GLUniformData("mgl_ActiveTexture", mPlayer.getTextureUnit()))) { - throw new GLException("Error setting mgl_ActiveTexture in shader: "+st); - } - - float dWidth = drawable.getWidth(); - float dHeight = drawable.getHeight(); - float mWidth = mPlayer.getWidth(); - float mHeight = mPlayer.getHeight(); - float mAspect = mWidth/mHeight; - System.err.println("XXX0: mov aspect: "+mAspect); - float[] verts; - float xs, ys; - if(orthoProjection) { - if(mPlayerScaleOrig && mWidth < dWidth && mHeight < dHeight) { - xs = mWidth/2f; ys = xs / mAspect; - } else { - xs = dWidth/2f; ys = xs / mAspect; // w>h + // Push the 1st uniform down the path + st.useProgram(gl, true); + + int[] viewPort = new int[] { 0, 0, drawable.getWidth(), drawable.getHeight()}; + pmvMatrix = new PMVMatrix(); + reshapePMV(viewPort[2], viewPort[3]); + pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); + if(!st.uniform(gl, pmvMatrixUniform)) { + throw new GLException("Error setting PMVMatrix in shader: "+st); } - } else { - if(mPlayerScaleOrig && mWidth < dWidth && mHeight < dHeight) { - xs = mAspect * ( mWidth / dWidth ) ; ys = xs / mAspect ; + if(!st.uniform(gl, new GLUniformData("mgl_ActiveTexture", mPlayer.getTextureUnit()))) { + throw new GLException("Error setting mgl_ActiveTexture in shader: "+st); + } + + float dWidth = drawable.getWidth(); + float dHeight = drawable.getHeight(); + float mWidth = mPlayer.getWidth(); + float mHeight = mPlayer.getHeight(); + float mAspect = mWidth/mHeight; + System.err.println("XXX0: mov aspect: "+mAspect); + float xs, ys; + if(orthoProjection) { + if(mPlayerScaleOrig && mWidth < dWidth && mHeight < dHeight) { + xs = mWidth/2f; ys = xs / mAspect; + } else { + xs = dWidth/2f; ys = xs / mAspect; // w>h + } } else { - xs = mAspect; ys = 1f; // b>h + if(mPlayerScaleOrig && mWidth < dWidth && mHeight < dHeight) { + xs = mAspect * ( mWidth / dWidth ) ; ys = xs / mAspect ; + } else { + xs = mAspect; ys = 1f; // b>h + } + } + verts = new float[] { -1f*xs, -1f*ys, 0f, // LB + 1f*xs, 1f*ys, 0f // RT + }; + { + System.err.println("XXX0: pixel LB: "+verts[0]+", "+verts[1]+", "+verts[2]); + System.err.println("XXX0: pixel RT: "+verts[3]+", "+verts[4]+", "+verts[5]); + float[] winLB = new float[3]; + float[] winRT = new float[3]; + pmvMatrix.gluProject(verts[0], verts[1], verts[2], viewPort, 0, winLB, 0); + pmvMatrix.gluProject(verts[3], verts[4], verts[5], viewPort, 0, winRT, 0); + System.err.println("XXX0: win LB: "+winLB[0]+", "+winLB[1]+", "+winLB[2]); + System.err.println("XXX0: win RT: "+winRT[0]+", "+winRT[1]+", "+winRT[2]); } + + interleavedVBO = GLArrayDataServer.createGLSLInterleaved(3+4+2, GL.GL_FLOAT, false, 3*4, GL.GL_STATIC_DRAW); + { + interleavedVBO.addGLSLSubArray("mgl_Vertex", 3, GL.GL_ARRAY_BUFFER); + interleavedVBO.addGLSLSubArray("mgl_Color", 4, GL.GL_ARRAY_BUFFER); + interleavedVBO.addGLSLSubArray("mgl_MultiTexCoord", 2, GL.GL_ARRAY_BUFFER); + } + updateInterleavedVBO(gl, tex); + + st.ownAttribute(interleavedVBO, true); + gl.glClearColor(0.3f, 0.3f, 0.3f, 0.3f); + + gl.glEnable(GL2ES2.GL_DEPTH_TEST); + + st.useProgram(gl, false); + + // Let's show the completed shader state .. + System.out.println("iVBO: "+interleavedVBO); + System.out.println(st); } - verts = new float[] { -1f*xs, -1f*ys, 0f, // LB - 1f*xs, 1f*ys, 0f // RT - }; - { - System.err.println("XXX0: pixel LB: "+verts[0]+", "+verts[1]+", "+verts[2]); - System.err.println("XXX0: pixel RT: "+verts[3]+", "+verts[4]+", "+verts[5]); - float[] winLB = new float[3]; - float[] winRT = new float[3]; - pmvMatrix.gluProject(verts[0], verts[1], verts[2], viewPort, 0, winLB, 0); - pmvMatrix.gluProject(verts[3], verts[4], verts[5], viewPort, 0, winRT, 0); - System.err.println("XXX0: win LB: "+winLB[0]+", "+winLB[1]+", "+winLB[2]); - System.err.println("XXX0: win RT: "+winRT[0]+", "+winRT[1]+", "+winRT[2]); + + if(!mPlayerShared) { + mPlayer.play(); + System.out.println("play.0 "+mPlayer); } - final float ss = 1f, ts = 1f; // scale tex-coord + startTime = System.currentTimeMillis(); - interleavedVBO = GLArrayDataServer.createGLSLInterleaved(3+4+2, GL.GL_FLOAT, false, 3*4, GL.GL_STATIC_DRAW); - { - interleavedVBO.addGLSLSubArray("mgl_Vertex", 3, GL.GL_ARRAY_BUFFER); - interleavedVBO.addGLSLSubArray("mgl_Color", 4, GL.GL_ARRAY_BUFFER); - interleavedVBO.addGLSLSubArray("mgl_MultiTexCoord", 2, GL.GL_ARRAY_BUFFER); - + final Object upstreamWidget = drawable.getUpstreamWidget(); + if (upstreamWidget instanceof Window) { + final Window window = (Window) upstreamWidget; + window.addMouseListener(mouseAction); + window.addKeyListener(keyAction); + winWidth = window.getWidth(); + winHeight = window.getHeight(); + } + drawable.addGLEventListener(textRendererGLEL); + } + + protected void updateInterleavedVBO(GL gl, Texture tex) { + final float ss = 1f, ts = 1f; // scale tex-coord + final boolean wasEnabled = interleavedVBO.enabled(); + interleavedVBO.seal(gl, false); + interleavedVBO.rewind(); + { final FloatBuffer ib = (FloatBuffer)interleavedVBO.getBuffer(); - final TextureCoords tc = tex.getImageTexCoords(); - final float aspect = tex.getAspectRatio(); - System.err.println("XXX0: tex aspect: "+aspect); + final TextureCoords tc = tex.getImageTexCoords(); + System.err.println("XXX0: "+tc); + System.err.println("XXX0: tex aspect: "+tex.getAspectRatio()); System.err.println("XXX0: tex y-flip: "+tex.getMustFlipVertically()); - System.err.println("XXX0: "+tex.getImageTexCoords()); - + // left-bottom ib.put(verts[0]); ib.put(verts[1]); ib.put(verts[2]); if( hasEffect(EFFECT_GRADIENT_BOTTOM2TOP) ) { @@ -352,11 +596,11 @@ public class MovieSimple implements GLEventListener, GLMediaEventListener { ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha); } ib.put( tc.left() *ss); ib.put( tc.bottom() *ts); - + // right-bottom ib.put(verts[3]); ib.put(verts[1]); ib.put(verts[2]); if( hasEffect(EFFECT_GRADIENT_BOTTOM2TOP) ) { - ib.put( 0); ib.put( 0); ib.put( 0); ib.put(alpha); + ib.put( 0); ib.put( 0); ib.put( 0); ib.put(alpha); } else { ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha); } @@ -370,66 +614,45 @@ public class MovieSimple implements GLEventListener, GLMediaEventListener { ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha); } ib.put( tc.left() *ss); ib.put( tc.top() *ts); - + // right-top ib.put(verts[3]); ib.put(verts[4]); ib.put(verts[2]); if( hasEffect(EFFECT_GRADIENT_BOTTOM2TOP) ) { ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha); } else { ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha); - } - ib.put( tc.right() *ss); ib.put( tc.top() *ts); + } + ib.put( tc.right() *ss); ib.put( tc.top() *ts); } interleavedVBO.seal(gl, true); - interleavedVBO.enableBuffer(gl, false); - st.ownAttribute(interleavedVBO, true); - gl.glClearColor(0.3f, 0.3f, 0.3f, 0.3f); - - gl.glEnable(GL2ES2.GL_DEPTH_TEST); - - st.useProgram(gl, false); - - // Let's show the completed shader state .. - System.out.println("iVBO: "+interleavedVBO); - System.out.println(st); - - if(null!=mPlayer) { - start(); - System.out.println("p2 "+mPlayer); - } - - startTime = System.currentTimeMillis(); - - if (drawable instanceof Window) { - Window window = (Window) drawable; - window.addMouseListener(mouseAction); - winWidth = window.getWidth(); - winHeight = window.getHeight(); + if( !wasEnabled ) { + interleavedVBO.enableBuffer(gl, false); } } - + + @Override public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); if(null == mPlayer) { return; } winWidth = width; winHeight = height; - + if(null != st) { reshapePMV(width, height); - GL2ES2 gl = drawable.getGL().getGL2ES2(); st.useProgram(gl, true); st.uniform(gl, pmvMatrixUniform); st.useProgram(gl, false); } - + System.out.println("pR "+mPlayer); } - + private void reshapePMV(int width, int height) { pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); pmvMatrix.glLoadIdentity(); if(orthoProjection) { - final float fw = (float) width / 2f; - final float fh = (float) height/ 2f; + final float fw = width / 2f; + final float fh = height/ 2f; pmvMatrix.glOrthof(-fw, fw, -fh, fh, -1.0f, 1.0f); nearPlaneNormalized = 0f; } else { @@ -440,57 +663,98 @@ public class MovieSimple implements GLEventListener, GLMediaEventListener { pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); pmvMatrix.glLoadIdentity(); - pmvMatrix.glTranslatef(0, 0, zoom0); + pmvMatrix.glTranslatef(0, 0, zoom0); } + @Override public void dispose(GLAutoDrawable drawable) { + drawable.disposeGLEventListener(textRendererGLEL, true); + disposeImpl(drawable, true); + } + + private void disposeImpl(GLAutoDrawable drawable, boolean disposePlayer) { if(null == mPlayer) { return; } - - stop(); - System.out.println("pD.1 "+mPlayer); - - GL2ES2 gl = drawable.getGL().getGL2ES2(); - mPlayer.removeEventListener(this); - if(!mPlayerExternal) { - mPlayer.destroy(gl); + final Object upstreamWidget = drawable.getUpstreamWidget(); + if (upstreamWidget instanceof Window) { + final Window window = (Window) upstreamWidget; + window.removeMouseListener(mouseAction); + window.removeKeyListener(keyAction); + } + + System.out.println("pD.1 "+mPlayer+", disposePlayer "+disposePlayer); + GL2ES2 gl = drawable.getGL().getGL2ES2(); + if( disposePlayer ) { + if(!mPlayerShared) { + mPlayer.destroy(gl); + } + System.out.println("pD.X "+mPlayer); + mPlayer=null; } - System.out.println("pD.X "+mPlayer); - mPlayer=null; pmvMatrixUniform = null; - pmvMatrix.destroy(); - pmvMatrix=null; - st.destroy(gl); - st=null; + if(null != pmvMatrix) { + pmvMatrix.destroy(); + pmvMatrix=null; + } + if(null != st) { + st.destroy(gl); + st=null; + } } + long lastPerfPos = 0; + + @Override public void display(GLAutoDrawable drawable) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + if(-1 != swapInterval) { + gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there) + drawable.getAnimator().resetFPSCounter(); + swapIntervalSet = swapInterval; + swapInterval = -1; + } if(null == mPlayer) { return; } - - GL2ES2 gl = drawable.getGL().getGL2ES2(); + + if( resetGLState ) { + resetGLState = false; + System.err.println("XXX resetGLState"); + disposeImpl(drawable, false); + init(drawable); + reshape(drawable, 0, 0, drawable.getWidth(), drawable.getHeight()); + } + + final long currentPos = System.currentTimeMillis(); + if( currentPos - lastPerfPos > 2000 ) { + System.err.println( mPlayer.getPerfString() ); + lastPerfPos = currentPos; + } gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + if(null == st) { + return; + } + st.useProgram(gl, true); pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); pmvMatrix.glLoadIdentity(); pmvMatrix.glTranslatef(0, 0, zoom); if(rotate > 0) { - final float ang = ((float) (System.currentTimeMillis() - startTime) * 360.0f) / 8000.0f; + final float ang = ((System.currentTimeMillis() - startTime) * 360.0f) / 8000.0f; pmvMatrix.glRotatef(ang, 0, 0, 1); } else { rotate = 0; } st.uniform(gl, pmvMatrixUniform); interleavedVBO.enableBuffer(gl, true); - Texture tex = null; + Texture tex = null; if(null!=mPlayer) { final TextureSequence.TextureFrame texFrame; if(mPlayerShared) { texFrame=mPlayer.getLastTexture(); } else { - texFrame=mPlayer.getNextTexture(gl, true); + texFrame=mPlayer.getNextTexture(gl); } if(null != texFrame) { tex = texFrame.getTexture(); @@ -507,53 +771,265 @@ public class MovieSimple implements GLEventListener, GLMediaEventListener { st.useProgram(gl, false); } - public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) { - } + static class MyGLMediaEventListener implements GLMediaEventListener { + void destroyWindow(final Window window) { + new Thread() { + public void run() { + window.destroy(); + } }.start(); + } - public static void main(String[] args) throws IOException, MalformedURLException { + @Override + public void newFrameAvailable(GLMediaPlayer ts, TextureFrame newFrame, long when) { + } + + @Override + public void attributesChanged(final GLMediaPlayer mp, int event_mask, long when) { + System.err.println("MovieSimple AttributesChanges: events_mask 0x"+Integer.toHexString(event_mask)+", when "+when); + System.err.println("MovieSimple State: "+mp); + final GLWindow window = (GLWindow) mp.getAttachedObject(WINDOW_KEY); + final MovieSimple ms = (MovieSimple)mp.getAttachedObject(PLAYER); + if( 0 != ( GLMediaEventListener.EVENT_CHANGE_SIZE & event_mask ) ) { + System.err.println("MovieSimple State: CHANGE_SIZE"); + if( origSize ) { + window.setSize(mp.getWidth(), mp.getHeight()); + } + // window.disposeGLEventListener(ms, false /* remove */ ); + ms.resetGLState(); + } + if( 0 != ( GLMediaEventListener.EVENT_CHANGE_INIT & event_mask ) ) { + System.err.println("MovieSimple State: INIT"); + // Use GLEventListener in all cases [A+V, V, A] + window.addGLEventListener(ms); + final GLAnimatorControl anim = window.getAnimator(); + anim.setUpdateFPSFrames(60, null); + anim.resetFPSCounter(); + /** + * Kick off player w/o GLEventListener, i.e. for audio only. + * + new Thread() { + public void run() { + try { + mp.initGL(null); + if ( GLMediaPlayer.State.Paused == mp.getState() ) { // init OK + mp.play(); + } + System.out.println("play.1 "+mp); + } catch (Exception e) { + e.printStackTrace(); + destroyWindow(); + return; + } + } + }.start(); + */ + } + if( 0 != ( GLMediaEventListener.EVENT_CHANGE_PLAY & event_mask ) ) { + window.getAnimator().resetFPSCounter(); + } + + boolean destroy = false; + Throwable err = null; + + if( 0 != ( GLMediaEventListener.EVENT_CHANGE_EOS & event_mask ) ) { + err = ms.mPlayer.getStreamException(); + if( null != err ) { + System.err.println("MovieSimple State: EOS + Exception"); + destroy = true; + } else { + System.err.println("MovieSimple State: EOS"); + if( loopEOS ) { + new Thread() { + public void run() { + mp.setPlaySpeed(1f); + mp.seek(0); + mp.play(); + } + }.start(); + } else { + destroy = true; + } + } + } + if( 0 != ( GLMediaEventListener.EVENT_CHANGE_ERR & event_mask ) ) { + err = ms.mPlayer.getStreamException(); + if( null != err ) { + System.err.println("MovieSimple State: ERR + Exception"); + } else { + System.err.println("MovieSimple State: ERR"); + } + destroy = true; + } + if( destroy ) { + if( null != err ) { + err.printStackTrace(); + } + destroyWindow(window); + } + } + }; + final static MyGLMediaEventListener myGLMediaEventListener = new MyGLMediaEventListener(); + + static boolean loopEOS = false; + static boolean origSize; + + public static void main(String[] args) throws IOException, URISyntaxException { + int swapInterval = 1; int width = 640; int height = 600; + int textureCount = 3; // default - threaded boolean ortho = true; boolean zoom = false; - - String url_s="http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4"; - for(int i=0; i<args.length; i++) { - if(args[i].equals("-width")) { - i++; - width = MiscUtils.atoi(args[i], width); - } else if(args[i].equals("-height")) { - i++; - height = MiscUtils.atoi(args[i], height); - } else if(args[i].equals("-projection")) { - ortho=false; - } else if(args[i].equals("-zoom")) { - zoom=true; - } else if(args[i].equals("-url")) { - i++; - url_s = args[i]; - } - } - final MovieSimple ms = new MovieSimple(new URL(url_s).openConnection()); - ms.setScaleOrig(!zoom); - ms.setOrthoProjection(ortho); - - try { - GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES2()); - GLWindow window = GLWindow.create(caps); - window.addGLEventListener(ms); + boolean forceES2 = false; + boolean forceES3 = false; + boolean forceGL3 = false; + boolean forceGLDef = false; + int vid = GLMediaPlayer.STREAM_ID_AUTO; + int aid = GLMediaPlayer.STREAM_ID_AUTO; - window.setSize(width, height); - window.setVisible(true); - final Animator anim = new Animator(window); + final int windowCount; + { + int _windowCount = 1; + for(int i=0; i<args.length; i++) { + if(args[i].equals("-windows")) { + i++; + _windowCount = MiscUtils.atoi(args[i], _windowCount); + } + } + windowCount = _windowCount; + } + String[] urls_s = new String[windowCount]; + String file_s1=null, file_s2=null; + { + boolean _origSize = false; + for(int i=0; i<args.length; i++) { + if(args[i].equals("-vid")) { + i++; + vid = MiscUtils.atoi(args[i], vid); + } else if(args[i].equals("-aid")) { + i++; + aid = MiscUtils.atoi(args[i], aid); + } else if(args[i].equals("-width")) { + i++; + width = MiscUtils.atoi(args[i], width); + } else if(args[i].equals("-height")) { + i++; + height = MiscUtils.atoi(args[i], height); + } else if(args[i].equals("-osize")) { + _origSize = true; + } else if(args[i].equals("-textureCount")) { + i++; + textureCount = MiscUtils.atoi(args[i], textureCount); + } else if(args[i].equals("-es2")) { + forceES2 = true; + } else if(args[i].equals("-es3")) { + forceES3 = true; + } else if(args[i].equals("-gl3")) { + forceGL3 = true; + } else if(args[i].equals("-gldef")) { + forceGLDef = true; + } else if(args[i].equals("-vsync")) { + i++; + swapInterval = MiscUtils.atoi(args[i], swapInterval); + } else if(args[i].equals("-projection")) { + ortho=false; + } else if(args[i].equals("-zoom")) { + zoom=true; + } else if(args[i].equals("-loop")) { + loopEOS=true; + } else if(args[i].equals("-urlN")) { + i++; + final int n = MiscUtils.atoi(args[i], 0); + i++; + urls_s[n] = args[i]; + } else if(args[i].equals("-url")) { + i++; + urls_s[0] = args[i]; + } else if(args[i].equals("-file1")) { + i++; + file_s1 = args[i]; + } else if(args[i].equals("-file2")) { + i++; + file_s2 = args[i]; + } else if(args[i].equals("-wait")) { + waitForKey = true; + } + } + origSize = _origSize; + } + final URI streamLoc0; + if( null != urls_s[0] ) { + streamLoc0 = new URI(urls_s[0]); + } else if( null != file_s1 ) { + File movieFile = new File(file_s1); + streamLoc0 = movieFile.toURI(); + } else if( null != file_s2 ) { + streamLoc0 = IOUtil.toURISimple(new File(file_s2)); + } else { + streamLoc0 = defURI; + } + System.err.println("url_s "+urls_s[0]); + System.err.println("file_s 1: "+file_s1+", 2: "+file_s2); + System.err.println("stream0 "+streamLoc0); + System.err.println("vid "+vid+", aid "+aid); + System.err.println("textureCount "+textureCount); + System.err.println("forceES2 "+forceES2); + System.err.println("forceES3 "+forceES3); + System.err.println("forceGL3 "+forceGL3); + System.err.println("forceGLDef "+forceGLDef); + System.err.println("swapInterval "+swapInterval); + + final GLProfile glp; + if(forceGLDef) { + glp = GLProfile.getDefault(); + } else if(forceGL3) { + glp = GLProfile.get(GLProfile.GL3); + } else if(forceES3) { + glp = GLProfile.get(GLProfile.GLES3); + } else if(forceES2) { + glp = GLProfile.get(GLProfile.GLES2); + } else { + glp = GLProfile.getGL2ES2(); + } + System.err.println("GLProfile: "+glp); + GLCapabilities caps = new GLCapabilities(glp); + + final MovieSimple[] mss = new MovieSimple[windowCount]; + final GLWindow[] windows = new GLWindow[windowCount]; + for(int i=0; i<windowCount; i++) { + final Animator anim = new Animator(); anim.start(); - window.addWindowListener(new WindowAdapter() { + windows[i] = GLWindow.create(caps); + windows[i].addWindowListener(new WindowAdapter() { public void windowDestroyed(WindowEvent e) { anim.stop(); - } + } }); - } catch (Throwable t) { - t.printStackTrace(); + mss[i] = new MovieSimple(null); + mss[i].setSwapInterval(swapInterval); + mss[i].setScaleOrig(!zoom); + mss[i].setOrthoProjection(ortho); + mss[i].mPlayer.attachObject(WINDOW_KEY, windows[i]); + mss[i].mPlayer.addEventListener(myGLMediaEventListener); + + windows[i].setTitle("Player "+i); + windows[i].setSize(width, height); + windows[i].setVisible(true); + anim.add(windows[i]); + + final URI streamLocN; + if( 0 == i ) { + streamLocN = streamLoc0; + } else { + if( null != urls_s[i] ) { + streamLocN = new URI(urls_s[i]); + } else { + streamLocN = defURI; + } + } + System.err.println("Win #"+i+": stream "+streamLocN); + mss[i].initStream(streamLocN, vid, aid, textureCount); } } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug816AppletGLCanvas01.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug816AppletGLCanvas01.java new file mode 100644 index 000000000..4cecd90a1 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug816AppletGLCanvas01.java @@ -0,0 +1,134 @@ +/** + * Copyright 2013 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.jogl.demos.es2.awt; + +import java.applet.Applet; +import java.awt.Color; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +import javax.media.opengl.GL; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; +import javax.swing.JFrame; +import javax.swing.JPanel; + +/** + * Bug 816: OSX CALayer Positioning Bug. + * <p> + * Diff. OSX CALayer positioning w/ java6, [7uxx..7u40[, and >= 7u40 + * </p> + * <p> + * Test simply positions a GLCanvas via setBounds(..) within it's Applet. + * </p> + */ +@SuppressWarnings("serial") +public class Bug816AppletGLCanvas01 extends Applet implements GLEventListener { + + public Bug816AppletGLCanvas01() { + } + + public static JFrame frame; + public static JPanel appletHolder; + public static boolean isApplet = true; + + static public void main(String args[]) { + Applet myApplet = null; + isApplet = false; + + myApplet = new Bug816AppletGLCanvas01(); + appletStarter(myApplet, "Bug861AppletGLCanvasTest01", 800, 600); + } + + static public void appletStarter(final Applet des, String frameName, int width, int height) { + appletHolder = new JPanel(); + if (frame != null) { + frame.dispose(); + frame = null; + } + frame = new JFrame(frameName); + frame.setVisible(false); + frame.getContentPane().add(appletHolder); + + appletHolder.setLayout(null); + des.setBounds(0, 0, width, height); + appletHolder.add(des); + + frame.setVisible(true); + int frameBorderSize = appletHolder.getLocationOnScreen().x - frame.getLocationOnScreen().x; + int titleBarHeight = appletHolder.getLocationOnScreen().y - frame.getLocationOnScreen().y; + int frameWidth = width + 2 * frameBorderSize; + int frameHeight = height + titleBarHeight + frameBorderSize; + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setSize(frameWidth, frameHeight); + frame.setVisible(true); + des.init(); + frame.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }); + } + + public void init() { + initOpenGLAWT(); + } + + public void initOpenGLAWT() { + setBackground(Color.gray); + setLayout(null); + + GLProfile glp = GLProfile.getDefault(); + GLCapabilities caps = new GLCapabilities(glp); + GLCanvas canvas = new GLCanvas((GLCapabilitiesImmutable) caps); + canvas.setBounds(50, 50, 200, 450); + canvas.addGLEventListener(this); + add(canvas); + } + + public void init(GLAutoDrawable gLAutoDrawable) { + GL gl = gLAutoDrawable.getGL(); + gl.glClearColor(1.0f, 0.0f, 0.0f, 1.0f); + gl.glClear(GL.GL_COLOR_BUFFER_BIT); + gLAutoDrawable.swapBuffers(); + } + + public void dispose(GLAutoDrawable glad) { + } + + public void display(GLAutoDrawable glad) { + } + + public void reshape(GLAutoDrawable glad, int i, int i1, int i2, int i3) { + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug816AppletGLCanvas02a.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug816AppletGLCanvas02a.java new file mode 100644 index 000000000..3bbb423fd --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug816AppletGLCanvas02a.java @@ -0,0 +1,89 @@ +/** + * Copyright 2013 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.jogl.demos.es2.awt; + +import java.applet.Applet; + +import javax.media.opengl.GLAnimatorControl; +import javax.media.opengl.awt.GLCanvas; +import javax.swing.BoxLayout; + +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.util.Animator; + +/** + * Bug 816: OSX CALayer Positioning Bug. + * <p> + * Diff. OSX CALayer positioning w/ java6, [7uxx..7u40[, and >= 7u40 + * </p> + * <p> + * Test uses a box layout within the Applet. + * </p> + */ +@SuppressWarnings("serial") +public class Bug816AppletGLCanvas02a extends Applet { + GLAnimatorControl animator; + boolean added = false; + + @Override + public void init() { + System.err.println("GearsApplet: init() - begin [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName()); + animator = new Animator(); + new BoxLayout(this, BoxLayout.X_AXIS); + setSize(664, 364); + add(createCanvas()); + add(createCanvas()); + System.err.println("GearsApplet: init() - end [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName()); + } + + private GLCanvas createCanvas() { + GLCanvas canvas = new GLCanvas(); + canvas.addGLEventListener(new GearsES2(1)); + canvas.setSize(300, 300); + animator.add(canvas); + return canvas; + } + + String currentThreadName() { + return Thread.currentThread().getName(); + } + + @Override + public void start() { + System.err.println("GearsApplet: start() - begin [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName()); + animator.start(); + animator.setUpdateFPSFrames(60, System.err); + System.err.println("GearsApplet: start() - end [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName()); + } + + @Override + public void stop() { + System.err.println("GearsApplet: stop() - [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName()); + animator.stop(); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug816AppletGLCanvas02b.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug816AppletGLCanvas02b.java new file mode 100644 index 000000000..87a7ea4f5 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug816AppletGLCanvas02b.java @@ -0,0 +1,89 @@ +/** + * Copyright 2013 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.jogl.demos.es2.awt; + +import java.applet.Applet; +import java.awt.GridLayout; + +import javax.media.opengl.GLAnimatorControl; +import javax.media.opengl.awt.GLCanvas; + +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.util.Animator; + +/** + * Bug 816: OSX CALayer Positioning Bug. + * <p> + * Diff. OSX CALayer positioning w/ java6, [7uxx..7u40[, and >= 7u40 + * </p> + * <p> + * Test uses a grid layout within the Applet. + * </p> + */ +@SuppressWarnings("serial") +public class Bug816AppletGLCanvas02b extends Applet { + GLAnimatorControl animator; + boolean added = false; + + @Override + public void init() { + System.err.println("GearsApplet: init() - begin [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName()); + animator = new Animator(); + this.setLayout(new GridLayout(1, 2)); + setSize(664, 364); + add(createCanvas()); + add(createCanvas()); + System.err.println("GearsApplet: init() - end [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName()); + } + + private GLCanvas createCanvas() { + GLCanvas canvas = new GLCanvas(); + canvas.addGLEventListener(new GearsES2(1)); + canvas.setSize(300, 300); + animator.add(canvas); + return canvas; + } + + String currentThreadName() { + return Thread.currentThread().getName(); + } + + @Override + public void start() { + System.err.println("GearsApplet: start() - begin [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName()); + animator.start(); + animator.setUpdateFPSFrames(60, System.err); + System.err.println("GearsApplet: start() - end [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName()); + } + + @Override + public void stop() { + System.err.println("GearsApplet: stop() - [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName()); + animator.stop(); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug816AppletOSXCALayerPos03a.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug816AppletOSXCALayerPos03a.java new file mode 100644 index 000000000..a0ce938fe --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug816AppletOSXCALayerPos03a.java @@ -0,0 +1,102 @@ +/** + * Copyright 2013 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.jogl.demos.es2.awt; + +import java.applet.Applet; +import java.awt.BorderLayout; + +import javax.media.opengl.GLAnimatorControl; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; +import javax.swing.JRootPane; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; + +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.util.Animator; + +/** + * Bug 816: OSX CALayer Positioning Bug - AWT Applet w/ 1 JRootPane and 2 JSplitPanes + * <p> + * Diff. OSX CALayer positioning w/ java6, [7uxx..7u40[, and >= 7u40 + * </p> + * <p> + * See also {@link com.jogamp.opengl.test.junit.jogl.awt.TestBug816OSXCALayerPos02AWT} + * </p> + * Bug persists in browser (Firefox, Safari) and not in appletviewer! + */ +@SuppressWarnings("serial") +public class Bug816AppletOSXCALayerPos03a extends Applet { + GLAnimatorControl animator; + boolean added = false; + + @Override + public void init() { + System.err.println("GearsApplet: init() - begin [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName()); + GLProfile glp = GLProfile.getDefault(); + final GLCapabilities caps = new GLCapabilities(glp); + final GLCanvas glCanvas1 = new GLCanvas(caps); + glCanvas1.addGLEventListener(new GearsES2(1)); + + animator = new Animator(); + animator.add(glCanvas1); + setLayout(new BorderLayout()); + + // Build a GUI where the canvas 3D is located at top right of the frame + // and can be resized with split panes dividers + JSplitPane verticalSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, + true, new JScrollPane(), glCanvas1); + verticalSplitPane.setResizeWeight(0.5); + JSplitPane horizontalSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, + true, new JScrollPane(), verticalSplitPane); + horizontalSplitPane.setResizeWeight(0.5); + JRootPane intermediateRootPane = new JRootPane(); + intermediateRootPane.setContentPane(horizontalSplitPane); + add(intermediateRootPane, BorderLayout.CENTER); + System.err.println("GearsApplet: init() - end [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName()); + } + + String currentThreadName() { + return Thread.currentThread().getName(); + } + + @Override + public void start() { + System.err.println("GearsApplet: start() - begin [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName()); + animator.start(); + animator.setUpdateFPSFrames(60, System.err); + System.err.println("GearsApplet: start() - end [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName()); + } + + @Override + public void stop() { + System.err.println("GearsApplet: stop() - [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName()); + animator.stop(); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug816AppletOSXCALayerPos03b.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug816AppletOSXCALayerPos03b.java new file mode 100644 index 000000000..48dac25e8 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug816AppletOSXCALayerPos03b.java @@ -0,0 +1,101 @@ +/** + * Copyright 2013 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.jogl.demos.es2.awt; + +import javax.media.opengl.GLAnimatorControl; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; +import javax.swing.JApplet; +import javax.swing.JRootPane; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; + +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.util.Animator; + +/** + * Bug 816: OSX CALayer Positioning Bug - Swing JApplet w/ 2 JRootPanes and 2 JSplitPanes + * <p> + * Diff. OSX CALayer positioning w/ java6, [7uxx..7u40[, and >= 7u40 + * </p> + * <p> + * See also {@link com.jogamp.opengl.test.junit.jogl.awt.TestBug816OSXCALayerPos02AWT} + * </p> + * Bug persists in browser (Firefox, Safari) and not in appletviewer! + */ +@SuppressWarnings("serial") +public class Bug816AppletOSXCALayerPos03b extends JApplet { + GLAnimatorControl animator; + boolean added = false; + + @Override + public void init() { + System.err.println("GearsApplet: init() - begin [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName()); + GLProfile glp = GLProfile.getDefault(); + final GLCapabilities caps = new GLCapabilities(glp); + final GLCanvas glCanvas1 = new GLCanvas(caps); + glCanvas1.addGLEventListener(new GearsES2(1)); + + animator = new Animator(); + animator.add(glCanvas1); + setSize(640, 480); + + // Build a GUI where the canvas 3D is located at top right of the frame + // and can be resized with split panes dividers + JSplitPane verticalSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, + true, new JScrollPane(), glCanvas1); + verticalSplitPane.setResizeWeight(0.5); + JSplitPane horizontalSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, + true, new JScrollPane(), verticalSplitPane); + horizontalSplitPane.setResizeWeight(0.5); + JRootPane intermediateRootPane = new JRootPane(); + intermediateRootPane.setContentPane(horizontalSplitPane); + intermediateRootPane.setSize(640, 480); + this.add(intermediateRootPane); + System.err.println("GearsApplet: init() - end [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName()); + } + + String currentThreadName() { + return Thread.currentThread().getName(); + } + + @Override + public void start() { + System.err.println("GearsApplet: start() - begin [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName()); + animator.start(); + animator.setUpdateFPSFrames(60, System.err); + System.err.println("GearsApplet: start() - end [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName()); + } + + @Override + public void stop() { + System.err.println("GearsApplet: stop() - [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName()); + animator.stop(); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug848AppletGLCanvas01.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug848AppletGLCanvas01.java new file mode 100644 index 000000000..c3d40b71d --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/Bug848AppletGLCanvas01.java @@ -0,0 +1,94 @@ +/** + * Copyright 2013 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.jogl.demos.es2.awt; + +import java.applet.Applet; +import java.util.ArrayList; +import java.util.List; + +import javax.media.opengl.GLAnimatorControl; +import javax.media.opengl.awt.GLCanvas; +import javax.swing.BoxLayout; + +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.util.Animator; + +/** + * Bug 848: Applet on OSX w/ CALayer and 2 or more GLCanvas may 'crash'. + * <p> + * Test uses 2x3 GLCanvas in a box layout within the Applet. + * </p> + */ +@SuppressWarnings("serial") +public class Bug848AppletGLCanvas01 extends Applet { + private final List<GLAnimatorControl> animators = new ArrayList<GLAnimatorControl>(2); + + @Override + public void init() { + System.err.println("GearsApplet: init() - begin [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName()); + new BoxLayout(this, BoxLayout.X_AXIS); + setSize(1024, 664); + add(createCanvas(0)); + add(createCanvas(0)); + add(createCanvas(0)); + add(createCanvas(0)); + add(createCanvas(0)); + add(createCanvas(1)); + System.err.println("GearsApplet: init() - end [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName()); + } + + private GLCanvas createCanvas(int vsyncI) { + GLCanvas canvas = new GLCanvas(); + canvas.addGLEventListener(new GearsES2(vsyncI)); + canvas.setSize(300, 300); + animators.add(new Animator(canvas)); + return canvas; + } + + String currentThreadName() { + return Thread.currentThread().getName(); + } + + @Override + public void start() { + System.err.println("GearsApplet: start() - begin [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName()); + for (GLAnimatorControl control : animators) { + control.start(); + control.setUpdateFPSFrames(60, System.err); + } + System.err.println("GearsApplet: start() - end [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName()); + } + + @Override + public void stop() { + System.err.println("GearsApplet: stop() - [visible "+isVisible()+", displayable "+isDisplayable()+"] - "+currentThreadName()); + for (GLAnimatorControl control : animators) { + control.stop(); + } + } +} 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 c6e224548..58600dacd 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 @@ -32,58 +32,186 @@ import javax.media.opengl.*; import com.jogamp.opengl.util.Animator; import javax.media.opengl.awt.GLCanvas; + +import com.jogamp.common.os.Platform; import com.jogamp.newt.event.awt.AWTKeyAdapter; import com.jogamp.newt.event.awt.AWTWindowAdapter; 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.AWTRobotUtil; 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.BorderLayout; +import java.awt.Button; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.EventQueue; import java.awt.Frame; +import java.awt.TextArea; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.lang.reflect.InvocationTargetException; import org.junit.Assert; +import org.junit.Assume; import org.junit.BeforeClass; import org.junit.AfterClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestGearsES2AWT extends UITestCase { + public enum FrameLayout { None, TextOnBottom, BorderCenterSurrounded, DoubleBorderCenterSurrounded }; + public enum ResizeBy { Component, Frame }; + + static long duration = 500; // ms static int width, height; - static boolean firstUIActionOnProcess = false; + static FrameLayout frameLayout = FrameLayout.None; + static ResizeBy resizeBy = ResizeBy.Component; + static boolean forceES2 = false; - static boolean shallUseOffscreenLayer = false; + static boolean forceGL3 = false; + static boolean mainRun = false; + static boolean shallUseOffscreenFBOLayer = false; + static boolean shallUseOffscreenPBufferLayer = false; + static boolean useMSAA = false; + static boolean useStencil = false; + static boolean shutdownRemoveGLCanvas = true; + static boolean shutdownDisposeFrame = true; + static boolean shutdownSystemExit = false; static int swapInterval = 1; - static boolean showFPS = false; + static boolean exclusiveContext = false; + static boolean useAnimator = true; + static Thread awtEDT; + static java.awt.Dimension rwsize = null; @BeforeClass public static void initClass() { - width = 512; - height = 512; + width = 640; + height = 480; + try { + EventQueue.invokeAndWait(new Runnable() { + public void run() { + awtEDT = Thread.currentThread(); + } } ); + } catch (Exception e) { + e.printStackTrace(); + Assert.assertNull(e); + } } @AfterClass public static void releaseClass() { } - protected void runTestGL(GLCapabilities caps) throws InterruptedException, InvocationTargetException { + static void setComponentSize(final Frame frame, final Component comp, final java.awt.Dimension new_sz) { + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + comp.setMinimumSize(new_sz); + comp.setPreferredSize(new_sz); + comp.setSize(new_sz); + if( null != frame ) { + frame.pack(); + } + } } ); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + } + static void setFrameSize(final Frame frame, final boolean frameLayout, final java.awt.Dimension new_sz) { + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setSize(new_sz); + if( frameLayout ) { + frame.validate(); + } + } } ); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + } + + static void setSize(final ResizeBy resizeBy, final Frame frame, final boolean frameLayout, final Component comp, final java.awt.Dimension new_sz) { + switch( resizeBy ) { + case Component: + setComponentSize(frameLayout ? frame : null, comp, new_sz); + break; + case Frame: + setFrameSize(frame, frameLayout, new_sz); + break; + } + } + + protected void runTestGL(GLCapabilities caps, final ResizeBy resizeBy, FrameLayout frameLayout) throws InterruptedException, InvocationTargetException { final Frame frame = new Frame("GearsES2 AWT Test"); Assert.assertNotNull(frame); final GLCanvas glCanvas = new GLCanvas(caps); Assert.assertNotNull(glCanvas); - glCanvas.setShallUseOffscreenLayer(shallUseOffscreenLayer); - frame.add(glCanvas); - frame.setSize(512, 512); + setSize(resizeBy, frame, false, glCanvas, new Dimension(width, height)); + + switch( frameLayout) { + case None: + frame.add(glCanvas); + break; + case TextOnBottom: + final TextArea ta = new TextArea(2, 20); + ta.append("0123456789"); + ta.append(Platform.getNewline()); + ta.append("Some Text"); + ta.append(Platform.getNewline()); + frame.setLayout(new BorderLayout()); + frame.add(ta, BorderLayout.SOUTH); + frame.add(glCanvas, BorderLayout.CENTER); + break; + case BorderCenterSurrounded: + frame.setLayout(new BorderLayout()); + frame.add(new Button("NORTH"), BorderLayout.NORTH); + frame.add(new Button("SOUTH"), BorderLayout.SOUTH); + frame.add(new Button("EAST"), BorderLayout.EAST); + frame.add(new Button("WEST"), BorderLayout.WEST); + frame.add(glCanvas, BorderLayout.CENTER); + break; + case DoubleBorderCenterSurrounded: + Container c = new Container(); + c.setLayout(new BorderLayout()); + c.add(new Button("north"), BorderLayout.NORTH); + c.add(new Button("south"), BorderLayout.SOUTH); + c.add(new Button("east"), BorderLayout.EAST); + c.add(new Button("west"), BorderLayout.WEST); + c.add(glCanvas, BorderLayout.CENTER); + + frame.setLayout(new BorderLayout()); + frame.add(new Button("NORTH"), BorderLayout.NORTH); + frame.add(new Button("SOUTH"), BorderLayout.SOUTH); + frame.add(new Button("EAST"), BorderLayout.EAST); + frame.add(new Button("WEST"), BorderLayout.WEST); + frame.add(c, BorderLayout.CENTER); + break; + } frame.setTitle("Gears AWT Test (translucent "+!caps.isBackgroundOpaque()+"), swapInterval "+swapInterval); - glCanvas.addGLEventListener(new GearsES2(swapInterval)); + final GearsES2 demo = new GearsES2(swapInterval); + glCanvas.addGLEventListener(demo); + + final SnapshotGLEventListener snap = new SnapshotGLEventListener(); + glCanvas.addGLEventListener(snap); - Animator animator = new Animator(glCanvas); + final Animator animator = useAnimator ? new Animator(glCanvas) : null; + if( useAnimator && exclusiveContext ) { + animator.setExclusiveContext(awtEDT); + } QuitAdapter quitAdapter = new QuitAdapter(); new AWTKeyAdapter(new TraceKeyAdapter(quitAdapter)).addTo(glCanvas); @@ -91,65 +219,196 @@ public class TestGearsES2AWT extends UITestCase { javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { - frame.setVisible(true); - }}); - animator.setUpdateFPSFrames(60, System.err); - animator.start(); + if( ResizeBy.Frame == resizeBy ) { + frame.validate(); + } else { + frame.pack(); + } + frame.setVisible(true); + }}); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas, true)); + + if( useAnimator ) { + animator.start(); + Assert.assertTrue(animator.isStarted()); + Assert.assertTrue(animator.isAnimating()); + Assert.assertEquals(exclusiveContext ? awtEDT : null, glCanvas.getExclusiveContextThread()); + animator.setUpdateFPSFrames(60, System.err); + } + + System.err.println("canvas pos/siz: "+glCanvas.getX()+"/"+glCanvas.getY()+" "+glCanvas.getWidth()+"x"+glCanvas.getHeight()); - while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) { + snap.setMakeSnapshot(); + + if( null != rwsize ) { + Thread.sleep(500); // 500ms delay + setSize(resizeBy, frame, true, glCanvas, rwsize); + System.err.println("window resize pos/siz: "+glCanvas.getX()+"/"+glCanvas.getY()+" "+glCanvas.getWidth()+"x"+glCanvas.getHeight()); + } + + snap.setMakeSnapshot(); + + final long t0 = System.currentTimeMillis(); + long t1 = t0; + while(!quitAdapter.shouldQuit() && t1 - t0 < duration) { Thread.sleep(100); + t1 = System.currentTimeMillis(); } Assert.assertNotNull(frame); Assert.assertNotNull(glCanvas); - Assert.assertNotNull(animator); + + if( useAnimator ) { + Assert.assertNotNull(animator); + Assert.assertEquals(exclusiveContext ? awtEDT : null, glCanvas.getExclusiveContextThread()); + animator.stop(); + Assert.assertFalse(animator.isAnimating()); + Assert.assertFalse(animator.isStarted()); + Assert.assertEquals(null, glCanvas.getExclusiveContextThread()); + } - animator.stop(); - Assert.assertEquals(false, animator.isAnimating()); - frame.setVisible(false); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + }}); Assert.assertEquals(false, frame.isVisible()); javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { - frame.remove(glCanvas); - frame.dispose(); + if(shutdownRemoveGLCanvas) { + frame.remove(glCanvas); + } + if(shutdownDisposeFrame) { + frame.dispose(); + } + if(shutdownSystemExit) { + System.exit(0); + } }}); } @Test public void test01() throws InterruptedException, InvocationTargetException { - GLCapabilities caps = new GLCapabilities(forceES2 ? GLProfile.get(GLProfile.GLES2) : GLProfile.getGL2ES2()); - runTestGL(caps); + final GLProfile glp; + if(forceGL3) { + glp = GLProfile.get(GLProfile.GL3); + } else if(forceES2) { + glp = GLProfile.get(GLProfile.GLES2); + } else { + glp = GLProfile.getGL2ES2(); + } + final GLCapabilities caps = new GLCapabilities(glp); + if(useMSAA) { + caps.setNumSamples(4); + caps.setSampleBuffers(true); + } + if(useStencil) { + caps.setStencilBits(1); + } + if(shallUseOffscreenFBOLayer) { + caps.setOnscreen(false); + } + if(shallUseOffscreenPBufferLayer) { + caps.setPBuffer(true); + } + runTestGL(caps, resizeBy, frameLayout); } - static long duration = 500; // ms - + @Test + public void test02_GLES2() throws InterruptedException, InvocationTargetException { + if(mainRun) return; + + if( !GLProfile.isAvailable(GLProfile.GLES2) ) { + System.err.println("GLES2 n/a"); + return; + } + final GLProfile glp = GLProfile.get(GLProfile.GLES2); + final GLCapabilities caps = new GLCapabilities( glp ); + runTestGL(caps, resizeBy, frameLayout); + } + + @Test + public void test03_GL3() throws InterruptedException, InvocationTargetException { + if(mainRun) return; + + if( !GLProfile.isAvailable(GLProfile.GL3) ) { + System.err.println("GL3 n/a"); + return; + } + final GLProfile glp = GLProfile.get(GLProfile.GL3); + final GLCapabilities caps = new GLCapabilities( glp ); + runTestGL(caps, resizeBy, frameLayout); + } + public static void main(String args[]) { boolean waitForKey = false; + int rw=-1, rh=-1; + mainRun = true; for(int i=0; i<args.length; i++) { if(args[i].equals("-time")) { i++; - try { - duration = Integer.parseInt(args[i]); - } catch (Exception ex) { ex.printStackTrace(); } + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-rwidth")) { + i++; + rw = MiscUtils.atoi(args[i], rw); + } else if(args[i].equals("-rheight")) { + i++; + rh = MiscUtils.atoi(args[i], rh); + } else if(args[i].equals("-layout")) { + i++; + frameLayout = FrameLayout.valueOf(args[i]); + } else if(args[i].equals("-resizeBy")) { + i++; + resizeBy = ResizeBy.valueOf(args[i]); } else if(args[i].equals("-es2")) { forceES2 = true; + } else if(args[i].equals("-gl3")) { + forceGL3 = 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("-exclctx")) { + exclusiveContext = true; + } else if(args[i].equals("-noanim")) { + useAnimator = false; + } else if(args[i].equals("-layeredFBO")) { + shallUseOffscreenFBOLayer = true; + } else if(args[i].equals("-layeredPBuffer")) { + shallUseOffscreenPBufferLayer = true; + } else if(args[i].equals("-msaa")) { + useMSAA = true; + } else if(args[i].equals("-stencil")) { + useStencil = true; } else if(args[i].equals("-wait")) { waitForKey = true; + } else if(args[i].equals("-shutdownKeepGLCanvas")) { + shutdownRemoveGLCanvas = false; + } else if(args[i].equals("-shutdownKeepFrame")) { + shutdownDisposeFrame = false; + } else if(args[i].equals("-shutdownKeepAll")) { + shutdownRemoveGLCanvas = false; + shutdownDisposeFrame = false; + } else if(args[i].equals("-shutdownSystemExit")) { + shutdownSystemExit = true; } } + if( 0 < rw && 0 < rh ) { + rwsize = new Dimension(rw, rh); + } + + System.err.println("resize "+rwsize); + System.err.println("frameLayout "+frameLayout); + System.err.println("resizeBy "+resizeBy); System.err.println("forceES2 "+forceES2); + System.err.println("forceGL3 "+forceGL3); System.err.println("swapInterval "+swapInterval); - System.err.println("shallUseOffscreenLayer "+shallUseOffscreenLayer); + System.err.println("exclusiveContext "+exclusiveContext); + System.err.println("useMSAA "+useMSAA); + System.err.println("useAnimator "+useAnimator); + + System.err.println("shallUseOffscreenFBOLayer "+shallUseOffscreenFBOLayer); + System.err.println("shallUseOffscreenPBufferLayer "+shallUseOffscreenPBufferLayer); if(waitForKey) { BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelAWT.java new file mode 100644 index 000000000..46e39bebf --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelAWT.java @@ -0,0 +1,379 @@ +/** + * 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.jogl.demos.es2.awt; + +import java.awt.AWTException; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLJPanel; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.event.TraceKeyAdapter; +import com.jogamp.newt.event.TraceWindowAdapter; +import com.jogamp.newt.event.awt.AWTKeyAdapter; +import com.jogamp.newt.event.awt.AWTWindowAdapter; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.FPSAnimator; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGearsES2GLJPanelAWT extends UITestCase { + static Dimension wsize, rwsize=null; + static boolean forceES2 = false; + static boolean forceGL3 = false; + static boolean forceGLFFP = false; + static boolean shallUsePBuffer = false; + static boolean shallUseBitmap = false; + static boolean useMSAA = false; + static int swapInterval = 0; + static boolean useAnimator = true; + static boolean manualTest = false; + static boolean skipGLOrientationVerticalFlip = false; + + @BeforeClass + public static void initClass() { + if(null == wsize) { + wsize = new Dimension(640, 480); + } + } + + @AfterClass + public static void releaseClass() { + } + + static void setFrameSize(final JFrame frame, final boolean frameLayout, final java.awt.Dimension new_sz) { + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setSize(new_sz); + if( frameLayout ) { + frame.validate(); + } + } } ); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + } + + protected void runTestGL(GLCapabilities caps) + throws AWTException, InterruptedException, InvocationTargetException + { + final JFrame frame = new JFrame("Swing GLJPanel"); + Assert.assertNotNull(frame); + + final GLJPanel glJPanel = new GLJPanel(caps); + Assert.assertNotNull(glJPanel); + glJPanel.setSkipGLOrientationVerticalFlip(skipGLOrientationVerticalFlip); + glJPanel.setMinimumSize(wsize); + glJPanel.setPreferredSize(wsize); + glJPanel.setSize(wsize); + if( caps.isBitmap() || caps.getGLProfile().isGL2() ) { + final Gears gears = new Gears(swapInterval); + gears.setFlipVerticalInGLOrientation(skipGLOrientationVerticalFlip); + glJPanel.addGLEventListener(gears); + } else { + final GearsES2 gears = new GearsES2(swapInterval); + gears.setFlipVerticalInGLOrientation(skipGLOrientationVerticalFlip); + glJPanel.addGLEventListener(gears); + } + final SnapshotGLEventListener snap = new SnapshotGLEventListener(); + glJPanel.addGLEventListener(snap); + + final FPSAnimator animator = useAnimator ? new FPSAnimator(glJPanel, 60) : null; + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.getContentPane().add(glJPanel, BorderLayout.CENTER); + frame.getContentPane().validate(); + frame.pack(); + frame.setVisible(true); + } } ) ; + + if( useAnimator ) { + animator.setUpdateFPSFrames(60, System.err); + animator.start(); + Assert.assertEquals(true, animator.isAnimating()); + } + + QuitAdapter quitAdapter = new QuitAdapter(); + + new AWTKeyAdapter(new TraceKeyAdapter(quitAdapter)).addTo(glJPanel); + new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter)).addTo(frame); + + snap.setMakeSnapshot(); + + if( null != rwsize ) { + Thread.sleep(500); // 500ms delay + setFrameSize(frame, true, rwsize); + System.err.println("window resize pos/siz: "+glJPanel.getX()+"/"+glJPanel.getY()+" "+glJPanel.getWidth()+"x"+glJPanel.getHeight()); + } + + snap.setMakeSnapshot(); + + final long t0 = System.currentTimeMillis(); + long t1 = t0; + boolean triggerSnap = false; + while(!quitAdapter.shouldQuit() && t1 - t0 < duration) { + Thread.sleep(100); + t1 = System.currentTimeMillis(); + snap.getDisplayCount(); + if( !triggerSnap && snap.getDisplayCount() > 1 ) { + // Snapshot only after one frame has been rendered to suite FBO MSAA! + snap.setMakeSnapshot(); + triggerSnap = true; + } + } + + Assert.assertNotNull(frame); + Assert.assertNotNull(glJPanel); + Assert.assertNotNull(animator); + + if( useAnimator ) { + animator.stop(); + Assert.assertEquals(false, animator.isAnimating()); + } + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + frame.getContentPane().remove(glJPanel); + frame.remove(glJPanel); + glJPanel.destroy(); + frame.dispose(); + } } ); + } + + @Test + public void test01_DefaultNorm() + throws AWTException, InterruptedException, InvocationTargetException + { + final GLProfile glp; + if(forceGL3) { + glp = GLProfile.get(GLProfile.GL3); + } else if(forceES2) { + glp = GLProfile.get(GLProfile.GLES2); + } else if(forceGLFFP) { + glp = GLProfile.getMaxFixedFunc(true); + } else { + glp = GLProfile.getGL2ES2(); + } + GLCapabilities caps = new GLCapabilities( glp ); + if(useMSAA) { + caps.setNumSamples(4); + caps.setSampleBuffers(true); + } + if(shallUsePBuffer) { + caps.setPBuffer(true); + } + if(shallUseBitmap) { + caps.setBitmap(true); + } + runTestGL(caps); + } + + @Test + public void test02_DefaultMsaa() + throws AWTException, InterruptedException, InvocationTargetException + { + if( manualTest ) { + return; + } + GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); + caps.setNumSamples(4); + caps.setSampleBuffers(true); + runTestGL(caps); + } + + @Test + public void test03_PbufferNorm() + throws AWTException, InterruptedException, InvocationTargetException + { + if( manualTest ) { + return; + } + GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); + caps.setPBuffer(true); + runTestGL(caps); + } + + @Test + public void test04_PbufferMsaa() + throws AWTException, InterruptedException, InvocationTargetException + { + if( manualTest ) { + return; + } + GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); + caps.setNumSamples(4); + caps.setSampleBuffers(true); + caps.setPBuffer(true); + runTestGL(caps); + } + + @Test + public void test05_BitmapNorm() + throws AWTException, InterruptedException, InvocationTargetException + { + if( manualTest ) { + return; + } + GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); + caps.setBitmap(true); + runTestGL(caps); + } + + @Test + public void test06_BitmapMsaa() + throws AWTException, InterruptedException, InvocationTargetException + { + if( manualTest ) { + return; + } + GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); + caps.setNumSamples(4); + caps.setSampleBuffers(true); + caps.setBitmap(true); + runTestGL(caps); + } + + @Test + public void test20_GLES2() + throws AWTException, InterruptedException, InvocationTargetException + { + if( manualTest ) { + return; + } + + if( !GLProfile.isAvailable(GLProfile.GLES2) ) { + System.err.println("GLES2 n/a"); + return; + } + final GLProfile glp = GLProfile.get(GLProfile.GLES2); + final GLCapabilities caps = new GLCapabilities( glp ); + runTestGL(caps); + } + + @Test + public void test30_GL3() + throws AWTException, InterruptedException, InvocationTargetException + { + if( manualTest ) { + return; + } + + if( !GLProfile.isAvailable(GLProfile.GL3) ) { + System.err.println("GL3 n/a"); + return; + } + final GLProfile glp = GLProfile.get(GLProfile.GL3); + final GLCapabilities caps = new GLCapabilities( glp ); + runTestGL(caps); + } + + static long duration = 500; // ms + + public static void main(String args[]) { + int w=640, h=480, rw=-1, rh=-1; + + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-es2")) { + forceES2 = true; + } else if(args[i].equals("-gl3")) { + forceGL3 = true; + } else if(args[i].equals("-glFFP")) { + forceGLFFP = true; + } else if(args[i].equals("-width")) { + i++; + w = MiscUtils.atoi(args[i], w); + } else if(args[i].equals("-height")) { + i++; + h = MiscUtils.atoi(args[i], h); + } else if(args[i].equals("-rwidth")) { + i++; + rw = MiscUtils.atoi(args[i], rw); + } else if(args[i].equals("-rheight")) { + i++; + rh = MiscUtils.atoi(args[i], rh); + } else if(args[i].equals("-userVFlip")) { + skipGLOrientationVerticalFlip = true; + } else if(args[i].equals("-vsync")) { + i++; + swapInterval = MiscUtils.atoi(args[i], swapInterval); + } else if(args[i].equals("-msaa")) { + useMSAA = true; + } else if(args[i].equals("-noanim")) { + useAnimator = false; + } else if(args[i].equals("-pbuffer")) { + shallUsePBuffer = true; + } else if(args[i].equals("-bitmap")) { + shallUseBitmap = true; + } else if(args[i].equals("-manual")) { + manualTest = true; + } + } + wsize = new Dimension(w, h); + if( 0 < rw && 0 < rh ) { + rwsize = new Dimension(rw, rh); + } + + System.err.println("size "+wsize); + System.err.println("resize "+rwsize); + System.err.println("userVFlip "+skipGLOrientationVerticalFlip); + System.err.println("swapInterval "+swapInterval); + System.err.println("forceES2 "+forceES2); + System.err.println("forceGL3 "+forceGL3); + System.err.println("forceGLFFP "+forceGLFFP); + System.err.println("useMSAA "+useMSAA); + System.err.println("useAnimator "+useAnimator); + System.err.println("shallUsePBuffer "+shallUsePBuffer); + System.err.println("shallUseBitmap "+shallUseBitmap); + System.err.println("manualTest "+manualTest); + + org.junit.runner.JUnitCore.main(TestGearsES2GLJPanelAWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelsAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelsAWT.java new file mode 100644 index 000000000..e48fc783e --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelsAWT.java @@ -0,0 +1,422 @@ +/** + * 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.jogl.demos.es2.awt; + +import java.awt.AWTException; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Container; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.lang.reflect.InvocationTargetException; +import java.nio.FloatBuffer; + +import javax.media.opengl.GLAnimatorControl; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLJPanel; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.common.nio.Buffers; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.FPSAnimator; +import com.jogamp.opengl.util.awt.AWTGLPixelBuffer.SingleAWTGLPixelBufferProvider; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGearsES2GLJPanelsAWT extends UITestCase { + static int demoCount = 4; + static boolean jOpaque = false; // flicker-less w/o opaque, opaque leads to overdraw w/ mixed clipRects -> flicker - due to JComponent _paintImmediately(..) (?) + static boolean glOpaque = true; // can be either .. + static float glAlpha = 0.3f; + static boolean jZOrder = false; + static GLProfile glp; + static boolean shallUsePBuffer = false; + static boolean shallUseBitmap = false; + static boolean useMSAA = false; + static int swapInterval = 0; + static boolean useAnimator = true; + static boolean manualTest = false; + static boolean initSingleBuffer = false; + + /** + * Even though GLJPanel uses a SingleAWTGLPixelBufferProvider per default, + * we like to initialize it's size to a common maximum to ensure + * only one {@link AWTGLPixelBuffer} gets allocated. + */ + static SingleAWTGLPixelBufferProvider singleAWTGLPixelBufferProvider; + + @BeforeClass + public static void initClass() { + if(GLProfile.isAvailable(GLProfile.GL2)) { + glp = GLProfile.get(GLProfile.GL2); + Assert.assertNotNull(glp); + } else { + setTestSupported(false); + } + + if( initSingleBuffer ) { + singleAWTGLPixelBufferProvider = new SingleAWTGLPixelBufferProvider( glp.isGL2ES3() /* allowRowStride */); + singleAWTGLPixelBufferProvider.initSingleton(4, 600, 600, 1, true); + } else { + singleAWTGLPixelBufferProvider = null; + } + } + + @AfterClass + public static void releaseClass() { + } + + final static boolean useInterPanel = true; + + /** Adds new JPanel to frame's content pane at index 0 */ + private JComponent addPanel(GLCapabilitiesImmutable caps, GLAnimatorControl anim, final JFrame frame, boolean opaque, int x, int y, int w, int h, FloatBuffer color, float[] clearColor) + throws InterruptedException, InvocationTargetException + { + final GLJPanel canvas = new GLJPanel(caps); + if( initSingleBuffer ) { + canvas.setPixelBufferProvider( singleAWTGLPixelBufferProvider ); + } + canvas.setOpaque(opaque); + if ( !useInterPanel ) { + canvas.setBounds(x, y, w, h); + } + final GLEventListener demo; + if( caps.isBitmap() ) { + demo = new Gears(swapInterval); + } else { + GearsES2 gdemo = new GearsES2(swapInterval); + gdemo.setIgnoreFocus(true); + gdemo.setGearsColors(color, color, color); + gdemo.setClearColor(clearColor); + demo = gdemo; + } + canvas.addGLEventListener(demo); + if( null != anim ) { + anim.add(canvas); + } + + final JPanel panel; + final JTextField text; + if ( useInterPanel ) { + panel = new JPanel(new BorderLayout()); + panel.setBounds(x, y, w, h); + panel.setOpaque(opaque); + text = new JTextField(x+"/"+y+" "+w+"x"+h); + text.setOpaque(true); + } else { + panel = null; + text = null; + } + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + if ( useInterPanel ) { + panel.add(text, BorderLayout.NORTH); + panel.add(canvas, BorderLayout.CENTER); + frame.getContentPane().add(panel, 0); + } else { + frame.getContentPane().add(canvas, 0); + } + } } ) ; + return useInterPanel ? panel : canvas; + } + + public static final FloatBuffer red = Buffers.newDirectFloatBuffer( new float[] { 1.0f, 0.0f, 0.0f, 1.0f } ); + public static final FloatBuffer green = Buffers.newDirectFloatBuffer( new float[] { 0.0f, 1.0f, 0.0f, 1.0f } ); + public static final FloatBuffer blue = Buffers.newDirectFloatBuffer( new float[] { 0.0f, 0.0f, 1.0f, 1.0f } ); + public static final FloatBuffer yellow = Buffers.newDirectFloatBuffer( new float[] { 1.0f, 1.0f, 0.0f, 1.0f } ); + public static final FloatBuffer grey = Buffers.newDirectFloatBuffer( new float[] { 0.5f, 0.5f, 0.5f, 1.0f } ); + public static final float grayf = 0.3f; + public static final float[] redish = new float[] { grayf, 0.0f, 0.0f, glAlpha }; + public static final float[] greenish = new float[] { 0.0f, grayf, 0.0f, glAlpha }; + public static final float[] blueish = new float[] { 0.0f, 0.0f, grayf, glAlpha }; + public static final float[] yellowish = new float[] { grayf, grayf, 0.0f, glAlpha }; + public static final float[] greyish = new float[] { grayf, grayf, grayf, glAlpha }; + + protected void relayout(Container cont, float oW, float oH) { + final int count = cont.getComponentCount(); + final int nW = cont.getWidth(); + final int nH = cont.getHeight(); + for(int i = 0 ; i < count; i++ ) { + final Component comp = cont.getComponent(i); + float fx = comp.getX() / oW; + float fy = comp.getY() / oH; + float fw = comp.getWidth() / oW; + float fh = comp.getHeight() / oH; + comp.setBounds( (int)(fx * nW), (int)(fy * nH), (int)(fw * nW), (int)(fh * nH) ); + } + } + + protected void runTestGL(GLCapabilities caps) + throws AWTException, InterruptedException, InvocationTargetException + { + if( !glOpaque ) { + caps.setAlphaBits(caps.getRedBits()); + } + + final JFrame frame = new JFrame("Swing GLJPanel"); + Assert.assertNotNull(frame); + + final FPSAnimator animator = useAnimator ? new FPSAnimator(60) : null; + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.getContentPane().setLayout(null); + } } ); + + final float[] oldSize = new float[] { 600f, 600f }; + + frame.addComponentListener(new ComponentAdapter() { + @Override + public void componentResized(ComponentEvent e) { + final int count = frame.getComponentCount(); + for(int i = 0 ; i < count; i++ ) { + relayout(frame.getContentPane(), oldSize[0], oldSize[1]); + } + frame.getContentPane().invalidate(); + frame.getContentPane().validate(); + // frame.pack(); + oldSize[0] = frame.getContentPane().getWidth(); + oldSize[1] = frame.getContentPane().getHeight(); + } + } ) ; + + if( demoCount > 0 ) { + addPanel(caps, animator, frame, jOpaque, 50, 50, 300, 300, red, redish); // A + } + if( demoCount > 1 ) { + addPanel(caps, animator, frame, jOpaque, 0, 250, 300, 300, blue, blueish); // C + } + if( demoCount > 2 ) { + addPanel(caps, animator, frame, jOpaque, 300, 0, 150, 150, green, greenish); // B + } + if( demoCount > 3 ) { + addPanel(caps, animator, frame, jOpaque, 300, 300, 100, 100, yellow, yellowish); // D + } + if( jZOrder ) { + final Container cont = frame.getContentPane(); + final int count = cont.getComponentCount(); + for(int i = 0 ; i < count; i++ ) { + cont.setComponentZOrder(cont.getComponent(i), count - 1 - i); + } + } + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setSize((int)oldSize[0], (int)oldSize[1]); + frame.getContentPane().validate(); + // frame.pack(); + frame.setVisible(true); + } } ) ; + + if( useAnimator ) { + animator.setUpdateFPSFrames(60, System.err); + animator.start(); + Assert.assertEquals(true, animator.isAnimating()); + } + + QuitAdapter quitAdapter = new QuitAdapter(); + + final long t0 = System.currentTimeMillis(); + long t1 = t0; + while(!quitAdapter.shouldQuit() && t1 - t0 < duration) { + Thread.sleep(100); + t1 = System.currentTimeMillis(); + } + + Assert.assertNotNull(frame); + Assert.assertNotNull(animator); + + if( useAnimator ) { + animator.stop(); + Assert.assertEquals(false, animator.isAnimating()); + } + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + // frame.getContentPane().removeAll(); + // frame.removeAll(); + frame.dispose(); + } } ); + } + + @Test + public void test01_DefaultNorm() + throws AWTException, InterruptedException, InvocationTargetException + { + GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); + if(useMSAA) { + caps.setNumSamples(4); + caps.setSampleBuffers(true); + } + if(shallUsePBuffer) { + caps.setPBuffer(true); + } + if(shallUseBitmap) { + caps.setBitmap(true); + } + runTestGL(caps); + } + + @Test + public void test02_DefaultMsaa() + throws AWTException, InterruptedException, InvocationTargetException + { + if( manualTest ) { + return; + } + GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); + caps.setNumSamples(4); + caps.setSampleBuffers(true); + runTestGL(caps); + } + + @Test + public void test03_PbufferNorm() + throws AWTException, InterruptedException, InvocationTargetException + { + if( manualTest ) { + return; + } + GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); + caps.setPBuffer(true); + runTestGL(caps); + } + + @Test + public void test04_PbufferMsaa() + throws AWTException, InterruptedException, InvocationTargetException + { + if( manualTest ) { + return; + } + GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); + caps.setNumSamples(4); + caps.setSampleBuffers(true); + caps.setPBuffer(true); + runTestGL(caps); + } + + @Test + public void test05_BitmapNorm() + throws AWTException, InterruptedException, InvocationTargetException + { + if( manualTest ) { + return; + } + GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); + caps.setBitmap(true); + runTestGL(caps); + } + + @Test + public void test06_BitmapMsaa() + throws AWTException, InterruptedException, InvocationTargetException + { + if( manualTest ) { + return; + } + GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); + caps.setNumSamples(4); + caps.setSampleBuffers(true); + caps.setBitmap(true); + runTestGL(caps); + } + + static long duration = 500; // ms + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-vsync")) { + i++; + swapInterval = MiscUtils.atoi(args[i], swapInterval); + } else if(args[i].equals("-msaa")) { + useMSAA = true; + } else if(args[i].equals("-jOpaque")) { + i++; + jOpaque = MiscUtils.atob(args[i], jOpaque); + } else if(args[i].equals("-glOpaque")) { + i++; + glOpaque = MiscUtils.atob(args[i], glOpaque); + } else if(args[i].equals("-alpha")) { + i++; + glAlpha = MiscUtils.atof(args[i], glAlpha); + } else if(args[i].equals("-initSingleBuffer")) { + i++; + initSingleBuffer = MiscUtils.atob(args[i], initSingleBuffer); + } else if(args[i].equals("-jZOrder")) { + jZOrder = true; + } else if(args[i].equals("-noanim")) { + useAnimator = false; + } else if(args[i].equals("-pbuffer")) { + shallUsePBuffer = true; + } else if(args[i].equals("-bitmap")) { + shallUseBitmap = true; + } else if(args[i].equals("-manual")) { + manualTest = true; + } else if(args[i].equals("-demos")) { + i++; + demoCount = MiscUtils.atoi(args[i], demoCount); + } + } + System.err.println("swapInterval "+swapInterval); + System.err.println("opaque gl "+glOpaque+", java/gljpanel "+jOpaque); + System.err.println("alpha "+glAlpha); + System.err.println("jZOrder "+jZOrder); + System.err.println("demos "+demoCount); + System.err.println("useMSAA "+useMSAA); + System.err.println("useAnimator "+useAnimator); + System.err.println("shallUsePBuffer "+shallUsePBuffer); + System.err.println("shallUseBitmap "+shallUseBitmap); + System.err.println("manualTest "+manualTest); + System.err.println("useSingleBuffer "+initSingleBuffer); + + org.junit.runner.JUnitCore.main(TestGearsES2GLJPanelsAWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestElektronenMultipliziererNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestElektronenMultipliziererNEWT.java index ed308bdfd..6c4885308 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestElektronenMultipliziererNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestElektronenMultipliziererNEWT.java @@ -28,7 +28,6 @@ package com.jogamp.opengl.test.junit.jogl.demos.es2.newt; -import com.jogamp.common.os.Platform; import com.jogamp.newt.event.KeyAdapter; import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.event.TraceWindowAdapter; @@ -45,13 +44,15 @@ import javax.media.opengl.GLProfile; import org.junit.Assert; import org.junit.BeforeClass; -import org.junit.AfterClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; /** * @see com.jogamp.opengl.test.junit.jogl.demos.es2.ElektronenMultiplizierer * @author Dominik Ströhlein (DemoscenePassivist), et.al. */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestElektronenMultipliziererNEWT extends UITestCase { static final int width = 640, height = 480; @@ -69,8 +70,8 @@ public class TestElektronenMultipliziererNEWT extends UITestCase { @BeforeClass public static void initClass() { GLProfile glp = GLProfile.getDefault(); - if( ! ( glp.isHardwareRasterizer() && glp.isGL2GL3() ) ) { - // Sorry .. mobile is too slow for this one. + if( ! ( glp.isHardwareRasterizer() && glp.isGL2ES3() ) ) { + // Sorry .. mobile ES2 is too slow for this one. setTestSupported(false); return; } @@ -103,7 +104,10 @@ public class TestElektronenMultipliziererNEWT extends UITestCase { final GLWindow f_glWindow = glWindow; glWindow.addKeyListener(new KeyAdapter() { - public void keyTyped(KeyEvent e) { + public void keyReleased(KeyEvent e) { + if( !e.isPrintableKey() || e.isAutoRepeat() ) { + return; + } if(e.getKeyChar()=='f') { new Thread() { public void run() { 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 3fe0706c4..5d5b0c9a1 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 @@ -3,14 +3,14 @@ * * 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 @@ -20,40 +20,44 @@ * 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.jogl.demos.es2.newt; -import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStreamReader; +import java.net.URLConnection; +import com.jogamp.common.util.IOUtil; import com.jogamp.newt.Display; +import com.jogamp.newt.Display.PointerIcon; import com.jogamp.newt.NewtFactory; import com.jogamp.newt.Screen; +import com.jogamp.newt.Window; import com.jogamp.newt.event.KeyAdapter; import com.jogamp.newt.event.KeyEvent; +import com.jogamp.newt.event.MouseAdapter; +import com.jogamp.newt.event.MouseEvent; import com.jogamp.newt.event.WindowEvent; import com.jogamp.newt.event.WindowAdapter; import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.newt.util.EDTUtil; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; 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 com.jogamp.opengl.util.Animator; - +import com.jogamp.opengl.util.PNGPixelRect; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import javax.media.nativewindow.NativeWindowFactory; import javax.media.nativewindow.util.Dimension; import javax.media.nativewindow.util.Point; import javax.media.nativewindow.util.PointImmutable; import javax.media.nativewindow.util.DimensionImmutable; - import javax.media.opengl.GLAnimatorControl; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; @@ -61,18 +65,24 @@ import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; +import jogamp.newt.DefaultEDTUtil; + import org.junit.Assert; import org.junit.BeforeClass; import org.junit.AfterClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; -public class TestGearsES2NEWT extends UITestCase { +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGearsES2NEWT extends UITestCase { static int screenIdx = 0; static PointImmutable wpos; - static DimensionImmutable wsize; + static DimensionImmutable wsize, rwsize=null; static long duration = 500; // ms static boolean opaque = true; + static int forceAlpha = -1; static boolean undecorated = false; static boolean alwaysOnTop = false; static boolean fullscreen = false; @@ -81,15 +91,25 @@ public class TestGearsES2NEWT extends UITestCase { static boolean waitForKey = false; static boolean mouseVisible = true; static boolean mouseConfined = false; + static boolean setPointerIcon = false; static boolean showFPS = false; static int loops = 1; - static GLProfile.ShutdownType loop_shutdown = null; + static boolean loop_shutdown = false; static boolean forceES2 = false; - + static boolean forceES3 = false; + static boolean forceGL3 = false; + static boolean forceGL2 = false; + static boolean mainRun = false; + static boolean exclusiveContext = false; + static boolean useAnimator = true; + static boolean useMappedBuffers = false; + static enum SysExit { none, testExit, testError, testEDTError, displayExit, displayError, displayEDTError }; + static SysExit sysExit = SysExit.none; + @BeforeClass public static void initClass() { if(null == wsize) { - wsize = new Dimension(200, 200); + wsize = new Dimension(640, 480); } } @@ -116,7 +136,12 @@ public class TestGearsES2NEWT extends UITestCase { final GearsES2 demo = new GearsES2(swapInterval); demo.setPMVUseBackingArray(pmvUseBackingArray); + demo.setUseMappedBuffers(useMappedBuffers); + demo.setValidateBuffers(true); glWindow.addGLEventListener(demo); + + final SnapshotGLEventListener snap = new SnapshotGLEventListener(); + glWindow.addGLEventListener(snap); if(waitForKey) { glWindow.addGLEventListener(new GLEventListener() { public void init(GLAutoDrawable drawable) { } @@ -124,11 +149,7 @@ public class TestGearsES2NEWT extends UITestCase { public void display(GLAutoDrawable drawable) { GLAnimatorControl actrl = drawable.getAnimator(); if(waitForKey && actrl.getTotalFPSFrames() == 60*3) { - BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); - System.err.println("Press enter to continue"); - try { - System.err.println(stdin.readLine()); - } catch (IOException e) { } + UITestCase.waitForKey("3s mark"); actrl.resetFPSCounter(); waitForKey = false; } @@ -138,9 +159,13 @@ public class TestGearsES2NEWT extends UITestCase { }); } - Animator animator = new Animator(glWindow); - QuitAdapter quitAdapter = new QuitAdapter(); + final Animator animator = useAnimator ? new Animator() : null; + if( useAnimator ) { + animator.setModeBits(false, Animator.MODE_EXPECT_AWT_RENDERING_THREAD); + animator.setExclusiveContext(exclusiveContext); + } + final QuitAdapter quitAdapter = new QuitAdapter(); //glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter)); //glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter)); glWindow.addKeyListener(quitAdapter); @@ -152,121 +177,358 @@ public class TestGearsES2NEWT extends UITestCase { } public void windowMoved(WindowEvent e) { System.err.println("window moved: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()); - } + } }); - + + final PointerIcon[] pointerIcons = { null, null, null }; + { + final Display disp = glWindow.getScreen().getDisplay(); + disp.createNative(); + { + PointerIcon _pointerIcon = null; + final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "newt/data/cross-grey-alpha-16x16.png" } ); + try { + _pointerIcon = disp.createPointerIcon(res, 8, 8); + System.err.println("Create PointerIcon #01: "+_pointerIcon); + } catch (Exception e) { + e.printStackTrace(); + } + pointerIcons[0] = _pointerIcon; + } + { + PointerIcon _pointerIcon = null; + final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "newt/data/pointer-grey-alpha-16x24.png" } ); + try { + _pointerIcon = disp.createPointerIcon(res, 0, 0); + System.err.println("Create PointerIcon #02: "+_pointerIcon); + } catch (Exception e) { + e.printStackTrace(); + } + pointerIcons[1] = _pointerIcon; + } + { + PointerIcon _pointerIcon = null; + final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "jogamp-pointer-64x64.png" } ); + try { + final URLConnection urlConn = res.resolve(0); + final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(), null, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); + System.err.println("Create PointerIcon #03: "+image); + _pointerIcon = disp.createPointerIcon(image, 32, 0); + System.err.println("Create PointerIcon #03: "+_pointerIcon); + } catch (Exception e) { + e.printStackTrace(); + } + pointerIcons[2] = _pointerIcon; + } + } + if( setPointerIcon ) { + glWindow.setPointerIcon(pointerIcons[0]); + System.err.println("Set PointerIcon: "+glWindow.getPointerIcon()); + } + glWindow.addKeyListener(new KeyAdapter() { - public void keyTyped(KeyEvent e) { + int pointerIconIdx = 0; + + @Override + public void keyPressed(final KeyEvent e) { + if( e.isAutoRepeat() ) { + return; + } if(e.getKeyChar()=='f') { new Thread() { public void run() { + final Thread t = glWindow.setExclusiveContextThread(null); System.err.println("[set fullscreen pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets()); - glWindow.setFullscreen(!glWindow.isFullscreen()); + if( glWindow.isFullscreen() ) { + glWindow.setFullscreen( false ); + } else { + if( e.isAltDown() ) { + glWindow.setFullscreen( null ); + } else { + glWindow.setFullscreen( true ); + } + } System.err.println("[set fullscreen post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets()); + glWindow.setExclusiveContextThread(t); } }.start(); } else if(e.getKeyChar()=='a') { new Thread() { public void run() { + final Thread t = glWindow.setExclusiveContextThread(null); System.err.println("[set alwaysontop pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets()); glWindow.setAlwaysOnTop(!glWindow.isAlwaysOnTop()); System.err.println("[set alwaysontop post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets()); + glWindow.setExclusiveContextThread(t); } }.start(); } else if(e.getKeyChar()=='d') { new Thread() { public void run() { + final Thread t = glWindow.setExclusiveContextThread(null); + // while( null != glWindow.getExclusiveContextThread() ) ; System.err.println("[set undecorated pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", d "+glWindow.isUndecorated()+", "+glWindow.getInsets()); glWindow.setUndecorated(!glWindow.isUndecorated()); System.err.println("[set undecorated post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", d "+glWindow.isUndecorated()+", "+glWindow.getInsets()); + glWindow.setExclusiveContextThread(t); } }.start(); } else if(e.getKeyChar()=='s') { new Thread() { public void run() { + final Thread t = glWindow.setExclusiveContextThread(null); System.err.println("[set position pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", "+glWindow.getInsets()); glWindow.setPosition(100, 100); System.err.println("[set position post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", "+glWindow.getInsets()); + glWindow.setExclusiveContextThread(t); + } }.start(); + } else if(e.getKeyChar()=='c') { + new Thread() { + public void run() { + final Thread t = glWindow.setExclusiveContextThread(null); + System.err.println("[set pointer-icon pre]"); + final PointerIcon currentPI = glWindow.getPointerIcon(); + final PointerIcon newPI; + if( pointerIconIdx >= pointerIcons.length ) { + newPI=null; + pointerIconIdx=0; + } else { + newPI=pointerIcons[pointerIconIdx++]; + } + glWindow.setPointerIcon( newPI ); + System.err.println("[set pointer-icon post] "+currentPI+" -> "+glWindow.getPointerIcon()); + glWindow.setExclusiveContextThread(t); } }.start(); } else if(e.getKeyChar()=='i') { new Thread() { public void run() { + final Thread t = glWindow.setExclusiveContextThread(null); System.err.println("[set mouse visible pre]: "+glWindow.isPointerVisible()); glWindow.setPointerVisible(!glWindow.isPointerVisible()); System.err.println("[set mouse visible post]: "+glWindow.isPointerVisible()); + glWindow.setExclusiveContextThread(t); } }.start(); } else if(e.getKeyChar()=='j') { new Thread() { public void run() { + final Thread t = glWindow.setExclusiveContextThread(null); System.err.println("[set mouse confined pre]: "+glWindow.isPointerConfined()); glWindow.confinePointer(!glWindow.isPointerConfined()); System.err.println("[set mouse confined post]: "+glWindow.isPointerConfined()); if(!glWindow.isPointerConfined()) { demo.setConfinedFixedCenter(false); } + glWindow.setExclusiveContextThread(t); } }.start(); } else if(e.getKeyChar()=='J') { new Thread() { public void run() { + final Thread t = glWindow.setExclusiveContextThread(null); System.err.println("[set mouse confined pre]: "+glWindow.isPointerConfined()); glWindow.confinePointer(!glWindow.isPointerConfined()); System.err.println("[set mouse confined post]: "+glWindow.isPointerConfined()); demo.setConfinedFixedCenter(glWindow.isPointerConfined()); + glWindow.setExclusiveContextThread(t); } }.start(); } else if(e.getKeyChar()=='w') { new Thread() { public void run() { + final Thread t = glWindow.setExclusiveContextThread(null); System.err.println("[set mouse pos pre]"); glWindow.warpPointer(glWindow.getWidth()/2, glWindow.getHeight()/2); System.err.println("[set mouse pos post]"); + glWindow.setExclusiveContextThread(t); } }.start(); } } }); + glWindow.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + if(e.getClickCount() == 2 && e.getPointerCount() == 1) { + glWindow.setFullscreen(!glWindow.isFullscreen()); + System.err.println("setFullscreen: "+glWindow.isFullscreen()); + } + } + }); - animator.start(); - // glWindow.setSkipContextReleaseThread(animator.getThread()); + if( useAnimator ) { + animator.add(glWindow); + animator.start(); + Assert.assertTrue(animator.isStarted()); + Assert.assertTrue(animator.isAnimating()); + Assert.assertEquals(exclusiveContext ? animator.getThread() : null, glWindow.getExclusiveContextThread()); + } + + if( SysExit.displayError == sysExit || SysExit.displayExit == sysExit || SysExit.displayEDTError == sysExit ) { + glWindow.addGLEventListener(new GLEventListener() { + @Override + public void init(GLAutoDrawable drawable) {} + @Override + public void dispose(GLAutoDrawable drawable) { } + @Override + public void display(GLAutoDrawable drawable) { + final GLAnimatorControl anim = drawable.getAnimator(); + if( null != anim && anim.isAnimating() ) { + final long ms = anim.getTotalFPSDuration(); + if( ms >= duration/2 || ms >= 3000 ) { // max 3s wait until provoking error + if( SysExit.displayError == sysExit ) { + throw new Error("test error send from GLEventListener.display - "+Thread.currentThread()); + } else if ( SysExit.displayExit == sysExit ) { + System.err.println("exit(0) send from GLEventListener"); + System.exit(0); + } else if ( SysExit.displayEDTError == sysExit ) { + final Object upstream = drawable.getUpstreamWidget(); + System.err.println("EDT invokeAndWaitError: upstream type "+upstream.getClass().getName()); + if( upstream instanceof Window ) { + final EDTUtil edt = ((Window)upstream).getScreen().getDisplay().getEDTUtil(); + System.err.println("EDT invokeAndWaitError: edt type "+edt.getClass().getName()); + if( edt instanceof DefaultEDTUtil ) { + quitAdapter.doQuit(); + ((DefaultEDTUtil)edt).invokeAndWaitError(new Runnable() { + public void run() { + throw new RuntimeException("XXX Should never ever be seen! - "+Thread.currentThread()); + } + }); + } + } + } + } + } else { + System.exit(0); + } + } + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } + }); + } glWindow.setVisible(true); - + if( useAnimator ) { + animator.setUpdateFPSFrames(60, showFPS ? System.err : null); + } + System.err.println("NW chosen: "+glWindow.getDelegatedWindow().getChosenCapabilities()); System.err.println("GL chosen: "+glWindow.getChosenCapabilities()); System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", "+glWindow.getInsets()); - - animator.setUpdateFPSFrames(60, showFPS ? System.err : null); - - while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) { + + snap.setMakeSnapshot(); + + if( null != rwsize ) { + Thread.sleep(500); // 500ms delay + glWindow.setSize(rwsize.getWidth(), rwsize.getHeight()); + System.err.println("window resize pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", "+glWindow.getInsets()); + } + + snap.setMakeSnapshot(); + + final long t0 = System.currentTimeMillis(); + long t1 = t0; + while(!quitAdapter.shouldQuit() && t1-t0<duration) { Thread.sleep(100); + t1 = System.currentTimeMillis(); + if( SysExit.testError == sysExit || SysExit.testExit == sysExit || SysExit.testEDTError == sysExit) { + final long ms = t1-t0; + if( ms >= duration/2 || ms >= 3000 ) { // max 3s wait until provoking error + if( SysExit.testError == sysExit ) { + throw new Error("test error send from test thread"); + } else if ( SysExit.testExit == sysExit ) { + System.err.println("exit(0) send from test thread"); + System.exit(0); + } else if ( SysExit.testEDTError == sysExit ) { + final EDTUtil edt = glWindow.getScreen().getDisplay().getEDTUtil(); + System.err.println("EDT invokeAndWaitError: edt type "+edt.getClass().getName()); + if( edt instanceof DefaultEDTUtil ) { + quitAdapter.doQuit(); + ((DefaultEDTUtil)edt).invokeAndWaitError(new Runnable() { + public void run() { + throw new RuntimeException("XXX Should never ever be seen!"); + } + }); + } + } + } + } } - animator.stop(); - Assert.assertFalse(animator.isAnimating()); - Assert.assertFalse(animator.isStarted()); + if( useAnimator ) { + Assert.assertEquals(exclusiveContext ? animator.getThread() : null, glWindow.getExclusiveContextThread()); + animator.stop(); + Assert.assertFalse(animator.isAnimating()); + Assert.assertFalse(animator.isStarted()); + } + Assert.assertEquals(null, glWindow.getExclusiveContextThread()); glWindow.destroy(); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false)); + if( NativeWindowFactory.isAWTAvailable() ) { + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false)); + } } @Test - public void test01GL2ES2() throws InterruptedException { + public void test01_GL2ES2() throws InterruptedException { for(int i=1; i<=loops; i++) { System.err.println("Loop "+i+"/"+loops); - GLCapabilities caps = new GLCapabilities(forceES2 ? GLProfile.get(GLProfile.GLES2) : GLProfile.getGL2ES2()); + final GLProfile glp; + if(forceGL3) { + glp = GLProfile.get(GLProfile.GL3); + } else if(forceES3) { + glp = GLProfile.get(GLProfile.GLES3); + } else if(forceES2) { + glp = GLProfile.get(GLProfile.GLES2); + } else if(forceGL2) { + glp = GLProfile.get(GLProfile.GL2); + } else { + glp = GLProfile.getGL2ES2(); + } + final GLCapabilities caps = new GLCapabilities( glp ); caps.setBackgroundOpaque(opaque); + if(-1 < forceAlpha) { + caps.setAlphaBits(forceAlpha); + } runTestGL(caps, undecorated); - if(null != loop_shutdown) { - GLProfile.shutdown(loop_shutdown); + if(loop_shutdown) { + GLProfile.shutdown(); } } } - public static void main(String args[]) throws IOException { - int x=0, y=0, w=200, h=200; - boolean useSize = false; + @Test + public void test02_GLES2() throws InterruptedException { + if(mainRun) return; + + if( !GLProfile.isAvailable(GLProfile.GLES2) ) { + System.err.println("GLES2 n/a"); + return; + } + final GLProfile glp = GLProfile.get(GLProfile.GLES2); + final GLCapabilities caps = new GLCapabilities( glp ); + runTestGL(caps, undecorated); + } + + @Test + public void test03_GL3() throws InterruptedException { + if(mainRun) return; + + if( !GLProfile.isAvailable(GLProfile.GL3) ) { + System.err.println("GL3 n/a"); + return; + } + final GLProfile glp = GLProfile.get(GLProfile.GL3); + final GLCapabilities caps = new GLCapabilities( glp ); + runTestGL(caps, undecorated); + } + + public static void main(String args[]) throws IOException { + mainRun = true; + + int x=0, y=0, w=640, h=480, rw=-1, rh=-1; boolean usePos = false; - + for(int i=0; i<args.length; i++) { if(args[i].equals("-time")) { i++; duration = MiscUtils.atol(args[i], duration); } else if(args[i].equals("-translucent")) { opaque = false; + } else if(args[i].equals("-forceAlpha")) { + i++; + forceAlpha = MiscUtils.atoi(args[i], 0); } else if(args[i].equals("-undecorated")) { undecorated = true; } else if(args[i].equals("-atop")) { @@ -278,24 +540,36 @@ public class TestGearsES2NEWT extends UITestCase { } else if(args[i].equals("-vsync")) { i++; swapInterval = MiscUtils.atoi(args[i], swapInterval); + } else if(args[i].equals("-exclctx")) { + exclusiveContext = true; + } else if(args[i].equals("-noanim")) { + useAnimator = false; } else if(args[i].equals("-es2")) { forceES2 = true; + } else if(args[i].equals("-es3")) { + forceES3 = true; + } else if(args[i].equals("-gl3")) { + forceGL3 = true; + } else if(args[i].equals("-gl2")) { + forceGL2 = true; + } else if(args[i].equals("-mappedBuffers")) { + useMappedBuffers = true; } else if(args[i].equals("-wait")) { waitForKey = true; } else if(args[i].equals("-mouseInvisible")) { mouseVisible = false; } else if(args[i].equals("-mouseConfine")) { mouseConfined = true; + } else if(args[i].equals("-pointerIcon")) { + setPointerIcon = true; } else if(args[i].equals("-showFPS")) { showFPS = true; } else if(args[i].equals("-width")) { i++; w = MiscUtils.atoi(args[i], w); - useSize = true; } else if(args[i].equals("-height")) { i++; h = MiscUtils.atoi(args[i], h); - useSize = true; } else if(args[i].equals("-x")) { i++; x = MiscUtils.atoi(args[i], x); @@ -304,6 +578,12 @@ public class TestGearsES2NEWT extends UITestCase { i++; y = MiscUtils.atoi(args[i], y); usePos = true; + } else if(args[i].equals("-rwidth")) { + i++; + rw = MiscUtils.atoi(args[i], rw); + } else if(args[i].equals("-rheight")) { + i++; + rh = MiscUtils.atoi(args[i], rh); } else if(args[i].equals("-screen")) { i++; screenIdx = MiscUtils.atoi(args[i], 0); @@ -311,41 +591,47 @@ public class TestGearsES2NEWT extends UITestCase { i++; loops = MiscUtils.atoi(args[i], 1); } else if(args[i].equals("-loop-shutdown")) { + loop_shutdown = true; + } else if(args[i].equals("-sysExit")) { i++; - switch(MiscUtils.atoi(args[i], 0)) { - case 1: loop_shutdown = GLProfile.ShutdownType.SHARED_ONLY; break; - case 2: loop_shutdown = GLProfile.ShutdownType.COMPLETE; break; - default: throw new IllegalArgumentException("should be [0..2], 0-off, 1-shared, 2-complete"); - } + sysExit = SysExit.valueOf(args[i]); } } - if(useSize) { - wsize = new Dimension(w, h); + wsize = new Dimension(w, h); + if( 0 < rw && 0 < rh ) { + rwsize = new Dimension(rw, rh); } + if(usePos) { wpos = new Point(x, y); } System.err.println("position "+wpos); System.err.println("size "+wsize); + System.err.println("resize "+rwsize); System.err.println("screen "+screenIdx); System.err.println("translucent "+(!opaque)); + System.err.println("forceAlpha "+forceAlpha); System.err.println("undecorated "+undecorated); System.err.println("atop "+alwaysOnTop); System.err.println("fullscreen "+fullscreen); System.err.println("pmvDirect "+(!pmvUseBackingArray)); - System.err.println("swapInterval "+swapInterval); System.err.println("mouseVisible "+mouseVisible); System.err.println("mouseConfined "+mouseConfined); + System.err.println("pointerIcon "+setPointerIcon); System.err.println("loops "+loops); System.err.println("loop shutdown "+loop_shutdown); System.err.println("forceES2 "+forceES2); + System.err.println("forceES3 "+forceES3); + System.err.println("forceGL3 "+forceGL3); + System.err.println("forceGL2 "+forceGL2); + System.err.println("swapInterval "+swapInterval); + System.err.println("exclusiveContext "+exclusiveContext); + System.err.println("useAnimator "+useAnimator); + System.err.println("sysExitWithin "+sysExit); + System.err.println("mappedBuffers "+useMappedBuffers); 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) { } + UITestCase.waitForKey("Start"); } org.junit.runner.JUnitCore.main(TestGearsES2NEWT.class.getName()); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NewtCanvasAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NewtCanvasAWT.java new file mode 100644 index 000000000..5d091bb6d --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NewtCanvasAWT.java @@ -0,0 +1,467 @@ +/** + * Copyright 2011 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.jogl.demos.es2.newt; + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Component; +import java.awt.Container; +import java.awt.Frame; +import java.awt.TextArea; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +import com.jogamp.common.os.Platform; +import com.jogamp.newt.Display; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Screen; +import com.jogamp.newt.awt.NewtCanvasAWT; +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +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 com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.newt.parenting.NewtAWTReparentingKeyAdapter; + +import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.Point; +import javax.media.nativewindow.util.PointImmutable; +import javax.media.nativewindow.util.DimensionImmutable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLProfile; +import javax.swing.SwingUtilities; + +import org.junit.Assert; +import org.junit.Assume; +import org.junit.BeforeClass; +import org.junit.AfterClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGearsES2NewtCanvasAWT extends UITestCase { + public enum FrameLayout { None, TextOnBottom, BorderBottom, BorderBottom2, BorderCenter, BorderCenterSurrounded, DoubleBorderCenterSurrounded }; + public enum ResizeBy { GLWindow, Component, Frame }; + + static int screenIdx = 0; + static PointImmutable wpos; + static DimensionImmutable wsize, rwsize = null; + static FrameLayout frameLayout = FrameLayout.None; + static ResizeBy resizeBy = ResizeBy.Component; + + static long duration = 500; // ms + static boolean opaque = true; + static int forceAlpha = -1; + static boolean fullscreen = false; + static boolean pmvUseBackingArray = true; + static int swapInterval = 1; + static boolean showFPS = false; + static int loops = 1; + static boolean loop_shutdown = false; + static boolean shallUseOffscreenFBOLayer = false; + static boolean forceES2 = false; + static boolean forceGL3 = false; + static boolean mainRun = false; + static boolean exclusiveContext = false; + static boolean useAnimator = true; + + @BeforeClass + public static void initClass() { + if(null == wsize) { + wsize = new Dimension(640, 480); + } + } + + @AfterClass + public static void releaseClass() { + } + + static void setGLWindowSize(final Frame frame, final GLWindow glw, final DimensionImmutable new_sz) { + try { + glw.setSize(new_sz.getWidth(), new_sz.getHeight()); + if( null != frame ) { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.pack(); + } } ); + } + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + } + static void setComponentSize(final Frame frame, final Component comp, final DimensionImmutable new_sz) { + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + java.awt.Dimension d = new java.awt.Dimension(new_sz.getWidth(), new_sz.getHeight()); + comp.setMinimumSize(d); + comp.setPreferredSize(d); + comp.setSize(d); + if( null != frame ) { + frame.pack(); + } + } } ); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + } + static void setFrameSize(final Frame frame, final boolean frameLayout, final DimensionImmutable new_sz) { + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + java.awt.Dimension d = new java.awt.Dimension(new_sz.getWidth(), new_sz.getHeight()); + frame.setSize(d); + if( frameLayout ) { + frame.validate(); + } + } } ); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + } + + static void setSize(final ResizeBy resizeBy, final Frame frame, final boolean frameLayout, final Component comp, final GLWindow glw, final DimensionImmutable new_sz) { + switch( resizeBy ) { + case GLWindow: + setGLWindowSize(frameLayout ? frame : null, glw, new_sz); + break; + case Component: + setComponentSize(frameLayout ? frame : null, comp, new_sz); + break; + case Frame: + setFrameSize(frame, frameLayout, new_sz); + break; + } + } + + // public enum ResizeBy { GLWindow, Component, Frame }; + protected void runTestGL(final GLCapabilitiesImmutable caps, final ResizeBy resizeBy, final FrameLayout frameLayout) throws InterruptedException, InvocationTargetException { + 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); + + final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow); + if ( shallUseOffscreenFBOLayer ) { + newtCanvasAWT.setShallUseOffscreenLayer(true); + } + + final Frame frame = new Frame("AWT Parent Frame"); + + setSize(resizeBy, frame, false, newtCanvasAWT, glWindow, wsize); + + switch( frameLayout) { + case None: + frame.add(newtCanvasAWT); + break; + case TextOnBottom: + final TextArea ta = new TextArea(2, 20); + ta.append("0123456789"); + ta.append(Platform.getNewline()); + ta.append("Some Text"); + ta.append(Platform.getNewline()); + frame.setLayout(new BorderLayout()); + frame.add(ta, BorderLayout.SOUTH); + frame.add(newtCanvasAWT, BorderLayout.CENTER); + break; + case BorderBottom: + frame.setLayout(new BorderLayout()); + frame.add(newtCanvasAWT, BorderLayout.SOUTH); + break; + case BorderBottom2: + frame.setLayout(new BorderLayout()); + frame.add(newtCanvasAWT, BorderLayout.SOUTH); + frame.add(new Button("North"), BorderLayout.NORTH); + break; + case BorderCenter: + frame.setLayout(new BorderLayout()); + frame.add(newtCanvasAWT, BorderLayout.CENTER); + break; + case BorderCenterSurrounded: + frame.setLayout(new BorderLayout()); + frame.add(new Button("NORTH"), BorderLayout.NORTH); + frame.add(new Button("SOUTH"), BorderLayout.SOUTH); + frame.add(new Button("EAST"), BorderLayout.EAST); + frame.add(new Button("WEST"), BorderLayout.WEST); + frame.add(newtCanvasAWT, BorderLayout.CENTER); + break; + case DoubleBorderCenterSurrounded: + Container c = new Container(); + c.setLayout(new BorderLayout()); + c.add(new Button("north"), BorderLayout.NORTH); + c.add(new Button("south"), BorderLayout.SOUTH); + c.add(new Button("east"), BorderLayout.EAST); + c.add(new Button("west"), BorderLayout.WEST); + c.add(newtCanvasAWT, BorderLayout.CENTER); + + frame.setLayout(new BorderLayout()); + frame.add(new Button("NORTH"), BorderLayout.NORTH); + frame.add(new Button("SOUTH"), BorderLayout.SOUTH); + frame.add(new Button("EAST"), BorderLayout.EAST); + frame.add(new Button("WEST"), BorderLayout.WEST); + frame.add(c, BorderLayout.CENTER); + break; + } + + frame.setTitle("Gears NewtCanvasAWT Test (translucent "+!caps.isBackgroundOpaque()+"), swapInterval "+swapInterval+", size "+wsize+", pos "+wpos); + + final GearsES2 demo = new GearsES2(swapInterval); + demo.setPMVUseBackingArray(pmvUseBackingArray); + glWindow.addGLEventListener(demo); + + final Animator animator = useAnimator ? new Animator() : null; + if( useAnimator ) { + animator.setModeBits(false, Animator.MODE_EXPECT_AWT_RENDERING_THREAD); + animator.setExclusiveContext(exclusiveContext); + } + + final QuitAdapter quitAdapter = new QuitAdapter(); + //glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter)); + //glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter)); + glWindow.addKeyListener(quitAdapter); + glWindow.addWindowListener(quitAdapter); + + glWindow.addWindowListener(new WindowAdapter() { + public void windowResized(WindowEvent e) { + System.err.println("window resized: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()); + } + public void windowMoved(WindowEvent e) { + System.err.println("window moved: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()); + } + }); + + glWindow.addKeyListener(new NewtAWTReparentingKeyAdapter(frame, newtCanvasAWT, glWindow, quitAdapter)); + + if( useAnimator ) { + animator.add(glWindow); + animator.start(); + Assert.assertTrue(animator.isStarted()); + Assert.assertTrue(animator.isAnimating()); + Assert.assertEquals(exclusiveContext ? animator.getThread() : null, glWindow.getExclusiveContextThread()); + } + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + if( ResizeBy.Frame == resizeBy ) { + frame.validate(); + } else { + frame.pack(); + } + frame.setVisible(true); + } + }); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, true)); + + if( useAnimator ) { + animator.setUpdateFPSFrames(60, showFPS ? System.err : null); + } + + System.err.println("NW chosen: "+glWindow.getDelegatedWindow().getChosenCapabilities()); + System.err.println("GL chosen: "+glWindow.getChosenCapabilities()); + System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", "+glWindow.getInsets()); + + if( null != rwsize ) { + Thread.sleep(500); // 500ms delay + setSize(resizeBy, frame, true, newtCanvasAWT, glWindow, rwsize); + System.err.println("window resize "+rwsize+" -> pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", "+glWindow.getInsets()); + } + + final long t0 = System.currentTimeMillis(); + long t1 = t0; + while(!quitAdapter.shouldQuit() && t1-t0<duration) { + Thread.sleep(100); + t1 = System.currentTimeMillis(); + } + + if( useAnimator ) { + Assert.assertEquals(exclusiveContext ? animator.getThread() : null, glWindow.getExclusiveContextThread()); + animator.stop(); + Assert.assertFalse(animator.isAnimating()); + Assert.assertFalse(animator.isStarted()); + } + Assert.assertEquals(null, glWindow.getExclusiveContextThread()); + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.dispose(); + } + }); + glWindow.destroy(); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false)); + } + + @Test + public void test01GL2ES2() throws InterruptedException, InvocationTargetException { + for(int i=1; i<=loops; i++) { + System.err.println("Loop "+i+"/"+loops); + final GLProfile glp; + if(forceGL3) { + glp = GLProfile.get(GLProfile.GL3); + } else if(forceES2) { + glp = GLProfile.get(GLProfile.GLES2); + } else { + glp = GLProfile.getGL2ES2(); + } + final GLCapabilities caps = new GLCapabilities( glp ); + caps.setBackgroundOpaque(opaque); + if(-1 < forceAlpha) { + caps.setAlphaBits(forceAlpha); + } + runTestGL(caps, resizeBy, frameLayout); + if(loop_shutdown) { + GLProfile.shutdown(); + } + } + } + + @Test + public void test02GL3() throws InterruptedException, InvocationTargetException { + if(mainRun) return; + + if( !GLProfile.isAvailable(GLProfile.GL3) ) { + System.err.println("GL3 n/a"); + return; + } + final GLProfile glp = GLProfile.get(GLProfile.GL3); + final GLCapabilities caps = new GLCapabilities( glp ); + runTestGL(caps, resizeBy, frameLayout); + } + + public static void main(String args[]) throws IOException { + mainRun = true; + + int x=0, y=0, w=640, h=480; + int rw=-1, rh=-1; + boolean usePos = false; + + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-rwidth")) { + i++; + rw = MiscUtils.atoi(args[i], rw); + } else if(args[i].equals("-rheight")) { + i++; + rh = MiscUtils.atoi(args[i], rh); + } else if(args[i].equals("-layout")) { + i++; + frameLayout = FrameLayout.valueOf(args[i]); + } else if(args[i].equals("-resizeBy")) { + i++; + resizeBy = ResizeBy.valueOf(args[i]); + } else if(args[i].equals("-translucent")) { + opaque = false; + } else if(args[i].equals("-forceAlpha")) { + i++; + forceAlpha = MiscUtils.atoi(args[i], 0); + } else if(args[i].equals("-fullscreen")) { + fullscreen = true; + } else if(args[i].equals("-pmvDirect")) { + pmvUseBackingArray = false; + } else if(args[i].equals("-vsync")) { + i++; + swapInterval = MiscUtils.atoi(args[i], swapInterval); + } else if(args[i].equals("-layeredFBO")) { + shallUseOffscreenFBOLayer = true; + } else if(args[i].equals("-exclctx")) { + exclusiveContext = true; + } else if(args[i].equals("-noanim")) { + useAnimator = false; + } else if(args[i].equals("-es2")) { + forceES2 = true; + } else if(args[i].equals("-gl3")) { + forceGL3 = true; + } else if(args[i].equals("-showFPS")) { + showFPS = true; + } else if(args[i].equals("-width")) { + i++; + w = MiscUtils.atoi(args[i], w); + } else if(args[i].equals("-height")) { + i++; + h = MiscUtils.atoi(args[i], h); + } else if(args[i].equals("-x")) { + i++; + x = MiscUtils.atoi(args[i], x); + usePos = true; + } else if(args[i].equals("-y")) { + i++; + y = MiscUtils.atoi(args[i], y); + usePos = true; + } else if(args[i].equals("-screen")) { + i++; + screenIdx = MiscUtils.atoi(args[i], 0); + } else if(args[i].equals("-loops")) { + i++; + loops = MiscUtils.atoi(args[i], 1); + } else if(args[i].equals("-loop-shutdown")) { + loop_shutdown = true; + } + } + wsize = new Dimension(w, h); + if( 0 < rw && 0 < rh ) { + rwsize = new Dimension(rw, rh); + } + + if(usePos) { + wpos = new Point(x, y); + } + + System.err.println("frameLayout "+frameLayout); + System.err.println("resizeBy "+resizeBy); + System.err.println("position "+wpos); + System.err.println("size "+wsize); + System.err.println("resize "+rwsize); + System.err.println("screen "+screenIdx); + System.err.println("translucent "+(!opaque)); + System.err.println("forceAlpha "+forceAlpha); + System.err.println("fullscreen "+fullscreen); + System.err.println("pmvDirect "+(!pmvUseBackingArray)); + System.err.println("loops "+loops); + System.err.println("loop shutdown "+loop_shutdown); + System.err.println("shallUseOffscreenFBOLayer "+shallUseOffscreenFBOLayer); + System.err.println("forceES2 "+forceES2); + System.err.println("forceGL3 "+forceGL3); + System.err.println("swapInterval "+swapInterval); + System.err.println("exclusiveContext "+exclusiveContext); + System.err.println("useAnimator "+useAnimator); + + org.junit.runner.JUnitCore.main(TestGearsES2NewtCanvasAWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NewtCanvasSWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NewtCanvasSWT.java new file mode 100644 index 000000000..9b2db6bcc --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NewtCanvasSWT.java @@ -0,0 +1,384 @@ +/** + * Copyright 2011 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.jogl.demos.es2.newt; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +import com.jogamp.nativewindow.swt.SWTAccessor; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.event.KeyAdapter; +import com.jogamp.newt.event.KeyEvent; +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.newt.swt.NewtCanvasSWT; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +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 com.jogamp.opengl.util.Animator; + +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; + +import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.Point; +import javax.media.nativewindow.util.PointImmutable; +import javax.media.nativewindow.util.DimensionImmutable; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLProfile; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.junit.After; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.AfterClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGearsES2NewtCanvasSWT extends UITestCase { + static int screenIdx = 0; + static PointImmutable wpos; + static DimensionImmutable wsize, rwsize = null; + + static long duration = 500; // ms + static boolean opaque = true; + static int forceAlpha = -1; + static boolean fullscreen = false; + static boolean pmvUseBackingArray = true; + static int swapInterval = 1; + static boolean showFPS = false; + static int loops = 1; + static boolean loop_shutdown = false; + static boolean forceES2 = false; + static boolean forceGL3 = false; + static boolean mainRun = false; + static boolean exclusiveContext = false; + + @BeforeClass + public static void initClass() { + if(null == wsize) { + wsize = new Dimension(640, 480); + } + } + + @AfterClass + public static void releaseClass() { + } + + Display display = null; + Shell shell = null; + Composite composite = null; + com.jogamp.newt.Display swtNewtDisplay = null; + + @Before + public void init() { + SWTAccessor.invoke(true, new Runnable() { + public void run() { + display = new Display(); + Assert.assertNotNull( display ); + }}); + display.syncExec(new Runnable() { + public void run() { + shell = new Shell( display ); + Assert.assertNotNull( shell ); + shell.setLayout( new FillLayout() ); + composite = new Composite( shell, SWT.NONE ); + composite.setLayout( new FillLayout() ); + Assert.assertNotNull( composite ); + }}); + swtNewtDisplay = NewtFactory.createDisplay(null, false); // no-reuse + } + + @After + public void release() { + Assert.assertNotNull( display ); + Assert.assertNotNull( shell ); + Assert.assertNotNull( composite ); + try { + display.syncExec(new Runnable() { + public void run() { + composite.dispose(); + shell.dispose(); + }}); + SWTAccessor.invoke(true, new Runnable() { + public void run() { + display.dispose(); + }}); + } + catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + swtNewtDisplay = null; + display = null; + shell = null; + composite = null; + } + + protected void runTestGL(GLCapabilitiesImmutable caps) throws InterruptedException, InvocationTargetException { + System.err.println("requested: vsync "+swapInterval+", "+caps); + com.jogamp.newt.Screen screen = NewtFactory.createScreen(swtNewtDisplay, screenIdx); + final GLWindow glWindow = GLWindow.create(screen, caps); + Assert.assertNotNull(glWindow); + + final GearsES2 demo = new GearsES2(swapInterval); + demo.setPMVUseBackingArray(pmvUseBackingArray); + glWindow.addGLEventListener(demo); + + Animator animator = new Animator(); + animator.setModeBits(false, Animator.MODE_EXPECT_AWT_RENDERING_THREAD); + animator.setExclusiveContext(exclusiveContext); + + QuitAdapter quitAdapter = new QuitAdapter(); + //glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter)); + //glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter)); + glWindow.addKeyListener(quitAdapter); + glWindow.addWindowListener(quitAdapter); + + glWindow.addWindowListener(new WindowAdapter() { + public void windowResized(WindowEvent e) { + System.err.println("window resized: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()); + } + public void windowMoved(WindowEvent e) { + System.err.println("window moved: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()); + } + }); + + glWindow.addKeyListener(new KeyAdapter() { + public void keyReleased(KeyEvent e) { + if( !e.isPrintableKey() || e.isAutoRepeat() ) { + return; + } + if(e.getKeyChar()=='f') { + new Thread() { + public void run() { + final Thread t = glWindow.setExclusiveContextThread(null); + System.err.println("[set fullscreen pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets()); + glWindow.setFullscreen(!glWindow.isFullscreen()); + System.err.println("[set fullscreen post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets()); + glWindow.setExclusiveContextThread(t); + } }.start(); + } + } + }); + + animator.add(glWindow); + animator.start(); + Assert.assertTrue(animator.isStarted()); + Assert.assertTrue(animator.isAnimating()); + Assert.assertEquals(exclusiveContext ? animator.getThread() : null, glWindow.getExclusiveContextThread()); + + final NewtCanvasSWT canvas1 = NewtCanvasSWT.create( composite, 0, glWindow ); + Assert.assertNotNull( canvas1 ); + + display.syncExec( new Runnable() { + public void run() { + shell.setText( getSimpleTestName(".") ); + shell.setSize( wsize.getWidth(), wsize.getHeight() ); + if( null != wpos ) { + shell.setLocation( wpos.getX(), wpos.getY() ); + } + shell.open(); + } + }); + + animator.setUpdateFPSFrames(60, showFPS ? System.err : null); + + System.err.println("NW chosen: "+glWindow.getDelegatedWindow().getChosenCapabilities()); + System.err.println("GL chosen: "+glWindow.getChosenCapabilities()); + System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", "+glWindow.getInsets()); + + if( null != rwsize ) { + for(int i=0; i<50; i++) { // 500 ms dispatched delay + if( !display.readAndDispatch() ) { + // blocks on linux .. display.sleep(); + Thread.sleep(10); + } + } + display.syncExec( new Runnable() { + public void run() { + shell.setSize( rwsize.getWidth(), rwsize.getHeight() ); + } + }); + System.err.println("window resize pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", "+glWindow.getInsets()); + } + + while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) { + if( !display.readAndDispatch() ) { + // blocks on linux .. display.sleep(); + Thread.sleep(10); + } + } + + Assert.assertEquals(exclusiveContext ? animator.getThread() : null, glWindow.getExclusiveContextThread()); + animator.stop(); + Assert.assertFalse(animator.isAnimating()); + Assert.assertFalse(animator.isStarted()); + Assert.assertEquals(null, glWindow.getExclusiveContextThread()); + + canvas1.dispose(); + glWindow.destroy(); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false)); + } + + @Test + public void test01GL2ES2() throws InterruptedException, InvocationTargetException { + for(int i=1; i<=loops; i++) { + System.err.println("Loop "+i+"/"+loops); + final GLProfile glp; + if(forceGL3) { + glp = GLProfile.get(GLProfile.GL3); + } else if(forceES2) { + glp = GLProfile.get(GLProfile.GLES2); + } else { + glp = GLProfile.getGL2ES2(); + } + final GLCapabilities caps = new GLCapabilities( glp ); + caps.setBackgroundOpaque(opaque); + if(-1 < forceAlpha) { + caps.setAlphaBits(forceAlpha); + } + runTestGL(caps); + if(loop_shutdown) { + GLProfile.shutdown(); + } + } + } + + @Test + public void test02GL3() throws InterruptedException, InvocationTargetException { + if(mainRun) return; + + if( !GLProfile.isAvailable(GLProfile.GL3) ) { + System.err.println("GL3 n/a"); + return; + } + final GLProfile glp = GLProfile.get(GLProfile.GL3); + final GLCapabilities caps = new GLCapabilities( glp ); + runTestGL(caps); + } + + public static void main(String args[]) throws IOException { + mainRun = true; + + int x=0, y=0, w=640, h=480, rw=-1, rh=-1; + boolean usePos = false; + + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-translucent")) { + opaque = false; + } else if(args[i].equals("-forceAlpha")) { + i++; + forceAlpha = MiscUtils.atoi(args[i], 0); + } else if(args[i].equals("-fullscreen")) { + fullscreen = true; + } else if(args[i].equals("-pmvDirect")) { + pmvUseBackingArray = false; + } else if(args[i].equals("-vsync")) { + i++; + swapInterval = MiscUtils.atoi(args[i], swapInterval); + } else if(args[i].equals("-exclctx")) { + exclusiveContext = true; + } else if(args[i].equals("-es2")) { + forceES2 = true; + } else if(args[i].equals("-gl3")) { + forceGL3 = true; + } else if(args[i].equals("-showFPS")) { + showFPS = true; + } else if(args[i].equals("-width")) { + i++; + w = MiscUtils.atoi(args[i], w); + } else if(args[i].equals("-height")) { + i++; + h = MiscUtils.atoi(args[i], h); + } else if(args[i].equals("-x")) { + i++; + x = MiscUtils.atoi(args[i], x); + usePos = true; + } else if(args[i].equals("-y")) { + i++; + y = MiscUtils.atoi(args[i], y); + usePos = true; + } else if(args[i].equals("-rwidth")) { + i++; + rw = MiscUtils.atoi(args[i], rw); + } else if(args[i].equals("-rheight")) { + i++; + rh = MiscUtils.atoi(args[i], rh); + } else if(args[i].equals("-screen")) { + i++; + screenIdx = MiscUtils.atoi(args[i], 0); + } else if(args[i].equals("-loops")) { + i++; + loops = MiscUtils.atoi(args[i], 1); + } else if(args[i].equals("-loop-shutdown")) { + loop_shutdown = true; + } + } + wsize = new Dimension(w, h); + if( 0 < rw && 0 < rh ) { + rwsize = new Dimension(rw, rh); + } + + if(usePos) { + wpos = new Point(x, y); + } + System.err.println("position "+wpos); + System.err.println("size "+wsize); + System.err.println("resize "+rwsize); + System.err.println("screen "+screenIdx); + System.err.println("translucent "+(!opaque)); + System.err.println("forceAlpha "+forceAlpha); + System.err.println("fullscreen "+fullscreen); + System.err.println("pmvDirect "+(!pmvUseBackingArray)); + System.err.println("loops "+loops); + System.err.println("loop shutdown "+loop_shutdown); + System.err.println("forceES2 "+forceES2); + System.err.println("forceGL3 "+forceGL3); + System.err.println("swapInterval "+swapInterval); + System.err.println("exclusiveContext "+exclusiveContext); + + org.junit.runner.JUnitCore.main(TestGearsES2NewtCanvasSWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestLandscapeES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestLandscapeES2NEWT.java new file mode 100644 index 000000000..50a5de1f9 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestLandscapeES2NEWT.java @@ -0,0 +1,181 @@ +/** + * Copyright 2011 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.jogl.demos.es2.newt; + +import com.jogamp.newt.event.KeyAdapter; +import com.jogamp.newt.event.KeyEvent; +import com.jogamp.newt.opengl.GLWindow; +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 com.jogamp.opengl.util.Animator; + +import com.jogamp.opengl.test.junit.jogl.demos.es2.LandscapeES2; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; + +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestLandscapeES2NEWT extends UITestCase { + static int width = 500, height = 290; + static int swapInterval = 1; + static boolean forceES2 = false; + static boolean forceGL3 = false; + static boolean mainRun = false; + static boolean exclusiveContext = false; + static boolean useAnimator = true; + + protected void runTestGL(GLCapabilities caps) throws InterruptedException { + System.err.println("requested: swapInterval "+swapInterval+", "+caps); + final GLWindow glWindow = GLWindow.create(caps); + glWindow.setTitle(getSimpleTestName(".")); + glWindow.setSize(width, height); + + final LandscapeES2 demo = new LandscapeES2(swapInterval); + glWindow.addGLEventListener(demo); + + final SnapshotGLEventListener snap = new SnapshotGLEventListener(); + snap.setPostSNDetail(demo.getClass().getSimpleName()); + glWindow.addGLEventListener(snap); + + final Animator animator = useAnimator ? new Animator() : null; + if( useAnimator ) { + animator.setModeBits(false, Animator.MODE_EXPECT_AWT_RENDERING_THREAD); + animator.setExclusiveContext(exclusiveContext); + } + + QuitAdapter quitAdapter = new QuitAdapter(); + + //glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter)); + //glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter)); + glWindow.addKeyListener(quitAdapter); + glWindow.addWindowListener(quitAdapter); + + glWindow.addKeyListener(new KeyAdapter() { + public void keyReleased(KeyEvent e) { + if( !e.isPrintableKey() || e.isAutoRepeat() ) { + return; + } + if(e.getKeyChar()=='f') { + new Thread() { + public void run() { + glWindow.setFullscreen(!glWindow.isFullscreen()); + } }.start(); + } else if(e.getKeyChar()=='d') { + new Thread() { + public void run() { + glWindow.setUndecorated(!glWindow.isUndecorated()); + } }.start(); + } + } + }); + + if( useAnimator ) { + animator.add(glWindow); + animator.start(); + } + glWindow.setVisible(true); + if( useAnimator ) { + animator.setUpdateFPSFrames(60, System.err); + } + + System.err.println("NW chosen: "+glWindow.getDelegatedWindow().getChosenCapabilities()); + System.err.println("GL chosen: "+glWindow.getChosenCapabilities()); + System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", "+glWindow.getInsets()); + + snap.setMakeSnapshot(); + + while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) { + Thread.sleep(100); + } + + if( useAnimator ) { + animator.stop(); + } + glWindow.destroy(); + } + + @Test + public void test01GL2ES2() throws InterruptedException { + final GLProfile glp; + if(forceGL3) { + glp = GLProfile.get(GLProfile.GL3); + } else if(forceES2) { + glp = GLProfile.get(GLProfile.GLES2); + } else { + glp = GLProfile.getGL2ES2(); + } + final GLCapabilities caps = new GLCapabilities(glp); + runTestGL(caps); + } + + @Test + public void test02GL3() throws InterruptedException { + if(mainRun) return; + + if( !GLProfile.isAvailable(GLProfile.GL3) ) { + System.err.println("GL3 n/a"); + return; + } + final GLProfile glp = GLProfile.get(GLProfile.GL3); + final GLCapabilities caps = new GLCapabilities( glp ); + runTestGL(caps); + } + + static long duration = 500; // ms + + public static void main(String args[]) { + mainRun = true; + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-vsync")) { + i++; + swapInterval = MiscUtils.atoi(args[i], swapInterval); + } else if(args[i].equals("-exclctx")) { + exclusiveContext = true; + } else if(args[i].equals("-noanim")) { + useAnimator = false; + } else if(args[i].equals("-es2")) { + forceES2 = true; + } else if(args[i].equals("-gl3")) { + forceGL3 = true; + } + } + System.err.println("forceES2 "+forceES2); + System.err.println("forceGL3 "+forceGL3); + org.junit.runner.JUnitCore.main(TestLandscapeES2NEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestLandscapeES2NewtCanvasAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestLandscapeES2NewtCanvasAWT.java new file mode 100644 index 000000000..adc2b23ae --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestLandscapeES2NewtCanvasAWT.java @@ -0,0 +1,217 @@ +/** + * Copyright 2013 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.jogl.demos.es2.newt; + +import java.awt.Frame; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +import com.jogamp.newt.Display; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Screen; +import com.jogamp.newt.awt.NewtCanvasAWT; +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.opengl.GLWindow; +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 com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.test.junit.jogl.demos.es2.LandscapeES2; +import com.jogamp.opengl.test.junit.newt.parenting.NewtAWTReparentingKeyAdapter; + +import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.DimensionImmutable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLProfile; +import javax.swing.SwingUtilities; + +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestLandscapeES2NewtCanvasAWT extends UITestCase { + static DimensionImmutable wsize = new Dimension(500, 290); + + static long duration = 500; // ms + static int swapInterval = 1; + static boolean shallUseOffscreenFBOLayer = false; + static boolean forceES2 = false; + static boolean forceGL3 = false; + static boolean mainRun = false; + static boolean exclusiveContext = false; + static boolean useAnimator = true; + + // public enum ResizeBy { GLWindow, Component, Frame }; + protected void runTestGL(final GLCapabilitiesImmutable caps) throws InterruptedException, InvocationTargetException { + System.err.println("requested: vsync "+swapInterval+", "+caps); + Display dpy = NewtFactory.createDisplay(null); + Screen screen = NewtFactory.createScreen(dpy, 0); + final GLWindow glWindow = GLWindow.create(screen, caps); + + final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow); + if ( shallUseOffscreenFBOLayer ) { + newtCanvasAWT.setShallUseOffscreenLayer(true); + } + + final Frame frame = new Frame("AWT Parent Frame"); + { + java.awt.Dimension d = new java.awt.Dimension(wsize.getWidth(), wsize.getHeight()); + frame.setSize(d); + } + frame.add(newtCanvasAWT); + frame.setTitle("Gears NewtCanvasAWT Test (translucent "+!caps.isBackgroundOpaque()+"), swapInterval "+swapInterval+", size "+wsize); + + final LandscapeES2 demo = new LandscapeES2(swapInterval); + glWindow.addGLEventListener(demo); + + final Animator animator = useAnimator ? new Animator() : null; + if( useAnimator ) { + animator.setModeBits(false, Animator.MODE_EXPECT_AWT_RENDERING_THREAD); + animator.setExclusiveContext(exclusiveContext); + } + + final QuitAdapter quitAdapter = new QuitAdapter(); + //glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter)); + //glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter)); + glWindow.addKeyListener(quitAdapter); + glWindow.addWindowListener(quitAdapter); + + glWindow.addWindowListener(new WindowAdapter() { + public void windowResized(WindowEvent e) { + System.err.println("window resized: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()); + } + public void windowMoved(WindowEvent e) { + System.err.println("window moved: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()); + } + }); + + glWindow.addKeyListener(new NewtAWTReparentingKeyAdapter(frame, newtCanvasAWT, glWindow, quitAdapter)); + + if( useAnimator ) { + animator.add(glWindow); + animator.start(); + } + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.validate(); + frame.setVisible(true); + } + }); + + if( useAnimator ) { + animator.setUpdateFPSFrames(60, System.err); + } + + System.err.println("NW chosen: "+glWindow.getDelegatedWindow().getChosenCapabilities()); + System.err.println("GL chosen: "+glWindow.getChosenCapabilities()); + System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", "+glWindow.getInsets()); + + final long t0 = System.currentTimeMillis(); + long t1 = t0; + while(!quitAdapter.shouldQuit() && t1-t0<duration) { + Thread.sleep(100); + t1 = System.currentTimeMillis(); + } + + if( useAnimator ) { + animator.stop(); + } + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.dispose(); + } + }); + glWindow.destroy(); + } + + @Test + public void test01GL2ES2() throws InterruptedException, InvocationTargetException { + final GLProfile glp; + if(forceGL3) { + glp = GLProfile.get(GLProfile.GL3); + } else if(forceES2) { + glp = GLProfile.get(GLProfile.GLES2); + } else { + glp = GLProfile.getGL2ES2(); + } + final GLCapabilities caps = new GLCapabilities( glp ); + runTestGL(caps); + } + + @Test + public void test02GL3() throws InterruptedException, InvocationTargetException { + if(mainRun) return; + + if( !GLProfile.isAvailable(GLProfile.GL3) ) { + System.err.println("GL3 n/a"); + return; + } + final GLProfile glp = GLProfile.get(GLProfile.GL3); + final GLCapabilities caps = new GLCapabilities( glp ); + runTestGL(caps); + } + + public static void main(String args[]) throws IOException { + mainRun = true; + + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-vsync")) { + i++; + swapInterval = MiscUtils.atoi(args[i], swapInterval); + } else if(args[i].equals("-layeredFBO")) { + shallUseOffscreenFBOLayer = true; + } else if(args[i].equals("-exclctx")) { + exclusiveContext = true; + } else if(args[i].equals("-noanim")) { + useAnimator = false; + } else if(args[i].equals("-es2")) { + forceES2 = true; + } else if(args[i].equals("-gl3")) { + forceGL3 = true; + } + } + + System.err.println("size "+wsize); + System.err.println("shallUseOffscreenFBOLayer "+shallUseOffscreenFBOLayer); + System.err.println("forceES2 "+forceES2); + System.err.println("forceGL3 "+forceGL3); + System.err.println("swapInterval "+swapInterval); + System.err.println("exclusiveContext "+exclusiveContext); + System.err.println("useAnimator "+useAnimator); + + org.junit.runner.JUnitCore.main(TestLandscapeES2NewtCanvasAWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestRedSquareES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestRedSquareES2NEWT.java index 74d52c352..6300bbd68 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestRedSquareES2NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestRedSquareES2NEWT.java @@ -3,14 +3,14 @@ * * 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 @@ -20,12 +20,12 @@ * 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.jogl.demos.es2.newt; import com.jogamp.newt.event.KeyAdapter; @@ -35,25 +35,33 @@ import com.jogamp.opengl.test.junit.util.AWTRobotUtil; 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 com.jogamp.opengl.util.Animator; - import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareMappedES2; +import javax.media.nativewindow.NativeWindowFactory; import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.AfterClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestRedSquareES2NEWT extends UITestCase { static int width, height; static int loops = 1; - static GLProfile.ShutdownType loop_shutdown = null; + static boolean loop_shutdown = false; static boolean vsync = false; static boolean forceES2 = false; + static boolean forceGL3 = false; + static boolean mainRun = false; + static boolean doRotate = true; + static boolean useMappedBuffers = false; @BeforeClass public static void initClass() { @@ -67,12 +75,26 @@ public class TestRedSquareES2NEWT extends UITestCase { protected void runTestGL(GLCapabilities caps) throws InterruptedException { System.err.println("requested: vsync "+vsync+", "+caps); - GLWindow glWindow = GLWindow.create(caps); + final GLWindow glWindow = GLWindow.create(caps); Assert.assertNotNull(glWindow); - glWindow.setTitle("Gears NEWT Test"); + glWindow.setTitle(getSimpleTestName(".")); glWindow.setSize(width, height); - glWindow.addGLEventListener(new RedSquareES2(vsync ? 1 : -1)); + final GLEventListener demo; + if( useMappedBuffers ) { + final RedSquareMappedES2 red = new RedSquareMappedES2(vsync ? 1 : -1); + red.setDoRotation(doRotate); + demo = red; + } else { + final RedSquareES2 red = new RedSquareES2(vsync ? 1 : -1); + red.setDoRotation(doRotate); + demo = red; + } + glWindow.addGLEventListener(demo); + + final SnapshotGLEventListener snap = new SnapshotGLEventListener(); + snap.setPostSNDetail(demo.getClass().getSimpleName()); + glWindow.addGLEventListener(snap); Animator animator = new Animator(glWindow); QuitAdapter quitAdapter = new QuitAdapter(); @@ -82,33 +104,36 @@ public class TestRedSquareES2NEWT extends UITestCase { glWindow.addKeyListener(quitAdapter); glWindow.addWindowListener(quitAdapter); - final GLWindow f_glWindow = glWindow; glWindow.addKeyListener(new KeyAdapter() { - public void keyTyped(KeyEvent e) { + public void keyReleased(KeyEvent e) { + if( !e.isPrintableKey() || e.isAutoRepeat() ) { + return; + } if(e.getKeyChar()=='f') { new Thread() { public void run() { - f_glWindow.setFullscreen(!f_glWindow.isFullscreen()); + glWindow.setFullscreen(!glWindow.isFullscreen()); } }.start(); } else if(e.getKeyChar()=='d') { new Thread() { public void run() { - f_glWindow.setUndecorated(!f_glWindow.isUndecorated()); + glWindow.setUndecorated(!glWindow.isUndecorated()); } }.start(); } } }); animator.start(); - + glWindow.setVisible(true); System.err.println("NW chosen: "+glWindow.getDelegatedWindow().getChosenCapabilities()); System.err.println("GL chosen: "+glWindow.getChosenCapabilities()); System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", "+glWindow.getInsets()); - + animator.setUpdateFPSFrames(60, System.err); - + snap.setMakeSnapshot(); + while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) { Thread.sleep(100); } @@ -117,47 +142,72 @@ public class TestRedSquareES2NEWT extends UITestCase { Assert.assertFalse(animator.isAnimating()); Assert.assertFalse(animator.isStarted()); glWindow.destroy(); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false)); + if( NativeWindowFactory.isAWTAvailable() ) { + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false)); + } } @Test public void test01GL2ES2() throws InterruptedException { for(int i=1; i<=loops; i++) { System.err.println("Loop "+i+"/"+loops); - GLCapabilities caps = new GLCapabilities(forceES2 ? GLProfile.get(GLProfile.GLES2) : GLProfile.getGL2ES2()); + final GLProfile glp; + if(forceGL3) { + glp = GLProfile.get(GLProfile.GL3); + } else if(forceES2) { + glp = GLProfile.get(GLProfile.GLES2); + } else { + glp = GLProfile.getGL2ES2(); + } + final GLCapabilities caps = new GLCapabilities(glp); runTestGL(caps); - if(null != loop_shutdown) { - GLProfile.shutdown(loop_shutdown); + if(loop_shutdown) { + GLProfile.shutdown(); } } } + @Test + public void test02GL3() throws InterruptedException { + if(mainRun) return; + + if( !GLProfile.isAvailable(GLProfile.GL3) ) { + System.err.println("GL3 n/a"); + return; + } + final GLProfile glp = GLProfile.get(GLProfile.GL3); + final GLCapabilities caps = new GLCapabilities( glp ); + runTestGL(caps); + } + static long duration = 500; // ms public static void main(String args[]) { + mainRun = true; for(int i=0; i<args.length; i++) { if(args[i].equals("-time")) { i++; - try { - duration = Integer.parseInt(args[i]); - } catch (Exception ex) { ex.printStackTrace(); } + duration = MiscUtils.atol(args[i], duration); } else if(args[i].equals("-es2")) { forceES2 = true; + } else if(args[i].equals("-gl3")) { + forceGL3 = true; + } else if(args[i].equals("-norotate")) { + doRotate = false; + } else if(args[i].equals("-mappedBuffers")) { + useMappedBuffers = true; } else if(args[i].equals("-loops")) { i++; loops = MiscUtils.atoi(args[i], 1); } else if(args[i].equals("-loop-shutdown")) { - i++; - switch(MiscUtils.atoi(args[i], 0)) { - case 1: loop_shutdown = GLProfile.ShutdownType.SHARED_ONLY; break; - case 2: loop_shutdown = GLProfile.ShutdownType.COMPLETE; break; - default: throw new IllegalArgumentException("should be [0..2], 0-off, 1-shared, 2-complete"); - } + loop_shutdown = true; } } System.err.println("loops "+loops); System.err.println("loop shutdown "+loop_shutdown); System.err.println("forceES2 "+forceES2); + System.err.println("forceGL3 "+forceGL3); + System.err.println("mappedBuffers "+useMappedBuffers); org.junit.runner.JUnitCore.main(TestRedSquareES2NEWT.class.getName()); } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/PointsShader.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/PointsShader.fp new file mode 100644 index 000000000..3210762b1 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/PointsShader.fp @@ -0,0 +1,47 @@ + +#if __VERSION__ >= 130 + #define varying in + out vec4 mgl_FragColor; +#else + #define mgl_FragColor gl_FragColor +#endif + +// [0].rgba: 0, smooth, attnMinSz, attnMaxSz +// [1].rgba: attnCoeff(3), attnFadeTs +uniform vec4 mgl_PointParams[2]; + +#define pointSmooth (mgl_PointParams[0].g) + +varying vec4 frontColor; + +// #define TEST 1 + +void main (void) +{ + mgl_FragColor = frontColor; + + if( pointSmooth > 0.5 ) { + // smooth (AA) + const float border = 0.90; // take/give 10% for AA + + // origin to 0/0, [-1/-1 .. 1/1] + vec2 pointPos = 2.0 * gl_PointCoord - 1.0 ; + float r = length( pointPos ); // one-circle sqrt(x * x + y * y), range: in-circle [0..1], out >1 + float r1 = 1.0 - ( step(border, r) * 10.0 * ( r - border ) ) ; // [0..1] + #ifndef TEST + if( r1 < 0.0 ) { + discard; + } + #endif + + #ifndef TEST + mgl_FragColor.a *= r1; + #else + mgl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); + mgl_FragColor.r = r1 < 0.0 ? 1.0 : 0.0; + mgl_FragColor.g = r > 1.0 ? 1.0 : 0.0; + mgl_FragColor.b = r > border ? 1.0 : 0.0; + #endif + } +} + diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/PointsShader.vp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/PointsShader.vp new file mode 100644 index 000000000..4fa49b901 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/PointsShader.vp @@ -0,0 +1,47 @@ + +#if __VERSION__ >= 130 + #define attribute in + #define varying out +#endif + +uniform vec4 mgl_ColorStatic; +uniform mat4 mgl_PMVMatrix[4]; // P, Mv, Mvi and Mvit (transpose(inverse(ModelView)) == normalMatrix) + +// [0].rgba: 0, smooth, attnMinSz, attnMaxSz +// [1].rgba: attnCoeff(3), attnFadeTs +uniform vec4 mgl_PointParams[2]; + +#define pointSmooth (mgl_PointParams[0].g) +#define pointSizeMin (mgl_PointParams[0].b) +#define pointSizeMax (mgl_PointParams[0].a) +#define pointDistanceConstantAtten (mgl_PointParams[1].r) +#define pointDistanceLinearAtten (mgl_PointParams[1].g) +#define pointDistanceQuadraticAtten (mgl_PointParams[1].b) +#define pointFadeThresholdSize (mgl_PointParams[1].a) + +attribute vec4 mgl_Vertex; +attribute float mgl_PointSize; + +varying vec4 frontColor; + +void main(void) +{ + frontColor = mgl_ColorStatic; + + vec4 eyeCoord = mgl_PMVMatrix[1] * mgl_Vertex; + gl_Position = mgl_PMVMatrix[0] * eyeCoord; + + float dist = distance(eyeCoord, vec4(0.0, 0.0, 0.0, 1.0)); + float atten = sqrt( 1.0 / ( pointDistanceConstantAtten + + ( pointDistanceLinearAtten + + pointDistanceQuadraticAtten * dist + ) * dist + ) + ); + float size = clamp(mgl_PointSize * atten, pointSizeMin, pointSizeMax); + gl_PointSize = max(size, pointFadeThresholdSize); + + float fade = min(size, pointFadeThresholdSize) / pointFadeThresholdSize; + frontColor.a *= fade * fade; +} + diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader.fp index d3cfecd94..60b92401e 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader.fp +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader.fp @@ -1,23 +1,16 @@ // Copyright 2010 JogAmp Community. All rights reserved. -/** - * AMD complains: #version must occur before any other statement in the program -#ifdef GL_ES - #version 100 +#if __VERSION__ >= 130 + #define varying in + out vec4 mgl_FragColor; #else - #version 110 + #define mgl_FragColor gl_FragColor #endif - */ -#ifdef GL_ES - precision mediump float; - precision mediump int; -#endif - -varying vec4 frontColor; +varying vec4 frontColor; void main (void) { - gl_FragColor = frontColor; + mgl_FragColor = frontColor; } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader.java index cdbf3d9b8..07f3a97cb 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader.java @@ -35,6 +35,11 @@ public class RedSquareShader { " precision mediump int;\n" + "#endif\n" + "\n" + + "#if __VERSION__ >= 130\n" + + " #define attribute in\n" + + " #define varying out\n" + + "#endif\n"+ + "\n" + "uniform mat4 mgl_PMVMatrix[2];\n" + "attribute vec4 mgl_Vertex;\n" + "attribute vec4 mgl_Color;\n" + @@ -52,10 +57,17 @@ public class RedSquareShader { " precision mediump int;\n" + "#endif\n" + "\n" + + "#if __VERSION__ >= 130\n" + + " #define varying in\n" + + " out vec4 mgl_FragColor;\n" + + "#else\n" + + " #define mgl_FragColor gl_FragColor\n" + + "#endif\n" + + "\n" + "varying vec4 frontColor;\n" + "\n" + "void main (void)\n" + "{\n" + - " gl_FragColor = frontColor;\n" + + " mgl_FragColor = frontColor;\n" + "}\n" ; } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader.vp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader.vp index bfd44c8f4..9283dd7bd 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader.vp +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader.vp @@ -1,17 +1,8 @@ // Copyright 2010 JogAmp Community. All rights reserved. -/** - * AMD complains: #version must occur before any other statement in the program -#ifdef GL_ES - #version 100 -#else - #version 110 -#endif - */ - -#ifdef GL_ES - precision mediump float; - precision mediump int; +#if __VERSION__ >= 130 + #define attribute in + #define varying out #endif uniform mat4 mgl_PMVMatrix[2]; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader2.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader2.fp index 01e4b0964..25a2df2d7 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader2.fp +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/RedSquareShader2.fp @@ -1,26 +1,16 @@ // Copyright 2010 JogAmp Community. All rights reserved. -/** - * AMD complains: #version must occur before any other statement in the program -#ifdef GL_ES - #version 100 +#if __VERSION__ >= 130 + #define varying in + out vec4 mgl_FragColor; #else - #version 110 + #define mgl_FragColor gl_FragColor #endif - */ -#ifdef GL_ES - #define MEDIUMP mediump - #define HIGHP highp -#else - #define MEDIUMP - #define HIGHP -#endif - -varying HIGHP vec4 frontColor; +varying vec4 frontColor; void main (void) { - gl_FragColor = vec4(0.0, frontColor.g, frontColor.b, 1.0); + mgl_FragColor = vec4(0.0, frontColor.g, frontColor.b, 1.0); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/default.vp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/default.vp index 99ad6e400..2037086f1 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/default.vp +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/default.vp @@ -1,5 +1,10 @@ //Copyright 2010 JogAmp Community. All rights reserved. +#if __VERSION__ >= 130 + #define attribute in + #define varying out +#endif + #ifdef GL_ES #define MEDIUMP mediump #define HIGHP highp diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/elektronenmultiplizierer_development.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/elektronenmultiplizierer_development.fp index 22fb65e90..60f054b46 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/elektronenmultiplizierer_development.fp +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/elektronenmultiplizierer_development.fp @@ -9,6 +9,14 @@ * author: Dominik Stroehlein (DemoscenePassivist) **/ +#if __VERSION__ >= 130 + #define varying in + out vec4 mgl_FragColor; + #define texture2D texture +#else + #define mgl_FragColor gl_FragColor +#endif + #ifdef GL_ES precision mediump float; precision mediump sampler2D; @@ -343,7 +351,7 @@ void main() { color = raymarch_orbittrap_image(oglFragCoord.xy); } if (en==2 || en==7) { - gl_FragColor = color; + mgl_FragColor = color; } else { //do normal rendering ... //analog-tv distortion ... @@ -376,6 +384,6 @@ void main() { //tv flicker effect color_tv *= 0.97+0.13*sin(2.5*tm); color_tv *= br; - gl_FragColor = vec4(color_tv,1.0); + mgl_FragColor = vec4(color_tv,1.0); } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/elektronenmultiplizierer_port.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/elektronenmultiplizierer_port.fp index d3df81994..77c34f74f 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/elektronenmultiplizierer_port.fp +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/elektronenmultiplizierer_port.fp @@ -12,6 +12,14 @@ //When I wrote this, only God and I understood what I was doing ... // ... now only God knows! X-) +#if __VERSION__ >= 130 + #define varying in + out vec4 mgl_FragColor; + #define texture2D texture +#else + #define mgl_FragColor gl_FragColor +#endif + uniform int en; uniform float et; uniform sampler2D fb; @@ -209,7 +217,7 @@ void main() { } else n=D(c.xy); if(en==2||en==7) - gl_FragColor=n; + mgl_FragColor=n; else { vec2 i=c.xy/v.xy; i.y*=-1.; @@ -229,6 +237,6 @@ void main() { x*=.9+.1*sin(1.5*tm+i.y*1000.); x*=.97+.13*sin(2.5*tm); x*=br; - gl_FragColor=vec4(x,1.); + mgl_FragColor=vec4(x,1.); } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-1.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-1.fp index 1738d96d1..563e0a4b0 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-1.fp +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-1.fp @@ -1,11 +1,16 @@ //Copyright 2010 JogAmp Community. All rights reserved. -#version 110 +#if __VERSION__ >= 130 + #define varying in + out vec4 mgl_FragData[2]; +#else + #define mgl_FragData gl_FragData +#endif varying vec4 frontColor; void main (void) { - gl_FragData[0] = vec4( frontColor.r, 0.0, 0.0, 1.0 ); - gl_FragData[1] = vec4( 0.0, frontColor.g, 0.0, 1.0 ); + mgl_FragData[0] = vec4( frontColor.r, 0.0, 0.0, 1.0 ); + mgl_FragData[1] = vec4( 0.0, frontColor.g, 0.0, 1.0 ); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-1.vp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-1.vp index 7f95a650a..4cab59c64 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-1.vp +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-1.vp @@ -1,6 +1,9 @@ // Copyright 2010 JogAmp Community. All rights reserved. -#version 110 +#if __VERSION__ >= 130 + #define attribute in + #define varying out +#endif uniform mat4 gcu_PMVMatrix[2]; // P, Mv, and Mvi attribute vec4 gca_Vertices; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-2.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-2.fp index deac58ce1..510096d66 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-2.fp +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-2.fp @@ -1,6 +1,12 @@ //Copyright 2010 JogAmp Community. All rights reserved. -#version 110 +#if __VERSION__ >= 130 + #define varying in + out vec4 mgl_FragData[2]; + #define texture2D texture +#else + #define mgl_FragData gl_FragData +#endif uniform sampler2D gcs_TexUnit0; uniform sampler2D gcs_TexUnit1; @@ -12,5 +18,5 @@ void main (void) { vec2 rg = texture2D(gcs_TexUnit0, texCoord).rg + texture2D(gcs_TexUnit1, texCoord).rg; float b = frontColor.b - length(rg); - gl_FragData[0] = vec4( rg, b, 1.0 ); -}
\ No newline at end of file + mgl_FragData[0] = vec4( rg, b, 1.0 ); +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-2.vp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-2.vp index 1b2c02328..89290b05a 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-2.vp +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/fbo-mrt-2.vp @@ -1,6 +1,9 @@ //Copyright 2010 JogAmp Community. All rights reserved. -#version 110 +#if __VERSION__ >= 130 + #define attribute in + #define varying out +#endif uniform mat4 gcu_PMVMatrix[2]; // P, Mv, and Mvi attribute vec4 gca_Vertices; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/gears.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/gears.fp index f41addad8..14328dc1e 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/gears.fp +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/gears.fp @@ -1,9 +1,11 @@ // Copyright (C) 2011 JogAmp Community. All rights reserved. // Details see GearsES2.java -#ifdef GL_ES - precision mediump float; - precision mediump int; +#if __VERSION__ >= 130 + #define varying in + out vec4 mgl_FragColor; +#else + #define mgl_FragColor gl_FragColor #endif uniform vec4 color; @@ -42,5 +44,5 @@ void main() specular += color * pow(NdotHV, matShininess) * attenuation * matSpecular; } - gl_FragColor = ambient + diffuse + specular ; + mgl_FragColor = ambient + diffuse + specular ; } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/gears.vp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/gears.vp index b2d77082b..24f4f9c52 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/gears.vp +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/gears.vp @@ -1,10 +1,11 @@ // Copyright (C) 2011 JogAmp Community. All rights reserved. // Details see GearsES2.java -#ifdef GL_ES - precision mediump float; - precision mediump int; +#if __VERSION__ >= 130 + #define attribute in + #define varying out #endif + uniform mat4 pmvMatrix[4]; // P, Mv, Mvi and Mvit uniform vec3 lightPos; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/landscape.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/landscape.fp new file mode 100644 index 000000000..b19c057d3 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/landscape.fp @@ -0,0 +1,339 @@ +// Elevated shader +// https://www.shadertoy.com/view/MdX3Rr by inigo quilez + +#if __VERSION__ >= 130 + #define varying in + out vec4 mgl_FragColor; +#else + #define mgl_FragColor gl_FragColor +#endif + +uniform vec3 iResolution; +uniform float iGlobalTime; + +// Created by inigo quilez - iq/2013 +// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. + +//stereo thanks to Croqueteer +//#define STEREO + +mat3 m = mat3( 0.00, 0.80, 0.60, + -0.80, 0.36, -0.48, + -0.60, -0.48, 0.64 ); + +float hash( float n ) +{ + return fract(sin(n)*43758.5453123); +} + + +float noise( in vec3 x ) +{ + vec3 p = floor(x); + vec3 f = fract(x); + + f = f*f*(3.0-2.0*f); + + float n = p.x + p.y*57.0 + 113.0*p.z; + + float res = mix(mix(mix( hash(n+ 0.0), hash(n+ 1.0),f.x), + mix( hash(n+ 57.0), hash(n+ 58.0),f.x),f.y), + mix(mix( hash(n+113.0), hash(n+114.0),f.x), + mix( hash(n+170.0), hash(n+171.0),f.x),f.y),f.z); + return res; +} + + + + +vec3 noised( in vec2 x ) +{ + vec2 p = floor(x); + vec2 f = fract(x); + + vec2 u = f*f*(3.0-2.0*f); + + float n = p.x + p.y*57.0; + + float a = hash(n+ 0.0); + float b = hash(n+ 1.0); + float c = hash(n+ 57.0); + float d = hash(n+ 58.0); + return vec3(a+(b-a)*u.x+(c-a)*u.y+(a-b-c+d)*u.x*u.y, + 30.0*f*f*(f*(f-2.0)+1.0)*(vec2(b-a,c-a)+(a-b-c+d)*u.yx)); + +} + +float noise( in vec2 x ) +{ + vec2 p = floor(x); + vec2 f = fract(x); + + f = f*f*(3.0-2.0*f); + + float n = p.x + p.y*57.0; + + float res = mix(mix( hash(n+ 0.0), hash(n+ 1.0),f.x), + mix( hash(n+ 57.0), hash(n+ 58.0),f.x),f.y); + + return res; +} + +float fbm( vec3 p ) +{ + float f = 0.0; + + f += 0.5000*noise( p ); p = m*p*2.02; + f += 0.2500*noise( p ); p = m*p*2.03; + f += 0.1250*noise( p ); p = m*p*2.01; + f += 0.0625*noise( p ); + + return f/0.9375; +} + +mat2 m2 = mat2(1.6,-1.2,1.2,1.6); + +float fbm( vec2 p ) +{ + float f = 0.0; + + f += 0.5000*noise( p ); p = m2*p*2.02; + f += 0.2500*noise( p ); p = m2*p*2.03; + f += 0.1250*noise( p ); p = m2*p*2.01; + f += 0.0625*noise( p ); + + return f/0.9375; +} + +float terrain( in vec2 x ) +{ + vec2 p = x*0.003; + float a = 0.0; + float b = 1.0; + vec2 d = vec2(0.0); + for(int i=0;i<5; i++) + { + vec3 n = noised(p); + d += n.yz; + a += b*n.x/(1.0+dot(d,d)); + b *= 0.5; + p=mat2(1.6,-1.2,1.2,1.6)*p; + } + + return 140.0*a; +} + +float terrain2( in vec2 x ) +{ + vec2 p = x*0.003; + float a = 0.0; + float b = 1.0; + vec2 d = vec2(0.0); + for(int i=0;i<14; i++) + { + vec3 n = noised(p); + d += n.yz; + a += b*n.x/(1.0+dot(d,d)); + b *= 0.5; + p=m2*p; + } + + return 140.0*a; +} + + +float map( in vec3 p ) +{ + float h = terrain(p.xz); + + float ss = 0.03; + float hh = h*ss; + float fh = fract(hh); + float ih = floor(hh); + fh = mix( sqrt(fh), fh, smoothstep(50.0,140.0,h) ); + h = (ih+fh)/ss; + + return p.y - h; +} + +float map2( in vec3 p ) +{ + float h = terrain2(p.xz); + + + float ss = 0.03; + float hh = h*ss; + float fh = fract(hh); + float ih = floor(hh); + fh = mix( sqrt(fh), fh, smoothstep(50.0,140.0,h) ); + h = (ih+fh)/ss; + + return p.y - h; +} + +bool jinteresct(in vec3 rO, in vec3 rD, out float resT ) +{ + float h = 0.0; + float t = 0.0; + for( int j=0; j<120; j++ ) + { + //if( t>2000.0 ) break; + + vec3 p = rO + t*rD; +if( p.y>300.0 ) break; + h = map( p ); + + if( h<0.1 ) + { + resT = t; + return true; + } + t += max(0.1,0.5*h); + + } + + if( h<5.0 ) + { + resT = t; + return true; + } + return false; +} + +float sinteresct(in vec3 rO, in vec3 rD ) +{ + float res = 1.0; + float t = 0.0; + for( int j=0; j<50; j++ ) + { + //if( t>1000.0 ) break; + vec3 p = rO + t*rD; + + float h = map( p ); + + if( h<0.1 ) + { + return 0.0; + } + res = min( res, 16.0*h/t ); + t += h; + + } + + return clamp( res, 0.0, 1.0 ); +} + +vec3 calcNormal( in vec3 pos, float t ) +{ + float e = 0.001; + e = 0.001*t; + vec3 eps = vec3(e,0.0,0.0); + vec3 nor; + nor.x = map2(pos+eps.xyy) - map2(pos-eps.xyy); + nor.y = map2(pos+eps.yxy) - map2(pos-eps.yxy); + nor.z = map2(pos+eps.yyx) - map2(pos-eps.yyx); + return normalize(nor); +} + +vec3 camPath( float time ) +{ + vec2 p = 600.0*vec2( cos(1.4+0.37*time), + cos(3.2+0.31*time) ); + + return vec3( p.x, 0.0, p.y ); +} + +void main(void) +{ + vec2 xy = -1.0 + 2.0*gl_FragCoord.xy / iResolution.xy; + + vec2 s = xy*vec2(1.75,1.0); + + #ifdef STEREO + float isCyan = mod(gl_FragCoord.x + mod(gl_FragCoord.y,2.0),2.0); + #endif + + float time = iGlobalTime*.15; + + vec3 light1 = normalize( vec3( 0.4, 0.22, 0.6 ) ); + vec3 light2 = vec3( -0.707, 0.000, -0.707 ); + + + vec3 campos = camPath( time ); + vec3 camtar = camPath( time + 3.0 ); + campos.y = terrain( campos.xz ) + 15.0; + camtar.y = campos.y*0.5; + + float roll = 0.1*cos(0.1*time); + vec3 cw = normalize(camtar-campos); + vec3 cp = vec3(sin(roll), cos(roll),0.0); + vec3 cu = normalize(cross(cw,cp)); + vec3 cv = normalize(cross(cu,cw)); + vec3 rd = normalize( s.x*cu + s.y*cv + 1.6*cw ); + + #ifdef STEREO + campos += 2.0*cu*isCyan; // move camera to the right - the rd vector is still good + #endif + + float sundot = clamp(dot(rd,light1),0.0,1.0); + vec3 col; + float t; + if( !jinteresct(campos,rd,t) ) + { + col = 0.9*vec3(0.97,.99,1.0)*(1.0-0.3*rd.y); + col += 0.2*vec3(0.8,0.7,0.5)*pow( sundot, 4.0 ); + } + else + { + vec3 pos = campos + t*rd; + + vec3 nor = calcNormal( pos, t ); + + float dif1 = clamp( dot( light1, nor ), 0.0, 1.0 ); + float dif2 = clamp( 0.2 + 0.8*dot( light2, nor ), 0.0, 1.0 ); + float sh = 1.0; + if( dif1>0.001 ) + sh = sinteresct(pos+light1*20.0,light1); + + vec3 dif1v = vec3(dif1); + dif1v *= vec3( sh, sh*sh*0.5+0.5*sh, sh*sh ); + + float r = noise( 7.0*pos.xz ); + + col = (r*0.25+0.75)*0.9*mix( vec3(0.10,0.05,0.03), vec3(0.13,0.10,0.08), clamp(terrain2( vec2(pos.x,pos.y*48.0))/200.0,0.0,1.0) ); + col = mix( col, 0.17*vec3(0.5,.23,0.04)*(0.50+0.50*r),smoothstep(0.70,0.9,nor.y) ); + col = mix( col, 0.10*vec3(0.2,.30,0.00)*(0.25+0.75*r),smoothstep(0.95,1.0,nor.y) ); + col *= 0.75; + // snow + #if 1 + float h = smoothstep(55.0,80.0,pos.y + 25.0*fbm(0.01*pos.xz) ); + float e = smoothstep(1.0-0.5*h,1.0-0.1*h,nor.y); + float o = 0.3 + 0.7*smoothstep(0.0,0.1,nor.x+h*h); + float s = h*e*o; + s = smoothstep( 0.1, 0.9, s ); + col = mix( col, 0.4*vec3(0.6,0.65,0.7), s ); + #endif + + + vec3 brdf = 2.0*vec3(0.17,0.19,0.20)*clamp(nor.y,0.0,1.0); + brdf += 6.0*vec3(1.00,0.95,0.80)*dif1v; + brdf += 2.0*vec3(0.20,0.20,0.20)*dif2; + + col *= brdf; + + float fo = 1.0-exp(-pow(0.0015*t,1.5)); + vec3 fco = vec3(0.7) + 0.6*vec3(0.8,0.7,0.5)*pow( sundot, 4.0 ); + col = mix( col, fco, fo ); + } + + col = sqrt(col); + + vec2 uv = xy*0.5+0.5; + col *= 0.7 + 0.3*pow(16.0*uv.x*uv.y*(1.0-uv.x)*(1.0-uv.y),0.1); + + #ifdef STEREO + col *= vec3( isCyan, 1.0-isCyan, 1.0-isCyan ); + #endif + + mgl_FragColor = vec4(col,1.0); +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/landscape.vp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/landscape.vp new file mode 100644 index 000000000..fc698f2a8 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/landscape.vp @@ -0,0 +1,11 @@ + +#if __VERSION__ >= 130 + #define attribute in + #define varying out +#endif + +attribute vec2 inVertex; + +void main() { + gl_Position = vec4(inVertex, 0, 1); +}
\ No newline at end of file diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/mgl_default_xxx.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/mgl_default_xxx.fp new file mode 100644 index 000000000..a2abf9e2c --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/mgl_default_xxx.fp @@ -0,0 +1,16 @@ +// Copyright 2012 JogAmp Community. All rights reserved. + +#if __VERSION__ >= 130 + #define varying in + out vec4 mgl_FragColor; +#else + #define mgl_FragColor gl_FragColor +#endif + +varying vec4 frontColor; + +void main (void) +{ + mgl_FragColor = frontColor; +} + diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/mgl_default_xxx.vp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/mgl_default_xxx.vp new file mode 100644 index 000000000..98e7916ab --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/mgl_default_xxx.vp @@ -0,0 +1,18 @@ +//Copyright 2012 JogAmp Community. All rights reserved. + +#if __VERSION__ >= 130 + #define attribute in + #define varying out +#endif + +uniform mat4 mgl_PMVMatrix[2]; // P, Mv +attribute vec4 mgl_Vertex; +attribute vec4 mgl_Color; + +varying vec4 frontColor; + +void main(void) +{ + frontColor = mgl_Color; + gl_Position = mgl_PMVMatrix[0] * mgl_PMVMatrix[1] * mgl_Vertex; +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/ruler.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/ruler.fp index b2f4d7a6a..f16a3eeb1 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/ruler.fp +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/ruler.fp @@ -1,5 +1,12 @@ //Copyright 2010 JogAmp Community. All rights reserved. +#if __VERSION__ >= 130 + #define varying in + out vec4 mgl_FragColor; +#else + #define mgl_FragColor gl_FragColor +#endif + #ifdef GL_ES #define MEDIUMP mediump #define HIGHP highp @@ -19,7 +26,7 @@ void main (void) { MEDIUMP vec2 c = step( onev2, mod(gl_FragCoord.xy, gcu_RulerPixFreq) ); if( c.s == 0.0 || c.t == 0.0 ) { - gl_FragColor = vec4(gcu_RulerColor, 1.0); + mgl_FragColor = vec4(gcu_RulerColor, 1.0); } else { discard; } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texsequence_xxx.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texsequence_xxx.fp index adde23d0a..e4f21f95f 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texsequence_xxx.fp +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texsequence_xxx.fp @@ -1,5 +1,13 @@ // Copyright 2012 JogAmp Community. All rights reserved. +#if __VERSION__ >= 130 + #define varying in + out vec4 mgl_FragColor; + #define texture2D texture +#else + #define mgl_FragColor gl_FragColor +#endif + varying vec2 mgl_texCoord; varying vec4 frontColor; @@ -17,6 +25,6 @@ void main (void) } // mix frontColor with texture .. - gl_FragColor = vec4(frontColor*texColor); + mgl_FragColor = vec4(frontColor*texColor); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texsequence_xxx.vp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texsequence_xxx.vp index c521e3757..1030dab47 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texsequence_xxx.vp +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texsequence_xxx.vp @@ -1,5 +1,10 @@ // Copyright 2012 JogAmp Community. All rights reserved. +#if __VERSION__ >= 130 + #define attribute in + #define varying out +#endif + uniform mat4 mgl_PMVMatrix[2]; // uniform mat4 mgl_STMatrix; attribute vec4 mgl_Vertex; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texture01_xxx.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texture01_xxx.fp new file mode 100644 index 000000000..93f252cd6 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texture01_xxx.fp @@ -0,0 +1,28 @@ +// Copyright 2012 JogAmp Community. All rights reserved. + +#if __VERSION__ >= 130 + #define varying in + out vec4 mgl_FragColor; + #define texture2D texture +#else + #define mgl_FragColor gl_FragColor +#endif + +varying vec2 mgl_texCoord; +varying vec4 frontColor; + +uniform sampler2D mgl_ActiveTexture; + +void main (void) +{ + vec4 texColor; + if(0.0 <= mgl_texCoord.t && mgl_texCoord.t<=1.0) { + texColor = texture2D(mgl_ActiveTexture, mgl_texCoord); + } else { + discard; + } + + // mix frontColor with texture .. pre-multiplying texture alpha + mgl_FragColor = vec4( mix( frontColor.rgb, texColor.rgb, texColor.a ), frontColor.a ); +} + diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texture01_xxx.vp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texture01_xxx.vp new file mode 100644 index 000000000..1030dab47 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texture01_xxx.vp @@ -0,0 +1,22 @@ +// Copyright 2012 JogAmp Community. All rights reserved. + +#if __VERSION__ >= 130 + #define attribute in + #define varying out +#endif + +uniform mat4 mgl_PMVMatrix[2]; +// uniform mat4 mgl_STMatrix; +attribute vec4 mgl_Vertex; +attribute vec4 mgl_Color; +attribute vec4 mgl_MultiTexCoord; +varying vec4 frontColor; +varying vec2 mgl_texCoord; + +void main(void) +{ + frontColor=mgl_Color; + // mgl_texCoord = (mgl_STMatrix * mgl_MultiTexCoord).st; + mgl_texCoord = mgl_MultiTexCoord.st; + gl_Position = mgl_PMVMatrix[0] * mgl_PMVMatrix[1] * mgl_Vertex; +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texture02_xxx.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texture02_xxx.fp new file mode 100644 index 000000000..10073e85c --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texture02_xxx.fp @@ -0,0 +1,28 @@ +// Copyright 2012 JogAmp Community. All rights reserved. + +#if __VERSION__ >= 130 + #define varying in + out vec4 mgl_FragColor; + #define texture2D texture +#else + #define mgl_FragColor gl_FragColor +#endif + +varying vec2 mgl_texCoord; +varying vec4 frontColor; + +uniform sampler2D mgl_Texture0; +uniform sampler2D mgl_Texture1; + +const vec4 One = vec4(1.0, 1.0, 1.0, 1.0); + +void main (void) +{ + vec4 texColor0 = texture2D(mgl_Texture0, mgl_texCoord); + vec4 texColor1 = texture2D(mgl_Texture1, mgl_texCoord); + + // mgl_FragColor = ( ( texColor0 + texColor1 ) / 2.0 ) * frontColor; + // mgl_FragColor = mix(texColor0, texColor1, One/2.0) * frontColor; + mgl_FragColor = min(One, mix(texColor0, texColor1, One/2.0) * 1.6) * frontColor; +} + diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/swt/TestGearsES2SWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/swt/TestGearsES2SWT.java new file mode 100644 index 000000000..b6463ac0f --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/swt/TestGearsES2SWT.java @@ -0,0 +1,344 @@ +/** + * Copyright 2011 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.jogl.demos.es2.swt; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +import com.jogamp.nativewindow.swt.SWTAccessor; +import com.jogamp.opengl.swt.GLCanvas; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; + +import com.jogamp.opengl.util.Animator; + +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; + +import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.Point; +import javax.media.nativewindow.util.PointImmutable; +import javax.media.nativewindow.util.DimensionImmutable; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLProfile; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.junit.After; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.AfterClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGearsES2SWT extends UITestCase { + static int screenIdx = 0; + static PointImmutable wpos; + static DimensionImmutable wsize, rwsize=null; + + static long duration = 500; // ms + static boolean opaque = true; + static int forceAlpha = -1; + static boolean fullscreen = false; + static boolean pmvUseBackingArray = true; + static int swapInterval = 1; + static boolean showFPS = false; + static int loops = 1; + static boolean loop_shutdown = false; + static boolean forceES2 = false; + static boolean forceGL3 = false; + static boolean mainRun = false; + static boolean exclusiveContext = false; + + @BeforeClass + public static void initClass() { + if(null == wsize) { + wsize = new Dimension(640, 480); + } + } + + @AfterClass + public static void releaseClass() { + } + + Display display = null; + Shell shell = null; + Composite composite = null; + + @Before + public void init() { + SWTAccessor.invoke(true, new Runnable() { + public void run() { + display = new Display(); + Assert.assertNotNull( display ); + }}); + display.syncExec(new Runnable() { + public void run() { + shell = new Shell( display ); + Assert.assertNotNull( shell ); + shell.setLayout( new FillLayout() ); + composite = new Composite( shell, SWT.NONE ); + composite.setLayout( new FillLayout() ); + Assert.assertNotNull( composite ); + }}); + } + + @After + public void release() { + Assert.assertNotNull( display ); + Assert.assertNotNull( shell ); + Assert.assertNotNull( composite ); + try { + display.syncExec(new Runnable() { + public void run() { + composite.dispose(); + shell.dispose(); + }}); + SWTAccessor.invoke(true, new Runnable() { + public void run() { + display.dispose(); + }}); + } + catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + display = null; + shell = null; + composite = null; + } + + protected void runTestGL(GLCapabilitiesImmutable caps) throws InterruptedException, InvocationTargetException { + System.err.println("requested: vsync "+swapInterval+", "+caps); + + final GLCanvas canvas = GLCanvas.create( composite, 0, caps, null); + Assert.assertNotNull( canvas ); + + final GearsES2 demo = new GearsES2(swapInterval); + demo.setPMVUseBackingArray(pmvUseBackingArray); + canvas.addGLEventListener(demo); + + Animator animator = new Animator(); + animator.setModeBits(false, Animator.MODE_EXPECT_AWT_RENDERING_THREAD); + animator.setExclusiveContext(exclusiveContext); + + animator.add(canvas); + animator.start(); + Assert.assertTrue(animator.isStarted()); + Assert.assertTrue(animator.isAnimating()); + Assert.assertEquals(exclusiveContext ? animator.getThread() : null, canvas.getExclusiveContextThread()); + + display.syncExec( new Runnable() { + public void run() { + shell.setText( getSimpleTestName(".") ); + shell.setSize( wsize.getWidth(), wsize.getHeight() ); + if( null != wpos ) { + shell.setLocation( wpos.getX(), wpos.getY() ); + } + shell.open(); + } + }); + + animator.setUpdateFPSFrames(60, showFPS ? System.err : null); + + while(animator.isAnimating() && !canvas.isRealized() && animator.getTotalFPSDuration()<duration) { + if( !display.readAndDispatch() ) { + // blocks on linux .. display.sleep(); + Thread.sleep(10); + } + } + System.err.println("NW chosen: "+canvas.getDelegatedDrawable().getChosenGLCapabilities()); + System.err.println("GL chosen: "+canvas.getChosenGLCapabilities()); + System.err.println("window pos/siz: "+canvas.getLocation()+" "+canvas.getWidth()+"x"+canvas.getHeight()); + + if( null != rwsize ) { + for(int i=0; i<50; i++) { // 500 ms dispatched delay + if( !display.readAndDispatch() ) { + // blocks on linux .. display.sleep(); + Thread.sleep(10); + } + } + display.syncExec( new Runnable() { + public void run() { + shell.setSize( rwsize.getWidth(), rwsize.getHeight() ); + } + }); + System.err.println("window resize pos/siz: "+canvas.getLocation()+" "+canvas.getWidth()+"x"+canvas.getHeight()); + } + + while(animator.isAnimating() && animator.getTotalFPSDuration()<duration) { + if( !display.readAndDispatch() ) { + // blocks on linux .. display.sleep(); + Thread.sleep(10); + } + } + + Assert.assertEquals(exclusiveContext ? animator.getThread() : null, canvas.getExclusiveContextThread()); + animator.stop(); + Assert.assertFalse(animator.isAnimating()); + Assert.assertFalse(animator.isStarted()); + Assert.assertEquals(null, canvas.getExclusiveContextThread()); + + display.syncExec(new Runnable() { + public void run() { + canvas.dispose(); + } } ); + } + + @Test + public void test01GL2ES2() throws InterruptedException, InvocationTargetException { + for(int i=1; i<=loops; i++) { + System.err.println("Loop "+i+"/"+loops); + final GLProfile glp; + if(forceGL3) { + glp = GLProfile.get(GLProfile.GL3); + } else if(forceES2) { + glp = GLProfile.get(GLProfile.GLES2); + } else { + glp = GLProfile.getGL2ES2(); + } + final GLCapabilities caps = new GLCapabilities( glp ); + caps.setBackgroundOpaque(opaque); + if(-1 < forceAlpha) { + caps.setAlphaBits(forceAlpha); + } + runTestGL(caps); + if(loop_shutdown) { + GLProfile.shutdown(); + } + } + } + + @Test + public void test02GL3() throws InterruptedException, InvocationTargetException { + if(mainRun) return; + + if( !GLProfile.isAvailable(GLProfile.GL3) ) { + System.err.println("GL3 n/a"); + return; + } + final GLProfile glp = GLProfile.get(GLProfile.GL3); + final GLCapabilities caps = new GLCapabilities( glp ); + runTestGL(caps); + } + + public static void main(String args[]) throws IOException { + mainRun = true; + + int x=0, y=0, w=640, h=480, rw=-1, rh=-1; + boolean usePos = false; + + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-translucent")) { + opaque = false; + } else if(args[i].equals("-forceAlpha")) { + i++; + forceAlpha = MiscUtils.atoi(args[i], 0); + } else if(args[i].equals("-fullscreen")) { + fullscreen = true; + } else if(args[i].equals("-pmvDirect")) { + pmvUseBackingArray = false; + } else if(args[i].equals("-vsync")) { + i++; + swapInterval = MiscUtils.atoi(args[i], swapInterval); + } else if(args[i].equals("-exclctx")) { + exclusiveContext = true; + } else if(args[i].equals("-es2")) { + forceES2 = true; + } else if(args[i].equals("-gl3")) { + forceGL3 = true; + } else if(args[i].equals("-showFPS")) { + showFPS = true; + } else if(args[i].equals("-width")) { + i++; + w = MiscUtils.atoi(args[i], w); + } else if(args[i].equals("-height")) { + i++; + h = MiscUtils.atoi(args[i], h); + } else if(args[i].equals("-x")) { + i++; + x = MiscUtils.atoi(args[i], x); + usePos = true; + } else if(args[i].equals("-y")) { + i++; + y = MiscUtils.atoi(args[i], y); + usePos = true; + } else if(args[i].equals("-rwidth")) { + i++; + rw = MiscUtils.atoi(args[i], rw); + } else if(args[i].equals("-rheight")) { + i++; + rh = MiscUtils.atoi(args[i], rh); + } else if(args[i].equals("-screen")) { + i++; + screenIdx = MiscUtils.atoi(args[i], 0); + } else if(args[i].equals("-loops")) { + i++; + loops = MiscUtils.atoi(args[i], 1); + } else if(args[i].equals("-loop-shutdown")) { + loop_shutdown = true; + } + } + wsize = new Dimension(w, h); + if( 0 < rw && 0 < rh ) { + rwsize = new Dimension(rw, rh); + } + + if(usePos) { + wpos = new Point(x, y); + } + System.err.println("position "+wpos); + System.err.println("size "+wsize); + System.err.println("resize "+rwsize); + System.err.println("screen "+screenIdx); + System.err.println("translucent "+(!opaque)); + System.err.println("forceAlpha "+forceAlpha); + System.err.println("fullscreen "+fullscreen); + System.err.println("pmvDirect "+(!pmvUseBackingArray)); + System.err.println("loops "+loops); + System.err.println("loop shutdown "+loop_shutdown); + System.err.println("forceES2 "+forceES2); + System.err.println("forceGL3 "+forceGL3); + System.err.println("swapInterval "+swapInterval); + System.err.println("exclusiveContext "+exclusiveContext); + + org.junit.runner.JUnitCore.main(TestGearsES2SWT.class.getName()); + } +} 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 b4881ab51..0d71c7ad0 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 @@ -1,6 +1,7 @@ package com.jogamp.opengl.test.junit.jogl.demos.gl2; +import javax.media.opengl.GL; import javax.media.opengl.GL2; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLEventListener; @@ -16,6 +17,8 @@ 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.JoglVersion; +import com.jogamp.opengl.util.TileRendererBase; /** * Gears.java <BR> @@ -23,12 +26,19 @@ import com.jogamp.newt.event.awt.AWTMouseAdapter; * * This version is equal to Brian Paul's version 1.2 1999/10/21 */ - -public class Gears implements GLEventListener { - private float view_rotx = 20.0f, view_roty = 30.0f, view_rotz = 0.0f; +public class Gears implements GLEventListener, TileRendererBase.TileRendererListener { + 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 float angle = 0.0f; - private int swapInterval; + private boolean doRotate = true; + private final int swapInterval; + private final MouseListener gearsMouse = new GearsMouseAdapter(); + private final KeyListener gearsKeys = new GearsKeyAdapter(); + private TileRendererBase tileRendererInUse = null; + private boolean doRotateBeforePrinting; + private boolean verbose = true; + private boolean flipVerticalInGLOrientation = false; // private boolean mouseRButtonDown = false; private int prevMouseX, prevMouseY; @@ -40,7 +50,31 @@ public class Gears implements GLEventListener { public Gears() { this.swapInterval = 1; } - + + @Override + public void addTileRendererNotify(TileRendererBase tr) { + tileRendererInUse = tr; + doRotateBeforePrinting = doRotate; + setDoRotation(false); + } + @Override + public void removeTileRendererNotify(TileRendererBase tr) { + tileRendererInUse = null; + setDoRotation(doRotateBeforePrinting); + } + @Override + public void startTileRendering(TileRendererBase tr) { + System.err.println("Gears.startTileRendering: "+tr); + } + @Override + public void endTileRendering(TileRendererBase tr) { + System.err.println("Gears.endTileRendering: "+tr); + } + + public void setDoRotation(boolean rotate) { doRotate = rotate; } + public void setVerbose(boolean v) { verbose = v; } + public void setFlipVerticalInGLOrientation(boolean v) { flipVerticalInGLOrientation=v; } + public void setGears(int g1, int g2, int g3) { gear1 = g1; gear2 = g2; @@ -62,30 +96,47 @@ public class Gears implements GLEventListener { */ public int getGear3() { return gear3; } + @Override public void init(GLAutoDrawable drawable) { - System.err.println("Gears: Init: "+drawable); - // Use debug pipeline - // drawable.setGL(new DebugGL(drawable.getGL())); - GL2 gl = drawable.getGL().getGL2(); - System.err.println("Chosen GLCapabilities: " + drawable.getChosenGLCapabilities()); - System.err.println("INIT GL IS: " + gl.getClass().getName()); - System.err.println("GL_VENDOR: " + gl.glGetString(GL2.GL_VENDOR)); - System.err.println("GL_RENDERER: " + gl.glGetString(GL2.GL_RENDERER)); - System.err.println("GL_VERSION: " + gl.glGetString(GL2.GL_VERSION)); + init(gl); - float pos[] = { 5.0f, 5.0f, 10.0f, 0.0f }; - float red[] = { 0.8f, 0.1f, 0.0f, 0.7f }; - float green[] = { 0.0f, 0.8f, 0.2f, 0.7f }; - float blue[] = { 0.2f, 0.2f, 1.0f, 0.7f }; + final Object upstreamWidget = drawable.getUpstreamWidget(); + if (upstreamWidget instanceof Window) { + final Window window = (Window) upstreamWidget; + window.addMouseListener(gearsMouse); + window.addKeyListener(gearsKeys); + } else if (GLProfile.isAWTAvailable() && upstreamWidget instanceof java.awt.Component) { + final java.awt.Component comp = (java.awt.Component) upstreamWidget; + new AWTMouseAdapter(gearsMouse).addTo(comp); + new AWTKeyAdapter(gearsKeys).addTo(comp); + } + } - gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_POSITION, pos, 0); - gl.glEnable(GL2.GL_CULL_FACE); + public void init(GL2 gl) { + final float lightPos[] = { 5.0f, 5.0f, 10.0f, 0.0f }; + final float red[] = { 0.8f, 0.1f, 0.0f, 0.7f }; + final float green[] = { 0.0f, 0.8f, 0.2f, 0.7f }; + final float blue[] = { 0.2f, 0.2f, 1.0f, 0.7f }; + + System.err.println(Thread.currentThread()+" Gears.init: tileRendererInUse "+tileRendererInUse); + if(verbose) { + System.err.println("GearsES2 init on "+Thread.currentThread()); + System.err.println("Chosen GLCapabilities: " + gl.getContext().getGLDrawable().getChosenGLCapabilities()); + System.err.println("INIT GL IS: " + gl.getClass().getName()); + System.err.println(JoglVersion.getGLStrings(gl, null, false).toString()); + } + + gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_POSITION, lightPos, 0); + if( ! ( flipVerticalInGLOrientation && gl.getContext().getGLDrawable().isGLOriented() ) ) { + // Only possible if we do not flip the projection matrix + gl.glEnable(GL2.GL_CULL_FACE); + } gl.glEnable(GL2.GL_LIGHTING); gl.glEnable(GL2.GL_LIGHT0); gl.glEnable(GL2.GL_DEPTH_TEST); - + /* make the gears */ if(0>=gear1) { gear1 = gl.glGenLists(1); @@ -97,7 +148,7 @@ public class Gears implements GLEventListener { } else { System.err.println("gear1 list reused: "+gear1); } - + if(0>=gear2) { gear2 = gl.glGenLists(1); gl.glNewList(gear2, GL2.GL_COMPILE); @@ -108,7 +159,7 @@ public class Gears implements GLEventListener { } else { System.err.println("gear2 list reused: "+gear2); } - + if(0>=gear3) { gear3 = gl.glGenLists(1); gl.glNewList(gear3, GL2.GL_COMPILE); @@ -119,58 +170,116 @@ public class Gears implements GLEventListener { } else { System.err.println("gear3 list reused: "+gear3); } - + gl.glEnable(GL2.GL_NORMALIZE); - - // MouseListener gearsMouse = new TraceMouseAdapter(new GearsMouseAdapter()); - MouseListener gearsMouse = new GearsMouseAdapter(); - KeyListener gearsKeys = new GearsKeyAdapter(); + } - if (drawable instanceof Window) { - Window window = (Window) drawable; - window.addMouseListener(gearsMouse); - window.addKeyListener(gearsKeys); - } else if (GLProfile.isAWTAvailable() && drawable instanceof java.awt.Component) { - java.awt.Component comp = (java.awt.Component) drawable; - new AWTMouseAdapter(gearsMouse).addTo(comp); - new AWTKeyAdapter(gearsKeys).addTo(comp); - } + @Override + public void reshape(GLAutoDrawable glad, int x, int y, int width, int height) { + final GL2 gl = glad.getGL().getGL2(); + if(-1 != swapInterval) { + gl.setSwapInterval(swapInterval); + } + reshape(gl, x, y, width, height, width, height); } - - public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { - System.err.println("Gears: Reshape "+x+"/"+y+" "+width+"x"+height); - GL2 gl = drawable.getGL().getGL2(); - gl.setSwapInterval(swapInterval); + @Override + public void reshapeTile(TileRendererBase tr, + int tileX, int tileY, int tileWidth, int tileHeight, + int imageWidth, int imageHeight) { + final GL2 gl = tr.getAttachedDrawable().getGL().getGL2(); + gl.setSwapInterval(0); + reshape(gl, tileX, tileY, tileWidth, tileHeight, imageWidth, imageHeight); + } - float h = (float)height / (float)width; - - gl.glMatrixMode(GL2.GL_PROJECTION); + public void reshape(GL2 gl, int tileX, int tileY, int tileWidth, int tileHeight, int imageWidth, int imageHeight) { + final boolean msaa = gl.getContext().getGLDrawable().getChosenGLCapabilities().getSampleBuffers(); + System.err.println(Thread.currentThread()+" Gears.reshape "+tileX+"/"+tileY+" "+tileWidth+"x"+tileHeight+" of "+imageWidth+"x"+imageHeight+", swapInterval "+swapInterval+", drawable 0x"+Long.toHexString(gl.getContext().getGLDrawable().getHandle())+", msaa "+msaa+", tileRendererInUse "+tileRendererInUse); + + if( msaa ) { + gl.glEnable(GL.GL_MULTISAMPLE); + } + + // compute projection parameters 'normal' + float left, right, bottom, top; + if( imageHeight > imageWidth ) { + float a = (float)imageHeight / (float)imageWidth; + left = -1.0f; + right = 1.0f; + bottom = -a; + top = a; + } else { + float a = (float)imageWidth / (float)imageHeight; + left = -a; + right = a; + bottom = -1.0f; + top = 1.0f; + } + final float w = right - left; + final float h = top - bottom; + + // compute projection parameters 'tiled' + final float l = left + tileX * w / imageWidth; + final float r = l + tileWidth * w / imageWidth; + final float b = bottom + tileY * h / imageHeight; + final float t = b + tileHeight * h / imageHeight; + + final float _w = r - l; + final float _h = t - b; + if(verbose) { + System.err.println(">> Gears angle "+angle+", [l "+left+", r "+right+", b "+bottom+", t "+top+"] "+w+"x"+h+" -> [l "+l+", r "+r+", b "+b+", t "+t+"] "+_w+"x"+_h+", v-flip "+flipVerticalInGLOrientation); + } + + gl.glMatrixMode(GL2.GL_PROJECTION); gl.glLoadIdentity(); - gl.glFrustum(-1.0f, 1.0f, -h, h, 5.0f, 60.0f); + if( flipVerticalInGLOrientation && gl.getContext().getGLDrawable().isGLOriented() ) { + gl.glScalef(1f, -1f, 1f); + } + gl.glFrustum(l, r, b, t, 5.0f, 60.0f); + gl.glMatrixMode(GL2.GL_MODELVIEW); gl.glLoadIdentity(); gl.glTranslatef(0.0f, 0.0f, -40.0f); + + if( msaa ) { + gl.glDisable(GL.GL_MULTISAMPLE); + } } + @Override public void dispose(GLAutoDrawable drawable) { - System.err.println("Gears: Dispose"); + System.err.println(Thread.currentThread()+" Gears.dispose: tileRendererInUse "+tileRendererInUse); + try { + final Object upstreamWidget = drawable.getUpstreamWidget(); + if (upstreamWidget instanceof Window) { + final Window window = (Window) upstreamWidget; + window.removeMouseListener(gearsMouse); + window.removeKeyListener(gearsKeys); + } + } catch (Exception e) { System.err.println("Catched: "); e.printStackTrace(); } setGears(0, 0, 0); } + @Override public void display(GLAutoDrawable drawable) { - // Turn the gears' teeth - angle += 2.0f; - // Get the GL corresponding to the drawable we are animating GL2 gl = drawable.getGL().getGL2(); + final boolean msaa = gl.getContext().getGLDrawable().getChosenGLCapabilities().getSampleBuffers(); - gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + if( msaa ) { + gl.glEnable(GL.GL_MULTISAMPLE); + } + + if( null == tileRendererInUse ) { + gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + } else { + gl.glClearColor(1.0f, 1.0f, 1.0f, 0.0f); + } // Special handling for the case where the GLJPanel is translucent // and wants to be composited with other Java 2D content - if (GLProfile.isAWTAvailable() && + if (GLProfile.isAWTAvailable() && (drawable instanceof javax.media.opengl.awt.GLJPanel) && !((javax.media.opengl.awt.GLJPanel) drawable).isOpaque() && ((javax.media.opengl.awt.GLJPanel) drawable).shouldPreserveColorBufferIfTranslucent()) { @@ -178,35 +287,60 @@ public class Gears implements GLEventListener { } else { gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT); } - + displayImpl(gl); + if( msaa ) { + gl.glDisable(GL.GL_MULTISAMPLE); + } + } + public void display(GL2 gl) { + final boolean msaa = gl.getContext().getGLDrawable().getChosenGLCapabilities().getSampleBuffers(); + if( msaa ) { + gl.glEnable(GL.GL_MULTISAMPLE); + } + if( null == tileRendererInUse ) { + gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + } else { + gl.glClearColor(1.0f, 1.0f, 1.0f, 0.0f); + } + gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT); + displayImpl(gl); + if( msaa ) { + gl.glDisable(GL.GL_MULTISAMPLE); + } + } + private void displayImpl(GL2 gl) { + if( doRotate ) { + // Turn the gears' teeth + angle += 2.0f; + } // Rotate the entire assembly of gears based on how the user // dragged the mouse around gl.glPushMatrix(); gl.glRotatef(view_rotx, 1.0f, 0.0f, 0.0f); gl.glRotatef(view_roty, 0.0f, 1.0f, 0.0f); 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(); - + // Remember that every push needs a pop; this one is paired with // rotating the entire gear assembly gl.glPopMatrix(); @@ -227,9 +361,9 @@ public class Gears implements GLEventListener { r0 = inner_radius; r1 = outer_radius - tooth_depth / 2.0f; r2 = outer_radius + tooth_depth / 2.0f; - + da = 2.0f * (float) Math.PI / teeth / 4.0f; - + gl.glShadeModel(GL2.GL_FLAT); gl.glNormal3f(0.0f, 0.0f, 1.0f); @@ -260,7 +394,7 @@ public class Gears implements GLEventListener { gl.glVertex3f(r1 * (float)Math.cos(angle + 3.0f * da), r1 * (float)Math.sin(angle + 3.0f * da), width * 0.5f); } gl.glEnd(); - + /* draw back face */ gl.glBegin(GL2.GL_QUAD_STRIP); for (i = 0; i <= teeth; i++) @@ -272,7 +406,7 @@ public class Gears implements GLEventListener { gl.glVertex3f(r0 * (float)Math.cos(angle), r0 * (float)Math.sin(angle), -width * 0.5f); } gl.glEnd(); - + /* draw back sides of teeth */ gl.glBegin(GL2.GL_QUADS); for (i = 0; i < teeth; i++) @@ -284,7 +418,7 @@ public class Gears implements GLEventListener { gl.glVertex3f(r1 * (float)Math.cos(angle), r1 * (float)Math.sin(angle), -width * 0.5f); } gl.glEnd(); - + /* draw outward faces of teeth */ gl.glBegin(GL2.GL_QUAD_STRIP); for (i = 0; i < teeth; i++) @@ -313,9 +447,9 @@ public class Gears implements GLEventListener { gl.glVertex3f(r1 * (float)Math.cos(0), r1 * (float)Math.sin(0), width * 0.5f); gl.glVertex3f(r1 * (float)Math.cos(0), r1 * (float)Math.sin(0), -width * 0.5f); gl.glEnd(); - + gl.glShadeModel(GL2.GL_SMOOTH); - + /* draw inside radius cylinder */ gl.glBegin(GL2.GL_QUAD_STRIP); for (i = 0; i <= teeth; i++) @@ -328,7 +462,7 @@ public class Gears implements GLEventListener { gl.glEnd(); } - class GearsKeyAdapter extends KeyAdapter { + class GearsKeyAdapter extends KeyAdapter { public void keyPressed(KeyEvent e) { int kc = e.getKeyCode(); if(KeyEvent.VK_LEFT == kc) { @@ -342,7 +476,7 @@ public class Gears implements GLEventListener { } } } - + class GearsMouseAdapter extends MouseAdapter { public void mousePressed(MouseEvent e) { prevMouseX = e.getX(); @@ -351,13 +485,13 @@ public class Gears implements GLEventListener { // mouseRButtonDown = true; } } - + public void mouseReleased(MouseEvent e) { if ((e.getModifiers() & InputEvent.BUTTON3_MASK) != 0) { // mouseRButtonDown = false; } } - + public void mouseDragged(MouseEvent e) { int x = e.getX(); int y = e.getY(); @@ -376,7 +510,7 @@ public class Gears implements GLEventListener { } float thetaY = 360.0f * ( (float)(x-prevMouseX)/(float)width); float thetaX = 360.0f * ( (float)(prevMouseY-y)/(float)height); - + prevMouseX = x; prevMouseY = y; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Teapot.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Teapot.java new file mode 100644 index 000000000..dac917ee2 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Teapot.java @@ -0,0 +1,124 @@ +package com.jogamp.opengl.test.junit.jogl.demos.gl2; + +import java.net.URLConnection; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; + +import com.jogamp.common.util.IOUtil; +import com.jogamp.opengl.util.gl2.GLUT; +import com.jogamp.opengl.util.texture.Texture; +import com.jogamp.opengl.util.texture.TextureIO; + +/** + * Adapted from + * http://www.java-tips.org/other-api-tips/jogl/how-to-draw-a-texture-mapped-teapot-with-automatically-generated-texture-coordi.html + */ +public class Teapot implements GLEventListener { + + private GLUT glut; + + /* glTexGen stuff: */ + private float sgenparams[] = { 1.0f, 1.0f, 1.0f, 0.0f }; + + private Texture tex = null; + + @Override + public void init(GLAutoDrawable drawable) { + GL2 gl = drawable.getGL().getGL2(); + glut = new GLUT(); + + gl.glClearColor(0.5f, 0.5f, 0.5f, 0.0f); + + try { + URLConnection urlConn = IOUtil.getResource("jogl/util/data/av/test-ntsc01-57x32.png", this.getClass().getClassLoader()); + tex = TextureIO.newTexture(gl, TextureIO.newTextureData(gl.getGLProfile(), urlConn.getInputStream(), false, TextureIO.PNG)); + } catch (Exception e) { + e.printStackTrace(); + } + tex.bind(gl); + + // uncomment this and comment the above to see a working texture + // makeStripeImage(); + // gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1); + // gl.glTexEnvf(GL2.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE, + // GL2.GL_MODULATE); + // gl.glTexParameterf(GL2.GL_TEXTURE_1D, GL.GL_TEXTURE_WRAP_S, + // GL.GL_REPEAT); + // gl.glTexParameterf(GL2.GL_TEXTURE_1D, GL.GL_TEXTURE_MAG_FILTER, + // GL.GL_LINEAR); + // gl.glTexParameterf(GL2.GL_TEXTURE_1D, GL.GL_TEXTURE_MIN_FILTER, + // GL.GL_LINEAR); + // gl.glTexImage1D(GL2.GL_TEXTURE_1D, 0, 3, stripeImageWidth, 0, + // GL.GL_RGB, GL.GL_UNSIGNED_BYTE, stripeImageBuf); + + gl.glTexParameterf(GL2.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT); + + // gl.glTexGeni(GL2.GL_S, GL2.GL_TEXTURE_GEN_MODE, GL2.GL_OBJECT_LINEAR); + // gl.glTexGenfv(GL2.GL_S, GL2.GL_OBJECT_PLANE, sgenparams, 0); + + gl.glEnable(GL.GL_DEPTH_TEST); + gl.glDepthFunc(GL.GL_LESS); + // gl.glEnable(GL2.GL_TEXTURE_GEN_S); + // gl.glEnable(GL2.GL_TEXTURE_1D); + gl.glEnable(GL2.GL_TEXTURE_2D); + gl.glEnable(GL2.GL_CULL_FACE); + gl.glEnable(GL2.GL_LIGHTING); + gl.glEnable(GL2.GL_LIGHT0); + gl.glEnable(GL2.GL_AUTO_NORMAL); + gl.glEnable(GL2.GL_NORMALIZE); + gl.glFrontFace(GL.GL_CW); + gl.glCullFace(GL.GL_BACK); + gl.glMaterialf(GL.GL_FRONT, GL2.GL_SHININESS, 64.0f); + } + + float angleZ = 0.0f; + float rotDir = 1.0f; + public float rotIncr = 0.4f; + + @Override + public void display(GLAutoDrawable gLDrawable) { + final GL2 gl = gLDrawable.getGL().getGL2(); + + tex.bind(gl); + gl.glEnable(GL2.GL_TEXTURE_2D); + + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + gl.glPushMatrix(); + gl.glRotatef(angleZ, 0.0f, 1.0f, 0.0f); + gl.glRotatef(45.0f, 0.0f, 0.0f, 1.0f); + glut.glutSolidTeapot(2.0f); + gl.glPopMatrix(); + gl.glFlush(); + if( angleZ >= 180.0f ) { + rotDir = -1.0f; + } else if (angleZ <= 0.0f ) { + rotDir = +1.0f; + } + angleZ += rotIncr * rotDir; + } + + @Override + public void reshape(GLAutoDrawable gLDrawable, int x, int y, int w, int h) { + GL2 gl = gLDrawable.getGL().getGL2(); + + gl.glViewport(0, 0, w, h); + gl.glMatrixMode(GL2.GL_PROJECTION); + gl.glLoadIdentity(); + if (w <= h) { + gl.glOrtho(-3.5, 3.5, -3.5 * (float) h / (float) w, + 3.5 * (float) h / (float) w, -3.5, 3.5); + } else { + gl.glOrtho(-3.5 * (float) w / (float) h, + 3.5 * (float) w / (float) h, -3.5, 3.5, -3.5, 3.5); + } + gl.glMatrixMode(GL2.GL_MODELVIEW); + gl.glLoadIdentity(); + } + + @Override + public void dispose(GLAutoDrawable gLDrawable) { + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/gl2/TextureGL2ListenerDraw1.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/TextureDraw01GL2Listener.java index 084caa682..fb8e6bfa3 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/gl2/TextureGL2ListenerDraw1.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/TextureDraw01GL2Listener.java @@ -26,8 +26,9 @@ * or implied, of JogAmp Community. */ -package com.jogamp.opengl.test.junit.jogl.util.texture.gl2; +package com.jogamp.opengl.test.junit.jogl.demos.gl2; +import com.jogamp.opengl.test.junit.jogl.demos.TextureDraw01Accessor; import com.jogamp.opengl.util.texture.Texture; import com.jogamp.opengl.util.texture.TextureCoords; import com.jogamp.opengl.util.texture.TextureData; @@ -38,25 +39,39 @@ import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLEventListener; import javax.media.opengl.glu.GLU; -public class TextureGL2ListenerDraw1 implements GLEventListener { +public class TextureDraw01GL2Listener implements GLEventListener, TextureDraw01Accessor { private GLU glu = new GLU(); private TextureData textureData; private Texture texture; + boolean keepTextureBound; - public TextureGL2ListenerDraw1(TextureData td) { + public TextureDraw01GL2Listener(TextureData td) { this.textureData = td; + this.keepTextureBound = false; } + @Override + public void setKeepTextureBound(boolean v) { + this.keepTextureBound = v; + } + @Override + public Texture getTexture( ) { + return this.texture; + } + + @Override public void init(GLAutoDrawable drawable) { + GL2 gl = drawable.getGL().getGL2(); if(null!=textureData) { - this.texture = TextureIO.newTexture(textureData); + this.texture = TextureIO.newTexture(drawable.getGL(), textureData); + if( keepTextureBound ) { + texture.enable(gl); + texture.bind(gl); + } } } - public void setTexture( Texture texture ) { - this.texture = texture; - } - + @Override public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { GL2 gl = drawable.getGL().getGL2(); gl.glMatrixMode(GL2ES1.GL_PROJECTION); @@ -66,6 +81,7 @@ public class TextureGL2ListenerDraw1 implements GLEventListener { gl.glLoadIdentity(); } + @Override public void dispose(GLAutoDrawable drawable) { GL2 gl = drawable.getGL().getGL2(); if(null!=texture) { @@ -77,22 +93,16 @@ public class TextureGL2ListenerDraw1 implements GLEventListener { } } + @Override public void display(GLAutoDrawable drawable) { GL2 gl = drawable.getGL().getGL2(); - // need a valid GL context for this .. - - /** OpenGL .. - texture.updateSubImage(textureData, 0, - 20, 20, - 20, 20, - 100, 100); */ - - - // Now draw one quad with the texture + // draw one quad with the texture if(null!=texture) { - texture.enable(gl); - texture.bind(gl); + if( !keepTextureBound ) { + texture.enable(gl); + texture.bind(gl); + } gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_REPLACE); TextureCoords coords = texture.getImageTexCoords(); gl.glBegin(GL2.GL_QUADS); @@ -105,7 +115,9 @@ public class TextureGL2ListenerDraw1 implements GLEventListener { gl.glTexCoord2f(coords.left(), coords.top()); gl.glVertex3f(0, 1, 0); gl.glEnd(); - texture.disable(gl); + if( !keepTextureBound ) { + texture.disable(gl); + } } } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/Bug818GLJPanelApplet.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/Bug818GLJPanelApplet.java new file mode 100644 index 000000000..7e3d78b92 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/Bug818GLJPanelApplet.java @@ -0,0 +1,306 @@ +/**
+ * Copyright 2013 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.jogl.demos.gl2.awt;
+
+import java.awt.Dimension;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.GL2ES1;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.awt.GLCanvas;
+import javax.media.opengl.awt.GLJPanel;
+import javax.media.opengl.fixedfunc.GLLightingFunc;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+import javax.swing.JApplet;
+import javax.swing.JPanel;
+import javax.swing.JFrame;
+
+import com.jogamp.common.util.VersionUtil;
+import com.jogamp.opengl.JoglVersion;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.texture.Texture;
+import com.jogamp.opengl.util.texture.TextureIO;
+
+/**
+ * Bug 818: OSX GLJPanel Crash
+ * <pre>
+ * - NVIDIA GeForce GT 330M
+ * - GL_VENDOR: "NVIDIA Corporation"
+ * - GL_RENDERER: "NVIDIA GeForce GT 330M OpenGL Engine"
+ * - GL_VERSION: "2.1 NVIDIA-8.12.47 310.40.00.05f01"
+ * - Mac OSX 10.6.8
+ * </pre>
+ */
+public class Bug818GLJPanelApplet extends JApplet {
+
+ private static final long serialVersionUID = 1L;
+
+ private Animator animatorCanvas;
+
+ private Animator animatorPanel;
+
+ public static JFrame frame;
+ public static JPanel appletHolder;
+ public static boolean isApplet = true;
+
+ static public void main(String args[]) {
+ isApplet = false;
+
+ final JApplet myApplet = new Bug818GLJPanelApplet();
+
+ appletHolder = new JPanel();
+
+ frame = new JFrame("Bug818GLJPanelApplet");
+ frame.getContentPane().add(myApplet);
+
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ frame.addWindowListener(new WindowAdapter() {
+ public void windowClosing(WindowEvent e) {
+ System.exit(0);
+ }
+ });
+
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ myApplet.init();
+ frame.validate();
+ frame.pack();
+ frame.setVisible(true);
+ } } );
+ } catch( Throwable throwable ) {
+ throwable.printStackTrace();
+ }
+
+ myApplet.start();
+ }
+
+
+ @Override
+ public void init() {
+
+ final JPanel panel = new JPanel();
+ setContentPane(panel);
+
+ final GLCanvas glCanvas = new GLCanvas();
+ glCanvas.addGLEventListener(new JOGLQuad(true));
+ animatorCanvas = new Animator(glCanvas);
+ glCanvas.setPreferredSize(new Dimension(300, 300));
+ panel.add(glCanvas);
+
+ final GLJPanel gljPanel = new GLJPanel();
+ gljPanel.addGLEventListener(new JOGLQuad(false));
+ animatorPanel = new Animator(gljPanel);
+ gljPanel.setPreferredSize(new Dimension(300, 300));
+ panel.add(gljPanel);
+ }
+
+ @Override
+ public void start() {
+
+ animatorCanvas.start();
+ animatorCanvas.setUpdateFPSFrames(60, System.err);
+ animatorPanel.start();
+ animatorPanel.setUpdateFPSFrames(60, System.err);
+ }
+
+ @Override
+ public void stop() {
+
+ animatorCanvas.stop();
+ animatorPanel.stop();
+ }
+
+ @Override
+ public void destroy() {}
+
+ /**
+ * Self-contained example (within a single class only to keep it simple) displaying a rotating quad
+ */
+ static class JOGLQuad implements GLEventListener {
+
+ private static final float[] VERTEX_DATA = {
+ -1.0f, 1.0f, 0.0f, // Top Left
+ 1.0f, 1.0f, 0.0f, // Top Right
+ 1.0f, -1.0f, 0.0f, // Bottom Right
+ -1.0f, -1.0f, 0.0f // Bottom Left
+ };
+
+ private static final float[] TEXCOORD_DATA = {
+ 0.0f, 1.0f, // Top Left
+ 1.0f, 1.0f, // Top Right
+ 1.0f, 0.0f, // Bottom Right
+ 0.0f, 0.0f // Bottom Left
+ };
+
+ private FloatBuffer vertexBuf;
+
+ private FloatBuffer texCoordBuf;
+
+ private int vertexVBO;
+
+ private int texCoordVBO;
+
+ private float rotateT = 0.0f;
+
+ private boolean canvas;
+
+ private Texture texture;
+
+ JOGLQuad(boolean canvas) {
+
+ this.canvas = canvas;
+
+ ByteBuffer bb = ByteBuffer.allocateDirect(VERTEX_DATA.length * 4);
+ bb.order(ByteOrder.nativeOrder());
+ vertexBuf = bb.asFloatBuffer();
+ vertexBuf.put(VERTEX_DATA);
+ vertexBuf.rewind();
+
+ bb = ByteBuffer.allocateDirect(TEXCOORD_DATA.length * 4);
+ bb.order(ByteOrder.nativeOrder());
+ texCoordBuf = bb.asFloatBuffer();
+ texCoordBuf.put(TEXCOORD_DATA);
+ texCoordBuf.rewind();
+ }
+
+ @Override
+ public void init(GLAutoDrawable glDrawable) {
+
+ final GL2 gl = glDrawable.getGL().getGL2();
+
+ System.err.println(VersionUtil.getPlatformInfo());
+ System.err.println(JoglVersion.getGLInfo(gl, null, false /* withCapabilitiesAndExtensionInfo */).toString());
+
+ gl.glShadeModel(GLLightingFunc.GL_SMOOTH);
+ gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ gl.glClearDepth(1.0f);
+ gl.glEnable(GL.GL_DEPTH_TEST);
+ gl.glDepthFunc(GL.GL_LEQUAL);
+ gl.glHint(GL2ES1.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);
+
+ int[] tmp = new int[2];
+ gl.glGenBuffers(tmp.length, tmp, 0);
+ vertexVBO = tmp[0];
+ texCoordVBO = tmp[1];
+
+ gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, vertexVBO);
+ gl.glBufferData(GL2.GL_ARRAY_BUFFER, VERTEX_DATA.length * 4, vertexBuf, GL2.GL_STATIC_DRAW);
+ gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, texCoordVBO);
+ gl.glBufferData(GL2.GL_ARRAY_BUFFER, TEXCOORD_DATA.length * 4, texCoordBuf, GL2.GL_STATIC_DRAW);
+ gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0);
+
+ try {
+ InputStream stream = getClass().getClassLoader().getResourceAsStream("com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90-90pct-yuv444-base.jpg");
+ texture = TextureIO.newTexture(stream, true, TextureIO.JPG);
+ } catch (Exception exc) {
+ exc.printStackTrace(System.err);
+ }
+ }
+
+ @Override
+ public void dispose(GLAutoDrawable drawable) {
+
+ final GL2 gl = drawable.getGL().getGL2();
+ int[] tmp = new int[] {vertexVBO, texCoordVBO};
+ gl.glGenBuffers(tmp.length, tmp, 0);
+ }
+
+ @Override
+ public void reshape(GLAutoDrawable gLDrawable, int x, int y, int width, int height) {
+
+ final GL2 gl = gLDrawable.getGL().getGL2();
+ final float aspect = (float) width / (float) height;
+ gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ gl.glLoadIdentity();
+ final float fh = 0.5f;
+ final float fw = fh * aspect;
+ gl.glFrustumf(-fw, fw, -fh, fh, 1.0f, 1000.0f);
+ gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ gl.glLoadIdentity();
+ }
+
+ @Override
+ public void display(GLAutoDrawable gLDrawable) {
+
+ final GL2 gl = gLDrawable.getGL().getGL2();
+
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ gl.glLoadIdentity();
+ gl.glTranslatef(0.0f, 0.0f, -5.0f);
+
+ // rotate about the three axes
+ gl.glRotatef(rotateT, 1.0f, 0.0f, 0.0f);
+ gl.glRotatef(rotateT, 0.0f, 1.0f, 0.0f);
+ gl.glRotatef(rotateT, 0.0f, 0.0f, 1.0f);
+
+ // set the color of the quad
+ if (canvas) {
+ gl.glColor3f(0.2f, 1.0f, 1.0f);
+ } else {
+ gl.glColor3f(1.0f, 0.2f, 0.2f);
+ }
+
+ if (texture != null) {
+ texture.bind(gl);
+ texture.enable(gl);
+ } else {
+ System.err.println("no texture");
+ }
+
+ // Draw A Quad
+ gl.glEnableClientState(GL2.GL_VERTEX_ARRAY);
+ gl.glEnableClientState(GL2.GL_TEXTURE_COORD_ARRAY);
+ gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, vertexVBO);
+ gl.glVertexPointer(3, GL2.GL_FLOAT, 0, 0);
+ gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, texCoordVBO);
+ gl.glTexCoordPointer(2, GL2.GL_FLOAT, 0, 0);
+ gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0);
+ gl.glDrawArrays(GL2.GL_QUADS, 0, 4);
+ gl.glDisableClientState(GL2.GL_TEXTURE_COORD_ARRAY);
+ gl.glDisableClientState(GL2.GL_VERTEX_ARRAY);
+
+ if (texture != null) {
+ texture.disable(gl);
+ }
+
+ // increasing rotation for the next iteration
+ rotateT += 0.2f;
+ }
+
+ }
+}
+
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsGLJPanelAWTBug450.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGLJPanelAWTBug450.java index 7207e7815..0a8c406fb 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsGLJPanelAWTBug450.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGLJPanelAWTBug450.java @@ -30,11 +30,13 @@ import javax.media.opengl.*; import com.jogamp.opengl.util.FPSAnimator; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; import javax.media.opengl.awt.GLJPanel; import javax.media.opengl.glu.gl2.GLUgl2; -import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; import com.jogamp.opengl.test.junit.util.UITestCase; import java.awt.AWTException; import java.awt.BorderLayout; @@ -48,6 +50,8 @@ import org.junit.Assert; import org.junit.BeforeClass; import org.junit.AfterClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; /** * Test for bug 450, which causes the right part of the frame to be black @@ -59,23 +63,23 @@ import org.junit.Test; * * @author Wade Walker (adapted from TestGearsGLJPanelAWT) */ -public class TestGearsGLJPanelAWTBug450 extends UITestCase { +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLJPanelAWTBug450 extends UITestCase { static GLProfile glp; static int width, height; + static int r_x, r_y; /** Set this if test fails. Needed because we can't throw an exception * all the way up the stack from where we test the pixel. */ static boolean failed; @BeforeClass public static void initClass() { - if(GLProfile.isAvailable(GLProfile.GL2)) { - glp = GLProfile.get(GLProfile.GL2); - Assert.assertNotNull(glp); - width = 512; - height = 256; - } else { - setTestSupported(false); - } + glp = GLProfile.getGL2ES2(); + Assert.assertNotNull(glp); + height = 256; + width = 2*height; + r_x = 5*height/4; // 5/8 * width + r_y = height/2; } @AfterClass @@ -85,37 +89,54 @@ public class TestGearsGLJPanelAWTBug450 extends UITestCase { protected void runTestGL(GLCapabilities caps) throws AWTException, InterruptedException, InvocationTargetException { - JFrame frame = new JFrame("Swing GLJPanel"); + final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); + final JFrame frame = new JFrame("Swing GLJPanel"); Assert.assertNotNull(frame); - GLJPanel glJPanel = new GLJPanel(caps); + final GLJPanel glJPanel = new GLJPanel(caps); Assert.assertNotNull(glJPanel); - glJPanel.addGLEventListener(new Gears() { + RedSquareES2 demo = new RedSquareES2(); + demo.setAspect((float)width/(float)height); + demo.setDoRotation(false); + glJPanel.addGLEventListener(demo); + glJPanel.addGLEventListener(new GLEventListener() { + int f = 0; + @Override + public void init(GLAutoDrawable drawable) { + // drawable.getGL().glClearColor(0, 0, 1, 1); + } @Override public void display(GLAutoDrawable drawable) { - super.display(drawable); // look at one pixel at the bottom of the frame, just right of // the center line, and make sure it's not black GL2 gl = GLUgl2.getCurrentGL2(); ByteBuffer bytebuffer = ByteBuffer.allocateDirect( 3 ); - gl.glReadPixels( 260, 10, 1, 1, GL2.GL_BGR, GL2.GL_UNSIGNED_BYTE, bytebuffer ); + gl.glReadPixels( r_x, r_y, 1, 1, GL2.GL_BGR, GL2.GL_UNSIGNED_BYTE, bytebuffer ); byte byte0 = bytebuffer.get( 0 ); byte byte1 = bytebuffer.get( 1 ); byte byte2 = bytebuffer.get( 2 ); - if( (byte0 == 0) && (byte1 == 0) && (byte2 == 0) ) + if( (byte0 == 0) && (byte1 == 0) && (byte2 == 0) ) { failed = true; + } + if(0 == f) { + System.err.println("BGR ("+r_x+"/"+r_y+"): "+byte0+", "+byte1+", "+byte2+" - OK "+(!failed)); + snapshot(f, null, gl, screenshot, TextureIO.PNG, null); + } + f++; } + @Override + public void dispose(GLAutoDrawable drawable) {} + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } }); FPSAnimator animator = new FPSAnimator(glJPanel, 60); - final JFrame _frame = frame; - final GLJPanel _glJPanel = glJPanel; SwingUtilities.invokeAndWait(new Runnable() { public void run() { - _frame.getContentPane().add(_glJPanel, BorderLayout.CENTER); - _frame.setSize(width, height); - _frame.setVisible(true); + frame.getContentPane().add(glJPanel, BorderLayout.CENTER); + frame.setSize(width, height); + frame.setVisible(true); } } ) ; animator.setUpdateFPSFrames(1, null); @@ -134,11 +155,11 @@ public class TestGearsGLJPanelAWTBug450 extends UITestCase { Assert.assertEquals(false, animator.isAnimating()); SwingUtilities.invokeAndWait(new Runnable() { public void run() { - _frame.setVisible(false); - _frame.getContentPane().remove(_glJPanel); - _frame.remove(_glJPanel); - _glJPanel.destroy(); - _frame.dispose(); + frame.setVisible(false); + frame.getContentPane().remove(glJPanel); + frame.remove(glJPanel); + glJPanel.destroy(); + frame.dispose(); } } ); Assert.assertFalse( failed ); @@ -163,6 +184,6 @@ public class TestGearsGLJPanelAWTBug450 extends UITestCase { } catch (Exception ex) { ex.printStackTrace(); } } } - org.junit.runner.JUnitCore.main(TestGearsGLJPanelAWTBug450.class.getName()); + org.junit.runner.JUnitCore.main(TestGLJPanelAWTBug450.class.getName()); } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsAWT.java index ff24979eb..24a6d578c 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsAWT.java @@ -40,6 +40,8 @@ import com.jogamp.newt.event.TraceWindowAdapter; import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.util.QuitAdapter; + +import java.awt.Dimension; import java.awt.Frame; import java.io.BufferedReader; import java.io.IOException; @@ -50,19 +52,23 @@ import org.junit.Assert; import org.junit.BeforeClass; import org.junit.AfterClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestGearsAWT extends UITestCase { static GLProfile glp; static int width, height; static boolean waitForKey = false; + static int msaaCount = 0; @BeforeClass public static void initClass() { if(GLProfile.isAvailable(GLProfile.GL2)) { glp = GLProfile.get(GLProfile.GL2); Assert.assertNotNull(glp); - width = 512; - height = 512; + width = 640; + height = 480; } else { setTestSupported(false); } @@ -80,8 +86,11 @@ public class TestGearsAWT extends UITestCase { final GLCanvas glCanvas = new GLCanvas(caps); Assert.assertNotNull(glCanvas); + Dimension glc_sz = new Dimension(width, height); + glCanvas.setMinimumSize(glc_sz); + glCanvas.setPreferredSize(glc_sz); + glCanvas.setSize(glc_sz); frame.add(glCanvas); - frame.setSize(512, 512); glCanvas.addGLEventListener(new Gears(1)); @@ -93,6 +102,7 @@ public class TestGearsAWT extends UITestCase { javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame.pack(); frame.setVisible(true); }}); animator.setUpdateFPSFrames(60, System.err); @@ -108,7 +118,10 @@ public class TestGearsAWT extends UITestCase { animator.stop(); Assert.assertEquals(false, animator.isAnimating()); - frame.setVisible(false); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + }}); Assert.assertEquals(false, frame.isVisible()); javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { @@ -120,6 +133,10 @@ public class TestGearsAWT extends UITestCase { @Test public void test01() throws InterruptedException, InvocationTargetException { GLCapabilities caps = new GLCapabilities(glp); + if( msaaCount > 0 ) { + caps.setSampleBuffers(true); + caps.setNumSamples(msaaCount); + } runTestGL(caps); } @@ -132,9 +149,14 @@ public class TestGearsAWT extends UITestCase { try { duration = Integer.parseInt(args[i]); } catch (Exception ex) { ex.printStackTrace(); } + } else if(args[i].equals("-msaa")) { + i++; + try { + msaaCount = Integer.parseInt(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } } else if(args[i].equals("-wait")) { waitForKey = true; - } + } } if(waitForKey) { BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsAWTAnalyzeBug455.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsAWTAnalyzeBug455.java index 4807e5d25..66b9e4a78 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsAWTAnalyzeBug455.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsAWTAnalyzeBug455.java @@ -50,7 +50,10 @@ import org.junit.Assert; import org.junit.BeforeClass; import org.junit.AfterClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestGearsAWTAnalyzeBug455 extends UITestCase { static long duration = 500; // ms static boolean waitForKey = false; // for manual profiling @@ -105,7 +108,6 @@ public class TestGearsAWTAnalyzeBug455 extends UITestCase { Assert.assertNotNull(glCanvas); glCanvas.setAutoSwapBufferMode(!altSwap); frame.add(glCanvas); - frame.setSize(512, 512); glCanvas.addGLEventListener(new Gears(0)); glCanvas.addGLEventListener(new Swapper()); @@ -118,6 +120,7 @@ public class TestGearsAWTAnalyzeBug455 extends UITestCase { javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame.setSize(512, 512); frame.setVisible(true); }}); animator.setUpdateFPSFrames(60, System.err); @@ -133,7 +136,10 @@ public class TestGearsAWTAnalyzeBug455 extends UITestCase { animator.stop(); Assert.assertEquals(false, animator.isAnimating()); - frame.setVisible(false); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + }}); Assert.assertEquals(false, frame.isVisible()); javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsGLJPanelAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsGLJPanelAWT.java index c7254dda6..5de08c738 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsGLJPanelAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsGLJPanelAWT.java @@ -30,13 +30,21 @@ package com.jogamp.opengl.test.junit.jogl.demos.gl2.awt; import javax.media.opengl.*; +import com.jogamp.newt.event.TraceKeyAdapter; +import com.jogamp.newt.event.TraceWindowAdapter; +import com.jogamp.newt.event.awt.AWTKeyAdapter; +import com.jogamp.newt.event.awt.AWTWindowAdapter; import com.jogamp.opengl.util.FPSAnimator; import javax.media.opengl.awt.GLJPanel; import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.QuitAdapter; import com.jogamp.opengl.test.junit.util.UITestCase; + import java.awt.AWTException; import java.awt.BorderLayout; +import java.awt.Dimension; import java.lang.reflect.InvocationTargetException; import javax.swing.JFrame; import javax.swing.SwingUtilities; @@ -45,18 +53,27 @@ import org.junit.Assert; import org.junit.BeforeClass; import org.junit.AfterClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestGearsGLJPanelAWT extends UITestCase { static GLProfile glp; static int width, height; + static boolean shallUsePBuffer = false; + static boolean shallUseBitmap = false; + static boolean useMSAA = false; + static int swapInterval = 0; + static boolean useAnimator = true; + static boolean manualTest = false; @BeforeClass public static void initClass() { if(GLProfile.isAvailable(GLProfile.GL2)) { glp = GLProfile.get(GLProfile.GL2); Assert.assertNotNull(glp); - width = 512; - height = 512; + width = 640; + height = 480; } else { setTestSupported(false); } @@ -69,67 +86,184 @@ public class TestGearsGLJPanelAWT extends UITestCase { protected void runTestGL(GLCapabilities caps) throws AWTException, InterruptedException, InvocationTargetException { - JFrame frame = new JFrame("Swing GLJPanel"); + final JFrame frame = new JFrame("Swing GLJPanel"); Assert.assertNotNull(frame); - GLJPanel glJPanel = new GLJPanel(caps); + final GLJPanel glJPanel = new GLJPanel(caps); Assert.assertNotNull(glJPanel); - glJPanel.addGLEventListener(new Gears()); + Dimension glc_sz = new Dimension(width, height); + glJPanel.setMinimumSize(glc_sz); + glJPanel.setPreferredSize(glc_sz); + glJPanel.setSize(glc_sz); + glJPanel.addGLEventListener(new Gears(swapInterval)); + final SnapshotGLEventListener snap = new SnapshotGLEventListener(); + glJPanel.addGLEventListener(snap); - FPSAnimator animator = new FPSAnimator(glJPanel, 60); + final FPSAnimator animator = useAnimator ? new FPSAnimator(glJPanel, 60) : null; - final JFrame _frame = frame; - final GLJPanel _glJPanel = glJPanel; SwingUtilities.invokeAndWait(new Runnable() { public void run() { - _frame.getContentPane().add(_glJPanel, BorderLayout.CENTER); - _frame.setSize(512, 512); - _frame.setVisible(true); + frame.getContentPane().add(glJPanel, BorderLayout.CENTER); + frame.getContentPane().validate(); + frame.pack(); + frame.setVisible(true); } } ) ; - animator.setUpdateFPSFrames(1, null); - animator.start(); - Assert.assertEquals(true, animator.isAnimating()); + if( useAnimator ) { + animator.setUpdateFPSFrames(60, System.err); + animator.start(); + Assert.assertEquals(true, animator.isAnimating()); + } + + QuitAdapter quitAdapter = new QuitAdapter(); - while(animator.isAnimating() && animator.getTotalFPSDuration()<duration) { + new AWTKeyAdapter(new TraceKeyAdapter(quitAdapter)).addTo(glJPanel); + new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter)).addTo(frame); + + final long t0 = System.currentTimeMillis(); + long t1 = t0; + boolean triggerSnap = false; + while(!quitAdapter.shouldQuit() && t1 - t0 < duration) { Thread.sleep(100); + t1 = System.currentTimeMillis(); + snap.getDisplayCount(); + if( !triggerSnap && snap.getDisplayCount() > 1 ) { + // Snapshot only after one frame has been rendered to suite FBO MSAA! + snap.setMakeSnapshot(); + triggerSnap = true; + } } Assert.assertNotNull(frame); Assert.assertNotNull(glJPanel); Assert.assertNotNull(animator); - animator.stop(); - Assert.assertEquals(false, animator.isAnimating()); + if( useAnimator ) { + animator.stop(); + Assert.assertEquals(false, animator.isAnimating()); + } SwingUtilities.invokeAndWait(new Runnable() { public void run() { - _frame.setVisible(false); - _frame.getContentPane().remove(_glJPanel); - _frame.remove(_glJPanel); - _glJPanel.destroy(); - _frame.dispose(); + frame.setVisible(false); + frame.getContentPane().remove(glJPanel); + frame.remove(glJPanel); + glJPanel.destroy(); + frame.dispose(); } } ); } @Test - public void test01() + public void test01_DefaultNorm() throws AWTException, InterruptedException, InvocationTargetException { GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); + if(useMSAA) { + caps.setNumSamples(4); + caps.setSampleBuffers(true); + } + if(shallUsePBuffer) { + caps.setPBuffer(true); + } + if(shallUseBitmap) { + caps.setBitmap(true); + } runTestGL(caps); } + @Test + public void test02_DefaultMsaa() + throws AWTException, InterruptedException, InvocationTargetException + { + if( manualTest ) { + return; + } + GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); + caps.setNumSamples(4); + caps.setSampleBuffers(true); + runTestGL(caps); + } + + @Test + public void test03_PbufferNorm() + throws AWTException, InterruptedException, InvocationTargetException + { + if( manualTest ) { + return; + } + GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); + caps.setPBuffer(true); + runTestGL(caps); + } + + @Test + public void test04_PbufferMsaa() + throws AWTException, InterruptedException, InvocationTargetException + { + if( manualTest ) { + return; + } + GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); + caps.setNumSamples(4); + caps.setSampleBuffers(true); + caps.setPBuffer(true); + runTestGL(caps); + } + + @Test + public void test05_BitmapNorm() + throws AWTException, InterruptedException, InvocationTargetException + { + if( manualTest ) { + return; + } + GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); + caps.setBitmap(true); + runTestGL(caps); + } + + @Test + public void test06_BitmapMsaa() + throws AWTException, InterruptedException, InvocationTargetException + { + if( manualTest ) { + return; + } + GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); + caps.setNumSamples(4); + caps.setSampleBuffers(true); + caps.setBitmap(true); + runTestGL(caps); + } + static long duration = 500; // ms public static void main(String args[]) { for(int i=0; i<args.length; i++) { if(args[i].equals("-time")) { i++; - try { - duration = Integer.parseInt(args[i]); - } catch (Exception ex) { ex.printStackTrace(); } + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-vsync")) { + i++; + swapInterval = MiscUtils.atoi(args[i], swapInterval); + } else if(args[i].equals("-msaa")) { + useMSAA = true; + } else if(args[i].equals("-noanim")) { + useAnimator = false; + } else if(args[i].equals("-pbuffer")) { + shallUsePBuffer = true; + } else if(args[i].equals("-bitmap")) { + shallUseBitmap = true; + } else if(args[i].equals("-manual")) { + manualTest = true; } } + System.err.println("swapInterval "+swapInterval); + System.err.println("useMSAA "+useMSAA); + System.err.println("useAnimator "+useAnimator); + System.err.println("shallUsePBuffer "+shallUsePBuffer); + System.err.println("shallUseBitmap "+shallUseBitmap); + System.err.println("manualTest "+manualTest); + org.junit.runner.JUnitCore.main(TestGearsGLJPanelAWT.class.getName()); } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestGearsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestGearsNEWT.java index 0f3c7e2ba..a5134254b 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestGearsNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestGearsNEWT.java @@ -45,7 +45,10 @@ import org.junit.Assert; import org.junit.BeforeClass; import org.junit.AfterClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestGearsNEWT extends UITestCase { static GLProfile glp; static int width, height; @@ -55,8 +58,8 @@ public class TestGearsNEWT extends UITestCase { if(GLProfile.isAvailable(GLProfile.GL2)) { glp = GLProfile.get(GLProfile.GL2); Assert.assertNotNull(glp); - width = 512; - height = 512; + width = 640; + height = 480; } else { setTestSupported(false); } @@ -83,7 +86,10 @@ public class TestGearsNEWT extends UITestCase { final GLWindow f_glWindow = glWindow; glWindow.addKeyListener(new KeyAdapter() { - public void keyTyped(KeyEvent e) { + public void keyReleased(KeyEvent e) { + if( !e.isPrintableKey() || e.isAutoRepeat() ) { + return; + } if(e.getKeyChar()=='f') { new Thread() { public void run() { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestGearsNewtAWTWrapper.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestGearsNewtAWTWrapper.java index 54cfd0a99..84e6670c3 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestGearsNewtAWTWrapper.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestGearsNewtAWTWrapper.java @@ -33,6 +33,8 @@ import javax.media.opengl.*; import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +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 com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; @@ -44,17 +46,23 @@ import org.junit.Assert; import org.junit.BeforeClass; import org.junit.AfterClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestGearsNewtAWTWrapper extends UITestCase { static GLProfile glp; static int width, height; + static boolean useAnimator = true; + static boolean doResizeTest = true; + static long duration = 500; // ms @BeforeClass public static void initClass() { glp = GLProfile.getGL2ES2(); Assert.assertNotNull(glp); - width = 512; - height = 512; + width = 640; + height = 480; } @AfterClass @@ -72,22 +80,50 @@ public class TestGearsNewtAWTWrapper extends UITestCase { glWindow.addGLEventListener(new GearsES2(1)); - Animator animator = new Animator(glWindow); + Animator animator = useAnimator ? new Animator(glWindow) : null; QuitAdapter quitAdapter = new QuitAdapter(); glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter)); glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter)); - glWindow.setSize(width, height); + if( useAnimator ) { + animator.start(); + } + + int div = 3; + glWindow.setSize(width/div, height/div); glWindow.setVisible(true); - animator.setUpdateFPSFrames(1, null); - animator.start(); + if( doResizeTest ) { + glWindow.display(); + Assert.assertTrue("Size not reached: Expected "+(width/div)+"x"+(height/div)+", Is "+glWindow.getWidth()+"x"+glWindow.getHeight(), + AWTRobotUtil.waitForSize(glWindow, width/div, height/div)); + Thread.sleep(600); + + div = 2; + glWindow.setSize(width/div, height/div); + glWindow.display(); + Assert.assertTrue("Size not reached: Expected "+(width/div)+"x"+(height/div)+", Is "+glWindow.getWidth()+"x"+glWindow.getHeight(), + AWTRobotUtil.waitForSize(glWindow, width/div, height/div)); + Thread.sleep(600); + + div = 1; + glWindow.setSize(width/div, height/div); + glWindow.display(); + Assert.assertTrue("Size not reached: Expected "+(width/div)+"x"+(height/div)+", Is "+glWindow.getWidth()+"x"+glWindow.getHeight(), + AWTRobotUtil.waitForSize(glWindow, width/div, height/div)); + Thread.sleep(600); + } - while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) { + final long t0 = System.currentTimeMillis(); + long t1 = t0; + while(!quitAdapter.shouldQuit() && t1-t0<duration) { Thread.sleep(100); + t1 = System.currentTimeMillis(); } - animator.stop(); + if( useAnimator ) { + animator.stop(); + } glWindow.destroy(); } @@ -97,17 +133,18 @@ public class TestGearsNewtAWTWrapper extends UITestCase { runTestGL(caps); } - static long duration = 500; // ms - public static void main(String args[]) { for(int i=0; i<args.length; i++) { if(args[i].equals("-time")) { i++; - try { - duration = Integer.parseInt(args[i]); - } catch (Exception ex) { ex.printStackTrace(); } + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-noanim")) { + useAnimator = false; + } else if(args[i].equals("-noresize")) { + doResizeTest = false; } } + System.err.println("useAnimator "+useAnimator); org.junit.runner.JUnitCore.main(TestGearsNewtAWTWrapper.class.getName()); } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestTeapotNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestTeapotNEWT.java new file mode 100644 index 000000000..5a22fc7b1 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestTeapotNEWT.java @@ -0,0 +1,162 @@ +/** + * 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.jogl.demos.gl2.newt; + +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.test.junit.util.QuitAdapter; + +import com.jogamp.opengl.util.Animator; + +import com.jogamp.opengl.test.junit.jogl.demos.gl2.Teapot; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.AfterClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestTeapotNEWT extends UITestCase { + static GLProfile glp; + static int width, height; + + @BeforeClass + public static void initClass() { + if(GLProfile.isAvailable(GLProfile.GL2)) { + glp = GLProfile.get(GLProfile.GL2); + Assert.assertNotNull(glp); + width = 640; + height = 480; + } else { + setTestSupported(false); + } + } + + @AfterClass + public static void releaseClass() { + } + + protected void runTestGL(GLCapabilities caps, boolean withAnimator) throws InterruptedException { + final GLWindow glWindow = GLWindow.create(caps); + + glWindow.setTitle("Teapot NEWT Test"); + Teapot demo = new Teapot(); + if( !withAnimator ) { + demo.rotIncr *= 10f; + } + glWindow.addGLEventListener(demo); + final SnapshotGLEventListener snap = new SnapshotGLEventListener(); + glWindow.addGLEventListener(snap); + + final Animator animator = withAnimator ? new Animator(glWindow) : null; + final QuitAdapter quitAdapter = new QuitAdapter(); + + //glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter)); + //glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter)); + glWindow.addKeyListener(quitAdapter); + glWindow.addWindowListener(quitAdapter); + + glWindow.setSize(width, height); + glWindow.setVisible(true); + if( withAnimator ) { + animator.setUpdateFPSFrames(60, System.err); + animator.start(); + } + + final long t0 = System.currentTimeMillis(); + long t1 = t0; + int snaps=3; + while(!quitAdapter.shouldQuit() && t1-t0<duration) { + Thread.sleep(100); + t1 = System.currentTimeMillis(); + if( snaps-- > 0 ) { + snap.setMakeSnapshot(); + } + if( !withAnimator ) { + glWindow.display(); + } + } + + if( withAnimator ) { + animator.stop(); + } + glWindow.destroy(); + } + + @Test + public void test01_DefCaps_Anim() throws InterruptedException { + final GLCapabilities caps = new GLCapabilities(GLProfile.getMaxFixedFunc(true)); + runTestGL(caps, true); + } + + @Test + public void test02_DefCaps_NoAnim() throws InterruptedException { + final GLCapabilities caps = new GLCapabilities(GLProfile.getMaxFixedFunc(true)); + runTestGL(caps, false); + } + + @Test + public void test12_FBOCaps_NoAnim() throws InterruptedException { + final GLCapabilities caps = new GLCapabilities(GLProfile.getMaxFixedFunc(true)); + caps.setHardwareAccelerated(true); + caps.setDoubleBuffered(true); + caps.setAlphaBits(8); + caps.setDepthBits(8); + caps.setNumSamples(0); + caps.setSampleBuffers(false); + caps.setStencilBits(0); + caps.setRedBits(8); + caps.setBlueBits(8); + caps.setGreenBits(8); + + // caps.setPBuffer(true); + caps.setFBO(true); + + runTestGL(caps, false); + } + + static long duration = 500; // ms + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + try { + duration = Integer.parseInt(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } + } + org.junit.runner.JUnitCore.main(TestTeapotNEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/GeomShader01TextureGL3.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/GeomShader01TextureGL3.java new file mode 100644 index 000000000..e69286311 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/GeomShader01TextureGL3.java @@ -0,0 +1,293 @@ +/** + * Copyright 2013 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.jogl.demos.gl3; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URLConnection; +import java.nio.FloatBuffer; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GL3; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLException; +import javax.media.opengl.GLUniformData; +import javax.media.opengl.fixedfunc.GLMatrixFunc; + +import com.jogamp.common.util.IOUtil; +import com.jogamp.opengl.util.GLArrayDataServer; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; +import com.jogamp.opengl.util.glsl.ShaderState; +import com.jogamp.opengl.util.glsl.ShaderUtil; +import com.jogamp.opengl.util.texture.Texture; +import com.jogamp.opengl.util.texture.TextureCoords; +import com.jogamp.opengl.util.texture.TextureData; +import com.jogamp.opengl.util.texture.TextureIO; + +/** + * JOGL Geometry ShaderCode test case using OpenGL 3.2 core profile features only. + * <p> + * Demonstrates <code>pass through</code> and <code>XYZ flipping</code> + * geometry shader. + * </p> + * <p> + * If the <code>XYZ flipping</code> geometry shader functions properly, + * the texture will be flipped horizontally and vertically. + * </p> + * + * @author Chuck Ritola December 2012 + * @author Sven Gothel (GL3 core, pass-though, core geometry shader) + */ +public class GeomShader01TextureGL3 implements GLEventListener { + private final int geomShader; + private Texture texture; + private ShaderState st; + private PMVMatrix pmvMatrix; + private GLUniformData pmvMatrixUniform; + private GLArrayDataServer interleavedVBO; + + static final String shaderBasename = "texture01_xxx"; + static final String[] geomShaderBaseNames = new String[] { "passthrough01_xxx", "flipXYZ01_xxx" }; + + public GeomShader01TextureGL3(int geomShader) { + this.geomShader = geomShader; + } + + @Override + public void init(GLAutoDrawable drawable) { + { + final GL gl = drawable.getGL(); + System.err.println("Init - START - useGeomShader "+geomShader+" -> "+geomShaderBaseNames[geomShader]); + System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR)); + System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER)); + System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION)); + System.err.println("GL GLSL: "+gl.hasGLSL()+", has-compiler-func: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none")); + System.err.println("GL Profile: "+gl.getGLProfile()); + System.err.println("GL Renderer Quirks:" + gl.getContext().getRendererQuirks().toString()); + System.err.println("GL:" + gl + ", " + gl.getContext().getGLVersion()); + if( !gl.isGL3() ) { + throw new RuntimeException("GL object not a GL3 core compatible profile: "+gl); + } + if( !ShaderUtil.isGeometryShaderSupported(gl) ) { + throw new RuntimeException("GL object not >= 3.2, i.e. no geometry shader support.: "+gl); + } + } + final GL3 gl = drawable.getGL().getGL3(); + + final ShaderProgram sp; + { + final ShaderCode vs, gs, fs; + vs = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(), + "shader", "shader/bin", shaderBasename, true); + gs = ShaderCode.create(gl, GL3.GL_GEOMETRY_SHADER, this.getClass(), + "shader", "shader/bin", geomShaderBaseNames[geomShader], true); + fs = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(), + "shader", "shader/bin", shaderBasename, true); + vs.defaultShaderCustomization(gl, true, true); + gs.defaultShaderCustomization(gl, true, true); + fs.defaultShaderCustomization(gl, true, true); + + sp = new ShaderProgram(); + sp.add(gl, vs, System.err); + sp.add(gl, gs, System.err); + sp.add(gl, fs, System.err); + if(!sp.link(gl, System.err)) { + throw new GLException("Couldn't link program: "+sp); + } + } + + st=new ShaderState(); + st.attachShaderProgram(gl, sp, true); + + // setup mgl_PMVMatrix + pmvMatrix = new PMVMatrix(); + pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); // P, Mv + st.ownUniform(pmvMatrixUniform); + st.uniform(gl, pmvMatrixUniform); + + st.ownUniform(pmvMatrixUniform); + if(!st.uniform(gl, pmvMatrixUniform)) { + throw new GLException("Error setting PMVMatrix in shader: "+st); + } + if(!st.uniform(gl, new GLUniformData("mgl_ActiveTexture", 0))) { + throw new GLException("Error setting mgl_ActiveTexture in shader: "+st); + } + + try { + texture = createTestTexture(gl); + } catch (IOException e) { + throw new RuntimeException(e); + } + if(null == texture) { + throw new RuntimeException("Could not load test texture"); + } + + // Tri order: + // TL, BL, BR + // TL, TR, BR + { + int i=0; + TextureCoords tc = texture.getImageTexCoords(); + s_triTexCoords[i++] = tc.left(); s_triTexCoords[i++] = tc.top(); + s_triTexCoords[i++] = tc.left(); s_triTexCoords[i++] = tc.bottom(); + s_triTexCoords[i++] = tc.right(); s_triTexCoords[i++] = tc.bottom(); + s_triTexCoords[i++] = tc.left(); s_triTexCoords[i++] = tc.top(); + s_triTexCoords[i++] = tc.right(); s_triTexCoords[i++] = tc.top(); + s_triTexCoords[i++] = tc.right(); s_triTexCoords[i++] = tc.bottom(); + } + + interleavedVBO = GLArrayDataServer.createGLSLInterleaved(2+4+2, GL.GL_FLOAT, false, 3*6, GL.GL_STATIC_DRAW); + { + interleavedVBO.addGLSLSubArray("mgl_Vertex", 2, GL.GL_ARRAY_BUFFER); + interleavedVBO.addGLSLSubArray("mgl_Color", 4, GL.GL_ARRAY_BUFFER); + interleavedVBO.addGLSLSubArray("mgl_MultiTexCoord", 2, GL.GL_ARRAY_BUFFER); + + FloatBuffer ib = (FloatBuffer)interleavedVBO.getBuffer(); + + for(int i=0; i<6; i++) { + ib.put(s_triVertices, i*2, 2); + ib.put(s_triColors, i*4, 4); + ib.put(s_triTexCoords, i*2, 2); + } + } + interleavedVBO.seal(gl, true); + interleavedVBO.enableBuffer(gl, false); + st.ownAttribute(interleavedVBO, true); + + gl.glClearColor(0f, 0f, 0f, 0f); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + st.useProgram(gl, false); + } + + private Texture createTestTexture(GL3 gl) throws IOException { + final URLConnection urlConn = IOUtil.getResource(this.getClass(), "../../util/texture/test-ntscN_3-01-160x90.png"); + if(null == urlConn) { return null; } + final InputStream istream = urlConn.getInputStream(); + if(null == istream) { return null; } + final TextureData texData = TextureIO.newTextureData(gl.getGLProfile(), istream, false /* mipmap */, TextureIO.PNG); + final Texture res = TextureIO.newTexture(gl, texData); + texData.destroy(); + return res; + } + + @Override + public void dispose(GLAutoDrawable drawable) { + final GL3 gl = drawable.getGL().getGL3(); + if(null!=texture) { + texture.disable(gl); + texture.destroy(gl); + } + + if(null != st) { + pmvMatrixUniform = null; + pmvMatrix.destroy(); + pmvMatrix=null; + st.destroy(gl); + st=null; + } + } + + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + GL3 gl = drawable.getGL().getGL3(); + + gl.setSwapInterval(1); + + // Clear background to white + gl.glClearColor(1.0f, 1.0f, 1.0f, 0.4f); + + if(null != st) { + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glOrthof(-1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 10.0f); + + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + + st.useProgram(gl, true); + st.uniform(gl, pmvMatrixUniform); + st.useProgram(gl, false); + } + } + + @Override + public void display(GLAutoDrawable drawable) { + final GL3 gl = drawable.getGL().getGL3(); + + gl.glClear(GL.GL_DEPTH_BUFFER_BIT | GL.GL_COLOR_BUFFER_BIT); + + if(null != st) { + //Draw the image as a pseudo-quad using two triangles + st.useProgram(gl, true); + interleavedVBO.enableBuffer(gl, true); + gl.glActiveTexture(GL.GL_TEXTURE0); + texture.enable(gl); + texture.bind(gl); + + gl.glDrawArrays(GL.GL_TRIANGLES, 0, 6); + + texture.disable(gl); + interleavedVBO.enableBuffer(gl, false); + st.useProgram(gl, false); + } + }//end display() + + private static final float[] s_triVertices = { + -1f, 1f, // TL + -1f, -1f, // BL + 1f, -1f, // BR + -1f, 1f, // TL + 1f, 1f, // TR + 1f, -1f // BR + }; + private static final float[] s_triColors = { + 1f, 1f, 1f, 1f, + 1f, 1f, 1f, 1f, + 1f, 1f, 1f, 1f, + 1f, 1f, 1f, 1f, + 1f, 1f, 1f, 1f, + 1f, 1f, 1f, 1f + }; + private static final float[] s_triTexCoords = { + 0f, 1f, // TL + 0f, 0f, // BL + 1f, 0f, // BR + 0f, 1f, // TL + 1f, 1f, // TR + 1f, 0f // BR + }; + +}//end Test diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/newt/TestGeomShader01TextureGL3NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/newt/TestGeomShader01TextureGL3NEWT.java new file mode 100644 index 000000000..8e582bd3b --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/newt/TestGeomShader01TextureGL3NEWT.java @@ -0,0 +1,129 @@ +/** + * Copyright 2013 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.jogl.demos.gl3.newt; + +import java.io.IOException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.jogl.demos.gl3.GeomShader01TextureGL3; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; + +/** + * Test Geometry shader demo GeomShader01TextureGL3 + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGeomShader01TextureGL3NEWT extends UITestCase { + static long duration = 500; // ms + + static GLCapabilities getCaps(String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return new GLCapabilities(GLProfile.get(profile)); + } + + @Test + public void test01_GL3Core_Passthrough() throws InterruptedException { + GLCapabilities caps = getCaps(GLProfile.GL3); + if( null == caps ) { return; } + testImpl(caps, 0); + } + + @Test + public void test02_GL3Core_FlipXYZ() throws InterruptedException { + GLCapabilities caps = getCaps(GLProfile.GL3); + if( null == caps ) { return; } + testImpl(caps, 1); + } + + @Test + public void test11_GL3Compat_Passthrough() throws InterruptedException { + GLCapabilities caps = getCaps(GLProfile.GL3bc); + if( null == caps ) { return; } + testImpl(caps, 0); + } + + @Test + public void test12_GL3Compat_FlipXYZ() throws InterruptedException { + GLCapabilities caps = getCaps(GLProfile.GL3bc); + if( null == caps ) { return; } + testImpl(caps, 1); + } + + private void testImpl(GLCapabilities caps, int geomShader) throws InterruptedException { + GLWindow glWindow = GLWindow.create(caps); + Assert.assertNotNull(glWindow); + glWindow.setSize(800, 600); + glWindow.setVisible(true); + glWindow.setTitle("JOGL Geometry Shader Banana Test"); + Assert.assertTrue(glWindow.isNativeValid()); + + QuitAdapter quitAdapter = new QuitAdapter(); + glWindow.addKeyListener(quitAdapter); + glWindow.addWindowListener(quitAdapter); + glWindow.addGLEventListener( new GeomShader01TextureGL3(geomShader) ); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + glWindow.addGLEventListener(snapshotGLEventListener); + + final Animator animator = new Animator(glWindow); + animator.start(); + + animator.setUpdateFPSFrames(60, System.err); + snapshotGLEventListener.setMakeSnapshot(); + + while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) { + Thread.sleep(100); + } + + animator.stop(); + glWindow.destroy(); + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } + } + org.junit.runner.JUnitCore.main(TestGeomShader01TextureGL3NEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/shader/flipXYZ01_xxx.gp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/shader/flipXYZ01_xxx.gp new file mode 100644 index 000000000..f65ffacdb --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/shader/flipXYZ01_xxx.gp @@ -0,0 +1,32 @@ +// Copyright 2012 JogAmp Community. All rights reserved. +// Requires version >= 150 + +layout (triangles) in; +layout (triangle_strip, max_vertices=3) out; + +in VertexData { + vec4 frontColor; + vec2 texCoord; +} vp_data[3]; + +out VertexData { + vec4 frontColor; + vec2 texCoord; +} gp_data; + +void main() +{ + for(int i = 0; i < gl_in.length(); i++) + { + // copy attributes + gl_Position = vec4(gl_in[i].gl_Position.xyz*-1,1); // This line flips the coordinates. + gp_data.frontColor = vp_data[i].frontColor; + gp_data.texCoord = vp_data[i].texCoord; + + // done with the vertex + EmitVertex(); + } +} + + + diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/shader/passthrough01_xxx.gp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/shader/passthrough01_xxx.gp new file mode 100644 index 000000000..588b72426 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/shader/passthrough01_xxx.gp @@ -0,0 +1,31 @@ +// Copyright 2012 JogAmp Community. All rights reserved. +// Requires version >= 150 + +layout (triangles) in; +layout (triangle_strip, max_vertices=3) out; + +in VertexData { + vec4 frontColor; + vec2 texCoord; +} vp_data[3]; + +out VertexData { + vec4 frontColor; + vec2 texCoord; +} gp_data; + +void main() +{ + for(int i = 0; i < gl_in.length(); i++) + { + // copy attributes + gl_Position = gl_in[i].gl_Position; + gp_data.frontColor = vp_data[i].frontColor; + gp_data.texCoord = vp_data[i].texCoord; + + // done with the vertex + EmitVertex(); + } +} + + diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/shader/texture01_xxx.fp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/shader/texture01_xxx.fp new file mode 100644 index 000000000..61f4529ac --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/shader/texture01_xxx.fp @@ -0,0 +1,20 @@ +// Copyright 2012 JogAmp Community. All rights reserved. +// Requires version >= 130 + +in VertexData { + vec4 frontColor; + vec2 texCoord; +} gp_data; + +out vec4 mgl_FragColor; + +uniform sampler2D mgl_ActiveTexture; + +void main (void) +{ + vec4 texColor = texture(mgl_ActiveTexture, gp_data.texCoord); + + // mix frontColor with texture .. + mgl_FragColor = vec4(gp_data.frontColor*texColor); +} + diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/shader/texture01_xxx.vp b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/shader/texture01_xxx.vp new file mode 100644 index 000000000..b220c83f1 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/shader/texture01_xxx.vp @@ -0,0 +1,20 @@ +// Copyright 2012 JogAmp Community. All rights reserved. +// Requires version >= 130 + +uniform mat4 mgl_PMVMatrix[2]; + +in vec4 mgl_Vertex; +in vec4 mgl_Color; +in vec4 mgl_MultiTexCoord; + +out VertexData { + vec4 frontColor; + vec2 texCoord; +} vp_data; + +void main(void) +{ + vp_data.frontColor = mgl_Color; + vp_data.texCoord = mgl_MultiTexCoord.st; + gl_Position = mgl_PMVMatrix[0] * mgl_PMVMatrix[1] * mgl_Vertex; +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/drawable/TestDrawable01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/drawable/TestDrawable01NEWT.java deleted file mode 100644 index 731f7c867..000000000 --- a/src/test/com/jogamp/opengl/test/junit/jogl/drawable/TestDrawable01NEWT.java +++ /dev/null @@ -1,183 +0,0 @@ -/** - * 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.jogl.drawable; - -import com.jogamp.opengl.test.junit.util.UITestCase; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.AfterClass; -import org.junit.Test; - -import javax.media.opengl.*; - -import com.jogamp.newt.*; -import java.io.IOException; - -public class TestDrawable01NEWT extends UITestCase { - static GLProfile glp; - static GLDrawableFactory factory; - static int width, height; - GLCapabilities caps; - Window window; - GLDrawable drawable; - GLContext context; - - @BeforeClass - public static void initClass() { - glp = GLProfile.getDefault(); - Assert.assertNotNull(glp); - factory = GLDrawableFactory.getFactory(glp); - Assert.assertNotNull(factory); - width = 640; - height = 480; - } - - @AfterClass - public static void releaseClass() { - Assert.assertNotNull(factory); - factory=null; - } - - @Before - public void initTest() { - caps = new GLCapabilities(glp); - Assert.assertNotNull(caps); - } - - void createWindow(boolean onscreen, boolean pbuffer, boolean undecorated) { - caps.setOnscreen(onscreen); - caps.setPBuffer(!onscreen && pbuffer); - caps.setDoubleBuffered(onscreen); - // System.out.println("Requested: "+caps); - - // - // Create native windowing resources .. X11/Win/OSX - // - Display display = NewtFactory.createDisplay(null); // local display - Assert.assertNotNull(display); - - Screen screen = NewtFactory.createScreen(display, 0); // screen 0 - Assert.assertNotNull(screen); - - window = NewtFactory.createWindow(screen, caps); - Assert.assertNotNull(window); - window.setUndecorated(onscreen && undecorated); - window.setSize(width, height); - window.setVisible(true); - // System.out.println("Created: "+window); - - // - // Create native OpenGL resources .. XGL/WGL/CGL .. - // equivalent to GLAutoDrawable methods: setVisible(true) - // - GLCapabilities glCaps = (GLCapabilities) window.getGraphicsConfiguration().getChosenCapabilities(); - Assert.assertNotNull(glCaps); - Assert.assertTrue(glCaps.getGreenBits()>5); - Assert.assertTrue(glCaps.getBlueBits()>5); - Assert.assertTrue(glCaps.getRedBits()>5); - Assert.assertEquals(glCaps.isOnscreen(),onscreen); - Assert.assertTrue(onscreen || !pbuffer || glCaps.isPBuffer()); // pass if onscreen, or !pbuffer req. or have pbuffer - Assert.assertEquals(glCaps.getDoubleBuffered(),onscreen); - Assert.assertTrue(glCaps.getDepthBits()>4); - - drawable = factory.createGLDrawable(window); - Assert.assertNotNull(drawable); - // System.out.println("Pre: "+drawable); - // - drawable.setRealized(true); - // Assert.assertEquals(width,drawable.getWidth()); - // Assert.assertEquals(height,drawable.getHeight()); - // Assert.assertEquals(glCaps,drawable.getChosenGLCapabilities()); - Assert.assertEquals(window,drawable.getNativeSurface()); - // System.out.println("Post: "+drawable); - - context = drawable.createContext(null); - Assert.assertNotNull(context); - // System.out.println(context); - - int res = context.makeCurrent(); - Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res); - - // draw something .. - - drawable.swapBuffers(); - context.release(); - - // System.out.println("Final: "+window); - } - - void destroyWindow() { - // GLWindow.dispose(..) sequence - Assert.assertNotNull(context); - context.destroy(); - - Assert.assertNotNull(drawable); - drawable.setRealized(false); - - // GLWindow.destroy(..) sequence cont.. - Assert.assertNotNull(window); - window.destroy(); - - drawable = null; - context = null; - window = null; - } - - @Test - public void testOnScreenDecorated() throws InterruptedException { - createWindow(true, false, false); - Thread.sleep(1000); // 1000 ms - destroyWindow(); - } - - @Test - public void testOnScreenUndecorated() throws InterruptedException { - createWindow(true, false, true); - Thread.sleep(1000); // 1000 ms - destroyWindow(); - } - - public static void main(String args[]) throws IOException { - String tstname = TestDrawable01NEWT.class.getName(); - org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] { - tstname, - "filtertrace=true", - "haltOnError=false", - "haltOnFailure=false", - "showoutput=true", - "outputtoformatters=true", - "logfailedtests=true", - "logtestlistenerevents=true", - "formatter=org.apache.tools.ant.taskdefs.optional.junit.PlainJUnitResultFormatter", - "formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,TEST-"+tstname+".xml" } ); - } - -} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/GLSLMiscHelper.java b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/GLSLMiscHelper.java index 297cbbb90..f55e331a7 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/GLSLMiscHelper.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/GLSLMiscHelper.java @@ -40,8 +40,7 @@ public class GLSLMiscHelper { public static final int frames_perftest = 600; // frames public static final int frames_warmup = 100; // frames - public static void validateGLArrayDataServerState(GL2ES2 gl, GLArrayDataServer data) { - final ShaderState st = ShaderState.getShaderState(gl); + public static void validateGLArrayDataServerState(GL2ES2 gl, ShaderState st, GLArrayDataServer data) { int[] qi = new int[1]; if(null != st) { Assert.assertEquals(data, st.getAttribute(data.getName())); @@ -66,7 +65,7 @@ public class GLSLMiscHelper { } } - public static void displayVCArrays(GLDrawable drawable, GL2ES2 gl, boolean preEnable, GLArrayDataServer vertices, GLArrayDataServer colors, boolean postDisable, int num, long postDelay) throws InterruptedException { + public static void displayVCArrays(GLDrawable drawable, GL2ES2 gl, ShaderState st, boolean preEnable, GLArrayDataServer vertices, GLArrayDataServer colors, boolean postDisable, int num, long postDelay) throws InterruptedException { System.err.println("screen #"+num); if(preEnable) { vertices.enableBuffer(gl, true); @@ -81,8 +80,8 @@ public class GLSLMiscHelper { Assert.assertTrue(vertices.enabled()); Assert.assertTrue(colors.enabled()); - validateGLArrayDataServerState(gl, vertices); - validateGLArrayDataServerState(gl, colors); + validateGLArrayDataServerState(gl, st, vertices); + validateGLArrayDataServerState(gl, st, colors); gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4); Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); @@ -111,88 +110,98 @@ public class GLSLMiscHelper { drawable.swapBuffers(); } - public static GLArrayDataServer createRSVertices0(GL2ES2 gl, int location) { - final ShaderState st = ShaderState.getShaderState(gl); - + public static GLArrayDataServer createVertices(GL2ES2 gl, ShaderState st, int shaderProgram, int location, float[] vertices) { + if(null != st && 0 != shaderProgram) { + throw new InternalError("Use either ShaderState _or_ shader-program, not both"); + } + if(null == st && 0 == shaderProgram) { + throw new InternalError("Pass a valid ShaderState _xor_ shader-program, not none"); + } // Allocate Vertex Array0 - GLArrayDataServer vertices0 = GLArrayDataServer.createGLSL("mgl_Vertex", 3, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW); - if(0<=location) { - st.bindAttribLocation(gl, location, vertices0); + GLArrayDataServer vDataArray = GLArrayDataServer.createGLSL("mgl_Vertex", 3, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW); + if(null != st) { + st.ownAttribute(vDataArray, true); + if(0<=location) { + st.bindAttribLocation(gl, location, vDataArray); + } + } else { + if(0<=location) { + vDataArray.setLocation(gl, shaderProgram, location); + } else { + vDataArray.setLocation(gl, shaderProgram); + } } - Assert.assertTrue(vertices0.isVBO()); - Assert.assertTrue(vertices0.isVertexAttribute()); - Assert.assertTrue(!vertices0.isVBOWritten()); - Assert.assertTrue(!vertices0.sealed()); - vertices0.putf(-2); vertices0.putf(2); vertices0.putf(0); - vertices0.putf(2); vertices0.putf(2); vertices0.putf(0); - vertices0.putf(-2); vertices0.putf(-2); vertices0.putf(0); - vertices0.putf(2); vertices0.putf(-2); vertices0.putf(0); - vertices0.seal(gl, true); - Assert.assertTrue(vertices0.isVBOWritten()); - Assert.assertTrue(vertices0.sealed()); - Assert.assertEquals(4, vertices0.getElementCount()); + Assert.assertTrue(vDataArray.isVBO()); + Assert.assertTrue(vDataArray.isVertexAttribute()); + Assert.assertTrue(!vDataArray.isVBOWritten()); + Assert.assertTrue(!vDataArray.sealed()); + int i=0; + vDataArray.putf(vertices[i++]); vDataArray.putf(vertices[i++]); vDataArray.putf(vertices[i++]); + vDataArray.putf(vertices[i++]); vDataArray.putf(vertices[i++]); vDataArray.putf(vertices[i++]); + vDataArray.putf(vertices[i++]); vDataArray.putf(vertices[i++]); vDataArray.putf(vertices[i++]); + vDataArray.putf(vertices[i++]); vDataArray.putf(vertices[i++]); vDataArray.putf(vertices[i++]); + vDataArray.seal(gl, true); + Assert.assertTrue(vDataArray.isVBOWritten()); + Assert.assertTrue(vDataArray.sealed()); + Assert.assertEquals(4, vDataArray.getElementCount()); Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); - Assert.assertEquals(vertices0.getVBOName(), gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER)); - validateGLArrayDataServerState(gl, vertices0); - return vertices0; + Assert.assertEquals(0, gl.getBoundBuffer(GL.GL_ARRAY_BUFFER)); // should be cleared ASAP + validateGLArrayDataServerState(gl, st, vDataArray); + return vDataArray; } + public static float[] vertices0 = new float[] { -2f, 2f, 0f, + 2f, 2f, 0f, + -2f, -2f, 0f, + 2f, -2f, 0f }; - public static GLArrayDataServer createRSVertices1(GL2ES2 gl) { - GLArrayDataServer vertices1 = GLArrayDataServer.createGLSL("mgl_Vertex", 3, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW); - Assert.assertTrue(vertices1.isVBO()); - Assert.assertTrue(vertices1.isVertexAttribute()); - Assert.assertTrue(!vertices1.isVBOWritten()); - Assert.assertTrue(!vertices1.sealed()); - vertices1.putf(-2); vertices1.putf(1); vertices1.putf(0); - vertices1.putf(2); vertices1.putf(1); vertices1.putf(0); - vertices1.putf(-2); vertices1.putf(-1); vertices1.putf(0); - vertices1.putf(2); vertices1.putf(-1); vertices1.putf(0); - vertices1.seal(gl, true); - Assert.assertTrue(vertices1.isVBOWritten()); - Assert.assertTrue(vertices1.sealed()); - Assert.assertEquals(4, vertices1.getElementCount()); - Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); - Assert.assertEquals(vertices1.getVBOName(), gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER)); - validateGLArrayDataServerState(gl, vertices1); - return vertices1; - } - - public static GLArrayDataServer createRSColors0(GL2ES2 gl, int location) { - final ShaderState st = ShaderState.getShaderState(gl); - GLArrayDataServer colors0 = GLArrayDataServer.createGLSL("mgl_Color", 4, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW); - if(0<=location) { - st.bindAttribLocation(gl, location, colors0); - } - colors0.putf(1); colors0.putf(0); colors0.putf(0); colors0.putf(1); - colors0.putf(0); colors0.putf(0); colors0.putf(1); colors0.putf(1); - colors0.putf(1); colors0.putf(0); colors0.putf(0); colors0.putf(1); - colors0.putf(1); colors0.putf(0); colors0.putf(0); colors0.putf(1); - colors0.seal(gl, true); - Assert.assertTrue(colors0.isVBO()); - Assert.assertTrue(colors0.isVertexAttribute()); - Assert.assertTrue(colors0.isVBOWritten()); - Assert.assertTrue(colors0.sealed()); + public static float[] vertices1 = new float[] { -2f, 1f, 0f, + 2f, 1f, 0f, + -2f, -1f, 0f, + 2f, -1f, 0f }; + + public static GLArrayDataServer createColors(GL2ES2 gl, ShaderState st, int shaderProgram, int location, float[] colors) { + if(null != st && 0 != shaderProgram) { + throw new InternalError("Use either ShaderState _or_ shader-program, not both"); + } + if(null == st && 0 == shaderProgram) { + throw new InternalError("Pass a valid ShaderState _xor_ shader-program, not none"); + } + GLArrayDataServer cDataArray = GLArrayDataServer.createGLSL("mgl_Color", 4, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW); + if(null != st) { + st.ownAttribute(cDataArray, true); + if(0<=location) { + st.bindAttribLocation(gl, location, cDataArray); + } + } else { + if(0<=location) { + cDataArray.setLocation(gl, shaderProgram, location); + } else { + cDataArray.setLocation(gl, shaderProgram); + } + } + int i=0; + cDataArray.putf(colors[i++]); cDataArray.putf(colors[i++]); cDataArray.putf(colors[i++]); cDataArray.putf(colors[i++]); + cDataArray.putf(colors[i++]); cDataArray.putf(colors[i++]); cDataArray.putf(colors[i++]); cDataArray.putf(colors[i++]); + cDataArray.putf(colors[i++]); cDataArray.putf(colors[i++]); cDataArray.putf(colors[i++]); cDataArray.putf(colors[i++]); + cDataArray.putf(colors[i++]); cDataArray.putf(colors[i++]); cDataArray.putf(colors[i++]); cDataArray.putf(colors[i++]); + cDataArray.seal(gl, true); + Assert.assertTrue(cDataArray.isVBO()); + Assert.assertTrue(cDataArray.isVertexAttribute()); + Assert.assertTrue(cDataArray.isVBOWritten()); + Assert.assertTrue(cDataArray.sealed()); Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); - Assert.assertEquals(colors0.getVBOName(), gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER)); - validateGLArrayDataServerState(gl, colors0); - return colors0; + Assert.assertEquals(0, gl.getBoundBuffer(GL.GL_ARRAY_BUFFER)); // should be cleared ASAP + validateGLArrayDataServerState(gl, st, cDataArray); + return cDataArray; } + public static float[] colors0 = new float[] { 1f, 0f, 0f, 1f, + 0f, 0f, 1f, 1f, + 1f, 0f, 0f, 1f, + 1f, 0f, 1f, 1f }; + + public static float[] colors1 = new float[] { 1f, 0f, 1f, 1f, + 0f, 1f, 0f, 1f, + 1f, 0f, 1f, 1f, + 1f, 0f, 1f, 1f }; - public static GLArrayDataServer createRSColors1(GL2ES2 gl) { - // Allocate Color Array1 - GLArrayDataServer colors1 = GLArrayDataServer.createGLSL("mgl_Color", 4, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW); - colors1.putf(1); colors1.putf(0); colors1.putf(1); colors1.putf(1); - colors1.putf(0); colors1.putf(1); colors1.putf(0); colors1.putf(1); - colors1.putf(1); colors1.putf(0); colors1.putf(1); colors1.putf(1); - colors1.putf(1); colors1.putf(0); colors1.putf(1); colors1.putf(1); - colors1.seal(gl, true); - Assert.assertTrue(colors1.isVBO()); - Assert.assertTrue(colors1.isVertexAttribute()); - Assert.assertTrue(colors1.isVBOWritten()); - Assert.assertTrue(colors1.sealed()); - Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); - Assert.assertEquals(colors1.getVBOName(), gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER)); - validateGLArrayDataServerState(gl, colors1); - return colors1; - } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState01NEWT.java index 881399ddb..c240731a1 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState01NEWT.java @@ -47,12 +47,14 @@ import javax.media.opengl.GLUniformData; import org.junit.Assert; import org.junit.Test; -import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; /** * Testing different vertex attribute (VA) data sets on one shader * and shader state in general. */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestGLSLShaderState01NEWT extends UITestCase { static long durationPerTest = 10; // ms static boolean firstUIActionOnProcess = false; @@ -61,7 +63,123 @@ public class TestGLSLShaderState01NEWT extends UITestCase { static final int colors0_loc = 1; @Test - public void testShaderState01Validation() throws InterruptedException { + public void test00NoShaderState_Validation() throws InterruptedException { + // preset .. + final NEWTGLContext.WindowContext winctx = NEWTGLContext.createOnscreenWindow( + new GLCapabilities(GLProfile.getGL2ES2()), 480, 480, true); + final GLDrawable drawable = winctx.context.getGLDrawable(); + final GL2ES2 gl = winctx.context.getGL().getGL2ES2(); + System.err.println(winctx.context); + + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + // test code .. + final ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, RedSquareES2.class, + "shader", "shader/bin", "RedSquareShader", true); + final ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, + "shader", "shader/bin", "RedSquareShader", true); + rsVp.defaultShaderCustomization(gl, true, true); + rsFp.defaultShaderCustomization(gl, true, true); + + final ShaderProgram sp = new ShaderProgram(); + Assert.assertTrue(0 == sp.program()); + + sp.add(gl, rsVp, System.err); + sp.add(gl, rsFp, System.err); + + Assert.assertTrue(0 != sp.program()); + Assert.assertTrue(!sp.inUse()); + Assert.assertTrue(!sp.linked()); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + Assert.assertTrue( sp.link(gl, System.err) ); + sp.useProgram(gl, true); + + // Allocate Vertex Array0 + final GLArrayDataServer vertices0 = GLSLMiscHelper.createVertices(gl, null, sp.program(), vertices0_loc, GLSLMiscHelper.vertices0); + System.err.println("vertices0: " + vertices0); + vertices0.enableBuffer(gl, false); + Assert.assertEquals(vertices0_loc, vertices0.getLocation()); + + // Allocate Color Array0 + final GLArrayDataServer colors0 = GLSLMiscHelper.createColors(gl, null, sp.program(), colors0_loc, GLSLMiscHelper.colors0); + System.err.println("colors0: " + colors0); + colors0.enableBuffer(gl, false); + Assert.assertEquals(colors0_loc, colors0.getLocation()); + + Assert.assertTrue(sp.link(gl, System.err)); + Assert.assertTrue(sp.linked()); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + Assert.assertEquals(vertices0_loc, vertices0.getLocation()); + GLSLMiscHelper.validateGLArrayDataServerState(gl, null, vertices0); + + Assert.assertEquals(colors0_loc, colors0.getLocation()); + GLSLMiscHelper.validateGLArrayDataServerState(gl, null, colors0); + + sp.useProgram(gl, true); + Assert.assertTrue(sp.inUse()); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + // setup mgl_PMVMatrix + final PMVMatrix pmvMatrix = new PMVMatrix(); + final GLUniformData pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + pmvMatrixUniform.setLocation(gl, sp.program()); + gl.glUniform(pmvMatrixUniform); + + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + // Allocate Vertex Array1 + final GLArrayDataServer vertices1 = GLSLMiscHelper.createVertices(gl, null, sp.program(), -1, GLSLMiscHelper.vertices1); + System.err.println("vertices1: " + vertices1); + vertices1.enableBuffer(gl, false); + GLSLMiscHelper.validateGLArrayDataServerState(gl, null, vertices1); + + // Allocate Color Array1 + final GLArrayDataServer colors1 = GLSLMiscHelper.createColors(gl, null, sp.program(), -1, GLSLMiscHelper.colors1); + System.err.println("colors1: " + colors1); + colors1.enableBuffer(gl, false); + GLSLMiscHelper.validateGLArrayDataServerState(gl, null, colors1); + + // misc GL setup + gl.glClearColor(0, 0, 0, 1); + gl.glEnable(GL2ES2.GL_DEPTH_TEST); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + // reshape + pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.gluPerspective(45.0F, (float) drawable.getWidth() / (float) drawable.getHeight(), 1.0F, 100.0F); + pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glTranslatef(0, 0, -10); + gl.glUniform(pmvMatrixUniform); + + gl.glViewport(0, 0, drawable.getWidth(), drawable.getHeight()); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + // display #1 vertices0 / colors0 (post-disable) + GLSLMiscHelper.displayVCArrays(drawable, gl, null, true, vertices0, colors0, true, 1, durationPerTest); + + // display #2 #1 vertices1 / colors1 (post-disable) + GLSLMiscHelper.displayVCArrays(drawable, gl, null, true, vertices1, colors1, true, 2, durationPerTest); + + // display #3 vertices0 / colors0 (post-disable) + GLSLMiscHelper.displayVCArrays(drawable, gl, null, true, vertices0, colors0, true, 3, durationPerTest); + + // cleanup + sp.useProgram(gl, false); + sp.destroy(gl); + vertices1.destroy(gl); + colors0.destroy(gl); + colors1.destroy(gl); + + NEWTGLContext.destroyWindow(winctx); + } + + @Test + public void test01ShaderState_Validation() throws InterruptedException { // preset .. final NEWTGLContext.WindowContext winctx = NEWTGLContext.createOnscreenWindow( new GLCapabilities(GLProfile.getGL2ES2()), 480, 480, true); @@ -75,17 +193,19 @@ public class TestGLSLShaderState01NEWT extends UITestCase { final ShaderState st = new ShaderState(); final ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, RedSquareES2.class, "shader", - "shader/bin", "RedSquareShader", false); + "shader/bin", "RedSquareShader", true); final ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, "shader", - "shader/bin", "RedSquareShader", false); + "shader/bin", "RedSquareShader", true); + rsVp.defaultShaderCustomization(gl, true, true); + rsFp.defaultShaderCustomization(gl, true, true); final ShaderProgram sp = new ShaderProgram(); - Assert.assertTrue(0>sp.program()); + Assert.assertTrue(0 == sp.program()); sp.add(gl, rsVp, System.err); sp.add(gl, rsFp, System.err); - Assert.assertTrue(0<=sp.program()); + Assert.assertTrue(0 != sp.program()); Assert.assertTrue(!sp.inUse()); Assert.assertTrue(!sp.linked()); Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); @@ -94,33 +214,27 @@ public class TestGLSLShaderState01NEWT extends UITestCase { Assert.assertTrue(!sp.inUse()); Assert.assertTrue(!sp.linked()); - Assert.assertEquals(null, ShaderState.getShaderState(gl)); - st.setShaderState(gl); // pre-use attach - Assert.assertEquals(st, ShaderState.getShaderState(gl)); - // Allocate Vertex Array0 - final GLArrayDataServer vertices0 = GLSLMiscHelper.createRSVertices0(gl, vertices0_loc); + final GLArrayDataServer vertices0 = GLSLMiscHelper.createVertices(gl, st, 0, vertices0_loc, GLSLMiscHelper.vertices0); System.err.println("vertices0: " + vertices0); vertices0.enableBuffer(gl, false); Assert.assertEquals(vertices0_loc, vertices0.getLocation()); - st.ownAttribute(vertices0, true); // Allocate Color Array0 - final GLArrayDataServer colors0 = GLSLMiscHelper.createRSColors0(gl, colors0_loc); + final GLArrayDataServer colors0 = GLSLMiscHelper.createColors(gl, st, 0, colors0_loc, GLSLMiscHelper.colors0); System.err.println("colors0: " + colors0); colors0.enableBuffer(gl, false); Assert.assertEquals(colors0_loc, colors0.getLocation()); - st.ownAttribute(colors0, true); Assert.assertTrue(sp.link(gl, System.err)); Assert.assertTrue(sp.linked()); Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); Assert.assertEquals(vertices0_loc, vertices0.getLocation()); - GLSLMiscHelper.validateGLArrayDataServerState(gl, vertices0); + GLSLMiscHelper.validateGLArrayDataServerState(gl, st, vertices0); Assert.assertEquals(colors0_loc, colors0.getLocation()); - GLSLMiscHelper.validateGLArrayDataServerState(gl, colors0); + GLSLMiscHelper.validateGLArrayDataServerState(gl, st, colors0); st.useProgram(gl, true); Assert.assertTrue(sp.inUse()); @@ -137,18 +251,16 @@ public class TestGLSLShaderState01NEWT extends UITestCase { Assert.assertEquals(pmvMatrixUniform, st.getUniform("mgl_PMVMatrix")); // Allocate Vertex Array1 - final GLArrayDataServer vertices1 = GLSLMiscHelper.createRSVertices1(gl); + final GLArrayDataServer vertices1 = GLSLMiscHelper.createVertices(gl, st, 0, -1, GLSLMiscHelper.vertices1); System.err.println("vertices1: " + vertices1); vertices1.enableBuffer(gl, false); - GLSLMiscHelper.validateGLArrayDataServerState(gl, vertices1); - st.ownAttribute(vertices1, true); + GLSLMiscHelper.validateGLArrayDataServerState(gl, st, vertices1); // Allocate Color Array1 - final GLArrayDataServer colors1 = GLSLMiscHelper.createRSColors1(gl); + final GLArrayDataServer colors1 = GLSLMiscHelper.createColors(gl, st, 0, -1, GLSLMiscHelper.colors1); System.err.println("colors1: " + colors1); colors1.enableBuffer(gl, false); - GLSLMiscHelper.validateGLArrayDataServerState(gl, colors1); - st.ownAttribute(colors0, true); + GLSLMiscHelper.validateGLArrayDataServerState(gl, st, colors1); // misc GL setup gl.glClearColor(0, 0, 0, 1); @@ -167,13 +279,13 @@ public class TestGLSLShaderState01NEWT extends UITestCase { Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); // display #1 vertices0 / colors0 (post-disable) - GLSLMiscHelper.displayVCArrays(drawable, gl, true, vertices0, colors0, true, 1, durationPerTest); + GLSLMiscHelper.displayVCArrays(drawable, gl, st, true, vertices0, colors0, true, 1, durationPerTest); // display #2 #1 vertices1 / colors1 (post-disable) - GLSLMiscHelper.displayVCArrays(drawable, gl, true, vertices1, colors1, true, 2, durationPerTest); + GLSLMiscHelper.displayVCArrays(drawable, gl, st, true, vertices1, colors1, true, 2, durationPerTest); // display #3 vertices0 / colors0 (post-disable) - GLSLMiscHelper.displayVCArrays(drawable, gl, true, vertices0, colors0, true, 3, durationPerTest); + GLSLMiscHelper.displayVCArrays(drawable, gl, st, true, vertices0, colors0, true, 3, durationPerTest); // cleanup st.destroy(gl); @@ -182,15 +294,15 @@ public class TestGLSLShaderState01NEWT extends UITestCase { } @Test(timeout=240000) - public void testShaderState00PerformanceSingleKeepEnabled() throws InterruptedException { - testShaderState00PerformanceSingle(false); + public void test02ShaderState_PerformanceSingleKeepEnabled() throws InterruptedException { + testShaderState_PerformanceSingleImpl(false); } @Test(timeout=240000) - public void testShaderState00PerformanceSingleToggleEnable() throws InterruptedException { - testShaderState00PerformanceSingle(true); + public void test03ShaderState_PerformanceSingleToggleEnable() throws InterruptedException { + testShaderState_PerformanceSingleImpl(true); } - void testShaderState00PerformanceSingle(boolean toggleEnable) throws InterruptedException { + private void testShaderState_PerformanceSingleImpl(boolean toggleEnable) throws InterruptedException { // preset .. final NEWTGLContext.WindowContext winctx = NEWTGLContext.createOnscreenWindow( new GLCapabilities(GLProfile.getGL2ES2()), 480, 480, false); @@ -205,9 +317,11 @@ public class TestGLSLShaderState01NEWT extends UITestCase { final ShaderState st = new ShaderState(); final ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, RedSquareES2.class, "shader", - "shader/bin", "RedSquareShader", false); + "shader/bin", "RedSquareShader", true); final ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, "shader", - "shader/bin", "RedSquareShader", false); + "shader/bin", "RedSquareShader", true); + rsVp.defaultShaderCustomization(gl, true, true); + rsFp.defaultShaderCustomization(gl, true, true); final ShaderProgram sp = new ShaderProgram(); sp.add(rsVp); @@ -225,13 +339,11 @@ public class TestGLSLShaderState01NEWT extends UITestCase { st.uniform(gl, pmvMatrixUniform); // Allocate Vertex Array0 - final GLArrayDataServer vertices0 = GLSLMiscHelper.createRSVertices0(gl, -1); - st.ownAttribute(vertices0, true); + final GLArrayDataServer vertices0 = GLSLMiscHelper.createVertices(gl, st, 0, -1, GLSLMiscHelper.vertices0); vertices0.enableBuffer(gl, toggleEnable ? false : true); // Allocate Color Array0 - final GLArrayDataServer colors0 = GLSLMiscHelper.createRSColors0(gl, -1); - st.ownAttribute(colors0, true); + final GLArrayDataServer colors0 = GLSLMiscHelper.createColors(gl, st, 0, -1, GLSLMiscHelper.colors0); colors0.enableBuffer(gl, toggleEnable ? false : true); // misc GL setup @@ -251,7 +363,7 @@ public class TestGLSLShaderState01NEWT extends UITestCase { gl.setSwapInterval(0); // validation .. - GLSLMiscHelper.displayVCArrays(drawable, gl, toggleEnable, vertices0, colors0, toggleEnable, 1, 0); + GLSLMiscHelper.displayVCArrays(drawable, gl, st, toggleEnable, vertices0, colors0, toggleEnable, 1, 0); // warmup .. for(int frames=0; frames<GLSLMiscHelper.frames_warmup; frames++) { @@ -279,7 +391,7 @@ public class TestGLSLShaderState01NEWT extends UITestCase { } @Test(timeout=240000) - public void testShaderState01PerformanceDouble() throws InterruptedException { + public void test04ShaderState_PerformanceDouble() throws InterruptedException { // preset .. final NEWTGLContext.WindowContext winctx = NEWTGLContext.createOnscreenWindow( new GLCapabilities(GLProfile.getGL2ES2()), 480, 480, false); @@ -294,9 +406,11 @@ public class TestGLSLShaderState01NEWT extends UITestCase { final ShaderState st = new ShaderState(); final ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, RedSquareES2.class, "shader", - "shader/bin", "RedSquareShader", false); + "shader/bin", "RedSquareShader", true); final ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, "shader", - "shader/bin", "RedSquareShader", false); + "shader/bin", "RedSquareShader", true); + rsVp.defaultShaderCustomization(gl, true, true); + rsFp.defaultShaderCustomization(gl, true, true); final ShaderProgram sp = new ShaderProgram(); sp.add(rsVp); @@ -314,23 +428,19 @@ public class TestGLSLShaderState01NEWT extends UITestCase { st.uniform(gl, pmvMatrixUniform); // Allocate Vertex Array0 - final GLArrayDataServer vertices0 = GLSLMiscHelper.createRSVertices0(gl, -1); - st.ownAttribute(vertices0, true); + final GLArrayDataServer vertices0 = GLSLMiscHelper.createVertices(gl, st, 0, -1, GLSLMiscHelper.vertices0); vertices0.enableBuffer(gl, false); // Allocate Vertex Array1 - final GLArrayDataServer vertices1 = GLSLMiscHelper.createRSVertices1(gl); - st.ownAttribute(vertices1, true); + final GLArrayDataServer vertices1 = GLSLMiscHelper.createVertices(gl, st, 0, -1, GLSLMiscHelper.vertices1); vertices1.enableBuffer(gl, false); // Allocate Color Array0 - final GLArrayDataServer colors0 = GLSLMiscHelper.createRSColors0(gl, -1); - st.ownAttribute(colors0, true); + final GLArrayDataServer colors0 = GLSLMiscHelper.createColors(gl, st, 0, -1, GLSLMiscHelper.colors0); colors0.enableBuffer(gl, false); // Allocate Color Array1 - final GLArrayDataServer colors1 = GLSLMiscHelper.createRSColors1(gl); - st.ownAttribute(colors1, true); + final GLArrayDataServer colors1 = GLSLMiscHelper.createColors(gl, st, 0, -1, GLSLMiscHelper.colors1); colors1.enableBuffer(gl, false); // misc GL setup @@ -350,8 +460,8 @@ public class TestGLSLShaderState01NEWT extends UITestCase { gl.setSwapInterval(0); // validation .. - GLSLMiscHelper.displayVCArrays(drawable, gl, true, vertices0, colors0, true, 1, 0); - GLSLMiscHelper.displayVCArrays(drawable, gl, true, vertices1, colors1, true, 2, 0); + GLSLMiscHelper.displayVCArrays(drawable, gl, st, true, vertices0, colors0, true, 1, 0); + GLSLMiscHelper.displayVCArrays(drawable, gl, st, true, vertices1, colors1, true, 2, 0); // warmup .. for(int frames=0; frames<GLSLMiscHelper.frames_warmup; frames+=2) { @@ -396,7 +506,7 @@ public class TestGLSLShaderState01NEWT extends UITestCase { while(-1 == System.in.read()) ; TestGLSLShaderState01NEWT tst = new TestGLSLShaderState01NEWT(); try { - tst.testShaderState01PerformanceDouble(); + tst.test04ShaderState_PerformanceDouble(); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState02NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState02NEWT.java index 6421c2405..eb5a3fcf5 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState02NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLShaderState02NEWT.java @@ -47,12 +47,14 @@ import javax.media.opengl.GLUniformData; import org.junit.Assert; import org.junit.Test; -import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; /** * Testing different vertex attribute (VA) data sets on one shader * and shader state in general. */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestGLSLShaderState02NEWT extends UITestCase { static long durationPerTest = 10; // ms @@ -82,19 +84,22 @@ public class TestGLSLShaderState02NEWT extends UITestCase { final ShaderState st = new ShaderState(); final ShaderCode rsVp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, RedSquareES2.class, "shader", - "shader/bin", "RedSquareShader", false); + "shader/bin", "RedSquareShader", true); final ShaderCode rsFp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, "shader", - "shader/bin", "RedSquareShader", false); + "shader/bin", "RedSquareShader", true); final ShaderCode rsFp1 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, "shader", - "shader/bin", "RedSquareShader2", false); + "shader/bin", "RedSquareShader2", true); + rsVp0.defaultShaderCustomization(gl, true, true); + rsFp0.defaultShaderCustomization(gl, true, true); + rsFp1.defaultShaderCustomization(gl, true, true); final ShaderProgram sp1 = new ShaderProgram(); sp1.add(rsVp0); sp1.add(rsFp1); Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); - Assert.assertTrue(0>sp1.program()); - sp1.init(gl); - Assert.assertTrue(0<=sp1.program()); + Assert.assertTrue(0 == sp1.program()); + Assert.assertTrue(sp1.init(gl)); + Assert.assertTrue(0 != sp1.program()); Assert.assertTrue(!sp1.inUse()); Assert.assertTrue(!sp1.linked()); Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); @@ -109,9 +114,9 @@ public class TestGLSLShaderState02NEWT extends UITestCase { sp0.add(rsFp0); Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); - Assert.assertTrue(0>sp0.program()); - sp0.init(gl); - Assert.assertTrue(0<=sp0.program()); + Assert.assertTrue(0 == sp0.program()); + Assert.assertTrue(sp0.init(gl)); + Assert.assertTrue(0 != sp0.program()); Assert.assertTrue(!sp0.inUse()); Assert.assertTrue(!sp0.linked()); Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); @@ -119,20 +124,15 @@ public class TestGLSLShaderState02NEWT extends UITestCase { st.attachShaderProgram(gl, sp0, false); Assert.assertTrue(!sp0.inUse()); Assert.assertTrue(!sp0.linked()); - Assert.assertEquals(null, ShaderState.getShaderState(gl)); - st.setShaderState(gl); // pre-use attach - Assert.assertEquals(st, ShaderState.getShaderState(gl)); // Allocate Vertex Array0 - final GLArrayDataServer vertices0 = GLSLMiscHelper.createRSVertices0(gl, vertices0_loc); - st.ownAttribute(vertices0, true); + final GLArrayDataServer vertices0 = GLSLMiscHelper.createVertices(gl, st, 0, vertices0_loc, GLSLMiscHelper.vertices0); System.err.println("vertices0: " + vertices0); vertices0.enableBuffer(gl, false); Assert.assertEquals(vertices0_loc, vertices0.getLocation()); // Allocate Color Array0 - final GLArrayDataServer colors0 = GLSLMiscHelper.createRSColors0(gl, colors0_loc); - st.ownAttribute(colors0, true); + final GLArrayDataServer colors0 = GLSLMiscHelper.createColors(gl, st, 0, colors0_loc, GLSLMiscHelper.colors0); System.err.println("colors0: " + colors0); colors0.enableBuffer(gl, false); Assert.assertEquals(colors0_loc, colors0.getLocation()); @@ -164,14 +164,12 @@ public class TestGLSLShaderState02NEWT extends UITestCase { Assert.assertEquals(pmvMatrixUniform, st.getUniform("mgl_PMVMatrix")); // Allocate Vertex Array1 - final GLArrayDataServer vertices1 = GLSLMiscHelper.createRSVertices1(gl); - st.ownAttribute(vertices1, true); + final GLArrayDataServer vertices1 = GLSLMiscHelper.createVertices(gl, st, 0, -1, GLSLMiscHelper.vertices1); System.err.println("vertices1: " + vertices1); vertices1.enableBuffer(gl, false); // Allocate Color Array1 - final GLArrayDataServer colors1 = GLSLMiscHelper.createRSColors1(gl); - st.ownAttribute(colors1, true); + final GLArrayDataServer colors1 = GLSLMiscHelper.createColors(gl, st, 0, -1, GLSLMiscHelper.colors1); System.err.println("colors1: " + colors1); colors1.enableBuffer(gl, false); @@ -192,16 +190,16 @@ public class TestGLSLShaderState02NEWT extends UITestCase { Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); // display #1 vertices0 / colors0 (post-disable) - GLSLMiscHelper.displayVCArrays(drawable, gl, true, vertices0, colors0, true, 1, durationPerTest); + GLSLMiscHelper.displayVCArrays(drawable, gl, st, true, vertices0, colors0, true, 1, durationPerTest); // display #2 vertices1 / colors1 (post-disable) - GLSLMiscHelper.displayVCArrays(drawable, gl, true, vertices1, colors1, true, 2, durationPerTest); + GLSLMiscHelper.displayVCArrays(drawable, gl, st, true, vertices1, colors1, true, 2, durationPerTest); // display #3 vertices0 / colors0 (post-disable) - GLSLMiscHelper.displayVCArrays(drawable, gl, true, vertices0, colors0, true, 3, durationPerTest); + GLSLMiscHelper.displayVCArrays(drawable, gl, st, true, vertices0, colors0, true, 3, durationPerTest); // display #4 vertices1 / colors1 (post-disable) - GLSLMiscHelper.displayVCArrays(drawable, gl, true, vertices1, colors1, true, 4, durationPerTest); + GLSLMiscHelper.displayVCArrays(drawable, gl, st, true, vertices1, colors1, true, 4, durationPerTest); // SP1 st.attachShaderProgram(gl, sp1, true); @@ -220,16 +218,16 @@ public class TestGLSLShaderState02NEWT extends UITestCase { } // display #1 vertices0 / colors0 (post-disable) - GLSLMiscHelper.displayVCArrays(drawable, gl, true, vertices0, colors0, true, 10, durationPerTest); + GLSLMiscHelper.displayVCArrays(drawable, gl, st, true, vertices0, colors0, true, 10, durationPerTest); // display #2 vertices1 / colors1 (post-disable) - GLSLMiscHelper.displayVCArrays(drawable, gl, true, vertices1, colors1, true, 20, durationPerTest); + GLSLMiscHelper.displayVCArrays(drawable, gl, st, true, vertices1, colors1, true, 20, durationPerTest); // display #3 vertices0 / colors0 (post-disable) - GLSLMiscHelper.displayVCArrays(drawable, gl, true, vertices0, colors0, true, 30, durationPerTest); + GLSLMiscHelper.displayVCArrays(drawable, gl, st, true, vertices0, colors0, true, 30, durationPerTest); // display #4 vertices1 / colors1 (post-disable) - GLSLMiscHelper.displayVCArrays(drawable, gl, true, vertices1, colors1, true, 40, durationPerTest); + GLSLMiscHelper.displayVCArrays(drawable, gl, st, true, vertices1, colors1, true, 40, durationPerTest); // cleanup st.destroy(gl); @@ -253,25 +251,29 @@ public class TestGLSLShaderState02NEWT extends UITestCase { final ShaderState st = new ShaderState(); final ShaderCode rsVp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, RedSquareES2.class, "shader", - "shader/bin", "RedSquareShader", false); + "shader/bin", "RedSquareShader", true); final ShaderCode rsFp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, "shader", - "shader/bin", "RedSquareShader", false); + "shader/bin", "RedSquareShader", true); final ShaderCode rsFp1 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, "shader", - "shader/bin", "RedSquareShader2", false); + "shader/bin", "RedSquareShader2", true); + rsVp0.defaultShaderCustomization(gl, true, true); + rsFp0.defaultShaderCustomization(gl, true, true); + rsFp1.defaultShaderCustomization(gl, true, true); final ShaderProgram sp1 = new ShaderProgram(); sp1.add(rsVp0); sp1.add(rsFp1); Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); - Assert.assertTrue(0>sp1.program()); - sp1.init(gl); + Assert.assertTrue(0 == sp1.program()); + Assert.assertTrue(sp1.init(gl)); + Assert.assertTrue(0 != sp1.program()); Assert.assertTrue(sp1.link(gl, System.err)); final ShaderProgram sp0 = new ShaderProgram(); sp0.add(rsVp0); sp0.add(rsFp0); - sp0.init(gl); + Assert.assertTrue(sp0.init(gl)); Assert.assertTrue(sp0.link(gl, System.err)); st.attachShaderProgram(gl, sp0, true); @@ -283,23 +285,19 @@ public class TestGLSLShaderState02NEWT extends UITestCase { st.uniform(gl, pmvMatrixUniform); // Allocate Vertex Array0 - final GLArrayDataServer vertices0 = GLSLMiscHelper.createRSVertices0(gl, -1); - st.ownAttribute(vertices0, true); + final GLArrayDataServer vertices0 = GLSLMiscHelper.createVertices(gl, st, 0, -1, GLSLMiscHelper.vertices0); vertices0.enableBuffer(gl, false); // Allocate Vertex Array1 - final GLArrayDataServer vertices1 = GLSLMiscHelper.createRSVertices1(gl); - st.ownAttribute(vertices1, true); + final GLArrayDataServer vertices1 = GLSLMiscHelper.createVertices(gl, st, 0, -1, GLSLMiscHelper.vertices1); vertices1.enableBuffer(gl, false); // Allocate Color Array0 - final GLArrayDataServer colors0 = GLSLMiscHelper.createRSColors0(gl, -1); - st.ownAttribute(colors0, true); + final GLArrayDataServer colors0 = GLSLMiscHelper.createColors(gl, st, 0, -1, GLSLMiscHelper.colors0); colors0.enableBuffer(gl, false); // Allocate Color Array1 - final GLArrayDataServer colors1 = GLSLMiscHelper.createRSColors1(gl); - st.ownAttribute(colors1, true); + final GLArrayDataServer colors1 = GLSLMiscHelper.createColors(gl, st, 0, -1, GLSLMiscHelper.colors1); colors1.enableBuffer(gl, false); // misc GL setup @@ -320,11 +318,11 @@ public class TestGLSLShaderState02NEWT extends UITestCase { // validation .. st.attachShaderProgram(gl, sp0, true); - GLSLMiscHelper.displayVCArrays(drawable, gl, true, vertices0, colors0, true, 1, 0); - GLSLMiscHelper.displayVCArrays(drawable, gl, true, vertices1, colors1, true, 2, 0); + GLSLMiscHelper.displayVCArrays(drawable, gl, st, true, vertices0, colors0, true, 1, 0); + GLSLMiscHelper.displayVCArrays(drawable, gl, st, true, vertices1, colors1, true, 2, 0); st.attachShaderProgram(gl, sp1, true); - GLSLMiscHelper.displayVCArrays(drawable, gl, true, vertices0, colors0, true, 1, 0); - GLSLMiscHelper.displayVCArrays(drawable, gl, true, vertices1, colors1, true, 2, 0); + GLSLMiscHelper.displayVCArrays(drawable, gl, st, true, vertices0, colors0, true, 1, 0); + GLSLMiscHelper.displayVCArrays(drawable, gl, st, true, vertices1, colors1, true, 2, 0); // warmup .. for(int frames=0; frames<GLSLMiscHelper.frames_warmup; frames+=2) { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLSimple01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLSimple01NEWT.java index dde7252e8..9a70a0859 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLSimple01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestGLSLSimple01NEWT.java @@ -39,6 +39,8 @@ import javax.media.opengl.GLProfile; import org.junit.Assert; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.util.Animator; @@ -48,6 +50,7 @@ import com.jogamp.opengl.test.junit.util.MiscUtils; import java.io.IOException; import javax.media.opengl.GL2ES2; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestGLSLSimple01NEWT extends UITestCase { static long durationPerTest = 100; // ms diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestRulerNEWT01.java b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestRulerNEWT01.java index 87d317037..360f4e8d7 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestRulerNEWT01.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestRulerNEWT01.java @@ -28,8 +28,8 @@ package com.jogamp.opengl.test.junit.jogl.glsl; import com.jogamp.common.nio.Buffers; -import com.jogamp.newt.ScreenMode; -import com.jogamp.newt.util.MonitorMode; +import com.jogamp.newt.MonitorDevice; +import com.jogamp.newt.MonitorMode; import com.jogamp.opengl.util.GLArrayDataServer; import com.jogamp.opengl.util.PMVMatrix; import com.jogamp.opengl.util.glsl.ShaderCode; @@ -53,7 +53,10 @@ import javax.media.opengl.GLUniformData; import org.junit.Assert; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestRulerNEWT01 extends UITestCase { static long durationPerTest = 10; // ms @@ -74,14 +77,16 @@ public class TestRulerNEWT01 extends UITestCase { final ShaderState st = new ShaderState(); final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, RedSquareES2.class, "shader", - "shader/bin", "default", false); + "shader/bin", "default", true); final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, "shader", - "shader/bin", "ruler", false); + "shader/bin", "ruler", true); + vp0.defaultShaderCustomization(gl, true, true); + fp0.defaultShaderCustomization(gl, true, true); final ShaderProgram sp0 = new ShaderProgram(); sp0.add(gl, vp0, System.err); sp0.add(gl, fp0, System.err); - Assert.assertTrue(0<=sp0.program()); + Assert.assertTrue(0 != sp0.program()); Assert.assertTrue(!sp0.inUse()); Assert.assertTrue(!sp0.linked()); Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); @@ -107,11 +112,13 @@ public class TestRulerNEWT01 extends UITestCase { Assert.assertNotNull(winctx); Assert.assertNotNull(winctx.window); Assert.assertNotNull(winctx.window.getScreen()); - ScreenMode sm = winctx.window.getScreen().getCurrentScreenMode(); - Assert.assertNotNull(sm); - System.err.println(sm); - final MonitorMode mmode = sm.getMonitorMode(); - final DimensionImmutable sdim = mmode.getScreenSizeMM(); + final MonitorDevice monitor = winctx.window.getMainMonitor(); + Assert.assertNotNull(monitor); + System.err.println(monitor); + final MonitorMode mmode = monitor.getCurrentMode(); + Assert.assertNotNull(mmode); + System.err.println(mmode); + final DimensionImmutable sdim = monitor.getSizeMM(); final DimensionImmutable spix = mmode.getSurfaceSize().getResolution(); final GLUniformData rulerPixFreq = new GLUniformData("gcu_RulerPixFreq", 2, Buffers.newDirectFloatBuffer(2)); final FloatBuffer rulerPixFreqV = (FloatBuffer) rulerPixFreq.getBuffer(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestShaderCompilationBug459AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestShaderCompilationBug459AWT.java index d133ebde5..f26927a5c 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestShaderCompilationBug459AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestShaderCompilationBug459AWT.java @@ -44,11 +44,14 @@ import org.junit.Assume; import org.junit.BeforeClass; import org.junit.AfterClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; /** * Duplicates bug 459, where a vertex shader won't compile when 8 bits of stencil are requested. * This bug is Windows-only; it works on Mac OS X and CentOS. */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestShaderCompilationBug459AWT extends UITestCase { static int width, height; static long duration = 500; // ms @@ -81,7 +84,6 @@ public class TestShaderCompilationBug459AWT extends UITestCase { final GLCanvas glCanvas = new GLCanvas(caps); Assert.assertNotNull(glCanvas); frame.add(glCanvas); - frame.setSize(512, 512); glCanvas.addGLEventListener(new GLEventListener() { /* @Override */ @@ -131,7 +133,15 @@ public class TestShaderCompilationBug459AWT extends UITestCase { }); Animator animator = new Animator(glCanvas); - frame.setVisible(true); + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setSize(512, 512); + frame.setVisible(true); + } } ); + } catch(Exception ex) { + throw new RuntimeException(ex); + } animator.setUpdateFPSFrames(1, null); animator.start(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestTransformFeedbackVaryingsBug407NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestTransformFeedbackVaryingsBug407NEWT.java index 3be08971b..bbfe1dd1a 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestTransformFeedbackVaryingsBug407NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestTransformFeedbackVaryingsBug407NEWT.java @@ -15,6 +15,8 @@ import javax.media.opengl.GLProfile; import org.junit.Assert; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import com.jogamp.opengl.util.glsl.ShaderUtil; @@ -24,6 +26,7 @@ import java.io.IOException; * Bug 'Function glTransformFeedbackVaryings incorrectly passes argument' * http://jogamp.org/bugzilla/show_bug.cgi?id=407 */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestTransformFeedbackVaryingsBug407NEWT extends UITestCase { private static final boolean debugGL = true; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glu/TestBug365TextureGenerateMipMaps.java b/src/test/com/jogamp/opengl/test/junit/jogl/glu/TestBug365TextureGenerateMipMaps.java new file mode 100644 index 000000000..b9e64e1da --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/glu/TestBug365TextureGenerateMipMaps.java @@ -0,0 +1,270 @@ +package com.jogamp.opengl.test.junit.jogl.glu;
+
+import java.nio.ByteBuffer;
+
+import javax.media.opengl.GL2;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLOffscreenAutoDrawable;
+import javax.media.opengl.GLProfile;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+import jogamp.opengl.glu.mipmap.Mipmap;
+import jogamp.opengl.glu.mipmap.ScaleInternal;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.texture.Texture;
+import com.jogamp.opengl.util.texture.TextureData;
+import com.jogamp.opengl.util.texture.TextureIO;
+
+/**
+ * This test creates a {@link Texture} from {@link TextureData} of various pixel formats
+ * and pixel types with auto generate mipmaps set to {@code true}.
+ * <br></br>
+ * Bug Reference: https://jogamp.org/bugzilla/show_bug.cgi?id=365
+ * <br></br>
+ * The bug pertains to mipmap generation from a Texture and exists in {@link ScaleInternal}
+ * where a {@link java.nio.BufferUnderflowException} is thrown.
+ * <br></br>
+ * <ul>This suite of test cases test:
+ * <li>{@link ScaleInternal#scale_internal_ubyte(int, int, int, ByteBuffer, int, int, ByteBuffer, int, int, int)}</li>
+ * <li>{@link ScaleInternal#scale_internal_byte(int, int, int, ByteBuffer, int, int, ByteBuffer, int, int, int)}</li>
+ * <li>{@link ScaleInternal#scale_internal_ushort(int, int, int, ByteBuffer, int, int, java.nio.ShortBuffer, int, int, int, boolean)}</li>
+ * <li>{@link ScaleInternal#scale_internal_short(int, int, int, ByteBuffer, int, int, java.nio.ShortBuffer, int, int, int, boolean)}</li>
+ * <li>{@link ScaleInternal#scale_internal_uint(int, int, int, ByteBuffer, int, int, java.nio.IntBuffer, int, int, int, boolean)}</li>
+ * <li>{@link ScaleInternal#scale_internal_int(int, int, int, ByteBuffer, int, int, java.nio.IntBuffer, int, int, int, boolean)}</li>
+ * <li>{@link ScaleInternal#scale_internal_float(int, int, int, ByteBuffer, int, int, java.nio.FloatBuffer, int, int, int, boolean)}</li>
+ * </ul>
+ *
+ * @author Michael Esemplare, et.al.
+ *
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestBug365TextureGenerateMipMaps extends UITestCase {
+ static GLOffscreenAutoDrawable drawable;
+
+ @BeforeClass
+ public static void setup() throws Throwable {
+ // disableNPOT
+ System.setProperty("jogl.texture.nonpot", "true");
+ try {
+ setUpOffscreenAutoDrawable();
+ } catch (Throwable t) {
+ throw t;
+ }
+ }
+
+ @AfterClass
+ public static void teardown() {
+ tearDownOffscreenAutoDrawable();
+ }
+
+ private static void setUpOffscreenAutoDrawable() throws Throwable {
+ GLProfile glp = GLProfile.getDefault();
+ GLCapabilities caps = new GLCapabilities(glp);
+
+ GLDrawableFactory factory = GLDrawableFactory.getFactory(glp);
+
+ // Make a drawable to get an offscreen context
+ drawable = factory.createOffscreenAutoDrawable(null, caps, null, 2, 2);
+ drawable.display(); // trigger context creation
+ GLContext glContext = drawable.getContext();
+ try {
+ Assert.assertTrue("Could not make context current", GLContext.CONTEXT_NOT_CURRENT < glContext.makeCurrent());
+ } catch (Throwable t) {
+ tearDownOffscreenAutoDrawable();
+ throw t;
+ }
+ }
+
+ private static void tearDownOffscreenAutoDrawable() {
+ if(drawable != null) {
+ drawable.getContext().release();
+ drawable.destroy();
+ drawable = null;
+ }
+ }
+
+ private static void testTextureMipMapGeneration(int width, int height, int pixelFormat, int pixelType) {
+ int internalFormat = pixelFormat;
+ int border = 0;
+ boolean mipmap = true;
+ boolean dataIsCompressed = false;
+ boolean mustFlipVertically = false;
+
+ int memReq = Mipmap.image_size( width, height, pixelFormat, pixelType );
+ ByteBuffer buffer = Buffers.newDirectByteBuffer( memReq );
+
+ TextureData data = new TextureData(drawable.getGLProfile(),
+ internalFormat,
+ width,
+ height,
+ border,
+ pixelFormat,
+ pixelType,
+ mipmap,
+ dataIsCompressed,
+ mustFlipVertically,
+ buffer,
+ null);
+
+ Texture texture = TextureIO.newTexture(drawable.getGL(), data);
+ // Cleanup
+ texture.destroy(drawable.getGL());
+ data.destroy();
+ buffer.clear();
+ buffer = null;
+ }
+
+ @Test
+ public void test00_MipMap_ScaleInternal_RGB_UBYTE () {
+ int width = 1;
+ int height = 7;
+ int pixelFormat = GL2.GL_RGB;
+ int pixelType = GL2.GL_UNSIGNED_BYTE;
+
+ testTextureMipMapGeneration(width, height, pixelFormat, pixelType);
+ }
+
+ @Test
+ public void test01_MipMap_ScaleInternal_RGBA_UBYTE () {
+ int width = 1;
+ int height = 7;
+ int pixelFormat = GL2.GL_RGBA;
+ int pixelType = GL2.GL_UNSIGNED_BYTE;
+
+ testTextureMipMapGeneration(width, height, pixelFormat, pixelType);
+ }
+
+ @Test
+ public void test02_MipMap_ScaleInternal_RGB_BYTE () {
+ int width = 1;
+ int height = 7;
+ int pixelFormat = GL2.GL_RGB;
+ int pixelType = GL2.GL_BYTE;
+
+ testTextureMipMapGeneration(width, height, pixelFormat, pixelType);
+ }
+
+ @Test
+ public void test03_MipMap_ScaleInternal_RGBA_BYTE () {
+ int width = 1;
+ int height = 7;
+ int pixelFormat = GL2.GL_RGBA;
+ int pixelType = GL2.GL_BYTE;
+
+ testTextureMipMapGeneration(width, height, pixelFormat, pixelType);
+ }
+
+ @Test
+ public void test04_MipMap_ScaleInternal_RGB_USHORT () {
+ int width = 1;
+ int height = 7;
+ int pixelFormat = GL2.GL_RGB;
+ int pixelType = GL2.GL_UNSIGNED_SHORT;
+
+ testTextureMipMapGeneration(width, height, pixelFormat, pixelType);
+ }
+
+ @Test
+ public void test05_MipMap_ScaleInternal_RGBA_USHORT () {
+ int width = 1;
+ int height = 7;
+ int pixelFormat = GL2.GL_RGBA;
+ int pixelType = GL2.GL_UNSIGNED_SHORT;
+
+ testTextureMipMapGeneration(width, height, pixelFormat, pixelType);
+ }
+
+ @Test
+ public void test06_MipMap_ScaleInternal_RGB_SHORT () {
+ int width = 1;
+ int height = 7;
+ int pixelFormat = GL2.GL_RGB;
+ int pixelType = GL2.GL_SHORT;
+
+ testTextureMipMapGeneration(width, height, pixelFormat, pixelType);
+ }
+
+ @Test
+ public void test07_MipMap_ScaleInternal_RGBA_SHORT () {
+ int width = 1;
+ int height = 7;
+ int pixelFormat = GL2.GL_RGBA;
+ int pixelType = GL2.GL_SHORT;
+
+ testTextureMipMapGeneration(width, height, pixelFormat, pixelType);
+ }
+
+ @Test
+ public void test08_MipMap_ScaleInternal_RGB_UINT () {
+ int width = 1;
+ int height = 7;
+ int pixelFormat = GL2.GL_RGB;
+ int pixelType = GL2.GL_UNSIGNED_INT;
+
+ testTextureMipMapGeneration(width, height, pixelFormat, pixelType);
+ }
+
+ @Test
+ public void test09_MipMap_ScaleInternal_RGBA_UINT () {
+ int width = 1;
+ int height = 7;
+ int pixelFormat = GL2.GL_RGBA;
+ int pixelType = GL2.GL_UNSIGNED_INT;
+
+ testTextureMipMapGeneration(width, height, pixelFormat, pixelType);
+ }
+
+ @Test
+ public void test10_MipMap_ScaleInternal_RGB_INT () {
+ int width = 1;
+ int height = 7;
+ int pixelFormat = GL2.GL_RGB;
+ int pixelType = GL2.GL_INT;
+
+ testTextureMipMapGeneration(width, height, pixelFormat, pixelType);
+ }
+
+ @Test
+ public void test11_MipMap_ScaleInternal_RGBA_INT () {
+ int width = 1;
+ int height = 7;
+ int pixelFormat = GL2.GL_RGBA;
+ int pixelType = GL2.GL_INT;
+
+ testTextureMipMapGeneration(width, height, pixelFormat, pixelType);
+ }
+
+ @Test
+ public void test12_MipMap_ScaleInternal_RGB_FLOAT () {
+ int width = 1;
+ int height = 7;
+ int pixelFormat = GL2.GL_RGB;
+ int pixelType = GL2.GL_FLOAT;
+
+ testTextureMipMapGeneration(width, height, pixelFormat, pixelType);
+ }
+
+ @Test
+ public void test13_MipMap_ScaleInternal_RGBA_FLOAT () {
+ int width = 1;
+ int height = 7;
+ int pixelFormat = GL2.GL_RGBA;
+ int pixelType = GL2.GL_FLOAT;
+
+ testTextureMipMapGeneration(width, height, pixelFormat, pixelType);
+ }
+
+ public static void main(String[] args) {
+ org.junit.runner.JUnitCore.main(TestBug365TextureGenerateMipMaps.class.getName());
+ }
+}
\ No newline at end of file diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glu/TestBug463ScaleImageMemoryAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/glu/TestBug463ScaleImageMemoryAWT.java index 3f122accb..e5690a0b0 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/glu/TestBug463ScaleImageMemoryAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/glu/TestBug463ScaleImageMemoryAWT.java @@ -41,6 +41,8 @@ import javax.media.opengl.glu.gl2es1.GLUgl2es1; import org.junit.Assume; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import com.jogamp.opengl.test.junit.util.UITestCase; @@ -52,6 +54,7 @@ import com.jogamp.opengl.test.junit.util.UITestCase; * was in JOGL 1) solves the problem. * @author Wade Walker */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestBug463ScaleImageMemoryAWT extends UITestCase implements GLEventListener { /* @Override */ diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glu/TestBug694ScaleImageUnpackBufferSizeAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/glu/TestBug694ScaleImageUnpackBufferSizeAWT.java new file mode 100644 index 000000000..ca5b089e1 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/glu/TestBug694ScaleImageUnpackBufferSizeAWT.java @@ -0,0 +1,163 @@ +/** + * Copyright 2013 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.jogl.glu; + +import java.awt.Frame; +import java.nio.ByteBuffer; + +import javax.media.opengl.GL; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; +import javax.media.opengl.glu.GLU; + +import org.junit.Assume; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.common.nio.Buffers; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.GLBuffers; +import com.jogamp.opengl.util.GLPixelStorageModes; + +/** + * Demonstrates how to use {@link GLBuffers#sizeof(GL, int[], int, int, int, int, int, boolean)} + * to determine the unpack buffer size for {@link GLU#gluScaleImage(int, int, int, int, java.nio.Buffer, int, int, int, java.nio.Buffer)}. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestBug694ScaleImageUnpackBufferSizeAWT extends UITestCase implements GLEventListener { + + /* @Override */ + public void init(GLAutoDrawable drawable) { + } + + /* @Override */ + public void display(GLAutoDrawable drawable) { + if( !testDone ) { + testDone = true; + + final GL gl = drawable.getGL(); + GLU glu = GLU.createGLU(gl); + testGLUScaleImage(gl, glu, 0); // default 4 + testGLUScaleImage(gl, glu, 1); + testGLUScaleImage(gl, glu, 4); + testGLUScaleImage(gl, glu, 8); + glu.destroy(); + } + } + + boolean testDone = false; + + private void testGLUScaleImage(GL gl, GLU glu, int unpackAlignment) { + final GLPixelStorageModes psm = new GLPixelStorageModes(gl); + if(0 < unpackAlignment) { + psm.setUnpackAlignment(gl, unpackAlignment); + } + + final int widthin = 213; + final int heightin = 213; + + final int widthout = 256; + final int heightout = 256; + + final int glFormat = GL.GL_LUMINANCE; + final int glType = GL.GL_UNSIGNED_BYTE; + final int tmp[] = new int[1]; + + final int unpackSizeInLen = GLBuffers.sizeof(gl, tmp, glFormat, glType, widthin, heightin, 1, false); + final int unpackSizeOutLen = GLBuffers.sizeof(gl, tmp, glFormat, glType, widthout, heightout, 1, false); + + System.err.println("Unpack-Alignment "+unpackAlignment+": in-size "+unpackSizeInLen); + System.err.println("Unpack-Alignment "+unpackAlignment+": out-size "+unpackSizeOutLen); + + ByteBuffer bufferIn = Buffers.newDirectByteBuffer(unpackSizeInLen); + ByteBuffer bufferOut = Buffers.newDirectByteBuffer(unpackSizeOutLen); + + glu.gluScaleImage( GL.GL_LUMINANCE, + widthin, heightin, GL.GL_UNSIGNED_BYTE, bufferIn, + widthout, heightout, GL.GL_UNSIGNED_BYTE, bufferOut ); + + psm.restore(gl); + } + + /* @Override */ + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + } + + + /* @Override */ + public void dispose(GLAutoDrawable drawable) { + } + + @Test + public void test01() throws InterruptedException { + GLProfile glprofile = GLProfile.getDefault(); + GLCapabilities glCapabilities = new GLCapabilities(glprofile); + final GLCanvas canvas = new GLCanvas(glCapabilities); + canvas.addGLEventListener( this ); + + final Frame frame = new Frame("Test"); + frame.add(canvas); + frame.setSize(256, 256); + frame.validate(); + + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(true); + }}); + } catch (Throwable t) { + t.printStackTrace(); + Assume.assumeNoException(t); + } + + canvas.display(); + + Thread.sleep(200); + + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + frame.remove(canvas); + frame.dispose(); + }}); + } catch (Throwable t) { + t.printStackTrace(); + Assume.assumeNoException(t); + } + } + + public static void main(String args[]) { + org.junit.runner.JUnitCore.main(TestBug694ScaleImageUnpackBufferSizeAWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/math/TestBinary16NOUI.java b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestBinary16NOUI.java new file mode 100644 index 000000000..8f56c133e --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestBinary16NOUI.java @@ -0,0 +1,715 @@ +/** + * Copyright 2013 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.jogl.math; + +import org.junit.Assert; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import com.jogamp.opengl.math.Binary16; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public final class TestBinary16NOUI extends UITestCase /* due to hardship on machine, we want to run this test exclusively! */ +{ + static int stepping = 1; + static boolean verbose = false; + + /** + * Exponents in the range [-15, 16] are encoded and decoded correctly. + */ + + @SuppressWarnings("static-method") @Test public void testExponentIdentity() + { + System.out.println("-- Exponent identities"); + for (int e = -15; e <= 16; ++e) { + final char p = Binary16.packSetExponentUnbiasedUnchecked(e); + final int u = Binary16.unpackGetExponentUnbiased(p); + if( verbose ) { + System.out.println("e: " + e +", p: "+Integer.toHexString(p)+", u: "+u); + } + Assert.assertEquals(e, u); + } + } + + /** + * Infinities are infinite. + */ + + @SuppressWarnings("static-method") @Test public void testInfinite() + { + Assert.assertTrue(Binary16.isInfinite(Binary16.POSITIVE_INFINITY)); + Assert.assertTrue(Binary16.isInfinite(Binary16.NEGATIVE_INFINITY)); + Assert.assertFalse(Binary16.isInfinite(Binary16.exampleNaN())); + + for (int i = 0; i <= 65535; i+=stepping) { + Assert.assertFalse(Binary16.isInfinite(Binary16.packDouble(i))); + } + } + + /** + * The unencoded exponent of infinity is 16. + */ + + @SuppressWarnings("static-method") @Test public void testInfinityExponent() + { + Assert.assertEquals( + 16, + Binary16.unpackGetExponentUnbiased(Binary16.POSITIVE_INFINITY)); + } + + /** + * The unencoded exponent of infinity is 16. + */ + + @SuppressWarnings("static-method") @Test public + void + testInfinityNegativeExponent() + { + Assert.assertEquals( + 16, + Binary16.unpackGetExponentUnbiased(Binary16.NEGATIVE_INFINITY)); + } + + /** + * The sign of negative infinity is 1. + */ + + @SuppressWarnings("static-method") @Test public + void + testInfinityNegativeSign() + { + Assert + .assertEquals(1, Binary16.unpackGetSign(Binary16.NEGATIVE_INFINITY)); + } + + /** + * The significand of infinity is 0. + */ + + @SuppressWarnings("static-method") @Test public + void + testInfinityNegativeSignificand() + { + Assert.assertEquals( + 0, + Binary16.unpackGetSignificand(Binary16.NEGATIVE_INFINITY)); + } + + /** + * The sign of positive infinity is 0. + */ + + @SuppressWarnings("static-method") @Test public void testInfinitySign() + { + Assert + .assertEquals(0, Binary16.unpackGetSign(Binary16.POSITIVE_INFINITY)); + } + + /** + * The significand of infinity is 0. + */ + + @SuppressWarnings("static-method") @Test public + void + testInfinitySignificand() + { + Assert.assertEquals( + 0, + Binary16.unpackGetSignificand(Binary16.POSITIVE_INFINITY)); + } + + /** + * NaN is NaN. + */ + + @SuppressWarnings("static-method") @Test public void testNaN() + { + final int n = + Binary16.packSetExponentUnbiasedUnchecked(16) + | Binary16.packSetSignificandUnchecked(1); + final char c = (char) n; + Assert.assertEquals(16, Binary16.unpackGetExponentUnbiased(c)); + Assert.assertEquals(1, Binary16.unpackGetSignificand(c)); + Assert.assertEquals( + 16, + Binary16.unpackGetExponentUnbiased(Binary16.exampleNaN())); + Assert.assertEquals( + 1, + Binary16.unpackGetSignificand(Binary16.exampleNaN())); + Assert.assertTrue(Binary16.isNaN(c)); + Assert.assertTrue(Binary16.isNaN(Binary16.exampleNaN())); + } + + /** + * Packing NaN results in NaN. + */ + + @SuppressWarnings("static-method") @Test public void testPackDoubleNaN() + { + final double k = Double.NaN; + final char r = Binary16.packDouble(k); + Assert.assertTrue(Binary16.isNaN(r)); + } + + /** + * Packing negative infinity results in negative infinity. + */ + + @SuppressWarnings("static-method") @Test public + void + testPackDoubleNegativeInfinity() + { + Assert.assertTrue(Binary16.NEGATIVE_INFINITY == Binary16 + .packDouble(Double.NEGATIVE_INFINITY)); + } + + /** + * Packing negative zero results in negative zero. + */ + + @SuppressWarnings("static-method") @Test public + void + testPackDoubleNegativeZero() + { + Assert.assertTrue(Binary16.NEGATIVE_ZERO == Binary16.packDouble(-0.0)); + } + + /** + * Packing positive infinity results in positive infinity. + */ + + @SuppressWarnings("static-method") @Test public + void + testPackDoublePositiveInfinity() + { + Assert.assertTrue(Binary16.POSITIVE_INFINITY == Binary16 + .packDouble(Double.POSITIVE_INFINITY)); + } + + /** + * Packing positive zero results in positive zero. + */ + + @SuppressWarnings("static-method") @Test public + void + testPackDoublePositiveZero() + { + Assert.assertTrue(Binary16.POSITIVE_ZERO == Binary16.packDouble(0.0)); + } + + /** + * Integers in the range [0, 65520] should be representable. + */ + + @SuppressWarnings({ "static-method", "boxing" }) @Test public + void + testPackDoubleUnpackFloat() + { + for (int i = 0; i <= 65536; i+=stepping) { + final double in = i; + final char packed = Binary16.packDouble(in); + final float r = Binary16.unpackFloat(packed); + if( verbose ) { + System.out.println(String.format( + "packed: 0x%04x 0b%s in: %f unpacked: %f", + (int) packed, + Binary16.toRawBinaryString(packed), + in, + r)); + } + + if (i <= 2048) { + Assert.assertEquals(in, r, 0.0); + } + if ((i > 2048) && (i <= 4096)) { + Assert.assertTrue((r % 2) == 0); + } + if ((i > 4096) && (i <= 8192)) { + Assert.assertTrue((r % 4) == 0); + } + if ((i > 8192) && (i <= 16384)) { + Assert.assertTrue((r % 8) == 0); + } + if ((i > 16384) && (i <= 32768)) { + Assert.assertTrue((r % 16) == 0); + } + if ((i > 32768) && (i < 65536)) { + Assert.assertTrue((r % 32) == 0); + } + if (i == 65536) { + Assert.assertTrue(Double.isInfinite(r)); + } + } + } + + /** + * Integers in the range [0, 65520] should be representable. + */ + + @SuppressWarnings({ "static-method", "boxing" }) @Test public + void + testPackFloatDoubleEquivalent() + { + for (int i = 0; i <= 65536; i+=stepping) { + final float f_in = i; + final double d_in = i; + final char pf = Binary16.packFloat(f_in); + final char pd = Binary16.packDouble(d_in); + + if( verbose ) { + System.out.println("i: " + i); + System.out.println(String.format( + "pack_f: 0x%04x 0b%s", + (int) pf, + Binary16.toRawBinaryString(pf))); + System.out.println(String.format( + "pack_d: 0x%04x 0b%s", + (int) pd, + Binary16.toRawBinaryString(pd))); + } + + Assert.assertEquals(pf, pd); + } + } + + /** + * Packing NaN results in NaN. + */ + + @SuppressWarnings("static-method") @Test public void testPackFloatNaN() + { + final float k = Float.NaN; + final char r = Binary16.packFloat(k); + Assert.assertTrue(Binary16.isNaN(r)); + } + + /** + * Packing negative infinity results in negative infinity. + */ + + @SuppressWarnings("static-method") @Test public + void + testPackFloatNegativeInfinity() + { + Assert.assertTrue(Binary16.NEGATIVE_INFINITY == Binary16 + .packFloat(Float.NEGATIVE_INFINITY)); + } + + /** + * Packing negative zero results in negative zero. + */ + + @SuppressWarnings("static-method") @Test public + void + testPackFloatNegativeZero() + { + Assert.assertTrue(Binary16.NEGATIVE_ZERO == Binary16.packFloat(-0.0f)); + } + + /** + * Packing positive infinity results in positive infinity. + */ + + @SuppressWarnings("static-method") @Test public + void + testPackFloatPositiveInfinity() + { + Assert.assertTrue(Binary16.POSITIVE_INFINITY == Binary16 + .packFloat(Float.POSITIVE_INFINITY)); + } + + /** + * Packing positive zero results in positive zero. + */ + + @SuppressWarnings("static-method") @Test public + void + testPackFloatPositiveZero() + { + Assert.assertTrue(Binary16.POSITIVE_ZERO == Binary16.packFloat(0.0f)); + } + + /** + * Integers in the range [0, 65520] should be representable. + */ + + @SuppressWarnings({ "static-method", "boxing" }) @Test public + void + testPackFloatUnpackDouble() + { + for (int i = 0; i <= 65536; i+=stepping) { + final float in = i; + final char packed = Binary16.packFloat(in); + final double r = Binary16.unpackDouble(packed); + if( verbose ) { + System.out.println(String.format( + "packed: 0x%04x 0b%s in: %f unpacked: %f", + (int) packed, + Binary16.toRawBinaryString(packed), + in, + r)); + } + + if (i <= 2048) { + Assert.assertEquals(in, r, 0.0); + } + if ((i > 2048) && (i <= 4096)) { + Assert.assertTrue((r % 2) == 0); + } + if ((i > 4096) && (i <= 8192)) { + Assert.assertTrue((r % 4) == 0); + } + if ((i > 8192) && (i <= 16384)) { + Assert.assertTrue((r % 8) == 0); + } + if ((i > 16384) && (i <= 32768)) { + Assert.assertTrue((r % 16) == 0); + } + if ((i > 32768) && (i < 65536)) { + Assert.assertTrue((r % 32) == 0); + } + if (i == 65536) { + Assert.assertTrue(Double.isInfinite(r)); + } + } + } + + /** + * Integers in the range [0, 65520] should be representable. + */ + + @SuppressWarnings({ "static-method", "boxing" }) @Test public + void + testPackUnpackDouble() + { + for (int i = 0; i <= 65536; i+=stepping) { + final double in = i; + final char packed = Binary16.packDouble(in); + final double r = Binary16.unpackDouble(packed); + if( verbose ) { + System.out.println(String.format( + "packed: 0x%04x 0b%s in: %f unpacked: %f", + (int) packed, + Binary16.toRawBinaryString(packed), + in, + r)); + } + + if (i <= 2048) { + Assert.assertEquals(in, r, 0.0); + } + if ((i > 2048) && (i <= 4096)) { + Assert.assertTrue((r % 2) == 0); + } + if ((i > 4096) && (i <= 8192)) { + Assert.assertTrue((r % 4) == 0); + } + if ((i > 8192) && (i <= 16384)) { + Assert.assertTrue((r % 8) == 0); + } + if ((i > 16384) && (i <= 32768)) { + Assert.assertTrue((r % 16) == 0); + } + if ((i > 32768) && (i < 65536)) { + Assert.assertTrue((r % 32) == 0); + } + if (i == 65536) { + Assert.assertTrue(Double.isInfinite(r)); + } + } + } + + /** + * Integers in the range [0, 65520] should be representable. + */ + + @SuppressWarnings({ "static-method", "boxing" }) @Test public + void + testPackUnpackFloat() + { + for (int i = 0; i <= 65536; i+=stepping) { + final float in = i; + final char packed = Binary16.packFloat(in); + final float r = Binary16.unpackFloat(packed); + if( verbose ) { + System.out.println(String.format( + "packed: 0x%04x 0b%s in: %f unpacked: %f", + (int) packed, + Binary16.toRawBinaryString(packed), + in, + r)); + } + if (i <= 2048) { + Assert.assertEquals(in, r, 0.0); + } + if ((i > 2048) && (i <= 4096)) { + Assert.assertTrue((r % 2) == 0); + } + if ((i > 4096) && (i <= 8192)) { + Assert.assertTrue((r % 4) == 0); + } + if ((i > 8192) && (i <= 16384)) { + Assert.assertTrue((r % 8) == 0); + } + if ((i > 16384) && (i <= 32768)) { + Assert.assertTrue((r % 16) == 0); + } + if ((i > 32768) && (i < 65536)) { + Assert.assertTrue((r % 32) == 0); + } + if (i == 65536) { + Assert.assertTrue(Float.isInfinite(r)); + } + } + } + + /** + * Signs in the range [0, 1] are encoded and decoded correctly. + */ + + @SuppressWarnings("static-method") @Test public void testSignIdentity() + { + System.out.println("-- Sign identities"); + for (int e = 0; e <= 1; ++e) { + final char p = Binary16.packSetSignUnchecked(e); + final int u = Binary16.unpackGetSign(p); + if( verbose ) { + System.out.println("e: " + e +", p: "+Integer.toHexString(p)+", u: "+u); + } + Assert.assertEquals(e, u); + } + } + + /** + * Significands in the range [0, 1023] are encoded and decoded correctly. + */ + + @SuppressWarnings("static-method") @Test public + void + testSignificandIdentity() + { + System.out.println("-- Significand identities"); + for (int e = 0; e <= 1023; ++e) { + final char p = Binary16.packSetSignificandUnchecked(e); + final int u = Binary16.unpackGetSignificand(p); + if( verbose ) { + System.out.println("e: " + e +", p: "+Integer.toHexString(p)+", u: "+u); + } + Assert.assertEquals(e, u); + } + } + + /** + * Unpacking NaN results in NaN. + */ + + @SuppressWarnings("static-method") @Test public void testUnpackDoubleNaN() + { + final double k = Binary16.unpackDouble(Binary16.exampleNaN()); + Assert.assertTrue(Double.isNaN(k)); + } + + /** + * Unpacking negative infinity results in negative infinity. + */ + + @SuppressWarnings("static-method") @Test public + void + testUnpackDoubleNegativeInfinity() + { + Assert.assertTrue(Double.NEGATIVE_INFINITY == Binary16 + .unpackDouble(Binary16.NEGATIVE_INFINITY)); + } + + /** + * Unpacking negative zero results in negative zero. + */ + + @SuppressWarnings("static-method") @Test public + void + testUnpackDoubleNegativeZero() + { + Assert.assertTrue(-0.0 == Binary16.unpackDouble(Binary16.NEGATIVE_ZERO)); + } + + /** + * Unpacking 1.0 results in 1.0. + */ + + @SuppressWarnings({ "static-method", "boxing" }) @Test public + void + testUnpackDoubleOne() + { + final char one = 0x3C00; + final double r = Binary16.unpackDouble(one); + System.out.println(String.format("0x%04x -> %f", (int) one, r)); + Assert.assertEquals(r, 1.0, 0.0); + } + + /** + * Unpacking -1.0 results in -1.0. + */ + + @SuppressWarnings({ "static-method", "boxing" }) @Test public + void + testUnpackDoubleOneNegative() + { + final char one = 0xBC00; + final double r = Binary16.unpackDouble(one); + System.out.println(String.format("0x%04x -> %f", (int) one, r)); + Assert.assertEquals(r, -1.0, 0.0); + } + + /** + * Unpacking positive infinity results in positive infinity. + */ + + @SuppressWarnings("static-method") @Test public + void + testUnpackDoublePositiveInfinity() + { + Assert.assertTrue(Double.POSITIVE_INFINITY == Binary16 + .unpackDouble(Binary16.POSITIVE_INFINITY)); + } + + /** + * Unpacking positive zero results in positive zero. + */ + + @SuppressWarnings("static-method") @Test public + void + testUnpackDoublePositiveZero() + { + Assert.assertTrue(0.0 == Binary16.unpackDouble(Binary16.POSITIVE_ZERO)); + } + + /** + * Unpacking 2.0 results in 2.0. + */ + + @SuppressWarnings({ "static-method", "boxing" }) @Test public + void + testUnpackDoubleTwo() + { + final char one = 0x4000; + final double r = Binary16.unpackDouble(one); + System.out.println(String.format("%04x -> %f", (int) one, r)); + Assert.assertEquals(r, 2.0, 0.0); + } + + /** + * Unpacking -2.0 results in -2.0. + */ + + @SuppressWarnings({ "static-method", "boxing" }) @Test public + void + testUnpackDoubleTwoNegative() + { + final char one = 0xC000; + final double r = Binary16.unpackDouble(one); + System.out.println(String.format("%04x -> %f", (int) one, r)); + Assert.assertEquals(r, -2.0, 0.0); + } + + /** + * Unpacking NaN results in NaN. + */ + + @SuppressWarnings("static-method") @Test public void testUnpackFloatNaN() + { + final float k = Binary16.unpackFloat(Binary16.exampleNaN()); + Assert.assertTrue(Float.isNaN(k)); + } + + /** + * Unpacking negative infinity results in negative infinity. + */ + + @SuppressWarnings("static-method") @Test public + void + testUnpackFloatNegativeInfinity() + { + Assert.assertTrue(Float.NEGATIVE_INFINITY == Binary16 + .unpackFloat(Binary16.NEGATIVE_INFINITY)); + } + + /** + * Unpacking negative zero results in negative zero. + */ + + @SuppressWarnings("static-method") @Test public + void + testUnpackFloatNegativeZero() + { + Assert.assertTrue(-0.0 == Binary16.unpackFloat(Binary16.NEGATIVE_ZERO)); + } + + /** + * Unpacking 1.0 results in 1.0. + */ + + @SuppressWarnings({ "static-method", "boxing" }) @Test public + void + testUnpackFloatOne() + { + final char one = 0x3C00; + final float r = Binary16.unpackFloat(one); + System.out.println(String.format("0x%04x -> %f", (int) one, r)); + Assert.assertEquals(r, 1.0, 0.0); + } + + /** + * Unpacking -1.0 results in -1.0. + */ + + @SuppressWarnings({ "static-method", "boxing" }) @Test public + void + testUnpackFloatOneNegative() + { + final char one = 0xBC00; + final float r = Binary16.unpackFloat(one); + System.out.println(String.format("0x%04x -> %f", (int) one, r)); + Assert.assertEquals(r, -1.0, 0.0); + } + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-stepping")) { + stepping = MiscUtils.atoi(args[++i], stepping); + } else if(args[i].equals("-verbose")) { + verbose = true; + } + } + org.junit.runner.JUnitCore.main(TestBinary16NOUI.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/math/TestBinary32NOUI.java b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestBinary32NOUI.java new file mode 100644 index 000000000..d2a9a92ce --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestBinary32NOUI.java @@ -0,0 +1,93 @@ +/** + * Copyright 2013 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.jogl.math; + +import org.junit.Assert; +import org.junit.Test; + +import com.jogamp.opengl.math.Binary32; + +public class TestBinary32NOUI +{ + @SuppressWarnings("static-method") @Test public void testInfinityExponent() + { + Assert.assertEquals( + 128, + Binary32.unpackGetExponentUnbiased(Float.POSITIVE_INFINITY)); + } + + @SuppressWarnings("static-method") @Test public + void + testInfinityNegativeExponent() + { + Assert.assertEquals( + 128, + Binary32.unpackGetExponentUnbiased(Float.NEGATIVE_INFINITY)); + } + + @SuppressWarnings("static-method") @Test public + void + testInfinityNegativeSign() + { + Assert.assertEquals(1, Binary32.unpackGetSign(Float.NEGATIVE_INFINITY)); + } + + @SuppressWarnings("static-method") @Test public + void + testInfinityNegativeSignificand() + { + Assert.assertEquals( + 0, + Binary32.unpackGetSignificand(Float.NEGATIVE_INFINITY)); + } + + @SuppressWarnings("static-method") @Test public void testInfinitySign() + { + Assert.assertEquals(0, Binary32.unpackGetSign(Float.POSITIVE_INFINITY)); + } + + @SuppressWarnings("static-method") @Test public + void + testInfinitySignificand() + { + Assert.assertEquals( + 0, + Binary32.unpackGetSignificand(Float.POSITIVE_INFINITY)); + } + + @SuppressWarnings("static-method") @Test public void testNaNExponent() + { + Assert.assertEquals(128, Binary32.unpackGetExponentUnbiased(Float.NaN)); + } + + @SuppressWarnings("static-method") @Test public void testNaNSignificand() + { + Assert.assertTrue(Binary32.unpackGetSignificand(Float.NaN) > 0); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/math/TestBinary64NOUI.java b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestBinary64NOUI.java new file mode 100644 index 000000000..f16ea2bee --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestBinary64NOUI.java @@ -0,0 +1,93 @@ +/** + * Copyright 2013 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.jogl.math; + +import org.junit.Assert; +import org.junit.Test; + +import com.jogamp.opengl.math.Binary64; + +public class TestBinary64NOUI +{ + @SuppressWarnings("static-method") @Test public void testInfinityExponent() + { + Assert.assertEquals( + 1024, + Binary64.unpackGetExponentUnbiased(Double.POSITIVE_INFINITY)); + } + + @SuppressWarnings("static-method") @Test public + void + testInfinityNegativeExponent() + { + Assert.assertEquals( + 1024, + Binary64.unpackGetExponentUnbiased(Double.NEGATIVE_INFINITY)); + } + + @SuppressWarnings("static-method") @Test public + void + testInfinityNegativeSign() + { + Assert.assertEquals(1, Binary64.unpackGetSign(Double.NEGATIVE_INFINITY)); + } + + @SuppressWarnings("static-method") @Test public + void + testInfinityNegativeSignificand() + { + Assert.assertEquals( + 0, + Binary64.unpackGetSignificand(Double.NEGATIVE_INFINITY)); + } + + @SuppressWarnings("static-method") @Test public void testInfinitySign() + { + Assert.assertEquals(0, Binary64.unpackGetSign(Double.POSITIVE_INFINITY)); + } + + @SuppressWarnings("static-method") @Test public + void + testInfinitySignificand() + { + Assert.assertEquals( + 0, + Binary64.unpackGetSignificand(Double.POSITIVE_INFINITY)); + } + + @SuppressWarnings("static-method") @Test public void testNaNExponent() + { + Assert.assertEquals(1024, Binary64.unpackGetExponentUnbiased(Double.NaN)); + } + + @SuppressWarnings("static-method") @Test public void testNaNSignificand() + { + Assert.assertTrue(Binary64.unpackGetSignificand(Double.NaN) > 0); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFloatUtil01MatrixMatrixMultNOUI.java b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestFloatUtil01MatrixMatrixMultNOUI.java index 42b5972bb..3f22fec2b 100755..100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFloatUtil01MatrixMatrixMultNOUI.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestFloatUtil01MatrixMatrixMultNOUI.java @@ -26,13 +26,16 @@ * or implied, of JogAmp Community. */ -package com.jogamp.opengl.test.junit.jogl.acore; +package com.jogamp.opengl.test.junit.jogl.math; import org.junit.Assert; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; -import com.jogamp.opengl.FloatUtil; +import com.jogamp.opengl.math.FloatUtil; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestFloatUtil01MatrixMatrixMultNOUI { final float[] m1 = new float[]{ 1, 3, 4, 0, diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glu/TestGluUnprojectDoubleNOUI.java b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestGluUnprojectDoubleNOUI.java index 34b30f04e..db40dad15 100755..100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/glu/TestGluUnprojectDoubleNOUI.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestGluUnprojectDoubleNOUI.java @@ -26,16 +26,19 @@ * or implied, of JogAmp Community. */ -package com.jogamp.opengl.test.junit.jogl.glu; +package com.jogamp.opengl.test.junit.jogl.math; import javax.media.opengl.glu.GLU; import org.junit.Assert; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; /** * @author Julien Gouesse */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestGluUnprojectDoubleNOUI { @Test diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glu/TestGluUnprojectFloatNOUI.java b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestGluUnprojectFloatNOUI.java index 717d5e4b8..0f9a45fd7 100755..100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/glu/TestGluUnprojectFloatNOUI.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestGluUnprojectFloatNOUI.java @@ -26,13 +26,16 @@ * or implied, of JogAmp Community. */ -package com.jogamp.opengl.test.junit.jogl.glu; +package com.jogamp.opengl.test.junit.jogl.math; import javax.media.opengl.glu.GLU; import org.junit.Assert; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestGluUnprojectFloatNOUI { @Test diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/math/TestPMVMatrix01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestPMVMatrix01NEWT.java new file mode 100644 index 000000000..fa18abd6e --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestPMVMatrix01NEWT.java @@ -0,0 +1,469 @@ +/** + * Copyright 2012 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.jogl.math; + +import java.nio.FloatBuffer; + +import javax.media.opengl.GL2ES1; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLProfile; +import javax.media.opengl.fixedfunc.GLMatrixFunc; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.common.os.Platform; +import com.jogamp.opengl.math.FloatUtil; +import com.jogamp.opengl.math.geom.Frustum; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.PMVMatrix; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestPMVMatrix01NEWT extends UITestCase { + + static final float epsilon = 0.00001f; + + // matrix 2 rows x 3 columns - In row major order + static FloatBuffer matrix2x3R = FloatBuffer.wrap( new float[] { 1.0f, 2.0f, 3.0f, + 4.0f, 5.0f, 6.0f } ); + + // matrix 2 rows x 3 columns - In column major order + static FloatBuffer matrix2x3C = FloatBuffer.wrap( new float[] { 1.0f, 4.0f, + 2.0f, 5.0f, + 3.0f, 6.0f } ); + + // matrix 3 rows x 2 columns - In row major order + static FloatBuffer matrix3x2R = FloatBuffer.wrap( new float[] { 1.0f, 2.0f, + 3.0f, 4.0f, + 5.0f, 6.0f } ); + + // matrix 3 rows x 2 columns - In column major order + static FloatBuffer matrix3x2C = FloatBuffer.wrap( new float[] { 1.0f, 3.0f, 5.0f, + 2.0f, 4.0f, 6.0f } ); + + // Translated xyz 123 - Row - In row major order ! + static FloatBuffer translated123R = FloatBuffer.wrap( new float[] { 1.0f, 0.0f, 0.0f, 1.0f, + 0.0f, 1.0f, 0.0f, 2.0f, + 0.0f, 0.0f, 1.0f, 3.0f, + 0.0f, 0.0f, 0.0f, 1.0f } ); + + // Translated xyz 123 - Column - In column major order ! + static FloatBuffer translated123C = FloatBuffer.wrap( new float[] { 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 1.0f, 2.0f, 3.0f, 1.0f } ); + + // Translated xyz 123 - Inverse - In column major order ! + static FloatBuffer translated123I = FloatBuffer.wrap( new float[] { 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + -1.0f, -2.0f, -3.0f, 1.0f } ); + + // Translated xyz 123 - Inverse and Transposed - In column major order ! + static FloatBuffer translated123IT = FloatBuffer.wrap( new float[] { 1.0f, 0.0f, 0.0f, -1.0f, + 0.0f, 1.0f, 0.0f, -2.0f, + 0.0f, 0.0f, 1.0f, -3.0f, + 0.0f, 0.0f, 0.0f, 1.0f } ); + + @Test + public void test00MatrixToString() { + final String s4x4Cpmv = PMVMatrix.matrixToString(null, "%10.5f", translated123C).toString(); + final String s4x4Cflu = FloatUtil.matrixToString(null, null, "%10.5f", translated123C, 0, 4, 4, false).toString(); + final String s4x4Rflu = FloatUtil.matrixToString(null, null, "%10.5f", translated123R, 0, 4, 4, true).toString(); + System.err.println("PMV-C-O 4x4: "); + System.err.println(s4x4Cpmv); + System.err.println(); + System.err.println("FLU-C-O 4x4: "); + System.err.println(s4x4Cflu); + System.err.println(); + System.err.println("FLU-R-O 4x4: "); + System.err.println(s4x4Rflu); + System.err.println(); + Assert.assertEquals(s4x4Cpmv, s4x4Cflu); + Assert.assertEquals(s4x4Cflu, s4x4Rflu); + + final String s2x3Rflu = FloatUtil.matrixToString(null, null, "%10.5f", matrix2x3R, 0, 2, 3, true).toString(); + final String s2x3Cflu = FloatUtil.matrixToString(null, null, "%10.5f", matrix2x3C, 0, 2, 3, false).toString(); + System.err.println("FLU-R-O 2x3: "); + System.err.println(s2x3Rflu); + System.err.println(); + System.err.println("FLU-C-O 2x3: "); + System.err.println(s2x3Cflu); + System.err.println(); + Assert.assertEquals(s2x3Cflu, s2x3Rflu); + + final String s3x2Rflu = FloatUtil.matrixToString(null, null, "%10.5f", matrix3x2R, 0, 3, 2, true).toString(); + final String s3x2Cflu = FloatUtil.matrixToString(null, null, "%10.5f", matrix3x2C, 0, 3, 2, false).toString(); + System.err.println("FLU-R-O 3x2: "); + System.err.println(s3x2Rflu); + System.err.println(); + System.err.println("FLU-C-O 3x2: "); + System.err.println(s3x2Cflu); + System.err.println(); + Assert.assertEquals(s3x2Cflu, s3x2Rflu); + } + + /** + * Test using traditional access workflow, i.e. 1) operation 2) get-matrix references + * <p> + * The Mvi, Mvit and Frustum dirty-bits and request-mask will be validated. + * </p> + */ + @SuppressWarnings("deprecation") + @Test + public void test01MviUpdateTraditionalAccess() { + FloatBuffer p, mv, mvi, mvit; + Frustum frustum; + boolean b; + final PMVMatrix pmv = new PMVMatrix(true); + // System.err.println("P0: "+pmv.toString()); + + Assert.assertTrue("Dirty bits clean, "+pmv.toString(), 0 != pmv.getDirtyBits()); + Assert.assertEquals("Remaining dirty bits not Mvi|Mvit|Frustum, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW|PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW | PMVMatrix.DIRTY_FRUSTUM, pmv.getDirtyBits()); + Assert.assertEquals("Request bits not zero, "+pmv.toString(), 0, pmv.getRequestMask()); + + // + // Action #0 + // + final FloatBuffer ident; + { + pmv.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmv.glLoadIdentity(); + ident = pmv.glGetPMatrixf(); + + pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmv.glLoadIdentity(); + } + Assert.assertTrue("Modified bits zero", 0 != pmv.getModifiedBits(true)); // clear & test + Assert.assertTrue("Dirty bits clean, "+pmv.toString(), 0 != pmv.getDirtyBits()); + Assert.assertEquals("Remaining dirty bits not Mvi|Mvit|Frustum, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW|PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW | PMVMatrix.DIRTY_FRUSTUM, pmv.getDirtyBits()); + Assert.assertEquals("Request bits not zero, "+pmv.toString(), 0, pmv.getRequestMask()); + + // + // Action #1 + // + pmv.glTranslatef(1f, 2f, 3f); // all dirty ! + Assert.assertTrue("Modified bits zero", 0 != pmv.getModifiedBits(true)); // clear & test + Assert.assertTrue("Dirty bits clean, "+pmv.toString(), 0 != pmv.getDirtyBits()); + Assert.assertEquals("Remaining dirty bits not Mvi|Mvit|Frustum, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW|PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW | PMVMatrix.DIRTY_FRUSTUM, pmv.getDirtyBits()); + Assert.assertEquals("Request bits not zero, "+pmv.toString(), 0, pmv.getRequestMask()); + // System.err.println("P1: "+pmv.toString()); + + b = pmv.update(); // will not clean dirty bits, since no request has been made -> false + Assert.assertEquals("Update has been perfomed, but non requested", false, b); + Assert.assertTrue("Dirty bits clean, "+pmv.toString(), 0 != pmv.getDirtyBits()); + Assert.assertEquals("Remaining dirty bits not Mvi|Mvit|Frustum, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW|PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW | PMVMatrix.DIRTY_FRUSTUM, pmv.getDirtyBits()); + Assert.assertEquals("Request bits not zero, "+pmv.toString(), 0, pmv.getRequestMask()); + // System.err.println("P2: "+pmv.toString()); + + // + // Get + // + p = pmv.glGetPMatrixf(); + MiscUtils.assertFloatBufferEquals("P not identity, "+pmv.toString(), ident, p, epsilon); + mv = pmv.glGetMvMatrixf(); + MiscUtils.assertFloatBufferEquals("Mv not translated123, "+pmv.toString(), translated123C, mv, epsilon); + mvi = pmv.glGetMviMatrixf(); + MiscUtils.assertFloatBufferEquals("Mvi not translated123, "+pmv.toString(), translated123I, mvi, epsilon); + Assert.assertEquals("Request bit Mvi not set, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW, pmv.getRequestMask()); + Assert.assertEquals("Remaining dirty bits not Mvit|Frustum, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW | PMVMatrix.DIRTY_FRUSTUM, pmv.getDirtyBits()); + + frustum = pmv.glGetFrustum(); + Assert.assertNotNull("Frustum is null"+pmv.toString(), frustum); // FIXME: Test Frustum value! + Assert.assertEquals("Remaining dirty bits not Mvit, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW, pmv.getDirtyBits()); + Assert.assertEquals("Request bits Mvi|Frustum not set, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW | PMVMatrix.DIRTY_FRUSTUM, pmv.getRequestMask()); + // System.err.println("P3: "+pmv.toString()); + + mvit = pmv.glGetMvitMatrixf(); + MiscUtils.assertFloatBufferEquals("Mvit not translated123, "+pmv.toString()+pmv.toString(), translated123IT, mvit, epsilon); + Assert.assertTrue("Dirty bits not clean, "+pmv.toString(), 0 == pmv.getDirtyBits()); + Assert.assertEquals("Request bits Mvi|Mvit|Frustum not set, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW | PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW | PMVMatrix.DIRTY_FRUSTUM, pmv.getRequestMask()); + // System.err.println("P4: "+pmv.toString()); + + // + // Action #2 + // + pmv.glLoadIdentity(); // all dirty + Assert.assertTrue("Modified bits zero", 0 != pmv.getModifiedBits(true)); // clear & test + Assert.assertTrue("Dirty bits clean, "+pmv.toString(), 0 != pmv.getDirtyBits()); + Assert.assertEquals("Remaining dirty bits not Mvi|Mvit|Frustum, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW|PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW | PMVMatrix.DIRTY_FRUSTUM, pmv.getDirtyBits()); + Assert.assertEquals("Request bits Mvi|Mvit|Frustum not set, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW | PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW | PMVMatrix.DIRTY_FRUSTUM, pmv.getRequestMask()); + MiscUtils.assertFloatBufferEquals("P not identity, "+pmv.toString(), ident, p, epsilon); + MiscUtils.assertFloatBufferEquals("Mv not identity, "+pmv.toString(), ident, mv, epsilon); + MiscUtils.assertFloatBufferNotEqual("Mvi already identity w/o update, "+pmv.toString(), ident, mvi, epsilon); + MiscUtils.assertFloatBufferNotEqual("Mvit already identity w/o update, "+pmv.toString(), ident, mvit, epsilon); + MiscUtils.assertFloatBufferEquals("Mvi not translated123, "+pmv.toString()+pmv.toString(), translated123I, mvi, epsilon); + MiscUtils.assertFloatBufferEquals("Mvit not translated123, "+pmv.toString()+pmv.toString(), translated123IT, mvit, epsilon); + Assert.assertNotNull("Frustum is null"+pmv.toString(), frustum); // FIXME: Test Frustum value! + + b = pmv.update(); // will clean dirty bits, since request has been made -> true + Assert.assertEquals("Update has not been perfomed, but requested", true, b); + Assert.assertTrue("Dirty bits not clean, "+pmv.toString(), 0 == pmv.getDirtyBits()); + Assert.assertEquals("Request bits Mvi|Mvit|Frustum not set, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW | PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW | PMVMatrix.DIRTY_FRUSTUM, pmv.getRequestMask()); + MiscUtils.assertFloatBufferEquals("Mvi not identity after update, "+pmv.toString(), ident, mvi, epsilon); + MiscUtils.assertFloatBufferEquals("Mvit not identity after update, "+pmv.toString(), ident, mvit, epsilon); + Assert.assertNotNull("Frustum is null"+pmv.toString(), frustum); // FIXME: Test Frustum value! + } + + /** + * Test using shader access workflow, i.e. 1) get-matrix references 2) operations + * <p> + * The Mvi, Mvit and Frustum dirty-bits and request-mask will be validated. + * </p> + */ + @SuppressWarnings("deprecation") + @Test + public void test02MviUpdateShaderAccess() { + final FloatBuffer p, mv, mvi, mvit; + Frustum frustum; + boolean b; + final PMVMatrix pmv = new PMVMatrix(true); + // System.err.println("P0: "+pmv.toString()); + + Assert.assertTrue("Dirty bits clean, "+pmv.toString(), 0 != pmv.getDirtyBits()); + Assert.assertEquals("Remaining dirty bits not Mvi|Mvit|Frustum, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW|PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW | PMVMatrix.DIRTY_FRUSTUM, pmv.getDirtyBits()); + Assert.assertEquals("Request bits not zero, "+pmv.toString(), 0, pmv.getRequestMask()); + + // + // Action #0 + // + final FloatBuffer ident; + { + pmv.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmv.glLoadIdentity(); + ident = pmv.glGetPMatrixf(); + + pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmv.glLoadIdentity(); + } + // System.err.println("P0: "+pmv.toString()); + Assert.assertTrue("Modified bits zero", 0 != pmv.getModifiedBits(true)); // clear & test + Assert.assertTrue("Dirty bits clean, "+pmv.toString(), 0 != pmv.getDirtyBits()); + Assert.assertEquals("Remaining dirty bits not Mvi|Mvit|Frustum, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW|PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW | PMVMatrix.DIRTY_FRUSTUM, pmv.getDirtyBits()); + Assert.assertEquals("Request bits not zero, "+pmv.toString(), 0, pmv.getRequestMask()); + // System.err.println("P1: "+pmv.toString()); + + // + // Get + // + p = pmv.glGetPMatrixf(); + MiscUtils.assertFloatBufferEquals("P not identity, "+pmv.toString(), ident, p, epsilon); + mv = pmv.glGetMvMatrixf(); + MiscUtils.assertFloatBufferEquals("Mv not identity, "+pmv.toString(), ident, mv, epsilon); + Assert.assertTrue("Dirty bits clean, "+pmv.toString(), 0 != pmv.getDirtyBits()); + Assert.assertEquals("Request bits not zero, "+pmv.toString(), 0, pmv.getRequestMask()); + + mvi = pmv.glGetMviMatrixf(); + MiscUtils.assertFloatBufferEquals("Mvi not identity, "+pmv.toString(), ident, mvi, epsilon); + Assert.assertEquals("Remaining dirty bits not Mvit|Frustum, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW | PMVMatrix.DIRTY_FRUSTUM, pmv.getDirtyBits()); + Assert.assertEquals("Request bit Mvi not set, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW, pmv.getRequestMask()); + + mvit = pmv.glGetMvitMatrixf(); + MiscUtils.assertFloatBufferEquals("Mvi not identity, "+pmv.toString(), ident, mvit, epsilon); + Assert.assertEquals("Remaining dirty bits not Frustum, "+pmv.toString(), PMVMatrix.DIRTY_FRUSTUM, pmv.getDirtyBits()); + Assert.assertEquals("Request bits Mvi and Mvit not set, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW | PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW, pmv.getRequestMask()); + + frustum = pmv.glGetFrustum(); + Assert.assertNotNull("Frustum is null"+pmv.toString(), frustum); // FIXME: Test Frustum value! + Assert.assertTrue("Dirty bits not clean, "+pmv.toString(), 0 == pmv.getDirtyBits()); + Assert.assertEquals("Request bits Mvi|Mvit|Frustum not set, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW | PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW | PMVMatrix.DIRTY_FRUSTUM, pmv.getRequestMask()); + + // + // Action #1 + // + pmv.glTranslatef(1f, 2f, 3f); // all dirty ! + Assert.assertTrue("Modified bits zero", 0 != pmv.getModifiedBits(true)); // clear & test + Assert.assertTrue("Dirty bits clean, "+pmv.toString(), 0 != pmv.getDirtyBits()); + Assert.assertEquals("Remaining dirty bits not Mvi|Mvit|Frustum, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW|PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW | PMVMatrix.DIRTY_FRUSTUM, pmv.getDirtyBits()); + MiscUtils.assertFloatBufferEquals("P not identity, "+pmv.toString()+pmv.toString(), ident, p, epsilon); + MiscUtils.assertFloatBufferEquals("Mv not translated123, "+pmv.toString()+pmv.toString(), translated123C, mv, epsilon); + MiscUtils.assertFloatBufferNotEqual("Mvi already translated123 w/o update, "+pmv.toString()+pmv.toString(), translated123I, mvi, epsilon); + MiscUtils.assertFloatBufferNotEqual("Mvit already translated123 w/o update, "+pmv.toString()+pmv.toString(), translated123IT, mvit, epsilon); + MiscUtils.assertFloatBufferEquals("Mvi not identity, "+pmv.toString()+pmv.toString(), ident, mvi, epsilon); + MiscUtils.assertFloatBufferEquals("Mvit not identity, "+pmv.toString()+pmv.toString(), ident, mvit, epsilon); + Assert.assertNotNull("Frustum is null"+pmv.toString(), frustum); // FIXME: Test Frustum value! + + b = pmv.update(); // will clean dirty bits, since all requests has been made -> true + Assert.assertEquals("Update has not been perfomed, but requested", true, b); + Assert.assertTrue("Dirty bits not clean, "+pmv.toString(), 0 == pmv.getDirtyBits()); + Assert.assertEquals("Request bits Mvi|Mvit|Frustum not set, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW | PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW | PMVMatrix.DIRTY_FRUSTUM, pmv.getRequestMask()); + MiscUtils.assertFloatBufferEquals("Mvi not translated123, "+pmv.toString()+pmv.toString(), translated123I, mvi, epsilon); + MiscUtils.assertFloatBufferEquals("Mvit not translated123, "+pmv.toString()+pmv.toString(), translated123IT, mvit, epsilon); + // System.err.println("P2: "+pmv.toString()); + } + + @SuppressWarnings("unused") + @Test + public void test03MvTranslate() { + final FloatBuffer pmvMv, pmvMvi, pmvMvit; + { + final PMVMatrix pmv = new PMVMatrix(true); + pmv.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmv.glLoadIdentity(); + pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmv.glLoadIdentity(); + pmv.glTranslatef(5f, 6f, 7f); + + pmvMv = pmv.glGetMvMatrixf(); + pmvMvi = pmv.glGetMviMatrixf(); + pmvMvit = pmv.glGetMvitMatrixf(); + } + + final FloatBuffer glMv = FloatBuffer.allocate(16); + { + GL2ES1 gl = dc.glc.getGL().getGL2ES1(); + gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + gl.glLoadIdentity(); + gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + gl.glLoadIdentity(); + gl.glTranslatef(5f, 6f, 7f); + + gl.glGetFloatv(GLMatrixFunc.GL_MODELVIEW_MATRIX, glMv); + } + // System.err.println(PMVMatrix.matrixToString(null, "%10.5f", glMv, pmvMv).toString()); + + MiscUtils.assertFloatBufferEquals("Arrays not equal, expected"+Platform.NEWLINE+PMVMatrix.matrixToString(null, "%10.5f", glMv).toString()+ + ", actual"+Platform.NEWLINE+PMVMatrix.matrixToString(null, "%10.5f", pmvMv).toString(), + glMv, pmvMv, epsilon); + + // System.err.println("pmvMvi: "+Platform.NEWLINE+PMVMatrix.matrixToString(null, "%10.5f", pmvMvi)); + // System.err.println("pmvMvit: "+Platform.NEWLINE+PMVMatrix.matrixToString(null, "%10.5f", pmvMvit)); + } + + @SuppressWarnings("unused") + @Test + public void test04MvTranslateRotate() { + final FloatBuffer pmvMv, pmvMvi, pmvMvit; + { + final PMVMatrix pmv = new PMVMatrix(true); + pmv.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmv.glLoadIdentity(); + pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmv.glLoadIdentity(); + pmv.glTranslatef(5f, 6f, 7f); + pmv.glRotatef(90f, 1f, 0f, 0f); + + pmvMv = pmv.glGetMvMatrixf(); + pmvMvi = pmv.glGetMviMatrixf(); + pmvMvit = pmv.glGetMvitMatrixf(); + } + + final FloatBuffer glMv = FloatBuffer.allocate(16); + { + GL2ES1 gl = dc.glc.getGL().getGL2ES1(); + gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + gl.glLoadIdentity(); + gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + gl.glLoadIdentity(); + gl.glTranslatef(5f, 6f, 7f); + gl.glRotatef(90f, 1f, 0f, 0f); + + gl.glGetFloatv(GLMatrixFunc.GL_MODELVIEW_MATRIX, glMv); + } + // System.err.println(PMVMatrix.matrixToString(null, "%10.5f", glMv, pmvMv).toString()); + + MiscUtils.assertFloatBufferEquals("Arrays not equal, expected"+Platform.NEWLINE+PMVMatrix.matrixToString(null, "%10.5f", glMv).toString()+ + ", actual"+Platform.NEWLINE+PMVMatrix.matrixToString(null, "%10.5f", pmvMv).toString(), + glMv, pmvMv, epsilon); + + // System.err.println("pmvMvi: "+Platform.NEWLINE+PMVMatrix.matrixToString(null, "%10.5f", pmvMvi)); + // System.err.println("pmvMvit: "+Platform.NEWLINE+PMVMatrix.matrixToString(null, "%10.5f", pmvMvit)); + } + + static DrawableContext dc; + + @BeforeClass + public static void setup() throws Throwable { + try { + dc = createOffscreenDrawableAndCurrentFFPContext(); + } catch (Throwable t) { + setTestSupported(false); + throw t; + } + } + + @AfterClass + public static void cleanup() { + destroyDrawableContext(dc); + } + + static class DrawableContext { + DrawableContext(GLDrawable d, GLContext glc) { + this.d = d; + this.glc = glc; + } + GLDrawable d; + GLContext glc; + } + + private static DrawableContext createOffscreenDrawableAndCurrentFFPContext() throws Throwable { + GLProfile glp = GLProfile.getMaxFixedFunc(true); + GLCapabilities glCaps = new GLCapabilities(glp); + glCaps.setOnscreen(false); + glCaps.setPBuffer(true); + GLDrawableFactory factory = GLDrawableFactory.getFactory(glp); + GLDrawable d = factory.createOffscreenDrawable(null, glCaps, null, 64, 64); + d.setRealized(true); + GLContext glc = null; + try { + glc = d.createContext(null); + Assert.assertTrue("Context could not be made current", GLContext.CONTEXT_NOT_CURRENT < glc.makeCurrent()); + return new DrawableContext(d, glc); + } catch (Throwable t) { + if(null != glc) { + glc.destroy(); + } + d.setRealized(false); + throw t; + } + } + + private static void destroyDrawableContext(DrawableContext dc) { + if(null != dc.glc) { + dc.glc.destroy(); + dc.glc = null; + } + if(null != dc.d) { + dc.d.setRealized(false); + dc.d = null; + } + } + + public static void main(String args[]) { + org.junit.runner.JUnitCore.main(TestPMVMatrix01NEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/math/TestPMVMatrix02NOUI.java b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestPMVMatrix02NOUI.java new file mode 100644 index 000000000..2c3a6f36a --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestPMVMatrix02NOUI.java @@ -0,0 +1,112 @@ +/**
+ * Copyright 2012 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.jogl.math;
+
+import org.junit.Before;
+import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters;
+
+import com.jogamp.opengl.util.PMVMatrix;
+
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+import java.nio.FloatBuffer;
+
+import static org.junit.Assert.assertArrayEquals;
+
+/**
+ * @author Thomas De Bodt
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestPMVMatrix02NOUI {
+
+ private PMVMatrix fMat;
+
+ @Before
+ public void setUp() throws Exception {
+ fMat = new PMVMatrix();
+ }
+
+ @Test
+ public void testLookAtNegZIsNoOp() throws Exception {
+ fMat.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ // Look towards -z
+ fMat.gluLookAt(
+ 0, 0, 0,
+ 0, 0, -1,
+ 0, 1, 0
+ );
+ FloatBuffer mvMatrix = fMat.glGetMvMatrixf();
+ float[] mvMatrixArr = new float[16];
+ mvMatrix.asReadOnlyBuffer().get(mvMatrixArr);
+ assertArrayEquals(
+ /**
+ * The 3 rows of the matrix (= the 3 columns of the array/buffer) should be: side, up, -forward.
+ */
+ new float[] {
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1
+ },
+ mvMatrixArr,
+ 1e-6f
+ );
+ }
+ @Test
+ public void testLookAtPosY() throws Exception {
+ fMat.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ // Look towards +y
+ fMat.gluLookAt(
+ 0, 0, 0,
+ 0, 1, 0,
+ 0, 0, 1
+ );
+ FloatBuffer mvMatrix = fMat.glGetMvMatrixf();
+ float[] mvMatrixArr = new float[16];
+ mvMatrix.asReadOnlyBuffer().get(mvMatrixArr);
+ assertArrayEquals(
+ /**
+ * The 3 rows of the matrix (= the 3 columns of the array/buffer) should be: side, up, -forward.
+ */
+ new float[] {
+ 1, 0, 0, 0,
+ 0, 0, -1, 0,
+ 0, 1, 0, 0,
+ 0, 0, 0, 1
+ },
+ mvMatrixArr,
+ 1e-6f
+ );
+ }
+
+ public static void main(String args[]) {
+ org.junit.runner.JUnitCore.main(TestPMVMatrix02NOUI.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/math/TestPMVMatrix03NOUI.java b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestPMVMatrix03NOUI.java new file mode 100644 index 000000000..df149169a --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestPMVMatrix03NOUI.java @@ -0,0 +1,128 @@ +package com.jogamp.opengl.test.junit.jogl.math; + +import java.util.Arrays; + +import jogamp.opengl.ProjectFloat; + +import com.jogamp.opengl.math.FloatUtil; +import com.jogamp.opengl.util.PMVMatrix; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestPMVMatrix03NOUI { + + static final float epsilon = 0.00001f; + + // Simple 10 x 10 view port + static final int[] viewport = new int[] { 0,0,10,10}; + + @Test + public void test01() { + float[] winA00 = new float[4]; + float[] winA01 = new float[4]; + float[] winA10 = new float[4]; + float[] winA11 = new float[4]; + PMVMatrix m = new PMVMatrix(); + + m.gluProject(1f, 0f, 0f, viewport, 0, winA00, 0); + System.out.println("A.0.0 - Project 1,0 -->" + Arrays.toString(winA00)); + + m.gluProject(0f, 0f, 0f, viewport, 0, winA01, 0); + System.out.println("A.0.1 - Project 0,0 -->" + Arrays.toString(winA01)); + + m.glMatrixMode(PMVMatrix.GL_PROJECTION); + m.glOrthof(0, 10, 0, 10, 1, -1); + System.out.println("MATRIX - Ortho 0,0,10,10 - Locate the origin in the bottom left and scale"); + System.out.println(m); + float[] projMatrixA = new float[16]; + float[] modelMatrixA = new float[16]; + m.glGetFloatv(PMVMatrix.GL_PROJECTION, projMatrixA, 0); + m.glGetFloatv(PMVMatrix.GL_MODELVIEW, modelMatrixA, 0); + + m.gluProject(1f, 0f, 0f, viewport, 0, winA10, 0); + System.out.println("A.1.0 - Project 1,0 -->" +Arrays.toString(winA10)); + + m.gluProject(0f, 0f, 0f, viewport, 0, winA11, 0); + System.out.println("A.1.1 - Project 0,0 -->" +Arrays.toString(winA11)); + + + //////////////////// + ///////////////////// + + float[] winB00 = new float[4]; + float[] winB01 = new float[4]; + float[] winB10 = new float[4]; + float[] winB11 = new float[4]; + float[] projMatrixB = new float[16]; + float[] modelMatrixB = new float[16]; + FloatUtil.makeIdentityf(projMatrixB, 0); + FloatUtil.makeIdentityf(modelMatrixB, 0); + final ProjectFloat projectFloat = new ProjectFloat(true); + + projectFloat.gluProject(1f, 0f, 0f, modelMatrixB, 0, projMatrixB, 0, viewport, 0, winB00, 0); + System.out.println("B.0.0 - Project 1,0 -->" +Arrays.toString(winB00)); + + projectFloat.gluProject(0f, 0f, 0f, modelMatrixB, 0, projMatrixB, 0, viewport, 0, winB01, 0); + System.out.println("B.0.1 - Project 0,0 -->" +Arrays.toString(winB01)); + + glOrthof(projMatrixB, 0, 10, 0, 10, 1, -1); + System.out.println("FloatUtil - Ortho 0,0,10,10 - Locate the origin in the bottom left and scale"); + System.out.println("Projection"); + System.err.println(FloatUtil.matrixToString(null, null, "%10.5f", projMatrixB, 0, 4, 4, false /* rowMajorOrder */)); + System.out.println("Modelview"); + System.err.println(FloatUtil.matrixToString(null, null, "%10.5f", modelMatrixB, 0, 4, 4, false /* rowMajorOrder */)); + + projectFloat.gluProject(1f, 0f, 0f, modelMatrixB, 0, projMatrixB, 0, viewport, 0, winB10, 0); + System.out.println("B.1.0 - Project 1,0 -->" +Arrays.toString(winB10)); + + projectFloat.gluProject(0f, 0f, 0f, modelMatrixB, 0, projMatrixB, 0, viewport, 0, winB11, 0); + System.out.println("B.1.1 - Project 0,0 -->" +Arrays.toString(winB11)); + + Assert.assertArrayEquals("A/B 0.0 Project 1,0 failure", winB00, winA00, epsilon); + Assert.assertArrayEquals("A/B 0.1 Project 0,0 failure", winB01, winA01, epsilon); + Assert.assertArrayEquals("A/B 1.0 Project 1,0 failure", winB10, winA10, epsilon); + Assert.assertArrayEquals("A/B 1.1 Project 0,0 failure", winB11, winA11, epsilon); + + Assert.assertEquals("A 0.0 Project 1,0 failure X", 10.0, winA00[0], epsilon); + Assert.assertEquals("A 0.0 Project 1,0 failure Y", 5.0, winA00[1], epsilon); + Assert.assertEquals("A.0.1 Project 0,0 failure X", 5.0, winA01[0], epsilon); + Assert.assertEquals("A.0.1 Project 0,0 failure Y", 5.0, winA01[1], epsilon); + Assert.assertEquals("A 1.0 Project 1,0 failure X", 1.0, winA10[0], epsilon); + Assert.assertEquals("A 1.0 Project 1,0 failure Y", 0.0, winA10[1], epsilon); + Assert.assertEquals("A.1.1 Project 0,0 failure X", 0.0, winA11[0], epsilon); + Assert.assertEquals("A.1.1 Project 0,0 failure Y", 0.0, winA11[1], epsilon); + } + + public final void glOrthof(final float[] m, final float left, final float right, final float bottom, final float top, final float zNear, final float zFar) { + // Ortho matrix: + // 2/dx 0 0 tx + // 0 2/dy 0 ty + // 0 0 2/dz tz + // 0 0 0 1 + final float dx=right-left; + final float dy=top-bottom; + final float dz=zFar-zNear; + final float tx=-1.0f*(right+left)/dx; + final float ty=-1.0f*(top+bottom)/dy; + final float tz=-1.0f*(zFar+zNear)/dz; + + float[] matrixOrtho = new float[16]; + FloatUtil.makeIdentityf(matrixOrtho, 0); + matrixOrtho[0+4*0] = 2.0f/dx; + matrixOrtho[1+4*1] = 2.0f/dy; + matrixOrtho[2+4*2] = -2.0f/dz; + matrixOrtho[0+4*3] = tx; + matrixOrtho[1+4*3] = ty; + matrixOrtho[2+4*3] = tz; + + FloatUtil.multMatrixf(m, 0, matrixOrtho, 0); + } + + public static void main(String args[]) { + org.junit.runner.JUnitCore.main(TestPMVMatrix03NOUI.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/newt/TestSwingAWTRobotUsageBeforeJOGLInitBug411.java b/src/test/com/jogamp/opengl/test/junit/jogl/newt/TestSwingAWTRobotUsageBeforeJOGLInitBug411.java index b165a9693..2f5fb2606 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/newt/TestSwingAWTRobotUsageBeforeJOGLInitBug411.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/newt/TestSwingAWTRobotUsageBeforeJOGLInitBug411.java @@ -33,6 +33,8 @@ import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.util.*; import java.lang.reflect.InvocationTargetException; + +import javax.media.nativewindow.NativeWindowFactory; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLProfile; import javax.media.opengl.GLCapabilities; @@ -66,7 +68,10 @@ import org.junit.Assert; import org.junit.BeforeClass; import org.junit.AfterClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestSwingAWTRobotUsageBeforeJOGLInitBug411 extends UITestCase { static long durationPerTest = 150; // ms static Robot robot; @@ -140,24 +145,33 @@ public class TestSwingAWTRobotUsageBeforeJOGLInitBug411 extends UITestCase { } }); frame.setContentPane(panel); - frame.setSize(512, 512); - frame.setLocation(0, 0); - frame.pack(); // AWT/Swing: From here on (post setVisible(true) // you need to use AWT/Swing's invokeAndWait() javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame.setSize(512, 512); + frame.setLocation(0, 0); + frame.pack(); frame.setVisible(true); colorPanel.setBackground(Color.white); colorPanel.repaint(); }}); - + robot = new Robot(); robot.setAutoWaitForIdle(true); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); + // NativeWindow/JOGL is not initialized yet .. + for (int wait=0; wait<AWTRobotUtil.POLL_DIVIDER && !frame.isVisible(); wait++) { + Thread.sleep(AWTRobotUtil.TIME_SLICE); + } + Assert.assertEquals(true, frame.isVisible()); + + System.err.println("TestSwingAWTRobotUsageBeforeJOGLInitBug411.setup(): Before NativeWindow init"); + + NativeWindowFactory.initSingleton(); + AWTRobotUtil.clearAWTFocus(robot); AWTRobotUtil.toFrontAndRequestFocus(robot, frame); AWTRobotUtil.requestFocus(robot, button); @@ -199,6 +213,8 @@ public class TestSwingAWTRobotUsageBeforeJOGLInitBug411 extends UITestCase { AWTRobotUtil.toFrontAndRequestFocus(robot, frame); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(drawable, true)); + drawable.addGLEventListener(new GearsES2()); for(int i=0; i<100; i++) { @@ -251,6 +267,8 @@ public class TestSwingAWTRobotUsageBeforeJOGLInitBug411 extends UITestCase { GLWindow win0 = GLWindow.create(caps); win0.setSize(100,100); win0.setVisible(true); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(win0, true)); + Screen screen = win0.getScreen(); win0.setPosition(screen.getWidth()-150, 0); win0.addGLEventListener(new GearsES2()); @@ -263,6 +281,7 @@ public class TestSwingAWTRobotUsageBeforeJOGLInitBug411 extends UITestCase { runTestGL(newtCanvasAWT, win1); win0.destroy(); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(win0, false)); Assert.assertEquals(false, win0.isNativeValid()); Assert.assertEquals(true, anim.isAnimating()); // due to newtCanvasAWT/win1 @@ -302,8 +321,7 @@ public class TestSwingAWTRobotUsageBeforeJOGLInitBug411 extends UITestCase { GLCanvas glCanvas = new GLCanvas(caps); anim.add(glCanvas); runTestGL(glCanvas, glCanvas); - - Assert.assertEquals(true, anim.isAnimating()); + anim.remove(glCanvas); Assert.assertEquals(false, anim.isAnimating()); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/ReadBufferBase.java b/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/ReadBufferBase.java index e3ca25ae6..f8e064a4e 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/ReadBufferBase.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/ReadBufferBase.java @@ -70,7 +70,7 @@ public class ReadBufferBase implements GLEventListener { _gl.getContext().setGLReadDrawable(externalRead); if(_gl.isGL2GL3()) { - _gl.getGL2GL3().glReadBuffer(GL2GL3.GL_FRONT); + _gl.getGL2GL3().glReadBuffer(GL.GL_FRONT); } System.out.println("---------------------------"); System.out.println(_gl.getContext()); @@ -85,9 +85,7 @@ public class ReadBufferBase implements GLEventListener { } public void display(GLAutoDrawable drawable) { - GL gl = drawable.getGL(); - - readBufferUtil.readPixels(gl, drawable, false); + readBufferUtil.readPixels(drawable.getGL(), false); } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/Surface2File.java b/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/Surface2File.java index d1297e034..974e32289 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/Surface2File.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/Surface2File.java @@ -34,14 +34,24 @@ import com.jogamp.opengl.util.GLReadBufferUtil; import java.io.File; import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; import javax.media.nativewindow.*; public class Surface2File implements SurfaceUpdatedListener { - GLReadBufferUtil readBufferUtil = new GLReadBufferUtil(false, false); + final String filename; + final boolean alpha; + final GLReadBufferUtil readBufferUtil; int shotNum = 0; + public Surface2File(String filename, boolean alpha) { + this.filename = filename; + this.alpha = alpha; + this.readBufferUtil = new GLReadBufferUtil(alpha, false); + } + public void dispose(GL gl) { readBufferUtil.dispose(gl); } @@ -54,10 +64,10 @@ public class Surface2File implements SurfaceUpdatedListener { GL gl = ctx.getGL(); // FIXME glFinish() is an expensive paranoia sync, should not be necessary due to spec gl.glFinish(); - if(readBufferUtil.readPixels(gl, drawable, false)) { + if(readBufferUtil.readPixels(gl, false)) { gl.glFinish(); try { - surface2File("shot"); + surface2File(); } catch (IOException ex) { throw new RuntimeException("can not write survace to file", ex); } @@ -66,14 +76,17 @@ public class Surface2File implements SurfaceUpdatedListener { } } - public void surface2File(String basename) throws IOException { + public void surface2File() throws IOException { if (!readBufferUtil.isValid()) { return; } - - File file = File.createTempFile(basename + shotNum + "-", ".tga"); + final StringWriter sw = new StringWriter(); + { + final String pfmt = alpha ? "rgba" : "rgb_" ; + new PrintWriter(sw).printf("%s-I_%s-%04d.png", filename, pfmt, shotNum); + } + File file = new File(sw.toString()); readBufferUtil.write(file); - System.err.println("Wrote: " + file.getAbsolutePath() + ", ..."); shotNum++; } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/TestOffscreen01GLPBufferNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/TestOffscreen01GLPBufferNEWT.java index 3f1fd144f..3f0dae6b0 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/TestOffscreen01GLPBufferNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/TestOffscreen01GLPBufferNEWT.java @@ -32,22 +32,22 @@ import com.jogamp.newt.Display; import com.jogamp.newt.NewtFactory; import com.jogamp.newt.Screen; import com.jogamp.newt.Window; -import com.jogamp.newt.event.MouseListener; -import com.jogamp.newt.event.WindowListener; import com.jogamp.newt.opengl.GLWindow; import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import javax.media.opengl.*; -import javax.media.nativewindow.*; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; import java.io.IOException; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestOffscreen01GLPBufferNEWT extends UITestCase { static GLProfile glpDefault; static GLDrawableFactory glDrawableFactory; @@ -59,7 +59,7 @@ public class TestOffscreen01GLPBufferNEWT extends UITestCase { glpDefault = GLProfile.getDefault(); Assert.assertNotNull(glpDefault); glDrawableFactory = GLDrawableFactory.getFactory(glpDefault); - System.out.println("INFO: PBuffer supported: "+ glDrawableFactory.canCreateGLPbuffer(null)); + System.out.println("INFO: PBuffer supported: "+ glDrawableFactory.canCreateGLPbuffer(null, glpDefault)); width = 640; height = 480; } @@ -72,6 +72,7 @@ public class TestOffscreen01GLPBufferNEWT extends UITestCase { public void init() { capsDefault = new GLCapabilities(glpDefault); Assert.assertNotNull(capsDefault); + capsDefault.setAlphaBits(1); // req. alpha channel } private void do01OffscreenWindowPBuffer(GLCapabilities caps) { @@ -110,7 +111,7 @@ public class TestOffscreen01GLPBufferNEWT extends UITestCase { @Test public void test01aOffscreenWindowPBuffer() { - if(!glDrawableFactory.canCreateGLPbuffer(null)) { + if(!glDrawableFactory.canCreateGLPbuffer(null, capsDefault.getGLProfile())) { System.out.println("WARNING: PBuffer not supported on this platform - cannot test"); return; } @@ -120,7 +121,7 @@ public class TestOffscreen01GLPBufferNEWT extends UITestCase { @Test public void test01bOffscreenWindowPBufferStencil() { - if(!glDrawableFactory.canCreateGLPbuffer(null)) { + if(!glDrawableFactory.canCreateGLPbuffer(null, capsDefault.getGLProfile())) { System.out.println("WARNING: PBuffer not supported on this platform - cannot test"); return; } @@ -131,7 +132,7 @@ public class TestOffscreen01GLPBufferNEWT extends UITestCase { @Test public void test01cOffscreenWindowPBufferStencilAlpha() { - if(!glDrawableFactory.canCreateGLPbuffer(null)) { + if(!glDrawableFactory.canCreateGLPbuffer(null, capsDefault.getGLProfile())) { System.out.println("WARNING: PBuffer not supported on this platform - cannot test"); return; } @@ -143,7 +144,7 @@ public class TestOffscreen01GLPBufferNEWT extends UITestCase { @Test public void test01cOffscreenWindowPBuffer555() { - if(!glDrawableFactory.canCreateGLPbuffer(null)) { + if(!glDrawableFactory.canCreateGLPbuffer(null, capsDefault.getGLProfile())) { System.out.println("WARNING: PBuffer not supported on this platform - cannot test"); return; } @@ -156,7 +157,7 @@ public class TestOffscreen01GLPBufferNEWT extends UITestCase { @Test public void test02Offscreen3Windows1DisplayPBuffer() { - if(!glDrawableFactory.canCreateGLPbuffer(null)) { + if(!glDrawableFactory.canCreateGLPbuffer(null, capsDefault.getGLProfile())) { System.out.println("WARNING: PBuffer not supported on this platform - cannot test"); return; } @@ -209,7 +210,7 @@ public class TestOffscreen01GLPBufferNEWT extends UITestCase { @Test public void test03Offscreen3Windows3DisplaysPBuffer() { - if(!glDrawableFactory.canCreateGLPbuffer(null)) { + if(!glDrawableFactory.canCreateGLPbuffer(null, capsDefault.getGLProfile())) { System.out.println("WARNING: PBuffer not supported on this platform - cannot test"); return; } @@ -262,7 +263,7 @@ public class TestOffscreen01GLPBufferNEWT extends UITestCase { @Test public void test04OffscreenSnapshotWithDemoPBuffer() { - if(!glDrawableFactory.canCreateGLPbuffer(null)) { + if(!glDrawableFactory.canCreateGLPbuffer(null, capsDefault.getGLProfile())) { System.out.println("WARNING: PBuffer not supported on this platform - cannot test"); return; } @@ -280,14 +281,8 @@ public class TestOffscreen01GLPBufferNEWT extends UITestCase { Assert.assertNotNull(glWindow); glWindow.setVisible(true); - WindowListener wl=null; - MouseListener ml=null; - SurfaceUpdatedListener ul=null; - - GLEventListener demo = new RedSquareES2(); - Assert.assertNotNull(demo); - - WindowUtilNEWT.run(glWindow, demo, null, wl, ml, ul, 2, true /*snapshot*/, false /*debug*/); + WindowUtilNEWT.run(getSimpleTestName("."), glWindow, new RedSquareES2(), null, null, null, null, + 2 /* frames */, true /*snapshot*/, false /*debug*/); if(null!=glWindow) { glWindow.destroy(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/TestOffscreen02BitmapNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/TestOffscreen02BitmapNEWT.java index 7898ddad9..72cb7a512 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/TestOffscreen02BitmapNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/TestOffscreen02BitmapNEWT.java @@ -33,14 +33,13 @@ import com.jogamp.newt.Display; import com.jogamp.newt.NewtFactory; import com.jogamp.newt.Screen; import com.jogamp.newt.Window; -import com.jogamp.newt.event.MouseListener; -import com.jogamp.newt.event.WindowListener; import com.jogamp.newt.opengl.GLWindow; import org.junit.Assert; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import javax.media.opengl.*; -import javax.media.nativewindow.*; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.jogl.demos.es1.RedSquareES1; @@ -50,6 +49,7 @@ import java.io.IOException; * Using ES1 GL demo, since pixmap might not be hw accelerated, * hence it is possible to not have GLSL. */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestOffscreen02BitmapNEWT extends UITestCase { static final int width = 640, height = 480; @@ -119,14 +119,8 @@ public class TestOffscreen02BitmapNEWT extends UITestCase { Assert.assertNotNull(glWindow); glWindow.setVisible(true); - WindowListener wl=null; - MouseListener ml=null; - SurfaceUpdatedListener ul=null; - - GLEventListener demo = new RedSquareES1(); - Assert.assertNotNull(demo); - - WindowUtilNEWT.run(glWindow, demo, null, wl, ml, ul, 2, true /*snapshot*/, false /*debug*/); + WindowUtilNEWT.run(getSimpleTestName("."), glWindow, new RedSquareES1(), null, null, null, null, + 2 /* frames */, true /*snapshot*/, false /*debug*/); if(null!=glWindow) { glWindow.destroy(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/WindowUtilNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/WindowUtilNEWT.java index 1d1ee1e0c..efca752a1 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/WindowUtilNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/offscreen/WindowUtilNEWT.java @@ -60,8 +60,8 @@ public class WindowUtilNEWT { } } - public static void run(GLWindow windowOffScreen, GLEventListener demo, - GLWindow windowOnScreen, WindowListener wl, MouseListener ml, + public static void run(String testName, GLWindow windowOffScreen, GLEventListener demo, + GLWindow windowOnScreenBlit, WindowListener wl, MouseListener ml, SurfaceUpdatedListener ul, int frames, boolean snapshot, boolean debug) { Assert.assertNotNull(windowOffScreen); Assert.assertNotNull(demo); @@ -69,35 +69,34 @@ public class WindowUtilNEWT { setDemoFields(demo, windowOffScreen, windowOffScreen, debug); windowOffScreen.addGLEventListener(demo); - if ( null != windowOnScreen ) { + if ( null != windowOnScreenBlit ) { if(null!=wl) { - windowOnScreen.addWindowListener(wl); + windowOnScreenBlit.addWindowListener(wl); } if(null!=ml) { - windowOnScreen.addMouseListener(ml); + windowOnScreenBlit.addMouseListener(ml); } - windowOnScreen.setVisible(true); + windowOnScreenBlit.setVisible(true); } GLDrawable readDrawable = windowOffScreen.getContext().getGLDrawable() ; - - if ( null == windowOnScreen ) { - if(snapshot) { - Surface2File s2f = new Surface2File(); - windowOffScreen.addSurfaceUpdatedListener(s2f); - } - } else { + if ( null != windowOnScreenBlit ) { ReadBuffer2Screen readDemo = new ReadBuffer2Screen( readDrawable ) ; - windowOnScreen.addGLEventListener(readDemo); + windowOnScreenBlit.addGLEventListener(readDemo); + } + if(snapshot) { + final boolean alpha = windowOffScreen.getChosenGLCapabilities().getAlphaBits()>0; + Surface2File s2f = new Surface2File(testName, alpha); + windowOffScreen.addSurfaceUpdatedListener(s2f); } if(null!=ul) { windowOffScreen.addSurfaceUpdatedListener(ul); } if(debug) { - System.err.println("+++++++++++++++++++++++++++"); + System.err.println("+++++++++++++++++++++++++++ "+testName); System.err.println(windowOffScreen); - System.err.println("+++++++++++++++++++++++++++"); + System.err.println("+++++++++++++++++++++++++++ "+testName); } while ( windowOffScreen.getTotalFPSFrames() < frames) { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/perf/TestPerf001GLJPanelInit01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/perf/TestPerf001GLJPanelInit01AWT.java new file mode 100644 index 000000000..0ca84e4c3 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/perf/TestPerf001GLJPanelInit01AWT.java @@ -0,0 +1,258 @@ +/** + * Copyright 2013 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.jogl.perf; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLAnimatorControl; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; +import javax.media.opengl.awt.GLJPanel; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +import org.junit.Assume; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import com.jogamp.common.os.Platform; +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.util.Animator; + +/** + * Multiple GLJPanels in a JFrame's Grid + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestPerf001GLJPanelInit01AWT extends UITestCase { + final long INIT_TIMEOUT = 10L*1000L; // 10s + + @BeforeClass + public static void initClass() { + GLProfile.initSingleton(); + } + + public void test(final GLCapabilitiesImmutable caps, final boolean useGears, final int width, final int height, final int rows, + final int columns, final boolean useGLJPanel, final boolean useAnim) { + final GLAnimatorControl animator = useAnim ? new Animator() : null; + + final JFrame frame; + final JPanel panel; + + panel = new JPanel(); + frame = new JFrame("DemoGLJPanelGridAWT"); + + panel.setLayout(new GridLayout(rows, columns)); + // panel.setBounds(0, 0, width, height); + final int panelCount = rows*columns; + final Dimension eSize = new Dimension(width/columns, height/rows); + final long[] t = new long[10]; + if( wait ) { + UITestCase.waitForKey("Pre-Init"); + } + System.err.println("INIT START"); + initCount = 0; + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + t[0] = Platform.currentTimeMillis(); + for(int i=0; i<panelCount; i++) { + final GLAutoDrawable glad = useGLJPanel ? createGLJPanel(caps, useGears, animator, eSize) : createGLCanvas(caps, useGears, animator, eSize); + glad.addGLEventListener(new GLEventListener() { + @Override + public void init(GLAutoDrawable drawable) { + initCount++; + } + @Override + public void dispose(GLAutoDrawable drawable) {} + @Override + public void display(GLAutoDrawable drawable) {} + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {} + }); + panel.add((Component)glad); + } + t[1] = Platform.currentTimeMillis(); + frame.getContentPane().add(panel); + + // frame.validate(); + frame.pack(); + frame.setVisible(true); + t[2] = Platform.currentTimeMillis(); + } } ); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + final long t0 = System.currentTimeMillis(); + long t1 = t0; + while( panelCount > initCount && INIT_TIMEOUT > t1 - t0 ) { + try { + Thread.sleep(100); + System.err.println("Sleep initialized: "+initCount+"/"+panelCount); + } catch (InterruptedException e1) { + e1.printStackTrace(); + } + t1 = System.currentTimeMillis(); + } + t[3] = Platform.currentTimeMillis(); + final double panelCountF = initCount; + System.err.printf("P: %d %s:%n\tctor\t%6d/t %6.2f/1%n\tvisible\t%6d/t %6.2f/1%n\tsum-i\t%6d/t %6.2f/1%n", + initCount, + useGLJPanel?"GLJPanel":"GLCanvas", + t[1]-t[0], (t[1]-t[0])/panelCountF, + t[3]-t[1], (t[3]-t[1])/panelCountF, + t[3]-t[0], (t[3]-t[0])/panelCountF); + System.err.println("INIT END: "+initCount+"/"+panelCount); + if( wait ) { + UITestCase.waitForKey("Post-Init"); + } + try { + Thread.sleep(duration); + } catch (InterruptedException e1) { + e1.printStackTrace(); + } + t[4] = Platform.currentTimeMillis(); + try { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.dispose(); + } } ); + } catch (Exception e1) { + e1.printStackTrace(); + } + final long ti_net = (t[4]-t[0])-duration; + System.err.printf("T: duration %d %d%n\ttotal-d\t%6d/t %6.2f/1%n\ttotal-i\t%6d/t %6.2f/1%n", + duration, t[4]-t[3], + t[4]-t[0], (t[4]-t[0])/panelCountF, + ti_net, ti_net/panelCountF); + System.err.println("Total: "+(t[4]-t[0])); + } + + private GLAutoDrawable createGLCanvas(GLCapabilitiesImmutable caps, boolean useGears, GLAnimatorControl anim, Dimension size) { + GLCanvas canvas = new GLCanvas(caps); + canvas.setSize(size); + canvas.setPreferredSize(size); + if( useGears ) { + canvas.addGLEventListener(new GearsES2()); + } + if( null != anim ) { + anim.add(canvas); + } + return canvas; + } + private GLAutoDrawable createGLJPanel(GLCapabilitiesImmutable caps, boolean useGears, GLAnimatorControl anim, Dimension size) { + GLJPanel canvas = new GLJPanel(caps); + canvas.setSize(size); + canvas.setPreferredSize(size); + if( useGears ) { + canvas.addGLEventListener(new GearsES2()); + } + if( null != anim ) { + anim.add(canvas); + } + return canvas; + } + + @Test + public void test01NopGLJPanelDef() throws InterruptedException, InvocationTargetException { + test(new GLCapabilities(null), false /*useGears*/, width, height, rows, cols, true /* useGLJPanel */, false /*useAnim*/); + } + + @Test + public void test02NopGLJPanelBitmap() throws InterruptedException, InvocationTargetException { + GLCapabilities caps = new GLCapabilities(null); + caps.setBitmap(true); + test(caps, false /*useGears*/, width, height, rows, cols, true /* useGLJPanel */, false /*useAnim*/); + } + + @Test + public void test11NopGLCanvasDef() throws InterruptedException, InvocationTargetException { + test(new GLCapabilities(null), false /*useGears*/, width, height, rows, cols, false /* useGLJPanel */, false /*useAnim*/); + } + + static long duration = 0; // ms + static boolean wait = false; + static int width = 800, height = 600, rows = 5, cols = 5; + + volatile int initCount = 0; + + public static void main(String[] args) { + boolean useGLJPanel = true, useGears = false, manual=false; + boolean waitMain = false; + + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-width")) { + width = MiscUtils.atoi(args[++i], width); + } else if(args[i].equals("-height")) { + height = MiscUtils.atoi(args[++i], height); + } else if(args[i].equals("-rows")) { + rows = MiscUtils.atoi(args[++i], rows); + } else if(args[i].equals("-cols")) { + cols = MiscUtils.atoi(args[++i], cols); + } else if(args[i].equals("-glcanvas")) { + useGLJPanel = false; + } else if(args[i].equals("-gears")) { + useGears = true; + } else if(args[i].equals("-wait")) { + wait = true; + manual = true; + } else if(args[i].equals("-waitMain")) { + waitMain = true; + manual = true; + } else if(args[i].equals("-manual")) { + manual = true; + } + } + if( waitMain ) { + UITestCase.waitForKey("Main-Start"); + } + if( manual ) { + GLProfile.initSingleton(); + TestPerf001GLJPanelInit01AWT demo = new TestPerf001GLJPanelInit01AWT(); + demo.test(null, useGears, width, height, rows, cols, useGLJPanel, false /*useAnim*/); + } else { + org.junit.runner.JUnitCore.main(TestPerf001GLJPanelInit01AWT.class.getName()); + } + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/perf/TestPerf001GLJPanelInit02AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/perf/TestPerf001GLJPanelInit02AWT.java new file mode 100644 index 000000000..2b1dc411f --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/perf/TestPerf001GLJPanelInit02AWT.java @@ -0,0 +1,446 @@ +/** + * Copyright 2013 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.jogl.perf; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLAnimatorControl; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; +import javax.media.opengl.awt.GLJPanel; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTextArea; +import javax.swing.SwingUtilities; + +import org.junit.Assume; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import com.jogamp.common.os.Platform; +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.util.Animator; + +/** + * Multiple GLJPanels in a JFrame + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestPerf001GLJPanelInit02AWT extends UITestCase { + final long INIT_TIMEOUT = 10L*1000L; // 10s + + @BeforeClass + public static void initClass() { + GLProfile.initSingleton(); + } + + public void test(final GLCapabilitiesImmutable caps, final boolean useGears, final boolean skipGLOrientationVerticalFlip, final int width, + final int height, final int frameCount, final boolean initMT, final boolean useGLJPanel, + final boolean useSwingDoubleBuffer, final boolean useGLCanvas, final boolean useAnim, final boolean overlap) { + final GLAnimatorControl animator; + if( useAnim ) { + animator = new Animator(); + animator.start(); + } else { + animator = null; + } + final int eWidth, eHeight; + { + final int cols = (int)Math.round(Math.sqrt(frameCount)); + final int rows = frameCount / cols; + eWidth = width/cols-32; + eHeight = height/rows-32; + } + System.err.println("Frame size: "+width+"x"+height+" -> "+frameCount+" x "+eWidth+"x"+eHeight+", overlap "+overlap); + System.err.println("SkipGLOrientationVerticalFlip "+skipGLOrientationVerticalFlip+", useGears "+useGears+", initMT "+initMT+", useAnim "+useAnim); + final JFrame[] frame = new JFrame[frameCount]; + final long[] t = new long[10]; + if( wait ) { + UITestCase.waitForKey("Pre-Init"); + } + System.err.println("INIT START"); + initCount = 0; + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + t[0] = Platform.currentTimeMillis(); + int x = 32, y = 32; + for(int i=0; i<frameCount; i++) { + frame[i] = new JFrame("frame_"+i+"/"+frameCount); + frame[i].setLocation(x, y); + if(!overlap) { + x+=eWidth+32; + if(x>=width) { + x=32; + y+=eHeight+32; + } + } + final JPanel panel = new JPanel(); + panel.setLayout(new BorderLayout()); + panel.setDoubleBuffered(useSwingDoubleBuffer); + // panel.setBounds(0, 0, width, height); + final Dimension eSize = new Dimension(eWidth, eHeight); + final GLAutoDrawable glad = useGLJPanel ? createGLJPanel(initMT, useSwingDoubleBuffer, caps, useGears, skipGLOrientationVerticalFlip, animator, eSize) : ( useGLCanvas ? createGLCanvas(caps, useGears, animator, eSize) : null ); + if( null != glad ) { + glad.addGLEventListener(new GLEventListener() { + @Override + public void init(GLAutoDrawable drawable) { + initCount++; + } + @Override + public void dispose(GLAutoDrawable drawable) {} + @Override + public void display(GLAutoDrawable drawable) {} + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {} + }); + panel.add((Component)glad); + } else { + @SuppressWarnings("serial") + final JTextArea c = new JTextArea("area "+i) { + boolean initialized = false, added = false; + int reshapeWidth=0, reshapeHeight=0; + @Override + public void addNotify() { + added = true; + super.addNotify(); + } + @SuppressWarnings("deprecation") + @Override + public void reshape(int x, int y, int width, int height) { + super.reshape(x, y, width, height); + reshapeWidth = width; reshapeHeight = height; + } + @Override + protected void paintComponent(final Graphics g) { + super.paintComponent(g); + if( !initialized && added && reshapeWidth > 0 && reshapeHeight > 0 && isDisplayable() ) { + initialized = true; + initCount++; + } + } + }; + c.setEditable(false); + c.setSize(eSize); + c.setPreferredSize(eSize); + panel.add(c); + } + frame[i].getContentPane().add(panel); + + // frame.validate(); + frame[i].pack(); + } + t[1] = Platform.currentTimeMillis(); + for(int i=0; i<frameCount; i++) { + frame[i].setVisible(true); + } + t[2] = Platform.currentTimeMillis(); + } } ); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + final long t0 = System.currentTimeMillis(); + long t1 = t0; + while( frameCount > initCount && INIT_TIMEOUT > t1 - t0 ) { + try { + Thread.sleep(100); + System.err.println("Sleep initialized: "+initCount+"/"+frameCount); + } catch (InterruptedException e1) { + e1.printStackTrace(); + } + t1 = System.currentTimeMillis(); + } + t[3] = Platform.currentTimeMillis(); + final double panelCountF = initCount; + System.err.printf("P: %d %s%s:%n\tctor\t%6d/t %6.2f/1%n\tvisible\t%6d/t %6.2f/1%n\tsum-i\t%6d/t %6.2f/1%n", + initCount, + useGLJPanel?"GLJPanel":(useGLCanvas?"GLCanvas":"No_GL"), initMT?" (mt)":" (01)", + t[1]-t[0], (t[1]-t[0])/panelCountF, + t[3]-t[1], (t[3]-t[1])/panelCountF, + t[3]-t[0], (t[3]-t[0])/panelCountF); + + System.err.println("INIT END: "+initCount+"/"+frameCount); + if( wait ) { + UITestCase.waitForKey("Post-Init"); + } + try { + Thread.sleep(duration); + } catch (InterruptedException e1) { + e1.printStackTrace(); + } + t[4] = Platform.currentTimeMillis(); + try { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + for(int i=0; i<frameCount; i++) { + frame[i].dispose(); + } + } } ); + } catch (Exception e1) { + e1.printStackTrace(); + } + + final long ti_net = (t[4]-t[0])-duration; + System.err.printf("T: duration %d %d%n\ttotal-d\t%6d/t %6.2f/1%n\ttotal-i\t%6d/t %6.2f/1%n", + duration, t[4]-t[3], + t[4]-t[0], (t[4]-t[0])/panelCountF, + ti_net, ti_net/panelCountF); + System.err.println("Total: "+(t[4]-t[0])); + } + + private GLAutoDrawable createGLCanvas(GLCapabilitiesImmutable caps, boolean useGears, GLAnimatorControl anim, Dimension size) { + GLCanvas canvas = new GLCanvas(caps); + canvas.setSize(size); + canvas.setPreferredSize(size); + if( useGears ) { + final GearsES2 g = new GearsES2(0); + g.setVerbose(false); + canvas.addGLEventListener(g); + } + if( null != anim ) { + anim.add(canvas); + } + return canvas; + } + private GLAutoDrawable createGLJPanel(boolean initMT, boolean useSwingDoubleBuffer, GLCapabilitiesImmutable caps, boolean useGears, boolean skipGLOrientationVerticalFlip, GLAnimatorControl anim, Dimension size) { + GLJPanel canvas = new GLJPanel(caps); + canvas.setSize(size); + canvas.setPreferredSize(size); + canvas.setDoubleBuffered(useSwingDoubleBuffer); + if( skipGLOrientationVerticalFlip ) { // don't fiddle w/ default .. + canvas.setSkipGLOrientationVerticalFlip(skipGLOrientationVerticalFlip); + } + if( useGears ) { + final GearsES2 g = new GearsES2(0); + g.setVerbose(false); + g.setFlipVerticalInGLOrientation(skipGLOrientationVerticalFlip); + canvas.addGLEventListener(g); + } + if( null != anim ) { + anim.add(canvas); + } + if( initMT ) { + canvas.initializeBackend(true /* offthread */); + } + return canvas; + } + + static GLCapabilitiesImmutable caps = null; + + // + // NOP + // + + @Test + public void test00NopNoGLDefGrid() throws InterruptedException, InvocationTargetException { + test(new GLCapabilities(null), false /*useGears*/, false /*skipGLOrientationVerticalFlip*/, width , height, frameCount, false /* initMT */, + false /* useGLJPanel */, false /*useSwingDoubleBuffer*/, false /* useGLCanvas */, false /*useAnim*/, false /* overlap */); + } + + @Test + public void test01NopGLCanvasDefGrid() throws InterruptedException, InvocationTargetException { + test(new GLCapabilities(null), false /*useGears*/, false /*skipGLOrientationVerticalFlip*/, width , height, frameCount, false /* initMT */, + false /* useGLJPanel */, false /*useSwingDoubleBuffer*/, true /* useGLCanvas */, false /*useAnim*/, false /* overlap */); + } + + @Test + public void test02NopGLJPanelDefGridSingleAutoFlip() throws InterruptedException, InvocationTargetException { + test(new GLCapabilities(null), false /*useGears*/, false /*skipGLOrientationVerticalFlip*/, width , height, frameCount, false /* initMT */, + true /* useGLJPanel */, false /*useSwingDoubleBuffer*/, false /* useGLCanvas */, false /*useAnim*/, false /* overlap */); + } + + @Test + public void test03NopGLJPanelDefGridSingleManualFlip() throws InterruptedException, InvocationTargetException { + test(new GLCapabilities(null), false /*useGears*/, true /*skipGLOrientationVerticalFlip*/, width , height, frameCount, false /* initMT */, + true /* useGLJPanel */, false /*useSwingDoubleBuffer*/, false /* useGLCanvas */, false /*useAnim*/, false /* overlap */); + } + + @Test + public void test04NopGLJPanelDefGridMTManualFlip() throws InterruptedException, InvocationTargetException { + test(new GLCapabilities(null), false /*useGears*/, true /*skipGLOrientationVerticalFlip*/, width , height, frameCount, true /* initMT */, + true /* useGLJPanel */, false /*useSwingDoubleBuffer*/, false /* useGLCanvas */, false /*useAnim*/, false /* overlap */); + } + + // + // Gears + // + + @Test + public void test10GearsNoGLDefGrid() throws InterruptedException, InvocationTargetException { + test(new GLCapabilities(null), true /*useGears*/, false /*skipGLOrientationVerticalFlip*/, width , height, frameCount, false /* initMT */, + false /* useGLJPanel */, false /*useSwingDoubleBuffer*/, false /* useGLCanvas */, false /*useAnim*/, false /* overlap */); + } + + @Test + public void test11GearsGLCanvasDefGrid() throws InterruptedException, InvocationTargetException { + test(new GLCapabilities(null), true /*useGears*/, false /*skipGLOrientationVerticalFlip*/, width , height, frameCount, false /* initMT */, + false /* useGLJPanel */, false /*useSwingDoubleBuffer*/, true /* useGLCanvas */, false /*useAnim*/, false /* overlap */); + } + + @Test + public void test12GearsGLJPanelDefGridSingleAutoFlip() throws InterruptedException, InvocationTargetException { + test(new GLCapabilities(null), true /*useGears*/, false /*skipGLOrientationVerticalFlip*/, width , height, frameCount, false /* initMT */, + true /* useGLJPanel */, false /*useSwingDoubleBuffer*/, false /* useGLCanvas */, false /*useAnim*/, false /* overlap */); + } + + @Test + public void test13GearsGLJPanelDefGridSingleManualFlip() throws InterruptedException, InvocationTargetException { + test(new GLCapabilities(null), true /*useGears*/, true /*skipGLOrientationVerticalFlip*/, width , height, frameCount, false /* initMT */, + true /* useGLJPanel */, false /*useSwingDoubleBuffer*/, false /* useGLCanvas */, false /*useAnim*/, false /* overlap */); + } + + @Test + public void test14GearsGLJPanelDefGridMTManualFlip() throws InterruptedException, InvocationTargetException { + test(new GLCapabilities(null), true /*useGears*/, true /*skipGLOrientationVerticalFlip*/, width , height, frameCount, true /* initMT */, + true /* useGLJPanel */, false /*useSwingDoubleBuffer*/, false /* useGLCanvas */, false /*useAnim*/, false /* overlap */); + } + + + // + // Overlap + NOP + // + + + @Test + public void test20NopNoGLDefOverlap() throws InterruptedException, InvocationTargetException { + test(null, false /*useGears*/, false /*skipGLOrientationVerticalFlip*/, width , height, frameCount, false /* initMT */, + false /* useGLJPanel */, false /*useSwingDoubleBuffer*/, false /* useGLCanvas */, false /*useAnim*/, true /* overlap */); + } + + @Test + public void test21NopGLCanvasDefOverlap() throws InterruptedException, InvocationTargetException { + test(new GLCapabilities(null), false /*useGears*/, false /*skipGLOrientationVerticalFlip*/, width , height, frameCount, false /* initMT */, + false /* useGLJPanel */, false /*useSwingDoubleBuffer*/, true /* useGLCanvas */, false /*useAnim*/, true /* overlap */); + } + + @Test + public void test22NopGLJPanelDefOverlapSingle() throws InterruptedException, InvocationTargetException { + test(new GLCapabilities(null), false /*useGears*/, false /*skipGLOrientationVerticalFlip*/, width , height, frameCount, false /* initMT */, + true /* useGLJPanel */, false /*useSwingDoubleBuffer*/, false /* useGLCanvas */, false /*useAnim*/, true /* overlap */); + } + + @Test + public void test23NopGLJPanelDefOverlapMT() throws InterruptedException, InvocationTargetException { + test(new GLCapabilities(null), false /*useGears*/, false /*skipGLOrientationVerticalFlip*/, width , height, frameCount, true /* initMT */, + true /* useGLJPanel */, false /*useSwingDoubleBuffer*/, false /* useGLCanvas */, false /*useAnim*/, true /* overlap */); + } + + // @Test + public void testXXNopGLJPanelDefOverlapSingle() throws InterruptedException, InvocationTargetException { + test(new GLCapabilities(null), false /*useGears*/, false /*skipGLOrientationVerticalFlip*/, width , height, frameCount, false /* initMT */, + true /* useGLJPanel */, false /*useSwingDoubleBuffer*/, false /* useGLCanvas */, false /*useAnim*/, true /* overlap */); + } + + // @Test + public void testXXNopGLJPanelBitmapGridSingle() throws InterruptedException, InvocationTargetException { + GLCapabilities caps = new GLCapabilities(null); + caps.setBitmap(true); + test(caps, false /*useGears*/, false /*skipGLOrientationVerticalFlip*/, width , height, frameCount, false /* initMT */, + true /* useGLJPanel */, false /*useSwingDoubleBuffer*/, false /* useGLCanvas */, false /*useAnim*/, false); + } + + static long duration = 0; // ms + static boolean wait = false; + static int width = 800, height = 600, frameCount = 25; + + volatile int initCount = 0; + + public static void main(String[] args) { + boolean manual=false; + boolean waitMain = false; + boolean useGLJPanel = true, initMT = false, useGLCanvas = false, useSwingDoubleBuffer=false; + boolean useGears = false, skipGLOrientationVerticalFlip=false, useAnim = false; + boolean overlap = false; + + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-width")) { + width = MiscUtils.atoi(args[++i], width); + } else if(args[i].equals("-height")) { + height = MiscUtils.atoi(args[++i], height); + } else if(args[i].equals("-count")) { + frameCount = MiscUtils.atoi(args[++i], frameCount); + } else if(args[i].equals("-initMT")) { + initMT = true; + manual = true; + } else if(args[i].equals("-glcanvas")) { + useGLJPanel = false; + useGLCanvas = true; + manual = true; + } else if(args[i].equals("-swingDoubleBuffer")) { + useSwingDoubleBuffer = true; + } else if(args[i].equals("-glnone")) { + useGLJPanel = false; + useGLCanvas = false; + manual = true; + } else if(args[i].equals("-gears")) { + useGears = true; + } else if(args[i].equals("-anim")) { + useAnim = true; + } else if(args[i].equals("-userVertFlip")) { + skipGLOrientationVerticalFlip = true; + } else if(args[i].equals("-overlap")) { + overlap = true; + } else if(args[i].equals("-wait")) { + wait = true; + manual = true; + } else if(args[i].equals("-waitMain")) { + waitMain = true; + manual = true; + } else if(args[i].equals("-manual")) { + manual = true; + } + } + if( waitMain ) { + UITestCase.waitForKey("Main-Start"); + } + if( manual ) { + GLProfile.initSingleton(); + TestPerf001GLJPanelInit02AWT demo = new TestPerf001GLJPanelInit02AWT(); + demo.test(null, useGears, skipGLOrientationVerticalFlip, width, height, frameCount, + initMT, useGLJPanel, useSwingDoubleBuffer, useGLCanvas, useAnim, overlap); + } else { + org.junit.runner.JUnitCore.main(TestPerf001GLJPanelInit02AWT.class.getName()); + } + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/perf/TestPerf001GLWindowInit03NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/perf/TestPerf001GLWindowInit03NEWT.java new file mode 100644 index 000000000..18b3d5454 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/perf/TestPerf001GLWindowInit03NEWT.java @@ -0,0 +1,213 @@ +/** + * Copyright 2013 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.jogl.perf; + +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import com.jogamp.common.os.Platform; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Screen; +import com.jogamp.newt.opengl.GLWindow; +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; + +/** + * Multiple GLJPanels in a JFrame + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestPerf001GLWindowInit03NEWT extends UITestCase { + final long INIT_TIMEOUT = 10L*1000L; // 10s + + @BeforeClass + public static void initClass() { + GLProfile.initSingleton(); + } + + public void test(final GLCapabilitiesImmutable caps, final boolean useGears, final int width, final int height, final int frameCount, boolean reuseDevice) { + final int cols = (int)Math.round(Math.sqrt(frameCount)); + final int rows = frameCount / cols; + final int eWidth = width/cols; + final int eHeight = height/rows; + + final GLWindow[] frame = new GLWindow[frameCount]; + final long[] t = new long[10]; + if( wait ) { + UITestCase.waitForKey("Pre-Init"); + } + System.err.println("INIT START"); + initCount = 0; + + t[0] = Platform.currentTimeMillis(); + int x = 32, y = 32; + for(int i=0; i<frameCount; i++) { + final Screen screen = NewtFactory.createScreen(NewtFactory.createDisplay(null, reuseDevice), 0); + frame[i] = GLWindow.create(screen, caps); + frame[i].setTitle("frame_"+i+"/"+frameCount); + frame[i].setPosition(x, y); + x+=eWidth+32; + if(x>=width) { + x=32; + y+=eHeight+32; + } + frame[i].setSize(eWidth, eHeight); + if( useGears ) { + frame[i].addGLEventListener(new GearsES2()); + } + frame[i].addGLEventListener(new GLEventListener() { + @Override + public void init(GLAutoDrawable drawable) { + initCount++; + } + @Override + public void dispose(GLAutoDrawable drawable) {} + @Override + public void display(GLAutoDrawable drawable) {} + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {} + }); + } + t[1] = Platform.currentTimeMillis(); + for(int i=0; i<frameCount; i++) { + frame[i].setVisible(false /*wait*/, true /*visible*/); + } + t[2] = Platform.currentTimeMillis(); + + final long t0 = System.currentTimeMillis(); + long t1 = t0; + while( frameCount > initCount && INIT_TIMEOUT > t1 - t0 ) { + try { + Thread.sleep(100); + System.err.println("Sleep initialized: "+initCount+"/"+frameCount); + } catch (InterruptedException e1) { + e1.printStackTrace(); + } + t1 = System.currentTimeMillis(); + } + t[3] = Platform.currentTimeMillis(); + final double panelCountF = initCount; + System.err.printf("P: %d GLWindow:%n\tctor\t%6d/t %6.2f/1%n\tvisible\t%6d/t %6.2f/1%n\tsum-i\t%6d/t %6.2f/1%n", + initCount, + t[1]-t[0], (t[1]-t[0])/panelCountF, + t[3]-t[1], (t[3]-t[1])/panelCountF, + t[3]-t[0], (t[3]-t[0])/panelCountF); + + System.err.println("INIT END: "+initCount+"/"+frameCount); + if( wait ) { + UITestCase.waitForKey("Post-Init"); + } + try { + Thread.sleep(duration); + } catch (InterruptedException e1) { + e1.printStackTrace(); + } + t[4] = Platform.currentTimeMillis(); + for(int i=0; i<frameCount; i++) { + frame[i].destroy(); + } + + final long ti_net = (t[4]-t[0])-duration; + System.err.printf("T: duration %d %d%n\ttotal-d\t%6d/t %6.2f/1%n\ttotal-i\t%6d/t %6.2f/1%n", + duration, t[4]-t[3], + t[4]-t[0], (t[4]-t[0])/panelCountF, + ti_net, ti_net/panelCountF); + System.err.println("Total: "+(t[4]-t[0])); + } + + static GLCapabilitiesImmutable caps = null; + + @Test + public void test01NopGLWindowNoReuse() throws InterruptedException, InvocationTargetException { + if(!mainRun) { + System.err.println("Disabled for auto unit test until further analysis - Windows/ATI driver crash"); + return; + } + test(new GLCapabilities(null), false /*useGears*/, width, height , frameCount, false /* reuseDevice */); + } + @Test + public void test02NopGLWindowReuse() throws InterruptedException, InvocationTargetException { + test(new GLCapabilities(null), false /*useGears*/, width, height , frameCount, true /* reuseDevice */); + } + + static long duration = 0; // ms + static boolean wait = false, mainRun = false; + static int width = 800, height = 600, frameCount = 25; + + volatile int initCount = 0; + + public static void main(String[] args) { + mainRun = true; + boolean useGears = false, manual=false; + boolean waitMain = false; + + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-width")) { + width = MiscUtils.atoi(args[++i], width); + } else if(args[i].equals("-height")) { + height = MiscUtils.atoi(args[++i], height); + } else if(args[i].equals("-count")) { + frameCount = MiscUtils.atoi(args[++i], frameCount); + } else if(args[i].equals("-gears")) { + useGears = true; + } else if(args[i].equals("-wait")) { + wait = true; + manual = true; + } else if(args[i].equals("-waitMain")) { + waitMain = true; + manual = true; + } else if(args[i].equals("-manual")) { + manual = true; + } + } + if( waitMain ) { + UITestCase.waitForKey("Main-Start"); + } + if( manual ) { + GLProfile.initSingleton(); + TestPerf001GLWindowInit03NEWT demo = new TestPerf001GLWindowInit03NEWT(); + demo.test(null, useGears, width, height, frameCount, false /* reuseDevice */); + } else { + org.junit.runner.JUnitCore.main(TestPerf001GLWindowInit03NEWT.class.getName()); + } + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/perf/TestPerf001RawInit00NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/perf/TestPerf001RawInit00NEWT.java new file mode 100644 index 000000000..6f7d9329b --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/perf/TestPerf001RawInit00NEWT.java @@ -0,0 +1,234 @@ +/** + * Copyright 2013 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.jogl.perf; + +import java.lang.reflect.InvocationTargetException; + +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.GraphicsConfigurationFactory; +import javax.media.nativewindow.VisualIDHolder; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLProfile; + +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import com.jogamp.common.os.Platform; +import com.jogamp.newt.Display; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Screen; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Raw initialization of multiple offscreen GLAutoDrawables + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestPerf001RawInit00NEWT extends UITestCase { + + @BeforeClass + public static void initClass() { + GLProfile.initSingleton(); + } + + public void testChooseOnly(final int runNum, final Screen screen, final int count) throws InterruptedException { + final long[] t = new long[10]; + final GLProfile glp = GLProfile.getGL2ES2(); + final int[] chosenCfgs = { 0 }; + + final GLCapabilitiesImmutable caps = new GLCapabilities(glp); + final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(screen.getDisplay().getGraphicsDevice(), caps); + + if( wait && 0 == runNum ) { + UITestCase.waitForKey("Pre-Init"); + } + System.err.println("INIT START #"+runNum); + screen.getDisplay().getEDTUtil().invoke(true, new Runnable() { + public void run() { + t[0] = Platform.currentTimeMillis(); + for(int i=0; i<count; i++) { + final AbstractGraphicsConfiguration cfg = factory.chooseGraphicsConfiguration(caps, caps, null, screen.getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED); + if( null != cfg ) { + chosenCfgs[0]++; + } + } + t[1] = Platform.currentTimeMillis(); + } } ); + + final double countF = count; + System.err.printf("Run: %d, count %d/%d raw:%n\tchoose\t%6d/t %6.2f/1%n", + runNum, chosenCfgs[0], count, t[1]-t[0], (t[1]-t[0])/countF); + System.err.println("INIT END #"+runNum); + if( wait && 2 == runNum ) { + UITestCase.waitForKey("Post-Init"); + } + } + + public void testFull(final int runNum, final int width, final int height, final int count) { + // panel.setBounds(0, 0, width, height); + final long[] t = new long[10]; + final GLDrawable[] glDrawables = new GLDrawable[count]; + final GLContext[] glConti = new GLContext[count]; + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilitiesImmutable caps = new GLCapabilities(glp); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(glp); + if( wait && 0 == runNum ) { + UITestCase.waitForKey("Pre-Init"); + } + System.err.println("INIT START #"+runNum); + t[0] = Platform.currentTimeMillis(); + for(int i=0; i<count; i++) { + glDrawables[i] = factory.createOffscreenDrawable(null, caps, null, width, height); + } + t[1] = Platform.currentTimeMillis(); + for(int i=0; i<count; i++) { + glDrawables[i].setRealized(true); + } + t[2] = Platform.currentTimeMillis(); + // 1st makeCurrent - context creation incl. release + for(int i=0; i<count; i++) { + final GLContext context = glDrawables[i].createContext(null); + if( GLContext.CONTEXT_NOT_CURRENT >= context.makeCurrent() ) { + // oops + glDrawables[i].setRealized(false); + glDrawables[i] = null; + glConti[i] = null; + continue; + } + glConti[i] = context; + context.release(); + } + t[3] = Platform.currentTimeMillis(); + // 2nd makeCurrent and release + for(int i=0; i<count; i++) { + final GLContext context = glConti[i]; + if( GLContext.CONTEXT_NOT_CURRENT >= context.makeCurrent() ) { + // oops + glDrawables[i].setRealized(false); + glDrawables[i] = null; + glConti[i] = null; + continue; + } + context.release(); + } + t[4] = Platform.currentTimeMillis(); + + final double countF = count; + System.err.printf("Run: %d, count %d raw:%n\tglad-create\t%6d/t %6.2f/1%n"+ + "\tglad-realize\t%6d/t %6.2f/1%n"+ + "\tctx-create1\t%6d/t %6.2f/1%n"+ + "\tctx-curren2\t%6d/t %6.2f/1%n"+ + "\tglad-ctx-init\t%6d/t %6.2f/1%n", + runNum, count, + t[1]-t[0], (t[1]-t[0])/countF, // create + t[2]-t[1], (t[2]-t[1])/countF, // realize + t[3]-t[2], (t[3]-t[2])/countF, // context-create1 + t[4]-t[3], (t[4]-t[3])/countF, // context-curren2 + t[3]-t[0], (t[3]-t[0])/countF);// init total + System.err.println("INIT END #"+runNum); + if( wait && 2 == runNum ) { + UITestCase.waitForKey("Post-Init"); + } + + // destroy + for(int i=0; i<count; i++) { + final GLContext context = glConti[i]; + if( null != context ) { + context.destroy(); + } + final GLDrawable glDrawable = glDrawables[i]; + if( null != glDrawable ) { + glDrawable.setRealized(false); + } + glConti[i] = null; + glDrawables[i] = null; + } + } + + @Test + public void test01ChooseOnly() throws InterruptedException, InvocationTargetException { + if( 0 != manualTest && 1 != manualTest ) { + return; + } + final Display display = NewtFactory.createDisplay(null, false); + final Screen screen = NewtFactory.createScreen(display, 0); + screen.addReference(); + try { + testChooseOnly(0, screen, count); // warm-up + testChooseOnly(1, screen, count); + testChooseOnly(2, screen, count); + } finally { + screen.removeReference(); + } + } + + @Test + public void test02Full() throws InterruptedException, InvocationTargetException { + if( 0 != manualTest && 2 != manualTest ) { + return; + } + testFull(0, width, height, count); // warm-up + testFull(1, width, height, count); + testFull(2, width, height, count); + } + + static boolean wait = false; + static int manualTest = 0; + static int width = 800, height = 600, count = 50; + + public static void main(String[] args) { + boolean waitMain = false; + + for(int i=0; i<args.length; i++) { + if(args[i].equals("-width")) { + width = MiscUtils.atoi(args[++i], width); + } else if(args[i].equals("-height")) { + height = MiscUtils.atoi(args[++i], height); + } else if(args[i].equals("-count")) { + count = MiscUtils.atoi(args[++i], count); + } else if(args[i].equals("-wait")) { + wait = true; + } else if(args[i].equals("-waitMain")) { + waitMain = true; + } else if(args[i].equals("-test")) { + manualTest = MiscUtils.atoi(args[++i], manualTest); + } + } + if( waitMain ) { + UITestCase.waitForKey("Main-Start"); + } + org.junit.runner.JUnitCore.main(TestPerf001RawInit00NEWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestBug672NewtCanvasSWTSashForm.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestBug672NewtCanvasSWTSashForm.java new file mode 100644 index 000000000..4b7537655 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestBug672NewtCanvasSWTSashForm.java @@ -0,0 +1,332 @@ +/** + * Copyright 2011 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.jogl.swt; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +import com.jogamp.nativewindow.swt.SWTAccessor; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.event.KeyAdapter; +import com.jogamp.newt.event.KeyEvent; +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.newt.swt.NewtCanvasSWT; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +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 com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; + +import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.Point; +import javax.media.nativewindow.util.PointImmutable; +import javax.media.nativewindow.util.DimensionImmutable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLProfile; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.SashForm; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.junit.After; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.AfterClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestBug672NewtCanvasSWTSashForm extends UITestCase { + static int screenIdx = 0; + static PointImmutable wpos; + static DimensionImmutable wsize, rwsize = null; + + static long duration = 500; // ms + + @BeforeClass + public static void initClass() { + if(null == wsize) { + wsize = new Dimension(640, 480); + } + } + + @AfterClass + public static void releaseClass() { + } + + Display display = null; + Shell shell = null; + Composite composite = null; + SashForm sash = null; + com.jogamp.newt.Display swtNewtDisplay = null; + + @Before + public void init() { + SWTAccessor.invoke(true, new Runnable() { + public void run() { + display = new Display(); + Assert.assertNotNull( display ); + }}); + display.syncExec(new Runnable() { + public void run() { + shell = new Shell( display ); + Assert.assertNotNull( shell ); + shell.setLayout( new FillLayout() ); + composite = new Composite( shell, SWT.NONE ); + composite.setLayout( new FillLayout() ); + Assert.assertNotNull( composite ); + sash = new SashForm(composite, SWT.NONE); + Assert.assertNotNull( sash ); + final org.eclipse.swt.widgets.Label c = new org.eclipse.swt.widgets.Label(sash, SWT.NONE); + c.setText("Left cell"); + }}); + swtNewtDisplay = NewtFactory.createDisplay(null, false); // no-reuse + } + + @After + public void release() { + Assert.assertNotNull( display ); + Assert.assertNotNull( shell ); + Assert.assertNotNull( composite ); + Assert.assertNotNull( sash ); + try { + display.syncExec(new Runnable() { + public void run() { + sash.dispose(); + composite.dispose(); + shell.dispose(); + }}); + SWTAccessor.invoke(true, new Runnable() { + public void run() { + display.dispose(); + }}); + } + catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + swtNewtDisplay = null; + display = null; + shell = null; + composite = null; + sash = null; + } + + class WaitAction implements Runnable { + private final long sleepMS; + + WaitAction(long sleepMS) { + this.sleepMS = sleepMS; + } + public void run() { + if( !display.readAndDispatch() ) { + // blocks on linux .. display.sleep(); + try { + Thread.sleep(sleepMS); + } catch (InterruptedException e) { } + } + } + } + final WaitAction awtRobotWaitAction = new WaitAction(AWTRobotUtil.TIME_SLICE); + final WaitAction generalWaitAction = new WaitAction(10); + + protected void runTestGL(GLCapabilitiesImmutable caps) throws InterruptedException, InvocationTargetException { + com.jogamp.newt.Screen screen = NewtFactory.createScreen(swtNewtDisplay, screenIdx); + final GLWindow glWindow = GLWindow.create(screen, caps); + Assert.assertNotNull(glWindow); + + final GearsES2 demo = new GearsES2(1); + glWindow.addGLEventListener(demo); + + Animator animator = new Animator(); + animator.setModeBits(false, Animator.MODE_EXPECT_AWT_RENDERING_THREAD); + + QuitAdapter quitAdapter = new QuitAdapter(); + //glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter)); + //glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter)); + glWindow.addKeyListener(quitAdapter); + glWindow.addWindowListener(quitAdapter); + + glWindow.addWindowListener(new WindowAdapter() { + public void windowResized(WindowEvent e) { + System.err.println("window resized: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()); + } + public void windowMoved(WindowEvent e) { + System.err.println("window moved: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()); + } + }); + + glWindow.addKeyListener(new KeyAdapter() { + public void keyReleased(KeyEvent e) { + if( !e.isPrintableKey() || e.isAutoRepeat() ) { + return; + } + if(e.getKeyChar()=='f') { + new Thread() { + public void run() { + final Thread t = glWindow.setExclusiveContextThread(null); + System.err.println("[set fullscreen pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets()); + glWindow.setFullscreen(!glWindow.isFullscreen()); + System.err.println("[set fullscreen post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets()); + glWindow.setExclusiveContextThread(t); + } }.start(); + } + } + }); + + animator.add(glWindow); + animator.start(); + Assert.assertTrue(animator.isStarted()); + Assert.assertTrue(animator.isAnimating()); + animator.setUpdateFPSFrames(60, null); + final NewtCanvasSWT canvas1 = NewtCanvasSWT.create( sash, 0, glWindow ); + Assert.assertNotNull( canvas1 ); + + display.syncExec( new Runnable() { + public void run() { + shell.setText( getSimpleTestName(".") ); + shell.setSize( wsize.getWidth(), wsize.getHeight() ); + if( null != wpos ) { + shell.setLocation( wpos.getX(), wpos.getY() ); + } + shell.open(); + } + }); + Assert.assertTrue("GLWindow didn't become visible natively!", AWTRobotUtil.waitForRealized(glWindow, awtRobotWaitAction, true)); + Assert.assertNotNull( canvas1.getNativeWindow() ); + + System.err.println("NW chosen: "+glWindow.getDelegatedWindow().getChosenCapabilities()); + System.err.println("GL chosen: "+glWindow.getChosenCapabilities()); + System.err.println("window pos/siz.0: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", "+glWindow.getInsets()); + System.err.println("GLWindow LOS.0: "+glWindow.getLocationOnScreen(null)); + System.err.println("NewtCanvasSWT LOS.0: "+canvas1.getNativeWindow().getLocationOnScreen(null)); + + if( null != rwsize ) { + for(int i=0; i<50; i++) { // 500 ms dispatched delay + generalWaitAction.run(); + } + display.syncExec( new Runnable() { + public void run() { + shell.setSize( rwsize.getWidth(), rwsize.getHeight() ); + } + }); + System.err.println("window resize pos/siz.1: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", "+glWindow.getInsets()); + System.err.println("GLWindow LOS.1: "+glWindow.getLocationOnScreen(null)); + System.err.println("NewtCanvasSWT LOS.1: "+canvas1.getNativeWindow().getLocationOnScreen(null)); + } + + final PointImmutable pSashRightClient = new Point(wsize.getWidth(), 0); + final PointImmutable pNatWinLOS = canvas1.getNativeWindow().getLocationOnScreen(null); + final PointImmutable pGLWinLOS = glWindow.getLocationOnScreen(null); + + System.err.println("GLWindow LOS: "+pGLWinLOS); + System.err.println("NewtCanvasSWT LOS: "+pNatWinLOS); + + Assert.assertTrue( "NewtCanvasAWT LOS "+pNatWinLOS+" not >= sash-right "+pSashRightClient, pNatWinLOS.compareTo(pSashRightClient) >= 0 ); + Assert.assertTrue( "GLWindow LOS "+pGLWinLOS+" not >= sash-right "+pSashRightClient, pGLWinLOS.compareTo(pSashRightClient) >= 0 ); + + while( !quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration ) { + generalWaitAction.run(); + } + + animator.stop(); + Assert.assertFalse(animator.isAnimating()); + Assert.assertFalse(animator.isStarted()); + Assert.assertEquals(null, glWindow.getExclusiveContextThread()); + + canvas1.dispose(); + glWindow.destroy(); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false)); + } + + @Test + public void test01() throws InterruptedException, InvocationTargetException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities( glp ); + runTestGL(caps); + } + + public static void main(String args[]) throws IOException { + int x=0, y=0, w=640, h=480, rw=-1, rh=-1; + boolean usePos = false; + + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-width")) { + i++; + w = MiscUtils.atoi(args[i], w); + } else if(args[i].equals("-height")) { + i++; + h = MiscUtils.atoi(args[i], h); + } else if(args[i].equals("-x")) { + i++; + x = MiscUtils.atoi(args[i], x); + usePos = true; + } else if(args[i].equals("-y")) { + i++; + y = MiscUtils.atoi(args[i], y); + usePos = true; + } else if(args[i].equals("-rwidth")) { + i++; + rw = MiscUtils.atoi(args[i], rw); + } else if(args[i].equals("-rheight")) { + i++; + rh = MiscUtils.atoi(args[i], rh); + } else if(args[i].equals("-screen")) { + i++; + screenIdx = MiscUtils.atoi(args[i], 0); + } + } + wsize = new Dimension(w, h); + if( 0 < rw && 0 < rh ) { + rwsize = new Dimension(rw, rh); + } + + if(usePos) { + wpos = new Point(x, y); + } + System.err.println("position "+wpos); + System.err.println("size "+wsize); + System.err.println("resize "+rwsize); + System.err.println("screen "+screenIdx); + + org.junit.runner.JUnitCore.main(TestBug672NewtCanvasSWTSashForm.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestBug672NewtCanvasSWTSashFormComposite.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestBug672NewtCanvasSWTSashFormComposite.java new file mode 100644 index 000000000..876eafe86 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestBug672NewtCanvasSWTSashFormComposite.java @@ -0,0 +1,339 @@ +/** + * Copyright 2011 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.jogl.swt; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +import com.jogamp.nativewindow.swt.SWTAccessor; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.event.KeyAdapter; +import com.jogamp.newt.event.KeyEvent; +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.newt.swt.NewtCanvasSWT; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +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 com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; + +import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.Point; +import javax.media.nativewindow.util.PointImmutable; +import javax.media.nativewindow.util.DimensionImmutable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLProfile; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.SashForm; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.junit.After; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.AfterClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestBug672NewtCanvasSWTSashFormComposite extends UITestCase { + static int screenIdx = 0; + static PointImmutable wpos; + static DimensionImmutable wsize, rwsize = null; + + static long duration = 500; // ms + + @BeforeClass + public static void initClass() { + if(null == wsize) { + wsize = new Dimension(640, 480); + } + } + + @AfterClass + public static void releaseClass() { + } + + Display display = null; + Shell shell = null; + Composite composite = null; + SashForm sash = null; + Composite innerComposite = null; + com.jogamp.newt.Display swtNewtDisplay = null; + + @Before + public void init() { + SWTAccessor.invoke(true, new Runnable() { + public void run() { + display = new Display(); + Assert.assertNotNull( display ); + }}); + display.syncExec(new Runnable() { + public void run() { + shell = new Shell( display ); + Assert.assertNotNull( shell ); + shell.setLayout( new FillLayout() ); + composite = new Composite( shell, SWT.NONE ); + composite.setLayout( new FillLayout() ); + Assert.assertNotNull( composite ); + sash = new SashForm(composite, SWT.NONE); + Assert.assertNotNull( sash ); + final org.eclipse.swt.widgets.Label c = new org.eclipse.swt.widgets.Label(sash, SWT.NONE); + c.setText("Left cell"); + innerComposite = new Composite(sash, SWT.NONE); + Assert.assertNotNull( innerComposite ); + innerComposite.setLayout( new FillLayout() ); + }}); + swtNewtDisplay = NewtFactory.createDisplay(null, false); // no-reuse + } + + @After + public void release() { + Assert.assertNotNull( display ); + Assert.assertNotNull( shell ); + Assert.assertNotNull( composite ); + Assert.assertNotNull( sash ); + Assert.assertNotNull( innerComposite ); + try { + display.syncExec(new Runnable() { + public void run() { + innerComposite.dispose(); + sash.dispose(); + composite.dispose(); + shell.dispose(); + }}); + SWTAccessor.invoke(true, new Runnable() { + public void run() { + display.dispose(); + }}); + } + catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + swtNewtDisplay = null; + display = null; + shell = null; + composite = null; + sash = null; + innerComposite = null; + } + + class WaitAction implements Runnable { + private final long sleepMS; + + WaitAction(long sleepMS) { + this.sleepMS = sleepMS; + } + public void run() { + if( !display.readAndDispatch() ) { + // blocks on linux .. display.sleep(); + try { + Thread.sleep(sleepMS); + } catch (InterruptedException e) { } + } + } + } + final WaitAction awtRobotWaitAction = new WaitAction(AWTRobotUtil.TIME_SLICE); + final WaitAction generalWaitAction = new WaitAction(10); + + protected void runTestGL(GLCapabilitiesImmutable caps) throws InterruptedException, InvocationTargetException { + com.jogamp.newt.Screen screen = NewtFactory.createScreen(swtNewtDisplay, screenIdx); + final GLWindow glWindow = GLWindow.create(screen, caps); + Assert.assertNotNull(glWindow); + + final GearsES2 demo = new GearsES2(1); + glWindow.addGLEventListener(demo); + + Animator animator = new Animator(); + animator.setModeBits(false, Animator.MODE_EXPECT_AWT_RENDERING_THREAD); + + QuitAdapter quitAdapter = new QuitAdapter(); + //glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter)); + //glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter)); + glWindow.addKeyListener(quitAdapter); + glWindow.addWindowListener(quitAdapter); + + glWindow.addWindowListener(new WindowAdapter() { + public void windowResized(WindowEvent e) { + System.err.println("window resized: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()); + } + public void windowMoved(WindowEvent e) { + System.err.println("window moved: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()); + } + }); + + glWindow.addKeyListener(new KeyAdapter() { + public void keyReleased(KeyEvent e) { + if( !e.isPrintableKey() || e.isAutoRepeat() ) { + return; + } + if(e.getKeyChar()=='f') { + new Thread() { + public void run() { + final Thread t = glWindow.setExclusiveContextThread(null); + System.err.println("[set fullscreen pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets()); + glWindow.setFullscreen(!glWindow.isFullscreen()); + System.err.println("[set fullscreen post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets()); + glWindow.setExclusiveContextThread(t); + } }.start(); + } + } + }); + + animator.add(glWindow); + animator.start(); + Assert.assertTrue(animator.isStarted()); + Assert.assertTrue(animator.isAnimating()); + animator.setUpdateFPSFrames(60, null); + final NewtCanvasSWT canvas1 = NewtCanvasSWT.create( innerComposite, 0, glWindow ); + Assert.assertNotNull( canvas1 ); + + display.syncExec( new Runnable() { + public void run() { + shell.setText( getSimpleTestName(".") ); + shell.setSize( wsize.getWidth(), wsize.getHeight() ); + if( null != wpos ) { + shell.setLocation( wpos.getX(), wpos.getY() ); + } + shell.open(); + } + }); + Assert.assertTrue("GLWindow didn't become visible natively!", AWTRobotUtil.waitForRealized(glWindow, awtRobotWaitAction, true)); + Assert.assertNotNull( canvas1.getNativeWindow() ); + + System.err.println("NW chosen: "+glWindow.getDelegatedWindow().getChosenCapabilities()); + System.err.println("GL chosen: "+glWindow.getChosenCapabilities()); + System.err.println("window pos/siz.0: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", "+glWindow.getInsets()); + System.err.println("GLWindow LOS.0: "+glWindow.getLocationOnScreen(null)); + System.err.println("NewtCanvasSWT LOS.0: "+canvas1.getNativeWindow().getLocationOnScreen(null)); + + if( null != rwsize ) { + for(int i=0; i<50; i++) { // 500 ms dispatched delay + generalWaitAction.run(); + } + display.syncExec( new Runnable() { + public void run() { + shell.setSize( rwsize.getWidth(), rwsize.getHeight() ); + } + }); + System.err.println("window resize pos/siz.1: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", "+glWindow.getInsets()); + System.err.println("GLWindow LOS.1: "+glWindow.getLocationOnScreen(null)); + System.err.println("NewtCanvasSWT LOS.1: "+canvas1.getNativeWindow().getLocationOnScreen(null)); + } + + final PointImmutable pSashRightClient = new Point(wsize.getWidth(), 0); + final PointImmutable pNatWinLOS = canvas1.getNativeWindow().getLocationOnScreen(null); + final PointImmutable pGLWinLOS = glWindow.getLocationOnScreen(null); + + System.err.println("GLWindow LOS: "+pGLWinLOS); + System.err.println("NewtCanvasSWT LOS: "+pNatWinLOS); + + Assert.assertTrue( "NewtCanvasAWT LOS "+pNatWinLOS+" not >= sash-right "+pSashRightClient, pNatWinLOS.compareTo(pSashRightClient) >= 0 ); + Assert.assertTrue( "GLWindow LOS "+pGLWinLOS+" not >= sash-right "+pSashRightClient, pGLWinLOS.compareTo(pSashRightClient) >= 0 ); + + while( !quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration ) { + generalWaitAction.run(); + } + + animator.stop(); + Assert.assertFalse(animator.isAnimating()); + Assert.assertFalse(animator.isStarted()); + Assert.assertEquals(null, glWindow.getExclusiveContextThread()); + + canvas1.dispose(); + glWindow.destroy(); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false)); + } + + @Test + public void test01() throws InterruptedException, InvocationTargetException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities( glp ); + runTestGL(caps); + } + + public static void main(String args[]) throws IOException { + int x=0, y=0, w=640, h=480, rw=-1, rh=-1; + boolean usePos = false; + + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-width")) { + i++; + w = MiscUtils.atoi(args[i], w); + } else if(args[i].equals("-height")) { + i++; + h = MiscUtils.atoi(args[i], h); + } else if(args[i].equals("-x")) { + i++; + x = MiscUtils.atoi(args[i], x); + usePos = true; + } else if(args[i].equals("-y")) { + i++; + y = MiscUtils.atoi(args[i], y); + usePos = true; + } else if(args[i].equals("-rwidth")) { + i++; + rw = MiscUtils.atoi(args[i], rw); + } else if(args[i].equals("-rheight")) { + i++; + rh = MiscUtils.atoi(args[i], rh); + } else if(args[i].equals("-screen")) { + i++; + screenIdx = MiscUtils.atoi(args[i], 0); + } + } + wsize = new Dimension(w, h); + if( 0 < rw && 0 < rh ) { + rwsize = new Dimension(rw, rh); + } + + if(usePos) { + wpos = new Point(x, y); + } + System.err.println("position "+wpos); + System.err.println("size "+wsize); + System.err.println("resize "+rwsize); + System.err.println("screen "+screenIdx); + + org.junit.runner.JUnitCore.main(TestBug672NewtCanvasSWTSashFormComposite.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTBug628ResizeDeadlockAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTBug628ResizeDeadlockAWT.java new file mode 100644 index 000000000..be3a11bfc --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTBug628ResizeDeadlockAWT.java @@ -0,0 +1,427 @@ +/** + * Copyright 2012 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.jogl.swt; + +import java.awt.AWTException; +import java.awt.Robot; +import java.lang.reflect.InvocationTargetException; + +import org.eclipse.swt.SWT ; +import org.eclipse.swt.layout.FillLayout ; +import org.eclipse.swt.widgets.Composite ; +import org.eclipse.swt.widgets.Display ; +import org.eclipse.swt.widgets.Shell ; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import javax.media.opengl.GL ; +import javax.media.opengl.GL2 ; +import javax.media.opengl.GLAutoDrawable ; +import javax.media.opengl.GLCapabilities ; +import javax.media.opengl.GLEventListener ; +import javax.media.opengl.GLProfile; + +import com.jogamp.nativewindow.swt.SWTAccessor; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.event.KeyAdapter; +import com.jogamp.newt.event.KeyEvent; +import com.jogamp.newt.opengl.GLWindow ; +import com.jogamp.newt.swt.NewtCanvasSWT ; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; + +//////////////////////////////////////////////////////////////////////////////// + + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestNewtCanvasSWTBug628ResizeDeadlockAWT extends UITestCase { + + static int duration = 500; + + static class BigFlashingX implements GLEventListener + { + float r = 0f, g = 0f, b = 0f; + + public void init( GLAutoDrawable drawable ) + { + GL2 gl = drawable.getGL().getGL2() ; + + gl.glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ) ; + + gl.glEnable( GL.GL_LINE_SMOOTH ) ; + gl.glEnable( GL.GL_BLEND ) ; + gl.glBlendFunc( GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA ) ; + } + + public void reshape( GLAutoDrawable drawable, int x, int y, int width, int height ) + { + // System.err.println( ">>>>>>>> reshape " + x + ", " + y + ", " + width + ", " +height ) ; + GL2 gl = drawable.getGL().getGL2() ; + + gl.glViewport( 0, 0, width, height ) ; + + gl.glMatrixMode( GL2.GL_PROJECTION ) ; + gl.glLoadIdentity() ; + gl.glOrtho( -1.0, 1.0, -1.0, 1.0, -1.0, 1.0 ) ; + + gl.glMatrixMode( GL2.GL_MODELVIEW ) ; + gl.glLoadIdentity() ; + } + + public void display( GLAutoDrawable drawable ) + { + // System.err.println( ">>>> display" ) ; + GL2 gl = drawable.getGL().getGL2() ; + + // Sven: I could have been seeing things, but it seemed that if this + // glClear is in here twice it seems aggravates the problem. Not + // sure why other than it just takes longer, but this is pretty + // fast operation. + gl.glClear( GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT ) ; + gl.glClear( GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT ) ; + + gl.glColor4f( r, g, b, 1.0f ) ; + + gl.glBegin( GL.GL_LINES ) ; + { + gl.glVertex2f( -1.0f, 1.0f ) ; + gl.glVertex2f( 1.0f, -1.0f ) ; + + gl.glVertex2f( -1.0f, -1.0f ) ; + gl.glVertex2f( 1.0f, 1.0f ) ; + } + gl.glEnd() ; + + if(r<1f) { + r+=0.1f; + } else if(g<1f) { + g+=0.1f; + } else if(b<1f) { + b+=0.1f; + } else { + r = 0f; + g = 0f; + b = 0f; + } + } + + public void dispose( GLAutoDrawable drawable ) + { + } + } + + //////////////////////////////////////////////////////////////////////////////// + + static class ResizeThread extends Thread { + volatile boolean shallStop = false; + private final Shell _shell ; + private int _n ; + + public ResizeThread( Shell shell ) + { + super(); + _shell = shell ; + } + + final Runnable resizeAction = new Runnable() { + public void run() + { + System.err.println("[R-i shallStop "+shallStop+", disposed "+_shell.isDisposed()+"]"); + if( shallStop || _shell.isDisposed() ) { + return; + } + try { + if( _n % 2 == 0 ) { + _shell.setSize( 200, 200 ) ; + } else { + _shell.setSize( 400, 450 ) ; + } + } catch (Exception e0) { + e0.printStackTrace(); + Assert.assertTrue("Deadlock @ setSize: "+e0, false); + } + ++_n ; + } }; + + public void run() + { + // The problem was originally observed by grabbing the lower right + // corner of the window and moving the mouse around rapidly e.g. in + // a circle. Eventually the UI will hang with something similar to + // the backtrace noted in the bug report. + // + // This loop simulates rapid resizing by the user by toggling + // the shell back-and-forth between two sizes. + + System.err.println("[R-0 shallStop "+shallStop+", disposed "+_shell.isDisposed()+"]"); + + final Display display = _shell.getDisplay(); + + while( !shallStop && !_shell.isDisposed() ) + { + try + { + System.err.println("[R-n shallStop "+shallStop+", disposed "+_shell.isDisposed()+"]"); + display.asyncExec( resizeAction ); + display.wake(); + + Thread.sleep( 50L ) ; + } catch( InterruptedException e ) { + break ; + } + } + System.err.println("*R-Exit* shallStop "+shallStop+", disposed "+_shell.isDisposed()); + } + } + + //////////////////////////////////////////////////////////////////////////////// + + static class KeyfireThread extends Thread + { + volatile boolean shallStop = false; + Display _display; + Robot _robot; + int _n = 0; + + public KeyfireThread(Robot robot, Display display) + { + _robot = robot; + _display = display; + } + + public void run() + { + System.err.println("[K-0]"); + + while( !shallStop ) + { + try { + System.err.println("[K-"+_n+"]"); + AWTRobotUtil.waitForIdle(_robot); + AWTRobotUtil.newtKeyPress(_n, _robot, true, KeyEvent.VK_0, 10); + AWTRobotUtil.newtKeyPress(_n, _robot, false, KeyEvent.VK_0, 0); + Thread.sleep( 40L ) ; + _n++; + if(!_display.isDisposed()) { + _display.wake(); + } + } catch( InterruptedException e ) { + break ; + } + } + System.err.println("*K-Exit*"); + } + } + + //////////////////////////////////////////////////////////////////////////////// + + private volatile boolean shallStop = false; + + static class SWT_DSC { + volatile Display display; + volatile Shell shell; + volatile Composite composite; + volatile com.jogamp.newt.Display swtNewtDisplay = null; + + public void init() { + SWTAccessor.invoke(true, new Runnable() { + public void run() { + display = new Display(); + Assert.assertNotNull( display ); + }}); + + display.syncExec(new Runnable() { + public void run() { + shell = new Shell( display ); + Assert.assertNotNull( shell ); + shell.setLayout( new FillLayout() ); + composite = new Composite( shell, SWT.NO_BACKGROUND ); + composite.setLayout( new FillLayout() ); + Assert.assertNotNull( composite ); + }}); + swtNewtDisplay = NewtFactory.createDisplay(null, false); // no-reuse + } + + public void dispose() { + Assert.assertNotNull( display ); + Assert.assertNotNull( shell ); + Assert.assertNotNull( composite ); + try { + display.syncExec(new Runnable() { + public void run() { + composite.dispose(); + shell.dispose(); + }}); + SWTAccessor.invoke(true, new Runnable() { + public void run() { + display.dispose(); + }}); + } + catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + swtNewtDisplay = null; + display = null; + shell = null; + composite = null; + } + class WaitAction implements Runnable { + private final long sleepMS; + + WaitAction(long sleepMS) { + this.sleepMS = sleepMS; + } + public void run() { + if( !display.readAndDispatch() ) { + // blocks on linux .. display.sleep(); + try { + Thread.sleep(sleepMS); + } catch (InterruptedException e) { } + } + } + } + final WaitAction awtRobotWaitAction = new WaitAction(AWTRobotUtil.TIME_SLICE); + } + + @Test + public void test() throws InterruptedException, AWTException, InvocationTargetException { + final Robot robot = new Robot(); + + final SWT_DSC dsc = new SWT_DSC(); + dsc.init(); + + final GLWindow glWindow; + { + final GLProfile gl2Profile = GLProfile.get( GLProfile.GL2 ) ; + final GLCapabilities caps = new GLCapabilities( gl2Profile ) ; + com.jogamp.newt.Screen screen = NewtFactory.createScreen(dsc.swtNewtDisplay, 0); + glWindow = GLWindow.create( screen, caps ) ; + glWindow.addGLEventListener( new BigFlashingX() ) ; + glWindow.addKeyListener(new KeyAdapter() { + @Override + public void keyReleased(com.jogamp.newt.event.KeyEvent e) { + if( !e.isPrintableKey() || e.isAutoRepeat() ) { + return; + } + System.err.print("."); + glWindow.display(); + } + }); + NewtCanvasSWT.create( dsc.composite, 0, glWindow ) ; + } + + dsc.display.syncExec( new Runnable() { + public void run() { + dsc.shell.setText( "NewtCanvasSWT Resize Bug Demo" ) ; + dsc.shell.setSize( 400, 450 ) ; + dsc.shell.open() ; + } } ); + Assert.assertTrue("GLWindow didn't become visible natively!", AWTRobotUtil.waitForRealized(glWindow, dsc.awtRobotWaitAction, true)); + + AWTRobotUtil.requestFocus(robot, glWindow, false); + AWTRobotUtil.setMouseToClientLocation(robot, glWindow, 50, 50); + + shallStop = false; + + final ResizeThread resizer; + { + resizer = new ResizeThread( dsc.shell ) ; + resizer.start() ; + } + + final KeyfireThread keyfire; + { + keyfire = new KeyfireThread( robot, dsc.display ) ; + keyfire.start() ; + } + + { + final Thread t = new Thread(new Runnable() { + @Override + public void run() { + try { + Thread.sleep(duration); + } catch (InterruptedException e) {} + resizer.shallStop = true; + keyfire.shallStop = true; + try + { + resizer.join(); + } catch( InterruptedException e ) { } + try + { + keyfire.join(); + } catch( InterruptedException e ) { } + shallStop = true; + if( null != dsc.display && !dsc.display.isDisposed() ) { + dsc.display.wake(); + } + } } ); + t.setDaemon(true); + t.start(); + } + + try { + while( !shallStop && !dsc.display.isDisposed() ) { + dsc.display.syncExec( new Runnable() { + public void run() { + if( !dsc.display.isDisposed() && !dsc.display.readAndDispatch() && !shallStop ) { + // blocks on linux .. dsc.display.sleep(); + try { + Thread.sleep(10); + } catch (InterruptedException ie) { ie.printStackTrace(); } + } + } } ); + } + } catch (Exception e0) { + e0.printStackTrace(); + Assert.assertTrue("Deadlock @ dispatch: "+e0, false); + } + + // canvas is disposed implicit, due to it's disposed listener ! + + dsc.dispose(); + } + + public static void main( String[] args ) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + duration = MiscUtils.atoi(args[++i], duration); + } + } + System.out.println("durationPerTest: "+duration); + org.junit.runner.JUnitCore.main(TestNewtCanvasSWTBug628ResizeDeadlockAWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTGLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTGLn.java new file mode 100644 index 000000000..5426ab7af --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTGLn.java @@ -0,0 +1,261 @@ +/** + * 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.jogl.swt; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.After; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.nativewindow.swt.SWTAccessor; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Screen; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.newt.swt.NewtCanvasSWT; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.MultisampleDemoES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; + +/** + * Tests that a basic SWT app can open without crashing under different GL profiles + * _and_ custom GLCapabilities. + * <p> + * Uses JOGL's NewtCanvasSWT, which allows to be a native container of a NEWT Window.<br/> + * This method allows utilizing custom GLCapability settings, + * independent from the already instantiated SWT visual. + * </p> + * <p> + * Note that {@link SWTAccessor#invoke(boolean, Runnable)} is still used to comply w/ + * SWT running on Mac OSX, i.e. to enforce UI action on the main thread. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestNewtCanvasSWTGLn extends UITestCase { + + static int duration = 250; + + static final int iwidth = 640; + static final int iheight = 480; + + Display display = null; + Shell shell = null; + Composite composite = null; + com.jogamp.newt.Display swtNewtDisplay = null; + + @BeforeClass + public static void startup() { + System.out.println( "GLProfile " + GLProfile.glAvailabilityToString() ); + } + + @Before + public void init() { + SWTAccessor.invoke(true, new Runnable() { + public void run() { + display = new Display(); + Assert.assertNotNull( display ); + }}); + display.syncExec(new Runnable() { + public void run() { + shell = new Shell( display ); + Assert.assertNotNull( shell ); + shell.setLayout( new FillLayout() ); + composite = new Composite( shell, SWT.NONE ); + composite.setLayout( new FillLayout() ); + Assert.assertNotNull( composite ); + }}); + swtNewtDisplay = NewtFactory.createDisplay(null, false); // no-reuse + } + + @After + public void release() { + Assert.assertNotNull( display ); + Assert.assertNotNull( shell ); + Assert.assertNotNull( composite ); + try { + display.syncExec(new Runnable() { + public void run() { + composite.dispose(); + shell.dispose(); + }}); + SWTAccessor.invoke(true, new Runnable() { + public void run() { + display.dispose(); + }}); + } + catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + swtNewtDisplay = null; + display = null; + shell = null; + composite = null; + } + + class WaitAction implements Runnable { + private final long sleepMS; + + WaitAction(long sleepMS) { + this.sleepMS = sleepMS; + } + public void run() { + if( !display.readAndDispatch() ) { + // blocks on linux .. display.sleep(); + try { + Thread.sleep(sleepMS); + } catch (InterruptedException e) { } + } + } + } + final WaitAction awtRobotWaitAction = new WaitAction(AWTRobotUtil.TIME_SLICE); + final WaitAction generalWaitAction = new WaitAction(10); + + protected void runTestAGL( GLCapabilitiesImmutable caps, GLEventListener demo, + boolean postAttach, boolean useAnimator ) throws InterruptedException { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false); + + final Screen screen = NewtFactory.createScreen(swtNewtDisplay, 0); + final GLWindow glWindow1 = GLWindow.create(screen, caps); + Assert.assertNotNull(glWindow1); + Assert.assertEquals(false, glWindow1.isVisible()); + Assert.assertEquals(false, glWindow1.isNativeValid()); + Assert.assertNull(glWindow1.getParent()); + glWindow1.addGLEventListener(demo); + glWindow1.addGLEventListener(new GLEventListener() { + int displayCount = 0; + public void init(final GLAutoDrawable drawable) { } + public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { } + public void display(final GLAutoDrawable drawable) { + if(displayCount < 3) { + snapshot(displayCount++, null, drawable.getGL(), screenshot, TextureIO.PNG, null); + } + } + public void dispose(final GLAutoDrawable drawable) { } + }); + + final NewtCanvasSWT canvas1 = NewtCanvasSWT.create( composite, 0, postAttach ? null : glWindow1 ); + Assert.assertNotNull( canvas1 ); + + display.syncExec( new Runnable() { + public void run() { + shell.setText( getSimpleTestName(".") ); + shell.setSize( 640, 480 ); + shell.open(); + } + }); + + if(postAttach) { + canvas1.setNEWTChild(glWindow1); + } + + Assert.assertTrue("GLWindow didn't become visible natively!", AWTRobotUtil.waitForRealized(glWindow1, awtRobotWaitAction, true)); + + System.err.println("GLWindow LOS.0: "+glWindow1.getLocationOnScreen(null)); + System.err.println("NewtCanvasSWT LOS.0: "+canvas1.getNativeWindow().getLocationOnScreen(null)); + + // canvas1.update(); + + Animator anim; + if(useAnimator) { + anim = new Animator(glWindow1); + anim.start(); + } else { + anim = null; + } + + long lStartTime = System.currentTimeMillis(); + long lEndTime = lStartTime + duration; + try { + while( (System.currentTimeMillis() < lEndTime) && !canvas1.isDisposed() ) { + generalWaitAction.run(); + } + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + if(null != anim) { + anim.stop(); + } + + canvas1.dispose(); + } + + @Test + public void preAttach_WithAnimator() throws InterruptedException { + runTestAGL( new GLCapabilities(GLProfile.getGL2ES2()), new GearsES2(), false /* postAttach */, true /* animator */); + } + + @Test + public void preAttach_NoAnimator() throws InterruptedException { + runTestAGL( new GLCapabilities(GLProfile.getGL2ES2()), new GearsES2(), false /* postAttach */, false /* animator */); + } + + @Test + public void postAttach_WithAnimator() throws InterruptedException { + runTestAGL( new GLCapabilities(GLProfile.getGL2ES2()), new GearsES2(), true /* postAttach */, true /* animator */); + } + + @Test + public void test_MultisampleAndAlpha() throws InterruptedException { + GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES2()); + caps.setSampleBuffers(true); + caps.setNumSamples(2); + runTestAGL( caps, new MultisampleDemoES2(true), false /* postAttach */, false /* animator */); + } + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + duration = MiscUtils.atoi(args[++i], duration); + } + } + System.out.println("durationPerTest: "+duration); + org.junit.runner.JUnitCore.main(TestNewtCanvasSWTGLn.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor02GLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor02GLn.java deleted file mode 100644 index 0c350255e..000000000 --- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor02GLn.java +++ /dev/null @@ -1,257 +0,0 @@ -/** - * 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.jogl.swt; - -import javax.media.opengl.GL2ES1; -import javax.media.opengl.GLContext; -import javax.media.opengl.GLDrawableFactory; -import javax.media.opengl.GLProfile; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.PaintEvent; -import org.eclipse.swt.events.PaintListener; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.layout.FillLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Listener; -import org.eclipse.swt.widgets.Shell; - -import org.junit.Assert; -import org.junit.Assume; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.After; -import org.junit.Test; - -import com.jogamp.nativewindow.swt.SWTAccessor; -import com.jogamp.opengl.test.junit.jogl.demos.es1.OneTriangle; -import com.jogamp.opengl.test.junit.util.UITestCase; -import javax.media.nativewindow.AbstractGraphicsDevice; -import javax.media.nativewindow.ProxySurface; -import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLDrawable; -import org.eclipse.swt.widgets.Canvas; - -/** - * Tests that a basic SWT app can open without crashing under different GL profiles. - * <p> - * Uses JOGL's SWTAccessor only. - * </p> - * @author Wade Walker, et.al. - */ -public class TestSWTAccessor02GLn extends UITestCase { - - static int duration = 250; - - static final int iwidth = 640; - static final int iheight = 480; - - Display display = null; - Shell shell = null; - Composite composite = null; - - @BeforeClass - public static void startup() { - System.out.println( "GLProfile " + GLProfile.glAvailabilityToString() ); - } - - @Before - public void init() { - final Display[] r = new Display[1]; - final Shell[] s = new Shell[1]; - SWTAccessor.invoke(true, new Runnable() { - public void run() { - r[0] = new Display(); - s[0] = new Shell(); - } - }); - display = r[0]; - shell = s[0]; - Assert.assertNotNull( display ); - Assert.assertNotNull( shell ); - - SWTAccessor.invoke(true, new Runnable() { - public void run() { - shell.setLayout( new FillLayout() ); - composite = new Composite( shell, SWT.NONE ); - Assert.assertNotNull( composite ); - composite.setLayout( new FillLayout() ); - }}); - } - - @After - public void release() { - Assert.assertNotNull( display ); - Assert.assertNotNull( shell ); - Assert.assertNotNull( composite ); - try { - SWTAccessor.invoke(true, new Runnable() { - public void run() { - composite.dispose(); - shell.dispose(); - display.dispose(); - }}); - } - catch( Throwable throwable ) { - throwable.printStackTrace(); - Assume.assumeNoException( throwable ); - } - display = null; - shell = null; - composite = null; - } - - class CanvasCStr implements Runnable { - Canvas canvas; - - public void run() { - canvas = new Canvas( composite, SWT.NO_BACKGROUND); - } - } - - protected void runTestAGL( GLProfile glprofile ) throws InterruptedException { - GLCapabilities caps = new GLCapabilities(glprofile); - GLDrawableFactory factory = GLDrawableFactory.getFactory(glprofile); - - // need SWT.NO_BACKGROUND to prevent SWT from clearing the window - // at the wrong times (we use glClear for this instead) - CanvasCStr canvasCstr = new CanvasCStr(); - - SWTAccessor.invoke(true, canvasCstr); - final Canvas canvas = canvasCstr.canvas; - Assert.assertNotNull( canvas ); - - SWTAccessor.setRealized(canvas, true); - AbstractGraphicsDevice device = SWTAccessor.getDevice(canvas); - long nativeWindowHandle = SWTAccessor.getWindowHandle(canvas); - System.err.println("*** device: " + device); - System.err.println("*** window handle: 0x" + Long.toHexString(nativeWindowHandle)); - - ProxySurface proxySurface = factory.createProxySurface(device, nativeWindowHandle, caps, null); - Assert.assertNotNull( proxySurface ); - proxySurface.surfaceSizeChanged( 640, 480 ); - System.err.println("*** ProxySurface: " + proxySurface); - final GLDrawable drawable = factory.createGLDrawable(proxySurface); - Assert.assertNotNull( drawable ); - drawable.setRealized(true); - System.err.println("*** Drawable: " + drawable); - Assert.assertTrue( drawable.isRealized() ); - final GLContext glcontext = drawable.createContext(null); - // trigger native creation .. - if( GLContext.CONTEXT_NOT_CURRENT < glcontext.makeCurrent() ) { - glcontext.release(); - } - - final boolean[] sizeMissing = new boolean[] { false }; - - // fix the viewport when the user resizes the window - canvas.addListener( SWT.Resize, new Listener() { - public void handleEvent( Event event ) { - Rectangle rectangle = canvas.getClientArea(); - boolean glok=false; - if( GLContext.CONTEXT_NOT_CURRENT < glcontext.makeCurrent() ) { - glok=true; - GL2ES1 gl = glcontext.getGL().getGL2ES1(); - OneTriangle.setup( gl, rectangle.width, rectangle.height ); - glcontext.release(); - } else { - sizeMissing[0] = true; - } - System.err.println("resize: glok " + glok); - } - }); - - // draw the triangle when the OS tells us that any part of the window needs drawing - canvas.addPaintListener( new PaintListener() { - public void paintControl( PaintEvent paintevent ) { - Rectangle rectangle = canvas.getClientArea(); - boolean glok=false; - if( GLContext.CONTEXT_NOT_CURRENT < glcontext.makeCurrent() ) { - glok=true; - GL2ES1 gl = glcontext.getGL().getGL2ES1(); - if(sizeMissing[0]) { - OneTriangle.setup( gl, rectangle.width, rectangle.height); - sizeMissing[0] = false; - } - OneTriangle.render( gl, rectangle.width, rectangle.height); - drawable.swapBuffers(); - glcontext.release(); - } - System.err.println("paint: glok " + glok); - } - }); - - shell.setText( getClass().getName() ); - shell.setSize( 640, 480 ); - shell.open(); - - long lStartTime = System.currentTimeMillis(); - long lEndTime = lStartTime + duration; - try { - while( (System.currentTimeMillis() < lEndTime) && !canvas.isDisposed() ) { - if( !display.readAndDispatch() ) { - // blocks on linux .. display.sleep(); - Thread.sleep(10); - } - } - } catch( Throwable throwable ) { - throwable.printStackTrace(); - Assume.assumeNoException( throwable ); - } - glcontext.destroy(); - drawable.setRealized(false); - canvas.dispose(); - } - - @Test - public void test() throws InterruptedException { - GLProfile glprofile = GLProfile.getGL2ES1(); - runTestAGL( glprofile ); - } - - static int atoi(String a) { - int i=0; - try { - i = Integer.parseInt(a); - } catch (Exception ex) { ex.printStackTrace(); } - return i; - } - - public static void main(String args[]) { - for(int i=0; i<args.length; i++) { - if(args[i].equals("-time")) { - duration = atoi(args[++i]); - } - } - System.out.println("durationPerTest: "+duration); - org.junit.runner.JUnitCore.main(TestSWTAccessor02GLn.class.getName()); - } -} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAWT01GLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor03AWTGLn.java index 021e1178a..7cc19a72f 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAWT01GLn.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor03AWTGLn.java @@ -49,13 +49,15 @@ import org.eclipse.swt.widgets.Shell; import org.junit.Assert; import org.junit.Assume; -import org.junit.Before; import org.junit.BeforeClass; -import org.junit.After; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +import com.jogamp.common.os.Platform; import com.jogamp.nativewindow.swt.SWTAccessor; import com.jogamp.opengl.test.junit.jogl.demos.es1.OneTriangle; +import com.jogamp.opengl.test.junit.util.MiscUtils; import com.jogamp.opengl.test.junit.util.UITestCase; /** @@ -63,9 +65,10 @@ import com.jogamp.opengl.test.junit.util.UITestCase; * the SWT_AWT bridge. * @author Wade Walker, et.al. */ -public class TestSWTAWT01GLn extends UITestCase { +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestSWTAccessor03AWTGLn extends UITestCase { - static final int duration = 250; + static int duration = 250; Display display = null; Shell shell = null; @@ -75,14 +78,31 @@ public class TestSWTAWT01GLn extends UITestCase { @BeforeClass public static void startup() { - System.out.println( "GLProfile " + GLProfile.glAvailabilityToString() ); + if( Platform.getOSType() == Platform.OSType.MACOS ) { + // NSLocking issues on OSX and AWT, able to freeze whole test suite! + // Since this test is merely a technical nature to validate the accessor w/ SWT + // we can drop it w/o bothering. + UITestCase.setTestSupported(false); + return; + } + System.out.println( "GLProfile " + GLProfile.glAvailabilityToString() ); + final Frame f0 = new Frame("Test - AWT 1st"); + f0.add(new java.awt.Label("AWT was here 1st")); + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + f0.pack(); + f0.setVisible(true); + }}); + } catch (Exception e) { + throw new RuntimeException(e); + } if(!GLProfile.isAvailable(GLProfile.GL2)) { setTestSupported(false); } } - @Before - public void init() throws InterruptedException, InvocationTargetException { + protected void init() throws InterruptedException, InvocationTargetException { SWTAccessor.invoke(true, new Runnable() { public void run() { display = new Display(); @@ -98,20 +118,23 @@ public class TestSWTAWT01GLn extends UITestCase { }}); } - @After - public void release() throws InterruptedException, InvocationTargetException { + protected void release() throws InterruptedException, InvocationTargetException { Assert.assertNotNull( display ); Assert.assertNotNull( shell ); Assert.assertNotNull( composite ); Assert.assertNotNull( glcanvas ); - javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + final Runnable releaseAWT = new Runnable() { public void run() { + // deadlocks Java7 on Windows frame.setVisible(false); frame.remove(glcanvas); frame.dispose(); frame = null; glcanvas = null; - }}); + } }; + // Deadlocks Java7 on Windows + // javax.swing.SwingUtilities.invokeAndWait( releaseAWT ); + releaseAWT.run(); SWTAccessor.invoke(true, new Runnable() { public void run() { @@ -125,71 +148,81 @@ public class TestSWTAWT01GLn extends UITestCase { }}); } - protected void runTestGL( GLProfile glprofile ) throws InterruptedException { - GLCapabilities glcapabilities = new GLCapabilities( glprofile ); - glcanvas = new GLCanvas( glcapabilities ); - Assert.assertNotNull( glcanvas ); - frame.add( glcanvas ); - - glcanvas.addGLEventListener( new GLEventListener() { - /* @Override */ - public void init( GLAutoDrawable glautodrawable ) { - } - - /* @Override */ - public void dispose( GLAutoDrawable glautodrawable ) { - } - - /* @Override */ - public void display( GLAutoDrawable glautodrawable ) { - Rectangle rectangle = new Rectangle( 0, 0, glautodrawable.getWidth(), glautodrawable.getHeight() ); - GL2ES1 gl = glautodrawable.getGL().getGL2ES1(); - OneTriangle.render( gl, rectangle.width, rectangle.height ); - } - - /* @Override */ - public void reshape( GLAutoDrawable glautodrawable, int x, int y, int width, int height ) { - Rectangle rectangle = new Rectangle( 0, 0, glautodrawable.getWidth(), glautodrawable.getHeight() ); - GL2ES1 gl = glautodrawable.getGL().getGL2ES1(); - OneTriangle.setup( gl, rectangle.width, rectangle.height ); - } - }); - - SWTAccessor.invoke(true, new Runnable() { - public void run() { - shell.setText( getClass().getName() ); - shell.setSize( 640, 480 ); - shell.open(); - }}); - - long lStartTime = System.currentTimeMillis(); - long lEndTime = lStartTime + duration; + protected void runTestGL( GLProfile glprofile ) throws InterruptedException, InvocationTargetException { + init(); try { - while( (System.currentTimeMillis() < lEndTime) && !composite.isDisposed() ) { - SWTAccessor.invoke(true, new Runnable() { - public void run() { - if( !display.readAndDispatch() ) { - // blocks on linux .. display.sleep(); - try { - Thread.sleep(10); - } catch (InterruptedException e) { } - } - }}); + GLCapabilities glcapabilities = new GLCapabilities( glprofile ); + glcanvas = new GLCanvas( glcapabilities ); + Assert.assertNotNull( glcanvas ); + frame.add( glcanvas ); + + glcanvas.addGLEventListener( new GLEventListener() { + /* @Override */ + public void init( GLAutoDrawable glautodrawable ) { + } + + /* @Override */ + public void dispose( GLAutoDrawable glautodrawable ) { + } + + /* @Override */ + public void display( GLAutoDrawable glautodrawable ) { + Rectangle rectangle = new Rectangle( 0, 0, glautodrawable.getWidth(), glautodrawable.getHeight() ); + GL2ES1 gl = glautodrawable.getGL().getGL2ES1(); + OneTriangle.render( gl, rectangle.width, rectangle.height ); + } + + /* @Override */ + public void reshape( GLAutoDrawable glautodrawable, int x, int y, int width, int height ) { + Rectangle rectangle = new Rectangle( 0, 0, glautodrawable.getWidth(), glautodrawable.getHeight() ); + GL2ES1 gl = glautodrawable.getGL().getGL2ES1(); + OneTriangle.setup( gl, rectangle.width, rectangle.height ); + } + }); + + SWTAccessor.invoke(true, new Runnable() { + public void run() { + shell.setText( getClass().getName() ); + shell.setSize( 640, 480 ); + shell.open(); + }}); + + long lStartTime = System.currentTimeMillis(); + long lEndTime = lStartTime + duration; + try { + while( (System.currentTimeMillis() < lEndTime) && !composite.isDisposed() ) { + SWTAccessor.invoke(true, new Runnable() { + public void run() { + if( !display.readAndDispatch() ) { + // blocks on linux .. display.sleep(); + try { + Thread.sleep(10); + } catch (InterruptedException e) { } + } + }}); + } } - } - catch( Throwable throwable ) { - throwable.printStackTrace(); - Assume.assumeNoException( throwable ); + catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + } finally { + release(); } } @Test - public void test() throws InterruptedException { + public void test() throws InterruptedException, InvocationTargetException { GLProfile glprofile = GLProfile.getGL2ES1(); runTestGL( glprofile ); } public static void main(String args[]) { - org.junit.runner.JUnitCore.main( TestSWTAWT01GLn.class.getName() ); + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + duration = MiscUtils.atoi(args[++i], duration); + } + } + org.junit.runner.JUnitCore.main( TestSWTAccessor03AWTGLn.class.getName() ); } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTBug643AsyncExec.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTBug643AsyncExec.java new file mode 100644 index 000000000..fd6d370ac --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTBug643AsyncExec.java @@ -0,0 +1,350 @@ +/** + * Copyright 2012 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.jogl.swt; + +import java.lang.reflect.InvocationTargetException; + +import org.eclipse.swt.SWT ; + +import org.eclipse.swt.layout.FillLayout ; + +import org.eclipse.swt.widgets.Composite ; +import org.eclipse.swt.widgets.Display ; +import org.eclipse.swt.widgets.Shell ; + +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities ; +import javax.media.opengl.GLProfile; + +import jogamp.newt.swt.SWTEDTUtil; +import jogamp.newt.swt.event.SWTNewtEventFactory; + +import com.jogamp.nativewindow.swt.SWTAccessor; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.opengl.GLWindow ; +import com.jogamp.newt.swt.NewtCanvasSWT ; +import com.jogamp.opengl.swt.GLCanvas; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; + +//////////////////////////////////////////////////////////////////////////////// + + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestSWTBug643AsyncExec extends UITestCase { + + static int duration = 500; + static boolean useAnimator = false; + + //////////////////////////////////////////////////////////////////////////////// + + static void resetSWTAndNEWTEDTCounter() { + synchronized(swtCountSync) { + swtCount=0; + } + synchronized(edtCountSync) { + edtCount=0; + } + } + static int incrSWTCount() { + synchronized(swtCountSync) { + swtCount++; + return swtCount; + } + } + static int getSWTCount() { + synchronized(swtCountSync) { + return swtCount; + } + } + static int incrNEWTCount() { + synchronized(edtCountSync) { + edtCount++; + return edtCount; + } + } + static int getNEWTCount() { + synchronized(edtCountSync) { + return edtCount; + } + } + static Object swtCountSync = new Object(); + static int swtCount = 0; + static Object edtCountSync = new Object(); + static int edtCount = 0; + + //////////////////////////////////////////////////////////////////////////////// + + static class AsyncExecEDTFeederThread extends Thread { + volatile boolean shallStop = false; + private final Display swtDisplay ; + private final jogamp.newt.DisplayImpl newtDisplay; + private int swtN, newtN ; + + public AsyncExecEDTFeederThread( Display swtDisplay, com.jogamp.newt.Display newtDisplay ) + { + super(); + this.swtDisplay = swtDisplay ; + this.newtDisplay = (jogamp.newt.DisplayImpl)newtDisplay; + } + + final Runnable swtAsyncAction = new Runnable() { + public void run() + { + ++swtN ; incrSWTCount(); + System.err.println("[SWT A-i shallStop "+shallStop+"]: Counter[loc "+swtN+", glob: "+getSWTCount()+"]"); + } }; + + final Runnable newtAsyncAction = new Runnable() { + public void run() + { + ++newtN ; incrNEWTCount(); + System.err.println("[NEWT A-i shallStop "+shallStop+"]: Counter[loc "+newtN+", glob: "+getNEWTCount()+"]"); + } }; + + public void run() + { + System.err.println("[A-0 shallStop "+shallStop+"]"); + + while( !shallStop && !swtDisplay.isDisposed() ) + { + try + { + if( !swtDisplay.isDisposed() ) { + swtDisplay.asyncExec( swtAsyncAction ); + } + if(null != newtDisplay && newtDisplay.isNativeValid() && newtDisplay.getEDTUtil().isRunning()) { + // only perform async exec on valid and already running NEWT EDT! + newtDisplay.runOnEDTIfAvail(false, newtAsyncAction); + } + Thread.sleep( 50L ) ; + } catch( InterruptedException e ) { + break ; + } + } + System.err.println("*R-Exit* shallStop "+shallStop); + } + } + + //////////////////////////////////////////////////////////////////////////////// + + private volatile boolean shallStop = false; + + static class SWT_DSC { + Display display; + Shell shell; + Composite composite; + + public void init() { + SWTAccessor.invoke(true, new Runnable() { + public void run() { + display = new Display(); + Assert.assertNotNull( display ); + }}); + + display.syncExec(new Runnable() { + public void run() { + shell = new Shell( display ); + Assert.assertNotNull( shell ); + shell.setLayout( new FillLayout() ); + composite = new Composite( shell, SWT.NO_BACKGROUND ); + composite.setLayout( new FillLayout() ); + Assert.assertNotNull( composite ); + }}); + } + + public void dispose() { + Assert.assertNotNull( display ); + Assert.assertNotNull( shell ); + Assert.assertNotNull( composite ); + try { + display.syncExec(new Runnable() { + public void run() { + composite.dispose(); + shell.dispose(); + }}); + SWTAccessor.invoke(true, new Runnable() { + public void run() { + display.dispose(); + }}); + } + catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + display = null; + shell = null; + composite = null; + } + } + + private void testImpl(boolean useJOGLGLCanvas, boolean useNewtCanvasSWT, boolean glWindowPreVisible) throws InterruptedException, InvocationTargetException { + resetSWTAndNEWTEDTCounter(); + + final SWT_DSC dsc = new SWT_DSC(); + dsc.init(); + + final com.jogamp.newt.Display newtDisplay; + { + final GLProfile gl2Profile = GLProfile.get( GLProfile.GL2 ) ; + final GLCapabilities caps = new GLCapabilities( gl2Profile ) ; + + final GLAutoDrawable glad; + if( useJOGLGLCanvas ) { + final GearsES2 demo = new GearsES2(); + final GLCanvas glc = GLCanvas.create(dsc.composite, 0, caps, null); + final SWTNewtEventFactory swtNewtEventFactory = new SWTNewtEventFactory(); + swtNewtEventFactory.attachDispatchListener(glc, glc, demo.gearsMouse, demo.gearsKeys); + glc.addGLEventListener( demo ) ; + glad = glc; + newtDisplay = null; + } else if( useNewtCanvasSWT ) { + newtDisplay = NewtFactory.createDisplay(null, false); // no-reuse + com.jogamp.newt.Screen screen = NewtFactory.createScreen(newtDisplay, 0); + final GLWindow glWindow = GLWindow.create( screen, caps ) ; + glWindow.addGLEventListener( new GearsES2() ) ; + if( glWindowPreVisible ) { + newtDisplay.setEDTUtil(new SWTEDTUtil(newtDisplay, dsc.display)); // Especially Windows requires creation access via same thread! + glWindow.setVisible(true); + AWTRobotUtil.waitForRealized(glWindow, true); + Thread.sleep(120); // let it render a bit, before consumed by SWT + } + glad = glWindow; + NewtCanvasSWT.create( dsc.composite, 0, glWindow ) ; + } else { + throw new InternalError("XXX"); + } + if(useAnimator) { + Animator animator = new Animator(glad); + animator.start(); + } + } + + System.err.println("**** Pre Shell Open"); + dsc.display.syncExec( new Runnable() { + public void run() { + dsc.shell.setText( "NewtCanvasSWT Resize Bug Demo" ) ; + dsc.shell.setSize( 400, 450 ) ; + dsc.shell.open() ; + } } ); + System.err.println("**** Post Shell Open"); + + shallStop = false; + + final int[] counterBeforeExit = new int[] { 0 /* SWT */, 0 /* NEWT */ }; + + final AsyncExecEDTFeederThread asyncExecFeeder; + { + asyncExecFeeder = new AsyncExecEDTFeederThread(dsc.display, newtDisplay) ; + asyncExecFeeder.start() ; + } + + { + final Thread t = new Thread(new Runnable() { + @Override + public void run() { + try { + Thread.sleep(duration); + } catch (InterruptedException e) {} + + counterBeforeExit[0] = getSWTCount(); + counterBeforeExit[1] = getNEWTCount(); + asyncExecFeeder.shallStop = true; + try + { + asyncExecFeeder.join(); + } catch( InterruptedException e ) { } + shallStop = true; + dsc.display.wake(); + } } ); + t.setDaemon(true); + t.start(); + } + + try { + final Display d = dsc.display; + while( !shallStop && !d.isDisposed() ) { + if( !d.readAndDispatch() && !shallStop ) { + // blocks on linux .. dsc.display.sleep(); + Thread.sleep(10); + } + } + } catch (Exception e0) { + e0.printStackTrace(); + Assert.assertTrue("Deadlock @ dispatch: "+e0, false); + } + + // canvas is disposed implicit, due to it's disposed listener ! + + dsc.dispose(); + + System.err.println("EDT Counter before exit: SWT " + counterBeforeExit[0] + ", NEWT "+counterBeforeExit[1]); + Assert.assertTrue("SWT EDT Counter not greater zero before dispose!", 0 < counterBeforeExit[0]); + if( null != newtDisplay ) { + Assert.assertTrue("NEWT EDT Counter not greater zero before dispose!", 0 < counterBeforeExit[1]); + } + } + + @Test + public void test01JOGLGLCanvas() throws InterruptedException, InvocationTargetException { + testImpl(true /* useJOGLGLCanvas */, false /* useNewtCanvasSWT */, false /* glWindowPreVisible */); + } + + @Test + public void test02NewtCanvasSWTSimple() throws InterruptedException, InvocationTargetException { + testImpl(false /* useJOGLGLCanvas */, true /* useNewtCanvasSWT */, false /* glWindowPreVisible */); + } + + @Test + public void test02NewtCanvasSWTPreVisible() throws InterruptedException, InvocationTargetException { + testImpl(false /* useJOGLGLCanvas */, true /* useNewtCanvasSWT */, true /* glWindowPreVisible */); + } + + public static void main( String[] args ) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + duration = MiscUtils.atoi(args[++i], duration); + } else if(args[i].equals("-anim")) { + useAnimator = true; + } + } + System.out.println("durationPerTest: "+duration); + org.junit.runner.JUnitCore.main(TestSWTBug643AsyncExec.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTEclipseGLCanvas01GLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTEclipseGLCanvas01GLn.java index f38d5c7dc..b0acbedc2 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTEclipseGLCanvas01GLn.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTEclipseGLCanvas01GLn.java @@ -52,7 +52,10 @@ import org.junit.Before; import org.junit.BeforeClass; import org.junit.After; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +import com.jogamp.nativewindow.swt.SWTAccessor; import com.jogamp.opengl.test.junit.jogl.demos.es1.OneTriangle; import com.jogamp.opengl.test.junit.util.UITestCase; @@ -63,6 +66,7 @@ import com.jogamp.opengl.test.junit.util.UITestCase; * </p> * @author Wade Walker, et.al. */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestSWTEclipseGLCanvas01GLn extends UITestCase { static int duration = 250; @@ -81,14 +85,17 @@ public class TestSWTEclipseGLCanvas01GLn extends UITestCase { @Before public void init() { - display = new Display(); - Assert.assertNotNull( display ); - shell = new Shell( display ); - Assert.assertNotNull( shell ); - shell.setLayout( new FillLayout() ); - composite = new Composite( shell, SWT.NONE ); - composite.setLayout( new FillLayout() ); - Assert.assertNotNull( composite ); + SWTAccessor.invoke(true, new Runnable() { + public void run() { + display = new Display(); + Assert.assertNotNull( display ); + shell = new Shell( display ); + Assert.assertNotNull( shell ); + shell.setLayout( new FillLayout() ); + composite = new Composite( shell, SWT.NONE ); + composite.setLayout( new FillLayout() ); + Assert.assertNotNull( composite ); + }}); } @After @@ -97,9 +104,12 @@ public class TestSWTEclipseGLCanvas01GLn extends UITestCase { Assert.assertNotNull( shell ); Assert.assertNotNull( composite ); try { - composite.dispose(); - shell.dispose(); - display.dispose(); + SWTAccessor.invoke(true, new Runnable() { + public void run() { + composite.dispose(); + shell.dispose(); + display.dispose(); + }}); } catch( Throwable throwable ) { throwable.printStackTrace(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLnAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java index 6abca288b..b38bf0c2c 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLnAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java @@ -3,14 +3,14 @@ * * 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 @@ -20,12 +20,12 @@ * 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.jogl.swt; import javax.media.opengl.GLAutoDrawable; @@ -46,25 +46,36 @@ import org.junit.Before; import org.junit.BeforeClass; import org.junit.After; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +import com.jogamp.nativewindow.swt.SWTAccessor; import com.jogamp.opengl.swt.GLCanvas; -import com.jogamp.opengl.test.junit.jogl.demos.es1.OneTriangle; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.MultisampleDemoES2; import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; /** * Tests that a basic SWT app can open without crashing under different GL profiles. - * <p> - * Uses JOGL's new SWT GLCanvas. + * <p> + * Uses JOGL's new SWT GLCanvas, + * which allows utilizing custom GLCapability settings, + * independent from the already instantiated SWT visual. * </p> * <p> - * Holds AWT in it's test name, since our impl. still needs the AWT threading, - * see {@link GLCanvas}. + * Note that {@link SWTAccessor#invoke(boolean, Runnable)} is still used to comply w/ + * SWT running on Mac OSX, i.e. to enforce UI action on the main thread. * </p> - * @author Wade Walker, et.al. + * @author Wade Walker, et al. */ -public class TestSWTJOGLGLCanvas01GLnAWT extends UITestCase { +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestSWTJOGLGLCanvas01GLn extends UITestCase { static int duration = 250; + static boolean doAnimation = true; static final int iwidth = 640; static final int iheight = 480; @@ -80,14 +91,20 @@ public class TestSWTJOGLGLCanvas01GLnAWT extends UITestCase { @Before public void init() { - display = new Display(); - Assert.assertNotNull( display ); - shell = new Shell( display ); - Assert.assertNotNull( shell ); - shell.setLayout( new FillLayout() ); - composite = new Composite( shell, SWT.NONE ); - composite.setLayout( new FillLayout() ); - Assert.assertNotNull( composite ); + SWTAccessor.invoke(true, new Runnable() { + public void run() { + display = new Display(); + Assert.assertNotNull( display ); + }}); + display.syncExec(new Runnable() { + public void run() { + shell = new Shell( display ); + Assert.assertNotNull( shell ); + shell.setLayout( new FillLayout() ); + composite = new Composite( shell, SWT.NO_BACKGROUND ); + composite.setLayout( new FillLayout() ); + Assert.assertNotNull( composite ); + }}); } @After @@ -96,9 +113,15 @@ public class TestSWTJOGLGLCanvas01GLnAWT extends UITestCase { Assert.assertNotNull( shell ); Assert.assertNotNull( composite ); try { - composite.dispose(); - shell.dispose(); - display.dispose(); + display.syncExec(new Runnable() { + public void run() { + composite.dispose(); + shell.dispose(); + }}); + SWTAccessor.invoke(true, new Runnable() { + public void run() { + display.dispose(); + }}); } catch( Throwable throwable ) { throwable.printStackTrace(); @@ -109,28 +132,37 @@ public class TestSWTJOGLGLCanvas01GLnAWT extends UITestCase { composite = null; } - protected void runTestAGL( GLProfile glprofile ) throws InterruptedException { - // need SWT.NO_BACKGROUND to prevent SWT from clearing the window - // at the wrong times (we use glClear for this instead) - final GLCapabilitiesImmutable caps = new GLCapabilities( glprofile ); - - final GLCanvas canvas = new GLCanvas( composite, SWT.NO_BACKGROUND, caps, null, null); + protected void runTestAGL( GLCapabilitiesImmutable caps, GLEventListener demo ) throws InterruptedException { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false); + + final GLCanvas canvas = GLCanvas.create( composite, 0, caps, null); Assert.assertNotNull( canvas ); + canvas.addGLEventListener( demo ); canvas.addGLEventListener(new GLEventListener() { + int displayCount = 0; public void init(final GLAutoDrawable drawable) { } - public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { - OneTriangle.setup( drawable.getGL().getGL2(), width, height ); - } + public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { } public void display(final GLAutoDrawable drawable) { - OneTriangle.render( drawable.getGL().getGL2(), drawable.getWidth(), drawable.getHeight()); + if(displayCount < 3) { + snapshot(displayCount++, null, drawable.getGL(), screenshot, TextureIO.PNG, null); + } } - public void dispose(final GLAutoDrawable drawable) {} + public void dispose(final GLAutoDrawable drawable) { } }); - - shell.setText( getClass().getName() ); - shell.setSize( 640, 480 ); - shell.open(); + + display.syncExec(new Runnable() { + public void run() { + shell.setText( getSimpleTestName(".") ); + shell.setSize( 640, 480 ); + shell.open(); + } } ); + + Animator anim = new Animator(); + if(doAnimation) { + anim.add(canvas); + anim.start(); + } long lStartTime = System.currentTimeMillis(); long lEndTime = lStartTime + duration; @@ -145,13 +177,26 @@ public class TestSWTJOGLGLCanvas01GLnAWT extends UITestCase { throwable.printStackTrace(); Assume.assumeNoException( throwable ); } - canvas.dispose(); + + anim.stop(); + + display.syncExec(new Runnable() { + public void run() { + canvas.dispose(); + } } ); } @Test public void test() throws InterruptedException { - GLProfile glprofile = GLProfile.getGL2ES1(); - runTestAGL( glprofile ); + runTestAGL( new GLCapabilities(GLProfile.getGL2ES2()), new GearsES2() ); + } + + @Test + public void test_MultisampleAndAlpha() throws InterruptedException { + GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES2()); + caps.setSampleBuffers(true); + caps.setNumSamples(2); + runTestAGL( caps, new MultisampleDemoES2(true) ); } static int atoi(String a) { @@ -166,9 +211,11 @@ public class TestSWTJOGLGLCanvas01GLnAWT extends UITestCase { for(int i=0; i<args.length; i++) { if(args[i].equals("-time")) { duration = atoi(args[++i]); + } else if(args[i].equals("-still")) { + doAnimation = false; } } System.out.println("durationPerTest: "+duration); - org.junit.runner.JUnitCore.main(TestSWTJOGLGLCanvas01GLnAWT.class.getName()); + org.junit.runner.JUnitCore.main(TestSWTJOGLGLCanvas01GLn.class.getName()); } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/OffscreenPrintable.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/OffscreenPrintable.java new file mode 100644 index 000000000..78fdde3ee --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/OffscreenPrintable.java @@ -0,0 +1,182 @@ +/** + * Copyright 2013 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.jogl.tile; + +import java.awt.Container; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; +import java.awt.print.PageFormat; +import java.awt.print.Paper; +import java.awt.print.Printable; +import java.awt.print.PrinterException; +import java.awt.print.PrinterJob; +import java.io.File; +import java.io.IOException; + +import javax.imageio.ImageIO; + +import com.jogamp.common.util.awt.AWTEDTExecutor; +import com.jogamp.nativewindow.awt.DirectDataBufferInt; +import com.jogamp.opengl.util.TileRenderer; + +/** + * {@link Printable} implementation using NIO {@link DirectDataBufferInt} {@link BufferedImage} + * for offscreen rendered printing. + * + * @see OnscreenPrintable + * @see PrintableBase + */ +public class OffscreenPrintable extends PrintableBase implements Printable { + + public final int imageType; + public final String pngFilename; + + /** + * + * @param job + * @param printContainer + * @param printDPI + * @param numSamples multisampling value: < 0 turns off, == 0 leaves as-is, > 0 enables using given num samples + * @param tileWidth custom tile width for {@link TileRenderer#setTileSize(int, int, int) tile renderer}, pass -1 for default. + * @param tileHeight custom tile height for {@link TileRenderer#setTileSize(int, int, int) tile renderer}, pass -1 for default. + * @param imageType AWT BufferedImage type (must be one of the integer types) + * @param pngFilename TODO + */ + public OffscreenPrintable(PrinterJob job, Container printContainer, int printDPI, int numSamples, int tileWidth, int tileHeight, int imageType, String pngFilename) { + super(job, printContainer, printDPI, numSamples, tileWidth, tileHeight); + this.imageType = imageType; + this.pngFilename = pngFilename; + } + + @Override + public int print(Graphics g, PageFormat pf, int page) throws PrinterException { + if (page > 0) { // We have only one page, and 'page' is zero-based + return NO_SUCH_PAGE; + } + + lockPrinting.lock(); + try { + final Paper paper = pf.getPaper(); + final double paperWWidthInch = paper.getWidth() / 72.0; + final double paperWHeightInch = paper.getHeight() / 72.0; + final double paperIWidthInch = paper.getImageableWidth() / 72.0; + final double paperIHeightInch = paper.getImageableHeight() / 72.0; + final double paperWWidthMM = paperWWidthInch * MM_PER_INCH; + final double paperWHeightMM = paperWHeightInch * MM_PER_INCH; + final double paperIWidthMM = paperIWidthInch * MM_PER_INCH; + final double paperIHeightMM = paperIHeightInch * MM_PER_INCH; + + final double pfWWidthInch = pf.getWidth() / 72.0; + final double pfWHeightInch = pf.getHeight() / 72.0; + final double pfIWidthInch = pf.getImageableWidth() / 72.0; + final double pfIHeightInch = pf.getImageableHeight() / 72.0; + final double pfWWidthMM = pfWWidthInch * MM_PER_INCH; + final double pfWHeightMM = pfWHeightInch * MM_PER_INCH; + final double pfIWidthMM = pfIWidthInch * MM_PER_INCH; + final double pfIHeightMM = pfIHeightInch * MM_PER_INCH; + + System.err.println("PF: Paper whole size "+ + Math.round(paperWWidthMM)+" x "+Math.round(paperWHeightMM)+" mm, "+ + Math.round(paperWWidthInch)+" x "+Math.round(paperWHeightInch)+" inch"); + + System.err.println("PF: Paper image size "+paper.getImageableX()+" / "+paper.getImageableY()+" "+ + Math.round(paperIWidthMM)+" x "+Math.round(paperIHeightMM)+" mm, "+ + Math.round(paperIWidthInch)+" x "+Math.round(paperIHeightInch)+" inch, "+ + Math.round(paper.getImageableWidth())+"x"+Math.round(paper.getImageableHeight())+" 72dpi dots"); + + System.err.println("PF: Page whole size "+ + Math.round(pfWWidthMM)+" x "+Math.round(pfWHeightMM)+" mm, "+ + Math.round(pfWWidthInch)+" x "+Math.round(pfWHeightInch)+" inch"); + + System.err.println("PF: Page image size "+pf.getImageableX()+" / "+pf.getImageableY()+" "+ + Math.round(pfIWidthMM)+" x "+Math.round(pfIHeightMM)+" mm, "+ + Math.round(pfIWidthInch)+" x "+Math.round(pfIHeightInch)+" inch, "+ + Math.round(pf.getImageableWidth())+"x"+Math.round(pf.getImageableHeight())+" 72dpi dots"); + + System.err.println("PF: Page orientation "+pf.getOrientation()); + + /** + * See: 'Scaling of Frame and GL content' in Class description! + * Note: Frame size contains the frame border (i.e. insets)! + */ + final Insets frameInsets = cont.getInsets(); + final int frameWidth = cont.getWidth(); + final int frameHeight= cont.getHeight(); + final double scaleGraphics = dpi / 72.0; + final int frameSWidth = (int) ( frameWidth * scaleGraphics ); + final int frameSHeight = (int) ( frameHeight * scaleGraphics ); + final double scaleComp72; + { + final double sx = pf.getImageableWidth() / (double)frameSWidth; + final double sy = pf.getImageableHeight() / (double)frameSHeight; + scaleComp72 = Math.min(sx, sy); + } + + System.err.println("PRINT.offscrn thread "+Thread.currentThread().getName()); + System.err.println("PRINT.offscrn DPI: scaleGraphics "+scaleGraphics+", scaleComp72 "+scaleComp72); + System.err.println("PRINT.offscrn DPI: frame: border "+frameInsets+", size "+frameWidth+"x"+frameHeight+ + " -> scaled "+frameSWidth+ "x" + frameSHeight); + + final BufferedImage image = DirectDataBufferInt.createBufferedImage(frameSWidth, frameSHeight, imageType, null /* location */, null /* properties */); + { + System.err.println("PRINT.offscrn image "+image); + final Graphics2D g2d = (Graphics2D) image.getGraphics(); + g2d.setClip(0, 0, frameSWidth, frameSHeight); + g2d.scale(scaleGraphics, scaleGraphics); + // g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + AWTEDTExecutor.singleton.invoke(true, new Runnable() { + public void run() { + cont.printAll(g2d); + } + }); + } + if( null != pngFilename ) { + final File fout = new File(pngFilename); + try { + ImageIO.write(image, "png", fout); + } catch (IOException e) { + e.printStackTrace(); + } + } + + final Graphics2D g2d = (Graphics2D)g; + g2d.translate(pf.getImageableX(), pf.getImageableY()); + g2d.scale(scaleComp72, scaleComp72); + g2d.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null); // Null ImageObserver since image data is ready. + + /* tell the caller that this page is part of the printed document */ + return PAGE_EXISTS; + } finally { + lockPrinting.unlock(); + } + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/OnscreenPrintable.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/OnscreenPrintable.java new file mode 100644 index 000000000..6f73ef2b4 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/OnscreenPrintable.java @@ -0,0 +1,165 @@ +/** + * Copyright 2013 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.jogl.tile; + +import java.awt.Container; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.RenderingHints; +import java.awt.print.PageFormat; +import java.awt.print.Paper; +import java.awt.print.Printable; +import java.awt.print.PrinterException; +import java.awt.print.PrinterJob; + +import com.jogamp.common.util.awt.AWTEDTExecutor; +import com.jogamp.opengl.util.TileRenderer; + +/** + * <h5>Scaling of Frame and GL content</h5> + * <p> + * We fit the frame into the imageable area with for 72 dpi, + * assuming that is the default AWT painting density. + * </p> + * <p> + * The frame borders are considered. + * </p> + * <p> + * The frame's scale factor is used for the graphics print matrix + * of the overall print-job, hence no frame resize is required. + * </p> + * <p> + * The GL scale factor 'scaleGLMatXY', 72dpi/glDPI, is passed to the GL object + * which locally scales the print matrix and renders the scene with 1/scaleGLMatXY pixels. + * </p> + */ +public class OnscreenPrintable extends PrintableBase implements Printable { + + /** + * + * @param job + * @param printContainer + * @param printDPI + * @param numSamples multisampling value: < 0 turns off, == 0 leaves as-is, > 0 enables using given num samples + * @param tileWidth custom tile width for {@link TileRenderer#setTileSize(int, int, int) tile renderer}, pass -1 for default. + * @param tileHeight custom tile height for {@link TileRenderer#setTileSize(int, int, int) tile renderer}, pass -1 for default. + */ + public OnscreenPrintable(PrinterJob job, Container printContainer, int printDPI, int numSamples, int tileWidth, int tileHeight) { + super(job, printContainer, printDPI, numSamples, tileWidth, tileHeight); + } + + + @Override + public int print(Graphics g, PageFormat pf, int page) throws PrinterException { + if (page > 0) { // We have only one page, and 'page' is zero-based + return NO_SUCH_PAGE; + } + + lockPrinting.lock(); + try { + final Paper paper = pf.getPaper(); + final double paperWWidthInch = paper.getWidth() / 72.0; + final double paperWHeightInch = paper.getHeight() / 72.0; + final double paperIWidthInch = paper.getImageableWidth() / 72.0; + final double paperIHeightInch = paper.getImageableHeight() / 72.0; + final double paperWWidthMM = paperWWidthInch * MM_PER_INCH; + final double paperWHeightMM = paperWHeightInch * MM_PER_INCH; + final double paperIWidthMM = paperIWidthInch * MM_PER_INCH; + final double paperIHeightMM = paperIHeightInch * MM_PER_INCH; + + final double pfWWidthInch = pf.getWidth() / 72.0; + final double pfWHeightInch = pf.getHeight() / 72.0; + final double pfIWidthInch = pf.getImageableWidth() / 72.0; + final double pfIHeightInch = pf.getImageableHeight() / 72.0; + final double pfWWidthMM = pfWWidthInch * MM_PER_INCH; + final double pfWHeightMM = pfWHeightInch * MM_PER_INCH; + final double pfIWidthMM = pfIWidthInch * MM_PER_INCH; + final double pfIHeightMM = pfIHeightInch * MM_PER_INCH; + + System.err.println("PF: Paper whole size "+ + Math.round(paperWWidthMM)+" x "+Math.round(paperWHeightMM)+" mm, "+ + Math.round(paperWWidthInch)+" x "+Math.round(paperWHeightInch)+" inch"); + + System.err.println("PF: Paper image size "+paper.getImageableX()+" / "+paper.getImageableY()+" "+ + Math.round(paperIWidthMM)+" x "+Math.round(paperIHeightMM)+" mm, "+ + Math.round(paperIWidthInch)+" x "+Math.round(paperIHeightInch)+" inch, "+ + Math.round(paper.getImageableWidth())+"x"+Math.round(paper.getImageableHeight())+" 72dpi dots"); + + System.err.println("PF: Page whole size "+ + Math.round(pfWWidthMM)+" x "+Math.round(pfWHeightMM)+" mm, "+ + Math.round(pfWWidthInch)+" x "+Math.round(pfWHeightInch)+" inch"); + + System.err.println("PF: Page image size "+pf.getImageableX()+" / "+pf.getImageableY()+" "+ + Math.round(pfIWidthMM)+" x "+Math.round(pfIHeightMM)+" mm, "+ + Math.round(pfIWidthInch)+" x "+Math.round(pfIHeightInch)+" inch, "+ + Math.round(pf.getImageableWidth())+"x"+Math.round(pf.getImageableHeight())+" 72dpi dots"); + + System.err.println("PF: Page orientation "+pf.getOrientation()); + + /** + * See: 'Scaling of Frame and GL content' in Class description! + * Note: Frame size contains the frame border (i.e. insets)! + */ + final Insets frameInsets = cont.getInsets(); + final int frameWidth = cont.getWidth(); + final int frameHeight= cont.getHeight(); + final double scaleGraphics = dpi / 72.0; + final int frameSWidth = (int) ( frameWidth * scaleGraphics ); + final int frameSHeight = (int) ( frameHeight * scaleGraphics ); + final double scaleComp72; + { + final double sx = pf.getImageableWidth() / (double)frameWidth; + final double sy = pf.getImageableHeight() / (double)frameHeight; + scaleComp72 = Math.min(sx, sy); + } + System.err.println("PRINT.onscrn thread "+Thread.currentThread().getName()); + System.err.println("PRINT.onscrn DPI: scaleGraphics "+scaleGraphics+", scaleComp72 "+scaleComp72); + System.err.println("PRINT.onscrn DPI: frame: border "+frameInsets+", size "+frameWidth+"x"+frameHeight+ + " -> scaled "+frameSWidth+ "x" + frameSHeight); + + final Graphics2D g2d = (Graphics2D)g; + System.err.println("PRINT at.pre: "+g2d.getTransform()); + g2d.translate(pf.getImageableX(), pf.getImageableY()); + g2d.scale(scaleComp72, scaleComp72); // WARNING: Produces rounding artifacts due to diff scale-factor of AWT/GL comps !!! + // g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + + AWTEDTExecutor.singleton.invoke(true, new Runnable() { + public void run() { + cont.printAll(g2d); + } + }); + + /* tell the caller that this page is part of the printed document */ + return PAGE_EXISTS; + } finally { + lockPrinting.unlock(); + } + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/PrintableBase.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/PrintableBase.java new file mode 100644 index 000000000..dd9de60c3 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/PrintableBase.java @@ -0,0 +1,88 @@ +/** + * Copyright 2013 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.jogl.tile; + +import java.awt.Container; +import java.awt.print.Printable; +import java.awt.print.PrinterJob; + +import com.jogamp.common.util.locks.LockFactory; +import com.jogamp.common.util.locks.RecursiveLock; +import com.jogamp.opengl.util.TileRenderer; + +/** + * Base {@link Printable} implementation class. + * + * <h5>Virtual printer driver</h5> + * <p> + * Note, on OSX you might need to setup a dummy printer, i.e. <i>print to file</i>.<br> + * As root: + * <pre> + cupsctl FileDevice=Yes + killall -HUP cupsd + mkdir /data/lp + chown USER /data/lp + chmod ugo+rwx /data/lp + lpadmin -p lprint -E -v file:/data/lp/out.ps -P /Library/Printers/PPDs/Contents/Resources/HP\ LaserJet\ 4\ Plus.gz + * </pre> + */ +public abstract class PrintableBase implements Printable { + + public static final double MM_PER_INCH = 25.4; + + public final PrinterJob job; + public final Container cont; + public final int dpi; + public final int numSamples; + public final int tileWidth, tileHeight; + protected final RecursiveLock lockPrinting = LockFactory.createRecursiveLock(); + + /** + * + * @param job + * @param printContainer + * @param printDPI + * @param numSamples multisampling value: < 0 turns off, == 0 leaves as-is, > 0 enables using given num samples + * @param tileWidth custom tile width for {@link TileRenderer#setTileSize(int, int, int) tile renderer}, pass -1 for default. + * @param tileHeight custom tile height for {@link TileRenderer#setTileSize(int, int, int) tile renderer}, pass -1 for default. + */ + public PrintableBase(PrinterJob job, Container printContainer, int printDPI, int numSamples, int tileWidth, int tileHeight) { + this.job = job; + this.cont = printContainer; + this.dpi = printDPI; + this.numSamples = numSamples; + this.tileWidth = tileWidth; + this.tileHeight = tileHeight; + } + + /** Wait for idle .. simply acquiring all locks and releasing them. */ + public void waitUntilIdle() { + lockPrinting.lock(); + lockPrinting.unlock(); + } +}
\ No newline at end of file diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering2GL2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering2GL2NEWT.java new file mode 100644 index 000000000..16c1b33f4 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering2GL2NEWT.java @@ -0,0 +1,193 @@ +/** + * Copyright 2013 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.jogl.tile; + +import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.GLPixelBuffer; +import com.jogamp.opengl.util.RandomTileRenderer; +import com.jogamp.opengl.util.TileRendererBase; +import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes; +import com.jogamp.opengl.util.texture.TextureData; +import com.jogamp.opengl.util.texture.TextureIO; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GL; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLOffscreenAutoDrawable; +import javax.media.opengl.GLRunnable; + +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +/** + * Demos offscreen {@link GLAutoDrawable} being used for + * {@link RandomTileRenderer} rendering to produce a PNG file. + * <p> + * {@link RandomTileRenderer} is being kicked off from the main thread. + * </p> + * <p> + * {@link RandomTileRenderer} buffer allocation is performed + * within the pre {@link GLEventListener} + * set via {@link TileRendererBase#setGLEventListener(GLEventListener, GLEventListener)} + * on the main thread. + * </p> + * <p> + * At tile rendering finish, the viewport and + * and the original {@link GLEventListener}'s PMV matrix as well. + * The latter is done by calling it's {@link GLEventListener#reshape(GLAutoDrawable, int, int, int, int) reshape} method. + * </p> +*/ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestRandomTiledRendering2GL2NEWT extends UITestCase { + static long duration = 500; // ms + + @Test + public void test01_aa0() throws IOException, InterruptedException, InvocationTargetException { + doTest(0); + } + @Test + public void test02_aa8() throws IOException, InterruptedException, InvocationTargetException { + doTest(8); + } + + void doTest(int msaaCount) throws IOException, InterruptedException, InvocationTargetException { + final GLCapabilities caps = new GLCapabilities(null); + caps.setDoubleBuffered(true); + if( msaaCount > 0 ) { + caps.setSampleBuffers(true); + caps.setNumSamples(msaaCount); + } + + final int maxTileSize = 64; + final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); + final GLOffscreenAutoDrawable glad = factory.createOffscreenAutoDrawable(null, caps, null, maxTileSize, maxTileSize); + + final Gears gears = new Gears(); + glad.addGLEventListener( gears ); + + // Fix the image size for now + final int imageWidth = 256 * 6; + final int imageHeight = 256 * 4; + + final String filename = this.getSnapshotFilename(0, "-tile", glad.getChosenGLCapabilities(), imageWidth, imageHeight, false, TextureIO.PNG, null); + final File file = new File(filename); + + // Initialize the tile rendering library + final RandomTileRenderer renderer = new RandomTileRenderer(); + renderer.attachAutoDrawable(glad); + renderer.setImageSize(imageWidth, imageHeight); + + final GLPixelBuffer.GLPixelBufferProvider pixelBufferProvider = GLPixelBuffer.defaultProviderWithRowStride; + final boolean[] flipVertically = { false }; + + final GLEventListener preTileGLEL = new GLEventListener() { + @Override + public void init(GLAutoDrawable drawable) { + final GL gl = drawable.getGL(); + GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, 3); + GLPixelBuffer pixelBuffer = pixelBufferProvider.allocate(gl, pixelAttribs, imageWidth, imageHeight, 1, true, 0); + renderer.setImageBuffer(pixelBuffer); + if( drawable.isGLOriented() ) { + flipVertically[0] = false; + } else { + flipVertically[0] = true; + } + } + @Override + public void dispose(GLAutoDrawable drawable) {} + @Override + public void display(GLAutoDrawable drawable) {} + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {} + }; + renderer.setGLEventListener(preTileGLEL, null); + + final int w = maxTileSize, h = maxTileSize; + int dx = 0, dy = 0; + while( dx+w <= imageWidth && dy+h <= imageHeight ) { + renderer.display(dx, dy, w, h); + dx+=w+w/2; + if( dx + w > imageWidth ) { + dx = 0; + dy+=h+h/2; + } + } + + renderer.detachAutoDrawable(); + + // Restore viewport and Gear's PMV matrix + // .. even though we close the demo, this is for documentation! + glad.invoke(true, new GLRunnable() { + @Override + public boolean run(GLAutoDrawable drawable) { + drawable.getGL().glViewport(0, 0, drawable.getWidth(), drawable.getHeight()); + gears.reshape(drawable, 0, 0, drawable.getWidth(), drawable.getHeight()); + return false; + } + }); + + glad.destroy(); + + final GLPixelBuffer imageBuffer = renderer.getImageBuffer(); + imageBuffer.clear(); // full size available + System.err.println("XXX2: "+imageBuffer); + final TextureData textureData = new TextureData( + caps.getGLProfile(), + 0 /* internalFormat */, + imageWidth, imageHeight, + 0, + imageBuffer.pixelAttributes, + false, false, + flipVertically[0], + imageBuffer.buffer, + null /* Flusher */); + System.err.println("XXX3: "+textureData.getPixelFormat()+", "+textureData.getPixelAttributes()); + + TextureIO.write(textureData, file); + } + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + try { + duration = Integer.parseInt(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } + } + org.junit.runner.JUnitCore.main(TestRandomTiledRendering2GL2NEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering3GL2AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering3GL2AWT.java new file mode 100644 index 000000000..7d3f1f622 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering3GL2AWT.java @@ -0,0 +1,261 @@ +/** + * Copyright 2013 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.jogl.tile; + +import com.jogamp.newt.event.TraceKeyAdapter; +import com.jogamp.newt.event.TraceWindowAdapter; +import com.jogamp.newt.event.awt.AWTKeyAdapter; +import com.jogamp.newt.event.awt.AWTWindowAdapter; +import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; +import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.GLPixelBuffer; +import com.jogamp.opengl.util.RandomTileRenderer; +import com.jogamp.opengl.util.TileRendererBase; +import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes; +import com.jogamp.opengl.util.texture.TextureData; +import com.jogamp.opengl.util.texture.TextureIO; + +import java.awt.Dimension; +import java.awt.Frame; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GL; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.awt.GLCanvas; + +import org.junit.Assert; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +/** + * Demos an onscreen AWT {@link GLCanvas} being used for + * {@link RandomTileRenderer} rendering to produce a PNG file. + * <p> + * {@link RandomTileRenderer} is being kicked off from the main thread. + * </p> + * <p> + * {@link RandomTileRenderer} setup and finishing is performed + * within the pre- and post {@link GLEventListener} + * set via {@link TileRendererBase#setGLEventListener(GLEventListener, GLEventListener)} + * on the animation thread. + * </p> + * <p> + * At tile rendering finish, the viewport and + * and the original {@link GLEventListener}'s PMV matrix as well. + * The latter is done by calling it's {@link GLEventListener#reshape(GLAutoDrawable, int, int, int, int) reshape} method. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestRandomTiledRendering3GL2AWT extends UITestCase { + static long duration = 3500; // ms + static int width = 512; + static int height = 512; + + @Test + public void test01_aa0() throws IOException, InterruptedException, InvocationTargetException { + doTest(0); + } + @Test + public void test02_aa8() throws IOException, InterruptedException, InvocationTargetException { + doTest(8); + } + + void doTest(int msaaCount) throws IOException, InterruptedException, InvocationTargetException { + final GLCapabilities caps = new GLCapabilities(null); + if( msaaCount > 0 ) { + caps.setSampleBuffers(true); + caps.setNumSamples(msaaCount); + } + + final Frame frame = new Frame("Gears AWT Test"); + Assert.assertNotNull(frame); + + final GLCanvas glad = new GLCanvas(caps); + Assert.assertNotNull(glad); + Dimension glc_sz = new Dimension(width, height); + glad.setMinimumSize(glc_sz); + glad.setPreferredSize(glc_sz); + glad.setSize(glc_sz); + frame.add(glad); + + final Gears gears = new Gears(); + glad.addGLEventListener( gears ); + + final Animator animator = new Animator(glad); + final QuitAdapter quitAdapter = new QuitAdapter(); + + new AWTKeyAdapter(new TraceKeyAdapter(quitAdapter)).addTo(glad); + new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter)).addTo(frame); + + // Fix the image size for now + final int maxTileSize = 64; + final int imageWidth = 256 * 6; + final int imageHeight = 256 * 4; + + // Initialize the tile rendering library + final RandomTileRenderer renderer = new RandomTileRenderer(); + renderer.setImageSize(imageWidth, imageHeight); + final GLPixelBuffer.GLPixelBufferProvider pixelBufferProvider = GLPixelBuffer.defaultProviderWithRowStride; + final boolean[] flipVertically = { false }; + final boolean[] rendererActive = { true }; + + final GLEventListener preTileGLEL = new GLEventListener() { + final int w = maxTileSize, h = maxTileSize; + int dx = 0, dy = 0; + + @Override + public void init(GLAutoDrawable drawable) { + final GL gl = drawable.getGL(); + GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, 3); + GLPixelBuffer pixelBuffer = pixelBufferProvider.allocate(gl, pixelAttribs, imageWidth, imageHeight, 1, true, 0); + renderer.setImageBuffer(pixelBuffer); + if( drawable.isGLOriented() ) { + flipVertically[0] = false; + } else { + flipVertically[0] = true; + } + System.err.println("XXX pre-init: "+renderer); + } + @Override + public void dispose(GLAutoDrawable drawable) {} + @Override + public void display(GLAutoDrawable drawable) { + if( dx+w <= imageWidth && dy+h <= imageHeight ) { + renderer.setTileRect(dx, dy, w, h); + dx+=w+w/2; + if( dx + w > imageWidth ) { + dx = 0; + dy+=h+h/2; + } + } else if( rendererActive[0] ) { + rendererActive[0] = false; + } + System.err.println("XXX pre-display: "+renderer); + } + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {} + }; + final GLEventListener postTileGLEL = new GLEventListener() { + @Override + public void init(GLAutoDrawable drawable) {} + @Override + public void dispose(GLAutoDrawable drawable) {} + @Override + public void display(GLAutoDrawable drawable) { + if( !rendererActive[0] ) { + final GLPixelBuffer imageBuffer = renderer.getImageBuffer(); + imageBuffer.clear(); // full size available + System.err.println("XXX !active -> save"); + System.err.println("XXX post-display: "+renderer); + final TextureData textureData = new TextureData( + caps.getGLProfile(), + 0 /* internalFormat */, + imageWidth, imageHeight, + 0, + imageBuffer.pixelAttributes, + false, false, + flipVertically[0], + imageBuffer.buffer, + null /* Flusher */); + try { + final String filename = getSnapshotFilename(0, "-tile", glad.getChosenGLCapabilities(), imageWidth, imageHeight, false, TextureIO.PNG, null); + final File file = new File(filename); + TextureIO.write(textureData, file); + } catch (IOException e) { + e.printStackTrace(); + } + renderer.detachAutoDrawable(); + System.err.println("XXX post-display detached: "+renderer); + drawable.getGL().glViewport(0, 0, drawable.getWidth(), drawable.getHeight()); + glad.getGLEventListener(0).reshape(drawable, 0, 0, drawable.getWidth(), drawable.getHeight()); + } + } + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {} + }; + renderer.setGLEventListener(preTileGLEL, postTileGLEL); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.pack(); + frame.setVisible(true); + }}); + animator.setUpdateFPSFrames(60, System.err); + animator.start(); + + boolean signalTileRenderer = true; + + while(!quitAdapter.shouldQuit() && animator.isAnimating() && + ( rendererActive[0] || animator.getTotalFPSDuration()<duration ) ) + { + if( signalTileRenderer && animator.getTotalFPSDuration() > 90 ) { + signalTileRenderer = false; + // tile rendering ! + System.err.println("XXX START TILE RENDERING"); + renderer.attachAutoDrawable(glad); + } + Thread.sleep(100); + } + + Assert.assertNotNull(frame); + Assert.assertNotNull(glad); + Assert.assertNotNull(animator); + + animator.stop(); + Assert.assertEquals(false, animator.isAnimating()); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + }}); + Assert.assertEquals(false, frame.isVisible()); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.remove(glad); + frame.dispose(); + }}); + } + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + try { + duration = Integer.parseInt(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } + } + org.junit.runner.JUnitCore.main(TestRandomTiledRendering3GL2AWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsAWT.java new file mode 100644 index 000000000..30e0ba4e6 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsAWT.java @@ -0,0 +1,279 @@ +/** + * Copyright 2013 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.jogl.tile; + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.Label; +import java.awt.Panel; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.image.BufferedImage; +import java.awt.print.PageFormat; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.event.TraceKeyAdapter; +import com.jogamp.newt.event.TraceWindowAdapter; +import com.jogamp.newt.event.awt.AWTKeyAdapter; +import com.jogamp.newt.event.awt.AWTWindowAdapter; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; +import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.util.Animator; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestTiledPrintingGearsAWT extends TiledPrintingAWTBase { + + static boolean waitForKey = false; + /** only when run manually .. */ + static boolean allow600dpi = false; + static GLProfile glp; + static int width, height; + + @BeforeClass + public static void initClass() { + if(GLProfile.isAvailable(GLProfile.GL2)) { + glp = GLProfile.get(GLProfile.GL2); + Assert.assertNotNull(glp); + width = 640; + height = 480; + } else { + setTestSupported(false); + } + // Runtime.getRuntime().traceInstructions(true); + // Runtime.getRuntime().traceMethodCalls(true); + } + + @AfterClass + public static void releaseClass() { + } + + protected void runTestGL(GLCapabilities caps) throws InterruptedException, InvocationTargetException { + final Dimension glc_sz = new Dimension(width/2, height); + final GLCanvas glCanvas1 = new GLCanvas(caps); + Assert.assertNotNull(glCanvas1); + glCanvas1.setMinimumSize(glc_sz); + glCanvas1.setPreferredSize(glc_sz); + glCanvas1.setSize(glc_sz); + glCanvas1.addGLEventListener(new Gears()); + + final GLCanvas glCanvas2 = new GLCanvas(caps); + Assert.assertNotNull(glCanvas2); + glCanvas2.setMinimumSize(glc_sz); + glCanvas2.setPreferredSize(glc_sz); + glCanvas2.setSize(glc_sz); + glCanvas2.addGLEventListener(new RedSquareES2()); + + final Panel demoPanel = new Panel(); + demoPanel.add(glCanvas1); + demoPanel.add(glCanvas2); + + final Frame frame = new Frame("AWT Print"); + Assert.assertNotNull(frame); + + final ActionListener print72DPIAction = new ActionListener() { + public void actionPerformed(ActionEvent e) { + doPrintManual(frame, 72, 0, -1, -1); + } }; + final ActionListener print300DPIAction = new ActionListener() { + public void actionPerformed(ActionEvent e) { + doPrintManual(frame, 300, -1, -1, -1); + } }; + final ActionListener print600DPIAction = new ActionListener() { + public void actionPerformed(ActionEvent e) { + doPrintManual(frame, 600, -1, -1, -1); + } }; + final Button print72DPIButton = new Button("72dpi"); + print72DPIButton.addActionListener(print72DPIAction); + final Button print300DPIButton = new Button("300dpi"); + print300DPIButton.addActionListener(print300DPIAction); + final Button print600DPIButton = new Button("600dpi"); + print600DPIButton.addActionListener(print600DPIAction); + + frame.setLayout(new BorderLayout()); + Panel printPanel = new Panel(); + printPanel.add(print72DPIButton); + printPanel.add(print300DPIButton); + printPanel.add(print600DPIButton); + Panel southPanel = new Panel(); + southPanel.add(new Label("South")); + Panel eastPanel = new Panel(); + eastPanel.add(new Label("East")); + Panel westPanel = new Panel(); + westPanel.add(new Label("West")); + frame.add(printPanel, BorderLayout.NORTH); + frame.add(demoPanel, BorderLayout.CENTER); + frame.add(southPanel, BorderLayout.SOUTH); + frame.add(eastPanel, BorderLayout.EAST); + frame.add(westPanel, BorderLayout.WEST); + frame.setTitle("Tiles AWT Print Test"); + + Animator animator = new Animator(); + animator.add(glCanvas1); + animator.add(glCanvas2); + QuitAdapter quitAdapter = new QuitAdapter(); + + new AWTKeyAdapter(new TraceKeyAdapter(quitAdapter)).addTo(glCanvas1); + new AWTKeyAdapter(new TraceKeyAdapter(quitAdapter)).addTo(glCanvas2); + new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter)).addTo(frame); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.pack(); + frame.setVisible(true); + }}); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas1, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas2, true)); + + animator.setUpdateFPSFrames(60, System.err); + animator.start(); + + boolean printDone = false; + while(!quitAdapter.shouldQuit() && animator.isAnimating() && ( 0 == duration || animator.getTotalFPSDuration()<duration )) { + Thread.sleep(200); + if( !printDone ) { + printDone = true; + { + final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 72, 0, -1, -1, false /* resizeWithinPrint */); + waitUntilPrintJobsIdle(p); + } + { + final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 72, 8, -1, -1, false /* resizeWithinPrint */); + waitUntilPrintJobsIdle(p); + } + { + // No AA needed for 150 dpi and greater :) + final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 150, -1, -1, -1, false /* resizeWithinPrint */); + waitUntilPrintJobsIdle(p); + } + { + // No AA needed for 150 dpi and greater :) + final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 150, -1, 2048, 2048, false /* resizeWithinPrint */); + waitUntilPrintJobsIdle(p); + } + { + // No AA needed for 150 dpi and greater :) + final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 150, -1, -1, -1, true /* resizeWithinPrint */); + waitUntilPrintJobsIdle(p); + } + { + // No AA needed for 150 dpi and greater :) + final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, BufferedImage.TYPE_INT_ARGB_PRE /* offscreen-type */, 150, -1, -1, -1, false /* resizeWithinPrint */); + waitUntilPrintJobsIdle(p); + } + { + // No AA needed for 150 dpi and greater :) + final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, BufferedImage.TYPE_INT_ARGB_PRE /* offscreen-type */, 150, -1, -1, -1, true/* resizeWithinPrint */); + waitUntilPrintJobsIdle(p); + } + if( allow600dpi ) { + // No AA needed for 300 dpi and greater :) + final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 600, -1, -1, -1, false /* resizeWithinPrint */); + waitUntilPrintJobsIdle(p); + } + } + } + + Assert.assertNotNull(frame); + Assert.assertNotNull(glCanvas1); + Assert.assertNotNull(glCanvas2); + Assert.assertNotNull(animator); + + animator.stop(); + Assert.assertEquals(false, animator.isAnimating()); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + }}); + Assert.assertEquals(false, frame.isVisible()); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + final Frame _frame = frame; + _frame.remove(demoPanel); + _frame.dispose(); + }}); + } + + @Test + public void test01_aa0() throws InterruptedException, InvocationTargetException { + GLCapabilities caps = new GLCapabilities(glp); + runTestGL(caps); + } + + @Test + public void test02_aa8() throws InterruptedException, InvocationTargetException { + GLCapabilities caps = new GLCapabilities(glp); + caps.setSampleBuffers(true); + caps.setNumSamples(8); + runTestGL(caps); + } + + static long duration = 500; // ms + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + try { + duration = Integer.parseInt(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } else if(args[i].equals("-600dpi")) { + allow600dpi = true; + } else if(args[i].equals("-wait")) { + waitForKey = true; + } + } + 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(TestTiledPrintingGearsAWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsNewtAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsNewtAWT.java new file mode 100644 index 000000000..ec1d7b1d6 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsNewtAWT.java @@ -0,0 +1,286 @@ +/** + * Copyright 2013 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.jogl.tile; + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.Label; +import java.awt.Panel; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.image.BufferedImage; +import java.awt.print.PageFormat; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.lang.reflect.InvocationTargetException; + +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.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.awt.NewtCanvasAWT; +import com.jogamp.newt.event.TraceKeyAdapter; +import com.jogamp.newt.event.TraceWindowAdapter; +import com.jogamp.newt.event.awt.AWTKeyAdapter; +import com.jogamp.newt.event.awt.AWTWindowAdapter; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; +import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.util.Animator; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestTiledPrintingGearsNewtAWT extends TiledPrintingAWTBase { + + static boolean waitForKey = false; + /** only when run manually .. */ + static boolean allow600dpi = false; + static GLProfile glp; + static int width, height; + + @BeforeClass + public static void initClass() { + if(GLProfile.isAvailable(GLProfile.GL2)) { + glp = GLProfile.get(GLProfile.GL2); + Assert.assertNotNull(glp); + width = 640; + height = 480; + } else { + setTestSupported(false); + } + // Runtime.getRuntime().traceInstructions(true); + // Runtime.getRuntime().traceMethodCalls(true); + } + + @AfterClass + public static void releaseClass() { + } + + protected void runTestGL(GLCapabilities caps) throws InterruptedException, InvocationTargetException { + final Dimension glc_sz = new Dimension(width/2, height); + final GLWindow glad1 = GLWindow.create(caps); + Assert.assertNotNull(glad1); + final NewtCanvasAWT canvas1 = new NewtCanvasAWT(glad1); + Assert.assertNotNull(canvas1); + canvas1.setMinimumSize(glc_sz); + canvas1.setPreferredSize(glc_sz); + canvas1.setSize(glc_sz); + glad1.addGLEventListener(new Gears()); + + final GLWindow glad2 = GLWindow.create(caps); + Assert.assertNotNull(glad2); + final NewtCanvasAWT canvas2 = new NewtCanvasAWT(glad2); + Assert.assertNotNull(canvas2); + canvas2.setMinimumSize(glc_sz); + canvas2.setPreferredSize(glc_sz); + canvas2.setSize(glc_sz); + glad2.addGLEventListener(new RedSquareES2()); + + final Panel demoPanel = new Panel(); + demoPanel.add(canvas1); + demoPanel.add(canvas2); + + final Frame frame = new Frame("Newt/AWT Print"); + Assert.assertNotNull(frame); + + final ActionListener print72DPIAction = new ActionListener() { + public void actionPerformed(ActionEvent e) { + doPrintManual(frame, 72, 0, -1, -1); + } }; + final ActionListener print300DPIAction = new ActionListener() { + public void actionPerformed(ActionEvent e) { + doPrintManual(frame, 300, -1, -1, -1); + } }; + final ActionListener print600DPIAction = new ActionListener() { + public void actionPerformed(ActionEvent e) { + doPrintManual(frame, 600, -1, -1, -1); + } }; + final Button print72DPIButton = new Button("72dpi"); + print72DPIButton.addActionListener(print72DPIAction); + final Button print300DPIButton = new Button("300dpi"); + print300DPIButton.addActionListener(print300DPIAction); + final Button print600DPIButton = new Button("600dpi"); + print600DPIButton.addActionListener(print600DPIAction); + + frame.setLayout(new BorderLayout()); + Panel printPanel = new Panel(); + printPanel.add(print72DPIButton); + printPanel.add(print300DPIButton); + printPanel.add(print600DPIButton); + Panel southPanel = new Panel(); + southPanel.add(new Label("South")); + Panel eastPanel = new Panel(); + eastPanel.add(new Label("East")); + Panel westPanel = new Panel(); + westPanel.add(new Label("West")); + frame.add(printPanel, BorderLayout.NORTH); + frame.add(demoPanel, BorderLayout.CENTER); + frame.add(southPanel, BorderLayout.SOUTH); + frame.add(eastPanel, BorderLayout.EAST); + frame.add(westPanel, BorderLayout.WEST); + frame.setTitle("Tiles Newt/AWT Print Test"); + + Animator animator = new Animator(); + animator.add(glad1); + animator.add(glad2); + QuitAdapter quitAdapter = new QuitAdapter(); + + new AWTKeyAdapter(new TraceKeyAdapter(quitAdapter)).addTo(canvas1); + new AWTKeyAdapter(new TraceKeyAdapter(quitAdapter)).addTo(canvas2); + new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter)).addTo(frame); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.pack(); + frame.setVisible(true); + }}); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(canvas1, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(canvas2, true)); + + animator.setUpdateFPSFrames(60, System.err); + animator.start(); + + boolean printDone = false; + while(!quitAdapter.shouldQuit() && animator.isAnimating() && ( 0 == duration || animator.getTotalFPSDuration()<duration )) { + Thread.sleep(200); + if( !printDone ) { + printDone = true; + { + final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 72, 0, -1, -1, false /* resizeWithinPrint */); + waitUntilPrintJobsIdle(p); + } + { + final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 72, 8, -1, -1, false /* resizeWithinPrint */); + waitUntilPrintJobsIdle(p); + } + { + // No AA needed for 150 dpi and greater :) + final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 150, -1, -1, -1, false /* resizeWithinPrint */); + waitUntilPrintJobsIdle(p); + } + { + // No AA needed for 150 dpi and greater :) + final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 150, -1, 2048, 2048, false /* resizeWithinPrint */); + waitUntilPrintJobsIdle(p); + } + { + // No AA needed for 150 dpi and greater :) + final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 150, -1, -1, -1, true /* resizeWithinPrint */); + waitUntilPrintJobsIdle(p); + } + { + // No AA needed for 150 dpi and greater :) + final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, BufferedImage.TYPE_INT_ARGB_PRE /* offscreen-type */, 150, -1, -1, -1, false /* resizeWithinPrint */); + waitUntilPrintJobsIdle(p); + } + { + // No AA needed for 150 dpi and greater :) + final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, BufferedImage.TYPE_INT_ARGB_PRE /* offscreen-type */, 150, -1, -1, -1, true /* resizeWithinPrint */); + waitUntilPrintJobsIdle(p); + } + if( allow600dpi ) { + // No AA needed for 300 dpi and greater :) + final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 600, -1, -1, -1, false /* resizeWithinPrint */); + waitUntilPrintJobsIdle(p); + } + } + } + + Assert.assertNotNull(frame); + Assert.assertNotNull(canvas1); + Assert.assertNotNull(canvas2); + Assert.assertNotNull(animator); + + animator.stop(); + Assert.assertEquals(false, animator.isAnimating()); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + }}); + Assert.assertEquals(false, frame.isVisible()); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + final Frame _frame = frame; + _frame.remove(demoPanel); + _frame.dispose(); + }}); + glad1.destroy(); + glad2.destroy(); + } + + @Test + public void test01_aa0() throws InterruptedException, InvocationTargetException { + GLCapabilities caps = new GLCapabilities(glp); + runTestGL(caps); + } + + @Test + public void test02_aa8() throws InterruptedException, InvocationTargetException { + GLCapabilities caps = new GLCapabilities(glp); + caps.setSampleBuffers(true); + caps.setNumSamples(8); + runTestGL(caps); + } + + static long duration = 500; // ms + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + try { + duration = Integer.parseInt(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } else if(args[i].equals("-600dpi")) { + allow600dpi = true; + } else if(args[i].equals("-wait")) { + waitForKey = true; + } + } + 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(TestTiledPrintingGearsNewtAWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsSwingAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsSwingAWT.java new file mode 100644 index 000000000..3dd3a83c8 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsSwingAWT.java @@ -0,0 +1,412 @@ +/** + * Copyright 2013 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.jogl.tile; + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.Label; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.image.BufferedImage; +import java.awt.print.PageFormat; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLJPanel; +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JLayeredPane; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import com.jogamp.common.os.Platform; +import com.jogamp.newt.event.TraceKeyAdapter; +import com.jogamp.newt.event.TraceWindowAdapter; +import com.jogamp.newt.event.awt.AWTKeyAdapter; +import com.jogamp.newt.event.awt.AWTWindowAdapter; +import com.jogamp.opengl.test.junit.jogl.demos.es1.RedSquareES1; +import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.util.Animator; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestTiledPrintingGearsSwingAWT extends TiledPrintingAWTBase { + + static boolean waitForKey = false; + /** only when run manually .. */ + static boolean allow600dpi = false; + static GLProfile glp; + static int width, height; + + @BeforeClass + public static void initClass() { + if(GLProfile.isAvailable(GLProfile.GL2)) { + glp = GLProfile.get(GLProfile.GL2); + Assert.assertNotNull(glp); + width = 640; + height = 480; + } else { + setTestSupported(false); + } + // Runtime.getRuntime().traceInstructions(true); + // Runtime.getRuntime().traceMethodCalls(true); + } + + @AfterClass + public static void releaseClass() { + } + + protected void runTestGL(GLCapabilities caps, boolean layered, boolean skipGLOrientationVerticalFlip) throws InterruptedException, InvocationTargetException { + final int layerStepX = width/6, layerStepY = height/6; + final Dimension glc_sz = new Dimension(layered ? width - 2*layerStepX : width/2, layered ? height - 2*layerStepY : height); + final GLJPanel glJPanel1 = new GLJPanel(caps); + Assert.assertNotNull(glJPanel1); + glJPanel1.setSkipGLOrientationVerticalFlip(skipGLOrientationVerticalFlip); + glJPanel1.setMinimumSize(glc_sz); + glJPanel1.setPreferredSize(glc_sz); + if( layered ) { + glJPanel1.setBounds(layerStepX/2, layerStepY/2, glc_sz.width, glc_sz.height); + } else { + glJPanel1.setBounds(0, 0, glc_sz.width, glc_sz.height); + } + { + final Gears demo = new Gears(); + demo.setFlipVerticalInGLOrientation(skipGLOrientationVerticalFlip); + glJPanel1.addGLEventListener(demo); + } + + final GLJPanel glJPanel2 = new GLJPanel(caps); + Assert.assertNotNull(glJPanel2); + glJPanel2.setSkipGLOrientationVerticalFlip(skipGLOrientationVerticalFlip); + glJPanel2.setMinimumSize(glc_sz); + glJPanel2.setPreferredSize(glc_sz); + if( layered ) { + glJPanel2.setBounds(3*layerStepY, 2*layerStepY, glc_sz.width, glc_sz.height); + } else { + glJPanel2.setBounds(0, 0, glc_sz.width, glc_sz.height); + } + { + final RedSquareES1 demo = new RedSquareES1(); + demo.setFlipVerticalInGLOrientation(skipGLOrientationVerticalFlip); + glJPanel2.addGLEventListener(demo); + } + + final JComponent demoPanel; + if( layered ) { + glJPanel1.setOpaque(true); + glJPanel2.setOpaque(false); + final Dimension lsz = new Dimension(width, height); + demoPanel = new JLayeredPane(); + demoPanel.setMinimumSize(lsz); + demoPanel.setPreferredSize(lsz); + demoPanel.setBounds(0, 0, lsz.width, lsz.height); + demoPanel.setBorder(BorderFactory.createTitledBorder("Layered Pane")); + demoPanel.add(glJPanel1, JLayeredPane.DEFAULT_LAYER); + demoPanel.add(glJPanel2, Integer.valueOf(1)); + final JButton tb = new JButton("On Top"); + tb.setBounds(4*layerStepY, 3*layerStepY, 100, 50); + demoPanel.add(tb, Integer.valueOf(2)); + } else { + demoPanel = new JPanel(); + demoPanel.add(glJPanel1); + demoPanel.add(glJPanel2); + } + + final JFrame frame = new JFrame("Swing Print"); + Assert.assertNotNull(frame); + + final ActionListener print72DPIAction = new ActionListener() { + public void actionPerformed(ActionEvent e) { + doPrintManual(frame, 72, 0, -1, -1); + } }; + final ActionListener print300DPIAction = new ActionListener() { + public void actionPerformed(ActionEvent e) { + doPrintManual(frame, 300, -1, -1, -1); + } }; + final ActionListener print600DPIAction = new ActionListener() { + public void actionPerformed(ActionEvent e) { + doPrintManual(frame, 600, -1, -1, -1); + } }; + final Button print72DPIButton = new Button("72dpi"); + print72DPIButton.addActionListener(print72DPIAction); + final Button print300DPIButton = new Button("300dpi"); + print300DPIButton.addActionListener(print300DPIAction); + final Button print600DPIButton = new Button("600dpi"); + print600DPIButton.addActionListener(print600DPIAction); + + final JPanel printPanel = new JPanel(); + printPanel.add(print72DPIButton); + printPanel.add(print300DPIButton); + printPanel.add(print600DPIButton); + final JPanel southPanel = new JPanel(); + southPanel.add(new Label("South")); + final JPanel eastPanel = new JPanel(); + eastPanel.add(new Label("East")); + final JPanel westPanel = new JPanel(); + westPanel.add(new Label("West")); + + Animator animator = new Animator(); + animator.add(glJPanel1); + animator.add(glJPanel2); + QuitAdapter quitAdapter = new QuitAdapter(); + + new AWTKeyAdapter(new TraceKeyAdapter(quitAdapter)).addTo(glJPanel1); + new AWTKeyAdapter(new TraceKeyAdapter(quitAdapter)).addTo(glJPanel2); + new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter)).addTo(frame); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + final Container fcont = frame.getContentPane(); + fcont.setLayout(new BorderLayout()); + fcont.add(printPanel, BorderLayout.NORTH); + fcont.add(demoPanel, BorderLayout.CENTER); + fcont.add(southPanel, BorderLayout.SOUTH); + fcont.add(eastPanel, BorderLayout.EAST); + fcont.add(westPanel, BorderLayout.WEST); + fcont.validate(); + frame.pack(); + frame.setVisible(true); + } } ) ; + + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glJPanel1, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glJPanel2, true)); + + animator.setUpdateFPSFrames(60, System.err); + animator.start(); + Assert.assertEquals(true, animator.isAnimating()); + + boolean printDone = false; + while(!quitAdapter.shouldQuit() && animator.isAnimating() && ( 0 == duration || animator.getTotalFPSDuration()<duration )) { + Thread.sleep(200); + if( !printDone ) { + printDone = true; + { + final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 72, 0, -1, -1, false /* resizeWithinPrint */); + waitUntilPrintJobsIdle(p); + } + { + final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 72, 8, -1, -1, false /* resizeWithinPrint */); + waitUntilPrintJobsIdle(p); + } + { + // No AA needed for 150 dpi and greater :) + final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 150, -1, -1, -1, false /* resizeWithinPrint */); + waitUntilPrintJobsIdle(p); + } + { + // No AA needed for 150 dpi and greater :) + final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 150, -1, 2048, 2048, false /* resizeWithinPrint */); + waitUntilPrintJobsIdle(p); + } + { + // No AA needed for 150 dpi and greater :) + final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 150, -1, -1, -1, true /* resizeWithinPrint */); + waitUntilPrintJobsIdle(p); + } + { + // No AA needed for 150 dpi and greater :) + final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, BufferedImage.TYPE_INT_ARGB_PRE /* offscreen-type */, 150, -1, -1, -1, false /* resizeWithinPrint */); + waitUntilPrintJobsIdle(p); + } + { + // No AA needed for 150 dpi and greater :) + final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, BufferedImage.TYPE_INT_ARGB /* offscreen-type */, 150, -1, -1, -1, false /* resizeWithinPrint */); + waitUntilPrintJobsIdle(p); + } + { + // No AA needed for 150 dpi and greater :) + final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, BufferedImage.TYPE_INT_RGB /* offscreen-type */, 150, -1, -1, -1, false /* resizeWithinPrint */); + waitUntilPrintJobsIdle(p); + } + { + // No AA needed for 150 dpi and greater :) + final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, BufferedImage.TYPE_INT_BGR /* offscreen-type */, 150, -1, -1, -1, false /* resizeWithinPrint */); + waitUntilPrintJobsIdle(p); + } + { + // No AA needed for 150 dpi and greater :) + final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, BufferedImage.TYPE_INT_ARGB_PRE /* offscreen-type */, 150, -1, -1, -1, true /* resizeWithinPrint */); + waitUntilPrintJobsIdle(p); + } + if( allow600dpi ) { + // No AA needed for 300 dpi and greater :) + final PrintableBase p = doPrintAuto(frame, PageFormat.LANDSCAPE, null, -1 /* offscreen-type */, 600, -1, -1, -1, false /* resizeWithinPrint */); + waitUntilPrintJobsIdle(p); + } + } + } + + Assert.assertNotNull(frame); + Assert.assertNotNull(glJPanel1); + Assert.assertNotNull(glJPanel2); + Assert.assertNotNull(animator); + + animator.stop(); + Assert.assertEquals(false, animator.isAnimating()); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + }}); + Assert.assertEquals(false, frame.isVisible()); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + final Frame _frame = frame; + _frame.remove(demoPanel); + _frame.dispose(); + }}); + } + + @Test + public void test01_flip1_aa0() throws InterruptedException, InvocationTargetException { + GLCapabilities caps = new GLCapabilities(glp); + runTestGL(caps, false, false); + } + + @Test + public void test01_flip1_aa0_layered() throws InterruptedException, InvocationTargetException { + GLCapabilities caps = new GLCapabilities(glp); + caps.setAlphaBits(8); + runTestGL(caps, true, false); + } + + @Test + public void test01_flip1_aa0_bitmap() throws InterruptedException, InvocationTargetException { + if( Platform.OSType.WINDOWS == Platform.getOSType() ) { + GLCapabilities caps = new GLCapabilities(glp); + caps.setBitmap(true); + runTestGL(caps, false, false); + } // issues w/ AMD catalyst driver and pixmap surface .. + } + + @Test + public void test01_flip1_aa0_bitmap_layered() throws InterruptedException, InvocationTargetException { + if( Platform.OSType.WINDOWS == Platform.getOSType() ) { + GLCapabilities caps = new GLCapabilities(glp); + caps.setBitmap(true); + caps.setAlphaBits(8); + runTestGL(caps, true, false); + } // issues w/ AMD catalyst driver and pixmap surface .. + } + + @Test + public void test02_flip1_aa8() throws InterruptedException, InvocationTargetException { + GLCapabilities caps = new GLCapabilities(glp); + caps.setSampleBuffers(true); + caps.setNumSamples(8); + runTestGL(caps, false, false); + } + + @Test + public void test11_flip0_aa0() throws InterruptedException, InvocationTargetException { + GLCapabilities caps = new GLCapabilities(glp); + runTestGL(caps, false, true); + } + + @Test + public void test11_flip0_aa0_layered() throws InterruptedException, InvocationTargetException { + GLCapabilities caps = new GLCapabilities(glp); + caps.setAlphaBits(8); + runTestGL(caps, true, true); + } + + @Test + public void test11_flip0_aa0_bitmap() throws InterruptedException, InvocationTargetException { + if( Platform.OSType.WINDOWS == Platform.getOSType() ) { + GLCapabilities caps = new GLCapabilities(glp); + caps.setBitmap(true); + runTestGL(caps, false, true); + } // issues w/ AMD catalyst driver and pixmap surface .. + } + + @Test + public void test11_flip0_aa0_bitmap_layered() throws InterruptedException, InvocationTargetException { + if( Platform.OSType.WINDOWS == Platform.getOSType() ) { + GLCapabilities caps = new GLCapabilities(glp); + caps.setBitmap(true); + caps.setAlphaBits(8); + runTestGL(caps, true, true); + } // issues w/ AMD catalyst driver and pixmap surface .. + } + + @Test + public void test12_flip0_aa8() throws InterruptedException, InvocationTargetException { + GLCapabilities caps = new GLCapabilities(glp); + caps.setSampleBuffers(true); + caps.setNumSamples(8); + runTestGL(caps, false, true); + } + + static long duration = 500; // ms + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-width")) { + i++; + width = MiscUtils.atoi(args[i], width); + } else if(args[i].equals("-height")) { + i++; + height = MiscUtils.atoi(args[i], height); + } else if(args[i].equals("-600dpi")) { + allow600dpi = true; + } else if(args[i].equals("-wait")) { + waitForKey = true; + } + } + 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(TestTiledPrintingGearsSwingAWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsSwingAWT2.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsSwingAWT2.java new file mode 100644 index 000000000..29bf8a6c3 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsSwingAWT2.java @@ -0,0 +1,409 @@ +/** + * Copyright 2013 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.jogl.tile; + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.Label; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.print.PageFormat; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLJPanel; +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JLayeredPane; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import com.jogamp.common.os.Platform; +import com.jogamp.newt.event.TraceKeyAdapter; +import com.jogamp.newt.event.TraceWindowAdapter; +import com.jogamp.newt.event.awt.AWTKeyAdapter; +import com.jogamp.newt.event.awt.AWTWindowAdapter; +import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.util.Animator; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestTiledPrintingGearsSwingAWT2 extends TiledPrintingAWTBase { + + static boolean waitForKey = false; + static GLProfile glp; + static int width, height; + + @BeforeClass + public static void initClass() { + if(GLProfile.isAvailable(GLProfile.GL2)) { + glp = GLProfile.get(GLProfile.GL2); + Assert.assertNotNull(glp); + width = 560; // 640; + height = 420; // 480; + } else { + setTestSupported(false); + } + // Runtime.getRuntime().traceInstructions(true); + // Runtime.getRuntime().traceMethodCalls(true); + } + + @AfterClass + public static void releaseClass() { + } + + protected void runTestGL(GLCapabilities caps, final boolean addLayout, boolean layered, boolean skipGLOrientationVerticalFlip, boolean useAnim) throws InterruptedException, InvocationTargetException { + final Dimension glc_sz = new Dimension(width, height); + final GLJPanel glJPanel1 = new GLJPanel(caps); + Assert.assertNotNull(glJPanel1); + glJPanel1.setSkipGLOrientationVerticalFlip(skipGLOrientationVerticalFlip); + glJPanel1.setMinimumSize(glc_sz); + glJPanel1.setPreferredSize(glc_sz); + glJPanel1.setBounds(0, 0, glc_sz.width, glc_sz.height); + { + final Gears demo = new Gears(); + demo.setFlipVerticalInGLOrientation(skipGLOrientationVerticalFlip); + glJPanel1.addGLEventListener(demo); + } + + final JComponent tPanel, demoPanel; + if( layered ) { + glJPanel1.setOpaque(true); + final JButton tb = new JButton("On Top"); + tb.setBounds(width/2, height/2, 200, 50); + if( addLayout ) { + tPanel = null; + final Dimension lsz = new Dimension(width, height); + demoPanel = new JLayeredPane(); + demoPanel.setMinimumSize(lsz); + demoPanel.setPreferredSize(lsz); + demoPanel.setBounds(0, 0, lsz.width, lsz.height); + demoPanel.setBorder(BorderFactory.createTitledBorder("Layered Pane")); + demoPanel.add(glJPanel1, JLayeredPane.DEFAULT_LAYER); + demoPanel.add(tb, Integer.valueOf(2)); + } else { + tPanel = new TransparentPanel(); + tPanel.setBounds(0, 0, width, height); + tPanel.setLayout(null); + tPanel.add(tb); + demoPanel = glJPanel1; + } + } else { + tPanel = null; + if( addLayout ) { + demoPanel = new JPanel(); + demoPanel.add(glJPanel1); + } else { + demoPanel = glJPanel1; + } + } + + final JFrame frame = new JFrame("Swing Print"); + Assert.assertNotNull(frame); + + final ActionListener print72DPIAction = new ActionListener() { + public void actionPerformed(ActionEvent e) { + doPrintManual(frame, 72, 0, -1, -1); + } }; + final ActionListener print150DPIAction = new ActionListener() { + public void actionPerformed(ActionEvent e) { + doPrintManual(frame, 150, -1, -1, -1); + } }; + final ActionListener print300DPIAction = new ActionListener() { + public void actionPerformed(ActionEvent e) { + doPrintManual(frame, 300, -1, -1, -1); + } }; + final Button print72DPIButton = new Button("72dpi"); + print72DPIButton.addActionListener(print72DPIAction); + final Button print150DPIButton = new Button("150dpi"); + print150DPIButton.addActionListener(print150DPIAction); + final Button print300DPIButton = new Button("300dpi"); + print300DPIButton.addActionListener(print300DPIAction); + + final JPanel printPanel = new JPanel(); + printPanel.add(print72DPIButton); + printPanel.add(print150DPIButton); + printPanel.add(print300DPIButton); + final JPanel southPanel = new JPanel(); + southPanel.add(new Label("South")); + final JPanel eastPanel = new JPanel(); + eastPanel.add(new Label("East")); + final JPanel westPanel = new JPanel(); + westPanel.add(new Label("West")); + + final Animator animator = useAnim ? new Animator() : null; + if( null != animator ) { + animator.add(glJPanel1); + } + QuitAdapter quitAdapter = new QuitAdapter(); + + new AWTKeyAdapter(new TraceKeyAdapter(quitAdapter)).addTo(glJPanel1); + new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter)).addTo(frame); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + final Container fcont = frame.getContentPane(); + if( addLayout ) { + fcont.setLayout(new BorderLayout()); + fcont.add(printPanel, BorderLayout.NORTH); + fcont.add(demoPanel, BorderLayout.CENTER); + fcont.add(southPanel, BorderLayout.SOUTH); + fcont.add(eastPanel, BorderLayout.EAST); + fcont.add(westPanel, BorderLayout.WEST); + fcont.validate(); + frame.pack(); + } else { + frame.setSize(glc_sz); + fcont.setLayout(null); + if( null != tPanel ) { + fcont.add(tPanel); + } + fcont.add(demoPanel); + } + frame.setVisible(true); + } } ) ; + + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glJPanel1, true)); + + if( null != animator ) { + animator.setUpdateFPSFrames(60, System.err); + animator.start(); + Assert.assertEquals(true, animator.isAnimating()); + } + + final long t0 = System.currentTimeMillis(); + long t1 = t0; + boolean printDone = false; + while( !quitAdapter.shouldQuit() && ( 0 == duration || ( t1 - t0 ) < duration ) ) { + Thread.sleep(200); + if( !printDone ) { + printDone = true; + { + // No AA needed for 150 dpi and greater :) + final PrintableBase p = doPrintAuto(frame, PageFormat.PORTRAIT, null, -1 /* offscreen-type */, 150, -1, -1, -1, false); + waitUntilPrintJobsIdle(p); + } + } + t1 = System.currentTimeMillis(); + } + + Assert.assertNotNull(frame); + Assert.assertNotNull(glJPanel1); + + if( null != animator ) { + animator.stop(); + Assert.assertEquals(false, animator.isAnimating()); + } + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + }}); + Assert.assertEquals(false, frame.isVisible()); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + final Frame _frame = frame; + _frame.remove(demoPanel); + _frame.dispose(); + }}); + } + + @Test + public void test001_flip1_norm_layout0_layered0() throws InterruptedException, InvocationTargetException { + GLCapabilities caps = new GLCapabilities(glp); + runTestGL(caps, false /* addLayout */, false /* layered */, false /* skipGLOrientationVerticalFlip */, false /* useAnim */); + } + + @Test + public void test002_flip1_norm_layout1_layered0() throws InterruptedException, InvocationTargetException { + GLCapabilities caps = new GLCapabilities(glp); + runTestGL(caps, true /* addLayout */, false /* layered */, false /* skipGLOrientationVerticalFlip */, false /* useAnim */); + } + + @Test + public void test003_flip1_norm_layout0_layered1() throws InterruptedException, InvocationTargetException { + GLCapabilities caps = new GLCapabilities(glp); + runTestGL(caps, false /* addLayout */, true /* layered */, false /* skipGLOrientationVerticalFlip */, false /* useAnim */); + } + + @Test + public void test004_flip1_norm_layout1_layered1() throws InterruptedException, InvocationTargetException { + GLCapabilities caps = new GLCapabilities(glp); + runTestGL(caps, true /* addLayout */, true /* layered */, false /* skipGLOrientationVerticalFlip */, false /* useAnim */); + } + + @Test + public void test011_flip1_bitm_layout0_layered0() throws InterruptedException, InvocationTargetException { + if( Platform.OSType.WINDOWS != Platform.getOSType() ) { + return; + } + GLCapabilities caps = new GLCapabilities(glp); + caps.setBitmap(true); + runTestGL(caps, false /* addLayout */, false /* layered */, false /* skipGLOrientationVerticalFlip */, false /* useAnim */); + } + + @Test + public void test012_flip1_bitm_layout1_layered0() throws InterruptedException, InvocationTargetException { + if( Platform.OSType.WINDOWS != Platform.getOSType() ) { + return; + } + GLCapabilities caps = new GLCapabilities(glp); + caps.setBitmap(true); + runTestGL(caps, true /* addLayout */, false /* layered */, false /* skipGLOrientationVerticalFlip */, false /* useAnim */); + } + + @Test + public void test013_flip1_bitm_layout0_layered1() throws InterruptedException, InvocationTargetException { + if( Platform.OSType.WINDOWS != Platform.getOSType() ) { + return; + } + GLCapabilities caps = new GLCapabilities(glp); + caps.setBitmap(true); + runTestGL(caps, false /* addLayout */, true /* layered */, false /* skipGLOrientationVerticalFlip */, false /* useAnim */); + } + + @Test + public void test014_flip1_bitm_layout1_layered1() throws InterruptedException, InvocationTargetException { + if( Platform.OSType.WINDOWS != Platform.getOSType() ) { + return; + } + GLCapabilities caps = new GLCapabilities(glp); + caps.setBitmap(true); + runTestGL(caps, true /* addLayout */, true /* layered */, false /* skipGLOrientationVerticalFlip */, false /* useAnim */); + } + + @Test + public void test101_flip1_norm_layout0_layered0() throws InterruptedException, InvocationTargetException { + GLCapabilities caps = new GLCapabilities(glp); + runTestGL(caps, false /* addLayout */, false /* layered */, true /* skipGLOrientationVerticalFlip */, false /* useAnim */); + } + + @Test + public void test102_flip1_norm_layout1_layered0() throws InterruptedException, InvocationTargetException { + GLCapabilities caps = new GLCapabilities(glp); + runTestGL(caps, true /* addLayout */, false /* layered */, true /* skipGLOrientationVerticalFlip */, false /* useAnim */); + } + + @Test + public void test103_flip1_norm_layout0_layered1() throws InterruptedException, InvocationTargetException { + GLCapabilities caps = new GLCapabilities(glp); + runTestGL(caps, false /* addLayout */, true /* layered */, true /* skipGLOrientationVerticalFlip */, false /* useAnim */); + } + + @Test + public void test104_flip1_norm_layout1_layered1() throws InterruptedException, InvocationTargetException { + GLCapabilities caps = new GLCapabilities(glp); + runTestGL(caps, true /* addLayout */, true /* layered */, true /* skipGLOrientationVerticalFlip */, false /* useAnim */); + } + + @Test + public void test111_flip1_bitm_layout0_layered0() throws InterruptedException, InvocationTargetException { + if( Platform.OSType.WINDOWS != Platform.getOSType() ) { + return; + } + GLCapabilities caps = new GLCapabilities(glp); + caps.setBitmap(true); + runTestGL(caps, false /* addLayout */, false /* layered */, true /* skipGLOrientationVerticalFlip */, false /* useAnim */); + } + + @Test + public void test112_flip1_bitm_layout1_layered0() throws InterruptedException, InvocationTargetException { + if( Platform.OSType.WINDOWS != Platform.getOSType() ) { + return; + } + GLCapabilities caps = new GLCapabilities(glp); + caps.setBitmap(true); + runTestGL(caps, true /* addLayout */, false /* layered */, true /* skipGLOrientationVerticalFlip */, false /* useAnim */); + } + + @Test + public void test113_flip1_bitm_layout0_layered1() throws InterruptedException, InvocationTargetException { + if( Platform.OSType.WINDOWS != Platform.getOSType() ) { + return; + } + GLCapabilities caps = new GLCapabilities(glp); + caps.setBitmap(true); + runTestGL(caps, false /* addLayout */, true /* layered */, true /* skipGLOrientationVerticalFlip */, false /* useAnim */); + } + + @Test + public void test114_flip1_bitm_layout1_layered1() throws InterruptedException, InvocationTargetException { + if( Platform.OSType.WINDOWS != Platform.getOSType() ) { + return; + } + GLCapabilities caps = new GLCapabilities(glp); + caps.setBitmap(true); + runTestGL(caps, true /* addLayout */, true /* layered */, true /* skipGLOrientationVerticalFlip */, false /* useAnim */); + } + + static long duration = 500; // ms + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-width")) { + i++; + width = MiscUtils.atoi(args[i], width); + } else if(args[i].equals("-height")) { + i++; + height = MiscUtils.atoi(args[i], height); + } else if(args[i].equals("-wait")) { + waitForKey = true; + } + } + 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(TestTiledPrintingGearsSwingAWT2.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingNIOImageSwingAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingNIOImageSwingAWT.java new file mode 100644 index 000000000..b51bfae87 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingNIOImageSwingAWT.java @@ -0,0 +1,320 @@ +/** + * Copyright 2013 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.jogl.tile; + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.Label; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.lang.reflect.InvocationTargetException; + +import javax.imageio.ImageIO; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLJPanel; +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JLayeredPane; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import com.jogamp.common.util.awt.AWTEDTExecutor; +import com.jogamp.nativewindow.awt.AWTPrintLifecycle; +import com.jogamp.nativewindow.awt.DirectDataBufferInt; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; +import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.texture.TextureIO; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestTiledPrintingNIOImageSwingAWT extends UITestCase { + + static boolean waitForKey = false; + /** only when run manually .. */ + static boolean allow600dpi = false; + static GLProfile glp; + static int width, height; + + @BeforeClass + public static void initClass() { + if(GLProfile.isAvailable(GLProfile.GL2)) { + glp = GLProfile.get(GLProfile.GL2); + Assert.assertNotNull(glp); + width = 640; + height = 480; + } else { + setTestSupported(false); + } + // Runtime.getRuntime().traceInstructions(true); + // Runtime.getRuntime().traceMethodCalls(true); + } + + @AfterClass + public static void releaseClass() { + } + + protected void printOffscreenToFile(final BufferedImage image, final Frame frame, final GLCapabilities caps, final int num, final String detail) { + final Insets frameInsets = frame.getInsets(); + final int frameWidth = frame.getWidth(); + final int frameHeight= frame.getHeight(); + final int imageWidth = image.getWidth(); + final int imageHeight= image.getHeight(); + final double scaleComp72; + // Note: Frame size contains the frame border (i.e. insets)! + { + final double sx = (double)imageWidth / frameWidth; + final double sy = (double)imageHeight / frameHeight; + scaleComp72 = Math.min(sx, sy); + } + System.err.println("PRINT DPI: scaleComp72 "+scaleComp72+", image-size "+imageWidth+"x"+imageHeight+", frame[border "+frameInsets+", size "+frameWidth+"x"+frameHeight+"]"); + + System.err.println("XXX: image "+image); + System.err.println("XXX: cm "+image.getColorModel()); + System.err.println("XXX: raster "+image.getRaster()); + System.err.println("XXX: dataBuffer "+image.getRaster().getDataBuffer()); + + AWTEDTExecutor.singleton.invoke(true, new Runnable() { + public void run() { + final Graphics2D g2d = (Graphics2D) image.getGraphics(); + g2d.setClip(0, 0, image.getWidth(), image.getHeight()); + g2d.scale(scaleComp72, scaleComp72); + // g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + + // frame.paintAll(g2d); + final AWTPrintLifecycle.Context ctx = AWTPrintLifecycle.Context.setupPrint(frame, 1.0/scaleComp72, 1.0/scaleComp72, 0, -1, -1); + try { + frame.printAll(g2d); + } finally { + ctx.releasePrint(); + } + // to file + final String fname = getSnapshotFilename(num, detail, caps, image.getWidth(), image.getHeight(), false, TextureIO.PNG, null); + System.err.println("XXX file "+fname); + final File fout = new File(fname); + try { + ImageIO.write(image, "png", fout); + } catch (IOException e) { + e.printStackTrace(); + } + } }); + } + + protected void runTestGL(final GLCapabilities caps, final boolean layered) throws InterruptedException, InvocationTargetException { + final int layerStepX = width/6, layerStepY = height/6; + final Dimension glc_sz = new Dimension(layered ? width - 2*layerStepX : width/2, layered ? height - 2*layerStepY : height); + final GLJPanel glJPanel1 = new GLJPanel(caps); + Assert.assertNotNull(glJPanel1); + glJPanel1.setMinimumSize(glc_sz); + glJPanel1.setPreferredSize(glc_sz); + if( layered ) { + glJPanel1.setBounds(layerStepX/2, layerStepY/2, glc_sz.width, glc_sz.height); + } else { + glJPanel1.setBounds(0, 0, glc_sz.width, glc_sz.height); + } + glJPanel1.addGLEventListener(new Gears()); + + final GLJPanel glJPanel2 = new GLJPanel(caps); + Assert.assertNotNull(glJPanel2); + glJPanel2.setMinimumSize(glc_sz); + glJPanel2.setPreferredSize(glc_sz); + if( layered ) { + glJPanel2.setBounds(3*layerStepY, 2*layerStepY, glc_sz.width, glc_sz.height); + } else { + glJPanel2.setBounds(0, 0, glc_sz.width, glc_sz.height); + } + glJPanel2.addGLEventListener(new RedSquareES2()); + // glJPanel2.addGLEventListener(new Gears()); + + final JComponent demoPanel; + if( layered ) { + glJPanel1.setOpaque(true); + glJPanel2.setOpaque(false); + final Dimension lsz = new Dimension(width, height); + demoPanel = new JLayeredPane(); + demoPanel.setMinimumSize(lsz); + demoPanel.setPreferredSize(lsz); + demoPanel.setBounds(0, 0, lsz.width, lsz.height); + demoPanel.setBorder(BorderFactory.createTitledBorder("Layered Pane")); + demoPanel.add(glJPanel1, JLayeredPane.DEFAULT_LAYER); + demoPanel.add(glJPanel2, Integer.valueOf(1)); + final JButton tb = new JButton("On Top"); + tb.setBounds(4*layerStepY, 3*layerStepY, 100, 50); + demoPanel.add(tb, Integer.valueOf(2)); + } else { + demoPanel = new JPanel(); + demoPanel.add(glJPanel1); + demoPanel.add(glJPanel2); + } + + final JFrame frame = new JFrame("Swing Print"); + Assert.assertNotNull(frame); + + final Button print72DPIButton = new Button("72dpi"); // dummy + final Button print300DPIButton = new Button("300dpi"); // dummy + final Button print600DPIButton = new Button("600dpi"); // dummy + + final JPanel printPanel = new JPanel(); + printPanel.add(print72DPIButton); + printPanel.add(print300DPIButton); + printPanel.add(print600DPIButton); + final JPanel southPanel = new JPanel(); + southPanel.add(new Label("South")); + final JPanel eastPanel = new JPanel(); + eastPanel.add(new Label("East")); + final JPanel westPanel = new JPanel(); + westPanel.add(new Label("West")); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + final Container fcont = frame.getContentPane(); + fcont.setLayout(new BorderLayout()); + fcont.add(printPanel, BorderLayout.NORTH); + fcont.add(demoPanel, BorderLayout.CENTER); + fcont.add(southPanel, BorderLayout.SOUTH); + fcont.add(eastPanel, BorderLayout.EAST); + fcont.add(westPanel, BorderLayout.WEST); + fcont.validate(); + frame.pack(); + frame.setVisible(true); + } } ) ; + + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glJPanel1, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glJPanel2, true)); + + // paint offscreen: array 72dpi ARGB + { + final BufferedImage image = new BufferedImage(frame.getWidth(), frame.getHeight(), BufferedImage.TYPE_INT_ARGB); + printOffscreenToFile(image, frame, caps, 0, "array_072dpi_argb"); + } + // paint offscreen: NIO 72dpi ARGB + { + final BufferedImage image = DirectDataBufferInt.createBufferedImage(frame.getWidth(), frame.getHeight(), BufferedImage.TYPE_INT_ARGB, null /* location */, null /* properties */); + printOffscreenToFile(image, frame, caps, 1, "newio_072dpi_argb"); + } + // paint offscreen: NIO 150dpi ARGB + { + final int scale = (int) ( 150.0 / 72.0 + 0.5 ); + final BufferedImage image = DirectDataBufferInt.createBufferedImage(frame.getWidth()*scale, frame.getHeight()*scale, BufferedImage.TYPE_INT_ARGB, null /* location */, null /* properties */); + printOffscreenToFile(image, frame, caps, 2, "newio_150dpi_argb"); + } + // paint offscreen: NIO 150dpi ARGB_PRE + { + final int scale = (int) ( 150.0 / 72.0 + 0.5 ); + final BufferedImage image = DirectDataBufferInt.createBufferedImage(frame.getWidth()*scale, frame.getHeight()*scale, BufferedImage.TYPE_INT_ARGB_PRE, null /* location */, null /* properties */); + printOffscreenToFile(image, frame, caps, 2, "newio_150dpi_argbp"); + } + // paint offscreen: NIO 150dpi RGB + { + final int scale = (int) ( 150.0 / 72.0 + 0.5 ); + final BufferedImage image = DirectDataBufferInt.createBufferedImage(frame.getWidth()*scale, frame.getHeight()*scale, BufferedImage.TYPE_INT_RGB, null /* location */, null /* properties */); + printOffscreenToFile(image, frame, caps, 2, "newio_150dpi_rgb"); + } + // paint offscreen: NIO 150dpi BGR + { + final int scale = (int) ( 150.0 / 72.0 + 0.5 ); + final BufferedImage image = DirectDataBufferInt.createBufferedImage(frame.getWidth()*scale, frame.getHeight()*scale, BufferedImage.TYPE_INT_BGR, null /* location */, null /* properties */); + printOffscreenToFile(image, frame, caps, 2, "newio_150dpi_bgr"); + } + + Assert.assertNotNull(frame); + Assert.assertNotNull(glJPanel1); + Assert.assertNotNull(glJPanel2); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + }}); + Assert.assertEquals(false, frame.isVisible()); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + final Frame _frame = frame; + _frame.remove(demoPanel); + _frame.dispose(); + }}); + } + + @Test + public void test01_Offscreen_aa0() throws InterruptedException, InvocationTargetException { + GLCapabilities caps = new GLCapabilities(glp); + runTestGL(caps, false); + } + + @Test + public void test01_Offscreen_aa0_layered() throws InterruptedException, InvocationTargetException { + GLCapabilities caps = new GLCapabilities(glp); + runTestGL(caps, true); + } + + static long duration = 500; // ms + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + try { + duration = Integer.parseInt(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } else if(args[i].equals("-600dpi")) { + allow600dpi = true; + } else if(args[i].equals("-wait")) { + waitForKey = true; + } + } + 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(TestTiledPrintingNIOImageSwingAWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering1GL2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering1GL2NEWT.java new file mode 100644 index 000000000..e0fabc3cc --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering1GL2NEWT.java @@ -0,0 +1,243 @@ +/** + * Copyright 2013 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.jogl.tile; + +import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.GLPixelBuffer; +import com.jogamp.opengl.util.TileRenderer; +import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes; +import com.jogamp.opengl.util.TileRendererBase; +import com.jogamp.opengl.util.texture.TextureData; +import com.jogamp.opengl.util.texture.TextureIO; + +import java.io.File; +import java.io.IOException; + +import javax.media.opengl.GL2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +/** + * Demos offscreen {@link GLDrawable} being used for + * {@link TileRenderer} rendering to produce a PNG file. + * <p> + * All {@link TileRenderer} operations are + * being performed from the main thread sequentially + * without {@link GLAutoDrawable} or {@link GLEventListener}. + * </p> +*/ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestTiledRendering1GL2NEWT extends UITestCase { + static long duration = 500; // ms + + static class DrawableContext { + DrawableContext(GLDrawable d, GLContext glc) { + this.d = d; + this.glc = glc; + } + GLDrawable d; + GLContext glc; + } + + private static DrawableContext createDrawableAndCurrentCtx(GLCapabilities glCaps, int width, int height) { + GLDrawableFactory factory = GLDrawableFactory.getFactory(glCaps.getGLProfile()); + GLDrawable d = factory.createOffscreenDrawable(null, glCaps, null, width, height); + d.setRealized(true); + GLContext glc = null; + glc = d.createContext(null); + Assert.assertTrue("Context could not be made current", GLContext.CONTEXT_NOT_CURRENT < glc.makeCurrent()); + return new DrawableContext(d, glc); + } + + private static void destroyDrawableContext(DrawableContext dc) { + if(null != dc.glc) { + dc.glc.destroy(); + dc.glc = null; + } + if(null != dc.d) { + dc.d.setRealized(false); + dc.d = null; + } + } + + @Test + public void test01() throws IOException { + GLProfile glp = GLProfile.getMaxFixedFunc(true); + GLCapabilities caps = new GLCapabilities(glp); + caps.setOnscreen(false); + + final int maxTileSize = 256; + DrawableContext dc = createDrawableAndCurrentCtx(caps, maxTileSize, maxTileSize); + final GL2 gl = dc.glc.getGL().getGL2(); + + // Fix the image size for now + final int imageWidth = dc.d.getWidth() * 6; + final int imageHeight = dc.d.getHeight() * 4; + + final String filename = this.getSnapshotFilename(0, "-tile", dc.d.getChosenGLCapabilities(), imageWidth, imageHeight, false, TextureIO.PNG, null); + final File file = new File(filename); + + // Initialize the tile rendering library + final TileRenderer renderer = new com.jogamp.opengl.util.TileRenderer(); + renderer.setTileSize(dc.d.getWidth(), dc.d.getHeight(), 0); + renderer.setImageSize(imageWidth, imageHeight); + + final GLPixelBuffer.GLPixelBufferProvider pixelBufferProvider = GLPixelBuffer.defaultProviderWithRowStride; + final boolean[] flipVertically = { false }; + + GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, 3); + GLPixelBuffer pixelBuffer = pixelBufferProvider.allocate(gl, pixelAttribs, imageWidth, imageHeight, 1, true, 0); + renderer.setImageBuffer(pixelBuffer); + flipVertically[0] = false; + + final Gears gears = new Gears(); + gears.setVerbose(false); + gears.init(gl); + + gears.addTileRendererNotify(renderer); + while( !renderer.eot() ) { + renderer.beginTile(gl); + gears.reshape(gl, + renderer.getParam(TileRendererBase.TR_CURRENT_TILE_X_POS), renderer.getParam(TileRendererBase.TR_CURRENT_TILE_Y_POS), + renderer.getParam(TileRendererBase.TR_CURRENT_TILE_WIDTH), renderer.getParam(TileRendererBase.TR_CURRENT_TILE_HEIGHT), + renderer.getParam(TileRendererBase.TR_IMAGE_WIDTH), renderer.getParam(TileRendererBase.TR_IMAGE_HEIGHT)); + gears.display(gl); + renderer.endTile(gl); + } + gears.removeTileRendererNotify(renderer); + + destroyDrawableContext(dc); + + final GLPixelBuffer imageBuffer = renderer.getImageBuffer(); + final TextureData textureData = new TextureData( + caps.getGLProfile(), + 0 /* internalFormat */, + imageWidth, imageHeight, + 0, + imageBuffer.pixelAttributes, + false, false, + flipVertically[0], + imageBuffer.buffer, + null /* Flusher */); + + TextureIO.write(textureData, file); + } + + @Test + public void test02_EOT_01() throws IOException { + GLProfile glp = GLProfile.getMaxFixedFunc(true); + GLCapabilities caps = new GLCapabilities(glp); + caps.setOnscreen(false); + + final int maxTileSize = 256; + DrawableContext dc = createDrawableAndCurrentCtx(caps, maxTileSize, maxTileSize); + final GL2 gl = dc.glc.getGL().getGL2(); + + // Fix the image size for now + final int imageWidth = dc.d.getWidth() * 6; + final int imageHeight = dc.d.getHeight() * 4; + + // Initialize the tile rendering library + final TileRenderer renderer = new com.jogamp.opengl.util.TileRenderer(); + renderer.setTileSize(dc.d.getWidth(), dc.d.getHeight(), 0); + + IllegalStateException ise = null; + try { + renderer.beginTile(gl); // Image size has not been set + } catch (IllegalStateException _ise) { + ise = _ise; + System.err.println("Expected "+ise.getClass().getSimpleName()+": "+ise.getMessage()); + } + Assert.assertNotNull("TileRenderer.beginTile: Image-size exception missing", ise); + + renderer.setImageSize(imageWidth, imageHeight); + + renderer.clipImageSize(0, 0); + try { + renderer.beginTile(gl); // EOT reached (1) + } catch (IllegalStateException _ise) { + ise = _ise; + System.err.println("Expected "+ise.getClass().getSimpleName()+": "+ise.getMessage()); + } + Assert.assertNotNull("TileRenderer.beginTile: EOT (1) exception missing", ise); + + renderer.clipImageSize(imageWidth, imageHeight); // back to full size + + final Gears gears = new Gears(); + gears.setVerbose(false); + gears.init(gl); + + gears.addTileRendererNotify(renderer); + int numTiles = 0; + while( !renderer.eot() ) { + renderer.beginTile(gl); + gears.reshape(gl, + renderer.getParam(TileRendererBase.TR_CURRENT_TILE_X_POS), renderer.getParam(TileRendererBase.TR_CURRENT_TILE_Y_POS), + renderer.getParam(TileRendererBase.TR_CURRENT_TILE_WIDTH), renderer.getParam(TileRendererBase.TR_CURRENT_TILE_HEIGHT), + renderer.getParam(TileRendererBase.TR_IMAGE_WIDTH), renderer.getParam(TileRendererBase.TR_IMAGE_HEIGHT)); + gears.display(gl); + renderer.endTile(gl); + numTiles++; + } + try { + renderer.beginTile(gl); // EOT reached (2) + } catch (IllegalStateException _ise) { + ise = _ise; + System.err.println("Expected "+ise.getClass().getSimpleName()+": "+ise.getMessage()); + } + Assert.assertNotNull("TileRenderer.beginTile: EOT (2) exception missing", ise); + gears.removeTileRendererNotify(renderer); + + Assert.assertTrue("TileRenderer not rendered more than one tile but "+numTiles, numTiles > 1); + + destroyDrawableContext(dc); + } + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + try { + duration = Integer.parseInt(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } + } + org.junit.runner.JUnitCore.main(TestTiledRendering1GL2NEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering2NEWT.java new file mode 100644 index 000000000..2220c1fb3 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering2NEWT.java @@ -0,0 +1,263 @@ +/** + * Copyright 2013 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.jogl.tile; + +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.GLPixelBuffer; +import com.jogamp.opengl.util.TileRenderer; +import com.jogamp.opengl.util.TileRendererBase; +import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes; +import com.jogamp.opengl.util.texture.TextureData; +import com.jogamp.opengl.util.texture.TextureIO; + +import java.io.File; +import java.io.IOException; +import javax.media.opengl.GL; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; +import javax.media.opengl.GLRunnable; + +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +/** + * Demos offscreen {@link GLAutoDrawable} being used for + * {@link TileRenderer} rendering to produce a PNG file. + * <p> + * {@link TileRenderer} is being kicked off from the main thread. + * </p> + * <p> + * {@link TileRenderer} buffer allocation is performed + * within the pre {@link GLEventListener} + * set via {@link TileRendererBase#setGLEventListener(GLEventListener, GLEventListener)} + * on the main thread. + * </p> + * <p> + * At tile rendering finish, the viewport and + * and the original {@link GLEventListener}'s PMV matrix as well. + * The latter is done by calling it's {@link GLEventListener#reshape(GLAutoDrawable, int, int, int, int) reshape} method. + * </p> +*/ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestTiledRendering2NEWT extends UITestCase { + static long duration = 500; // ms + + static GLProfile getGLProfile(String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return GLProfile.get(profile); + } + static GLProfile getGL2ES3() { + final GLProfile glp = GLProfile.getMaxProgrammableCore(true); + if( null == glp || !glp.isGL2ES3() ) { + System.err.println("GL2ES3 n/a, has max-core "+glp); + return null; + } + return glp; + } + + @Test + public void test001_off_gl2___aa0() throws IOException { + GLProfile glp = getGLProfile(GLProfile.GL2); + if( null == glp ) { + return; + } + doTest(false, new Gears(), glp, 0); + } + @Test + public void test002_off_gl2___aa8() throws IOException { + GLProfile glp = getGLProfile(GLProfile.GL2); + if( null == glp ) { + return; + } + doTest(false, new Gears(), glp, 8); + } + @Test + public void test011_off_gl2es3_aa0() throws IOException { + GLProfile glp = getGL2ES3(); + if( null == glp ) { + return; + } + doTest(false, new GearsES2(), glp, 0); + } + @Test + public void test012_off_gl2es3_aa8() throws IOException { + GLProfile glp = getGL2ES3(); + if( null == glp ) { + return; + } + doTest(false, new GearsES2(), glp, 8); + } + @Test + public void test101_on__gl2___aa0() throws IOException { + GLProfile glp = getGLProfile(GLProfile.GL2); + if( null == glp ) { + return; + } + doTest(true, new Gears(), glp, 0); + } + @Test + public void test102_on__gl2___aa8() throws IOException { + GLProfile glp = getGLProfile(GLProfile.GL2); + if( null == glp ) { + return; + } + doTest(true, new Gears(), glp, 8); + } + @Test + public void test111_on__gl2es3_aa0() throws IOException { + GLProfile glp = getGL2ES3(); + if( null == glp ) { + return; + } + doTest(true, new GearsES2(), glp, 0); + } + @Test + public void test112_on__gl2es3_aa8() throws IOException { + GLProfile glp = getGL2ES3(); + if( null == glp ) { + return; + } + doTest(true, new GearsES2(), glp, 8); + } + + void doTest(boolean onscreen, final GLEventListener demo, GLProfile glp, final int msaaCount) throws IOException { + GLCapabilities caps = new GLCapabilities(glp); + caps.setDoubleBuffered(onscreen); + if( msaaCount > 0 ) { + caps.setSampleBuffers(true); + caps.setNumSamples(msaaCount); + } + + final int maxTileSize = 256; + final GLAutoDrawable glad; + if( onscreen ) { + final GLWindow glWin = GLWindow.create(caps); + glWin.setSize(maxTileSize, maxTileSize); + glWin.setVisible(true); + glad = glWin; + } else { + final GLDrawableFactory factory = GLDrawableFactory.getFactory(glp); + glad = factory.createOffscreenAutoDrawable(null, caps, null, maxTileSize, maxTileSize); + } + + glad.addGLEventListener( demo ); + + // Fix the image size for now + final int imageWidth = glad.getWidth() * 6; + final int imageHeight = glad.getHeight() * 4; + + final String filename = this.getSnapshotFilename(0, "-tile", glad.getChosenGLCapabilities(), imageWidth, imageHeight, false, TextureIO.PNG, null); + final File file = new File(filename); + + // Initialize the tile rendering library + final TileRenderer renderer = new TileRenderer(); + renderer.setImageSize(imageWidth, imageHeight); + renderer.setTileSize(glad.getWidth(), glad.getHeight(), 0); + renderer.attachAutoDrawable(glad); + + final GLPixelBuffer.GLPixelBufferProvider pixelBufferProvider = GLPixelBuffer.defaultProviderWithRowStride; + final boolean[] flipVertically = { false }; + + final GLEventListener preTileGLEL = new GLEventListener() { + @Override + public void init(GLAutoDrawable drawable) { + final GL gl = drawable.getGL(); + GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, 3); + GLPixelBuffer pixelBuffer = pixelBufferProvider.allocate(gl, pixelAttribs, imageWidth, imageHeight, 1, true, 0); + renderer.setImageBuffer(pixelBuffer); + if( drawable.isGLOriented() ) { + flipVertically[0] = false; + } else { + flipVertically[0] = true; + } + } + @Override + public void dispose(GLAutoDrawable drawable) {} + @Override + public void display(GLAutoDrawable drawable) {} + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {} + }; + renderer.setGLEventListener(preTileGLEL, null); + + while ( !renderer.eot() ) { + renderer.display(); + } + + renderer.detachAutoDrawable(); + + // Restore viewport and Gear's PMV matrix + // .. even though we close the demo, this is for documentation! + glad.invoke(true, new GLRunnable() { + @Override + public boolean run(GLAutoDrawable drawable) { + drawable.getGL().glViewport(0, 0, drawable.getWidth(), drawable.getHeight()); + demo.reshape(drawable, 0, 0, drawable.getWidth(), drawable.getHeight()); + return false; + } + }); + + final GLPixelBuffer imageBuffer = renderer.getImageBuffer(); + final TextureData textureData = new TextureData( + caps.getGLProfile(), + 0 /* internalFormat */, + imageWidth, imageHeight, + 0, + imageBuffer.pixelAttributes, + false, false, + flipVertically[0], + imageBuffer.buffer, + null /* Flusher */); + + TextureIO.write(textureData, file); + + glad.destroy(); + } + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + try { + duration = Integer.parseInt(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } + } + org.junit.runner.JUnitCore.main(TestTiledRendering2NEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TiledPrintingAWTBase.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TiledPrintingAWTBase.java new file mode 100644 index 000000000..4e9d4bdbe --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TiledPrintingAWTBase.java @@ -0,0 +1,273 @@ +/** + * Copyright 2013 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.jogl.tile; + +import java.awt.Component; +import java.awt.Container; +import java.awt.Rectangle; +import java.awt.Window; +import java.awt.print.PageFormat; +import java.awt.print.Paper; +import java.awt.print.Printable; +import java.awt.print.PrinterException; +import java.awt.print.PrinterJob; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; + +import javax.media.opengl.GLAutoDrawable; +import javax.print.StreamPrintService; +import javax.print.StreamPrintServiceFactory; +import javax.print.attribute.HashPrintRequestAttributeSet; +import javax.print.attribute.PrintRequestAttributeSet; +import javax.print.attribute.standard.MediaSizeName; + +import jogamp.nativewindow.awt.AWTMisc; + +import org.junit.Assert; + +import com.jogamp.common.os.Platform; +import com.jogamp.common.util.awt.AWTEDTExecutor; +import com.jogamp.common.util.locks.LockFactory; +import com.jogamp.common.util.locks.RecursiveLock; +import com.jogamp.nativewindow.awt.AWTPrintLifecycle; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.TileRenderer; + +/** + * Base unit test class implementing + * issuing {@link PrinterJob#print()} on a {@link Printable} implementation, + * i.e. {@link OnscreenPrintable} or {@link OffscreenPrintable}. + */ +public abstract class TiledPrintingAWTBase extends UITestCase { + + private RecursiveLock lock = LockFactory.createRecursiveLock(); + private int printCount = 0; + + public TiledPrintingAWTBase() { + super(); + } + + /** + * + * @param cont + * @param pOrientation + * @param paper + * @param offscrnImageType if < 0 onscreen, otherwise integer BufferedImage type + * @param dpi + * @param numSamples multisampling value: < 0 turns off, == 0 leaves as-is, > 0 enables using given num samples + * @param tileWidth custom tile width for {@link TileRenderer#setTileSize(int, int, int) tile renderer}, pass -1 for default. + * @param tileHeight custom tile height for {@link TileRenderer#setTileSize(int, int, int) tile renderer}, pass -1 for default. + * @param resizeWithinPrintTest TODO + */ + public PrintableBase doPrintAuto(Container cont, int pOrientation, Paper paper, + int offscrnImageType, int dpi, int numSamples, int tileWidth, int tileHeight, boolean resizeWithinPrintTest) { + lock.lock(); + try { + final PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet(); + aset.add(MediaSizeName.ISO_A1); // 594 × 841 mm + aset.add(MediaSizeName.ISO_A2); // 420 × 594 mm + aset.add(MediaSizeName.ISO_A3); // 297 × 420 mm + aset.add(MediaSizeName.ISO_A4); // 210 × 297 mm + + printCount++; + + final String psMimeType = "application/postscript"; + final String pdfMimeType = "application/pdf"; + final PrinterJob pj = PrinterJob.getPrinterJob(); + + StreamPrintServiceFactory[] factories = PrinterJob.lookupStreamPrintServices(pdfMimeType); + if (factories.length > 0) { + final String fname = getPrintFilename(offscrnImageType, dpi, numSamples, tileWidth, tileHeight, "pdf", resizeWithinPrintTest); + System.err.println("doPrint: dpi "+dpi+", "+fname); + FileOutputStream outstream; + try { + outstream = new FileOutputStream(fname); + return doPrintAutoImpl(cont, pj, factories[0].getPrintService(outstream), pOrientation, paper, + offscrnImageType, dpi, numSamples, tileWidth, tileHeight, resizeWithinPrintTest); + } catch (FileNotFoundException e) { + Assert.assertNull("Unexpected exception", e); + } + } + System.err.println("No PDF"); + + factories = PrinterJob.lookupStreamPrintServices(psMimeType); + if (factories.length > 0) { + final String fname = getPrintFilename(offscrnImageType, dpi, numSamples, tileWidth, tileHeight, "ps", resizeWithinPrintTest); + System.err.println("doPrint: dpi "+dpi+", "+fname); + FileOutputStream outstream; + try { + outstream = new FileOutputStream(fname); + return doPrintAutoImpl(cont, pj, factories[0].getPrintService(outstream), pOrientation, paper, offscrnImageType, dpi, numSamples, tileWidth, tileHeight, resizeWithinPrintTest); + } catch (FileNotFoundException e) { + Assert.assertNull("Unexpected exception", e); + } + } + System.err.println("No PS"); + return null; + } finally { + lock.unlock(); + } + } + private String getPrintFilename(int offscrnImageType, int dpi, int numSamples, int tileWidth, int tileHeight, String suffix, boolean resizeWithinPrintTest) { + final int maxSimpleTestNameLen = getMaxTestNameLen()+getClass().getSimpleName().length()+1; + final String simpleTestName = getSimpleTestName("."); + final String onoffscrn = 0 > offscrnImageType ? "on_screen" : "offscrn_"+offscrnImageType; + final String aa = 0 <= numSamples ? "aa"+numSamples : "aaN"; + return String.format("%-"+maxSimpleTestNameLen+"s-n%04d-%s-dpi%03d-%s-tSz%04dx%04d-resize%d.%s", + simpleTestName, printCount, onoffscrn, dpi, aa, tileWidth, tileHeight, resizeWithinPrintTest?1:0, suffix).replace(' ', '_'); + } + private PrintableBase doPrintAutoImpl(Container cont, PrinterJob job, + StreamPrintService ps, int pOrientation, Paper paper, + int offscrnImageType, int dpi, int numSamples, int tileWidth, int tileHeight, boolean resizeWithinPrintTest) { + try { + PageFormat pageFormat = job.defaultPage(); + if( null != paper ) { + /** + Paper paper = new Paper(); + paper.setSize(500,500); // Large Address Dimension + paper.setImageableArea(20, 20, 450, 420); */ + pageFormat.setPaper(paper); + } + pageFormat.setOrientation(pOrientation); // PageFormat.LANDSCAPE or PageFormat.PORTRAIT + job.setPrintService(ps); + final PrintableBase printable; + if( 0 < offscrnImageType ) { + printable = new OffscreenPrintable(job, cont, dpi, numSamples, tileWidth, tileHeight, offscrnImageType, getPrintFilename(offscrnImageType, dpi, numSamples, tileWidth, tileHeight, "png", resizeWithinPrintTest)); + } else { + printable = new OnscreenPrintable(job, cont, dpi, numSamples, tileWidth, tileHeight); + } + printable.job.setPrintable(printable, pageFormat); + doPrintImpl(printable, resizeWithinPrintTest); + return printable; + } catch (PrinterException pe) { + pe.printStackTrace(); + return null; + } + } + + /** + * @param cont + * @param dpi + * @param numSamples multisampling value: < 0 turns off, == 0 leaves as-is, > 0 enables using given num samples + * @param tileWidth custom tile width for {@link TileRenderer#setTileSize(int, int, int) tile renderer}, pass -1 for default. + * @param tileHeight custom tile height for {@link TileRenderer#setTileSize(int, int, int) tile renderer}, pass -1 for default. + */ + public PrintableBase doPrintManual(Container cont, int dpi, int numSamples, int tileWidth, int tileHeight) { + lock.lock(); + try { + final OnscreenPrintable printable = new OnscreenPrintable(PrinterJob.getPrinterJob(), cont, dpi, numSamples, tileWidth, tileHeight); + printable.job.setPrintable(printable); + boolean ok = printable.job.printDialog(); + if (ok) { + doPrintImpl(printable, false); + } + return printable; + } finally { + lock.unlock(); + } + } + + private final AWTMisc.ComponentAction resizePlusAction = new AWTMisc.ComponentAction() { + @Override + public void run(Component c) { + final Rectangle r = c.getBounds(); + r.width += 64; + r.height += 64; + c.setBounds(r); + } }; + private final AWTMisc.ComponentAction resizeMinusAction = new AWTMisc.ComponentAction() { + @Override + public void run(Component c) { + final Rectangle r = c.getBounds(); + r.width -= 64; + r.height -= 64; + c.setBounds(r); + } }; + + private void doPrintImpl(final PrintableBase printable, final boolean resizeWithinPrintTest) { + final double scaleGLMatXY = 72.0 / printable.dpi; + System.err.println("PRINTable: "+printable.getClass().getSimpleName()); + System.err.println("PRINT DPI: "+printable.dpi+", AA "+printable.numSamples+", scaleGL "+scaleGLMatXY); + final AWTPrintLifecycle.Context ctx = + AWTPrintLifecycle.Context.setupPrint(printable.cont, scaleGLMatXY, scaleGLMatXY, + printable.numSamples, printable.tileWidth, printable.tileHeight); + System.err.println("PRINT AWTPrintLifecycle.setup.count "+ctx.getCount()); + final int w = printable.cont.getWidth(); + final int h = printable.cont.getHeight(); + final long t0 = Platform.currentTimeMillis(); + try { + AWTEDTExecutor.singleton.invoke(true, new Runnable() { + public void run() { + try { + if( resizeWithinPrintTest ) { + System.err.println("PRINT resizeWithinPrint size+ "+(w+64)+"x"+(h+64)); + AWTMisc.performAction(printable.cont, GLAutoDrawable.class, resizePlusAction); + printable.cont.validate(); + if( printable.cont instanceof Window ) { + ((Window)printable.cont).pack(); + } + } + printable.job.print(); + } catch (PrinterException ex) { + ex.printStackTrace(); + } + } }); + } finally { + ctx.releasePrint(); + final long td = Platform.currentTimeMillis() - t0; + System.err.println("PRINT Duration "+td+" ms"); + if( resizeWithinPrintTest ) { + AWTEDTExecutor.singleton.invoke(true, new Runnable() { + public void run() { + System.err.println("PRINT resizeWithinPrint repaint"); + printable.cont.repaint(); + System.err.println("PRINT resizeWithinPrint size- "+w+"x"+h); + AWTMisc.performAction(printable.cont, GLAutoDrawable.class, resizeMinusAction); + printable.cont.validate(); + if( printable.cont instanceof Window ) { + ((Window)printable.cont).pack(); + } + } }); + } + System.err.println("PRINT AWTPrintLifecycle.release.count "+ctx.getCount()); + } + } + + /** Wait for idle .. simply acquiring all locks and releasing them. */ + public void waitUntilPrintJobsIdle(PrintableBase p) { + lock.lock(); + try { + if( null != p ) { + p.waitUntilIdle(); + } + } finally { + lock.unlock(); + } + } +}
\ No newline at end of file diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TransparentPanel.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TransparentPanel.java new file mode 100644 index 000000000..d68f878fa --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TransparentPanel.java @@ -0,0 +1,59 @@ +package com.jogamp.opengl.test.junit.jogl.tile; + +import java.awt.*; +import javax.swing.*; +import java.lang.reflect.Method; + +public class TransparentPanel extends JPanel { + public TransparentPanel() { + super.setOpaque(false); + setMixingCutoutShape(new Rectangle()); + } + + @Override + public void setOpaque(boolean isOpaque) { + // Don't let this panel become opaque + } + + /** + * Helper utility needed to implement TransparentPanel. + * This class provides the ability to cut out the background of a lightweight + * panel so that it can be layered on top of a heavyweight component and have + * the heavyweight component show through. For more infromation, see: + * + * http://today.java.net/article/2009/11/02/transparent-panel-mixing-heavyweight-and-lightweight-components + */ + private static Method mSetComponentMixing; + + /** + * Set the cut out shape on a given Component. + * + * @param c The Component on which to set the cut out shape. + * @param s The shape to cut out of the given Component. + */ + public void setMixingCutoutShape(Shape s) + { + // Get the cut out shape method + if (mSetComponentMixing == null) { + try { + Class<?> awtUtilitiesClass = + Class.forName("com.sun.awt.AWTUtilities"); + mSetComponentMixing = + awtUtilitiesClass.getMethod( + "setComponentMixingCutoutShape", + Component.class, Shape.class); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + // Cut out the shape + if (mSetComponentMixing != null) { + try { + mSetComponentMixing.invoke( null, this, s ); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES1ImmModeSink.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES1ImmModeSink.java new file mode 100644 index 000000000..c82e7def4 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES1ImmModeSink.java @@ -0,0 +1,120 @@ +/** + * Copyright 2012 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.jogl.util; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES1; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLPipelineFactory; +import javax.media.opengl.glu.GLU; +import javax.media.opengl.glu.gl2es1.GLUgl2es1; + +import com.jogamp.opengl.util.ImmModeSink; +import com.jogamp.opengl.util.glsl.fixedfunc.FixedFuncUtil; +import com.jogamp.opengl.util.glsl.fixedfunc.ShaderSelectionMode; + +class DemoGL2ES1ImmModeSink implements GLEventListener { + private boolean debugFFPEmu = false; + private boolean verboseFFPEmu = false; + private boolean traceFFPEmu = false; + private boolean forceFFPEmu = false; + final ImmModeSink ims; + final GLU glu; + + DemoGL2ES1ImmModeSink(boolean useVBO) { + ims = ImmModeSink.createFixed(3*3, + 3, GL.GL_FLOAT, // vertex + 3, GL.GL_FLOAT, // color + 0, GL.GL_FLOAT, // normal + 0, GL.GL_FLOAT, // texCoords + useVBO ? GL.GL_STATIC_DRAW : 0); + glu = new GLUgl2es1(); + } + + public void setForceFFPEmu(boolean forceFFPEmu, boolean verboseFFPEmu, boolean debugFFPEmu, boolean traceFFPEmu) { + this.forceFFPEmu = forceFFPEmu; + this.verboseFFPEmu = verboseFFPEmu; + this.debugFFPEmu = debugFFPEmu; + this.traceFFPEmu = traceFFPEmu; + } + + @Override + public void init(GLAutoDrawable drawable) { + GL _gl = drawable.getGL(); + if(debugFFPEmu) { + // Debug .. + _gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", GL2ES2.class, _gl, null) ); + } + if(traceFFPEmu) { + // Trace .. + _gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", GL2ES2.class, _gl, new Object[] { System.err } ) ); + } + GL2ES1 gl = FixedFuncUtil.wrapFixedFuncEmul(_gl, ShaderSelectionMode.AUTO, null, forceFFPEmu, verboseFFPEmu); + + System.err.println("GL_VENDOR "+gl.glGetString(GL.GL_VENDOR)); + System.err.println("GL_RENDERER "+gl.glGetString(GL.GL_RENDERER)); + System.err.println("GL_VERSION "+gl.glGetString(GL.GL_VERSION)); + } + + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + GL2ES1 gl = drawable.getGL().getGL2ES1(); + + gl.glMatrixMode( GL2ES1.GL_PROJECTION ); + gl.glLoadIdentity(); + + // coordinate system origin at lower left with width and height same as the window + glu.gluOrtho2D( 0.0f, width, 0.0f, height ); + + gl.glMatrixMode( GL2ES1.GL_MODELVIEW ); + gl.glLoadIdentity(); + } + + @Override + public void display(GLAutoDrawable drawable) { + GL2ES1 gl = drawable.getGL().getGL2ES1(); + + gl.glClear( GL.GL_COLOR_BUFFER_BIT ); + + // draw a triangle filling the window + ims.glBegin(GL.GL_TRIANGLES); + ims.glColor3f( 1, 0, 0 ); + ims.glVertex2f( 0, 0 ); + ims.glColor3f( 0, 1, 0 ); + ims.glVertex2f( drawable.getWidth(), 0 ); + ims.glColor3f( 0, 0, 1 ); + ims.glVertex2f( drawable.getWidth() / 2, drawable.getHeight() ); + ims.glEnd(gl, true); + } + + @Override + public void dispose(GLAutoDrawable drawable) { + } +}
\ No newline at end of file diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES1Plain.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES1Plain.java new file mode 100644 index 000000000..0df368615 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES1Plain.java @@ -0,0 +1,188 @@ +/** + * Copyright 2012 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.jogl.util; + +import java.nio.ByteBuffer; +import java.nio.FloatBuffer; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES1; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLException; +import javax.media.opengl.fixedfunc.GLPointerFunc; +import javax.media.opengl.glu.GLU; +import javax.media.opengl.glu.gl2es1.GLUgl2es1; + +import com.jogamp.common.nio.Buffers; +import com.jogamp.opengl.util.GLArrayDataWrapper; +import com.jogamp.opengl.util.GLBuffers; + +class DemoGL2ES1Plain implements GLEventListener { + final boolean useArrayData; + final boolean useVBO; + final GLU glu; + + final float[] vertices = new float[] { 0, 0, 0, + TestImmModeSinkES1NEWT.iWidth, 0, 0, + TestImmModeSinkES1NEWT.iWidth / 2, TestImmModeSinkES1NEWT.iHeight, 0 }; + + final float[] colors = new float[] { 1, 0, 0, + 0, 1, 0, + 0, 0, 1 }; + + final ByteBuffer bufferAll; + final int bufferVOffset, bufferCOffset; + final int bufferVSize, bufferCSize; + final FloatBuffer bufferC, bufferV; + final int[] vboName = new int[] { 0 }; + final GLArrayDataWrapper arrayC, arrayV; + + DemoGL2ES1Plain(boolean useArrayData, boolean useVBO) { + this.useArrayData = useArrayData; + this.useVBO = useVBO; + this.glu = new GLUgl2es1(); + + bufferAll = Buffers.newDirectByteBuffer( ( colors.length + vertices.length ) * Buffers.SIZEOF_FLOAT ); + + bufferVOffset = 0; + bufferVSize = 3*3*GLBuffers.sizeOfGLType(GL.GL_FLOAT); + bufferCOffset = bufferVSize; + bufferCSize = 3*3*GLBuffers.sizeOfGLType(GL.GL_FLOAT); + + bufferV = (FloatBuffer) GLBuffers.sliceGLBuffer(bufferAll, bufferVOffset, bufferVSize, GL.GL_FLOAT); + bufferV.put(vertices, 0, vertices.length).rewind(); + bufferC = (FloatBuffer) GLBuffers.sliceGLBuffer(bufferAll, bufferCOffset, bufferCSize, GL.GL_FLOAT); + bufferC.put(colors, 0, colors.length).rewind(); + + System.err.println("bufferAll: "+bufferAll+", byteOffset "+Buffers.getDirectBufferByteOffset(bufferAll)); + System.err.println("bufferV: off "+bufferVOffset+", size "+bufferVSize+": "+bufferV+", byteOffset "+Buffers.getDirectBufferByteOffset(bufferV)); + System.err.println("bufferC: off "+bufferCOffset+", size "+bufferCSize+": "+bufferC+", byteOffset "+Buffers.getDirectBufferByteOffset(bufferC)); + + if(useArrayData) { + arrayV = GLArrayDataWrapper.createFixed(GLPointerFunc.GL_VERTEX_ARRAY, 3, GL.GL_FLOAT, false, 0, + bufferV, 0, bufferVOffset, GL.GL_STATIC_DRAW, GL.GL_ARRAY_BUFFER); + + arrayC = GLArrayDataWrapper.createFixed(GLPointerFunc.GL_COLOR_ARRAY, 3, GL.GL_FLOAT, false, 0, + bufferC, 0, bufferCOffset, GL.GL_STATIC_DRAW, GL.GL_ARRAY_BUFFER); + } else { + arrayV = null; + arrayC = null; + } + } + + @Override + public void init(GLAutoDrawable drawable) { + GL gl = drawable.getGL(); + System.err.println("GL_VENDOR "+gl.glGetString(GL.GL_VENDOR)); + System.err.println("GL_RENDERER "+gl.glGetString(GL.GL_RENDERER)); + System.err.println("GL_VERSION "+gl.glGetString(GL.GL_VERSION)); + if(useVBO) { + gl.glGenBuffers(1, vboName, 0); + if(0 == vboName[0]) { + throw new GLException("glGenBuffers didn't return valid VBO name"); + } + } + } + + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + GL2ES1 gl = drawable.getGL().getGL2ES1(); + + gl.glMatrixMode( GL2ES1.GL_PROJECTION ); + gl.glLoadIdentity(); + + // coordinate system origin at lower left with width and height same as the window + glu.gluOrtho2D( 0.0f, width, 0.0f, height ); + + gl.glMatrixMode( GL2ES1.GL_MODELVIEW ); + gl.glLoadIdentity(); + + gl.glViewport( 0, 0, width, height ); + } + + @Override + public void display(GLAutoDrawable drawable) { + GL2ES1 gl = drawable.getGL().getGL2ES1(); + + gl.glClear( GL.GL_COLOR_BUFFER_BIT ); + + // draw a triangle filling the window + gl.glLoadIdentity(); + + if(useVBO) { + gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vboName[0]); + gl.glBufferData(GL.GL_ARRAY_BUFFER, bufferAll.limit(), bufferAll, GL.GL_STATIC_DRAW); + if(useArrayData) { + arrayV.setVBOName(vboName[0]); + arrayC.setVBOName(vboName[0]); + } + } + + gl.glEnableClientState(GLPointerFunc.GL_VERTEX_ARRAY); + if(useArrayData) { + gl.glVertexPointer(arrayV); + } else { + if(useVBO) { + gl.glVertexPointer(3, GL.GL_FLOAT, 0, bufferVOffset); + } else { + gl.glVertexPointer(3, GL.GL_FLOAT, 0, bufferV); + } + } + + gl.glEnableClientState(GLPointerFunc.GL_COLOR_ARRAY); + if(useArrayData) { + gl.glColorPointer(arrayC); + } else { + if(useVBO) { + gl.glColorPointer(3, GL.GL_FLOAT, 0, bufferCOffset); + } else { + gl.glColorPointer(3, GL.GL_FLOAT, 0, bufferC); + } + } + + if(useVBO) { + gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0); + } + + gl.glDrawArrays(GL.GL_TRIANGLES, 0, 3); + gl.glFlush(); + + gl.glDisableClientState(GLPointerFunc.GL_COLOR_ARRAY); + gl.glDisableClientState(GLPointerFunc.GL_VERTEX_ARRAY); + } + + @Override + public void dispose(GLAutoDrawable drawable) { + GL gl = drawable.getGL(); + if(0 != vboName[0]) { + gl.glDeleteBuffers(1, vboName, 0); + vboName[0] = 0; + } + } +}
\ No newline at end of file diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES1TextureImmModeSink.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES1TextureImmModeSink.java new file mode 100644 index 000000000..d776021ba --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES1TextureImmModeSink.java @@ -0,0 +1,162 @@ +/** + * 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.jogl.util; + +import java.io.InputStream; +import java.net.URLConnection; + +import com.jogamp.common.util.IOUtil; +import com.jogamp.opengl.test.junit.jogl.demos.TextureDraw01Accessor; +import com.jogamp.opengl.util.ImmModeSink; +import com.jogamp.opengl.util.glsl.fixedfunc.FixedFuncUtil; +import com.jogamp.opengl.util.glsl.fixedfunc.ShaderSelectionMode; +import com.jogamp.opengl.util.texture.Texture; +import com.jogamp.opengl.util.texture.TextureCoords; +import com.jogamp.opengl.util.texture.TextureData; +import com.jogamp.opengl.util.texture.TextureIO; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES1; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLPipelineFactory; +import javax.media.opengl.glu.GLU; + +public class DemoGL2ES1TextureImmModeSink implements GLEventListener, TextureDraw01Accessor { + private boolean debugFFPEmu = false; + private boolean verboseFFPEmu = false; + private boolean traceFFPEmu = false; + private boolean forceFFPEmu = false; + private ImmModeSink ims; + private GLU glu = new GLU(); + private TextureData textureData; + private Texture texture; + boolean keepTextureBound; + + public DemoGL2ES1TextureImmModeSink() { + this.ims = ImmModeSink.createFixed(32, 3, GL.GL_FLOAT, 4, GL.GL_FLOAT, 0, GL.GL_FLOAT, 2, GL.GL_FLOAT, GL.GL_STATIC_DRAW); + this.keepTextureBound = false; + } + + public void setForceFFPEmu(boolean forceFFPEmu, boolean verboseFFPEmu, boolean debugFFPEmu, boolean traceFFPEmu) { + this.forceFFPEmu = forceFFPEmu; + this.verboseFFPEmu = verboseFFPEmu; + this.debugFFPEmu = debugFFPEmu; + this.traceFFPEmu = traceFFPEmu; + } + + + @Override + public void setKeepTextureBound(boolean v) { + this.keepTextureBound = v; + } + @Override + public Texture getTexture( ) { + return this.texture; + } + + @Override + public void init(GLAutoDrawable drawable) { + GL _gl = drawable.getGL(); + if(debugFFPEmu) { + // Debug .. + _gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", GL2ES2.class, _gl, null) ); + } + if(traceFFPEmu) { + // Trace .. + _gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", GL2ES2.class, _gl, new Object[] { System.err } ) ); + } + GL2ES1 gl = FixedFuncUtil.wrapFixedFuncEmul(_gl, ShaderSelectionMode.AUTO, null, forceFFPEmu, verboseFFPEmu); + + URLConnection testTextureUrlConn = IOUtil.getResource("jogl/util/data/av/test-ntsc01-57x32.png", this.getClass().getClassLoader()); + try { + InputStream testTextureStream = testTextureUrlConn.getInputStream(); + textureData = TextureIO.newTextureData(gl.getGLProfile(), testTextureStream , false /* mipmap */, TextureIO.PNG); + texture = TextureIO.newTexture(gl, textureData); + if( keepTextureBound && null != texture ) { + texture.enable(gl); + texture.bind(gl); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + GL2ES1 gl = drawable.getGL().getGL2ES1(); + gl.glMatrixMode(GL2ES1.GL_PROJECTION); + gl.glLoadIdentity(); + glu.gluOrtho2D(0, 1, 0, 1); + gl.glMatrixMode(GL2ES1.GL_MODELVIEW); + gl.glLoadIdentity(); + } + + @Override + public void dispose(GLAutoDrawable drawable) { + GL2ES1 gl = drawable.getGL().getGL2ES1(); + if(null!=texture) { + texture.disable(gl); + texture.destroy(gl); + } + if(null!=textureData) { + textureData.destroy(); + } + } + + @Override + public void display(GLAutoDrawable drawable) { + GL2ES1 gl = drawable.getGL().getGL2ES1(); + + // draw one quad with the texture + if(null!=texture) { + if( !keepTextureBound ) { + texture.enable(gl); + texture.bind(gl); + } + // gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_REPLACE); + TextureCoords coords = texture.getImageTexCoords(); + ims.glBegin(ImmModeSink.GL_QUADS); + ims.glTexCoord2f(coords.left(), coords.bottom()); + ims.glVertex3f(0, 0, 0); + ims.glTexCoord2f(coords.right(), coords.bottom()); + ims.glVertex3f(1, 0, 0); + ims.glTexCoord2f(coords.right(), coords.top()); + ims.glVertex3f(1, 1, 0); + ims.glTexCoord2f(coords.left(), coords.top()); + ims.glVertex3f(0, 1, 0); + ims.glEnd(gl); + if( !keepTextureBound ) { + texture.disable(gl); + } + } + } +} + diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES2ImmModeSink.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES2ImmModeSink.java new file mode 100644 index 000000000..02f161cf6 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES2ImmModeSink.java @@ -0,0 +1,193 @@ +/** + * Copyright 2012 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.jogl.util; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLException; +import javax.media.opengl.GLUniformData; +import javax.media.opengl.fixedfunc.GLMatrixFunc; + +import com.jogamp.opengl.util.ImmModeSink; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; +import com.jogamp.opengl.util.glsl.ShaderState; + +public class DemoGL2ES2ImmModeSink implements GLEventListener { + + private final ShaderState st; + private final PMVMatrix pmvMatrix; + private int glBufferUsage; + private ShaderProgram sp; + private GLUniformData pmvMatrixUniform; + private ImmModeSink ims; + + public DemoGL2ES2ImmModeSink(boolean useVBO, boolean useShaderState) { + if(useShaderState) { + st = new ShaderState(); + st.setVerbose(true); + } else { + st = null; + } + glBufferUsage = useVBO ? GL.GL_STATIC_DRAW : 0; + pmvMatrix = new PMVMatrix(); + } + + public void init(GLAutoDrawable glad) { + final GL2ES2 gl = glad.getGL().getGL2ES2(); + + System.err.println("GL_VENDOR "+gl.glGetString(GL.GL_VENDOR)); + System.err.println("GL_RENDERER "+gl.glGetString(GL.GL_RENDERER)); + System.err.println("GL_VERSION "+gl.glGetString(GL.GL_VERSION)); + + final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, DemoGL2ES2ImmModeSink.class, + "../demos/es2/shader", "../demos/es2/shader/bin", "mgl_default_xxx", true); + final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, DemoGL2ES2ImmModeSink.class, + "../demos/es2/shader", "../demos/es2/shader/bin", "mgl_default_xxx", true); + vp0.defaultShaderCustomization(gl, true, true); + fp0.defaultShaderCustomization(gl, true, true); + + sp = new ShaderProgram(); + sp.add(gl, vp0, System.err); + sp.add(gl, fp0, System.err); + if( null != st ) { + st.attachShaderProgram(gl, sp, true); + } else { + if(!sp.link(gl, System.err)) { + throw new GLException("Could not link program: "+sp); + } + sp.useProgram(gl, true); + } + + pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); + if(null != st) { + st.ownUniform(pmvMatrixUniform); + st.uniform(gl, pmvMatrixUniform); + } else { + if( pmvMatrixUniform.setLocation(gl, sp.program()) < 0 ) { + throw new GLException("Could not find location for uniform: "+pmvMatrixUniform+", "+sp); + } + gl.glUniform(pmvMatrixUniform); + } + + // Using predef array names, see + // GLPointerFuncUtil.getPredefinedArrayIndexName(glArrayIndex); + if( null != st ) { + ims = ImmModeSink.createGLSL(40, + 3, GL.GL_FLOAT, // vertex + 4, GL.GL_FLOAT, // color + 0, GL.GL_FLOAT, // normal + 0, GL.GL_FLOAT, // texCoords + glBufferUsage, st); + } else { + ims = ImmModeSink.createGLSL(40, + 3, GL.GL_FLOAT, // vertex + 4, GL.GL_FLOAT, // color + 0, GL.GL_FLOAT, // normal + 0, GL.GL_FLOAT, // texCoords + glBufferUsage, sp.program()); + } + final int numSteps = 20; + final double increment = Math.PI / numSteps; + final double radius = 1; + ims.glBegin(GL.GL_LINES); + for (int i = numSteps - 1; i >= 0; i--) { + ims.glVertex3f((float) (radius * Math.cos(i * increment)), + (float) (radius * Math.sin(i * increment)), + 0f); + ims.glColor4f( 1f, 1f, 1f, 1f ); + ims.glVertex3f((float) (-1.0 * radius * Math.cos(i * increment)), + (float) (-1.0 * radius * Math.sin(i * increment)), + 0f); + ims.glColor4f( 1f, 1f, 1f, 1f ); + } + ims.glEnd(gl, false); + + if(null != st) { + st.useProgram(gl, false); + } else { + gl.glUseProgram(0); + } + } + + public void dispose(GLAutoDrawable glad) { + final GL2ES2 gl = glad.getGL().getGL2ES2(); + ims.destroy(gl); + ims = null; + if(null != st) { + st.destroy(gl); + } + } + + public void display(GLAutoDrawable drawable) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + + gl.glClear( GL.GL_COLOR_BUFFER_BIT ); + + // draw a triangle filling the window + ims.glBegin(GL.GL_TRIANGLES); + ims.glColor3f( 1, 0, 0 ); + ims.glVertex2f( 0, 0 ); + ims.glColor3f( 0, 1, 0 ); + ims.glVertex2f( drawable.getWidth(), 0 ); + ims.glColor3f( 0, 0, 1 ); + ims.glVertex2f( drawable.getWidth() / 2, drawable.getHeight() ); + ims.glEnd(gl, true); + } + + // Unused routines + public void reshape(GLAutoDrawable glad, int x, int y, int width, int height) { + System.err.println("reshape .."); + final GL2ES2 gl = glad.getGL().getGL2ES2(); + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + + // coordinate system origin at lower left with width and height same as the window + pmvMatrix.glOrthof( 0.0f, width, 0.0f, height, -1, 1 ); + + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + + if(null != st) { + st.useProgram(gl, true); + st.uniform(gl, pmvMatrixUniform); + st.useProgram(gl, false); + } else { + gl.glUseProgram(sp.program()); + gl.glUniform(pmvMatrixUniform); + gl.glUseProgram(0); + } + } + + public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) { + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/TestES1FixedFunctionPipelineNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/TestES1FixedFunctionPipelineNEWT.java new file mode 100644 index 000000000..e8e3b12d9 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/TestES1FixedFunctionPipelineNEWT.java @@ -0,0 +1,154 @@ +/** + * Copyright 2011 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.jogl.util; + +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.test.junit.util.QuitAdapter; + +import com.jogamp.opengl.util.Animator; + +import com.jogamp.opengl.test.junit.jogl.demos.es1.GearsES1; +import com.jogamp.opengl.test.junit.jogl.demos.es1.RedSquareES1; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.AfterClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestES1FixedFunctionPipelineNEWT extends UITestCase { + static int width, height; + + @BeforeClass + public static void initClass() { + width = 512; + height = 512; + } + + @AfterClass + public static void releaseClass() { + } + + protected void runTestGL0(GLCapabilities caps, GLEventListener demo) throws InterruptedException { + GLWindow glWindow = GLWindow.create(caps); + Assert.assertNotNull(glWindow); + glWindow.setTitle(getSimpleTestName(".")); + + glWindow.addGLEventListener(demo); + final SnapshotGLEventListener snap = new SnapshotGLEventListener(); + snap.setPostSNDetail(demo.getClass().getSimpleName()); + glWindow.addGLEventListener(snap); + + Animator animator = new Animator(glWindow); + QuitAdapter quitAdapter = new QuitAdapter(); + glWindow.addKeyListener(quitAdapter); + glWindow.addWindowListener(quitAdapter); + + glWindow.setSize(width, height); + glWindow.setVisible(true); + animator.setUpdateFPSFrames(1, null); + animator.start(); + + snap.setMakeSnapshot(); + while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) { + Thread.sleep(100); + } + glWindow.removeGLEventListener(demo); + + animator.stop(); + glWindow.destroy(); + } + + protected void runTestGL(GLCapabilities caps, boolean forceFFPEmu) throws InterruptedException { + final RedSquareES1 demo01 = new RedSquareES1(); + demo01.setForceFFPEmu(forceFFPEmu, false, false, false); + runTestGL0(caps, demo01); + + final GearsES1 demo02 = new GearsES1(); + demo02.setForceFFPEmu(forceFFPEmu, false, false, false); + runTestGL0(caps, demo02); + + final DemoGL2ES1ImmModeSink demo03 = new DemoGL2ES1ImmModeSink(true); + demo03.setForceFFPEmu(forceFFPEmu, false, false, false); + runTestGL0(caps, demo03); + + final DemoGL2ES1TextureImmModeSink demo04 = new DemoGL2ES1TextureImmModeSink(); + demo04.setForceFFPEmu(forceFFPEmu, false, false, false); + runTestGL0(caps, demo04); + } + + @Test + public void test01GL2Normal() throws InterruptedException { + if(!GLProfile.isAvailable(GLProfile.GL2)) { System.err.println("GL2 n/a"); return; } + GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL2)); + runTestGL(caps, false); + } + + @Test + public void test02GL2FFPEmu() throws InterruptedException { + if(!GLProfile.isAvailable(GLProfile.GL2)) { System.err.println("GL2 n/a"); return; } + GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL2)); + runTestGL(caps, true); + } + + @Test + public void test03GL2ES1Normal() throws InterruptedException { + if(!GLProfile.isAvailable(GLProfile.GL2ES1)) { System.err.println("GL2ES1 n/a"); return; } + GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL2ES1)); + runTestGL(caps, false); + } + + @Test + public void test04ES2FFPEmu() throws InterruptedException { + if(!GLProfile.isAvailable(GLProfile.GLES2)) { System.err.println("GLES2 n/a"); return; } + GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); + runTestGL(caps, false); // should be FFPEmu implicit + } + + static long duration = 1000; // ms + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + try { + duration = Integer.parseInt(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } + } + org.junit.runner.JUnitCore.main(TestES1FixedFunctionPipelineNEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/TestImmModeSinkES1NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/TestImmModeSinkES1NEWT.java new file mode 100644 index 000000000..0ac01bc31 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/TestImmModeSinkES1NEWT.java @@ -0,0 +1,143 @@ +/** + * 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.jogl.util; + +import java.io.IOException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Testing the ImmModeSink w/ GL2ES1 context + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestImmModeSinkES1NEWT extends UITestCase { + static int duration = 100; + static final int iWidth = 400; + static final int iHeight = 400; + + static GLCapabilities getCaps(String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return new GLCapabilities(GLProfile.get(profile)); + } + + void doTest(GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException { + System.out.println("Requested GL Caps: "+reqGLCaps); + + // + // Create native windowing resources .. X11/Win/OSX + // + final GLWindow glad = GLWindow.create(reqGLCaps); + glad.addGLEventListener(demo); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + glad.addGLEventListener(snapshotGLEventListener); + glad.setSize(iWidth, iHeight); + glad.setVisible(true); + + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); // initial resize/display + + Thread.sleep(duration); + + glad.destroy(); + } + + @Test + public void test01Plain__GL2ES1_VBOOffUsePlain() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES1); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new DemoGL2ES1Plain(false, false)); + } + + @Test + public void test02Plain__GL2ES1_VBOOffUseArrayData() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES1); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new DemoGL2ES1Plain(true, false)); + } + + @Test + public void test03Plain__GL2ES1_VBOOnUsePlain() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES1); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new DemoGL2ES1Plain(false, true)); + } + + @Test + public void test04Plain__GL2ES1_VBOOnUseArrayData() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES1); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new DemoGL2ES1Plain(true, true)); + } + + @Test + public void test05ImmSinkGL2ES1_VBOOff() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES1); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new DemoGL2ES1ImmModeSink(false)); + } + + @Test + public void test06ImmSinkGL2ES1_VBOOn() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES1); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new DemoGL2ES1ImmModeSink(true)); + } + + @Test + public void test07ImmSinkGL2ES1_VBOOnTexture() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES1); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new DemoGL2ES1TextureImmModeSink()); + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + duration = MiscUtils.atoi(args[++i], duration); + } + } + org.junit.runner.JUnitCore.main(TestImmModeSinkES1NEWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/TestImmModeSinkES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/TestImmModeSinkES2NEWT.java new file mode 100644 index 000000000..de6aef55e --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/TestImmModeSinkES2NEWT.java @@ -0,0 +1,120 @@ +/** + * 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.jogl.util; + +import java.io.IOException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Testing the ImmModeSink w/ GL2ES1 context + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestImmModeSinkES2NEWT extends UITestCase { + static int duration = 100; + static final int iWidth = 400; + static final int iHeight = 400; + + static GLCapabilities getCaps(String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return new GLCapabilities(GLProfile.get(profile)); + } + + void doTest(GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException { + System.out.println("Requested GL Caps: "+reqGLCaps); + + // + // Create native windowing resources .. X11/Win/OSX + // + final GLWindow glad = GLWindow.create(reqGLCaps); + glad.addGLEventListener(demo); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + glad.addGLEventListener(snapshotGLEventListener); + glad.setSize(iWidth, iHeight); + glad.setVisible(true); + + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); // initial resize/display + + Thread.sleep(duration); + + glad.destroy(); + } + + @Test + public void test05ImmSinkGL2ES2_VBOOff_Direct() throws InterruptedException { + final GLCapabilities reqGLCaps = new GLCapabilities( GLProfile.getMaxFixedFunc(true) ); + doTest(reqGLCaps, new DemoGL2ES2ImmModeSink(false, false)); + } + + @Test + public void test05ImmSinkGL2ES2_VBOOff_ShaderState() throws InterruptedException { + final GLCapabilities reqGLCaps = new GLCapabilities( GLProfile.getMaxFixedFunc(true) ); + doTest(reqGLCaps, new DemoGL2ES2ImmModeSink(false, true)); + } + + @Test + public void test06ImmSinkGL2ES2_VBOOn_Direct() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new DemoGL2ES2ImmModeSink(true, false)); + } + + @Test + public void test06ImmSinkGL2ES2_VBOOn_ShaderState() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new DemoGL2ES2ImmModeSink(true, true)); + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + duration = MiscUtils.atoi(args[++i], duration); + } + } + org.junit.runner.JUnitCore.main(TestImmModeSinkES2NEWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/TestPNGImage01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/TestPNGImage01NEWT.java deleted file mode 100644 index 5a0c18de7..000000000 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/TestPNGImage01NEWT.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.jogamp.opengl.test.junit.jogl.util; - -import java.io.File; -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URLConnection; - -import org.junit.Assert; -import org.junit.Test; - -import com.jogamp.common.util.IOUtil; -import com.jogamp.opengl.test.junit.util.UITestCase; -import com.jogamp.opengl.util.texture.spi.PNGImage; - -public class TestPNGImage01NEWT extends UITestCase { - @Test - public void testPNGReadWriteAndCompare() throws InterruptedException, IOException, MalformedURLException { - final File out1_f=new File(getSimpleTestName(".")+"-PNGImageTest1.png"); - final File out2_f=new File(getSimpleTestName(".")+"-PNGImageTest2.png"); - final String url_s="jogl/util/data/av/test-ntsc01-160x90.png"; - URLConnection urlConn = IOUtil.getResource(url_s, PNGImage.class.getClassLoader()); - PNGImage image0 = PNGImage.read(urlConn.getInputStream()); - System.err.println("PNGImage - Orig: "+image0); - image0.write(out1_f, true); - { - Assert.assertEquals(image0.getData(), PNGImage.read(IOUtil.toURL(out1_f).openStream()).getData()); - } - - final PNGImage image1 = PNGImage.createFromData(image0.getWidth(), image0.getHeight(), - image0.getDpi()[0], image0.getDpi()[1], - image0.getBytesPerPixel(), false, image0.getData()); - image1.write(out2_f, true); - { - Assert.assertEquals(image0.getData(), PNGImage.read(IOUtil.toURL(out2_f).openStream()).getData()); - } - } - - public static void main(String args[]) { - org.junit.runner.JUnitCore.main(TestPNGImage01NEWT.class.getName()); - } -} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/PNGTstFiles.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/PNGTstFiles.java new file mode 100644 index 000000000..0d5d74a97 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/PNGTstFiles.java @@ -0,0 +1,54 @@ +/** + * Copyright 2014 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.jogl.util.texture; + +public class PNGTstFiles { + static public final String[] allBasenames = { + "test-ntscN_3-01-160x90", + "test-ntscN_4-01-160x90", + "test-ntscNG4-01-160x90", + "test-ntscI_3-01-160x90", + "test-ntscI_4-01-160x90", + "test-ntscIG3-01-160x90", + "test-ntscIG4-01-160x90", + "test-ntscP_3-01-160x90", + "test-ntscP_4-01-160x90", + "grayscale_texture", + "bug724-transparent-grey_orig", + "bug724-transparent-grey_gimpexp", + "cross-grey-alpha-16x16", + "pointer-grey-alpha-16x24", + }; + static public final String[] greyBasenames = { + "grayscale_texture", + "bug724-transparent-grey_orig", + "bug724-transparent-grey_gimpexp", + "cross-grey-alpha-16x16", + "pointer-grey-alpha-16x24", + }; +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestBug362DDSImageCreateFromData.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestBug362DDSImageCreateFromData.java new file mode 100644 index 000000000..4212abae7 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestBug362DDSImageCreateFromData.java @@ -0,0 +1,98 @@ +package com.jogamp.opengl.test.junit.jogl.util.texture; + +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLConnection; +import java.nio.ByteBuffer; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.jogamp.common.util.IOUtil; +import com.jogamp.opengl.util.texture.spi.DDSImage; +import com.jogamp.opengl.util.texture.spi.DDSImage.ImageInfo; + +/** + * This test uses the DDSImage class to read a dds image from file, extract the data, + * and use the class to create a new DDSImage from the extracted data + * <br></br> + * Bug Reference: https://jogamp.org/bugzilla/show_bug.cgi?id=362 + * <br></br> + * The bug pertains to incorrect size calculation for checking validity of data. Compressed DXT1 has min of 8 bytes, DXT5 has min of 16 bytes. + * It exists in {@link DDSImage#createFromData(int, int, int, ByteBuffer[])} + * where an {@link IllegalArgumentException} is thrown for Mipmap level size mismatch. + * <br></br> + * <ul>The following cases are tested: + * <li>Uncompressed 64x32 RGB DDS Image with all mipmap levels (64x32 --> 1x1)</li> + * <li>DXT1 compressed 64x32 RGB DDS Image with all mipmap levels (64x32 --> 1x1)</li> + * <li>DXT5 compressed 64x32 RGB DDS Image with all mipmap levels (64x32 --> 1x1)</li> + * </ul> + * + * @author Michael Esemplare + * + */ +public class TestBug362DDSImageCreateFromData { + + File testDDSImage01Uncompressed; + File testDDSImage02DXT1; + File testDDSImage03DXT5; + + @Before + public void setup() throws Throwable { + testDDSImage01Uncompressed = initFile("test-64x32_uncompressed.dds"); + testDDSImage02DXT1 = initFile("test-64x32_DXT1.dds"); + testDDSImage03DXT5 = initFile("test-64x32_DXT5.dds"); + } + + @After + public void teardown() { + testDDSImage01Uncompressed = null; + testDDSImage02DXT1 = null; + testDDSImage03DXT5 = null; + } + + private File initFile(String filename) throws URISyntaxException { + URLConnection connection = IOUtil.getResource(getClass(), filename); + Assert.assertNotNull(connection); + URL url = connection.getURL(); + File file = new File(url.toURI()); + Assert.assertTrue(file.exists()); + return file; + } + + private void testImpl(File file) throws IOException { + DDSImage ddsImage = DDSImage.read(file); + Assert.assertNotNull(ddsImage); + int numMipMaps = ddsImage.getNumMipMaps(); + ByteBuffer[] mipMapArray = new ByteBuffer[numMipMaps]; + for (int i=0;i<numMipMaps;i++){ + ImageInfo info = ddsImage.getMipMap(i); + mipMapArray[i] = info.getData(); + } + DDSImage newImage = DDSImage.createFromData(ddsImage.getPixelFormat(), ddsImage.getWidth(), ddsImage.getHeight(), mipMapArray); + Assert.assertNotNull(newImage); + } + + @Test + public void test00_DDSImage_CreateFromData_Uncompressed_RGB () throws IOException { + testImpl(testDDSImage01Uncompressed); + } + + @Test + public void test01_DDSImage_CreateFromData_DXT1_RGB () throws IOException { + testImpl(testDDSImage02DXT1); + } + + @Test + public void test02_DDSImage_CreateFromData_DXT5_RGB () throws IOException { + testImpl(testDDSImage03DXT5); + } + + public static void main(String[] args) { + org.junit.runner.JUnitCore.main(TestBug362DDSImageCreateFromData.class.getName()); + } +}
\ No newline at end of file diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestBug817GLReadBufferUtilGLCTXDefFormatTypeES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestBug817GLReadBufferUtilGLCTXDefFormatTypeES2NEWT.java new file mode 100644 index 000000000..679f0692b --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestBug817GLReadBufferUtilGLCTXDefFormatTypeES2NEWT.java @@ -0,0 +1,130 @@ +/** + * Copyright 2013 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.jogl.util.texture; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.opengl.GLWindow; +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.util.GLPixelBuffer.GLPixelAttributes; +import com.jogamp.opengl.util.GLPixelBuffer.GLPixelBufferProvider; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestBug817GLReadBufferUtilGLCTXDefFormatTypeES2NEWT extends UITestCase { + static long durationPerTest = 60; // ms + + public static void main(String[] args) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + durationPerTest = MiscUtils.atoi(args[++i], 500); + } + } + System.out.println("durationPerTest: "+durationPerTest); + String tstname = TestBug817GLReadBufferUtilGLCTXDefFormatTypeES2NEWT.class.getName(); + org.junit.runner.JUnitCore.main(tstname); + } + + @Test + public void test00_RGBtoRGB() throws InterruptedException { + testImpl(false, false, false, false); + } + @Test + public void test01_RGBtoRGBA() throws InterruptedException { + testImpl(false, true, false, false); + } + + @Test + public void test10_RGBAtoRGB() throws InterruptedException { + testImpl(true, false, false, false); + } + @Test + public void test11_RGBAtoRGBA() throws InterruptedException { + testImpl(true, true, false, false); + } + @Test + public void test21_RGBtoRGBA_pbuffer() throws InterruptedException { + testImpl(false, true, true, false); + } + @Test + public void test22_RGBtoRGBA_fbo() throws InterruptedException { + testImpl(false, true, false, true); + } + @Test + public void test31_RGBAtoRGBA_pbuffer() throws InterruptedException { + testImpl(true, true, true, false); + } + @Test + public void test32_RGBAtoRGBA_fbo() throws InterruptedException { + testImpl(true, true, false, true); + } + + private void testImpl(final boolean alphaCaps, final boolean readAlpha, boolean pbuffer, boolean fbo) throws InterruptedException { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(readAlpha ? true : false, false); + GLProfile glp = GLProfile.getGL2ES2(); + GLCapabilities caps = new GLCapabilities(glp); + + caps.setAlphaBits( alphaCaps ? 1 : 0 ); + caps.setPBuffer( pbuffer ); + caps.setFBO( fbo); + + final GLWindow window = GLWindow.create(caps); + window.addGLEventListener(new GearsES2()); + window.addGLEventListener(new GLEventListener() { + int displayCount = 0; + public void init(GLAutoDrawable drawable) {} + public void dispose(GLAutoDrawable drawable) {} + public void display(GLAutoDrawable drawable) { + final GLPixelBufferProvider pixelBufferProvider = screenshot.getPixelBufferProvider(); + final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(drawable.getGL(), readAlpha ? 4 : 3); + System.err.println("GLPixelAttributes: "+pixelAttribs); + snapshot(displayCount++, null, drawable.getGL(), screenshot, TextureIO.PNG, null); + } + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } + }); + window.setSize(512, 512); + window.setVisible(true); + window.requestFocus(); + + Thread.sleep(durationPerTest); + + window.destroy(); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite01AWT.java new file mode 100644 index 000000000..21987c504 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite01AWT.java @@ -0,0 +1,159 @@ +/** + * Copyright 2011 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.jogl.util.texture; + +import java.awt.Dimension; +import java.awt.Frame; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; + +import jogamp.nativewindow.jawt.JAWTUtil; + +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; + +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; + +import org.junit.Assert; +import org.junit.Assume; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLReadBufferUtilTextureIOWrite01AWT extends UITestCase { + static GLProfile glp; + static GLCapabilities caps; + static int width, height; + + @BeforeClass + public static void initClass() { + glp = GLProfile.getDefault(); + Assert.assertNotNull(glp); + caps = new GLCapabilities(glp); + Assert.assertNotNull(caps); + caps.setAlphaBits(1); // req. alpha channel + width = 256; + height = 256; + } + + protected void testWritePNG_Impl(boolean offscreenLayer) throws InterruptedException { + final GLReadBufferUtil screenshotRGB = new GLReadBufferUtil(false, false); + final GLReadBufferUtil screenshotRGBA = new GLReadBufferUtil(true, false); + + if(!offscreenLayer && JAWTUtil.isOffscreenLayerRequired()) { + System.err.println("onscreen layer n/a"); + return; + } + if(offscreenLayer && !JAWTUtil.isOffscreenLayerSupported()) { + System.err.println("offscreen layer n/a"); + return; + } + final GLCanvas glc = new GLCanvas(caps); + glc.setShallUseOffscreenLayer(offscreenLayer); // trigger offscreen layer - if supported + Dimension glc_sz = new Dimension(width, height); + glc.setMinimumSize(glc_sz); + glc.setPreferredSize(glc_sz); + final Frame frame = new Frame(getSimpleTestName(".")); + Assert.assertNotNull(frame); + frame.add(glc); + + glc.setSize(width, height); + glc.addGLEventListener(new GearsES2(1)); + glc.addGLEventListener(new GLEventListener() { + int f = 0; + public void init(GLAutoDrawable drawable) {} + public void dispose(GLAutoDrawable drawable) {} + public void display(GLAutoDrawable drawable) { + snapshot(f, null, drawable.getGL(), screenshotRGBA, TextureIO.PNG, null); + snapshot(f, null, drawable.getGL(), screenshotRGB, TextureIO.PNG, null); + f++; + } + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } + }); + + Animator animator = new Animator(glc); + animator.setUpdateFPSFrames(60, null); + + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.pack(); + frame.setVisible(true); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glc, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(glc, true)); + Assert.assertEquals(JAWTUtil.isOffscreenLayerSupported() && offscreenLayer, + glc.isOffscreenLayerSurfaceEnabled()); + animator.start(); + + while(animator.getTotalFPSFrames() < 2) { + Thread.sleep(60); + } + + animator.stop(); + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + frame.remove(glc); + frame.dispose(); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + } + + @Test + public void testOnscreenWritePNG() throws InterruptedException { + testWritePNG_Impl(false); + } + + @Test + public void testOffscreenWritePNG() throws InterruptedException { + testWritePNG_Impl(true); + } + + public static void main(String args[]) { + org.junit.runner.JUnitCore.main(TestGLReadBufferUtilTextureIOWrite01AWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/TestGLReadBufferUtilTextureIOWrite02NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite01NEWT.java index 79ae31612..521e89a8b 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/TestGLReadBufferUtilTextureIOWrite02NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite01NEWT.java @@ -26,11 +26,7 @@ * or implied, of JogAmp Community. */ -package com.jogamp.opengl.test.junit.jogl.util; - -import java.io.File; -import java.io.PrintWriter; -import java.io.StringWriter; +package com.jogamp.opengl.test.junit.jogl.util.texture; import com.jogamp.newt.opengl.GLWindow; @@ -39,15 +35,20 @@ import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.offscreen.WindowUtilNEWT; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; -public class TestGLReadBufferUtilTextureIOWrite02NEWT extends UITestCase { +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLReadBufferUtilTextureIOWrite01NEWT extends UITestCase { static GLProfile glp; static GLCapabilities caps; static int width, height; @@ -58,89 +59,65 @@ public class TestGLReadBufferUtilTextureIOWrite02NEWT extends UITestCase { Assert.assertNotNull(glp); caps = new GLCapabilities(glp); Assert.assertNotNull(caps); + caps.setAlphaBits(1); // req. alpha channel width = 256; height = 256; } - protected void snapshot(GLAutoDrawable drawable, GLReadBufferUtil screenshot, String filename) { - if(screenshot.readPixels(drawable.getGL(), drawable, false)) { - screenshot.write(new File(filename)); - } - } - @Test - public void testWriteTGAWithResize() throws InterruptedException { - final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); + public void testOnscreenWritePNG_TGA_PAM() throws InterruptedException { + final GLReadBufferUtil screenshotRGB = new GLReadBufferUtil(false, false); + final GLReadBufferUtil screenshotRGBA = new GLReadBufferUtil(true, false); GLWindow glWindow = GLWindow.create(caps); Assert.assertNotNull(glWindow); glWindow.setTitle("Shared Gears NEWT Test"); glWindow.setSize(width, height); glWindow.addGLEventListener(new GearsES2(1)); glWindow.addGLEventListener(new GLEventListener() { - int i=0; + int f = 0; public void init(GLAutoDrawable drawable) {} public void dispose(GLAutoDrawable drawable) {} public void display(GLAutoDrawable drawable) { - StringWriter filename = new StringWriter(); - { - PrintWriter pw = new PrintWriter(filename); - pw.printf("%s-rgba-%s-%03dx%03d-n%03d.tga", - getSimpleTestName("."), drawable.getGLProfile().getName(), - drawable.getWidth(), drawable.getHeight(), i++); - } - if(screenshot.readPixels(drawable.getGL(), drawable, false)) { - screenshot.write(new File(filename.toString())); - } + snapshot(f++, null, drawable.getGL(), screenshotRGBA, TextureIO.PNG, null); + snapshot(f++, null, drawable.getGL(), screenshotRGB, TextureIO.PNG, null); + snapshot(f++, null, drawable.getGL(), screenshotRGBA, TextureIO.TGA, null); + snapshot(f++, null, drawable.getGL(), screenshotRGB, TextureIO.TGA, null); + snapshot(f++, null, drawable.getGL(), screenshotRGBA, TextureIO.PAM, null); + snapshot(f++, null, drawable.getGL(), screenshotRGB, TextureIO.PAM, null); } - public void reshape(GLAutoDrawable drawable, int x, int y, - int width, int height) { } + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } }); glWindow.setVisible(true); Thread.sleep(60); - glWindow.setSize(300, 300); - Thread.sleep(60); - glWindow.setSize(400, 400); - Thread.sleep(60); - glWindow.destroy(); + glWindow.destroy(); } @Test - public void testWritePNGWithResize() throws InterruptedException { - final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); - GLWindow glWindow = GLWindow.create(caps); + public void testOffscreenWritePNG() throws InterruptedException { + final GLReadBufferUtil screenshotRGB = new GLReadBufferUtil(false, false); + final GLReadBufferUtil screenshotRGBA = new GLReadBufferUtil(true, false); + final GLCapabilities caps2 = WindowUtilNEWT.fixCaps(caps, false, true, false); + GLWindow glWindow = GLWindow.create(caps2); Assert.assertNotNull(glWindow); - glWindow.setTitle("Shared Gears NEWT Test"); glWindow.setSize(width, height); glWindow.addGLEventListener(new GearsES2(1)); glWindow.addGLEventListener(new GLEventListener() { - int i=0; + int f = 0; public void init(GLAutoDrawable drawable) {} public void dispose(GLAutoDrawable drawable) {} public void display(GLAutoDrawable drawable) { - StringWriter filename = new StringWriter(); - { - PrintWriter pw = new PrintWriter(filename); - pw.printf("%s-rgba-%s-%03dx%03d-n%03d.png", - getSimpleTestName("."), drawable.getGLProfile().getName(), - drawable.getWidth(), drawable.getHeight(), i++); - } - if(screenshot.readPixels(drawable.getGL(), drawable, false)) { - screenshot.write(new File(filename.toString())); - } + snapshot(f, null, drawable.getGL(), screenshotRGBA, TextureIO.PNG, null); + snapshot(f, null, drawable.getGL(), screenshotRGB, TextureIO.PNG, null); + f++; } - public void reshape(GLAutoDrawable drawable, int x, int y, - int width, int height) { } + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } }); glWindow.setVisible(true); Thread.sleep(60); - glWindow.setSize(300, 300); - Thread.sleep(60); - glWindow.setSize(400, 400); - Thread.sleep(60); - glWindow.destroy(); + glWindow.destroy(); } public static void main(String args[]) { - org.junit.runner.JUnitCore.main(TestGLReadBufferUtilTextureIOWrite02NEWT.class.getName()); + org.junit.runner.JUnitCore.main(TestGLReadBufferUtilTextureIOWrite01NEWT.class.getName()); } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02AWT.java new file mode 100644 index 000000000..3822bff09 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02AWT.java @@ -0,0 +1,184 @@ +/** + * Copyright 2011 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.jogl.util.texture; + +import java.awt.Dimension; +import java.awt.Frame; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; +import javax.media.opengl.Threading; +import javax.media.opengl.awt.GLCanvas; + +import jogamp.nativewindow.jawt.JAWTUtil; + +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; + +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; + +import org.junit.Assert; +import org.junit.Assume; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLReadBufferUtilTextureIOWrite02AWT extends UITestCase { + static GLProfile glp; + static GLCapabilities caps; + static int width, height; + + @BeforeClass + public static void initClass() { + glp = GLProfile.getDefault(); + Assert.assertNotNull(glp); + caps = new GLCapabilities(glp); + Assert.assertNotNull(caps); + caps.setAlphaBits(1); // req. alpha channel + width = 64; + height = 64; + } + + protected void testWritePNGWithResizeImpl(boolean offscreenLayer) throws InterruptedException { + if(!offscreenLayer && JAWTUtil.isOffscreenLayerRequired()) { + System.err.println("onscreen layer n/a"); + return; + } + if(offscreenLayer && !JAWTUtil.isOffscreenLayerSupported()) { + System.err.println("offscreen layer n/a"); + return; + } + final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); + final GLCanvas glc = new GLCanvas(caps); + glc.setShallUseOffscreenLayer(offscreenLayer); // trigger offscreen layer - if supported + Dimension glc_sz = new Dimension(width, height); + glc.setMinimumSize(glc_sz); + glc.setPreferredSize(glc_sz); + glc.setSize(glc_sz); + final Frame frame = new Frame(getSimpleTestName(".")); + Assert.assertNotNull(frame); + frame.add(glc); + + glc.addGLEventListener(new GearsES2(1)); + glc.addGLEventListener(new GLEventListener() { + int i=0, fw_old=0, dw_old=0, c=0; + public void init(GLAutoDrawable drawable) {} + public void dispose(GLAutoDrawable drawable) {} + public void display(GLAutoDrawable drawable) { + final int fw = frame.getWidth(); + final int fh = frame.getHeight(); + final int dw = drawable.getWidth(); + final int dh = drawable.getHeight(); + final boolean sz_changed = fw_old != fw && dw_old != dw && dw <= 512; // need to check both sizes [frame + drawable], due to async resize of AWT! + final boolean snap; + if(sz_changed) { + c++; + snap = c>3; // only snap the 3rd image .. + } else { + snap = false; + } + + if(snap) { + System.err.println("XXX: ["+fw_old+", "+dw_old+"], "+fw+"x"+fh+", "+dw+"x"+dh+", sz_changed "+sz_changed+", snap "+snap); + c=0; + snapshot(i++, null, drawable.getGL(), screenshot, TextureIO.PNG, null); + dw_old = dw; + fw_old = fw; + Threading.invoke(true, new Runnable() { + public void run() { + final Dimension new_sz = new Dimension(2*dw, 2*dh); + glc.setMinimumSize(new_sz); + glc.setPreferredSize(new_sz); + glc.setSize(new_sz); + frame.pack(); + frame.validate(); + } }, glc.getTreeLock()); + } + } + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } + }); + + Animator animator = new Animator(glc); + animator.setUpdateFPSFrames(60, null); + + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.pack(); + frame.setVisible(true); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glc, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(glc, true)); + Assert.assertEquals(JAWTUtil.isOffscreenLayerSupported() && offscreenLayer, + glc.isOffscreenLayerSurfaceEnabled()); + animator.start(); + + while(animator.getTotalFPSFrames() < 30) { + Thread.sleep(60); + } + + animator.stop(); + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + frame.remove(glc); + frame.dispose(); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + } + + @Test + public void testOnscreenWritePNGWithResize() throws InterruptedException { + testWritePNGWithResizeImpl(false); + } + + @Test + public void testOffscreenWritePNGWithResize() throws InterruptedException { + testWritePNGWithResizeImpl(true); + } + + public static void main(String args[]) { + org.junit.runner.JUnitCore.main(TestGLReadBufferUtilTextureIOWrite02AWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/TestGLReadBufferUtilTextureIOWrite01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02NEWT.java index ab8e54246..9615297e3 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/TestGLReadBufferUtilTextureIOWrite01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02NEWT.java @@ -26,9 +26,7 @@ * or implied, of JogAmp Community. */ -package com.jogamp.opengl.test.junit.jogl.util; - -import java.io.File; +package com.jogamp.opengl.test.junit.jogl.util.texture; import com.jogamp.newt.opengl.GLWindow; @@ -36,16 +34,23 @@ import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; + +import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.offscreen.WindowUtilNEWT; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; -public class TestGLReadBufferUtilTextureIOWrite01NEWT extends UITestCase { +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLReadBufferUtilTextureIOWrite02NEWT extends UITestCase { static GLProfile glp; static GLCapabilities caps; static int width, height; @@ -56,45 +61,78 @@ public class TestGLReadBufferUtilTextureIOWrite01NEWT extends UITestCase { Assert.assertNotNull(glp); caps = new GLCapabilities(glp); Assert.assertNotNull(caps); - width = 256; - height = 256; + caps.setAlphaBits(1); // req. alpha channel + width = 64; + height = 64; } - protected void snapshot(GLAutoDrawable drawable, boolean alpha, boolean flip, String filename) { - GLReadBufferUtil screenshot = new GLReadBufferUtil(alpha, false); - if(screenshot.readPixels(drawable.getGL(), drawable, flip)) { - screenshot.write(new File(filename)); - } - } - - @Test - public void testWritePNG_TGA_PAM() throws InterruptedException { - GLWindow glWindow = GLWindow.create(caps); + private void testWritePNGWithResizeImpl(boolean offscreen) throws InterruptedException { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); + final GLCapabilities caps2 = offscreen ? WindowUtilNEWT.fixCaps(caps, false, true, false) : caps; + final GLWindow glWindow = GLWindow.create(caps2); Assert.assertNotNull(glWindow); glWindow.setTitle("Shared Gears NEWT Test"); glWindow.setSize(width, height); glWindow.addGLEventListener(new GearsES2(1)); glWindow.addGLEventListener(new GLEventListener() { - public void init(GLAutoDrawable drawable) {} - public void dispose(GLAutoDrawable drawable) {} + int i=0, dw_old=0, c=0; + public void init(GLAutoDrawable drawable) { + System.err.println("XXX: init"); + } + public void dispose(GLAutoDrawable drawable) { + System.err.println("XXX: dispose"); + } public void display(GLAutoDrawable drawable) { - // snapshot(drawable, false, true, getSimpleTestName(".")+"-rgb_-"+drawable.getGLProfile().getName()+".ppm"); - snapshot(drawable, true, false, getSimpleTestName(".")+"-rgba-"+drawable.getGLProfile().getName()+".png"); - snapshot(drawable, true, false, getSimpleTestName(".")+"-rgba-"+drawable.getGLProfile().getName()+".tga"); - snapshot(drawable, true, true, getSimpleTestName(".")+"-rgba-"+drawable.getGLProfile().getName()+".pam"); - snapshot(drawable, false, false, getSimpleTestName(".")+"-rgb_-"+drawable.getGLProfile().getName()+".png"); - snapshot(drawable, false, false, getSimpleTestName(".")+"-rgb_-"+drawable.getGLProfile().getName()+".tga"); - snapshot(drawable, false, true, getSimpleTestName(".")+"-rgb_-"+drawable.getGLProfile().getName()+".pam"); + final int dw = drawable.getWidth(); + final int dh = drawable.getHeight(); + final boolean sz_changed = dw_old != dw && dw <= 512; + final boolean snap; + if(sz_changed) { + c++; + snap = c>1; // only snap the 3rd image .. + } else { + snap = false; + } + + if(snap) { + System.err.println("XXX: ["+dw_old+"], "+dw+"x"+dh+", sz_changed "+sz_changed+", snap "+snap); + c=0; + snapshot(i++, null, drawable.getGL(), screenshot, TextureIO.PNG, null); + dw_old = dw; + new Thread() { + @Override + public void run() { + glWindow.setSize(2*dw, 2*dh); + } }.start(); + } } - public void reshape(GLAutoDrawable drawable, int x, int y, - int width, int height) { } + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } }); + Animator animator = new Animator(glWindow); + animator.setUpdateFPSFrames(60, null); + glWindow.setVisible(true); - Thread.sleep(60); + animator.start(); + + while(animator.getTotalFPSFrames() < 50) { + Thread.sleep(60); + } + + animator.stop(); glWindow.destroy(); } + + @Test + public void testOnscreenWritePNGWithResize() throws InterruptedException { + testWritePNGWithResizeImpl(false); + } + + @Test + public void testOffscreenWritePNGWithResize() throws InterruptedException { + testWritePNGWithResizeImpl(true); + } public static void main(String args[]) { - org.junit.runner.JUnitCore.main(TestGLReadBufferUtilTextureIOWrite01NEWT.class.getName()); + org.junit.runner.JUnitCore.main(TestGLReadBufferUtilTextureIOWrite02NEWT.class.getName()); } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGImage01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGImage01NEWT.java new file mode 100644 index 000000000..c92174a77 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGImage01NEWT.java @@ -0,0 +1,166 @@ +/** + * Copyright 2012 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.jogl.util.texture; + +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URLConnection; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.common.util.IOUtil; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.jogl.demos.TextureDraw01Accessor; +import com.jogamp.opengl.test.junit.jogl.demos.es2.TextureDraw01ES2Listener; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureData; +import com.jogamp.opengl.util.texture.TextureIO; +import com.jogamp.opengl.util.texture.spi.JPEGImage; +import javax.media.opengl.GL; + +/** + * Test reading and displaying a JPG image. + * <p> + * Main function accepts arbitrary JPG file name for manual tests. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestJPEGImage01NEWT extends UITestCase { + + static boolean showFPS = false; + static long duration = 100; // ms + + public void testImpl(final InputStream istream) throws InterruptedException, IOException { + final JPEGImage image = JPEGImage.read(istream); + Assert.assertNotNull(image); + final boolean hasAlpha = 4 == image.getBytesPerPixel(); + System.err.println("JPEGImage: "+image+", hasAlpha "+hasAlpha); + + final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities(glp); + if( hasAlpha ) { + caps.setAlphaBits(1); + } + + final int internalFormat; + if(glp.isGL2ES3()) { + internalFormat = hasAlpha ? GL.GL_RGBA8 : GL.GL_RGB8; + } else { + internalFormat = hasAlpha ? GL.GL_RGBA : GL.GL_RGB; + } + final TextureData texData = new TextureData(glp, internalFormat, + image.getWidth(), + image.getHeight(), + 0, + new GLPixelAttributes(image.getGLFormat(), image.getGLType()), + false /* mipmap */, + false /* compressed */, + false /* must flip-vert */, + image.getData(), + null); + // final TextureData texData = TextureIO.newTextureData(glp, istream, false /* mipmap */, TextureIO.JPG); + System.err.println("TextureData: "+texData); + + final GLWindow glad = GLWindow.create(caps); + glad.setTitle("TestJPEGImage01NEWT"); + // Size OpenGL to Video Surface + glad.setSize(texData.getWidth(), texData.getHeight()); + + // load texture from file inside current GL context to match the way + // the bug submitter was doing it + final GLEventListener gle = new TextureDraw01ES2Listener( texData, 0 ) ; + glad.addGLEventListener(gle); + glad.addGLEventListener(new GLEventListener() { + boolean shot = false; + + @Override public void init(GLAutoDrawable drawable) {} + + public void display(GLAutoDrawable drawable) { + // 1 snapshot + if(null!=((TextureDraw01Accessor)gle).getTexture() && !shot) { + shot = true; + snapshot(0, null, drawable.getGL(), screenshot, TextureIO.PNG, null); + } + } + + @Override public void dispose(GLAutoDrawable drawable) { } + @Override public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } + }); + + Animator animator = new Animator(glad); + animator.setUpdateFPSFrames(60, showFPS ? System.err : null); + QuitAdapter quitAdapter = new QuitAdapter(); + glad.addKeyListener(quitAdapter); + glad.addWindowListener(quitAdapter); + glad.setVisible(true); + animator.start(); + + while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) { + Thread.sleep(100); + } + + animator.stop(); + glad.destroy(); + } + + @Test + public void testReadES2_RGBn() throws InterruptedException, IOException, MalformedURLException { + final String fname = null == _fname ? "test-ntscN_3-01-160x90-90pct-yuv444-base.jpg" : _fname; + final URLConnection urlConn = IOUtil.getResource(this.getClass(), fname); + testImpl(urlConn.getInputStream()); + } + + static String _fname = null; + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-file")) { + i++; + _fname = args[i]; + } + } + org.junit.runner.JUnitCore.main(TestJPEGImage01NEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTBenchmarkNewtAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTBenchmarkNewtAWT.java new file mode 100644 index 000000000..bd2488e26 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTBenchmarkNewtAWT.java @@ -0,0 +1,154 @@ +/** + * Copyright 2012 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.jogl.util.texture; + + +import com.jogamp.common.util.IOUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; + +import javax.imageio.ImageIO; +import javax.media.opengl.GL; +import javax.media.opengl.GLProfile; + +import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes; +import com.jogamp.opengl.util.texture.TextureData; +import com.jogamp.opengl.util.texture.awt.AWTTextureData; +import com.jogamp.opengl.util.texture.spi.JPEGImage; + +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.InputStream; +import java.net.URLConnection; +import java.nio.Buffer; + +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestJPEGJoglAWTBenchmarkNewtAWT extends UITestCase { + static boolean showFPS = false; + static String fname = "j1-baseline.jpg"; + + @Test + public void benchmark() throws IOException { + benchmarkImpl(100, fname); + } + void benchmarkImpl(int loops, String fname) throws IOException { + { + final long t0 = System.currentTimeMillis(); + for(int i = 0; i< loops; i++ ) { + final URLConnection urlConn = IOUtil.getResource(this.getClass(), fname); + final InputStream istream = urlConn.getInputStream(); + final JPEGImage image = JPEGImage.read(istream); // parsing & completion done !!! + final int internalFormat = (image.getBytesPerPixel()==4)?GL.GL_RGBA:GL.GL_RGB; + final TextureData texData = new TextureData(GLProfile.getGL2ES2(), internalFormat, + image.getWidth(), + image.getHeight(), + 0, + new GLPixelAttributes(image.getGLFormat(), image.getGLType()), + false /* mipmap */, + false /* compressed */, + false /* must flip-vert */, + image.getData(), + null); + if(0==i || loops-1==i) { + System.err.println(i+": "+image.toString()); + System.err.println(i+": "+texData+", buffer "+texData.getBuffer()); + } + istream.close(); + } + final long t1 = System.currentTimeMillis(); + final long dt = t1 - t0; + final float msPl = (float)dt / (float)loops ; + System.err.println("JOGL.RGB Loops "+loops+", dt "+dt+" ms, "+msPl+" ms/l"); + } + { + final long t0 = System.currentTimeMillis(); + for(int i = 0; i< loops; i++ ) { + final URLConnection urlConn = IOUtil.getResource(this.getClass(), fname); + final InputStream istream = urlConn.getInputStream(); + final JPEGImage image = JPEGImage.read(istream, TextureData.ColorSpace.YCbCr); // parsing & completion done !!! + final int internalFormat = (image.getBytesPerPixel()==4)?GL.GL_RGBA:GL.GL_RGB; + final TextureData texData = new TextureData(GLProfile.getGL2ES2(), internalFormat, + image.getWidth(), + image.getHeight(), + 0, + new GLPixelAttributes(image.getGLFormat(), image.getGLType()), + false /* mipmap */, + false /* compressed */, + false /* must flip-vert */, + image.getData(), + null); + if(0==i || loops-1==i) { + System.err.println(i+": "+image.toString()); + System.err.println(i+": "+texData+", buffer "+texData.getBuffer()); + } + istream.close(); + } + final long t1 = System.currentTimeMillis(); + final long dt = t1 - t0; + final float msPl = (float)dt / (float)loops ; + System.err.println("JOGL.YUV Loops "+loops+", dt "+dt+" ms, "+msPl+" ms/l"); + } + { + final long t0 = System.currentTimeMillis(); + for(int i = 0; i< loops; i++ ) { + final URLConnection urlConn = IOUtil.getResource(this.getClass(), fname); + final InputStream istream = urlConn.getInputStream(); + Buffer data = null; + try { + BufferedImage img = ImageIO.read(istream); + AWTTextureData texData = new AWTTextureData(GLProfile.getGL2ES2(), 0, 0, false, img); + data = texData.getBuffer(); // completes data conversion !!! + if(0==i || loops-1==i) { + System.err.println(i+": "+texData+", buffer "+data); + } + } catch (Exception e) { + System.err.println("AWT ImageIO failure w/ file "+fname+": "+e.getMessage()); + } + istream.close(); + } + final long t1 = System.currentTimeMillis(); + final long dt = t1 - t0; + final float msPl = (float)dt / (float)loops ; + System.err.println("AWT..... Loops "+loops+", dt "+dt+" ms, "+msPl+" ms/l"); + } + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-file")) { + i++; + fname = args[i]; + } + } + org.junit.runner.JUnitCore.main(TestJPEGJoglAWTBenchmarkNewtAWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTCompareNewtAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTCompareNewtAWT.java new file mode 100644 index 000000000..dbb4002a3 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTCompareNewtAWT.java @@ -0,0 +1,270 @@ +/** + * Copyright 2012 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.jogl.util.texture; + + +import com.jogamp.common.util.IOUtil; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.jogl.demos.TextureDraw01Accessor; +import com.jogamp.opengl.test.junit.jogl.demos.es2.TextureDraw01ES2Listener; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.test.junit.util.UITestCase; + +import javax.imageio.ImageIO; +import javax.media.opengl.GL; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; +import javax.media.opengl.GLCapabilities; + +import com.jogamp.opengl.util.texture.TextureData; +import com.jogamp.opengl.util.texture.TextureIO; +import com.jogamp.opengl.util.texture.awt.AWTTextureData; +import com.jogamp.opengl.util.texture.spi.JPEGImage; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes; +import com.jogamp.opengl.util.GLReadBufferUtil; + +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.InputStream; +import java.net.URLConnection; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestJPEGJoglAWTCompareNewtAWT extends UITestCase { + static boolean showFPS = false; + static long duration = 100; // ms + + String[] files = { "test-ntscN_3-01-160x90-90pct-yuv444-base.jpg", // 0 + "test-ntscN_3-01-160x90-90pct-yuv444-prog.jpg", // 1 + "test-ntscN_3-01-160x90-60pct-yuv422h-base.jpg", // 2 + "test-ntscN_3-01-160x90-60pct-yuv422h-prog.jpg", // 3 + "j1-baseline.jpg", // 4 + "j2-progressive.jpg", // 5 + "j3-baseline_gray.jpg", // 6 + "test-cmyk-01.jpg", // 7 + "test-ycck-01.jpg" }; // 8 + + void testImpl(final String fname) throws InterruptedException, IOException { + final Animator animator = new Animator(); + + final GLWindow w1 = testJOGLJpeg(fname); + final GLWindow w2 = testAWTJpeg(fname, w1.getWidth() + 50); + + animator.add(w1); + animator.add(w2); + animator.setUpdateFPSFrames(60, showFPS ? System.err : null); + QuitAdapter quitAdapter = new QuitAdapter(); + w1.setVisible(true); + w2.setVisible(true); + animator.start(); + + while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) { + Thread.sleep(100); + } + + animator.stop(); + w1.destroy(); + w2.destroy(); + } + + GLWindow testJOGLJpeg(final String fname) throws InterruptedException, IOException { + URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), fname); + Assert.assertNotNull(testTextureUrlConn); + InputStream istream = testTextureUrlConn.getInputStream(); + Assert.assertNotNull(istream); + + final JPEGImage image = JPEGImage.read(istream); + Assert.assertNotNull(image); + System.err.println("JPEGImage: "+image); + + GLProfile glp = GLProfile.getGL2ES2(); + final int internalFormat = (image.getBytesPerPixel()==4)?GL.GL_RGBA:GL.GL_RGB; + final TextureData texData = new TextureData(glp, internalFormat, + image.getWidth(), + image.getHeight(), + 0, + new GLPixelAttributes(image.getGLFormat(), image.getGLType()), + false /* mipmap */, + false /* compressed */, + false /* must flip-vert */, + image.getData(), + null); + // final TextureData texData = TextureIO.newTextureData(glp, istream, false /* mipmap */, TextureIO.JPG); + System.err.println("TextureData: "+texData); + + final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setAlphaBits(1); + + final GLWindow glad1 = GLWindow.create(caps); + glad1.setTitle("JPEG JOGL"); + // Size OpenGL to Video Surface + glad1.setSize(texData.getWidth(), texData.getHeight()); + glad1.setPosition(0, 0); + + // load texture from file inside current GL context to match the way + // the bug submitter was doing it + final GLEventListener gle = new TextureDraw01ES2Listener( texData, 0 ) ; + glad1.addGLEventListener(gle); + glad1.addGLEventListener(new GLEventListener() { + boolean shot = false; + + @Override public void init(GLAutoDrawable drawable) {} + + public void display(GLAutoDrawable drawable) { + // 1 snapshot + if(null!=((TextureDraw01Accessor)gle).getTexture() && !shot) { + shot = true; + snapshot(0, "JoglJPEG", drawable.getGL(), screenshot, TextureIO.PNG, null); + } + } + + @Override public void dispose(GLAutoDrawable drawable) { } + @Override public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } + }); + + return glad1; + } + + GLWindow testAWTJpeg(final String fname, int xpos) throws InterruptedException, IOException { + URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), fname); + Assert.assertNotNull(testTextureUrlConn); + InputStream istream = testTextureUrlConn.getInputStream(); + Assert.assertNotNull(istream); + + GLProfile glp = GLProfile.getGL2ES2(); + TextureData texData = null; + int w = 300, h = 300; + try { + BufferedImage img = ImageIO.read(istream); + texData = new AWTTextureData(glp, 0, 0, false, img); + System.err.println("TextureData: "+texData); + w = texData.getWidth(); + h = texData.getHeight(); + } catch (Exception e) { + System.err.println("AWT ImageIO failure w/ file "+fname+": "+e.getMessage()); + // e.printStackTrace(); // : CMYK, YCCK -> com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(Unknown Source) + } + + final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setAlphaBits(1); + + final GLWindow glad1 = GLWindow.create(caps); + glad1.setTitle("JPEG AWT"); + // Size OpenGL to Video Surface + glad1.setSize(w, h); + glad1.setPosition(xpos, 0); + + // load texture from file inside current GL context to match the way + // the bug submitter was doing it + final GLEventListener gle; + if( texData != null ) { + gle = new TextureDraw01ES2Listener( texData, 0 ) ; + glad1.addGLEventListener(gle); + } else { + gle = null; + } + glad1.addGLEventListener(new GLEventListener() { + boolean shot = false; + + @Override public void init(GLAutoDrawable drawable) {} + + public void display(GLAutoDrawable drawable) { + // 1 snapshot + if( null!=gle && null!=((TextureDraw01Accessor)gle).getTexture() && !shot) { + shot = true; + snapshot(0, "AWTJPEG", drawable.getGL(), screenshot, TextureIO.PNG, null); + } + } + + @Override public void dispose(GLAutoDrawable drawable) { } + @Override public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } + }); + + return glad1; + } + + @Test + public void test01YUV444Base__ES2() throws InterruptedException, IOException { + testImpl(files[0]); + } + @Test + public void test01YUV444Prog__ES2() throws InterruptedException, IOException { + testImpl(files[1]); + } + + @Test + public void test01YUV422hBase__ES2() throws InterruptedException, IOException { + testImpl(files[2]); + } + @Test + public void test01YUV422hProg_ES2() throws InterruptedException, IOException { + testImpl(files[3]); + } + + @Test + public void test02YUV420Base__ES2() throws InterruptedException, IOException { + testImpl(files[4]); + } + @Test + public void test02YUV420Prog_ES2() throws InterruptedException, IOException { + testImpl(files[5]); + } + @Test + public void test02YUV420BaseGray_ES2() throws InterruptedException, IOException { + testImpl(files[6]); + } + + @Test + public void test03CMYK_01_ES2() throws InterruptedException, IOException { + testImpl(files[7]); + } + @Test + public void test03YCCK_01_ES2() throws InterruptedException, IOException { + testImpl(files[8]); + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } + } + org.junit.runner.JUnitCore.main(TestJPEGJoglAWTCompareNewtAWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGTextureFromFileNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGTextureFromFileNEWT.java new file mode 100644 index 000000000..60855e5be --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGTextureFromFileNEWT.java @@ -0,0 +1,284 @@ +/** + * Copyright 2012 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.jogl.util.texture; + + +import com.jogamp.common.util.IOUtil; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.jogl.demos.TextureDraw01Accessor; +import com.jogamp.opengl.test.junit.jogl.demos.es2.TextureDraw01ES2Listener; +import com.jogamp.opengl.test.junit.jogl.demos.gl2.TextureDraw01GL2Listener; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.test.junit.util.UITestCase; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; +import javax.media.opengl.GLCapabilities; + +import com.jogamp.opengl.util.texture.TextureData; +import com.jogamp.opengl.util.texture.TextureIO; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.GLReadBufferUtil; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URLConnection; + +import org.junit.Assert; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestJPEGTextureFromFileNEWT extends UITestCase { + static boolean showFPS = false; + static long duration = 100; // ms + + InputStream testTextureStream01YUV444_Base; + InputStream testTextureStream01YUV444_Prog; + + InputStream testTextureStream01YUV422h_Base; + InputStream testTextureStream01YUV422h_Prog; + + InputStream testTextureStream02YUV420_Base; + InputStream testTextureStream02YUV420_Prog; + InputStream testTextureStream02YUV420_BaseGray; + + InputStream testTextureStream03CMYK_01; + InputStream testTextureStream03YCCK_01; + + InputStream testTextureStream04QTTDefPostFrame; + + @Before + public void initTest() throws IOException { + { + URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscN_3-01-160x90-90pct-yuv444-base.jpg"); + Assert.assertNotNull(testTextureUrlConn); + testTextureStream01YUV444_Base = testTextureUrlConn.getInputStream(); + Assert.assertNotNull(testTextureStream01YUV444_Base); + } + { + URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscN_3-01-160x90-90pct-yuv444-prog.jpg"); + Assert.assertNotNull(testTextureUrlConn); + testTextureStream01YUV444_Prog = testTextureUrlConn.getInputStream(); + Assert.assertNotNull(testTextureStream01YUV444_Prog); + } + { + URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscN_3-01-160x90-60pct-yuv422h-base.jpg"); + Assert.assertNotNull(testTextureUrlConn); + testTextureStream01YUV422h_Base = testTextureUrlConn.getInputStream(); + Assert.assertNotNull(testTextureStream01YUV422h_Base); + } + { + URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscN_3-01-160x90-60pct-yuv422h-prog.jpg"); + Assert.assertNotNull(testTextureUrlConn); + testTextureStream01YUV422h_Prog = testTextureUrlConn.getInputStream(); + Assert.assertNotNull(testTextureStream01YUV422h_Prog); + } + + { + URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "j1-baseline.jpg"); + Assert.assertNotNull(testTextureUrlConn); + testTextureStream02YUV420_Base = testTextureUrlConn.getInputStream(); + Assert.assertNotNull(testTextureStream02YUV420_Base); + } + { + URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "j2-progressive.jpg"); + Assert.assertNotNull(testTextureUrlConn); + testTextureStream02YUV420_Prog = testTextureUrlConn.getInputStream(); + Assert.assertNotNull(testTextureStream02YUV420_Prog); + } + { + URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "j3-baseline_gray.jpg"); + Assert.assertNotNull(testTextureUrlConn); + testTextureStream02YUV420_BaseGray = testTextureUrlConn.getInputStream(); + Assert.assertNotNull(testTextureStream02YUV420_BaseGray); + } + + { + URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-cmyk-01.jpg"); + Assert.assertNotNull(testTextureUrlConn); + testTextureStream03CMYK_01 = testTextureUrlConn.getInputStream(); + Assert.assertNotNull(testTextureStream03CMYK_01); + } + { + URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ycck-01.jpg"); + Assert.assertNotNull(testTextureUrlConn); + testTextureStream03YCCK_01 = testTextureUrlConn.getInputStream(); + Assert.assertNotNull(testTextureStream03YCCK_01); + } + { + URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "bug745_qttdef_post_frame.jpg"); + Assert.assertNotNull(testTextureUrlConn); + testTextureStream04QTTDefPostFrame = testTextureUrlConn.getInputStream(); + Assert.assertNotNull(testTextureStream04QTTDefPostFrame); + } + + } + + @After + public void cleanupTest() { + testTextureStream01YUV444_Base = null; + testTextureStream01YUV444_Prog = null; + testTextureStream01YUV422h_Base = null; + testTextureStream01YUV422h_Prog = null; + testTextureStream02YUV420_Base = null; + testTextureStream02YUV420_Prog = null; + testTextureStream02YUV420_BaseGray = null; + testTextureStream03CMYK_01 = null; + testTextureStream03YCCK_01 = null; + testTextureStream04QTTDefPostFrame = null; + } + + public void testImpl(boolean useFFP, final InputStream istream) throws InterruptedException, IOException { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); + GLProfile glp; + if(useFFP && GLProfile.isAvailable(GLProfile.GL2)) { + glp = GLProfile.getMaxFixedFunc(true); + } else if(!useFFP && GLProfile.isAvailable(GLProfile.GL2ES2)) { + glp = GLProfile.getGL2ES2(); + } else { + System.err.println(getSimpleTestName(".")+": GLProfile n/a, useFFP: "+useFFP); + return; + } + final GLCapabilities caps = new GLCapabilities(glp); + caps.setAlphaBits(1); + + final TextureData texData = TextureIO.newTextureData(glp, istream, false /* mipmap */, TextureIO.JPG); + System.err.println("TextureData: "+texData); + + final GLWindow glad = GLWindow.create(caps); + glad.setTitle("TestPNGTextureGL2FromFileNEWT"); + // Size OpenGL to Video Surface + glad.setSize(texData.getWidth(), texData.getHeight()); + + // load texture from file inside current GL context to match the way + // the bug submitter was doing it + final GLEventListener gle = useFFP ? new TextureDraw01GL2Listener( texData ) : new TextureDraw01ES2Listener( texData, 0 ) ; + glad.addGLEventListener(gle); + glad.addGLEventListener(new GLEventListener() { + boolean shot = false; + + @Override public void init(GLAutoDrawable drawable) {} + + public void display(GLAutoDrawable drawable) { + // 1 snapshot + if(null!=((TextureDraw01Accessor)gle).getTexture() && !shot) { + shot = true; + snapshot(0, null, drawable.getGL(), screenshot, TextureIO.PNG, null); + } + } + + @Override public void dispose(GLAutoDrawable drawable) { } + @Override public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } + }); + + Animator animator = new Animator(glad); + animator.setUpdateFPSFrames(60, showFPS ? System.err : null); + QuitAdapter quitAdapter = new QuitAdapter(); + glad.addKeyListener(quitAdapter); + glad.addWindowListener(quitAdapter); + glad.setVisible(true); + animator.start(); + + while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) { + Thread.sleep(100); + } + + animator.stop(); + glad.destroy(); + } + + @Test + public void test01YUV444Base__GL2() throws InterruptedException, IOException { + testImpl(true, testTextureStream01YUV444_Base); + } + @Test + public void test01YUV444Base__ES2() throws InterruptedException, IOException { + testImpl(false, testTextureStream01YUV444_Base); + } + @Test + public void test01YUV444Prog__GL2() throws InterruptedException, IOException { + testImpl(true, testTextureStream01YUV444_Prog); + } + @Test + public void test01YUV444Prog__ES2() throws InterruptedException, IOException { + testImpl(false, testTextureStream01YUV444_Prog); + } + + @Test + public void test01YUV422hBase__ES2() throws InterruptedException, IOException { + testImpl(false, testTextureStream01YUV422h_Base); + } + @Test + public void test01YUV422hProg_ES2() throws InterruptedException, IOException { + testImpl(false, testTextureStream01YUV422h_Prog); + } + + @Test + public void test02YUV420Base__ES2() throws InterruptedException, IOException { + testImpl(false, testTextureStream02YUV420_Base); + } + @Test + public void test02YUV420Prog_ES2() throws InterruptedException, IOException { + testImpl(false, testTextureStream02YUV420_Prog); + } + @Test + public void test02YUV420BaseGray_ES2() throws InterruptedException, IOException { + testImpl(false, testTextureStream02YUV420_BaseGray); + } + + @Test + public void test03CMYK_01_ES2() throws InterruptedException, IOException { + testImpl(false, testTextureStream03CMYK_01); + } + @Test + public void test03YCCK_01_ES2() throws InterruptedException, IOException { + testImpl(false, testTextureStream03YCCK_01); + } + + @Test + public void test04QTTDefPostFrame_ES2() throws InterruptedException, IOException { + testImpl(false, testTextureStream04QTTDefPostFrame); + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } + } + org.junit.runner.JUnitCore.main(TestJPEGTextureFromFileNEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect00NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect00NEWT.java new file mode 100644 index 000000000..c2b39f0f3 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect00NEWT.java @@ -0,0 +1,226 @@ +/** + * Copyright 2014 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.jogl.util.texture; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.net.MalformedURLException; +import java.net.URLConnection; + +import javax.media.nativewindow.util.PixelFormat; +import javax.media.nativewindow.util.PixelFormatUtil; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.common.util.IOUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.PNGPixelRect; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestPNGPixelRect00NEWT extends UITestCase { + @Test + public void testPNGRead01_All() throws InterruptedException, IOException, MalformedURLException { + for(int i=0; i<PNGTstFiles.allBasenames.length; i++) { + final String basename = PNGTstFiles.allBasenames[i]; + final String pathname=""; + testPNG01Impl(pathname, basename, null, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); + } + } + + @Test + public void testPNGRead02_RGB888_to_RGBA8888() throws InterruptedException, IOException, MalformedURLException { + final String basename ="test-ntscN_3-01-160x90"; + final String pathname=""; + testPNG01Impl(pathname, basename, PixelFormat.RGBA8888, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); + } + + @Test + public void testPNGRead03_RGB888_to_RGBA8888_stride1000() throws InterruptedException, IOException, MalformedURLException { + final String basename ="test-ntscN_3-01-160x90"; // 640 bytes = 4 * 160 + final String pathname=""; + testPNG01Impl(pathname, basename, PixelFormat.RGBA8888, 1000 /* destMinStrideInBytes */, false /* destIsGLOriented */); + } + + @Test + public void testPNGRead04_RGB888_to_RGBA8888_stride999() throws InterruptedException, IOException, MalformedURLException { + final String basename ="test-ntscN_3-01-160x90"; // 640 bytes = 4 * 160 + final String pathname=""; + testPNG01Impl(pathname, basename, PixelFormat.RGBA8888, 999 /* destMinStrideInBytes */, false /* destIsGLOriented */); + } + + @Test + public void testPNGRead11_RGBA8888_to_LUMINA() throws InterruptedException, IOException, MalformedURLException { + final String basename ="test-ntscN_4-01-160x90"; + final String pathname=""; + testPNG02Impl(pathname, basename, PixelFormat.LUMINANCE, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); + } + + @Test + public void testPNGRead12_RGBA8888_to_RGB888() throws InterruptedException, IOException, MalformedURLException { + final String basename ="test-ntscN_4-01-160x90"; + final String pathname=""; + testPNG02Impl(pathname, basename, PixelFormat.RGB888, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); + } + + @Test + public void testPNGRead13_RGBA8888_to_BGR888() throws InterruptedException, IOException, MalformedURLException { + final String basename ="test-ntscN_4-01-160x90"; + final String pathname=""; + testPNG02Impl(pathname, basename, PixelFormat.BGR888, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); + } + + @Test + public void testPNGRead14_RGBA8888_to_BGRA8888() throws InterruptedException, IOException, MalformedURLException { + final String basename ="test-ntscN_4-01-160x90"; + final String pathname=""; + testPNG02Impl(pathname, basename, PixelFormat.BGRA8888, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); + } + @Test + public void testPNGRead15_RGBA8888_to_ARGB8888() throws InterruptedException, IOException, MalformedURLException { + final String basename ="test-ntscN_4-01-160x90"; + final String pathname=""; + testPNG02Impl(pathname, basename, PixelFormat.ARGB8888, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); + } + @Test + public void testPNGRead16_RGBA8888_to_ABGR8888() throws InterruptedException, IOException, MalformedURLException { + final String basename ="test-ntscN_4-01-160x90"; + final String pathname=""; + testPNG02Impl(pathname, basename, PixelFormat.ABGR8888, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); + } + + private void testPNG01Impl(final String pathname, final String basename, + final PixelFormat destFmt, final int destMinStrideInBytes, final boolean destIsGLOriented) + throws InterruptedException, IOException, MalformedURLException + { + System.err.println("Test01: "+pathname+basename+".png, destFmt "+destFmt+", destMinStrideInBytes "+destMinStrideInBytes+", destIsGLOriented "+destIsGLOriented); + + final File out1_f=new File(getSimpleTestName(".")+"-01-"+basename+"-orig.png"); + final File out2F_f=new File(getSimpleTestName(".")+"-02-"+basename+"-flipped.png"); + final File out2R_f=new File(getSimpleTestName(".")+"-03-"+basename+"-reversed.png"); + final File out2RF_f=new File(getSimpleTestName(".")+"-04-"+basename+"-reversed_flipped.png"); + URLConnection urlConn = IOUtil.getResource(this.getClass(), pathname+basename+".png"); + if( null == urlConn ) { + throw new IOException("Cannot find "+pathname+basename+".png"); + } + final PNGPixelRect image1 = PNGPixelRect.read(urlConn.getInputStream(), destFmt, false /* directBuffer */, destMinStrideInBytes, destIsGLOriented); + System.err.println("PNGPixelRect - Orig: "+image1); + { + final OutputStream outs = new BufferedOutputStream(IOUtil.getFileOutputStream(out1_f, true /* allowOverwrite */)); + image1.write(outs, true /* close */); + { + final PNGPixelRect image1_R = PNGPixelRect.read(out1_f.toURI().toURL().openStream(), image1.getPixelformat(), false /* directBuffer */, destMinStrideInBytes, destIsGLOriented); + System.err.println("PNGPixelRect - Orig (Read Back): "+image1_R); + Assert.assertEquals(image1.getPixels(), image1_R.getPixels()); + } + } + + // + // Flipped Orientation + // + { + final PNGPixelRect image2F = new PNGPixelRect(image1.getPixelformat(), image1.getSize(), + image1.getStride(), !image1.isGLOriented(), image1.getPixels(), + image1.getDpi()[0], image1.getDpi()[1]); + System.err.println("PNGPixelRect - Flip : "+image2F); + final OutputStream outs = new BufferedOutputStream(IOUtil.getFileOutputStream(out2F_f, true /* allowOverwrite */)); + image2F.write(outs, true /* close */); + { + // flip again .. to compare w/ original + final PNGPixelRect image2F_R = PNGPixelRect.read(out2F_f.toURI().toURL().openStream(), image1.getPixelformat(), false /* directBuffer */, destMinStrideInBytes, !destIsGLOriented); + System.err.println("PNGPixelRect - Flip (Read Back): "+image2F_R); + Assert.assertEquals(image1.getPixels(), image2F_R.getPixels()); + } + } + + // + // Reversed Components + // + final PixelFormat revFmt = PixelFormatUtil.getReversed(image1.getPixelformat()); + { + final PNGPixelRect image2R = new PNGPixelRect(revFmt, image1.getSize(), + image1.getStride(), image1.isGLOriented(), image1.getPixels(), + image1.getDpi()[0], image1.getDpi()[1]); + System.err.println("PNGPixelRect - Reversed : "+image2R); + final OutputStream outs = new BufferedOutputStream(IOUtil.getFileOutputStream(out2R_f, true /* allowOverwrite */)); + image2R.write(outs, true /* close */); + { + // reverse again .. to compare w/ original + final PNGPixelRect image2R_R = PNGPixelRect.read(out2R_f.toURI().toURL().openStream(), revFmt, false /* directBuffer */, destMinStrideInBytes, destIsGLOriented); + System.err.println("PNGPixelRect - Reversed (Read Back): "+image2R_R); + Assert.assertEquals(image1.getPixels(), image2R_R.getPixels()); + } + } + + // reversed channels and flipped + { + final PNGPixelRect image2RF = new PNGPixelRect(revFmt, image1.getSize(), + image1.getStride(), !image1.isGLOriented(), image1.getPixels(), + image1.getDpi()[0], image1.getDpi()[1]); + System.err.println("PNGPixelRect - Reversed+Flipped : "+image2RF); + final OutputStream outs = new BufferedOutputStream(IOUtil.getFileOutputStream(out2RF_f, true /* allowOverwrite */)); + image2RF.write(outs, true /* close */); + { + // reverse+flip again .. to compare w/ original + final PNGPixelRect image2RF_R = PNGPixelRect.read(out2RF_f.toURI().toURL().openStream(), revFmt, false /* directBuffer */, destMinStrideInBytes, !destIsGLOriented); + System.err.println("PNGPixelRect - Reversed+FLipped (Read Back): "+image2RF_R); + Assert.assertEquals(image1.getPixels(), image2RF_R.getPixels()); + } + } + } + + private void testPNG02Impl(final String pathname, final String basename, + final PixelFormat destFmt, final int destMinStrideInBytes, final boolean destIsGLOriented) + throws InterruptedException, IOException, MalformedURLException + { + System.err.println("Test02: "+pathname+basename+".png, destFmt "+destFmt+", destMinStrideInBytes "+destMinStrideInBytes+", destIsGLOriented "+destIsGLOriented); + + final File out1_f=new File(getSimpleTestName(".")+"-"+basename+"-orig.png"); + URLConnection urlConn = IOUtil.getResource(this.getClass(), pathname+basename+".png"); + + final PNGPixelRect image1 = PNGPixelRect.read(urlConn.getInputStream(), destFmt, false /* directBuffer */, destMinStrideInBytes, destIsGLOriented); + System.err.println("PNGPixelRect - Orig: "+image1); + { + final OutputStream outs = new BufferedOutputStream(IOUtil.getFileOutputStream(out1_f, true /* allowOverwrite */)); + image1.write(outs, true /* close */); + { + final PNGPixelRect image1_R = PNGPixelRect.read(out1_f.toURI().toURL().openStream(), image1.getPixelformat(), false /* directBuffer */, destMinStrideInBytes, destIsGLOriented); + System.err.println("PNGPixelRect - Orig (Read Back): "+image1_R); + Assert.assertEquals(image1.getPixels(), image1_R.getPixels()); + } + } + } + + public static void main(String args[]) { + org.junit.runner.JUnitCore.main(TestPNGPixelRect00NEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect01NEWT.java new file mode 100644 index 000000000..3b1d9fbb0 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect01NEWT.java @@ -0,0 +1,207 @@ +/** + * 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.jogl.util.texture; + +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URLConnection; + +import javax.media.nativewindow.util.PixelFormat; +import javax.media.opengl.GL; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.common.util.IOUtil; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.jogl.demos.TextureDraw01Accessor; +import com.jogamp.opengl.test.junit.jogl.demos.es2.TextureDraw01ES2Listener; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.PNGPixelRect; +import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes; +import com.jogamp.opengl.util.texture.TextureData; +import com.jogamp.opengl.util.texture.TextureIO; + +/** + * Test reading and displaying a PNG image. + * <p> + * Main function accepts arbitrary PNG file name for manual tests. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestPNGPixelRect01NEWT extends UITestCase { + static boolean showFPS = false; + static long duration = 200; // ms + + public void testImpl(final int num, final String basename, final InputStream istream, final PixelFormat destFmt) throws InterruptedException, IOException { + final GLProfile glp = GLProfile.getGL2ES2(); + final PNGPixelRect image = PNGPixelRect.read(istream, destFmt, true /* directBuffer */, 0 /* destMinStrideInBytes */, true /* destIsGLOriented */); + Assert.assertNotNull(image); + final GLPixelAttributes glpa = GLPixelAttributes.convert(image.getPixelformat(), glp); + final boolean hasAlpha = 4 == glpa.bytesPerPixel; + System.err.println("PNGPixelRect: "+basename+", "+image+", glpa "+glpa); + + final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); + final GLCapabilities caps = new GLCapabilities(glp); + if( hasAlpha ) { + caps.setAlphaBits(1); + } + + final int internalFormat; + if(glp.isGL2ES3()) { + internalFormat = hasAlpha ? GL.GL_RGBA8 : GL.GL_RGB8; + } else { + internalFormat = hasAlpha ? GL.GL_RGBA : GL.GL_RGB; + } + final TextureData texData = new TextureData(glp, internalFormat, + image.getSize().getWidth(), + image.getSize().getHeight(), + 0, + glpa, + false /* mipmap */, + false /* compressed */, + false /* must flip-vert */, + image.getPixels(), + null); + + // final TextureData texData = TextureIO.newTextureData(glp, istream, false /* mipmap */, TextureIO.PNG); + System.err.println("TextureData: "+texData); + + final GLWindow glad = GLWindow.create(caps); + glad.setTitle(this.getSimpleTestName(".")); + // Size OpenGL to Video Surface + glad.setSize(texData.getWidth(), texData.getHeight()); + + // load texture from file inside current GL context to match the way + // the bug submitter was doing it + final TextureDraw01ES2Listener gle = new TextureDraw01ES2Listener( texData, 0 ) ; + // gle.setClearColor(new float[] { 1.0f, 0.0f, 0.0f, 1.0f } ); + + glad.addGLEventListener(gle); + glad.addGLEventListener(new GLEventListener() { + boolean shot = false; + + @Override public void init(GLAutoDrawable drawable) { + System.err.println("Chosen Caps: " + drawable.getChosenGLCapabilities()); + System.err.println("GL ctx: " + drawable.getGL().getContext()); + } + + @Override public void display(GLAutoDrawable drawable) { + // 1 snapshot + if(null!=((TextureDraw01Accessor)gle).getTexture() && !shot) { + shot = true; + snapshot(num, basename, drawable.getGL(), screenshot, TextureIO.PNG, null); + } + } + + @Override public void dispose(GLAutoDrawable drawable) { } + @Override public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } + }); + + Animator animator = new Animator(glad); + animator.setUpdateFPSFrames(60, showFPS ? System.err : null); + QuitAdapter quitAdapter = new QuitAdapter(); + glad.addKeyListener(quitAdapter); + glad.addWindowListener(quitAdapter); + glad.setVisible(true); + animator.start(); + + while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) { + Thread.sleep(100); + } + + animator.stop(); + glad.destroy(); + } + + @Test + public void testRead00_Manual() throws InterruptedException, IOException, MalformedURLException { + if( null == _fname ) { + return; + } + final URLConnection urlConn = IOUtil.getResource(this.getClass(), _fname); + if( null == urlConn ) { + throw new IOException("Cannot find "+_fname+".png"); + } + testImpl(0, _fname, urlConn.getInputStream(), null); + } + + @Test + public void testRead01_All() throws InterruptedException, IOException, MalformedURLException { + if( null != _fname ) { + return; + } + for(int i=0; i<PNGTstFiles.allBasenames.length; i++) { + final String basename = PNGTstFiles.allBasenames[i]; + final URLConnection urlConn = IOUtil.getResource(this.getClass(), basename+".png"); + if( null == urlConn ) { + throw new IOException("Cannot find "+basename+".png"); + } + testImpl(i, basename, urlConn.getInputStream(), null); + } + } + @Test + public void testRead02_Gray2RGBA() throws InterruptedException, IOException, MalformedURLException { + if( null != _fname ) { + return; + } + for(int i=0; i<PNGTstFiles.greyBasenames.length; i++) { + final String basename = PNGTstFiles.greyBasenames[i]; + final URLConnection urlConn = IOUtil.getResource(this.getClass(), basename+".png"); + if( null == urlConn ) { + throw new IOException("Cannot find "+basename+".png"); + } + testImpl(i, basename, urlConn.getInputStream(), PixelFormat.RGBA8888); + } + } + + static String _fname = null; + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-file")) { + i++; + _fname = args[i]; + } + } + org.junit.runner.JUnitCore.main(TestPNGPixelRect01NEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileAWT.java new file mode 100644 index 000000000..191d67d31 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileAWT.java @@ -0,0 +1,236 @@ +/** + * 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.jogl.util.texture; + + +import com.jogamp.common.util.IOUtil; +import com.jogamp.opengl.test.junit.jogl.demos.TextureDraw01Accessor; +import com.jogamp.opengl.test.junit.jogl.demos.es2.TextureDraw01ES2Listener; +import com.jogamp.opengl.test.junit.jogl.demos.gl2.TextureDraw01GL2Listener; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.test.junit.util.UITestCase; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.awt.GLCanvas; + +import com.jogamp.opengl.util.texture.TextureData; +import com.jogamp.opengl.util.texture.TextureIO; +import com.jogamp.opengl.util.texture.spi.TextureProvider; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.GLReadBufferUtil; + +import java.awt.Dimension; +import java.awt.Frame; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URLConnection; + +import org.junit.Assert; +import org.junit.After; +import org.junit.Assume; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +/** + * Unit test for bug 417, which shows a GLException when reading a grayscale texture. + * Couldn't duplicate the failure, so it must have been fixed unknowingly sometime + * after the bug was submitted. + * @author Wade Walker, et.al. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestPNGTextureFromFileAWT extends UITestCase { + static boolean showFPS = false; + static long duration = 100; // ms + InputStream grayTextureStream; + InputStream testTextureStream; + + @BeforeClass + public static void initClass() { + } + + @Before + public void initTest() throws IOException { + grayTextureStream = TestPNGTextureFromFileAWT.class.getResourceAsStream( "grayscale_texture.png" ); + Assert.assertNotNull(grayTextureStream); + { + URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscN_3-01-160x90.png"); + Assert.assertNotNull(testTextureUrlConn); + testTextureStream = testTextureUrlConn.getInputStream(); + Assert.assertNotNull(testTextureStream); + } + } + + @After + public void cleanupTest() { + grayTextureStream = null; + testTextureStream = null; + } + + public void testImpl(boolean useFFP, final InputStream istream, final boolean useAWTIIOP) + throws InterruptedException, IOException + { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); + GLProfile glp; + if(useFFP && GLProfile.isAvailable(GLProfile.GL2)) { + glp = GLProfile.getMaxFixedFunc(true); + } else if(!useFFP && GLProfile.isAvailable(GLProfile.GL2ES2)) { + glp = GLProfile.getGL2ES2(); + } else { + System.err.println(getSimpleTestName(".")+": GLProfile n/a, useFFP: "+useFFP); + return; + } + final GLCapabilities caps = new GLCapabilities(glp); + final TextureData texData; + if(useAWTIIOP) { + final TextureProvider texProvider = new com.jogamp.opengl.util.texture.spi.awt.IIOTextureProvider(); + texData = texProvider.newTextureData(glp, istream, 0 /* internalFormat */, 0 /* pixelFormat */, false /* mipmap */, TextureIO.PNG); + } else { + texData = TextureIO.newTextureData(glp, istream, false /* mipmap */, TextureIO.PNG); + } + System.err.println("TextureData: "+texData); + + final GLCanvas glc = new GLCanvas(caps); + Dimension glc_sz = new Dimension(texData.getWidth(), texData.getHeight()); + glc.setMinimumSize(glc_sz); + glc.setPreferredSize(glc_sz); + final Frame frame = new Frame("TestPNGTextureGL2FromFileAWT"); + Assert.assertNotNull(frame); + frame.add(glc); + + // load texture from file inside current GL context to match the way + // the bug submitter was doing it + final GLEventListener gle = useFFP ? new TextureDraw01GL2Listener( texData ) : new TextureDraw01ES2Listener( texData, 0 ) ; + glc.addGLEventListener(gle); + glc.addGLEventListener(new GLEventListener() { + boolean shot = false; + + @Override public void init(GLAutoDrawable drawable) {} + + @Override + public void display(GLAutoDrawable drawable) { + // 1 snapshot + if(null!=((TextureDraw01Accessor)gle).getTexture() && !shot) { + shot = true; + snapshot(0, null, drawable.getGL(), screenshot, TextureIO.PNG, null); + } + } + + @Override public void dispose(GLAutoDrawable drawable) { } + @Override public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } + }); + + Animator animator = new Animator(glc); + animator.setUpdateFPSFrames(60, showFPS ? System.err : null); + QuitAdapter quitAdapter = new QuitAdapter(); + new com.jogamp.newt.event.awt.AWTKeyAdapter(quitAdapter).addTo(glc); + new com.jogamp.newt.event.awt.AWTWindowAdapter(quitAdapter).addTo(glc); + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.pack(); + frame.setVisible(true); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + animator.start(); + + while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) { + Thread.sleep(100); + } + + animator.stop(); + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + frame.remove(glc); + frame.dispose(); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + } + + @Test + public void testGrayAWTILoaderGL2() throws InterruptedException, IOException { + testImpl(true, grayTextureStream, true); + } + @Test + public void testGrayAWTILoaderES2() throws InterruptedException, IOException { + testImpl(false, grayTextureStream, true); + } + + @Test + public void testGrayPNGJLoaderGL2() throws InterruptedException, IOException { + testImpl(true, grayTextureStream, false); + } + @Test + public void testGrayPNGJLoaderES2() throws InterruptedException, IOException { + testImpl(false, grayTextureStream, false); + } + + @Test + public void testTestAWTILoaderGL2() throws InterruptedException, IOException { + testImpl(true, testTextureStream, true); + } + @Test + public void testTestAWTILoaderES2() throws InterruptedException, IOException { + testImpl(false, testTextureStream, true); + } + + @Test + public void testTestPNGJLoaderGL2() throws InterruptedException, IOException { + testImpl(true, testTextureStream, false); + } + @Test + public void testTestPNGJLoaderES2() throws InterruptedException, IOException { + testImpl(false, testTextureStream, false); + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } + } + org.junit.runner.JUnitCore.main(TestPNGTextureFromFileAWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileNEWT.java new file mode 100644 index 000000000..ce363b612 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileNEWT.java @@ -0,0 +1,277 @@ +/** + * Copyright 2012 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.jogl.util.texture; + + +import com.jogamp.common.util.IOUtil; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.jogl.demos.TextureDraw01Accessor; +import com.jogamp.opengl.test.junit.jogl.demos.es2.TextureDraw01ES2Listener; +import com.jogamp.opengl.test.junit.jogl.demos.gl2.TextureDraw01GL2Listener; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.test.junit.util.UITestCase; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; +import javax.media.opengl.GLCapabilities; + +import com.jogamp.opengl.util.texture.TextureData; +import com.jogamp.opengl.util.texture.TextureIO; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.GLReadBufferUtil; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URLConnection; + +import org.junit.Assert; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestPNGTextureFromFileNEWT extends UITestCase { + static boolean showFPS = false; + static long duration = 100; // ms + InputStream grayTextureStream; + + InputStream testTextureStreamN_3; + InputStream testTextureStreamN_4; + InputStream testTextureStreamNG4; + + InputStream testTextureStreamI_3; + InputStream testTextureStreamIG3; + InputStream testTextureStreamI_4; + InputStream testTextureStreamIG4; + + InputStream testTextureStreamP_3; + InputStream testTextureStreamP_4; + + @Before + public void initTest() throws IOException { + grayTextureStream = TestPNGTextureFromFileNEWT.class.getResourceAsStream( "grayscale_texture.png" ); + Assert.assertNotNull(grayTextureStream); + { + URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscN_3-01-160x90.png"); + Assert.assertNotNull(testTextureUrlConn); + testTextureStreamN_3 = testTextureUrlConn.getInputStream(); + Assert.assertNotNull(testTextureStreamN_3); + } + { + URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscN_4-01-160x90.png"); + Assert.assertNotNull(testTextureUrlConn); + testTextureStreamN_4 = testTextureUrlConn.getInputStream(); + Assert.assertNotNull(testTextureStreamN_4); + } + { + URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscNG4-01-160x90.png"); + Assert.assertNotNull(testTextureUrlConn); + testTextureStreamNG4 = testTextureUrlConn.getInputStream(); + Assert.assertNotNull(testTextureStreamNG4); + } + + { + URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscI_3-01-160x90.png"); + Assert.assertNotNull(testTextureUrlConn); + testTextureStreamI_3 = testTextureUrlConn.getInputStream(); + Assert.assertNotNull(testTextureStreamI_3); + } + { + URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscIG3-01-160x90.png"); + Assert.assertNotNull(testTextureUrlConn); + testTextureStreamIG3 = testTextureUrlConn.getInputStream(); + Assert.assertNotNull(testTextureStreamIG3); + } + { + URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscI_4-01-160x90.png"); + Assert.assertNotNull(testTextureUrlConn); + testTextureStreamI_4 = testTextureUrlConn.getInputStream(); + Assert.assertNotNull(testTextureStreamI_4); + } + { + URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscIG4-01-160x90.png"); + Assert.assertNotNull(testTextureUrlConn); + testTextureStreamIG4 = testTextureUrlConn.getInputStream(); + Assert.assertNotNull(testTextureStreamIG4); + } + + + { + URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscP_3-01-160x90.png"); + Assert.assertNotNull(testTextureUrlConn); + testTextureStreamP_3 = testTextureUrlConn.getInputStream(); + Assert.assertNotNull(testTextureStreamP_3); + } + { + URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscP_4-01-160x90.png"); + Assert.assertNotNull(testTextureUrlConn); + testTextureStreamP_4 = testTextureUrlConn.getInputStream(); + Assert.assertNotNull(testTextureStreamP_4); + } + } + + @After + public void cleanupTest() { + grayTextureStream = null; + testTextureStreamN_3 = null; + testTextureStreamI_3 = null; + testTextureStreamIG3 = null; + testTextureStreamP_3 = null; + testTextureStreamP_4 = null; + } + + public void testImpl(boolean useFFP, final InputStream istream) throws InterruptedException, IOException { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); + GLProfile glp; + if(useFFP && GLProfile.isAvailable(GLProfile.GL2)) { + glp = GLProfile.getMaxFixedFunc(true); + } else if(!useFFP && GLProfile.isAvailable(GLProfile.GL2ES2)) { + glp = GLProfile.getGL2ES2(); + } else { + System.err.println(getSimpleTestName(".")+": GLProfile n/a, useFFP: "+useFFP); + return; + } + final GLCapabilities caps = new GLCapabilities(glp); + caps.setAlphaBits(1); + + final TextureData texData = TextureIO.newTextureData(glp, istream, false /* mipmap */, TextureIO.PNG); + System.err.println("TextureData: "+texData); + + final GLWindow glad = GLWindow.create(caps); + glad.setTitle("TestPNGTextureGL2FromFileNEWT"); + // Size OpenGL to Video Surface + glad.setSize(texData.getWidth(), texData.getHeight()); + + // load texture from file inside current GL context to match the way + // the bug submitter was doing it + final GLEventListener gle = useFFP ? new TextureDraw01GL2Listener( texData ) : new TextureDraw01ES2Listener( texData, 0 ) ; + glad.addGLEventListener(gle); + glad.addGLEventListener(new GLEventListener() { + boolean shot = false; + + @Override public void init(GLAutoDrawable drawable) {} + + public void display(GLAutoDrawable drawable) { + // 1 snapshot + if(null!=((TextureDraw01Accessor)gle).getTexture() && !shot) { + shot = true; + snapshot(0, null, drawable.getGL(), screenshot, TextureIO.PNG, null); + } + } + + @Override public void dispose(GLAutoDrawable drawable) { } + @Override public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } + }); + + Animator animator = new Animator(glad); + animator.setUpdateFPSFrames(60, showFPS ? System.err : null); + QuitAdapter quitAdapter = new QuitAdapter(); + glad.addKeyListener(quitAdapter); + glad.addWindowListener(quitAdapter); + glad.setVisible(true); + animator.start(); + + while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) { + Thread.sleep(100); + } + + animator.stop(); + glad.destroy(); + } + + @Test + public void testGray__GL2() throws InterruptedException, IOException { + testImpl(true, grayTextureStream); + } + @Test + public void testGray__ES2() throws InterruptedException, IOException { + testImpl(false, grayTextureStream); + } + + @Test + public void testRGB3__GL2() throws InterruptedException, IOException { + testImpl(true, testTextureStreamN_3); + } + @Test + public void testRGB3__ES2() throws InterruptedException, IOException { + testImpl(false, testTextureStreamN_3); + } + @Test + public void testRGB4__GL2() throws InterruptedException, IOException { + testImpl(true, testTextureStreamN_4); + } + @Test + public void testRGB4__ES2() throws InterruptedException, IOException { + testImpl(false, testTextureStreamN_4); + } + @Test + public void testRGB4G_ES2() throws InterruptedException, IOException { + testImpl(false, testTextureStreamNG4); + } + + @Test + public void testInterl3__ES2() throws InterruptedException, IOException { + testImpl(false, testTextureStreamI_3); + } + @Test + public void testInterl4__ES2() throws InterruptedException, IOException { + testImpl(false, testTextureStreamI_4); + } + @Test + public void testInterl3G_ES2() throws InterruptedException, IOException { + testImpl(false, testTextureStreamIG3); + } + @Test + public void testInterl4G_ES2() throws InterruptedException, IOException { + testImpl(false, testTextureStreamIG4); + } + + @Test + public void testPalette3__ES2() throws InterruptedException, IOException { + testImpl(false, testTextureStreamP_3); + } + @Test + public void testPalette4__ES2() throws InterruptedException, IOException { + testImpl(false, testTextureStreamP_4); + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } + } + org.junit.runner.JUnitCore.main(TestPNGTextureFromFileNEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil00NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil00NEWT.java new file mode 100644 index 000000000..bfcf9c2d7 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil00NEWT.java @@ -0,0 +1,364 @@ +/** + * Copyright 2014 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.jogl.util.texture; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.PixelFormat; +import javax.media.nativewindow.util.PixelFormatUtil; +import javax.media.nativewindow.util.PixelRectangle; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Testing PixelFormatUtil's Conversion using synthetic test data + * including strides, endian-order and all PixelFormat conversions. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestPixelFormatUtil00NEWT extends UITestCase { + @Test + public void testConversion01_srcS000_BE_TL_destS000_TL() throws InterruptedException, IOException, MalformedURLException { + testPNG00Impl(0 /* srcMinStrideInBytes */, ByteOrder.BIG_ENDIAN, false /* srcIsGLOriented */, + 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); + } + @Test + public void testConversion02_srcS000_LE_TL_destS000_TL() throws InterruptedException, IOException, MalformedURLException { + testPNG00Impl(0 /* srcMinStrideInBytes */, ByteOrder.LITTLE_ENDIAN, false /* srcIsGLOriented */, + 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); + } + @Test + public void testConversion03_srcS000_BE_TL_destS259_TL() throws InterruptedException, IOException, MalformedURLException { + testPNG00Impl(0 /* srcMinStrideInBytes */, ByteOrder.BIG_ENDIAN, false /* srcIsGLOriented */, + 259 /* destMinStrideInBytes */, false /* destIsGLOriented */); + } + @Test + public void testConversion04_srcS259_BE_TL_destS259_TL() throws InterruptedException, IOException, MalformedURLException { + testPNG00Impl(259 /* srcMinStrideInBytes */, ByteOrder.BIG_ENDIAN, false /* srcIsGLOriented */, + 259 /* destMinStrideInBytes */, false /* destIsGLOriented */); + } + @Test + public void testConversion05_srcS301_BE_TL_destS259_TL() throws InterruptedException, IOException, MalformedURLException { + testPNG00Impl(301 /* srcMinStrideInBytes */, ByteOrder.BIG_ENDIAN, false /* srcIsGLOriented */, + 259 /* destMinStrideInBytes */, false /* destIsGLOriented */); + } + + static final byte red___val = (byte)0x01; + static final byte green_val = (byte)0x02; + static final byte blue__val = (byte)0x03; + static final byte alpha_val = (byte)0x04; + static final byte undef_val = (byte)0xff; + + static final void getComponents(final int srcComps, final PixelFormat fmt, final byte[] components) { + final byte b1, b2, b3, b4; + if( 1 == srcComps ) { + // LUM -> Fmt Conversion + switch(fmt) { + case LUMINANCE: + b1 = red___val; + b2 = undef_val; + b3 = undef_val; + b4 = undef_val; + break; + case RGB888: + b1 = red___val; + b2 = red___val; + b3 = red___val; + b4 = undef_val; + break; + case BGR888: + b1 = red___val; + b2 = red___val; + b3 = red___val; + b4 = undef_val; + break; + case RGBA8888: + b1 = red___val; + b2 = red___val; + b3 = red___val; + b4 = undef_val; + break; + case ABGR8888: + b1 = undef_val; + b2 = red___val; + b3 = red___val; + b4 = red___val; + break; + case BGRA8888: + b1 = red___val; + b2 = red___val; + b3 = red___val; + b4 = undef_val; + break; + case ARGB8888: + b1 = undef_val; + b2 = red___val; + b3 = red___val; + b4 = red___val; + break; + default: + throw new InternalError("Unhandled format "+fmt); + } + } else { + // 1:1 values + switch(fmt) { + case LUMINANCE: + if( srcComps > 1 ) { + b1 = ( red___val + green_val+ blue__val ) / 3; + b2 = undef_val; + b3 = undef_val; + b4 = undef_val; + } else { + b1 = red___val; + b2 = undef_val; + b3 = undef_val; + b4 = undef_val; + } + break; + case RGB888: + b1 = red___val; + b2 = green_val; + b3 = blue__val; + b4 = undef_val; + break; + case BGR888: + b1 = blue__val; + b2 = green_val; + b3 = red___val; + b4 = undef_val; + break; + case RGBA8888: + b1 = red___val; + b2 = green_val; + b3 = blue__val; + b4 = srcComps > 3 ? alpha_val : undef_val; + break; + case ABGR8888: + b1 = srcComps > 3 ? alpha_val : undef_val; + b2 = blue__val; + b3 = green_val; + b4 = red___val; + break; + case BGRA8888: + b1 = blue__val; + b2 = green_val; + b3 = red___val; + b4 = srcComps > 3 ? alpha_val : undef_val; + break; + case ARGB8888: + b1 = srcComps > 3 ? alpha_val : undef_val; + b2 = red___val; + b3 = green_val; + b4 = blue__val; + break; + default: + throw new InternalError("Unhandled format "+fmt); + } + } + components[0] = b1; + components[1] = b2; + components[2] = b3; + components[3] = b4; + } + private void testPNG00Impl(final int srcMinStrideInBytes, final ByteOrder srcByteOrder, final boolean srcIsGLOriented, + final int destMinStrideInBytes, final boolean destIsGLOriented) + throws InterruptedException, IOException, MalformedURLException + { + System.err.println("Test00: srcMinStrideInBytes "+srcMinStrideInBytes+", srcByteOrder "+srcByteOrder+", srcIsGLOriented "+srcIsGLOriented+ + ", destMinStrideInBytes "+destMinStrideInBytes+", destIsGLOriented "+destIsGLOriented); + + final PixelFormat[] formats = PixelFormat.values(); + final int width = 64, height = 64; + + for(int i=0; i<formats.length; i++) { + final PixelFormat srcFmt = formats[i]; + final int srcBpp = srcFmt.bytesPerPixel(); + final int srcStrideBytes = Math.max(srcMinStrideInBytes, width*srcBpp); + final ByteBuffer srcPixels = ByteBuffer.allocate(height*srcStrideBytes).order(srcByteOrder); + final byte[] srcComponents = new byte[4]; + getComponents(srcFmt.componentCount, srcFmt, srcComponents); + for(int y=0; y<height; y++) { + int o = y*srcStrideBytes; + for(int x=0; x<width; x++) { + switch(srcFmt) { + case LUMINANCE: + srcPixels.put(o++, srcComponents[0]); + break; + case RGB888: + case BGR888: + srcPixels.put(o++, srcComponents[0]); + srcPixels.put(o++, srcComponents[1]); + srcPixels.put(o++, srcComponents[2]); + break; + case RGBA8888: + case ABGR8888: + case BGRA8888: + case ARGB8888: + srcPixels.put(o++, srcComponents[0]); + srcPixels.put(o++, srcComponents[1]); + srcPixels.put(o++, srcComponents[2]); + srcPixels.put(o++, srcComponents[3]); + break; + default: + throw new InternalError("Unhandled format "+srcFmt); + } + } + } + final PixelRectangle imageSrc = new PixelRectangle.GenericPixelRect(srcFmt, new Dimension(width, height), srcStrideBytes, srcIsGLOriented, srcPixels); + System.err.println("CONVERT["+i+"][*]: Image0 - Orig: "+imageSrc); + testComponents(imageSrc, 0, 0, srcComponents); + testComponents(imageSrc, width-1, height-1, srcComponents); + + for(int j=0; j<formats.length; j++) { + final PixelFormat destFmt = formats[j]; + System.err.println("CONVERT["+i+"]["+j+"]: "+srcFmt+" -> "+destFmt); + + final int destStrideBytes = Math.max(destMinStrideInBytes, width*destFmt.bytesPerPixel()); + final byte[] destComponents = new byte[4]; + getComponents(srcFmt.componentCount, destFmt, destComponents); + final PixelRectangle imageConv1 = PixelFormatUtil.convert32(imageSrc, destFmt, destStrideBytes, destIsGLOriented, false /* nio */); + System.err.println("CONVERT["+i+"]["+j+"]: Conv1: "+imageConv1); + testComponents(imageConv1, 0, 0, destComponents); + testComponents(imageConv1, width-1, height-1, destComponents); + if( PixelFormat.LUMINANCE != srcFmt && PixelFormat.LUMINANCE == destFmt ) { + // Cannot convert: RGB* -> LUM -> RGB* + System.err.println("CONVERT["+i+"]["+j+"]: Conv2: Dropped due to RGB* -> LUM"); + } else if( srcFmt.componentCount > destFmt.componentCount ) { + // Cannot convert back if: src.componentCount > dest.componentCount + System.err.println("CONVERT["+i+"]["+j+"]: Conv2: Dropped due to src.componentCount > dest.componentCount"); + } else { + final PixelRectangle imageConv2 = PixelFormatUtil.convert32(imageConv1, imageSrc.getPixelformat(), imageSrc.getStride(), imageSrc.isGLOriented(), false /* nio */); + System.err.println("CONVERT["+i+"]["+j+"]: Conv2: "+imageConv2); + testComponents(imageConv2, 0, 0, srcComponents); + testComponents(imageConv2, width-1, height-1, srcComponents); + if( imageSrc.getStride() == imageConv1.getStride() ) { + Assert.assertEquals(imageSrc.getPixels(), imageConv2.getPixels()); + } + } + } + } + } + private void dumpComponents(PixelRectangle image, int x1, int y1, int w, int h) { + if( x1 + w >= image.getSize().getWidth() ) { + x1 = image.getSize().getWidth() - w; + } + if( y1 + h >= image.getSize().getHeight() ) { + y1 = image.getSize().getHeight() - h; + } + System.err.print("PixelsBytes "+x1+"/"+y1+" "+w+"x"+h+":"); + final ByteBuffer bb = image.getPixels(); + final int bpp = image.getPixelformat().bytesPerPixel(); + for(int y = y1; y< y1+h; y++) { + System.err.printf("%n[%3d][%3d] ", x1, y); + int o = y * image.getStride()+x1*bpp; + for(int x = x1; x< x1+w; x++) { + switch(bpp) { + case 1: { + final byte a = bb.get(o++); + System.err.printf(" 0x%02X", a); + } + break; + case 2: { + final byte a = bb.get(o++), b = bb.get(o++); + System.err.printf(" 0x%02X%02X", b, a); + } + break; + case 3: { + final byte a = bb.get(o++), b = bb.get(o++), c = bb.get(o++); + System.err.printf(" 0x%02X%02X%02X", c, b, a); + } + break; + case 4: { + final byte a = bb.get(o++), b = bb.get(o++), c = bb.get(o++), d = bb.get(o++); + System.err.printf(" 0x%02X%02X%02X%02X", d, c, b, a); + } + break; + } + } + } + System.err.println(); + } + private void testComponents(PixelRectangle image, int x, int y, byte[] components) { + dumpComponents(image, x, y, 3, 3); + final ByteBuffer bb = image.getPixels(); + final int bpp = image.getPixelformat().bytesPerPixel(); + int o = y * image.getStride()+x*bpp; + switch(bpp) { + case 1: { + final byte c1 = bb.get(o++); + final boolean equal = c1==components[0]; + System.err.printf("Test [%3d][%3d] exp 0x%02X == has 0x%02X : %b%n", + x, y, components[0], c1, equal ); + Assert.assertEquals(components[0], c1); + } + break; + case 2: { + final byte c1 = bb.get(o++), c2 = bb.get(o++); + final boolean equal = c1==components[0] && c2==components[1]; + System.err.printf("Test [%3d][%3d] exp 0x%02X%02X == has 0x%02X%02X : %b%n", + x, components[1], components[0], c2, c1, equal ); + Assert.assertEquals(components[0], c1); + Assert.assertEquals(components[1], c2); + } + break; + case 3: { + final byte c1 = bb.get(o++), c2 = bb.get(o++), c3 = bb.get(o++); + final boolean equal = c1==components[0] && c2==components[1] && c3==components[2]; + System.err.printf("Test [%3d][%3d] exp 0x%02X%02X%02X == has 0x%02X%02X%02X : %b%n", + x, y, components[2], components[1], components[0], c3, c2, c1, equal ); + Assert.assertEquals(components[0], c1); + Assert.assertEquals(components[1], c2); + Assert.assertEquals(components[2], c3); + } + break; + case 4: { + final byte c1 = bb.get(o++), c2 = bb.get(o++), c3 = bb.get(o++), c4 = bb.get(o++); + final boolean equal = c1==components[0] && c2==components[1] && c3==components[2] && c4==components[3]; + System.err.printf("Test [%3d][%3d] exp 0x%02X%02X%02X%02X == has 0x%02X%02X%02X%02X : %b%n", + x, y, components[3], components[2], components[1], components[0], c4, c3, c2, c1, equal ); + Assert.assertEquals(components[0], c1); + Assert.assertEquals(components[1], c2); + Assert.assertEquals(components[2], c3); + Assert.assertEquals(components[3], c4); + } + break; + } + } + + public static void main(String args[]) { + org.junit.runner.JUnitCore.main(TestPixelFormatUtil00NEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil01NEWT.java new file mode 100644 index 000000000..f54861371 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil01NEWT.java @@ -0,0 +1,105 @@ +/** + * Copyright 2014 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.jogl.util.texture; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URLConnection; + +import javax.media.nativewindow.util.PixelFormat; +import javax.media.nativewindow.util.PixelFormatUtil; +import javax.media.nativewindow.util.PixelRectangle; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.common.util.IOUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.PNGPixelRect; + +/** + * Testing PixelFormatUtil's Conversion using PNG test data + * including strides, endian-order and PixelFormat conversions: + * { PixelFormat.RGBA8888, PixelFormat.ABGR8888, PixelFormat.BGRA8888, PixelFormat.ARGB8888 } + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestPixelFormatUtil01NEWT extends UITestCase { + @Test + public void testPNGRead11_fromRGBA8888() throws InterruptedException, IOException, MalformedURLException { + final String basename ="test-ntscN_4-01-160x90"; + final String pathname=""; + testPNG01Impl(pathname, basename, PixelFormat.RGBA8888, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); + } + @Test + public void testPNGRead12_fromABGR8888() throws InterruptedException, IOException, MalformedURLException { + final String basename ="test-ntscN_4-01-160x90"; + final String pathname=""; + testPNG01Impl(pathname, basename, PixelFormat.ABGR8888, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); + } + @Test + public void testPNGRead13_fromBGRA8888() throws InterruptedException, IOException, MalformedURLException { + final String basename ="test-ntscN_4-01-160x90"; + final String pathname=""; + testPNG01Impl(pathname, basename, PixelFormat.BGRA8888, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); + } + @Test + public void testPNGRead14_fromARGB8888() throws InterruptedException, IOException, MalformedURLException { + final String basename ="test-ntscN_4-01-160x90"; + final String pathname=""; + testPNG01Impl(pathname, basename, PixelFormat.ARGB8888, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); + } + + private void testPNG01Impl(final String pathname, final String basename, final PixelFormat srcFmt, + final int destMinStrideInBytes, final boolean destIsGLOriented) + throws InterruptedException, IOException, MalformedURLException + { + System.err.println("Test01: "+pathname+basename+".png, srcFmt "+srcFmt+", destMinStrideInBytes "+destMinStrideInBytes+", destIsGLOriented "+destIsGLOriented); + + URLConnection urlConn = IOUtil.getResource(this.getClass(), pathname+basename+".png"); + + final PNGPixelRect image1 = PNGPixelRect.read(urlConn.getInputStream(), srcFmt, false /* directBuffer */, destMinStrideInBytes, false /* isGLOriented */); + System.err.println("PNGPixelRect - Orig: "+image1); + + final PixelFormat[] formats = new PixelFormat[] { PixelFormat.RGBA8888, PixelFormat.ABGR8888, PixelFormat.BGRA8888, PixelFormat.ARGB8888 }; + for(int i=0; i<formats.length; i++) { + final PixelFormat destFmt = formats[i]; + System.err.println("CONVERT["+i+"]: "+srcFmt+" -> "+destFmt); + final PixelRectangle imageConv1 = PixelFormatUtil.convert32(image1, destFmt, destMinStrideInBytes, destIsGLOriented, false /* nio */); + System.err.println("PNGPixelRect - Conv1: "+imageConv1); + final PixelRectangle imageConv2 = PixelFormatUtil.convert32(imageConv1, image1.getPixelformat(), image1.getStride(), image1.isGLOriented(), false /* nio */); + System.err.println("PNGPixelRect - Conv2: "+imageConv2); + Assert.assertEquals(image1.getPixels(), imageConv2.getPixels()); + } + } + + public static void main(String args[]) { + org.junit.runner.JUnitCore.main(TestPixelFormatUtil01NEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTGATextureFromFileNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTGATextureFromFileNEWT.java new file mode 100644 index 000000000..859e4e4b5 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTGATextureFromFileNEWT.java @@ -0,0 +1,168 @@ +/** + * Copyright 2013 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.jogl.util.texture; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URLConnection; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.common.util.IOUtil; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.jogl.demos.TextureDraw01Accessor; +import com.jogamp.opengl.test.junit.jogl.demos.es2.TextureDraw01ES2Listener; +import com.jogamp.opengl.test.junit.jogl.demos.gl2.TextureDraw01GL2Listener; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureData; +import com.jogamp.opengl.util.texture.TextureIO; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestTGATextureFromFileNEWT extends UITestCase { + static boolean showFPS = false; + static long duration = 100; // ms + + InputStream testTextureStream01U32; + InputStream testTextureStream02RLE32; + + @Before + public void initTest() throws IOException { + { + URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-u32.tga"); + Assert.assertNotNull(testTextureUrlConn); + testTextureStream01U32 = testTextureUrlConn.getInputStream(); + Assert.assertNotNull(testTextureStream01U32); + } + { + URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "bug744-rle32.tga"); + Assert.assertNotNull(testTextureUrlConn); + testTextureStream02RLE32 = testTextureUrlConn.getInputStream(); + Assert.assertNotNull(testTextureStream02RLE32); + } + } + + public void testImpl(boolean useFFP, final InputStream istream) throws InterruptedException, IOException { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); + GLProfile glp; + if(useFFP && GLProfile.isAvailable(GLProfile.GL2)) { + glp = GLProfile.getMaxFixedFunc(true); + } else if(!useFFP && GLProfile.isAvailable(GLProfile.GL2ES2)) { + glp = GLProfile.getGL2ES2(); + } else { + System.err.println(getSimpleTestName(".")+": GLProfile n/a, useFFP: "+useFFP); + return; + } + final GLCapabilities caps = new GLCapabilities(glp); + caps.setAlphaBits(1); + + final TextureData texData = TextureIO.newTextureData(glp, istream, false /* mipmap */, TextureIO.TGA); + System.err.println("TextureData: "+texData); + + final GLWindow glad = GLWindow.create(caps); + glad.setTitle("TestTGATextureGL2FromFileNEWT"); + // Size OpenGL to Video Surface + glad.setSize(texData.getWidth(), texData.getHeight()); + + // load texture from file inside current GL context to match the way + // the bug submitter was doing it + final GLEventListener gle = useFFP ? new TextureDraw01GL2Listener( texData ) : new TextureDraw01ES2Listener( texData, 0 ) ; + glad.addGLEventListener(gle); + glad.addGLEventListener(new GLEventListener() { + boolean shot = false; + + @Override public void init(GLAutoDrawable drawable) {} + + public void display(GLAutoDrawable drawable) { + // 1 snapshot + if(null!=((TextureDraw01Accessor)gle).getTexture() && !shot) { + shot = true; + snapshot(0, null, drawable.getGL(), screenshot, TextureIO.PNG, null); + } + } + + @Override public void dispose(GLAutoDrawable drawable) { } + @Override public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } + }); + + Animator animator = new Animator(glad); + animator.setUpdateFPSFrames(60, showFPS ? System.err : null); + QuitAdapter quitAdapter = new QuitAdapter(); + glad.addKeyListener(quitAdapter); + glad.addWindowListener(quitAdapter); + glad.setVisible(true); + animator.start(); + + while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) { + Thread.sleep(100); + } + + animator.stop(); + glad.destroy(); + } + + @Test + public void test01U32__GL2() throws InterruptedException, IOException { + testImpl(true, testTextureStream01U32); + } + + @Test + public void test02RLE32__GL2() throws InterruptedException, IOException { + testImpl(true, testTextureStream02RLE32); + } + + @After + public void cleanupTest() { + testTextureStream01U32 = null; + testTextureStream02RLE32 = null; + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } + } + org.junit.runner.JUnitCore.main(TestTGATextureFromFileNEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/texture/TestTexture01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture01AWT.java index 217b8aca3..855529f9c 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/texture/TestTexture01AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture01AWT.java @@ -26,20 +26,28 @@ * or implied, of JogAmp Community. */ -package com.jogamp.opengl.test.junit.jogl.texture; +package com.jogamp.opengl.test.junit.jogl.util.texture; -import com.jogamp.opengl.test.junit.jogl.util.texture.gl2.TextureGL2ListenerDraw1; +import com.jogamp.common.util.awt.AWTEDTExecutor; +import com.jogamp.opengl.test.junit.jogl.demos.gl2.TextureDraw01GL2Listener; +import com.jogamp.opengl.test.junit.util.MiscUtils; import com.jogamp.opengl.test.junit.util.UITestCase; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; import javax.media.opengl.GLCapabilities; import javax.media.opengl.awt.GLCanvas; +import javax.swing.ImageIcon; +import javax.swing.JLabel; + +import com.jogamp.opengl.util.awt.AWTGLReadBufferUtil; import com.jogamp.opengl.util.texture.TextureData; import com.jogamp.opengl.util.texture.awt.AWTTextureIO; -import com.jogamp.opengl.util.Animator; import java.awt.AlphaComposite; +import java.awt.Canvas; import java.awt.Color; import java.awt.Frame; import java.awt.GradientPaint; @@ -53,8 +61,18 @@ import org.junit.Assume; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +/** + * Demonstrates TextureData w/ AWT usage in both directions, + * i.e. generating a texture based on an AWT BufferedImage data + * as well as reading out GL framebuffer and displaying it + * as an BufferedImage. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestTexture01AWT extends UITestCase { + static long durationPerTest = 500; static GLProfile glp; static GLCapabilities caps; BufferedImage textureImage; @@ -65,7 +83,7 @@ public class TestTexture01AWT extends UITestCase { UITestCase.setTestSupported(false); return; } - glp = GLProfile.getGL2GL3(); + glp = GLProfile.getMaxFixedFunc(true); Assert.assertNotNull(glp); caps = new GLCapabilities(glp); Assert.assertNotNull(caps); @@ -107,29 +125,74 @@ public class TestTexture01AWT extends UITestCase { @Test public void test1() throws InterruptedException { + final AWTGLReadBufferUtil awtGLReadBufferUtil = new AWTGLReadBufferUtil(caps.getGLProfile(), false); + final Frame frame0 = new Frame("GL -> AWT"); + final Canvas canvas = new Canvas(); + frame0.add(canvas); + final GLCanvas glCanvas = new GLCanvas(caps); - final Frame frame = new Frame("Texture Test"); - Assert.assertNotNull(frame); - frame.add(glCanvas); - frame.setSize(512, 512); + final Frame frame1 = new Frame("AWT -> Texture"); + Assert.assertNotNull(frame1); + frame1.add(glCanvas); // create texture TextureData textureData = AWTTextureIO.newTextureData(caps.getGLProfile(), textureImage, false); - glCanvas.addGLEventListener(new TextureGL2ListenerDraw1(textureData)); - - Animator animator = new Animator(glCanvas); - frame.setVisible(true); - animator.start(); + glCanvas.addGLEventListener(new TextureDraw01GL2Listener(textureData)); + glCanvas.addGLEventListener(new GLEventListener() { + + @Override + public void init(GLAutoDrawable drawable) { } + @Override + public void dispose(GLAutoDrawable drawable) { } + @Override + public void display(GLAutoDrawable drawable) { + BufferedImage outputImage = awtGLReadBufferUtil.readPixelsToBufferedImage(drawable.getGL(), true /* awtOrientation */); + ImageIcon imageIcon = new ImageIcon(outputImage); + final JLabel imageLabel = new JLabel(imageIcon); + try { + AWTEDTExecutor.singleton.invoke(true, new Runnable() { + public void run() { + frame0.removeAll(); + frame0.add(imageLabel); + frame0.validate(); + }}); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + frame0.setSize(frame1.getWidth(), frame1.getHeight()); + frame0.setLocation(frame1.getX()+frame1.getWidth()+32, frame0.getY()); + frame0.validate(); + } + }); - Thread.sleep(500); // 500 ms + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame1.setSize(256, 256); + frame1.setLocation(0, 0); + frame1.setVisible(true); + frame0.setSize(frame1.getWidth(), frame1.getHeight()); + frame0.setLocation(frame1.getX()+frame1.getWidth()+32, frame0.getY()); + frame0.setVisible(true); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + + Thread.sleep(durationPerTest); - animator.stop(); try { javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { - frame.setVisible(false); - frame.remove(glCanvas); - frame.dispose(); + frame0.setVisible(false); + frame0.dispose(); + frame1.setVisible(false); + frame1.dispose(); }}); } catch( Throwable throwable ) { throwable.printStackTrace(); @@ -138,6 +201,11 @@ public class TestTexture01AWT extends UITestCase { } public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + durationPerTest = MiscUtils.atol(args[++i], durationPerTest); + } + } String tstname = TestTexture01AWT.class.getName(); org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] { tstname, diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/texture/TestGrayTextureFromFileAWTBug417.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture02AWT.java index d43a3a0c5..566ce0f18 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/texture/TestGrayTextureFromFileAWTBug417.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture02AWT.java @@ -26,115 +26,133 @@ * or implied, of JogAmp Community. */ -package com.jogamp.opengl.test.junit.jogl.texture; +package com.jogamp.opengl.test.junit.jogl.util.texture; -import com.jogamp.opengl.test.junit.jogl.util.texture.gl2.TextureGL2ListenerDraw1; +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 javax.media.opengl.GLAutoDrawable; -import javax.media.opengl.GLException; +import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; import javax.media.opengl.GLCapabilities; import javax.media.opengl.awt.GLCanvas; -import com.jogamp.opengl.util.texture.TextureIO; -import com.jogamp.opengl.util.Animator; +import javax.swing.ImageIcon; +import javax.swing.JLabel; + +import com.jogamp.opengl.util.FPSAnimator; +import com.jogamp.opengl.util.awt.AWTGLReadBufferUtil; import java.awt.Frame; +import java.awt.image.BufferedImage; import java.io.IOException; -import java.io.InputStream; - import org.junit.Assert; -import org.junit.After; import org.junit.Assume; -import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; /** - * Unit test for bug 417, which shows a GLException when reading a grayscale texture. - * Couldn't duplicate the failure, so it must have been fixed unknowingly sometime - * after the bug was submitted. - * @author Wade Walker + * Demonstrates TextureData w/ AWT usage, + * i.e. reading out an animated GL framebuffer and displaying it + * as an BufferedImage. */ -public class TestGrayTextureFromFileAWTBug417 extends UITestCase { +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestTexture02AWT extends UITestCase { + static long durationPerTest = 500; static GLProfile glp; static GLCapabilities caps; - InputStream textureStream; @BeforeClass public static void initClass() { - if(!GLProfile.isAvailable(GLProfile.GL2GL3)) { + if(!GLProfile.isAvailable(GLProfile.GL2ES2)) { UITestCase.setTestSupported(false); return; } - glp = GLProfile.getGL2GL3(); + glp = GLProfile.getGL2ES2(); Assert.assertNotNull(glp); caps = new GLCapabilities(glp); Assert.assertNotNull(caps); } - @Before - public void initTest() { - textureStream = TestGrayTextureFromFileAWTBug417.class.getResourceAsStream( "grayscale_texture.png" ); - Assert.assertNotNull(textureStream); - } - - @After - public void cleanupTest() { - textureStream=null; - } - @Test public void test1() throws InterruptedException { + final AWTGLReadBufferUtil awtGLReadBufferUtil = new AWTGLReadBufferUtil(caps.getGLProfile(), false); + final Frame frame0 = new Frame("GL -> AWT"); + final ImageIcon imageIcon = new ImageIcon(); + final JLabel imageLabel = new JLabel(imageIcon); + frame0.add(imageLabel); + final GLCanvas glCanvas = new GLCanvas(caps); - final Frame frame = new Frame("Texture Test"); - Assert.assertNotNull(frame); - frame.add(glCanvas); - frame.setSize( 256, 128 ); + final Frame frame1 = new Frame("GearsES2"); + Assert.assertNotNull(frame1); + frame1.add(glCanvas); - // load texture from file inside current GL context to match the way - // the bug submitter was doing it - glCanvas.addGLEventListener(new TextureGL2ListenerDraw1( null ) { + glCanvas.addGLEventListener(new GearsES2(1)); + glCanvas.addGLEventListener(new GLEventListener() { + @Override + public void init(GLAutoDrawable drawable) { } + @Override + public void dispose(GLAutoDrawable drawable) { } @Override - public void init(GLAutoDrawable drawable) { - try { - setTexture( TextureIO.newTexture( textureStream, true, TextureIO.PNG ) ); - } - catch(GLException glexception) { - glexception.printStackTrace(); - Assume.assumeNoException(glexception); - } - catch(IOException ioexception) { - ioexception.printStackTrace(); - Assume.assumeNoException(ioexception); - } + public void display(GLAutoDrawable drawable) { + BufferedImage outputImage = awtGLReadBufferUtil.readPixelsToBufferedImage(drawable.getGL(), true /* awtOrientation */); + imageIcon.setImage(outputImage); + imageLabel.repaint(); } + + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + frame0.setSize(frame1.getWidth(), frame1.getHeight()); + frame0.setLocation(frame1.getX()+frame1.getWidth()+32, frame0.getY()); + frame0.validate(); + } }); - Animator animator = new Animator(glCanvas); - frame.setVisible(true); + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame1.setSize(256, 256); + frame1.setLocation(0, 0); + frame1.setVisible(true); + frame0.setSize(frame1.getWidth(), frame1.getHeight()); + frame0.setLocation(frame1.getX()+frame1.getWidth()+32, frame0.getY()); + frame0.setVisible(true); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + FPSAnimator animator = new FPSAnimator(glCanvas, 15); // 15fps animator.start(); - - Thread.sleep(500); // 500 ms + + Thread.sleep(durationPerTest); animator.stop(); try { javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { - frame.setVisible(false); - frame.remove(glCanvas); - frame.dispose(); + frame0.setVisible(false); + frame0.dispose(); + frame1.setVisible(false); + frame1.dispose(); }}); } catch( Throwable throwable ) { throwable.printStackTrace(); Assume.assumeNoException( throwable ); - } + } } public static void main(String args[]) throws IOException { - String tstname = TestGrayTextureFromFileAWTBug417.class.getName(); + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + durationPerTest = MiscUtils.atol(args[++i], durationPerTest); + } + } + String tstname = TestTexture02AWT.class.getName(); org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] { tstname, "filtertrace=true", diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTextureSequence01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTextureSequence01AWT.java new file mode 100644 index 000000000..2b3ead5b9 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTextureSequence01AWT.java @@ -0,0 +1,123 @@ +package com.jogamp.opengl.test.junit.jogl.util.texture; + +import java.awt.Frame; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; + +import org.junit.Assert; +import org.junit.Assume; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.opengl.test.junit.jogl.demos.TextureSequenceDemo01; +import com.jogamp.opengl.test.junit.jogl.demos.es2.TextureSequenceCubeES2; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestTextureSequence01AWT extends UITestCase { + static boolean showFPS = false; + static int width = 510; + static int height = 300; + static boolean useBuildInTexLookup = false; + static long duration = 500; // ms + static GLProfile glp; + static GLCapabilities caps; + + @BeforeClass + public static void initClass() { + glp = GLProfile.getGL2ES2(); + Assert.assertNotNull(glp); + caps = new GLCapabilities(glp); + Assert.assertNotNull(caps); + } + + void testImpl() throws InterruptedException { + final GLCanvas glc = new GLCanvas(caps); + final Frame frame = new Frame("TestTextureSequence01AWT"); + Assert.assertNotNull(frame); + frame.add(glc); + + final TextureSequenceDemo01 texSource = new TextureSequenceDemo01(useBuildInTexLookup); + glc.addGLEventListener(new GLEventListener() { + @Override + public void init(GLAutoDrawable drawable) { + texSource.initGLResources(drawable.getGL()); + } + @Override + public void dispose(GLAutoDrawable drawable) { } + @Override + public void display(GLAutoDrawable drawable) { } + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } + }); + glc.addGLEventListener(new TextureSequenceCubeES2(texSource, false, -2.3f, 0f, 0f)); + final Animator animator = new Animator(glc); + animator.setUpdateFPSFrames(60, showFPS ? System.err : null); + QuitAdapter quitAdapter = new QuitAdapter(); + new com.jogamp.newt.event.awt.AWTKeyAdapter(quitAdapter).addTo(glc); + new com.jogamp.newt.event.awt.AWTWindowAdapter(quitAdapter).addTo(glc); + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setSize(width, height); + frame.setVisible(true); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + animator.start(); + + while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) { + Thread.sleep(100); + } + + animator.stop(); + Assert.assertFalse(animator.isAnimating()); + Assert.assertFalse(animator.isStarted()); + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + frame.remove(glc); + frame.dispose(); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + } + + @Test + public void test1() throws InterruptedException { + testImpl(); + } + + public static void main(String[] args) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-width")) { + i++; + width = MiscUtils.atoi(args[i], width); + } else if(args[i].equals("-height")) { + i++; + height = MiscUtils.atoi(args[i], height); + } else if(args[i].equals("-shaderBuildIn")) { + useBuildInTexLookup = true; + } + } + org.junit.runner.JUnitCore.main(TestTextureSequence01AWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTextureSequence01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTextureSequence01NEWT.java new file mode 100644 index 000000000..5145e104f --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTextureSequence01NEWT.java @@ -0,0 +1,100 @@ +package com.jogamp.opengl.test.junit.jogl.util.texture; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.jogl.demos.TextureSequenceDemo01; +import com.jogamp.opengl.test.junit.jogl.demos.es2.TextureSequenceCubeES2; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestTextureSequence01NEWT extends UITestCase { + static boolean showFPS = false; + static int width = 510; + static int height = 300; + static boolean useBuildInTexLookup = false; + static long duration = 500; // ms + static GLProfile glp; + static GLCapabilities caps; + + @BeforeClass + public static void initClass() { + glp = GLProfile.getGL2ES2(); + Assert.assertNotNull(glp); + caps = new GLCapabilities(glp); + Assert.assertNotNull(caps); + } + + void testImpl() throws InterruptedException { + final GLWindow window = GLWindow.create(caps); + window.setTitle("TestTextureSequence01NEWT"); + // Size OpenGL to Video Surface + window.setSize(width, height); + final TextureSequenceDemo01 texSource = new TextureSequenceDemo01(useBuildInTexLookup); + window.addGLEventListener(new GLEventListener() { + @Override + public void init(GLAutoDrawable drawable) { + texSource.initGLResources(drawable.getGL()); + } + @Override + public void dispose(GLAutoDrawable drawable) { } + @Override + public void display(GLAutoDrawable drawable) { } + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } + }); + window.addGLEventListener(new TextureSequenceCubeES2(texSource, false, -2.3f, 0f, 0f)); + final Animator animator = new Animator(window); + animator.setUpdateFPSFrames(60, showFPS ? System.err : null); + QuitAdapter quitAdapter = new QuitAdapter(); + window.addKeyListener(quitAdapter); + window.addWindowListener(quitAdapter); + animator.start(); + window.setVisible(true); + + while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) { + Thread.sleep(100); + } + + animator.stop(); + Assert.assertFalse(animator.isAnimating()); + Assert.assertFalse(animator.isStarted()); + window.destroy(); + } + + @Test + public void test1() throws InterruptedException { + testImpl(); + } + + public static void main(String[] args) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-width")) { + i++; + width = MiscUtils.atoi(args[i], width); + } else if(args[i].equals("-height")) { + i++; + height = MiscUtils.atoi(args[i], height); + } else if(args[i].equals("-shaderBuildIn")) { + useBuildInTexLookup = true; + } + } + org.junit.runner.JUnitCore.main(TestTextureSequence01NEWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/bug724-transparent-grey_gimpexp.png b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/bug724-transparent-grey_gimpexp.png Binary files differnew file mode 100644 index 000000000..53b2ec07b --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/bug724-transparent-grey_gimpexp.png diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/bug724-transparent-grey_orig.png b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/bug724-transparent-grey_orig.png Binary files differnew file mode 100644 index 000000000..b85bf7e15 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/bug724-transparent-grey_orig.png diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/bug744-rle32.tga b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/bug744-rle32.tga Binary files differnew file mode 100644 index 000000000..18220ed40 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/bug744-rle32.tga diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/bug745_qttdef_post_frame.jpg b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/bug745_qttdef_post_frame.jpg Binary files differnew file mode 100644 index 000000000..1c7009321 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/bug745_qttdef_post_frame.jpg diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/cross-grey-alpha-16x16.png b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/cross-grey-alpha-16x16.png Binary files differnew file mode 100644 index 000000000..303c454fa --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/cross-grey-alpha-16x16.png diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/texture/grayscale_texture.png b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/grayscale_texture.png Binary files differindex dac0f13de..dac0f13de 100755..100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/texture/grayscale_texture.png +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/grayscale_texture.png diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/j1-baseline.jpg b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/j1-baseline.jpg Binary files differnew file mode 100644 index 000000000..8efe6af1f --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/j1-baseline.jpg diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/j2-progressive.jpg b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/j2-progressive.jpg Binary files differnew file mode 100644 index 000000000..aa5fbd0d9 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/j2-progressive.jpg diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/j3-baseline_gray.jpg b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/j3-baseline_gray.jpg Binary files differnew file mode 100644 index 000000000..048eb791b --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/j3-baseline_gray.jpg diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/pointer-grey-alpha-16x24.png b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/pointer-grey-alpha-16x24.png Binary files differnew file mode 100644 index 000000000..98b2c8640 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/pointer-grey-alpha-16x24.png diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-64x32_DXT1.dds b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-64x32_DXT1.dds Binary files differnew file mode 100644 index 000000000..81ae64e33 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-64x32_DXT1.dds diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-64x32_DXT5.dds b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-64x32_DXT5.dds Binary files differnew file mode 100644 index 000000000..5b9e364e0 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-64x32_DXT5.dds diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-64x32_uncompressed.dds b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-64x32_uncompressed.dds Binary files differnew file mode 100644 index 000000000..034d2516c --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-64x32_uncompressed.dds diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-cmyk-01.jpg b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-cmyk-01.jpg Binary files differnew file mode 100644 index 000000000..40a300f2d --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-cmyk-01.jpg diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscIG3-01-160x90.png b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscIG3-01-160x90.png Binary files differnew file mode 100644 index 000000000..b90a90988 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscIG3-01-160x90.png diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscIG4-01-160x90.png b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscIG4-01-160x90.png Binary files differnew file mode 100644 index 000000000..db0ae01fa --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscIG4-01-160x90.png diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscI_3-01-160x90.png b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscI_3-01-160x90.png Binary files differnew file mode 100644 index 000000000..e579c58c6 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscI_3-01-160x90.png diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscI_4-01-160x90.png b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscI_4-01-160x90.png Binary files differnew file mode 100644 index 000000000..e42d22be6 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscI_4-01-160x90.png diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscNG4-01-160x90.png b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscNG4-01-160x90.png Binary files differnew file mode 100644 index 000000000..762ba3e57 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscNG4-01-160x90.png diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90-60pct-yuv422h-base.jpg b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90-60pct-yuv422h-base.jpg Binary files differnew file mode 100644 index 000000000..8e4fe9a09 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90-60pct-yuv422h-base.jpg diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90-60pct-yuv422h-prog.jpg b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90-60pct-yuv422h-prog.jpg Binary files differnew file mode 100644 index 000000000..35556f90b --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90-60pct-yuv422h-prog.jpg diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90-90pct-yuv444-base.jpg b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90-90pct-yuv444-base.jpg Binary files differnew file mode 100644 index 000000000..051a166cd --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90-90pct-yuv444-base.jpg diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90-90pct-yuv444-prog.jpg b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90-90pct-yuv444-prog.jpg Binary files differnew file mode 100644 index 000000000..40b0fc8c2 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90-90pct-yuv444-prog.jpg diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90.png b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90.png Binary files differnew file mode 100644 index 000000000..3df47432e --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90.png diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_4-01-160x90.png b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_4-01-160x90.png Binary files differnew file mode 100644 index 000000000..c233c34da --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_4-01-160x90.png diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscP_3-01-160x90.png b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscP_3-01-160x90.png Binary files differnew file mode 100644 index 000000000..32e7f0042 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscP_3-01-160x90.png diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscP_4-01-160x90.png b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscP_4-01-160x90.png Binary files differnew file mode 100644 index 000000000..55405ee89 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscP_4-01-160x90.png diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-u32.tga b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-u32.tga Binary files differnew file mode 100644 index 000000000..9066e17f7 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-u32.tga diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ycck-01.jpg b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ycck-01.jpg Binary files differnew file mode 100644 index 000000000..84c1984f9 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ycck-01.jpg diff --git a/src/test/com/jogamp/opengl/test/junit/newt/DemoCreateAndDisposeOnCloseNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/DemoCreateAndDisposeOnCloseNEWT.java new file mode 100644 index 000000000..e82204fd0 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/newt/DemoCreateAndDisposeOnCloseNEWT.java @@ -0,0 +1,140 @@ +/** + * Copyright 2013 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 javax.media.nativewindow.WindowClosingProtocol; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.util.Animator; + +/** + * Manual test case validating closing behavior. + * <p> + * Validates bugs: + * <ul> + * <li>Bug 882: Crash on OSX when closing NEWT window</li> + * </ul> + * </p> + * + */ +public class DemoCreateAndDisposeOnCloseNEWT { + public static void main(String[] args) { + int closeMode = 0; // 0 - none, 1 - window, animator, 2 - animator, window, 3 - System.exit + + for(int i=0; i<args.length; i++) { + if(args[i].equals("-close")) { + closeMode = MiscUtils.atoi(args[++i], closeMode); + } + } + System.err.println("Close Mode: "+closeMode); + + final GLCapabilities caps = new GLCapabilities(GLProfile.getMaxProgrammable(true)); + caps.setBackgroundOpaque(true); + caps.setDoubleBuffered(true); + caps.setDepthBits(16); + final Animator animator = new Animator(); + GLWindow glWindow = GLWindow.create(caps); + animator.add(glWindow); + glWindow.addGLEventListener(new GLEventListener() { + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + System.out.println("GLEventListener.reshape"); + } + + @Override + public void init(GLAutoDrawable drawable) { + System.out.println("GLEventListener.init"); + } + + @Override + public void dispose(GLAutoDrawable drawable) { + System.out.println("GLEventListener.dispose"); + } + + @Override + public void display(GLAutoDrawable drawable) { + } + }); + glWindow.setTitle("Test"); + glWindow.setSize(1024, 768); + glWindow.setUndecorated(false); + glWindow.setPointerVisible(true); + glWindow.setVisible(true); + glWindow.setFullscreen(false); + glWindow.setDefaultCloseOperation(WindowClosingProtocol.WindowClosingMode.DISPOSE_ON_CLOSE); + glWindow.addWindowListener(new WindowAdapter() { + @Override + public void windowDestroyNotify(WindowEvent e) { + System.out.println("GLWindow.destroyNotify"); + } + + @Override + public void windowDestroyed(WindowEvent e) { + System.out.println("GLWindow.destroyed"); + animator.stop(); + } + }); + + animator.start(); + + switch( closeMode ) { + case 1: + sleep1s(); + glWindow.destroy(); + sleep1s(); + animator.stop(); + break; + case 2: + sleep1s(); + animator.stop(); + sleep1s(); + glWindow.destroy(); + break; + case 3: + sleep1s(); + System.exit(0); + break; + default: break; // 0 - nop + } + } + static void sleep1s() { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestCloseNewtAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestCloseNewtAWT.java index 4ebb7dddd..817f4140e 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestCloseNewtAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestCloseNewtAWT.java @@ -29,6 +29,8 @@ package com.jogamp.opengl.test.junit.newt; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import org.junit.Assert; import java.lang.reflect.InvocationTargetException; @@ -45,7 +47,9 @@ import com.jogamp.newt.awt.NewtCanvasAWT; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil.WindowClosingListener; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestCloseNewtAWT extends UITestCase { GLWindow newtWindow = null; @@ -107,9 +111,11 @@ public class TestCloseNewtAWT extends UITestCase { frame.setVisible(true); } }); - Thread.sleep(500); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(newtWindow, true)); + final WindowClosingListener closingListener = AWTRobotUtil.addClosingListener(frame); - Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, true)); + Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, true, closingListener)); } public static void main(String[] args) { diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestDisplayLifecycle01NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestDisplayLifecycle01NEWT.java index c9450c2d6..b007f57f3 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestDisplayLifecycle01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestDisplayLifecycle01NEWT.java @@ -31,18 +31,23 @@ package com.jogamp.opengl.test.junit.newt; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import javax.media.opengl.*; import com.jogamp.newt.*; import com.jogamp.newt.event.*; import com.jogamp.newt.opengl.*; +import com.jogamp.newt.util.EDTUtil; + import java.io.IOException; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.util.MiscUtils; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestDisplayLifecycle01NEWT extends UITestCase { static GLProfile glp; static GLCapabilities caps; @@ -199,8 +204,17 @@ public class TestDisplayLifecycle01NEWT extends UITestCase { Assert.assertEquals(0,Display.getActiveDisplayNumber()); Assert.assertEquals(0,display.getReferenceCount()); Assert.assertEquals(false,display.isNativeValid()); - Assert.assertNotNull(display.getEDTUtil()); - Assert.assertEquals(false,display.getEDTUtil().isRunning()); + { + final EDTUtil edtUtil = display.getEDTUtil(); + Assert.assertNotNull(edtUtil); + Assert.assertEquals(false,edtUtil.isRunning()); + edtUtil.start(); + edtUtil.invoke(true, null); + Assert.assertEquals(true,edtUtil.isRunning()); + edtUtil.invokeStop(true, null); + edtUtil.waitUntilStopped(); + Assert.assertEquals(false,edtUtil.isRunning()); + } Assert.assertEquals(0,screen.getReferenceCount()); Assert.assertEquals(false,screen.isNativeValid()); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestDisplayLifecycle02NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestDisplayLifecycle02NEWT.java index bf509124b..87cb6f05b 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestDisplayLifecycle02NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestDisplayLifecycle02NEWT.java @@ -31,6 +31,8 @@ package com.jogamp.opengl.test.junit.newt; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import javax.media.opengl.*; @@ -39,10 +41,12 @@ import com.jogamp.newt.event.*; import com.jogamp.newt.opengl.*; import java.io.IOException; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.util.MiscUtils; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestDisplayLifecycle02NEWT extends UITestCase { static GLProfile glp; static GLCapabilities caps; @@ -141,6 +145,9 @@ public class TestDisplayLifecycle02NEWT extends UITestCase { // destruction.. ref count down, but keep all window.destroy(); + Assert.assertTrue(AWTRobotUtil.waitForRealized(window, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false)); + Assert.assertEquals(screen,window.getScreen()); Assert.assertEquals(0,Display.getActiveDisplayNumber()); Assert.assertEquals(0,display.getReferenceCount()); @@ -186,6 +193,9 @@ public class TestDisplayLifecycle02NEWT extends UITestCase { System.err.println("duration: "+window.getTotalFPSDuration()); window.destroy(); + Assert.assertTrue(AWTRobotUtil.waitForRealized(window, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false)); + Assert.assertEquals(screen,window.getScreen()); Assert.assertEquals(false,window.isNativeValid()); Assert.assertEquals(false,window.isVisible()); @@ -208,7 +218,9 @@ public class TestDisplayLifecycle02NEWT extends UITestCase { Assert.assertEquals(0,Display.getActiveDisplayNumber()); // Create Display/Screen, pending lazy native creation + System.err.println("Pass - 1"); testDisplayCreate01Impl(); + System.err.println("Pass - 2"); testDisplayCreate01Impl(); Assert.assertEquals(0,Display.getActiveDisplayNumber()); @@ -285,6 +297,8 @@ public class TestDisplayLifecycle02NEWT extends UITestCase { // destruction ... window1.destroy(); + Assert.assertTrue(AWTRobotUtil.waitForRealized(window1, false)); + Assert.assertNotNull(window1.getScreen()); Assert.assertEquals(false,window1.isNativeValid()); Assert.assertEquals(false,window1.isVisible()); @@ -300,6 +314,9 @@ public class TestDisplayLifecycle02NEWT extends UITestCase { // destruction window2.destroy(); + Assert.assertTrue(AWTRobotUtil.waitForRealized(window2, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false)); + Assert.assertNotNull(window2.getScreen()); Assert.assertEquals(false,window2.isNativeValid()); Assert.assertEquals(false,window2.isVisible()); @@ -314,12 +331,12 @@ public class TestDisplayLifecycle02NEWT extends UITestCase { Assert.assertEquals(0,screen.getReferenceCount()); Assert.assertEquals(false,screen.isNativeValid()); - // invalidate .. remove all refs + // invalidate (again) .. window1.destroy(); Assert.assertEquals(false,window1.isNativeValid()); Assert.assertEquals(false,window1.isVisible()); - // invalidate .. remove all refs + // invalidate (again) .. window2.destroy(); Assert.assertEquals(false,window2.isNativeValid()); Assert.assertEquals(false,window2.isVisible()); @@ -331,7 +348,9 @@ public class TestDisplayLifecycle02NEWT extends UITestCase { Assert.assertEquals(0,Display.getActiveDisplayNumber()); // Create Display/Screen, pending lazy native creation + System.err.println("Pass - 1"); testDisplayCreate02Impl(); + System.err.println("Pass - 2"); testDisplayCreate02Impl(); Assert.assertEquals(0,Display.getActiveDisplayNumber()); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestEventSourceNotAWTBug.java b/src/test/com/jogamp/opengl/test/junit/newt/TestEventSourceNotAWTBug.java index ecf0ada8a..a2100cfc5 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestEventSourceNotAWTBug.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestEventSourceNotAWTBug.java @@ -30,6 +30,8 @@ package com.jogamp.opengl.test.junit.newt; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import java.io.IOException; import java.lang.reflect.InvocationTargetException; @@ -48,6 +50,7 @@ import com.jogamp.opengl.test.junit.util.*; /** * This simple program will throw a {@link RuntimeException} when the application is closed. */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestEventSourceNotAWTBug extends UITestCase { @BeforeClass diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindowInvisiblePointer01NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindowInvisiblePointer01NEWT.java new file mode 100644 index 000000000..75a9e87af --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindowInvisiblePointer01NEWT.java @@ -0,0 +1,117 @@ +package com.jogamp.opengl.test.junit.newt; + +import java.io.IOException; + +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.Screen; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.jogl.demos.es1.GearsES1; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLWindowInvisiblePointer01NEWT extends UITestCase { + static GLProfile glp; + static int width, height; + static long durationPerTest = 4000; // ms + + @BeforeClass + public static void initClass() { + width = 640; + height = 480; + glp = GLProfile.getDefault(); + } + + static GLWindow createWindow(Screen screen, GLCapabilitiesImmutable caps) + throws InterruptedException + { + Assert.assertNotNull(caps); + // + // Create native windowing resources .. X11/Win/OSX + // + GLWindow glWindow; + if(null!=screen) { + glWindow = GLWindow.create(screen, caps); + Assert.assertNotNull(glWindow); + } else { + glWindow = GLWindow.create(caps); + Assert.assertNotNull(glWindow); + } + glWindow.setUpdateFPSFrames(1, null); + + GLEventListener demo = new GearsES1(); + glWindow.addGLEventListener(demo); + + glWindow.setSize(512, 512); + glWindow.setVisible(true); + Assert.assertEquals(true,glWindow.isVisible()); + Assert.assertEquals(true,glWindow.isNativeValid()); + + return glWindow; + } + + static void destroyWindow(GLWindow glWindow) { + if(null!=glWindow) { + glWindow.destroy(); + Assert.assertEquals(false,glWindow.isNativeValid()); + } + } + + @Test + public void testWindow00() throws InterruptedException { + GLCapabilities caps = new GLCapabilities(glp); + Assert.assertNotNull(caps); + GLWindow window1 = createWindow(null, caps); // local + Assert.assertEquals(true,window1.isNativeValid()); + Assert.assertEquals(true,window1.isVisible()); + Animator animator = new Animator(); + animator.setUpdateFPSFrames(1, null); + animator.add(window1); + animator.start(); + AbstractGraphicsDevice device1 = window1.getScreen().getDisplay().getGraphicsDevice(); + + System.err.println("GLProfiles window1: "+device1.getConnection()+": "+GLProfile.glAvailabilityToString(device1)); + + window1.warpPointer(width / 2, height / 2); + window1.requestFocus(); + while(animator.isAnimating() && animator.getTotalFPSDuration()<durationPerTest) { + boolean pointerVisibleNewVal = (animator.getTotalFPSDuration()/100)%2==0; + window1.setPointerVisible(pointerVisibleNewVal); + Assert.assertEquals(pointerVisibleNewVal,window1.isPointerVisible()); + Thread.sleep(100); + } + + destroyWindow(window1); + } + + static int atoi(String a) { + int i=0; + try { + i = Integer.parseInt(a); + } catch (Exception ex) { ex.printStackTrace(); } + return i; + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + durationPerTest = atoi(args[++i]); + } + } + System.out.println("durationPerTest: "+durationPerTest); + String tstname = TestGLWindowInvisiblePointer01NEWT.class.getName(); + org.junit.runner.JUnitCore.main(tstname); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindowWarpPointer01NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindowWarpPointer01NEWT.java new file mode 100644 index 000000000..d6b550c80 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindowWarpPointer01NEWT.java @@ -0,0 +1,174 @@ +package com.jogamp.opengl.test.junit.newt; + +import java.io.IOException; +import java.util.Random; + +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.Screen; +import com.jogamp.newt.event.MouseAdapter; +import com.jogamp.newt.event.MouseEvent; +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; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLWindowWarpPointer01NEWT extends UITestCase { + static GLProfile glp; + static int width, height; + static long durationPerTest = 2000; // ms + + @BeforeClass + public static void initClass() { + width = 640; + height = 480; + glp = GLProfile.getDefault(); + } + + static GLWindow createWindow(Screen screen, GLCapabilitiesImmutable caps) + throws InterruptedException + { + Assert.assertNotNull(caps); + // + // Create native windowing resources .. X11/Win/OSX + // + GLWindow glWindow; + if(null!=screen) { + glWindow = GLWindow.create(screen, caps); + Assert.assertNotNull(glWindow); + } else { + glWindow = GLWindow.create(caps); + Assert.assertNotNull(glWindow); + } + glWindow.setUpdateFPSFrames(1, null); + + GLEventListener demo = new GearsES2(); + glWindow.addGLEventListener(demo); + + glWindow.setSize(512, 512); + glWindow.setVisible(true); + Assert.assertEquals(true,glWindow.isVisible()); + Assert.assertEquals(true,glWindow.isNativeValid()); + + return glWindow; + } + + static void destroyWindow(GLWindow glWindow) { + if(null!=glWindow) { + glWindow.destroy(); + Assert.assertEquals(false,glWindow.isNativeValid()); + } + } + + @Test + public void testWarp01Center() throws InterruptedException { + testWarpImpl(false); + } + + @Test + public void testWarp02Random() throws InterruptedException { + testWarpImpl(true); + } + + void testWarpImpl(final boolean random) throws InterruptedException { + GLCapabilities caps = new GLCapabilities(glp); + Assert.assertNotNull(caps); + final GLWindow window1 = createWindow(null, caps); // local + Assert.assertEquals(true,window1.isNativeValid()); + Assert.assertEquals(true,window1.isVisible()); + Animator animator = new Animator(); + animator.setUpdateFPSFrames(1, null); + animator.add(window1); + animator.start(); + AbstractGraphicsDevice device1 = window1.getScreen().getDisplay().getGraphicsDevice(); + + System.err.println("GLProfiles window1: "+device1.getConnection()+": "+GLProfile.glAvailabilityToString(device1)); + + window1.warpPointer(width / 2, height / 2); + window1.requestFocus(); + + window1.addMouseListener(new MouseAdapter() { + void warpCenter() { + window1.warpPointer(width / 2, height / 2); + } + + @Override + public void mouseEntered(MouseEvent e) { + } + + @Override + public void mouseExited(MouseEvent e) { + warpCenter(); + } + + @Override + public void mouseMoved(MouseEvent e) { + } + }); + + if( random ) { + window1.addGLEventListener(new GLEventListener() { + final Random r = new Random(); + + void warpRandom(int width, int height) { + int x = r.nextInt(width); + int y = r.nextInt(height); + window1.warpPointer(x, y); + } + + @Override + public void init(GLAutoDrawable drawable) {} + + @Override + public void dispose(GLAutoDrawable drawable) {} + + @Override + public void display(GLAutoDrawable drawable) { + warpRandom(drawable.getWidth(), drawable.getHeight()); + } + + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {} + + }); + } + + while(animator.isAnimating() && animator.getTotalFPSDuration()<durationPerTest) { + Thread.sleep(100); + } + + destroyWindow(window1); + } + + static int atoi(String a) { + int i=0; + try { + i = Integer.parseInt(a); + } catch (Exception ex) { ex.printStackTrace(); } + return i; + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + durationPerTest = atoi(args[++i]); + } + } + System.out.println("durationPerTest: "+durationPerTest); + String tstname = TestGLWindowWarpPointer01NEWT.class.getName(); + org.junit.runner.JUnitCore.main(tstname); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows00NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows00NEWT.java index 309d7c7cb..384b6806a 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows00NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows00NEWT.java @@ -31,6 +31,8 @@ package com.jogamp.opengl.test.junit.newt; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import javax.media.opengl.*; @@ -43,6 +45,7 @@ import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import javax.media.nativewindow.AbstractGraphicsDevice; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestGLWindows00NEWT extends UITestCase { static GLProfile glp; static int width, height; diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows01NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows01NEWT.java index 0c6f60b5f..2b3e448db 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows01NEWT.java @@ -31,6 +31,8 @@ package com.jogamp.opengl.test.junit.newt; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import javax.media.opengl.*; @@ -43,6 +45,7 @@ import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.util.MiscUtils; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestGLWindows01NEWT extends UITestCase { static GLProfile glp; static int width, height; diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows02NEWTAnimated.java b/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows02NEWTAnimated.java index 6f4ced53c..86cb53319 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows02NEWTAnimated.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows02NEWTAnimated.java @@ -32,6 +32,8 @@ package com.jogamp.opengl.test.junit.newt; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import javax.media.opengl.*; @@ -45,6 +47,7 @@ import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.util.MiscUtils; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestGLWindows02NEWTAnimated extends UITestCase { static GLProfile glp; static int width, height; @@ -131,8 +134,9 @@ public class TestGLWindows02NEWTAnimated extends UITestCase { Assert.assertEquals(true, animator.isStarted()); animator.remove(window); + Thread.sleep(250); // give animator a chance to become paused Assert.assertEquals(false, animator.isAnimating()); - Assert.assertEquals(false, animator.isPaused()); + Assert.assertEquals(true, animator.isPaused()); // zero drawables Assert.assertEquals(true, animator.isStarted()); Assert.assertTrue(animator.stop()); } @@ -142,21 +146,26 @@ public class TestGLWindows02NEWTAnimated extends UITestCase { GLCapabilities caps = new GLCapabilities(glp); Assert.assertNotNull(caps); GLWindow window = createWindow(null, caps, width, height, true /* onscreen */, false /* undecorated */, true /* vsync */); - Animator animator = new Animator(window); + Animator animator = new Animator(); animator.setUpdateFPSFrames(1, null); Assert.assertTrue(animator.start()); + Thread.sleep(250); // give animator a chance to become paused + Assert.assertEquals(false, animator.isAnimating()); // zero drawables + Assert.assertEquals(true, animator.isPaused()); // zero drawables + animator.add(window); while(animator.isAnimating() && animator.getTotalFPSDuration()<durationPerTest) { Thread.sleep(100); } destroyWindow(window); destroyWindow(window); Assert.assertEquals(true, animator.isAnimating()); - Assert.assertEquals(false, animator.isPaused()); Assert.assertEquals(true, animator.isStarted()); + Assert.assertEquals(false, animator.isPaused()); animator.remove(window); + Thread.sleep(250); // give animator a chance to become paused Assert.assertEquals(false, animator.isAnimating()); - Assert.assertEquals(false, animator.isPaused()); Assert.assertEquals(true, animator.isStarted()); + Assert.assertEquals(true, animator.isPaused()); // zero drawables Assert.assertTrue(animator.stop()); } @@ -181,13 +190,14 @@ public class TestGLWindows02NEWTAnimated extends UITestCase { Animator animator = new Animator(); animator.setUpdateFPSFrames(1, null); Assert.assertEquals(false, animator.isStarted()); - Assert.assertEquals(false, animator.isAnimating()); - Assert.assertEquals(false, animator.isPaused()); + Assert.assertEquals(false, animator.isAnimating()); // zero drawables + Assert.assertEquals(false, animator.isPaused()); // zero drawables, but not started Assert.assertTrue(animator.start()); Assert.assertEquals(true, animator.isStarted()); - Assert.assertEquals(false, animator.isAnimating()); - Assert.assertEquals(false, animator.isPaused()); + Thread.sleep(250); // give animator a chance to become paused + Assert.assertEquals(false, animator.isAnimating()); // zero drawables + Assert.assertEquals(true, animator.isPaused()); // zero drawables animator.add(window1); Assert.assertEquals(true, animator.isStarted()); @@ -214,8 +224,9 @@ public class TestGLWindows02NEWTAnimated extends UITestCase { window2.destroy(); animator.remove(window2); Assert.assertEquals(true, animator.isStarted()); - Assert.assertEquals(false, animator.isAnimating()); - Assert.assertEquals(false, animator.isPaused()); + Thread.sleep(250); // give animator a chance to become paused + Assert.assertEquals(false, animator.isAnimating()); // zero drawables + Assert.assertEquals(true, animator.isPaused()); // zero drawables Assert.assertTrue(animator.stop()); } @@ -250,8 +261,9 @@ public class TestGLWindows02NEWTAnimated extends UITestCase { Assert.assertTrue(animator.start()); Assert.assertEquals(true, animator.isStarted()); - Assert.assertEquals(false, animator.isAnimating()); - Assert.assertEquals(false, animator.isPaused()); + Thread.sleep(250); // give animator a chance to become paused + Assert.assertEquals(false, animator.isAnimating()); // zero drawables + Assert.assertEquals(true, animator.isPaused()); // zero drawables animator.add(window1); Assert.assertEquals(true, animator.isStarted()); @@ -275,21 +287,29 @@ public class TestGLWindows02NEWTAnimated extends UITestCase { while(animator.isAnimating() && animator.getTotalFPSDuration()<durationPerTest+durationPerTest/10) { Thread.sleep(100); } - destroyWindow(window2); - animator.remove(window2); - Assert.assertEquals(true, animator.isStarted()); - Assert.assertEquals(false, animator.isAnimating()); + + Assert.assertEquals(true, animator.isStarted()); + Assert.assertEquals(true, animator.isAnimating()); Assert.assertEquals(false, animator.isPaused()); - + Assert.assertEquals(true, animator.pause()); + Assert.assertEquals(true, animator.isStarted()); Assert.assertEquals(false, animator.isAnimating()); Assert.assertEquals(true, animator.isPaused()); Assert.assertEquals(true, animator.resume()); + Assert.assertEquals(true, animator.isStarted()); - Assert.assertEquals(false, animator.isAnimating()); + Assert.assertEquals(true, animator.isAnimating()); Assert.assertEquals(false, animator.isPaused()); + + destroyWindow(window2); + animator.remove(window2); + Assert.assertEquals(true, animator.isStarted()); + Thread.sleep(250); // give animator a chance to become paused + Assert.assertEquals(false, animator.isAnimating()); // zero drawables + Assert.assertEquals(true, animator.isPaused()); // zero drawables Assert.assertTrue(animator.stop()); Assert.assertEquals(false, animator.isStarted()); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows03NEWTAnimResize.java b/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows03NEWTAnimResize.java new file mode 100644 index 000000000..026656607 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows03NEWTAnimResize.java @@ -0,0 +1,138 @@ +/** + * Copyright 2013 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.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.event.TraceWindowAdapter; +import com.jogamp.newt.opengl.GLWindow; +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.util.Animator; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLWindows03NEWTAnimResize extends UITestCase { + static GLProfile glp; + static int step = 4; + static int width, height; + static long durationPerTest = step*500; // ms + + @BeforeClass + public static void initClass() { + width = 800; + height = 600; + glp = GLProfile.getDefault(); + } + + static void test(GLCapabilitiesImmutable caps, boolean undecorated) throws InterruptedException { + Assert.assertNotNull(caps); + + // + // Create native windowing resources .. X11/Win/OSX + // + final GLWindow glWindow = GLWindow.create(caps); + + glWindow.setUpdateFPSFrames(1, null); + Assert.assertNotNull(glWindow); + glWindow.setUndecorated(undecorated); + + GLEventListener demo = new GearsES2(1); + glWindow.addGLEventListener(demo); + glWindow.addWindowListener(new TraceWindowAdapter()); + Assert.assertEquals(false,glWindow.isNativeValid()); + + glWindow.setPosition(100, 100); + glWindow.setSize(width/step, height/step); + Assert.assertEquals(false,glWindow.isVisible()); + glWindow.setVisible(true); + Assert.assertEquals(true,glWindow.isVisible()); + Assert.assertEquals(true,glWindow.isNativeValid()); + + final Animator animator = new Animator(glWindow); + animator.setUpdateFPSFrames(1, null); + Assert.assertTrue(animator.start()); + + int step_i = 0; + for(int i=0; i<durationPerTest; i+=50) { + Thread.sleep(50); + int j = (int) ( i / (durationPerTest/step) ) + 1; + if(j>step_i) { + final int w = width/step * j; + final int h = height/step * j; + System.err.println("resize: "+step_i+" -> "+j+" - "+w+"x"+h); + glWindow.setSize(w, h); + step_i = j; + } + } + Thread.sleep(50); + + animator.stop(); + glWindow.destroy(); + Assert.assertEquals(false, glWindow.isNativeValid()); + Assert.assertEquals(false, glWindow.isVisible()); + } + + @Test + public void test01WindowDecor() throws InterruptedException { + GLCapabilities caps = new GLCapabilities(glp); + Assert.assertNotNull(caps); + test(caps, false /* undecorated */); + } + + @Test + public void test02WindowUndecor() throws InterruptedException { + GLCapabilities caps = new GLCapabilities(glp); + Assert.assertNotNull(caps); + test(caps, true /* undecorated */); + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + durationPerTest = MiscUtils.atol(args[++i], durationPerTest); + } + } + String tstname = TestGLWindows03NEWTAnimResize.class.getName(); + org.junit.runner.JUnitCore.main(tstname); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestListenerCom01AWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestListenerCom01AWT.java index fa7f0f915..91937c8c8 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestListenerCom01AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestListenerCom01AWT.java @@ -31,6 +31,8 @@ package com.jogamp.opengl.test.junit.newt; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import java.awt.Frame; @@ -47,6 +49,7 @@ import java.lang.reflect.InvocationTargetException; import com.jogamp.opengl.test.junit.util.*; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestListenerCom01AWT extends UITestCase { static int width, height; static long durationPerTest = 500; diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestRemoteGLWindows01NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestRemoteGLWindows01NEWT.java index 35e24403f..d4e8e7eac 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestRemoteGLWindows01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestRemoteGLWindows01NEWT.java @@ -30,8 +30,9 @@ package com.jogamp.opengl.test.junit.newt; import org.junit.Assert; import org.junit.Assume; -import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import javax.media.opengl.*; @@ -47,6 +48,7 @@ import com.jogamp.opengl.test.junit.jogl.demos.es1.GearsES1; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeWindowException; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestRemoteGLWindows01NEWT extends UITestCase { static int width = 640, height = 480; static long durationPerTest = 100; // ms diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestRemoteWindow01NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestRemoteWindow01NEWT.java index eb652584c..a26b96e38 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestRemoteWindow01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestRemoteWindow01NEWT.java @@ -33,6 +33,8 @@ import org.junit.Assert; import org.junit.Assume; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import javax.media.nativewindow.*; @@ -41,13 +43,14 @@ import java.io.IOException; import com.jogamp.opengl.test.junit.util.UITestCase; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestRemoteWindow01NEWT extends UITestCase { static int width, height; static String remoteDisplay = "localhost:0.0"; @BeforeClass public static void initClass() { - NativeWindowFactory.initSingleton(true); + NativeWindowFactory.initSingleton(); width = 640; height = 480; } diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode00NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode00NEWT.java deleted file mode 100644 index a5b7a76e7..000000000 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode00NEWT.java +++ /dev/null @@ -1,142 +0,0 @@ -/** - * 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.util.MonitorMode; -import com.jogamp.newt.util.ScreenModeUtil; -import com.jogamp.opengl.test.junit.util.UITestCase; -import java.util.Iterator; -import java.util.List; -import javax.media.nativewindow.util.Dimension; -import javax.media.nativewindow.util.DimensionImmutable; -import javax.media.nativewindow.util.SurfaceSize; - -public class TestScreenMode00NEWT extends UITestCase { - static int screenIdx = 0; - 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 testScreenModeInfo00() throws InterruptedException { - DimensionImmutable res = new Dimension(640, 480); - SurfaceSize surfsz = new SurfaceSize(res, 32); - DimensionImmutable mm = new Dimension(500, 400); - MonitorMode mon = new MonitorMode(surfsz, mm, 60); - ScreenMode sm_out = new ScreenMode(mon, 90); - System.err.println("00 out: "+sm_out); - - int[] props = ScreenModeUtil.streamOut(sm_out); - ScreenMode sm_in = ScreenModeUtil.streamIn(props, 0); - System.err.println("00 in : "+sm_in); - - Assert.assertEquals(sm_in.getMonitorMode().getSurfaceSize().getResolution(), - sm_out.getMonitorMode().getSurfaceSize().getResolution()); - - Assert.assertEquals(sm_in.getMonitorMode().getSurfaceSize(), - sm_out.getMonitorMode().getSurfaceSize()); - - Assert.assertEquals(sm_in.getMonitorMode().getScreenSizeMM(), - sm_out.getMonitorMode().getScreenSizeMM()); - - Assert.assertEquals(sm_in.getMonitorMode(), sm_out.getMonitorMode()); - - Assert.assertEquals(sm_in, sm_out); - - Assert.assertEquals(sm_out.hashCode(), sm_in.hashCode()); - } - - @Test - public void testScreenModeInfo01() throws InterruptedException { - Display dpy = NewtFactory.createDisplay(null); - Screen screen = NewtFactory.createScreen(dpy, screenIdx); - screen.addReference(); - Assert.assertEquals(true,screen.isNativeValid()); - Assert.assertEquals(true,screen.getDisplay().isNativeValid()); - System.err.println("Screen: "+screen.toString()); - - List<ScreenMode> screenModes = screen.getScreenModes(); - 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: "+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); - - screen.removeReference(); - - Assert.assertEquals(false,screen.isNativeValid()); - Assert.assertEquals(false,screen.getDisplay().isNativeValid()); - } - - static int atoi(String a) { - try { - return Integer.parseInt(a); - } catch (Exception ex) { throw new RuntimeException(ex); } - } - - public static void main(String args[]) throws IOException { - for(int i=0; i<args.length; i++) { - if(args[i].equals("-screen")) { - i++; - screenIdx = atoi(args[i]); - } - } - String tstname = TestScreenMode00NEWT.class.getName(); - org.junit.runner.JUnitCore.main(tstname); - } -} diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01bNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01bNEWT.java deleted file mode 100644 index 38612faa8..000000000 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01bNEWT.java +++ /dev/null @@ -1,189 +0,0 @@ -/** - * 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() { - 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(screenModes.size()==1) { - // 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 deleted file mode 100644 index 1c9cb91f3..000000000 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode02NEWT.java +++ /dev/null @@ -1,187 +0,0 @@ -/** - * 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.opengl.GLCapabilities; -import javax.media.opengl.GLProfile; - -import com.jogamp.opengl.util.Animator; - -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; - -public class TestScreenMode02NEWT extends UITestCase { - static GLProfile glp; - static int width, height; - - static int waitTimeShort = 2000; // 2 sec - static int waitTimeLong = 8000; // 8 sec - - @BeforeClass - public static void initClass() { - width = 640; - height = 480; - glp = GLProfile.getDefault(); - } - - @AfterClass - public static void releaseClass() throws InterruptedException { - Thread.sleep(waitTimeShort); - } - - static GLWindow createWindow(Screen screen, GLCapabilities caps, int width, int height, boolean onscreen, boolean undecorated) { - Assert.assertNotNull(caps); - caps.setOnscreen(onscreen); - - GLWindow window = GLWindow.create(screen, caps); - window.setSize(width, height); - window.addGLEventListener(new GearsES2()); - Assert.assertNotNull(window); - window.setVisible(true); - Assert.assertTrue(window.isVisible()); - return window; - } - - static void destroyWindow(Window window) { - if(null!=window) { - window.destroy(); - } - } - - @Test - public void testScreenRotationChange01() 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); - GLWindow window = createWindow(screen, caps, width, height, true /* onscreen */, false /* undecorated */); - Assert.assertNotNull(window); - - List<ScreenMode> screenModes = screen.getScreenModes(); - if(screenModes.size()==1) { - // no support .. - System.err.println("Your platform has no ScreenMode change support, sorry"); - destroyWindow(window); - return; - } - Assert.assertTrue(screenModes.size()>0); - - Animator animator = new Animator(window); - animator.start(); - - 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, 90); - if(null==screenModes) { - // no rotation support .. - System.err.println("Your platform has no rotation support, sorry"); - destroyWindow(window); - return; - } - 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(waitTimeLong); - - // check reset .. - - Assert.assertEquals(true,display.isNativeValid()); - Assert.assertEquals(true,screen.isNativeValid()); - Assert.assertEquals(true,window.isNativeValid()); - Assert.assertEquals(true,window.isVisible()); - - animator.stop(); - destroyWindow(window); - - Assert.assertEquals(false,window.isVisible()); - Assert.assertEquals(false,window.isNativeValid()); - Assert.assertEquals(false,screen.isNativeValid()); - Assert.assertEquals(false,display.isNativeValid()); - - screen.createNative(); // trigger native re-creation - - Assert.assertEquals(true,display.isNativeValid()); - Assert.assertEquals(true,screen.isNativeValid()); - - smCurrent = screen.getCurrentScreenMode(); - System.err.println("[1] current/orig: "+smCurrent); - - Assert.assertNotNull(smCurrent); - Assert.assertEquals(smCurrent, smOrig); - - screen.destroy(); - - Assert.assertEquals(false,screen.isNativeValid()); - Assert.assertEquals(false,display.isNativeValid()); - } - - public static void main(String args[]) throws IOException { - String tstname = TestScreenMode02NEWT.class.getName(); - org.junit.runner.JUnitCore.main(tstname); - } - -} diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol01AWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol01AWT.java index d63f0d2a7..a88b20714 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol01AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol01AWT.java @@ -29,6 +29,8 @@ package com.jogamp.opengl.test.junit.newt; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import org.junit.Assert; import java.lang.reflect.InvocationTargetException; @@ -46,13 +48,15 @@ import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil.WindowClosingListener; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestWindowClosingProtocol01AWT extends UITestCase { @Test public void testCloseFrameGLCanvas() throws InterruptedException, InvocationTargetException { final Frame frame = new Frame("testCloseFrameGLCanvas AWT"); - + final WindowClosingListener closingListener = AWTRobotUtil.addClosingListener(frame); GLProfile glp = GLProfile.getGL2ES2(); GLCapabilities caps = new GLCapabilities(glp); final GLCanvas glCanvas = new GLCanvas(caps); @@ -74,12 +78,14 @@ public class TestWindowClosingProtocol01AWT extends UITestCase { WindowClosingMode op = glCanvas.getDefaultCloseOperation(); Assert.assertEquals(WindowClosingMode.DO_NOTHING_ON_CLOSE, op); - Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, false)); // nop + Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, false, closingListener)); // nop Thread.sleep(100); - Assert.assertEquals(true, frame.isDisplayable()); + Assert.assertEquals(true, frame.isDisplayable()); Assert.assertEquals(true, frame.isVisible()); - Assert.assertEquals(true, glCanvas.isValid()); - Assert.assertEquals(true, glCanvas.isDisplayable()); + Assert.assertEquals(true, glCanvas.isValid()); + Assert.assertEquals(true, glCanvas.isDisplayable()); + Assert.assertEquals(true, closingListener.isWindowClosing()); + Assert.assertEquals(false, closingListener.isWindowClosed()); // // close with op (GLCanvas): DISPOSE_ON_CLOSE -> dispose @@ -87,11 +93,18 @@ public class TestWindowClosingProtocol01AWT extends UITestCase { glCanvas.setDefaultCloseOperation(WindowClosingMode.DISPOSE_ON_CLOSE); op = glCanvas.getDefaultCloseOperation(); Assert.assertEquals(WindowClosingMode.DISPOSE_ON_CLOSE, op); + + Thread.sleep(300); - Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, false)); // no frame close - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas, false)); + Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, false, closingListener)); // no frame close, but GLCanvas's GL resources will be destroyed + Thread.sleep(100); Assert.assertEquals(true, frame.isDisplayable()); Assert.assertEquals(true, frame.isVisible()); + Assert.assertEquals(true, closingListener.isWindowClosing()); + Assert.assertEquals(false, closingListener.isWindowClosed()); + for (int wait=0; wait<AWTRobotUtil.POLL_DIVIDER && glCanvas.isRealized(); wait++) { + Thread.sleep(AWTRobotUtil.TIME_SLICE); + } Assert.assertEquals(false, glCanvas.isRealized()); SwingUtilities.invokeAndWait(new Runnable() { @@ -103,17 +116,18 @@ public class TestWindowClosingProtocol01AWT extends UITestCase { @Test public void testCloseJFrameGLCanvas() throws InterruptedException, InvocationTargetException { final JFrame frame = new JFrame("testCloseJFrameGLCanvas AWT"); - + final WindowClosingListener closingListener = AWTRobotUtil.addClosingListener(frame); + GLProfile glp = GLProfile.getGL2ES2(); GLCapabilities caps = new GLCapabilities(glp); - GLCanvas glCanvas = new GLCanvas(caps); + final GLCanvas glCanvas = new GLCanvas(caps); glCanvas.addGLEventListener(new GearsES2()); - frame.getContentPane().add(glCanvas); - frame.pack(); - frame.setSize(512, 512); - frame.validate(); SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame.getContentPane().add(glCanvas); + frame.pack(); + frame.setSize(512, 512); + frame.validate(); frame.setVisible(true); } }); Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); @@ -126,9 +140,12 @@ public class TestWindowClosingProtocol01AWT extends UITestCase { WindowClosingMode op = glCanvas.getDefaultCloseOperation(); Assert.assertEquals(WindowClosingMode.DO_NOTHING_ON_CLOSE, op); - Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, false)); // nop - Thread.sleep(100); + Thread.sleep(300); + + Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, false, closingListener)); // hide + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, false)); // hide -> invisible Assert.assertEquals(true, frame.isDisplayable()); + Assert.assertEquals(false, frame.isVisible()); Assert.assertEquals(true, glCanvas.isValid()); Assert.assertEquals(true, glCanvas.isDisplayable()); @@ -138,6 +155,8 @@ public class TestWindowClosingProtocol01AWT extends UITestCase { } }); Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas, true)); + Assert.assertEquals(true, frame.isDisplayable()); + Assert.assertEquals(true, frame.isVisible()); // // close with op (JFrame): DISPOSE_ON_CLOSE -- GLCanvas --> dispose @@ -147,7 +166,7 @@ public class TestWindowClosingProtocol01AWT extends UITestCase { op = glCanvas.getDefaultCloseOperation(); Assert.assertEquals(WindowClosingMode.DISPOSE_ON_CLOSE, op); - Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, true)); + Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, true, closingListener)); Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas, false)); Assert.assertEquals(false, frame.isDisplayable()); Assert.assertEquals(false, glCanvas.isValid()); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol02NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol02NEWT.java index 1657fcbe9..020581cb0 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol02NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol02NEWT.java @@ -31,6 +31,8 @@ package com.jogamp.opengl.test.junit.newt; import java.lang.reflect.InvocationTargetException; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import org.junit.Assert; import javax.media.nativewindow.WindowClosingProtocol.WindowClosingMode; @@ -45,6 +47,7 @@ import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.UITestCase; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestWindowClosingProtocol02NEWT extends UITestCase { @Test @@ -52,7 +55,7 @@ public class TestWindowClosingProtocol02NEWT extends UITestCase { GLProfile glp = GLProfile.getGL2ES2(); GLCapabilities caps = new GLCapabilities(glp); final GLWindow glWindow = GLWindow.create(caps); - final AWTRobotUtil.WindowClosingListener windowClosingListener = AWTRobotUtil.addClosingListener(glWindow); + final AWTRobotUtil.WindowClosingListener closingListener = AWTRobotUtil.addClosingListener(glWindow); glWindow.addGLEventListener(new GearsES2()); glWindow.setSize(512, 512); @@ -69,11 +72,13 @@ public class TestWindowClosingProtocol02NEWT extends UITestCase { glWindow.setDefaultCloseOperation(WindowClosingMode.DO_NOTHING_ON_CLOSE); op = glWindow.getDefaultCloseOperation(); Assert.assertEquals(WindowClosingMode.DO_NOTHING_ON_CLOSE, op); + + Thread.sleep(300); - Assert.assertEquals(true, AWTRobotUtil.closeWindow(glWindow, false)); // nop + Assert.assertEquals(true, AWTRobotUtil.closeWindow(glWindow, false, closingListener)); // nop Assert.assertEquals(true, glWindow.isNativeValid()); - Assert.assertEquals(true, windowClosingListener.isWindowClosing()); - windowClosingListener.reset(); + Assert.assertEquals(true, closingListener.isWindowClosing()); + closingListener.reset(); // // close with op (GLCanvas): DISPOSE_ON_CLOSE -> dispose @@ -82,9 +87,9 @@ public class TestWindowClosingProtocol02NEWT extends UITestCase { op = glWindow.getDefaultCloseOperation(); Assert.assertEquals(WindowClosingMode.DISPOSE_ON_CLOSE, op); - Assert.assertEquals(true, AWTRobotUtil.closeWindow(glWindow, true)); + Assert.assertEquals(true, AWTRobotUtil.closeWindow(glWindow, true, closingListener)); Assert.assertEquals(false, glWindow.isNativeValid()); - Assert.assertEquals(true, windowClosingListener.isWindowClosing()); + Assert.assertEquals(true, closingListener.isWindowClosing()); } public static void main(String[] args) { diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol03NewtAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol03NewtAWT.java index 65068e9e8..efc833d88 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol03NewtAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol03NewtAWT.java @@ -31,6 +31,8 @@ package com.jogamp.opengl.test.junit.newt; import com.jogamp.newt.awt.NewtCanvasAWT; import com.jogamp.newt.opengl.GLWindow; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import org.junit.Assert; import java.lang.reflect.InvocationTargetException; @@ -46,17 +48,20 @@ import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil.WindowClosingListener; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestWindowClosingProtocol03NewtAWT extends UITestCase { @Test public void testCloseJFrameNewtCanvasAWT() throws InterruptedException, InvocationTargetException { final JFrame frame = new JFrame("testCloseJFrameNewtCanvasAWT"); - + final WindowClosingListener awtClosingListener = AWTRobotUtil.addClosingListener(frame); + GLProfile glp = GLProfile.getGL2ES2(); GLCapabilities caps = new GLCapabilities(glp); final GLWindow glWindow = GLWindow.create(caps); - final AWTRobotUtil.WindowClosingListener windowClosingListener = AWTRobotUtil.addClosingListener(glWindow); + final AWTRobotUtil.WindowClosingListener newtClosingListener = AWTRobotUtil.addClosingListener(glWindow); glWindow.addGLEventListener(new GearsES2()); @@ -81,42 +86,60 @@ public class TestWindowClosingProtocol03NewtAWT extends UITestCase { // // close with op: DO_NOTHING_ON_CLOSE -> NOP / HIDE (default) // - Assert.assertEquals(JFrame.HIDE_ON_CLOSE, frame.getDefaultCloseOperation()); - WindowClosingMode op = newtCanvas.getDefaultCloseOperation(); - Assert.assertEquals(WindowClosingMode.DO_NOTHING_ON_CLOSE, op); + { + Assert.assertEquals(JFrame.HIDE_ON_CLOSE, frame.getDefaultCloseOperation()); + WindowClosingMode op = newtCanvas.getDefaultCloseOperation(); + Assert.assertEquals(WindowClosingMode.DO_NOTHING_ON_CLOSE, op); + } - Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, false)); + Thread.sleep(300); + + Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, false, awtClosingListener)); // hide + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, false)); // hide -> invisible Assert.assertEquals(true, frame.isDisplayable()); Assert.assertEquals(false, frame.isVisible()); Assert.assertEquals(true, newtCanvas.isValid()); Assert.assertEquals(true, newtCanvas.isDisplayable()); Assert.assertEquals(true, glWindow.isNativeValid()); - Assert.assertEquals(true, windowClosingListener.isWindowClosing()); - windowClosingListener.reset(); + Assert.assertEquals(true, awtClosingListener.isWindowClosing()); + Assert.assertEquals(false, awtClosingListener.isWindowClosed()); + Assert.assertEquals(true, newtClosingListener.isWindowClosing()); + Assert.assertEquals(false, newtClosingListener.isWindowClosed()); + awtClosingListener.reset(); + newtClosingListener.reset(); SwingUtilities.invokeAndWait(new Runnable() { public void run() { frame.setVisible(true); } }); Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, true)); Assert.assertEquals(true, frame.isDisplayable()); Assert.assertEquals(true, frame.isVisible()); // // close with op (JFrame): DISPOSE_ON_CLOSE -- newtCanvas -- glWindow --> dispose // - frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); - Assert.assertEquals(JFrame.DISPOSE_ON_CLOSE, frame.getDefaultCloseOperation()); - op = newtCanvas.getDefaultCloseOperation(); - Assert.assertEquals(WindowClosingMode.DISPOSE_ON_CLOSE, op); + { + frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + Assert.assertEquals(JFrame.DISPOSE_ON_CLOSE, frame.getDefaultCloseOperation()); + WindowClosingMode op = newtCanvas.getDefaultCloseOperation(); + Assert.assertEquals(WindowClosingMode.DISPOSE_ON_CLOSE, op); + } + + Thread.sleep(300); - Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, true)); + Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, true, awtClosingListener)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false)); Assert.assertEquals(false, frame.isDisplayable()); Assert.assertEquals(false, frame.isVisible()); Assert.assertEquals(false, newtCanvas.isValid()); Assert.assertEquals(false, newtCanvas.isDisplayable()); Assert.assertEquals(false, glWindow.isNativeValid()); - Assert.assertEquals(true, windowClosingListener.isWindowClosing()); + Assert.assertEquals(true, awtClosingListener.isWindowClosing()); + Assert.assertEquals(true, awtClosingListener.isWindowClosed()); + Assert.assertEquals(true, newtClosingListener.isWindowClosing()); + Assert.assertEquals(true, newtClosingListener.isWindowClosed()); } public static void main(String[] args) { diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestWindows01NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestWindows01NEWT.java index a99edfadb..6b44a4b2c 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestWindows01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestWindows01NEWT.java @@ -31,21 +31,23 @@ package com.jogamp.opengl.test.junit.newt; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import javax.media.nativewindow.*; -import javax.media.nativewindow.util.Point; import com.jogamp.newt.*; import java.io.IOException; import com.jogamp.opengl.test.junit.util.UITestCase; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestWindows01NEWT extends UITestCase { static int width, height; @BeforeClass public static void initClass() { - NativeWindowFactory.initSingleton(true); + NativeWindowFactory.initSingleton(); width = 256; height = 256; } diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/BaseNewtEventModifiers.java b/src/test/com/jogamp/opengl/test/junit/newt/event/BaseNewtEventModifiers.java new file mode 100644 index 000000000..a46e21b23 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/newt/event/BaseNewtEventModifiers.java @@ -0,0 +1,783 @@ +/** + * 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.event ; + +import java.io.PrintStream ; +import java.util.ArrayList ; + +import javax.media.opengl.GLProfile ; + +import org.junit.Assert ; +import org.junit.BeforeClass ; +import org.junit.FixMethodOrder; +import org.junit.Test ; +import org.junit.runners.MethodSorters; + +import com.jogamp.common.util.RunnableTask; +import com.jogamp.newt.event.MouseEvent; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase ; + +/** + * Test whether or not event modifiers are preserved by NEWT. This + * class defines most of the tests, but leaves the type of window + * and canvas up to subclasses. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public abstract class BaseNewtEventModifiers extends UITestCase { + + //////////////////////////////////////////////////////////////////////////// + + protected static final int TEST_FRAME_X = 100 ; + protected static final int TEST_FRAME_Y = 100 ; + + protected static final int TEST_FRAME_WIDTH = 400 ; + protected static final int TEST_FRAME_HEIGHT = 400 ; + + protected static final int INITIAL_MOUSE_X = TEST_FRAME_X + ( TEST_FRAME_WIDTH / 2 ) ; + protected static final int INITIAL_MOUSE_Y = TEST_FRAME_Y + ( TEST_FRAME_HEIGHT / 2 ) ; + + protected static final int MS_ROBOT_KEY_PRESS_DELAY = 50 ; + protected static final int MS_ROBOT_KEY_RELEASE_DELAY = 50 ; + protected static final int MS_ROBOT_MOUSE_MOVE_DELAY = 200 ; + + protected static final int MS_ROBOT_AUTO_DELAY = 50 ; + protected static final int MS_ROBOT_POST_TEST_DELAY = 100; + + protected static final boolean _debug = true ; + protected static PrintStream _debugPrintStream = System.err ; + + //////////////////////////////////////////////////////////////////////////// + + static + { + GLProfile.initSingleton() ; + } + + private static class TestMouseListener implements com.jogamp.newt.event.MouseListener + { + private static final String NO_EVENT_DELIVERY = "no event delivery" ; + + private boolean _modifierCheckEnabled ; + private int _expectedModifiers; + private volatile int _eventCount ; + private ArrayList<String> _failures = new ArrayList<String>() ; + + public synchronized void setModifierCheckEnabled( boolean value ) { + _modifierCheckEnabled = value ; + } + + public synchronized boolean modifierCheckEnabled() { + return _modifierCheckEnabled ; + } + + /** + * Sets the modifiers the listener should expect, and clears + * out any existing accumulated failures. Normally this kind + * of double duty in a setter might be considered evil, but + * in this test code it's probably ok. + */ + + public synchronized void setExpectedModifiers( int value ) { + _expectedModifiers = value ; + clear(); + } + + public synchronized ArrayList<String> clear() { + ArrayList<String> old = _failures; + + _eventCount = 0; + + // Assume we will have a failure due to no event delivery. + // If an event is delivered and it's good this assumed + // failure will get cleared out. + _failures = new ArrayList<String>(); + _failures.add( NO_EVENT_DELIVERY ); + return old; + } + + public ArrayList<String> getFailures(int waitEventCount) { + int j; + for(j=0; j < 20 && _eventCount < waitEventCount; j++) { // wait until events are collected + _robot.delay(MS_ROBOT_AUTO_DELAY); + } + if(0 == _eventCount) { + _debugPrintStream.println("**** No Event. Waited "+j+" * "+MS_ROBOT_AUTO_DELAY+"ms, eventCount "+_eventCount); + } + return clear(); + } + + private synchronized void _checkModifiers( com.jogamp.newt.event.MouseEvent hasEvent ) { + if( _modifierCheckEnabled ) { + + final MouseEvent expEvent = new MouseEvent(hasEvent.getEventType(), hasEvent.getSource(), hasEvent.getWhen(), _expectedModifiers, + hasEvent.getX(), hasEvent.getY(), hasEvent.getClickCount(), hasEvent.getButton(), + hasEvent.getRotation(), hasEvent.getRotationScale()); + + _checkModifierMask( expEvent, hasEvent, com.jogamp.newt.event.InputEvent.SHIFT_MASK, "shift" ) ; + _checkModifierMask( expEvent, hasEvent, com.jogamp.newt.event.InputEvent.CTRL_MASK, "ctrl" ) ; + _checkModifierMask( expEvent, hasEvent, com.jogamp.newt.event.InputEvent.META_MASK, "meta" ) ; + _checkModifierMask( expEvent, hasEvent, com.jogamp.newt.event.InputEvent.ALT_MASK, "alt" ) ; + _checkModifierMask( expEvent, hasEvent, com.jogamp.newt.event.InputEvent.ALT_GRAPH_MASK, "graph" ) ; + + for( int n = 0 ; n < _numButtonsToTest ; ++n ) { + _checkModifierMask( expEvent, hasEvent, com.jogamp.newt.event.InputEvent.getButtonMask( n + 1 ), "button"+(n+1) ) ; + } + } + } + + private synchronized void _checkModifierMask( com.jogamp.newt.event.MouseEvent expEvent, com.jogamp.newt.event.MouseEvent hasEvent, int mask, String maskS ) { + + // If the "no event delivery" failure is still in the list then + // get rid of it since that obviously isn't true anymore. We + // want to do this whether or not there's an issue with the + // modifiers. + + if( _failures.size() == 1 && _failures.get(0).equals( NO_EVENT_DELIVERY ) ) { + _failures.clear() ; + } + + if( ( hasEvent.getModifiers() & mask ) != ( expEvent.getModifiers() & mask ) ) { + StringBuilder sb = new StringBuilder(); + sb.append( com.jogamp.newt.event.MouseEvent.getEventTypeString( hasEvent.getEventType() ) ).append(": mask ").append(maskS).append(" 0x").append(Integer.toHexString(mask)); + sb.append(", eventCount ").append(_eventCount).append(", expected:"); + expEvent.getModifiersString(sb); + sb.append(", have: "); + hasEvent.getModifiersString(sb); + sb.append(" - full event: "); + hasEvent.toString(sb); + _failures.add( sb.toString() ) ; + } + } + + public synchronized void mousePressed( com.jogamp.newt.event.MouseEvent event ) { + _eventCount++; + if( _debug ) { + _debugPrintStream.println( "MousePressed "+_eventCount+": "+event); + } + _checkModifiers( event ) ; + } + + public synchronized void mouseReleased( com.jogamp.newt.event.MouseEvent event ) { + _eventCount++; + if( _debug ) { + _debugPrintStream.println( "MouseReleased "+_eventCount+": "+event); + } + _checkModifiers( event ) ; + } + + public synchronized void mouseDragged( com.jogamp.newt.event.MouseEvent event ) { + _eventCount++; + if( _debug ) { + _debugPrintStream.println( "MouseDragged "+_eventCount+": "+event); + } + _checkModifiers( event ) ; + } + + // + // IGNORED + // + + public synchronized void mouseMoved( com.jogamp.newt.event.MouseEvent event ) { + // Ignored, since mouse MOVE doesn't hold mouse button, we look for DRAGGED! + // _eventCount++; + if( _debug ) { + _debugPrintStream.println( "MouseMoved ignored: "+event); + } + // _checkModifiers( event ) ; + } + + public synchronized void mouseClicked( com.jogamp.newt.event.MouseEvent event ) { + // Ignored, since we look for PRESS/RELEASE only! + // _eventCount++; + if( _debug ) { + _debugPrintStream.println( "MouseClicked ignored: "+event); + } + // _checkModifiers( event ) ; + } + + public synchronized void mouseWheelMoved( com.jogamp.newt.event.MouseEvent event ) { + // _eventCount++; + if( _debug ) { + _debugPrintStream.println( "MouseWheeleMoved ignored: "+event); + } + // _checkModifiers( event ) ; + } + + public synchronized void mouseEntered( com.jogamp.newt.event.MouseEvent event ) { + // _eventCount++; + if( _debug ) { + _debugPrintStream.println( "MouseEntered ignored: "+event); + } + // _checkModifiers( event ) ; + } + + public synchronized void mouseExited( com.jogamp.newt.event.MouseEvent event ) { + // _eventCount++; + if( _debug ) { + _debugPrintStream.println( "MouseExited ignored: "+event); + } + // _checkModifiers( event ) ; + } + + } + + //////////////////////////////////////////////////////////////////////////// + + private static int _numButtonsToTest ; + private static int _awtButtonMasks[] ; + + protected static java.awt.Robot _robot ; + + protected static TestMouseListener _testMouseListener ; + + //////////////////////////////////////////////////////////////////////////// + + public static int getAWTButtonMask(int button) { + // Java7: java.awt.event.InputEvent.getMaskForButton( n + 1 ) ; -> using InputEvent.BUTTON1_DOWN_MASK .. etc + // Java6: Only use BUTTON1_MASK, .. + int m; + switch(button) { + case 1 : m = java.awt.event.InputEvent.BUTTON1_MASK; break; + case 2 : m = java.awt.event.InputEvent.BUTTON2_MASK; break; + case 3 : m = java.awt.event.InputEvent.BUTTON3_MASK; break; + default: throw new IllegalArgumentException("Only buttons 1-3 have a MASK value, requested button "+button); + } + return m; + } + + @BeforeClass + public static void baseBeforeClass() throws Exception { + + // Who know how many buttons the AWT will say exist on given platform. + // We'll test the smaller of what NEWT supports and what the + // AWT says is available. + /** Java7: + if( java.awt.Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled() ) { + _numButtonsToTest = java.awt.MouseInfo.getNumberOfButtons() ; + } else { + _numButtonsToTest = 3 ; + } */ + _numButtonsToTest = 3 ; + + // Then again, maybe not: + + // FIXME? - for reasons I'm not quite sure of the AWT MouseEvent + // constructor does some strange things for buttons other than + // 1, 2, and 3. Furthermore, while developing this test it + // appeared that events sent by the robot for buttons 9 and + // up weren't even delivered to the listeners. + // + // So... for now we're only going to test 3 buttons since + // that's the common case _and_ Java6 safe. + + _numButtonsToTest = 3 ; + + { + if( _numButtonsToTest > com.jogamp.newt.event.MouseEvent.BUTTON_COUNT ) { + _numButtonsToTest = com.jogamp.newt.event.MouseEvent.BUTTON_COUNT ; + } + + // These two arrays are assumed to be peers, i.e. are the same + // size, and a given index references the same button in + // either array. + + _awtButtonMasks = new int[_numButtonsToTest] ; + + for( int n = 0 ; n < _awtButtonMasks.length ; ++n ) { + _awtButtonMasks[n] = getAWTButtonMask( n + 1 ); + } + } + + _robot = new java.awt.Robot() ; + _robot.setAutoWaitForIdle( true ) ; + + _testMouseListener = new TestMouseListener() ; + } + + //////////////////////////////////////////////////////////////////////////// + // Following both methods are mandatory to deal with SWT's requirement + // to run the SWT event dispatch on the TK thread - which must be the main thread on OSX. + // We spawn off the actual test-action into another thread, + // while dispatching the events until the test-action is completed. + // YES: This is sort of ideal - NOT :) + + protected void eventDispatch() { + try { + Thread.sleep(100); + } catch (InterruptedException e) { } + } + + private void execOffThreadWithOnThreadEventDispatch(Runnable testAction) throws Exception { + _testMouseListener.setModifierCheckEnabled( false ) ; + _robot.setAutoDelay( MS_ROBOT_AUTO_DELAY ) ; + { + // Make sure all the buttons and modifier keys are released. + clearKeyboadAndMouse(); + } + _testMouseListener.setModifierCheckEnabled( true ) ; + + Throwable throwable = null; + // final Object sync = new Object(); + final RunnableTask rt = new RunnableTask( testAction, null, true, System.err ); + try { + // synchronized(sync) { + new Thread(rt, "Test-Thread").start(); + int i=0; + while( !rt.isExecuted() && null == throwable ) { + System.err.println("WAIT-till-done: eventDispatch() #"+i++); + eventDispatch(); + } + if(null==throwable) { + throwable = rt.getThrowable(); + } + if(null!=throwable) { + throw new RuntimeException(throwable); + } + // } + } finally { + System.err.println("WAIT-till-done: DONE"); + _testMouseListener.setModifierCheckEnabled( false ) ; + clearKeyboadAndMouse(); + } + } + + //////////////////////////////////////////////////////////////////////////// + + // The approach on all these tests is to tell the test mouse listener what + // modifiers we think it should receive. Then when the events are delivered + // it compares what we told it to expect with what actually showed up and + // complains if there are differences. + // + // As things stand currently the tests below generally work for AWTCanvas + // and fail for everything else. This may point to a flaw in the test + // code, or a flaw in the NEWT stuff; not sure yet. One exception is the + // tests involving ALT and META, which on at least X11 cause the desktop + // to do undesirable stuff while the tests are in progress. So... these + // tests have been commented out for now and probably should be left + // that way. + // + // Due to the fact that a majority of these fail currently for + // everything but AWTCanvas for the time being we probably shouldn't + // run the tests for NewtCanvasAWT and NewtCanvasSWT until we can + // pay more attention to the NEWT event modifier stuff. + + @Test(timeout=180000) // TO 3 min + public void testSingleButtonPressAndRelease() throws Exception { + execOffThreadWithOnThreadEventDispatch(new Runnable() { + public void run() { + try { + _doSingleButtonPressAndRelease( 0, 0 ); + } catch (Exception e) { throw new RuntimeException(e); } + } } ); + } + + @Test(timeout=180000) // TO 3 min + public void testSingleButtonPressAndReleaseWithShift() throws Exception { + execOffThreadWithOnThreadEventDispatch(new Runnable() { + public void run() { + try { + _doSingleButtonPressAndRelease( java.awt.event.KeyEvent.VK_SHIFT, java.awt.event.InputEvent.SHIFT_DOWN_MASK ) ; + } catch (Exception e) { throw new RuntimeException(e); } + } } ); + } + + @Test(timeout=180000) // TO 3 min + public void testSingleButtonPressAndReleaseWithCtrl() throws Exception { + execOffThreadWithOnThreadEventDispatch(new Runnable() { + public void run() { + try { + _doSingleButtonPressAndRelease( java.awt.event.KeyEvent.VK_CONTROL, java.awt.event.InputEvent.CTRL_DOWN_MASK ) ; + } catch (Exception e) { throw new RuntimeException(e); } + } } ); + } + + /** + * The META and ALT tests get too tied up with functions of the window system on X11, + * so it's probably best to leave them commented out. + @Test(timeout=180000) // TO 3 min + public void testSingleButtonPressAndReleaseWithMeta() throws Exception { + execOffThreadWithOnThreadEventDispatch(new Runnable() { + public void run() { + try { + _doSingleButtonPressAndRelease( java.awt.event.KeyEvent.VK_META, java.awt.event.InputEvent.META_DOWN_MASK ) ; + } catch (Exception e) { throw new RuntimeException(e); } + } } ); + } + + @Test(timeout=180000) // TO 3 min + public void testSingleButtonPressAndReleaseWithAlt() throws Exception { + execOffThreadWithOnThreadEventDispatch(new Runnable() { + public void run() { + try { + _doSingleButtonPressAndRelease( java.awt.event.KeyEvent.VK_ALT, java.awt.event.InputEvent.ALT_DOWN_MASK ) ; + } catch (Exception e) { throw new RuntimeException(e); } + } } ); + } + */ + + /** + * FIXME - not sure yet what's up with ALT_GRAPH. It appears that this + * modifier didn't make it through, so I had to disable this test else it would always fail. + * + * My US keyboard doesn't have an AltGr key, so maybe X is smart + * enough to not let this modifier slip through (?). + @Test + public void testSingleButtonPressAndReleaseWithAltGraph() throws Exception { + execOffThreadWithOnThreadEventDispatch(new Runnable() { + public void run() { + try { + _doSingleButtonPressAndRelease( java.awt.event.KeyEvent.VK_ALT_GRAPH, java.awt.event.InputEvent.ALT_GRAPH_DOWN_MASK ) ; + } catch (Exception e) { throw new RuntimeException(e); } + } } ); + } + */ + + //////////////////////////////////////////////////////////////////////////// + + @Test(timeout=180000) // TO 3 min + public void testHoldOneButtonAndPressAnother() throws Exception { + execOffThreadWithOnThreadEventDispatch(new Runnable() { + public void run() { + try { + _doHoldOneButtonAndPressAnother( 0, 0 ) ; + } catch (Exception e) { throw new RuntimeException(e); } + } } ); + } + + @Test(timeout=180000) // TO 3 min + public void testPressAllButtonsInSequence() throws Exception { + execOffThreadWithOnThreadEventDispatch(new Runnable() { + public void run() { + try { + _doPressAllButtonsInSequence( 0, 0 ) ; + } catch (Exception e) { throw new RuntimeException(e); } + } } ); + } + + @Test(timeout=180000) // TO 3 min + public void testSingleButtonClickAndDrag() throws Exception { + execOffThreadWithOnThreadEventDispatch(new Runnable() { + public void run() { + try { + _doSingleButtonClickAndDrag( 0, 0 ) ; + } catch (Exception e) { throw new RuntimeException(e); } + } } ); + } + + //////////////////////////////////////////////////////////////////////////// + + private void _doSingleButtonPressAndRelease( final int keyCode, final int keyModifierMask ) throws Exception { + + if( _debug ) { _debugPrintStream.println( "\n>>>> _doSingleButtonPressAndRelease" ) ; } + + _doKeyPress( keyCode ) ; + + for (int n = 0 ; n < _numButtonsToTest ; ++n) { + + int awtButtonMask = _awtButtonMasks[n] ; + + if( _debug ) { _debugPrintStream.println( "*** pressing button " + ( n + 1 ) ) ; } + _testMouseListener.setExpectedModifiers( _getNewtModifiersForAwtExtendedModifiers( keyModifierMask | awtButtonMask ) ) ; + _robot.mousePress( awtButtonMask ) ; + _checkFailures("mouse-press("+(n+1)+")", 1) ; + + if( _debug ) { _debugPrintStream.println( "*** releasing button " + ( n + 1 ) ) ; } + _testMouseListener.setExpectedModifiers( _getNewtModifiersForAwtExtendedModifiers( keyModifierMask | awtButtonMask ) ) ; + _robot.mouseRelease( awtButtonMask ) ; + _checkFailures("mouse-release("+(n+1)+")", 1) ; + } + + _doKeyRelease( keyCode ) ; + } + + //////////////////////////////////////////////////////////////////////////// + + private void _doHoldOneButtonAndPressAnother( final int keyCode, final int keyModifierMask ) throws Exception { + + if( _debug ) { _debugPrintStream.println( "\n>>>> _doHoldOneButtonAndPressAnother" ) ; } + + _doKeyPress( keyCode ) ; + + for (int n = 0 ; n < _numButtonsToTest ; ++n) { + + int awtButtonMask = _awtButtonMasks[n] ; + + if( _debug ) { _debugPrintStream.println( "*** pressing button " + ( n + 1 ) ) ; } + _testMouseListener.setExpectedModifiers( _getNewtModifiersForAwtExtendedModifiers( keyModifierMask | awtButtonMask ) ) ; + _robot.mousePress( awtButtonMask ) ; + _checkFailures("mouse-press("+(n+1)+")", 1) ; + + for (int m = 0 ; m < _numButtonsToTest ; ++m) { + + if( n != m ) { + + if( _debug ) { _debugPrintStream.println( "*** pressing additional button " + ( m + 1 ) ) ; } + _testMouseListener.setExpectedModifiers( _getNewtModifiersForAwtExtendedModifiers( keyModifierMask | awtButtonMask | _awtButtonMasks[m] ) ) ; + _robot.mousePress( _awtButtonMasks[m] ) ; + _checkFailures("mouse-press("+(n+1)+", "+(m+1)+")", 1) ; + + if( _debug ) { _debugPrintStream.println( "*** releasing additional button " + ( m + 1 ) ) ; } + _testMouseListener.setExpectedModifiers( _getNewtModifiersForAwtExtendedModifiers( keyModifierMask | awtButtonMask | _awtButtonMasks[m] ) ) ; + _robot.mouseRelease( _awtButtonMasks[m] ) ; + _checkFailures("mouse-release("+(n+1)+", "+(m+1)+")", 1) ; + } + } + + if( _debug ) { _debugPrintStream.println( "*** releasing button " + ( n + 1 ) ) ; } + _testMouseListener.setExpectedModifiers( _getNewtModifiersForAwtExtendedModifiers( keyModifierMask | awtButtonMask ) ) ; + _robot.mouseRelease( awtButtonMask ) ; + _checkFailures("mouse-release("+(n+1)+")", 1); + } + + _doKeyRelease( keyCode ) ; + } + + //////////////////////////////////////////////////////////////////////////// + + private void _doPressAllButtonsInSequence( final int keyCode, final int keyModifierMask ) throws Exception { + + if( _debug ) { _debugPrintStream.println( "\n>>>> _doPressAllButtonsInSequence" ) ; } + + _doKeyPress( keyCode ) ; + + { + int cumulativeAwtModifiers = 0 ; + + for (int n = 0 ; n < _numButtonsToTest ; ++n) { + + cumulativeAwtModifiers |= _awtButtonMasks[n] ; + + if( _debug ) { _debugPrintStream.println( "*** pressing button " + ( n + 1 ) ) ; } + _testMouseListener.setExpectedModifiers( _getNewtModifiersForAwtExtendedModifiers( keyModifierMask | cumulativeAwtModifiers ) ) ; + _robot.mousePress( _awtButtonMasks[n] ) ; + _checkFailures("mouse-press("+(n+1)+")", 1) ; + } + + for (int n = _numButtonsToTest - 1 ; n >= 0 ; --n) { + + if( _debug ) { _debugPrintStream.println( "*** releasing button " + ( n + 1 ) ) ; } + _testMouseListener.setExpectedModifiers( _getNewtModifiersForAwtExtendedModifiers( keyModifierMask | cumulativeAwtModifiers ) ) ; + _robot.mouseRelease( _awtButtonMasks[n] ) ; + _checkFailures("mouse-release("+(n+1)+")", 1) ; + + cumulativeAwtModifiers &= ~_awtButtonMasks[n] ; + } + } + + _doKeyRelease( keyCode ) ; + } + + //////////////////////////////////////////////////////////////////////////// + + private void _doSingleButtonClickAndDrag( final int keyCode, final int keyModifierMask ) throws Exception { + + if( _debug ) { _debugPrintStream.println( "\n>>>> _doSingleButtonClickAndDrag" ) ; } + + _doKeyPress( keyCode ) ; + + _testMouseListener.setModifierCheckEnabled( true ) ; + + for (int n = 0 ; n < _numButtonsToTest ; ++n) { + + int awtButtonMask = _awtButtonMasks[n] ; + + if( _debug ) { _debugPrintStream.println( "*** pressing button " + ( n + 1 ) ) ; } + _testMouseListener.setExpectedModifiers( _getNewtModifiersForAwtExtendedModifiers( keyModifierMask | awtButtonMask ) ) ; + _robot.mousePress( awtButtonMask ) ; + _checkFailures("mouse-press("+(n+1)+")", 1) ; + + // To get a drag we only need to move one pixel. + if( _debug ) { _debugPrintStream.println( "*** moving mouse" ) ; } + final int newX = INITIAL_MOUSE_X + 8, newY = INITIAL_MOUSE_Y + 8; + _robot.mouseMove( newX, newY ) ; + _robot.delay(MS_ROBOT_MOUSE_MOVE_DELAY); + _checkFailures("mouse-move("+newX+", "+newY+")", 1) ; + + if( _debug ) { _debugPrintStream.println( "*** releasing button " + ( n + 1 ) ) ; } + _testMouseListener.setExpectedModifiers( _getNewtModifiersForAwtExtendedModifiers( keyModifierMask | awtButtonMask ) ) ; + _robot.mouseRelease( awtButtonMask ) ; + _checkFailures("mouse-release("+(n+1)+")", 1) ; + + _testMouseListener.setModifierCheckEnabled( false ) ; + _robot.mouseMove( INITIAL_MOUSE_X, INITIAL_MOUSE_Y ) ; + _robot.delay(MS_ROBOT_MOUSE_MOVE_DELAY); + _testMouseListener.setModifierCheckEnabled( true ) ; + } + + _doKeyRelease( keyCode ) ; + } + + //////////////////////////////////////////////////////////////////////////// + + private void _doKeyPress( int keyCode ) { + AWTRobotUtil.validateAWTEDTIsAlive(); + if( keyCode != 0 ) { + boolean modifierCheckEnabled = _testMouseListener.modifierCheckEnabled() ; + _testMouseListener.setModifierCheckEnabled( false ) ; + _robot.keyPress( keyCode ) ; + _robot.delay(MS_ROBOT_KEY_PRESS_DELAY); + _testMouseListener.setModifierCheckEnabled( modifierCheckEnabled ) ; + } + } + + //////////////////////////////////////////////////////////////////////////// + + private void _doKeyRelease( int keyCode ) { + AWTRobotUtil.validateAWTEDTIsAlive(); + if( keyCode != 0 ) { + boolean modifierCheckEnabled = _testMouseListener.modifierCheckEnabled() ; + _testMouseListener.setModifierCheckEnabled( false ) ; + _robot.keyRelease( keyCode ) ; + _robot.delay(MS_ROBOT_KEY_RELEASE_DELAY); + _testMouseListener.setModifierCheckEnabled( modifierCheckEnabled ) ; + } + } + + //////////////////////////////////////////////////////////////////////////// + + private void _checkFailures(String descr, int waitEventCount) { + ArrayList<String> failures = _testMouseListener.getFailures(waitEventCount) ; + + _debugPrintStream.print(getSimpleTestName(".")+" - "+descr+": "); + int numFailures = failures.size() ; + if( numFailures == 0 ) { + _debugPrintStream.println( " PASSED" ) ; + } else { + _debugPrintStream.println( " FAILED" ) ; + for( int n = 0 ; n < numFailures ; ++n ) { + _debugPrintStream.print( " " ) ; + _debugPrintStream.println( failures.get(n) ) ; + } + } + + Assert.assertTrue( failures.size() == 0 ) ; + } + + //////////////////////////////////////////////////////////////////////////// + + public void eventDispatchedPostTestDelay() throws Exception { + eventDispatch(); eventDispatch(); eventDispatch(); + Thread.sleep( MS_ROBOT_POST_TEST_DELAY ) ; + eventDispatch(); eventDispatch(); eventDispatch(); + _testMouseListener.clear(); + } + + public void clearKeyboadAndMouse() throws Exception { + // Make sure all modifiers are released, otherwise the user's + // desktop can get locked up (ask me how I know this). + _releaseModifiers() ; + _escape() ; + eventDispatchedPostTestDelay(); + } + + //////////////////////////////////////////////////////////////////////////// + + private void _releaseModifiers() { + + if (_robot != null) { + AWTRobotUtil.validateAWTEDTIsAlive(); + + _robot.setAutoDelay( MS_ROBOT_AUTO_DELAY ) ; + + boolean modifierCheckEnabled = _testMouseListener.modifierCheckEnabled() ; + _testMouseListener.setModifierCheckEnabled( false ) ; + + { + _robot.keyRelease( java.awt.event.KeyEvent.VK_SHIFT ) ; + _robot.keyRelease( java.awt.event.KeyEvent.VK_CONTROL ) ; + // _robot.keyRelease( java.awt.event.KeyEvent.VK_META ) ; + // _robot.keyRelease( java.awt.event.KeyEvent.VK_ALT ) ; + // _robot.keyRelease( java.awt.event.KeyEvent.VK_ALT_GRAPH ) ; + + for (int n = 0 ; n < _awtButtonMasks.length ; ++n) { + _robot.mouseRelease( _awtButtonMasks[n] ) ; + } + } + + _testMouseListener.setModifierCheckEnabled( modifierCheckEnabled ) ; + } + } + + private void _escape() { + if (_robot != null) { + AWTRobotUtil.validateAWTEDTIsAlive(); + _robot.keyPress( java.awt.event.KeyEvent.VK_ESCAPE ) ; + _robot.keyRelease( java.awt.event.KeyEvent.VK_ESCAPE ) ; + } + } + + //////////////////////////////////////////////////////////////////////////// + + /** + * Brute force method to return the NEWT event modifiers equivalent + * to the specified AWT event extended modifiers. + * + * @param awtExtendedModifiers + * The AWT extended modifiers. + * + * @return + * The equivalent NEWT modifiers. + */ + + private int _getNewtModifiersForAwtExtendedModifiers( int awtExtendedModifiers ) { + + int mask = 0 ; + + if( ( awtExtendedModifiers & java.awt.event.InputEvent.SHIFT_DOWN_MASK ) != 0 ) { + mask |= com.jogamp.newt.event.InputEvent.SHIFT_MASK ; + } + + if( ( awtExtendedModifiers & java.awt.event.InputEvent.CTRL_DOWN_MASK ) != 0 ) { + mask |= com.jogamp.newt.event.InputEvent.CTRL_MASK ; + } + + if( ( awtExtendedModifiers & java.awt.event.InputEvent.META_DOWN_MASK ) != 0 ) { + mask |= com.jogamp.newt.event.InputEvent.META_MASK ; + } + + if( ( awtExtendedModifiers & java.awt.event.InputEvent.ALT_DOWN_MASK ) != 0 ) { + mask |= com.jogamp.newt.event.InputEvent.ALT_MASK ; + } + + if( ( awtExtendedModifiers & java.awt.event.InputEvent.ALT_GRAPH_DOWN_MASK ) != 0 ) { + mask |= com.jogamp.newt.event.InputEvent.ALT_GRAPH_MASK ; + } + + for (int n = 0 ; n < _numButtonsToTest ; ++n) { + if ((awtExtendedModifiers & getAWTButtonMask(n+1)) != 0) { + mask |= com.jogamp.newt.event.InputEvent.getButtonMask(n+1) ; + } + } + + return mask ; + } + + //////////////////////////////////////////////////////////////////////////// +} diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersAWTCanvas.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersAWTCanvas.java new file mode 100644 index 000000000..f1906f560 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersAWTCanvas.java @@ -0,0 +1,106 @@ +/** + * 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.event; + +import javax.media.opengl.awt.GLCanvas ; + +import javax.swing.JFrame ; +import javax.swing.SwingUtilities ; +import javax.swing.WindowConstants ; + +import org.junit.AfterClass ; +import org.junit.Assert; +import org.junit.BeforeClass ; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.event.awt.AWTMouseAdapter ; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; + +/** + * Test whether or not event modifiers are preserved by NEWT when + * the source is an AWT canvas. + */ + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestNewtEventModifiersAWTCanvas extends BaseNewtEventModifiers { + + private static JFrame _testFrame ; + + //////////////////////////////////////////////////////////////////////////// + + @BeforeClass + public static void beforeClass() throws Exception { + + final GLCanvas canvas = new GLCanvas() ; + canvas.addGLEventListener( new RedSquareES2() ) ; + new AWTMouseAdapter( _testMouseListener ).addTo( (java.awt.Component)canvas ) ; + + _testFrame = new JFrame( "Event Modifier Test AWTCanvas" ) ; + _testFrame.setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE ) ; + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + _testFrame.getContentPane().add( canvas ) ; + _testFrame.setBounds( TEST_FRAME_X, TEST_FRAME_Y, TEST_FRAME_WIDTH, TEST_FRAME_HEIGHT ) ; + _testFrame.setVisible( true ) ; + } + }) ; + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(_testFrame, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(canvas, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(canvas, true)); + + AWTRobotUtil.assertRequestFocusAndWait(null, canvas, canvas, null, null); // programmatic + Assert.assertNotNull(_robot); + AWTRobotUtil.requestFocus(_robot, canvas, false); // within unit framework, prev. tests (TestFocus02SwingAWTRobot) 'confuses' Windows keyboard input + } + + //////////////////////////////////////////////////////////////////////////// + + @AfterClass + public static void afterClass() throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + if( null != _testFrame ) { + _testFrame.dispose() ; + } + } + }) ; + } + + //////////////////////////////////////////////////////////////////////////// + + public static void main(String args[]) throws Exception { + String testName = TestNewtEventModifiersAWTCanvas.class.getName() ; + org.junit.runner.JUnitCore.main( testName ) ; + } + + //////////////////////////////////////////////////////////////////////////// +} diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersNEWTWindowAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersNEWTWindowAWT.java new file mode 100644 index 000000000..c4bd3eb71 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersNEWTWindowAWT.java @@ -0,0 +1,87 @@ +/** + * 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.event; + +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.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; + +/** + * Test whether or not event modifiers are properly delivered by NEWT. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestNewtEventModifiersNEWTWindowAWT extends BaseNewtEventModifiers { + + private static GLWindow _glWindow; + + //////////////////////////////////////////////////////////////////////////// + + @BeforeClass + public static void beforeClass() throws Exception { + _glWindow = GLWindow.create( new GLCapabilities( GLProfile.getGL2ES2() ) ); + _glWindow.setTitle("Event Modifier Test GLWindow"); + _glWindow.addGLEventListener( new RedSquareES2() ) ; + _glWindow.addMouseListener(_testMouseListener); + _glWindow.setSize(TEST_FRAME_WIDTH, TEST_FRAME_HEIGHT); + _glWindow.setPosition(TEST_FRAME_X, TEST_FRAME_Y); + _glWindow.setVisible(true); + + Assert.assertTrue(AWTRobotUtil.waitForVisible(_glWindow, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(_glWindow, true)); + + AWTRobotUtil.assertRequestFocusAndWait(null, _glWindow, _glWindow, null, null); // programmatic + Assert.assertNotNull(_robot); + AWTRobotUtil.requestFocus(_robot, _glWindow, false); // within unit framework, prev. tests (TestFocus02SwingAWTRobot) 'confuses' Windows keyboard input + } + + //////////////////////////////////////////////////////////////////////////// + + @AfterClass + public static void afterClass() throws Exception { + _glWindow.destroy(); + } + + //////////////////////////////////////////////////////////////////////////// + + public static void main(String args[]) throws Exception { + String testName = TestNewtEventModifiersNEWTWindowAWT.class.getName() ; + org.junit.runner.JUnitCore.main( testName ) ; + } + + //////////////////////////////////////////////////////////////////////////// +} diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersNewtCanvasAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersNewtCanvasAWT.java new file mode 100644 index 000000000..0abadb0d4 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersNewtCanvasAWT.java @@ -0,0 +1,120 @@ +/** + * 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.event ; + +import java.awt.BorderLayout ; + +import javax.media.opengl.GLCapabilities ; +import javax.media.opengl.GLProfile ; + +import javax.swing.JFrame ; +import javax.swing.SwingUtilities ; +import javax.swing.WindowConstants ; + +import org.junit.AfterClass ; +import org.junit.Assert; +import org.junit.BeforeClass ; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.awt.NewtCanvasAWT ; +import com.jogamp.newt.opengl.GLWindow ; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; + +/** + * Test whether or not event modifiers are preserved by NEWT when + * the canvas is a NewtCanvasAWT. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestNewtEventModifiersNewtCanvasAWT extends BaseNewtEventModifiers { + + private static JFrame _testFrame ; + private static GLWindow _glWindow ; + + //////////////////////////////////////////////////////////////////////////// + + @BeforeClass + public static void beforeClass() throws Exception { + + SwingUtilities.invokeAndWait( new Runnable() { + public void run() { + + _testFrame = new JFrame( "Event Modifier Test NewtCanvasAWT" ) ; + _testFrame.setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE ) ; + + { + GLCapabilities caps = new GLCapabilities( GLProfile.getGL2ES2() ) ; + _glWindow = GLWindow.create( caps ) ; + + NewtCanvasAWT canvas = new NewtCanvasAWT( _glWindow ) ; + _testFrame.getContentPane().add( canvas, BorderLayout.CENTER ) ; + + _glWindow.addGLEventListener( new RedSquareES2() ) ; + } + + _testFrame.setBounds( TEST_FRAME_X, TEST_FRAME_Y, TEST_FRAME_WIDTH, TEST_FRAME_HEIGHT ) ; + _testFrame.setVisible( true ) ; + } + } ) ; + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(_testFrame, true)); + Assert.assertTrue(AWTRobotUtil.waitForVisible(_glWindow, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(_glWindow, true)); + + AWTRobotUtil.assertRequestFocusAndWait(null, _glWindow, _glWindow, null, null); // programmatic + Assert.assertNotNull(_robot); + AWTRobotUtil.requestFocus(_robot, _glWindow, false); // within unit framework, prev. tests (TestFocus02SwingAWTRobot) 'confuses' Windows keyboard input + + _glWindow.addMouseListener( _testMouseListener ) ; + } + + //////////////////////////////////////////////////////////////////////////// + + @AfterClass + public static void afterClass() throws Exception { + SwingUtilities.invokeAndWait( new Runnable() { + public void run() { + if( null != _testFrame ) { + _testFrame.dispose() ; + } + } + } ) ; + + _glWindow.destroy() ; + } + + //////////////////////////////////////////////////////////////////////////// + + public static void main(String args[]) throws Exception { + String testName = TestNewtEventModifiersNewtCanvasAWT.class.getName() ; + org.junit.runner.JUnitCore.main( testName ) ; + } + + //////////////////////////////////////////////////////////////////////////// +} diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersNewtCanvasSWTAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersNewtCanvasSWTAWT.java new file mode 100644 index 000000000..2a6b8ba19 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersNewtCanvasSWTAWT.java @@ -0,0 +1,182 @@ +/** + * 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.event; + +import org.eclipse.swt.SWT ; +import org.eclipse.swt.layout.FillLayout ; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display ; +import org.eclipse.swt.widgets.Shell ; + +import javax.media.opengl.GLCapabilities ; +import javax.media.opengl.GLProfile ; + +import org.junit.AfterClass ; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.BeforeClass ; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.nativewindow.swt.SWTAccessor; +import com.jogamp.newt.opengl.GLWindow ; +import com.jogamp.newt.swt.NewtCanvasSWT ; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; + +/** + * Test whether or not event modifiers preserved by NEWT when + * the canvas is a NewtCanvasSWT. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestNewtEventModifiersNewtCanvasSWTAWT extends BaseNewtEventModifiers { + + private static Display _display = null; + private static Shell _shell = null; + private static Composite _composite = null; + private static GLWindow _glWindow ; + + //////////////////////////////////////////////////////////////////////////// + + protected static void eventDispatchImpl() { + final int maxEvents = 10; + try { + Thread.sleep(100); + } catch (InterruptedException e) { } + final boolean[] res = { false }; + int i=0; + do { + SWTAccessor.invoke(_display, true, new Runnable() { + public void run() { + if( !_display.isDisposed() ) { + res[0] = _display.readAndDispatch(); + } else { + res[0] = false; + } + } } ); + i++; + } while( i<maxEvents && res[0] ); + } + + @Override + protected void eventDispatch() { + eventDispatchImpl(); + } + + //////////////////////////////////////////////////////////////////////////// + + @BeforeClass + public static void beforeClass() throws Exception { + + // FIXME: Hangs .. w/ Java7 .. every now and then! + setTestSupported(false); + + /*** + SWTAccessor.invoke(true, new Runnable() { + public void run() { + _display = new Display(); + }}); + Assert.assertNotNull( _display ); + + SWTAccessor.invoke(_display, true, new Runnable() { + public void run() { + _shell = new Shell( _display ); + Assert.assertNotNull( _shell ); + _shell.setText( "Event Modifier Test NewtCanvasSWT" ) ; + _shell.setLayout( new FillLayout() ); + _composite = new Composite( _shell, SWT.NONE ); + _composite.setLayout( new FillLayout() ); + Assert.assertNotNull( _composite ); + }}); + + { + GLCapabilities caps = new GLCapabilities( GLProfile.get( GLProfile.GL2ES2 ) ) ; + _glWindow = GLWindow.create( caps ) ; + _glWindow.addGLEventListener( new RedSquareES2() ) ; + + NewtCanvasSWT.create( _composite, SWT.NO_BACKGROUND, _glWindow ) ; + } + + SWTAccessor.invoke(_display, true, new Runnable() { + public void run() { + _shell.setBounds( TEST_FRAME_X, TEST_FRAME_Y, TEST_FRAME_WIDTH, TEST_FRAME_HEIGHT ) ; + _shell.open(); + } + }); + + // no AWT idling, may deadlock on OSX! + Assert.assertNotNull(_robot); + _robot.setAutoWaitForIdle( false ) ; + + // no waiting for results .. + AWTRobotUtil.requestFocus(null, _glWindow, false); // programmatic + eventDispatchImpl(); + AWTRobotUtil.requestFocus(_robot, _glWindow, INITIAL_MOUSE_X, INITIAL_MOUSE_Y); + eventDispatchImpl(); + + _glWindow.addMouseListener( _testMouseListener ) ; + */ + } + + //////////////////////////////////////////////////////////////////////////// + + @AfterClass + public static void afterClass() throws Exception { + /** + _glWindow.destroy() ; + + try { + SWTAccessor.invoke(_display, true, new Runnable() { + public void run() { + if( null != _composite ) { + _composite.dispose(); + } + if( null != _shell ) { + _shell.dispose(); + } + if( null != _display && !_display.isDisposed()) { + _display.dispose(); + } + }}); + } + catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } */ + } + + //////////////////////////////////////////////////////////////////////////// + + public static void main(String args[]) throws Exception { + String testName = TestNewtEventModifiersNewtCanvasSWTAWT.class.getName() ; + org.junit.runner.JUnitCore.main( testName ) ; + } + + //////////////////////////////////////////////////////////////////////////// +} diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodeModifiersAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodeModifiersAWT.java new file mode 100644 index 000000000..2516fc536 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodeModifiersAWT.java @@ -0,0 +1,308 @@ +/** + * Copyright 2012 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.event; + +import org.junit.After; +import org.junit.Assert; +import org.junit.AfterClass; +import org.junit.Assume; +import org.junit.Before; + +import java.awt.AWTException; +import java.awt.BorderLayout; +import java.awt.Robot; +import java.lang.reflect.InvocationTargetException; +import java.util.EventObject; +import java.util.List; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.swing.JFrame; + +import java.io.IOException; + +import jogamp.nativewindow.jawt.JAWTUtil; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.awt.NewtCanvasAWT; +import com.jogamp.newt.event.InputEvent; +import com.jogamp.newt.event.KeyEvent; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; + +import com.jogamp.opengl.test.junit.util.*; + +/** + * Testing combinations of key code modifiers of key event. + * + * <p> + * Due to limitation of AWT Robot, the test machine needs to have US keyboard enabled, + * even though we do unify VK codes to US keyboard across all layouts. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestNewtKeyCodeModifiersAWT extends UITestCase { + static int width, height; + static long durationPerTest = 100; + static long awtWaitTimeout = 1000; + + static GLCapabilities glCaps; + + @BeforeClass + public static void initClass() { + width = 640; + height = 480; + glCaps = new GLCapabilities(null); + } + + @AfterClass + public static void release() { + } + + @Before + public void initTest() { + } + + @After + public void releaseTest() { + } + + @Test(timeout=180000) // TO 3 min + public void test01NEWT() throws AWTException, InterruptedException, InvocationTargetException { + GLWindow glWindow = GLWindow.create(glCaps); + glWindow.setSize(width, height); + glWindow.setVisible(true); + + testImpl(glWindow); + + glWindow.destroy(); + } + + private void testNewtCanvasAWT_Impl(boolean onscreen) throws AWTException, InterruptedException, InvocationTargetException { + GLWindow glWindow = GLWindow.create(glCaps); + + // Wrap the window in a canvas. + final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow); + if( !onscreen ) { + newtCanvasAWT.setShallUseOffscreenLayer(true); + } + + // Add the canvas to a frame, and make it all visible. + final JFrame frame1 = new JFrame("Swing AWT Parent Frame: "+ glWindow.getTitle()); + frame1.getContentPane().add(newtCanvasAWT, BorderLayout.CENTER); + frame1.setSize(width, height); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame1.setVisible(true); + } } ); + + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame1, true)); + + testImpl(glWindow); + + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame1.setVisible(false); + frame1.dispose(); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + glWindow.destroy(); + } + + @Test(timeout=180000) // TO 3 min + public void test02NewtCanvasAWT_Onscreen() throws AWTException, InterruptedException, InvocationTargetException { + if( JAWTUtil.isOffscreenLayerRequired() ) { + System.err.println("Platform doesn't support onscreen rendering."); + return; + } + testNewtCanvasAWT_Impl(true); + } + + @Test(timeout=180000) // TO 3 min + public void test03NewtCanvasAWT_Offsccreen() throws AWTException, InterruptedException, InvocationTargetException { + if( !JAWTUtil.isOffscreenLayerSupported() ) { + System.err.println("Platform doesn't support offscreen rendering."); + return; + } + testNewtCanvasAWT_Impl(false); + } + + static void testKeyCodeModifier(Robot robot, NEWTKeyAdapter keyAdapter, short modifierKey, int modifierMask, short keyCode, + char keyCharOnly, char keyCharMod) { + keyAdapter.reset(); + AWTRobotUtil.waitForIdle(robot); + AWTRobotUtil.newtKeyPress(0, robot, true, keyCode, 10); // press keyCode + AWTRobotUtil.newtKeyPress(0, robot, false, keyCode, 100); // release keyCode + AWTRobotUtil.waitForIdle(robot); + for(int j=0; j < 100 && keyAdapter.getQueueSize() < 2; j++) { // wait until events are collected + robot.delay(100); + } + + AWTRobotUtil.waitForIdle(robot); + AWTRobotUtil.newtKeyPress(0, robot, true, modifierKey, 10); // press MOD + AWTRobotUtil.newtKeyPress(0, robot, true, keyCode, 10); // press keyCode + AWTRobotUtil.newtKeyPress(0, robot, false, keyCode, 10); // release keyCode + AWTRobotUtil.newtKeyPress(0, robot, false, modifierKey, 100); // release MOD + AWTRobotUtil.waitForIdle(robot); + for(int j=0; j < 100 && keyAdapter.getQueueSize() < 2+4; j++) { // wait until events are collected + robot.delay(100); + } + NEWTKeyUtil.validateKeyAdapterStats(keyAdapter, + 3 /* press-SI */, 3 /* release-SI */, + 0 /* press-AR */, 0 /* release-AR */ ); + + final List<EventObject> queue = keyAdapter.copyQueue(); + int i=0; + NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED, 0, keyCode, keyCharOnly); + NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_RELEASED, 0, keyCode, keyCharOnly); + + NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED, modifierMask, modifierKey, KeyEvent.NULL_CHAR); + NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED, modifierMask, keyCode, keyCharMod); + NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_RELEASED, modifierMask, keyCode, keyCharMod); + KeyEvent e = (KeyEvent) queue.get(i++); + NEWTKeyUtil.validateKeyEvent(e, KeyEvent.EVENT_KEY_RELEASED, modifierMask, modifierKey, KeyEvent.NULL_CHAR); + } + + static void testKeyCodeAllModifierV1(Robot robot, NEWTKeyAdapter keyAdapter) { + final short m1k = KeyEvent.VK_ALT; + final int m1m = InputEvent.ALT_MASK; + final short m2k = KeyEvent.VK_CONTROL; + final int m2m = InputEvent.CTRL_MASK; + final short m3k = KeyEvent.VK_SHIFT; + final int m3m = InputEvent.SHIFT_MASK; + + keyAdapter.reset(); + AWTRobotUtil.waitForIdle(robot); + AWTRobotUtil.newtKeyPress(0, robot, true, m1k, 10); // press MOD1 + AWTRobotUtil.newtKeyPress(0, robot, true, m2k, 10); // press MOD2 + AWTRobotUtil.newtKeyPress(0, robot, true, m3k, 10); // press MOD3 + AWTRobotUtil.newtKeyPress(0, robot, true, KeyEvent.VK_1, 10); // press P + + AWTRobotUtil.newtKeyPress(0, robot, false, KeyEvent.VK_1, 100); // release P + AWTRobotUtil.newtKeyPress(0, robot, false, m3k, 10); // release MOD + AWTRobotUtil.newtKeyPress(0, robot, false, m2k, 10); // release MOD + AWTRobotUtil.newtKeyPress(0, robot, false, m1k, 10); // release MOD + AWTRobotUtil.waitForIdle(robot); + + for(int j=0; j < 100 && keyAdapter.getQueueSize() < 4+4; j++) { // wait until events are collected + robot.delay(100); + } + NEWTKeyUtil.validateKeyAdapterStats(keyAdapter, + 4 /* press-SI */, 4 /* release-SI */, + 0 /* press-AR */, 0 /* release-AR */ ); + + final List<EventObject> queue = keyAdapter.copyQueue(); + int i=0; + NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED, m1m, m1k, KeyEvent.NULL_CHAR); + NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED, m1m|m2m, m2k, KeyEvent.NULL_CHAR); + NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED, m1m|m2m|m3m, m3k, KeyEvent.NULL_CHAR); + + NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED, m1m|m2m|m3m, KeyEvent.VK_1, KeyEvent.NULL_CHAR); + NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_RELEASED, m1m|m2m|m3m, KeyEvent.VK_1, KeyEvent.NULL_CHAR); + KeyEvent e = (KeyEvent) queue.get(i++); + NEWTKeyUtil.validateKeyEvent(e, KeyEvent.EVENT_KEY_RELEASED, m1m|m2m|m3m, m3k, KeyEvent.NULL_CHAR); + NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_RELEASED, m1m|m2m, m2k, KeyEvent.NULL_CHAR); + NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_RELEASED, m1m, m1k, KeyEvent.NULL_CHAR); + } + + void testImpl(GLWindow glWindow) throws AWTException, InterruptedException, InvocationTargetException { + final Robot robot = new Robot(); + robot.setAutoWaitForIdle(true); + + GLEventListener demo1 = new RedSquareES2(); + glWindow.addGLEventListener(demo1); + + // NEWTFocusAdapter glWindow1FA = new NEWTFocusAdapter("GLWindow1"); + // glWindow.addWindowListener(glWindow1FA); + NEWTKeyAdapter glWindow1KA = new NEWTKeyAdapter("GLWindow1"); + glWindow1KA.setVerbose(false); + glWindow.addKeyListener(glWindow1KA); + + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, true)); + + // Continuous animation .. + Animator animator = new Animator(glWindow); + animator.start(); + + Thread.sleep(durationPerTest); // manual testing + + AWTRobotUtil.assertRequestFocusAndWait(null, glWindow, glWindow, null, null); // programmatic + AWTRobotUtil.requestFocus(robot, glWindow, false); // within unit framework, prev. tests (TestFocus02SwingAWTRobot) 'confuses' Windows keyboard input + glWindow1KA.reset(); + + testKeyCodeModifier(robot, glWindow1KA, KeyEvent.VK_SHIFT, InputEvent.SHIFT_MASK, KeyEvent.VK_1, '1', '!'); + testKeyCodeModifier(robot, glWindow1KA, KeyEvent.VK_SHIFT, InputEvent.SHIFT_MASK, KeyEvent.VK_Y, 'y', 'Y'); // US: Y, DE: Z + testKeyCodeModifier(robot, glWindow1KA, KeyEvent.VK_SHIFT, InputEvent.SHIFT_MASK, KeyEvent.VK_P, 'p', 'P'); + testKeyCodeModifier(robot, glWindow1KA, KeyEvent.VK_CONTROL, InputEvent.CTRL_MASK, KeyEvent.VK_1, '1', KeyEvent.NULL_CHAR); + testKeyCodeModifier(robot, glWindow1KA, KeyEvent.VK_ALT, InputEvent.ALT_MASK, KeyEvent.VK_1, '1', KeyEvent.NULL_CHAR); + + testKeyCodeAllModifierV1(robot, glWindow1KA); + + // Remove listeners to avoid logging during dispose/destroy. + glWindow.removeKeyListener(glWindow1KA); + + // Shutdown the test. + animator.stop(); + } + + static int atoi(String a) { + int i=0; + try { + i = Integer.parseInt(a); + } catch (Exception ex) { ex.printStackTrace(); } + return i; + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + durationPerTest = atoi(args[++i]); + } + } + /** + BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); + System.err.println("Press enter to continue"); + System.err.println(stdin.readLine()); + */ + System.out.println("durationPerTest: "+durationPerTest); + String tstname = TestNewtKeyCodeModifiersAWT.class.getName(); + org.junit.runner.JUnitCore.main(tstname); + } + + +} diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodesAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodesAWT.java new file mode 100644 index 000000000..71778c611 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodesAWT.java @@ -0,0 +1,292 @@ +/** + * Copyright 2012 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.event; + +import org.junit.After; +import org.junit.Assert; +import org.junit.AfterClass; +import org.junit.Assume; +import org.junit.Before; + +import java.awt.AWTException; +import java.awt.BorderLayout; +import java.awt.Robot; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.EventObject; +import java.util.List; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.swing.JFrame; + +import java.io.IOException; + +import jogamp.nativewindow.jawt.JAWTUtil; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.awt.NewtCanvasAWT; +import com.jogamp.newt.event.KeyEvent; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; +import com.jogamp.opengl.test.junit.util.*; +import com.jogamp.opengl.test.junit.util.NEWTKeyUtil.CodeSeg; + +/** + * Testing key code of key events. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestNewtKeyCodesAWT extends UITestCase { + static int width, height; + static long durationPerTest = 100; + static long awtWaitTimeout = 1000; + + static GLCapabilities glCaps; + + @BeforeClass + public static void initClass() { + width = 640; + height = 480; + glCaps = new GLCapabilities(null); + } + + @AfterClass + public static void release() { + } + + @Before + public void initTest() { + } + + @After + public void releaseTest() { + } + + @Test(timeout=180000) // TO 3 min + public void test01NEWT() throws AWTException, InterruptedException, InvocationTargetException { + GLWindow glWindow = GLWindow.create(glCaps); + glWindow.setSize(width, height); + glWindow.setVisible(true); + + testImpl(glWindow); + + glWindow.destroy(); + } + + private void testNewtCanvasAWT_Impl(boolean onscreen) throws AWTException, InterruptedException, InvocationTargetException { + GLWindow glWindow = GLWindow.create(glCaps); + + // Wrap the window in a canvas. + final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow); + if( !onscreen ) { + newtCanvasAWT.setShallUseOffscreenLayer(true); + } + + // Add the canvas to a frame, and make it all visible. + final JFrame frame1 = new JFrame("Swing AWT Parent Frame: "+ glWindow.getTitle()); + frame1.getContentPane().add(newtCanvasAWT, BorderLayout.CENTER); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame1.setSize(width, height); + frame1.setVisible(true); + } } ); + + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame1, true)); + + testImpl(glWindow); + + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame1.setVisible(false); + frame1.dispose(); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + glWindow.destroy(); + } + + @Test(timeout=180000) // TO 3 min + public void test02NewtCanvasAWT_Onscreen() throws AWTException, InterruptedException, InvocationTargetException { + if( JAWTUtil.isOffscreenLayerRequired() ) { + System.err.println("Platform doesn't support onscreen rendering."); + return; + } + testNewtCanvasAWT_Impl(true); + } + + @Test(timeout=180000) // TO 3 min + public void test03NewtCanvasAWT_Offsccreen() throws AWTException, InterruptedException, InvocationTargetException { + if( !JAWTUtil.isOffscreenLayerSupported() ) { + System.err.println("Platform doesn't support offscreen rendering."); + return; + } + testNewtCanvasAWT_Impl(false); + } + + /** Almost all keyCodes reachable w/o modifiers [shift, alt, ..] on US keyboard! */ + static CodeSeg[] codeSegments = new CodeSeg[] { + // new CodeSeg(KeyEvent.VK_HOME, KeyEvent.VK_PRINTSCREEN, "home, end, final, prnt"), + new CodeSeg(KeyEvent.VK_BACK_SPACE, KeyEvent.VK_BACK_SPACE, "bs"), + // new CodeSeg(KeyEvent.VK_TAB, KeyEvent.VK_TAB, "tab"), // TAB functions as focus traversal key + new CodeSeg(KeyEvent.VK_ENTER, KeyEvent.VK_ENTER, "cr"), + new CodeSeg(KeyEvent.VK_PAGE_DOWN, KeyEvent.VK_PAGE_DOWN, "pg_down"), + new CodeSeg(KeyEvent.VK_SHIFT, KeyEvent.VK_ALT, "shift, pg_up, ctrl, alt"), + // new CodeSeg(KeyEvent.VK_ALT_GRAPH, KeyEvent.VK_ALT_GRAPH, "alt_gr"), // AWT Robot produces 0xff7e on X11 + // new CodeSeg(KeyEvent.VK_SCROLL_LOCK, KeyEvent.VK_SCROLL_LOCK, "scroll lock"), + new CodeSeg(KeyEvent.VK_ESCAPE, KeyEvent.VK_ESCAPE, "esc"), + new CodeSeg(KeyEvent.VK_SPACE, KeyEvent.VK_SPACE, "space"), + new CodeSeg(KeyEvent.VK_QUOTE, KeyEvent.VK_QUOTE, "quote"), + new CodeSeg(KeyEvent.VK_COMMA, KeyEvent.VK_SLASH, ", - . /"), + new CodeSeg(KeyEvent.VK_0, KeyEvent.VK_9, "0 - 9"), + new CodeSeg(KeyEvent.VK_SEMICOLON, KeyEvent.VK_SEMICOLON, ";"), + new CodeSeg(KeyEvent.VK_EQUALS, KeyEvent.VK_EQUALS, "="), + new CodeSeg(KeyEvent.VK_A, KeyEvent.VK_Z, "a - z"), + new CodeSeg(KeyEvent.VK_OPEN_BRACKET, KeyEvent.VK_CLOSE_BRACKET, "[ \\ ]"), + new CodeSeg(KeyEvent.VK_BACK_QUOTE, KeyEvent.VK_BACK_QUOTE, "`"), + new CodeSeg(KeyEvent.VK_F1, KeyEvent.VK_F8, "f1..f8"), + // new CodeSeg(KeyEvent.VK_F1, KeyEvent.VK_F12, "f1..f12"), // f9-f12 may cause some odd desktop functions! + new CodeSeg(KeyEvent.VK_DELETE, KeyEvent.VK_DELETE, "del"), + // new CodeSeg(KeyEvent.VK_NUMPAD0, KeyEvent.VK_NUMPAD9, "numpad0-9"), // can be mapped to normal keycodes + // new CodeSeg(KeyEvent.VK_DECIMAL, KeyEvent.VK_DIVIDE, "numpad ops"), // can be mapped to normal keycodes + // new CodeSeg(KeyEvent.VK_NUM_LOCK, KeyEvent.VK_NUM_LOCK, "num lock"), + // new CodeSeg(KeyEvent.VK_KP_LEFT, KeyEvent.VK_KP_DOWN, "numpad cursor arrows"), + new CodeSeg(KeyEvent.VK_LEFT, KeyEvent.VK_DOWN, "cursor arrows"), + // new CodeSeg(KeyEvent.VK_WINDOWS, KeyEvent.VK_HELP, "windows, meta, hlp"), + }; + + static void testKeyCodes(Robot robot, Object obj, NEWTKeyAdapter keyAdapter) throws InterruptedException, InvocationTargetException { + final List<List<EventObject>> cse = new ArrayList<List<EventObject>>(); + + keyAdapter.setVerbose(true); // FIXME + final int[] objCenter = AWTRobotUtil.getCenterLocation(obj, false /* onTitleBarIfWindow */); + + for(int i=0; i<codeSegments.length; i++) { + keyAdapter.reset(); + final CodeSeg codeSeg = codeSegments[i]; + // System.err.println("*** Segment "+codeSeg.description); + int eventCount = 0; + for(short c=codeSeg.min; c<=codeSeg.max; c++) { + AWTRobotUtil.waitForIdle(robot); + // System.err.println("*** KeyCode 0x"+Integer.toHexString(c)); + try { + AWTRobotUtil.newtKeyPress(0, robot, true, c, 10); + } catch (Exception e) { + System.err.println("Exception @ AWT Robot.PRESS "+MiscUtils.toHexString(c)+" - "+e.getMessage()); + break; + } + eventCount++; + try { + AWTRobotUtil.newtKeyPress(0, robot, false, c, 100); + } catch (Exception e) { + System.err.println("Exception @ AWT Robot.RELEASE "+MiscUtils.toHexString(c)+" - "+e.getMessage()); + break; + } + eventCount++; + } + AWTRobotUtil.waitForIdle(robot); + for(int j=0; j < NEWTKeyUtil.POLL_DIVIDER && keyAdapter.getQueueSize() < eventCount; j++) { // wait until events are collected + robot.delay(NEWTKeyUtil.TIME_SLICE); + // Bug 919 - TestNewtKeyCodesAWT w/ NewtCanvasAWT Fails on Windows Due to Clogged Key-Release Event by AWT Robot + final int off = 0==j%2 ? 1 : -1; + AWTRobotUtil.awtRobotMouseMove(robot, objCenter[0]+off, objCenter[1]); + } + AWTRobotUtil.awtRobotMouseMove(robot, objCenter[0], objCenter[1]); // Bug 919: Reset mouse position + cse.add(keyAdapter.copyQueue()); + } + Assert.assertEquals("KeyCode impl. incomplete", true, NEWTKeyUtil.validateKeyCodes(codeSegments, cse, true)); + } + + void testImpl(GLWindow glWindow) throws AWTException, InterruptedException, InvocationTargetException { + final Robot robot = new Robot(); + robot.setAutoWaitForIdle(true); + + GLEventListener demo1 = new RedSquareES2(); + glWindow.addGLEventListener(demo1); + + // NEWTFocusAdapter glWindow1FA = new NEWTFocusAdapter("GLWindow1"); + // glWindow.addWindowListener(glWindow1FA); + NEWTKeyAdapter glWindow1KA = new NEWTKeyAdapter("GLWindow1"); + glWindow1KA.setVerbose(false); + glWindow.addKeyListener(glWindow1KA); + + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, true)); + + // Continuous animation .. + Animator animator = new Animator(glWindow); + animator.start(); + + Thread.sleep(durationPerTest); // manual testing + + AWTRobotUtil.assertRequestFocusAndWait(null, glWindow, glWindow, null, null); // programmatic + AWTRobotUtil.requestFocus(robot, glWindow, false); // within unit framework, prev. tests (TestFocus02SwingAWTRobot) 'confuses' Windows keyboard input + glWindow1KA.reset(); + + testKeyCodes(robot, glWindow, glWindow1KA); + + // Remove listeners to avoid logging during dispose/destroy. + glWindow.removeKeyListener(glWindow1KA); + + // Shutdown the test. + animator.stop(); + } + + static int atoi(String a) { + int i=0; + try { + i = Integer.parseInt(a); + } catch (Exception ex) { ex.printStackTrace(); } + return i; + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + durationPerTest = atoi(args[++i]); + } + } + /** + BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); + System.err.println("Press enter to continue"); + System.err.println(stdin.readLine()); + */ + System.out.println("durationPerTest: "+durationPerTest); + String tstname = TestNewtKeyCodesAWT.class.getName(); + org.junit.runner.JUnitCore.main(tstname); + } + + +} diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventAutoRepeatAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventAutoRepeatAWT.java new file mode 100644 index 000000000..c374f1efe --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventAutoRepeatAWT.java @@ -0,0 +1,319 @@ +/** + * Copyright 2012 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.event; + +import org.junit.After; +import org.junit.Assert; +import org.junit.AfterClass; +import org.junit.Assume; +import org.junit.Before; + +import java.awt.AWTException; +import java.awt.BorderLayout; +import java.awt.Robot; +import java.lang.reflect.InvocationTargetException; +import java.util.Arrays; +import java.util.EventObject; +import java.util.List; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.swing.JFrame; + +import java.io.IOException; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.awt.NewtCanvasAWT; +import com.jogamp.newt.event.InputEvent; +import com.jogamp.newt.event.KeyEvent; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; +import com.jogamp.opengl.test.junit.util.*; + +/** + * Testing key event order incl. auto-repeat (Bug 601) + * + * <p> + * Note Event order: + * <ol> + * <li>{@link #EVENT_KEY_PRESSED}</li> + * <li>{@link #EVENT_KEY_RELEASED}</li> + * </ol> + * </p> + * <p> + * Auto-Repeat shall behave as follow: + * <pre> + D = pressed, U = released + 0 = normal, 1 = auto-repeat + + D(0), [ U(1), D(1), U(1), D(1) ..], U(0) + * </pre> + * + * The idea is if you mask out auto-repeat in your event listener + * you just get one long pressed key D/U tuple. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestNewtKeyEventAutoRepeatAWT extends UITestCase { + static int width, height; + static long durationPerTest = 100; + static long awtWaitTimeout = 1000; + + static GLCapabilities glCaps; + + @BeforeClass + public static void initClass() { + width = 640; + height = 480; + glCaps = new GLCapabilities(null); + } + + @AfterClass + public static void release() { + } + + @Before + public void initTest() { + } + + @After + public void releaseTest() { + } + + @Test(timeout=180000) // TO 3 min + public void test01NEWT() throws AWTException, InterruptedException, InvocationTargetException { + GLWindow glWindow = GLWindow.create(glCaps); + glWindow.setSize(width, height); + glWindow.setVisible(true); + + testImpl(glWindow); + + glWindow.destroy(); + } + + @Test(timeout=180000) // TO 3 min + public void test02NewtCanvasAWT() throws AWTException, InterruptedException, InvocationTargetException { + GLWindow glWindow = GLWindow.create(glCaps); + + // Wrap the window in a canvas. + final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow); + + // Add the canvas to a frame, and make it all visible. + final JFrame frame1 = new JFrame("Swing AWT Parent Frame: "+ glWindow.getTitle()); + frame1.getContentPane().add(newtCanvasAWT, BorderLayout.CENTER); + frame1.setSize(width, height); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame1.setVisible(true); + } } ); + + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame1, true)); + + testImpl(glWindow); + + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame1.setVisible(false); + frame1.dispose(); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + glWindow.destroy(); + } + + static void testKeyEventAutoRepeat(Robot robot, NEWTKeyAdapter keyAdapter, int loops, int pressDurationMS) { + System.err.println("KEY Event Auto-Repeat Test: "+loops); + EventObject[][] first = new EventObject[loops][2]; + EventObject[][] last = new EventObject[loops][2]; + + keyAdapter.reset(); + int firstIdx = 0; + // final ArrayList<EventObject> keyEvents = new ArrayList<EventObject>(); + for(int i=0; i<loops; i++) { + System.err.println("+++ KEY Event Auto-Repeat START Input Loop: "+i); + AWTRobotUtil.waitForIdle(robot); + AWTRobotUtil.keyPress(0, robot, true, java.awt.event.KeyEvent.VK_A, pressDurationMS); + AWTRobotUtil.keyPress(0, robot, false, java.awt.event.KeyEvent.VK_A, 500); // 1s .. no AR anymore + AWTRobotUtil.waitForIdle(robot); + final int minCodeCount = firstIdx + 2; + final int desiredCodeCount = firstIdx + 4; + for(int j=0; j < NEWTKeyUtil.POLL_DIVIDER && keyAdapter.getQueueSize() < desiredCodeCount; j++) { // wait until events are collected + robot.delay(NEWTKeyUtil.TIME_SLICE); + } + final List<EventObject> keyEvents = keyAdapter.copyQueue(); + Assert.assertTrue("AR Test didn't collect enough key events: required min "+minCodeCount+", received "+(keyAdapter.getQueueSize()-firstIdx)+", "+keyEvents, + keyAdapter.getQueueSize() >= minCodeCount ); + first[i][0] = keyEvents.get(firstIdx+0); + first[i][1] = keyEvents.get(firstIdx+1); + firstIdx = keyEvents.size() - 2; + last[i][0] = keyEvents.get(firstIdx+0); + last[i][1] = keyEvents.get(firstIdx+1); + System.err.println("+++ KEY Event Auto-Repeat END Input Loop: "+i); + + // add a pair of normal press/release in between auto-repeat! + firstIdx = keyEvents.size(); + AWTRobotUtil.waitForIdle(robot); + AWTRobotUtil.keyPress(0, robot, true, java.awt.event.KeyEvent.VK_B, 10); + AWTRobotUtil.keyPress(0, robot, false, java.awt.event.KeyEvent.VK_B, 250); + AWTRobotUtil.waitForIdle(robot); + for(int j=0; j < NEWTKeyUtil.POLL_DIVIDER && keyAdapter.getQueueSize() < firstIdx+2; j++) { // wait until events are collected + robot.delay(NEWTKeyUtil.TIME_SLICE); + } + firstIdx = keyAdapter.getQueueSize(); + } + // dumpKeyEvents(keyEvents); + final List<EventObject> keyEvents = keyAdapter.copyQueue(); + NEWTKeyUtil.validateKeyEventOrder(keyEvents); + + final boolean hasAR = 0 < keyAdapter.getKeyPressedCount(true) ; + + { + final int perLoopSI = 2; // per loop: 1 non AR event and 1 for non AR 'B' + final int expSI, expAR; + if( hasAR ) { + expSI = perLoopSI * loops; + expAR = ( keyEvents.size() - expSI*2 ) / 2; // auto-repeat release + } else { + expSI = keyEvents.size() / 2; // all released events + expAR = 0; + } + + NEWTKeyUtil.validateKeyAdapterStats(keyAdapter, + expSI /* press-SI */, expSI /* release-SI */, + expAR /* press-AR */, expAR /* release-AR */ ); + } + + if( !hasAR ) { + System.err.println("No AUTO-REPEAT triggered by AWT Robot .. aborting test analysis"); + return; + } + + for(int i=0; i<loops; i++) { + System.err.println("Auto-Repeat Loop "+i+" - Head:"); + NEWTKeyUtil.dumpKeyEvents(Arrays.asList(first[i])); + System.err.println("Auto-Repeat Loop "+i+" - Tail:"); + NEWTKeyUtil.dumpKeyEvents(Arrays.asList(last[i])); + } + for(int i=0; i<loops; i++) { + KeyEvent e = (KeyEvent) first[i][0]; + Assert.assertTrue("1st Shall be A, but is "+e, KeyEvent.VK_A == e.getKeyCode() ); + Assert.assertTrue("1st Shall be PRESSED, but is "+e, KeyEvent.EVENT_KEY_PRESSED == e.getEventType() ); + Assert.assertTrue("1st Shall not be AR, but is "+e, 0 == ( InputEvent.AUTOREPEAT_MASK & e.getModifiers() ) ); + + e = (KeyEvent) first[i][1]; + Assert.assertTrue("2nd Shall be A, but is "+e, KeyEvent.VK_A == e.getKeyCode() ); + Assert.assertTrue("2nd Shall be RELEASED, but is "+e, KeyEvent.EVENT_KEY_RELEASED == e.getEventType() ); + Assert.assertTrue("2nd Shall be AR, but is "+e, 0 != ( InputEvent.AUTOREPEAT_MASK & e.getModifiers() ) ); + + e = (KeyEvent) last[i][0]; + Assert.assertTrue("last-1 Shall be A, but is "+e, KeyEvent.VK_A == e.getKeyCode() ); + Assert.assertTrue("last-1 Shall be PRESSED, but is "+e, KeyEvent.EVENT_KEY_PRESSED == e.getEventType() ); + Assert.assertTrue("last-1 Shall be AR, but is "+e, 0 != ( InputEvent.AUTOREPEAT_MASK & e.getModifiers() ) ); + + e = (KeyEvent) last[i][1]; + Assert.assertTrue("last-0 Shall be A, but is "+e, KeyEvent.VK_A == e.getKeyCode() ); + Assert.assertTrue("last-2 Shall be RELEASED, but is "+e, KeyEvent.EVENT_KEY_RELEASED == e.getEventType() ); + Assert.assertTrue("last-0 Shall not be AR, but is "+e, 0 == ( InputEvent.AUTOREPEAT_MASK & e.getModifiers() ) ); + } + } + + void testImpl(GLWindow glWindow) throws AWTException, InterruptedException, InvocationTargetException { + final Robot robot = new Robot(); + robot.setAutoWaitForIdle(true); + + GLEventListener demo1 = new RedSquareES2(); + glWindow.addGLEventListener(demo1); + + NEWTKeyAdapter glWindow1KA = new NEWTKeyAdapter("GLWindow1"); + glWindow1KA.setVerbose(false); + glWindow.addKeyListener(glWindow1KA); + + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, true)); + + // Continuous animation .. + Animator animator = new Animator(glWindow); + animator.start(); + + Thread.sleep(durationPerTest); // manual testing + + AWTRobotUtil.assertRequestFocusAndWait(null, glWindow, glWindow, null, null); // programmatic + AWTRobotUtil.requestFocus(robot, glWindow, false); // within unit framework, prev. tests (TestFocus02SwingAWTRobot) 'confuses' Windows keyboard input + glWindow1KA.reset(); + + // + // Test the key event order w/ auto-repeat + // + final int origAutoDelay = robot.getAutoDelay(); + robot.setAutoDelay(10); + try { + testKeyEventAutoRepeat(robot, glWindow1KA, 3, 1000); + } finally { + robot.setAutoDelay(origAutoDelay); + } + + // Remove listeners to avoid logging during dispose/destroy. + glWindow.removeKeyListener(glWindow1KA); + + // Shutdown the test. + animator.stop(); + } + + static int atoi(String a) { + int i=0; + try { + i = Integer.parseInt(a); + } catch (Exception ex) { ex.printStackTrace(); } + return i; + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + durationPerTest = atoi(args[++i]); + } + } + /** + BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); + System.err.println("Press enter to continue"); + System.err.println(stdin.readLine()); + */ + System.out.println("durationPerTest: "+durationPerTest); + String tstname = TestNewtKeyEventAutoRepeatAWT.class.getName(); + org.junit.runner.JUnitCore.main(tstname); + } + + +} diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventOrderAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventOrderAWT.java new file mode 100644 index 000000000..8cc427508 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventOrderAWT.java @@ -0,0 +1,262 @@ +/** + * Copyright 2012 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.event; + +import org.junit.After; +import org.junit.Assert; +import org.junit.AfterClass; +import org.junit.Assume; +import org.junit.Before; + +import java.awt.AWTException; +import java.awt.BorderLayout; +import java.awt.Robot; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.swing.JFrame; + +import java.io.IOException; + +import jogamp.nativewindow.jawt.JAWTUtil; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.awt.NewtCanvasAWT; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; + +import com.jogamp.opengl.test.junit.util.*; + +/** + * Testing key event order excl. auto-repeat (Bug 601) + * + * <p> + * Note Event order: + * <ol> + * <li>{@link #EVENT_KEY_PRESSED}</li> + * <li>{@link #EVENT_KEY_RELEASED}</li> + * </ol> + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestNewtKeyEventOrderAWT extends UITestCase { + static int width, height; + static long durationPerTest = 100; + static long awtWaitTimeout = 1000; + + static GLCapabilities glCaps; + + @BeforeClass + public static void initClass() { + width = 640; + height = 480; + glCaps = new GLCapabilities(null); + } + + @AfterClass + public static void release() { + } + + @Before + public void initTest() { + } + + @After + public void releaseTest() { + } + + @Test(timeout=180000) // TO 3 min + public void test01NEWT() throws AWTException, InterruptedException, InvocationTargetException { + GLWindow glWindow = GLWindow.create(glCaps); + glWindow.setSize(width, height); + glWindow.setVisible(true); + + testImpl(glWindow); + + glWindow.destroy(); + } + + private void testNewtCanvasAWT_Impl(boolean onscreen) throws AWTException, InterruptedException, InvocationTargetException { + GLWindow glWindow = GLWindow.create(glCaps); + + // Wrap the window in a canvas. + final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow); + if( !onscreen ) { + newtCanvasAWT.setShallUseOffscreenLayer(true); + } + + // Add the canvas to a frame, and make it all visible. + final JFrame frame1 = new JFrame("Swing AWT Parent Frame: "+ glWindow.getTitle()); + frame1.getContentPane().add(newtCanvasAWT, BorderLayout.CENTER); + frame1.setSize(width, height); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame1.setVisible(true); + } } ); + + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame1, true)); + + testImpl(glWindow); + + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame1.setVisible(false); + frame1.dispose(); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + glWindow.destroy(); + } + + @Test(timeout=180000) // TO 3 min + public void test02NewtCanvasAWT_Onscreen() throws AWTException, InterruptedException, InvocationTargetException { + if( JAWTUtil.isOffscreenLayerRequired() ) { + System.err.println("Platform doesn't support onscreen rendering."); + return; + } + testNewtCanvasAWT_Impl(true); + } + + @Test(timeout=180000) // TO 3 min + public void test03NewtCanvasAWT_Offsccreen() throws AWTException, InterruptedException, InvocationTargetException { + if( !JAWTUtil.isOffscreenLayerSupported() ) { + System.err.println("Platform doesn't support offscreen rendering."); + return; + } + testNewtCanvasAWT_Impl(false); + } + + static void testKeyEventOrder(Robot robot, NEWTKeyAdapter keyAdapter, int loops) { + System.err.println("KEY Event Order Test: "+loops); + keyAdapter.reset(); + for(int i=0; i<loops; i++) { + // 1 + AWTRobotUtil.waitForIdle(robot); + AWTRobotUtil.keyPress(0, robot, true, java.awt.event.KeyEvent.VK_A, 10); + AWTRobotUtil.keyPress(0, robot, false, java.awt.event.KeyEvent.VK_A, 100); + // 2 + AWTRobotUtil.waitForIdle(robot); + AWTRobotUtil.keyPress(0, robot, true, java.awt.event.KeyEvent.VK_B, 10); + AWTRobotUtil.keyPress(0, robot, false, java.awt.event.KeyEvent.VK_B, 100); + // 3 + 4 + AWTRobotUtil.waitForIdle(robot); + AWTRobotUtil.keyPress(0, robot, true, java.awt.event.KeyEvent.VK_A, 10); + AWTRobotUtil.keyPress(0, robot, true, java.awt.event.KeyEvent.VK_B, 10); + AWTRobotUtil.keyPress(0, robot, false, java.awt.event.KeyEvent.VK_A, 10); + AWTRobotUtil.keyPress(0, robot, false, java.awt.event.KeyEvent.VK_B, 10); + // 5 + 6 + AWTRobotUtil.waitForIdle(robot); + AWTRobotUtil.keyPress(0, robot, true, java.awt.event.KeyEvent.VK_A, 10); + AWTRobotUtil.keyPress(0, robot, true, java.awt.event.KeyEvent.VK_B, 10); + AWTRobotUtil.keyPress(0, robot, false, java.awt.event.KeyEvent.VK_B, 10); + AWTRobotUtil.keyPress(0, robot, false, java.awt.event.KeyEvent.VK_A, 10); + } + AWTRobotUtil.waitForIdle(robot); + robot.delay(250); + // dumpKeyEvents(keyAdapter.getQueued()); + + NEWTKeyUtil.validateKeyEventOrder(keyAdapter.copyQueue()); + + final int expTotal = 6*loops; // all typed events + NEWTKeyUtil.validateKeyAdapterStats(keyAdapter, + expTotal /* press-SI */, expTotal /* release-SI */, + 0 /* press-AR */, 0 /* release-AR */ ); + + } + + void testImpl(GLWindow glWindow) throws AWTException, InterruptedException, InvocationTargetException { + final Robot robot = new Robot(); + robot.setAutoWaitForIdle(true); + + GLEventListener demo1 = new RedSquareES2(); + glWindow.addGLEventListener(demo1); + + NEWTKeyAdapter glWindow1KA = new NEWTKeyAdapter("GLWindow1"); + glWindow1KA.setVerbose(false); + glWindow.addKeyListener(glWindow1KA); + + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, true)); + + // Continuous animation .. + Animator animator = new Animator(glWindow); + animator.start(); + + Thread.sleep(durationPerTest); // manual testing + + AWTRobotUtil.assertRequestFocusAndWait(null, glWindow, glWindow, null, null); // programmatic + AWTRobotUtil.requestFocus(robot, glWindow, false); // within unit framework, prev. tests (TestFocus02SwingAWTRobot) 'confuses' Windows keyboard input + glWindow1KA.reset(); + + // + // Test the key event order w/o auto-repeat + // + testKeyEventOrder(robot, glWindow1KA, 6); + + // Remove listeners to avoid logging during dispose/destroy. + glWindow.removeKeyListener(glWindow1KA); + + // Shutdown the test. + animator.stop(); + } + + static int atoi(String a) { + int i=0; + try { + i = Integer.parseInt(a); + } catch (Exception ex) { ex.printStackTrace(); } + return i; + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + durationPerTest = atoi(args[++i]); + } + } + /** + BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); + System.err.println("Press enter to continue"); + System.err.println(stdin.readLine()); + */ + System.out.println("durationPerTest: "+durationPerTest); + String tstname = TestNewtKeyEventOrderAWT.class.getName(); + org.junit.runner.JUnitCore.main(tstname); + } + + +} diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyPressReleaseUnmaskRepeatAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyPressReleaseUnmaskRepeatAWT.java new file mode 100644 index 000000000..f48a07a8c --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyPressReleaseUnmaskRepeatAWT.java @@ -0,0 +1,240 @@ +/** + * Copyright 2012 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.event; + +import org.junit.After; +import org.junit.Assert; +import org.junit.AfterClass; +import org.junit.Assume; +import org.junit.Before; + +import java.awt.AWTException; +import java.awt.BorderLayout; +import java.awt.Robot; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.swing.JFrame; + +import java.io.IOException; + +import jogamp.nativewindow.jawt.JAWTUtil; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.awt.NewtCanvasAWT; +import com.jogamp.newt.event.InputEvent; +import com.jogamp.newt.event.KeyEvent; +import com.jogamp.newt.event.KeyListener; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; + +import com.jogamp.opengl.test.junit.util.*; + +/** + * Testing key press and release events w/o AUTO-REPEAT + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestNewtKeyPressReleaseUnmaskRepeatAWT extends UITestCase { + static int width, height; + static long durationPerTest = 100; + static long awtWaitTimeout = 1000; + + static GLCapabilities glCaps; + + @BeforeClass + public static void initClass() { + width = 640; + height = 480; + glCaps = new GLCapabilities(null); + } + + @AfterClass + public static void release() { + } + + @Before + public void initTest() { + } + + @After + public void releaseTest() { + } + + @Test(timeout=180000) // TO 3 min + public void test01NEWT() throws AWTException, InterruptedException, InvocationTargetException { + GLWindow glWindow = GLWindow.create(glCaps); + glWindow.setSize(width, height); + glWindow.setVisible(true); + + testImpl(glWindow); + + glWindow.destroy(); + } + + private void testNewtCanvasAWT_Impl(boolean onscreen) throws AWTException, InterruptedException, InvocationTargetException { + GLWindow glWindow = GLWindow.create(glCaps); + + // Wrap the window in a canvas. + final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow); + if( !onscreen ) { + newtCanvasAWT.setShallUseOffscreenLayer(true); + } + + // Add the canvas to a frame, and make it all visible. + final JFrame frame1 = new JFrame("Swing AWT Parent Frame: "+ glWindow.getTitle()); + frame1.getContentPane().add(newtCanvasAWT, BorderLayout.CENTER); + frame1.setSize(width, height); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame1.setVisible(true); + } } ); + + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame1, true)); + + testImpl(glWindow); + + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame1.setVisible(false); + frame1.dispose(); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + glWindow.destroy(); + } + + @Test(timeout=180000) // TO 3 min + public void test02NewtCanvasAWT_Onscreen() throws AWTException, InterruptedException, InvocationTargetException { + if( JAWTUtil.isOffscreenLayerRequired() ) { + System.err.println("Platform doesn't support onscreen rendering."); + return; + } + testNewtCanvasAWT_Impl(true); + } + + @Test(timeout=180000) // TO 3 min + public void test03NewtCanvasAWT_Offsccreen() throws AWTException, InterruptedException, InvocationTargetException { + if( !JAWTUtil.isOffscreenLayerSupported() ) { + System.err.println("Platform doesn't support offscreen rendering."); + return; + } + testNewtCanvasAWT_Impl(false); + } + + void testImpl(GLWindow glWindow) throws AWTException, InterruptedException, InvocationTargetException { + final Robot robot = new Robot(); + robot.setAutoWaitForIdle(true); + + GLEventListener demo1 = new RedSquareES2(); + glWindow.addGLEventListener(demo1); + + SimpleKeyPressRelease simpleKeyPressRelease = new SimpleKeyPressRelease(); + glWindow.addKeyListener(simpleKeyPressRelease); + + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, true)); + + // Continuous animation .. + Animator animator = new Animator(glWindow); + animator.start(); + + Thread.sleep(durationPerTest); // manual testing + + AWTRobotUtil.assertRequestFocusAndWait(null, glWindow, glWindow, null, null); // programmatic + AWTRobotUtil.requestFocus(robot, glWindow, false); // within unit framework, prev. tests (TestFocus02SwingAWTRobot) 'confuses' Windows keyboard input + + // Remove listeners to avoid logging during dispose/destroy. + glWindow.removeKeyListener(simpleKeyPressRelease); + + // Shutdown the test. + animator.stop(); + } + + static int atoi(String a) { + int i=0; + try { + i = Integer.parseInt(a); + } catch (Exception ex) { ex.printStackTrace(); } + return i; + } + + static class SimpleKeyPressRelease implements KeyListener { + int seq; + + SimpleKeyPressRelease() { + reset(); + } + + public void reset() { + seq=0; + } + + @Override + public void keyPressed(KeyEvent e) { + if( 0 == ( InputEvent.AUTOREPEAT_MASK & e.getModifiers() ) ) { + seq++; + System.err.println(seq+": "+e); + } + } + + @Override + public void keyReleased(KeyEvent e) { + if( 0 == ( InputEvent.AUTOREPEAT_MASK & e.getModifiers() ) ) { + seq++; + System.err.println(seq+": "+e); + } + } + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + durationPerTest = atoi(args[++i]); + } + } + /** + BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); + System.err.println("Press enter to continue"); + System.err.println(stdin.readLine()); + */ + System.out.println("durationPerTest: "+durationPerTest); + String tstname = TestNewtKeyPressReleaseUnmaskRepeatAWT.class.getName(); + org.junit.runner.JUnitCore.main(tstname); + } + + +} diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestFocus01SwingAWTRobot.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestParentingFocus01SwingAWTRobot.java index bb67e77ea..d3c29cfac 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestFocus01SwingAWTRobot.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestParentingFocus01SwingAWTRobot.java @@ -3,14 +3,14 @@ * * 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 @@ -20,13 +20,13 @@ * 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; + +package com.jogamp.opengl.test.junit.newt.event; import org.junit.Assert; import org.junit.AfterClass; @@ -35,6 +35,7 @@ import org.junit.Assume; import java.awt.AWTException; import java.awt.BorderLayout; import java.awt.Button; +import java.awt.Container; import java.awt.Robot; import java.lang.reflect.InvocationTargetException; @@ -47,15 +48,27 @@ import java.io.IOException; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import com.jogamp.newt.awt.NewtCanvasAWT; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; - +import com.jogamp.opengl.test.junit.newt.TestListenerCom01AWT; import com.jogamp.opengl.test.junit.util.*; -public class TestFocus01SwingAWTRobot extends UITestCase { +/** + * Testing focus <i>mouse-click</i> and <i>programmatic</i> traversal of an AWT component tree with {@link NewtCanvasAWT} attached. + * <p> + * {@link JFrame} . {@link Container}+ [ Button*, {@link NewtCanvasAWT} . {@link GLWindow} ] + * </p> + * <p> + * <i>+ Container is the JFrame's implicit root content pane</i><br/> + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestParentingFocus01SwingAWTRobot extends UITestCase { static int width, height; static long durationPerTest = 10; static long awtWaitTimeout = 1000; @@ -105,6 +118,7 @@ public class TestFocus01SwingAWTRobot extends UITestCase { // Wrap the window in a canvas. final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow1); + // newtCanvasAWT.setShallUseOffscreenLayer(true); // Monitor AWT focus and keyboard events. AWTKeyAdapter newtCanvasAWTKA = new AWTKeyAdapter("NewtCanvasAWT"); @@ -116,8 +130,6 @@ public class TestFocus01SwingAWTRobot extends UITestCase { // Add the canvas to a frame, and make it all visible. final JFrame frame1 = new JFrame("Swing AWT Parent Frame: " + glWindow1.getTitle()); - AWTFocusAdapter frame1FA = new AWTFocusAdapter("frame1"); - frame1.addFocusListener(frame1FA); frame1.getContentPane().add(newtCanvasAWT, BorderLayout.CENTER); final Button button = new Button("Click me .."); AWTFocusAdapter buttonFA = new AWTFocusAdapter("Button"); @@ -125,6 +137,10 @@ public class TestFocus01SwingAWTRobot extends UITestCase { AWTKeyAdapter buttonKA = new AWTKeyAdapter("Button"); button.addKeyListener(buttonKA); eventCountAdapters.add(buttonKA); + AWTMouseAdapter buttonMA = new AWTMouseAdapter("Button"); + button.addMouseListener(buttonMA); + eventCountAdapters.add(buttonMA); + frame1.getContentPane().add(button, BorderLayout.NORTH); frame1.setSize(width, height); javax.swing.SwingUtilities.invokeAndWait(new Runnable() { @@ -132,12 +148,12 @@ public class TestFocus01SwingAWTRobot extends UITestCase { frame1.setVisible(true); } } ); Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame1, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow1, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow1, true)); AWTRobotUtil.clearAWTFocus(robot); Assert.assertTrue(AWTRobotUtil.toFrontAndRequestFocus(robot, frame1)); Thread.sleep(durationPerTest); // manual testing - + int wait=0; while(wait<awtWaitTimeout/100 && glWindow1.getTotalFPSFrames()<1) { Thread.sleep(awtWaitTimeout/10); wait++; } System.err.println("Frames for initial setVisible(true): "+glWindow1.getTotalFPSFrames()); @@ -149,25 +165,38 @@ public class TestFocus01SwingAWTRobot extends UITestCase { animator.start(); // Button Focus - Thread.sleep(100); // allow event sync - + Thread.sleep(200); // allow event sync + System.err.println("FOCUS AWT Button request"); EventCountAdapterUtil.reset(eventCountAdapters); - AWTRobotUtil.assertRequestFocusAndWait(robot, button, button, buttonFA, frame1FA); + AWTRobotUtil.assertRequestFocusAndWait(robot, button, button, buttonFA, null); // OSX sporadically button did not gain - major UI failure Assert.assertEquals(false, glWindow1FA.focusGained()); Assert.assertEquals(false, newtCanvasAWTFA.focusGained()); System.err.println("FOCUS AWT Button sync"); AWTRobotUtil.assertKeyType(robot, java.awt.event.KeyEvent.VK_A, 2, button, buttonKA); + AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 1, + button, buttonMA); + AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 2, + button, buttonMA); // Request the AWT focus, which should automatically provide the NEWT window with focus. Thread.sleep(100); // allow event sync System.err.println("FOCUS NEWT Canvas/GLWindow request"); EventCountAdapterUtil.reset(eventCountAdapters); - AWTRobotUtil.assertRequestFocusAndWait(robot, newtCanvasAWT, newtCanvasAWT.getNEWTChild(), glWindow1FA, buttonFA); - Assert.assertEquals(false, newtCanvasAWTFA.focusGained()); + AWTRobotUtil.assertRequestFocusAndWait(robot, newtCanvasAWT, newtCanvasAWT.getNEWTChild(), glWindow1FA, buttonFA); // OSX sporadically button did not loose - minor UI failure + // Manually tested on Java7/[Linux,Windows] (where this assertion failed), + // Should be OK to have the AWT component assume it also has the focus. + // Assert.assertTrue("Focus prev. gained, but NewtCanvasAWT didn't loose it. Gainer: "+glWindow1FA+"; Looser "+newtCanvasAWTFA, + // AWTRobotUtil.waitForFocus(glWindow1FA, newtCanvasAWTFA)); + if( !AWTRobotUtil.waitForFocus(glWindow1FA, newtCanvasAWTFA) ) { + System.err.println("Info: Focus prev. gained, but NewtCanvasAWT didn't loose it. Gainer: "+glWindow1FA+"; Looser "+newtCanvasAWTFA); + } System.err.println("FOCUS NEWT Canvas/GLWindow sync"); AWTRobotUtil.assertKeyType(robot, java.awt.event.KeyEvent.VK_A, 2, glWindow1, glWindow1KA); - Assert.assertEquals("AWT parent canvas received keyboard events", 0, newtCanvasAWTKA.getCount()); + Assert.assertEquals("AWT parent canvas received non consumed keyboard events", newtCanvasAWTKA.getConsumedCount(), newtCanvasAWTKA.getCount()); + if( !newtCanvasAWT.isAWTEventPassThrough() ) { + Assert.assertEquals("AWT parent canvas received consumed keyboard events", 0, newtCanvasAWTKA.getConsumedCount()); + } // Remove listeners to avoid logging during dispose/destroy. glWindow1.removeKeyListener(glWindow1KA); @@ -186,8 +215,9 @@ public class TestFocus01SwingAWTRobot extends UITestCase { } catch( Throwable throwable ) { throwable.printStackTrace(); Assume.assumeNoException( throwable ); - } + } glWindow1.destroy(); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow1, false)); } static int atoi(String a) { @@ -207,10 +237,10 @@ public class TestFocus01SwingAWTRobot extends UITestCase { /** BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); System.err.println("Press enter to continue"); - System.err.println(stdin.readLine()); + System.err.println(stdin.readLine()); */ System.out.println("durationPerTest: "+durationPerTest); - String tstname = TestFocus01SwingAWTRobot.class.getName(); + String tstname = TestParentingFocus01SwingAWTRobot.class.getName(); org.junit.runner.JUnitCore.main(tstname); } diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestFocus02SwingAWTRobot.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestParentingFocus02SwingAWTRobot.java index a0efa53ad..edf82caa8 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestFocus02SwingAWTRobot.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestParentingFocus02SwingAWTRobot.java @@ -3,14 +3,14 @@ * * 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 @@ -20,13 +20,13 @@ * 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; + +package com.jogamp.opengl.test.junit.newt.event; import java.lang.reflect.*; @@ -34,6 +34,8 @@ import org.junit.Assert; import org.junit.BeforeClass; import org.junit.AfterClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import java.awt.AWTException; import java.awt.Button; @@ -56,22 +58,37 @@ import java.io.IOException; import com.jogamp.opengl.test.junit.util.*; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; -public class TestFocus02SwingAWTRobot extends UITestCase { +/** + * Testing focus <i>mouse-click</i> and <i>programmatic</i> traversal of an AWT component tree with {@link NewtCanvasAWT} attached. + * <p> + * {@link JFrame} . {@link JPanel}+ . {@link Container} [ Button*, {@link NewtCanvasAWT} . {@link GLWindow} ] + * </p> + * <p> + * <i>+ JPanel is set as JFrame's root content pane</i><br/> + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestParentingFocus02SwingAWTRobot extends UITestCase { static int width, height; static long durationPerTest = 10; static long awtWaitTimeout = 1000; static GLCapabilities glCaps; @BeforeClass - public static void initClass() throws AWTException { + public static void initClass() throws AWTException, InterruptedException, InvocationTargetException { width = 640; height = 480; - JFrame f = new JFrame(); - f.setSize(100,100); - f.setVisible(true); - f.dispose(); - f=null; + final JFrame f = new JFrame(); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + f.setSize(100,100); + f.setVisible(true); + } } ); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + f.dispose(); + } } ); glCaps = new GLCapabilities(null); } @@ -79,15 +96,12 @@ public class TestFocus02SwingAWTRobot extends UITestCase { @AfterClass public static void release() { } - - private void testFocus01ProgrFocusImpl(Robot robot) + + private void testFocus01ProgrFocusImpl(Robot robot) throws AWTException, InterruptedException, InvocationTargetException { ArrayList<EventCountAdapter> eventCountAdapters = new ArrayList<EventCountAdapter>(); - /** - * JFrame . JPanel . Container . NewtCanvasAWT . GLWindow - */ GLWindow glWindow1 = GLWindow.create(glCaps); glWindow1.setTitle("testWindowParenting01CreateVisibleDestroy"); GLEventListener demo1 = new GearsES2(); @@ -120,7 +134,7 @@ public class TestFocus02SwingAWTRobot extends UITestCase { AWTMouseAdapter buttonNorthInnerMA = new AWTMouseAdapter("ButtonNorthInner"); buttonNorthInner.addMouseListener(buttonNorthInnerMA); eventCountAdapters.add(buttonNorthInnerMA); - Container container1 = new Container(); + final Container container1 = new Container(); container1.setLayout(new BorderLayout()); container1.add(buttonNorthInner, BorderLayout.NORTH); container1.add(new Button("south"), BorderLayout.SOUTH); @@ -137,7 +151,7 @@ public class TestFocus02SwingAWTRobot extends UITestCase { AWTMouseAdapter buttonNorthOuterMA = new AWTMouseAdapter("ButtonNorthOuter"); buttonNorthOuter.addMouseListener(buttonNorthOuterMA); eventCountAdapters.add(buttonNorthOuterMA); - JPanel jPanel1 = new JPanel(); + final JPanel jPanel1 = new JPanel(); jPanel1.setLayout(new BorderLayout()); jPanel1.add(buttonNorthOuter, BorderLayout.NORTH); jPanel1.add(new Button("south"), BorderLayout.SOUTH); @@ -146,8 +160,6 @@ public class TestFocus02SwingAWTRobot extends UITestCase { jPanel1.add(container1, BorderLayout.CENTER); final JFrame jFrame1 = new JFrame("Swing Parent JFrame"); - AWTFocusAdapter jFrame1FA = new AWTFocusAdapter("JFrame1"); - jFrame1.addFocusListener(jFrame1FA); // jFrame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jFrame1.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // equivalent to Frame, use windowClosing event! jFrame1.setContentPane(jPanel1); @@ -157,7 +169,7 @@ public class TestFocus02SwingAWTRobot extends UITestCase { jFrame1.setVisible(true); } } ); Assert.assertEquals(true, AWTRobotUtil.waitForVisible(jFrame1, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow1, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow1, true)); AWTRobotUtil.clearAWTFocus(robot); Assert.assertTrue(AWTRobotUtil.toFrontAndRequestFocus(robot, jFrame1)); @@ -172,52 +184,60 @@ public class TestFocus02SwingAWTRobot extends UITestCase { animator1.start(); Thread.sleep(durationPerTest); // manual testing - + // Button Outer Focus Thread.sleep(100); // allow event sync System.err.println("FOCUS AWT Button Outer request"); EventCountAdapterUtil.reset(eventCountAdapters); - AWTRobotUtil.assertRequestFocusAndWait(robot, buttonNorthOuter, buttonNorthOuter, buttonNorthOuterFA, jFrame1FA); + AWTRobotUtil.assertRequestFocusAndWait(robot, buttonNorthOuter, buttonNorthOuter, buttonNorthOuterFA, null); // OSX sporadically buttonNorthOuter did not gain - major UI failure Assert.assertEquals(false, glWindow1FA.focusGained()); Assert.assertEquals(false, newtCanvasAWTFA.focusGained()); Assert.assertEquals(false, buttonNorthInnerFA.focusGained()); System.err.println("FOCUS AWT Button Outer sync"); - AWTRobotUtil.assertKeyType(robot, java.awt.event.KeyEvent.VK_A, 2, buttonNorthOuter, buttonNorthOuterKA); - AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 1, + AWTRobotUtil.assertKeyType(robot, java.awt.event.KeyEvent.VK_A, 2, buttonNorthOuter, buttonNorthOuterKA); // OSX sporadically won't receive the keyboard input - major UI failure + AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 1, + buttonNorthOuter, buttonNorthOuterMA); + AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 2, buttonNorthOuter, buttonNorthOuterMA); - AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 2, - buttonNorthOuter, buttonNorthOuterMA); // NEWT Focus Thread.sleep(100); // allow event sync System.err.println("FOCUS NEWT Canvas/GLWindow request"); EventCountAdapterUtil.reset(eventCountAdapters); AWTRobotUtil.assertRequestFocusAndWait(robot, newtCanvasAWT, newtCanvasAWT.getNEWTChild(), glWindow1FA, buttonNorthOuterFA); - Assert.assertEquals(false, newtCanvasAWTFA.focusGained()); + // Manually tested on Java7/[Linux,Windows] (where this assertion failed), + // Should be OK to have the AWT component assume it also has the focus. + // Assert.assertTrue("Focus prev. gained, but NewtCanvasAWT didn't loose it. Gainer: "+glWindow1FA+"; Looser "+newtCanvasAWTFA, + // AWTRobotUtil.waitForFocus(glWindow1FA, newtCanvasAWTFA)); + if( !AWTRobotUtil.waitForFocus(glWindow1FA, newtCanvasAWTFA) ) { + System.err.println("Info: Focus prev. gained, but NewtCanvasAWT didn't loose it. Gainer: "+glWindow1FA+"; Looser "+newtCanvasAWTFA); + } Assert.assertEquals(false, buttonNorthInnerFA.focusGained()); - Assert.assertEquals(false, jFrame1FA.focusGained()); System.err.println("FOCUS NEWT Canvas/GLWindow sync"); AWTRobotUtil.assertKeyType(robot, java.awt.event.KeyEvent.VK_A, 2, glWindow1, glWindow1KA); - Assert.assertEquals("AWT parent canvas received keyboard events", 0, newtCanvasAWTKA.getCount()); - AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 1, + Assert.assertEquals("AWT parent canvas received non consumed keyboard events", newtCanvasAWTKA.getConsumedCount(), newtCanvasAWTKA.getCount()); + AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 1, glWindow1, glWindow1MA); - AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 2, + AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 2, glWindow1, glWindow1MA); - Assert.assertEquals("AWT parent canvas received mouse events", 0, newtCanvasAWTMA.getCount()); + if( !newtCanvasAWT.isAWTEventPassThrough() ) { + Assert.assertEquals("AWT parent canvas received consumed keyboard events", 0, newtCanvasAWTKA.getConsumedCount()); + Assert.assertEquals("AWT parent canvas received mouse events", 0, newtCanvasAWTMA.getCount()); + } // Button Inner Focus Thread.sleep(100); // allow event sync System.err.println("FOCUS AWT Button request"); EventCountAdapterUtil.reset(eventCountAdapters); AWTRobotUtil.assertRequestFocusAndWait(robot, buttonNorthInner, buttonNorthInner, buttonNorthInnerFA, glWindow1FA); + Assert.assertEquals(false, glWindow1FA.focusGained()); Assert.assertEquals(false, newtCanvasAWTFA.focusGained()); Assert.assertEquals(false, buttonNorthOuterFA.focusGained()); - Assert.assertEquals(false, jFrame1FA.focusGained()); System.err.println("FOCUS AWT Button sync"); AWTRobotUtil.assertKeyType(robot, java.awt.event.KeyEvent.VK_A, 2, buttonNorthInner, buttonNorthInnerKA); - AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 1, + AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 1, buttonNorthInner, buttonNorthInnerMA); - AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 2, + AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 2, buttonNorthInner, buttonNorthInnerMA); // NEWT Focus @@ -225,33 +245,39 @@ public class TestFocus02SwingAWTRobot extends UITestCase { System.err.println("FOCUS NEWT Canvas/GLWindow request"); EventCountAdapterUtil.reset(eventCountAdapters); AWTRobotUtil.assertRequestFocusAndWait(robot, newtCanvasAWT, newtCanvasAWT.getNEWTChild(), glWindow1FA, buttonNorthInnerFA); - Assert.assertTrue(AWTRobotUtil.waitForFocusCount(false, newtCanvasAWTFA)); - Assert.assertEquals(false, newtCanvasAWTFA.focusGained()); + // Manually tested on Java7/[Linux,Windows] (where this assertion failed), + // Should be OK to have the AWT component assume it also has the focus. + // Assert.assertTrue("Focus prev. gained, but NewtCanvasAWT didn't loose it. Gainer: "+glWindow1FA+"; Looser "+newtCanvasAWTFA, + // AWTRobotUtil.waitForFocus(glWindow1FA, newtCanvasAWTFA)); + if( !AWTRobotUtil.waitForFocus(glWindow1FA, newtCanvasAWTFA) ) { + System.err.println("Info: Focus prev. gained, but NewtCanvasAWT didn't loose it. Gainer: "+glWindow1FA+"; Looser "+newtCanvasAWTFA); + } + Assert.assertEquals(false, buttonNorthOuterFA.focusGained()); - Assert.assertEquals(false, jFrame1FA.focusGained()); System.err.println("FOCUS NEWT Canvas/GLWindow sync"); AWTRobotUtil.assertKeyType(robot, java.awt.event.KeyEvent.VK_A, 2, glWindow1, glWindow1KA); - Assert.assertEquals("AWT parent canvas received keyboard events", 0, newtCanvasAWTKA.getCount()); - AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 1, + Assert.assertEquals("AWT parent canvas received non consumed keyboard events", newtCanvasAWTKA.getConsumedCount(), newtCanvasAWTKA.getCount()); + AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 1, glWindow1, glWindow1MA); - AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 2, + AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 2, glWindow1, glWindow1MA); - Assert.assertEquals("AWT parent canvas received mouse events", 0, newtCanvasAWTMA.getCount()); + if( !newtCanvasAWT.isAWTEventPassThrough() ) { + Assert.assertEquals("AWT parent canvas received consumed keyboard events", 0, newtCanvasAWTKA.getConsumedCount()); + Assert.assertEquals("AWT parent canvas received mouse events", 0, newtCanvasAWTMA.getCount()); + } animator1.stop(); Assert.assertEquals(false, animator1.isAnimating()); - final JFrame _jFrame1 = jFrame1; - final JPanel _jPanel1 = jPanel1; - final Container _container1 = container1; SwingUtilities.invokeAndWait(new Runnable() { public void run() { - _jFrame1.setVisible(false); - _jPanel1.remove(_container1); - _jFrame1.dispose(); + jFrame1.setVisible(false); + jPanel1.remove(container1); + jFrame1.dispose(); } }); glWindow1.destroy(); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow1, false)); } @Test @@ -275,8 +301,8 @@ public class TestFocus02SwingAWTRobot extends UITestCase { } @SuppressWarnings("unused") - public static void main(String args[]) - throws IOException, AWTException, InterruptedException, InvocationTargetException + public static void main(String args[]) + throws IOException, AWTException, InterruptedException, InvocationTargetException { for(int i=0; i<args.length; i++) { if(args[i].equals("-time")) { @@ -284,14 +310,14 @@ public class TestFocus02SwingAWTRobot extends UITestCase { } } if(true) { - String tstname = TestFocus02SwingAWTRobot.class.getName(); + String tstname = TestParentingFocus02SwingAWTRobot.class.getName(); org.junit.runner.JUnitCore.main(tstname); - } else { - TestFocus02SwingAWTRobot.initClass(); - TestFocus02SwingAWTRobot test = new TestFocus02SwingAWTRobot(); + } else { + TestParentingFocus02SwingAWTRobot.initClass(); + TestParentingFocus02SwingAWTRobot test = new TestParentingFocus02SwingAWTRobot(); test.testFocus01ProgrFocus(); test.testFocus02RobotFocus(); - TestFocus02SwingAWTRobot.release(); + TestParentingFocus02SwingAWTRobot.release(); } } } diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParentingFocusTraversal01AWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestParentingFocus03KeyTraversalAWT.java index f39b5df3b..71cc3fce3 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParentingFocusTraversal01AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestParentingFocus03KeyTraversalAWT.java @@ -3,14 +3,14 @@ * * 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 @@ -20,13 +20,13 @@ * 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.parenting; + +package com.jogamp.opengl.test.junit.newt.event; import java.lang.reflect.*; import java.util.HashSet; @@ -36,6 +36,8 @@ import java.util.Set; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import java.awt.AWTException; import java.awt.AWTKeyStroke; @@ -61,19 +63,28 @@ import jogamp.newt.driver.DriverClearFocus; import com.jogamp.opengl.test.junit.util.*; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.newt.parenting.NewtAWTReparentingKeyAdapter; -public class TestParentingFocusTraversal01AWT extends UITestCase { +/** + * Testing focus <i>key</i> traversal of an AWT component tree with {@link NewtCanvasAWT} attached. + * <p> + * {@link Frame} [ Button*, {@link NewtCanvasAWT} . {@link GLWindow} ] + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestParentingFocus03KeyTraversalAWT extends UITestCase { static Dimension glSize, fSize; static int numFocus = 8; static long durationPerTest = numFocus * 200; static GLCapabilities glCaps; static boolean manual = false; + static boolean forceGL3 = false; @BeforeClass public static void initClass() { glSize = new Dimension(200,200); fSize = new Dimension(300,300); - glCaps = new GLCapabilities(null); + glCaps = new GLCapabilities( forceGL3 ? GLProfile.get(GLProfile.GL3) : null ); } @Test @@ -88,22 +99,22 @@ public class TestParentingFocusTraversal01AWT extends UITestCase { public void testWindowParentingAWTFocusTraversal(boolean onscreen) throws InterruptedException, InvocationTargetException, AWTException { Robot robot = new Robot(); - + // Bug 4908075 - http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4908075 // Bug 6463168 - http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6463168 { final KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager(); - final Set<AWTKeyStroke> bwdKeys = kfm.getDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS); + final Set<AWTKeyStroke> bwdKeys = kfm.getDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS); final AWTKeyStroke newBack = AWTKeyStroke.getAWTKeyStroke(java.awt.event.KeyEvent.VK_BACK_SPACE, 0, false); Assert.assertNotNull(newBack); - final Set<AWTKeyStroke> bwdKeys2 = new HashSet<AWTKeyStroke>(bwdKeys); + final Set<AWTKeyStroke> bwdKeys2 = new HashSet<AWTKeyStroke>(bwdKeys); bwdKeys2.add(newBack); kfm.setDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, bwdKeys2); } { final KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager(); - final Set<AWTKeyStroke> fwdKeys = kfm.getDefaultFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS); - final Set<AWTKeyStroke> bwdKeys = kfm.getDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS); + final Set<AWTKeyStroke> fwdKeys = kfm.getDefaultFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS); + final Set<AWTKeyStroke> bwdKeys = kfm.getDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS); Iterator<AWTKeyStroke> iter; for(iter = fwdKeys.iterator(); iter.hasNext(); ) { System.err.println("FTKL.fwd-keys: "+iter.next()); @@ -112,7 +123,7 @@ public class TestParentingFocusTraversal01AWT extends UITestCase { System.err.println("FTKL.bwd-keys: "+iter.next()); } } - + final Frame frame1 = new Frame("AWT Parent Frame"); final Button cWest = new Button("WEST"); final Button cEast = new Button("EAST"); @@ -130,7 +141,7 @@ public class TestParentingFocusTraversal01AWT extends UITestCase { cWest.addFocusListener(bWestFA); AWTFocusAdapter bEastFA = new AWTFocusAdapter("EAST"); cEast.addFocusListener(bEastFA); - + // Test KeyAdapter NEWTKeyAdapter glWindow1KA = new NEWTKeyAdapter("GLWindow1"); glWindow1.addKeyListener(glWindow1KA); @@ -138,39 +149,42 @@ public class TestParentingFocusTraversal01AWT extends UITestCase { cWest.addKeyListener(bWestKA); AWTKeyAdapter bEastKA = new AWTKeyAdapter("East"); cEast.addKeyListener(bEastKA); - + // demo .. GLEventListener demo1 = new GearsES2(1); setDemoFields(demo1, glWindow1, false); glWindow1.addGLEventListener(demo1); - glWindow1.addKeyListener(new NewtAWTReparentingKeyAdapter(frame1, newtCanvasAWT1, glWindow1)); + glWindow1.addKeyListener(new NewtAWTReparentingKeyAdapter(frame1, newtCanvasAWT1, glWindow1, null)); glWindow1.addKeyListener(new KeyAdapter() { - public void keyTyped(KeyEvent e) { - if(e.getKeyChar()=='c') { + public void keyReleased(KeyEvent e) { + if( !e.isPrintableKey() || e.isAutoRepeat() ) { + return; + } + if(e.getKeyChar()=='c') { System.err.println("Focus Clear"); if(glWindow1.getDelegatedWindow() instanceof DriverClearFocus) { ((DriverClearFocus)glWindow1.getDelegatedWindow()).clearFocus(); } - } else if(e.getKeyChar()=='e') { + } else if(e.getKeyChar()=='e') { System.err.println("Focus East"); try { java.awt.EventQueue.invokeLater(new Runnable() { public void run() { cEast.requestFocusInWindow(); - } + } }); } catch (Exception ex) { ex.printStackTrace(); } - } else if(e.getKeyChar()=='w') { + } else if(e.getKeyChar()=='w') { System.err.println("Focus West"); try { java.awt.EventQueue.invokeLater(new Runnable() { public void run() { cWest.requestFocusInWindow(); - } + } }); } catch (Exception ex) { ex.printStackTrace(); } } - } + } }); GLAnimatorControl animator1 = new Animator(glWindow1); animator1.start(); @@ -182,99 +196,108 @@ public class TestParentingFocusTraversal01AWT extends UITestCase { frame1.add(newtCanvasAWT1, BorderLayout.CENTER); frame1.add(cEast, BorderLayout.EAST); - frame1.setLocation(0, 0); - frame1.setSize(fSize); javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { - frame1.validate(); + frame1.setLocation(0, 0); + frame1.setSize(fSize); + frame1.validate(); frame1.setVisible(true); }}); Assert.assertEquals(true, AWTRobotUtil.waitForVisible(glWindow1, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow1, true)); Assert.assertEquals(newtCanvasAWT1.getNativeWindow(),glWindow1.getParent()); AWTRobotUtil.clearAWTFocus(robot); Assert.assertTrue(AWTRobotUtil.toFrontAndRequestFocus(robot, frame1)); - + Assert.assertEquals(true, animator1.isAnimating()); // Assert.assertEquals(false, animator1.isPaused()); Assert.assertNotNull(animator1.getThread()); - + if(manual) { - Thread.sleep(durationPerTest); + Thread.sleep(durationPerTest); } else { // // initial focus on bWest - // + // AWTRobotUtil.assertRequestFocusAndWait(robot, cWest, cWest, bWestFA, null); Thread.sleep(durationPerTest/numFocus); - + // // forth // - + // bWest -> glWin AWTRobotUtil.keyType(0, robot, java.awt.event.KeyEvent.VK_TAB, cWest, null); - Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(glWindow1, glWindow1FA, bWestFA)); + Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(glWindow1, glWindow1FA, bWestFA)); Assert.assertEquals(true, glWindow1FA.focusGained()); Assert.assertEquals(true, bWestFA.focusLost()); Thread.sleep(durationPerTest/numFocus); - + // glWin -> bEast AWTRobotUtil.keyType(0, robot, java.awt.event.KeyEvent.VK_TAB, glWindow1, null); - Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(cEast, bEastFA, glWindow1FA)); + Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(cEast, bEastFA, glWindow1FA)); Assert.assertEquals(true, bEastFA.focusGained()); Assert.assertEquals(true, glWindow1FA.focusLost()); Thread.sleep(durationPerTest/numFocus); - + // // back (using custom back traversal key 'backspace') // // bEast -> glWin AWTRobotUtil.keyType(0, robot, java.awt.event.KeyEvent.VK_BACK_SPACE, cEast, null); - Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(glWindow1, glWindow1FA, bEastFA)); + Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(glWindow1, glWindow1FA, bEastFA)); Assert.assertEquals(true, glWindow1FA.focusGained()); Assert.assertEquals(true, bEastFA.focusLost()); Thread.sleep(durationPerTest/numFocus); - + AWTRobotUtil.keyType(0, robot, java.awt.event.KeyEvent.VK_BACK_SPACE, glWindow1, null); - Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(cWest, bWestFA, glWindow1FA)); + Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(cWest, bWestFA, glWindow1FA)); Assert.assertEquals(true, bWestFA.focusGained()); Assert.assertEquals(true, glWindow1FA.focusLost()); - Thread.sleep(durationPerTest/numFocus); - - // direct AWT request focus + Thread.sleep(durationPerTest/numFocus); + + System.err.println("Test: Direct NewtCanvasAWT focus"); try { java.awt.EventQueue.invokeAndWait(new Runnable() { public void run() { newtCanvasAWT1.requestFocus(); - } + } }); - } catch (Exception ex) { ex.printStackTrace(); } - Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(glWindow1, glWindow1FA, bWestFA)); + } catch (Exception ex) { ex.printStackTrace(); } + Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(glWindow1, glWindow1FA, bWestFA)); Assert.assertEquals(true, glWindow1FA.focusGained()); Assert.assertEquals(true, bWestFA.focusLost()); Thread.sleep(durationPerTest/numFocus); - - // direct AWT request focus + + System.err.println("Test: Direct AWT Button-West focus"); try { java.awt.EventQueue.invokeAndWait(new Runnable() { public void run() { cWest.requestFocus(); - } + } }); - } catch (Exception ex) { ex.printStackTrace(); } - Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(cWest, bWestFA, glWindow1FA)); + } catch (Exception ex) { ex.printStackTrace(); } + Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(cWest, bWestFA, glWindow1FA)); Assert.assertEquals(true, bWestFA.focusGained()); Assert.assertEquals(true, glWindow1FA.focusLost()); Thread.sleep(durationPerTest/numFocus); - - // direct NEWT request focus + + System.err.println("Test: Direct NEWT-Child request focus"); glWindow1.requestFocus(); - Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(glWindow1, glWindow1FA, bWestFA)); + { + // Short: Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(glWindow1, glWindow1FA, bWestFA)); + // More verbose: + final boolean ok = AWTRobotUtil.waitForFocus(glWindow1, glWindow1FA, bWestFA); + System.err.println("glWindow hasFocus "+glWindow1.hasFocus()); + System.err.println("glWindow1FA "+glWindow1FA); + System.err.println("bWestFA "+bWestFA); + Assert.assertTrue("Did not gain focus", ok); + } Assert.assertEquals(true, glWindow1FA.focusGained()); Assert.assertEquals(true, bWestFA.focusLost()); - Thread.sleep(durationPerTest/numFocus); + Thread.sleep(durationPerTest/numFocus); } - + animator1.stop(); Assert.assertEquals(false, animator1.isAnimating()); Assert.assertEquals(false, animator1.isPaused()); @@ -314,9 +337,11 @@ public class TestParentingFocusTraversal01AWT extends UITestCase { durationPerTest = atoi(args[++i]); } else if(args[i].equals("-manual")) { manual = true; + } else if(args[i].equals("-gl3")) { + forceGL3 = true; } } - String tstname = TestParentingFocusTraversal01AWT.class.getName(); + String tstname = TestParentingFocus03KeyTraversalAWT.class.getName(); /* org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] { tstname, diff --git a/src/test/com/jogamp/opengl/test/junit/newt/ManualScreenMode03NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/mm/ManualScreenMode03aNEWT.java index 29ec443f7..464efa5bb 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/ManualScreenMode03NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/mm/ManualScreenMode03aNEWT.java @@ -26,7 +26,7 @@ * or implied, of JogAmp Community. */ -package com.jogamp.opengl.test.junit.newt; +package com.jogamp.opengl.test.junit.newt.mm; import java.io.IOException; import javax.media.opengl.GLCapabilities; @@ -35,11 +35,12 @@ import javax.media.opengl.GLProfile; import com.jogamp.opengl.util.Animator; import com.jogamp.newt.Display; +import com.jogamp.newt.MonitorDevice; import com.jogamp.newt.NewtFactory; import com.jogamp.newt.Screen; -import com.jogamp.newt.ScreenMode; +import com.jogamp.newt.MonitorMode; import com.jogamp.newt.opengl.GLWindow; -import com.jogamp.newt.util.ScreenModeUtil; +import com.jogamp.newt.util.MonitorModeUtil; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.util.UITestCase; import java.util.List; @@ -50,7 +51,7 @@ import javax.media.nativewindow.util.Dimension; * which shall reset the ScreenMode to it's original state * when the application exists (normal or ctrl-c). */ -public class ManualScreenMode03NEWT extends UITestCase { +public class ManualScreenMode03aNEWT extends UITestCase { static int waitTime = 7000; // 1 sec static GLWindow createWindow(Screen screen, GLCapabilities caps, int width, int height, boolean onscreen, boolean undecorated) { @@ -72,8 +73,8 @@ public class ManualScreenMode03NEWT extends UITestCase { Screen screen = NewtFactory.createScreen(display, 0); // screen 0 GLWindow window = createWindow(screen, caps, width, height, true /* onscreen */, false /* undecorated */); - List<ScreenMode> screenModes = screen.getScreenModes(); - if(null==screenModes) { + List<MonitorMode> monitorModes = screen.getMonitorModes(); + if(null==monitorModes) { // no support .. System.err.println("Your platform has no ScreenMode change support, sorry"); return; @@ -81,18 +82,21 @@ public class ManualScreenMode03NEWT extends UITestCase { Animator animator = new Animator(window); animator.start(); - ScreenMode smCurrent = screen.getCurrentScreenMode(); - ScreenMode smOrig = screen.getOriginalScreenMode(); - System.err.println("[0] current/orig: "+smCurrent); + MonitorDevice monitor = window.getMainMonitor(); + MonitorMode mmCurrent = monitor.queryCurrentMode(); + MonitorMode mmOrig = monitor.getOriginalMode(); + System.err.println("[0] orig : "+mmOrig); + System.err.println("[0] current: "+mmCurrent); - screenModes = ScreenModeUtil.filterByRate(screenModes, smOrig.getMonitorMode().getRefreshRate()); - screenModes = ScreenModeUtil.filterByRotation(screenModes, 0); - screenModes = ScreenModeUtil.filterByResolution(screenModes, new Dimension(801, 601)); - screenModes = ScreenModeUtil.getHighestAvailableBpp(screenModes); + monitorModes = MonitorModeUtil.filterByFlags(monitorModes, 0); // no interlace, double-scan etc + monitorModes = MonitorModeUtil.filterByRotation(monitorModes, 0); + monitorModes = MonitorModeUtil.filterByResolution(monitorModes, new Dimension(801, 601)); + monitorModes = MonitorModeUtil.filterByRate(monitorModes, mmOrig.getRefreshRate()); + monitorModes = MonitorModeUtil.getHighestAvailableBpp(monitorModes); - ScreenMode sm = (ScreenMode) screenModes.get(0); - System.err.println("[0] set current: "+sm); - screen.setCurrentScreenMode(sm); + MonitorMode mm = (MonitorMode) monitorModes.get(0); + System.err.println("[0] set current: "+mm); + monitor.setCurrentMode(mm); System.err.print("[0] post setting .. wait <"); try { @@ -104,7 +108,7 @@ public class ManualScreenMode03NEWT extends UITestCase { } public static void main(String args[]) throws IOException { - ManualScreenMode03NEWT t = new ManualScreenMode03NEWT(); + ManualScreenMode03aNEWT t = new ManualScreenMode03aNEWT(); t.run(); } } diff --git a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00aNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00aNEWT.java new file mode 100644 index 000000000..93e005b53 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00aNEWT.java @@ -0,0 +1,217 @@ +/** + * 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.mm; + +import java.io.IOException; +import javax.media.nativewindow.NativeWindowFactory; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.common.util.ArrayHashSet; +import com.jogamp.newt.Display; +import com.jogamp.newt.MonitorDevice; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.MonitorMode; +import com.jogamp.newt.Screen; +import com.jogamp.newt.util.MonitorModeUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; + +import java.util.Iterator; +import java.util.List; +import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.DimensionImmutable; +import javax.media.nativewindow.util.Rectangle; +import javax.media.nativewindow.util.SurfaceSize; +import javax.media.opengl.GLProfile; + +import jogamp.newt.MonitorDeviceImpl; +import jogamp.newt.MonitorModeProps; + +/** + * Validating consistency of MonitorMode data from Screen (all modes) + * and from a particular MonitorDevice. + * <p> + * Also validates the descending order of the given MonitorMode lists. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestScreenMode00aNEWT extends UITestCase { + static int screenIdx = 0; + static int width, height; + + static int waitTimeShort = 4; //1 sec + static int waitTimeLong = 6; //6 sec + + + + @BeforeClass + public static void initClass() { + setResetXRandRIfX11AfterClass(); + GLProfile.initSingleton(); // hack to initialize GL for BCM_IV (Rasp.Pi) + NativeWindowFactory.initSingleton(); + width = 640; + height = 480; + } + + @Test + public void testScreenModeInfo00() throws InterruptedException { + final DimensionImmutable res = new Dimension(640, 480); + final SurfaceSize surfsz = new SurfaceSize(res, 32); + final MonitorMode modeOut = new MonitorMode(surfsz, 60.0f, 0, 0); + System.err.println("00 out: "+modeOut); + final MonitorModeProps.Cache cache = new MonitorModeProps.Cache(); + cache.monitorModes.add(modeOut); + { + final int[] props = MonitorModeProps.streamOutMonitorMode(modeOut); + final MonitorMode modeIn = MonitorModeProps.streamInMonitorMode(null, cache, props, 0); + System.err.println("00 in : "+modeIn); + + Assert.assertEquals(modeOut.getSurfaceSize().getResolution(), modeIn.getSurfaceSize().getResolution()); + + Assert.assertEquals(modeOut.getSurfaceSize(), modeIn.getSurfaceSize()); + + Assert.assertEquals(modeOut.hashCode(), modeIn.hashCode()); + + Assert.assertEquals(modeOut, modeIn); + } + + final DimensionImmutable sizeMM = new Dimension(50, 50); + final Rectangle viewport = new Rectangle(0, 0, 1920, 1080); + final ArrayHashSet<MonitorMode> supportedModes = new ArrayHashSet<MonitorMode>(); + supportedModes.add(modeOut); + final MonitorDevice monOut = new MonitorDeviceImpl(null, -1, sizeMM, viewport, modeOut, supportedModes); + System.err.println("01 out : "+monOut); + cache.monitorDevices.add(monOut); + { + final int[] props = MonitorModeProps.streamOutMonitorDevice(monOut); + final MonitorDevice monIn = MonitorModeProps.streamInMonitorDevice(null, cache, null, props, 0); + System.err.println("01 in : "+monIn); + + Assert.assertEquals(monOut.getCurrentMode(), monOut.getOriginalMode()); + Assert.assertEquals(monOut.getSupportedModes(), monIn.getSupportedModes()); + Assert.assertEquals(monOut.getViewport(), monIn.getViewport()); + Assert.assertEquals(monOut.getOriginalMode(), monIn.getOriginalMode()); + Assert.assertEquals(monOut.getCurrentMode(), monIn.getCurrentMode()); + Assert.assertEquals(monOut.hashCode(), monIn.hashCode()); + Assert.assertEquals(monOut, monIn); + } + } + + @Test + public void testScreenModeInfo01() throws InterruptedException { + Display dpy = NewtFactory.createDisplay(null); + Screen screen = NewtFactory.createScreen(dpy, screenIdx); + screen.addReference(); + Assert.assertEquals(true,screen.isNativeValid()); + Assert.assertEquals(true,screen.getDisplay().isNativeValid()); + System.err.println("Screen: "+screen.toString()); + List<MonitorMode> allMonitorModes = screen.getMonitorModes(); + Assert.assertTrue(allMonitorModes.size()>0); + { + int i=0; + MonitorMode mmPre = null; + for(Iterator<MonitorMode> iMode=allMonitorModes.iterator(); iMode.hasNext(); i++) { + final MonitorMode mm = iMode.next(); + System.err.println(String.format("All-0[%03d]: %s", i, mm)); + if( null != mmPre ) { + Assert.assertTrue("Wrong order", mmPre.compareTo(mm) >= 0); + } + mmPre = mm; + } + } + MonitorModeUtil.sort(allMonitorModes, true /* ascendingOrder*/); + { + int i=0; + MonitorMode mmPre = null; + for(Iterator<MonitorMode> iMode=allMonitorModes.iterator(); iMode.hasNext(); i++) { + final MonitorMode mm = iMode.next(); + System.err.println(String.format("All-1[%03d]: %s", i, mm)); + if( null != mmPre ) { + Assert.assertTrue("Wrong order", mmPre.compareTo(mm) <= 0); + } + mmPre = mm; + } + } + + List<MonitorDevice> monitors = screen.getMonitorDevices(); + Assert.assertTrue(monitors.size()>0); + int j=0; + for(Iterator<MonitorDevice> iMonitor=monitors.iterator(); iMonitor.hasNext(); j++) { + MonitorDevice monitor = iMonitor.next(); + System.err.println(j+": "+monitor); + List<MonitorMode> modes = monitor.getSupportedModes(); + Assert.assertTrue(modes.size()>0); + int i=0; + MonitorMode mmPre = null; + for(Iterator<MonitorMode> iMode=modes.iterator(); iMode.hasNext(); i++) { + final MonitorMode mm = iMode.next(); + System.err.println(String.format("[%02d][%03d]: %s", j, i, mm)); + if( null != mmPre ) { + Assert.assertTrue("Wrong order", mmPre.compareTo(mm) >= 0); + } + mmPre = mm; + } + Assert.assertTrue(allMonitorModes.containsAll(modes)); + + MonitorMode sm_o = monitor.getOriginalMode(); + Assert.assertNotNull(sm_o); + MonitorMode sm_c = monitor.queryCurrentMode(); + System.err.println("[0] orig : "+sm_o); + System.err.println("[0] current: "+sm_c); + Assert.assertNotNull(sm_c); + Assert.assertEquals(sm_o, sm_c); + } + + screen.removeReference(); + + Assert.assertEquals(false,screen.isNativeValid()); + Assert.assertEquals(false,screen.getDisplay().isNativeValid()); + } + + static int atoi(String a) { + try { + return Integer.parseInt(a); + } catch (Exception ex) { throw new RuntimeException(ex); } + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-screen")) { + i++; + screenIdx = atoi(args[i]); + } + } + String tstname = TestScreenMode00aNEWT.class.getName(); + org.junit.runner.JUnitCore.main(tstname); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode00bNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00bNEWT.java index e9e66da2c..69f19c258 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode00bNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00bNEWT.java @@ -26,7 +26,7 @@ * or implied, of JogAmp Community. */ -package com.jogamp.opengl.test.junit.newt; +package com.jogamp.opengl.test.junit.newt.mm; import java.io.IOException; import javax.media.nativewindow.NativeWindowFactory; @@ -34,13 +34,17 @@ import javax.media.nativewindow.NativeWindowFactory; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import com.jogamp.newt.Display; +import com.jogamp.newt.MonitorDevice; import com.jogamp.newt.NewtFactory; import com.jogamp.newt.Screen; -import com.jogamp.newt.ScreenMode; +import com.jogamp.newt.MonitorMode; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.util.Animator; @@ -49,6 +53,11 @@ import java.util.List; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesImmutable; +/** + * Queries the current MonitorMode 50 times, + * stressing a possible race condition. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestScreenMode00bNEWT extends UITestCase { static int width, height; @@ -57,7 +66,8 @@ public class TestScreenMode00bNEWT extends UITestCase { @BeforeClass public static void initClass() { - NativeWindowFactory.initSingleton(true); + setResetXRandRIfX11AfterClass(); + NativeWindowFactory.initSingleton(); width = 640; height = 480; } @@ -81,23 +91,24 @@ public class TestScreenMode00bNEWT extends UITestCase { Assert.assertEquals(true,screen.isNativeValid()); Assert.assertEquals(true,display.isNativeValid()); - List<ScreenMode> screenModes = screen.getScreenModes(); + List<MonitorMode> screenModes = screen.getMonitorModes(); Assert.assertTrue(screenModes.size()>0); int i=0; - for(Iterator<ScreenMode> iter=screenModes.iterator(); iter.hasNext(); i++) { + for(Iterator<MonitorMode> iter=screenModes.iterator(); iter.hasNext(); i++) { System.err.println(i+": "+iter.next()); } - ScreenMode sm_o = screen.getOriginalScreenMode(); + MonitorDevice monitor = window.getMainMonitor(); + MonitorMode mm_o = monitor.getOriginalMode(); - 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); + Assert.assertNotNull(mm_o); + MonitorMode mm_c = monitor.queryCurrentMode(); + Assert.assertNotNull(mm_c); + System.err.println("orig: "+mm_o); + System.err.println("curr: "+mm_c); for(i=0; i<50; i++) { - sm_c = screen.getCurrentScreenMode(); - Assert.assertNotNull(sm_c); + mm_c = monitor.queryCurrentMode(); + Assert.assertNotNull(mm_c); System.err.print("."+i); } System.err.println("!"); @@ -108,6 +119,7 @@ public class TestScreenMode00bNEWT extends UITestCase { Assert.assertEquals(false,window.isVisible()); Assert.assertEquals(false,window.isNativeValid()); + Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false)); Assert.assertEquals(false,screen.isNativeValid()); Assert.assertEquals(false,display.isNativeValid()); } diff --git a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00cNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00cNEWT.java new file mode 100644 index 000000000..de856e569 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00cNEWT.java @@ -0,0 +1,247 @@ +/** + * 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.mm; + +import java.io.IOException; +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 org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.Display; +import com.jogamp.newt.MonitorDevice; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Screen; +import com.jogamp.newt.Window; +import com.jogamp.newt.MonitorMode; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.newt.util.MonitorModeUtil; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; + +import java.util.List; + +import javax.media.nativewindow.NativeWindowFactory; +import javax.media.nativewindow.util.Dimension; + +/** + * Tests X11 XRandR MonitorMode reset via {@link UITestCase#resetXRandRIfX11()}. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestScreenMode00cNEWT extends UITestCase { + static boolean manualTest = false; + static GLProfile glp; + static int width, height; + + static final int waitTimeShort = 2000; + static long duration = waitTimeShort; + + @BeforeClass + public static void initClass() { + setResetXRandRIfX11AfterClass(); + NativeWindowFactory.initSingleton(); + if( !manualTest || NativeWindowFactory.TYPE_X11 != NativeWindowFactory.getNativeWindowType(true) ) { + setTestSupported(false); + return; + } + 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) throws InterruptedException { + if(null!=window) { + window.destroy(); + Assert.assertTrue(AWTRobotUtil.waitForRealized(window, false)); + } + } + + @Test + public void testScreenModeChange01() throws InterruptedException { + Thread.sleep(waitTimeShort); + + final GLCapabilities caps = new GLCapabilities(glp); + Assert.assertNotNull(caps); + final Display display = NewtFactory.createDisplay(null); // local display + Assert.assertNotNull(display); + final Screen screen = NewtFactory.createScreen(display, 0); // screen 0 + Assert.assertNotNull(screen); + final Window window0 = createWindow(screen, caps, "win0", 0, 0, width, height); + Assert.assertNotNull(window0); + + final List<MonitorMode> allMonitorModes = screen.getMonitorModes(); + Assert.assertTrue(allMonitorModes.size()>0); + if(allMonitorModes.size()==1) { + // no support .. + System.err.println("Your platform has no MonitorMode change support (all), sorry"); + destroyWindow(window0); + return; + } + + final MonitorDevice monitor = screen.getMonitorDevices().get(0); + + List<MonitorMode> monitorModes = monitor.getSupportedModes(); + Assert.assertTrue(monitorModes.size()>0); + if(monitorModes.size()==1) { + // no support .. + System.err.println("Your platform has no MonitorMode change support (monitor), sorry"); + destroyWindow(window0); + return; + } + Assert.assertTrue(allMonitorModes.containsAll(monitorModes)); + + final MonitorMode mmSet0 = monitor.queryCurrentMode(); + Assert.assertNotNull(mmSet0); + final MonitorMode mmOrig = monitor.getOriginalMode(); + Assert.assertNotNull(mmOrig); + System.err.println("[0] orig : "+mmOrig); + System.err.println("[0] current: "+mmSet0); + Assert.assertEquals(mmSet0, mmOrig); + + + monitorModes = MonitorModeUtil.filterByFlags(monitorModes, 0); // no interlace, double-scan etc + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + monitorModes = MonitorModeUtil.filterByRotation(monitorModes, 0); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + monitorModes = MonitorModeUtil.filterByResolution(monitorModes, new Dimension(801, 601)); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + monitorModes = MonitorModeUtil.filterByRate(monitorModes, mmOrig.getRefreshRate()); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + + monitorModes = MonitorModeUtil.getHighestAvailableBpp(monitorModes); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + + // set mode + { + MonitorMode mm = monitorModes.get(0); + System.err.println("[0] set current: "+mm); + final boolean smOk = monitor.setCurrentMode(mm); + MonitorMode mmCurrent = monitor.getCurrentMode(); + System.err.println("[0] has current: "+mmCurrent+", changeOK "+smOk); + Assert.assertTrue(monitor.isModeChangedByUs()); + Assert.assertEquals(mm, mmCurrent); + Assert.assertNotSame(mmOrig, mmCurrent); + Assert.assertEquals(mmCurrent, monitor.queryCurrentMode()); + Assert.assertTrue(smOk); + } + + Thread.sleep(duration); + + Assert.assertEquals(true,display.isNativeValid()); + Assert.assertEquals(true,screen.isNativeValid()); + Assert.assertEquals(true,window0.isNativeValid()); + Assert.assertEquals(true,window0.isVisible()); + + // WARNING: See note in 'UITestCase.resetXRandRIfX11();' + UITestCase.resetXRandRIfX11(); + System.err.println("XRandR Reset :"+monitor.queryCurrentMode()); + validateScreenModeReset0(mmOrig); + + destroyWindow(window0); + + Thread.sleep(waitTimeShort); + validateScreenModeReset(mmOrig); + } + + void validateScreenModeReset0(final MonitorMode mmOrig) { + final Display display = NewtFactory.createDisplay(null); // local display + Assert.assertNotNull(display); + final Screen screen = NewtFactory.createScreen(display, 0); // screen 0 + Assert.assertNotNull(screen); + screen.addReference(); + Assert.assertEquals(true,display.isNativeValid()); + Assert.assertEquals(true,screen.isNativeValid()); + + final MonitorDevice monitor = screen.getMonitorDevices().get(0); + Assert.assertEquals(mmOrig, monitor.queryCurrentMode()); + + screen.removeReference(); + } + void validateScreenModeReset(final MonitorMode mmOrig) { + final Display display = NewtFactory.createDisplay(null); // local display + Assert.assertNotNull(display); + final Screen screen = NewtFactory.createScreen(display, 0); // screen 0 + Assert.assertNotNull(screen); + Assert.assertEquals(false,display.isNativeValid()); + Assert.assertEquals(false,screen.isNativeValid()); + screen.addReference(); + Assert.assertEquals(true,display.isNativeValid()); + Assert.assertEquals(true,screen.isNativeValid()); + + final MonitorDevice monitor = screen.getMonitorDevices().get(0); + Assert.assertEquals(mmOrig, monitor.getCurrentMode()); + + screen.removeReference(); + Assert.assertEquals(false,display.isNativeValid()); + Assert.assertEquals(false,screen.isNativeValid()); + } + + public static void main(String args[]) throws IOException { + manualTest = true; + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } + } + String tstname = TestScreenMode00cNEWT.class.getName(); + org.junit.runner.JUnitCore.main(tstname); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01aNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01aNEWT.java new file mode 100644 index 000000000..0f3dbeefc --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01aNEWT.java @@ -0,0 +1,228 @@ +/** + * 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.mm; + +import java.io.IOException; +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 org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.Display; +import com.jogamp.newt.MonitorDevice; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Screen; +import com.jogamp.newt.Window; +import com.jogamp.newt.MonitorMode; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.newt.util.MonitorModeUtil; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; + +import java.util.List; +import javax.media.nativewindow.util.Dimension; + +/** + * <p> + * Tests MonitorMode reset, by destroying the last Screen (reference), + * i.e. the original MonitorMode should get reinstated! + * </p> + * <p> + * Documents remedy B) for NV RANDR/GL bug + * </p> + * + * @see TestScreenMode01dNEWT#cleanupGL() + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestScreenMode01aNEWT extends UITestCase { + static GLProfile glp; + static int width, height; + + static int waitTimeShort = 2000; + static int waitTimeLong = 2000; + + @BeforeClass + public static void initClass() { + setResetXRandRIfX11AfterClass(); + 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) throws InterruptedException { + if(null!=window) { + window.destroy(); + Assert.assertTrue(AWTRobotUtil.waitForRealized(window, false)); + } + } + + @Test + public void testScreenModeChange01() throws InterruptedException { + Thread.sleep(waitTimeShort); + + final GLCapabilities caps = new GLCapabilities(glp); + Assert.assertNotNull(caps); + final Display display = NewtFactory.createDisplay(null); // local display + Assert.assertNotNull(display); + final Screen screen = NewtFactory.createScreen(display, 0); // screen 0 + Assert.assertNotNull(screen); + final Window window0 = createWindow(screen, caps, "win0", 0, 0, width, height); + Assert.assertNotNull(window0); + + final List<MonitorMode> allMonitorModes = screen.getMonitorModes(); + Assert.assertTrue(allMonitorModes.size()>0); + if(allMonitorModes.size()==1) { + // no support .. + System.err.println("Your platform has no MonitorMode change support (all), sorry"); + destroyWindow(window0); + return; + } + + final MonitorDevice monitor = screen.getMonitorDevices().get(0); + + List<MonitorMode> monitorModes = monitor.getSupportedModes(); + Assert.assertTrue(monitorModes.size()>0); + if(monitorModes.size()==1) { + // no support .. + System.err.println("Your platform has no MonitorMode change support (monitor), sorry"); + destroyWindow(window0); + return; + } + Assert.assertTrue(allMonitorModes.containsAll(monitorModes)); + + final MonitorMode mmSet0 = monitor.queryCurrentMode(); + Assert.assertNotNull(mmSet0); + final MonitorMode mmOrig = monitor.getOriginalMode(); + Assert.assertNotNull(mmOrig); + System.err.println("[0] orig : "+mmOrig); + System.err.println("[0] current: "+mmSet0); + Assert.assertEquals(mmSet0, mmOrig); + + + monitorModes = MonitorModeUtil.filterByFlags(monitorModes, 0); // no interlace, double-scan etc + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + monitorModes = MonitorModeUtil.filterByRotation(monitorModes, 0); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + monitorModes = MonitorModeUtil.filterByResolution(monitorModes, new Dimension(801, 601)); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + monitorModes = MonitorModeUtil.filterByRate(monitorModes, mmOrig.getRefreshRate()); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + + monitorModes = MonitorModeUtil.getHighestAvailableBpp(monitorModes); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + + // set mode + { + MonitorMode mm = monitorModes.get(0); + System.err.println("[0] set current: "+mm); + final boolean smOk = monitor.setCurrentMode(mm); + MonitorMode mmCurrent = monitor.getCurrentMode(); + System.err.println("[0] has current: "+mmCurrent+", changeOK "+smOk); + Assert.assertTrue(monitor.isModeChangedByUs()); + Assert.assertEquals(mm, mmCurrent); + Assert.assertNotSame(mmOrig, mmCurrent); + Assert.assertEquals(mmCurrent, monitor.queryCurrentMode()); + Assert.assertTrue(smOk); + } + + Thread.sleep(waitTimeShort); + + Assert.assertEquals(true,display.isNativeValid()); + Assert.assertEquals(true,screen.isNativeValid()); + Assert.assertEquals(true,window0.isNativeValid()); + Assert.assertEquals(true,window0.isVisible()); + + // Auto reset by destruction! + destroyWindow(window0); + + Assert.assertEquals(false,window0.isVisible()); + Assert.assertEquals(false,window0.isNativeValid()); + Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false)); + Assert.assertEquals(false,screen.isNativeValid()); + Assert.assertEquals(false,display.isNativeValid()); + + Thread.sleep(waitTimeShort); + + validateScreenModeReset(mmOrig, 0); + } + + void validateScreenModeReset(final MonitorMode mmOrig, int mmIdx) { + final Display display = NewtFactory.createDisplay(null); // local display + Assert.assertNotNull(display); + final Screen screen = NewtFactory.createScreen(display, 0); // screen 0 + Assert.assertNotNull(screen); + Assert.assertEquals(false,display.isNativeValid()); + Assert.assertEquals(false,screen.isNativeValid()); + screen.addReference(); + Assert.assertEquals(true,display.isNativeValid()); + Assert.assertEquals(true,screen.isNativeValid()); + + final MonitorDevice monitor = screen.getMonitorDevices().get(0); + Assert.assertEquals(mmOrig, monitor.getCurrentMode()); + + screen.removeReference(); + Assert.assertEquals(false,display.isNativeValid()); + Assert.assertEquals(false,screen.isNativeValid()); + } + + public static void main(String args[]) throws IOException { + String tstname = TestScreenMode01aNEWT.class.getName(); + org.junit.runner.JUnitCore.main(tstname); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01bNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01bNEWT.java new file mode 100644 index 000000000..4804a753c --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01bNEWT.java @@ -0,0 +1,267 @@ +/** + * Copyright 2013 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.mm; + +import java.io.IOException; +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 org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.Display; +import com.jogamp.newt.MonitorDevice; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Screen; +import com.jogamp.newt.Window; +import com.jogamp.newt.MonitorMode; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.newt.util.MonitorModeUtil; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; + +import java.util.List; +import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.RectangleImmutable; + +/** + * Mode change on separate monitors .. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestScreenMode01bNEWT extends UITestCase { + static GLProfile glp; + static int width, height; + + static long waitTimeShort = 2000; + static long duration = 6000; + + @BeforeClass + public static void initClass() { + setResetXRandRIfX11AfterClass(); + width = 200; + height = 200; + glp = GLProfile.getDefault(); + } + + @AfterClass + public static void releaseClass() throws InterruptedException { + Thread.sleep(waitTimeShort); + } + + static GLWindow createWindow(Screen screen, GLCapabilities caps, String name, int x, int y, int width, int height) throws InterruptedException { + 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); + final long t0 = System.currentTimeMillis(); + window.setVisible(true); + System.err.println("Time for visible/pos: "+(System.currentTimeMillis()-t0)+" ms"); + return window; + } + + static void destroyWindow(Window window) throws InterruptedException { + if(null!=window) { + window.destroy(); + Assert.assertTrue(AWTRobotUtil.waitForRealized(window, false)); + } + } + + @Test + public void testScreenModeChangeSingleQ1() throws InterruptedException { + final Display display = NewtFactory.createDisplay(null); // local display + Assert.assertNotNull(display); + final Screen screen = NewtFactory.createScreen(display, 0); // screen 0 + Assert.assertNotNull(screen); + screen.addReference(); // trigger creation + try { + RectangleImmutable monitorVp = screen.getMonitorDevices().get(0).getViewport(); + testScreenModeChangeImpl(screen, monitorVp.getX(), monitorVp.getY()); + } finally { + screen.removeReference(); + Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false)); + } + } + + @Test + public void testScreenModeChangeSingleQ2() throws InterruptedException { + final Display display = NewtFactory.createDisplay(null); // local display + Assert.assertNotNull(display); + final Screen screen = NewtFactory.createScreen(display, 0); // screen 0 + Assert.assertNotNull(screen); + screen.addReference(); // trigger creation + try { + if( 2 > screen.getMonitorDevices().size() ) { + System.err.println("Test Disabled (1): Monitor count < 2: "+screen); + return; + } + RectangleImmutable monitorVp = screen.getMonitorDevices().get(1).getViewport(); + testScreenModeChangeImpl(screen, monitorVp.getX(), monitorVp.getY()); + } finally { + screen.removeReference(); + Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false)); + } + } + + void testScreenModeChangeImpl(final Screen screen, int xpos, int ypos) throws InterruptedException { + Thread.sleep(waitTimeShort); + + final GLCapabilities caps = new GLCapabilities(glp); + Assert.assertNotNull(caps); + final Display display = screen.getDisplay(); + System.err.println("Test.0: Window screen: "+screen); + + System.err.println("Test.0: Window bounds (pre): "+xpos+"/"+ypos+" "+width+"x"+height+" within "+screen.getViewport()); + + GLWindow window0 = createWindow(screen, caps, "win0", xpos, ypos, width, height); + Assert.assertNotNull(window0); + System.err.println("Test.0: Window bounds: "+window0.getX()+"/"+window0.getY()+" "+window0.getWidth()+"x"+window0.getHeight()+" within "+screen.getViewport()); + + final Animator anim = new Animator(window0); + anim.start(); + + List<MonitorMode> allMonitorModes = screen.getMonitorModes(); + Assert.assertTrue(allMonitorModes.size()>0); + if(allMonitorModes.size()==1) { + // no support .. + System.err.println("Your platform has no MonitorMode change support (all), sorry"); + destroyWindow(window0); + return; + } + + MonitorDevice monitor = window0.getMainMonitor(); + System.err.println("Test.0: Window monitor: "+monitor); + + List<MonitorMode> monitorModes = monitor.getSupportedModes(); + Assert.assertTrue(monitorModes.size()>0); + if(monitorModes.size()==1) { + // no support .. + System.err.println("Your platform has no MonitorMode change support (monitor), sorry"); + destroyWindow(window0); + return; + } + Assert.assertTrue(allMonitorModes.containsAll(monitorModes)); + + MonitorMode mmCurrent = monitor.getCurrentMode(); + Assert.assertNotNull(mmCurrent); + MonitorMode mmOrig = monitor.getOriginalMode(); + Assert.assertNotNull(mmOrig); + System.err.println("[0] orig : "+mmOrig); + System.err.println("[0] current: "+mmCurrent); + Assert.assertEquals(mmCurrent, mmOrig); + + monitorModes = MonitorModeUtil.filterByFlags(monitorModes, 0); // no interlace, double-scan etc + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + monitorModes = MonitorModeUtil.filterByRotation(monitorModes, 0); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + monitorModes = MonitorModeUtil.filterByResolution(monitorModes, new Dimension(801, 601)); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + monitorModes = MonitorModeUtil.filterByRate(monitorModes, mmOrig.getRefreshRate()); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + + monitorModes = MonitorModeUtil.getHighestAvailableBpp(monitorModes); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + + // set mode + { + MonitorMode mm = monitorModes.get(0); + System.err.println("[0] set current: "+mm); + final boolean smOk = monitor.setCurrentMode(mm); + mmCurrent = monitor.getCurrentMode(); + System.err.println("[0] has current: "+mmCurrent+", changeOK "+smOk); + Assert.assertTrue(monitor.isModeChangedByUs()); + Assert.assertEquals(mm, mmCurrent); + Assert.assertNotSame(mmOrig, mmCurrent); + Assert.assertEquals(mmCurrent, monitor.queryCurrentMode()); + Assert.assertTrue(smOk); + } + + System.err.println("Test.1: Window screen: "+screen); + System.err.println("Test.1: Window bounds: "+window0.getX()+"/"+window0.getY()+" "+window0.getWidth()+"x"+window0.getHeight()+" within "+screen.getViewport()); + System.err.println("Test.1: Window monitor: "+window0.getMainMonitor()); + + Thread.sleep(duration); + + Assert.assertEquals(true,display.isNativeValid()); + Assert.assertEquals(true,screen.isNativeValid()); + Assert.assertEquals(true,window0.isNativeValid()); + Assert.assertEquals(true,window0.isVisible()); + + // manual restore! + { + System.err.println("[1] set orig: "+mmOrig); + final boolean smOk = monitor.setCurrentMode(mmOrig); + mmCurrent = monitor.getCurrentMode(); + System.err.println("[1] has orig?: "+mmCurrent+", changeOK "+smOk); + Assert.assertFalse(monitor.isModeChangedByUs()); + Assert.assertEquals(mmOrig, mmCurrent); + Assert.assertTrue(smOk); + } + + System.err.println("Test.2: Window screen: "+screen); + System.err.println("Test.2: Window bounds: "+window0.getX()+"/"+window0.getY()+" "+window0.getWidth()+"x"+window0.getHeight()+" within "+screen.getViewport()); + System.err.println("Test.2: Window monitor: "+window0.getMainMonitor()); + + Thread.sleep(duration); + anim.stop(); + destroyWindow(window0); + + Assert.assertEquals(false,window0.isVisible()); + Assert.assertEquals(false,window0.isNativeValid()); + Assert.assertEquals(true,display.isNativeValid()); + Assert.assertEquals(true,screen.isNativeValid()); + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } + } + String tstname = TestScreenMode01bNEWT.class.getName(); + org.junit.runner.JUnitCore.main(tstname); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01cNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01cNEWT.java new file mode 100644 index 000000000..db6360a19 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01cNEWT.java @@ -0,0 +1,259 @@ +/** + * Copyright 2013 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.mm; + +import java.io.IOException; +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 org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.Display; +import com.jogamp.newt.MonitorDevice; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Screen; +import com.jogamp.newt.Window; +import com.jogamp.newt.MonitorMode; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; + +import java.util.ArrayList; +import java.util.List; +import javax.media.nativewindow.util.Rectangle; +import javax.media.nativewindow.util.RectangleImmutable; + +/** + * Fullscreen on separate monitors, incl. spanning across multiple monitors. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestScreenMode01cNEWT extends UITestCase { + static GLProfile glp; + static int width, height; + + static long waitTimeShort = 2000; + static long duration = 4000; + + @BeforeClass + public static void initClass() { + setResetXRandRIfX11AfterClass(); + width = 200; + height = 200; + glp = GLProfile.getDefault(); + } + + @AfterClass + public static void releaseClass() throws InterruptedException { + Thread.sleep(waitTimeShort); + } + + static GLWindow createWindow(Screen screen, GLCapabilities caps, String name, int x, int y, int width, int height) throws InterruptedException { + 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); + final long t0 = System.currentTimeMillis(); + window.setVisible(true); + System.err.println("Time for visible/pos: "+(System.currentTimeMillis()-t0)+" ms"); + return window; + } + + static void destroyWindow(Window window) throws InterruptedException { + if(null!=window) { + window.destroy(); + Assert.assertTrue(AWTRobotUtil.waitForRealized(window, false)); + } + } + + @Test + public void testScreenFullscreenSingleQ1() throws InterruptedException { + final Display display = NewtFactory.createDisplay(null); // local display + Assert.assertNotNull(display); + final Screen screen = NewtFactory.createScreen(display, 0); // screen 0 + Assert.assertNotNull(screen); + screen.addReference(); // trigger creation + try { + RectangleImmutable monitorVp = screen.getMonitorDevices().get(0).getViewport(); + testScreenFullscreenImpl(screen, monitorVp.getX(), monitorVp.getY(), false, null); + } finally { + screen.removeReference(); + Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false)); + } + } + + @Test + public void testScreenFullscreenSingleQ2() throws InterruptedException { + final Display display = NewtFactory.createDisplay(null); // local display + Assert.assertNotNull(display); + final Screen screen = NewtFactory.createScreen(display, 0); // screen 0 + Assert.assertNotNull(screen); + screen.addReference(); // trigger creation + try { + if( 2 > screen.getMonitorDevices().size() ) { + System.err.println("Test Disabled (1): Monitor count < 2: "+screen); + return; + } + RectangleImmutable monitorVp = screen.getMonitorDevices().get(1).getViewport(); + testScreenFullscreenImpl(screen, monitorVp.getX(), monitorVp.getY(), false, null); + } finally { + screen.removeReference(); + Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false)); + } + } + + @Test + public void testScreenFullscreenSpanQ1Q2() throws InterruptedException { + final Display display = NewtFactory.createDisplay(null); // local display + Assert.assertNotNull(display); + final Screen screen = NewtFactory.createScreen(display, 0); // screen 0 + Assert.assertNotNull(screen); + screen.addReference(); // trigger creation + try { + final int crtCount = screen.getMonitorDevices().size(); + if( 2 >= crtCount ) { + System.err.println("Test Disabled (2): Spanning monitor count "+2+" >= screen monitor count: "+screen); + return; + } + final ArrayList<MonitorDevice> monitors = new ArrayList<MonitorDevice>(); + monitors.add(screen.getMonitorDevices().get(0)); // Q1 + monitors.add(screen.getMonitorDevices().get(1)); // Q2 + RectangleImmutable monitorVp = screen.getMonitorDevices().get(0).getViewport(); + testScreenFullscreenImpl(screen, monitorVp.getX()+50, monitorVp.getY()+50, true, monitors); + } finally { + screen.removeReference(); + Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false)); + } + } + + @Test + public void testScreenFullscreenSpanALL() throws InterruptedException { + final Display display = NewtFactory.createDisplay(null); // local display + Assert.assertNotNull(display); + final Screen screen = NewtFactory.createScreen(display, 0); // screen 0 + Assert.assertNotNull(screen); + screen.addReference(); // trigger creation + try { + if( 2 > screen.getMonitorDevices().size() ) { + System.err.println("Test Disabled (3): Monitor count < 2: "+screen); + return; + } + RectangleImmutable monitorVp = screen.getMonitorDevices().get(1).getViewport(); + testScreenFullscreenImpl(screen, monitorVp.getX()-50, monitorVp.getY()+50, true, null); + } finally { + screen.removeReference(); + Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false)); + } + } + + void testScreenFullscreenImpl(final Screen screen, int xpos, int ypos, boolean spanAcrossMonitors, List<MonitorDevice> monitors) throws InterruptedException { + Thread.sleep(waitTimeShort); + + final GLCapabilities caps = new GLCapabilities(glp); + Assert.assertNotNull(caps); + final Display display = screen.getDisplay(); + + System.err.println("Test.0: Window screen: "+screen); + + System.err.println("Test.0: Window bounds (pre): "+xpos+"/"+ypos+" "+width+"x"+height+" within "+screen.getViewport()); + + GLWindow window0 = createWindow(screen, caps, "win0", xpos, ypos, width, height); + Assert.assertNotNull(window0); + System.err.println("Test.0: Window bounds: "+window0.getX()+"/"+window0.getY()+" "+window0.getWidth()+"x"+window0.getHeight()+" within "+screen.getViewport()); + + final Animator anim = new Animator(window0); + anim.start(); + + List<MonitorMode> allMonitorModes = screen.getMonitorModes(); + Assert.assertTrue(allMonitorModes.size()>0); + + MonitorDevice monitor = window0.getMainMonitor(); + System.err.println("Test.0: Window monitor: "+monitor); + if( !spanAcrossMonitors ) { + window0.setFullscreen(true); + } else { + window0.setFullscreen(monitors); + } + + monitor = window0.getMainMonitor(); + System.err.println("Test.1: Window bounds: "+window0.getX()+"/"+window0.getY()+" "+window0.getWidth()+"x"+window0.getHeight()+" within "+screen.getViewport()); + System.err.println("Test.1: Window monitor: "+monitor.getViewport()); + Rectangle window0Rect = new Rectangle(window0.getX(), window0.getY(), window0.getWidth(), window0.getHeight()); + if( !spanAcrossMonitors ) { + Assert.assertEquals(monitor.getViewport(), window0Rect); + } else { + List<MonitorDevice> monitorsUsed = monitors; + if( null == monitorsUsed ) { + monitorsUsed = window0.getScreen().getMonitorDevices(); + } + Rectangle monitorsUsedViewport = MonitorDevice.unionOfViewports(new Rectangle(), monitorsUsed); + Assert.assertEquals(monitorsUsedViewport, window0Rect); + } + + Thread.sleep(duration); + + window0.setFullscreen(false); + + window0Rect = new Rectangle(window0.getX(), window0.getY(), window0.getWidth(), window0.getHeight()); + monitor = window0.getMainMonitor(); + System.err.println("Test.2: Window bounds: "+window0.getX()+"/"+window0.getY()+" "+window0.getWidth()+"x"+window0.getHeight()+" within "+screen.getViewport()); + System.err.println("Test.2: Window monitor: "+monitor.getViewport()); + + Thread.sleep(duration); + anim.stop(); + destroyWindow(window0); + Assert.assertEquals(false,window0.isVisible()); + Assert.assertEquals(false,window0.isNativeValid()); + Assert.assertEquals(true,display.isNativeValid()); + Assert.assertEquals(true,screen.isNativeValid()); + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } + } + String tstname = TestScreenMode01cNEWT.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/mm/TestScreenMode01dNEWT.java index c3c68e46c..6158e6244 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode01dNEWT.java @@ -26,7 +26,7 @@ * or implied, of JogAmp Community. */ -package com.jogamp.opengl.test.junit.newt; +package com.jogamp.opengl.test.junit.newt.mm; import java.io.IOException; import javax.media.opengl.GLCapabilities; @@ -34,32 +34,42 @@ 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; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import com.jogamp.newt.Display; +import com.jogamp.newt.MonitorDevice; import com.jogamp.newt.NewtFactory; import com.jogamp.newt.Screen; import com.jogamp.newt.Window; -import com.jogamp.newt.ScreenMode; +import com.jogamp.newt.MonitorMode; import com.jogamp.newt.opengl.GLWindow; -import com.jogamp.newt.util.ScreenModeUtil; +import com.jogamp.newt.util.MonitorModeUtil; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.UITestCase; import java.util.List; import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.Rectangle; +import javax.media.nativewindow.util.RectangleImmutable; /** - * Demonstrates fullscreen with and without ScreenMode change. - * + * Demonstrates fullscreen without MonitorMode change + * and fullscreen before and after MonitorMode change. + * <p> + * Also tests MonitorMode reset, by destroying the last Screen (reference), + * i.e. the original MonitorMode should get reinstated! + * </p> * <p> - * Also documents NV RANDR/GL bug, see {@link TestScreenMode01NEWT#cleanupGL()}.</p> + * Also documents NV RANDR/GL bug, see {@link TestScreenMode01dNEWT#cleanupGL()}.</p> */ -public class TestScreenMode01NEWT extends UITestCase { +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestScreenMode01dNEWT extends UITestCase { static GLProfile glp; static int width, height; @@ -68,6 +78,7 @@ public class TestScreenMode01NEWT extends UITestCase { @BeforeClass public static void initClass() { + setResetXRandRIfX11AfterClass(); width = 640; height = 480; glp = GLProfile.getDefault(); @@ -109,10 +120,12 @@ public class TestScreenMode01NEWT extends UITestCase { * Remedy B) is shown in {@link TestScreenMode01bNEWT} * </pre> */ - @After - public void cleanupGL() throws InterruptedException { - GLProfile.shutdown(GLProfile.ShutdownType.COMPLETE); + private void cleanupGL() throws InterruptedException { + System.err.println("*** cleanupGL.shutdown"); + GLProfile.shutdown(); + System.err.println("*** cleanupGL.initSingleton"); GLProfile.initSingleton(); + System.err.println("*** cleanupGL.DONE"); } static GLWindow createWindow(Screen screen, GLCapabilities caps, int width, int height, boolean onscreen, boolean undecorated) { @@ -127,14 +140,15 @@ public class TestScreenMode01NEWT extends UITestCase { return window; } - static void destroyWindow(Window window) { + static void destroyWindow(Window window) throws InterruptedException { if(null!=window) { window.destroy(); + Assert.assertTrue(AWTRobotUtil.waitForRealized(window, false)); } } @Test - public void testFullscreenChange01() throws InterruptedException { + public void test01FullscreenChange01() throws InterruptedException { Thread.sleep(waitTimeShort); GLCapabilities caps = new GLCapabilities(glp); Assert.assertNotNull(caps); @@ -147,14 +161,16 @@ public class TestScreenMode01NEWT extends UITestCase { Animator animator = new Animator(window); animator.start(); + final MonitorDevice monitor = window.getMainMonitor(); + Assert.assertEquals(false, window.isFullscreen()); Assert.assertEquals(width, window.getWidth()); Assert.assertEquals(height, window.getHeight()); window.setFullscreen(true); - Assert.assertEquals(true, window.isFullscreen()); - Assert.assertEquals(window.getScreen().getWidth(), window.getWidth()); - Assert.assertEquals(window.getScreen().getHeight(), window.getHeight()); + Assert.assertEquals(true, window.isFullscreen()); + Assert.assertEquals(monitor.getViewport().getWidth(), window.getWidth()); + Assert.assertEquals(monitor.getViewport().getHeight(), window.getHeight()); Thread.sleep(waitTimeShort); @@ -166,11 +182,23 @@ public class TestScreenMode01NEWT extends UITestCase { Thread.sleep(waitTimeShort); animator.stop(); - destroyWindow(window); + Assert.assertEquals(false, animator.isAnimating()); + Assert.assertEquals(false, animator.isStarted()); + + destroyWindow(window); + + Assert.assertEquals(false,window.isVisible()); + Assert.assertEquals(false,window.isRealized()); + Assert.assertEquals(false,window.isNativeValid()); + Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false)); + Assert.assertEquals(false,screen.isNativeValid()); + Assert.assertEquals(false,display.isNativeValid()); + + cleanupGL(); } @Test - public void testScreenModeChange01() throws InterruptedException { + public void test02ScreenModeChange01() throws InterruptedException { Thread.sleep(waitTimeShort); GLCapabilities caps = new GLCapabilities(glp); @@ -182,90 +210,94 @@ public class TestScreenMode01NEWT extends UITestCase { GLWindow window = createWindow(screen, caps, width, height, true /* onscreen */, false /* undecorated */); Assert.assertNotNull(window); - List<ScreenMode> screenModes = screen.getScreenModes(); - if(screenModes.size()==1) { + final RectangleImmutable winRect = new Rectangle(window.getX(), window.getY(), window.getWidth(), window.getHeight()); + final MonitorDevice monitor = screen.getMainMonitor(winRect); + + List<MonitorMode> monitorModes = monitor.getSupportedModes(); + Assert.assertTrue(monitorModes.size()>0); + if(monitorModes.size()==1) { // no support .. - System.err.println("Your platform has no ScreenMode change support, sorry"); + System.err.println("Your platform has no MonitorMode change support, sorry"); destroyWindow(window); return; } - Assert.assertTrue(screenModes.size()>0); Animator animator = new Animator(window); animator.start(); - 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); + MonitorMode mmCurrent = monitor.queryCurrentMode(); + Assert.assertNotNull(mmCurrent); + MonitorMode mmOrig = monitor.getOriginalMode(); + Assert.assertNotNull(mmOrig); + System.err.println("[0] orig : "+mmOrig); + System.err.println("[0] current: "+mmCurrent); + Assert.assertEquals(mmCurrent, mmOrig); + + monitorModes = MonitorModeUtil.filterByFlags(monitorModes, 0); // no interlace, double-scan etc + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + monitorModes = MonitorModeUtil.filterByRotation(monitorModes, 0); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + monitorModes = MonitorModeUtil.filterByResolution(monitorModes, new Dimension(801, 601)); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + monitorModes = MonitorModeUtil.filterByRate(monitorModes, mmOrig.getRefreshRate()); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + + monitorModes = MonitorModeUtil.getHighestAvailableBpp(monitorModes); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + + // set mode + { + MonitorMode sm = (MonitorMode) monitorModes.get(0); + System.err.println("[0] set current: "+sm); + final boolean smOk = monitor.setCurrentMode(sm); + mmCurrent = monitor.getCurrentMode(); + System.err.println("[0] has current: "+mmCurrent+", changeOK "+smOk); + Assert.assertTrue(monitor.isModeChangedByUs()); + Assert.assertEquals(sm, mmCurrent); + Assert.assertNotSame(mmOrig, mmCurrent); + Assert.assertEquals(mmCurrent, monitor.queryCurrentMode()); + Assert.assertTrue(smOk); + } - 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(waitTimeLong); - // check reset .. - Assert.assertEquals(true,display.isNativeValid()); Assert.assertEquals(true,screen.isNativeValid()); Assert.assertEquals(true,window.isNativeValid()); Assert.assertEquals(true,window.isVisible()); - animator.stop(); + animator.stop(); + Assert.assertEquals(false, animator.isAnimating()); + Assert.assertEquals(false, animator.isStarted()); + destroyWindow(window); - Thread.sleep(waitTimeShort); Assert.assertEquals(false,window.isVisible()); + Assert.assertEquals(false,window.isRealized()); Assert.assertEquals(false,window.isNativeValid()); + Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false)); Assert.assertEquals(false,screen.isNativeValid()); Assert.assertEquals(false,display.isNativeValid()); - screen.createNative(); // trigger native re-creation - - Assert.assertEquals(true,display.isNativeValid()); - Assert.assertEquals(true,screen.isNativeValid()); - - smCurrent = screen.getCurrentScreenMode(); - System.err.println("[1] current/orig: "+smCurrent); - - Assert.assertNotNull(smCurrent); - Assert.assertEquals(smCurrent, smOrig); - - screen.destroy(); - - Assert.assertEquals(false,screen.isNativeValid()); - Assert.assertEquals(false,display.isNativeValid()); + validateScreenModeReset(mmOrig, winRect); + cleanupGL(); } @Test - public void testScreenModeChangeWithFS01Pre() throws InterruptedException { + public void test03ScreenModeChangeWithFS01Post() throws InterruptedException { Thread.sleep(waitTimeShort); - testScreenModeChangeWithFS01Impl(true) ; + testScreenModeChangeWithFS01Impl(false) ; } @Test - public void testScreenModeChangeWithFS01Post() throws InterruptedException { + public void test04ScreenModeChangeWithFS01Pre() throws InterruptedException { Thread.sleep(waitTimeShort); - testScreenModeChangeWithFS01Impl(false) ; + testScreenModeChangeWithFS01Impl(true) ; } protected void testScreenModeChangeWithFS01Impl(boolean preFS) throws InterruptedException { @@ -276,27 +308,31 @@ public class TestScreenMode01NEWT extends UITestCase { Animator animator = new Animator(window); animator.start(); - 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); + final RectangleImmutable winRect = new Rectangle(window.getX(), window.getY(), window.getWidth(), window.getHeight()); + final MonitorDevice monitor = screen.getMainMonitor(winRect); + MonitorMode mmCurrent = monitor.queryCurrentMode(); + Assert.assertNotNull(mmCurrent); + MonitorMode mmOrig = monitor.getOriginalMode(); + Assert.assertNotNull(mmOrig); + System.err.println("[0] orig : "+mmOrig); + System.err.println("[0] current: "+mmCurrent); + Assert.assertEquals(mmCurrent, mmOrig); - List<ScreenMode> screenModes = screen.getScreenModes(); - if(screenModes.size()==1) { + List<MonitorMode> monitorModes = monitor.getSupportedModes(); + if(monitorModes.size()==1) { // no support .. destroyWindow(window); return; } - Assert.assertTrue(screenModes.size()>0); - screenModes = ScreenModeUtil.filterByRate(screenModes, smOrig.getMonitorMode().getRefreshRate()); - screenModes = ScreenModeUtil.filterByRotation(screenModes, 0); - screenModes = ScreenModeUtil.filterByResolution(screenModes, new Dimension(801, 601)); - screenModes = ScreenModeUtil.getHighestAvailableBpp(screenModes); - - ScreenMode screenMode = (ScreenMode) screenModes.get(0); - Assert.assertNotNull(screenMode); + Assert.assertTrue(monitorModes.size()>0); + monitorModes = MonitorModeUtil.filterByFlags(monitorModes, 0); // no interlace, double-scan etc + monitorModes = MonitorModeUtil.filterByRotation(monitorModes, 0); + monitorModes = MonitorModeUtil.filterByResolution(monitorModes, new Dimension(801, 601)); + monitorModes = MonitorModeUtil.filterByRate(monitorModes, mmOrig.getRefreshRate()); + monitorModes = MonitorModeUtil.getHighestAvailableBpp(monitorModes); + + MonitorMode monitorMode = (MonitorMode) monitorModes.get(0); + Assert.assertNotNull(monitorMode); if(preFS) { System.err.println("[0] set FS pre 0: "+window.isFullscreen()); @@ -305,9 +341,20 @@ public class TestScreenMode01NEWT extends UITestCase { Assert.assertEquals(true, window.isFullscreen()); System.err.println("[0] set FS pre X: "+window.isFullscreen()); } - - System.err.println("[0] set current: "+screenMode); - screen.setCurrentScreenMode(screenMode); + Thread.sleep(waitTimeShort); + + // set mode + { + System.err.println("[0] set current: "+monitorMode); + final boolean smOk = monitor.setCurrentMode(monitorMode); + mmCurrent = monitor.getCurrentMode(); + System.err.println("[0] has current: "+mmCurrent+", changeOK "+smOk); + Assert.assertTrue(monitor.isModeChangedByUs()); + Assert.assertEquals(monitorMode, mmCurrent); + Assert.assertNotSame(mmOrig, mmCurrent); + Assert.assertEquals(mmCurrent, monitor.queryCurrentMode()); + Assert.assertTrue(smOk); + } if(!preFS) { System.err.println("[0] set FS post 0: "+window.isFullscreen()); @@ -318,38 +365,57 @@ public class TestScreenMode01NEWT extends UITestCase { Thread.sleep(waitTimeLong); - // check reset .. - + if(!preFS) { + System.err.println("[0] set !FS post 0: "+window.isFullscreen()); + window.setFullscreen(false); + Assert.assertEquals(false, window.isFullscreen()); + System.err.println("[0] set !FS post X: "+window.isFullscreen()); + Thread.sleep(waitTimeShort); + } + Assert.assertEquals(true,display.isNativeValid()); Assert.assertEquals(true,screen.isNativeValid()); Assert.assertEquals(true,window.isNativeValid()); Assert.assertEquals(true,window.isVisible()); animator.stop(); + Assert.assertEquals(false, animator.isAnimating()); + Assert.assertEquals(false, animator.isStarted()); + destroyWindow(window); - Thread.sleep(waitTimeShort); Assert.assertEquals(false,window.isVisible()); + Assert.assertEquals(false,window.isRealized()); Assert.assertEquals(false,window.isNativeValid()); + Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false)); Assert.assertEquals(false,screen.isNativeValid()); Assert.assertEquals(false,display.isNativeValid()); - screen.createNative(); // trigger native re-creation + validateScreenModeReset(mmOrig, winRect); + cleanupGL(); + } + void validateScreenModeReset(final MonitorMode mmOrig, final RectangleImmutable rect) { + final Display display = NewtFactory.createDisplay(null); // local display + Assert.assertNotNull(display); + final Screen screen = NewtFactory.createScreen(display, 0); // screen 0 + Assert.assertNotNull(screen); + Assert.assertEquals(false,display.isNativeValid()); + Assert.assertEquals(false,screen.isNativeValid()); + screen.addReference(); Assert.assertEquals(true,display.isNativeValid()); Assert.assertEquals(true,screen.isNativeValid()); - smCurrent = screen.getCurrentScreenMode(); - System.err.println("[1] current/orig: "+smCurrent); - - Assert.assertNotNull(smCurrent); - Assert.assertEquals(smCurrent, smOrig); - - screen.destroy(); + final MonitorDevice monitor = screen.getMainMonitor(rect); + Assert.assertEquals(mmOrig, monitor.getCurrentMode()); + + screen.removeReference(); + Assert.assertEquals(false,display.isNativeValid()); + Assert.assertEquals(false,screen.isNativeValid()); } - + public static void main(String args[]) throws IOException { - String tstname = TestScreenMode01NEWT.class.getName(); + String tstname = TestScreenMode01dNEWT.class.getName(); org.junit.runner.JUnitCore.main(tstname); } } diff --git a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode02aNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode02aNEWT.java new file mode 100644 index 000000000..e87194bc6 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode02aNEWT.java @@ -0,0 +1,253 @@ +/** + * 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.mm; + +import java.io.IOException; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; + +import com.jogamp.opengl.util.Animator; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.common.os.Platform; +import com.jogamp.newt.Display; +import com.jogamp.newt.MonitorDevice; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Screen; +import com.jogamp.newt.Window; +import com.jogamp.newt.MonitorMode; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.newt.util.MonitorModeUtil; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; +import java.util.List; +import javax.media.nativewindow.util.Dimension; + +/** + * Tests MonitorMode change w/ changed rotation, + * w/ and w/o fullscreen, pre and post MonitorMode change. + * <p> + * MonitorMode change does not use highest resolution. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestScreenMode02aNEWT extends UITestCase { + static GLProfile glp; + static int width, height; + + static int waitTimeShort = 2000; // 2 sec + static int waitTimeLong = 8000; // 8 sec + + @BeforeClass + public static void initClass() { + setResetXRandRIfX11AfterClass(); + width = 640; + height = 480; + glp = GLProfile.getDefault(); + } + + static GLWindow createWindow(Screen screen, GLCapabilities caps, int width, int height, boolean onscreen, boolean undecorated) { + Assert.assertNotNull(caps); + caps.setOnscreen(onscreen); + + GLWindow window = GLWindow.create(screen, caps); + window.setSize(width, height); + window.addGLEventListener(new GearsES2(1)); + Assert.assertNotNull(window); + return window; + } + + static void destroyWindow(Window window) throws InterruptedException { + if(null!=window) { + window.destroy(); + Assert.assertTrue(AWTRobotUtil.waitForRealized(window, false)); + } + } + + @Test + public void testScreenRotationChange01_PreWin() throws InterruptedException { + testScreenRotationChangeImpl(true, true, false); + } + + @Test + public void testScreenRotationChange02_PreFull() throws InterruptedException { + testScreenRotationChangeImpl(true, true, true); + } + + @Test + public void testScreenRotationChange11_PostWin() throws InterruptedException { + testScreenRotationChangeImpl(true, false, false); + } + + @Test + public void testScreenRotationChange12_PostFull() throws InterruptedException { + testScreenRotationChangeImpl(true, false, true); + } + + void testScreenRotationChangeImpl(boolean changeMode, boolean preVis, boolean fullscreen) throws InterruptedException { + 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); + GLWindow window = createWindow(screen, caps, width, height, true /* onscreen */, false /* undecorated */); + Assert.assertNotNull(window); + if( preVis ) { + window.setVisible(true); + if( fullscreen ) { + window.setFullscreen(true); + } + } else { + screen.createNative(); + Assert.assertEquals(true,display.isNativeValid()); + Assert.assertEquals(true,screen.isNativeValid()); + } + + Animator animator = new Animator(window); + animator.start(); + + final MonitorDevice monitor = window.getMainMonitor(); + final MonitorMode mmOrig = monitor.getOriginalMode(); + Assert.assertNotNull(mmOrig); + if(changeMode) { + Thread.sleep(waitTimeShort); + + List<MonitorMode> monitorModes = monitor.getSupportedModes(); + if(monitorModes.size()==1) { + // no support .. + System.err.println("Your platform has no ScreenMode change support, sorry"); + animator.stop(); + destroyWindow(window); + return; + } + Assert.assertTrue(monitorModes.size()>0); + + MonitorMode mmCurrent = monitor.getCurrentMode(); + Assert.assertNotNull(mmCurrent); + System.err.println("[0] orig : "+mmOrig); + System.err.println("[0] current: "+mmCurrent); + Assert.assertEquals(mmCurrent, mmOrig); + + monitorModes = MonitorModeUtil.filterByFlags(monitorModes, 0); // no interlace, double-scan etc + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + monitorModes = MonitorModeUtil.filterByRotation(monitorModes, 90); + if(null==monitorModes || Platform.getOSType() == Platform.OSType.MACOS ) { + // no rotation support .. + System.err.println("Your platform has no rotation support, sorry"); + animator.stop(); + destroyWindow(window); + return; + } + monitorModes = MonitorModeUtil.filterByResolution(monitorModes, new Dimension(801, 601)); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + monitorModes = MonitorModeUtil.filterByRate(monitorModes, mmOrig.getRefreshRate()); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + monitorModes = MonitorModeUtil.getHighestAvailableBpp(monitorModes); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + + // set mode + { + MonitorMode mm = monitorModes.get(0); + System.err.println("[0] set current: "+mm); + final boolean smOk = monitor.setCurrentMode(mm); + mmCurrent = monitor.getCurrentMode(); + System.err.println("[0] has current: "+mmCurrent+", changeOK "+smOk); + Assert.assertTrue(monitor.isModeChangedByUs()); + Assert.assertEquals(mm, mmCurrent); + Assert.assertNotSame(mmOrig, mmCurrent); + Assert.assertEquals(mmCurrent, monitor.queryCurrentMode()); + Assert.assertTrue(smOk); + } + } + + if( !preVis ) { + if( fullscreen ) { + window.setFullscreen(true); + } + window.setVisible(true); + } + + Thread.sleep(waitTimeLong); + + if( !preVis && fullscreen ) { + window.setFullscreen(false); + } + + if(changeMode) { + Thread.sleep(waitTimeShort); + + // manual restore! + { + System.err.println("[1] set orig: "+mmOrig); + final boolean smOk = monitor.setCurrentMode(mmOrig); + MonitorMode mmCurrent = monitor.getCurrentMode(); + System.err.println("[1] has orig?: "+mmCurrent+", changeOK "+smOk); + Assert.assertFalse(monitor.isModeChangedByUs()); + Assert.assertEquals(mmOrig, mmCurrent); + Assert.assertTrue(smOk); + } + Thread.sleep(waitTimeShort); + } + + if( preVis && fullscreen ) { + window.setFullscreen(false); + } + + Assert.assertEquals(true,display.isNativeValid()); + Assert.assertEquals(true,screen.isNativeValid()); + Assert.assertEquals(true,window.isNativeValid()); + Assert.assertEquals(true,window.isVisible()); + + animator.stop(); + destroyWindow(window); + + Assert.assertEquals(false,window.isVisible()); + Assert.assertEquals(false,window.isNativeValid()); + Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false)); + Assert.assertEquals(false,screen.isNativeValid()); + Assert.assertEquals(false,display.isNativeValid()); + } + + public static void main(String args[]) throws IOException { + String tstname = TestScreenMode02aNEWT.class.getName(); + org.junit.runner.JUnitCore.main(tstname); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode02bNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode02bNEWT.java new file mode 100644 index 000000000..2da2abd32 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode02bNEWT.java @@ -0,0 +1,261 @@ +/** + * 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.mm; + +import java.io.IOException; +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 org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.common.os.Platform; +import com.jogamp.newt.Display; +import com.jogamp.newt.MonitorDevice; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Screen; +import com.jogamp.newt.Window; +import com.jogamp.newt.MonitorMode; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.newt.util.MonitorModeUtil; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; + +import java.util.List; +import javax.media.nativewindow.util.Dimension; + +/** + * Tests MonitorMode change w/ changed rotation and fullscreen. + * <p> + * MonitorMode change uses highest resolution. + * </p> + * <p> + * Bug 734 could not be reproduced, however on tests systems + * here - AMD fglrx and Intel Mesa, the rotated height + * is cut off .. probably due to bug of driver code and rotation. + * </p> + * <p> + * Documents remedy B) for NV RANDR/GL bug + * </p> + * + * @see TestScreenMode01NEWT#cleanupGL() + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestScreenMode02bNEWT extends UITestCase { + static GLProfile glp; + + static int waitTimeShort = 2000; // 2 sec + static int waitTimeLong = 8000; // 8 sec + + @BeforeClass + public static void initClass() { + setResetXRandRIfX11AfterClass(); + glp = GLProfile.getDefault(); + } + + @AfterClass + public static void releaseClass() throws InterruptedException { + Thread.sleep(waitTimeShort); + } + + static GLWindow 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(1)); + Assert.assertNotNull(window); + return window; + } + + static void destroyWindow(Window window) throws InterruptedException { + if(null!=window) { + window.destroy(); + Assert.assertTrue(AWTRobotUtil.waitForRealized(window, false)); + } + } + + @Test + public void testScreenModeChange01_PreFull() throws InterruptedException { + testScreenModeChangeImpl(true); + } + + @Test + public void testScreenModeChange02_PostFull() throws InterruptedException { + testScreenModeChangeImpl(false); + } + + void testScreenModeChangeImpl(boolean preVis) throws InterruptedException { + 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); + screen.createNative(); // instantiate for resolution query and keep it alive ! + final int swidth = screen.getWidth(); + final int sheight = screen.getHeight(); + + GLWindow window = createWindow(screen, caps, "win0", 0, 0, 640, 480); + if( preVis ) { + window.setVisible(true); + window.setFullscreen(true); + } + window.setUndecorated(true); + Assert.assertNotNull(window); + + List<MonitorMode> allMonitorModes = screen.getMonitorModes(); + Assert.assertTrue(allMonitorModes.size()>0); + if(allMonitorModes.size()==1) { + // no support .. + System.err.println("Your platform has no MonitorMode change support (all), sorry"); + destroyWindow(window); + return; + } + + MonitorDevice monitor = window.getMainMonitor(); + List<MonitorMode> monitorModes = monitor.getSupportedModes(); + Assert.assertTrue(monitorModes.size()>0); + if(monitorModes.size()==1) { + // no support .. + System.err.println("Your platform has no MonitorMode change support (monitor), sorry"); + destroyWindow(window); + return; + } + Assert.assertTrue(allMonitorModes.containsAll(monitorModes)); + + Animator animator = new Animator(window); + animator.start(); + + MonitorMode mmCurrent = monitor.queryCurrentMode(); + Assert.assertNotNull(mmCurrent); + final MonitorMode mmOrig = monitor.getOriginalMode(); + Assert.assertNotNull(mmOrig); + System.err.println("[0] orig : "+mmOrig); + System.err.println("[0] current: "+mmCurrent); + Assert.assertEquals(mmCurrent, mmOrig); + + monitorModes = MonitorModeUtil.filterByFlags(monitorModes, 0); // no interlace, double-scan etc + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + monitorModes = MonitorModeUtil.filterByRotation(monitorModes, 90); + if(null==monitorModes || Platform.getOSType() == Platform.OSType.MACOS ) { + // no rotation support .. + System.err.println("Your platform has no rotation support, sorry"); + animator.stop(); + destroyWindow(window); + return; + } + monitorModes = MonitorModeUtil.filterByResolution(monitorModes, new Dimension(swidth, sheight)); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + monitorModes = MonitorModeUtil.filterByRate(monitorModes, mmOrig.getRefreshRate()); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + + monitorModes = MonitorModeUtil.getHighestAvailableBpp(monitorModes); + Assert.assertNotNull(monitorModes); + Assert.assertTrue(monitorModes.size()>0); + + // set mode + { + MonitorMode mm = monitorModes.get(0); // highest resolution .. + System.err.println("[0] set current: "+mm); + final boolean smOk = monitor.setCurrentMode(mm); + mmCurrent = monitor.getCurrentMode(); + System.err.println("[0] has current: "+mmCurrent+", changeOK "+smOk); + if( !smOk ) { + System.err.println("ERROR: Full MonitorMode w/ rotation failure - Expected on some platforms (NV driver) - Tolerated for now."); + animator.stop(); + destroyWindow(window); + return; + } + Assert.assertTrue(monitor.isModeChangedByUs()); + Assert.assertEquals(mm, mmCurrent); + Assert.assertNotSame(mmOrig, mmCurrent); + Assert.assertEquals(mmCurrent, monitor.queryCurrentMode()); + Assert.assertTrue(smOk); + } + + if( !preVis ) { + window.setFullscreen(true); + window.setVisible(true); + } + + Thread.sleep(waitTimeLong); + + if( !preVis ) { + window.setFullscreen(false); + } + + // manual restore! + { + System.err.println("[1] set orig: "+mmOrig); + final boolean smOk = monitor.setCurrentMode(mmOrig); + mmCurrent = monitor.getCurrentMode(); + System.err.println("[1] has orig?: "+mmCurrent+", changeOK "+smOk); + Assert.assertFalse(monitor.isModeChangedByUs()); + Assert.assertEquals(mmOrig, mmCurrent); + Assert.assertTrue(smOk); + } + Thread.sleep(waitTimeShort); + + if( preVis ) { + window.setFullscreen(false); + } + + Assert.assertEquals(true,display.isNativeValid()); + Assert.assertEquals(true,screen.isNativeValid()); + Assert.assertEquals(true,window.isNativeValid()); + Assert.assertEquals(true,window.isVisible()); + + animator.stop(); + destroyWindow(window); + + Assert.assertEquals(false,window.isVisible()); + Assert.assertEquals(false,window.isNativeValid()); + Assert.assertTrue(AWTRobotUtil.waitForRealized(screen, false)); + Assert.assertEquals(false,screen.isNativeValid()); + Assert.assertEquals(false,display.isNativeValid()); + } + + public static void main(String args[]) throws IOException { + String tstname = TestScreenMode02bNEWT.class.getName(); + org.junit.runner.JUnitCore.main(tstname); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/KeyAction.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/KeyAction.java index 3313ec65c..0ae94d7af 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/KeyAction.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/KeyAction.java @@ -38,7 +38,10 @@ class KeyAction extends KeyAdapter { this.eventFifo = eventFifo; } - public void keyTyped(KeyEvent e) { + public void keyReleased(KeyEvent e) { + if( !e.isPrintableKey() || e.isAutoRepeat() ) { + return; + } eventFifo.put(e); } } diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtAWTReparentingKeyAdapter.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtAWTReparentingKeyAdapter.java index 473f2f584..dc9aac8ea 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtAWTReparentingKeyAdapter.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtAWTReparentingKeyAdapter.java @@ -3,14 +3,14 @@ * * 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 @@ -20,7 +20,7 @@ * 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. @@ -28,72 +28,207 @@ package com.jogamp.opengl.test.junit.newt.parenting; import java.awt.Frame; +import java.net.URLConnection; import javax.media.nativewindow.util.InsetsImmutable; +import com.jogamp.common.util.IOUtil; +import com.jogamp.newt.Display; +import com.jogamp.newt.Display.PointerIcon; import com.jogamp.newt.awt.NewtCanvasAWT; import com.jogamp.newt.event.KeyAdapter; import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.util.PNGPixelRect; + +public class NewtAWTReparentingKeyAdapter extends KeyAdapter { + final Frame frame; + final NewtCanvasAWT newtCanvasAWT; + final GLWindow glWindow; + final QuitAdapter quitAdapter; + PointerIcon[] pointerIcons = null; + int pointerIconIdx = 0; -class NewtAWTReparentingKeyAdapter extends KeyAdapter { - Frame frame; - NewtCanvasAWT newtCanvasAWT; - GLWindow glWindow; - - public NewtAWTReparentingKeyAdapter(Frame frame, NewtCanvasAWT newtCanvasAWT, GLWindow glWindow) { + public NewtAWTReparentingKeyAdapter(Frame frame, NewtCanvasAWT newtCanvasAWT, GLWindow glWindow, QuitAdapter quitAdapter) { this.frame = frame; this.newtCanvasAWT = newtCanvasAWT; this.glWindow = glWindow; + this.quitAdapter = quitAdapter; } - - public void keyTyped(KeyEvent e) { - if(e.getKeyChar()=='d') { - glWindow.setUndecorated(!glWindow.isUndecorated()); - } else if(e.getKeyChar()=='f') { - glWindow.setFullscreen(!glWindow.isFullscreen()); - } else if(e.getKeyChar()=='l') { + + public void keyReleased(KeyEvent e) { + if( !e.isPrintableKey() || e.isAutoRepeat() ) { + return; + } + if( e.getKeySymbol() == KeyEvent.VK_L ) { javax.media.nativewindow.util.Point p0 = newtCanvasAWT.getNativeWindow().getLocationOnScreen(null); javax.media.nativewindow.util.Point p1 = glWindow.getLocationOnScreen(null); - System.err.println("NewtCanvasAWT position: "+p0+", "+p1); - } else if(e.getKeyChar()=='p') { + System.err.println("NewtCanvasAWT position: "+p0+", "+p1); + } else if( e.getKeySymbol() == KeyEvent.VK_D ) { + glWindow.setUndecorated(!glWindow.isUndecorated()); + } else if( e.getKeySymbol() == KeyEvent.VK_S ) { + if(glWindow.getParent()==null) { + System.err.println("XXX glWin to 100/100"); + glWindow.setPosition(100, 100); + } else { + System.err.println("XXX glWin to 0/0"); + glWindow.setPosition(0, 0); + } + } else if( e.getKeySymbol() == KeyEvent.VK_F ) { + if( null != quitAdapter ) { + quitAdapter.enable(false); + } + new Thread() { + public void run() { + final Thread t = glWindow.setExclusiveContextThread(null); + System.err.println("[set fullscreen pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets()); + glWindow.setFullscreen(!glWindow.isFullscreen()); + System.err.println("[set fullscreen post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets()); + glWindow.setExclusiveContextThread(t); + if( null != quitAdapter ) { + quitAdapter.clear(); + quitAdapter.enable(true); + } + } }.start(); + } else if( e.getKeySymbol() == KeyEvent.VK_P ) { new Thread() { public void run() { if(glWindow.getAnimator().isPaused()) { glWindow.getAnimator().resume(); } else { - glWindow.getAnimator().pause(); - } + glWindow.getAnimator().pause(); + } } }.run(); - } else if(e.getKeyChar()=='r') { - if(glWindow.getParent()==null) { - System.err.println("XXX glWin to home"); - glWindow.reparentWindow(newtCanvasAWT.getNativeWindow()); - } else { - final InsetsImmutable nInsets = glWindow.getInsets(); - java.awt.Insets aInsets = frame.getInsets(); - System.err.println("XXX glWin to TOP - insets " + nInsets + ", " + aInsets); - glWindow.reparentWindow(null); - int dx, dy; - if(nInsets.getTotalHeight()==0) { - dx = aInsets.left; - dy = aInsets.top; - } else { - dx = nInsets.getLeftWidth(); - dy = nInsets.getTopHeight(); + } else if( e.getKeySymbol() == KeyEvent.VK_A ) { + new Thread() { + public void run() { + glWindow.setAlwaysOnTop(!glWindow.isAlwaysOnTop()); } - glWindow.setPosition(frame.getX()+frame.getWidth()+dx, frame.getY()+dy); + }.run(); + } else if( e.getKeySymbol() == KeyEvent.VK_R ) { + if( null != quitAdapter ) { + quitAdapter.enable(false); } - glWindow.requestFocus(); - } else if(e.getKeyChar()=='s') { - if(glWindow.getParent()==null) { - System.err.println("XXX glWin to 100/100"); - glWindow.setPosition(100, 100); - } else { - System.err.println("XXX glWin to 0/0"); - glWindow.setPosition(0, 0); + new Thread() { + public void run() { + final Thread t = glWindow.setExclusiveContextThread(null); + if(glWindow.getParent()==null) { + System.err.println("XXX glWin to HOME"); + glWindow.reparentWindow(newtCanvasAWT.getNativeWindow(), -1, -1, 0 /* hints */); + } else { + if( null != frame ) { + final InsetsImmutable nInsets = glWindow.getInsets(); + final java.awt.Insets aInsets = frame.getInsets(); + int dx, dy; + if( nInsets.getTotalHeight()==0 ) { + dx = aInsets.left; + dy = aInsets.top; + } else { + dx = nInsets.getLeftWidth(); + dy = nInsets.getTopHeight(); + } + final int topLevelX = frame.getX()+frame.getWidth()+dx; + final int topLevelY = frame.getY()+dy; + System.err.println("XXX glWin to TOP.1 "+topLevelX+"/"+topLevelY+" - insets " + nInsets + ", " + aInsets); + glWindow.reparentWindow(null, topLevelX, topLevelY, 0 /* hint */); + } else { + System.err.println("XXX glWin to TOP.0"); + glWindow.reparentWindow(null, -1, -1, 0 /* hints */); + } + } + glWindow.requestFocus(); + glWindow.setExclusiveContextThread(t); + if( null != quitAdapter ) { + quitAdapter.clear(); + quitAdapter.enable(true); + } + } }.start(); + } else if(e.getKeySymbol() == KeyEvent.VK_C ) { + if( null == pointerIcons ) { + { + pointerIcons = new PointerIcon[3]; + final Display disp = glWindow.getScreen().getDisplay(); + { + PointerIcon _pointerIcon = null; + final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "newt/data/cross-grey-alpha-16x16.png" } ); + try { + _pointerIcon = disp.createPointerIcon(res, 8, 8); + System.err.println("Create PointerIcon #01: "+_pointerIcon); + } catch (Exception ex) { + ex.printStackTrace(); + } + pointerIcons[0] = _pointerIcon; + } + { + PointerIcon _pointerIcon = null; + final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "newt/data/pointer-grey-alpha-16x24.png" } ); + try { + _pointerIcon = disp.createPointerIcon(res, 0, 0); + System.err.println("Create PointerIcon #02: "+_pointerIcon); + } catch (Exception ex) { + ex.printStackTrace(); + } + pointerIcons[1] = _pointerIcon; + } + { + PointerIcon _pointerIcon = null; + final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "jogamp-pointer-64x64.png" } ); + try { + final URLConnection urlConn = res.resolve(0); + final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(), null, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); + System.err.println("Create PointerIcon #03: "+image); + _pointerIcon = disp.createPointerIcon(image, 32, 0); + System.err.println("Create PointerIcon #03: "+_pointerIcon); + } catch (Exception ex) { + ex.printStackTrace(); + } + pointerIcons[2] = _pointerIcon; + } + } } + new Thread() { + public void run() { + final Thread t = glWindow.setExclusiveContextThread(null); + System.err.println("[set pointer-icon pre]"); + final PointerIcon currentPI = glWindow.getPointerIcon(); + final PointerIcon newPI; + if( pointerIconIdx >= pointerIcons.length ) { + newPI=null; + pointerIconIdx=0; + } else { + newPI=pointerIcons[pointerIconIdx++]; + } + glWindow.setPointerIcon( newPI ); + System.err.println("[set pointer-icon post] "+currentPI+" -> "+glWindow.getPointerIcon()); + glWindow.setExclusiveContextThread(t); + } }.start(); + } else if( e.getKeySymbol() == KeyEvent.VK_I ) { + new Thread() { + public void run() { + final Thread t = glWindow.setExclusiveContextThread(null); + System.err.println("[set mouse visible pre]: "+glWindow.isPointerVisible()); + glWindow.setPointerVisible(!glWindow.isPointerVisible()); + System.err.println("[set mouse visible post]: "+glWindow.isPointerVisible()); + glWindow.setExclusiveContextThread(t); + } }.start(); + } else if(e.getKeySymbol() == KeyEvent.VK_J ) { + new Thread() { + public void run() { + final Thread t = glWindow.setExclusiveContextThread(null); + System.err.println("[set mouse confined pre]: "+glWindow.isPointerConfined()); + glWindow.confinePointer(!glWindow.isPointerConfined()); + System.err.println("[set mouse confined post]: "+glWindow.isPointerConfined()); + glWindow.setExclusiveContextThread(t); + } }.start(); + } else if(e.getKeySymbol() == KeyEvent.VK_W ) { + new Thread() { + public void run() { + System.err.println("[set mouse pos pre]"); + glWindow.warpPointer(glWindow.getWidth()/2, glWindow.getHeight()/2); + System.err.println("[set mouse pos post]"); + } }.start(); } } -}
\ No newline at end of file +} diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01NEWT.java index 6b7b155c5..714c397f3 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01NEWT.java @@ -3,14 +3,14 @@ * * 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 @@ -20,18 +20,20 @@ * 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.parenting; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import javax.media.opengl.*; @@ -45,6 +47,7 @@ import com.jogamp.opengl.test.junit.util.*; import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestParenting01NEWT extends UITestCase { static int width, height; static long durationPerTest = 600; @@ -59,7 +62,7 @@ public class TestParenting01NEWT extends UITestCase { } @Test - public void testWindowParenting01CreateVisibleDestroy() throws InterruptedException { + public void test01CreateVisibleDestroy() throws InterruptedException { Assert.assertEquals(0,Display.getActiveDisplayNumber()); Display display = null; Screen screen = null; @@ -74,12 +77,12 @@ public class TestParenting01NEWT extends UITestCase { Assert.assertEquals(0,display.getReferenceCount()); Assert.assertEquals(false,display.isNativeValid()); Assert.assertNotNull(display.getEDTUtil()); - Assert.assertEquals(true,display.getEDTUtil().isRunning()); + Assert.assertEquals(false,display.getEDTUtil().isRunning()); Assert.assertEquals(0,screen.getReferenceCount()); Assert.assertEquals(false,screen.isNativeValid()); Assert.assertEquals(0,Display.getActiveDisplayNumber()); - glWindow1.setTitle("testWindowParenting01CreateVisibleDestroy"); + glWindow1.setTitle("test01CreateVisibleDestroy"); glWindow1.setSize(640, 480); GLEventListener demo1 = new RedSquareES2(); setDemoFields(demo1, glWindow1, false); @@ -148,13 +151,13 @@ public class TestParenting01NEWT extends UITestCase { glWindow1.resetFPSCounter(); glWindow2.resetFPSCounter(); Animator animator1 = new Animator(glWindow1); - animator1.setUpdateFPSFrames(1, null); + animator1.setUpdateFPSFrames(1, null); animator1.start(); Assert.assertEquals(true, animator1.isAnimating()); Assert.assertEquals(false, animator1.isPaused()); Assert.assertNotNull(animator1.getThread()); Animator animator2 = new Animator(glWindow2); - animator2.setUpdateFPSFrames(1, null); + animator2.setUpdateFPSFrames(1, null); animator2.start(); Assert.assertEquals(true, animator2.isAnimating()); Assert.assertEquals(false, animator2.isPaused()); @@ -283,25 +286,27 @@ public class TestParenting01NEWT extends UITestCase { } @Test - public void testWindowParenting02ReparentTop2WinReparentRecreate() throws InterruptedException { - testWindowParenting02ReparentTop2WinImpl(true); + public void test02aReparentTop2WinReparentRecreate() throws InterruptedException { + test02ReparentTop2WinImpl(true); } @Test - public void testWindowParenting02ReparentTop2WinReparentNative() throws InterruptedException { - testWindowParenting02ReparentTop2WinImpl(false); + public void test02bReparentTop2WinReparentNative() throws InterruptedException { + test02ReparentTop2WinImpl(false); } /** * @param reparentRecreate true, if the followup reparent should utilize destroy/create, instead of native reparenting */ - protected void testWindowParenting02ReparentTop2WinImpl(boolean reparentRecreate) throws InterruptedException { + protected void test02ReparentTop2WinImpl(final boolean reparentRecreate) throws InterruptedException { + final int reparentHints = reparentRecreate ? Window.REPARENT_HINT_FORCE_RECREATION : 0; + Assert.assertEquals(0,Display.getActiveDisplayNumber()); Display display1 = null; Screen screen1 = null; GLWindow glWindow1 = GLWindow.create(glCaps); - glWindow1.setTitle("testWindowParenting02ReparentTop2Win"); + glWindow1.setTitle("test02ReparentTop2Win"); glWindow1.setSize(640, 480); GLEventListener demo1 = new RedSquareES2(); setDemoFields(demo1, glWindow1, false); @@ -369,19 +374,38 @@ public class TestParenting01NEWT extends UITestCase { int state = 0; Window.ReparentOperation reparentAction; - while(animator1.isAnimating() && animator1.getTotalFPSDuration()<3*durationPerTest) { + while(animator1.isAnimating() && animator1.getTotalFPSDuration()<7*durationPerTest) { Thread.sleep(durationPerTest); switch(state) { case 0: + // top-level glWindow2 hide + Assert.assertEquals(true, glWindow1.isVisible()); + Assert.assertEquals(true, glWindow2.isVisible()); + glWindow2.setVisible(false); + Assert.assertEquals(false, glWindow2.isVisible()); + Assert.assertEquals(true, glWindow1.isVisible()); + break; + + case 1: + // top-level glWindow2 show + Assert.assertEquals(true, glWindow1.isVisible()); + Assert.assertEquals(false, glWindow2.isVisible()); + glWindow2.setVisible(true); + Assert.assertEquals(true, glWindow2.isVisible()); + Assert.assertEquals(true, glWindow1.isVisible()); + break; + + case 2: // glWindow2 -- child --> glWindow1: compatible Assert.assertEquals(true, glWindow2.isVisible()); System.err.println("Frames(1) "+glWindow2.getTotalFPSFrames()); - reparentAction = glWindow2.reparentWindow(glWindow1, reparentRecreate); + reparentAction = glWindow2.reparentWindow(glWindow1, -1, -1, reparentHints); System.err.println("Frames(2) "+glWindow2.getTotalFPSFrames()); Assert.assertTrue(Window.ReparentOperation.ACTION_INVALID != reparentAction); Assert.assertEquals(true, glWindow2.isVisible()); Assert.assertEquals(true, glWindow2.isNativeValid()); Assert.assertSame(glWindow1,glWindow2.getParent()); + Thread.sleep(20*16); // Wait for a few frames since counter could be reset - 20 frames at 60Hz System.err.println("Frames for reparentWindow(parent, "+reparentRecreate+"): "+reparentAction+", B2: "+glWindow2.getTotalFPSFrames()); Assert.assertTrue(0 < glWindow2.getTotalFPSFrames()); @@ -397,15 +421,34 @@ public class TestParenting01NEWT extends UITestCase { break; - case 1: + case 3: + // child glWindow2 hide + Assert.assertEquals(true, glWindow1.isVisible()); + Assert.assertEquals(true, glWindow2.isVisible()); + glWindow2.setVisible(false); + Assert.assertEquals(false, glWindow2.isVisible()); + Assert.assertEquals(true, glWindow1.isVisible()); + break; + + case 4: + // child glWindow2 show + Assert.assertEquals(true, glWindow1.isVisible()); + Assert.assertEquals(false, glWindow2.isVisible()); + glWindow2.setVisible(true); + Assert.assertEquals(true, glWindow2.isVisible()); + Assert.assertEquals(true, glWindow1.isVisible()); + break; + + case 5: // glWindow2 --> top Assert.assertEquals(true, glWindow2.isVisible()); - reparentAction = glWindow2.reparentWindow(null, reparentRecreate); + reparentAction = glWindow2.reparentWindow(null, -1, -1, reparentHints); Assert.assertTrue(Window.ReparentOperation.ACTION_INVALID != reparentAction); Assert.assertEquals(true, glWindow2.isVisible()); Assert.assertEquals(true, glWindow2.isNativeValid()); Assert.assertNull(glWindow2.getParent()); + Thread.sleep(20*16); // Wait for a few frames since counter could be reset - 20 frames at 60Hz System.err.println("Frames for reparentWindow(parent, "+reparentRecreate+"): "+reparentAction+", B3: "+glWindow2.getTotalFPSFrames()); Assert.assertTrue(0 < glWindow2.getTotalFPSFrames()); @@ -479,16 +522,18 @@ public class TestParenting01NEWT extends UITestCase { } @Test - public void testWindowParenting03ReparentWin2TopReparentRecreate() throws InterruptedException { - testWindowParenting03ReparentWin2TopImpl(true); + public void test03aReparentWin2TopReparentRecreate() throws InterruptedException { + test03ReparentWin2TopImpl(true); } @Test - public void testWindowParenting03ReparentWin2TopReparentNative() throws InterruptedException { - testWindowParenting03ReparentWin2TopImpl(false); + public void test03bReparentWin2TopReparentNative() throws InterruptedException { + test03ReparentWin2TopImpl(false); } - protected void testWindowParenting03ReparentWin2TopImpl(boolean reparentRecreate) throws InterruptedException { + protected void test03ReparentWin2TopImpl(final boolean reparentRecreate) throws InterruptedException { + final int reparentHints = reparentRecreate ? Window.REPARENT_HINT_FORCE_RECREATION : 0; + Assert.assertEquals(0,Display.getActiveDisplayNumber()); Display display1 = null; Screen screen1 = null; @@ -498,7 +543,7 @@ public class TestParenting01NEWT extends UITestCase { GLWindow glWindow1 = GLWindow.create(glCaps); screen1 = glWindow1.getScreen(); display1 = screen1.getDisplay(); - glWindow1.setTitle("testWindowParenting03ReparentWin2Top"); + glWindow1.setTitle("test03ReparentWin2Top"); glWindow1.setSize(640, 480); GLEventListener demo1 = new RedSquareES2(); setDemoFields(demo1, glWindow1, false); @@ -557,30 +602,73 @@ public class TestParenting01NEWT extends UITestCase { int state = 0; Window.ReparentOperation reparentAction; - while(animator1.isAnimating() && animator1.getTotalFPSDuration()<3*durationPerTest) { + while(animator1.isAnimating() && animator1.getTotalFPSDuration()<7*durationPerTest) { Thread.sleep(durationPerTest); switch(state) { case 0: + // child glWindow2 hide + Assert.assertEquals(true, glWindow1.isVisible()); + Assert.assertEquals(true, glWindow2.isVisible()); + glWindow2.setVisible(false); + Assert.assertEquals(false, glWindow2.isVisible()); + Assert.assertEquals(true, glWindow1.isVisible()); + break; + + case 1: + // child glWindow2 show + Assert.assertEquals(true, glWindow1.isVisible()); + Assert.assertEquals(false, glWindow2.isVisible()); + glWindow2.setVisible(true); Assert.assertEquals(true, glWindow2.isVisible()); - reparentAction = glWindow2.reparentWindow(null, reparentRecreate); + Assert.assertEquals(true, glWindow1.isVisible()); + break; + + case 2: + // glWindow2 --> top + Assert.assertEquals(true, glWindow2.isVisible()); + reparentAction = glWindow2.reparentWindow(null, -1, -1, reparentHints); Assert.assertTrue(Window.ReparentOperation.ACTION_INVALID != reparentAction); Assert.assertEquals(true, glWindow2.isVisible()); Assert.assertEquals(true, glWindow2.isNativeValid()); + Thread.sleep(20*16); // Wait for a few frames since counter could be reset - 20 frames at 60Hz System.err.println("Frames for reparentWindow(parent, "+reparentRecreate+"): "+reparentAction+", B2: "+glWindow2.getTotalFPSFrames()); Assert.assertTrue(0 < glWindow2.getTotalFPSFrames()); + Assert.assertNull(glWindow2.getParent()); Assert.assertSame(screen1,glWindow2.getScreen()); Assert.assertSame(display1,glWindow2.getScreen().getDisplay()); Assert.assertEquals(1,Display.getActiveDisplayNumber()); break; - case 1: + + case 3: + // top-level glWindow2 hide + Assert.assertEquals(true, glWindow1.isVisible()); + Assert.assertEquals(true, glWindow2.isVisible()); + glWindow2.setVisible(false); + Assert.assertEquals(false, glWindow2.isVisible()); + Assert.assertEquals(true, glWindow1.isVisible()); + break; + + case 4: + // top-level glWindow2 show + Assert.assertEquals(true, glWindow1.isVisible()); + Assert.assertEquals(false, glWindow2.isVisible()); + glWindow2.setVisible(true); Assert.assertEquals(true, glWindow2.isVisible()); - reparentAction = glWindow2.reparentWindow(glWindow1, reparentRecreate); + Assert.assertEquals(true, glWindow1.isVisible()); + break; + + case 5: + // glWindow2 -- child --> glWindow1: compatible + Assert.assertEquals(true, glWindow2.isVisible()); + reparentAction = glWindow2.reparentWindow(glWindow1, -1, -1, reparentHints); Assert.assertTrue(Window.ReparentOperation.ACTION_INVALID != reparentAction); Assert.assertEquals(true, glWindow2.isVisible()); Assert.assertEquals(true, glWindow2.isNativeValid()); + Thread.sleep(20*16); // Wait for a few frames since counter could be reset - 20 frames at 60Hz System.err.println("Frames for reparentWindow(parent, "+reparentRecreate+"): "+reparentAction+", B3 "+glWindow2.getTotalFPSFrames()); Assert.assertTrue(0 < glWindow2.getTotalFPSFrames()); + Assert.assertSame(glWindow1,glWindow2.getParent()); Assert.assertSame(screen1,glWindow2.getScreen()); Assert.assertSame(display1,glWindow2.getScreen().getDisplay()); @@ -648,7 +736,7 @@ public class TestParenting01NEWT extends UITestCase { public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) { Assert.assertNotNull(demo); - Assert.assertNotNull(glWindow); + Assert.assertNotNull(glWindow); if(debug) { MiscUtils.setFieldIfExists(demo, "glDebug", true); MiscUtils.setFieldIfExists(demo, "glTrace", true); @@ -667,14 +755,28 @@ public class TestParenting01NEWT extends UITestCase { } public static void main(String args[]) throws IOException { + boolean asMain = false; for(int i=0; i<args.length; i++) { if(args[i].equals("-time")) { durationPerTest = atoi(args[++i]); + } else if(args[i].equals("-asMain")) { + asMain = true; } } System.err.println("durationPerTest: "+durationPerTest); - String tstname = TestParenting01NEWT.class.getName(); - org.junit.runner.JUnitCore.main(tstname); + if( asMain ) { + try { + TestParenting01NEWT.initClass(); + TestParenting01NEWT m = new TestParenting01NEWT(); + m.test02aReparentTop2WinReparentRecreate(); + m.test01CreateVisibleDestroy(); + } catch (Throwable t ) { + t.printStackTrace(); + } + } else { + String tstname = TestParenting01NEWT.class.getName(); + org.junit.runner.JUnitCore.main(tstname); + } } } diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aAWT.java index de29db417..420a39cb2 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aAWT.java @@ -3,14 +3,14 @@ * * 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 @@ -20,7 +20,7 @@ * 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. @@ -31,6 +31,8 @@ package com.jogamp.opengl.test.junit.newt.parenting; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import java.awt.Button; import java.awt.BorderLayout; @@ -50,6 +52,7 @@ import java.lang.reflect.InvocationTargetException; import com.jogamp.opengl.test.junit.util.*; import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestParenting01aAWT extends UITestCase { static int width, height; static long durationPerTest = 800; @@ -65,7 +68,7 @@ public class TestParenting01aAWT extends UITestCase { } @Test - public void testWindowParenting01CreateVisibleDestroy1() throws InterruptedException, InvocationTargetException { + public void test01WindowParenting01CreateVisibleDestroy1() throws InterruptedException, InvocationTargetException { final GLWindow glWindow1 = GLWindow.create(glCaps); Assert.assertNotNull(glWindow1); Assert.assertEquals(false, glWindow1.isVisible()); @@ -98,22 +101,22 @@ public class TestParenting01aAWT extends UITestCase { container1.add(newtCanvasAWT, BorderLayout.CENTER); frame1.add(container1, BorderLayout.CENTER); - frame1.setSize(width, height); // visible test SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame1.setSize(width, height); frame1.setVisible(true); } }); Assert.assertEquals(newtCanvasAWT.getNativeWindow(),glWindow1.getParent()); final Animator animator1 = new Animator(glWindow1); - animator1.setUpdateFPSFrames(1, null); + animator1.setUpdateFPSFrames(1, null); animator1.start(); Assert.assertTrue(AWTRobotUtil.waitForRealized(glWindow1, true)); Assert.assertTrue(AWTRobotUtil.waitForVisible(glWindow1, true)); - + while(animator1.isAnimating() && animator1.getTotalFPSDuration()<durationPerTest) { Thread.sleep(100); } @@ -123,34 +126,40 @@ public class TestParenting01aAWT extends UITestCase { SwingUtilities.invokeAndWait(new Runnable() { public void run() { frame1.setVisible(false); - } } ); + } } ); Assert.assertEquals(true, glWindow1.isNativeValid()); SwingUtilities.invokeAndWait(new Runnable() { public void run() { frame1.setVisible(true); - } } ); + } } ); Assert.assertEquals(true, glWindow1.isNativeValid()); + final boolean wasOnscreen = glWindow1.getChosenCapabilities().isOnscreen(); + SwingUtilities.invokeAndWait(new Runnable() { public void run() { frame1.remove(newtCanvasAWT); } } ); // Assert.assertNull(glWindow1.getParent()); - Assert.assertEquals(true, glWindow1.isNativeValid()); + if( wasOnscreen ) { + Assert.assertEquals(true, glWindow1.isNativeValid()); + } // else OK to be destroyed - due to offscreen/onscreen transition SwingUtilities.invokeAndWait(new Runnable() { public void run() { frame1.dispose(); } } ); - Assert.assertEquals(true, glWindow1.isNativeValid()); + if( wasOnscreen ) { + Assert.assertEquals(true, glWindow1.isNativeValid()); + } // else OK to be destroyed - due to offscreen/onscreen transition glWindow1.destroy(); Assert.assertEquals(false, glWindow1.isNativeValid()); } @Test - public void testWindowParenting02CreateVisibleDestroy2Defered() throws InterruptedException, InvocationTargetException { + public void test02WindowParenting02CreateVisibleDestroy2Defered() throws InterruptedException, InvocationTargetException { final GLWindow glWindow1 = GLWindow.create(glCaps); Assert.assertNotNull(glWindow1); Assert.assertEquals(false, glWindow1.isVisible()); @@ -168,11 +177,11 @@ public class TestParenting01aAWT extends UITestCase { final Frame frame = new Frame("AWT Parent Frame"); Assert.assertNotNull(frame); - frame.setSize(width, height); // visible test SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame.setSize(width, height); frame.setVisible(true); } }); @@ -202,7 +211,7 @@ public class TestParenting01aAWT extends UITestCase { } @Test - public void testWindowParenting02CreateVisibleDestroy3Odd() throws InterruptedException, InvocationTargetException { + public void test03WindowParenting02CreateVisibleDestroy3Odd() throws InterruptedException, InvocationTargetException { GLWindow glWindow1 = GLWindow.create(glCaps); GLEventListener demo1 = new RedSquareES2(); setDemoFields(demo1, glWindow1, false); @@ -212,11 +221,11 @@ public class TestParenting01aAWT extends UITestCase { final Frame frame = new Frame("AWT Parent Frame"); Assert.assertNotNull(frame); - frame.setSize(width, height); // visible test SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame.setSize(width, height); frame.setVisible(true); } }); @@ -247,7 +256,7 @@ public class TestParenting01aAWT extends UITestCase { } @Test - public void testWindowParenting03ReparentNewtWin2Top() throws InterruptedException, InvocationTargetException { + public void test04WindowParenting03ReparentNewtWin2Top() throws InterruptedException, InvocationTargetException { GLWindow glWindow1 = GLWindow.create(glCaps); GLEventListener demo1 = new RedSquareES2(); setDemoFields(demo1, glWindow1, false); @@ -256,10 +265,10 @@ public class TestParenting01aAWT extends UITestCase { final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow1); final Frame frame = new Frame("AWT Parent Frame"); - frame.setSize(width, height); - frame.setLocation(640, 480); SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame.setSize(width, height); + frame.setLocation(640, 480); frame.setVisible(true); } }); @@ -274,7 +283,7 @@ public class TestParenting01aAWT extends UITestCase { Assert.assertEquals(newtCanvasAWT.getNativeWindow(),glWindow1.getParent()); Animator animator1 = new Animator(glWindow1); - animator1.setUpdateFPSFrames(1, null); + animator1.setUpdateFPSFrames(1, null); animator1.start(); int state = 0; @@ -282,12 +291,12 @@ public class TestParenting01aAWT extends UITestCase { Thread.sleep(durationPerTest); switch(state) { case 0: - glWindow1.reparentWindow(null); + System.err.println("Reparent CHILD -> TOP: "+glWindow1.reparentWindow(null, -1, -1, 0 /* hints */)); Assert.assertEquals(true, glWindow1.isNativeValid()); Assert.assertNull(glWindow1.getParent()); break; case 1: - glWindow1.reparentWindow(newtCanvasAWT.getNativeWindow()); + System.err.println("Reparent TOP -> CHILD: "+glWindow1.reparentWindow(newtCanvasAWT.getNativeWindow(), -1, -1, 0 /* hints */)); Assert.assertEquals(true, glWindow1.isNativeValid()); Assert.assertEquals(newtCanvasAWT.getNativeWindow(),glWindow1.getParent()); break; @@ -306,7 +315,7 @@ public class TestParenting01aAWT extends UITestCase { } @Test - public void testWindowParenting04ReparentNewtWin2TopLayouted() throws InterruptedException, InvocationTargetException { + public void test05WindowParenting04ReparentNewtWin2TopLayouted() throws InterruptedException, InvocationTargetException { GLWindow glWindow1 = GLWindow.create(glCaps); GLEventListener demo1 = new RedSquareES2(); setDemoFields(demo1, glWindow1, false); @@ -320,11 +329,11 @@ public class TestParenting01aAWT extends UITestCase { frame.add(new Button("South"), BorderLayout.SOUTH); frame.add(new Button("East"), BorderLayout.EAST); frame.add(new Button("West"), BorderLayout.WEST); - frame.setSize(width, height); - frame.setLocation(640, 480); - + SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame.setSize(width, height); + frame.setLocation(640, 480); frame.setVisible(true); } }); @@ -335,11 +344,11 @@ public class TestParenting01aAWT extends UITestCase { frame.validate(); } }); - + Assert.assertEquals(newtCanvasAWT.getNativeWindow(),glWindow1.getParent()); Animator animator1 = new Animator(glWindow1); - animator1.setUpdateFPSFrames(1, null); + animator1.setUpdateFPSFrames(1, null); animator1.start(); int state = 0; @@ -347,12 +356,12 @@ public class TestParenting01aAWT extends UITestCase { Thread.sleep(durationPerTest); switch(state) { case 0: - glWindow1.reparentWindow(null); + System.err.println("Reparent CHILD -> TOP: "+glWindow1.reparentWindow(null, -1, -1, 0 /* hints */)); Assert.assertEquals(true, glWindow1.isNativeValid()); Assert.assertNull(glWindow1.getParent()); break; case 1: - glWindow1.reparentWindow(newtCanvasAWT.getNativeWindow()); + System.err.println("Reparent TOP -> CHILD: "+glWindow1.reparentWindow(newtCanvasAWT.getNativeWindow(), -1, -1, 0 /* hints */)); Assert.assertEquals(true, glWindow1.isNativeValid()); Assert.assertEquals(newtCanvasAWT.getNativeWindow(),glWindow1.getParent()); break; @@ -371,7 +380,7 @@ public class TestParenting01aAWT extends UITestCase { } @Test - public void testWindowParenting05ReparentAWTWinHopFrame2Frame() throws InterruptedException, InvocationTargetException { + public void test06WindowParenting05ReparentAWTWinHopFrame2Frame() throws InterruptedException, InvocationTargetException { GLWindow glWindow1 = GLWindow.create(glCaps); glWindow1.setUndecorated(true); GLEventListener demo1 = new RedSquareES2(); @@ -386,10 +395,10 @@ public class TestParenting01aAWT extends UITestCase { frame1.add(new Button("South"), BorderLayout.SOUTH); frame1.add(new Button("East"), BorderLayout.EAST); frame1.add(new Button("West"), BorderLayout.WEST); - frame1.setSize(width, height); - frame1.setLocation(0, 0); SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame1.setSize(width, height); + frame1.setLocation(0, 0); frame1.setVisible(true); } }); @@ -400,10 +409,10 @@ public class TestParenting01aAWT extends UITestCase { frame2.add(new Button("South"), BorderLayout.SOUTH); frame2.add(new Button("East"), BorderLayout.EAST); frame2.add(new Button("West"), BorderLayout.WEST); - frame2.setSize(width, height); - frame2.setLocation(640, 480); SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame2.setSize(width, height); + frame2.setLocation(640, 480); frame2.setVisible(true); } }); @@ -418,7 +427,7 @@ public class TestParenting01aAWT extends UITestCase { Assert.assertEquals(newtCanvasAWT.getNativeWindow(),glWindow1.getParent()); Animator animator1 = new Animator(glWindow1); - animator1.setUpdateFPSFrames(1, null); + animator1.setUpdateFPSFrames(1, null); animator1.start(); int state = 0; @@ -433,7 +442,7 @@ public class TestParenting01aAWT extends UITestCase { frame1.validate(); frame2.validate(); } - }); + }); break; case 1: SwingUtilities.invokeAndWait(new Runnable() { @@ -443,7 +452,7 @@ public class TestParenting01aAWT extends UITestCase { frame2.validate(); frame1.validate(); } - }); + }); break; } state++; @@ -462,7 +471,7 @@ public class TestParenting01aAWT extends UITestCase { public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) { Assert.assertNotNull(demo); - Assert.assertNotNull(glWindow); + Assert.assertNotNull(glWindow); if(debug) { MiscUtils.setFieldIfExists(demo, "glDebug", true); MiscUtils.setFieldIfExists(demo, "glTrace", true); @@ -489,17 +498,7 @@ public class TestParenting01aAWT extends UITestCase { } } String tstname = TestParenting01aAWT.class.getName(); - org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] { - tstname, - "filtertrace=true", - "haltOnError=false", - "haltOnFailure=false", - "showoutput=true", - "outputtoformatters=true", - "logfailedtests=true", - "logtestlistenerevents=true", - "formatter=org.apache.tools.ant.taskdefs.optional.junit.PlainJUnitResultFormatter", - "formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,TEST-"+tstname+".xml" } ); + org.junit.runner.JUnitCore.main(tstname); } } diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aSWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aSWT.java new file mode 100644 index 000000000..4bb64c766 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aSWT.java @@ -0,0 +1,218 @@ +/** + * Copyright 2012 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.parenting; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.junit.After; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.nativewindow.swt.SWTAccessor; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Window; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.newt.swt.NewtCanvasSWT; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Simple visibility test .. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestParenting01aSWT extends UITestCase { + static int width, height; + static long durationPerTest = 800; + static GLCapabilities glCaps; + + Display display = null; + Shell shell = null; + Composite composite1 = null; + com.jogamp.newt.Display swtNewtDisplay = null; + + @BeforeClass + public static void initClass() { + width = 640; + height = 480; + glCaps = new GLCapabilities(null); + } + + @Before + public void init() { + SWTAccessor.invoke(true, new Runnable() { + public void run() { + display = new Display(); + Assert.assertNotNull( display ); + shell = new Shell( display ); + Assert.assertNotNull( shell ); + shell.setLayout( new FillLayout() ); + composite1 = new Composite( shell, SWT.NONE ); + composite1.setLayout( new FillLayout() ); + Assert.assertNotNull( composite1 ); + }}); + swtNewtDisplay = NewtFactory.createDisplay(null, false); // no-reuse + } + + @After + public void release() { + Assert.assertNotNull( display ); + Assert.assertNotNull( shell ); + Assert.assertNotNull( composite1 ); + try { + SWTAccessor.invoke(true, new Runnable() { + public void run() { + composite1.dispose(); + shell.dispose(); + display.dispose(); + }}); + } + catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + swtNewtDisplay = null; + display = null; + shell = null; + composite1 = null; + } + + @Test + public void testWindowParenting01CreateVisibleDestroy1() throws InterruptedException, InvocationTargetException { + + com.jogamp.newt.Screen screen = NewtFactory.createScreen(swtNewtDisplay, 0); + GLWindow glWindow1 = GLWindow.create(screen, glCaps); + Assert.assertNotNull(glWindow1); + Assert.assertEquals(false, glWindow1.isVisible()); + Assert.assertEquals(false, glWindow1.isNativeValid()); + Assert.assertNull(glWindow1.getParent()); + glWindow1.setTitle("testWindowParenting01CreateVisibleDestroy"); + GLEventListener demo1 = new RedSquareES2(); + setDemoFields(demo1, glWindow1, false); + glWindow1.addGLEventListener(demo1); + + final NewtCanvasSWT canvas1 = NewtCanvasSWT.create( composite1, 0, glWindow1 ); + Assert.assertNotNull(canvas1); + Assert.assertEquals(false, glWindow1.isVisible()); + Assert.assertEquals(false, glWindow1.isNativeValid()); + Assert.assertNull(glWindow1.getParent()); + + SWTAccessor.invoke(true, new Runnable() { + public void run() { + shell.setText( getSimpleTestName(".") ); + shell.setSize( 640, 480 ); + shell.open(); + } + }); + + // visible test + Assert.assertEquals(canvas1.getNativeWindow(),glWindow1.getParent()); + + for(int i=0; i*10<durationPerTest; i++) { + if( !display.readAndDispatch() ) { + // blocks on linux .. display.sleep(); + Thread.sleep(10); + } + } + + SWTAccessor.invoke(true, new Runnable() { + public void run() { + canvas1.setVisible(false); + } + }); + Assert.assertEquals(true, glWindow1.isNativeValid()); + + SWTAccessor.invoke(true, new Runnable() { + public void run() { + canvas1.setVisible(true); + } + }); + Assert.assertEquals(true, glWindow1.isNativeValid()); + + canvas1.dispose(); + + Assert.assertEquals(false, glWindow1.isNativeValid()); + } + + public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) { + Assert.assertNotNull(demo); + Assert.assertNotNull(glWindow); + Window window = glWindow.getDelegatedWindow(); + if(debug) { + MiscUtils.setFieldIfExists(demo, "glDebug", true); + MiscUtils.setFieldIfExists(demo, "glTrace", true); + } + if(!MiscUtils.setFieldIfExists(demo, "window", window)) { + MiscUtils.setFieldIfExists(demo, "glWindow", glWindow); + } + } + + static int atoi(String a) { + int i=0; + try { + i = Integer.parseInt(a); + } catch (Exception ex) { ex.printStackTrace(); } + return i; + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + durationPerTest = atoi(args[++i]); + } + } + String tstname = TestParenting01aSWT.class.getName(); + org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] { + tstname, + "filtertrace=true", + "haltOnError=false", + "haltOnFailure=false", + "showoutput=true", + "outputtoformatters=true", + "logfailedtests=true", + "logtestlistenerevents=true", + "formatter=org.apache.tools.ant.taskdefs.optional.junit.PlainJUnitResultFormatter", + "formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,TEST-"+tstname+".xml" } ); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01bAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01bAWT.java index d98a540ec..598e5f10f 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01bAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01bAWT.java @@ -3,14 +3,14 @@ * * 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 @@ -20,17 +20,19 @@ * 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.parenting; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import java.awt.Button; import java.awt.BorderLayout; @@ -51,6 +53,7 @@ import java.lang.reflect.InvocationTargetException; import com.jogamp.opengl.test.junit.util.*; import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestParenting01bAWT extends UITestCase { static int width, height; static long durationPerTest = 800; @@ -65,16 +68,16 @@ public class TestParenting01bAWT extends UITestCase { } @Test - public void testWindowParenting05ReparentAWTWinHopFrame2FrameFPS25Animator() throws InterruptedException, InvocationTargetException { - testWindowParenting05ReparentAWTWinHopFrame2FrameImpl(25); + public void test01AWTWinHopFrame2FrameFPS25Animator() throws InterruptedException, InvocationTargetException { + testAWTWinHopFrame2FrameImpl(25); } @Test - public void testWindowParenting05ReparentAWTWinHopFrame2FrameStdAnimator() throws InterruptedException, InvocationTargetException { - testWindowParenting05ReparentAWTWinHopFrame2FrameImpl(0); + public void test02AWTWinHopFrame2FrameStdAnimator() throws InterruptedException, InvocationTargetException { + testAWTWinHopFrame2FrameImpl(0); } - public void testWindowParenting05ReparentAWTWinHopFrame2FrameImpl(int fps) throws InterruptedException, InvocationTargetException { + public void testAWTWinHopFrame2FrameImpl(int fps) throws InterruptedException, InvocationTargetException { GLWindow glWindow1 = GLWindow.create(glCaps); glWindow1.setUndecorated(true); GLEventListener demo1 = new RedSquareES2(); @@ -82,18 +85,18 @@ public class TestParenting01bAWT extends UITestCase { glWindow1.addGLEventListener(demo1); final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow1); - + final Frame frame1 = new Frame("AWT Parent Frame"); frame1.setLayout(new BorderLayout()); frame1.add(new Button("North"), BorderLayout.NORTH); frame1.add(new Button("South"), BorderLayout.SOUTH); frame1.add(new Button("East"), BorderLayout.EAST); frame1.add(new Button("West"), BorderLayout.WEST); - frame1.setSize(width, height); - frame1.setLocation(0, 0); SwingUtilities.invokeAndWait(new Runnable() { public void run() { - frame1.setVisible(true); + frame1.setSize(width, height); + frame1.setLocation(0, 0); + frame1.setVisible(true); } }); @@ -103,11 +106,11 @@ public class TestParenting01bAWT extends UITestCase { frame2.add(new Button("South"), BorderLayout.SOUTH); frame2.add(new Button("East"), BorderLayout.EAST); frame2.add(new Button("West"), BorderLayout.WEST); - frame2.setSize(width, height); - frame2.setLocation(640, 480); SwingUtilities.invokeAndWait(new Runnable() { public void run() { - frame2.setVisible(true); + frame2.setSize(width, height); + frame2.setLocation(640, 480); + frame2.setVisible(true); } }); @@ -139,7 +142,7 @@ public class TestParenting01bAWT extends UITestCase { frame1.validate(); frame2.validate(); } - }); + }); break; case 1: SwingUtilities.invokeAndWait(new Runnable() { @@ -149,7 +152,7 @@ public class TestParenting01bAWT extends UITestCase { frame2.validate(); frame1.validate(); } - }); + }); break; } } diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01cAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01cAWT.java index dfd0787e7..1d7401728 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01cAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01cAWT.java @@ -31,6 +31,8 @@ package com.jogamp.opengl.test.junit.newt.parenting; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import java.awt.Button; import java.awt.BorderLayout; @@ -50,6 +52,7 @@ import java.lang.reflect.InvocationTargetException; import com.jogamp.opengl.test.junit.util.*; import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestParenting01cAWT extends UITestCase { static int width, height; static long durationPerTest = 800; @@ -63,7 +66,7 @@ public class TestParenting01cAWT extends UITestCase { } @Test - public void testWindowParenting01CreateVisibleDestroy1() throws InterruptedException, InvocationTargetException { + public void test01CreateVisibleDestroy1() throws InterruptedException, InvocationTargetException { int i; GLWindow glWindow1 = GLWindow.create(glCaps); @@ -98,11 +101,11 @@ public class TestParenting01cAWT extends UITestCase { container1.add(newtCanvasAWT, BorderLayout.CENTER); frame1.add(container1, BorderLayout.CENTER); - frame1.setSize(width, height); // visible test SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame1.setSize(width, height); frame1.setVisible(true); } }); @@ -126,26 +129,32 @@ public class TestParenting01cAWT extends UITestCase { }); Assert.assertEquals(true, glWindow1.isNativeValid()); + final boolean wasOnscreen = glWindow1.getChosenCapabilities().isOnscreen(); + SwingUtilities.invokeAndWait(new Runnable() { public void run() { frame1.remove(newtCanvasAWT); } }); // Assert.assertNull(glWindow1.getParent()); - Assert.assertEquals(true, glWindow1.isNativeValid()); + if( wasOnscreen ) { + Assert.assertEquals(true, glWindow1.isNativeValid()); + } // else OK to be destroyed - due to offscreen/onscreen transition SwingUtilities.invokeAndWait(new Runnable() { public void run() { frame1.dispose(); } } ); - Assert.assertEquals(true, glWindow1.isNativeValid()); + if( wasOnscreen ) { + Assert.assertEquals(true, glWindow1.isNativeValid()); + } // else OK to be destroyed - due to offscreen/onscreen transition glWindow1.destroy(); Assert.assertEquals(false, glWindow1.isNativeValid()); } @Test - public void testWindowParenting05ReparentAWTWinHopFrame2Frame() throws InterruptedException, InvocationTargetException { + public void test02AWTWinHopFrame2Frame() throws InterruptedException, InvocationTargetException { GLWindow glWindow1 = GLWindow.create(glCaps); glWindow1.setUndecorated(true); GLEventListener demo1 = new RedSquareES2(); @@ -160,10 +169,10 @@ public class TestParenting01cAWT extends UITestCase { frame1.add(new Button("South"), BorderLayout.SOUTH); frame1.add(new Button("East"), BorderLayout.EAST); frame1.add(new Button("West"), BorderLayout.WEST); - frame1.setSize(width, height); - frame1.setLocation(0, 0); SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame1.setSize(width, height); + frame1.setLocation(0, 0); frame1.setVisible(true); } }); @@ -174,10 +183,10 @@ public class TestParenting01cAWT extends UITestCase { frame2.add(new Button("South"), BorderLayout.SOUTH); frame2.add(new Button("East"), BorderLayout.EAST); frame2.add(new Button("West"), BorderLayout.WEST); - frame2.setSize(width, height); - frame2.setLocation(640, 480); SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame2.setSize(width, height); + frame2.setLocation(640, 480); frame2.setVisible(true); } }); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01cSwingAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01cSwingAWT.java index 22ed7c6fd..4d5c3b25d 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01cSwingAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01cSwingAWT.java @@ -33,6 +33,8 @@ import java.lang.reflect.*; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import java.awt.Button; import java.awt.BorderLayout; @@ -53,6 +55,7 @@ import java.io.IOException; import com.jogamp.opengl.test.junit.util.*; import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestParenting01cSwingAWT extends UITestCase { static int width, height; static long durationPerTest = 800; @@ -66,8 +69,59 @@ public class TestParenting01cSwingAWT extends UITestCase { glCaps = new GLCapabilities(null); } + static class GLDisturbanceAction implements Runnable { + public boolean isRunning = false; + private volatile boolean shallStop = false; + private final GLAutoDrawable glad; + private final GLRunnable glRunnable; + + public GLDisturbanceAction(GLAutoDrawable glad) { + this.glad = glad; + this.glRunnable = new GLRunnableDummy(); + } + + public void waitUntilRunning() { + synchronized(this) { + while(!isRunning) { + try { + this.wait(); + } catch (InterruptedException e) { e.printStackTrace(); } + } + } + } + + public void stopAndWaitUntilDone() { + shallStop = true; + synchronized(this) { + while(isRunning) { + try { + this.wait(); + } catch (InterruptedException e) { e.printStackTrace(); } + } + } + } + + public void run() { + synchronized(this) { + isRunning = true; + this.notifyAll(); + System.err.println("$"); + } + while(!shallStop) { + try { + glad.invoke(true, glRunnable); + Thread.sleep(100); + } catch (Throwable t) {} + } + synchronized(this) { + isRunning = false; + this.notifyAll(); + } + } + } + @Test - public void testWindowParenting01CreateVisibleDestroy1() throws InterruptedException, InvocationTargetException { + public void test01CreateVisibleDestroy1() throws InterruptedException, InvocationTargetException { /** * JFrame . JPanel . Container . NewtCanvasAWT . GLWindow */ @@ -84,22 +138,9 @@ public class TestParenting01cSwingAWT extends UITestCase { animator1.setUpdateFPSFrames(1, null); animator1.start(); - final GLWindow _glWindow1 = glWindow1; - final GLRunnable _glRunnable = new GLRunnableDummy(); - Thread disturbanceThread = new Thread(new Runnable() { - public void run() { - System.out.println("$"); - while(true) - { - try { - _glWindow1.invoke(true, _glRunnable); - Thread.sleep(100); - } catch (Throwable t) {} - } - } - }); - disturbanceThread.start(); - + final GLDisturbanceAction disturbanceAction = new GLDisturbanceAction(glWindow1); + new Thread(disturbanceAction).start(); + disturbanceAction.waitUntilRunning(); final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow1); Assert.assertNotNull(newtCanvasAWT); @@ -127,10 +168,11 @@ public class TestParenting01cSwingAWT extends UITestCase { // jFrame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jFrame1.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // equivalent to Frame, use windowClosing event! jFrame1.setContentPane(jPanel1); - jFrame1.setSize(width, height); - System.out.println("Demos: 1 - Visible"); + System.err.println("Demos: 1 - Visible"); SwingUtilities.invokeAndWait(new Runnable() { public void run() { + jFrame1.setSize(width, height); + jFrame1.validate(); jFrame1.setVisible(true); } }); @@ -143,44 +185,58 @@ public class TestParenting01cSwingAWT extends UITestCase { while(animator1.isAnimating() && animator1.getTotalFPSDuration()<durationPerTest) { Thread.sleep(100); } - System.out.println("Demos: 2 - StopAnimator"); + System.err.println("Demos: 2 - StopAnimator"); animator1.stop(); Assert.assertEquals(false, animator1.isAnimating()); SwingUtilities.invokeAndWait(new Runnable() { public void run() { - System.out.println("Demos: 3 - !Visible"); + System.err.println("Demos: 3 - !Visible"); jFrame1.setVisible(false); } }); Assert.assertEquals(true, AWTRobotUtil.waitForVisible(glWindow1, false)); SwingUtilities.invokeAndWait(new Runnable() { public void run() { - System.out.println("Demos: 4 - Visible"); + System.err.println("Demos: 4 - Visible"); jFrame1.setVisible(true); } }); Assert.assertEquals(true, AWTRobotUtil.waitForVisible(glWindow1, true)); + final boolean wasOnscreen = glWindow1.getChosenCapabilities().isOnscreen(); + + // Always recommended to remove our native parented Window + // from the AWT resources before destruction, since it could lead + // to a BadMatch X11 error w/o. SwingUtilities.invokeAndWait(new Runnable() { public void run() { - System.out.println("Demos: 5 - X Container"); + System.err.println("Demos: 5 - X Container"); jPanel1.remove(container1); jFrame1.validate(); } }); - Assert.assertEquals(true, glWindow1.isNativeValid()); + if( wasOnscreen ) { + Assert.assertEquals(true, glWindow1.isNativeValid()); + } // else OK to be destroyed - due to offscreen/onscreen transition SwingUtilities.invokeAndWait(new Runnable() { public void run() { + System.err.println("Demos: 6 - X Frame"); jFrame1.dispose(); } }); - Assert.assertEquals(true, glWindow1.isNativeValid()); + if( wasOnscreen ) { + Assert.assertEquals(true, glWindow1.isNativeValid()); + } // else OK to be destroyed - due to offscreen/onscreen transition + System.err.println("Demos: 7 - X GLWindow"); glWindow1.destroy(); Assert.assertEquals(false, glWindow1.isNativeValid()); + + System.err.println("Demos: 8 - X DisturbanceThread"); + disturbanceAction.stopAndWaitUntilDone(); } @Test - public void testWindowParenting05ReparentAWTWinHopFrame2Frame() throws InterruptedException, InvocationTargetException { + public void test02AWTWinHopFrame2Frame() throws InterruptedException, InvocationTargetException { /** * JFrame . JPanel . Container . NewtCanvasAWT . GLWindow */ @@ -192,26 +248,33 @@ public class TestParenting01cSwingAWT extends UITestCase { glWindow1.setTitle("testWindowParenting01CreateVisibleDestroy"); GLEventListener demo1 = new RedSquareES2(); setDemoFields(demo1, glWindow1, false); + /* + glWindow1.addGLEventListener(new GLEventListener() { + @Override + public void init(GLAutoDrawable drawable) { + System.err.println("XXX init"); + } + @Override + public void dispose(GLAutoDrawable drawable) { + System.err.println("XXX dispose"); + // Thread.dumpStack(); + } + @Override + public void display(GLAutoDrawable drawable) {} + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + System.err.println("XXX reshape"); + // Thread.dumpStack(); + } + }); */ glWindow1.addGLEventListener(demo1); Animator animator1 = new Animator(glWindow1); animator1.setUpdateFPSFrames(1, null); animator1.start(); - - final GLWindow _glWindow1 = glWindow1; - final GLRunnable _glRunnable = new GLRunnableDummy(); - Thread disturbanceThread = new Thread(new Runnable() { - public void run() { - System.out.println("$"); - while(true) - { - try { - _glWindow1.invoke(true, _glRunnable); - Thread.sleep(100); - } catch (Throwable t) {} - } - } - }); - disturbanceThread.start(); + + final GLDisturbanceAction disturbanceAction = new GLDisturbanceAction(glWindow1); + new Thread(disturbanceAction).start(); + disturbanceAction.waitUntilRunning(); final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow1); Assert.assertNotNull(newtCanvasAWT); @@ -239,10 +302,10 @@ public class TestParenting01cSwingAWT extends UITestCase { // jFrame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jFrame1.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // equivalent to Frame, use windowClosing event! jFrame1.setContentPane(jPanel1); - jFrame1.setLocation(0, 0); - jFrame1.setSize(width, height); SwingUtilities.invokeAndWait(new Runnable() { public void run() { + jFrame1.setLocation(0, 0); + jFrame1.setSize(width, height); jFrame1.setVisible(true); } }); @@ -258,10 +321,10 @@ public class TestParenting01cSwingAWT extends UITestCase { // jFrame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jFrame2.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // equivalent to Frame, use windowClosing event! jFrame2.setContentPane(jPanel2); - jFrame2.setLocation(640, 480); - jFrame2.setSize(width, height); SwingUtilities.invokeAndWait(new Runnable() { public void run() { + jFrame2.setLocation(640, 480); + jFrame2.setSize(width, height); jFrame2.setVisible(true); } }); @@ -269,6 +332,8 @@ public class TestParenting01cSwingAWT extends UITestCase { // visible test Assert.assertEquals(newtCanvasAWT.getNativeWindow(),glWindow1.getParent()); + final boolean wasOnscreen = glWindow1.getChosenCapabilities().isOnscreen(); + int state = 0; while(animator1.isAnimating() && animator1.getTotalFPSDuration()<3*durationPerTest) { Thread.sleep(durationPerTest); @@ -298,22 +363,50 @@ public class TestParenting01cSwingAWT extends UITestCase { animator1.stop(); Assert.assertEquals(false, animator1.isAnimating()); + /* + * Always recommended to remove our native parented Window + * from the AWT resources before destruction, since it could lead + * to a BadMatch X11 error w/o (-> XAWT related). + * Or ensure old/new parent is visible, see below. + * + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + System.err.println("Demos: 1 - X Container 1"); + container1.remove(newtCanvasAWT); + jFrame1.validate(); + System.err.println("Demos: 1 - X Container 2"); + jPanel2.remove(newtCanvasAWT); + jFrame2.validate(); + } }); */ + /* + * Invisible X11 windows may also case BadMatch (-> XAWT related) + */ SwingUtilities.invokeAndWait(new Runnable() { public void run() { + System.err.println("Demos: 2 - !visible"); jFrame1.setVisible(false); + System.err.println("Demos: 3 - !visible"); jFrame2.setVisible(false); } }); Assert.assertEquals(true, glWindow1.isNativeValid()); SwingUtilities.invokeAndWait(new Runnable() { public void run() { + System.err.println("Demos: 4 - X frame"); jFrame1.dispose(); + System.err.println("Demos: 5 - X frame"); jFrame2.dispose(); } }); - Assert.assertEquals(true, glWindow1.isNativeValid()); + if( wasOnscreen ) { + Assert.assertEquals(true, glWindow1.isNativeValid()); + } // else OK to be destroyed - due to offscreen/onscreen transition + System.err.println("Demos: 6 - X GLWindow"); glWindow1.destroy(); Assert.assertEquals(false, glWindow1.isNativeValid()); + + System.err.println("Demos: 7 - X DisturbanceThread"); + disturbanceAction.stopAndWaitUntilDone(); } public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) { @@ -345,8 +438,10 @@ public class TestParenting01cSwingAWT extends UITestCase { waitReparent = atoi(args[++i]); } } - System.out.println("durationPerTest "+durationPerTest); - System.out.println("waitReparent "+waitReparent); + System.err.println("durationPerTest "+durationPerTest); + System.err.println("waitReparent "+waitReparent); + org.junit.runner.JUnitCore.main(TestParenting01cSwingAWT.class.getName()); + /** String tstname = TestParenting01cSwingAWT.class.getName(); org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] { tstname, @@ -358,7 +453,7 @@ public class TestParenting01cSwingAWT extends UITestCase { "logfailedtests=true", "logtestlistenerevents=true", "formatter=org.apache.tools.ant.taskdefs.optional.junit.PlainJUnitResultFormatter", - "formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,TEST-"+tstname+".xml" } ); + "formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,TEST-"+tstname+".xml" } ); */ } } diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01dAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01dAWT.java new file mode 100644 index 000000000..288918e48 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01dAWT.java @@ -0,0 +1,251 @@ +/** + * Copyright 2013 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.parenting; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import java.awt.Button; +import java.awt.BorderLayout; +import java.awt.Container; +import java.awt.Frame; + +import javax.media.opengl.*; +import javax.swing.SwingUtilities; + +import com.jogamp.newt.Window; +import com.jogamp.newt.opengl.*; +import com.jogamp.newt.awt.NewtCanvasAWT; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +import com.jogamp.opengl.test.junit.util.*; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; + +/** + * Test GL preservation case for reparenting. + * <p> + * Also simulates adding and attaching an already created GLWindow + * to a NewtCanvasAWT in recreation mode, where the GL state shall be preserved. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestParenting01dAWT extends UITestCase { + static int width, height; + static long durationPerTest = 800; + static GLCapabilities glCaps; + + @BeforeClass + public static void initClass() throws InterruptedException { + width = 640; + height = 480; + glCaps = new GLCapabilities(null); + // Thread.sleep(10000); + } + + static class MyGLEventListenerCounter extends GLEventListenerCounter { + @Override + public void init(GLAutoDrawable drawable) { + super.init(drawable); + System.err.println("MyGLEventListenerCounter.init: "+this); + // Thread.dumpStack(); + } + + @Override + public void dispose(GLAutoDrawable drawable) { + super.dispose(drawable); + System.err.println("MyGLEventListenerCounter.dispose: "+this); + // Thread.dumpStack(); + } + } + + @Test + public void test01GLWindowReparentRecreateNoPreserve() throws InterruptedException, InvocationTargetException { + testGLWindowInvisibleReparentRecreateImpl(false /* triggerPreserveGLState */); + } + + @Test + public void test02GLWindowReparentRecreateGLPreserve() throws InterruptedException, InvocationTargetException { + testGLWindowInvisibleReparentRecreateImpl(true /* triggerPreserveGLState */); + } + + private void testGLWindowInvisibleReparentRecreateImpl(boolean triggerPreserveGLState) throws InterruptedException, InvocationTargetException { + final GLWindow glWindow1 = GLWindow.create(glCaps); + Assert.assertNotNull(glWindow1); + Assert.assertEquals(false, glWindow1.isVisible()); + Assert.assertEquals(false, glWindow1.isNativeValid()); + Assert.assertNull(glWindow1.getParent()); + glWindow1.setTitle("testWindowParenting01CreateVisibleDestroy"); + final MyGLEventListenerCounter glelCounter = new MyGLEventListenerCounter(); + glWindow1.addGLEventListener(glelCounter); + GLEventListener demo1 = new RedSquareES2(); + glWindow1.addGLEventListener(demo1); + Assert.assertEquals("Init Counter Invalid "+glelCounter, 0, glelCounter.initCount); + + final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow1); + Assert.assertNotNull(newtCanvasAWT); + Assert.assertEquals(false, glWindow1.isVisible()); + Assert.assertEquals(false, glWindow1.isNativeValid()); + Assert.assertNull(glWindow1.getParent()); + Assert.assertEquals("Init Counter Invalid "+glelCounter, 0, glelCounter.initCount); + + final Frame frame1 = new Frame("AWT Parent Frame"); + frame1.setLayout(new BorderLayout()); + frame1.add(new Button("North"), BorderLayout.NORTH); + frame1.add(new Button("South"), BorderLayout.SOUTH); + frame1.add(new Button("East"), BorderLayout.EAST); + frame1.add(new Button("West"), BorderLayout.WEST); + + final Container container1 = new Container(); + container1.setLayout(new BorderLayout()); + container1.add(new Button("north"), BorderLayout.NORTH); + container1.add(new Button("south"), BorderLayout.SOUTH); + container1.add(new Button("east"), BorderLayout.EAST); + container1.add(new Button("west"), BorderLayout.WEST); + container1.add(newtCanvasAWT, BorderLayout.CENTER); + + frame1.add(container1, BorderLayout.CENTER); + + // visible test + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame1.setSize(width, height); + frame1.setVisible(true); + } + }); + Assert.assertEquals(newtCanvasAWT.getNativeWindow(),glWindow1.getParent()); + + Assert.assertTrue(AWTRobotUtil.waitForVisible(glWindow1, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(glWindow1, true)); + glWindow1.display(); + Assert.assertEquals("Init Counter Invalid "+glelCounter, 1, glelCounter.initCount); + Assert.assertEquals("Dispose Counter Invalid "+glelCounter, 0, glelCounter.disposeCount); + + final int reparentingHints = Window.REPARENT_HINT_FORCE_RECREATION | + ( triggerPreserveGLState ? Window.REPARENT_HINT_BECOMES_VISIBLE : 0 ); + + // + // Even though the hint REPARENT_HINT_BECOMES_VISIBLE is not set (triggerPrerveGLState == false), + // since GLWindow is visible already the GL state shall be preserved! + // + System.err.println(getSimpleTestName(".")+": Start Reparent #1"); + final Window.ReparentOperation rop1 = glWindow1.reparentWindow(null, -1, -1, reparentingHints); + System.err.println(getSimpleTestName(".")+": Result Reparent #1: "+rop1); + Assert.assertEquals(Window.ReparentOperation.ACTION_NATIVE_CREATION, rop1); + glWindow1.display(); + Assert.assertEquals("Init Counter Invalid (Preserve Failed 1) "+glelCounter, 1, glelCounter.initCount); + Assert.assertEquals("Dispose Counter Invalid (Preserve Failed 1) "+glelCounter, 0, glelCounter.disposeCount); + + // + // The following step is equivalent with adding and attaching an already created GLWindow + // to a NewtCanvasAWT in recreation mode if REPARENT_HINT_BECOMES_VISIBLE hint is set (triggerPrerveGLState == true). + // GL state shall be preserved! + // + glWindow1.setVisible(false); + Assert.assertTrue(AWTRobotUtil.waitForVisible(glWindow1, false)); + System.err.println(getSimpleTestName(".")+": Start Reparent #2"); + final Window.ReparentOperation rop2 = glWindow1.reparentWindow(newtCanvasAWT.getNativeWindow(), -1, -1, reparentingHints); + System.err.println(getSimpleTestName(".")+": Result Reparent #2: "+rop2); + Assert.assertEquals(Window.ReparentOperation.ACTION_NATIVE_CREATION, rop2); + glWindow1.setVisible(true); + Assert.assertTrue(AWTRobotUtil.waitForVisible(glWindow1, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(glWindow1, true)); + glWindow1.display(); + if( triggerPreserveGLState ) { + Assert.assertEquals("Init Counter Invalid (Preserve Failed 2) "+glelCounter, 1, glelCounter.initCount); + Assert.assertEquals("Dispose Counter Invalid (Preserve Failed 2) "+glelCounter, 0, glelCounter.disposeCount); + } else { + Assert.assertEquals("Init Counter Invalid (Preserve Failed 2) "+glelCounter, 2, glelCounter.initCount); + Assert.assertEquals("Dispose Counter Invalid (Preserve Failed 2) "+glelCounter, 1, glelCounter.disposeCount); + } + + final long t0 = System.currentTimeMillis(); + long t1 = t0; + while( t1 - t0 < durationPerTest ) { + Thread.sleep(100); + t1 = System.currentTimeMillis(); + } + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame1.setVisible(false); + } } ); + Assert.assertEquals(true, glWindow1.isNativeValid()); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame1.setVisible(true); + } } ); + Assert.assertEquals(true, glWindow1.isNativeValid()); + + final boolean wasOnscreen = glWindow1.getChosenCapabilities().isOnscreen(); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame1.remove(newtCanvasAWT); + } } ); + // Assert.assertNull(glWindow1.getParent()); + if( wasOnscreen ) { + Assert.assertEquals(true, glWindow1.isNativeValid()); + } // else OK to be destroyed - due to offscreen/onscreen transition + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame1.dispose(); + } } ); + if( wasOnscreen ) { + Assert.assertEquals(true, glWindow1.isNativeValid()); + } // else OK to be destroyed - due to offscreen/onscreen transition + + glWindow1.destroy(); + Assert.assertEquals(false, glWindow1.isNativeValid()); + if( triggerPreserveGLState ) { + Assert.assertEquals("Init Counter Invalid (Preserve Failed 1) "+glelCounter, 1, glelCounter.initCount); + Assert.assertEquals("Dispose Counter Invalid (Preserve Failed 1) "+glelCounter, 1, glelCounter.disposeCount); + } else { + Assert.assertEquals("Init Counter Invalid (Preserve Failed 1) "+glelCounter, 2, glelCounter.initCount); + Assert.assertEquals("Dispose Counter Invalid (Preserve Failed 1) "+glelCounter, 2, glelCounter.disposeCount); + } + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + durationPerTest = MiscUtils.atol(args[++i], durationPerTest); + } + } + String tstname = TestParenting01dAWT.class.getName(); + org.junit.runner.JUnitCore.main(tstname); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting02AWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting02AWT.java index da689cea6..b304a2ce7 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting02AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting02AWT.java @@ -3,14 +3,14 @@ * * 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 @@ -20,17 +20,19 @@ * 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.parenting; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import java.awt.Button; import java.awt.BorderLayout; @@ -49,6 +51,7 @@ import java.lang.reflect.InvocationTargetException; import com.jogamp.opengl.test.junit.util.*; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestParenting02AWT extends UITestCase { static int width, height; static long durationPerTest = 500; @@ -62,22 +65,22 @@ public class TestParenting02AWT extends UITestCase { } @Test - public void testWindowParenting01NewtChildOnAWTParentLayouted() throws InterruptedException, InvocationTargetException { + public void test01NewtChildOnAWTParentLayouted() throws InterruptedException, InvocationTargetException { runNewtChildOnAWTParent(true, false); } @Test - public void testWindowParenting02NewtChildOnAWTParentLayoutedDef() throws InterruptedException, InvocationTargetException { + public void test02NewtChildOnAWTParentLayoutedDef() throws InterruptedException, InvocationTargetException { runNewtChildOnAWTParent(true, true); } @Test - public void testWindowParenting03NewtChildOnAWTParentDirect() throws InterruptedException, InvocationTargetException { + public void test03NewtChildOnAWTParentDirect() throws InterruptedException, InvocationTargetException { runNewtChildOnAWTParent(false, false); } @Test - public void testWindowParenting04NewtChildOnAWTParentDirectDef() throws InterruptedException, InvocationTargetException { + public void test04NewtChildOnAWTParentDirectDef() throws InterruptedException, InvocationTargetException { runNewtChildOnAWTParent(false, true); } @@ -118,11 +121,10 @@ public class TestParenting02AWT extends UITestCase { } } - // frame.setSize(width, height); - frame.setBounds(100, 100, width, height); - javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { + // frame.setSize(width, height); + frame.setBounds(100, 100, width, height); frame.setVisible(true); }}); // X11: true, Windows: false - Assert.assertEquals(true, glWindow.isVisible()); @@ -149,6 +151,8 @@ public class TestParenting02AWT extends UITestCase { glWindow.display(); } while(!glWindow.isNativeValid()) ; + final boolean wasOnscreen = glWindow.getChosenCapabilities().isOnscreen(); + Assert.assertEquals(true, glWindow.isNativeValid()); Assert.assertNotNull(glWindow.getParent()); if(verbose) { @@ -164,7 +168,9 @@ public class TestParenting02AWT extends UITestCase { frame.validate(); }}); Assert.assertEquals(false, glWindow.isVisible()); - Assert.assertEquals(true, glWindow.isNativeValid()); + if( wasOnscreen ) { + Assert.assertEquals(true, glWindow.isNativeValid()); + } // else OK to be destroyed - due to offscreen/onscreen transition Assert.assertNull(glWindow.getParent()); if(verbose) { System.out.println("+++++++++++++++++++ REMOVED!"); @@ -197,7 +203,7 @@ public class TestParenting02AWT extends UITestCase { Thread.sleep(step); duration -= step; - while( null != ( event = (NEWTEvent) eventFifo.get() ) ) { + while( null != ( event = eventFifo.get() ) ) { Window source = (Window) event.getSource(); if(event instanceof KeyEvent) { KeyEvent keyEvent = (KeyEvent) event; @@ -209,7 +215,7 @@ public class TestParenting02AWT extends UITestCase { source.setFullscreen(!source.isFullscreen()); break; } - } + } } } if(verbose) { diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting02NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting02NEWT.java index bc3988338..9f56ecdbf 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting02NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting02NEWT.java @@ -3,14 +3,14 @@ * * 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 @@ -20,18 +20,20 @@ * 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.parenting; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import javax.media.opengl.*; import javax.media.nativewindow.*; @@ -48,6 +50,7 @@ import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; // import com.jogamp.opengl.test.junit.jogl.demos.es1.RedSquareES1; // import com.jogamp.opengl.test.junit.jogl.demos.es1.GearsES1; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestParenting02NEWT extends UITestCase { static int width, height; static long durationPerTest = 500; @@ -89,7 +92,7 @@ public class TestParenting02NEWT extends UITestCase { } @Test - public void testWindowParenting01NewtOnNewtParentChildDraw() throws InterruptedException { + public void test01NewtOnNewtParentChildDraw() throws InterruptedException { GLCapabilities caps = new GLCapabilities(null); Assert.assertNotNull(caps); Display display = NewtFactory.createDisplay(null); // local display @@ -109,10 +112,10 @@ public class TestParenting02NEWT extends UITestCase { glWindow1.setSize(width, height); Assert.assertEquals(width,glWindow1.getWidth()); Assert.assertEquals(height,glWindow1.getHeight()); - glWindow1.setTitle("testWindowParenting01NewtOnNewtParentChildDraw - PARENT"); + glWindow1.setTitle("test01NewtOnNewtParentChildDraw - PARENT"); glWindow1.setPosition(x,y); - glWindow1.addKeyListener(new TraceKeyAdapter(new KeyAction(eventFifo))); - glWindow1.addWindowListener(new TraceWindowAdapter()); + //glWindow1.addKeyListener(new TraceKeyAdapter(new KeyAction(eventFifo))); + //glWindow1.addWindowListener(new TraceWindowAdapter()); GLEventListener demo1 = new RedSquareES2(); setDemoFields(demo1, window1, glWindow1, false); @@ -130,10 +133,10 @@ public class TestParenting02NEWT extends UITestCase { glWindow2.setSize(width/2, height/2); //Assert.assertEquals(width/2,glWindow2.getWidth()); //Assert.assertEquals(height/2,glWindow2.getHeight()); - glWindow2.setTitle("testWindowParenting01NewtOnNewtParentChildDraw - CHILD"); + glWindow2.setTitle("test01NewtOnNewtParentChildDraw - CHILD"); glWindow2.setPosition(glWindow1.getWidth()/2, glWindow1.getHeight()/2); - glWindow2.addKeyListener(new TraceKeyAdapter(new KeyAction(eventFifo))); - glWindow2.addWindowListener(new TraceWindowAdapter(new WindowAction(eventFifo))); + //glWindow2.addKeyListener(new TraceKeyAdapter(new KeyAction(eventFifo))); + //glWindow2.addWindowListener(new TraceWindowAdapter(new WindowAction(eventFifo))); // glWindow2.addMouseListener(new TraceMouseAdapter()); GLEventListener demo2 = new GearsES2(); @@ -163,7 +166,7 @@ public class TestParenting02NEWT extends UITestCase { glWindow2.setPosition(glWindow1.getWidth()/2,glWindow1.getHeight()/2-y); Thread.sleep(step); - while( null != ( event = (NEWTEvent) eventFifo.get() ) ) { + while( null != ( event = eventFifo.get() ) ) { Window source = (Window) event.getSource(); if(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY == event.getEventType()) { shouldQuit = true; @@ -177,7 +180,7 @@ public class TestParenting02NEWT extends UITestCase { source.setFullscreen(!source.isFullscreen()); break; } - } + } } } destroyWindow(null, null, window2, glWindow2); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting03AWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting03AWT.java index b33a40fae..b7497196c 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting03AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting03AWT.java @@ -3,14 +3,14 @@ * * 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 @@ -20,12 +20,12 @@ * 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.parenting; import java.lang.reflect.*; @@ -33,6 +33,8 @@ import java.lang.reflect.*; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import java.awt.BorderLayout; import java.awt.Button; @@ -52,6 +54,7 @@ import java.io.IOException; import com.jogamp.opengl.test.junit.util.*; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestParenting03AWT extends UITestCase { static Dimension glSize, fSize; static long durationPerTest = 1100; @@ -66,16 +69,16 @@ public class TestParenting03AWT extends UITestCase { } @Test - public void testWindowParenting1AWTOneNewtChilds01() throws InterruptedException, InvocationTargetException { - testWindowParenting1AWT(false); + public void test01AWTOneNewtChilds01() throws InterruptedException, InvocationTargetException { + testImpl(false); } @Test - public void testWindowParenting1AWTTwoNewtChilds01() throws InterruptedException, InvocationTargetException { - testWindowParenting1AWT(true); + public void test02AWTTwoNewtChilds01() throws InterruptedException, InvocationTargetException { + testImpl(true); } - - public void testWindowParenting1AWT(boolean use2nd) throws InterruptedException, InvocationTargetException { + + public void testImpl(boolean use2nd) throws InterruptedException, InvocationTargetException { final Frame frame1 = new Frame("AWT Parent Frame"); GLWindow glWindow1 = GLWindow.create(glCaps); glWindow1.setUpdateFPSFrames(1, null); @@ -85,7 +88,7 @@ public class TestParenting03AWT extends UITestCase { GLEventListener demo1 = new GearsES2(1); setDemoFields(demo1, glWindow1, false); glWindow1.addGLEventListener(demo1); - glWindow1.addKeyListener(new NewtAWTReparentingKeyAdapter(frame1, newtCanvasAWT1, glWindow1)); + glWindow1.addKeyListener(new NewtAWTReparentingKeyAdapter(frame1, newtCanvasAWT1, glWindow1, null)); GLAnimatorControl animator1 = new Animator(glWindow1); animator1.start(); @@ -97,11 +100,11 @@ public class TestParenting03AWT extends UITestCase { glWindow2.setUpdateFPSFrames(1, null); newtCanvasAWT2 = new NewtCanvasAWT(glWindow2); newtCanvasAWT2.setPreferredSize(glSize); - + GLEventListener demo2 = new GearsES2(1); setDemoFields(demo2, glWindow2, false); glWindow2.addGLEventListener(demo2); - glWindow2.addKeyListener(new NewtAWTReparentingKeyAdapter(frame1, newtCanvasAWT2, glWindow2)); + glWindow2.addKeyListener(new NewtAWTReparentingKeyAdapter(frame1, newtCanvasAWT2, glWindow2, null)); animator2 = new Animator(glWindow2); animator2.start(); } @@ -133,17 +136,17 @@ public class TestParenting03AWT extends UITestCase { frame1.add(new Button("CENTER"), BorderLayout.CENTER); frame1.add(new Button("SOUTH"), BorderLayout.SOUTH); frame1.add(cont1, BorderLayout.EAST); - frame1.setLocation(0, 0); - frame1.setSize(fSize); javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { System.err.println("******* Frame setVisible"); - frame1.validate(); + frame1.setLocation(0, 0); + frame1.setSize(fSize); + frame1.validate(); frame1.setVisible(true); }}); Assert.assertEquals(newtCanvasAWT1.getNativeWindow(),glWindow1.getParent()); - + Assert.assertEquals(true, animator1.isAnimating()); Assert.assertEquals(false, animator1.isPaused()); Assert.assertNotNull(animator1.getThread()); @@ -154,7 +157,7 @@ public class TestParenting03AWT extends UITestCase { Assert.assertNotNull(animator2.getThread()); Thread.sleep(waitAdd2nd); - + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { frame1.add(cont2, BorderLayout.WEST); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04AWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04AWT.java new file mode 100644 index 000000000..126aaaffa --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04AWT.java @@ -0,0 +1,246 @@ +/** + * 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.parenting; + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Frame; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.swing.SwingUtilities; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.Window; +import com.jogamp.newt.awt.NewtCanvasAWT; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; + +/** + * Using {@link NewtCanvasAWT#setNEWTChild(Window)} for reparenting, i.e. NEWT/AWT hopping + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestParenting04AWT extends UITestCase { + static int width, height; + static long durationPerTest = 800; + static GLCapabilities glCaps; + + @BeforeClass + public static void initClass() { + width = 400; + height = 400; + glCaps = new GLCapabilities(null); + } + + @Test + public void test01WinHopFrame2FrameDirectHop() throws InterruptedException, InvocationTargetException { + // Will produce some artifacts .. resizing etc + winHopFrame2Frame(false); + } + + @Test + public void test02WinHopFrame2FrameDetachFirst() throws InterruptedException, InvocationTargetException { + // Note: detaching first setNEWTChild(null) is much cleaner visually + winHopFrame2Frame(true); + } + + protected void winHopFrame2Frame(final boolean detachFirst) throws InterruptedException, InvocationTargetException { + final GLWindow glWindow1 = GLWindow.create(glCaps); + GLEventListener demo1 = new RedSquareES2(); + setDemoFields(demo1, glWindow1, false); + glWindow1.addGLEventListener(demo1); + Animator anim1 = new Animator(glWindow1); + + final GLWindow glWindow2 = GLWindow.create(glCaps); + GLEventListener demo2 = new GearsES2(); + setDemoFields(demo2, glWindow2, false); + glWindow2.addGLEventListener(demo2); + Animator anim2 = new Animator(glWindow2); + + final NewtCanvasAWT canvas1 = new NewtCanvasAWT(glWindow1); + final NewtCanvasAWT canvas2 = new NewtCanvasAWT(glWindow2); + + final Frame frame1 = new Frame("AWT Parent Frame"); + frame1.setLayout(new BorderLayout()); + frame1.add(new Button("North"), BorderLayout.NORTH); + frame1.add(new Button("South"), BorderLayout.SOUTH); + frame1.add(new Button("East"), BorderLayout.EAST); + frame1.add(new Button("West"), BorderLayout.WEST); + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame1.setSize(width, height); + frame1.setLocation(0, 0); + frame1.setVisible(true); + frame1.validate(); + } + }); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame1.add(canvas1, BorderLayout.CENTER); + frame1.validate(); + } + }); + Assert.assertEquals(canvas1.getNativeWindow(),glWindow1.getParent()); + + final Frame frame2 = new Frame("AWT Parent Frame"); + frame2.setLayout(new BorderLayout()); + frame2.add(new Button("North"), BorderLayout.NORTH); + frame2.add(new Button("South"), BorderLayout.SOUTH); + frame2.add(new Button("East"), BorderLayout.EAST); + frame2.add(new Button("West"), BorderLayout.WEST); + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame2.setSize(width, height); + frame2.setLocation(width+50, 0); + frame2.setVisible(true); + frame2.validate(); + } + }); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame2.add(canvas2, BorderLayout.CENTER); + frame2.validate(); + } + }); + Assert.assertEquals(canvas2.getNativeWindow(),glWindow2.getParent()); + + anim1.start(); + anim2.start(); + + int state; + for(state=0; state<3; state++) { + Thread.sleep(durationPerTest); + switch(state) { + case 0: + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + // 1 -> 2 + if(detachFirst) { + canvas1.setNEWTChild(null); + canvas2.setNEWTChild(null); + } else { + canvas2.setNEWTChild(null); // free g2 of w2 + } + canvas1.setNEWTChild(glWindow2); // put g2 -> w1. free g1 of w1 + canvas2.setNEWTChild(glWindow1); // put g1 -> w2 + frame1.invalidate(); + frame2.invalidate(); + frame1.validate(); + frame2.validate(); + } + }); + break; + case 1: + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + // 2 -> 1 + if(detachFirst) { + canvas1.setNEWTChild(null); + canvas2.setNEWTChild(null); + } else { + canvas2.setNEWTChild(null); + } + canvas1.setNEWTChild(glWindow1); + canvas2.setNEWTChild(glWindow2); + frame1.invalidate(); + frame2.invalidate(); + frame1.validate(); + frame2.validate(); + } + }); + break; + } + } + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame1.dispose(); + frame2.dispose(); + } } ); + glWindow1.destroy(); + glWindow2.destroy(); + Assert.assertEquals(false, glWindow1.isNativeValid()); + Assert.assertEquals(false, glWindow2.isNativeValid()); + } + + public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) { + Assert.assertNotNull(demo); + Assert.assertNotNull(glWindow); + Window window = glWindow.getDelegatedWindow(); + if(debug) { + MiscUtils.setFieldIfExists(demo, "glDebug", true); + MiscUtils.setFieldIfExists(demo, "glTrace", true); + } + if(!MiscUtils.setFieldIfExists(demo, "window", window)) { + MiscUtils.setFieldIfExists(demo, "glWindow", glWindow); + } + } + + static int atoi(String a) { + int i=0; + try { + i = Integer.parseInt(a); + } catch (Exception ex) { ex.printStackTrace(); } + return i; + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + durationPerTest = atoi(args[++i]); + } + } + String tstname = TestParenting04AWT.class.getName(); + org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] { + tstname, + "filtertrace=true", + "haltOnError=false", + "haltOnFailure=false", + "showoutput=true", + "outputtoformatters=true", + "logfailedtests=true", + "logtestlistenerevents=true", + "formatter=org.apache.tools.ant.taskdefs.optional.junit.PlainJUnitResultFormatter", + "formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,TEST-"+tstname+".xml" } ); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04SWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04SWT.java new file mode 100644 index 000000000..586db8a2b --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04SWT.java @@ -0,0 +1,273 @@ +/** + * 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.parenting; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.junit.After; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.nativewindow.swt.SWTAccessor; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Window; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.newt.swt.NewtCanvasSWT; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; + +/** + * Using {@link NewtCanvasSWT#setNEWTChild(Window)} for reparenting, i.e. NEWT/AWT hopping + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestParenting04SWT extends UITestCase { + static int width, height; + static long durationPerTest = 800; + static GLCapabilities glCaps; + + Display display = null; + Shell shell1 = null; + Shell shell2 = null; + Composite composite1 = null; + Composite composite2 = null; + com.jogamp.newt.Display swtNewtDisplay = null; + + @BeforeClass + public static void initClass() { + width = 400; + height = 400; + glCaps = new GLCapabilities(null); + } + + @Before + public void init() { + SWTAccessor.invoke(true, new Runnable() { + public void run() { + display = new Display(); + Assert.assertNotNull( display ); + + shell1 = new Shell( display ); + Assert.assertNotNull( shell1 ); + shell1.setLayout( new FillLayout() ); + composite1 = new Composite( shell1, SWT.NONE ); + composite1.setLayout( new FillLayout() ); + Assert.assertNotNull( composite1 ); + + shell2 = new Shell( display ); + Assert.assertNotNull( shell2 ); + shell2.setLayout( new FillLayout() ); + composite2 = new Composite( shell2, SWT.NONE ); + composite2.setLayout( new FillLayout() ); + Assert.assertNotNull( composite2 ); + }}); + swtNewtDisplay = NewtFactory.createDisplay(null, false); // no-reuse + } + + @After + public void release() { + Assert.assertNotNull( display ); + Assert.assertNotNull( shell1 ); + Assert.assertNotNull( shell2 ); + Assert.assertNotNull( composite1 ); + Assert.assertNotNull( composite2 ); + try { + SWTAccessor.invoke(true, new Runnable() { + public void run() { + composite1.dispose(); + composite2.dispose(); + shell1.dispose(); + shell2.dispose(); + display.dispose(); + }}); + } + catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + swtNewtDisplay = null; + display = null; + shell1 = null; + shell2 = null; + composite1 = null; + composite2 = null; + } + + @Test + public void test01WinHopFrame2FrameDirectHop() throws InterruptedException, InvocationTargetException { + // Will produce some artifacts .. resizing etc + winHopFrame2Frame(false); + } + + @Test + public void test02WinHopFrame2FrameDetachFirst() throws InterruptedException, InvocationTargetException { + // Note: detaching first setNEWTChild(null) is much cleaner visually + winHopFrame2Frame(true); + } + + protected void winHopFrame2Frame(final boolean detachFirst) throws InterruptedException, InvocationTargetException { + com.jogamp.newt.Screen screen = NewtFactory.createScreen(swtNewtDisplay, 0); + + final GLWindow glWindow1 = GLWindow.create(screen, glCaps); + GLEventListener demo1 = new RedSquareES2(); + setDemoFields(demo1, glWindow1, false); + glWindow1.addGLEventListener(demo1); + Animator anim1 = new Animator(glWindow1); + + final GLWindow glWindow2 = GLWindow.create(screen, glCaps); + GLEventListener demo2 = new GearsES2(); + setDemoFields(demo2, glWindow2, false); + glWindow2.addGLEventListener(demo2); + Animator anim2 = new Animator(glWindow2); + + final NewtCanvasSWT canvas1 = NewtCanvasSWT.create( composite1, 0, glWindow1 ); + final NewtCanvasSWT canvas2 = NewtCanvasSWT.create( composite2, 0, glWindow2 ); + + SWTAccessor.invoke(true, new Runnable() { + public void run() { + shell1.setText( getSimpleTestName(".")+"-Win1" ); + shell1.setSize( width, height); + shell1.setLocation(0, 0); + shell1.open(); + shell2.setText( getSimpleTestName(".")+"-Win2" ); + shell2.setSize( width, height); + shell2.setLocation(width + 50, 0); + shell2.open(); + } + }); + Assert.assertEquals(canvas1.getNativeWindow(),glWindow1.getParent()); + Assert.assertEquals(canvas2.getNativeWindow(),glWindow2.getParent()); + + anim1.start(); + anim2.start(); + + int state; + for(state=0; state<3; state++) { + for(int i=0; i*10<durationPerTest; i++) { + if( !display.readAndDispatch() ) { + // blocks on linux .. display.sleep(); + Thread.sleep(10); + } + } + switch(state) { + case 0: + SWTAccessor.invoke(true, new Runnable() { + public void run() { + // 1 -> 2 + if(detachFirst) { + canvas1.setNEWTChild(null); + canvas2.setNEWTChild(null); + } else { + canvas2.setNEWTChild(null); // free g2 of w2 + } + canvas1.setNEWTChild(glWindow2); // put g2 -> w1. free g1 of w1 + canvas2.setNEWTChild(glWindow1); // put g1 -> w2 + } } ); + break; + case 1: + SWTAccessor.invoke(true, new Runnable() { + public void run() { + // 2 -> 1 + if(detachFirst) { + canvas1.setNEWTChild(null); + canvas2.setNEWTChild(null); + } else { + canvas2.setNEWTChild(null); + } + canvas1.setNEWTChild(glWindow1); + canvas2.setNEWTChild(glWindow2); + } } ); + break; + } + } + + canvas1.dispose(); + canvas2.dispose(); + Assert.assertEquals(false, glWindow1.isNativeValid()); + Assert.assertEquals(false, glWindow2.isNativeValid()); + } + + public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) { + Assert.assertNotNull(demo); + Assert.assertNotNull(glWindow); + Window window = glWindow.getDelegatedWindow(); + if(debug) { + MiscUtils.setFieldIfExists(demo, "glDebug", true); + MiscUtils.setFieldIfExists(demo, "glTrace", true); + } + if(!MiscUtils.setFieldIfExists(demo, "window", window)) { + MiscUtils.setFieldIfExists(demo, "glWindow", glWindow); + } + } + + static int atoi(String a) { + int i=0; + try { + i = Integer.parseInt(a); + } catch (Exception ex) { ex.printStackTrace(); } + return i; + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + durationPerTest = atoi(args[++i]); + } + } + String tstname = TestParenting04SWT.class.getName(); + org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] { + tstname, + "filtertrace=true", + "haltOnError=false", + "haltOnFailure=false", + "showoutput=true", + "outputtoformatters=true", + "logfailedtests=true", + "logtestlistenerevents=true", + "formatter=org.apache.tools.ant.taskdefs.optional.junit.PlainJUnitResultFormatter", + "formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,TEST-"+tstname+".xml" } ); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestTranslucentChildWindowBug632NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestTranslucentChildWindowBug632NEWT.java new file mode 100644 index 000000000..b2286a8b7 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestTranslucentChildWindowBug632NEWT.java @@ -0,0 +1,135 @@ +package com.jogamp.opengl.test.junit.newt.parenting; + +import java.io.IOException; + +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.NativeWindow; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.opengl.GLWindow; +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.util.Animator; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestTranslucentChildWindowBug632NEWT extends UITestCase { + static long durationPerTest = 2*300; + static GLProfile glp; + static boolean opaque; + + @BeforeClass + public static void initClass() { + glp = GLProfile.getDefault(); + opaque = false; + } + + static GLWindow createParentWindow(GLCapabilitiesImmutable caps, int width, int height) + throws InterruptedException + { + Assert.assertNotNull(caps); + // + // Create native windowing resources .. X11/Win/OSX + // + GLWindow glWindow; + glWindow = GLWindow.create(caps); + Assert.assertNotNull(glWindow); + + glWindow.setTitle("NEWT Parenting Window Test"); + + glWindow.addGLEventListener(new GearsES2(1)); + + glWindow.setSize(width, height); + glWindow.setVisible(true); + Assert.assertEquals(true,glWindow.isVisible()); + Assert.assertEquals(true,glWindow.isNativeValid()); + + return glWindow; + } + + static GLWindow createNestedWindow(NativeWindow nativeParentWindow, GLCapabilitiesImmutable caps, int x, int y, int width, int height) + throws InterruptedException { + + Assert.assertNotNull(nativeParentWindow); + Assert.assertNotNull(caps); + // + // Create native windowing resources .. X11/Win/OSX + // + GLWindow glWindow; + glWindow = GLWindow.create(nativeParentWindow, caps); + Assert.assertNotNull(glWindow); + + glWindow.setTitle("NEWT Parenting Window Test"); + + glWindow.addGLEventListener(new GearsES2(1)); + + glWindow.setPosition(x, y); + glWindow.setSize(width, height); + glWindow.setVisible(true); + Assert.assertEquals(true,glWindow.isVisible()); + Assert.assertEquals(true,glWindow.isNativeValid()); + + return glWindow; + } + + static void destroyWindow(GLWindow glWindow) { + if(null!=glWindow) { + glWindow.destroy(); + Assert.assertEquals(false,glWindow.isNativeValid()); + } + } + + @Test + public void testWindow00() throws InterruptedException { + final Animator animator = new Animator(); + + GLCapabilities caps = new GLCapabilities(glp); + Assert.assertNotNull(caps); + caps.setBackgroundOpaque(opaque); + GLWindow window1 = createParentWindow(caps, 400, 400); + Assert.assertEquals(true,window1.isNativeValid()); + Assert.assertEquals(true,window1.isVisible()); + animator.add(window1); + + GLWindow window2 = createNestedWindow(window1, caps, 400-300, 400-300, 300, 300); + Assert.assertEquals(true,window2.isNativeValid()); + Assert.assertEquals(true,window2.isVisible()); + animator.add(window2); + + animator.start(); + + AbstractGraphicsDevice device1 = window1.getScreen().getDisplay().getGraphicsDevice(); + + System.err.println("GLProfiles window1: "+device1.getConnection()+": "+GLProfile.glAvailabilityToString(device1)); + + Thread.sleep(durationPerTest/2); + + window1.setSize(512, 512); + window2.setPosition(512-300, 512-300); + + Thread.sleep(durationPerTest/2); + + animator.stop(); + + destroyWindow(window2); + destroyWindow(window1); + } + + public static void main(String[] args) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + durationPerTest = MiscUtils.atol(args[++i], durationPerTest); + } + } + String testName = TestTranslucentChildWindowBug632NEWT.class.getName(); + org.junit.runner.JUnitCore.main(testName); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestTranslucentParentingAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestTranslucentParentingAWT.java index 57b8517a6..f273f7672 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestTranslucentParentingAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestTranslucentParentingAWT.java @@ -49,6 +49,8 @@ import javax.media.opengl.GLEventListener; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; import com.jogamp.common.util.ReflectionUtil; import com.jogamp.newt.Window; @@ -59,6 +61,7 @@ import com.jogamp.opengl.test.junit.util.MiscUtils; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.util.Animator; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestTranslucentParentingAWT extends UITestCase { static Dimension size; static long durationPerTest = 400; @@ -69,7 +72,6 @@ public class TestTranslucentParentingAWT extends UITestCase { public static void initClass() { size = new Dimension(400,200); glCaps = new GLCapabilities(null); - glCaps.setAlphaBits(8); glCaps.setBackgroundOpaque(false); } @@ -138,10 +140,10 @@ public class TestTranslucentParentingAWT extends UITestCase { frame1.setLayout(new BorderLayout()); frame1.add(cont1, BorderLayout.EAST); frame1.add(new Label("center"), BorderLayout.CENTER); - frame1.setLocation(0, 0); - frame1.setSize((int)size.getWidth(), (int)size.getHeight()); javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame1.setLocation(0, 0); + frame1.setSize((int)size.getWidth(), (int)size.getHeight()); frame1.pack(); frame1.setVisible(true); }}); @@ -158,7 +160,10 @@ public class TestTranslucentParentingAWT extends UITestCase { Assert.assertEquals(false, animator1.isPaused()); Assert.assertEquals(null, animator1.getThread()); - frame1.dispose(); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame1.dispose(); + } } ); glWindow1.destroy(); } @@ -175,20 +180,12 @@ public class TestTranslucentParentingAWT extends UITestCase { } } - static int atoi(String a) { - int i=0; - try { - i = Integer.parseInt(a); - } catch (Exception ex) { ex.printStackTrace(); } - return i; - } - public static void main(String args[]) throws IOException { for(int i=0; i<args.length; i++) { if(args[i].equals("-time")) { - durationPerTest = atoi(args[++i]); + durationPerTest = MiscUtils.atol(args[++i], durationPerTest); } else if(args[i].equals("-wait")) { - waitAdd2nd = atoi(args[++i]); + waitAdd2nd = MiscUtils.atol(args[++i], waitAdd2nd); } } String tstname = TestTranslucentParentingAWT.class.getName(); diff --git a/src/test/com/jogamp/opengl/test/junit/util/AWTFocusAdapter.java b/src/test/com/jogamp/opengl/test/junit/util/AWTFocusAdapter.java index fe0f2acc0..32ff6022c 100644 --- a/src/test/com/jogamp/opengl/test/junit/util/AWTFocusAdapter.java +++ b/src/test/com/jogamp/opengl/test/junit/util/AWTFocusAdapter.java @@ -36,12 +36,15 @@ public class AWTFocusAdapter implements FocusEventCountAdapter, FocusListener { String prefix; int focusCount; boolean wasTemporary; + boolean verbose = true; public AWTFocusAdapter(String prefix) { this.prefix = prefix; reset(); } + public void setVerbose(boolean v) { verbose = false; } + public boolean focusLost() { return focusCount<0; } @@ -65,7 +68,9 @@ public class AWTFocusAdapter implements FocusEventCountAdapter, FocusListener { if(focusCount<0) { focusCount=0; } focusCount++; wasTemporary = e.isTemporary(); - System.err.println("FOCUS AWT GAINED "+(wasTemporary?"TEMP":"PERM")+" [fc "+focusCount+"]: "+prefix+", "+e); + if( verbose ) { + System.err.println("FOCUS AWT GAINED "+(wasTemporary?"TEMP":"PERM")+" [fc "+focusCount+"]: "+prefix+", "+e); + } } /* @Override */ @@ -73,7 +78,9 @@ public class AWTFocusAdapter implements FocusEventCountAdapter, FocusListener { if(focusCount>0) { focusCount=0; } focusCount--; wasTemporary = e.isTemporary(); - System.err.println("FOCUS AWT LOST "+(wasTemporary?"TEMP":"PERM")+" [fc "+focusCount+"]: "+prefix+", "+e); + if( verbose ) { + System.err.println("FOCUS AWT LOST "+(wasTemporary?"TEMP":"PERM")+" [fc "+focusCount+"]: "+prefix+", "+e); + } } public String toString() { return prefix+"[focusCount "+focusCount +", temp "+wasTemporary+"]"; } diff --git a/src/test/com/jogamp/opengl/test/junit/util/AWTKeyAdapter.java b/src/test/com/jogamp/opengl/test/junit/util/AWTKeyAdapter.java index 6c0156170..9461af5c0 100644 --- a/src/test/com/jogamp/opengl/test/junit/util/AWTKeyAdapter.java +++ b/src/test/com/jogamp/opengl/test/junit/util/AWTKeyAdapter.java @@ -3,14 +3,14 @@ * * 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 @@ -20,55 +20,92 @@ * 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.util; import java.awt.event.KeyEvent; +import java.util.ArrayList; +import java.util.EventObject; +import java.util.List; -public class AWTKeyAdapter extends java.awt.event.KeyAdapter implements InputEventCountAdapter { +public class AWTKeyAdapter extends java.awt.event.KeyAdapter implements KeyEventCountAdapter { String prefix; - int keyTyped; + int keyPressed, keyReleased; + int consumed; boolean pressed; + List<EventObject> queue = new ArrayList<EventObject>(); + boolean verbose = true; public AWTKeyAdapter(String prefix) { this.prefix = prefix; reset(); } - public boolean isPressed() { + public synchronized void setVerbose(boolean v) { verbose = v; } + + public synchronized boolean isPressed() { return pressed; } - - public int getCount() { - return keyTyped; + + public synchronized int getCount() { + return keyReleased; + } + + public synchronized int getConsumedCount() { + return consumed; + } + + public synchronized int getKeyPressedCount(boolean autoRepeatOnly) { + return keyPressed; } - public void reset() { - keyTyped = 0; + public synchronized int getKeyReleasedCount(boolean autoRepeatOnly) { + return keyReleased; + } + + public synchronized List<EventObject> copyQueue() { + return new ArrayList<EventObject>(queue); + } + + public synchronized int getQueueSize() { + return queue.size(); + } + + public synchronized void reset() { + keyPressed = 0; + keyReleased = 0; + consumed = 0; pressed = false; + queue.clear(); } - public void keyPressed(KeyEvent e) { + public synchronized void keyPressed(KeyEvent e) { pressed = true; - System.err.println("KEY AWT PRESSED ["+pressed+"]: "+prefix+", "+e); + keyPressed++; + queue.add(e); + if( verbose ) { + System.err.println("KEY AWT PRESSED ["+pressed+"]: "+prefix+", "+e); + } } - public void keyReleased(KeyEvent e) { + public synchronized void keyReleased(KeyEvent e) { pressed = false; - System.err.println("KEY AWT RELEASED ["+pressed+"]: "+prefix+", "+e); + keyReleased++; + if(e.isConsumed()) { + consumed++; + } + queue.add(e); + if( verbose ) { + System.err.println("KEY AWT RELEASED ["+pressed+"]: "+prefix+", "+e); + } } - public void keyTyped(java.awt.event.KeyEvent e) { - ++keyTyped; - System.err.println("KEY AWT TYPED ["+keyTyped+"]: "+prefix+", "+e); - } - - public String toString() { return prefix+"[pressed "+pressed+", typed "+keyTyped+"]"; } + public String toString() { return prefix+"[pressed "+pressed+", keyReleased "+keyReleased+", consumed "+consumed+"]"; } } diff --git a/src/test/com/jogamp/opengl/test/junit/util/AWTMouseAdapter.java b/src/test/com/jogamp/opengl/test/junit/util/AWTMouseAdapter.java index b94802348..c1bec79f5 100644 --- a/src/test/com/jogamp/opengl/test/junit/util/AWTMouseAdapter.java +++ b/src/test/com/jogamp/opengl/test/junit/util/AWTMouseAdapter.java @@ -3,14 +3,14 @@ * * 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 @@ -20,54 +20,88 @@ * 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.util; import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.EventObject; +import java.util.List; public class AWTMouseAdapter extends java.awt.event.MouseAdapter implements InputEventCountAdapter { String prefix; int mouseClicked; + int consumed; boolean pressed; + List<EventObject> queue = new ArrayList<EventObject>(); + boolean verbose = true; public AWTMouseAdapter(String prefix) { this.prefix = prefix; reset(); } - public boolean isPressed() { + public synchronized void setVerbose(boolean v) { verbose = v; } + + public synchronized boolean isPressed() { return pressed; } - - public int getCount() { + + public synchronized int getCount() { return mouseClicked; } - - public void reset() { + + public synchronized int getConsumedCount() { + return consumed; + } + + public synchronized List<EventObject> copyQueue() { + return new ArrayList<EventObject>(queue); + } + + public synchronized int getQueueSize() { + return queue.size(); + } + + public synchronized void reset() { mouseClicked = 0; + consumed = 0; pressed = false; + queue.clear(); } - public void mousePressed(MouseEvent e) { + public synchronized void mousePressed(MouseEvent e) { pressed = true; - System.err.println("MOUSE AWT PRESSED ["+pressed+"]: "+prefix+", "+e); + queue.add(e); + if( verbose ) { + System.err.println("MOUSE AWT PRESSED ["+pressed+"]: "+prefix+", "+e); + } } - public void mouseReleased(MouseEvent e) { + public synchronized void mouseReleased(MouseEvent e) { pressed = false; - System.err.println("MOUSE AWT RELEASED ["+pressed+"]: "+prefix+", "+e); + queue.add(e); + if( verbose ) { + System.err.println("MOUSE AWT RELEASED ["+pressed+"]: "+prefix+", "+e); + } } - - public void mouseClicked(java.awt.event.MouseEvent e) { + + public synchronized void mouseClicked(java.awt.event.MouseEvent e) { mouseClicked+=e.getClickCount(); - System.err.println("MOUSE AWT CLICKED ["+mouseClicked+"]: "+prefix+", "+e); - } - - public String toString() { return prefix+"[pressed "+pressed+", clicked "+mouseClicked+"]"; } + if(e.isConsumed()) { + consumed++; + } + queue.add(e); + if( verbose ) { + System.err.println("MOUSE AWT CLICKED ["+mouseClicked+"]: "+prefix+", "+e); + } + } + + public String toString() { return prefix+"[pressed "+pressed+", clicked "+mouseClicked+", consumed "+consumed+"]"; } } diff --git a/src/test/com/jogamp/opengl/test/junit/util/AWTRobotUtil.java b/src/test/com/jogamp/opengl/test/junit/util/AWTRobotUtil.java index 35a2d9669..599a6dc9f 100644 --- a/src/test/com/jogamp/opengl/test/junit/util/AWTRobotUtil.java +++ b/src/test/com/jogamp/opengl/test/junit/util/AWTRobotUtil.java @@ -3,14 +3,14 @@ * * 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 @@ -20,39 +20,93 @@ * 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.util; import jogamp.newt.WindowImplAccess; +import jogamp.newt.awt.event.AWTNewtEventFactory; + +import java.lang.Thread.UncaughtExceptionHandler; import java.lang.reflect.InvocationTargetException; import java.awt.AWTException; -import java.awt.Component; import java.awt.EventQueue; -import java.awt.KeyboardFocusManager; import java.awt.Robot; -import java.awt.Toolkit; import javax.media.nativewindow.NativeWindow; -import javax.media.opengl.awt.GLCanvas; +import javax.media.nativewindow.NativeWindowFactory; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; import org.junit.Assert; +import com.jogamp.common.util.awt.AWTEDTExecutor; +import com.jogamp.newt.event.WindowEvent; + public class AWTRobotUtil { static final boolean DEBUG = false; - + public static final int RETRY_NUMBER = 5; public static final int ROBOT_DELAY = 100; // ms public static final int TIME_OUT = 2000; // 2s public static final int POLL_DIVIDER = 20; // TO/20 public static final int TIME_SLICE = TIME_OUT / POLL_DIVIDER ; - public static Integer AWT_CLICK_TO = null; - + public static Integer AWT_CLICK_TO = null; + + static class OurUncaughtExceptionHandler implements UncaughtExceptionHandler { + @Override + public void uncaughtException(Thread t, Throwable e) { + System.err.println("*** AWTRobotUtil: UncaughtException (this Thread "+Thread.currentThread().getName()+") : Thread <"+t.getName()+">, "+e.getClass().getName()+": "+e.getMessage()); + e.printStackTrace(); + } + } + + static { + Thread.setDefaultUncaughtExceptionHandler( new OurUncaughtExceptionHandler() ); + // System.err.println("AWT EDT alive: "+isAWTEDTAlive()); + } + + /** Probes whether AWT's EDT is alive or not. */ + public static boolean isAWTEDTAlive() { + if( EventQueue.isDispatchThread() ) { + return true; + } + synchronized ( awtEDTAliveSync ) { + awtEDTAliveFlag = false; + EventQueue.invokeLater(aliveRun); + for (int wait=0; wait<POLL_DIVIDER && !awtEDTAliveFlag; wait++) { + try { + Thread.sleep(TIME_SLICE); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + return awtEDTAliveFlag; + } + } + private static Runnable aliveRun = new Runnable() { public void run() { awtEDTAliveFlag = true; } }; + private static Object awtEDTAliveSync = new Object(); + private static volatile boolean awtEDTAliveFlag = false; + + /** Throws Error if {@link #isAWTEDTAlive()} returns false. */ + public static void validateAWTEDTIsAlive() { + if( !isAWTEDTAlive() ) { + throw new Error("AWT EDT not alive"); + } + } + + /** Issuing {@link #validateAWTEDTIsAlive()} before calling {@link Robot#waitForIdle()}. */ + public static void waitForIdle(Robot robot) { + validateAWTEDTIsAlive(); + robot.waitForIdle(); + } + public static void clearAWTFocus(Robot robot) throws InterruptedException, InvocationTargetException, AWTException { if(null == robot) { robot = new Robot(); @@ -61,50 +115,74 @@ public class AWTRobotUtil { javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { System.err.println("******** clearAWTFocus.0"); - KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner(); + java.awt.KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner(); }}); robot.delay(ROBOT_DELAY); System.err.println("******** clearAWTFocus.X"); } - - public static java.awt.Point getCenterLocation(Object obj, boolean onTitleBarIfWindow) - throws InterruptedException, InvocationTargetException { - Component comp = null; - com.jogamp.newt.Window win = null; + public static int[] getCenterLocation(Object obj, boolean onTitleBarIfWindow) + throws InterruptedException, InvocationTargetException { if(obj instanceof com.jogamp.newt.Window) { - win = (com.jogamp.newt.Window) obj; - } else if(obj instanceof Component) { - comp = (Component) obj; + return getCenterLocationNEWT((com.jogamp.newt.Window)obj, onTitleBarIfWindow); + } else if(NativeWindowFactory.isAWTAvailable() && obj instanceof java.awt.Component) { + return getCenterLocationAWT((java.awt.Component)obj, onTitleBarIfWindow); } else { throw new RuntimeException("Neither AWT nor NEWT: "+obj); } + } + private static int[] getCenterLocationNEWT(com.jogamp.newt.Window win, boolean onTitleBarIfWindow) + throws InterruptedException, InvocationTargetException { + javax.media.nativewindow.util.Point p0 = win.getLocationOnScreen(null); + if( onTitleBarIfWindow ) { + javax.media.nativewindow.util.InsetsImmutable insets = win.getInsets(); + p0.translate(win.getWidth()/2, insets.getTopHeight()/2); + } else { + p0.translate(win.getWidth()/2, win.getHeight()/2); + } + return new int[] { p0.getX(), p0.getY() }; + } + private static int[] getCenterLocationAWT(java.awt.Component comp, boolean onTitleBarIfWindow) + throws InterruptedException, InvocationTargetException { int x0, y0; - if(null!=comp) { - java.awt.Point p0 = comp.getLocationOnScreen(); - java.awt.Rectangle r0 = comp.getBounds(); - if( onTitleBarIfWindow && comp instanceof java.awt.Window) { - java.awt.Window window = (java.awt.Window) comp; - java.awt.Insets insets = window.getInsets(); - y0 = (int) ( p0.getY() + insets.top / 2.0 + .5 ) ; - } else { - y0 = (int) ( p0.getY() + r0.getHeight() / 2.0 + .5 ) ; - } - x0 = (int) ( p0.getX() + r0.getWidth() / 2.0 + .5 ) ; + java.awt.Point p0 = comp.getLocationOnScreen(); + java.awt.Rectangle r0 = comp.getBounds(); + if( onTitleBarIfWindow && comp instanceof java.awt.Window) { + java.awt.Window window = (java.awt.Window) comp; + java.awt.Insets insets = window.getInsets(); + y0 = (int) ( p0.getY() + insets.top / 2.0 + .5 ) ; } else { - javax.media.nativewindow.util.Point p0 = win.getLocationOnScreen(null); - if( onTitleBarIfWindow ) { - javax.media.nativewindow.util.InsetsImmutable insets = win.getInsets(); - p0.translate(win.getWidth()/2, insets.getTopHeight()/2); - } else { - p0.translate(win.getWidth()/2, win.getHeight()/2); - } - x0 = p0.getX(); - y0 = p0.getY(); + y0 = (int) ( p0.getY() + r0.getHeight() / 2.0 + .5 ) ; } + x0 = (int) ( p0.getX() + r0.getWidth() / 2.0 + .5 ) ; + return new int[] { x0, y0 }; + } - return new java.awt.Point(x0, y0); + public static int[] getClientLocation(Object obj, int x, int y) + throws InterruptedException, InvocationTargetException { + if(obj instanceof com.jogamp.newt.Window) { + return getClientLocationNEWT((com.jogamp.newt.Window)obj, x, y); + } else if(NativeWindowFactory.isAWTAvailable() && obj instanceof java.awt.Component) { + return getClientLocationAWT((java.awt.Component)obj, x, y); + } else { + throw new RuntimeException("Neither AWT nor NEWT: "+obj); + } + } + private static int[] getClientLocationNEWT(com.jogamp.newt.Window win, int x, int y) + throws InterruptedException, InvocationTargetException { + javax.media.nativewindow.util.Point p0 = win.getLocationOnScreen(null); + return new int[] { p0.getX(), p0.getY() }; + } + private static int[] getClientLocationAWT(java.awt.Component comp, int x, int y) + throws InterruptedException, InvocationTargetException { + java.awt.Point p0 = comp.getLocationOnScreen(); + return new int[] { (int)p0.getX(), (int)p0.getY() }; + } + + public static void awtRobotMouseMove(Robot robot, int x, int y) { + robot.mouseMove( x, y ); + robot.delay(ROBOT_DELAY); } /** @@ -120,15 +198,14 @@ public class AWTRobotUtil { // just for event tracing .. AWTWindowFocusAdapter winFA = new AWTWindowFocusAdapter("window"); window.addWindowFocusListener(winFA); - + if(null == robot) { robot = new Robot(); robot.setAutoWaitForIdle(true); } - java.awt.Point p0 = getCenterLocation(window, false); - System.err.println("toFront: robot pos: "+p0); - robot.mouseMove( (int) p0.getX(), (int) p0.getY() ); - robot.delay(ROBOT_DELAY); + int[] p0 = getCenterLocation(window, false); + System.err.println("toFront: robot pos: "+p0[0]+"/"+p0[1]); + awtRobotMouseMove(robot, p0[0], p0[1] ); int wait=0; do { @@ -145,7 +222,7 @@ public class AWTRobotUtil { wait++; } while (wait<POLL_DIVIDER && !window.hasFocus()); final boolean success = wait<POLL_DIVIDER; - + window.removeWindowFocusListener(winFA); if(!success) { System.err.println("*** AWTRobotUtil.toFrontAndRequestFocus() UI failure"); @@ -160,7 +237,7 @@ public class AWTRobotUtil { * centerMouse * @param onTitleBarIfWindow TODO */ - public static void centerMouse(Robot robot, Object obj, boolean onTitleBarIfWindow) + public static void centerMouse(Robot robot, Object obj, boolean onTitleBarIfWindow) throws AWTException, InterruptedException, InvocationTargetException { if(null == robot) { @@ -168,80 +245,114 @@ public class AWTRobotUtil { robot.setAutoWaitForIdle(true); } - java.awt.Point p0 = getCenterLocation(obj, onTitleBarIfWindow); - System.err.println("centerMouse: robot pos: "+p0+", onTitleBarIfWindow: "+onTitleBarIfWindow); + int[] p0 = getCenterLocation(obj, onTitleBarIfWindow); + System.err.println("centerMouse: robot pos: "+p0[0]+"x"+p0[1]+", onTitleBarIfWindow: "+onTitleBarIfWindow); + awtRobotMouseMove(robot, p0[0], p0[1] ); + } - robot.mouseMove( (int) p0.getX(), (int) p0.getY() ); - robot.delay(ROBOT_DELAY); + public static void setMouseToClientLocation(Robot robot, Object obj, int x, int y) + throws AWTException, InterruptedException, InvocationTargetException { + + if(null == robot) { + robot = new Robot(); + robot.setAutoWaitForIdle(true); + } + + int[] p0 = getClientLocation(obj, x, y); + awtRobotMouseMove(robot, p0[0], p0[1] ); } public static int getClickTimeout(Object obj) { if(obj instanceof com.jogamp.newt.Window) { return com.jogamp.newt.event.MouseEvent.getClickTimeout(); - } else if(obj instanceof Component) { + } else if(NativeWindowFactory.isAWTAvailable() && obj instanceof java.awt.Component) { if(null == AWT_CLICK_TO) { AWT_CLICK_TO = - (Integer) Toolkit.getDefaultToolkit().getDesktopProperty("awt.multiClickInterval"); - if(null == AWT_CLICK_TO) { + (Integer) java.awt.Toolkit.getDefaultToolkit().getDesktopProperty("awt.multiClickInterval"); + if(null == AWT_CLICK_TO) { AWT_CLICK_TO = new Integer(500); } } return AWT_CLICK_TO.intValue(); } else { throw new RuntimeException("Neither AWT nor NEWT: "+obj); - } + } } - + /** * requestFocus, if robot is valid, use mouse operation, - * otherwise programatic, ie call requestFocus + * otherwise programmatic, ie call requestFocus */ - public static void requestFocus(Robot robot, Object obj) + public static void requestFocus(Robot robot, Object obj) throws AWTException, InterruptedException, InvocationTargetException { - final Component comp; - final com.jogamp.newt.Window win; + requestFocus(robot, obj, true); + } - if(obj instanceof com.jogamp.newt.Window) { - win = (com.jogamp.newt.Window) obj; - comp = null; - } else if(obj instanceof Component) { - win = null; - comp = (Component) obj; - } else { - throw new RuntimeException("Neither AWT nor NEWT: "+obj); - } - - if(null == robot) { - if(null!=comp) { - javax.swing.SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - comp.requestFocus(); - System.err.println("requestFocus: AWT Component"); - }}); - } else { - win.requestFocus(); - System.err.println("requestFocus: NEWT Component"); - } - } else { - final int mouseButton = java.awt.event.InputEvent.BUTTON1_MASK; - centerMouse(robot, obj, true); - - robot.waitForIdle(); + /** + * requestFocus, if robot is valid, use mouse operation, + * otherwise programmatic, ie call requestFocus + */ + public static void requestFocus(Robot robot, Object obj, boolean onTitleBarIfWindow) + throws AWTException, InterruptedException, InvocationTargetException { + if(null != robot) { + final int mouseButton = java.awt.event.InputEvent.BUTTON1_MASK; + centerMouse(robot, obj, onTitleBarIfWindow); + + waitForIdle(robot); robot.mousePress(mouseButton); robot.mouseRelease(mouseButton); final int d = getClickTimeout(obj) + 1; - robot.delay( d ); + robot.delay( d ); System.err.println("requestFocus: click, d: "+d+" ms"); + } else { + if(obj instanceof com.jogamp.newt.Window) { + requestFocusNEWT((com.jogamp.newt.Window) obj, onTitleBarIfWindow); + } else if(NativeWindowFactory.isAWTAvailable() && obj instanceof java.awt.Component) { + requestFocusAWT((java.awt.Component) obj, onTitleBarIfWindow); + } else { + throw new RuntimeException("Neither AWT nor NEWT: "+obj); + } } } + private static void requestFocusNEWT(com.jogamp.newt.Window win, boolean onTitleBarIfWindow) + throws AWTException, InterruptedException, InvocationTargetException { + win.requestFocus(); + System.err.println("requestFocus: NEWT Component"); + } + private static void requestFocusAWT(final java.awt.Component comp, boolean onTitleBarIfWindow) + throws AWTException, InterruptedException, InvocationTargetException { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + comp.requestFocus(); + System.err.println("requestFocus: AWT Component"); + }}); + } + + public static void requestFocus(Robot robot, Object obj, int x, int y) + throws AWTException, InterruptedException, InvocationTargetException { + validateAWTEDTIsAlive(); + + final boolean idling = robot.isAutoWaitForIdle(); + final int mouseButton = java.awt.event.InputEvent.BUTTON1_MASK; + robot.mouseMove( x, y ); + if( idling ) { + robot.waitForIdle(); + } else { + try { Thread.sleep(50); } catch (InterruptedException e) { } + } + robot.mousePress(mouseButton); + robot.mouseRelease(mouseButton); + final int d = getClickTimeout(obj) + 1; + robot.delay( d ); + } public static boolean hasFocus(Object obj) { - if(obj instanceof Component) { - final Component comp = (Component) obj; - final KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager(); - return comp == kfm.getPermanentFocusOwner(); - } else if(obj instanceof com.jogamp.newt.Window) { + if(obj instanceof com.jogamp.newt.Window) { return ((com.jogamp.newt.Window) obj).hasFocus(); + } else if(NativeWindowFactory.isAWTAvailable() && obj instanceof java.awt.Component) { + final java.awt.Component comp = (java.awt.Component) obj; + final java.awt.KeyboardFocusManager kfm = java.awt.KeyboardFocusManager.getCurrentKeyboardFocusManager(); + return comp == kfm.getPermanentFocusOwner(); } else { throw new RuntimeException("Neither AWT nor NEWT: "+obj); } @@ -253,17 +364,17 @@ public class AWTRobotUtil { */ public static boolean waitForFocus(Object obj) throws InterruptedException { int wait; - if(obj instanceof Component) { - final Component comp = (Component) obj; - final KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager(); - for (wait=0; wait<POLL_DIVIDER && comp != kfm.getPermanentFocusOwner(); wait++) { - Thread.sleep(TIME_SLICE); - } - } else if(obj instanceof com.jogamp.newt.Window) { + if(obj instanceof com.jogamp.newt.Window) { final com.jogamp.newt.Window win = (com.jogamp.newt.Window) obj; for (wait=0; wait<POLL_DIVIDER && !win.hasFocus(); wait++) { Thread.sleep(TIME_SLICE); } + } else if(NativeWindowFactory.isAWTAvailable() && obj instanceof java.awt.Component) { + final java.awt.Component comp = (java.awt.Component) obj; + final java.awt.KeyboardFocusManager kfm = java.awt.KeyboardFocusManager.getCurrentKeyboardFocusManager(); + for (wait=0; wait<POLL_DIVIDER && comp != kfm.getPermanentFocusOwner(); wait++) { + Thread.sleep(TIME_SLICE); + } } else { throw new RuntimeException("Neither AWT nor NEWT: "+obj); } @@ -274,18 +385,11 @@ public class AWTRobotUtil { * * @return True if the Window became the global focused Window within TIME_OUT */ - public static boolean waitForFocus(Object obj, FocusEventCountAdapter gain, - FocusEventCountAdapter lost) throws InterruptedException { - if(!waitForFocus(obj)) { - return false; - } - if(null == gain) { - return true; - } - + public static boolean waitForFocus(FocusEventCountAdapter gain, + FocusEventCountAdapter lost) throws InterruptedException { int wait; for (wait=0; wait<POLL_DIVIDER; wait++) { - if( ( null == lost || lost.focusLost() ) && gain.focusGained() ) { + if( ( null == lost || lost.focusLost() ) && ( null == gain || gain.focusGained() ) ) { return true; } Thread.sleep(TIME_SLICE); @@ -293,79 +397,160 @@ public class AWTRobotUtil { return false; } - public static void assertRequestFocusAndWait(Robot robot, Object requestFocus, Object waitForFocus, + /** + * + * @return True if the Window became the global focused Window within TIME_OUT + */ + public static boolean waitForFocus(Object obj, FocusEventCountAdapter gain, + FocusEventCountAdapter lost) throws InterruptedException { + if(!waitForFocus(obj)) { + return false; + } + return waitForFocus(gain, lost); + } + + public static void assertRequestFocusAndWait(Robot robot, Object requestFocus, Object waitForFocus, FocusEventCountAdapter gain, FocusEventCountAdapter lost) throws AWTException, InterruptedException, InvocationTargetException { int i = 0; boolean hasFocus = false; - + for(i=0; i < RETRY_NUMBER && !hasFocus; i++) { requestFocus(robot, requestFocus); hasFocus = waitForFocus(waitForFocus, gain, lost); } if(!hasFocus) { System.err.print("*** AWTRobotUtil.assertRequestFocusAndWait() "); - if(gain.focusGained() && !lost.focusLost()) { - // be error tolerant here, some impl. may lack focus-lost events (OS X) + if( ( null == gain || gain.focusGained() ) && ( null == lost || !lost.focusLost() ) ) { + // be error tolerant here, some impl. may lack focus-lost events (OS X) System.err.println("minor UI failure"); hasFocus = true; } else { System.err.println("major UI failure"); } - if(requestFocus instanceof Component) { - System.err.println("*** requestFocus.hasFocus() - AWT: "+((Component)requestFocus).hasFocus()); - } else if(requestFocus instanceof NativeWindow) { + if(requestFocus instanceof NativeWindow) { System.err.println("*** requestFocus.hasFocus() - NW: "+((NativeWindow)requestFocus).hasFocus()); + } else if(NativeWindowFactory.isAWTAvailable() && requestFocus instanceof java.awt.Component) { + System.err.println("*** requestFocus.hasFocus() - AWT: "+((java.awt.Component)requestFocus).hasFocus()); } - if(waitForFocus instanceof Component) { - System.err.println("*** waitForFocus.hasFocus() - AWT: "+((Component)waitForFocus).hasFocus()); - } else if(waitForFocus instanceof NativeWindow) { + if(waitForFocus instanceof NativeWindow) { System.err.println("*** waitForFocus.hasFocus() - NW: "+((NativeWindow)waitForFocus).hasFocus()); + } else if(NativeWindowFactory.isAWTAvailable() && waitForFocus instanceof java.awt.Component) { + System.err.println("*** waitForFocus.hasFocus() - AWT: "+((java.awt.Component)waitForFocus).hasFocus()); } System.err.println("*** gain: "+gain); System.err.println("*** lost: "+lost); - Thread.dumpStack(); + Thread.dumpStack(); } Assert.assertTrue("Did not gain focus", hasFocus); } + private static void awtRobotKeyPress(final Robot robot, final int keyCode, final int msDelay) { + robot.keyPress(keyCode); + robot.delay(msDelay); + } + private static void awtRobotKeyRelease(final Robot robot, final int keyCode, final int msDelay) { + robot.keyRelease(keyCode); + robot.delay(msDelay); + } + public static int keyType(int i, Robot robot, int keyCode, - Object obj, InputEventCountAdapter counter) throws InterruptedException, AWTException, InvocationTargetException + Object obj, KeyEventCountAdapter counter) throws InterruptedException, AWTException, InvocationTargetException { int tc = 0; int j; final long t0 = System.currentTimeMillis(); - + final int c0 = null!=counter ? counter.getCount() : 0; + for(j=0; 1 > tc && j<RETRY_NUMBER; j++) { if(!hasFocus(obj)) { // focus lost for some reason, regain it programmatic - if(DEBUG) { System.err.println(i+":"+j+" KC1.0: "+counter+" - regain focus"); } + if(DEBUG) { System.err.println(i+":"+j+" KC1.0: "+counter+" - regain focus on thread "+Thread.currentThread().getName()); } requestFocus(null, obj); } - final int c0 = null!=counter ? counter.getCount() : 0; - if(DEBUG) { System.err.println(i+":"+j+" KC1.1: "+counter); } - robot.waitForIdle(); - robot.keyPress(keyCode); - robot.keyRelease(keyCode); - if(DEBUG) { System.err.println(i+":"+j+" KC1.2: "+counter); } + waitForIdle(robot); + if(DEBUG) { System.err.println(i+":"+j+" KC1.1: "+counter+" on thread "+Thread.currentThread().getName()); } + awtRobotKeyPress(robot, keyCode, 50); + if(DEBUG) { System.err.println(i+":"+j+" KC1.2: "+counter+" on thread "+Thread.currentThread().getName()); } + awtRobotKeyRelease(robot, keyCode, 100); + waitForIdle(robot); + if(DEBUG) { System.err.println(i+":"+j+" KC1.3: "+counter); } tc = ( null!=counter ? counter.getCount() : 1 ) - c0; for (int wait=0; wait<POLL_DIVIDER && 1 > tc; wait++) { + if(DEBUG) { System.err.println(i+":"+j+" KC1.4."+wait+": "+counter+", sleep for "+TIME_OUT+"ms"); } robot.delay(TIME_SLICE); tc = counter.getCount() - c0; } - if(DEBUG) { System.err.println(i+":"+j+" KC1.X: tc "+tc+", "+counter); } + if(DEBUG) { System.err.println(i+":"+j+" KC1.X: tc "+tc+", "+counter+" on thread "+Thread.currentThread().getName()); } } - Assert.assertEquals("Key ("+i+":"+j+") not typed one time", 1, tc); + Assert.assertEquals("Key ("+i+":"+j+") not typed one time on thread "+Thread.currentThread().getName(), 1, tc); return (int) ( System.currentTimeMillis() - t0 ) ; } - + + /** No validation is performed .. */ + public static int keyPress(int i, Robot robot, boolean press, int keyCode, int msDelay) { + final long t0 = System.currentTimeMillis(); + if(press) { + awtRobotKeyPress(robot, keyCode, msDelay); + } else { + awtRobotKeyRelease(robot, keyCode, msDelay); + } + + return (int) ( System.currentTimeMillis() - t0 ) ; + } + + /** No validation is performed .. */ + public static int newtKeyPress(int i, Robot robot, boolean press, short newtKeyCode, int msDelay) { + final int keyCode = AWTNewtEventFactory.newtKeyCode2AWTKeyCode(newtKeyCode); + final long t0 = System.currentTimeMillis(); + if(press) { + awtRobotKeyPress(robot, keyCode, msDelay); + } else { + awtRobotKeyRelease(robot, keyCode, msDelay); + } + + return (int) ( System.currentTimeMillis() - t0 ) ; + } + + /** + * @param keyCode TODO + * @param counter shall return the number of keys typed (press + release) + */ + public static void assertKeyType(Robot robot, int keyCode, int typeCount, + Object obj, KeyEventCountAdapter counter) + throws AWTException, InterruptedException, InvocationTargetException { + + if(null == robot) { + robot = new Robot(); + robot.setAutoWaitForIdle(true); + } + + centerMouse(robot, obj, false); + + Assert.assertEquals("Key already pressed", false, counter.isPressed()); + + if(DEBUG) { + System.err.println("**************************************"); + System.err.println("KC0: "+counter); + } + + final int c0 = counter.getCount(); + + for(int i=0; i<typeCount; i++) { + keyType(i, robot, keyCode, obj, counter); + } + + if(DEBUG) { System.err.println("KC3.0: "+counter); } + Assert.assertEquals("Wrong key count", typeCount, counter.getCount()-c0); + } + /** * @param keyCode TODO * @param counter shall return the number of keys typed (press + release) */ - public static void assertKeyType(Robot robot, int keyCode, int typeCount, - Object obj, InputEventCountAdapter counter) + public static void assertKeyPress(Robot robot, int keyCode, int typeCount, + Object obj, KeyEventCountAdapter counter) throws AWTException, InterruptedException, InvocationTargetException { if(null == robot) { @@ -376,16 +561,16 @@ public class AWTRobotUtil { centerMouse(robot, obj, false); Assert.assertEquals("Key already pressed", false, counter.isPressed()); - + if(DEBUG) { System.err.println("**************************************"); System.err.println("KC0: "+counter); } - + final int c0 = counter.getCount(); for(int i=0; i<typeCount; i++) { - keyType(i, robot, keyCode, obj, counter); + keyType(i, robot, keyCode, obj, counter); } if(DEBUG) { System.err.println("KC3.0: "+counter); } @@ -393,12 +578,12 @@ public class AWTRobotUtil { } static int mouseClick(int i, Robot robot, int mouseButton, - Object obj, InputEventCountAdapter counter) throws InterruptedException, AWTException, InvocationTargetException + Object obj, InputEventCountAdapter counter) throws InterruptedException, AWTException, InvocationTargetException { int j; int tc = 0; final long t0 = System.currentTimeMillis(); - + for(j=0; 1 > tc && j<RETRY_NUMBER; j++) { if(!hasFocus(obj)) { // focus lost for some reason, regain it programmatic @@ -407,7 +592,7 @@ public class AWTRobotUtil { } final int c0 = null != counter ? counter.getCount() : 0; if(DEBUG) { System.err.println(i+":"+j+" MC1.1: "+counter); } - robot.waitForIdle(); + waitForIdle(robot); robot.mousePress(mouseButton); robot.mouseRelease(mouseButton); if(DEBUG) { System.err.println(i+":"+j+" MC1.2: "+counter); } @@ -421,13 +606,13 @@ public class AWTRobotUtil { Assert.assertEquals("Mouse ("+i+":"+j+") not clicked one time", 1, tc); return (int) ( System.currentTimeMillis() - t0 ) ; } - + /** * @param mouseButton ie InputEvent.BUTTON1_MASK * @param clickCount ie 1, or 2 */ public static void assertMouseClick(Robot robot, int mouseButton, int clickCount, - Object obj, InputEventCountAdapter counter) + Object obj, InputEventCountAdapter counter) throws AWTException, InterruptedException, InvocationTargetException { if(null == robot) { @@ -440,14 +625,14 @@ public class AWTRobotUtil { centerMouse(robot, obj, false); Assert.assertEquals("Mouse already pressed", false, counter.isPressed()); - + if(DEBUG) { System.err.println("**************************************"); System.err.println("MC0: "+counter); } - + final int c0 = counter.getCount(); - + for(int i=0; i<clickCount; i++) { final int waited = mouseClick(i, robot, mouseButton, obj, counter); if(DEBUG) { System.err.println(i+": MC2.X: "+counter+", consumed: "+waited); } @@ -460,34 +645,20 @@ public class AWTRobotUtil { /** * - * @return True if the FocusEventCountAdapter became the desired value within TIME_OUT - */ - public static boolean waitForFocusCount(boolean desired, FocusEventCountAdapter eca) throws InterruptedException { - for (int wait=0; wait<POLL_DIVIDER; wait++) { - if( desired && eca.focusGained() || !desired && eca.focusLost() ) { - return true; - } - Thread.sleep(TIME_SLICE); - } - return false; - } - - /** - * * @return True if the Component becomes <code>visible</code> within TIME_OUT */ public static boolean waitForVisible(Object obj, boolean visible) throws InterruptedException { int wait; - if(obj instanceof Component) { - Component comp = (Component) obj; - for (wait=0; wait<POLL_DIVIDER && visible != comp.isVisible(); wait++) { - Thread.sleep(TIME_SLICE); - } - } else if(obj instanceof com.jogamp.newt.Window) { + if(obj instanceof com.jogamp.newt.Window) { com.jogamp.newt.Window win = (com.jogamp.newt.Window) obj; for (wait=0; wait<POLL_DIVIDER && visible != win.isVisible(); wait++) { Thread.sleep(TIME_SLICE); } + } else if(NativeWindowFactory.isAWTAvailable() && obj instanceof java.awt.Component) { + java.awt.Component comp = (java.awt.Component) obj; + for (wait=0; wait<POLL_DIVIDER && visible != comp.isShowing(); wait++) { + Thread.sleep(TIME_SLICE); + } } else { throw new RuntimeException("Neither AWT nor NEWT: "+obj); } @@ -496,41 +667,131 @@ public class AWTRobotUtil { /** * + * @return True if the GLDrawable receives the expected size within TIME_OUT + */ + public static boolean waitForSize(GLDrawable drawable, int width, int height) throws InterruptedException { + int wait; + for (wait=0; wait<POLL_DIVIDER && ( width != drawable.getWidth() || height != drawable.getHeight() ) ; wait++) { + Thread.sleep(TIME_SLICE); + } + return wait<POLL_DIVIDER; + } + + /** + * @param obj the component to wait for + * @param realized true if waiting for component to become realized, otherwise false * @return True if the Component becomes realized (not displayable, native invalid) within TIME_OUT + * @throws InterruptedException */ public static boolean waitForRealized(Object obj, boolean realized) throws InterruptedException { - int wait; - if (obj instanceof Component) { - Component comp = (Component) obj; - for (wait=0; wait<POLL_DIVIDER && realized != comp.isDisplayable(); wait++) { - Thread.sleep(TIME_SLICE); + return waitForRealized(obj, null, realized); + } + + /** + * @param obj the component to wait for + * @param waitAction if not null, Runnable shall wait {@link #TIME_SLICE} ms, if appropriate + * @param realized true if waiting for component to become realized, otherwise false + * @return True if the Component becomes realized (not displayable, native invalid) within TIME_OUT + * @throws InterruptedException + */ + public static boolean waitForRealized(Object obj, Runnable waitAction, boolean realized) throws InterruptedException { + long t0 = System.currentTimeMillis(); + long t1 = t0; + if(obj instanceof com.jogamp.newt.Screen) { + com.jogamp.newt.Screen screen = (com.jogamp.newt.Screen) obj; + while( (t1-t0) < TIME_OUT && realized != screen.isNativeValid() ) { + if( null != waitAction ) { + waitAction.run(); + } else { + Thread.sleep(TIME_SLICE); + } + t1 = System.currentTimeMillis(); } - // if GLCanvas, ensure it got also painted -> drawable.setRealized(true); - if(wait<POLL_DIVIDER && comp instanceof GLCanvas) { - GLCanvas glcanvas = (GLCanvas) comp; - for (wait=0; wait<POLL_DIVIDER && realized != glcanvas.isRealized(); wait++) { + } else if(obj instanceof com.jogamp.newt.Window) { + com.jogamp.newt.Window win = (com.jogamp.newt.Window) obj; + while( (t1-t0) < TIME_OUT && realized != win.isNativeValid() ) { + if( null != waitAction ) { + waitAction.run(); + } else { Thread.sleep(TIME_SLICE); } - if(wait>=POLL_DIVIDER) { - // for some reason GLCanvas hasn't been painted yet, force it! - System.err.println("XXX: FORCE REPAINT PRE - canvas: "+glcanvas); - glcanvas.repaint(); - for (wait=0; wait<POLL_DIVIDER && realized != glcanvas.isRealized(); wait++) { + t1 = System.currentTimeMillis(); + } + } else if (NativeWindowFactory.isAWTAvailable() && obj instanceof java.awt.Component) { + java.awt.Component comp = (java.awt.Component) obj; + while( (t1-t0) < TIME_OUT && realized != comp.isShowing() ) { + if( null != waitAction ) { + waitAction.run(); + } else { + Thread.sleep(TIME_SLICE); + } + t1 = System.currentTimeMillis(); + } + // if GLCanvas, ensure it got also painted -> drawable.setRealized(true); + if( (t1-t0) < TIME_OUT && comp instanceof GLAutoDrawable) { + GLAutoDrawable glad = (GLAutoDrawable) comp; + t0 = System.currentTimeMillis(); + while( (t1-t0) < TIME_OUT && realized != glad.isRealized() ) { + if( null != waitAction ) { + waitAction.run(); + } else { Thread.sleep(TIME_SLICE); } - System.err.println("XXX: FORCE REPAINT POST - canvas: "+glcanvas); + t1 = System.currentTimeMillis(); } - for (wait=0; wait<POLL_DIVIDER && realized != glcanvas.isRealized(); wait++) { + if( (t1-t0) >= TIME_OUT ) { + // for some reason GLCanvas hasn't been painted yet, force it! + System.err.println("XXX: FORCE REPAINT PRE - glad: "+glad); + comp.repaint(); + t0 = System.currentTimeMillis(); + while( (t1-t0) < TIME_OUT && realized != glad.isRealized() ) { + if( null != waitAction ) { + waitAction.run(); + } else { + Thread.sleep(TIME_SLICE); + } + t1 = System.currentTimeMillis(); + } + System.err.println("XXX: FORCE REPAINT POST - glad: "+glad); + } + } + } else if(obj instanceof GLAutoDrawable) { + GLAutoDrawable glad = (GLAutoDrawable) obj; + while( (t1-t0) < TIME_OUT && realized != glad.isRealized() ) { + if( null != waitAction ) { + waitAction.run(); + } else { Thread.sleep(TIME_SLICE); } - } - } else if(obj instanceof com.jogamp.newt.Window) { - com.jogamp.newt.Window win = (com.jogamp.newt.Window) obj; - for (wait=0; wait<POLL_DIVIDER && realized != win.isNativeValid(); wait++) { - Thread.sleep(TIME_SLICE); + t1 = System.currentTimeMillis(); } } else { - throw new RuntimeException("Neither AWT nor NEWT: "+obj); + throw new RuntimeException("Neither AWT nor NEWT nor GLAutoDrawable: "+obj); + } + return (t1-t0) < TIME_OUT; + } + + /** + * + * @return True if the GLContext becomes created or not within TIME_OUT + */ + public static boolean waitForContextCreated(GLAutoDrawable autoDrawable, boolean created) throws InterruptedException { + if( null == autoDrawable ) { + return !created; + } + int wait; + for (wait=0; wait<POLL_DIVIDER ; wait++) { + final GLContext ctx = autoDrawable.getContext(); + if( created ) { + if( null != ctx && ctx.isCreated() ) { + break; + } + } else { + if( null == ctx || !ctx.isCreated() ) { + break; + } + } + Thread.sleep(TIME_SLICE); } return wait<POLL_DIVIDER; } @@ -541,16 +802,19 @@ public class AWTRobotUtil { * * @param obj either an AWT Window (Frame, JFrame) or NEWT Window * @param willClose indicating that the window will close, hence this method waits for the window to be closed + * @param wcl the WindowClosingListener to determine whether the AWT or NEWT widget has been closed. It should be attached + * to the widget ASAP before any other listener, e.g. via {@link #addClosingListener(Object)}. + * The WindowClosingListener will be reset before attempting to close the widget. * @return True if the Window is closing and closed (if willClose is true), each within TIME_OUT * @throws InterruptedException */ - public static boolean closeWindow(Object obj, boolean willClose) throws InterruptedException, InvocationTargetException { - WindowClosingListener closingListener = addClosingListener(obj); + public static boolean closeWindow(Object obj, boolean willClose, WindowClosingListener closingListener) throws InterruptedException { + closingListener.reset(); if(obj instanceof java.awt.Window) { final java.awt.Window win = (java.awt.Window) obj; - Toolkit tk = Toolkit.getDefaultToolkit(); - final EventQueue evtQ = tk.getSystemEventQueue(); - EventQueue.invokeAndWait(new Runnable() { + java.awt.Toolkit tk = java.awt.Toolkit.getDefaultToolkit(); + final java.awt.EventQueue evtQ = tk.getSystemEventQueue(); + AWTEDTExecutor.singleton.invoke(true, new Runnable() { public void run() { evtQ.postEvent(new java.awt.event.WindowEvent(win, java.awt.event.WindowEvent.WINDOW_CLOSING)); } }); @@ -570,12 +834,15 @@ public class AWTRobotUtil { return wait<POLL_DIVIDER; } - public static WindowClosingListener addClosingListener(Object obj) throws InterruptedException { + public static WindowClosingListener addClosingListener(Object obj) { WindowClosingListener cl = null; if(obj instanceof java.awt.Window) { - java.awt.Window win = (java.awt.Window) obj; - AWTWindowClosingAdapter acl = new AWTWindowClosingAdapter(); - win.addWindowListener(acl); + final java.awt.Window win = (java.awt.Window) obj; + final AWTWindowClosingAdapter acl = new AWTWindowClosingAdapter(); + AWTEDTExecutor.singleton.invoke(true, new Runnable() { + public void run() { + win.addWindowListener(acl); + } } ); cl = acl; } else if(obj instanceof com.jogamp.newt.Window) { com.jogamp.newt.Window win = (com.jogamp.newt.Window) obj; @@ -589,53 +856,77 @@ public class AWTRobotUtil { } public static interface WindowClosingListener { void reset(); + public int getWindowClosingCount(); + public int getWindowClosedCount(); public boolean isWindowClosing(); public boolean isWindowClosed(); } static class AWTWindowClosingAdapter extends java.awt.event.WindowAdapter implements WindowClosingListener { - volatile boolean closing = false; - volatile boolean closed = false; + volatile int closing = 0; + volatile int closed = 0; public void reset() { - closing = false; - closed = false; + closing = 0; + closed = 0; } - public boolean isWindowClosing() { + public int getWindowClosingCount() { return closing; } - public boolean isWindowClosed() { + public int getWindowClosedCount() { return closed; } + public boolean isWindowClosing() { + return 0 < closing; + } + public boolean isWindowClosed() { + return 0 < closed; + } public void windowClosing(java.awt.event.WindowEvent e) { - closing = true; + closing++; + System.err.println("AWTWindowClosingAdapter.windowClosing: "+this); } public void windowClosed(java.awt.event.WindowEvent e) { - closed = true; + closed++; + System.err.println("AWTWindowClosingAdapter.windowClosed: "+this); + } + public String toString() { + return "AWTWindowClosingAdapter[closing "+closing+", closed "+closed+"]"; } } static class NEWTWindowClosingAdapter extends com.jogamp.newt.event.WindowAdapter implements WindowClosingListener { - volatile boolean closing = false; - volatile boolean closed = false; + volatile int closing = 0; + volatile int closed = 0; public void reset() { - closing = false; - closed = false; + closing = 0; + closed = 0; } - public boolean isWindowClosing() { + public int getWindowClosingCount() { return closing; } - public boolean isWindowClosed() { + public int getWindowClosedCount() { return closed; } - public void windowDestroyNotify(com.jogamp.newt.event.WindowEvent e) { - closing = true; + public boolean isWindowClosing() { + return 0 < closing; + } + public boolean isWindowClosed() { + return 0 < closed; + } + public void windowDestroyNotify(WindowEvent e) { + closing++; + System.err.println("NEWTWindowClosingAdapter.windowDestroyNotify: "+this); + } + public void windowDestroyed(WindowEvent e) { + closed++; + System.err.println("NEWTWindowClosingAdapter.windowDestroyed: "+this); } - public void windowDestroyed(com.jogamp.newt.event.WindowEvent e) { - closed = true; + public String toString() { + return "NEWTWindowClosingAdapter[closing "+closing+", closed "+closed+"]"; } } diff --git a/src/test/com/jogamp/opengl/test/junit/util/AWTWindowFocusAdapter.java b/src/test/com/jogamp/opengl/test/junit/util/AWTWindowFocusAdapter.java index 16aacd2fd..2e74dfae8 100644 --- a/src/test/com/jogamp/opengl/test/junit/util/AWTWindowFocusAdapter.java +++ b/src/test/com/jogamp/opengl/test/junit/util/AWTWindowFocusAdapter.java @@ -35,12 +35,15 @@ public class AWTWindowFocusAdapter implements FocusEventCountAdapter, WindowFocu String prefix; int focusCount; + boolean verbose = true; public AWTWindowFocusAdapter(String prefix) { this.prefix = prefix; reset(); } + public void setVerbose(boolean v) { verbose = false; } + public boolean focusLost() { return focusCount<0; } @@ -57,14 +60,18 @@ public class AWTWindowFocusAdapter implements FocusEventCountAdapter, WindowFocu public void windowGainedFocus(WindowEvent e) { if(focusCount<0) { focusCount=0; } focusCount++; - System.err.println("FOCUS AWT GAINED (Window) [fc "+focusCount+"]: "+prefix+", "+e); + if( verbose ) { + System.err.println("FOCUS AWT GAINED (Window) [fc "+focusCount+"]: "+prefix+", "+e); + } } /* @Override */ public void windowLostFocus(WindowEvent e) { if(focusCount>0) { focusCount=0; } focusCount--; - System.err.println("FOCUS AWT LOST (Window) [fc "+focusCount+"]: "+prefix+", "+e); + if( verbose ) { + System.err.println("FOCUS AWT LOST (Window) [fc "+focusCount+"]: "+prefix+", "+e); + } } public String toString() { return prefix+"[focusCount "+focusCount +"]"; } diff --git a/src/test/com/jogamp/opengl/test/junit/util/DumpGLInfo.java b/src/test/com/jogamp/opengl/test/junit/util/DumpGLInfo.java index e49679dc3..99db0753b 100644 --- a/src/test/com/jogamp/opengl/test/junit/util/DumpGLInfo.java +++ b/src/test/com/jogamp/opengl/test/junit/util/DumpGLInfo.java @@ -3,14 +3,14 @@ * * 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 @@ -20,12 +20,12 @@ * 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.util; @@ -37,7 +37,7 @@ public class DumpGLInfo implements GLEventListener { public void init(GLAutoDrawable drawable) { GL gl = drawable.getGL(); - System.err.println(JoglVersion.getGLInfo(gl, null)); + System.err.println(JoglVersion.getGLInfo(gl, null, true)); } public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { diff --git a/src/test/com/jogamp/opengl/test/junit/util/EventCountAdapter.java b/src/test/com/jogamp/opengl/test/junit/util/EventCountAdapter.java index 76a1884c8..906e4a7c9 100644 --- a/src/test/com/jogamp/opengl/test/junit/util/EventCountAdapter.java +++ b/src/test/com/jogamp/opengl/test/junit/util/EventCountAdapter.java @@ -28,7 +28,16 @@ package com.jogamp.opengl.test.junit.util; +/** + * Base event count adapter. + * <p> + * Instance starts in verbose mode. + * </p> + */ public interface EventCountAdapter { void reset(); + + /** Instance starts in verbose mode, call w/ false to disable verbosity. */ + void setVerbose(boolean v); } diff --git a/src/test/com/jogamp/opengl/test/junit/util/GLEventListenerCounter.java b/src/test/com/jogamp/opengl/test/junit/util/GLEventListenerCounter.java new file mode 100644 index 000000000..b0f6e2c7e --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/util/GLEventListenerCounter.java @@ -0,0 +1,69 @@ +/** + * Copyright 2013 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.util; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; + +public class GLEventListenerCounter implements GLEventListener { + public int initCount = 0; + public int displayCount = 0; + public int reshapeCount = 0; + public int disposeCount = 0; + + public void reset() { + initCount = 0; + displayCount = 0; + reshapeCount = 0; + disposeCount = 0; + } + + @Override + public void init(GLAutoDrawable drawable) { + initCount++; + } + + @Override + public void dispose(GLAutoDrawable drawable) { + disposeCount++; + } + + @Override + public void display(GLAutoDrawable drawable) { + displayCount++; + } + + @Override + public void reshape(GLAutoDrawable d, int x, int y, int width, int height) { + reshapeCount++; + } + + public String toString() { + return "GLEventListenerCounter[init "+initCount+", dispose "+disposeCount+", reshape "+reshapeCount+", display "+displayCount+"]"; + } +}
\ No newline at end of file diff --git a/src/test/com/jogamp/opengl/test/junit/util/GLSLSimpleProgram.java b/src/test/com/jogamp/opengl/test/junit/util/GLSLSimpleProgram.java index 989de6c7e..926d4490c 100644 --- a/src/test/com/jogamp/opengl/test/junit/util/GLSLSimpleProgram.java +++ b/src/test/com/jogamp/opengl/test/junit/util/GLSLSimpleProgram.java @@ -58,7 +58,7 @@ public class GLSLSimpleProgram { int fragShader = gl.glCreateShader(GL2ES2.GL_FRAGMENT_SHADER); Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); - String[] vlines = new String[] { vertShaderCode }; + String[] vlines = new String[] { gl.getContext().getGLSLVersionString()+vertShaderCode }; int[] vlengths = new int[] { vlines[0].length() }; gl.glShaderSource(vertShader, vlines.length, vlines, vlengths, 0); gl.glCompileShader(vertShader); @@ -70,7 +70,7 @@ public class GLSLSimpleProgram { Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); - String[] flines = new String[] { fragShaderCode }; + String[] flines = new String[] { gl.getContext().getGLSLVersionString()+fragShaderCode }; int[] flengths = new int[] { flines[0].length() }; gl.glShaderSource(fragShader, flines.length, flines, flengths, 0); gl.glCompileShader(fragShader); diff --git a/src/test/com/jogamp/opengl/test/junit/util/InputEventCountAdapter.java b/src/test/com/jogamp/opengl/test/junit/util/InputEventCountAdapter.java index 27f3d7e29..a32e995d9 100644 --- a/src/test/com/jogamp/opengl/test/junit/util/InputEventCountAdapter.java +++ b/src/test/com/jogamp/opengl/test/junit/util/InputEventCountAdapter.java @@ -3,14 +3,14 @@ * * 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 @@ -20,16 +20,23 @@ * 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.util; +import java.util.EventObject; +import java.util.List; + public interface InputEventCountAdapter extends EventCountAdapter { + int getConsumedCount(); int getCount(); boolean isPressed(); + + public List<EventObject> copyQueue(); + public int getQueueSize(); } diff --git a/src/test/com/jogamp/opengl/test/junit/util/KeyEventCountAdapter.java b/src/test/com/jogamp/opengl/test/junit/util/KeyEventCountAdapter.java new file mode 100644 index 000000000..1d6d97a17 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/util/KeyEventCountAdapter.java @@ -0,0 +1,36 @@ +/** + * Copyright 2012 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.util; + +public interface KeyEventCountAdapter extends InputEventCountAdapter { + public int getKeyPressedCount(boolean autoRepeatOnly); + + public int getKeyReleasedCount(boolean autoRepeatOnly); +} + diff --git a/src/test/com/jogamp/opengl/test/junit/util/MiscUtils.java b/src/test/com/jogamp/opengl/test/junit/util/MiscUtils.java index 9cbeabb85..e5f13640d 100644 --- a/src/test/com/jogamp/opengl/test/junit/util/MiscUtils.java +++ b/src/test/com/jogamp/opengl/test/junit/util/MiscUtils.java @@ -3,14 +3,14 @@ * * 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 @@ -20,18 +20,39 @@ * 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.util; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; import java.lang.reflect.*; +import java.nio.FloatBuffer; +import java.util.Iterator; +import java.util.List; + +import javax.media.opengl.GLContext; + +import com.jogamp.common.os.Platform; public class MiscUtils { + public static boolean atob(String str, boolean def) { + try { + return Boolean.parseBoolean(str); + } catch (Exception ex) { + ex.printStackTrace(); + } + return def; + } + public static int atoi(String str, int def) { try { return Integer.parseInt(str); @@ -40,7 +61,7 @@ public class MiscUtils { } return def; } - + public static long atol(String str, long def) { try { return Long.parseLong(str); @@ -50,6 +71,78 @@ public class MiscUtils { return def; } + public static float atof(String str, float def) { + try { + return Float.parseFloat(str); + } catch (Exception ex) { + ex.printStackTrace(); + } + return def; + } + + public static String toHexString(byte hex) { + return "0x" + Integer.toHexString( hex & 0x000000FF ); + } + + public static String toHexString(short hex) { + return "0x" + Integer.toHexString( hex & 0x0000FFFF ); + } + + public static String toHexString(int hex) { + return "0x" + Integer.toHexString( hex ); + } + + public static String toHexString(long hex) { + return "0x" + Long.toHexString( hex ); + } + + public static void assertFloatBufferEquals(String errmsg, FloatBuffer expected, FloatBuffer actual, float delta) { + if(null == expected && null == actual) { + return; + } + String msg = null != errmsg ? errmsg + " " : ""; + if(null == expected) { + throw new AssertionError(msg+"; Expected is null, but actual not: "+actual); + } + if(null == actual) { + throw new AssertionError(msg+"; Actual is null, but expected not: "+expected); + } + if(expected.remaining() != actual.remaining()) { + throw new AssertionError(msg+"; Expected has "+expected.remaining()+" remaining, but actual has "+actual.remaining()); + } + final int a0 = expected.position(); + final int b0 = actual.position(); + for(int i=0; i<expected.remaining(); i++) { + final float ai = expected.get(a0 + i); + final float bi = actual.get(b0 + i); + final float daibi = Math.abs(ai - bi); + if( daibi > delta ) { + throw new AssertionError(msg+"; Expected @ ["+a0+"+"+i+"] has "+ai+", but actual @ ["+b0+"+"+i+"] has "+bi+", it's delta "+daibi+" > "+delta); + } + } + } + + public static void assertFloatBufferNotEqual(String errmsg, FloatBuffer expected, FloatBuffer actual, float delta) { + if(null == expected || null == actual) { + return; + } + if(expected.remaining() != actual.remaining()) { + return; + } + String msg = null != errmsg ? errmsg + " " : ""; + final int a0 = expected.position(); + final int b0 = actual.position(); + for(int i=0; i<expected.remaining(); i++) { + final float ai = expected.get(a0 + i); + final float bi = actual.get(b0 + i); + final float daibi = Math.abs(ai - bi); + if( daibi > delta ) { + return; + } + } + throw new AssertionError(msg+"; Expected and actual are equal."); + } + public static boolean setFieldIfExists(Object instance, String fieldName, Object value) { try { Field f = instance.getClass().getField(fieldName); @@ -66,6 +159,81 @@ public class MiscUtils { } return false; } + + public static class StreamDump extends Thread { + final InputStream is; + final StringBuilder outString; + final OutputStream outStream; + final String prefix; + final Object sync; + volatile boolean eos = false; + + public StreamDump(OutputStream out, String prefix, InputStream is, Object sync) { + this.is = is; + this.outString = null; + this.outStream = out; + this.prefix = prefix; + this.sync = sync; + } + public StreamDump(StringBuilder sb, InputStream is, Object sync) { + this.is = is; + this.outString = sb; + this.outStream = null; + this.prefix = null; + this.sync = sync; + } + + public final boolean eos() { return eos; } + + @Override + public void run() { + synchronized ( sync ) { + try { + final BufferedReader in = new BufferedReader( new InputStreamReader(is) ); + String line = null; + while ((line = in.readLine()) != null) { + if( null != outString ) { + outString.append(line).append(Platform.getNewline()); + } else if( null != outStream ) { + if( null != prefix ) { + outStream.write(prefix.getBytes()); + } + outStream.write(line.getBytes()); + outStream.write(Platform.getNewline().getBytes()); + outStream.flush(); + } + } + } catch (IOException ioe) { + System.err.println("Catched "+ioe.getClass().getName()+": "+ioe.getMessage()); + ioe.printStackTrace(); + } finally { + eos = true; + sync.notifyAll(); + } + } + } + } + + public static void dumpSharedGLContext(GLContext self) { + int i = 0, j = 0; + System.err.println("Myself: hash 0x"+Integer.toHexString(self.hashCode())+", \t(isShared "+self.isShared()+", created "+self.isCreated()+")"); + { + final List<GLContext> set = self.getCreatedShares(); + for (final Iterator<GLContext> iter = set.iterator(); iter.hasNext(); ) { + final GLContext c = iter.next(); + System.err.println("Ctx #"+(i++)+": hash 0x"+Integer.toHexString(c.hashCode())+", \t(created "+c.isCreated()+")"); + } + } + { + final List<GLContext> set = self.getDestroyedShares(); + for (final Iterator<GLContext> iter = set.iterator(); iter.hasNext(); ) { + final GLContext c = iter.next(); + System.err.println("Ctx #"+(j++)+": hash 0x"+Integer.toHexString(c.hashCode())+", \t(created "+c.isCreated()+")"); + } + } + System.err.println("\t Total created "+i+" + destroyed "+j+" = "+(i+j)); + System.err.println(); + } } diff --git a/src/test/com/jogamp/opengl/test/junit/util/NEWTFocusAdapter.java b/src/test/com/jogamp/opengl/test/junit/util/NEWTFocusAdapter.java index 27d4abd9c..ccb1bde78 100644 --- a/src/test/com/jogamp/opengl/test/junit/util/NEWTFocusAdapter.java +++ b/src/test/com/jogamp/opengl/test/junit/util/NEWTFocusAdapter.java @@ -36,12 +36,15 @@ public class NEWTFocusAdapter implements WindowListener, FocusEventCountAdapter String prefix; int focusCount; + boolean verbose = true; public NEWTFocusAdapter(String prefix) { this.prefix = prefix; reset(); } + public void setVerbose(boolean v) { verbose = false; } + public boolean focusLost() { return focusCount<0; } @@ -57,13 +60,17 @@ public class NEWTFocusAdapter implements WindowListener, FocusEventCountAdapter public void windowGainedFocus(WindowEvent e) { if(focusCount<0) { focusCount=0; } focusCount++; - System.err.println("FOCUS NEWT GAINED [fc "+focusCount+"]: "+prefix+", "+e); + if( verbose ) { + System.err.println("FOCUS NEWT GAINED [fc "+focusCount+"]: "+prefix+", "+e); + } } public void windowLostFocus(WindowEvent e) { if(focusCount>0) { focusCount=0; } focusCount--; - System.err.println("FOCUS NEWT LOST [fc "+focusCount+"]: "+prefix+", "+e); + if( verbose ) { + System.err.println("FOCUS NEWT LOST [fc "+focusCount+"]: "+prefix+", "+e); + } } public void windowResized(WindowEvent e) { } diff --git a/src/test/com/jogamp/opengl/test/junit/util/NEWTGLContext.java b/src/test/com/jogamp/opengl/test/junit/util/NEWTGLContext.java index 4edac15ed..a76b67d57 100644 --- a/src/test/com/jogamp/opengl/test/junit/util/NEWTGLContext.java +++ b/src/test/com/jogamp/opengl/test/junit/util/NEWTGLContext.java @@ -43,10 +43,12 @@ public class NEWTGLContext { public static class WindowContext { public final Window window; + public final GLDrawable drawable; public final GLContext context; - public WindowContext(Window w, GLContext c) { + public WindowContext(Window w, GLDrawable d, GLContext c) { window = w; + drawable = d; context = c; } } @@ -68,8 +70,8 @@ public class NEWTGLContext { Assert.assertNotNull(window); window.setSize(width, height); window.setVisible(true); - AWTRobotUtil.waitForVisible(window, true); - AWTRobotUtil.waitForRealized(window, true); + Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true)); GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); GLDrawable drawable = factory.createGLDrawable(window); @@ -86,7 +88,7 @@ public class NEWTGLContext { int res = context.makeCurrent(); Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res); - return new WindowContext(window, context); + return new WindowContext(window, drawable, context); } public static WindowContext createOnscreenWindow(GLCapabilities caps, int width, int height, boolean debugGL) throws InterruptedException { @@ -121,7 +123,7 @@ public class NEWTGLContext { int res = context.makeCurrent(); Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res); - return new WindowContext(window, context); + return new WindowContext(window, drawable, context); } public static void destroyWindow(WindowContext winctx) { diff --git a/src/test/com/jogamp/opengl/test/junit/util/NEWTKeyAdapter.java b/src/test/com/jogamp/opengl/test/junit/util/NEWTKeyAdapter.java index 32b392ca8..0e86afd93 100644 --- a/src/test/com/jogamp/opengl/test/junit/util/NEWTKeyAdapter.java +++ b/src/test/com/jogamp/opengl/test/junit/util/NEWTKeyAdapter.java @@ -3,14 +3,14 @@ * * 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 @@ -20,57 +20,104 @@ * 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.util; +import java.util.ArrayList; +import java.util.EventObject; +import java.util.List; + +import com.jogamp.newt.event.InputEvent; import com.jogamp.newt.event.KeyAdapter; import com.jogamp.newt.event.KeyEvent; -public class NEWTKeyAdapter extends KeyAdapter implements InputEventCountAdapter { +public class NEWTKeyAdapter extends KeyAdapter implements KeyEventCountAdapter { String prefix; - int keyTyped; + int keyPressed, keyReleased; + int keyPressedAR, keyReleasedAR; + int consumed; boolean pressed; + List<EventObject> queue = new ArrayList<EventObject>(); + boolean verbose = true; public NEWTKeyAdapter(String prefix) { this.prefix = prefix; reset(); } - public boolean isPressed() { + public synchronized void setVerbose(boolean v) { verbose = v; } + + public synchronized boolean isPressed() { return pressed; } - - public int getCount() { - return keyTyped; + + public synchronized int getCount() { + return keyReleased; } - public void reset() { - keyTyped = 0; + public synchronized int getConsumedCount() { + return consumed; + } + + public synchronized int getKeyPressedCount(boolean autoRepeatOnly) { + return autoRepeatOnly ? keyPressedAR: keyPressed; + } + + public synchronized int getKeyReleasedCount(boolean autoRepeatOnly) { + return autoRepeatOnly ? keyReleasedAR: keyReleased; + } + + public synchronized List<EventObject> copyQueue() { + return new ArrayList<EventObject>(queue); + } + + public synchronized int getQueueSize() { + return queue.size(); + } + + public synchronized void reset() { + keyPressed = 0; + keyReleased = 0; + consumed = 0; + keyPressedAR = 0; + keyReleasedAR = 0; pressed = false; + queue.clear(); } - public void keyPressed(KeyEvent e) { + public synchronized void keyPressed(KeyEvent e) { pressed = true; - System.err.println("NEWT AWT PRESSED ["+pressed+"]: "+prefix+", "+e); + keyPressed++; + if( 0 != ( e.getModifiers() & InputEvent.AUTOREPEAT_MASK ) ) { + keyPressedAR++; + } + queue.add(e); + if( verbose ) { + System.err.println("KEY NEWT PRESSED ["+pressed+"]: "+prefix+", "+e); + } } - - public void keyReleased(KeyEvent e) { + + public synchronized void keyReleased(KeyEvent e) { pressed = false; - System.err.println("NEWT AWT RELEASED ["+pressed+"]: "+prefix+", "+e); + keyReleased++; + if(e.isConsumed()) { + consumed++; + } + if( 0 != ( e.getModifiers() & InputEvent.AUTOREPEAT_MASK ) ) { + keyReleasedAR++; + } + queue.add(e); + if( verbose ) { + System.err.println("KEY NEWT RELEASED ["+pressed+"]: "+prefix+", "+e); + } } - - @Override - public void keyTyped(KeyEvent e) { - ++keyTyped; - System.err.println("KEY NEWT TYPED ["+keyTyped+"]: "+prefix+", "+e); - } - - public String toString() { return prefix+"[pressed "+pressed+", typed "+keyTyped+"]"; } + + public String toString() { return prefix+"[pressed "+pressed+", keysPressed "+keyPressed+" (AR "+keyPressedAR+"), keyReleased "+keyReleased+" (AR "+keyReleasedAR+"), consumed "+consumed+"]"; } } diff --git a/src/test/com/jogamp/opengl/test/junit/util/NEWTKeyUtil.java b/src/test/com/jogamp/opengl/test/junit/util/NEWTKeyUtil.java new file mode 100644 index 000000000..89bafbd8c --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/util/NEWTKeyUtil.java @@ -0,0 +1,213 @@ +/** + * Copyright 2012 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.util; + +import java.util.ArrayList; +import java.util.EventObject; +import java.util.List; + +import org.junit.Assert; + +import com.jogamp.common.util.IntIntHashMap; +import com.jogamp.newt.event.KeyEvent; + +public class NEWTKeyUtil { + public static final int TIME_OUT = 2000; // 2s + public static final int POLL_DIVIDER = 20; // TO/20 + public static final int TIME_SLICE = TIME_OUT / POLL_DIVIDER ; + + public static class CodeSeg { + public final short min; + public final short max; + public final String description; + + public CodeSeg(int min, int max, String description) { + this.min = (short)min; + this.max = (short)max; + this.description = description; + } + } + public static class CodeEvent { + public final short code; + public final String description; + public final KeyEvent event; + + public CodeEvent(short code, String description, KeyEvent event) { + this.code = code; + this.description = description; + this.event = event; + } + public String toString() { + return "Code 0x"+Integer.toHexString( code & 0x0000FFFF )+" != "+event+" // "+description; + } + } + + public static void dumpKeyEvents(List<EventObject> keyEvents) { + for(int i=0; i<keyEvents.size(); i++) { + System.err.println(i+": "+keyEvents.get(i)); + } + } + + public static boolean validateKeyCodes(CodeSeg[] codeSegments, List<List<EventObject>> keyEventsList, boolean verbose) { + final List<CodeEvent> missCodes = new ArrayList<CodeEvent>(); + int totalCodeCount = 0; + boolean res = true; + for(int i=0; i<codeSegments.length; i++) { + final CodeSeg codeSeg = codeSegments[i]; + totalCodeCount += codeSeg.max - codeSeg.min + 1; + final List<EventObject> keyEvents = keyEventsList.get(i); + res &= validateKeyCodes(missCodes, codeSeg, keyEvents, verbose); + } + if(verbose) { + System.err.println("*** Total KeyCode Misses "+missCodes.size()+" / "+totalCodeCount+", valid "+res); + for(int i=0; i<missCodes.size(); i++) { + System.err.println("Miss["+i+"]: "+missCodes.get(i)); + } + } + return res; + } + public static boolean validateKeyCodes(List<CodeEvent> missCodes, CodeSeg codeSeg, List<EventObject> keyEvents, boolean verbose) { + final int codeCount = codeSeg.max - codeSeg.min + 1; + int misses = 0; + int evtIdx = 0; + for(int i=0; i<codeCount; i++) { + // evtIdx -> KEY_PRESSED ! + final short c = (short) ( codeSeg.min + i ); + final KeyEvent e = (KeyEvent) ( evtIdx < keyEvents.size() ? keyEvents.get(evtIdx) : null ); + if( null == e ) { + missCodes.add(new CodeEvent(c, codeSeg.description, e)); + misses++; + evtIdx++; + } else { + if( c != e.getKeyCode() ) { + missCodes.add(new CodeEvent(c, codeSeg.description, e)); + misses++; + } + evtIdx += 2; + } + } + final boolean res = evtIdx == keyEvents.size() && 0 == missCodes.size(); + if(verbose) { + System.err.println("+++ Code Segment "+codeSeg.description+", Misses: "+misses+" / "+codeCount+", events "+keyEvents.size()+", valid "+res); + } + return res; + } + + public static void validateKeyEvent(KeyEvent e, short eventType, int modifiers, short keyCode, char keyChar) { + if(0 <= eventType) { + Assert.assertTrue("KeyEvent type mismatch, expected 0x"+Integer.toHexString(eventType)+", has "+e, eventType == e.getEventType()); + } + if(0 <= modifiers) { + Assert.assertTrue("KeyEvent modifier mismatch, expected 0x"+Integer.toHexString(modifiers)+", has "+e, modifiers == e.getModifiers()); + } + if(KeyEvent.VK_UNDEFINED != keyCode) { + Assert.assertTrue("KeyEvent code mismatch, expected 0x"+Integer.toHexString(keyCode)+", has "+e, keyCode == e.getKeyCode()); + } + if(KeyEvent.NULL_CHAR != keyChar) { + Assert.assertTrue("KeyEvent char mismatch, expected 0x"+Integer.toHexString(keyChar)+", has "+e, keyChar == e.getKeyChar()); + } + } + + public static short getNextKeyEventType(KeyEvent e) { + final int et = e.getEventType(); + switch( et ) { + case KeyEvent.EVENT_KEY_PRESSED: + return KeyEvent.EVENT_KEY_RELEASED; + case KeyEvent.EVENT_KEY_RELEASED: + return KeyEvent.EVENT_KEY_PRESSED; + default: + Assert.assertTrue("Invalid event "+e, false); + return 0; + } + } + + public static void validateKeyEventOrder(List<EventObject> keyEvents) { + IntIntHashMap keyCode2NextEvent = new IntIntHashMap(); + for(int i=0; i<keyEvents.size(); i++) { + final KeyEvent e = (KeyEvent) keyEvents.get(i); + int eet = keyCode2NextEvent.get(e.getKeyCode()); + if( 0 >= eet ) { + eet = KeyEvent.EVENT_KEY_PRESSED; + } + final int et = e.getEventType(); + Assert.assertEquals("Key event not in proper order "+i+"/"+keyEvents.size()+" - event "+e, eet, et); + eet = getNextKeyEventType(e); + keyCode2NextEvent.put(e.getKeyCode(), eet); + } + } + + /** + * @param keyAdapter + * @param expPressedCountSI number of single key press events + * @param expReleasedCountSI number of single key release events + * @param expPressedCountAR number of auto-repeat key press events + * @param expReleasedCountAR number of auto-repeat key release events + */ + public static void validateKeyAdapterStats(NEWTKeyAdapter keyAdapter, + int expPressedCountSI, int expReleasedCountSI, + int expPressedCountAR, int expReleasedCountAR) { + final int expPressReleaseCountSI = expPressedCountSI + expReleasedCountSI; + final int expPressReleaseCountAR = expPressedCountAR + expReleasedCountAR; + final int expPressReleaseCountALL = expPressReleaseCountSI + expPressReleaseCountAR; + + final int keyPressedALL = keyAdapter.getKeyPressedCount(false); + final int keyPressedAR = keyAdapter.getKeyPressedCount(true); + final int keyReleasedALL = keyAdapter.getKeyReleasedCount(false); + final int keyReleasedAR = keyAdapter.getKeyReleasedCount(true); + + final int keyPressedSI = keyPressedALL-keyPressedAR; + final int keyReleasedSI = keyReleasedALL-keyReleasedAR; + + final int pressReleaseCountALL = keyPressedALL + keyReleasedALL; + final int pressReleaseCountSI = keyPressedSI + keyReleasedSI; + final int pressReleaseCountAR = keyPressedAR + keyReleasedAR; + + System.err.println("Expec Single Press "+expPressedCountSI +", Release "+expReleasedCountSI); + System.err.println("Expec AutoRp Press "+expPressedCountAR +", Release "+expReleasedCountAR); + + System.err.println("Total Single Press "+keyPressedSI +", Release "+keyReleasedSI +", Events "+pressReleaseCountSI); + System.err.println("Total AutoRp Press "+keyPressedAR +", Release "+keyReleasedAR +", Events "+pressReleaseCountAR); + System.err.println("Total ALL Press "+keyPressedALL +", Release "+keyReleasedALL +", Events "+pressReleaseCountALL); + + Assert.assertEquals("Internal Error: pressReleaseSI != pressReleaseALL - pressReleaseAR", pressReleaseCountSI, pressReleaseCountALL - pressReleaseCountAR); + + Assert.assertEquals("Key press count failure (SI)", expPressedCountSI, keyPressedSI); + Assert.assertEquals("Key released count failure (SI)", expReleasedCountSI, keyReleasedSI); + + Assert.assertEquals("Key press count failure (AR)", expPressedCountAR, keyPressedAR); + Assert.assertEquals("Key released count failure (AR)", expReleasedCountAR, keyReleasedAR); + + Assert.assertEquals("Key pressRelease count failure (SI)", expPressReleaseCountSI, pressReleaseCountSI); + Assert.assertEquals("Key pressRelease count failure (AR)", expPressReleaseCountAR, pressReleaseCountAR); + + final List<EventObject> keyEvents = keyAdapter.copyQueue(); + + Assert.assertEquals("Key pressRelease count failure (ALL) w/ list sum ", expPressReleaseCountALL, pressReleaseCountALL); + Assert.assertEquals("Key total count failure (ALL) w/ list size ", pressReleaseCountALL, keyEvents.size()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/util/NEWTMouseAdapter.java b/src/test/com/jogamp/opengl/test/junit/util/NEWTMouseAdapter.java index d98b9ca74..22e241f71 100644 --- a/src/test/com/jogamp/opengl/test/junit/util/NEWTMouseAdapter.java +++ b/src/test/com/jogamp/opengl/test/junit/util/NEWTMouseAdapter.java @@ -3,14 +3,14 @@ * * 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 @@ -20,14 +20,18 @@ * 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.util; +import java.util.ArrayList; +import java.util.EventObject; +import java.util.List; + import com.jogamp.newt.event.MouseAdapter; import com.jogamp.newt.event.MouseEvent; @@ -35,41 +39,72 @@ public class NEWTMouseAdapter extends MouseAdapter implements InputEventCountAda String prefix; int mouseClicked; + int consumed; boolean pressed; + List<EventObject> queue = new ArrayList<EventObject>(); + boolean verbose = true; public NEWTMouseAdapter(String prefix) { this.prefix = prefix; reset(); } - public boolean isPressed() { + public synchronized void setVerbose(boolean v) { verbose = v; } + + public synchronized boolean isPressed() { return pressed; } - - public int getCount() { + + public synchronized int getCount() { return mouseClicked; } - public void reset() { + public synchronized int getConsumedCount() { + return consumed; + } + + public synchronized List<EventObject> copyQueue() { + return new ArrayList<EventObject>(queue); + } + + public synchronized int getQueueSize() { + return queue.size(); + } + + public synchronized void reset() { mouseClicked = 0; + consumed = 0; pressed = false; + queue.clear(); } - public void mousePressed(MouseEvent e) { + public synchronized void mousePressed(MouseEvent e) { pressed = true; - System.err.println("MOUSE NEWT PRESSED ["+pressed+"]: "+prefix+", "+e); + queue.add(e); + if( verbose ) { + System.err.println("MOUSE NEWT PRESSED ["+pressed+"]: "+prefix+", "+e); + } } - - public void mouseReleased(MouseEvent e) { + + public synchronized void mouseReleased(MouseEvent e) { pressed = false; - System.err.println("MOUSE NEWT RELEASED ["+pressed+"]: "+prefix+", "+e); + queue.add(e); + if( verbose ) { + System.err.println("MOUSE NEWT RELEASED ["+pressed+"]: "+prefix+", "+e); + } } - - public void mouseClicked(MouseEvent e) { + + public synchronized void mouseClicked(MouseEvent e) { mouseClicked+=e.getClickCount(); - System.err.println("MOUSE NEWT CLICKED ["+mouseClicked+"]: "+prefix+", "+e); + if(e.isConsumed()) { + consumed++; + } + queue.add(e); + if( verbose ) { + System.err.println("MOUSE NEWT CLICKED ["+mouseClicked+"]: "+prefix+", "+e); + } } - - public String toString() { return prefix+"[pressed "+pressed+", clicked "+mouseClicked+"]"; } + + public String toString() { return prefix+"[pressed "+pressed+", clicked "+mouseClicked+", consumed "+consumed+"]"; } } diff --git a/src/test/com/jogamp/opengl/test/junit/util/QuitAdapter.java b/src/test/com/jogamp/opengl/test/junit/util/QuitAdapter.java index 42d68dadb..467dd7fae 100644 --- a/src/test/com/jogamp/opengl/test/junit/util/QuitAdapter.java +++ b/src/test/com/jogamp/opengl/test/junit/util/QuitAdapter.java @@ -3,14 +3,14 @@ * * 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 @@ -20,33 +20,45 @@ * 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.util; import com.jogamp.newt.event.*; public class QuitAdapter extends WindowAdapter implements WindowListener, KeyListener { boolean shouldQuit = false; + boolean enabled = true; + + public void enable(boolean v) { enabled = v; } + + public void clear() { shouldQuit = false; } public boolean shouldQuit() { return shouldQuit; } + public void doQuit() { shouldQuit=true; } public void windowDestroyNotify(WindowEvent e) { - System.err.println("QUIT Window "+Thread.currentThread()); - shouldQuit = true; + if( enabled ) { + System.err.println("QUIT Window "+Thread.currentThread()); + shouldQuit = true; + } } - public void keyTyped(KeyEvent e) { - if(e.getKeyChar()=='q') { - System.err.println("QUIT Key "+Thread.currentThread()); - shouldQuit = true; + public void keyReleased(KeyEvent e) { + if( !e.isPrintableKey() || e.isAutoRepeat() ) { + return; + } + if( enabled ) { + if(e.getKeyChar()=='q') { + System.err.println("QUIT Key "+Thread.currentThread()); + shouldQuit = true; + } } } public void keyPressed(KeyEvent e) {} - public void keyReleased(KeyEvent e) {} } diff --git a/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java b/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java index 672675fab..a08e9f842 100644 --- a/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java +++ b/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java @@ -3,14 +3,14 @@ * * 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 @@ -20,37 +20,65 @@ * 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.util; +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.StringTokenizer; + +import javax.media.nativewindow.NativeWindowFactory; +import javax.media.opengl.GL; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLEventListener; + import com.jogamp.common.util.locks.SingletonInstance; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; import org.junit.Assume; import org.junit.Before; import org.junit.BeforeClass; import org.junit.After; import org.junit.AfterClass; +import org.junit.FixMethodOrder; import org.junit.Rule; import org.junit.rules.TestName; +import org.junit.runners.MethodSorters; +import org.junit.runners.model.FrameworkMethod; +import org.junit.runners.model.TestClass; - +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public abstract class UITestCase { @Rule public TestName _unitTestName = new TestName(); public static final String SINGLE_INSTANCE_LOCK_FILE = "UITestCase.lock"; public static final int SINGLE_INSTANCE_LOCK_PORT = 59999; - - public static final long SINGLE_INSTANCE_LOCK_TO = 3*60*1000; // wait up to 3 min + + public static final long SINGLE_INSTANCE_LOCK_TO = 6*60*1000; // wait up to 6 mins public static final long SINGLE_INSTANCE_LOCK_POLL = 1000; // poll every 1s - static volatile SingletonInstance singletonInstance; - - static volatile boolean testSupported = true; + private static volatile SingletonInstance singletonInstance; + + private static volatile boolean testSupported = true; + private static volatile boolean resetXRandRIfX11AfterClass = false; + + private static volatile int maxMethodNameLen = 0; private static final synchronized void initSingletonInstance() { if( null == singletonInstance ) { @@ -61,16 +89,145 @@ public abstract class UITestCase { } } } - + + public static boolean isTestSupported() { + return testSupported; + } + public static void setTestSupported(boolean v) { System.err.println("setTestSupported: "+v); testSupported = v; } + public static void setResetXRandRIfX11AfterClass() { + resetXRandRIfX11AfterClass = true; + } + + /** + * Iterates through all outputs and sets the preferred mode and normal rotation using RandR 1.3. + * <p> + * With NV drivers, one need to add the Modes in proper order to the Screen's Subsection "Display", + * otherwise they are either in unsorted resolution order or even n/a! + * </p> + */ + @SuppressWarnings("unused") + public static void resetXRandRIfX11() { + if( NativeWindowFactory.isInitialized() && NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(true) ) { + try { + final List<String> outputDevices = new ArrayList<String>(); + // final List<String> outputSizes = new ArrayList<String>(); + final Object ioSync = new Object(); + synchronized ( ioSync ) { + final StringBuilder out = new StringBuilder(); + final ProcessBuilder pb = new ProcessBuilder("xrandr", "-q"); + pb.redirectErrorStream(true); + System.err.println("XRandR Query: "+pb.command()); + final Process p = pb.start(); + final MiscUtils.StreamDump dump = new MiscUtils.StreamDump( out, p.getInputStream(), ioSync ); + dump.start(); + while( !dump.eos() ) { + ioSync.wait(); + } + p.waitFor(); // should be fine by now .. + final int errorCode = p.exitValue(); + if( 0 == errorCode ) { + // Parse connected output devices ! + final BufferedReader in = new BufferedReader( new StringReader( out.toString() ) ); + String line = null; + while ( ( line = in.readLine() ) != null) { + final String lline = line.toLowerCase(); + if( lline.contains("connected") && !lline.contains("disconnected") ) { + final String od = getFirst(line); + if( null != od ) { + outputDevices.add( od ); + /** + if ( ( line = in.readLine() ) != null ) { + outputSizes.add( getFirst(line) ); + } else { + outputSizes.add( null ); + } */ + } + } + } + } else { + System.err.println("XRandR Query Error Code "+errorCode); + System.err.println(out.toString()); + } + } + for(int i=0; i<outputDevices.size(); i++) { + final String outputDevice = outputDevices.get(i); + final String outputSize = null; // outputSizes.get(i); + final String[] cmdline; + if( null != outputSize ) { + cmdline = new String[] { "xrandr", "--output", outputDevice, "--mode", outputSize, "--rotate", "normal" }; + } else { + cmdline = new String[] { "xrandr", "--output", outputDevice, "--preferred", "--rotate", "normal" }; + } + System.err.println("XRandR Reset: "+Arrays.asList(cmdline)); + final int errorCode = processCommand(cmdline, System.err, "xrandr-reset> "); + if( 0 != errorCode ) { + System.err.println("XRandR Reset Error Code "+errorCode); + } + } + } catch (Exception e) { + System.err.println("Catched "+e.getClass().getName()+": "+e.getMessage()); + e.printStackTrace(); + } + } + } + private static String getFirst(String line) { + final StringTokenizer tok = new StringTokenizer(line); + if( tok.hasMoreTokens() ) { + final String s = tok.nextToken().trim(); + if( s.length() > 0 ) { + return s; + } + } + return null; + } + + public static int processCommand(String[] cmdline, OutputStream outstream, String outPrefix) { + int errorCode = 0; + final Object ioSync = new Object(); + try { + synchronized ( ioSync ) { + final ProcessBuilder pb = new ProcessBuilder(cmdline); + pb.redirectErrorStream(true); + final Process p = pb.start(); + final MiscUtils.StreamDump dump = new MiscUtils.StreamDump( outstream, outPrefix, p.getInputStream(), ioSync); + dump.start(); + while( !dump.eos() ) { + ioSync.wait(); + } + p.waitFor(); // should be fine by now .. + errorCode = p.exitValue(); + } + } catch (Exception e) { + System.err.println("Catched "+e.getClass().getName()+": "+e.getMessage()); + e.printStackTrace(); + errorCode = Integer.MIN_VALUE; + } + return errorCode; + } + + public int getMaxTestNameLen() { + if(0 == maxMethodNameLen) { + int ml = 0; + final TestClass tc = new TestClass(getClass()); + final List<FrameworkMethod> testMethods = tc.getAnnotatedMethods(org.junit.Test.class); + for(Iterator<FrameworkMethod> iter=testMethods.iterator(); iter.hasNext(); ) { + final int l = iter.next().getName().length(); + if( ml < l ) { ml = l; } + } + maxMethodNameLen = ml; + } + return maxMethodNameLen; + } + public final String getTestMethodName() { return _unitTestName.getMethodName(); } - + public final String getSimpleTestName(String separator) { return getClass().getSimpleName()+separator+getTestMethodName(); } @@ -78,16 +235,19 @@ public abstract class UITestCase { public final String getFullTestName(String separator) { return getClass().getName()+separator+getTestMethodName(); } - + @BeforeClass public static void oneTimeSetUp() { - // one-time initialization code + // one-time initialization code initSingletonInstance(); } @AfterClass public static void oneTimeTearDown() { // one-time cleanup code + if( resetXRandRIfX11AfterClass ) { + resetXRandRIfX11(); + } System.gc(); // force cleanup singletonInstance.unlock(); } @@ -97,17 +257,143 @@ public abstract class UITestCase { System.err.print("++++ UITestCase.setUp: "+getFullTestName(" - ")); if(!testSupported) { System.err.println(" - "+unsupportedTestMsg); - Assume.assumeTrue(testSupported); + Assume.assumeTrue(testSupported); // abort } - System.err.println(); + System.err.println(); } @After public void tearDown() { System.err.println("++++ UITestCase.tearDown: "+getFullTestName(" - ")); } - + + public static void waitForKey(String preMessage) { + BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); + System.err.println(preMessage+"> Press enter to continue"); + try { + System.err.println(stdin.readLine()); + } catch (IOException e) { } + } + static final String unsupportedTestMsg = "Test not supported on this platform."; + public String getSnapshotFilename(int sn, String postSNDetail, GLCapabilitiesImmutable caps, int width, int height, boolean sinkHasAlpha, String fileSuffix, String destPath) { + if(null == fileSuffix) { + fileSuffix = TextureIO.PNG; + } + final int maxSimpleTestNameLen = getMaxTestNameLen()+getClass().getSimpleName().length()+1; + final String simpleTestName = this.getSimpleTestName("."); + final String filenameBaseName; + { + final String accel = caps.getHardwareAccelerated() ? "hw" : "sw" ; + final String scrnm; + if(caps.isOnscreen()) { + scrnm = "onscreen"; + } else if(caps.isFBO()) { + scrnm = "fbobject"; + } else if(caps.isPBuffer()) { + scrnm = "pbuffer_"; + } else if(caps.isBitmap()) { + scrnm = "bitmap__"; + } else { + scrnm = "unknown_"; + } + final String dblb = caps.getDoubleBuffered() ? "dbl" : "one"; + final String F_pfmt = sinkHasAlpha ? "rgba" : "rgb_"; + final String pfmt = "rgba" + caps.getRedBits() + caps.getGreenBits() + caps.getBlueBits() + caps.getAlphaBits(); + final int depthBits = caps.getDepthBits(); + final int stencilBits = caps.getStencilBits(); + final int samples = caps.getNumSamples() ; + final String aaext = caps.getSampleExtension(); + postSNDetail = null != postSNDetail ? "-"+postSNDetail : ""; + + filenameBaseName = String.format("%-"+maxSimpleTestNameLen+"s-n%04d%s-%-6s-%s-%s-B%s-F%s_I%s-D%02d-St%02d-Sa%02d_%s-%04dx%04d.%s", + simpleTestName, sn, postSNDetail, caps.getGLProfile().getName(), accel, + scrnm, dblb, F_pfmt, pfmt, depthBits, stencilBits, samples, aaext, + width, height, fileSuffix).replace(' ', '_'); + } + return null != destPath ? destPath + File.separator + filenameBaseName : filenameBaseName; + } + + /** + * Takes a snapshot of the drawable's current front framebuffer. Example filenames: + * <pre> + * TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testES2OffScreenFBOSglBuf____-n0001-msaa0-GLES2_-sw-fbobject-Bdbl-Frgb__Irgba8888_-D24-St00-Sa00_default-0400x0300.png + * TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testES2OffScreenPbufferDblBuf-n0003-msaa0-GLES2_-sw-pbuffer_-Bdbl-Frgb__Irgba8880-D24-St00-Sa00_default-0200x0150.png + * TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testGL2OffScreenPbufferSglBuf-n0003-msaa0-GL2___-hw-pbuffer_-Bone-Frgb__Irgba5551-D24-St00-Sa00_default-0200x0150.png + * </pre> + * @param sn sequential number + * @param postSNDetail optional detail to be added to the filename after <code>sn</code> + * @param gl the current GL context object. It's read drawable is being used as the pixel source and to gather some details which will end up in the filename. + * @param readBufferUtil the {@link GLReadBufferUtil} to be used to read the pixels for the screenshot. + * @param fileSuffix Optional file suffix without a <i>dot</i> defining the file type, i.e. <code>"png"</code>. + * If <code>null</code> the <code>"png"</code> as defined in {@link TextureIO#PNG} is being used. + * @param destPath Optional platform dependent file path. It shall use {@link File#separatorChar} as is directory separator. + * It shall not end with a directory separator, {@link File#separatorChar}. + * If <code>null</code> the current working directory is being used. + */ + public void snapshot(int sn, String postSNDetail, GL gl, GLReadBufferUtil readBufferUtil, String fileSuffix, String destPath) { + final GLDrawable drawable = gl.getContext().getGLReadDrawable(); + final String filename = getSnapshotFilename(sn, postSNDetail, + drawable.getChosenGLCapabilities(), drawable.getWidth(), drawable.getHeight(), + readBufferUtil.hasAlpha(), fileSuffix, destPath); + System.err.println(Thread.currentThread().getName()+": ** screenshot: "+filename); + gl.glFinish(); // just make sure rendering finished .. + if(readBufferUtil.readPixels(gl, false)) { + readBufferUtil.write(new File(filename)); + } + } + + public class SnapshotGLEventListener implements GLEventListener { + private final GLReadBufferUtil screenshot; + private volatile boolean makeShot = false; + private volatile boolean makeShotAlways = false; + private volatile boolean verbose = false; + private volatile int displayCount=0; + private volatile int reshapeCount=0; + private volatile String postSNDetail = null; + public SnapshotGLEventListener(GLReadBufferUtil screenshot) { + this.screenshot = screenshot; + } + public SnapshotGLEventListener() { + this.screenshot = new GLReadBufferUtil(false, false); + } + public int getDisplayCount() { return displayCount; } + public int getReshapeCount() { return reshapeCount; } + public GLReadBufferUtil getGLReadBufferUtil() { return screenshot; } + public void init(GLAutoDrawable drawable) {} + public void dispose(GLAutoDrawable drawable) {} + public void display(GLAutoDrawable drawable) { + final GL gl = drawable.getGL(); + final boolean _makeShot = makeShot || makeShotAlways; + if(verbose) { + System.err.println(Thread.currentThread().getName()+": ** display: "+displayCount+": "+drawable.getWidth()+"x"+drawable.getHeight()+", makeShot "+_makeShot); + } + if(_makeShot) { + makeShot=false; + snapshot(displayCount, postSNDetail, gl, screenshot, TextureIO.PNG, null); + } + displayCount++; + } + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + if(verbose) { + System.err.println(Thread.currentThread().getName()+": ** reshape: "+reshapeCount+": "+width+"x"+height+" - "+drawable.getWidth()+"x"+drawable.getHeight()); + } + reshapeCount++; + } + public void setMakeSnapshot() { + makeShot=true; + } + public void setMakeSnapshotAlways(boolean v) { + makeShotAlways=v; + } + public void setVerbose(boolean v) { + verbose=v; + } + public void setPostSNDetail(String v) { + postSNDetail = v; + } + }; + } diff --git a/src/test/com/jogamp/opengl/test/junit/util/ValidateLockListener.java b/src/test/com/jogamp/opengl/test/junit/util/ValidateLockListener.java new file mode 100644 index 000000000..73c1ad74c --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/util/ValidateLockListener.java @@ -0,0 +1,71 @@ +/** + * Copyright 2012 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.util; + + +import javax.media.nativewindow.NativeSurface; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; + + +public class ValidateLockListener implements GLEventListener { + + private void validateLock(GLAutoDrawable drawable) { + final NativeSurface ns = drawable.getNativeSurface(); + ns.getGraphicsConfiguration().getScreen().getDevice().validateLocked(); + + final Thread current = Thread.currentThread(); + final Thread owner = ns.getSurfaceLockOwner(); + if( ns.isSurfaceLockedByOtherThread() ) { + throw new RuntimeException(current.getName()+": Locked by another thread(1), owner "+owner+", "+ns); + } + if( current != owner ) { + if( null == owner ) { + throw new RuntimeException(current.getName()+": Not locked: "+ns); + } + throw new RuntimeException(current.getName()+": Locked by another thread(2), owner "+owner+", "+ns); + } + } + + public void init(GLAutoDrawable drawable) { + validateLock(drawable); + } + + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + validateLock(drawable); + } + + public void display(GLAutoDrawable drawable) { + validateLock(drawable); + } + + public void dispose(GLAutoDrawable drawable) { + validateLock(drawable); + } +} |